Fix bug id 20020427.004 on %^H.
[p5sagit/p5-mst-13.2.git] / toke.c
diff --git a/toke.c b/toke.c
index cf219b2..7d37b39 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -1,6 +1,6 @@
 /*    toke.c
  *
- *    Copyright (c) 1991-2001, Larry Wall
+ *    Copyright (c) 1991-2002, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 #define yylval PL_yylval
 
 static char ident_too_long[] = "Identifier too long";
+static char c_without_g[] = "Use of /c modifier is meaningless without /g";
+static char c_in_subst[] = "Use of /c modifier is meaningless in s///";
 
-static void restore_rsfp(pTHXo_ void *f);
+static void restore_rsfp(pTHX_ void *f);
 #ifndef PERL_NO_UTF16_FILTER
-static I32 utf16_textfilter(pTHXo_ int idx, SV *sv, int maxlen);
-static I32 utf16rev_textfilter(pTHXo_ int idx, SV *sv, int maxlen);
+static I32 utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen);
+static I32 utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen);
 #endif
 
 #define XFAKEBRACK 128
 #define XENUMMASK 127
 
-#ifdef EBCDIC
-/* For now 'use utf8' does not affect tokenizer on EBCDIC */
-#define UTF (PL_linestr && DO_UTF8(PL_linestr))
+#ifdef USE_UTF8_SCRIPTS
+#   define UTF (!IN_BYTES)
 #else
-#define UTF ((PL_linestr && DO_UTF8(PL_linestr)) || (PL_hints & HINT_UTF8))
+#   ifdef EBCDIC /* For now 'use utf8' does not affect tokenizer on EBCDIC */
+#       define UTF (PL_linestr && DO_UTF8(PL_linestr))
+#   else
+#       define UTF ((PL_linestr && DO_UTF8(PL_linestr)) || (PL_hints & HINT_UTF8))
+#   endif
 #endif
 
 /* In variables named $^X, these are the legal values for X.
@@ -297,7 +302,7 @@ S_missingterm(pTHX_ char *s)
        s = tmpbuf;
     }
     else {
-       *tmpbuf = PL_multi_close;
+       *tmpbuf = (char)PL_multi_close;
        tmpbuf[1] = '\0';
        s = tmpbuf;
     }
@@ -313,7 +318,23 @@ void
 Perl_deprecate(pTHX_ char *s)
 {
     if (ckWARN(WARN_DEPRECATED))
-       Perl_warner(aTHX_ WARN_DEPRECATED, "Use of %s is deprecated", s);
+       Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), "Use of %s is deprecated", s);
+}
+
+void
+Perl_deprecate_old(pTHX_ char *s)
+{
+    /* This function should NOT be called for any new deprecated warnings */
+    /* Use Perl_deprecate instead                                         */
+    /*                                                                    */
+    /* It is here to maintain backward compatibility with the pre-5.8     */
+    /* warnings category hierarchy. The "deprecated" category used to     */
+    /* live under the "syntax" category. It is now a top-level category   */
+    /* in its own right.                                                  */
+
+    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
+       Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), 
+                       "Use of %s is deprecated", s);
 }
 
 /*
@@ -324,7 +345,7 @@ Perl_deprecate(pTHX_ char *s)
 STATIC void
 S_depcom(pTHX)
 {
-    deprecate("comma-less variable list");
+    deprecate_old("comma-less variable list");
 }
 
 /*
@@ -442,8 +463,6 @@ Perl_lex_start(pTHX_ SV *line)
     PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr);
     PL_bufend = PL_bufptr + SvCUR(PL_linestr);
     PL_last_lop = PL_last_uni = Nullch;
-    SvREFCNT_dec(PL_rs);
-    PL_rs = newSVpvn("\n", 1);
     PL_rsfp = 0;
 }
 
@@ -513,11 +532,7 @@ S_incline(pTHX_ char *s)
     ch = *t;
     *t = '\0';
     if (t - s > 0) {
-#ifdef USE_ITHREADS
-       Safefree(CopFILE(PL_curcop));
-#else
-       SvREFCNT_dec(CopFILEGV(PL_curcop));
-#endif
+       CopFILE_free(PL_curcop);
        CopFILE_set(PL_curcop, s);
     }
     *t = ch;
@@ -633,6 +648,8 @@ S_skipspace(pTHX_ register char *s)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
+            (void)SvIOK_on(sv);
+            SvIVX(sv) = 0;
            av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
        }
     }
@@ -663,42 +680,13 @@ S_check_uni(pTHX)
     if (ckWARN_d(WARN_AMBIGUOUS)){
         char ch = *s;
         *s = '\0';
-        Perl_warner(aTHX_ WARN_AMBIGUOUS,
+        Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                   "Warning: Use of \"%s\" without parens is ambiguous",
                   PL_last_uni);
         *s = ch;
     }
 }
 
-/* workaround to replace the UNI() macro with a function.  Only the
- * hints/uts.sh file mentions this.  Other comments elsewhere in the
- * source indicate Microport Unix might need it too.
- */
-
-#ifdef CRIPPLED_CC
-
-#undef UNI
-#define UNI(f) return uni(f,s)
-
-STATIC int
-S_uni(pTHX_ I32 f, char *s)
-{
-    yylval.ival = f;
-    PL_expect = XTERM;
-    PL_bufptr = s;
-    PL_last_uni = PL_oldbufptr;
-    PL_last_lop_op = f;
-    if (*s == '(')
-       return FUNC1;
-    s = skipspace(s);
-    if (*s == '(')
-       return FUNC1;
-    else
-       return UNIOP;
-}
-
-#endif /* CRIPPLED_CC */
-
 /*
  * LOP : macro to build a list operator.  Its behaviour has been replaced
  * with a subroutine, S_lop() for which LOP is just another name.
@@ -723,7 +711,7 @@ S_lop(pTHX_ I32 f, int x, char *s)
     PL_expect = x;
     PL_bufptr = s;
     PL_last_lop = PL_oldbufptr;
-    PL_last_lop_op = f;
+    PL_last_lop_op = (OPCODE)f;
     if (PL_nexttoke)
        return LSTOP;
     if (*s == '(')
@@ -861,10 +849,13 @@ Perl_str_to_version(pTHX_ SV *sv)
 /*
  * S_force_version
  * Forces the next token to be a version number.
+ * If the next token appears to be an invalid version number, (e.g. "v2b"),
+ * and if "guessing" is TRUE, then no new token is created (and the caller
+ * must use an alternative parsing method).
  */
 
 STATIC char *
-S_force_version(pTHX_ char *s)
+S_force_version(pTHX_ char *s, int guessing)
 {
     OP *version = Nullop;
     char *d;
@@ -875,7 +866,8 @@ S_force_version(pTHX_ char *s)
     if (*d == 'v')
        d++;
     if (isDIGIT(*d)) {
-        for (; isDIGIT(*d) || *d == '_' || *d == '.'; d++);
+       while (isDIGIT(*d) || *d == '_' || *d == '.')
+           d++;
         if (*d == ';' || isSPACE(*d) || *d == '}' || !*d) {
            SV *ver;
             s = scan_num(s, &yylval);
@@ -887,13 +879,15 @@ S_force_version(pTHX_ char *s)
                SvNOK_on(ver);          /* hint that it is a version */
            }
         }
+       else if (guessing)
+           return s;
     }
 
     /* NOTE: The parser sees the package name and the VERSION swapped */
     PL_nextval[PL_nexttoke].opval = version;
     force_next(WORD);
 
