This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
io/sem.t: eliminate warnings
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index 4ae9f96..9dcc7c3 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -147,6 +147,15 @@ static const char* const ident_var_zero_multi_digit = "Numeric variables with mo
 #define LEX_INTERPCONST                 2 /* NOT USED */
 #define LEX_FORMLINE            1 /* expecting a format line               */
 
+/* returned to yyl_try() to request it to retry the parse loop, expected to only
+   be returned directly by yyl_fake_eof(), but functions that call yyl_fake_eof()
+   can also return it.
+
+   yylex (aka Perl_yylex) returns 0 on EOF rather than returning -1,
+   other token values are 258 or higher (see perly.h), so -1 should be
+   a safe value here.
+*/
+#define YYL_RETRY (-1)
 
 #ifdef DEBUGGING
 static const char* const lex_state_names[] = {
@@ -196,8 +205,10 @@ static const char* const lex_state_names[] = {
  * Aop          : addition-level operator
  * AopNOASSIGN  : addition-level operator that is never part of .=
  * Mop          : multiplication-level operator
- * Eop          : equality-testing operator
- * Rop          : relational operator <= != gt
+ * ChEop        : chaining equality-testing operator
+ * NCEop        : non-chaining comparison operator at equality precedence
+ * ChRop        : chaining relational operator <= != gt
+ * NCRop        : non-chaining relational operator isa
  *
  * Also see LOP and lop() below.
  */
@@ -234,8 +245,10 @@ static const char* const lex_state_names[] = {
 #define Aop(f)   return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, (int)ADDOP))
 #define AopNOASSIGN(f) return (pl_yylval.ival=f, PL_bufptr=s, REPORT((int)ADDOP))
 #define Mop(f)   return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, (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))
+#define ChEop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)CHEQOP))
+#define NCEop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)NCEQOP))
+#define ChRop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)CHRELOP))
+#define NCRop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)NCRELOP))
 
 /* This bit of chicanery makes a unary function followed by
  * a parenthesis into a function with one argument, highest precedence.
@@ -303,7 +316,6 @@ struct code {
 
 static const struct code no_code = { NULL, NULL, NULL, NULL, NULL, 0, FALSE };
 
-
 #ifdef DEBUGGING
 
 /* how to interpret the pl_yylval associated with the token */
@@ -330,6 +342,8 @@ static struct debug_tokens {
     { ASSIGNOP,                TOKENTYPE_OPNUM,        "ASSIGNOP" },
     { BITANDOP,                TOKENTYPE_OPNUM,        "BITANDOP" },
     { BITOROP,         TOKENTYPE_OPNUM,        "BITOROP" },
+    { CHEQOP,          TOKENTYPE_OPNUM,        "CHEQOP" },
+    { CHRELOP,         TOKENTYPE_OPNUM,        "CHRELOP" },
     { COLONATTR,       TOKENTYPE_NONE,         "COLONATTR" },
     { CONTINUE,                TOKENTYPE_NONE,         "CONTINUE" },
     { DEFAULT,         TOKENTYPE_NONE,         "DEFAULT" },
@@ -340,7 +354,6 @@ static struct debug_tokens {
     { DOTDOT,          TOKENTYPE_IVAL,         "DOTDOT" },
     { ELSE,            TOKENTYPE_NONE,         "ELSE" },
     { ELSIF,           TOKENTYPE_IVAL,         "ELSIF" },
-    { EQOP,            TOKENTYPE_OPNUM,        "EQOP" },
     { FOR,             TOKENTYPE_IVAL,         "FOR" },
     { FORMAT,          TOKENTYPE_NONE,         "FORMAT" },
     { FORMLBRACK,      TOKENTYPE_NONE,         "FORMLBRACK" },
@@ -363,6 +376,8 @@ static struct debug_tokens {
     { METHOD,          TOKENTYPE_OPVAL,        "METHOD" },
     { MULOP,           TOKENTYPE_OPNUM,        "MULOP" },
     { MY,              TOKENTYPE_IVAL,         "MY" },
+    { NCEQOP,          TOKENTYPE_OPNUM,        "NCEQOP" },
+    { NCRELOP,         TOKENTYPE_OPNUM,        "NCRELOP" },
     { NOAMP,           TOKENTYPE_NONE,         "NOAMP" },
     { NOTOP,           TOKENTYPE_NONE,         "NOTOP" },
     { OROP,            TOKENTYPE_IVAL,         "OROP" },
@@ -380,7 +395,6 @@ static struct debug_tokens {
     { PRIVATEREF,      TOKENTYPE_OPVAL,        "PRIVATEREF" },
     { QWLIST,          TOKENTYPE_OPVAL,        "QWLIST" },
     { REFGEN,          TOKENTYPE_NONE,         "REFGEN" },
-    { RELOP,           TOKENTYPE_OPNUM,        "RELOP" },
     { REQUIRE,         TOKENTYPE_NONE,         "REQUIRE" },
     { SHIFTOP,         TOKENTYPE_OPNUM,        "SHIFTOP" },
     { SIGSUB,          TOKENTYPE_NONE,         "SIGSUB" },
@@ -1011,7 +1025,6 @@ function is more convenient.
 void
 Perl_lex_stuff_pvn(pTHX_ const char *pv, STRLEN len, U32 flags)
 {
-    dVAR;
     char *bufptr;
     PERL_ARGS_ASSERT_LEX_STUFF_PVN;
     if (flags & ~(LEX_STUFF_UTF8))
@@ -1443,7 +1456,6 @@ is encountered, an exception is generated.
 I32
 Perl_lex_peek_unichar(pTHX_ U32 flags)
 {
-    dVAR;
     char *s, *bufend;
     if (flags & ~(LEX_KEEP_PREVIOUS))
        Perl_croak(aTHX_ "Lexing code internal error (%s)", "lex_peek_unichar");
@@ -2586,6 +2598,64 @@ S_sublex_done(pTHX)
     }
 }
 
+HV *
+Perl_load_charnames(pTHX_ SV * char_name, const char * context,
+                          const STRLEN context_len, const char ** error_msg)
+{
+    /* Load the official _charnames module if not already there.  The
+     * parameters are just to give info for any error messages generated:
+     *  char_name   a name to look up which is the reason for loading this
+     *  context     'char_name' in the context in the input in which it appears
+     *  context_len how many bytes 'context' occupies
+     *  error_msg   *error_msg will be set to any error
+     *
+     *  Returns the ^H table if success; otherwise NULL */
+
+    unsigned int i;
+    HV * table;
+    SV **cvp;
+    SV * res;
+
+    PERL_ARGS_ASSERT_LOAD_CHARNAMES;
+
+    /* This loop is executed 1 1/2 times.  On the first time through, if it
+     * isn't already loaded, try loading it, and iterate just once to see if it
+     * worked.  */
+    for (i = 0; i < 2; i++) {
+        table = GvHV(PL_hintgv);                /* ^H */
+
+        if (    table
+            && (PL_hints & HINT_LOCALIZE_HH)
+            && (cvp = hv_fetchs(table, "charnames", FALSE))
+            &&  SvOK(*cvp))
+        {
+            return table;   /* Quit if already loaded */
+        }
+
+        if (i == 0) {
+            Perl_load_module(aTHX_
+                0,
+                newSVpvs("_charnames"),
+
+                /* version parameter; no need to specify it, as if we get too early
+                * a version, will fail anyway, not being able to find 'charnames'
+                * */
+                NULL,
+                newSVpvs(":full"),
+                newSVpvs(":short"),
+                NULL);
+        }
+    }
+
+    /* Here, it failed; new_constant will give appropriate error messages */
+    *error_msg = NULL;
+    res = new_constant( NULL, 0, "charnames", char_name, NULL,
+                        context, context_len, error_msg);
+    SvREFCNT_dec(res);
+
+    return NULL;
+}
+
 STATIC SV*
 S_get_and_check_backslash_N_name_wrapper(pTHX_ const char* s, const char* const e)
 {
@@ -2624,41 +2694,54 @@ Perl_get_and_check_backslash_N_name(pTHX_ const char* s,
      * 'is_utf8' is TRUE if we know we want the result to be UTF-8 even if it
      * doesn't have to be. */
 
+    SV* char_name;
     SV* res;
     HV * table;
     SV **cvp;
     SV *cv;
     SV *rv;
     HV *stash;
-    const char* backslash_ptr = s - 3; /* Points to the <\> of \N{... */
-    dVAR;
+
+    /* Points to the beginning of the \N{... so that any messages include the
+     * context of what's failing*/
+    const char* context = s - 3;
+    STRLEN context_len = e - context + 1; /* include all of \N{...} */
+
 
     PERL_ARGS_ASSERT_GET_AND_CHECK_BACKSLASH_N_NAME;
 
     assert(e >= s);
     assert(s > (char *) 3);
 
-    res = newSVpvn_flags(s, e - s, (is_utf8) ? SVf_UTF8 : 0);
+    char_name = newSVpvn_flags(s, e - s, (is_utf8) ? SVf_UTF8 : 0);
 
-    if (!SvCUR(res)) {
-        SvREFCNT_dec_NN(res);
+    if (!SvCUR(char_name)) {
+        SvREFCNT_dec_NN(char_name);
         /* diag_listed_as: Unknown charname '%s' */
         *error_msg = Perl_form(aTHX_ "Unknown charname ''");
         return NULL;
     }
 
-    res = new_constant( NULL, 0, "charnames", res, NULL, backslash_ptr,
-                        /* include the <}> */
-                        e - backslash_ptr + 1, error_msg);
-    if (! SvPOK(res)) {
-        SvREFCNT_dec_NN(res);
+    /* Autoload the charnames module */
+
+    table = load_charnames(char_name, context, context_len, error_msg);
+    if (table == NULL) {
+        return NULL;
+    }
+
+    *error_msg = NULL;
+    res = new_constant( NULL, 0, "charnames", char_name, NULL,
+                        context, context_len, error_msg);
+    if (*error_msg) {
+        *error_msg = Perl_form(aTHX_ "Unknown charname '%s'", SvPVX(char_name));
+
+        SvREFCNT_dec(res);
         return NULL;
     }
 
     /* See if the charnames handler is the Perl core's, and if so, we can skip
      * the validation needed for a user-supplied one, as Perl's does its own
      * validation. */
-    table = GvHV(PL_hintgv);            /* ^H */
     cvp = hv_fetchs(table, "charnames", FALSE);
     if (cvp && (cv = *cvp) && SvROK(cv) && (rv = SvRV(cv),
         SvTYPE(rv) == SVt_PVCV) && ((stash = CvSTASH(rv)) != NULL))
@@ -2755,7 +2838,7 @@ Perl_get_and_check_backslash_N_name(pTHX_ const char* s,
         *error_msg = Perl_form(aTHX_
             "charnames alias definitions may not contain trailing "
             "white-space; marked by <-- HERE in %.*s<-- HERE %.*s",
-            (int)(s - backslash_ptr + 1), backslash_ptr,
+            (int)(s - context + 1), context,
             (int)(e - s + 1), s + 1);
         return NULL;
     }
@@ -2775,7 +2858,7 @@ Perl_get_and_check_backslash_N_name(pTHX_ const char* s,
                                immediately after '%s' */
             *error_msg = Perl_form(aTHX_
                 "Malformed UTF-8 returned by %.*s immediately after '%.*s'",
-                 (int) (e - backslash_ptr + 1), backslash_ptr,
+                 (int) context_len, context,
                  (int) ((char *) first_bad_char_loc - str), str);
             return NULL;
         }
@@ -2791,7 +2874,7 @@ Perl_get_and_check_backslash_N_name(pTHX_ const char* s,
                            in \N{%s} */
         *error_msg = Perl_form(aTHX_
             "Invalid character in \\N{...}; marked by <-- HERE in %.*s<-- HERE %.*s",
-            (int)(s - backslash_ptr + 1), backslash_ptr,
+            (int)(s - context + 1), context,
             (int)(e - s + 1), s + 1);
         return NULL;
     }
@@ -2803,7 +2886,7 @@ Perl_get_and_check_backslash_N_name(pTHX_ const char* s,
         *error_msg = Perl_form(aTHX_
             "charnames alias definitions may not contain a sequence of "
             "multiple spaces; marked by <-- HERE in %.*s<-- HERE %.*s",
-            (int)(s - backslash_ptr + 1), backslash_ptr,
+            (int)(s - context + 1), context,
             (int)(e - s + 1), s + 1);
         return NULL;
 }
@@ -4181,7 +4264,7 @@ S_scan_const(pTHX_ char *start)
            } else if (PL_lex_inpat && SvIVX(PL_linestr) == '\'') {
                type = "q";
                typelen = 1;
-           } else  {
+           } else {
                type = "qq";
                typelen = 2;
            }
@@ -4392,6 +4475,9 @@ S_intuit_method(pTHX_ char *start, SV *ioname, CV *cv)
 
     PERL_ARGS_ASSERT_INTUIT_METHOD;
 
+    if (!FEATURE_INDIRECT_IS_ENABLED)
+        return 0;
+
     if (gv && SvTYPE(gv) == SVt_PVGV && GvIO(gv))
            return 0;
     if (cv && SvPOK(cv)) {
@@ -6252,7 +6338,7 @@ yyl_bang(pTHX_ char *s)
             TOKEN(0);
         }
 
-        Eop(OP_NE);
+        ChEop(OP_NE);
     }
 
     if (tmp == '~')
@@ -6381,7 +6467,7 @@ yyl_tilde(pTHX_ char *s)
         Perl_ck_warner_d(aTHX_
             packWARN(WARN_EXPERIMENTAL__SMARTMATCH),
             "Smartmatch is experimental");
-        Eop(OP_SMARTMATCH);
+        NCEop(OP_SMARTMATCH);
     }
     s++;
     if ((bof = FEATURE_BITWISE_IS_ENABLED) && *s == '.') {
@@ -6449,14 +6535,14 @@ yyl_leftpointy(pTHX_ char *s)
                 s -= 3;
                 TOKEN(0);
             }
-            Eop(OP_NCMP);
+            NCEop(OP_NCMP);
         }
         s--;
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE) {
             s -= 2;
             TOKEN(0);
         }
-        Rop(OP_LE);
+        ChRop(OP_LE);
     }
 
     s--;
@@ -6465,7 +6551,7 @@ yyl_leftpointy(pTHX_ char *s)
         TOKEN(0);
     }
 
-    Rop(OP_LT);
+    ChRop(OP_LT);
 }
 
 static int
@@ -6485,7 +6571,7 @@ yyl_rightpointy(pTHX_ char *s)
             s -= 2;
             TOKEN(0);
         }
-        Rop(OP_GE);
+        ChRop(OP_GE);
     }
 
     s--;
@@ -6494,7 +6580,7 @@ yyl_rightpointy(pTHX_ char *s)
         TOKEN(0);
     }
 
