This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
"\e" and "\a" didn't produce right escape under EBCDIC
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index 4ab20c2..dd8742b 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -1,6 +1,6 @@
 /*    toke.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, 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.
  */
 
 #include "EXTERN.h"
+#define PERL_IN_TOKE_C
 #include "perl.h"
 
 #define yychar PL_yychar
 #define yylval PL_yylval
 
-#ifndef PERL_OBJECT
-static void check_uni _((void));
-static void  force_next _((I32 type));
-static char *force_version _((char *start));
-static char *force_word _((char *start, int token, int check_keyword, int allow_pack, int allow_tick));
-static SV *tokeq _((SV *sv));
-static char *scan_const _((char *start));
-static char *scan_formline _((char *s));
-static char *scan_heredoc _((char *s));
-static char *scan_ident _((char *s, char *send, char *dest, STRLEN destlen,
-                          I32 ck_uni));
-static char *scan_inputsymbol _((char *start));
-static char *scan_pat _((char *start, I32 type));
-static char *scan_str _((char *start));
-static char *scan_subst _((char *start));
-static char *scan_trans _((char *start));
-static char *scan_word _((char *s, char *dest, STRLEN destlen,
-                         int allow_package, STRLEN *slp));
-static char *skipspace _((char *s));
-static void checkcomma _((char *s, char *name, char *what));
-static void force_ident _((char *s, int kind));
-static void incline _((char *s));
-static int intuit_method _((char *s, GV *gv));
-static int intuit_more _((char *s));
-static I32 lop _((I32 f, expectation x, char *s));
-static void missingterm _((char *s));
-static void no_op _((char *what, char *s));
-static void set_csh _((void));
-static I32 sublex_done _((void));
-static I32 sublex_push _((void));
-static I32 sublex_start _((void));
-#ifdef CRIPPLED_CC
-static int uni _((I32 f, char *s));
-#endif
-static char * filter_gets _((SV *sv, PerlIO *fp, STRLEN append));
-static void restore_rsfp _((void *f));
-static SV *new_constant _((char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type));
-static void restore_expect _((void *e));
-static void restore_lex_expect _((void *e));
-#endif /* PERL_OBJECT */
-
 static char ident_too_long[] = "Identifier too long";
 
 #define UTF (PL_hints & HINT_UTF8)
@@ -74,6 +34,10 @@ static char ident_too_long[] = "Identifier too long";
                                ? isALNUM(*(p)) \
                                : isALNUM_utf8((U8*)p))
 
+/* In variables name $^X, these are the legal values for X.  
+ * 1999-02-27 mjd-perl-patch@plover.com */
+#define isCONTROLVAR(x) (isUPPER(x) || strchr("[\\]^_?", (x)))
+
 /* The following are arranged oddly so that the guard on the switch statement
  * can get by with a single comparison (if the compiler is smart enough).
  */
@@ -117,8 +81,8 @@ int* yychar_pointer = NULL;
 #  define yylval (*yylval_pointer)
 #  define yychar (*yychar_pointer)
 #  define PERL_YYLEX_PARAM yylval_pointer,yychar_pointer
-#else
-#  define PERL_YYLEX_PARAM
+#  undef yylex
+#  define yylex()      Perl_yylex(aTHX_ yylval_pointer, yychar_pointer)
 #endif
 
 #include "keywords.h"
@@ -168,7 +132,7 @@ int* yychar_pointer = NULL;
 #define OLDLOP(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP)
 
 STATIC int
-ao(int toketype)
+S_ao(pTHX_ int toketype)
 {
     if (*PL_bufptr == '=') {
        PL_bufptr++;
@@ -182,32 +146,32 @@ ao(int toketype)
 }
 
 STATIC void
-no_op(char *what, char *s)
+S_no_op(pTHX_ char *what, char *s)
 {
     char *oldbp = PL_bufptr;
     bool is_first = (PL_oldbufptr == PL_linestart);
 
     PL_bufptr = s;
-    yywarn(form("%s found where operator expected", what));
+    yywarn(Perl_form(aTHX_ "%s found where operator expected", what));
     if (is_first)
-       warn("\t(Missing semicolon on previous line?)\n");
+       Perl_warn(aTHX_ "\t(Missing semicolon on previous line?)\n");
     else if (PL_oldoldbufptr && isIDFIRST_lazy(PL_oldoldbufptr)) {
        char *t;
        for (t = PL_oldoldbufptr; *t && (isALNUM_lazy(t) || *t == ':'); t++) ;
        if (t < PL_bufptr && isSPACE(*t))
-           warn("\t(Do you need to predeclare %.*s?)\n",
+           Perl_warn(aTHX_ "\t(Do you need to predeclare %.*s?)\n",
                t - PL_oldoldbufptr, PL_oldoldbufptr);
 
     }
     else if (s <= oldbp)
-       warn("\t(Missing operator before end of line?)\n");
+       Perl_warn(aTHX_ "\t(Missing operator before end of line?)\n");
     else
-       warn("\t(Missing operator before %.*s?)\n", s - oldbp, oldbp);
+       Perl_warn(aTHX_ "\t(Missing operator before %.*s?)\n", s - oldbp, oldbp);
     PL_bufptr = oldbp;
 }
 
 STATIC void
-missingterm(char *s)
+S_missingterm(pTHX_ char *s)
 {
     char tmpbuf[3];
     char q;
@@ -235,19 +199,19 @@ missingterm(char *s)
        s = tmpbuf;
     }
     q = strchr(s,'"') ? '\'' : '"';
-    croak("Can't find string terminator %c%s%c anywhere before EOF",q,s,q);
+    Perl_croak(aTHX_ "Can't find string terminator %c%s%c anywhere before EOF",q,s,q);
 }
 
 void
-deprecate(char *s)
+Perl_deprecate(pTHX_ char *s)
 {
     dTHR;
     if (ckWARN(WARN_DEPRECATED))
-       warner(WARN_DEPRECATED, "Use of %s is deprecated", s);
+       Perl_warner(aTHX_ WARN_DEPRECATED, "Use of %s is deprecated", s);
 }
 
 STATIC void
-depcom(void)
+S_depcom(pTHX)
 {
     deprecate("comma-less variable list");
 }
@@ -255,7 +219,7 @@ depcom(void)
 #ifdef WIN32
 
 STATIC I32
-win32_textfilter(int idx, SV *sv, int maxlen)
+S_win32_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
  I32 count = FILTER_READ(idx+1, sv, maxlen);
  if (count > 0 && !maxlen)
@@ -264,10 +228,8 @@ win32_textfilter(int idx, SV *sv, int maxlen)
 }
 #endif
 
-#ifndef PERL_OBJECT
-
 STATIC I32
-utf16_textfilter(int idx, SV *sv, int maxlen)
+S_utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
     I32 count = FILTER_READ(idx+1, sv, maxlen);
     if (count) {
@@ -282,7 +244,7 @@ utf16_textfilter(int idx, SV *sv, int maxlen)
 }
 
 STATIC I32
-utf16rev_textfilter(int idx, SV *sv, int maxlen)
+S_utf16rev_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
     I32 count = FILTER_READ(idx+1, sv, maxlen);
     if (count) {
@@ -296,10 +258,8 @@ utf16rev_textfilter(int idx, SV *sv, int maxlen)
     return count;
 }
 
-#endif
-
 void