-    return (s);
+    return s;
 }
 
 /*
@@ -1075,7 +1069,7 @@ S_sublex_push(pTHX)
     *PL_lex_casestack = '\0';
     PL_lex_starts = 0;
     PL_lex_state = LEX_INTERPCONCAT;
-    CopLINE_set(PL_curcop, PL_multi_start);
+    CopLINE_set(PL_curcop, (line_t)PL_multi_start);
 
     PL_lex_inwhat = PL_sublex_info.sub_inwhat;
     if (PL_lex_inwhat == OP_MATCH || PL_lex_inwhat == OP_QR || PL_lex_inwhat == OP_SUBST)
@@ -1187,7 +1181,7 @@ S_sublex_done(pTHX)
   It stops processing as soon as it finds an embedded $ or @ variable
   and leaves it to the caller to work out what's going on.
 
-  @ in pattern could be: @foo, @{foo}, @$foo, @'foo, @:foo.
+  @ in pattern could be: @foo, @{foo}, @$foo, @'foo, @::foo.
 
   $ in pattern could be $foo or could be tail anchor.  Assumption:
   it's a tail anchor if $ is the last thing in the string, or if it's
@@ -1294,7 +1288,7 @@ S_scan_const(pTHX_ char *start)
                else
 #endif
                    for (i = min; i <= max; i++)
-                       *d++ = i;
+                       *d++ = (char)i;
 
                /* mark the range as done, and continue */
                dorange = FALSE;
@@ -1362,7 +1356,7 @@ S_scan_const(pTHX_ char *start)
        }
 
        /* check for embedded arrays
-          (@foo, @:foo, @'foo, @{foo}, @$foo, @+, @-)
+          (@foo, @::foo, @'foo, @{foo}, @$foo, @+, @-)
           */
        else if (*s == '@' && s[1]
                 && (isALNUM_lazy_if(s+1,UTF) || strchr(":'{$+-", s[1])))
@@ -1396,7 +1390,7 @@ S_scan_const(pTHX_ char *start)
                isDIGIT(*s) && *s != '0' && !isDIGIT(s[1]))
            {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX, "\\%c better written as $%c", *s, *s);
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "\\%c better written as $%c", *s, *s);
                *--s = '$';
                break;
            }
@@ -1419,8 +1413,10 @@ S_scan_const(pTHX_ char *start)
                /* FALL THROUGH */
            default:
                {
-                   if (ckWARN(WARN_MISC) && isALNUM(*s))
-                       Perl_warner(aTHX_ WARN_MISC,
+                   if (ckWARN(WARN_MISC) &&
+                       isALNUM(*s) && 
+                       *s != '_')
+                       Perl_warner(aTHX_ packWARN(WARN_MISC),
                               "Unrecognized escape \\%c passed through",
                               *s);
                    /* default action is to copy the quoted character */
@@ -1431,8 +1427,9 @@ S_scan_const(pTHX_ char *start)
            case '0': case '1': case '2': case '3':
            case '4': case '5': case '6': case '7':
                {
-                   STRLEN len = 0;     /* disallow underscores */
-                   uv = (UV)scan_oct(s, 3, &len);
+                    I32 flags = 0;
+                    STRLEN len = 3;
+                   uv = grok_oct(s, &len, &flags, NULL);
                    s += len;
                }
                goto NUM_ESCAPE_INSERT;
@@ -1442,20 +1439,24 @@ S_scan_const(pTHX_ char *start)
                ++s;
                if (*s == '{') {
                    char* e = strchr(s, '}');
-                   STRLEN len = 1;             /* allow underscores */
+                    I32 flags = PERL_SCAN_ALLOW_UNDERSCORES |
+                      PERL_SCAN_DISALLOW_PREFIX;
+                   STRLEN len;
 
+                    ++s;
                    if (!e) {
                        yyerror("Missing right brace on \\x{}");
-                       ++s;
                        continue;
                    }
-                   uv = (UV)scan_hex(s + 1, e - s - 1, &len);
+                    len = e - s;
+                   uv = grok_hex(s, &len, &flags, NULL);
                    s = e + 1;
                }
                else {
                    {
-                       STRLEN len = 0;         /* disallow underscores */
-                       uv = (UV)scan_hex(s, 2, &len);
+                       STRLEN len = 2;
+                        I32 flags = PERL_SCAN_DISALLOW_PREFIX;
+                       uv = grok_hex(s, &len, &flags, NULL);
                        s += len;
                    }
                }
@@ -1495,8 +1496,8 @@ S_scan_const(pTHX_ char *start)
                            while (src >= (U8 *)SvPVX(sv)) {
                                if (!NATIVE_IS_INVARIANT(*src)) {
                                    U8 ch = NATIVE_TO_ASCII(*src);
-                                   *dst-- = UTF8_EIGHT_BIT_LO(ch);
-                                   *dst-- = UTF8_EIGHT_BIT_HI(ch);
+                                   *dst-- = (U8)UTF8_EIGHT_BIT_LO(ch);
+                                   *dst-- = (U8)UTF8_EIGHT_BIT_HI(ch);
                                }
                                else {
                                    *dst-- = *src;
@@ -1525,7 +1526,7 @@ S_scan_const(pTHX_ char *start)
                }
                continue;
 
-           /* \N{latin small letter a} is a named character */
+           /* \N{LATIN SMALL LETTER A} is a named character */
            case 'N':
                ++s;
                if (*s == '{') {
@@ -1545,6 +1546,26 @@ S_scan_const(pTHX_ char *start)
                    if (has_utf8)
                        sv_utf8_upgrade(res);
                    str = SvPV(res,len);
+#ifdef EBCDIC_NEVER_MIND
+                   /* charnames uses pack U and that has been
+                    * recently changed to do the below uni->native
+                    * mapping, so this would be redundant (and wrong,
+                    * the code point would be doubly converted).
+                    * But leave this in just in case the pack U change
+                    * gets revoked, but the semantics is still
+                    * desireable for charnames. --jhi */
+                   {
+                        UV uv = utf8_to_uvchr((U8*)str, 0);
+
+                        if (uv < 0x100) {
+                             U8 tmpbuf[UTF8_MAXLEN+1], *d;
+
+                             d = uvchr_to_utf8(tmpbuf, UNI_TO_NATIVE(uv));
+                             sv_setpvn(res, (char *)tmpbuf, d - tmpbuf);
+                             str = SvPV(res, len);
+                        }
+                   }
+#endif
                    if (!has_utf8 && SvUTF8(res)) {
                        char *ostart = SvPVX(sv);
                        SvCUR_set(sv, d - ostart);
@@ -1552,11 +1573,11 @@ S_scan_const(pTHX_ char *start)
                        *d = '\0';
                        sv_utf8_upgrade(sv);
                        /* this just broke our allocation above... */
-                       SvGROW(sv, send - start);
+                       SvGROW(sv, (STRLEN)(send - start));
                        d = SvPVX(sv) + SvCUR(sv);
                        has_utf8 = TRUE;
                    }
-                   if (len > e - s + 4) {
+                   if (len > (STRLEN)(e - s + 4)) { /* I _guess_ 4 is \N{} --jhi */
                        char *odest = SvPVX(sv);
 
                        SvGROW(sv, (SvLEN(sv) + len - (e - s + 4)));
@@ -1641,6 +1662,10 @@ S_scan_const(pTHX_ char *start)
       Perl_croak(aTHX_ "panic: constant overflowed allocated space");
 
     SvPOK_on(sv);
+    if (PL_encoding && !has_utf8) {
+        sv_recode_to_utf8(sv, PL_encoding);
+        has_utf8 = TRUE;
+    }
     if (has_utf8) {
        SvUTF8_on(sv);
        if (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op) {
@@ -1962,7 +1987,7 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
     IoANY(datasv) = (void *)funcp; /* stash funcp into spare field */
     IoFLAGS(datasv) |= IOf_FAKE_DIRP;
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_add func %p (%s)\n",
-                         funcp, SvPV_nolen(datasv)));
+                         (void*)funcp, SvPV_nolen(datasv)));
     av_unshift(PL_rsfp_filters, 1);
     av_store(PL_rsfp_filters, 0, datasv) ;
     return(datasv);
@@ -1974,7 +1999,7 @@ void
 Perl_filter_del(pTHX_ filter_t funcp)
 {
     SV *datasv;
-    DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p", funcp));
+    DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p", (void*)funcp));
     if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0)
        return;
     /* if filter is on top of stack (usual case) just pop it off */
@@ -2014,7 +2039,7 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
            int old_len = SvCUR(buf_sv) ;
 
            /* ensure buf_sv is large enough */
-           SvGROW(buf_sv, old_len + maxlen) ;
+           SvGROW(buf_sv, (STRLEN)(old_len + maxlen)) ;
            if ((len = PerlIO_read(PL_rsfp, SvPVX(buf_sv) + old_len, maxlen)) <= 0){
                if (PerlIO_error(PL_rsfp))
                    return -1;          /* error */
@@ -2044,11 +2069,11 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
     funcp = (filter_t)IoANY(datasv);
     DEBUG_P(PerlIO_printf(Perl_debug_log,
                          "filter_read %d: via function %p (%s)\n",
-                         idx, funcp, SvPV_nolen(datasv)));
+                         idx, (void*)funcp, SvPV_nolen(datasv)));
     /* Call function. The function is expected to      */
     /* call "FILTER_READ(idx+1, buf_sv)" first.                */
     /* Return: <0:error, =0:eof, >0:not eof            */
-    return (*funcp)(aTHXo_ idx, buf_sv, maxlen);
+    return (*funcp)(aTHX_ idx, buf_sv, maxlen);
 }
 
 STATIC char *
@@ -2166,7 +2191,7 @@ Perl_yylex(pTHX)
     bool bof = FALSE;
 
     /* check if there's an identifier for us to look at */
-    if (PL_pending_ident) 
+    if (PL_pending_ident)
         return S_pending_ident(aTHX);
 
     /* no identifier pending identification */
@@ -2226,7 +2251,7 @@ Perl_yylex(pTHX)
               "### Saw case modifier at '%s'\n", PL_bufptr); });
            s = PL_bufptr + 1;
            if (strnEQ(s, "L\\u", 3) || strnEQ(s, "U\\l", 3))
