This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add dtrace support
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index c862b16..c3a8475 100644 (file)
--- a/toke.c
+++ b/toke.c
 #define PERL_IN_TOKE_C
 #include "perl.h"
 
 #define PERL_IN_TOKE_C
 #include "perl.h"
 
-#define yylval (PL_parser->yylval)
+#define new_constant(a,b,c,d,e,f,g)    \
+       S_new_constant(aTHX_ a,b,STR_WITH_LEN(c),d,e,f, g)
+
+#define pl_yylval      (PL_parser->yylval)
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
 #define YYINITDEPTH 200
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
 #define YYINITDEPTH 200
 #define PL_pending_ident        (PL_parser->pending_ident)
 #define PL_preambled           (PL_parser->preambled)
 #define PL_sublex_info         (PL_parser->sublex_info)
 #define PL_pending_ident        (PL_parser->pending_ident)
 #define PL_preambled           (PL_parser->preambled)
 #define PL_sublex_info         (PL_parser->sublex_info)
+#define PL_linestr             (PL_parser->linestr)
+#define PL_expect              (PL_parser->expect)
+#define PL_copline             (PL_parser->copline)
+#define PL_bufptr              (PL_parser->bufptr)
+#define PL_oldbufptr           (PL_parser->oldbufptr)
+#define PL_oldoldbufptr                (PL_parser->oldoldbufptr)
+#define PL_linestart           (PL_parser->linestart)
+#define PL_bufend              (PL_parser->bufend)
+#define PL_last_uni            (PL_parser->last_uni)
+#define PL_last_lop            (PL_parser->last_lop)
+#define PL_last_lop_op         (PL_parser->last_lop_op)
+#define PL_lex_state           (PL_parser->lex_state)
+#define PL_rsfp                        (PL_parser->rsfp)
+#define PL_rsfp_filters                (PL_parser->rsfp_filters)
+#define PL_in_my               (PL_parser->in_my)
+#define PL_in_my_stash         (PL_parser->in_my_stash)
+#define PL_tokenbuf            (PL_parser->tokenbuf)
+#define PL_multi_end           (PL_parser->multi_end)
+#define PL_error_count         (PL_parser->error_count)
 
 #ifdef PERL_MAD
 #  define PL_endwhite          (PL_parser->endwhite)
 
 #ifdef PERL_MAD
 #  define PL_endwhite          (PL_parser->endwhite)
 #  define PL_thisstuff         (PL_parser->thisstuff)
 #  define PL_thistoken         (PL_parser->thistoken)
 #  define PL_thiswhite         (PL_parser->thiswhite)
 #  define PL_thisstuff         (PL_parser->thisstuff)
 #  define PL_thistoken         (PL_parser->thistoken)
 #  define PL_thiswhite         (PL_parser->thiswhite)
+#  define PL_thiswhite         (PL_parser->thiswhite)
+#  define PL_nexttoke          (PL_parser->nexttoke)
+#  define PL_curforce          (PL_parser->curforce)
+#else
+#  define PL_nexttoke          (PL_parser->nexttoke)
+#  define PL_nexttype          (PL_parser->nexttype)
+#  define PL_nextval           (PL_parser->nextval)
 #endif
 
 static int
 #endif
 
 static int
@@ -71,7 +100,6 @@ S_pending_ident(pTHX);
 static const char ident_too_long[] = "Identifier too long";
 static const char commaless_variable_list[] = "comma-less variable list";
 
 static const char ident_too_long[] = "Identifier too long";
 static const char commaless_variable_list[] = "comma-less variable list";
 
-static void restore_rsfp(pTHX_ void *f);
 #ifndef PERL_NO_UTF16_FILTER
 static I32 utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen);
 static I32 utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen);
 #ifndef PERL_NO_UTF16_FILTER
 static I32 utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen);
 static I32 utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen);
@@ -211,19 +239,19 @@ static const char* const lex_state_names[] = {
 #define PRETERMBLOCK(retval) return (PL_expect = XTERMBLOCK,PL_bufptr = s, REPORT(retval))
 #define PREREF(retval) return (PL_expect = XREF,PL_bufptr = s, REPORT(retval))
 #define TERM(retval) return (CLINE, PL_expect = XOPERATOR, PL_bufptr = s, REPORT(retval))
 #define PRETERMBLOCK(retval) return (PL_expect = XTERMBLOCK,PL_bufptr = s, REPORT(retval))
 #define PREREF(retval) return (PL_expect = XREF,PL_bufptr = s, REPORT(retval))
 #define TERM(retval) return (CLINE, PL_expect = XOPERATOR, PL_bufptr = s, REPORT(retval))
-#define LOOPX(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX))
-#define FTST(f)  return (yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP))
-#define FUN0(f)  return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0))
-#define FUN1(f)  return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC1))
-#define BOop(f)  return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITOROP)))
-#define BAop(f)  return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITANDOP)))
-#define SHop(f)  return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)SHIFTOP)))
-#define PWop(f)  return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)POWOP)))
-#define PMop(f)  return(yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MATCHOP))
-#define Aop(f)   return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)ADDOP)))
-#define Mop(f)   return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MULOP)))
-#define Eop(f)   return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)EQOP))
-#define Rop(f)   return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)RELOP))
+#define LOOPX(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX))
+#define FTST(f)  return (pl_yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP))
+#define FUN0(f)  return (pl_yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0))
+#define FUN1(f)  return (pl_yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC1))
+#define BOop(f)  return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITOROP)))
+#define BAop(f)  return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITANDOP)))
+#define SHop(f)  return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)SHIFTOP)))
+#define PWop(f)  return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)POWOP)))
+#define PMop(f)  return(pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MATCHOP))
+#define Aop(f)   return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)ADDOP)))
+#define Mop(f)   return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MULOP)))
+#define Eop(f)   return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)EQOP))
+#define Rop(f)   return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)RELOP))
 
 /* This bit of chicanery makes a unary function followed by
  * a parenthesis into a function with one argument, highest precedence.
 
 /* This bit of chicanery makes a unary function followed by
  * a parenthesis into a function with one argument, highest precedence.
@@ -231,7 +259,7 @@ static const char* const lex_state_names[] = {
  * operator (such as C<shift // 0>).
  */
 #define UNI2(f,x) { \
  * operator (such as C<shift // 0>).
  */
 #define UNI2(f,x) { \
-       yylval.ival = f; \
+       pl_yylval.ival = f; \
        PL_expect = x; \
        PL_bufptr = s; \
        PL_last_uni = PL_oldbufptr; \
        PL_expect = x; \
        PL_bufptr = s; \
        PL_last_uni = PL_oldbufptr; \
@@ -245,7 +273,7 @@ static const char* const lex_state_names[] = {
 #define UNIDOR(f) UNI2(f,XTERMORDORDOR)
 
 #define UNIBRACK(f) { \
 #define UNIDOR(f) UNI2(f,XTERMORDORDOR)
 
 #define UNIBRACK(f) { \
-       yylval.ival = f; \
+       pl_yylval.ival = f; \
        PL_bufptr = s; \
        PL_last_uni = PL_oldbufptr; \
        if (*s == '(') \
        PL_bufptr = s; \
        PL_last_uni = PL_oldbufptr; \
        if (*s == '(') \
@@ -255,15 +283,15 @@ static const char* const lex_state_names[] = {
        }
 
 /* grandfather return to old style */
        }
 
 /* grandfather return to old style */
-#define OLDLOP(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP)
+#define OLDLOP(f) return(pl_yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP)
 
 #ifdef DEBUGGING
 
 
 #ifdef DEBUGGING
 
-/* how to interpret the yylval associated with the token */
+/* how to interpret the pl_yylval associated with the token */
 enum token_type {
     TOKENTYPE_NONE,
     TOKENTYPE_IVAL,
 enum token_type {
     TOKENTYPE_NONE,
     TOKENTYPE_IVAL,
-    TOKENTYPE_OPNUM, /* yylval.ival contains an opcode number */
+    TOKENTYPE_OPNUM, /* pl_yylval.ival contains an opcode number */
     TOKENTYPE_PVAL,
     TOKENTYPE_OPVAL,
     TOKENTYPE_GVVAL
     TOKENTYPE_PVAL,
     TOKENTYPE_OPVAL,
     TOKENTYPE_GVVAL
@@ -343,7 +371,7 @@ static struct debug_tokens {
     { 0,               TOKENTYPE_NONE,         NULL }
 };
 
     { 0,               TOKENTYPE_NONE,         NULL }
 };
 
-/* dump the returned token in rv, plus any optional arg in yylval */
+/* dump the returned token in rv, plus any optional arg in pl_yylval */
 
 STATIC int
 S_tokereport(pTHX_ I32 rv)
 
 STATIC int
 S_tokereport(pTHX_ I32 rv)
@@ -375,22 +403,22 @@ S_tokereport(pTHX_ I32 rv)
        case TOKENTYPE_GVVAL: /* doesn't appear to be used */
            break;
        case TOKENTYPE_IVAL:
        case TOKENTYPE_GVVAL: /* doesn't appear to be used */
            break;
        case TOKENTYPE_IVAL:
-           Perl_sv_catpvf(aTHX_ report, "(ival=%"IVdf")", (IV)yylval.ival);
+           Perl_sv_catpvf(aTHX_ report, "(ival=%"IVdf")", (IV)pl_yylval.ival);
            break;
        case TOKENTYPE_OPNUM:
            Perl_sv_catpvf(aTHX_ report, "(ival=op_%s)",
            break;
        case TOKENTYPE_OPNUM:
            Perl_sv_catpvf(aTHX_ report, "(ival=op_%s)",
-                                   PL_op_name[yylval.ival]);
+                                   PL_op_name[pl_yylval.ival]);
            break;
        case TOKENTYPE_PVAL:
            break;
        case TOKENTYPE_PVAL:
-           Perl_sv_catpvf(aTHX_ report, "(pval=\"%s\")", yylval.pval);
+           Perl_sv_catpvf(aTHX_ report, "(pval=\"%s\")", pl_yylval.pval);
            break;
        case TOKENTYPE_OPVAL:
            break;
        case TOKENTYPE_OPVAL:
-           if (yylval.opval) {
+           if (pl_yylval.opval) {
                Perl_sv_catpvf(aTHX_ report, "(opval=op_%s)",
                Perl_sv_catpvf(aTHX_ report, "(opval=op_%s)",
-                                   PL_op_name[yylval.opval->op_type]);
-               if (yylval.opval->op_type == OP_CONST) {
+                                   PL_op_name[pl_yylval.opval->op_type]);
+               if (pl_yylval.opval->op_type == OP_CONST) {
                    Perl_sv_catpvf(aTHX_ report, " %s",
                    Perl_sv_catpvf(aTHX_ report, " %s",
-                       SvPEEK(cSVOPx_sv(yylval.opval)));
+                       SvPEEK(cSVOPx_sv(pl_yylval.opval)));
                }
 
            }
                }
 
            }
@@ -430,11 +458,11 @@ S_ao(pTHX_ int toketype)
     if (*PL_bufptr == '=') {
        PL_bufptr++;
        if (toketype == ANDAND)
     if (*PL_bufptr == '=') {
        PL_bufptr++;
        if (toketype == ANDAND)
-           yylval.ival = OP_ANDASSIGN;
+           pl_yylval.ival = OP_ANDASSIGN;
        else if (toketype == OROR)
        else if (toketype == OROR)
-           yylval.ival = OP_ORASSIGN;
+           pl_yylval.ival = OP_ORASSIGN;
        else if (toketype == DORDOR)
        else if (toketype == DORDOR)
-           yylval.ival = OP_DORASSIGN;
+           pl_yylval.ival = OP_DORASSIGN;
        toketype = ASSIGNOP;
     }
     return toketype;
        toketype = ASSIGNOP;
     }
     return toketype;
@@ -531,6 +559,9 @@ S_missingterm(pTHX_ char *s)
 #define FEATURE_IS_ENABLED(name)                                       \
        ((0 != (PL_hints & HINT_LOCALIZE_HH))                           \
            && S_feature_is_enabled(aTHX_ STR_WITH_LEN(name)))
 #define FEATURE_IS_ENABLED(name)                                       \
        ((0 != (PL_hints & HINT_LOCALIZE_HH))                           \
            && S_feature_is_enabled(aTHX_ STR_WITH_LEN(name)))
+/* The longest string we pass in.  */
+#define MAX_FEATURE_LEN (sizeof("switch")-1)
+
 /*
  * S_feature_is_enabled
  * Check whether the named feature is enabled.
 /*
  * S_feature_is_enabled
  * Check whether the named feature is enabled.
@@ -540,8 +571,9 @@ S_feature_is_enabled(pTHX_ const char *name, STRLEN namelen)
 {
     dVAR;
     HV * const hinthv = GvHV(PL_hintgv);
 {
     dVAR;
     HV * const hinthv = GvHV(PL_hintgv);
-    char he_name[32] = "feature_";
-    (void) my_strlcpy(&he_name[8], name, 24);
+    char he_name[8 + MAX_FEATURE_LEN] = "feature_";
+    assert(namelen <= MAX_FEATURE_LEN);
+    memcpy(&he_name[8], name, namelen);
 
     return (hinthv && hv_exists(hinthv, he_name, 8 + namelen));
 }
 
     return (hinthv && hv_exists(hinthv, he_name, 8 + namelen));
 }
@@ -615,22 +647,30 @@ S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 
 /*
  * Perl_lex_start
 
 /*
  * Perl_lex_start
- * Initialize variables.  Uses the Perl save_stack to save its state (for
- * recursive calls to the parser).
+ *
+ * Create a parser object and initialise its parser and lexer fields
+ *
+ * rsfp       is the opened file handle to read from (if any),
+ *
+ * line       holds any initial content already read from the file (or in
+ *            the case of no file, such as an eval, the whole contents);
+ *
+ * new_filter indicates that this is a new file and it shouldn't inherit
+ *            the filters from the current parser (ie require).
  */
 
 void
  */
 
 void
-Perl_lex_start(pTHX_ SV *line)
+Perl_lex_start(pTHX_ SV *line, PerlIO *rsfp, bool new_filter)
 {
     dVAR;
     const char *s = NULL;
     STRLEN len;
 {
     dVAR;
     const char *s = NULL;
     STRLEN len;
-    yy_parser *parser;
+    yy_parser *parser, *oparser;
 
     /* create and initialise a parser */
 
     Newxz(parser, 1, yy_parser);
 
     /* create and initialise a parser */
 
     Newxz(parser, 1, yy_parser);
-    parser->old_parser = PL_parser;
+    parser->old_parser = oparser = PL_parser;
     PL_parser = parser;
 
     Newx(parser->stack, YYINITDEPTH, yy_stack_frame);
     PL_parser = parser;
 
     Newx(parser->stack, YYINITDEPTH, yy_stack_frame);
@@ -641,77 +681,77 @@ Perl_lex_start(pTHX_ SV *line)
     parser->yyerrstatus = 0;
     parser->yychar = YYEMPTY;          /* Cause a token to be read.  */
 
     parser->yyerrstatus = 0;
     parser->yychar = YYEMPTY;          /* Cause a token to be read.  */
 
+    /* on scope exit, free this parser and restore any outer one */
+    SAVEPARSER(parser);
+    parser->saved_curcop = PL_curcop;
+
     /* initialise lexer state */
 
     /* initialise lexer state */
 
-    SAVEI32(PL_lex_state);
 #ifdef PERL_MAD
 #ifdef PERL_MAD
-    if (PL_lex_state == LEX_KNOWNEXT) {
-       I32 toke = parser->old_parser->lasttoke;
-       while (--toke >= 0) {
-           SAVEI32(PL_nexttoke[toke].next_type);
-           SAVEVPTR(PL_nexttoke[toke].next_val);
-           if (PL_madskills)
-               SAVEVPTR(PL_nexttoke[toke].next_mad);
-       }
-    }
-    SAVEI32(PL_curforce);
+    parser->curforce = -1;
 #else
 #else
-    if (PL_lex_state == LEX_KNOWNEXT) {
-       I32 toke = PL_nexttoke;
-       while (--toke >= 0) {
-           SAVEI32(PL_nexttype[toke]);
-           SAVEVPTR(PL_nextval[toke]);
-       }
-       SAVEI32(PL_nexttoke);
-    }
+    parser->nexttoke = 0;
 #endif
 #endif
-    SAVECOPLINE(PL_curcop);
-    SAVEPPTR(PL_bufptr);
-    SAVEPPTR(PL_bufend);
-    SAVEPPTR(PL_oldbufptr);
-    SAVEPPTR(PL_oldoldbufptr);
-    SAVEPPTR(PL_last_lop);
-    SAVEPPTR(PL_last_uni);
-    SAVEPPTR(PL_linestart);
-    SAVESPTR(PL_linestr);
-    SAVEDESTRUCTOR_X(restore_rsfp, PL_rsfp);
-    SAVEINT(PL_expect);
+    parser->copline = NOLINE;
+    parser->lex_state = LEX_NORMAL;
+    parser->expect = XSTATE;
+    parser->rsfp = rsfp;
+    parser->rsfp_filters = (new_filter || !oparser) ? newAV()
+               : (AV*)SvREFCNT_inc(oparser->rsfp_filters);
 
 
-    PL_copline = NOLINE;
-    PL_lex_state = LEX_NORMAL;
-    PL_expect = XSTATE;
     Newx(parser->lex_brackstack, 120, char);
     Newx(parser->lex_casestack, 12, char);
     *parser->lex_casestack = '\0';
     Newx(parser->lex_brackstack, 120, char);
     Newx(parser->lex_casestack, 12, char);
     *parser->lex_casestack = '\0';
-#ifndef PERL_MAD
-    PL_nexttoke = 0;
-#endif
 
     if (line) {
        s = SvPV_const(line, len);
     } else {
        len = 0;
     }
 
     if (line) {
        s = SvPV_const(line, len);
     } else {
        len = 0;
     }
+
     if (!len) {
     if (!len) {
-       PL_linestr = newSVpvs("\n;");
+       parser->linestr = newSVpvs("\n;");
     } else if (SvREADONLY(line) || s[len-1] != ';') {
     } else if (SvREADONLY(line) || s[len-1] != ';') {
-       PL_linestr = newSVsv(line);
+       parser->linestr = newSVsv(line);
        if (s[len-1] != ';')
        if (s[len-1] != ';')
-           sv_catpvs(PL_linestr, "\n;");
+           sv_catpvs(parser->linestr, "\n;");
     } else {
        SvTEMP_off(line);
        SvREFCNT_inc_simple_void_NN(line);
     } else {
        SvTEMP_off(line);
        SvREFCNT_inc_simple_void_NN(line);
-       PL_linestr = line;
-    }
-    /* PL_linestr needs to survive until end of scope, not just the next
-       FREETMPS. See changes 17505 and 17546 which fixed the symptoms only.  */
-    SAVEFREESV(PL_linestr);
-    PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr);
-    PL_bufend = PL_bufptr + SvCUR(PL_linestr);
-    PL_last_lop = PL_last_uni = NULL;
-    PL_rsfp = 0;
+       parser->linestr = line;
+    }
+    parser->oldoldbufptr =
+       parser->oldbufptr =
+       parser->bufptr =
+       parser->linestart = SvPVX(parser->linestr);
+    parser->bufend = parser->bufptr + SvCUR(parser->linestr);
+    parser->last_lop = parser->last_uni = NULL;
 }
 
 }
 
+
+/* delete a parser object */
+
+void
+Perl_parser_free(pTHX_  const yy_parser *parser)
+{
+    PL_curcop = parser->saved_curcop;
+    SvREFCNT_dec(parser->linestr);
+
+    if (parser->rsfp == PerlIO_stdin())
+       PerlIO_clearerr(parser->rsfp);
+    else if (parser->rsfp && parser->old_parser
+                         && parser->rsfp != parser->old_parser->rsfp)
+       PerlIO_close(parser->rsfp);
+    SvREFCNT_dec(parser->rsfp_filters);
+
+    Safefree(parser->stack);
+    Safefree(parser->lex_brackstack);
+    Safefree(parser->lex_casestack);
+    PL_parser = parser->old_parser;
+    Safefree(parser);
+}
+
+
 /*
  * Perl_lex_end
  * Finalizer for lexing operations.  Must be called when the parser is
 /*
  * Perl_lex_end
  * Finalizer for lexing operations.  Must be called when the parser is
@@ -784,8 +824,18 @@ S_incline(pTHX_ const char *s)
     if (t - s > 0) {
        const STRLEN len = t - s;
 #ifndef USE_ITHREADS
     if (t - s > 0) {
        const STRLEN len = t - s;
 #ifndef USE_ITHREADS
-       const char * const cf = CopFILE(PL_curcop);
-       STRLEN tmplen = cf ? strlen(cf) : 0;
+       SV *const temp_sv = CopFILESV(PL_curcop);
+       const char *cf;
+       STRLEN tmplen;
+
+       if (temp_sv) {
+           cf = SvPVX(temp_sv);
+           tmplen = SvCUR(temp_sv);
+       } else {
+           cf = NULL;
+           tmplen = 0;
+       }
+
        if (tmplen > 7 && strnEQ(cf, "(eval ", 6)) {
            /* must copy *{"::_<(eval N)[oldfilename:L]"}
             * to *{"::_<newfilename"} */
        if (tmplen > 7 && strnEQ(cf, "(eval ", 6)) {
            /* must copy *{"::_<(eval N)[oldfilename:L]"}
             * to *{"::_<newfilename"} */
@@ -1168,7 +1218,7 @@ STATIC I32
 S_lop(pTHX_ I32 f, int x, char *s)
 {
     dVAR;
 S_lop(pTHX_ I32 f, int x, char *s)
 {
     dVAR;
-    yylval.ival = f;
+    pl_yylval.ival = f;
     CLINE;
     PL_expect = x;
     PL_bufptr = s;
     CLINE;
     PL_expect = x;
     PL_bufptr = s;
@@ -1249,7 +1299,7 @@ S_curmad(pTHX_ char slot, SV *sv)
     /* keep a slot open for the head of the list? */
     if (slot != '_' && *where && (*where)->mad_key == '^') {
        (*where)->mad_key = slot;
     /* keep a slot open for the head of the list? */
     if (slot != '_' && *where && (*where)->mad_key == '^') {
        (*where)->mad_key = slot;
-       sv_free((*where)->mad_val);
+       sv_free((SV*)((*where)->mad_val));
        (*where)->mad_val = (void*)sv;
     }
     else
        (*where)->mad_val = (void*)sv;
     }
     else
@@ -1297,9 +1347,9 @@ STATIC SV *
 S_newSV_maybe_utf8(pTHX_ const char *start, STRLEN len)
 {
     dVAR;
 S_newSV_maybe_utf8(pTHX_ const char *start, STRLEN len)
 {
     dVAR;
-    SV * const sv = newSVpvn(start,len);
-    if (UTF && !IN_BYTES && is_utf8_string((const U8*)start, len))
-       SvUTF8_on(sv);
+    SV * const sv = newSVpvn_utf8(start, len,
+                                 UTF && !IN_BYTES
+                                 && is_utf8_string((const U8*)start, len));
     return sv;
 }
 
     return sv;
 }
 
@@ -1347,6 +1397,8 @@ S_force_word(pTHX_ register char *start, int token, int check_keyword, int allow
                PL_expect = XOPERATOR;
            }
        }
                PL_expect = XOPERATOR;
            }
        }
+       if (PL_madskills)
+           curmad('g', newSVpvs( "forced" ));
        NEXTVAL_NEXTTOKE.opval
            = (OP*)newSVOP(OP_CONST,0,
                           S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len));
        NEXTVAL_NEXTTOKE.opval
            = (OP*)newSVOP(OP_CONST,0,
                           S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len));
