- if ((flags & REXEC_SCREAM) && SvSCREAM(sv)) {
- last = screaminstr(sv, float_real, s - strbeg,
- end_shift, &scream_pos, 1); /* last one */
- if (!last)
- last = scream_olds; /* Only one occurrence. */
- /* we may be pointing at the wrong string */
- else if (RXp_MATCH_COPIED(prog))
- s = strbeg + (s - SvPVX_const(sv));
- }
- else {
- STRLEN len;
- const char * const little = SvPV_const(float_real, len);
-
- if (SvTAIL(float_real)) {
- if (memEQ(strend - len + 1, little, len - 1))
- last = strend - len + 1;
- else if (!multiline)
- last = memEQ(strend - len, little, len)
- ? strend - len : NULL;
- else
+ little = SvPV_const(float_real, len);
+ if (SvTAIL(float_real)) {
+ /* This means that float_real contains an artificial \n on the end
+ * due to the presence of something like this: /foo$/
+ * where we can match both "foo" and "foo\n" at the end of the string.
+ * So we have to compare the end of the string first against the float_real
+ * without the \n and then against the full float_real with the string.
+ * We have to watch out for cases where the string might be smaller
+ * than the float_real or the float_real without the \n.
+ */
+ char *checkpos= strend - len;
+ DEBUG_OPTIMISE_r(
+ PerlIO_printf(Perl_debug_log,
+ "%sChecking for float_real.%s\n",
+ PL_colors[4], PL_colors[5]));
+ if (checkpos + 1 < strbeg) {
+ /* can't match, even if we remove the trailing \n string is too short to match */
+ DEBUG_EXECUTE_r(
+ PerlIO_printf(Perl_debug_log,
+ "%sString shorter than required trailing substring, cannot match.%s\n",
+ PL_colors[4], PL_colors[5]));
+ goto phooey;
+ } else if (memEQ(checkpos + 1, little, len - 1)) {
+ /* can match, the end of the string matches without the "\n" */
+ last = checkpos + 1;
+ } else if (checkpos < strbeg) {
+ /* cant match, string is too short when the "\n" is included */
+ DEBUG_EXECUTE_r(
+ PerlIO_printf(Perl_debug_log,
+ "%sString does not contain required trailing substring, cannot match.%s\n",
+ PL_colors[4], PL_colors[5]));
+ goto phooey;
+ } else if (!multiline) {
+ /* non multiline match, so compare with the "\n" at the end of the string */
+ if (memEQ(checkpos, little, len)) {
+ last= checkpos;
+ } else {
+ DEBUG_EXECUTE_r(
+ PerlIO_printf(Perl_debug_log,
+ "%sString does not contain required trailing substring, cannot match.%s\n",
+ PL_colors[4], PL_colors[5]));
+ goto phooey;
+ }
+ } else {
+ /* multiline match, so we have to search for a place where the full string is located */