-               tmp = *s, *s = s[2], s[2] = tmp;        /* misordered... */
+               tmp = *s, *s = s[2], s[2] = (char)tmp;  /* misordered... */
            if (strchr("LU", *s) &&
                (strchr(PL_lex_casestack, 'L') || strchr(PL_lex_casestack, 'U')))
            {
@@ -2282,13 +2307,13 @@ Perl_yylex(pTHX)
        if (PL_lex_dojoin) {
            PL_nextval[PL_nexttoke].ival = 0;
            force_next(',');
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
            PL_nextval[PL_nexttoke].opval = newOP(OP_THREADSV, 0);
            PL_nextval[PL_nexttoke].opval->op_targ = find_threadsv("\"");
            force_next(PRIVATEREF);
 #else
            force_ident("\"", '$');
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
            PL_nextval[PL_nexttoke].ival = 0;
            force_next('$');
            PL_nextval[PL_nexttoke].ival = 0;
@@ -2424,7 +2449,7 @@ Perl_yylex(pTHX)
                    if (PL_minus_F) {
                        if (strchr("/'\"", *PL_splitstr)
                              && strchr(PL_splitstr + 1, *PL_splitstr))
-                           Perl_sv_catpvf(aTHX_ PL_linestr, "@F=split(%s);", PL_splitstr);
+                           Perl_sv_catpvf(aTHX_ PL_linestr, "our @F=split(%s);", PL_splitstr);
                        else {
                            char delim;
                            s = "'~#\200\1'"; /* surely one char is unused...*/
@@ -2453,6 +2478,8 @@ Perl_yylex(pTHX)
 
                sv_upgrade(sv, SVt_PVMG);
                sv_setsv(sv,PL_linestr);
+                (void)SvIOK_on(sv);
+                SvIVX(sv) = 0;
                av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
            }
            goto retry;
@@ -2508,7 +2535,7 @@ Perl_yylex(pTHX)
                if (!PL_preprocess)
                    bof = PerlIO_tell(PL_rsfp) == SvCUR(PL_linestr);
 #else
-               bof = PerlIO_tell(PL_rsfp) == SvCUR(PL_linestr);
+               bof = PerlIO_tell(PL_rsfp) == (Off_t)SvCUR(PL_linestr);
 #endif
                if (bof) {
                    PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
@@ -2516,9 +2543,6 @@ Perl_yylex(pTHX)
                }
            }
            if (PL_doextract) {
-               if (*s == '#' && s[1] == '!' && instr(s,"perl"))
-                   PL_doextract = FALSE;
-
                /* Incest with pod. */
                if (*s == '=' && strnEQ(s, "=cut", 4)) {
                    sv_setpv(PL_linestr, "");
@@ -2536,6 +2560,8 @@ Perl_yylex(pTHX)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
+            (void)SvIOK_on(sv);
+            SvIVX(sv) = 0;
            av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
        }
        PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
@@ -2576,7 +2602,7 @@ Perl_yylex(pTHX)
                     * at least, set argv[0] to the basename of the Perl
                     * interpreter. So, having found "#!", we'll set it right.
                     */
-                   SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV));
+                   SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV)); /* $^X */
                    assert(SvPOK(x) || SvGMAGICAL(x));
                    if (sv_eq(x, CopFILESV(PL_curcop))) {
                        sv_setpvn(x, ipath, ipathend - ipath);
@@ -2666,6 +2692,7 @@ Perl_yylex(pTHX)
                    while (SPACE_OR_TAB(*d)) d++;
 
                    if (*d++ == '-') {
+                       bool switches_done = PL_doswitches;
                        do {
                            if (*d == 'M' || *d == 'm') {
                                char *m = d;
@@ -2689,6 +2716,14 @@ Perl_yylex(pTHX)
                                (void)gv_fetchfile(PL_origfilename);
                            goto retry;
                        }
+                       if (PL_doswitches && !switches_done) {
+                           int argc = PL_origargc;
+                           char **argv = PL_origargv;
+                           do {
+                               argc--,argv++;
+                           } while (argc && argv[0][0] == '-' && argv[0][1]);
+                           init_argv_symbols(argc,argv);
+                       }
                    }
                }
            }