@@ -1451,8 +1503,8 @@ S_force_version(pTHX_ char *s, int guessing)
 #endif
         if (*d == ';' || isSPACE(*d) || *d == '}' || !*d) {
            SV *ver;
 #endif
         if (*d == ';' || isSPACE(*d) || *d == '}' || !*d) {
            SV *ver;
-            s = scan_num(s, &yylval);
-            version = yylval.opval;
+            s = scan_num(s, &pl_yylval);
+            version = pl_yylval.opval;
            ver = cSVOPx(version)->op_sv;
            if (SvPOK(ver) && !SvNIOK(ver)) {
                SvUPGRADE(ver, SVt_PVNV);
            ver = cSVOPx(version)->op_sv;
            if (SvPOK(ver) && !SvNIOK(ver)) {
                SvUPGRADE(ver, SVt_PVNV);
@@ -1518,9 +1570,7 @@ S_tokeq(pTHX_ SV *sv)
        goto finish;
     d = s;
     if ( PL_hints & HINT_NEW_STRING ) {
        goto finish;
     d = s;
     if ( PL_hints & HINT_NEW_STRING ) {
-       pv = sv_2mortal(newSVpvn(SvPVX_const(pv), len));
-       if (SvUTF8(sv))
-           SvUTF8_on(pv);
+       pv = newSVpvn_flags(SvPVX_const(pv), len, SVs_TEMP | SvUTF8(sv));
     }
     while (s < send) {
        if (*s == '\\') {
     }
     while (s < send) {
        if (*s == '\\') {
@@ -1533,7 +1583,7 @@ S_tokeq(pTHX_ SV *sv)
     SvCUR_set(sv, d - SvPVX_const(sv));
   finish:
     if ( PL_hints & HINT_NEW_STRING )
     SvCUR_set(sv, d - SvPVX_const(sv));
   finish:
     if ( PL_hints & HINT_NEW_STRING )
-       return new_constant(NULL, 0, "q", sv, pv, "q");
+       return new_constant(NULL, 0, "q", sv, pv, "q", 1);
     return sv;
 }
 
     return sv;
 }
 
@@ -1555,10 +1605,10 @@ S_tokeq(pTHX_ SV *sv)
 
 /*
  * S_sublex_start
 
 /*
  * S_sublex_start
- * Assumes that yylval.ival is the op we're creating (e.g. OP_LCFIRST).
+ * Assumes that pl_yylval.ival is the op we're creating (e.g. OP_LCFIRST).
  *
  * Pattern matching will set PL_lex_op to the pattern-matching op to
  *
  * Pattern matching will set PL_lex_op to the pattern-matching op to
- * make (we return THING if yylval.ival is OP_NULL, PMFUNC otherwise).
+ * make (we return THING if pl_yylval.ival is OP_NULL, PMFUNC otherwise).
  *
  * OP_CONST and OP_READLINE are easy--just make the new op and return.
  *
  *
  * OP_CONST and OP_READLINE are easy--just make the new op and return.
  *
@@ -1573,10 +1623,10 @@ STATIC I32
 S_sublex_start(pTHX)
 {
     dVAR;
 S_sublex_start(pTHX)
 {
     dVAR;
-    register const I32 op_type = yylval.ival;
+    register const I32 op_type = pl_yylval.ival;
 
     if (op_type == OP_NULL) {
 
     if (op_type == OP_NULL) {
-       yylval.opval = PL_lex_op;
+       pl_yylval.opval = PL_lex_op;
        PL_lex_op = NULL;
        return THING;
     }
        PL_lex_op = NULL;
        return THING;
     }
@@ -1587,13 +1637,11 @@ S_sublex_start(pTHX)
            /* Overloaded constants, nothing fancy: Convert to SVt_PV: */
            STRLEN len;
            const char * const p = SvPV_const(sv, len);
            /* Overloaded constants, nothing fancy: Convert to SVt_PV: */
            STRLEN len;
            const char * const p = SvPV_const(sv, len);
-           SV * const nsv = newSVpvn(p, len);
-           if (SvUTF8(sv))
-               SvUTF8_on(nsv);
+           SV * const nsv = newSVpvn_flags(p, len, SvUTF8(sv));
            SvREFCNT_dec(sv);
            sv = nsv;
        }
            SvREFCNT_dec(sv);
            sv = nsv;
        }
-       yylval.opval = (OP*)newSVOP(op_type, 0, sv);
+       pl_yylval.opval = (OP*)newSVOP(op_type, 0, sv);
        PL_lex_stuff = NULL;
        /* Allow <FH> // "foo" */
        if (op_type == OP_READLINE)
        PL_lex_stuff = NULL;
        /* Allow <FH> // "foo" */
        if (op_type == OP_READLINE)
@@ -1603,20 +1651,20 @@ S_sublex_start(pTHX)
     else if (op_type == OP_BACKTICK && PL_lex_op) {
        /* readpipe() vas overriden */
        cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv = tokeq(PL_lex_stuff);
     else if (op_type == OP_BACKTICK && PL_lex_op) {
        /* readpipe() vas overriden */
        cSVOPx(cLISTOPx(cUNOPx(PL_lex_op)->op_first)->op_first->op_sibling)->op_sv = tokeq(PL_lex_stuff);
-       yylval.opval = PL_lex_op;
+       pl_yylval.opval = PL_lex_op;
        PL_lex_op = NULL;
        PL_lex_stuff = NULL;
        return THING;
     }
 
     PL_sublex_info.super_state = PL_lex_state;
        PL_lex_op = NULL;
        PL_lex_stuff = NULL;
        return THING;
     }
 
     PL_sublex_info.super_state = PL_lex_state;
-    PL_sublex_info.sub_inwhat = op_type;
+    PL_sublex_info.sub_inwhat = (U16)op_type;
     PL_sublex_info.sub_op = PL_lex_op;
     PL_lex_state = LEX_INTERPPUSH;
 
     PL_expect = XTERM;
     if (PL_lex_op) {
     PL_sublex_info.sub_op = PL_lex_op;
     PL_lex_state = LEX_INTERPPUSH;
 
     PL_expect = XTERM;
     if (PL_lex_op) {
-       yylval.opval = PL_lex_op;
+       pl_yylval.opval = PL_lex_op;
        PL_lex_op = NULL;
        return PMFUNC;
     }
        PL_lex_op = NULL;
        return PMFUNC;
     }
@@ -1639,13 +1687,13 @@ S_sublex_push(pTHX)
     ENTER;
 
     PL_lex_state = PL_sublex_info.super_state;
     ENTER;
 
     PL_lex_state = PL_sublex_info.super_state;
-    SAVEI32(PL_lex_dojoin);
+    SAVEBOOL(PL_lex_dojoin);
     SAVEI32(PL_lex_brackets);
     SAVEI32(PL_lex_casemods);
     SAVEI32(PL_lex_starts);
     SAVEI32(PL_lex_brackets);
     SAVEI32(PL_lex_casemods);
     SAVEI32(PL_lex_starts);
-    SAVEI32(PL_lex_state);
+    SAVEI8(PL_lex_state);
     SAVEVPTR(PL_lex_inpat);
     SAVEVPTR(PL_lex_inpat);
-    SAVEI32(PL_lex_inwhat);
+    SAVEI16(PL_lex_inwhat);
     SAVECOPLINE(PL_curcop);
     SAVEPPTR(PL_bufptr);
     SAVEPPTR(PL_bufend);
     SAVECOPLINE(PL_curcop);
     SAVEPPTR(PL_bufptr);
     SAVEPPTR(PL_bufend);
@@ -1700,7 +1748,7 @@ S_sublex_done(pTHX)
        if (SvUTF8(PL_linestr))
            SvUTF8_on(sv);
        PL_expect = XOPERATOR;
        if (SvUTF8(PL_linestr))
            SvUTF8_on(sv);
        PL_expect = XOPERATOR;
-       yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
+       pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
        return THING;
     }
 
        return THING;
     }
 
@@ -1773,7 +1821,7 @@ S_sublex_done(pTHX)
   Returns a pointer to the character scanned up to. If this is
   advanced from the start pointer supplied (i.e. if anything was
   successfully parsed), will leave an OP for the substring scanned
   Returns a pointer to the character scanned up to. If this is
   advanced from the start pointer supplied (i.e. if anything was
   successfully parsed), will leave an OP for the substring scanned
-  in yylval. Caller must intuit reason for not parsing further
+  in pl_yylval. Caller must intuit reason for not parsing further
   by looking at the next characters herself.
 
   In patterns:
   by looking at the next characters herself.
 
   In patterns:
@@ -2238,7 +2286,6 @@ S_scan_const(pTHX_ char *start)
                    SV *res;
                    STRLEN len;
                    const char *str;
                    SV *res;
                    STRLEN len;
                    const char *str;
-                   SV *type;
 
                    if (!e) {
                        yyerror("Missing right brace on \\N{}");
 
                    if (!e) {
                        yyerror("Missing right brace on \\N{}");
@@ -2259,10 +2306,8 @@ S_scan_const(pTHX_ char *start)
                        goto NUM_ESCAPE_INSERT;
                    }
                    res = newSVpvn(s + 1, e - s - 1);
                        goto NUM_ESCAPE_INSERT;
                    }
                    res = newSVpvn(s + 1, e - s - 1);
-                   type = newSVpvn(s - 2,e - s + 3);
                    res = new_constant( NULL, 0, "charnames",
                    res = new_constant( NULL, 0, "charnames",
-                                       res, NULL, SvPVX(type) );
-                   SvREFCNT_dec(type);         
+                                       res, NULL, s - 2, e - s + 3 );
                    if (has_utf8)
                        sv_utf8_upgrade(res);
                    str = SvPV_const(res,len);
                    if (has_utf8)
                        sv_utf8_upgrade(res);
                    str = SvPV_const(res,len);
@@ -2415,19 +2460,29 @@ S_scan_const(pTHX_ char *start)
        SvPV_shrink_to_cur(sv);
     }
 
        SvPV_shrink_to_cur(sv);
     }
 