-    Rop(OP_GT);
+    ChRop(OP_GT);
 }
 
 static int
@@ -6513,9 +6599,10 @@ yyl_sglquote(pTHX_ char *s)
 }
 
 static int
-yyl_dblquote(pTHX_ char *s, STRLEN len)
+yyl_dblquote(pTHX_ char *s)
 {
     char *d;
+    STRLEN len;
     s = scan_str(s,FALSE,FALSE,FALSE,NULL);
     DEBUG_T( {
         if (s)
@@ -6809,7 +6896,7 @@ yyl_my(pTHX_ char *s, I32 my)
     OPERATOR(MY);
 }
 
-static int yyl_try(pTHX_ char*, STRLEN);
+static int yyl_try(pTHX_ char*);
 
 static bool
 yyl_eol_needs_semicolon(pTHX_ char **ps)
@@ -6859,7 +6946,7 @@ yyl_eol_needs_semicolon(pTHX_ char **ps)
 }
 
 static int
-yyl_fake_eof(pTHX_ U32 fake_eof, bool bof, char *s, STRLEN len)
+yyl_fake_eof(pTHX_ U32 fake_eof, bool bof, char *s)
 {
     char *d;
 
@@ -7034,7 +7121,6 @@ yyl_fake_eof(pTHX_ U32 fake_eof, bool bof, char *s, STRLEN len)
                 && !instr(s,"indir")
                 && instr(PL_origargv[0],"perl"))
             {
-                dVAR;
                 char **newargv;
 
                 *ipathend = '\0';
@@ -7101,13 +7187,13 @@ yyl_fake_eof(pTHX_ U32 fake_eof, bool bof, char *s, STRLEN len)
                              we must not do it again */
                     {
                         SvPVCLEAR(PL_linestr);
-                        PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+                        PL_bufptr = 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_preambled = FALSE;
                         if (PERLDB_LINE_OR_SAVESRC)
                             (void)gv_fetchfile(PL_origfilename);
-                        return yyl_try(aTHX_ s, len);
+                        return YYL_RETRY;
                     }
                 }
             }
