This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix here-docs in nested quote-like operators
authorFather Chrysostomos <sprout@cpan.org>
Tue, 21 Aug 2012 02:08:57 +0000 (19:08 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 21 Aug 2012 21:11:03 +0000 (14:11 -0700)
commit99bd9d90ba5640856c6c421a174ea6e2743a4b3a
treedbe5ec1fa0a7630371e6385039c63b0f9389a921
parent62abd0d789549020431af511c02492ac374cf355
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).
perl.h
t/base/lex.t
toke.c