summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-08-29 12:47:32 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-08-30 18:18:08 -0700
commit76f9939ee09e325216d1b8afce3e3d7183c5eeb8 (patch)
treeb1b472e7e77c818959bc0784f61442a2df193378 /toke.c
parent3328ab5af72319f76fe9be3910a8e07d38b14de2 (diff)
downloadperl-76f9939ee09e325216d1b8afce3e3d7183c5eeb8.tar.gz
Fix here-doc body extraction in eval 's//<<END/'
Outside of string eval, this: s//<<END/e; print "a END b\n"; prints this: a b But when we have string eval involved, eval 's//<<END/e; print "a END b\n"'; we get this: a b Amazing! The buggy code in question goes back to commit 0244c3a403. Since PL_linestr only contains the contents of the replacement ("<<END"), it peeks into the outer lexing scope’s linestr buffer, mod- ifying it in place to remove the here-doc body, by copying everything after the here-doc back to the spot where the body begins. It was off by one, however, and left an extra line break. When the code in question is reached, the variables are set as follows: bufptr = "; print \"a"... (just after the s///) s = "\nb\\n\"" (newline after the heredoc terminator) The herewas variable already contains everything after the quote- like operator containing the <<heredoc marker to the end of the line including the \n ("; print \"a\n"). But then we concatenate everything from s onwards. So we end up with the \n before the here-doc body and the \n from after the here-doc terminator juxtaposed. So after using s to extract the re-eval string, we increment s so it points afer the final newline.
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/toke.c b/toke.c
index c628a21efd..5f568b163d 100644
--- a/toke.c
+++ b/toke.c
@@ -9681,6 +9681,7 @@ S_scan_heredoc(pTHX_ register char *s)
sv_setpvn(herewas,bufptr,d-bufptr+1);
sv_setpvn(tmpstr,d+1,s-d);
s += len - 1;
+ shared->herelines++; /* the preceding stmt passes a newline */
/* See the Paranoia note in case LEX_INTERPEND in yylex, for why we
check shared->re_eval_str. */
if (shared->re_eval_start || shared->re_eval_str) {
@@ -9696,6 +9697,7 @@ S_scan_heredoc(pTHX_ register char *s)
cx->blk_eval.cur_text = newSVsv(linestr);
SvSCREAM_on(cx->blk_eval.cur_text);
}
+ s++;
sv_catpvn(herewas,s,bufend-s);
Copy(SvPVX_const(herewas),bufptr,SvCUR(herewas) + 1,char);
SvCUR_set(linestr,