-    /* return the substring (via yylval) only if we parsed anything */
+    /* return the substring (via pl_yylval) only if we parsed anything */
     if (s > PL_bufptr) {
     if (s > PL_bufptr) {
-       if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) )
-           sv = new_constant(start, s - start,
-                             (const char *)(PL_lex_inpat ? "qr" : "q"),
-                             sv, NULL,
-                             (const char *)
-                             (( PL_lex_inwhat == OP_TRANS
-                                ? "tr"
-                                : ( (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat)
-                                    ? "s"
-                                    : "qq"))));
-       yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
+       if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) ) {
+           const char *const key = PL_lex_inpat ? "qr" : "q";
+           const STRLEN keylen = PL_lex_inpat ? 2 : 1;
+           const char *type;
+           STRLEN typelen;
+
+           if (PL_lex_inwhat == OP_TRANS) {
+               type = "tr";
+               typelen = 2;
+           } else if (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat) {
+               type = "s";
+               typelen = 1;
+           } else  {
+               type = "qq";
+               typelen = 2;
+           }
+
+           sv = S_new_constant(aTHX_ start, s - start, key, keylen, sv, NULL,
+                               type, typelen);
+       }
+       pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
     } else
        SvREFCNT_dec(sv);
     return s;
     } else
        SvREFCNT_dec(sv);
     return s;
@@ -2646,7 +2701,8 @@ S_intuit_method(pTHX_ char *start, GV *gv, CV *cv)
      */
 
     if (*start == '$') {
      */
 
     if (*start == '$') {
-       if (gv || PL_last_lop_op == OP_PRINT || isUPPER(*PL_tokenbuf))
+       if (gv || PL_last_lop_op == OP_PRINT || PL_last_lop_op == OP_SAY ||
+               isUPPER(*PL_tokenbuf))
            return 0;
 #ifdef PERL_MAD
        len = start - SvPVX(PL_linestr);
            return 0;
 #ifdef PERL_MAD
        len = start - SvPVX(PL_linestr);
@@ -2698,29 +2754,6 @@ S_intuit_method(pTHX_ char *start, GV *gv, CV *cv)
     return 0;
 }
 
     return 0;
 }
 
-/*
- * S_incl_perldb
- * Return a string of Perl code to load the debugger.  If PERL5DB
- * is set, it will return the contents of that, otherwise a
- * compile-time require of perl5db.pl.
- */
-
-STATIC const char*
-S_incl_perldb(pTHX)
-{
-    dVAR;
-    if (PL_perldb) {
-       const char * const pdb = PerlEnv_getenv("PERL5DB");
-
-       if (pdb)
-           return pdb;
-       SETERRNO(0,SS_NORMAL);
-       return "BEGIN { require 'perl5db.pl' }";
-    }
-    return "";
-}
-
-
 /* Encoded script support. filter_add() effectively inserts a
  * 'pre-processing' function into the current source input stream.
  * Note that the filter function only applies to the current source file
 /* Encoded script support. filter_add() effectively inserts a
  * 'pre-processing' function into the current source input stream.
  * Note that the filter function only applies to the current source file
@@ -2745,6 +2778,9 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
     if (!funcp)
        return NULL;
 
     if (!funcp)
        return NULL;
 
+    if (!PL_parser)
+       return NULL;
+
     if (!PL_rsfp_filters)
        PL_rsfp_filters = newAV();
     if (!datasv)
     if (!PL_rsfp_filters)
        PL_rsfp_filters = newAV();
     if (!datasv)
@@ -2772,7 +2808,7 @@ Perl_filter_del(pTHX_ filter_t funcp)
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p",
                          FPTR2DPTR(void*, funcp)));
 #endif
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p",
                          FPTR2DPTR(void*, funcp)));
 #endif
-    if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0)
+    if (!PL_parser || !PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0)
        return;
     /* if filter is on top of stack (usual case) just pop it off */
     datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters));
        return;
     /* if filter is on top of stack (usual case) just pop it off */
     datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters));
@@ -2808,7 +2844,7 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
 #endif
        : maxlen;
 
 #endif
        : maxlen;
 
-    if (!PL_rsfp_filters)
+    if (!PL_parser || !PL_rsfp_filters)
        return -1;
     if (idx > AvFILLp(PL_rsfp_filters)) {       /* Any more filters?   */
        /* Provide a default input filter to make life easy.    */
        return -1;
     if (idx > AvFILLp(PL_rsfp_filters)) {       /* Any more filters?   */
        /* Provide a default input filter to make life easy.    */
@@ -2881,7 +2917,7 @@ S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
 }
 
 STATIC HV *
 }
 
 STATIC HV *
-S_find_in_my_stash(pTHX_ const char *pkgname, I32 len)
+S_find_in_my_stash(pTHX_ const char *pkgname, STRLEN len)
 {
     dVAR;
     GV *gv;
 {
     dVAR;
     GV *gv;
@@ -2901,10 +2937,10 @@ S_find_in_my_stash(pTHX_ const char *pkgname, I32 len)
     if (gv && GvCV(gv)) {
        SV * const sv = cv_const_sv(GvCV(gv));
        if (sv)
     if (gv && GvCV(gv)) {
        SV * const sv = cv_const_sv(GvCV(gv));
        if (sv)
-            pkgname = SvPV_nolen_const(sv);
+            pkgname = SvPV_const(sv, len);
     }
 
     }
 
-    return gv_stashpv(pkgname, 0);
+    return gv_stashpvn(pkgname, len, 0);
 }
 
 /*
 }
 
 /*
@@ -2917,7 +2953,7 @@ S_readpipe_override(pTHX)
 {
     GV **gvp;
     GV *gv_readpipe = gv_fetchpvs("readpipe", GV_NOTQUAL, SVt_PVCV);
 {
     GV **gvp;
     GV *gv_readpipe = gv_fetchpvs("readpipe", GV_NOTQUAL, SVt_PVCV);
-    yylval.ival = OP_BACKTICK;
+    pl_yylval.ival = OP_BACKTICK;
     if ((gv_readpipe
                && GvCVu(gv_readpipe) && GvIMPORTED_CV(gv_readpipe))
            ||
     if ((gv_readpipe
                && GvCVu(gv_readpipe) && GvIMPORTED_CV(gv_readpipe))
            ||
@@ -2930,9 +2966,6 @@ S_readpipe_override(pTHX)
                newSVOP(OP_CONST, 0, &PL_sv_undef), /* value will be read later */
                newCVREF(0, newGVOP(OP_GV, 0, gv_readpipe))));
     }
                newSVOP(OP_CONST, 0, &PL_sv_undef), /* value will be read later */
                newCVREF(0, newGVOP(OP_GV, 0, gv_readpipe))));
     }
-    else {
-       set_csh();
-    }
 }
 
 #ifdef PERL_MAD 
 }
 
 #ifdef PERL_MAD 
@@ -3043,8 +3076,8 @@ Perl_madlex(pTHX)
     case FUNC0SUB:
     case UNIOPSUB:
     case LSTOPSUB:
     case FUNC0SUB:
     case UNIOPSUB:
     case LSTOPSUB:
-       if (yylval.opval)
-           append_madprops(PL_thismad, yylval.opval, 0);
+       if (pl_yylval.opval)
+           append_madprops(PL_thismad, pl_yylval.opval, 0);
        PL_thismad = 0;
        return optype;
 
        PL_thismad = 0;
        return optype;
 
@@ -3114,7 +3147,7 @@ Perl_madlex(pTHX)
     }
 
     /* Create new token struct.  Note: opvals return early above. */
     }
 
     /* Create new token struct.  Note: opvals return early above. */