@@ -2795,7 +2830,7 @@ Perl_yylex(pTHX)
                break;
            }
            if (ftst) {
-               PL_last_lop_op = ftst;
+               PL_last_lop_op = (OPCODE)ftst;
                DEBUG_T( { PerlIO_printf(Perl_debug_log,
                         "### Saw file test %c\n", (int)ftst);
                } );
@@ -2957,6 +2992,8 @@ Perl_yylex(pTHX)
                    PL_lex_stuff = Nullsv;
                }
                else {
+                   /* NOTE: any CV attrs applied here need to be part of
+                      the CVf_BUILTIN_ATTRS define in cv.h! */
                    if (!PL_in_my && len == 6 && strnEQ(s, "lvalue", len))
                        CvLVALUE_on(PL_compcv);
                    else if (!PL_in_my && len == 6 && strnEQ(s, "locked", len))
@@ -2964,14 +3001,20 @@ Perl_yylex(pTHX)
                    else if (!PL_in_my && len == 6 && strnEQ(s, "method", len))
                        CvMETHOD_on(PL_compcv);
 #ifdef USE_ITHREADS
-      else if (PL_in_my == KEY_our && len == 6 && strnEQ(s, "unique", len))
+                   else if (PL_in_my == KEY_our && len == 6 &&
+                            strnEQ(s, "unique", len))
                        GvUNIQUE_on(cGVOPx_gv(yylval.opval));
 #endif
                    /* 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
-                      flags. To experiment with that, uncomment the
-                      following "else": */
+                      flags.  To experiment with that, uncomment the
+                      following "else".  (Note that's already been
+                      uncommented.  That keeps the above-applied built-in
+                      attributes from being intercepted (and possibly
+                      rejected) by a package's attribute routines, but is
+                      justified by the performance win for the common case
+                      of applying only built-in attributes.) */
                    else
                        attrs = append_elem(OP_LIST, attrs,
                                            newSVOP(OP_CONST, 0,
@@ -3239,7 +3282,7 @@ Perl_yylex(pTHX)
                && isIDFIRST_lazy_if(s,UTF) && PL_bufptr == PL_linestart)
            {
                CopLINE_dec(PL_curcop);
-               Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
+               Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), PL_warn_nosemi);
                CopLINE_inc(PL_curcop);
            }
            BAop(OP_BIT_AND);
@@ -3272,7 +3315,7 @@ Perl_yylex(pTHX)
        if (tmp == '~')
            PMop(OP_MATCH);
        if (ckWARN(WARN_SYNTAX) && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp))
-           Perl_warner(aTHX_ WARN_SYNTAX, "Reversed %c= operator",(int)tmp);
+           Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Reversed %c= operator",(int)tmp);
        s--;
        if (PL_expect == XSTATE && isALPHA(tmp) &&
                (s == PL_linestart+1 || s[-2] == '\n') )
@@ -3416,7 +3459,7 @@ Perl_yylex(pTHX)
                        PL_bufptr = skipspace(PL_bufptr);
                        while (t < PL_bufend && *t != ']')
                            t++;
-                       Perl_warner(aTHX_ WARN_SYNTAX,
+                       Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Multidimensional syntax %.*s not supported",
                                (t - PL_bufptr) + 1, PL_bufptr);
                    }
@@ -3434,7 +3477,7 @@ Perl_yylex(pTHX)
                        t = scan_word(t, tmpbuf, sizeof tmpbuf, TRUE, &len);
                        for (; isSPACE(*t); t++) ;
                        if (*t == ';' && get_cv(tmpbuf, FALSE))
-                           Perl_warner(aTHX_ WARN_SYNTAX,
+                           Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "You need to quote \"%s\"", tmpbuf);
                    }
                }
@@ -3513,7 +3556,7 @@ Perl_yylex(pTHX)
                    if (*t == '}' || *t == ']') {
                        t++;
                        PL_bufptr = skipspace(PL_bufptr);
-                       Perl_warner(aTHX_ WARN_SYNTAX,
+                       Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                            "Scalar value %.*s better written as $%.*s",
                            t-PL_bufptr, PL_bufptr, t-PL_bufptr-1, PL_bufptr+1);
                    }
@@ -3640,7 +3683,7 @@ Perl_yylex(pTHX)
     case '\\':
        s++;
        if (ckWARN(WARN_SYNTAX) && PL_lex_inwhat && isDIGIT(*s))
-           Perl_warner(aTHX_ WARN_SYNTAX,"Can't use \\%c to mean $%c in expression",
+           Perl_warner(aTHX_ packWARN(WARN_SYNTAX),"Can't use \\%c to mean $%c in expression",
                        *s, *s);
        if (PL_expect == XOPERATOR)
            no_op("Backslash",s);
@@ -3782,11 +3825,15 @@ Perl_yylex(pTHX)
            }
            else {                      /* no override */
                tmp = -tmp;
+               if (tmp == KEY_dump && ckWARN(WARN_MISC)) {
+                   Perl_warner(aTHX_ packWARN(WARN_MISC),
+                           "dump() better written as CORE::dump()");
+               }
                gv = Nullgv;
                gvp = 0;
                if (ckWARN(WARN_AMBIGUOUS) && hgv
                    && tmp != KEY_x && tmp != KEY_CORE) /* never ambiguous */
-                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                        "Ambiguous call resolved as CORE::%s(), %s",
                         GvENAME(hgv), "qualify as such or use &");
            }
@@ -3817,7 +3864,7 @@ Perl_yylex(pTHX)
                if (PL_expect == XOPERATOR) {
                    if (PL_bufptr == PL_linestart) {
                        CopLINE_dec(PL_curcop);
-                       Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
+                       Perl_warner(aTHX_ packWARN(WARN_SEMICOLON), PL_warn_nosemi);
                        CopLINE_inc(PL_curcop);
                    }
                    else
@@ -3832,7 +3879,7 @@ Perl_yylex(pTHX)
                    PL_tokenbuf[len - 2] == ':' && PL_tokenbuf[len - 1] == ':')
                {
                    if (ckWARN(WARN_BAREWORD) && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV))
-                       Perl_warner(aTHX_ WARN_BAREWORD,
+                       Perl_warner(aTHX_ packWARN(WARN_BAREWORD),
                            "Bareword \"%s\" refers to nonexistent package",
                             PL_tokenbuf);
                    len -= 2;
@@ -3946,7 +3993,7 @@ Perl_yylex(pTHX)
                if (gv && GvCVu(gv)) {
                    CV* cv;
                    if (lastchar == '-' && ckWARN_d(WARN_AMBIGUOUS))
-                       Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                       Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                                "Ambiguous use of -%s resolved as -&%s()",
                                PL_tokenbuf, PL_tokenbuf);
                    /* Check for a constant sub */
@@ -3974,7 +4021,8 @@ Perl_yylex(pTHX)
                        if (strEQ(proto, "$"))
                            OPERATOR(UNIOPSUB);
                        if (*proto == '&' && *s == '{') {
-                           sv_setpv(PL_subname,"__ANON__");
+                           sv_setpv(PL_subname, PL_curstash ? 
+                                       "__ANON__" : "__ANON__::__ANON__");
                            PREBLOCK(LSTOPSUB);
                        }
                    }