@@ -7120,7 +7206,8 @@ yyl_fake_eof(pTHX_ U32 fake_eof, bool bof, char *s, STRLEN len)
         TOKEN(';');
     }
 
-    return yyl_try(aTHX_ s, len);
+    PL_bufptr = s;
+    return YYL_RETRY;
 }
 
 static int
@@ -7422,7 +7509,7 @@ yyl_just_a_word(pTHX_ char *s, STRLEN len, I32 orig_keyword, struct code c)
 
     /* If followed by var or block, call it a method (unless sub) */
 
-    if ((*s == '$' || *s == '{') && !c.cv) {
+    if ((*s == '$' || *s == '{') && !c.cv && FEATURE_INDIRECT_IS_ENABLED) {
         op_free(c.rv2cv_op);
         PL_last_lop = PL_oldbufptr;
         PL_last_lop_op = OP_METHOD;
@@ -7506,7 +7593,7 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY___END__:
         if (PL_rsfp && (!PL_in_eval || PL_tokenbuf[2] == 'D'))
             yyl_data_handle(aTHX);
-        return yyl_fake_eof(aTHX_ LEX_FAKE_EOF, FALSE, s, len);
+        return yyl_fake_eof(aTHX_ LEX_FAKE_EOF, FALSE, s);
 
     case KEY___SUB__:
         FUN0OP(CvCLONE(PL_compcv)
@@ -7582,18 +7669,13 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_cmp:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Eop(OP_SCMP);
+        NCEop(OP_SCMP);
 
     case KEY_caller:
         UNI(OP_CALLER);
 
     case KEY_crypt:
-#ifdef FCRYPT
-        if (!PL_cryptseen) {
-            PL_cryptseen = TRUE;
-            init_des();
-        }
-#endif
+
         LOP(OP_CRYPT,XTERM);
 
     case KEY_chmod:
@@ -7656,7 +7738,7 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_eq:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Eop(OP_SEQ);
+        ChEop(OP_SEQ);
 
     case KEY_exists:
         UNI(OP_EXISTS);
@@ -7734,12 +7816,12 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_gt:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Rop(OP_SGT);
+        ChRop(OP_SGT);
 
     case KEY_ge:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Rop(OP_SGE);
+        ChRop(OP_SGE);
 
     case KEY_grep:
         LOP(OP_GREPSTART, XREF);
@@ -7858,7 +7940,7 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_isa:
         Perl_ck_warner_d(aTHX_
             packWARN(WARN_EXPERIMENTAL__ISA), "isa is experimental");
-        Rop(OP_ISA);
+        NCRop(OP_ISA);
 
     case KEY_join:
         LOP(OP_JOIN,XTERM);
@@ -7887,12 +7969,12 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_lt:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Rop(OP_SLT);
+        ChRop(OP_SLT);
 
     case KEY_le:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Rop(OP_SLE);
+        ChRop(OP_SLE);
 
     case KEY_localtime:
         UNI(OP_LOCALTIME);
@@ -7945,7 +8027,7 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct
     case KEY_ne:
         if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_COMPARE)
             return REPORT(0);
-        Eop(OP_SNE);
+        ChEop(OP_SNE);
 
     case KEY_no:
         s = tokenize_use(0, s);
@@ -8424,7 +8506,6 @@ yyl_key_core(pTHX_ char *s, STRLEN len, struct code c)
 static int
 yyl_keylookup(pTHX_ char *s, GV *gv)
 {
-    dVAR;
     STRLEN len;
     bool anydelim;
     I32 key;
@@ -8553,22 +8634,30 @@ yyl_keylookup(pTHX_ char *s, GV *gv)
 }
 
 static int
-yyl_try(pTHX_ char *s, STRLEN len)
+yyl_try(pTHX_ char *s)
 {
     char *d;
     GV *gv = NULL;
+    int tok;
 
   retry:
     switch (*s) {
     default:
-        if (UTF ? isIDFIRST_utf8_safe(s, PL_bufend) : isALNUMC(*s))
-            return yyl_keylookup(aTHX_ s, gv);
+        if (UTF ? isIDFIRST_utf8_safe(s, PL_bufend) : isALNUMC(*s)) {
+            if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+                return tok;
+            goto retry_bufptr;
+        }
         yyl_croak_unrecognised(aTHX_ s);
 
     case 4:
     case 26:
         /* emulate EOF on ^D or ^Z */
-        return yyl_fake_eof(aTHX_ LEX_FAKE_EOF, FALSE, s, len);
+        if ((tok = yyl_fake_eof(aTHX_ LEX_FAKE_EOF, FALSE, s)) != YYL_RETRY)
+            return tok;
+    retry_bufptr:
+        s = PL_bufptr;
+        goto retry;
 
     case 0:
        if ((!PL_rsfp || PL_lex_inwhat)
@@ -8624,7 +8713,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
            }
            if (PL_minus_E)
                sv_catpvs(PL_linestr,
-                         "use feature ':5." STRINGIFY(PERL_VERSION) "';");
+                         "use feature ':" STRINGIFY(PERL_REVISION) "." STRINGIFY(PERL_VERSION) "';");
            if (PL_minus_n || PL_minus_p) {
                sv_catpvs(PL_linestr, "LINE: while (<>) {"/*}*/);
                if (PL_minus_l)
@@ -8669,7 +8758,9 @@ yyl_try(pTHX_ char *s, STRLEN len)
                update_debugger_info(PL_linestr, NULL, 0);
            goto retry;
        }
-        return yyl_fake_eof(aTHX_ 0, cBOOL(PL_rsfp), s, len);
+        if ((tok = yyl_fake_eof(aTHX_ 0, cBOOL(PL_rsfp), s)) != YYL_RETRY)
+            return tok;
+        goto retry_bufptr;
 
     case '\r':
 #ifdef PERL_STRICT_CR
@@ -8754,7 +8845,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
 
     case '=':
         if (s[1] == '=' && (s == PL_linestart || s[-1] == '\n')
-            && memBEGINs(s + 2, (STRLEN) (PL_bufend - s + 2), "====="))
+            && memBEGINs(s + 2, (STRLEN) (PL_bufend - (s + 2)), "====="))
         {
             s = vcs_conflict_marker(s + 7);
             goto retry;
@@ -8770,7 +8861,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
                    s -= 2;
                    TOKEN(0);
                }
-               Eop(OP_EQ);
+               ChEop(OP_EQ);
            }
            if (tmp == '>') {
                if (!PL_lex_allbrackets
@@ -8848,7 +8939,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
 
     case '<':
         if (s[1] == '<' && (s == PL_linestart || s[-1] == '\n')
-            && memBEGINs(s+2, (STRLEN) (PL_bufend - (s+2)), "<<<<<"))
+            && memBEGINs(s + 2, (STRLEN) (PL_bufend - (s + 2)), "<<<<<"))
         {
             s = vcs_conflict_marker(s + 7);
             goto retry;
@@ -8857,7 +8948,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
 
     case '>':
         if (s[1] == '>' && (s == PL_linestart || s[-1] == '\n')
-            && memBEGINs(s + 2, (STRLEN) (PL_bufend - s + 2), ">>>>>"))
+            && memBEGINs(s + 2, (STRLEN) (PL_bufend - (s + 2)), ">>>>>"))
         {
             s = vcs_conflict_marker(s + 7);
             goto retry;
@@ -8940,7 +9031,7 @@ yyl_try(pTHX_ char *s, STRLEN len)
         return yyl_sglquote(aTHX_ s);
 
     case '"':
-        return yyl_dblquote(aTHX_ s, len);
+        return yyl_dblquote(aTHX_ s);
 
     case '`':
         return yyl_backtick(aTHX_ s);
@@ -8958,13 +9049,19 @@ yyl_try(pTHX_ char *s, STRLEN len)
                TERM(THING);
            }
            else if ((*start == ':' && start[1] == ':')
-                 || (PL_expect == XSTATE && *start == ':'))
-                return yyl_keylookup(aTHX_ s, gv);
+                     || (PL_expect == XSTATE && *start == ':')) {
+                if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+                    return tok;
+                goto retry_bufptr;
+            }
            else if (PL_expect == XSTATE) {
                d = start;
                while (d < PL_bufend && isSPACE(*d)) d++;
-               if (*d == ':')
-                    return yyl_keylookup(aTHX_ s, gv);
+               if (*d == ':') {
+                    if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+                        return tok;
+                    goto retry_bufptr;
+                }
            }
            /* avoid v123abc() or $h{v1}, allow C<print v10;> */
            if (!isALPHA(*start) && (PL_expect == XTERM
@@ -8978,14 +9075,18 @@ yyl_try(pTHX_ char *s, STRLEN len)
                }
            }
        }