-    yylval.tkval = newTOKEN(optype, yylval, PL_thismad);
+    pl_yylval.tkval = newTOKEN(optype, pl_yylval, PL_thismad);
     PL_thismad = 0;
     return optype;
 }
     PL_thismad = 0;
     return optype;
 }
@@ -3143,7 +3176,7 @@ S_tokenize_use(pTHX_ int is_use, char *s) {
        s = force_word(s,WORD,FALSE,TRUE,FALSE);
        s = force_version(s, FALSE);
     }
        s = force_word(s,WORD,FALSE,TRUE,FALSE);
        s = force_version(s, FALSE);
     }
-    yylval.ival = is_use;
+    pl_yylval.ival = is_use;
     return s;
 }
 #ifdef DEBUGGING
     return s;
 }
 #ifdef DEBUGGING
@@ -3224,7 +3257,7 @@ Perl_yylex(pTHX)
     case LEX_KNOWNEXT:
 #ifdef PERL_MAD
        PL_lasttoke--;
     case LEX_KNOWNEXT:
 #ifdef PERL_MAD
        PL_lasttoke--;
-       yylval = PL_nexttoke[PL_lasttoke].next_val;
+       pl_yylval = PL_nexttoke[PL_lasttoke].next_val;
        if (PL_madskills) {
            PL_thismad = PL_nexttoke[PL_lasttoke].next_mad;
            PL_nexttoke[PL_lasttoke].next_mad = 0;
        if (PL_madskills) {
            PL_thismad = PL_nexttoke[PL_lasttoke].next_mad;
            PL_nexttoke[PL_lasttoke].next_mad = 0;
@@ -3244,7 +3277,7 @@ Perl_yylex(pTHX)
        }
 #else
        PL_nexttoke--;
        }
 #else
        PL_nexttoke--;
-       yylval = PL_nextval[PL_nexttoke];
+       pl_yylval = PL_nextval[PL_nexttoke];
        if (!PL_nexttoke) {
            PL_lex_state = PL_lex_defer;
            PL_expect = PL_lex_expect;
        if (!PL_nexttoke) {
            PL_lex_state = PL_lex_defer;
            PL_expect = PL_lex_expect;
@@ -3345,8 +3378,10 @@ Perl_yylex(pTHX)
                else
                    Perl_croak(aTHX_ "panic: yylex");
                if (PL_madskills) {
                else
                    Perl_croak(aTHX_ "panic: yylex");
                if (PL_madskills) {
-                   SV* const tmpsv = newSVpvs("");
-                   Perl_sv_catpvf(aTHX_ tmpsv, "\\%c", *s);
+                   SV* const tmpsv = newSVpvs("\\ ");
+                   /* replace the space with the character we want to escape
+                    */
+                   SvPVX(tmpsv)[1] = *s;
                    curmad('_', tmpsv);
                }
                PL_bufptr = s + 1;
                    curmad('_', tmpsv);
                }
                PL_bufptr = s + 1;
@@ -3457,8 +3492,8 @@ Perl_yylex(pTHX)
            if (!PL_lex_inpat)
                sv = tokeq(sv);
            else if ( PL_hints & HINT_NEW_RE )
            if (!PL_lex_inpat)
                sv = tokeq(sv);
            else if ( PL_hints & HINT_NEW_RE )
-               sv = new_constant(NULL, 0, "qr", sv, sv, "q");
-           yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
+               sv = new_constant(NULL, 0, "qr", sv, sv, "q", 1);
+           pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
            s = PL_bufend;
        }
        else {
            s = PL_bufend;
        }
        else {
@@ -3474,7 +3509,7 @@ Perl_yylex(pTHX)
            if (PL_madskills) {
                curmad('X', newSVpvn(PL_bufptr,s-PL_bufptr));
            }
            if (PL_madskills) {
                curmad('X', newSVpvn(PL_bufptr,s-PL_bufptr));
            }
-           NEXTVAL_NEXTTOKE = yylval;
+           NEXTVAL_NEXTTOKE = pl_yylval;
            PL_expect = XTERM;
            force_next(THING);
            if (PL_lex_starts++) {
            PL_expect = XTERM;
            force_next(THING);
            if (PL_lex_starts++) {
@@ -3522,7 +3557,8 @@ Perl_yylex(pTHX)
     default:
        if (isIDFIRST_lazy_if(s,UTF))
            goto keylookup;
     default:
        if (isIDFIRST_lazy_if(s,UTF))
            goto keylookup;
-       Perl_croak(aTHX_ "Unrecognized character \\x%02X", *s & 255);
+       len = UTF ? Perl_utf8_length(aTHX_ (U8 *) PL_linestart, (U8 *) s) : (STRLEN) (s - PL_linestart);
+       Perl_croak(aTHX_ "Unrecognized character \\x%02X in column %d", *s & 255, (int) len + 1);
     case 4:
     case 26:
        goto fake_eof;                  /* emulate EOF on ^D or ^Z */
     case 4:
     case 26:
        goto fake_eof;                  /* emulate EOF on ^D or ^Z */
@@ -3555,15 +3591,29 @@ Perl_yylex(pTHX)
            if (PL_madskills)
                PL_faketokens = 1;
 #endif
            if (PL_madskills)
                PL_faketokens = 1;
 #endif
-           sv_setpv(PL_linestr,incl_perldb());
-           if (SvCUR(PL_linestr))
-               sv_catpvs(PL_linestr,";");
-           if (PL_preambleav){
-               while(AvFILLp(PL_preambleav) >= 0) {
-                   SV *tmpsv = av_shift(PL_preambleav);
-                   sv_catsv(PL_linestr, tmpsv);
+           if (PL_perldb) {
+               /* Generate a string of Perl code to load the debugger.
+                * If PERL5DB is set, it will return the contents of that,
+                * otherwise a compile-time require of perl5db.pl.  */
+
+               const char * const pdb = PerlEnv_getenv("PERL5DB");
+
+               if (pdb) {
+                   sv_setpv(PL_linestr, pdb);
+                   sv_catpvs(PL_linestr,";");
+               } else {
+                   SETERRNO(0,SS_NORMAL);
+                   sv_setpvs(PL_linestr, "BEGIN { require 'perl5db.pl' };");
+               }
+           } else
+               sv_setpvs(PL_linestr,"");
+           if (PL_preambleav) {
+               SV **svp = AvARRAY(PL_preambleav);
+               SV **const end = svp + AvFILLp(PL_preambleav);
+               while(svp <= end) {
+                   sv_catsv(PL_linestr, *svp);
+                   ++svp;
                    sv_catpvs(PL_linestr, ";");
                    sv_catpvs(PL_linestr, ";");
-                   sv_free(tmpsv);
                }
                sv_free((SV*)PL_preambleav);
                PL_preambleav = NULL;
                }
                sv_free((SV*)PL_preambleav);
                PL_preambleav = NULL;
@@ -3600,7 +3650,8 @@ Perl_yylex(pTHX)
                }
            }
            if (PL_minus_E)
                }
            }
            if (PL_minus_E)
-               sv_catpvs(PL_linestr,"use feature ':5.10';");
+               sv_catpvs(PL_linestr,
+                         "use feature ':5." STRINGIFY(PERL_VERSION) "';");
            sv_catpvs(PL_linestr, "\n");
            PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
            PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
            sv_catpvs(PL_linestr, "\n");
            PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
            PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
@@ -3631,10 +3682,10 @@ Perl_yylex(pTHX)
                    if (PL_madskills)
                        PL_faketokens = 1;
 #endif
                    if (PL_madskills)
                        PL_faketokens = 1;
 #endif
-                   sv_setpv(PL_linestr,
-                            (const char *)
-                            (PL_minus_p
-                             ? ";}continue{print;}" : ";}"));
+                   if (PL_minus_p)
+                       sv_setpvs(PL_linestr, ";}continue{print;}");
+                   else
+                       sv_setpvs(PL_linestr, ";}");
                    PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
                    PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
                    PL_last_lop = PL_last_uni = NULL;
                    PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
                    PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
                    PL_last_lop = PL_last_uni = NULL;
@@ -3851,17 +3902,18 @@ Perl_yylex(pTHX)
                        const U32 oldpdb = PL_perldb;
                        const bool oldn = PL_minus_n;
                        const bool oldp = PL_minus_p;
                        const U32 oldpdb = PL_perldb;
                        const bool oldn = PL_minus_n;
                        const bool oldp = PL_minus_p;
+                       const char *d1 = d;
 
                        do {
 
                        do {
-                           if (*d == 'M' || *d == 'm' || *d == 'C') {
-                               const char * const m = d;
-                               while (*d && !isSPACE(*d))
-                                   d++;
+                           if (*d1 == 'M' || *d1 == 'm' || *d1 == 'C') {
+                               const char * const m = d1;
+                               while (*d1 && !isSPACE(*d1))
+                                   d1++;
                                Perl_croak(aTHX_ "Too late for \"-%.*s\" option",
                                Perl_croak(aTHX_ "Too late for \"-%.*s\" option",
-                                     (int)(d - m), m);
+                                     (int)(d1 - m), m);
                            }
                            }
-                           d = moreswitches(d);
-                       } while (d);
+                           d1 = moreswitches(d1);
+                       } while (d1);
                        if (PL_doswitches && !switches_done) {
                            int argc = PL_origargc;
                            char **argv = PL_origargv;
                        if (PL_doswitches && !switches_done) {
                            int argc = PL_origargc;
                            char **argv = PL_origargv;
@@ -3906,10 +3958,11 @@ Perl_yylex(pTHX)
 #endif
 #ifdef PERL_MAD
        PL_realtokenstart = -1;
 #endif
 #ifdef PERL_MAD
        PL_realtokenstart = -1;
-       s = SKIPSPACE0(s);
-#else
-       s++;
+       if (!PL_thiswhite)
+           PL_thiswhite = newSVpvs("");
+       sv_catpvn(PL_thiswhite, s, 1);
 #endif
 #endif
+       s++;
        goto retry;
     case '#':
     case '\n':
        goto retry;
     case '#':
     case '\n':
@@ -4194,7 +4247,6 @@ Perl_yylex(pTHX)
                    switch (tmp) {
                    case KEY_or:
                    case KEY_and:
                    switch (tmp) {
                    case KEY_or:
                    case KEY_and:
-                   case KEY_err:
                    case KEY_for:
                    case KEY_unless:
                    case KEY_if:
                    case KEY_for:
                    case KEY_unless:
                    case KEY_if:
@@ -4232,7 +4284,7 @@ Perl_yylex(pTHX)
                        sv_free(sv);
                        if (PL_in_my == KEY_our) {
 #ifdef USE_ITHREADS
                        sv_free(sv);
                        if (PL_in_my == KEY_our) {
 #ifdef USE_ITHREADS
-                           GvUNIQUE_on(cGVOPx_gv(yylval.opval));
+                           GvUNIQUE_on(cGVOPx_gv(pl_yylval.opval));
 #else
                            /* skip to avoid loading attributes.pm */
 #endif
 #else
                            /* skip to avoid loading attributes.pm */
 #endif
@@ -4256,10 +4308,6 @@ Perl_yylex(pTHX)
                        sv_free(sv);
                        CvMETHOD_on(PL_compcv);
                    }
                        sv_free(sv);
                        CvMETHOD_on(PL_compcv);
                    }
-                   else if (!PL_in_my && len == 9 && strnEQ(SvPVX(sv), "assertion", len)) {
-                       sv_free(sv);
-                       CvASSERTION_on(PL_compcv);
-                   }
                    /* After we've set the flags, it could be argued that
                       we don't need to do the attributes.pm-based setting
                       process, and shouldn't bother appending recognized
                    /* After we've set the flags, it could be argued that
                       we don't need to do the attributes.pm-based setting
                       process, and shouldn't bother appending recognized
@@ -4354,7 +4402,9 @@ Perl_yylex(pTHX)
            --PL_lex_brackets;
        if (PL_lex_state == LEX_INTERPNORMAL) {
            if (PL_lex_brackets == 0) {
            --PL_lex_brackets;
        if (PL_lex_state == LEX_INTERPNORMAL) {
            if (PL_lex_brackets == 0) {
-               if (*s != '[' && *s != '{' && (*s != '-' || s[1] != '>'))
+               if (*s == '-' && s[1] == '>')
+                   PL_lex_state = LEX_INTERPENDMAYBE;
+               else if (*s != '[' && *s != '{')
                    PL_lex_state = LEX_INTERPEND;
            }
        }
                    PL_lex_state = LEX_INTERPEND;
            }
        }
@@ -4517,7 +4567,7 @@ Perl_yylex(pTHX)
            }
            break;
        }
            }
            break;
        }
-       yylval.ival = CopLINE(PL_curcop);
+       pl_yylval.ival = CopLINE(PL_curcop);
        if (isSPACE(*s) || *s == '#')
            PL_copline = NOLINE;   /* invalidate current command line number */
        TOKEN('{');
        if (isSPACE(*s) || *s == '#')
            PL_copline = NOLINE;   /* invalidate current command line number */
        TOKEN('{');
@@ -4590,7 +4640,7 @@ Perl_yylex(pTHX)
        }
        else
            PREREF('&');
        }
        else
            PREREF('&');
-       yylval.ival = (OPpENTERSUB_AMPER<<8);
+       pl_yylval.ival = (OPpENTERSUB_AMPER<<8);
        TERM('&');
 
     case '|':
        TERM('&');
 
     case '|':
@@ -4662,7 +4712,7 @@ Perl_yylex(pTHX)
                goto leftbracket;
            }
        }
                goto leftbracket;
            }
        }
-       yylval.ival = 0;
+       pl_yylval.ival = 0;
        OPERATOR(ASSIGNOP);
     case '!':
        s++;
        OPERATOR(ASSIGNOP);
     case '!':
        s++;
