This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #114040] Parse here-docs correctly in quoted constructs
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index c65aecf..fc2635b 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -314,8 +314,7 @@ enum token_type {
     TOKENTYPE_IVAL,
     TOKENTYPE_OPNUM, /* pl_yylval.ival contains an opcode number */
     TOKENTYPE_PVAL,
-    TOKENTYPE_OPVAL,
-    TOKENTYPE_GVVAL
+    TOKENTYPE_OPVAL
 };
 
 static struct debug_tokens {
@@ -345,6 +344,8 @@ static struct debug_tokens {
     { EQOP,            TOKENTYPE_OPNUM,        "EQOP" },
     { FOR,             TOKENTYPE_IVAL,         "FOR" },
     { FORMAT,          TOKENTYPE_NONE,         "FORMAT" },
+    { FORMLBRACK,      TOKENTYPE_NONE,         "FORMLBRACK" },
+    { FORMRBRACK,      TOKENTYPE_NONE,         "FORMRBRACK" },
     { FUNC,            TOKENTYPE_OPNUM,        "FUNC" },
     { FUNC0,           TOKENTYPE_OPNUM,        "FUNC0" },
     { FUNC0OP,         TOKENTYPE_OPVAL,        "FUNC0OP" },
@@ -369,6 +370,7 @@ static struct debug_tokens {
     { OROP,            TOKENTYPE_IVAL,         "OROP" },
     { OROR,            TOKENTYPE_NONE,         "OROR" },
     { PACKAGE,         TOKENTYPE_NONE,         "PACKAGE" },
+    { PEG,             TOKENTYPE_NONE,         "PEG" },
     { PLUGEXPR,                TOKENTYPE_OPVAL,        "PLUGEXPR" },
     { PLUGSTMT,                TOKENTYPE_OPVAL,        "PLUGSTMT" },
     { PMFUNC,          TOKENTYPE_OPVAL,        "PMFUNC" },
@@ -378,8 +380,10 @@ static struct debug_tokens {
     { PREDEC,          TOKENTYPE_NONE,         "PREDEC" },
     { PREINC,          TOKENTYPE_NONE,         "PREINC" },
     { PRIVATEREF,      TOKENTYPE_OPVAL,        "PRIVATEREF" },
+    { QWLIST,          TOKENTYPE_OPVAL,        "QWLIST" },
     { REFGEN,          TOKENTYPE_NONE,         "REFGEN" },
     { RELOP,           TOKENTYPE_OPNUM,        "RELOP" },
+    { REQUIRE,         TOKENTYPE_NONE,         "REQUIRE" },
     { SHIFTOP,         TOKENTYPE_OPNUM,        "SHIFTOP" },
     { SUB,             TOKENTYPE_NONE,         "SUB" },
     { THING,           TOKENTYPE_OPVAL,        "THING" },
@@ -428,7 +432,6 @@ S_tokereport(pTHX_ I32 rv, const YYSTYPE* lvalp)
            Perl_sv_catpvf(aTHX_ report, "?? %"IVdf, (IV)rv);
        switch (type) {
        case TOKENTYPE_NONE:
-       case TOKENTYPE_GVVAL: /* doesn't appear to be used */
            break;
        case TOKENTYPE_IVAL:
            Perl_sv_catpvf(aTHX_ report, "(ival=%"IVdf")", (IV)lvalp->ival);
@@ -626,8 +629,8 @@ Perl_feature_is_enabled(pTHX_ const char *const name, STRLEN namelen)
 static void
 strip_return(SV *sv)
 {
-    register const char *s = SvPVX_const(sv);
-    register const char * const e = s + SvCUR(sv);
+    const char *s = SvPVX_const(sv);
+    const char * const e = s + SvCUR(sv);
 
     PERL_ARGS_ASSERT_STRIP_RETURN;
 
@@ -635,7 +638,7 @@ strip_return(SV *sv)
     while (s < e) {
        if (*s++ == '\r' && *s == '\n') {
            /* hit a CR-LF, need to copy the rest */
-           register char *d = s - 1;
+           char *d = s - 1;
            *d++ = *s++;
            while (s < e) {
                if (*s == '\r' && s[1] == '\n')
@@ -1985,6 +1988,11 @@ S_force_next(pTHX_ I32 type)
        tokereport(type, &NEXTVAL_NEXTTOKE);
     }
 #endif
+    /* Don’t let opslab_force_free snatch it */
+    if (S_is_opval_token(type & 0xffff) && NEXTVAL_NEXTTOKE.opval) {
+       assert(!NEXTVAL_NEXTTOKE.opval->op_savefree);
+       NEXTVAL_NEXTTOKE.opval->op_savefree = 1;
+    }  
 #ifdef PERL_MAD
     if (PL_curforce < 0)
        start_force(PL_lasttoke);
@@ -2060,7 +2068,7 @@ STATIC char *
 S_force_word(pTHX_ register char *start, int token, int check_keyword, int allow_pack, int allow_initial_tick)
 {
     dVAR;
-    register char *s;
+    char *s;
     STRLEN len;
 
     PERL_ARGS_ASSERT_FORCE_WORD;
@@ -2305,9 +2313,9 @@ STATIC SV *
 S_tokeq(pTHX_ SV *sv)
 {
     dVAR;
-    register char *s;
-    register char *send;
-    register char *d;
+    char *s;
+    char *send;
+    char *d;
     STRLEN len = 0;
     SV *pv = sv;
 
@@ -2376,8 +2384,10 @@ STATIC I32
 S_sublex_start(pTHX)
 {
     dVAR;
-    register const I32 op_type = pl_yylval.ival;
+    const I32 op_type = pl_yylval.ival;
 
+    PL_sublex_info.super_bufptr = PL_bufptr;
+    PL_sublex_info.super_bufend = PL_bufend;
     if (op_type == OP_NULL) {
        pl_yylval.opval = PL_lex_op;
        PL_lex_op = NULL;
@@ -2443,6 +2453,7 @@ S_sublex_push(pTHX)
     SAVEBOOL(PL_lex_dojoin);
     SAVEI32(PL_lex_brackets);
     SAVEI32(PL_lex_allbrackets);
+    SAVEI32(PL_lex_formbrack);
     SAVEI8(PL_lex_fakeeof);
     SAVEI32(PL_lex_casemods);
     SAVEI32(PL_lex_starts);
@@ -2473,7 +2484,7 @@ S_sublex_push(pTHX)
     SAVEFREESV(PL_linestr);
 
     PL_lex_dojoin = FALSE;
-    PL_lex_brackets = 0;
+    PL_lex_brackets = PL_lex_formbrack = 0;
     PL_lex_allbrackets = 0;
     PL_lex_fakeeof = LEX_FAKEEOF_NEVER;
     Newx(PL_lex_brackstack, 120, char);
@@ -2663,11 +2674,11 @@ STATIC char *
 S_scan_const(pTHX_ char *start)
 {
     dVAR;
-    register char *send = PL_bufend;           /* end of the constant */
+    char *send = PL_bufend;            /* end of the constant */
     SV *sv = newSV(send - start);              /* sv for the constant.  See
                                                   note below on sizing. */
-    register char *s = start;                  /* start of the constant */
-    register char *d = SvPVX(sv);              /* destination for copies */
+    char *s = start;                   /* start of the constant */
+    char *d = SvPVX(sv);               /* destination for copies */
     bool dorange = FALSE;                      /* are we in a translit range? */
     bool didrange = FALSE;                     /* did we just finish a range? */
     bool in_charclass = FALSE;                 /* within /[...]/ */
@@ -4318,6 +4329,7 @@ S_tokenize_use(pTHX_ int is_use, char *s) {
     if (PL_expect != XSTATE)
        yyerror(Perl_form(aTHX_ "\"%s\" not allowed in expression",
                    is_use ? "use" : "no"));
+    PL_expect = XTERM;
     s = SKIPSPACE1(s);
     if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
        s = force_version(s, TRUE);
@@ -4389,10 +4401,11 @@ int
 Perl_yylex(pTHX)
 {
     dVAR;
-    register char *s = PL_bufptr;
-    register char *d;
+    char *s = PL_bufptr;
+    char *d;
     STRLEN len;
     bool bof = FALSE;
+    U8 formbrack = 0;
     U32 fake_eof = 0;
 
     /* orig_keyword, gvp, and gv are initialized here because
@@ -4475,6 +4488,8 @@ Perl_yylex(pTHX)
                    PL_lex_allbrackets--;
                next_type &= 0xffff;
            }
+           if (S_is_opval_token(next_type) && pl_yylval.opval)
+               pl_yylval.opval->op_savefree = 0; /* release */
 #ifdef PERL_MAD
            /* FIXME - can these be merged?  */
            return next_type;
@@ -4770,11 +4785,14 @@ Perl_yylex(pTHX)
 
        return yylex();
     case LEX_FORMLINE:
-       PL_lex_state = LEX_NORMAL;
        s = scan_formline(PL_bufptr);
        if (!PL_lex_formbrack)
+       {
+           formbrack = 1;
            goto rightbracket;
-       OPERATOR(';');
+       }
+       PL_bufptr = s;
+       return yylex();
     }
 
     s = PL_bufptr;
@@ -5166,9 +5184,11 @@ Perl_yylex(pTHX)
            }
        }
        if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
-           PL_bufptr = s;
            PL_lex_state = LEX_FORMLINE;
-           return yylex();
+           start_force(PL_curforce);
+           NEXTVAL_NEXTTOKE.ival = 0;
+           force_next(FORMRBRACK);
+           TOKEN(';');
        }
        goto retry;
     case '\r':
@@ -5223,9 +5243,11 @@ Perl_yylex(pTHX)
                incline(s);
            }
            if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
-               PL_bufptr = s;
                PL_lex_state = LEX_FORMLINE;
-               return yylex();
+               start_force(PL_curforce);
+               NEXTVAL_NEXTTOKE.ival = 0;
+               force_next(FORMRBRACK);
+               TOKEN(';');
            }
        }
        else {
@@ -5683,17 +5705,13 @@ Perl_yylex(pTHX)
        }
        TERM(']');
     case '{':
-      leftbracket:
        s++;
+      leftbracket:
        if (PL_lex_brackets > 100) {
            Renew(PL_lex_brackstack, PL_lex_brackets + 10, char);
        }
        switch (PL_expect) {
        case XTERM:
-           if (PL_lex_formbrack) {
-               s--;
-               PRETERMBLOCK(DO);
-           }
            if (PL_oldoldbufptr == PL_last_lop)
                PL_lex_brackstack[PL_lex_brackets++] = XTERM;
            else
@@ -5847,7 +5865,7 @@ Perl_yylex(pTHX)
        pl_yylval.ival = CopLINE(PL_curcop);
        if (isSPACE(*s) || *s == '#')
            PL_copline = NOLINE;   /* invalidate current command line number */
-       TOKEN('{');
+       TOKEN(formbrack ? '=' : '{');
     case '}':
        if (PL_lex_brackets && PL_lex_brackstack[PL_lex_brackets-1] == XFAKEEOF)
            TOKEN(0);
@@ -5858,8 +5876,6 @@ Perl_yylex(pTHX)
        else
            PL_expect = (expectation)PL_lex_brackstack[--PL_lex_brackets];
        PL_lex_allbrackets--;
-       if (PL_lex_brackets < PL_lex_formbrack && PL_lex_state != LEX_INTERPNORMAL)
-           PL_lex_formbrack = 0;
        if (PL_lex_state == LEX_INTERPNORMAL) {
            if (PL_lex_brackets == 0) {
                if (PL_expect & XFAKEBRACK) {
@@ -5891,11 +5907,17 @@ Perl_yylex(pTHX)
            curmad('X', newSVpvn(s-1,1));
            CURMAD('_', PL_thiswhite);
        }
-       force_next('}');
+       force_next(formbrack ? '.' : '}');
+       if (formbrack) LEAVE;
 #ifdef PERL_MAD
        if (!PL_thistoken)
            PL_thistoken = newSVpvs("");
 #endif
+       if (formbrack == 2) { /* means . where arguments were expected */
+           start_force(PL_curforce);
+           force_next(';');
+           TOKEN(FORMRBRACK);
+       }
        TOKEN(';');
     case '&':
        s++;
@@ -5981,7 +6003,8 @@ Perl_yylex(pTHX)
            if (PL_expect == XSTATE && isALPHA(tmp) &&
                (s == PL_linestart+1 || s[-2] == '\n') )
                {
-                   if (PL_in_eval && !PL_rsfp && !PL_parser->filtered) {
+                   if ((PL_in_eval && !PL_rsfp && !PL_parser->filtered)
+                       || PL_lex_state != LEX_NORMAL) {
                        d = PL_bufend;
                        while (s < d) {
                            if (*s++ == '\n') {
@@ -6012,7 +6035,7 @@ Perl_yylex(pTHX)
                    goto retry;
                }
        }
-       if (PL_lex_brackets < PL_lex_formbrack) {
+       if (PL_expect == XBLOCK) {
            const char *t = s;
 #ifdef PERL_STRICT_CR
            while (SPACE_OR_TAB(*t))
@@ -6021,8 +6044,12 @@ Perl_yylex(pTHX)
 #endif
                t++;
            if (*t == '\n' || *t == '#') {
-               s--;
-               PL_expect = XBLOCK;
+               formbrack = 1;
+               ENTER;
+               SAVEI8(PL_parser->form_lex_state);
+               SAVEI32(PL_lex_formbrack);
+               PL_parser->form_lex_state = PL_lex_state;
+               PL_lex_formbrack = PL_lex_brackets + 1;
                goto leftbracket;
            }
        }
@@ -6381,8 +6408,8 @@ Perl_yylex(pTHX)
 #endif
            && (s == PL_linestart || s[-1] == '\n') )
        {
-           PL_lex_formbrack = 0;
            PL_expect = XSTATE;
+           formbrack = 2; /* dot seen where arguments expected */
            goto rightbracket;
        }
        if (PL_expect == XSTATE && s[1] == '.' && s[2] == '.') {
@@ -7751,7 +7778,7 @@ Perl_yylex(pTHX)
 
        case KEY_no:
            s = tokenize_use(0, s);
-           OPERATOR(USE);
+           TERM(USE);
 
        case KEY_not:
            if (*s == '(' || (s = SKIPSPACE1(s), *s == '('))
@@ -8198,8 +8225,6 @@ Perl_yylex(pTHX)
                }
 
                if (key == KEY_format) {
-                   if (*s == '=')
-                       PL_lex_formbrack = PL_lex_brackets + 1;
 #ifdef PERL_MAD
                    PL_thistoken = subtoken;
                    s = d;
@@ -8208,7 +8233,7 @@ Perl_yylex(pTHX)
                        (void) force_word(PL_oldbufptr + tboffset, WORD,
                                          FALSE, TRUE, TRUE);
 #endif
-                   OPERATOR(FORMAT);
+                   PREBLOCK(FORMAT);
                }
 
                /* Look for a prototype */
@@ -8808,8 +8833,8 @@ STATIC char *
 S_scan_word(pTHX_ register char *s, char *dest, STRLEN destlen, int allow_package, STRLEN *slp)
 {
     dVAR;
-    register char *d = dest;
-    register char * const e = d + destlen - 3;  /* two-character token, ending NUL */
+    char *d = dest;
+    char * const e = d + destlen - 3;  /* two-character token, ending NUL */
 
     PERL_ARGS_ASSERT_SCAN_WORD;
 
@@ -8853,8 +8878,8 @@ S_scan_ident(pTHX_ register char *s, register const char *send, char *dest, STRL
     dVAR;
     char *bracket = NULL;
     char funny = *s++;
-    register char *d = dest;
-    register char * const e = d + destlen - 3;    /* two-character token, ending NUL */
+    char *d = dest;
+    char * const e = d + destlen - 3;    /* two-character token, ending NUL */
 
     PERL_ARGS_ASSERT_SCAN_IDENT;
 
@@ -9215,7 +9240,7 @@ S_scan_subst(pTHX_ char *start)
 {
     dVAR;
     char *s;
-    register PMOP *pm;
+    PMOP *pm;
     I32 first_start;
     I32 es = 0;
     char charset = '\0';    /* character set modifier */
@@ -9292,8 +9317,6 @@ S_scan_subst(pTHX_ char *start)
     if (es) {
        SV * const repl = newSVpvs("");
 
-       PL_sublex_info.super_bufptr = s;
-       PL_sublex_info.super_bufend = PL_bufend;
        PL_multi_end = 0;
        pm->op_pmflags |= PMf_EVAL;
        while (es-- > 0) {
@@ -9321,7 +9344,7 @@ STATIC char *
 S_scan_trans(pTHX_ char *start)
 {
     dVAR;
-    register char* s;
+    char* s;
     OP *o;
     U8 squash;
     U8 del;
@@ -9411,6 +9434,32 @@ S_scan_trans(pTHX_ char *start)
     return s;
 }
 
+/* scan_heredoc
+   Takes a pointer to the first < in <<FOO.
+   Returns a pointer to the byte following <<FOO.
+
+   This function scans a heredoc, which involves different methods
+   depending on whether we are in a string eval, quoted construct, etc.
+   This is because PL_linestr could containing a single line of input, or
+   a whole string being evalled, or the contents of the current quote-
+   like operator.
+
+   The three methods are:
+    - Steal lines from the input stream (stream)
+    - Scan the heredoc in PL_linestr and remove it therefrom (linestr)
+    - Peek at the PL_linestr of the outer lexing scope (peek)
+
+   They are used in these cases:
+     file scope or filtered eval               stream
+     string eval                               linestr
+     multiline quoted construct                        linestr
+     single-line quoted construct in file      stream
+     single-line quoted construct in eval      peek
+
+   Single-line also applies to heredocs that begin on the last line of a
+   quote-like operator.
+*/
+
 STATIC char *
 S_scan_heredoc(pTHX_ register char *s)
 {
@@ -9420,12 +9469,11 @@ S_scan_heredoc(pTHX_ register char *s)
     I32 len;
     SV *tmpstr;
     char term;
-    const char *found_newline;
-    register char *d;
-    register char *e;
+    const char *found_newline = 0;
+    char *d;
+    char *e;
     char *peek;
-    const int outer = (PL_rsfp || PL_parser->filtered)
-                  && !(PL_lex_inwhat == OP_SCALAR);
+    const bool infile = PL_rsfp || PL_parser->filtered;
 #ifdef PERL_MAD
     I32 stuffstart = s - SvPVX(PL_linestr);
     char *tstart;
@@ -9436,10 +9484,9 @@ S_scan_heredoc(pTHX_ register char *s)
     PERL_ARGS_ASSERT_SCAN_HEREDOC;
 
     s += 2;
-    d = PL_tokenbuf;
+    d = PL_tokenbuf + 1;
     e = PL_tokenbuf + sizeof PL_tokenbuf - 1;
-    if (!outer)
-       *d++ = '\n';
+    *PL_tokenbuf = '\n';
     peek = s;
     while (SPACE_OR_TAB(*peek))
        peek++;
@@ -9472,8 +9519,8 @@ S_scan_heredoc(pTHX_ register char *s)
 
 #ifdef PERL_MAD
     if (PL_madskills) {
-       tstart = PL_tokenbuf + !outer;
-       PL_thisclose = newSVpvn(tstart, len - !outer);
+       tstart = PL_tokenbuf + 1;
+       PL_thisclose = newSVpvn(tstart, len - 1);
        tstart = SvPVX(PL_linestr) + stuffstart;
        PL_thisopen = newSVpvn(tstart, s - tstart);
        stuffstart = s - SvPVX(PL_linestr);
@@ -9503,10 +9550,8 @@ S_scan_heredoc(pTHX_ register char *s)
        s = olds;
     }
 #endif
-#ifdef PERL_MAD
-    found_newline = 0;
-#endif
-    if ( outer || !(found_newline = (char*)memchr((void*)s, '\n', PL_bufend - s)) ) {
+    if ((infile && !PL_lex_inwhat)
+     || !(found_newline = (char*)memchr((void*)s, '\n', PL_bufend - s))) {
         herewas = newSVpvn(s,PL_bufend-s);
     }
     else {
@@ -9549,12 +9594,11 @@ S_scan_heredoc(pTHX_ register char *s)
     CLINE;
     PL_multi_start = CopLINE(PL_curcop);
     PL_multi_open = PL_multi_close = '<';
-    term = *PL_tokenbuf;
-    if (PL_lex_inwhat == OP_SUBST && PL_in_eval && !PL_rsfp
-     && !PL_parser->filtered) {
+    if (!infile && PL_lex_inwhat && !found_newline) {
        char * const bufptr = PL_sublex_info.super_bufptr;
        char * const bufend = PL_sublex_info.super_bufend;
        char * const olds = s - SvCUR(herewas);
+       term = *PL_tokenbuf;
        s = strchr(bufptr, '\n');
        if (!s)
            s = bufend;
@@ -9566,7 +9610,7 @@ S_scan_heredoc(pTHX_ register char *s)
        }
        if (s >= bufend) {
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
-           missingterm(PL_tokenbuf);
+           missingterm(PL_tokenbuf + 1);
        }
        sv_setpvn(herewas,bufptr,d-bufptr+1);
        sv_setpvn(tmpstr,d+1,s-d);
@@ -9577,7 +9621,8 @@ S_scan_heredoc(pTHX_ register char *s)
        s = olds;
        goto retval;
     }
-    else if (!outer) {
+    else if (!infile || found_newline) {
+       term = *PL_tokenbuf;
        d = s;
        while (s < PL_bufend &&
          (*s != term || memNE(s,PL_tokenbuf,len)) ) {
@@ -9586,7 +9631,7 @@ S_scan_heredoc(pTHX_ register char *s)
        }
        if (s >= PL_bufend) {
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
-           missingterm(PL_tokenbuf);
+           missingterm(PL_tokenbuf + 1);
        }
        sv_setpvn(tmpstr,d+1,s-d);
 #ifdef PERL_MAD
@@ -9609,6 +9654,8 @@ S_scan_heredoc(pTHX_ register char *s)
     }
     else
        sv_setpvs(tmpstr,"");   /* avoid "uninitialized" warning */
+    term = PL_tokenbuf[1];
+    len--;
     while (s >= PL_bufend) {   /* multiple line string? */
 #ifdef PERL_MAD
        if (PL_madskills) {
@@ -9621,9 +9668,9 @@ S_scan_heredoc(pTHX_ register char *s)
 #endif
        PL_bufptr = s;
        CopLINE_inc(PL_curcop);
-       if (!outer || !lex_next_chunk(0)) {
+       if (!lex_next_chunk(0)) {
            CopLINE_set(PL_curcop, (line_t)PL_multi_start);
-           missingterm(PL_tokenbuf);
+           missingterm(PL_tokenbuf + 1);
        }
        CopLINE_dec(PL_curcop);
        s = PL_bufptr;
@@ -9648,7 +9695,7 @@ S_scan_heredoc(pTHX_ register char *s)
        else if (PL_bufend - PL_linestart == 1 && PL_bufend[-1] == '\r')
            PL_bufend[-1] = '\n';
 #endif
-       if (*s == term && memEQ(s,PL_tokenbuf,len)) {
+       if (*s == term && memEQ(s,PL_tokenbuf + 1,len)) {
            STRLEN off = PL_bufend - 1 - SvPVX_const(PL_linestr);
            *(SvPVX(PL_linestr) + off ) = ' ';
            lex_grow_linestr(SvCUR(PL_linestr) + SvCUR(herewas) + 1);
@@ -9699,7 +9746,7 @@ STATIC char *
 S_scan_inputsymbol(pTHX_ char *start)
 {
     dVAR;
-    register char *s = start;          /* current position in buffer */
+    char *s = start;           /* current position in buffer */
     char *end;
     I32 len;
     char *d = PL_tokenbuf;                                     /* start of temp holding space */
@@ -9891,9 +9938,9 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims, int re_reparse)
     dVAR;
     SV *sv;                            /* scalar value: string */
     const char *tmps;                  /* temp string, used for delimiter matching */
-    register char *s = start;          /* current position in the buffer */
-    register char term;                        /* terminating character */
-    register char *to;                 /* current position in the sv's data */
+    char *s = start;           /* current position in the buffer */
+    char term;                 /* terminating character */
+    char *to;                  /* current position in the sv's data */
     I32 brackets = 1;                  /* bracket nesting level */
     bool has_utf8 = FALSE;             /* is there any utf8 content? */
     I32 termcode;                      /* terminating char. code */
@@ -10233,9 +10280,9 @@ char *
 Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
 {
     dVAR;
-    register const char *s = start;    /* current position in buffer */
-    register char *d;                  /* destination in temp buffer */
-    register char *e;                  /* end of temp buffer */
+    const char *s = start;     /* current position in buffer */
+    char *d;                   /* destination in temp buffer */
+    char *e;                   /* end of temp buffer */
     NV nv;                             /* number read, as a double */
     SV *sv = NULL;                     /* place to put the converted number */
     bool floatit;                      /* boolean: int or float? */
@@ -10606,8 +10653,8 @@ STATIC char *
 S_scan_formline(pTHX_ register char *s)
 {
     dVAR;
-    register char *eol;
-    register char *t;
+    char *eol;
+    char *t;
     SV * const stuff = newSVpvs("");
     bool needargs = FALSE;
     bool eofmt = FALSE;
@@ -10638,13 +10685,9 @@ S_scan_formline(pTHX_ register char *s)
                break;
             }
        }
-       if (PL_in_eval && !PL_rsfp && !PL_parser->filtered) {
-           eol = (char *) memchr(s,'\n',PL_bufend-s);
-           if (!eol++)
+       eol = (char *) memchr(s,'\n',PL_bufend-s);
+       if (!eol++)
                eol = PL_bufend;
-       }
-       else
-           eol = PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
        if (*s != '#') {
            for (t = s; t < eol; t++) {
                if (*t == '~' && t[1] == '~' && SvCUR(stuff)) {
@@ -10669,7 +10712,8 @@ S_scan_formline(pTHX_ register char *s)
              break;
        }
        s = (char*)eol;
-       if (PL_rsfp || PL_parser->filtered) {
+       if ((PL_rsfp || PL_parser->filtered)
+        && PL_parser->form_lex_state == LEX_NORMAL) {
            bool got_some;
 #ifdef PERL_MAD
            if (PL_madskills) {
@@ -10693,16 +10737,15 @@ S_scan_formline(pTHX_ register char *s)
        incline(s);
     }
   enough:
+    if (!SvCUR(stuff) || needargs)
+       PL_lex_state = PL_parser->form_lex_state;
     if (SvCUR(stuff)) {
-       PL_expect = XTERM;
+       PL_expect = XSTATE;
        if (needargs) {
-           PL_lex_state = LEX_NORMAL;
            start_force(PL_curforce);
            NEXTVAL_NEXTTOKE.ival = 0;
-           force_next(',');
+           force_next(FORMLBRACK);
        }
-       else
-           PL_lex_state = LEX_FORMLINE;
        if (!IN_BYTES) {
            if (UTF && is_utf8_string((U8*)SvPVX_const(stuff), SvCUR(stuff)))
                SvUTF8_on(stuff);
@@ -10712,15 +10755,11 @@ S_scan_formline(pTHX_ register char *s)
        start_force(PL_curforce);
        NEXTVAL_NEXTTOKE.opval = (OP*)newSVOP(OP_CONST, 0, stuff);
        force_next(THING);
-       start_force(PL_curforce);
-       NEXTVAL_NEXTTOKE.ival = OP_FORMLINE;
-       force_next(LSTOP);
     }
     else {
        SvREFCNT_dec(stuff);
        if (eofmt)
            PL_lex_formbrack = 0;
-       PL_bufptr = s;
     }
 #ifdef PERL_MAD
     if (PL_madskills) {
@@ -10741,9 +10780,6 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
     const I32 oldsavestack_ix = PL_savestack_ix;
     CV* const outsidecv = PL_compcv;
 
-    if (PL_compcv) {
-       assert(SvTYPE(PL_compcv) == SVt_PVCV);
-    }
     SAVEI32(PL_subline);
     save_item(PL_subname);
     SAVESPTR(PL_compcv);