@@ -3993,8 +4041,8 @@ Perl_yylex(pTHX)
                    if (ckWARN(WARN_RESERVED)) {
                        if (lastchar != '-') {
                            for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
-                           if (!*d)
-                               Perl_warner(aTHX_ WARN_RESERVED, PL_warn_reserved,
+                           if (!*d && strNE(PL_tokenbuf,"main"))
+                               Perl_warner(aTHX_ packWARN(WARN_RESERVED), PL_warn_reserved,
                                       PL_tokenbuf);
                        }
                    }
@@ -4002,10 +4050,10 @@ Perl_yylex(pTHX)
 
            safe_bareword:
                if (lastchar && strchr("*%&", lastchar) && ckWARN_d(WARN_AMBIGUOUS)) {
-                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                        "Operator or semicolon missing before %c%s",
                        lastchar, PL_tokenbuf);
-                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                        "Ambiguous use of %c resolved as operator %c",
                        lastchar, lastchar);
                }
@@ -4175,12 +4223,6 @@ Perl_yylex(pTHX)
            LOP(OP_CRYPT,XTERM);
 
        case KEY_chmod:
-           if (ckWARN(WARN_CHMOD)) {
-               for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ;
-               if (*d != '0' && isDIGIT(*d))
-                   Perl_warner(aTHX_ WARN_CHMOD,
-                               "chmod() mode argument is missing initial 0");
-           }
            LOP(OP_CHMOD,XTERM);
 
        case KEY_chown:
@@ -4203,7 +4245,7 @@ Perl_yylex(pTHX)
            if (*s == '{')
                PRETERMBLOCK(DO);
            if (*s != '\'')
-               s = force_word(s,WORD,FALSE,TRUE,FALSE);
+               s = force_word(s,WORD,TRUE,TRUE,FALSE);
            OPERATOR(DO);
 
        case KEY_die:
@@ -4533,7 +4575,7 @@ Perl_yylex(pTHX)
            if (PL_expect != XSTATE)
                yyerror("\"no\" not allowed in expression");
            s = force_word(s,WORD,FALSE,TRUE,FALSE);
-           s = force_version(s);
+           s = force_version(s, FALSE);
            yylval.ival = 0;
            OPERATOR(USE);
 
@@ -4550,7 +4592,7 @@ Perl_yylex(pTHX)
                for (d = s; isALNUM_lazy_if(d,UTF); d++) ;
                t = skipspace(d);
                if (strchr("|&*+-=!?:.", *t) && ckWARN_d(WARN_PRECEDENCE))
-                   Perl_warner(aTHX_ WARN_PRECEDENCE,
+                   Perl_warner(aTHX_ packWARN(WARN_PRECEDENCE),
                           "Precedence problem: open %.*s should be open(%.*s)",
                            d-s,s, d-s,s);
            }
