summaryrefslogtreecommitdiff
path: root/perl.h
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-08-20 19:08:57 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-08-21 14:11:03 -0700
commit99bd9d90ba5640856c6c421a174ea6e2743a4b3a (patch)
treedbe5ec1fa0a7630371e6385039c63b0f9389a921 /perl.h
parent62abd0d789549020431af511c02492ac374cf355 (diff)
downloadperl-99bd9d90ba5640856c6c421a174ea6e2743a4b3a.tar.gz
Fix here-docs in nested quote-like operators
When the lexer encounters a quote-like operator, it extracts the con- tents of the quotes and starts an inner lexing scope. To handle eval "s//<<FOO/e\n...", the here-doc parser peeks into the outer lexing scope’s PL_linestr (current line buffer, which inside an eval contains the entire string of code being parsed; for quote-like operators, that is where the contents of the quote are stored). It only does this inside a string eval. When parsing a file, the input comes in one line at a time. So the here-doc parser steals lines from the input stream for s//<<FOO/e outside an eval. This approach fails in this case, as the peekee is the linestr for s///, not for the eval: eval ' s//"${\<<END}"/e; print Just another Perl hacker, END 'or die $@ __END__ Can't find string terminator "END" anywhere before EOF at (eval 1) line 1. We also need to do this peeking stuff outside of a string eval, to solve this: s//"${\<<END}" Just another Perl hacker, END /e; print __END__ Can't find string terminator "END" anywhere before EOF at - line 1. In the first example above, we need to look not in the parent lexing scope’s linestr, but in that of the grandparent. To solve the second example, we need to check whether the outer lexing scope is a quote-like operator when we are not in an eval. For parsing here-docs in quotes in eval, we currently store two things, the former buffer pointer and the former linestr, in PL_sublex_info.super_{bufp,lines}tr. The values for upper scopes are stashed away on the savestack somewhere. We need to be able to iterate through the outer lexer scopes till we find one with multiple lines. Retrieving the information from the savestack would be too complex and error-prone. Since PL_linestr is an SV, we can abuse a couple of fields in it. Upgrading it to PVNV gives it both IVX and NVX fields, which are big enough to store pointers. IVX is already used to hold an op number. So for the innermost quoted scope we still need to use PL_sublex_info.super_bufptr. When entering a new lexing scope (in sublex_push), we can localise the IVX field of the outer PL_linestr SV and set it to what PL_sublex_info.super_bufptr was in that scope. SvIVX(linestr) is only used for an op number when that linestr’s lexing scope is the innermost one. PL_sublex_info.super_linestr can be eliminated and replaced with SvNVX(PL_linestr).
Diffstat (limited to 'perl.h')
-rw-r--r--perl.h1
1 files changed, 0 insertions, 1 deletions
diff --git a/perl.h b/perl.h
index ed9889ef48..d8b4179dae 100644
--- a/perl.h
+++ b/perl.h
@@ -3450,7 +3450,6 @@ struct _sublex_info {
U16 sub_inwhat; /* "lex_inwhat" to use */
OP *sub_op; /* "lex_op" to use */
char *super_bufptr; /* PL_parser->bufptr that was */
- SV *super_linestr; /* PL_parser->linestr that was */
char *re_eval_start;/* start of "(?{..." text */
};