@@ -4766,9 +4816,9 @@ Perl_yylex(pTHX)
 
        /* This kludge not intended to be bulletproof. */
        if (PL_tokenbuf[1] == '[' && !PL_tokenbuf[2]) {
 
        /* This kludge not intended to be bulletproof. */
        if (PL_tokenbuf[1] == '[' && !PL_tokenbuf[2]) {
-           yylval.opval = newSVOP(OP_CONST, 0,
+           pl_yylval.opval = newSVOP(OP_CONST, 0,
                                   newSViv(CopARYBASE_get(&PL_compiling)));
                                   newSViv(CopARYBASE_get(&PL_compiling)));
-           yylval.opval->op_private = OPpCONST_ARYBASE;
+           pl_yylval.opval->op_private = OPpCONST_ARYBASE;
            TERM(THING);
        }
 
            TERM(THING);
        }
 
@@ -4964,10 +5014,10 @@ Perl_yylex(pTHX)
                s++;
                if (*s == tmp) {
                    s++;
                s++;
                if (*s == tmp) {
                    s++;
-                   yylval.ival = OPf_SPECIAL;
+                   pl_yylval.ival = OPf_SPECIAL;
                }
                else
                }
                else
-                   yylval.ival = 0;
+                   pl_yylval.ival = 0;
                OPERATOR(DOTDOT);
            }
            if (PL_expect != XOPERATOR)
                OPERATOR(DOTDOT);
            }
            if (PL_expect != XOPERATOR)
@@ -4977,7 +5027,7 @@ Perl_yylex(pTHX)
        /* FALL THROUGH */
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
        /* FALL THROUGH */
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
-       s = scan_num(s, &yylval);
+       s = scan_num(s, &pl_yylval);
        DEBUG_T( { printbuf("### Saw number in %s\n", s); } );
        if (PL_expect == XOPERATOR)
            no_op("Number",s);
        DEBUG_T( { printbuf("### Saw number in %s\n", s); } );
        if (PL_expect == XOPERATOR)
            no_op("Number",s);
@@ -4997,7 +5047,7 @@ Perl_yylex(pTHX)
        }
        if (!s)
            missingterm(NULL);
        }
        if (!s)
            missingterm(NULL);
-       yylval.ival = OP_CONST;
+       pl_yylval.ival = OP_CONST;
        TERM(sublex_start());
 
     case '"':
        TERM(sublex_start());
 
     case '"':
@@ -5014,12 +5064,12 @@ Perl_yylex(pTHX)
        }
        if (!s)
            missingterm(NULL);
        }
        if (!s)
            missingterm(NULL);
-       yylval.ival = OP_CONST;
+       pl_yylval.ival = OP_CONST;
        /* FIXME. I think that this can be const if char *d is replaced by
           more localised variables.  */
        for (d = SvPV(PL_lex_stuff, len); len; len--, d++) {
            if (*d == '$' || *d == '@' || *d == '\\' || !UTF8_IS_INVARIANT((U8)*d)) {
        /* FIXME. I think that this can be const if char *d is replaced by
           more localised variables.  */
        for (d = SvPV(PL_lex_stuff, len); len; len--, d++) {
            if (*d == '$' || *d == '@' || *d == '\\' || !UTF8_IS_INVARIANT((U8)*d)) {
-               yylval.ival = OP_STRINGIFY;
+               pl_yylval.ival = OP_STRINGIFY;
                break;
            }
        }
                break;
            }
        }
@@ -5050,21 +5100,16 @@ Perl_yylex(pTHX)
            while (isDIGIT(*start) || *start == '_')
                start++;
            if (*start == '.' && isDIGIT(start[1])) {
            while (isDIGIT(*start) || *start == '_')
                start++;
            if (*start == '.' && isDIGIT(start[1])) {
-               s = scan_num(s, &yylval);
+               s = scan_num(s, &pl_yylval);
                TERM(THING);
            }
            /* avoid v123abc() or $h{v1}, allow C<print v10;> */
            else if (!isALPHA(*start) && (PL_expect == XTERM
                        || PL_expect == XREF || PL_expect == XSTATE
                        || PL_expect == XTERMORDORDOR)) {
                TERM(THING);
            }
            /* avoid v123abc() or $h{v1}, allow C<print v10;> */
            else if (!isALPHA(*start) && (PL_expect == XTERM
                        || PL_expect == XREF || PL_expect == XSTATE
                        || PL_expect == XTERMORDORDOR)) {
-               /* XXX Use gv_fetchpvn rather than stomping on a const string */
-               const char c = *start;
-               GV *gv;
-               *start = '\0';
-               gv = gv_fetchpv(s, 0, SVt_PVCV);
-               *start = c;
+               GV *const gv = gv_fetchpvn_flags(s, start - s, 0, SVt_PVCV);
                if (!gv) {
                if (!gv) {
-                   s = scan_num(s, &yylval);
+                   s = scan_num(s, &pl_yylval);
                    TERM(THING);
                }
            }
                    TERM(THING);
                }
            }
@@ -5133,7 +5178,7 @@ Perl_yylex(pTHX)
        if (!tmp && PL_expect == XSTATE
              && d < PL_bufend && *d == ':' && *(d + 1) != ':') {
            s = d + 1;
        if (!tmp && PL_expect == XSTATE
              && d < PL_bufend && *d == ':' && *(d + 1) != ':') {
            s = d + 1;
-           yylval.pval = CopLABEL_alloc(PL_tokenbuf);
+           pl_yylval.pval = CopLABEL_alloc(PL_tokenbuf);
            CLINE;
            TOKEN(LABEL);
        }
            CLINE;
            TOKEN(LABEL);
        }
@@ -5144,10 +5189,10 @@ Perl_yylex(pTHX)
        /* Is this a word before a => operator? */
        if (*d == '=' && d[1] == '>') {
            CLINE;
        /* Is this a word before a => operator? */
        if (*d == '=' && d[1] == '>') {
            CLINE;
-           yylval.opval
+           pl_yylval.opval
                = (OP*)newSVOP(OP_CONST, 0,
                               S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len));
                = (OP*)newSVOP(OP_CONST, 0,
                               S_newSV_maybe_utf8(aTHX_ PL_tokenbuf, len));
-           yylval.opval->op_private = OPpCONST_BARE;
+           pl_yylval.opval->op_private = OPpCONST_BARE;
            TERM(WORD);
        }
 
            TERM(WORD);
        }
 
@@ -5178,8 +5223,7 @@ Perl_yylex(pTHX)
            }
            else if (gv && !gvp
                     && -tmp==KEY_lock  /* XXX generalizable kludge */
            }
            else if (gv && !gvp
                     && -tmp==KEY_lock  /* XXX generalizable kludge */
-                    && GvCVu(gv)
-                    && !hv_fetchs(GvHVn(PL_incgv), "Thread.pm", FALSE))
+                    && GvCVu(gv))
            {
                tmp = 0;                /* any sub overrides "weak" keyword */
            }
            {
                tmp = 0;                /* any sub overrides "weak" keyword */
            }
@@ -5290,7 +5334,7 @@ Perl_yylex(pTHX)
 #ifdef PERL_MAD
                if (PL_madskills && !PL_thistoken) {
                    char *start = SvPVX(PL_linestr) + PL_realtokenstart;
 #ifdef PERL_MAD
                if (PL_madskills && !PL_thistoken) {
                    char *start = SvPVX(PL_linestr) + PL_realtokenstart;
-                   PL_thistoken = newSVpv(start,s - start);
+                   PL_thistoken = newSVpvn(start,s - start);
                    PL_realtokenstart = s - SvPVX(PL_linestr);
                }
 #endif
                    PL_realtokenstart = s - SvPVX(PL_linestr);
                }
 #endif
@@ -5298,8 +5342,8 @@ Perl_yylex(pTHX)
                /* Presume this is going to be a bareword of some sort. */
 
                CLINE;
                /* Presume this is going to be a bareword of some sort. */
 
                CLINE;
-               yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
-               yylval.opval->op_private = OPpCONST_BARE;
+               pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
+               pl_yylval.opval->op_private = OPpCONST_BARE;
                /* UTF-8 package name? */
                if (UTF && !IN_BYTES &&
                    is_utf8_string((U8*)SvPVX_const(sv), SvCUR(sv)))
                /* UTF-8 package name? */
                if (UTF && !IN_BYTES &&
                    is_utf8_string((U8*)SvPVX_const(sv), SvCUR(sv)))
@@ -5378,9 +5422,9 @@ Perl_yylex(pTHX)
                /* Is this a word before a => operator? */
                if (*s == '=' && s[1] == '>' && !pkgname) {
                    CLINE;
                /* Is this a word before a => operator? */
                if (*s == '=' && s[1] == '>' && !pkgname) {
                    CLINE;
-                   sv_setpv(((SVOP*)yylval.opval)->op_sv, PL_tokenbuf);
+                   sv_setpv(((SVOP*)pl_yylval.opval)->op_sv, PL_tokenbuf);
                    if (UTF && !IN_BYTES && is_utf8_string((U8*)PL_tokenbuf, len))
                    if (UTF && !IN_BYTES && is_utf8_string((U8*)PL_tokenbuf, len))
-                     SvUTF8_on(((SVOP*)yylval.opval)->op_sv);
+                     SvUTF8_on(((SVOP*)pl_yylval.opval)->op_sv);
                    TERM(WORD);
                }
 
                    TERM(WORD);
                }
 
@@ -5393,16 +5437,6 @@ Perl_yylex(pTHX)
                            d++;
                        if (*d == ')' && (sv = gv_const_sv(gv))) {
                            s = d + 1;
                            d++;
                        if (*d == ')' && (sv = gv_const_sv(gv))) {
                            s = d + 1;
-#ifdef PERL_MAD
-                           if (PL_madskills) {
-                               char *par = SvPVX(PL_linestr) + PL_realtokenstart; 
-                               sv_catpvn(PL_thistoken, par, s - par);
-                               if (PL_nextwhite) {
-                                   sv_free(PL_nextwhite);
-                                   PL_nextwhite = 0;
-                               }
-                           }
-#endif
                            goto its_constant;
                        }
                    }
                            goto its_constant;
                        }
                    }
@@ -5413,7 +5447,7 @@ Perl_yylex(pTHX)
                    }
                    start_force(PL_curforce);
 #endif
                    }
                    start_force(PL_curforce);
 #endif
-                   NEXTVAL_NEXTTOKE.opval = yylval.opval;
+                   NEXTVAL_NEXTTOKE.opval = pl_yylval.opval;
                    PL_expect = XOPERATOR;
 #ifdef PERL_MAD
                    if (PL_madskills) {
                    PL_expect = XOPERATOR;
 #ifdef PERL_MAD
                    if (PL_madskills) {
@@ -5423,7 +5457,7 @@ Perl_yylex(pTHX)
                    }
 #endif
                    force_next(WORD);
                    }
 #endif
                    force_next(WORD);
-                   yylval.ival = 0;
+                   pl_yylval.ival = 0;
                    TOKEN('&');
                }
 
                    TOKEN('&');
                }
 
@@ -5452,9 +5486,9 @@ Perl_yylex(pTHX)
                    /* Check for a constant sub */
                    if ((sv = gv_const_sv(gv))) {
                  its_constant:
                    /* Check for a constant sub */
                    if ((sv = gv_const_sv(gv))) {
                  its_constant:
-                       SvREFCNT_dec(((SVOP*)yylval.opval)->op_sv);
-                       ((SVOP*)yylval.opval)->op_sv = SvREFCNT_inc_simple(sv);
-                       yylval.opval->op_private = 0;
+                       SvREFCNT_dec(((SVOP*)pl_yylval.opval)->op_sv);
+                       ((SVOP*)pl_yylval.opval)->op_sv = SvREFCNT_inc_simple(sv);
+                       pl_yylval.opval->op_private = 0;
                        TOKEN(WORD);
                    }
 
                        TOKEN(WORD);
                    }
 
@@ -5467,9 +5501,9 @@ Perl_yylex(pTHX)
                        cv = GvCV(gv);
                    }
 
                        cv = GvCV(gv);
                    }
 
-                   op_free(yylval.opval);
-                   yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
-                   yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
+                   op_free(pl_yylval.opval);
+                   pl_yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
+                   pl_yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
                    PL_last_lop = PL_oldbufptr;
                    PL_last_lop_op = OP_ENTERSUB;
                    /* Is there a prototype? */
                    PL_last_lop = PL_oldbufptr;
                    PL_last_lop_op = OP_ENTERSUB;
                    /* Is there a prototype? */
@@ -5488,10 +5522,10 @@ Perl_yylex(pTHX)
                        while (*proto == ';')
                            proto++;
                        if (*proto == '&' && *s == '{') {
                        while (*proto == ';')
                            proto++;
                        if (*proto == '&' && *s == '{') {
-                           sv_setpv(PL_subname,
-                                    (const char *)
-                                    (PL_curstash ?
-                                     "__ANON__" : "__ANON__::__ANON__"));
+                           if (PL_curstash)
+                               sv_setpvs(PL_subname, "__ANON__");
+                           else
+                               sv_setpvs(PL_subname, "__ANON__::__ANON__");
                            PREBLOCK(LSTOPSUB);
                        }
                    }
                            PREBLOCK(LSTOPSUB);
                        }
                    }
@@ -5502,7 +5536,7 @@ Perl_yylex(pTHX)
                            PL_thiswhite = 0;
                        }
                        start_force(PL_curforce);
                            PL_thiswhite = 0;
                        }
                        start_force(PL_curforce);