@@ -4626,12 +4668,12 @@ Perl_yylex(pTHX)
                        if (!warned && ckWARN(WARN_QW)) {
                            for (; !isSPACE(*d) && len; --len, ++d) {
                                if (*d == ',') {
-                                   Perl_warner(aTHX_ WARN_QW,
+                                   Perl_warner(aTHX_ packWARN(WARN_QW),
                                        "Possible attempt to separate words with commas");
                                    ++warned;
                                }
                                else if (*d == '#') {
-                                   Perl_warner(aTHX_ WARN_QW,
+                                   Perl_warner(aTHX_ packWARN(WARN_QW),
                                        "Possible attempt to put comments in qw() list");
                                    ++warned;
                                }
@@ -4685,10 +4727,12 @@ Perl_yylex(pTHX)
 
        case KEY_require:
            s = skipspace(s);
-           if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
-               s = force_version(s);
+           if (isDIGIT(*s)) {
+               s = force_version(s, FALSE);
            }
-           else {
+           else if (*s != 'v' || !isDIGIT(s[1])
+                   || (s = force_version(s, TRUE), *s == 'v'))
+           {
                *PL_tokenbuf = '\0';
                s = force_word(s,WORD,TRUE,TRUE,FALSE);
                if (isIDFIRST_lazy_if(PL_tokenbuf,UTF))
@@ -4877,7 +4921,7 @@ Perl_yylex(pTHX)
                char tmpbuf[sizeof PL_tokenbuf];
                SSize_t tboffset = 0;
                expectation attrful;
-               bool have_name, have_proto;
+               bool have_name, have_proto, bad_proto;
                int key = tmp;
 
                s = skipspace(s);
@@ -4925,14 +4969,22 @@ Perl_yylex(pTHX)
                    s = scan_str(s,FALSE,FALSE);
                    if (!s)
                        Perl_croak(aTHX_ "Prototype not terminated");
-                   /* strip spaces */
+                   /* strip spaces and check for bad characters */
                    d = SvPVX(PL_lex_stuff);
                    tmp = 0;
+                   bad_proto = FALSE;
                    for (p = d; *p; ++p) {
-                       if (!isSPACE(*p))
+                       if (!isSPACE(*p)) {
                            d[tmp++] = *p;
+                           if (!strchr("$@%*;[]&\\", *p))
+                               bad_proto = TRUE;
+                       }
                    }
                    d[tmp] = '\0';
+                   if (bad_proto && ckWARN(WARN_SYNTAX))
+                       Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
+                                   "Illegal character in prototype for %s : %s",
+                                   SvPVX(PL_subname), d);
                    SvCUR(PL_lex_stuff) = tmp;
                    have_proto = TRUE;
 
@@ -4951,7 +5003,8 @@ Perl_yylex(pTHX)
                    force_next(THING);
                }
                if (!have_name) {
-                   sv_setpv(PL_subname,"__ANON__");
+                   sv_setpv(PL_subname,
+                       PL_curstash ? "__ANON__" : "__ANON__::__ANON__");
                    TOKEN(ANONSUB);
                }
                (void) force_word(PL_oldbufptr + tboffset, WORD,
@@ -5038,12 +5091,6 @@ Perl_yylex(pTHX)
            LOP(OP_UTIME,XTERM);
 
        case KEY_umask:
-           if (ckWARN(WARN_UMASK)) {
-               for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ;
-               if (*d != '0' && isDIGIT(*d))
-                   Perl_warner(aTHX_ WARN_UMASK,
-                               "umask: argument is missing initial 0");
-           }
            UNI(OP_UMASK);
 
        case KEY_unshift:
@@ -5054,15 +5101,19 @@ Perl_yylex(pTHX)
                yyerror("\"use\" not allowed in expression");
            s = skipspace(s);
            if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
-               s = force_version(s);
+               s = force_version(s, TRUE);
                if (*s == ';' || (s = skipspace(s), *s == ';')) {
                    PL_nextval[PL_nexttoke].opval = Nullop;
                    force_next(WORD);
                }
+               else if (*s == 'v') {
+                   s = force_word(s,WORD,FALSE,TRUE,FALSE);
+                   s = force_version(s, FALSE);
+               }
            }
            else {
                s = force_word(s,WORD,FALSE,TRUE,FALSE);
-               s = force_version(s);
+               s = force_version(s, FALSE);
            }
            yylval.ival = 1;
            OPERATOR(USE);
@@ -5093,10 +5144,9 @@ Perl_yylex(pTHX)
        case KEY_write:
 #ifdef EBCDIC
        {
-           static char ctl_l[2];
-
-           if (ctl_l[0] == '\0')
-               ctl_l[0] = toCTRL('L');
+           char ctl_l[2];
+           ctl_l[0] = toCTRL('L');
+           ctl_l[1] = '\0';
            gv_fetchpv(ctl_l,TRUE, SVt_PV);
        }
 #else
@@ -5173,7 +5223,7 @@ S_pending_ident(pTHX)
     */
 
     if (!strchr(PL_tokenbuf,':')) {
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
         /* Check for single character per-thread SVs */
         if (PL_tokenbuf[0] == '$' && PL_tokenbuf[2] == '\0'
             && !isALPHA(PL_tokenbuf[1]) /* Rule out obvious non-threadsvs */
@@ -5183,7 +5233,7 @@ S_pending_ident(pTHX)
             yylval.opval->op_targ = tmp;
             return PRIVATEREF;
         }
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
         if ((tmp = pad_findmy(PL_tokenbuf)) != NOT_IN_PAD) {
             SV *namesv = AvARRAY(PL_comppad_name)[tmp];
             /* might be an "our" variable" */
@@ -5197,7 +5247,7 @@ S_pending_ident(pTHX)
                 gv_fetchpv(SvPVX(sym),
                     (PL_in_eval
                         ? (GV_ADDMULTI | GV_ADDINEVAL)
-                        : TRUE
+                        : GV_ADDMULTI
                     ),
                     ((PL_tokenbuf[0] == '$') ? SVt_PV
                      : (PL_tokenbuf[0] == '@') ? SVt_PVAV
@@ -5239,7 +5289,7 @@ S_pending_ident(pTHX)
              && ckWARN(WARN_AMBIGUOUS))
         {
             /* Downgraded from fatal to warning 20000522 mjd */
-            Perl_warner(aTHX_ WARN_AMBIGUOUS,
+            Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                         "Possible unintended interpolation of %s in string",
                          PL_tokenbuf);
         }
@@ -5875,7 +5925,7 @@ S_checkcomma(pTHX_ register char *s, char *name, char *what)
            if (*w)
                for (; *w && isSPACE(*w); w++) ;
            if (!*w || !strchr(";|})]oaiuw!=", *w))     /* an advisory hack only... */
-               Perl_warner(aTHX_ WARN_SYNTAX,
+               Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                            "%s (...) interpreted as function",name);
        }
     }
@@ -6148,7 +6198,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
            if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
                if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
                    const char *brack = *s == '[' ? "[...]" : "{...}";
-                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                        "Ambiguous use of %c{%s%s} resolved to %c%s%s",
                        funny, dest, brack, funny, dest, brack);
                }
@@ -6180,7 +6230,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
                if (ckWARN(WARN_AMBIGUOUS) &&
                    (keyword(dest, d - dest) || get_cv(dest, FALSE)))
                {
-                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ packWARN(WARN_AMBIGUOUS),
                        "Ambiguous use of %c{%s} resolved to %c%s",
                        funny, dest, funny, dest);
                }
@@ -6197,7 +6247,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
 }
 
 void
-Perl_pmflag(pTHX_ U16 *pmfl, int ch)
+Perl_pmflag(pTHX_ U32* pmfl, int ch)
 {
     if (ch == 'i')
        *pmfl |= PMf_FOLD;
@@ -6236,6 +6286,13 @@ S_scan_pat(pTHX_ char *start, I32 type)
        while (*s && strchr("iogcmsx", *s))
            pmflag(&pm->op_pmflags,*s++);
     }
+    /* issue a warning if /c is specified,but /g is not */
+    if (ckWARN(WARN_REGEXP) && 
+        (pm->op_pmflags & PMf_CONTINUE) && !(pm->op_pmflags & PMf_GLOBAL))
+    {
+        Perl_warner(aTHX_ packWARN(WARN_REGEXP), c_without_g);
+    }
+
     pm->op_pmpermflags = pm->op_pmflags;
 
     PL_lex_op = (OP*)pm;
@@ -6284,6 +6341,12 @@ S_scan_subst(pTHX_ char *start)
            break;
     }
 
+    /* /c is not meaningful with s/// */
+    if (ckWARN(WARN_REGEXP) && (pm->op_pmflags & PMf_CONTINUE))
+    {
+        Perl_warner(aTHX_ packWARN(WARN_REGEXP), c_in_subst);
+    }
+
     if (es) {
        SV *repl;
        PL_sublex_info.super_bufptr = s;
@@ -6389,7 +6452,7 @@ S_scan_heredoc(pTHX_ register char *s)
        else
            term = '"';
        if (!isALNUM_lazy_if(s,UTF))
-           deprecate("bare << to mean <<\"\"");
+           deprecate_old("bare << to mean <<\"\"");
        for (; isALNUM_lazy_if(s,UTF); s++) {
            if (d < e)
                *d++ = *s;
@@ -6460,7 +6523,7 @@ S_scan_heredoc(pTHX_ register char *s)
                CopLINE_inc(PL_curcop);
        }
        if (s >= bufend) {
-           CopLINE_set(PL_curcop, PL_multi_start);
+           CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf);
        }
        sv_setpvn(herewas,bufptr,d-bufptr+1);
@@ -6480,7 +6543,7 @@ S_scan_heredoc(pTHX_ register char *s)
                CopLINE_inc(PL_curcop);
        }
        if (s >= PL_bufend) {
-           CopLINE_set(PL_curcop, PL_multi_start);
+           CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf);
        }
        sv_setpvn(tmpstr,d+1,s-d);