-        return yyl_keylookup(aTHX_ s, gv);
+        if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+            return tok;
+        goto retry_bufptr;
 
     case 'x':
        if (isDIGIT(s[1]) && PL_expect == XOPERATOR) {
            s++;
            Mop(OP_REPEAT);
        }
-        return yyl_keylookup(aTHX_ s, gv);
+        if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+            return tok;
+        goto retry_bufptr;
 
     case '_':
     case 'a': case 'A':
@@ -9014,7 +9115,9 @@ yyl_try(pTHX_ char *s, STRLEN len)
              case 'X':
     case 'y': case 'Y':
     case 'z': case 'Z':
-        return yyl_keylookup(aTHX_ s, gv);
+        if ((tok = yyl_keylookup(aTHX_ s, gv)) != YYL_RETRY)
+            return tok;
+        goto retry_bufptr;
     }
 }
 
@@ -9073,7 +9176,6 @@ yyl_try(pTHX_ char *s, STRLEN len)
 int
 Perl_yylex(pTHX)
 {
-    dVAR;
     char *s = PL_bufptr;
 
     if (UNLIKELY(PL_parser->recheck_utf8_validity)) {
@@ -9322,7 +9424,7 @@ Perl_yylex(pTHX)
            expecting an operator) have been a sigil.
         */
         bool expected_operator = (PL_expect == XOPERATOR);
-        int ret = yyl_try(aTHX_ s, 0);
+        int ret = yyl_try(aTHX_ s);
         switch (pl_yylval.ival) {
         case OP_BIT_AND:
         case OP_MODULO:
@@ -9592,75 +9694,31 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen,
     SV **cvp;
     SV *cv, *typesv;
     const char *why1 = "", *why2 = "", *why3 = "";
+    const char * optional_colon = ":";  /* Only some messages have a colon */
+    char *msg;
 
     PERL_ARGS_ASSERT_NEW_CONSTANT;
     /* We assume that this is true: */
-    if (*key == 'c') { assert (strEQ(key, "charnames")); }
     assert(type || s);
 
     sv_2mortal(sv);                    /* Parent created it permanently */
-    if (!table
-       || ! (PL_hints & HINT_LOCALIZE_HH)
-       || ! (cvp = hv_fetch(table, key, keylen, FALSE))
-       || ! SvOK(*cvp))
+
+    if (   ! table
+       || ! (PL_hints & HINT_LOCALIZE_HH))
     {
-       char *msg;
-
-       /* Here haven't found what we're looking for.  If it is charnames,
-        * perhaps it needs to be loaded.  Try doing that before giving up */
-       if (*key == 'c') {
-           Perl_load_module(aTHX_
-                           0,
-                           newSVpvs("_charnames"),
-                            /* version parameter; no need to specify it, as if
-                             * we get too early a version, will fail anyway,
-                             * not being able to find '_charnames' */
-                           NULL,
-                           newSVpvs(":full"),
-                           newSVpvs(":short"),
-                           NULL);
-            assert(sp == PL_stack_sp);
-           table = GvHV(PL_hintgv);
-           if (table
-               && (PL_hints & HINT_LOCALIZE_HH)
-               && (cvp = hv_fetch(table, key, keylen, FALSE))
-               && SvOK(*cvp))
-           {
-               goto now_ok;
-           }
-       }
-       if (!table || !(PL_hints & HINT_LOCALIZE_HH)) {
-           msg = Perl_form(aTHX_
-                              "Constant(%.*s) unknown",
-                               (int)(type ? typelen : len),
-                               (type ? type: s));
-       }
-       else {
-            why1 = "$^H{";
-            why2 = key;
-            why3 = "} is not defined";
-        report:
-            if (*key == 'c') {
-                msg = Perl_form(aTHX_
-                            /* The +3 is for '\N{'; -4 for that, plus '}' */
-                            "Unknown charname '%.*s'", (int)typelen - 4, type + 3
-                      );
-            }
-            else {
-                msg = Perl_form(aTHX_ "Constant(%.*s): %s%s%s",
-                                    (int)(type ? typelen : len),
-                                    (type ? type: s), why1, why2, why3);
-            }
-        }
-        if (error_msg) {
-            *error_msg = msg;
-        }
-        else {
-            yyerror_pv(msg, UTF ? SVf_UTF8 : 0);
-        }
-       return SvREFCNT_inc_simple_NN(sv);
+        why1 = "unknown";
+        optional_colon = "";
+        goto report;
     }
-  now_ok:
+
+    cvp = hv_fetch(table, key, keylen, FALSE);
+    if (!cvp || !SvOK(*cvp)) {
+        why1 = "$^H{";
+        why2 = key;
+        why3 = "} is not defined";
+        goto report;
+    }
+
     cv = *cvp;
     if (!pv && s)
        pv = newSVpvn_flags(s, len, SVs_TEMP);
@@ -9705,16 +9763,31 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen,
     LEAVE ;
     POPSTACK;
 
-    if (!SvOK(res)) {
-       why1 = "Call to &{$^H{";
-       why2 = key;
-       why3 = "}} did not return a defined value";
-       sv = res;
-       (void)sv_2mortal(sv);
-       goto report;
+    if (SvOK(res)) {
+        return res;
     }
 
-    return res;
+    sv = res;
+    (void)sv_2mortal(sv);
+
+    why1 = "Call to &{$^H{";
+    why2 = key;
+    why3 = "}} did not return a defined value";
+
+  report:
+
+    msg = Perl_form(aTHX_ "Constant(%.*s)%s %s%s%s",
+                        (int)(type ? typelen : len),
+                        (type ? type: s),
+                        optional_colon,
+                        why1, why2, why3);
+    if (error_msg) {
+        *error_msg = msg;
+    }
+    else {
+        yyerror_pv(msg, UTF ? SVf_UTF8 : 0);
+    }
+    return SvREFCNT_inc_simple_NN(sv);
 }
 
 PERL_STATIC_INLINE void
@@ -11267,7 +11340,7 @@ Perl_scan_str(pTHX_ char *start, int keep_bracketed_quoted, int keep_delims, int
     /* if we allocated too much space, give some back */
     if (SvCUR(sv) + 5 < SvLEN(sv)) {
        SvLEN_set(sv, SvCUR(sv) + 1);
-       SvPV_renew(sv, SvLEN(sv));
+       SvPV_shrink_to_cur(sv);
     }
 
     /* decide whether this is the first or second quoted string we've read
@@ -12683,7 +12756,7 @@ look something like this:
 
     static Perl_keyword_plugin_t next_keyword_plugin;
     static OP *my_keyword_plugin(pTHX_
-        char *keyword_plugin, STRLEN keyword_len, OP **op_ptr)
+        char *keyword_ptr, STRLEN keyword_len, OP **op_ptr)
     {
         if (memEQs(keyword_ptr, keyword_len,
                    "my_new_keyword")) {
@@ -12706,7 +12779,6 @@ void
 Perl_wrap_keyword_plugin(pTHX_
     Perl_keyword_plugin_t new_plugin, Perl_keyword_plugin_t *old_plugin_p)
 {
-    dVAR;
 
     PERL_UNUSED_CONTEXT;
     PERL_ARGS_ASSERT_WRAP_KEYWORD_PLUGIN;