-                       NEXTVAL_NEXTTOKE.opval = yylval.opval;
+                       NEXTVAL_NEXTTOKE.opval = pl_yylval.opval;
                        PL_expect = XTERM;
                        if (PL_madskills) {
                            PL_nextwhite = nextPL_nextwhite;
                        PL_expect = XTERM;
                        if (PL_madskills) {
                            PL_nextwhite = nextPL_nextwhite;
@@ -5535,15 +5569,15 @@ Perl_yylex(pTHX)
                    }
                    if (probable_sub) {
                        gv = gv_fetchpv(PL_tokenbuf, GV_ADD, SVt_PVCV);
                    }
                    if (probable_sub) {
                        gv = gv_fetchpv(PL_tokenbuf, GV_ADD, SVt_PVCV);
-                       op_free(yylval.opval);
-                       yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
-                       yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
+                       op_free(pl_yylval.opval);
+                       pl_yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
+                       pl_yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
                        PL_last_lop = PL_oldbufptr;
                        PL_last_lop_op = OP_ENTERSUB;
                        PL_nextwhite = PL_thiswhite;
                        PL_thiswhite = 0;
                        start_force(PL_curforce);
                        PL_last_lop = PL_oldbufptr;
                        PL_last_lop_op = OP_ENTERSUB;
                        PL_nextwhite = PL_thiswhite;
                        PL_thiswhite = 0;
                        start_force(PL_curforce);
-                       NEXTVAL_NEXTTOKE.opval = yylval.opval;
+                       NEXTVAL_NEXTTOKE.opval = pl_yylval.opval;
                        PL_expect = XTERM;
                        PL_nextwhite = nextPL_nextwhite;
                        curmad('X', PL_thistoken);
                        PL_expect = XTERM;
                        PL_nextwhite = nextPL_nextwhite;
                        curmad('X', PL_thistoken);
@@ -5552,7 +5586,7 @@ Perl_yylex(pTHX)
                        TOKEN(NOAMP);
                    }
 #else
                        TOKEN(NOAMP);
                    }
 #else
-                   NEXTVAL_NEXTTOKE.opval = yylval.opval;
+                   NEXTVAL_NEXTTOKE.opval = pl_yylval.opval;
                    PL_expect = XTERM;
                    force_next(WORD);
                    TOKEN(NOAMP);
                    PL_expect = XTERM;
                    force_next(WORD);
                    TOKEN(NOAMP);
@@ -5562,7 +5596,7 @@ Perl_yylex(pTHX)
                /* Call it a bare word */
 
                if (PL_hints & HINT_STRICT_SUBS)
                /* Call it a bare word */
 
                if (PL_hints & HINT_STRICT_SUBS)
-                   yylval.opval->op_private |= OPpCONST_STRICT;
+                   pl_yylval.opval->op_private |= OPpCONST_STRICT;
                else {
                bareword:
                    if (lastchar != '-') {
                else {
                bareword:
                    if (lastchar != '-') {
@@ -5591,17 +5625,17 @@ Perl_yylex(pTHX)
            }
 
        case KEY___FILE__:
            }
 
        case KEY___FILE__:
-           yylval.opval = (OP*)newSVOP(OP_CONST, 0,
+           pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0,
                                        newSVpv(CopFILE(PL_curcop),0));
            TERM(THING);
 
        case KEY___LINE__:
                                        newSVpv(CopFILE(PL_curcop),0));
            TERM(THING);
 
        case KEY___LINE__:
-            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
+            pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0,
                                     Perl_newSVpvf(aTHX_ "%"IVdf, (IV)CopLINE(PL_curcop)));
            TERM(THING);
 
        case KEY___PACKAGE__:
                                     Perl_newSVpvf(aTHX_ "%"IVdf, (IV)CopLINE(PL_curcop)));
            TERM(THING);
 
        case KEY___PACKAGE__:
-           yylval.opval = (OP*)newSVOP(OP_CONST, 0,
+           pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0,
                                        (PL_curstash
                                         ? newSVhek(HvNAME_HEK(PL_curstash))
                                         : &PL_sv_undef));
                                        (PL_curstash
                                         ? newSVhek(HvNAME_HEK(PL_curstash))
                                         : &PL_sv_undef));
@@ -5699,7 +5733,7 @@ Perl_yylex(pTHX)
                        PL_realtokenstart = -1;
                    }
                    while ((s = filter_gets(PL_endwhite, PL_rsfp,
                        PL_realtokenstart = -1;
                    }
                    while ((s = filter_gets(PL_endwhite, PL_rsfp,
-                                SvCUR(PL_endwhite))) != Nullch) ;
+                                SvCUR(PL_endwhite))) != NULL) ;
                }
 #endif
                PL_rsfp = NULL;
                }
 #endif
                PL_rsfp = NULL;
@@ -5841,10 +5875,10 @@ Perl_yylex(pTHX)
                s = force_word(s,WORD,TRUE,TRUE,FALSE);
            if (orig_keyword == KEY_do) {
                orig_keyword = 0;
                s = force_word(s,WORD,TRUE,TRUE,FALSE);
            if (orig_keyword == KEY_do) {
                orig_keyword = 0;
-               yylval.ival = 1;
+               pl_yylval.ival = 1;
            }
            else
            }
            else
-               yylval.ival = 0;
+               pl_yylval.ival = 0;
            OPERATOR(DO);
 
        case KEY_die:
            OPERATOR(DO);
 
        case KEY_die:
@@ -5872,7 +5906,7 @@ Perl_yylex(pTHX)
            PREBLOCK(ELSE);
 
        case KEY_elsif:
            PREBLOCK(ELSE);
 
        case KEY_elsif:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(ELSIF);
 
        case KEY_eq:
            OPERATOR(ELSIF);
 
        case KEY_eq:
@@ -5894,9 +5928,6 @@ Perl_yylex(pTHX)
        case KEY_eof:
            UNI(OP_EOF);
 
        case KEY_eof:
            UNI(OP_EOF);
 
-       case KEY_err:
-           OPERATOR(DOROP);
-
        case KEY_exp:
            UNI(OP_EXP);
 
        case KEY_exp:
            UNI(OP_EXP);
 
@@ -5904,7 +5935,6 @@ Perl_yylex(pTHX)
            UNI(OP_EACH);
 
        case KEY_exec:
            UNI(OP_EACH);
 
        case KEY_exec:
-           set_csh();
            LOP(OP_EXEC,XREF);
 
        case KEY_endhostent:
            LOP(OP_EXEC,XREF);
 
        case KEY_endhostent:
@@ -5927,7 +5957,7 @@ Perl_yylex(pTHX)
 
        case KEY_for:
        case KEY_foreach:
 
        case KEY_for:
        case KEY_foreach:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            s = SKIPSPACE1(s);
            if (PL_expect == XSTATE && isIDFIRST_lazy_if(s,UTF)) {
                char *p = s;
            s = SKIPSPACE1(s);
            if (PL_expect == XSTATE && isIDFIRST_lazy_if(s,UTF)) {
                char *p = s;
@@ -6065,18 +6095,17 @@ Perl_yylex(pTHX)
            FUN0(OP_GETLOGIN);
 
        case KEY_given:
            FUN0(OP_GETLOGIN);
 
        case KEY_given:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(GIVEN);
 
        case KEY_glob:
            OPERATOR(GIVEN);
 
        case KEY_glob:
-           set_csh();
            LOP(OP_GLOB,XTERM);
 
        case KEY_hex:
            UNI(OP_HEX);
 
        case KEY_if:
            LOP(OP_GLOB,XTERM);
 
        case KEY_hex:
            UNI(OP_HEX);
 
        case KEY_if:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(IF);
 
        case KEY_index:
            OPERATOR(IF);
 
        case KEY_index:
@@ -6108,7 +6137,7 @@ Perl_yylex(pTHX)
            UNI(OP_LCFIRST);
 
        case KEY_local:
            UNI(OP_LCFIRST);
 
        case KEY_local:
-           yylval.ival = 0;
+           pl_yylval.ival = 0;
            OPERATOR(LOCAL);
 
        case KEY_length:
            OPERATOR(LOCAL);
 
        case KEY_length:
@@ -6163,7 +6192,7 @@ Perl_yylex(pTHX)
        case KEY_our:
        case KEY_my:
        case KEY_state:
        case KEY_our:
        case KEY_my:
        case KEY_state:
-           PL_in_my = tmp;
+           PL_in_my = (U16)tmp;
            s = SKIPSPACE1(s);
            if (isIDFIRST_lazy_if(s,UTF)) {
 #ifdef PERL_MAD
            s = SKIPSPACE1(s);
            if (isIDFIRST_lazy_if(s,UTF)) {
 #ifdef PERL_MAD
@@ -6187,7 +6216,7 @@ Perl_yylex(pTHX)
                }
 #endif
            }
                }
 #endif
            }
-           yylval.ival = 1;
+           pl_yylval.ival = 1;
            OPERATOR(MY);
 
        case KEY_next:
            OPERATOR(MY);
 
        case KEY_next:
@@ -6228,7 +6257,7 @@ Perl_yylex(pTHX)
            LOP(OP_OPEN,XTERM);
 
        case KEY_or:
            LOP(OP_OPEN,XTERM);
 
        case KEY_or:
-           yylval.ival = OP_OR;
+           pl_yylval.ival = OP_OR;
            OPERATOR(OROP);
 
        case KEY_ord:
            OPERATOR(OROP);
 
        case KEY_ord:
@@ -6274,7 +6303,7 @@ Perl_yylex(pTHX)
            s = scan_str(s,!!PL_madskills,FALSE);
            if (!s)
                missingterm(NULL);
            s = scan_str(s,!!PL_madskills,FALSE);
            if (!s)
                missingterm(NULL);
-           yylval.ival = OP_CONST;
+           pl_yylval.ival = OP_CONST;
            TERM(sublex_start());
 
        case KEY_quotemeta:
            TERM(sublex_start());
 
        case KEY_quotemeta:
@@ -6314,9 +6343,7 @@ Perl_yylex(pTHX)
                            for (; !isSPACE(*d) && len; --len, ++d)
                                /**/;
                        }
                            for (; !isSPACE(*d) && len; --len, ++d)
                                /**/;
                        }
-                       sv = newSVpvn(b, d-b);
-                       if (DO_UTF8(PL_lex_stuff))
-                           SvUTF8_on(sv);
+                       sv = newSVpvn_utf8(b, d-b, DO_UTF8(PL_lex_stuff));
                        words = append_elem(OP_LIST, words,
                                            newSVOP(OP_CONST, 0, tokeq(sv)));
                    }
                        words = append_elem(OP_LIST, words,
                                            newSVOP(OP_CONST, 0, tokeq(sv)));
                    }
@@ -6338,7 +6365,7 @@ Perl_yylex(pTHX)
            s = scan_str(s,!!PL_madskills,FALSE);
            if (!s)
                missingterm(NULL);
            s = scan_str(s,!!PL_madskills,FALSE);
            if (!s)
                missingterm(NULL);
-           yylval.ival = OP_STRINGIFY;
+           pl_yylval.ival = OP_STRINGIFY;
            if (SvIVX(PL_lex_stuff) == '\'')
                SvIV_set(PL_lex_stuff, 0);      /* qq'$foo' should intepolate */
            TERM(sublex_start());
            if (SvIVX(PL_lex_stuff) == '\'')
                SvIV_set(PL_lex_stuff, 0);      /* qq'$foo' should intepolate */
            TERM(sublex_start());
@@ -6374,10 +6401,10 @@ Perl_yylex(pTHX)
            }
            if (orig_keyword == KEY_require) {
                orig_keyword = 0;
            }
            if (orig_keyword == KEY_require) {
                orig_keyword = 0;
-               yylval.ival = 1;
+               pl_yylval.ival = 1;
            }
            else 
            }
            else 
-               yylval.ival = 0;
+               pl_yylval.ival = 0;
            PL_expect = XTERM;
            PL_bufptr = s;
            PL_last_uni = PL_oldbufptr;
            PL_expect = XTERM;
            PL_bufptr = s;
            PL_last_uni = PL_oldbufptr;
@@ -6411,12 +6438,10 @@ Perl_yylex(pTHX)
            UNI(OP_READDIR);
 
        case KEY_readline:
            UNI(OP_READDIR);
 
        case KEY_readline:
-           set_csh();
            UNIDOR(OP_READLINE);
 
        case KEY_readpipe:
            UNIDOR(OP_READLINE);
 
        case KEY_readpipe:
-           set_csh();
-           UNI(OP_BACKTICK);
+           UNIDOR(OP_BACKTICK);
 
        case KEY_rewinddir:
            UNI(OP_REWINDDIR);
 
        case KEY_rewinddir:
            UNI(OP_REWINDDIR);
@@ -6435,7 +6460,7 @@ Perl_yylex(pTHX)
 
        case KEY_s:
            s = scan_subst(s);
 
        case KEY_s:
            s = scan_subst(s);
-           if (yylval.opval)
+           if (pl_yylval.opval)
                TERM(sublex_start());
            else
                TOKEN(1);       /* force error */
                TERM(sublex_start());
            else
                TOKEN(1);       /* force error */
@@ -6680,7 +6705,7 @@ Perl_yylex(pTHX)
                    CURMAD('Q', PL_thisclose);
                    NEXTVAL_NEXTTOKE.opval =
                        (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff);
                    CURMAD('Q', PL_thisclose);
                    NEXTVAL_NEXTTOKE.opval =
                        (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff);
-                   PL_lex_stuff = Nullsv;
+                   PL_lex_stuff = NULL;
                    force_next(THING);
 
                    s = SKIPSPACE2(s,tmpwhite);
                    force_next(THING);
 
                    s = SKIPSPACE2(s,tmpwhite);
@@ -6719,9 +6744,10 @@ Perl_yylex(pTHX)
                }
 #endif
                if (!have_name) {
                }
 #endif
                if (!have_name) {
-                   sv_setpv(PL_subname,
-                            (const char *)
-                            (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"));
+                   if (PL_curstash)
+                       sv_setpvs(PL_subname, "__ANON__");
+                   else
+                       sv_setpvs(PL_subname, "__ANON__::__ANON__");
                    TOKEN(ANONSUB);
                }
 #ifndef PERL_MAD
                    TOKEN(ANONSUB);
                }
 #ifndef PERL_MAD
@@ -6734,7 +6760,6 @@ Perl_yylex(pTHX)
            }
 
        case KEY_system:
            }
 
        case KEY_system:
-           set_csh();
            LOP(OP_SYSTEM,XREF);
 
        case KEY_symlink:
            LOP(OP_SYSTEM,XREF);
 
        case KEY_symlink:
@@ -6790,11 +6815,11 @@ Perl_yylex(pTHX)
            UNI(OP_UNTIE);
 
        case KEY_until:
            UNI(OP_UNTIE);
 
        case KEY_until:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(UNTIL);
 
        case KEY_unless:
            OPERATOR(UNTIL);
 
        case KEY_unless:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(UNLESS);
 
        case KEY_unlink:
            OPERATOR(UNLESS);
 
        case KEY_unlink:
@@ -6826,11 +6851,11 @@ Perl_yylex(pTHX)
            LOP(OP_VEC,XTERM);
 
        case KEY_when:
            LOP(OP_VEC,XTERM);
 
        case KEY_when:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(WHEN);
 
        case KEY_while:
            OPERATOR(WHEN);
 
        case KEY_while:
-           yylval.ival = CopLINE(PL_curcop);
+           pl_yylval.ival = CopLINE(PL_curcop);
            OPERATOR(WHILE);
 
        case KEY_warn:
            OPERATOR(WHILE);
 
        case KEY_warn:
@@ -6867,7 +6892,7 @@ Perl_yylex(pTHX)
            goto just_a_word;
 
        case KEY_xor:
            goto just_a_word;
 
        case KEY_xor:
-           yylval.ival = OP_XOR;
+           pl_yylval.ival = OP_XOR;
            OPERATOR(OROP);
 
        case KEY_y:
            OPERATOR(OROP);
 
        case KEY_y:
@@ -6888,6 +6913,9 @@ S_pending_ident(pTHX)
     PADOFFSET tmp = 0;
     /* pit holds the identifier we read and pending_ident is reset */
     char pit = PL_pending_ident;
     PADOFFSET tmp = 0;
     /* pit holds the identifier we read and pending_ident is reset */
     char pit = PL_pending_ident;
+    const STRLEN tokenbuf_len = strlen(PL_tokenbuf);
+    /* All routes through this function want to know if there is a colon.  */
+    const char *const has_colon = (const char*) memchr (PL_tokenbuf, ':', tokenbuf_len);
     PL_pending_ident = 0;
 
     /* PL_realtokenstart = realtokenend = PL_bufptr - SvPVX(PL_linestr); */
     PL_pending_ident = 0;
 
     /* PL_realtokenstart = realtokenend = PL_bufptr - SvPVX(PL_linestr); */
@@ -6902,19 +6930,19 @@ S_pending_ident(pTHX)
     */
     if (PL_in_my) {
         if (PL_in_my == KEY_our) {     /* "our" is merely analogous to "my" */
     */
     if (PL_in_my) {
         if (PL_in_my == KEY_our) {     /* "our" is merely analogous to "my" */
-            if (strchr(PL_tokenbuf,':'))
+            if (has_colon)
                 yyerror(Perl_form(aTHX_ "No package name allowed for "
                                   "variable %s in \"our\"",
                                   PL_tokenbuf));
             tmp = allocmy(PL_tokenbuf);
         }
         else {
                 yyerror(Perl_form(aTHX_ "No package name allowed for "
                                   "variable %s in \"our\"",
                                   PL_tokenbuf));
             tmp = allocmy(PL_tokenbuf);
         }
         else {
-            if (strchr(PL_tokenbuf,':'))
+            if (has_colon)
                 yyerror(Perl_form(aTHX_ PL_no_myglob,
                            PL_in_my == KEY_my ? "my" : "state", PL_tokenbuf));
 
                 yyerror(Perl_form(aTHX_ PL_no_myglob,
                            PL_in_my == KEY_my ? "my" : "state", PL_tokenbuf));
 
-            yylval.opval = newOP(OP_PADANY, 0);
-            yylval.opval->op_targ = allocmy(PL_tokenbuf);
+            pl_yylval.opval = newOP(OP_PADANY, 0);
+            pl_yylval.opval->op_targ = allocmy(PL_tokenbuf);
             return PRIVATEREF;
         }
     }
             return PRIVATEREF;
         }
     }
@@ -6931,7 +6959,7 @@ S_pending_ident(pTHX)
        (although why you'd do that is anyone's guess).
     */
 
        (although why you'd do that is anyone's guess).
     */
 
-    if (!strchr(PL_tokenbuf,':')) {
+    if (!has_colon) {
        if (!PL_in_my)
            tmp = pad_findmy(PL_tokenbuf);
         if (tmp != NOT_IN_PAD) {
        if (!PL_in_my)
            tmp = pad_findmy(PL_tokenbuf);
         if (tmp != NOT_IN_PAD) {
@@ -6942,9 +6970,9 @@ S_pending_ident(pTHX)
                HEK * const stashname = HvNAME_HEK(stash);
                SV *  const sym = newSVhek(stashname);
                 sv_catpvs(sym, "::");
                HEK * const stashname = HvNAME_HEK(stash);
                SV *  const sym = newSVhek(stashname);
                 sv_catpvs(sym, "::");
-                sv_catpv(sym, PL_tokenbuf+1);
-                yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym);
-                yylval.opval->op_private = OPpCONST_ENTERED;
+                sv_catpvn(sym, PL_tokenbuf+1, tokenbuf_len - 1);
+                pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, sym);
+                pl_yylval.opval->op_private = OPpCONST_ENTERED;
                 gv_fetchsv(sym,
                     (PL_in_eval
                         ? (GV_ADDMULTI | GV_ADDINEVAL)
                 gv_fetchsv(sym,
                     (PL_in_eval
                         ? (GV_ADDMULTI | GV_ADDINEVAL)
@@ -6973,8 +7001,8 @@ S_pending_ident(pTHX)
                 }
             }
 
                 }
             }
 
-            yylval.opval = newOP(OP_PADANY, 0);
-            yylval.opval->op_targ = tmp;
+            pl_yylval.opval = newOP(OP_PADANY, 0);
+            pl_yylval.opval->op_targ = tmp;
             return PRIVATEREF;
         }
     }
             return PRIVATEREF;
         }
     }
@@ -6985,7 +7013,8 @@ S_pending_ident(pTHX)
        table.
     */
     if (pit == '@' && PL_lex_state != LEX_NORMAL && !PL_lex_brackets) {
        table.
     */
     if (pit == '@' && PL_lex_state != LEX_NORMAL && !PL_lex_brackets) {
-        GV *gv = gv_fetchpv(PL_tokenbuf+1, 0, SVt_PVAV);
+        GV *const gv = gv_fetchpvn_flags(PL_tokenbuf + 1, tokenbuf_len - 1, 0,
+                                        SVt_PVAV);
         if ((!gv || ((PL_tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)))
                && ckWARN(WARN_AMBIGUOUS)
                /* DO NOT warn for @- and @+ */
         if ((!gv || ((PL_tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)))
                && ckWARN(WARN_AMBIGUOUS)
                /* DO NOT warn for @- and @+ */
@@ -7001,10 +7030,11 @@ S_pending_ident(pTHX)
     }
 
     /* build ops for a bareword */
     }
 
     /* build ops for a bareword */
-    yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0));
-    yylval.opval->op_private = OPpCONST_ENTERED;
-    gv_fetchpv(
-           PL_tokenbuf+1,
+    pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpvn(PL_tokenbuf + 1,
+                                                     tokenbuf_len - 1));
+    pl_yylval.opval->op_private = OPpCONST_ENTERED;
+    gv_fetchpvn_flags(
+           PL_tokenbuf + 1, tokenbuf_len - 1,
            /* If the identifier refers to a stash, don't autovivify it.
             * Change 24660 had the side effect of causing symbol table
             * hashes to always be defined, even if they were freshly
            /* If the identifier refers to a stash, don't autovivify it.
             * Change 24660 had the side effect of causing symbol table
             * hashes to always be defined, even if they were freshly
@@ -7017,7 +7047,9 @@ S_pending_ident(pTHX)
             * tests still give the expected answers, even though what
             * they're actually testing has now changed subtly.
             */
             * tests still give the expected answers, even though what
             * they're actually testing has now changed subtly.
             */
-           (*PL_tokenbuf == '%' && *(d = PL_tokenbuf + strlen(PL_tokenbuf) - 1) == ':' && d[-1] == ':'
+           (*PL_tokenbuf == '%'
+            && *(d = PL_tokenbuf + tokenbuf_len - 1) == ':'
+            && d[-1] == ':'
             ? 0
             : PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : GV_ADD),
            ((PL_tokenbuf[0] == '$') ? SVt_PV
             ? 0
             : PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : GV_ADD),
            ((PL_tokenbuf[0] == '$') ? SVt_PV
@@ -7300,14 +7332,6 @@ Perl_keyword (pTHX_ const char *name, I32 len, bool all_keywords)
 
               goto unknown;
 
 
               goto unknown;
 
-            case 'r':
-              if (name[2] == 'r')
-              {                                   /* err        */
-                return (all_keywords || FEATURE_IS_ENABLED("err") ? -KEY_err : 0);
-              }
-
-              goto unknown;
-
             case 'x':
               if (name[2] == 'p')
               {                                   /* exp        */
             case 'x':
               if (name[2] == 'p')
               {                                   /* exp        */
@@ -10442,7 +10466,11 @@ S_checkcomma(pTHX_ const char *s, const char *name, const char *what)
            }
            while (isSPACE(*w))
                ++w;
            }
            while (isSPACE(*w))
                ++w;
-           if (!*w || !strchr(";|})]oaiuw!=", *w))     /* an advisory hack only... */
+           /* the list of chars below is for end of statements or
+            * block / parens, boolean operators (&&, ||, //) and branch
+            * constructs (or, and, if, until, unless, while, err, for).
+            * Not a very solid hack... */
+           if (!*w || !strchr(";&/|})]oaiuwef!=", *w))
                Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                            "%s (...) interpreted as function",name);
        }
                Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                            "%s (...) interpreted as function",name);
        }
@@ -10478,8 +10506,8 @@ S_checkcomma(pTHX_ const char *s, const char *name, const char *what)
    and type is used with error messages only. */
 
 STATIC SV *
    and type is used with error messages only. */
 
 STATIC SV *
-S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv,
-              const char *type)
+S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen,
+              SV *sv, SV *pv, const char *type, STRLEN typelen)
 {
     dVAR; dSP;
     HV * const table = GvHV(PL_hintgv);                 /* ^H */
 {
     dVAR; dSP;
     HV * const table = GvHV(PL_hintgv);                 /* ^H */
@@ -10513,7 +10541,7 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv,
        SvREFCNT_dec(msg);
        return sv;
     }
        SvREFCNT_dec(msg);
        return sv;
     }
-    cvp = hv_fetch(table, key, strlen(key), FALSE);
+    cvp = hv_fetch(table, key, keylen, FALSE);
     if (!cvp || !SvOK(*cvp)) {
        why1 = "$^H{";
        why2 = key;
     if (!cvp || !SvOK(*cvp)) {
        why1 = "$^H{";
        why2 = key;
@@ -10523,9 +10551,9 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, SV *sv, SV *pv,
     sv_2mortal(sv);                    /* Parent created it permanently */
     cv = *cvp;
     if (!pv && s)
     sv_2mortal(sv);                    /* Parent created it permanently */
     cv = *cvp;
     if (!pv && s)
-       pv = sv_2mortal(newSVpvn(s, len));
+       pv = newSVpvn_flags(s, len, SVs_TEMP);
     if (type && pv)
     if (type && pv)
-       typesv = sv_2mortal(newSVpv(type, 0));
+       typesv = newSVpvn_flags(type, typelen, SVs_TEMP);
     else
        typesv = &PL_sv_undef;
 
     else
        typesv = &PL_sv_undef;
 
@@ -10815,8 +10843,28 @@ S_scan_pat(pTHX_ char *start, I32 type)
     }
 
     pm = (PMOP*)newPMOP(type, 0);
     }
 
     pm = (PMOP*)newPMOP(type, 0);
-    if (PL_multi_open == '?')
+    if (PL_multi_open == '?') {
+       /* This is the only point in the code that sets PMf_ONCE:  */
        pm->op_pmflags |= PMf_ONCE;
        pm->op_pmflags |= PMf_ONCE;
+
+       /* Hence it's safe to do this bit of PMOP book-keeping here, which
+          allows us to restrict the list needed by reset to just the ??
+          matches.  */
+       assert(type != OP_TRANS);
+       if (PL_curstash) {
+           MAGIC *mg = mg_find((SV*)PL_curstash, PERL_MAGIC_symtab);
+           U32 elements;
+           if (!mg) {
+               mg = sv_magicext((SV*)PL_curstash, 0, PERL_MAGIC_symtab, 0, 0,
+                                0);
+           }
+           elements = mg->mg_len / sizeof(PMOP**);
+           Renewc(mg->mg_ptr, elements + 1, PMOP*, char);
+           ((PMOP**)mg->mg_ptr) [elements++] = pm;
+           mg->mg_len = elements * sizeof(PMOP**);
+           PmopSTASH_set(pm,PL_curstash);
+       }
+    }
 #ifdef PERL_MAD
     modstart = s;
 #endif
 #ifdef PERL_MAD
     modstart = s;
 #endif
@@ -10836,10 +10884,8 @@ S_scan_pat(pTHX_ char *start, I32 type)
             "Use of /c modifier is meaningless without /g" );
     }
 
             "Use of /c modifier is meaningless without /g" );
     }
 
-    pm->op_pmpermflags = pm->op_pmflags;
-
     PL_lex_op = (OP*)pm;
     PL_lex_op = (OP*)pm;