@@ -6498,7 +6561,7 @@ S_scan_heredoc(pTHX_ register char *s)
     while (s >= PL_bufend) {   /* multiple line string? */
        if (!outer ||
         !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
-           CopLINE_set(PL_curcop, PL_multi_start);
+           CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            missingterm(PL_tokenbuf);
        }
        CopLINE_inc(PL_curcop);
@@ -6524,6 +6587,8 @@ S_scan_heredoc(pTHX_ register char *s)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
+            (void)SvIOK_on(sv);
+            SvIVX(sv) = 0;
            av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop),sv);
        }
        if (*s == term && memEQ(s,PL_tokenbuf,len)) {
@@ -6623,6 +6688,9 @@ S_scan_inputsymbol(pTHX_ char *start)
        return s;
     }
     else {
+       bool readline_overriden = FALSE;
+       GV *gv_readline = Nullgv;
+       GV **gvp;
        /* we're in a filehandle read situation */
        d = PL_tokenbuf;
 
@@ -6630,6 +6698,15 @@ S_scan_inputsymbol(pTHX_ char *start)
        if (!len)
            (void)strcpy(d,"ARGV");
 
+       /* Check whether readline() is overriden */
+       if (((gv_readline = gv_fetchpv("readline", FALSE, SVt_PVCV))
+               && GvCVu(gv_readline) && GvIMPORTED_CV(gv_readline))
+               ||
+               ((gvp = (GV**)hv_fetch(PL_globalstash, "readline", 8, FALSE))
+               && (gv_readline = *gvp) != (GV*)&PL_sv_undef
+               && GvCVu(gv_readline) && GvIMPORTED_CV(gv_readline)))
+           readline_overriden = TRUE;
+
        /* if <$fh>, create the ops to turn the variable into a
           filehandle
        */
@@ -6640,17 +6717,44 @@ S_scan_inputsymbol(pTHX_ char *start)
               add symbol table ops
            */
            if ((tmp = pad_findmy(d)) != NOT_IN_PAD) {
-               OP *o = newOP(OP_PADSV, 0);
-               o->op_targ = tmp;
-               PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, o);
+               SV *namesv = AvARRAY(PL_comppad_name)[tmp];
+               if (SvFLAGS(namesv) & SVpad_OUR) {
+                   SV *sym = sv_2mortal(newSVpv(HvNAME(GvSTASH(namesv)),0));
+                   sv_catpvn(sym, "::", 2);
+                   sv_catpv(sym, d+1);
+                   d = SvPVX(sym);
+                   goto intro_sym;
+               }
+               else {
+                   OP *o = newOP(OP_PADSV, 0);
+                   o->op_targ = tmp;
+                   PL_lex_op = readline_overriden
+                       ? (OP*)newUNOP(OP_ENTERSUB, OPf_STACKED,
+                               append_elem(OP_LIST, o,
+                                   newCVREF(0, newGVOP(OP_GV,0,gv_readline))))
+                       : (OP*)newUNOP(OP_READLINE, 0, o);
+               }
            }
            else {
-               GV *gv = gv_fetchpv(d+1,TRUE, SVt_PV);
-               PL_lex_op = (OP*)newUNOP(OP_READLINE, 0,
-                                           newUNOP(OP_RV2SV, 0,
-                                               newGVOP(OP_GV, 0, gv)));
-           }
-           PL_lex_op->op_flags |= OPf_SPECIAL;
+               GV *gv;
+               ++d;
+intro_sym:
+               gv = gv_fetchpv(d,
+                               (PL_in_eval
+                                ? (GV_ADDMULTI | GV_ADDINEVAL)
+                                : GV_ADDMULTI),
+                               SVt_PV);
+               PL_lex_op = readline_overriden
+                   ? (OP*)newUNOP(OP_ENTERSUB, OPf_STACKED,
+                           append_elem(OP_LIST,
+                               newUNOP(OP_RV2SV, 0, newGVOP(OP_GV, 0, gv)),
+                               newCVREF(0, newGVOP(OP_GV, 0, gv_readline))))
+                   : (OP*)newUNOP(OP_READLINE, 0,
+                           newUNOP(OP_RV2SV, 0,
+                               newGVOP(OP_GV, 0, gv)));
+           }
+           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;
        }
@@ -6659,7 +6763,12 @@ S_scan_inputsymbol(pTHX_ char *start)
           (<Foo::BAR> or <FOO>) so build a simple readline OP */
        else {
            GV *gv = gv_fetchpv(d,TRUE, SVt_PVIO);
-           PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv));
+           PL_lex_op = readline_overriden
+               ? (OP*)newUNOP(OP_ENTERSUB, OPf_STACKED,
+                       append_elem(OP_LIST,
+                           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;
        }
     }
@@ -6845,7 +6954,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
        if (!PL_rsfp ||
         !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
            sv_free(sv);
-           CopLINE_set(PL_curcop, PL_multi_start);
+           CopLINE_set(PL_curcop, (line_t)PL_multi_start);
            return Nullch;
        }
        /* we read a line, so increment our line counter */
@@ -6857,6 +6966,8 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
+            (void)SvIOK_on(sv);
+            SvIVX(sv) = 0;
            av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop), sv);
        }
 
@@ -6980,7 +7091,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
 
            if (*s == '_') {
               if (ckWARN(WARN_SYNTAX))
-                  Perl_warner(aTHX_ WARN_SYNTAX,
+                  Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                               "Misplaced _ in number");
               lastub = s++;
            }
@@ -7004,7 +7115,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
                /* _ are ignored -- but warned about if consecutive */
                case '_':
                    if (ckWARN(WARN_SYNTAX) && lastub && s == lastub + 1)
-                       Perl_warner(aTHX_ WARN_SYNTAX,
+                       Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                    "Misplaced _ in number");
                    lastub = s++;
                    break;
@@ -7047,7 +7158,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
                            overflowed = TRUE;
                            n = (NV) u;
                            if (ckWARN_d(WARN_OVERFLOW))
-                               Perl_warner(aTHX_ WARN_OVERFLOW,
+                               Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
                                            "Integer overflow in %s number",
                                            base);
                        } else