-lex_start(SV *line)
+Perl_lex_start(pTHX_ SV *line)
 {
     dTHR;
     char *s;
@@ -322,12 +282,12 @@ lex_start(SV *line)
     SAVESPTR(PL_linestr);
     SAVEPPTR(PL_lex_brackstack);
     SAVEPPTR(PL_lex_casestack);
-    SAVEDESTRUCTOR(restore_rsfp, PL_rsfp);
+    SAVEDESTRUCTOR(S_restore_rsfp, PL_rsfp);
     SAVESPTR(PL_lex_stuff);
     SAVEI32(PL_lex_defer);
     SAVESPTR(PL_lex_repl);
-    SAVEDESTRUCTOR(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
-    SAVEDESTRUCTOR(restore_lex_expect, PL_tokenbuf + PL_expect);
+    SAVEDESTRUCTOR(S_restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
+    SAVEDESTRUCTOR(S_restore_lex_expect, PL_tokenbuf + PL_expect);
 
     PL_lex_state = LEX_NORMAL;
     PL_lex_defer = 0;
@@ -359,18 +319,18 @@ lex_start(SV *line)
     PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr);
     PL_bufend = PL_bufptr + SvCUR(PL_linestr);
     SvREFCNT_dec(PL_rs);
-    PL_rs = newSVpv("\n", 1);
+    PL_rs = newSVpvn("\n", 1);
     PL_rsfp = 0;
 }
 
 void
-lex_end(void)
+Perl_lex_end(pTHX)
 {
     PL_doextract = FALSE;
 }
 
 STATIC void
-restore_rsfp(void *f)
+S_restore_rsfp(pTHX_ void *f)
 {
     PerlIO *fp = (PerlIO*)f;
 
@@ -382,21 +342,21 @@ restore_rsfp(void *f)
 }
 
 STATIC void
-restore_expect(void *e)
+S_restore_expect(pTHX_ void *e)
 {
     /* a safe way to store a small integer in a pointer */
     PL_expect = (expectation)((char *)e - PL_tokenbuf);
 }
 
 STATIC void
-restore_lex_expect(void *e)
+S_restore_lex_expect(pTHX_ void *e)
 {
     /* a safe way to store a small integer in a pointer */
     PL_lex_expect = (expectation)((char *)e - PL_tokenbuf);
 }
 
 STATIC void
-incline(char *s)
+S_incline(pTHX_ char *s)
 {
     dTHR;
     char *t;
@@ -437,7 +397,7 @@ incline(char *s)
 }
 
 STATIC char *
-skipspace(register char *s)
+S_skipspace(pTHX_ register char *s)
 {
     dTHR;
     if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
@@ -500,7 +460,8 @@ skipspace(register char *s)
 }
 
 STATIC void
-check_uni(void) {
+S_check_uni(pTHX)
+{
     char *s;
     char ch;
     char *t;
@@ -514,7 +475,7 @@ check_uni(void) {
        return;
     ch = *s;
     *s = '\0';
-    warn("Warning: Use of \"%s\" without parens is ambiguous", PL_last_uni);
+    Perl_warn(aTHX_ "Warning: Use of \"%s\" without parens is ambiguous", PL_last_uni);
     *s = ch;
 }
 
@@ -524,7 +485,7 @@ check_uni(void) {
 #define UNI(f) return uni(f,s)
 
 STATIC int
-uni(I32 f, char *s)
+S_uni(pTHX_ I32 f, char *s)
 {
     yylval.ival = f;
     PL_expect = XTERM;
@@ -545,7 +506,7 @@ uni(I32 f, char *s)
 #define LOP(f,x) return lop(f,x,s)
 
 STATIC I32
-lop(I32 f, expectation x, char *s)
+S_lop(pTHX_ I32 f, expectation x, char *s)
 {
     dTHR;
     yylval.ival = f;
@@ -566,7 +527,7 @@ lop(I32 f, expectation x, char *s)
 }
 
 STATIC void 
-force_next(I32 type)
+S_force_next(pTHX_ I32 type)
 {
     PL_nexttype[PL_nexttoke] = type;
     PL_nexttoke++;
@@ -578,7 +539,7 @@ force_next(I32 type)
 }
 
 STATIC char *
-force_word(register char *start, int token, int check_keyword, int allow_pack, int allow_initial_tick)
+S_force_word(pTHX_ register char *start, int token, int check_keyword, int allow_pack, int allow_initial_tick)
 {
     register char *s;
     STRLEN len;
@@ -608,7 +569,7 @@ force_word(register char *start, int token, int check_keyword, int allow_pack, i
 }
 
 STATIC void
-force_ident(register char *s, int kind)
+S_force_ident(pTHX_ register char *s, int kind)
 {
     if (s && *s) {
        OP* o = (OP*)newSVOP(OP_CONST, 0, newSVpv(s,0));
@@ -631,7 +592,7 @@ force_ident(register char *s, int kind)
 }
 
 STATIC char *
-force_version(char *s)
+S_force_version(pTHX_ char *s)
 {
     OP *version = Nullop;
 
@@ -658,7 +619,7 @@ force_version(char *s)
 }
 
 STATIC SV *
-tokeq(SV *sv)
+S_tokeq(pTHX_ SV *sv)
 {
     register char *s;
     register char *send;
@@ -679,7 +640,7 @@ tokeq(SV *sv)
        goto finish;
     d = s;
     if ( PL_hints & HINT_NEW_STRING )
-       pv = sv_2mortal(newSVpv(SvPVX(pv), len));
+       pv = sv_2mortal(newSVpvn(SvPVX(pv), len));
     while (s < send) {
        if (*s == '\\') {
            if (s + 1 < send && (s[1] == '\\'))
@@ -696,7 +657,7 @@ tokeq(SV *sv)
 }
 
 STATIC I32
-sublex_start(void)
+S_sublex_start(pTHX)
 {
     register I32 op_type = yylval.ival;
 
@@ -715,7 +676,7 @@ sublex_start(void)
            SV *nsv;
 
            p = SvPV(sv, len);
-           nsv = newSVpv(p, len);
+           nsv = newSVpvn(p, len);
            SvREFCNT_dec(sv);
            sv = nsv;
        } 
@@ -740,7 +701,7 @@ sublex_start(void)
 }
 
 STATIC I32
-sublex_push(void)
+S_sublex_push(pTHX)
 {
     dTHR;
     ENTER;
@@ -793,17 +754,17 @@ sublex_push(void)
 }
 
 STATIC I32
-sublex_done(void)
+S_sublex_done(pTHX)
 {
     if (!PL_lex_starts++) {
        PL_expect = XOPERATOR;
-       yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv("",0));
+       yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpvn("",0));
        return THING;
     }
 
     if (PL_lex_casemods) {             /* oops, we've got some unbalanced parens */
        PL_lex_state = LEX_INTERPCASEMOD;
-       return yylex(PERL_YYLEX_PARAM);
+       return yylex();
     }
 
     /* Is there a right-hand side to take care of? */
@@ -819,7 +780,7 @@ sublex_done(void)
        PL_lex_casemods = 0;
        *PL_lex_casestack = '\0';
        PL_lex_starts = 0;
-       if (SvCOMPILED(PL_lex_repl)) {
+       if (SvEVALED(PL_lex_repl)) {
            PL_lex_state = LEX_INTERPNORMAL;
            PL_lex_starts++;
            /*  we don't clear PL_lex_repl here, so that we can check later
@@ -916,7 +877,7 @@ sublex_done(void)
 */
 
 STATIC char *
-scan_const(char *start)
+S_scan_const(pTHX_ char *start)
 {
     register char *send = PL_bufend;           /* end of the constant */
     SV *sv = NEWSV(93, send - start);          /* sv for the constant */
@@ -924,10 +885,10 @@ scan_const(char *start)
     register char *d = SvPVX(sv);              /* destination for copies */
     bool dorange = FALSE;                      /* are we in a translit range? */
     I32 len;                                   /* ? */
-    I32 utf = PL_lex_inwhat == OP_TRANS
+    I32 utf = (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op)
        ? (PL_sublex_info.sub_op->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF))
        : UTF;
-    I32 thisutf = PL_lex_inwhat == OP_TRANS
+    I32 thisutf = (PL_lex_inwhat == OP_TRANS && PL_sublex_info.sub_op)
        ? (PL_sublex_info.sub_op->op_private & (PL_lex_repl ? OPpTRANS_FROM_UTF : OPpTRANS_TO_UTF))
        : UTF;
 
@@ -1073,7 +1034,7 @@ scan_const(char *start)
            {
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_SYNTAX))
-                   warner(WARN_SYNTAX, "\\%c better written as $%c", *s, *s);
+                   Perl_warner(aTHX_ WARN_SYNTAX, "\\%c better written as $%c", *s, *s);
                *--s = '$';
                break;
            }
@@ -1098,7 +1059,7 @@ scan_const(char *start)
                {
                    dTHR;
                    if (ckWARN(WARN_UNSAFE) && isALPHA(*s))
-                       warner(WARN_UNSAFE, 
+                       Perl_warner(aTHX_ WARN_UNSAFE, 
                               "Unrecognized escape \\%c passed through",
                               *s);
                    /* default action is to copy the quoted character */
@@ -1126,7 +1087,7 @@ scan_const(char *start)
                    if (!utf) {
                        dTHR;
                        if (ckWARN(WARN_UTF8))
-                           warner(WARN_UTF8,
+                           Perl_warner(aTHX_ WARN_UTF8,
                                   "Use of \\x{} without utf8 declaration");
                    }
                    /* note: utf always shorter than hex */
@@ -1146,7 +1107,7 @@ scan_const(char *start)
                        if (uv >= 127 && UTF) {
                            dTHR;
                            if (ckWARN(WARN_UTF8))
-                               warner(WARN_UTF8,
+                               Perl_warner(aTHX_ WARN_UTF8,
                                    "\\x%.*s will produce malformed UTF-8 character; use \\x{%.*s} for that",
                                    len,s,len,s);
                        }
@@ -1186,12 +1147,21 @@ scan_const(char *start)
            case 't':
                *d++ = '\t';
                break;
+#ifdef EBCDIC
+           case 'e':
+               *d++ = '\047';  /* CP 1047 */
+               break;
+           case 'a':
+               *d++ = '\057';  /* CP 1047 */
+               break;
+#else
            case 'e':
                *d++ = '\033';
                break;
            case 'a':
                *d++ = '\007';
                break;
+#endif
            } /* end switch */
 
            s++;
@@ -1230,7 +1200,7 @@ scan_const(char *start)
 
 /* This is the one truly awful dwimmer necessary to conflate C and sed. */
 STATIC int
-intuit_more(register char *s)
+S_intuit_more(pTHX_ register char *s)
 {
     if (PL_lex_brackets)
        return TRUE;
@@ -1360,7 +1330,7 @@ intuit_more(register char *s)
 }
 
 STATIC int
-intuit_method(char *start, GV *gv)
+S_intuit_method(pTHX_ char *start, GV *gv)
 {
     char *s = start + (*start == '$');
     char tmpbuf[sizeof PL_tokenbuf];
@@ -1407,7 +1377,7 @@ intuit_method(char *start, GV *gv)
                return 0;       /* no assumptions -- "=>" quotes bearword */
       bare_package:
            PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0,
-                                                  newSVpv(tmpbuf,0));
+                                                  newSVpvn(tmpbuf,len));
            PL_nextval[PL_nexttoke].opval->op_private = OPpCONST_BARE;
            PL_expect = XTERM;
            force_next(WORD);
@@ -1419,7 +1389,7 @@ intuit_method(char *start, GV *gv)
 }
 
 STATIC char*
-incl_perldb(void)
+S_incl_perldb(pTHX)
 {
     if (PL_perldb) {
        char *pdb = PerlEnv_getenv("PERL5DB");
@@ -1450,7 +1420,7 @@ incl_perldb(void)
  */
 
 SV *
-filter_add(filter_t funcp, SV *datasv)
+Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
 {
     if (!funcp){ /* temporary handy debugging hack to be deleted */
        PL_filter_debug = atoi((char*)datasv);
@@ -1461,11 +1431,11 @@ filter_add(filter_t funcp, SV *datasv)
     if (!datasv)
        datasv = NEWSV(255,0);
     if (!SvUPGRADE(datasv, SVt_PVIO))
-        die("Can't upgrade filter_add data to SVt_PVIO");
+        Perl_die(aTHX_ "Can't upgrade filter_add data to SVt_PVIO");
     IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */
     if (PL_filter_debug) {
        STRLEN n_a;
-       warn("filter_add func %p (%s)", funcp, SvPV(datasv, n_a));
+       Perl_warn(aTHX_ "filter_add func %p (%s)", funcp, SvPV(datasv, n_a));
     }
     av_unshift(PL_rsfp_filters, 1);
     av_store(PL_rsfp_filters, 0, datasv) ;
@@ -1475,26 +1445,27 @@ filter_add(filter_t funcp, SV *datasv)
 
 /* Delete most recently added instance of this filter function.        */
 void
-filter_del(filter_t funcp)
+Perl_filter_del(pTHX_ filter_t funcp)
 {
     if (PL_filter_debug)
-       warn("filter_del func %p", funcp);
+       Perl_warn(aTHX_ "filter_del func %p", funcp);
     if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0)
        return;
     /* if filter is on top of stack (usual case) just pop it off */
     if (IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) == (DIR*)funcp){
+       IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL;
        sv_free(av_pop(PL_rsfp_filters));
 
         return;
     }
     /* we need to search for the correct entry and clear it    */
-    die("filter_del can only delete in reverse order (currently)");
+    Perl_die(aTHX_ "filter_del can only delete in reverse order (currently)");
 }
 
 
 /* Invoke the n'th filter function for the current rsfp.        */
 I32
-filter_read(int idx, SV *buf_sv, int maxlen)
+Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
             
                
                                /* 0 = read one text line */
@@ -1508,7 +1479,7 @@ filter_read(int idx, SV *buf_sv, int maxlen)
        /* Provide a default input filter to make life easy.    */
        /* Note that we append to the line. This is handy.      */
        if (PL_filter_debug)
-           warn("filter_read %d: from rsfp\n", idx);
+           Perl_warn(aTHX_ "filter_read %d: from rsfp\n", idx);
        if (maxlen) { 
            /* Want a block */
            int len ;
@@ -1537,24 +1508,24 @@ filter_read(int idx, SV *buf_sv, int maxlen)
     /* Skip this filter slot if filter has been deleted        */
     if ( (datasv = FILTER_DATA(idx)) == &PL_sv_undef){
        if (PL_filter_debug)
-           warn("filter_read %d: skipped (filter deleted)\n", idx);
+           Perl_warn(aTHX_ "filter_read %d: skipped (filter deleted)\n", idx);
        return FILTER_READ(idx+1, buf_sv, maxlen); /* recurse */
     }
     /* Get function pointer hidden within datasv       */
     funcp = (filter_t)IoDIRP(datasv);
     if (PL_filter_debug) {
        STRLEN n_a;
-       warn("filter_read %d: via function %p (%s)\n",
+       Perl_warn(aTHX_ "filter_read %d: via function %p (%s)\n",
                idx, funcp, SvPV(datasv,n_a));
     }
     /* 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)(PERL_OBJECT_THIS_ idx, buf_sv, maxlen);
+    return (*funcp)(aTHXo_ idx, buf_sv, maxlen);
 }
 
 STATIC char *
-filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
+S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
 {
 #ifdef WIN32FILTER
     if (!PL_rsfp_filters) {
@@ -1605,7 +1576,12 @@ filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
       if we already built the token before, use it.
 */
 
-int yylex(PERL_YYLEX_PARAM_DECL)
+int
+#ifdef USE_PURE_BISON
+Perl_yylex(pTHX_ YYSTYPE *lvalp, int *lcharp)
+#else
+Perl_yylex(pTHX)
+#endif
 {
     dTHR;
     register char *s;
@@ -1634,7 +1610,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        */
        if (PL_in_my) {
            if (strchr(PL_tokenbuf,':'))
-               croak(PL_no_myglob,PL_tokenbuf);
+               yyerror(Perl_form(aTHX_ PL_no_myglob,PL_tokenbuf));
 
            yylval.opval = newOP(OP_PADANY, 0);
            yylval.opval->op_targ = pad_allocmy(PL_tokenbuf);
@@ -1677,7 +1653,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                         d++)
                    {
                        if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
-                           croak("Can't use \"my %s\" in sort comparison",
+                           Perl_croak(aTHX_ "Can't use \"my %s\" in sort comparison",
                                  PL_tokenbuf);
                        }
                    }
@@ -1697,7 +1673,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        if (pit == '@' && PL_lex_state != LEX_NORMAL && !PL_lex_brackets) {
            GV *gv = gv_fetchpv(PL_tokenbuf+1, FALSE, SVt_PVAV);
            if (!gv || ((PL_tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)))
-               yyerror(form("In string, %s now must be written as \\%s",
+               yyerror(Perl_form(aTHX_ "In string, %s now must be written as \\%s",
                             PL_tokenbuf, PL_tokenbuf));
        }
 
@@ -1737,7 +1713,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
     case LEX_INTERPCASEMOD:
 #ifdef DEBUGGING
        if (PL_bufptr != PL_bufend && *PL_bufptr != '\\')
-           croak("panic: INTERPCASEMOD");
+           Perl_croak(aTHX_ "panic: INTERPCASEMOD");
 #endif
        /* handle \E or end of string */
                if (PL_bufptr == PL_bufend || PL_bufptr[1] == 'E') {
@@ -1757,7 +1733,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            if (PL_bufptr != PL_bufend)
                PL_bufptr += 2;
            PL_lex_state = LEX_INTERPCONCAT;
-           return yylex(PERL_YYLEX_PARAM);
+           return yylex();
        }
        else {
            s = PL_bufptr + 1;
@@ -1792,7 +1768,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            else if (*s == 'Q')
                PL_nextval[PL_nexttoke].ival = OP_QUOTEMETA;
            else
-               croak("panic: yylex");
+               Perl_croak(aTHX_ "panic: yylex");
            PL_bufptr = s + 1;
            force_next(FUNC);
            if (PL_lex_starts) {
@@ -1801,7 +1777,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                Aop(OP_CONCAT);
            }
            else
-               return yylex(PERL_YYLEX_PARAM);
+               return yylex();
        }
 
     case LEX_INTERPPUSH:
@@ -1834,7 +1810,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            s = PL_bufptr;
            Aop(OP_CONCAT);
        }
-       return yylex(PERL_YYLEX_PARAM);
+       return yylex();
 
     case LEX_INTERPENDMAYBE:
        if (intuit_more(PL_bufptr)) {
@@ -1849,16 +1825,18 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            PL_lex_state = LEX_INTERPCONCAT;
            return ')';
        }
-       if (PL_lex_inwhat == OP_SUBST && PL_lex_repl && SvCOMPILED(PL_lex_repl)) {
+       if (PL_lex_inwhat == OP_SUBST && PL_linestr == PL_lex_repl
+           && SvEVALED(PL_lex_repl))
+       {
            if (PL_bufptr != PL_bufend)
-               croak("Bad evalled substitution pattern");
+               Perl_croak(aTHX_ "Bad evalled substitution pattern");
            PL_lex_repl = Nullsv;
        }
        /* FALLTHROUGH */
     case LEX_INTERPCONCAT:
 #ifdef DEBUGGING
        if (PL_lex_brackets)
-           croak("panic: INTERPCONCAT");
+           Perl_croak(aTHX_ "panic: INTERPCONCAT");
 #endif
        if (PL_bufptr == PL_bufend)
            return sublex_done();
@@ -1888,11 +1866,11 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                Aop(OP_CONCAT);
            else {
                PL_bufptr = s;
-               return yylex(PERL_YYLEX_PARAM);
+               return yylex();
            }
        }
 
-       return yylex(PERL_YYLEX_PARAM);
+       return yylex();
     case LEX_FORMLINE:
        PL_lex_state = LEX_NORMAL;
        s = scan_formline(PL_bufptr);
@@ -1913,7 +1891,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
     default:
        if (isIDFIRST_lazy(s))
            goto keylookup;
-       croak("Unrecognized character \\x%02X", *s & 255);
+       Perl_croak(aTHX_ "Unrecognized character \\x%02X", *s & 255);
     case 4:
     case 26:
        goto fake_eof;                  /* emulate EOF on ^D or ^Z */
@@ -1922,7 +1900,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            PL_last_uni = 0;
            PL_last_lop = 0;
            if (PL_lex_brackets)
-               yyerror("Missing right bracket");
+               yyerror("Missing right curly or square bracket");
            TOKEN(0);
        }
        if (s++ < PL_bufend)
@@ -1955,20 +1933,20 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    if (PL_minus_F) {
                        if (strchr("/'\"", *PL_splitstr)
                              && strchr(PL_splitstr + 1, *PL_splitstr))
-                           sv_catpvf(PL_linestr, "@F=split(%s);", PL_splitstr);
+                           Perl_sv_catpvf(aTHX_ PL_linestr, "@F=split(%s);", PL_splitstr);
                        else {
                            char delim;
                            s = "'~#\200\1'"; /* surely one char is unused...*/
                            while (s[1] && strchr(PL_splitstr, *s))  s++;
                            delim = *s;
-                           sv_catpvf(PL_linestr, "@F=split(%s%c",
+                           Perl_sv_catpvf(aTHX_ PL_linestr, "@F=split(%s%c",
                                      "q" + (delim == '\''), delim);
                            for (s = PL_splitstr; *s; s++) {
                                if (*s == '\\')
                                    sv_catpvn(PL_linestr, "\\", 1);
                                sv_catpvn(PL_linestr, s, 1);
                            }
-                           sv_catpvf(PL_linestr, "%c);", delim);
+                           Perl_sv_catpvf(aTHX_ PL_linestr, "%c);", delim);
                        }
                    }
                    else
@@ -2132,7 +2110,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                        newargv = PL_origargv;
                    newargv[0] = ipath;
                    PerlProc_execv(ipath, newargv);
-                   croak("Can't exec %s", ipath);
+                   Perl_croak(aTHX_ "Can't exec %s", ipath);
                }
                if (d) {
                    U32 oldpdb = PL_perldb;
@@ -2147,7 +2125,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                            if (*d == 'M' || *d == 'm') {
                                char *m = d;
                                while (*d && !isSPACE(*d)) d++;
-                               croak("Too late for \"-%.*s\" option",
+                               Perl_croak(aTHX_ "Too late for \"-%.*s\" option",
                                      (int)(d - m), m);
                            }
                            d = moreswitches(d);
@@ -2172,13 +2150,13 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
            PL_bufptr = s;
            PL_lex_state = LEX_FORMLINE;
-           return yylex(PERL_YYLEX_PARAM);
+           return yylex();
        }
        goto retry;
     case '\r':
 #ifdef PERL_STRICT_CR
-       warn("Illegal character \\%03o (carriage return)", '\r');
-       croak(
+       Perl_warn(aTHX_ "Illegal character \\%03o (carriage return)", '\r');
+       Perl_croak(aTHX_ 
       "(Maybe you didn't strip carriage returns after a network transfer?)\n");
 #endif
     case ' ': case '\t': case '\f': case 013:
@@ -2196,7 +2174,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
                PL_bufptr = s;
                PL_lex_state = LEX_FORMLINE;
-               return yylex(PERL_YYLEX_PARAM);
+               return yylex();
            }
        }
        else {
@@ -2248,7 +2226,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            case 'A': gv_fetchpv("\024",TRUE, SVt_PV); FTST(OP_FTATIME);
            case 'C': gv_fetchpv("\024",TRUE, SVt_PV); FTST(OP_FTCTIME);
            default:
-               croak("Unrecognized file test: -%c", (int)tmp);
+               Perl_croak(aTHX_ "Unrecognized file test: -%c", (int)tmp);
                break;
            }
        }
@@ -2366,7 +2344,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
     case ']':
        s++;
        if (PL_lex_brackets <= 0)
-           yyerror("Unmatched right bracket");
+           yyerror("Unmatched right square bracket");
        else
            --PL_lex_brackets;
        if (PL_lex_state == LEX_INTERPNORMAL) {
@@ -2523,7 +2501,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
       rightbracket:
        s++;
        if (PL_lex_brackets <= 0)
-           yyerror("Unmatched right bracket");
+           yyerror("Unmatched right curly bracket");
        else
            PL_expect = (expectation)PL_lex_brackstack[--PL_lex_brackets];
        if (PL_lex_brackets < PL_lex_formbrack)
@@ -2533,7 +2511,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                if (PL_lex_fakebrack) {
                    PL_lex_state = LEX_INTERPEND;
                    PL_bufptr = s;
-                   return yylex(PERL_YYLEX_PARAM);     /* ignore fake brackets */
+                   return yylex();     /* ignore fake brackets */
                }
                if (*s == '-' && s[1] == '>')
                    PL_lex_state = LEX_INTERPENDMAYBE;
@@ -2544,7 +2522,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        if (PL_lex_brackets < PL_lex_fakebrack) {
            PL_bufptr = s;
            PL_lex_fakebrack = 0;
-           return yylex(PERL_YYLEX_PARAM);             /* ignore fake brackets */
+           return yylex();             /* ignore fake brackets */
        }
        force_next('}');
        TOKEN(';');
@@ -2557,7 +2535,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        if (PL_expect == XOPERATOR) {
            if (ckWARN(WARN_SEMICOLON) && isIDFIRST_lazy(s) && PL_bufptr == PL_linestart) {
                PL_curcop->cop_line--;
-               warner(WARN_SEMICOLON, PL_warn_nosemi);
+               Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
                PL_curcop->cop_line++;
            }
            BAop(OP_BIT_AND);
@@ -2590,7 +2568,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        if (tmp == '~')
            PMop(OP_MATCH);
        if (ckWARN(WARN_SYNTAX) && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp))
-           warner(WARN_SYNTAX, "Reversed %c= operator",(int)tmp);
+           Perl_warner(aTHX_ WARN_SYNTAX, "Reversed %c= operator",(int)tmp);
        s--;
        if (PL_expect == XSTATE && isALPHA(tmp) &&
                (s == PL_linestart+1 || s[-2] == '\n') )
@@ -2717,6 +2695,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        }
 
        d = s;
+       tmp = (I32)*s;
        if (PL_lex_state == LEX_NORMAL)
            s = skipspace(s);
 
@@ -2732,7 +2711,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                        PL_bufptr = skipspace(PL_bufptr);
                        while (t < PL_bufend && *t != ']')
                            t++;
-                       warner(WARN_SYNTAX,
+                       Perl_warner(aTHX_ WARN_SYNTAX,
                                "Multidimensional syntax %.*s not supported",
                                (t - PL_bufptr) + 1, PL_bufptr);
                    }
@@ -2749,8 +2728,8 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    if (isIDFIRST_lazy(t)) {
                        t = scan_word(t, tmpbuf, sizeof tmpbuf, TRUE, &len);
                        for (; isSPACE(*t); t++) ;
-                       if (*t == ';' && perl_get_cv(tmpbuf, FALSE))
-                           warner(WARN_SYNTAX,
+                       if (*t == ';' && get_cv(tmpbuf, FALSE))
+                           Perl_warner(aTHX_ WARN_SYNTAX,
                                "You need to quote \"%s\"", tmpbuf);
                    }
                }
@@ -2758,7 +2737,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
        }
 
        PL_expect = XOPERATOR;
-       if (PL_lex_state == LEX_NORMAL && isSPACE(*d)) {
+       if (PL_lex_state == LEX_NORMAL && isSPACE((char)tmp)) {
            bool islop = (PL_last_lop == PL_oldoldbufptr);
            if (!islop || PL_last_lop_op == OP_GREPSTART)
                PL_expect = XOPERATOR;
@@ -2829,7 +2808,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    if (*t == '}' || *t == ']') {
                        t++;
                        PL_bufptr = skipspace(PL_bufptr);
-                       warner(WARN_SYNTAX,
+                       Perl_warner(aTHX_ WARN_SYNTAX,
                            "Scalar value %.*s better written as $%.*s",
                            t-PL_bufptr, PL_bufptr, t-PL_bufptr-1, PL_bufptr+1);
                    }
@@ -2943,7 +2922,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
     case '\\':
        s++;
        if (ckWARN(WARN_SYNTAX) && PL_lex_inwhat && isDIGIT(*s))
-           warner(WARN_SYNTAX,"Can't use \\%c to mean $%c in expression",
+           Perl_warner(aTHX_ WARN_SYNTAX,"Can't use \\%c to mean $%c in expression",
                        *s, *s);
        if (PL_expect == XOPERATOR)
            no_op("Backslash",s);
@@ -3062,7 +3041,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                gvp = 0;
                if (ckWARN(WARN_AMBIGUOUS) && hgv
                    && tmp != KEY_x && tmp != KEY_CORE) /* never ambiguous */
-                   warner(WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
                        "Ambiguous call resolved as CORE::%s(), %s",
                         GvENAME(hgv), "qualify as such or use &");
            }
@@ -3083,7 +3062,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    s = scan_word(s, PL_tokenbuf + len, sizeof PL_tokenbuf - len,
                                  TRUE, &morelen);
                    if (!morelen)
-                       croak("Bad name after %s%s", PL_tokenbuf,
+                       Perl_croak(aTHX_ "Bad name after %s%s", PL_tokenbuf,
                                *s == '\'' ? "'" : "::");
                    len += morelen;
                }
@@ -3091,7 +3070,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                if (PL_expect == XOPERATOR) {
                    if (PL_bufptr == PL_linestart) {
                        PL_curcop->cop_line--;
-                       warner(WARN_SEMICOLON, PL_warn_nosemi);
+                       Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
                        PL_curcop->cop_line++;
                    }
                    else
@@ -3106,7 +3085,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    PL_tokenbuf[len - 2] == ':' && PL_tokenbuf[len - 1] == ':')
                {
                    if (ckWARN(WARN_UNSAFE) && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV))
-                       warner(WARN_UNSAFE, 
+                       Perl_warner(aTHX_ WARN_UNSAFE, 
                            "Bareword \"%s\" refers to nonexistent package",
                             PL_tokenbuf);
                    len -= 2;
@@ -3123,7 +3102,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                /* if we saw a global override before, get the right name */
 
                if (gvp) {
-                   sv = newSVpv("CORE::GLOBAL::",14);
+                   sv = newSVpvn("CORE::GLOBAL::",14);
                    sv_catpv(sv,PL_tokenbuf);
                }
                else
@@ -3146,11 +3125,8 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    PL_oldoldbufptr < PL_bufptr &&
                    (PL_oldoldbufptr == PL_last_lop || PL_oldoldbufptr == PL_last_uni) &&
                    /* NO SKIPSPACE BEFORE HERE! */
-                   (PL_expect == XREF 
-                    || ((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF
-                    || (PL_last_lop_op == OP_ENTERSUB 
-                        && PL_last_proto 
-                        && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*')) )
+                   (PL_expect == XREF ||
+                    ((PL_opargs[PL_last_lop_op] >> OASHIFT)& 7) == OA_FILEREF))
                {
                    bool immediate_paren = *s == '(';
 
@@ -3166,8 +3142,10 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    /* (But it's an indir obj regardless for sort.) */
 
                    if ((PL_last_lop_op == OP_SORT ||
-                         (!immediate_paren && (!gv || !GvCVu(gv))) ) &&
-                        (PL_last_lop_op != OP_MAPSTART && PL_last_lop_op != OP_GREPSTART)){
+                         (!immediate_paren && (!gv || !GvCVu(gv)))) &&
+                        (PL_last_lop_op != OP_MAPSTART &&
+                        PL_last_lop_op != OP_GREPSTART))
+                   {
                        PL_expect = (PL_last_lop == PL_oldoldbufptr) ? XTERM : XOPERATOR;
                        goto bareword;
                    }
@@ -3180,11 +3158,8 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                if (*s == '(') {
                    CLINE;
                    if (gv && GvCVu(gv)) {
-                       CV *cv;
-                       if ((cv = GvCV(gv)) && SvPOK(cv))
-                           PL_last_proto = SvPV((SV*)cv, n_a);
                        for (d = s + 1; *d == ' ' || *d == '\t'; d++) ;
-                       if (*d == ')' && (sv = cv_const_sv(cv))) {
+                       if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) {
                            s = d + 1;
                            goto its_constant;
                        }
@@ -3193,7 +3168,6 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    PL_expect = XOPERATOR;
                    force_next(WORD);
                    yylval.ival = 0;
-                   PL_last_lop_op = OP_ENTERSUB;
                    TOKEN('&');
                }
 
@@ -3215,10 +3189,8 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                if (gv && GvCVu(gv)) {
                    CV* cv;
                    if (lastchar == '-')
-                       warn("Ambiguous use of -%s resolved as -&%s()",
+                       Perl_warn(aTHX_ "Ambiguous use of -%s resolved as -&%s()",
                                PL_tokenbuf, PL_tokenbuf);
-                   PL_last_lop = PL_oldbufptr;
-                   PL_last_lop_op = OP_ENTERSUB;
                    /* Check for a constant sub */
                    cv = GvCV(gv);
                    if ((sv = cv_const_sv(cv))) {
@@ -3232,60 +3204,49 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    /* Resolve to GV now. */
                    op_free(yylval.opval);
                    yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
+                   yylval.opval->op_private |= OPpENTERSUB_NOPAREN;
+                   PL_last_lop = PL_oldbufptr;
                    PL_last_lop_op = OP_ENTERSUB;
                    /* Is there a prototype? */
                    if (SvPOK(cv)) {
                        STRLEN len;
-                       PL_last_proto = SvPV((SV*)cv, len);
+                       char *proto = SvPV((SV*)cv, len);
                        if (!len)
                            TERM(FUNC0SUB);
-                       if (strEQ(PL_last_proto, "$"))
+                       if (strEQ(proto, "$"))
                            OPERATOR(UNIOPSUB);
-                       if (*PL_last_proto == '&' && *s == '{') {
+                       if (*proto == '&' && *s == '{') {
                            sv_setpv(PL_subname,"__ANON__");
                            PREBLOCK(LSTOPSUB);
                        }
-                   } else
-                       PL_last_proto = NULL;
+                   }
                    PL_nextval[PL_nexttoke].opval = yylval.opval;
                    PL_expect = XTERM;
                    force_next(WORD);
                    TOKEN(NOAMP);
                }
 
-               if (PL_hints & HINT_STRICT_SUBS &&
-                   lastchar != '-' &&
-                   strnNE(s,"->",2) &&
-                   PL_last_lop_op != OP_TRUNCATE &&  /* S/F prototype in opcode.pl */
-                   PL_last_lop_op != OP_ACCEPT &&
-                   PL_last_lop_op != OP_PIPE_OP &&
-                   PL_last_lop_op != OP_SOCKPAIR &&
-                   !(PL_last_lop_op == OP_ENTERSUB 
-                        && PL_last_proto 
-                        && PL_last_proto[PL_last_proto[0] == ';' ? 1 : 0] == '*'))
-               {
-                   warn(
-                    "Bareword \"%s\" not allowed while \"strict subs\" in use",
-                       PL_tokenbuf);
-                   ++PL_error_count;
-               }
-
                /* Call it a bare word */
 
-           bareword:
-               if (ckWARN(WARN_RESERVED)) {
-                   if (lastchar != '-') {
-                       for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
-                       if (!*d)
-                           warner(WARN_RESERVED, PL_warn_reserved, PL_tokenbuf);
+               if (PL_hints & HINT_STRICT_SUBS)
+                   yylval.opval->op_private |= OPpCONST_STRICT;
+               else {
+               bareword:
+                   if (ckWARN(WARN_RESERVED)) {
+                       if (lastchar != '-') {
+                           for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
+                           if (!*d)
+                               Perl_warner(aTHX_ WARN_RESERVED, PL_warn_reserved,
+                                      PL_tokenbuf);
+                       }
                    }
                }
 
            safe_bareword:
                if (lastchar && strchr("*%&", lastchar)) {
-                   warn("Operator or semicolon missing before %c%s",
+                   Perl_warn(aTHX_ "Operator or semicolon missing before %c%s",
                        lastchar, PL_tokenbuf);
-                   warn("Ambiguous use of %c resolved as operator %c",
+                   Perl_warn(aTHX_ "Ambiguous use of %c resolved as operator %c",
                        lastchar, lastchar);
                }
                TOKEN(WORD);
@@ -3298,7 +3259,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
 
        case KEY___LINE__:
            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                   newSVpvf("%ld", (long)PL_curcop->cop_line));
+                                   Perl_newSVpvf(aTHX_ "%ld", (long)PL_curcop->cop_line));
            TERM(THING);
 
        case KEY___PACKAGE__:
@@ -3317,7 +3278,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                char *pname = "main";
                if (PL_tokenbuf[2] == 'D')
                    pname = HvNAME(PL_curstash ? PL_curstash : PL_defstash);
-               gv = gv_fetchpv(form("%s::DATA", pname), TRUE, SVt_PVIO);
+               gv = gv_fetchpv(Perl_form(aTHX_ "%s::DATA", pname), TRUE, SVt_PVIO);
                GvMULTI_on(gv);
                if (!GvIO(gv))
                    GvIOp(gv) = newIO();
@@ -3532,7 +3493,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    p += 2;
                p = skipspace(p);
                if (isIDFIRST_lazy(p))
-                   croak("Missing $ on loop variable");
+                   Perl_croak(aTHX_ "Missing $ on loop variable");
            }
            OPERATOR(FOR);
 
@@ -3776,7 +3737,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                for (d = s; isALNUM_lazy(d); d++) ;
                t = skipspace(d);
                if (strchr("|&*+-=!?:.", *t))
-                   warn("Precedence problem: open %.*s should be open(%.*s)",
+                   Perl_warn(aTHX_ "Precedence problem: open %.*s should be open(%.*s)",
                        d-s,s, d-s,s);
            }
            LOP(OP_OPEN,XTERM);
@@ -3850,12 +3811,12 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                        if (!warned && ckWARN(WARN_SYNTAX)) {
                            for (; !isSPACE(*d) && len; --len, ++d) {
                                if (*d == ',') {
-                                   warner(WARN_SYNTAX,
+                                   Perl_warner(aTHX_ WARN_SYNTAX,
                                        "Possible attempt to separate words with commas");
                                    ++warned;
                                }
                                else if (*d == '#') {
-                                   warner(WARN_SYNTAX,
+                                   Perl_warner(aTHX_ WARN_SYNTAX,
                                        "Possible attempt to put comments in qw() list");
                                    ++warned;
                                }
@@ -4055,7 +4016,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
            checkcomma(s,PL_tokenbuf,"subroutine name");
            s = skipspace(s);
            if (*s == ';' || *s == ')')         /* probably a close */
-               croak("sort is now a reserved word");
+               Perl_croak(aTHX_ "sort is now a reserved word");
            PL_expect = XTERM;
            s = force_word(s,WORD,TRUE,TRUE,FALSE);
            LOP(OP_SORT,XREF);
@@ -4125,7 +4086,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
                    if (PL_lex_stuff)
                        SvREFCNT_dec(PL_lex_stuff);
                    PL_lex_stuff = Nullsv;
-                   croak("Prototype not terminated");
+                   Perl_croak(aTHX_ "Prototype not terminated");
                }
                /* strip spaces */
                d = SvPVX(PL_lex_stuff);
@@ -4317,7 +4278,7 @@ int yylex(PERL_YYLEX_PARAM_DECL)
 }
 
 I32
-keyword(register char *d, I32 len)
+Perl_keyword(pTHX_ register char *d, I32 len)
 {
     switch (*d) {
     case '_':
@@ -4440,7 +4401,7 @@ keyword(register char *d, I32 len)
            break;
        case 6:
            if (strEQ(d,"exists"))              return KEY_exists;
-           if (strEQ(d,"elseif")) warn("elseif should be elsif");
+           if (strEQ(d,"elseif")) Perl_warn(aTHX_ "elseif should be elsif");
            break;
        case 8:
            if (strEQ(d,"endgrent"))            return -KEY_endgrent;
@@ -4936,7 +4897,7 @@ keyword(register char *d, I32 len)
 }
 
 STATIC void
-checkcomma(register char *s, char *name, char *what)
+S_checkcomma(pTHX_ register char *s, char *name, char *what)
 {
     char *w;
 
@@ -4953,7 +4914,7 @@ checkcomma(register char *s, char *name, char *what)
            if (*w)
                for (; *w && isSPACE(*w); w++) ;
            if (!*w || !strchr(";|})]oaiuw!=", *w))     /* an advisory hack only... */
-               warner(WARN_SYNTAX, "%s (...) interpreted as function",name);
+               Perl_warner(aTHX_ WARN_SYNTAX, "%s (...) interpreted as function",name);
        }
     }
     while (s < PL_bufend && isSPACE(*s))
@@ -4971,17 +4932,17 @@ checkcomma(register char *s, char *name, char *what)
        if (*s == ',') {
            int kw;
            *s = '\0';
-           kw = keyword(w, s - w) || perl_get_cv(w, FALSE) != 0;
+           kw = keyword(w, s - w) || get_cv(w, FALSE) != 0;
            *s = ',';
            if (kw)
                return;
-           croak("No comma allowed after %s", what);
+           Perl_croak(aTHX_ "No comma allowed after %s", what);
        }
     }
 }
 
 STATIC SV *
-new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) 
+S_new_constant(pTHX_ char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) 
 {
     dSP;
     HV *table = GvHV(PL_hintgv);                /* ^H */
@@ -5005,7 +4966,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
     sv_2mortal(sv);                    /* Parent created it permanently */
     cv = *cvp;
     if (!pv)
-       pv = sv_2mortal(newSVpv(s, len));
+       pv = sv_2mortal(newSVpvn(s, len));
     if (type)
        typesv = sv_2mortal(newSVpv(type, 0));
     else
@@ -5023,7 +4984,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
     if (PERLDB_SUB && PL_curstash != PL_debstash)
        PL_op->op_private |= OPpENTERSUB_DB;
     PUTBACK;
-    pp_pushmark(ARGS);
+    Perl_pp_pushmark(aTHX);
 
     EXTEND(sp, 4);
     PUSHs(pv);
@@ -5032,8 +4993,8 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
     PUSHs(cv);
     PUTBACK;
 
-    if (PL_op = pp_entersub(ARGS))
-      CALLRUNOPS();
+    if (PL_op = Perl_pp_entersub(aTHX))
+      CALLRUNOPS(aTHX);
     LEAVE;
     SPAGAIN;
 
@@ -5051,13 +5012,13 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type)
 }
 
 STATIC char *
-scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLEN *slp)
+S_scan_word(pTHX_ register char *s, char *dest, STRLEN destlen, int allow_package, STRLEN *slp)
 {
     register char *d = dest;
     register char *e = d + destlen - 3;  /* two-character token, ending NUL */
     for (;;) {
        if (d >= e)
-           croak(ident_too_long);
+           Perl_croak(aTHX_ ident_too_long);
        if (isALNUM(*s))        /* UTF handled below */
            *d++ = *s++;
        else if (*s == '\'' && allow_package && isIDFIRST_lazy(s+1)) {
@@ -5074,7 +5035,7 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE
            while (*t & 0x80 && is_utf8_mark((U8*)t))
                t += UTF8SKIP(t);
            if (d + (t - s) > e)
-               croak(ident_too_long);
+               Perl_croak(aTHX_ ident_too_long);
            Copy(s, d, t - s, char);
            d += t - s;
            s = t;
@@ -5088,7 +5049,7 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE
 }
 
 STATIC char *
-scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I32 ck_uni)
+S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN destlen, I32 ck_uni)
 {
     register char *d;
     register char *e;
@@ -5104,14 +5065,14 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
     if (isDIGIT(*s)) {
        while (isDIGIT(*s)) {
            if (d >= e)
-               croak(ident_too_long);
+               Perl_croak(aTHX_ ident_too_long);
            *d++ = *s++;
        }
     }
     else {
        for (;;) {
            if (d >= e)
-               croak(ident_too_long);
+               Perl_croak(aTHX_ ident_too_long);
            if (isALNUM(*s))    /* UTF handled below */
                *d++ = *s++;
            else if (*s == '\'' && isIDFIRST_lazy(s+1)) {
@@ -5128,7 +5089,7 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                while (*t & 0x80 && is_utf8_mark((U8*)t))
                    t += UTF8SKIP(t);
                if (d + (t - s) > e)
-                   croak(ident_too_long);
+                   Perl_croak(aTHX_ ident_too_long);
                Copy(s, d, t - s, char);
                d += t - s;
                s = t;
@@ -5158,7 +5119,7 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
     if (s < send)
        *d = *s++;
     d[1] = '\0';
-    if (*d == '^' && *s && (isUPPER(*s) || strchr("[\\]^_?", *s))) {
+    if (*d == '^' && *s && isCONTROLVAR(*s)) {
        *d = toCTRL(*s);
        s++;
     }
@@ -5186,8 +5147,10 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                s = e;
            }
            else {
-               while (isALNUM(*s) || *s == ':')
+               while ((isALNUM(*s) || *s == ':') && d < e)
                    *d++ = *s++;
+               if (d >= e)
+                   Perl_croak(aTHX_ ident_too_long);
            }
            *d = '\0';
            while (s < send && (*s == ' ' || *s == '\t')) s++;
@@ -5195,7 +5158,7 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
                    char *brack = *s == '[' ? "[...]" : "{...}";
-                   warner(WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
                        "Ambiguous use of %c{%s%s} resolved to %c%s%s",
                        funny, dest, brack, funny, dest, brack);
                }
@@ -5204,6 +5167,19 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
                return s;
            }
+       } 
+       /* Handle extended ${^Foo} variables 
+        * 1999-02-27 mjd-perl-patch@plover.com */
+       else if (!isALNUM(*d) && !isPRINT(*d) /* isCTRL(d) */
+                && isALNUM(*s))
+       {
+           d++;
+           while (isALNUM(*s) && d < e) {
+               *d++ = *s++;
+           }
+           if (d >= e)
+               Perl_croak(aTHX_ ident_too_long);
+           *d = '\0';
        }
        if (*s == '}') {
            s++;
@@ -5214,9 +5190,9 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
            if (PL_lex_state == LEX_NORMAL) {
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_AMBIGUOUS) &&
-                   (keyword(dest, d - dest) || perl_get_cv(dest, FALSE)))
+                   (keyword(dest, d - dest) || get_cv(dest, FALSE)))
                {
-                   warner(WARN_AMBIGUOUS,
+                   Perl_warner(aTHX_ WARN_AMBIGUOUS,
                        "Ambiguous use of %c{%s} resolved to %c%s",
                        funny, dest, funny, dest);
                }
@@ -5232,7 +5208,8 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
     return s;
 }
 
-void pmflag(U16 *pmfl, int ch)
+void
+Perl_pmflag(pTHX_ U16 *pmfl, int ch)
 {
     if (ch == 'i')
        *pmfl |= PMf_FOLD;
@@ -5251,7 +5228,7 @@ void pmflag(U16 *pmfl, int ch)
 }
 
 STATIC char *
-scan_pat(char *start, I32 type)
+S_scan_pat(pTHX_ char *start, I32 type)
 {
     PMOP *pm;
     char *s;
@@ -5261,7 +5238,7 @@ scan_pat(char *start, I32 type)
        if (PL_lex_stuff)
            SvREFCNT_dec(PL_lex_stuff);
        PL_lex_stuff = Nullsv;
-       croak("Search pattern not terminated");
+       Perl_croak(aTHX_ "Search pattern not terminated");
     }
 
     pm = (PMOP*)newPMOP(type, 0);
@@ -5283,7 +5260,7 @@ scan_pat(char *start, I32 type)
 }
 
 STATIC char *
-scan_subst(char *start)
+S_scan_subst(pTHX_ char *start)
 {
     register char *s;
     register PMOP *pm;
@@ -5298,7 +5275,7 @@ scan_subst(char *start)
        if (PL_lex_stuff)
            SvREFCNT_dec(PL_lex_stuff);
        PL_lex_stuff = Nullsv;
-       croak("Substitution pattern not terminated");
+       Perl_croak(aTHX_ "Substitution pattern not terminated");
     }
 
     if (s[-1] == PL_multi_open)
@@ -5313,7 +5290,7 @@ scan_subst(char *start)
        if (PL_lex_repl)
            SvREFCNT_dec(PL_lex_repl);
        PL_lex_repl = Nullsv;
-       croak("Substitution replacement not terminated");
+       Perl_croak(aTHX_ "Substitution replacement not terminated");
     }
     PL_multi_start = first_start;      /* so whole substitution is taken together */
 
@@ -5331,14 +5308,17 @@ scan_subst(char *start)
 
     if (es) {
        SV *repl;
+       PL_sublex_info.super_bufptr = s;
+       PL_sublex_info.super_bufend = PL_bufend;
+       PL_multi_end = 0;
        pm->op_pmflags |= PMf_EVAL;
-       repl = newSVpv("",0);
+       repl = newSVpvn("",0);
        while (es-- > 0)
            sv_catpv(repl, es ? "eval " : "do ");
        sv_catpvn(repl, "{ ", 2);
        sv_catsv(repl, PL_lex_repl);
        sv_catpvn(repl, " };", 2);
-       SvCOMPILED_on(repl);
+       SvEVALED_on(repl);
        SvREFCNT_dec(PL_lex_repl);
        PL_lex_repl = repl;
     }
@@ -5350,7 +5330,7 @@ scan_subst(char *start)
 }
 
 STATIC char *
-scan_trans(char *start)
+S_scan_trans(pTHX_ char *start)
 {
     register char* s;
     OP *o;
@@ -5368,7 +5348,7 @@ scan_trans(char *start)
        if (PL_lex_stuff)
            SvREFCNT_dec(PL_lex_stuff);
        PL_lex_stuff = Nullsv;
-       croak("Transliteration pattern not terminated");
+       Perl_croak(aTHX_ "Transliteration pattern not terminated");
     }
     if (s[-1] == PL_multi_open)
        s--;
@@ -5381,7 +5361,7 @@ scan_trans(char *start)
        if (PL_lex_repl)
            SvREFCNT_dec(PL_lex_repl);
        PL_lex_repl = Nullsv;
-       croak("Transliteration replacement not terminated");
+       Perl_croak(aTHX_ "Transliteration replacement not terminated");
     }
 
     if (UTF) {
@@ -5417,7 +5397,7 @@ scan_trans(char *start)
                    utf8 |= OPpTRANS_TO_UTF;
                break;
            default: 
-               croak("Too many /C and /U options");
+               Perl_croak(aTHX_ "Too many /C and /U options");
            }
        }
        s++;
@@ -5430,7 +5410,7 @@ scan_trans(char *start)
 }
 
 STATIC char *
-scan_heredoc(register char *s)
+S_scan_heredoc(pTHX_ register char *s)
 {
     dTHR;
     SV *herewas;
@@ -5470,7 +5450,7 @@ scan_heredoc(register char *s)
        }
     }
     if (d >= PL_tokenbuf + sizeof PL_tokenbuf - 1)
-       croak("Delimiter for here document is too long");
+       Perl_croak(aTHX_ "Delimiter for here document is too long");
     *d++ = '\n';
     *d = '\0';
     len = d - PL_tokenbuf;
@@ -5500,9 +5480,9 @@ scan_heredoc(register char *s)
 #endif
     d = "\n";
     if (outer || !(d=ninstr(s,PL_bufend,d,d+1)))
-       herewas = newSVpv(s,PL_bufend-s);
+       herewas = newSVpvn(s,PL_bufend-s);
     else
-       s--, herewas = newSVpv(s,d-s);
+       s--, herewas = newSVpvn(s,d-s);
     s += SvCUR(herewas);
 
     tmpstr = NEWSV(87,79);
@@ -5520,7 +5500,33 @@ scan_heredoc(register char *s)
     PL_multi_start = PL_curcop->cop_line;
     PL_multi_open = PL_multi_close = '<';
     term = *PL_tokenbuf;
-    if (!outer) {
+    if (PL_lex_inwhat == OP_SUBST && PL_in_eval && !PL_rsfp) {
+       char *bufptr = PL_sublex_info.super_bufptr;
+       char *bufend = PL_sublex_info.super_bufend;
+       char *olds = s - SvCUR(herewas);
+       s = strchr(bufptr, '\n');
+       if (!s)
+           s = bufend;
+       d = s;
+       while (s < bufend &&
+         (*s != term || memNE(s,PL_tokenbuf,len)) ) {
+           if (*s++ == '\n')
+               PL_curcop->cop_line++;
+       }
+       if (s >= bufend) {
+           PL_curcop->cop_line = PL_multi_start;
+           missingterm(PL_tokenbuf);
+       }
+       sv_setpvn(herewas,bufptr,d-bufptr+1);
+       sv_setpvn(tmpstr,d+1,s-d);
+       s += len - 1;
+       sv_catpvn(herewas,s,bufend-s);
+       (void)strcpy(bufptr,SvPVX(herewas));
+
+       s = olds;
+       goto retval;
+    }
+    else if (!outer) {
        d = s;
        while (s < PL_bufend &&
          (*s != term || memNE(s,PL_tokenbuf,len)) ) {
@@ -5584,8 +5590,9 @@ scan_heredoc(register char *s)
            sv_catsv(tmpstr,PL_linestr);
        }
     }
-    PL_multi_end = PL_curcop->cop_line;
     s++;
+retval:
+    PL_multi_end = PL_curcop->cop_line;
     if (SvCUR(tmpstr) + 5 < SvLEN(tmpstr)) {
        SvLEN_set(tmpstr, SvCUR(tmpstr) + 1);
        Renew(SvPVX(tmpstr), SvLEN(tmpstr), char);
@@ -5613,25 +5620,29 @@ scan_heredoc(register char *s)
 */
 
 STATIC char *
-scan_inputsymbol(char *start)
+S_scan_inputsymbol(pTHX_ char *start)
 {
     register char *s = start;          /* current position in buffer */
     register char *d;
     register char *e;
+    char *end;
     I32 len;
 
     d = PL_tokenbuf;                   /* start of temp holding space */
     e = PL_tokenbuf + sizeof PL_tokenbuf;      /* end of temp holding space */
-    s = delimcpy(d, e, s + 1, PL_bufend, '>', &len);   /* extract until > */
+    end = strchr(s, '\n');
+    if (!end)
+       end = PL_bufend;
+    s = delimcpy(d, e, s + 1, end, '>', &len); /* extract until > */
 
     /* die if we didn't have space for the contents of the <>,
-       or if it didn't end
+       or if it didn't end, or if we see a newline
     */
 
     if (len >= sizeof PL_tokenbuf)
-       croak("Excessively long <> operator");
-    if (s >= PL_bufend)
-       croak("Unterminated <> operator");
+       Perl_croak(aTHX_ "Excessively long <> operator");
+    if (s >= end)
+       Perl_croak(aTHX_ "Unterminated <> operator");
 
     s++;
 
@@ -5659,7 +5670,7 @@ scan_inputsymbol(char *start)
        set_csh();
        s = scan_str(start);
        if (!s)
-          croak("Glob not terminated");
+          Perl_croak(aTHX_ "Glob not terminated");
        return s;
     }
     else {
@@ -5749,7 +5760,7 @@ scan_inputsymbol(char *start)
 */
 
 STATIC char *
-scan_str(char *start)
+S_scan_str(pTHX_ char *start)
 {
     dTHR;
     SV *sv;                            /* scalar value: string */
@@ -5936,7 +5947,7 @@ scan_str(char *start)
 */
   
 char *
-scan_num(char *start)
+Perl_scan_num(pTHX_ char *start)
 {
     register char *s = start;          /* current position in buffer */
     register char *d;                  /* destination in temp buffer */
@@ -5952,7 +5963,7 @@ scan_num(char *start)
 
     switch (*s) {
     default:
-      croak("panic: scan_num");
+      Perl_croak(aTHX_ "panic: scan_num");
       
     /* if it starts with a 0, it could be an octal number, a decimal in
        0.13 disguise, or a hexadecimal number, or a binary number.
@@ -6007,17 +6018,17 @@ scan_num(char *start)
                /* 8 and 9 are not octal */
                case '8': case '9':
                    if (shift == 3)
-                       yyerror("Illegal octal digit");
+                       yyerror(Perl_form(aTHX_ "Illegal octal digit '%c'", *s));
                    else
                        if (shift == 1)
-                           yyerror("Illegal binary digit");
+                           yyerror(Perl_form(aTHX_ "Illegal binary digit '%c'", *s));
                    /* FALL THROUGH */
 
                /* octal digits */
                case '2': case '3': case '4':
                case '5': case '6': case '7':
                    if (shift == 1)
-                       yyerror("Illegal binary digit");
+                       yyerror(Perl_form(aTHX_ "Illegal binary digit '%c'", *s));
                    /* FALL THROUGH */
 
                case '0': case '1':
@@ -6040,7 +6051,7 @@ scan_num(char *start)
                    n = u << shift;     /* make room for the digit */
                    if (!overflowed && (n >> shift) != u
                        && !(PL_hints & HINT_NEW_BINARY)) {
-                       warn("Integer overflow in %s number",
+                       Perl_warn(aTHX_ "Integer overflow in %s number",
                             (shift == 4) ? "hex"
                             : ((shift == 3) ? "octal" : "binary"));
                        overflowed = TRUE;
@@ -6080,13 +6091,13 @@ scan_num(char *start)
            if (*s == '_') {
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_SYNTAX) && lastub && s - lastub != 3)
-                   warner(WARN_SYNTAX, "Misplaced _ in number");
+                   Perl_warner(aTHX_ WARN_SYNTAX, "Misplaced _ in number");
                lastub = ++s;
            }
            else {
                /* check for end of fixed-length buffer */
                if (d >= e)
-                   croak(number_too_long);
+                   Perl_croak(aTHX_ number_too_long);
                /* if we're ok, copy the character */
                *d++ = *s++;
            }
@@ -6096,7 +6107,7 @@ scan_num(char *start)
        if (lastub && s - lastub != 3) {
            dTHR;
            if (ckWARN(WARN_SYNTAX))
-               warner(WARN_SYNTAX, "Misplaced _ in number");
+               Perl_warner(aTHX_ WARN_SYNTAX, "Misplaced _ in number");
        }
 
        /* read a decimal portion if there is one.  avoid
@@ -6113,7 +6124,7 @@ scan_num(char *start)
            for (; isDIGIT(*s) || *s == '_'; s++) {
                /* fixed length buffer check */
                if (d >= e)
-                   croak(number_too_long);
+                   Perl_croak(aTHX_ number_too_long);
                if (*s != '_')
                    *d++ = *s;
            }
@@ -6134,7 +6145,7 @@ scan_num(char *start)
            /* read digits of exponent (no underbars :-) */
            while (isDIGIT(*s)) {
                if (d >= e)
-                   croak(number_too_long);
+                   Perl_croak(aTHX_ number_too_long);
                *d++ = *s++;
            }
        }
@@ -6144,9 +6155,8 @@ scan_num(char *start)
 
        /* make an sv from the string */
        sv = NEWSV(92,0);
-       /* reset numeric locale in case we were earlier left in Swaziland */
-       SET_NUMERIC_STANDARD();
-       value = atof(PL_tokenbuf);
+
+       value = Atof(PL_tokenbuf);
 
        /* 
           See if we can make do with an integer value without loss of
@@ -6177,12 +6187,12 @@ scan_num(char *start)
 }
 
 STATIC char *
-scan_formline(register char *s)
+S_scan_formline(pTHX_ register char *s)
 {
     dTHR;
     register char *eol;
     register char *t;
-    SV *stuff = newSVpv("",0);
+    SV *stuff = newSVpvn("",0);
     bool needargs = FALSE;
 
     while (!needargs) {
@@ -6251,7 +6261,7 @@ scan_formline(register char *s)
 }
 
 STATIC void
-set_csh(void)
+S_set_csh(pTHX)
 {
 #ifdef CSH
     if (!PL_cshlen)
@@ -6260,7 +6270,7 @@ set_csh(void)
 }
 
 I32
-start_subparse(I32 is_format, U32 flags)
+Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
 {
     dTHR;
     I32 oldsavestack_ix = PL_savestack_ix;
@@ -6295,7 +6305,7 @@ start_subparse(I32 is_format, U32 flags)
     PL_padix = 0;
     PL_subline = PL_curcop->cop_line;
 #ifdef USE_THREADS
-    av_store(PL_comppad_name, 0, newSVpv("@_", 2));
+    av_store(PL_comppad_name, 0, newSVpvn("@_", 2));
     PL_curpad[0] = (SV*)newAV();
     SvPADMY_on(PL_curpad[0]);  /* XXX Needed? */
 #endif /* USE_THREADS */
@@ -6317,18 +6327,18 @@ start_subparse(I32 is_format, U32 flags)
 }
 
 int
-yywarn(char *s)
+Perl_yywarn(pTHX_ char *s)
 {
     dTHR;
     --PL_error_count;
-    PL_in_eval |= 2;
+    PL_in_eval |= EVAL_WARNONLY;
     yyerror(s);
-    PL_in_eval &= ~2;
+    PL_in_eval &= ~EVAL_WARNONLY;
     return 0;
 }
 
 int
-yyerror(char *s)
+Perl_yyerror(pTHX_ char *s)
 {
     dTHR;
     char *where = NULL;
@@ -6364,36 +6374,36 @@ yyerror(char *s)
            where = "within string";
     }
     else {
-       SV *where_sv = sv_2mortal(newSVpv("next char ", 0));
+       SV *where_sv = sv_2mortal(newSVpvn("next char ", 10));
        if (yychar < 32)
-           sv_catpvf(where_sv, "^%c", toCTRL(yychar));
+           Perl_sv_catpvf(aTHX_ where_sv, "^%c", toCTRL(yychar));
        else if (isPRINT_LC(yychar))
-           sv_catpvf(where_sv, "%c", yychar);
+           Perl_sv_catpvf(aTHX_ where_sv, "%c", yychar);
        else
-           sv_catpvf(where_sv, "\\%03o", yychar & 255);
+           Perl_sv_catpvf(aTHX_ where_sv, "\\%03o", yychar & 255);
        where = SvPVX(where_sv);
     }
     msg = sv_2mortal(newSVpv(s, 0));
-    sv_catpvf(msg, " at %_ line %ld, ",
+    Perl_sv_catpvf(aTHX_ msg, " at %_ line %ld, ",
              GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
     if (context)
-       sv_catpvf(msg, "near \"%.*s\"\n", contlen, context);
+       Perl_sv_catpvf(aTHX_ msg, "near \"%.*s\"\n", contlen, context);
     else
-       sv_catpvf(msg, "%s\n", where);
+       Perl_sv_catpvf(aTHX_ msg, "%s\n", where);
     if (PL_multi_start < PL_multi_end && (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) {
-       sv_catpvf(msg,
+       Perl_sv_catpvf(aTHX_ msg,
        "  (Might be a runaway multi-line %c%c string starting on line %ld)\n",
                (int)PL_multi_open,(int)PL_multi_close,(long)PL_multi_start);
         PL_multi_end = 0;
     }
-    if (PL_in_eval & 2)
-       warn("%_", msg);
+    if (PL_in_eval & EVAL_WARNONLY)
+       Perl_warn(aTHX_ "%_", msg);
     else if (PL_in_eval)
        sv_catsv(ERRSV, msg);
     else
        PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
     if (++PL_error_count >= 10)
-       croak("%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv));
+       Perl_croak(aTHX_ "%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv));
     PL_in_my = 0;
     PL_in_my_stash = Nullhv;
     return 0;