-    yylval.ival = OP_MATCH;
+    pl_yylval.ival = OP_MATCH;
     return s;
 }
 
     return s;
 }
 
@@ -10855,7 +10901,7 @@ S_scan_subst(pTHX_ char *start)
     char *modstart;
 #endif
 
     char *modstart;
 #endif
 
-    yylval.ival = OP_NULL;
+    pl_yylval.ival = OP_NULL;
 
     s = scan_str(start,!!PL_madskills,FALSE);
 
 
     s = scan_str(start,!!PL_madskills,FALSE);
 
@@ -10926,8 +10972,12 @@ S_scan_subst(pTHX_ char *start)
        PL_sublex_info.super_bufend = PL_bufend;
        PL_multi_end = 0;
        pm->op_pmflags |= PMf_EVAL;
        PL_sublex_info.super_bufend = PL_bufend;
        PL_multi_end = 0;
        pm->op_pmflags |= PMf_EVAL;
-       while (es-- > 0)
-           sv_catpv(repl, (const char *)(es ? "eval " : "do "));
+       while (es-- > 0) {
+           if (es)
+               sv_catpvs(repl, "eval ");
+           else
+               sv_catpvs(repl, "do ");
+       }
        sv_catpvs(repl, "{");
        sv_catsv(repl, PL_lex_repl);
        if (strchr(SvPVX(PL_lex_repl), '#'))
        sv_catpvs(repl, "{");
        sv_catsv(repl, PL_lex_repl);
        if (strchr(SvPVX(PL_lex_repl), '#'))
@@ -10938,9 +10988,8 @@ S_scan_subst(pTHX_ char *start)
        PL_lex_repl = repl;
     }
 
        PL_lex_repl = repl;
     }
 
-    pm->op_pmpermflags = pm->op_pmflags;
     PL_lex_op = (OP*)pm;
     PL_lex_op = (OP*)pm;
-    yylval.ival = OP_SUBST;
+    pl_yylval.ival = OP_SUBST;
     return s;
 }
 
     return s;
 }
 
@@ -10958,7 +11007,7 @@ S_scan_trans(pTHX_ char *start)
     char *modstart;
 #endif
 
     char *modstart;
 #endif
 
-    yylval.ival = OP_NULL;
+    pl_yylval.ival = OP_NULL;
 
     s = scan_str(start,!!PL_madskills,FALSE);
     if (!s)
 
     s = scan_str(start,!!PL_madskills,FALSE);
     if (!s)
@@ -11020,7 +11069,7 @@ S_scan_trans(pTHX_ char *start)
       (DO_UTF8(PL_lex_repl) ? OPpTRANS_TO_UTF   : 0);
 
     PL_lex_op = o;
       (DO_UTF8(PL_lex_repl) ? OPpTRANS_TO_UTF   : 0);
 
     PL_lex_op = o;
-    yylval.ival = OP_TRANS;
+    pl_yylval.ival = OP_TRANS;
 
 #ifdef PERL_MAD
     if (PL_madskills) {
 
 #ifdef PERL_MAD
     if (PL_madskills) {
@@ -11291,14 +11340,14 @@ retval:
            sv_recode_to_utf8(tmpstr, PL_encoding);
     }
     PL_lex_stuff = tmpstr;
            sv_recode_to_utf8(tmpstr, PL_encoding);
     }
     PL_lex_stuff = tmpstr;
-    yylval.ival = op_type;
+    pl_yylval.ival = op_type;
     return s;
 }
 
 /* scan_inputsymbol
    takes: current position in input buffer
    returns: new position in input buffer
     return s;
 }
 
 /* scan_inputsymbol
    takes: current position in input buffer
    returns: new position in input buffer
-   side-effects: yylval and lex_op are set.
+   side-effects: pl_yylval and lex_op are set.
 
    This code handles:
 
 
    This code handles:
 
@@ -11358,8 +11407,7 @@ S_scan_inputsymbol(pTHX_ char *start)
     */
 
     if (d - PL_tokenbuf != len) {
     */
 
     if (d - PL_tokenbuf != len) {
-       yylval.ival = OP_GLOB;
-       set_csh();
+       pl_yylval.ival = OP_GLOB;
        s = scan_str(start,!!PL_madskills,FALSE);
        if (!s)
           Perl_croak(aTHX_ "Glob not terminated");
        s = scan_str(start,!!PL_madskills,FALSE);
        if (!s)
           Perl_croak(aTHX_ "Glob not terminated");
@@ -11434,8 +11482,8 @@ intro_sym:
            }
            if (!readline_overriden)
                PL_lex_op->op_flags |= OPf_SPECIAL;
            }
            if (!readline_overriden)
                PL_lex_op->op_flags |= OPf_SPECIAL;
-           /* we created the ops in PL_lex_op, so make yylval.ival a null op */
-           yylval.ival = OP_NULL;
+           /* we created the ops in PL_lex_op, so make pl_yylval.ival a null op */
+           pl_yylval.ival = OP_NULL;
        }
 
        /* If it's none of the above, it must be a literal filehandle
        }
 
        /* If it's none of the above, it must be a literal filehandle
@@ -11448,7 +11496,7 @@ intro_sym:
                            newGVOP(OP_GV, 0, gv),
                            newCVREF(0, newGVOP(OP_GV, 0, gv_readline))))
                : (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv));
                            newGVOP(OP_GV, 0, gv),
                            newCVREF(0, newGVOP(OP_GV, 0, gv_readline))))
                : (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv));
-           yylval.ival = OP_NULL;
+           pl_yylval.ival = OP_NULL;
        }
     }
 
        }
     }
 
@@ -11828,7 +11876,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
   scan_num
   takes: pointer to position in buffer
   returns: pointer to new position in buffer
   scan_num
   takes: pointer to position in buffer
   returns: pointer to new position in buffer
-  side-effects: builds ops for the constant in yylval.op
+  side-effects: builds ops for the constant in pl_yylval.op
 
   Read a number in any of the formats that Perl accepts:
 
 
   Read a number in any of the formats that Perl accepts:
 
@@ -12038,9 +12086,9 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
            }
            if (just_zero && (PL_hints & HINT_NEW_INTEGER))
                sv = new_constant(start, s - start, "integer",
            }
            if (just_zero && (PL_hints & HINT_NEW_INTEGER))
                sv = new_constant(start, s - start, "integer",
-                                 sv, NULL, NULL);
+                                 sv, NULL, NULL, 0);
            else if (PL_hints & HINT_NEW_BINARY)
            else if (PL_hints & HINT_NEW_BINARY)
-               sv = new_constant(start, s - start, "binary", sv, NULL, NULL);
+               sv = new_constant(start, s - start, "binary", sv, NULL, NULL, 0);
        }
        break;
 
        }
        break;
 
@@ -12203,20 +12251,20 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
            sv_setnv(sv, nv);
        }
 
            sv_setnv(sv, nv);
        }
 
-       if ( floatit ? (PL_hints & HINT_NEW_FLOAT) :
-                      (PL_hints & HINT_NEW_INTEGER) )
-           sv = new_constant(PL_tokenbuf,
-                             d - PL_tokenbuf,
-                             (const char *)
-                             (floatit ? "float" : "integer"),
-                             sv, NULL, NULL);
+       if ( floatit
+            ? (PL_hints & HINT_NEW_FLOAT) : (PL_hints & HINT_NEW_INTEGER) ) {
+           const char *const key = floatit ? "float" : "integer";
+           const STRLEN keylen = floatit ? 5 : 7;
+           sv = S_new_constant(aTHX_ PL_tokenbuf, d - PL_tokenbuf,
+                               key, keylen, sv, NULL, NULL, 0);
+       }
        break;
 
     /* if it starts with a v, it could be a v-string */
     case 'v':
 vstring:
                sv = newSV(5); /* preallocate storage space */
        break;
 
     /* if it starts with a v, it could be a v-string */
     case 'v':
 vstring:
                sv = newSV(5); /* preallocate storage space */
-               s = scan_vstring(s,sv);
+               s = scan_vstring(s, PL_bufend, sv);
        break;
     }
 
        break;
     }
 
@@ -12361,20 +12409,6 @@ S_scan_formline(pTHX_ register char *s)
     return s;
 }
 
     return s;
 }
 
-STATIC void
-S_set_csh(pTHX)
-{
-#ifdef CSH
-    dVAR;
-    if (!PL_cshlen)
-       PL_cshlen = strlen(PL_cshname);
-#else
-#if defined(USE_ITHREADS)
-    PERL_UNUSED_CONTEXT;
-#endif
-#endif
-}
-
 I32
 Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
 {
 I32
 Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
 {
@@ -12470,11 +12504,13 @@ Perl_yyerror(pTHX_ const char *s)
            where = "within string";
     }
     else {
            where = "within string";
     }
     else {
-       SV * const where_sv = sv_2mortal(newSVpvs("next char "));
+       SV * const where_sv = newSVpvs_flags("next char ", SVs_TEMP);
        if (yychar < 32)
            Perl_sv_catpvf(aTHX_ where_sv, "^%c", toCTRL(yychar));
        if (yychar < 32)
            Perl_sv_catpvf(aTHX_ where_sv, "^%c", toCTRL(yychar));
-       else if (isPRINT_LC(yychar))
-           Perl_sv_catpvf(aTHX_ where_sv, "%c", yychar);
+       else if (isPRINT_LC(yychar)) {
+           const char string = yychar;
+           sv_catpvn(where_sv, &string, 1);
+       }
        else
            Perl_sv_catpvf(aTHX_ where_sv, "\\%03o", yychar & 255);
        where = SvPVX_const(where_sv);
        else
            Perl_sv_catpvf(aTHX_ where_sv, "\\%03o", yychar & 255);
        where = SvPVX_const(where_sv);
@@ -12492,8 +12528,10 @@ Perl_yyerror(pTHX_ const char *s)
                 (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start);
         PL_multi_end = 0;
     }
                 (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start);
         PL_multi_end = 0;
     }
-    if (PL_in_eval & EVAL_WARNONLY && ckWARN_d(WARN_SYNTAX))
-       Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "%"SVf, SVfARG(msg));
+    if (PL_in_eval & EVAL_WARNONLY) {
+       if (ckWARN_d(WARN_SYNTAX))
+           Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "%"SVf, SVfARG(msg));
+    }
     else
        qerror(msg);
     if (PL_error_count >= 10) {
     else
        qerror(msg);
     if (PL_error_count >= 10) {
@@ -12625,23 +12663,6 @@ S_swallow_bom(pTHX_ U8 *s)
     return (char*)s;
 }
 
     return (char*)s;
 }
 
-/*
- * restore_rsfp
- * Restore a source filter.
- */
-
-static void
-restore_rsfp(pTHX_ void *f)
-{
-    dVAR;
-    PerlIO * const fp = (PerlIO*)f;
-
-    if (PL_rsfp == PerlIO_stdin())
-       PerlIO_clearerr(PL_rsfp);
-    else if (PL_rsfp && (PL_rsfp != fp))
-       PerlIO_close(PL_rsfp);
-    PL_rsfp = fp;
-}
 
 #ifndef PERL_NO_UTF16_FILTER
 static I32
 
 #ifndef PERL_NO_UTF16_FILTER
 static I32
@@ -12698,28 +12719,29 @@ vstring, as well as updating the passed in sv.
 Function must be called like
 
        sv = newSV(5);
 Function must be called like
 
        sv = newSV(5);
-       s = scan_vstring(s,sv);
+       s = scan_vstring(s,e,sv);
 
 
+where s and e are the start and end of the string.
 The sv should already be large enough to store the vstring
 passed in, for performance reasons.
 
 */
 
 char *
 The sv should already be large enough to store the vstring
 passed in, for performance reasons.
 
 */
 
 char *
-Perl_scan_vstring(pTHX_ const char *s, SV *sv)
+Perl_scan_vstring(pTHX_ const char *s, const char *e, SV *sv)
 {
     dVAR;
     const char *pos = s;
     const char *start = s;
     if (*pos == 'v') pos++;  /* get past 'v' */
 {
     dVAR;
     const char *pos = s;
     const char *start = s;
     if (*pos == 'v') pos++;  /* get past 'v' */
-    while (pos < PL_bufend && (isDIGIT(*pos) || *pos == '_'))
+    while (pos < e && (isDIGIT(*pos) || *pos == '_'))
        pos++;
     if ( *pos != '.') {
        /* this may not be a v-string if followed by => */
        const char *next = pos;
        pos++;
     if ( *pos != '.') {
        /* this may not be a v-string if followed by => */
        const char *next = pos;
-       while (next < PL_bufend && isSPACE(*next))
+       while (next < e && isSPACE(*next))
            ++next;
            ++next;
-       if ((PL_bufend - next) >= 2 && *next == '=' && next[1] == '>' ) {
+       if ((e - next) >= 2 && *next == '=' && next[1] == '>' ) {
            /* return string not v-string */
            sv_setpvn(sv,(char *)s,pos-s);
            return (char *)pos;
            /* return string not v-string */
            sv_setpvn(sv,(char *)s,pos-s);
            return (char *)pos;
@@ -12759,13 +12781,13 @@ Perl_scan_vstring(pTHX_ const char *s, SV *sv)
            sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
            if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
                 SvUTF8_on(sv);
            sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
            if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
                 SvUTF8_on(sv);
-           if (pos + 1 < PL_bufend && *pos == '.' && isDIGIT(pos[1]))
+           if (pos + 1 < e && *pos == '.' && isDIGIT(pos[1]))
                 s = ++pos;
            else {
                 s = pos;
                 break;
            }
                 s = ++pos;
            else {
                 s = pos;
                 break;
            }
-           while (pos < PL_bufend && (isDIGIT(*pos) || *pos == '_'))
+           while (pos < e && (isDIGIT(*pos) || *pos == '_'))
                 pos++;
        }
        SvPOK_on(sv);
                 pos++;
        }
        SvPOK_on(sv);