@@ -7077,13 +7188,13 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            /* final misplaced underbar check */
            if (s[-1] == '_') {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX, "Misplaced _ in number");
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Misplaced _ in number");
            }
 
            sv = NEWSV(92,0);
            if (overflowed) {
                if (ckWARN(WARN_PORTABLE) && n > 4294967295.0)
-                   Perl_warner(aTHX_ WARN_PORTABLE,
+                   Perl_warner(aTHX_ packWARN(WARN_PORTABLE),
                                "%s number > %s non-portable",
                                Base, max);
                sv_setnv(sv, n);
@@ -7091,7 +7202,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            else {
 #if UVSIZE > 4
                if (ckWARN(WARN_PORTABLE) && u > 0xffffffff)
-                   Perl_warner(aTHX_ WARN_PORTABLE,
+                   Perl_warner(aTHX_ packWARN(WARN_PORTABLE),
                                "%s number > %s non-portable",
                                Base, max);
 #endif
@@ -7120,7 +7231,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            */
            if (*s == '_') {
                if (ckWARN(WARN_SYNTAX) && lastub && s == lastub + 1)
-                   Perl_warner(aTHX_ WARN_SYNTAX,
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Misplaced _ in number");
                lastub = s++;
            }
@@ -7136,7 +7247,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
        /* final misplaced underbar check */
        if (lastub && s == lastub + 1) {
            if (ckWARN(WARN_SYNTAX))
-               Perl_warner(aTHX_ WARN_SYNTAX, "Misplaced _ in number");
+               Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Misplaced _ in number");
        }
 
        /* read a decimal portion if there is one.  avoid
@@ -7149,7 +7260,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
 
            if (*s == '_') {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX,
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Misplaced _ in number");
                lastub = s;
            }
@@ -7162,7 +7273,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
                    Perl_croak(aTHX_ number_too_long);
                if (*s == '_') {
                   if (ckWARN(WARN_SYNTAX) && lastub && s == lastub + 1)
-                      Perl_warner(aTHX_ WARN_SYNTAX,
+                      Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                   "Misplaced _ in number");
                   lastub = s;
                }
@@ -7172,12 +7283,12 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            /* fractional part ending in underbar? */
            if (s[-1] == '_') {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX,
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Misplaced _ in number");
            }
            if (*s == '.' && isDIGIT(s[1])) {
                /* oops, it's really a v-string, but without the "v" */
-               s = start - 1;
+               s = start;
                goto vstring;
            }
        }
@@ -7193,7 +7304,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            /* stray preinitial _ */
            if (*s == '_') {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX,
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Misplaced _ in number");
                lastub = s++;
            }
@@ -7205,7 +7316,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
            /* stray initial _ */
            if (*s == '_') {
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX,
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                "Misplaced _ in number");
                lastub = s++;
            }
@@ -7221,7 +7332,7 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
                   if (ckWARN(WARN_SYNTAX) &&
                       ((lastub && s == lastub + 1) ||
                        (!isDIGIT(s[1]) && s[1] != '_')))
-                      Perl_warner(aTHX_ WARN_SYNTAX,
+                      Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                                   "Misplaced _ in number");
                   lastub = s++;
                }
@@ -7271,58 +7382,8 @@ Perl_scan_num(pTHX_ char *start, YYSTYPE* lvalp)
     /* if it starts with a v, it could be a v-string */
     case 'v':
 vstring:
-       {
-           char *pos = s;
-           pos++;
-           while (isDIGIT(*pos) || *pos == '_')
-               pos++;
-           if (!isALPHA(*pos)) {
-               UV rev;
-               U8 tmpbuf[UTF8_MAXLEN+1];
-               U8 *tmpend;
-               s++;                            /* get past 'v' */
-
-               sv = NEWSV(92,5);
-               sv_setpvn(sv, "", 0);
-
-               for (;;) {
-                   if (*s == '0' && isDIGIT(s[1]))
-                       yyerror("Octal number in vector unsupported");
-                   rev = 0;
-                   {
-                       /* this is atoi() that tolerates underscores */
-                       char *end = pos;
-                       UV mult = 1;
-                       while (--end >= s) {
-                           UV orev;
-                           if (*end == '_')
-                               continue;
-                           orev = rev;
-                           rev += (*end - '0') * mult;
-                           mult *= 10;
-                           if (orev > rev && ckWARN_d(WARN_OVERFLOW))
-                               Perl_warner(aTHX_ WARN_OVERFLOW,
-                                           "Integer overflow in decimal number");
-                       }
-                   }
-                   /* Append native character for the rev point */
-                   tmpend = uvchr_to_utf8(tmpbuf, rev);
-                   sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
-                   if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
-                       SvUTF8_on(sv);
-                   if (*pos == '.' && isDIGIT(pos[1]))
-                       s = ++pos;
-                   else {
-                       s = pos;
-                       break;
-                   }
-                   while (isDIGIT(*pos) || *pos == '_')
-                       pos++;
-               }
-               SvPOK_on(sv);
-               SvREADONLY_on(sv);
-           }
-       }
+               sv = NEWSV(92,5); /* preallocate storage space */
+               s = new_vstring(s,sv);
        break;
     }
 
@@ -7371,15 +7432,19 @@ S_scan_formline(pTHX_ register char *s)
                if (*t == '@' || *t == '^')
                    needargs = TRUE;
            }
-           sv_catpvn(stuff, s, eol-s);
+           if (eol > s) {
+               sv_catpvn(stuff, s, eol-s);
 #ifndef PERL_STRICT_CR
-           if (eol-s > 1 && eol[-2] == '\r' && eol[-1] == '\n') {
-               char *end = SvPVX(stuff) + SvCUR(stuff);
-               end[-2] = '\n';
-               end[-1] = '\0';
-               SvCUR(stuff)--;
-           }
+               if (eol-s > 1 && eol[-2] == '\r' && eol[-1] == '\n') {
+                   char *end = SvPVX(stuff) + SvCUR(stuff);
+                   end[-2] = '\n';
+                   end[-1] = '\0';
+                   SvCUR(stuff)--;
+               }
 #endif
+           }
+           else
+             break;
        }
        s = eol;
        if (PL_rsfp) {
@@ -7460,11 +7525,11 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
     PL_min_intro_pending = 0;
     PL_padix = 0;
     PL_subline = CopLINE(PL_curcop);
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
     av_store(PL_comppad_name, 0, newSVpvn("@_", 2));
     PL_curpad[0] = (SV*)newAV();
     SvPADMY_on(PL_curpad[0]);  /* XXX Needed? */
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
 
     comppadlist = newAV();
     AvREAL_off(comppadlist);
@@ -7473,11 +7538,11 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
 
     CvPADLIST(PL_compcv) = comppadlist;
     CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc(outsidecv);
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
     CvOWNER(PL_compcv) = 0;
     New(666, CvMUTEXP(PL_compcv), 1, perl_mutex);
     MUTEX_INIT(CvMUTEXP(PL_compcv));
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
 
     return oldsavestack_ix;
 }
@@ -7546,7 +7611,7 @@ Perl_yyerror(pTHX_ char *s)
     }
     msg = sv_2mortal(newSVpv(s, 0));
     Perl_sv_catpvf(aTHX_ msg, " at %s line %"IVdf", ",
-                  CopFILE(PL_curcop), (IV)CopLINE(PL_curcop));
+        OutCopFILE(PL_curcop), (IV)CopLINE(PL_curcop));
     if (context)
        Perl_sv_catpvf(aTHX_ msg, "near \"%.*s\"\n", contlen, context);
     else
@@ -7564,10 +7629,10 @@ Perl_yyerror(pTHX_ char *s)
     if (PL_error_count >= 10) {
        if (PL_in_eval && SvCUR(ERRSV))
            Perl_croak(aTHX_ "%"SVf"%s has too many errors.\n",
-                      ERRSV, CopFILE(PL_curcop));
+            ERRSV, OutCopFILE(PL_curcop));
        else
            Perl_croak(aTHX_ "%s has too many errors.\n",
-                      CopFILE(PL_curcop));
+            OutCopFILE(PL_curcop));
     }
     PL_in_my = 0;
     PL_in_my_stash = Nullhv;
@@ -7652,17 +7717,13 @@ S_swallow_bom(pTHX_ U8 *s)
     return (char*)s;
 }
 
-#ifdef PERL_OBJECT
-#include "XSUB.h"
-#endif
-
 /*
  * restore_rsfp
  * Restore a source filter.
  */
 
 static void
-restore_rsfp(pTHXo_ void *f)
+restore_rsfp(pTHX_ void *f)
 {
     PerlIO *fp = (PerlIO*)f;
 
@@ -7675,7 +7736,7 @@ restore_rsfp(pTHXo_ void *f)
 
 #ifndef PERL_NO_UTF16_FILTER
 static I32
-utf16_textfilter(pTHXo_ int idx, SV *sv, int maxlen)
+utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
     I32 count = FILTER_READ(idx+1, sv, maxlen);
     if (count) {
@@ -7694,7 +7755,7 @@ utf16_textfilter(pTHXo_ int idx, SV *sv, int maxlen)
 }
 
 static I32
-utf16rev_textfilter(pTHXo_ int idx, SV *sv, int maxlen)
+utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
     I32 count = FILTER_READ(idx+1, sv, maxlen);
     if (count) {
@@ -7712,3 +7773,4 @@ utf16rev_textfilter(pTHXo_ int idx, SV *sv, int maxlen)
     return count;
 }
 #endif
+