This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
improved diagnostic on syntax errors at EOL
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index 128b828..66d9947 100644 (file)
--- a/toke.c
+++ b/toke.c
 #include "EXTERN.h"
 #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 *q _((SV *sv));
+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));
+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));
@@ -49,20 +53,26 @@ 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";
 
-static char *linestart;                /* beg. of most recently read line */
-
-static char pending_ident;     /* pending identifier lookup */
-
-static struct {
-    I32 super_state;   /* lexer state to save */
-    I32 sub_inwhat;    /* "lex_inwhat" to use */
-    OP *sub_op;                /* "lex_op" to use */
-} sublex_info;
+#define UTF (PL_hints & HINT_UTF8)
+/*
+ * Note: we try to be careful never to call the isXXX_utf8() functions
+ * unless we're pretty sure we've seen the beginning of a UTF-8 character
+ * (that is, the two high bits are set).  Otherwise we risk loading in the
+ * heavy-duty SWASHINIT and SWASHGET routines unnecessarily.
+ */
+#define isIDFIRST_lazy(p) ((!UTF || (*((U8*)p) < 0xc0)) \
+                               ? isIDFIRST(*(p)) \
+                               : isIDFIRST_utf8((U8*)p))
+#define isALNUM_lazy(p) ((!UTF || (*((U8*)p) < 0xc0)) \
+                               ? isALNUM(*(p)) \
+                               : isALNUM_utf8((U8*)p))
 
 /* 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).
@@ -99,57 +109,69 @@ static struct {
 #undef ff_next
 #endif
 
+#ifdef USE_PURE_BISON
+YYSTYPE* yylval_pointer = NULL;
+int* yychar_pointer = NULL;
+#  undef yylval
+#  undef yychar
+#  define yylval (*yylval_pointer)
+#  define yychar (*yychar_pointer)
+#  define PERL_YYLEX_PARAM yylval_pointer,yychar_pointer
+#else
+#  define PERL_YYLEX_PARAM
+#endif
+
 #include "keywords.h"
 
 #ifdef CLINE
 #undef CLINE
 #endif
-#define CLINE (copline = (curcop->cop_line < copline ? curcop->cop_line : copline))
-
-#define TOKEN(retval) return (bufptr = s,(int)retval)
-#define OPERATOR(retval) return (expect = XTERM,bufptr = s,(int)retval)
-#define AOPERATOR(retval) return ao((expect = XTERM,bufptr = s,(int)retval))
-#define PREBLOCK(retval) return (expect = XBLOCK,bufptr = s,(int)retval)
-#define PRETERMBLOCK(retval) return (expect = XTERMBLOCK,bufptr = s,(int)retval)
-#define PREREF(retval) return (expect = XREF,bufptr = s,(int)retval)
-#define TERM(retval) return (CLINE, expect = XOPERATOR,bufptr = s,(int)retval)
-#define LOOPX(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)LOOPEX)
-#define FTST(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)UNIOP)
-#define FUN0(f) return(yylval.ival = f,expect = XOPERATOR,bufptr = s,(int)FUNC0)
-#define FUN1(f) return(yylval.ival = f,expect = XOPERATOR,bufptr = s,(int)FUNC1)
-#define BOop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)BITOROP))
-#define BAop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)BITANDOP))
-#define SHop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)SHIFTOP))
-#define PWop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)POWOP))
-#define PMop(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)MATCHOP)
-#define Aop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)ADDOP))
-#define Mop(f) return ao((yylval.ival=f,expect = XTERM,bufptr = s,(int)MULOP))
-#define Eop(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)EQOP)
-#define Rop(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)RELOP)
+#define CLINE (PL_copline = (PL_curcop->cop_line < PL_copline ? PL_curcop->cop_line : PL_copline))
+
+#define TOKEN(retval) return (PL_bufptr = s,(int)retval)
+#define OPERATOR(retval) return (PL_expect = XTERM,PL_bufptr = s,(int)retval)
+#define AOPERATOR(retval) return ao((PL_expect = XTERM,PL_bufptr = s,(int)retval))
+#define PREBLOCK(retval) return (PL_expect = XBLOCK,PL_bufptr = s,(int)retval)
+#define PRETERMBLOCK(retval) return (PL_expect = XTERMBLOCK,PL_bufptr = s,(int)retval)
+#define PREREF(retval) return (PL_expect = XREF,PL_bufptr = s,(int)retval)
+#define TERM(retval) return (CLINE, PL_expect = XOPERATOR,PL_bufptr = s,(int)retval)
+#define LOOPX(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LOOPEX)
+#define FTST(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)UNIOP)
+#define FUN0(f) return(yylval.ival = f,PL_expect = XOPERATOR,PL_bufptr = s,(int)FUNC0)
+#define FUN1(f) return(yylval.ival = f,PL_expect = XOPERATOR,PL_bufptr = s,(int)FUNC1)
+#define BOop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)BITOROP))
+#define BAop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)BITANDOP))
+#define SHop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)SHIFTOP))
+#define PWop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)POWOP))
+#define PMop(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)MATCHOP)
+#define Aop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)ADDOP))
+#define Mop(f) return ao((yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)MULOP))
+#define Eop(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)EQOP)
+#define Rop(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)RELOP)
 
 /* This bit of chicanery makes a unary function followed by
  * a parenthesis into a function with one argument, highest precedence.
  */
 #define UNI(f) return(yylval.ival = f, \
-       expect = XTERM, \
-       bufptr = s, \
-       last_uni = oldbufptr, \
-       last_lop_op = f, \
+       PL_expect = XTERM, \
+       PL_bufptr = s, \
+       PL_last_uni = PL_oldbufptr, \
+       PL_last_lop_op = f, \
        (*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) )
 
 #define UNIBRACK(f) return(yylval.ival = f, \
-       bufptr = s, \
-       last_uni = oldbufptr, \
+       PL_bufptr = s, \
+       PL_last_uni = PL_oldbufptr, \
        (*s == '(' || (s = skipspace(s), *s == '(') ? (int)FUNC1 : (int)UNIOP) )
 
 /* grandfather return to old style */
-#define OLDLOP(f) return(yylval.ival=f,expect = XTERM,bufptr = s,(int)LSTOP)
+#define OLDLOP(f) return(yylval.ival=f,PL_expect = XTERM,PL_bufptr = s,(int)LSTOP)
 
-static int
+STATIC int
 ao(int toketype)
 {
-    if (*bufptr == '=') {
-       bufptr++;
+    if (*PL_bufptr == '=') {
+       PL_bufptr++;
        if (toketype == ANDAND)
            yylval.ival = OP_ANDASSIGN;
        else if (toketype == OROR)
@@ -159,48 +181,56 @@ ao(int toketype)
     return toketype;
 }
 
-static void
+STATIC void
 no_op(char *what, char *s)
 {
-    char *oldbp = bufptr;
-    bool is_first = (oldbufptr == linestart);
+    char *oldbp = PL_bufptr;
+    bool is_first = (PL_oldbufptr == PL_linestart);
 
-    bufptr = s;
+    PL_bufptr = s;
     yywarn(form("%s found where operator expected", what));
     if (is_first)
        warn("\t(Missing semicolon on previous line?)\n");
-    else if (oldoldbufptr && isIDFIRST(*oldoldbufptr)) {
+    else if (PL_oldoldbufptr && isIDFIRST_lazy(PL_oldoldbufptr)) {
        char *t;
-       for (t = oldoldbufptr; *t && (isALNUM(*t) || *t == ':'); t++) ;
-       if (t < bufptr && isSPACE(*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",
-               t - oldoldbufptr, oldoldbufptr);
+               t - PL_oldoldbufptr, PL_oldoldbufptr);
 
     }
+    else if (s <= oldbp)
+       warn("\t(Missing operator before end of line?)\n");
     else
        warn("\t(Missing operator before %.*s?)\n", s - oldbp, oldbp);
-    bufptr = oldbp;
+    PL_bufptr = oldbp;
 }
 
-static void
+STATIC void
 missingterm(char *s)
 {
     char tmpbuf[3];
     char q;
     if (s) {
        char *nl = strrchr(s,'\n');
-       if (nl) 
+       if (nl)
            *nl = '\0';
     }
-    else if (multi_close < 32 || multi_close == 127) {
+    else if (
+#ifdef EBCDIC
+       iscntrl(PL_multi_close)
+#else
+       PL_multi_close < 32 || PL_multi_close == 127
+#endif
+       ) {
        *tmpbuf = '^';
-       tmpbuf[1] = toCTRL(multi_close);
+       tmpbuf[1] = toCTRL(PL_multi_close);
        s = "\\n";
        tmpbuf[2] = '\0';
        s = tmpbuf;
     }
     else {
-       *tmpbuf = multi_close;
+       *tmpbuf = PL_multi_close;
        tmpbuf[1] = '\0';
        s = tmpbuf;
     }
@@ -211,11 +241,12 @@ missingterm(char *s)
 void
 deprecate(char *s)
 {
-    if (dowarn)
-       warn("Use of %s is deprecated", s);
+    dTHR;
+    if (ckWARN(WARN_DEPRECATED))
+       warner(WARN_DEPRECATED, "Use of %s is deprecated", s);
 }
 
-static void
+STATIC void
 depcom(void)
 {
     deprecate("comma-less variable list");
@@ -223,7 +254,7 @@ depcom(void)
 
 #ifdef WIN32
 
-static I32
+STATIC I32
 win32_textfilter(int idx, SV *sv, int maxlen)
 {
  I32 count = FILTER_READ(idx+1, sv, maxlen);
@@ -233,6 +264,39 @@ win32_textfilter(int idx, SV *sv, int maxlen)
 }
 #endif
 
+#ifndef PERL_OBJECT
+
+STATIC I32
+utf16_textfilter(int idx, SV *sv, int maxlen)
+{
+    I32 count = FILTER_READ(idx+1, sv, maxlen);
+    if (count) {
+       U8* tmps;
+       U8* tend;
+       New(898, tmps, SvCUR(sv) * 3 / 2 + 1, U8);
+       tend = utf16_to_utf8((U16*)SvPVX(sv), tmps, SvCUR(sv));
+       sv_usepvn(sv, (char*)tmps, tend - tmps);
+    
+    }
+    return count;
+}
+
+STATIC I32
+utf16rev_textfilter(int idx, SV *sv, int maxlen)
+{
+    I32 count = FILTER_READ(idx+1, sv, maxlen);
+    if (count) {
+       U8* tmps;
+       U8* tend;
+       New(898, tmps, SvCUR(sv) * 3 / 2 + 1, U8);
+       tend = utf16_to_utf8_reversed((U16*)SvPVX(sv), tmps, SvCUR(sv));
+       sv_usepvn(sv, (char*)tmps, tend - tmps);
+    
+    }
+    return count;
+}
+
+#endif
 
 void
 lex_start(SV *line)
@@ -241,99 +305,97 @@ lex_start(SV *line)
     char *s;
     STRLEN len;
 
-    SAVEI32(lex_dojoin);
-    SAVEI32(lex_brackets);
-    SAVEI32(lex_fakebrack);
-    SAVEI32(lex_casemods);
-    SAVEI32(lex_starts);
-    SAVEI32(lex_state);
-    SAVESPTR(lex_inpat);
-    SAVEI32(lex_inwhat);
-    SAVEI16(curcop->cop_line);
-    SAVEPPTR(bufptr);
-    SAVEPPTR(bufend);
-    SAVEPPTR(oldbufptr);
-    SAVEPPTR(oldoldbufptr);
-    SAVEPPTR(linestart);
-    SAVESPTR(linestr);
-    SAVEPPTR(lex_brackstack);
-    SAVEPPTR(lex_casestack);
-    SAVEDESTRUCTOR(restore_rsfp, rsfp);
-    SAVESPTR(lex_stuff);
-    SAVEI32(lex_defer);
-    SAVESPTR(lex_repl);
-    SAVEDESTRUCTOR(restore_expect, tokenbuf + expect); /* encode as pointer */
-    SAVEDESTRUCTOR(restore_lex_expect, tokenbuf + expect);
-
-    lex_state = LEX_NORMAL;
-    lex_defer = 0;
-    expect = XSTATE;
-    lex_brackets = 0;
-    lex_fakebrack = 0;
-    New(899, lex_brackstack, 120, char);
-    New(899, lex_casestack, 12, char);
-    SAVEFREEPV(lex_brackstack);
-    SAVEFREEPV(lex_casestack);
-    lex_casemods = 0;
-    *lex_casestack = '\0';
-    lex_dojoin = 0;
-    lex_starts = 0;
-    lex_stuff = Nullsv;
-    lex_repl = Nullsv;
-    lex_inpat = 0;
-    lex_inwhat = 0;
-    linestr = line;
-    if (SvREADONLY(linestr))
-       linestr = sv_2mortal(newSVsv(linestr));
-    s = SvPV(linestr, len);
+    SAVEI32(PL_lex_dojoin);
+    SAVEI32(PL_lex_brackets);
+    SAVEI32(PL_lex_fakebrack);
+    SAVEI32(PL_lex_casemods);
+    SAVEI32(PL_lex_starts);
+    SAVEI32(PL_lex_state);
+    SAVESPTR(PL_lex_inpat);
+    SAVEI32(PL_lex_inwhat);
+    SAVEI16(PL_curcop->cop_line);
+    SAVEPPTR(PL_bufptr);
+    SAVEPPTR(PL_bufend);
+    SAVEPPTR(PL_oldbufptr);
+    SAVEPPTR(PL_oldoldbufptr);
+    SAVEPPTR(PL_linestart);
+    SAVESPTR(PL_linestr);
+    SAVEPPTR(PL_lex_brackstack);
+    SAVEPPTR(PL_lex_casestack);
+    SAVEDESTRUCTOR(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);
+
+    PL_lex_state = LEX_NORMAL;
+    PL_lex_defer = 0;
+    PL_expect = XSTATE;
+    PL_lex_brackets = 0;
+    PL_lex_fakebrack = 0;
+    New(899, PL_lex_brackstack, 120, char);
+    New(899, PL_lex_casestack, 12, char);
+    SAVEFREEPV(PL_lex_brackstack);
+    SAVEFREEPV(PL_lex_casestack);
+    PL_lex_casemods = 0;
+    *PL_lex_casestack = '\0';
+    PL_lex_dojoin = 0;
+    PL_lex_starts = 0;
+    PL_lex_stuff = Nullsv;
+    PL_lex_repl = Nullsv;
+    PL_lex_inpat = 0;
+    PL_lex_inwhat = 0;
+    PL_linestr = line;
+    if (SvREADONLY(PL_linestr))
+       PL_linestr = sv_2mortal(newSVsv(PL_linestr));
+    s = SvPV(PL_linestr, len);
     if (len && s[len-1] != ';') {
-       if (!(SvFLAGS(linestr) & SVs_TEMP))
-           linestr = sv_2mortal(newSVsv(linestr));
-       sv_catpvn(linestr, "\n;", 2);
+       if (!(SvFLAGS(PL_linestr) & SVs_TEMP))
+           PL_linestr = sv_2mortal(newSVsv(PL_linestr));
+       sv_catpvn(PL_linestr, "\n;", 2);
     }
-    SvTEMP_off(linestr);
-    oldoldbufptr = oldbufptr = bufptr = linestart = SvPVX(linestr);
-    bufend = bufptr + SvCUR(linestr);
-    SvREFCNT_dec(rs);
-    rs = newSVpv("\n", 1);
-    rsfp = 0;
+    SvTEMP_off(PL_linestr);
+    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_rsfp = 0;
 }
 
 void
 lex_end(void)
 {
-    doextract = FALSE;
+    PL_doextract = FALSE;
 }
 
-static void
+STATIC void
 restore_rsfp(void *f)
 {
     PerlIO *fp = (PerlIO*)f;
 
-    if (rsfp == PerlIO_stdin())
-       PerlIO_clearerr(rsfp);
-    else if (rsfp && (rsfp != fp))
-       PerlIO_close(rsfp);
-    rsfp = fp;
+    if (PL_rsfp == PerlIO_stdin())
+       PerlIO_clearerr(PL_rsfp);
+    else if (PL_rsfp && (PL_rsfp != fp))
+       PerlIO_close(PL_rsfp);
+    PL_rsfp = fp;
 }
 
-static void
-restore_expect(e)
-void *e;
+STATIC void
+restore_expect(void *e)
 {
     /* a safe way to store a small integer in a pointer */
-    expect = (expectation)((char *)e - tokenbuf);
+    PL_expect = (expectation)((char *)e - PL_tokenbuf);
 }
 
-static void
-restore_lex_expect(e)
-void *e;
+STATIC void
+restore_lex_expect(void *e)
 {
     /* a safe way to store a small integer in a pointer */
-    lex_expect = (expectation)((char *)e - tokenbuf);
+    PL_lex_expect = (expectation)((char *)e - PL_tokenbuf);
 }
 
-static void
+STATIC void
 incline(char *s)
 {
     dTHR;
@@ -342,7 +404,7 @@ incline(char *s)
     char ch;
     int sawline = 0;
 
-    curcop->cop_line++;
+    PL_curcop->cop_line++;
     if (*s++ != '#')
        return;
     while (*s == ' ' || *s == '\t') s++;
@@ -367,87 +429,92 @@ incline(char *s)
     ch = *t;
     *t = '\0';
     if (t - s > 0)
-       curcop->cop_filegv = gv_fetchfile(s);
+       PL_curcop->cop_filegv = gv_fetchfile(s);
     else
-       curcop->cop_filegv = gv_fetchfile(origfilename);
+       PL_curcop->cop_filegv = gv_fetchfile(PL_origfilename);
     *t = ch;
-    curcop->cop_line = atoi(n)-1;
+    PL_curcop->cop_line = atoi(n)-1;
 }
 
-static char *
+STATIC char *
 skipspace(register char *s)
 {
     dTHR;
-    if (lex_formbrack && lex_brackets <= lex_formbrack) {
-       while (s < bufend && (*s == ' ' || *s == '\t'))
+    if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
+       while (s < PL_bufend && (*s == ' ' || *s == '\t'))
            s++;
        return s;
     }
     for (;;) {
        STRLEN prevlen;
-       while (s < bufend && isSPACE(*s))
-           s++;
-       if (s < bufend && *s == '#') {
-           while (s < bufend && *s != '\n')
+       while (s < PL_bufend && isSPACE(*s)) {
+           if (*s++ == '\n' && PL_in_eval && !PL_rsfp)
+               incline(s);
+       }
+       if (s < PL_bufend && *s == '#') {
+           while (s < PL_bufend && *s != '\n')
                s++;
-           if (s < bufend)
+           if (s < PL_bufend) {
                s++;
+               if (PL_in_eval && !PL_rsfp) {
+                   incline(s);
+                   continue;
+               }
+           }
        }
-       if (s < bufend || !rsfp || lex_state != LEX_NORMAL)
+       if (s < PL_bufend || !PL_rsfp || PL_lex_state != LEX_NORMAL)
            return s;
-       if ((s = filter_gets(linestr, rsfp, (prevlen = SvCUR(linestr)))) == Nullch) {
-           if (minus_n || minus_p) {
-               sv_setpv(linestr,minus_p ?
+       if ((s = filter_gets(PL_linestr, PL_rsfp, (prevlen = SvCUR(PL_linestr)))) == Nullch) {
+           if (PL_minus_n || PL_minus_p) {
+               sv_setpv(PL_linestr,PL_minus_p ?
                         ";}continue{print or die qq(-p destination: $!\\n)" :
                         "");
-               sv_catpv(linestr,";}");
-               minus_n = minus_p = 0;
+               sv_catpv(PL_linestr,";}");
+               PL_minus_n = PL_minus_p = 0;
            }
            else
-               sv_setpv(linestr,";");
-           oldoldbufptr = oldbufptr = bufptr = s = linestart = SvPVX(linestr);
-           bufend = SvPVX(linestr) + SvCUR(linestr);
-           if (preprocess && !in_eval)
-               (void)PerlProc_pclose(rsfp);
-           else if ((PerlIO*)rsfp == PerlIO_stdin())
-               PerlIO_clearerr(rsfp);
+               sv_setpv(PL_linestr,";");
+           PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = s = PL_linestart = SvPVX(PL_linestr);
+           PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+           if (PL_preprocess && !PL_in_eval)
+               (void)PerlProc_pclose(PL_rsfp);
+           else if ((PerlIO*)PL_rsfp == PerlIO_stdin())
+               PerlIO_clearerr(PL_rsfp);
            else
-               (void)PerlIO_close(rsfp);
-           if (e_fp == rsfp)
-               e_fp = Nullfp;
-           rsfp = Nullfp;
+               (void)PerlIO_close(PL_rsfp);
+           PL_rsfp = Nullfp;
            return s;
        }
-       linestart = bufptr = s + prevlen;
-       bufend = s + SvCUR(linestr);
-       s = bufptr;
+       PL_linestart = PL_bufptr = s + prevlen;
+       PL_bufend = s + SvCUR(PL_linestr);
+       s = PL_bufptr;
        incline(s);
-       if (PERLDB_LINE && curstash != debstash) {
+       if (PERLDB_LINE && PL_curstash != PL_debstash) {
            SV *sv = NEWSV(85,0);
 
            sv_upgrade(sv, SVt_PVMG);
-           sv_setpvn(sv,bufptr,bufend-bufptr);
-           av_store(GvAV(curcop->cop_filegv),(I32)curcop->cop_line,sv);
+           sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
+           av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
        }
     }
 }
 
-static void
+STATIC void
 check_uni(void) {
     char *s;
     char ch;
     char *t;
 
-    if (oldoldbufptr != last_uni)
+    if (PL_oldoldbufptr != PL_last_uni)
        return;
-    while (isSPACE(*last_uni))
-       last_uni++;
-    for (s = last_uni; isALNUM(*s) || *s == '-'; s++) ;
-    if ((t = strchr(s, '(')) && t < bufptr)
+    while (isSPACE(*PL_last_uni))
+       PL_last_uni++;
+    for (s = PL_last_uni; isALNUM_lazy(s) || *s == '-'; s++) ;
+    if ((t = strchr(s, '(')) && t < PL_bufptr)
        return;
     ch = *s;
     *s = '\0';
-    warn("Warning: Use of \"%s\" without parens is ambiguous", last_uni);
+    warn("Warning: Use of \"%s\" without parens is ambiguous", PL_last_uni);
     *s = ch;
 }
 
@@ -456,14 +523,14 @@ check_uni(void) {
 #undef UNI
 #define UNI(f) return uni(f,s)
 
-static int
+STATIC int
 uni(I32 f, char *s)
 {
     yylval.ival = f;
-    expect = XTERM;
-    bufptr = s;
-    last_uni = oldbufptr;
-    last_lop_op = f;
+    PL_expect = XTERM;
+    PL_bufptr = s;
+    PL_last_uni = PL_oldbufptr;
+    PL_last_lop_op = f;
     if (*s == '(')
        return FUNC1;
     s = skipspace(s);
@@ -477,17 +544,17 @@ uni(I32 f, char *s)
 
 #define LOP(f,x) return lop(f,x,s)
 
-static I32
+STATIC I32
 lop(I32 f, expectation x, char *s)
 {
     dTHR;
     yylval.ival = f;
     CLINE;
-    expect = x;
-    bufptr = s;
-    last_lop = oldbufptr;
-    last_lop_op = f;
-    if (nexttoke)
+    PL_expect = x;
+    PL_bufptr = s;
+    PL_last_lop = PL_oldbufptr;
+    PL_last_lop_op = f;
+    if (PL_nexttoke)
        return LSTOP;
     if (*s == '(')
        return FUNC;
@@ -498,19 +565,19 @@ lop(I32 f, expectation x, char *s)
        return LSTOP;
 }
 
-static void 
+STATIC void 
 force_next(I32 type)
 {
-    nexttype[nexttoke] = type;
-    nexttoke++;
-    if (lex_state != LEX_KNOWNEXT) {
-       lex_defer = lex_state;
-       lex_expect = expect;
-       lex_state = LEX_KNOWNEXT;
+    PL_nexttype[PL_nexttoke] = type;
+    PL_nexttoke++;
+    if (PL_lex_state != LEX_KNOWNEXT) {
+       PL_lex_defer = PL_lex_state;
+       PL_lex_expect = PL_expect;
+       PL_lex_state = LEX_KNOWNEXT;
     }
 }
 
-static char *
+STATIC char *
 force_word(register char *start, int token, int check_keyword, int allow_pack, int allow_initial_tick)
 {
     register char *s;
@@ -518,36 +585,36 @@ force_word(register char *start, int token, int check_keyword, int allow_pack, i
     
     start = skipspace(start);
     s = start;
-    if (isIDFIRST(*s) ||
+    if (isIDFIRST_lazy(s) ||
        (allow_pack && *s == ':') ||
        (allow_initial_tick && *s == '\'') )
     {
-       s = scan_word(s, tokenbuf, sizeof tokenbuf, allow_pack, &len);
-       if (check_keyword && keyword(tokenbuf, len))
+       s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, allow_pack, &len);
+       if (check_keyword && keyword(PL_tokenbuf, len))
            return start;
        if (token == METHOD) {
            s = skipspace(s);
            if (*s == '(')
-               expect = XTERM;
+               PL_expect = XTERM;
            else {
-               expect = XOPERATOR;
+               PL_expect = XOPERATOR;
                force_next(')');
                force_next('(');
            }
        }
-       nextval[nexttoke].opval = (OP*)newSVOP(OP_CONST,0, newSVpv(tokenbuf,0));
-       nextval[nexttoke].opval->op_private |= OPpCONST_BARE;
+       PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST,0, newSVpv(PL_tokenbuf,0));
+       PL_nextval[PL_nexttoke].opval->op_private |= OPpCONST_BARE;
        force_next(token);
     }
     return s;
 }
 
-static void
+STATIC void
 force_ident(register char *s, int kind)
 {
     if (s && *s) {
        OP* o = (OP*)newSVOP(OP_CONST, 0, newSVpv(s,0));
-       nextval[nexttoke].opval = o;
+       PL_nextval[PL_nexttoke].opval = o;
        force_next(WORD);
        if (kind) {
            dTHR;               /* just for in_eval */
@@ -555,7 +622,7 @@ force_ident(register char *s, int kind)
            /* XXX see note in pp_entereval() for why we forgo typo
               warnings if the symbol must be introduced in an eval.
               GSAR 96-10-12 */
-           gv_fetchpv(s, in_eval ? GV_ADDMULTI : TRUE,
+           gv_fetchpv(s, PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : TRUE,
                kind == '$' ? SVt_PV :
                kind == '@' ? SVt_PVAV :
                kind == '%' ? SVt_PVHV :
@@ -565,7 +632,7 @@ force_ident(register char *s, int kind)
     }
 }
 
-static char *
+STATIC char *
 force_version(char *s)
 {
     OP *version = Nullop;
@@ -586,32 +653,35 @@ force_version(char *s)
     }
 
     /* NOTE: The parser sees the package name and the VERSION swapped */
-    nextval[nexttoke].opval = version;
+    PL_nextval[PL_nexttoke].opval = version;
     force_next(WORD); 
 
     return (s);
 }
 
-static SV *
-q(SV *sv)
+STATIC SV *
+tokeq(SV *sv)
 {
     register char *s;
     register char *send;
     register char *d;
-    STRLEN len;
+    STRLEN len = 0;
+    SV *pv = sv;
 
     if (!SvLEN(sv))
-       return sv;
+       goto finish;
 
     s = SvPV_force(sv, len);
     if (SvIVX(sv) == -1)
-       return sv;
+       goto finish;
     send = s + len;
     while (s < send && *s != '\\')
        s++;
     if (s == send)
-       return sv;
+       goto finish;
     d = s;
+    if ( PL_hints & HINT_NEW_STRING )
+       pv = sv_2mortal(newSVpv(SvPVX(pv), len));
     while (s < send) {
        if (*s == '\\') {
            if (s + 1 < send && (s[1] == '\\'))
@@ -621,139 +691,155 @@ q(SV *sv)
     }
     *d = '\0';
     SvCUR_set(sv, d - SvPVX(sv));
-
+  finish:
+    if ( PL_hints & HINT_NEW_STRING )
+       return new_constant(NULL, 0, "q", sv, pv, "q");
     return sv;
 }
 
-static I32
+STATIC I32
 sublex_start(void)
 {
     register I32 op_type = yylval.ival;
 
     if (op_type == OP_NULL) {
-       yylval.opval = lex_op;
-       lex_op = Nullop;
+       yylval.opval = PL_lex_op;
+       PL_lex_op = Nullop;
        return THING;
     }
     if (op_type == OP_CONST || op_type == OP_READLINE) {
-       SV *sv = q(lex_stuff);
-       STRLEN len;
-       char *p = SvPV(sv, len);
-       yylval.opval = (OP*)newSVOP(op_type, 0, newSVpv(p, len));
-       SvREFCNT_dec(sv);
-       lex_stuff = Nullsv;
+       SV *sv = tokeq(PL_lex_stuff);
+
+       if (SvTYPE(sv) == SVt_PVIV) {
+           /* Overloaded constants, nothing fancy: Convert to SVt_PV: */
+           STRLEN len;
+           char *p;
+           SV *nsv;
+
+           p = SvPV(sv, len);
+           nsv = newSVpv(p, len);
+           SvREFCNT_dec(sv);
+           sv = nsv;
+       } 
+       yylval.opval = (OP*)newSVOP(op_type, 0, sv);
+       PL_lex_stuff = Nullsv;
        return THING;
     }
 
-    sublex_info.super_state = lex_state;
-    sublex_info.sub_inwhat = op_type;
-    sublex_info.sub_op = lex_op;
-    lex_state = LEX_INTERPPUSH;
+    PL_sublex_info.super_state = PL_lex_state;
+    PL_sublex_info.sub_inwhat = op_type;
+    PL_sublex_info.sub_op = PL_lex_op;
+    PL_lex_state = LEX_INTERPPUSH;
 
-    expect = XTERM;
-    if (lex_op) {
-       yylval.opval = lex_op;
-       lex_op = Nullop;
+    PL_expect = XTERM;
+    if (PL_lex_op) {
+       yylval.opval = PL_lex_op;
+       PL_lex_op = Nullop;
        return PMFUNC;
     }
     else
        return FUNC;
 }
 
-static I32
+STATIC I32
 sublex_push(void)
 {
     dTHR;
     ENTER;
 
-    lex_state = sublex_info.super_state;
-    SAVEI32(lex_dojoin);
-    SAVEI32(lex_brackets);
-    SAVEI32(lex_fakebrack);
-    SAVEI32(lex_casemods);
-    SAVEI32(lex_starts);
-    SAVEI32(lex_state);
-    SAVESPTR(lex_inpat);
-    SAVEI32(lex_inwhat);
-    SAVEI16(curcop->cop_line);
-    SAVEPPTR(bufptr);
-    SAVEPPTR(oldbufptr);
-    SAVEPPTR(oldoldbufptr);
-    SAVEPPTR(linestart);
-    SAVESPTR(linestr);
-    SAVEPPTR(lex_brackstack);
-    SAVEPPTR(lex_casestack);
-
-    linestr = lex_stuff;
-    lex_stuff = Nullsv;
-
-    bufend = bufptr = oldbufptr = oldoldbufptr = linestart = SvPVX(linestr);
-    bufend += SvCUR(linestr);
-    SAVEFREESV(linestr);
-
-    lex_dojoin = FALSE;
-    lex_brackets = 0;
-    lex_fakebrack = 0;
-    New(899, lex_brackstack, 120, char);
-    New(899, lex_casestack, 12, char);
-    SAVEFREEPV(lex_brackstack);
-    SAVEFREEPV(lex_casestack);
-    lex_casemods = 0;
-    *lex_casestack = '\0';
-    lex_starts = 0;
-    lex_state = LEX_INTERPCONCAT;
-    curcop->cop_line = multi_start;
-
-    lex_inwhat = sublex_info.sub_inwhat;
-    if (lex_inwhat == OP_MATCH || lex_inwhat == OP_SUBST)
-       lex_inpat = sublex_info.sub_op;
+    PL_lex_state = PL_sublex_info.super_state;
+    SAVEI32(PL_lex_dojoin);
+    SAVEI32(PL_lex_brackets);
+    SAVEI32(PL_lex_fakebrack);
+    SAVEI32(PL_lex_casemods);
+    SAVEI32(PL_lex_starts);
+    SAVEI32(PL_lex_state);
+    SAVESPTR(PL_lex_inpat);
+    SAVEI32(PL_lex_inwhat);
+    SAVEI16(PL_curcop->cop_line);
+    SAVEPPTR(PL_bufptr);
+    SAVEPPTR(PL_oldbufptr);
+    SAVEPPTR(PL_oldoldbufptr);
+    SAVEPPTR(PL_linestart);
+    SAVESPTR(PL_linestr);
+    SAVEPPTR(PL_lex_brackstack);
+    SAVEPPTR(PL_lex_casestack);
+
+    PL_linestr = PL_lex_stuff;
+    PL_lex_stuff = Nullsv;
+
+    PL_bufend = PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr);
+    PL_bufend += SvCUR(PL_linestr);
+    SAVEFREESV(PL_linestr);
+
+    PL_lex_dojoin = FALSE;
+    PL_lex_brackets = 0;
+    PL_lex_fakebrack = 0;
+    New(899, PL_lex_brackstack, 120, char);
+    New(899, PL_lex_casestack, 12, char);
+    SAVEFREEPV(PL_lex_brackstack);
+    SAVEFREEPV(PL_lex_casestack);
+    PL_lex_casemods = 0;
+    *PL_lex_casestack = '\0';
+    PL_lex_starts = 0;
+    PL_lex_state = LEX_INTERPCONCAT;
+    PL_curcop->cop_line = 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)
+       PL_lex_inpat = PL_sublex_info.sub_op;
     else
-       lex_inpat = Nullop;
+       PL_lex_inpat = Nullop;
 
     return '(';
 }
 
-static I32
+STATIC I32
 sublex_done(void)
 {
-    if (!lex_starts++) {
-       expect = XOPERATOR;
+    if (!PL_lex_starts++) {
+       PL_expect = XOPERATOR;
        yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv("",0));
        return THING;
     }
 
-    if (lex_casemods) {                /* oops, we've got some unbalanced parens */
-       lex_state = LEX_INTERPCASEMOD;
-       return yylex();
+    if (PL_lex_casemods) {             /* oops, we've got some unbalanced parens */
+       PL_lex_state = LEX_INTERPCASEMOD;
+       return yylex(PERL_YYLEX_PARAM);
     }
 
     /* Is there a right-hand side to take care of? */
-    if (lex_repl && (lex_inwhat == OP_SUBST || lex_inwhat == OP_TRANS)) {
-       linestr = lex_repl;
-       lex_inpat = 0;
-       bufend = bufptr = oldbufptr = oldoldbufptr = linestart = SvPVX(linestr);
-       bufend += SvCUR(linestr);
-       SAVEFREESV(linestr);
-       lex_dojoin = FALSE;
-       lex_brackets = 0;
-       lex_fakebrack = 0;
-       lex_casemods = 0;
-       *lex_casestack = '\0';
-       lex_starts = 0;
-       if (SvCOMPILED(lex_repl)) {
-           lex_state = LEX_INTERPNORMAL;
-           lex_starts++;
+    if (PL_lex_repl && (PL_lex_inwhat == OP_SUBST || PL_lex_inwhat == OP_TRANS)) {
+       PL_linestr = PL_lex_repl;
+       PL_lex_inpat = 0;
+       PL_bufend = PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr);
+       PL_bufend += SvCUR(PL_linestr);
+       SAVEFREESV(PL_linestr);
+       PL_lex_dojoin = FALSE;
+       PL_lex_brackets = 0;
+       PL_lex_fakebrack = 0;
+       PL_lex_casemods = 0;
+       *PL_lex_casestack = '\0';
+       PL_lex_starts = 0;
+       if (SvCOMPILED(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
+               whether this is an evalled subst; that means we rely on the
+               logic to ensure sublex_done() is called again only via the
+               branch (in yylex()) that clears PL_lex_repl, else we'll loop */
+       }
+       else {
+           PL_lex_state = LEX_INTERPCONCAT;
+           PL_lex_repl = Nullsv;
        }
-       else
-           lex_state = LEX_INTERPCONCAT;
-       lex_repl = Nullsv;
        return ',';
     }
     else {
        LEAVE;
-       bufend = SvPVX(linestr);
-       bufend += SvCUR(linestr);
-       expect = XOPERATOR;
+       PL_bufend = SvPVX(PL_linestr);
+       PL_bufend += SvCUR(PL_linestr);
+       PL_expect = XOPERATOR;
        return ')';
     }
 }
@@ -764,10 +850,16 @@ sublex_done(void)
   Extracts a pattern, double-quoted string, or transliteration.  This
   is terrifying code.
 
-  It looks at lex_inwhat and lex_inpat to find out whether it's
-  processing a pattern (lex_inpat is true), a transliteration
+  It looks at lex_inwhat and PL_lex_inpat to find out whether it's
+  processing a pattern (PL_lex_inpat is true), a transliteration
   (lex_inwhat & OP_TRANS is true), or a double-quoted string.
 
+  Returns a pointer to the character scanned up to. Iff this is
+  advanced from the start pointer supplied (ie if anything was
+  successfully parsed), will leave an OP for the substring scanned
+  in yylval. Caller must intuit reason for not parsing further
+  by looking at the next characters herself.
+
   In patterns:
     backslashes:
       double-quoted style: \r and \n
@@ -825,34 +917,35 @@ sublex_done(void)
                  
 */
 
-static char *
+STATIC char *
 scan_const(char *start)
 {
-    register char *send = bufend;              /* end of the constant */
+    register char *send = PL_bufend;           /* end of the constant */
     SV *sv = NEWSV(93, send - start);          /* sv for the constant */
     register char *s = start;                  /* start of the constant */
     register char *d = SvPVX(sv);              /* destination for copies */
     bool dorange = FALSE;                      /* are we in a translit range? */
     I32 len;                                   /* ? */
-
-    /*
-      leave is the set of acceptably-backslashed characters.
-
-      I do *not* understand why there's the double hook here.
-    */
+    I32 utf = PL_lex_inwhat == OP_TRANS
+       ? (PL_sublex_info.sub_op->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF))
+       : UTF;
+    I32 thisutf = PL_lex_inwhat == OP_TRANS
+       ? (PL_sublex_info.sub_op->op_private & (PL_lex_repl ? OPpTRANS_FROM_UTF : OPpTRANS_TO_UTF))
+       : UTF;
+
+    /* leaveit is the set of acceptably-backslashed characters */
     char *leaveit =
-       lex_inpat
-           ? "\\.^$@AGZdDwWsSbB+*?|()-nrtfeaxc0123456789[{]} \t\n\r\f\v#"
-           : (lex_inwhat & OP_TRANS)
-               ? ""
-               : "";
+       PL_lex_inpat
+           ? "\\.^$@AGZdDwWsSbBpPXC+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#"
+           : "";
 
     while (s < send || dorange) {
         /* get transliterations out of the way (they're most literal) */
-       if (lex_inwhat == OP_TRANS) {
+       if (PL_lex_inwhat == OP_TRANS) {
            /* expand a range A-Z to the full set of characters.  AIE! */
            if (dorange) {
                I32 i;                          /* current expanded character */
+               I32 min;                        /* first character in range */
                I32 max;                        /* last character in range */
 
                i = d - SvPVX(sv);              /* remember current offset */
@@ -860,10 +953,26 @@ scan_const(char *start)
                d = SvPVX(sv) + i;              /* restore d after the grow potentially has changed the ptr */
                d -= 2;                         /* eat the first char and the - */
 
-               max = (U8)d[1];                 /* last char in range */
-
-               for (i = (U8)*d; i <= max; i++)
-                   *d++ = i;
+               min = (U8)*d;                   /* first char in range */
+               max = (U8)d[1];                 /* last char in range  */
+
+#ifndef ASCIIish
+               if ((isLOWER(min) && isLOWER(max)) ||
+                   (isUPPER(min) && isUPPER(max))) {
+                   if (isLOWER(min)) {
+                       for (i = min; i <= max; i++)
+                           if (isLOWER(i))
+                               *d++ = i;
+                   } else {
+                       for (i = min; i <= max; i++)
+                           if (isUPPER(i))
+                               *d++ = i;
+                   }
+               }
+               else
+#endif
+                   for (i = min; i <= max; i++)
+                       *d++ = i;
 
                /* mark the range as done, and continue */
                dorange = FALSE;
@@ -872,6 +981,11 @@ scan_const(char *start)
 
            /* range begins (ignore - as first or last char) */
            else if (*s == '-' && s+1 < send  && s != start) {
+               if (utf) {
+                   *d++ = (char)0xff;  /* use illegal utf8 byte--see pmtrans */
+                   s++;
+                   continue;
+               }
                dorange = TRUE;
                s++;
            }
@@ -879,14 +993,16 @@ scan_const(char *start)
 
        /* if we get here, we're not doing a transliteration */
 
-       /* skip for regexp comments /(?#comment)/ */
-       else if (*s == '(' && lex_inpat && s[1] == '?') {
+       /* skip for regexp comments /(?#comment)/ and code /(?{code})/,
+          except for the last char, which will be done separately. */
+       else if (*s == '(' && PL_lex_inpat && s[1] == '?') {
            if (s[2] == '#') {
                while (s < send && *s != ')')
                    *d++ = *s++;
-           } else if (s[2] == '{') {   /* This should march regcomp.c */
+           } else if (s[2] == '{'
+                      || s[2] == 'p' && s[3] == '{') { /* This should march regcomp.c */
                I32 count = 1;
-               char *regparse = s + 3;
+               char *regparse = s + (s[2] == '{' ? 3 : 4);
                char c;
 
                while (count && (c = *regparse)) {
@@ -898,59 +1014,74 @@ scan_const(char *start)
                        count--;
                    regparse++;
                }
-               if (*regparse == ')')
-                   regparse++;
-               else
+               if (*regparse != ')') {
+                   regparse--;         /* Leave one char for continuation. */
                    yyerror("Sequence (?{...}) not terminated or not {}-balanced");
-               while (s < regparse && *s != ')')
+               }
+               while (s < regparse)
                    *d++ = *s++;
            }
        }
 
        /* likewise skip #-initiated comments in //x patterns */
-       else if (*s == '#' && lex_inpat &&
-         ((PMOP*)lex_inpat)->op_pmflags & PMf_EXTENDED) {
+       else if (*s == '#' && PL_lex_inpat &&
+         ((PMOP*)PL_lex_inpat)->op_pmflags & PMf_EXTENDED) {
            while (s+1 < send && *s != '\n')
                *d++ = *s++;
        }
 
        /* check for embedded arrays (@foo, @:foo, @'foo, @{foo}, @$foo) */
-       else if (*s == '@' && s[1] && (isALNUM(s[1]) || strchr(":'{$", s[1])))
+       else if (*s == '@' && s[1] && (isALNUM_lazy(s+1) || strchr(":'{$", s[1])))
            break;
 
        /* check for embedded scalars.  only stop if we're sure it's a
           variable.
         */
        else if (*s == '$') {
-           if (!lex_inpat)     /* not a regexp, so $ must be var */
+           if (!PL_lex_inpat)  /* not a regexp, so $ must be var */
                break;
            if (s + 1 < send && !strchr("()| \n\t", s[1]))
                break;          /* in regexp, $ might be tail anchor */
        }
 
+       /* (now in tr/// code again) */
+
+       if (*s & 0x80 && thisutf) {
+           dTHR;                       /* only for ckWARN */
+           if (ckWARN(WARN_UTF8)) {
+               (void)utf8_to_uv((U8*)s, &len); /* could cvt latin-1 to utf8 here... */
+               if (len) {
+                   while (len--)
+                       *d++ = *s++;
+                   continue;
+               }
+           }
+       }
+
        /* backslashes */
        if (*s == '\\' && s+1 < send) {
            s++;
 
            /* some backslashes we leave behind */
-           if (*s && strchr(leaveit, *s)) {
+           if (*leaveit && *s && strchr(leaveit, *s)) {
                *d++ = '\\';
                *d++ = *s++;
                continue;
            }
 
            /* deprecate \1 in strings and substitution replacements */
-           if (lex_inwhat == OP_SUBST && !lex_inpat &&
+           if (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat &&
                isDIGIT(*s) && *s != '0' && !isDIGIT(s[1]))
            {
-               if (dowarn)
-                   warn("\\%c better written as $%c", *s, *s);
+               dTHR;                   /* only for ckWARN */
+               if (ckWARN(WARN_SYNTAX))
+                   warner(WARN_SYNTAX, "\\%c better written as $%c", *s, *s);
                *--s = '$';
                break;
            }
 
            /* string-change backslash escapes */
-           if (lex_inwhat != OP_TRANS && *s && strchr("lLuUEQ", *s)) {
+           if (PL_lex_inwhat != OP_TRANS && *s && strchr("lLuUEQ", *s)) {
                --s;
                break;
            }
@@ -960,15 +1091,22 @@ scan_const(char *start)
 
            /* quoted - in transliterations */
            case '-':
-               if (lex_inwhat == OP_TRANS) {
+               if (PL_lex_inwhat == OP_TRANS) {
                    *d++ = *s++;
                    continue;
                }
                /* FALL THROUGH */
-           /* default action is to copy the quoted character */
            default:
-               *d++ = *s++;
-               continue;
+               {
+                   dTHR;
+                   if (ckWARN(WARN_UNSAFE) && isALPHA(*s))
+                       warner(WARN_UNSAFE, 
+                              "Unrecognized escape \\%c passed through",
+                              *s);
+                   /* default action is to copy the quoted character */
+                   *d++ = *s++;
+                   continue;
+               }
 
            /* \132 indicates an octal constant */
            case '0': case '1': case '2': case '3':
@@ -979,15 +1117,59 @@ scan_const(char *start)
 
            /* \x24 indicates a hex constant */
            case 'x':
-               *d++ = scan_hex(++s, 2, &len);
-               s += len;
+               ++s;
+               if (*s == '{') {
+                   char* e = strchr(s, '}');
+
+                   if (!e) {
+                       yyerror("Missing right brace on \\x{}");
+                       e = s;
+                   }
+                   if (!utf) {
+                       dTHR;
+                       if (ckWARN(WARN_UTF8))
+                           warner(WARN_UTF8,
+                                  "Use of \\x{} without utf8 declaration");
+                   }
+                   /* note: utf always shorter than hex */
+                   d = (char*)uv_to_utf8((U8*)d,
+                                         scan_hex(s + 1, e - s - 1, &len));
+                   s = e + 1;
+                       
+               }
+               else {
+                   UV uv = (UV)scan_hex(s, 2, &len);
+                   if (utf && PL_lex_inwhat == OP_TRANS &&
+                       utf != (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF))
+                   {
+                       d = (char*)uv_to_utf8((U8*)d, uv);      /* doing a CU or UC */
+                   }
+                   else {
+                       if (uv >= 127 && UTF) {
+                           dTHR;
+                           if (ckWARN(WARN_UTF8))
+                               warner(WARN_UTF8,
+                                   "\\x%.*s will produce malformed UTF-8 character; use \\x{%.*s} for that",
+                                   len,s,len,s);
+                       }
+                       *d++ = (char)uv;
+                   }
+                   s += len;
+               }
                continue;
 
            /* \c is a control character */
            case 'c':
                s++;
+#ifdef EBCDIC
+               *d = *s++;
+               if (isLOWER(*d))
+                  *d = toUPPER(*d);
+               *d++ = toCTRL(*d); 
+#else
                len = *s++;
                *d++ = toCTRL(len);
+#endif
                continue;
 
            /* printf-style backslashes, formfeeds, newlines, etc */
@@ -1032,25 +1214,33 @@ scan_const(char *start)
        Renew(SvPVX(sv), SvLEN(sv), char);
     }
 
-    /* ??? */
-    if (s > bufptr)
+    /* return the substring (via yylval) only if we parsed anything */
+    if (s > PL_bufptr) {
+       if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) )
+           sv = new_constant(start, s - start, (PL_lex_inpat ? "qr" : "q"), 
+                             sv, Nullsv,
+                             ( PL_lex_inwhat == OP_TRANS 
+                               ? "tr"
+                               : ( (PL_lex_inwhat == OP_SUBST && !PL_lex_inpat)
+                                   ? "s"
+                                   : "qq")));
        yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
-    else
+    else
        SvREFCNT_dec(sv);
     return s;
 }
 
 /* This is the one truly awful dwimmer necessary to conflate C and sed. */
-static int
+STATIC int
 intuit_more(register char *s)
 {
-    if (lex_brackets)
+    if (PL_lex_brackets)
        return TRUE;
     if (*s == '-' && s[1] == '>' && (s[2] == '[' || s[2] == '{'))
        return TRUE;
     if (*s != '{' && *s != '[')
        return FALSE;
-    if (!lex_inpat)
+    if (!PL_lex_inpat)
        return TRUE;
 
     /* In a pattern, so maybe we have {n,m}. */
@@ -1078,9 +1268,9 @@ intuit_more(register char *s)
     else {
        int weight = 2;         /* let's weigh the evidence */
        char seen[256];
-       unsigned char un_char = 0, last_un_char;
+       unsigned char un_char = 255, last_un_char;
        char *send = strchr(s,']');
-       char tmpbuf[sizeof tokenbuf * 4];
+       char tmpbuf[sizeof PL_tokenbuf * 4];
 
        if (!send)              /* has to be an expression */
            return TRUE;
@@ -1104,7 +1294,7 @@ intuit_more(register char *s)
            case '&':
            case '$':
                weight -= seen[un_char] * 10;
-               if (isALNUM(s[1])) {
+               if (isALNUM_lazy(s+1)) {
                    scan_ident(s, send, tmpbuf, sizeof tmpbuf, FALSE);
                    if ((int)strlen(tmpbuf) > 1 && gv_fetchpv(tmpbuf,FALSE, SVt_PV))
                        weight -= 100;
@@ -1144,6 +1334,8 @@ intuit_more(register char *s)
                    weight += 30;
                if (strchr("zZ79~",s[1]))
                    weight += 30;
+               if (last_un_char == 255 && (isDIGIT(s[1]) || s[1] == '$'))
+                   weight -= 5;        /* cope with negative subscript */
                break;
            default:
                if (!isALNUM(last_un_char) && !strchr("$@&",last_un_char) &&
@@ -1169,11 +1361,11 @@ intuit_more(register char *s)
     return TRUE;
 }
 
-static int
+STATIC int
 intuit_method(char *start, GV *gv)
 {
     char *s = start + (*start == '$');
-    char tmpbuf[sizeof tokenbuf];
+    char tmpbuf[sizeof PL_tokenbuf];
     STRLEN len;
     GV* indirgv;
 
@@ -1194,11 +1386,11 @@ intuit_method(char *start, GV *gv)
     }
     s = scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
     if (*start == '$') {
-       if (gv || last_lop_op == OP_PRINT || isUPPER(*tokenbuf))
+       if (gv || PL_last_lop_op == OP_PRINT || isUPPER(*PL_tokenbuf))
            return 0;
        s = skipspace(s);
-       bufptr = start;
-       expect = XREF;
+       PL_bufptr = start;
+       PL_expect = XREF;
        return *s == '(' ? FUNCMETH : METHOD;
     }
     if (!keyword(tmpbuf, len)) {
@@ -1213,25 +1405,25 @@ intuit_method(char *start, GV *gv)
        /* filehandle or package name makes it a method */
        if (!gv || GvIO(indirgv) || gv_stashpvn(tmpbuf, len, FALSE)) {
            s = skipspace(s);
-           if ((bufend - s) >= 2 && *s == '=' && *(s+1) == '>')
+           if ((PL_bufend - s) >= 2 && *s == '=' && *(s+1) == '>')
                return 0;       /* no assumptions -- "=>" quotes bearword */
       bare_package:
-           nextval[nexttoke].opval = (OP*)newSVOP(OP_CONST, 0,
+           PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0,
                                                   newSVpv(tmpbuf,0));
-           nextval[nexttoke].opval->op_private = OPpCONST_BARE;
-           expect = XTERM;
+           PL_nextval[PL_nexttoke].opval->op_private = OPpCONST_BARE;
+           PL_expect = XTERM;
            force_next(WORD);
-           bufptr = s;
+           PL_bufptr = s;
            return *s == '(' ? FUNCMETH : METHOD;
        }
     }
     return 0;
 }
 
-static char*
+STATIC char*
 incl_perldb(void)
 {
-    if (perldb) {
+    if (PL_perldb) {
        char *pdb = PerlEnv_getenv("PERL5DB");
 
        if (pdb)
@@ -1267,17 +1459,19 @@ filter_add(filter_t funcp, SV *datasv)
        filter_debug = atoi((char*)datasv);
        return NULL;
     }
-    if (!rsfp_filters)
-       rsfp_filters = newAV();
+    if (!PL_rsfp_filters)
+       PL_rsfp_filters = newAV();
     if (!datasv)
        datasv = NEWSV(255,0);
     if (!SvUPGRADE(datasv, SVt_PVIO))
         die("Can't upgrade filter_add data to SVt_PVIO");
     IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */
-    if (filter_debug)
-       warn("filter_add func %p (%s)", funcp, SvPV(datasv,na));
-    av_unshift(rsfp_filters, 1);
-    av_store(rsfp_filters, 0, datasv) ;
+    if (filter_debug) {
+       STRLEN n_a;
+       warn("filter_add func %p (%s)", funcp, SvPV(datasv, n_a));
+    }
+    av_unshift(PL_rsfp_filters, 1);
+    av_store(PL_rsfp_filters, 0, datasv) ;
     return(datasv);
 }
  
@@ -1288,11 +1482,11 @@ filter_del(filter_t funcp)
 {
     if (filter_debug)
        warn("filter_del func %p", funcp);
-    if (!rsfp_filters || AvFILLp(rsfp_filters)<0)
+    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(rsfp_filters))) == (void*)funcp){
-       sv_free(av_pop(rsfp_filters));
+    if (IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) == (DIR*)funcp){
+       sv_free(av_pop(PL_rsfp_filters));
 
         return;
     }
@@ -1311,9 +1505,9 @@ filter_read(int idx, SV *buf_sv, int maxlen)
     filter_t funcp;
     SV *datasv = NULL;
 
-    if (!rsfp_filters)
+    if (!PL_rsfp_filters)
        return -1;
-    if (idx > AvFILLp(rsfp_filters)){       /* Any more filters?       */
+    if (idx > AvFILLp(PL_rsfp_filters)){       /* Any more filters?    */
        /* Provide a default input filter to make life easy.    */
        /* Note that we append to the line. This is handy.      */
        if (filter_debug)
@@ -1325,8 +1519,8 @@ filter_read(int idx, SV *buf_sv, int maxlen)
 
            /* ensure buf_sv is large enough */
            SvGROW(buf_sv, old_len + maxlen) ;
-           if ((len = PerlIO_read(rsfp, SvPVX(buf_sv) + old_len, maxlen)) <= 0){
-               if (PerlIO_error(rsfp))
+           if ((len = PerlIO_read(PL_rsfp, SvPVX(buf_sv) + old_len, maxlen)) <= 0){
+               if (PerlIO_error(PL_rsfp))
                    return -1;          /* error */
                else
                    return 0 ;          /* end of file */
@@ -1334,8 +1528,8 @@ filter_read(int idx, SV *buf_sv, int maxlen)
            SvCUR_set(buf_sv, old_len + len) ;
        } else {
            /* Want a line */
-            if (sv_gets(buf_sv, rsfp, SvCUR(buf_sv)) == NULL) {
-               if (PerlIO_error(rsfp))
+            if (sv_gets(buf_sv, PL_rsfp, SvCUR(buf_sv)) == NULL) {
+               if (PerlIO_error(PL_rsfp))
                    return -1;          /* error */
                else
                    return 0 ;          /* end of file */
@@ -1344,31 +1538,33 @@ filter_read(int idx, SV *buf_sv, int maxlen)
        return SvCUR(buf_sv);
     }
     /* Skip this filter slot if filter has been deleted        */
-    if ( (datasv = FILTER_DATA(idx)) == &sv_undef){
+    if ( (datasv = FILTER_DATA(idx)) == &PL_sv_undef){
        if (filter_debug)
            warn("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 (filter_debug)
+    if (filter_debug) {
+       STRLEN n_a;
        warn("filter_read %d: via function %p (%s)\n",
-               idx, funcp, SvPV(datasv,na));
+               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)(idx, buf_sv, maxlen);
+    return (*funcp)(PERL_OBJECT_THIS_ idx, buf_sv, maxlen);
 }
 
-static char *
+STATIC char *
 filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
 {
 #ifdef WIN32FILTER
-    if (!rsfp_filters) {
+    if (!PL_rsfp_filters) {
        filter_add(win32_textfilter,NULL);
     }
 #endif
-    if (rsfp_filters) {
+    if (PL_rsfp_filters) {
 
        if (!append)
             SvCUR_set(sv, 0);  /* start with empty line        */
@@ -1377,7 +1573,7 @@ filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
         else
            return Nullch ;
     }
-    else 
+    else
         return (sv_gets(sv, fp, append));
 }
 
@@ -1387,8 +1583,6 @@ filter_gets(register SV *sv, register PerlIO *fp, STRLEN append)
        { "OPERATOR", "TERM", "REF", "STATE", "BLOCK", "TERMBLOCK" };
 #endif
 
-EXT int yychar;                /* last token */
-
 /*
   yylex
 
@@ -1414,8 +1608,7 @@ EXT int yychar;           /* last token */
       if we already built the token before, use it.
 */
 
-int
-yylex(void)
+int yylex(PERL_YYLEX_PARAM_DECL)
 {
     dTHR;
     register char *s;
@@ -1425,11 +1618,16 @@ yylex(void)
     GV *gv = Nullgv;
     GV **gvp = 0;
 
+#ifdef USE_PURE_BISON
+    yylval_pointer = lvalp;
+    yychar_pointer = lcharp;
+#endif
+
     /* check if there's an identifier for us to look at */
-    if (pending_ident) {
+    if (PL_pending_ident) {
         /* pit holds the identifier we read and pending_ident is reset */
-       char pit = pending_ident;
-       pending_ident = 0;
+       char pit = PL_pending_ident;
+       PL_pending_ident = 0;
 
        /* if we're in a my(), we can't allow dynamics here.
           $foo'bar has already been turned into $foo::bar, so
@@ -1437,12 +1635,12 @@ yylex(void)
 
           if it's a legal name, the OP is a PADANY.
        */
-       if (in_my) {
-           if (strchr(tokenbuf,':'))
-               croak(no_myglob,tokenbuf);
+       if (PL_in_my) {
+           if (strchr(PL_tokenbuf,':'))
+               croak(PL_no_myglob,PL_tokenbuf);
 
            yylval.opval = newOP(OP_PADANY, 0);
-           yylval.opval->op_targ = pad_allocmy(tokenbuf);
+           yylval.opval->op_targ = pad_allocmy(PL_tokenbuf);
            return PRIVATEREF;
        }
 
@@ -1458,32 +1656,32 @@ yylex(void)
           (although why you'd do that is anyone's guess).
        */
 
-       if (!strchr(tokenbuf,':')) {
+       if (!strchr(PL_tokenbuf,':')) {
 #ifdef USE_THREADS
            /* Check for single character per-thread SVs */
-           if (tokenbuf[0] == '$' && tokenbuf[2] == '\0'
-               && !isALPHA(tokenbuf[1]) /* Rule out obvious non-threadsvs */
-               && (tmp = find_threadsv(&tokenbuf[1])) != NOT_IN_PAD)
+           if (PL_tokenbuf[0] == '$' && PL_tokenbuf[2] == '\0'
+               && !isALPHA(PL_tokenbuf[1]) /* Rule out obvious non-threadsvs */
+               && (tmp = find_threadsv(&PL_tokenbuf[1])) != NOT_IN_PAD)
            {
                yylval.opval = newOP(OP_THREADSV, 0);
                yylval.opval->op_targ = tmp;
                return PRIVATEREF;
            }
 #endif /* USE_THREADS */
-           if ((tmp = pad_findmy(tokenbuf)) != NOT_IN_PAD) {
+           if ((tmp = pad_findmy(PL_tokenbuf)) != NOT_IN_PAD) {
                /* if it's a sort block and they're naming $a or $b */
-               if (last_lop_op == OP_SORT &&
-                   tokenbuf[0] == '$' &&
-                   (tokenbuf[1] == 'a' || tokenbuf[1] == 'b')
-                   && !tokenbuf[2])
+               if (PL_last_lop_op == OP_SORT &&
+                   PL_tokenbuf[0] == '$' &&
+                   (PL_tokenbuf[1] == 'a' || PL_tokenbuf[1] == 'b')
+                   && !PL_tokenbuf[2])
                {
-                   for (d = in_eval ? oldoldbufptr : linestart;
-                        d < bufend && *d != '\n';
+                   for (d = PL_in_eval ? PL_oldoldbufptr : PL_linestart;
+                        d < PL_bufend && *d != '\n';
                         d++)
                    {
                        if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
                            croak("Can't use \"my %s\" in sort comparison",
-                                 tokenbuf);
+                                 PL_tokenbuf);
                        }
                    }
                }
@@ -1499,26 +1697,26 @@ yylex(void)
           and @foo isn't a variable we can find in the symbol
           table.
        */
-       if (pit == '@' && lex_state != LEX_NORMAL && !lex_brackets) {
-           GV *gv = gv_fetchpv(tokenbuf+1, FALSE, SVt_PVAV);
-           if (!gv || ((tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)))
+       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",
-                            tokenbuf, tokenbuf));
+                            PL_tokenbuf, PL_tokenbuf));
        }
 
        /* build ops for a bareword */
-       yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(tokenbuf+1, 0));
+       yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf+1, 0));
        yylval.opval->op_private = OPpCONST_ENTERED;
-       gv_fetchpv(tokenbuf+1, in_eval ? GV_ADDMULTI : TRUE,
-                  ((tokenbuf[0] == '$') ? SVt_PV
-                   : (tokenbuf[0] == '@') ? SVt_PVAV
+       gv_fetchpv(PL_tokenbuf+1, PL_in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : TRUE,
+                  ((PL_tokenbuf[0] == '$') ? SVt_PV
+                   : (PL_tokenbuf[0] == '@') ? SVt_PVAV
                    : SVt_PVHV));
        return WORD;
     }
 
     /* no identifier pending identification */
 
-    switch (lex_state) {
+    switch (PL_lex_state) {
 #ifdef COMMENTARY
     case LEX_NORMAL:           /* Some compilers will produce faster */
     case LEX_INTERPNORMAL:     /* code if we comment these out. */
@@ -1527,318 +1725,326 @@ yylex(void)
 
     /* when we're already built the next token, just pull it out the queue */
     case LEX_KNOWNEXT:
-       nexttoke--;
-       yylval = nextval[nexttoke];
-       if (!nexttoke) {
-           lex_state = lex_defer;
-           expect = lex_expect;
-           lex_defer = LEX_NORMAL;
+       PL_nexttoke--;
+       yylval = PL_nextval[PL_nexttoke];
+       if (!PL_nexttoke) {
+           PL_lex_state = PL_lex_defer;
+           PL_expect = PL_lex_expect;
+           PL_lex_defer = LEX_NORMAL;
        }
-       return(nexttype[nexttoke]);
+       return(PL_nexttype[PL_nexttoke]);
 
     /* interpolated case modifiers like \L \U, including \Q and \E.
-       when we get here, bufptr is at the \
+       when we get here, PL_bufptr is at the \
     */
     case LEX_INTERPCASEMOD:
 #ifdef DEBUGGING
-       if (bufptr != bufend && *bufptr != '\\')
+       if (PL_bufptr != PL_bufend && *PL_bufptr != '\\')
            croak("panic: INTERPCASEMOD");
 #endif
        /* handle \E or end of string */
-               if (bufptr == bufend || bufptr[1] == 'E') {
+               if (PL_bufptr == PL_bufend || PL_bufptr[1] == 'E') {
            char oldmod;
 
            /* if at a \E */
-           if (lex_casemods) {
-               oldmod = lex_casestack[--lex_casemods];
-               lex_casestack[lex_casemods] = '\0';
+           if (PL_lex_casemods) {
+               oldmod = PL_lex_casestack[--PL_lex_casemods];
+               PL_lex_casestack[PL_lex_casemods] = '\0';
 
-               if (bufptr != bufend && strchr("LUQ", oldmod)) {
-                   bufptr += 2;
-                   lex_state = LEX_INTERPCONCAT;
+               if (PL_bufptr != PL_bufend && strchr("LUQ", oldmod)) {
+                   PL_bufptr += 2;
+                   PL_lex_state = LEX_INTERPCONCAT;
                }
                return ')';
            }
-           if (bufptr != bufend)
-               bufptr += 2;
-           lex_state = LEX_INTERPCONCAT;
-           return yylex();
+           if (PL_bufptr != PL_bufend)
+               PL_bufptr += 2;
+           PL_lex_state = LEX_INTERPCONCAT;
+           return yylex(PERL_YYLEX_PARAM);
        }
        else {
-           s = bufptr + 1;
+           s = PL_bufptr + 1;
            if (strnEQ(s, "L\\u", 3) || strnEQ(s, "U\\l", 3))
                tmp = *s, *s = s[2], s[2] = tmp;        /* misordered... */
            if (strchr("LU", *s) &&
-               (strchr(lex_casestack, 'L') || strchr(lex_casestack, 'U')))
+               (strchr(PL_lex_casestack, 'L') || strchr(PL_lex_casestack, 'U')))
            {
-               lex_casestack[--lex_casemods] = '\0';
+               PL_lex_casestack[--PL_lex_casemods] = '\0';
                return ')';
            }
-           if (lex_casemods > 10) {
-               char* newlb = Renew(lex_casestack, lex_casemods + 2, char);
-               if (newlb != lex_casestack) {
+           if (PL_lex_casemods > 10) {
+               char* newlb = Renew(PL_lex_casestack, PL_lex_casemods + 2, char);
+               if (newlb != PL_lex_casestack) {
                    SAVEFREEPV(newlb);
-                   lex_casestack = newlb;
+                   PL_lex_casestack = newlb;
                }
            }
-           lex_casestack[lex_casemods++] = *s;
-           lex_casestack[lex_casemods] = '\0';
-           lex_state = LEX_INTERPCONCAT;
-           nextval[nexttoke].ival = 0;
+           PL_lex_casestack[PL_lex_casemods++] = *s;
+           PL_lex_casestack[PL_lex_casemods] = '\0';
+           PL_lex_state = LEX_INTERPCONCAT;
+           PL_nextval[PL_nexttoke].ival = 0;
            force_next('(');
            if (*s == 'l')
-               nextval[nexttoke].ival = OP_LCFIRST;
+               PL_nextval[PL_nexttoke].ival = OP_LCFIRST;
            else if (*s == 'u')
-               nextval[nexttoke].ival = OP_UCFIRST;
+               PL_nextval[PL_nexttoke].ival = OP_UCFIRST;
            else if (*s == 'L')
-               nextval[nexttoke].ival = OP_LC;
+               PL_nextval[PL_nexttoke].ival = OP_LC;
            else if (*s == 'U')
-               nextval[nexttoke].ival = OP_UC;
+               PL_nextval[PL_nexttoke].ival = OP_UC;
            else if (*s == 'Q')
-               nextval[nexttoke].ival = OP_QUOTEMETA;
+               PL_nextval[PL_nexttoke].ival = OP_QUOTEMETA;
            else
                croak("panic: yylex");
-           bufptr = s + 1;
+           PL_bufptr = s + 1;
            force_next(FUNC);
-           if (lex_starts) {
-               s = bufptr;
-               lex_starts = 0;
+           if (PL_lex_starts) {
+               s = PL_bufptr;
+               PL_lex_starts = 0;
                Aop(OP_CONCAT);
            }
            else
-               return yylex();
+               return yylex(PERL_YYLEX_PARAM);
        }
 
     case LEX_INTERPPUSH:
         return sublex_push();
 
     case LEX_INTERPSTART:
-       if (bufptr == bufend)
+       if (PL_bufptr == PL_bufend)
            return sublex_done();
-       expect = XTERM;
-       lex_dojoin = (*bufptr == '@');
-       lex_state = LEX_INTERPNORMAL;
-       if (lex_dojoin) {
-           nextval[nexttoke].ival = 0;
+       PL_expect = XTERM;
+       PL_lex_dojoin = (*PL_bufptr == '@');
+       PL_lex_state = LEX_INTERPNORMAL;
+       if (PL_lex_dojoin) {
+           PL_nextval[PL_nexttoke].ival = 0;
            force_next(',');
 #ifdef USE_THREADS
-           nextval[nexttoke].opval = newOP(OP_THREADSV, 0);
-           nextval[nexttoke].opval->op_targ = find_threadsv("\"");
+           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 */
-           nextval[nexttoke].ival = 0;
+           PL_nextval[PL_nexttoke].ival = 0;
            force_next('$');
-           nextval[nexttoke].ival = 0;
+           PL_nextval[PL_nexttoke].ival = 0;
            force_next('(');
-           nextval[nexttoke].ival = OP_JOIN;   /* emulate join($", ...) */
+           PL_nextval[PL_nexttoke].ival = OP_JOIN;     /* emulate join($", ...) */
            force_next(FUNC);
        }
-       if (lex_starts++) {
-           s = bufptr;
+       if (PL_lex_starts++) {
+           s = PL_bufptr;
            Aop(OP_CONCAT);
        }
-       return yylex();
+       return yylex(PERL_YYLEX_PARAM);
 
     case LEX_INTERPENDMAYBE:
-       if (intuit_more(bufptr)) {
-           lex_state = LEX_INTERPNORMAL;       /* false alarm, more expr */
+       if (intuit_more(PL_bufptr)) {
+           PL_lex_state = LEX_INTERPNORMAL;    /* false alarm, more expr */
            break;
        }
        /* FALL THROUGH */
 
     case LEX_INTERPEND:
-       if (lex_dojoin) {
-           lex_dojoin = FALSE;
-           lex_state = LEX_INTERPCONCAT;
+       if (PL_lex_dojoin) {
+           PL_lex_dojoin = FALSE;
+           PL_lex_state = LEX_INTERPCONCAT;
            return ')';
        }
+       if (PL_lex_inwhat == OP_SUBST && PL_lex_repl && SvCOMPILED(PL_lex_repl)) {
+           if (PL_bufptr != PL_bufend)
+               croak("Bad evalled substitution pattern");
+           PL_lex_repl = Nullsv;
+       }
        /* FALLTHROUGH */
     case LEX_INTERPCONCAT:
 #ifdef DEBUGGING
-       if (lex_brackets)
+       if (PL_lex_brackets)
            croak("panic: INTERPCONCAT");
 #endif
-       if (bufptr == bufend)
+       if (PL_bufptr == PL_bufend)
            return sublex_done();
 
-       if (SvIVX(linestr) == '\'') {
-           SV *sv = newSVsv(linestr);
-           if (!lex_inpat)
-               sv = q(sv);
+       if (SvIVX(PL_linestr) == '\'') {
+           SV *sv = newSVsv(PL_linestr);
+           if (!PL_lex_inpat)
+               sv = tokeq(sv);
+           else if ( PL_hints & HINT_NEW_RE )
+               sv = new_constant(NULL, 0, "qr", sv, sv, "q");
            yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
-           s = bufend;
+           s = PL_bufend;
        }
        else {
-           s = scan_const(bufptr);
+           s = scan_const(PL_bufptr);
            if (*s == '\\')
-               lex_state = LEX_INTERPCASEMOD;
+               PL_lex_state = LEX_INTERPCASEMOD;
            else
-               lex_state = LEX_INTERPSTART;
+               PL_lex_state = LEX_INTERPSTART;
        }
 
-       if (s != bufptr) {
-           nextval[nexttoke] = yylval;
-           expect = XTERM;
+       if (s != PL_bufptr) {
+           PL_nextval[PL_nexttoke] = yylval;
+           PL_expect = XTERM;
            force_next(THING);
-           if (lex_starts++)
+           if (PL_lex_starts++)
                Aop(OP_CONCAT);
            else {
-               bufptr = s;
-               return yylex();
+               PL_bufptr = s;
+               return yylex(PERL_YYLEX_PARAM);
            }
        }
 
-       return yylex();
+       return yylex(PERL_YYLEX_PARAM);
     case LEX_FORMLINE:
-       lex_state = LEX_NORMAL;
-       s = scan_formline(bufptr);
-       if (!lex_formbrack)
+       PL_lex_state = LEX_NORMAL;
+       s = scan_formline(PL_bufptr);
+       if (!PL_lex_formbrack)
            goto rightbracket;
        OPERATOR(';');
     }
 
-    s = bufptr;
-    oldoldbufptr = oldbufptr;
-    oldbufptr = s;
+    s = PL_bufptr;
+    PL_oldoldbufptr = PL_oldbufptr;
+    PL_oldbufptr = s;
     DEBUG_p( {
-       PerlIO_printf(PerlIO_stderr(), "### Tokener expecting %s at %s\n", exp_name[expect], s);
+       PerlIO_printf(PerlIO_stderr(), "### Tokener expecting %s at %s\n", exp_name[PL_expect], s);
     } )
 
   retry:
     switch (*s) {
     default:
-       croak("Unrecognized character \\%03o", *s & 255);
+       if (isIDFIRST_lazy(s))
+           goto keylookup;
+       croak("Unrecognized character \\x%02X", *s & 255);
     case 4:
     case 26:
        goto fake_eof;                  /* emulate EOF on ^D or ^Z */
     case 0:
-       if (!rsfp) {
-           last_uni = 0;
-           last_lop = 0;
-           if (lex_brackets)
+       if (!PL_rsfp) {
+           PL_last_uni = 0;
+           PL_last_lop = 0;
+           if (PL_lex_brackets)
                yyerror("Missing right bracket");
            TOKEN(0);
        }
-       if (s++ < bufend)
+       if (s++ < PL_bufend)
            goto retry;                 /* ignore stray nulls */
-       last_uni = 0;
-       last_lop = 0;
-       if (!in_eval && !preambled) {
-           preambled = TRUE;
-           sv_setpv(linestr,incl_perldb());
-           if (SvCUR(linestr))
-               sv_catpv(linestr,";");
-           if (preambleav){
-               while(AvFILLp(preambleav) >= 0) {
-                   SV *tmpsv = av_shift(preambleav);
-                   sv_catsv(linestr, tmpsv);
-                   sv_catpv(linestr, ";");
+       PL_last_uni = 0;
+       PL_last_lop = 0;
+       if (!PL_in_eval && !PL_preambled) {
+           PL_preambled = TRUE;
+           sv_setpv(PL_linestr,incl_perldb());
+           if (SvCUR(PL_linestr))
+               sv_catpv(PL_linestr,";");
+           if (PL_preambleav){
+               while(AvFILLp(PL_preambleav) >= 0) {
+                   SV *tmpsv = av_shift(PL_preambleav);
+                   sv_catsv(PL_linestr, tmpsv);
+                   sv_catpv(PL_linestr, ";");
                    sv_free(tmpsv);
                }
-               sv_free((SV*)preambleav);
-               preambleav = NULL;
+               sv_free((SV*)PL_preambleav);
+               PL_preambleav = NULL;
            }
-           if (minus_n || minus_p) {
-               sv_catpv(linestr, "LINE: while (<>) {");
-               if (minus_l)
-                   sv_catpv(linestr,"chomp;");
-               if (minus_a) {
+           if (PL_minus_n || PL_minus_p) {
+               sv_catpv(PL_linestr, "LINE: while (<>) {");
+               if (PL_minus_l)
+                   sv_catpv(PL_linestr,"chomp;");
+               if (PL_minus_a) {
                    GV* gv = gv_fetchpv("::F", TRUE, SVt_PVAV);
                    if (gv)
                        GvIMPORTED_AV_on(gv);
-                   if (minus_F) {
-                       if (strchr("/'\"", *splitstr)
-                             && strchr(splitstr + 1, *splitstr))
-                           sv_catpvf(linestr, "@F=split(%s);", splitstr);
+                   if (PL_minus_F) {
+                       if (strchr("/'\"", *PL_splitstr)
+                             && strchr(PL_splitstr + 1, *PL_splitstr))
+                           sv_catpvf(PL_linestr, "@F=split(%s);", PL_splitstr);
                        else {
                            char delim;
                            s = "'~#\200\1'"; /* surely one char is unused...*/
-                           while (s[1] && strchr(splitstr, *s))  s++;
+                           while (s[1] && strchr(PL_splitstr, *s))  s++;
                            delim = *s;
-                           sv_catpvf(linestr, "@F=split(%s%c",
+                           sv_catpvf(PL_linestr, "@F=split(%s%c",
                                      "q" + (delim == '\''), delim);
-                           for (s = splitstr; *s; s++) {
+                           for (s = PL_splitstr; *s; s++) {
                                if (*s == '\\')
-                                   sv_catpvn(linestr, "\\", 1);
-                               sv_catpvn(linestr, s, 1);
+                                   sv_catpvn(PL_linestr, "\\", 1);
+                               sv_catpvn(PL_linestr, s, 1);
                            }
-                           sv_catpvf(linestr, "%c);", delim);
+                           sv_catpvf(PL_linestr, "%c);", delim);
                        }
                    }
                    else
-                       sv_catpv(linestr,"@F=split(' ');");
+                       sv_catpv(PL_linestr,"@F=split(' ');");
                }
            }
-           sv_catpv(linestr, "\n");
-           oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
-           bufend = SvPVX(linestr) + SvCUR(linestr);
-           if (PERLDB_LINE && curstash != debstash) {
+           sv_catpv(PL_linestr, "\n");
+           PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+           PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+           if (PERLDB_LINE && PL_curstash != PL_debstash) {
                SV *sv = NEWSV(85,0);
 
                sv_upgrade(sv, SVt_PVMG);
-               sv_setsv(sv,linestr);
-               av_store(GvAV(curcop->cop_filegv),(I32)curcop->cop_line,sv);
+               sv_setsv(sv,PL_linestr);
+               av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
            }
            goto retry;
        }
        do {
-           if ((s = filter_gets(linestr, rsfp, 0)) == Nullch) {
+           if ((s = filter_gets(PL_linestr, PL_rsfp, 0)) == Nullch) {
              fake_eof:
-               if (rsfp) {
-                   if (preprocess && !in_eval)
-                       (void)PerlProc_pclose(rsfp);
-                   else if ((PerlIO *)rsfp == PerlIO_stdin())
-                       PerlIO_clearerr(rsfp);
+               if (PL_rsfp) {
+                   if (PL_preprocess && !PL_in_eval)
+                       (void)PerlProc_pclose(PL_rsfp);
+                   else if ((PerlIO *)PL_rsfp == PerlIO_stdin())
+                       PerlIO_clearerr(PL_rsfp);
                    else
-                       (void)PerlIO_close(rsfp);
-                   if (e_fp == rsfp)
-                       e_fp = Nullfp;
-                   rsfp = Nullfp;
+                       (void)PerlIO_close(PL_rsfp);
+                   PL_rsfp = Nullfp;
+                   PL_doextract = FALSE;
                }
-               if (!in_eval && (minus_n || minus_p)) {
-                   sv_setpv(linestr,minus_p ? ";}continue{print" : "");
-                   sv_catpv(linestr,";}");
-                   oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
-                   bufend = SvPVX(linestr) + SvCUR(linestr);
-                   minus_n = minus_p = 0;
+               if (!PL_in_eval && (PL_minus_n || PL_minus_p)) {
+                   sv_setpv(PL_linestr,PL_minus_p ? ";}continue{print" : "");
+                   sv_catpv(PL_linestr,";}");
+                   PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+                   PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+                   PL_minus_n = PL_minus_p = 0;
                    goto retry;
                }
-               oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
-               sv_setpv(linestr,"");
+               PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+               sv_setpv(PL_linestr,"");
                TOKEN(';');     /* not infinite loop because rsfp is NULL now */
            }
-           if (doextract) {
+           if (PL_doextract) {
                if (*s == '#' && s[1] == '!' && instr(s,"perl"))
-                   doextract = FALSE;
+                   PL_doextract = FALSE;
 
                /* Incest with pod. */
                if (*s == '=' && strnEQ(s, "=cut", 4)) {
-                   sv_setpv(linestr, "");
-                   oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
-                   bufend = SvPVX(linestr) + SvCUR(linestr);
-                   doextract = FALSE;
+                   sv_setpv(PL_linestr, "");
+                   PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+                   PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+                   PL_doextract = FALSE;
                }
            }
            incline(s);
-       } while (doextract);
-       oldoldbufptr = oldbufptr = bufptr = linestart = s;
-       if (PERLDB_LINE && curstash != debstash) {
+       } while (PL_doextract);
+       PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = s;
+       if (PERLDB_LINE && PL_curstash != PL_debstash) {
            SV *sv = NEWSV(85,0);
 
            sv_upgrade(sv, SVt_PVMG);
-           sv_setsv(sv,linestr);
-           av_store(GvAV(curcop->cop_filegv),(I32)curcop->cop_line,sv);
+           sv_setsv(sv,PL_linestr);
+           av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
        }
-       bufend = SvPVX(linestr) + SvCUR(linestr);
-       if (curcop->cop_line == 1) {
-           while (s < bufend && isSPACE(*s))
+       PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+       if (PL_curcop->cop_line == 1) {
+           while (s < PL_bufend && isSPACE(*s))
                s++;
            if (*s == ':' && s[1] != ':') /* for csh execing sh scripts */
                s++;
            d = Nullch;
-           if (!in_eval) {
+           if (!PL_in_eval) {
                if (*s == '#' && *(s+1) == '!')
                    d = s + 2;
 #ifdef ALTERNATE_SHEBANG
@@ -1870,7 +2076,7 @@ yylex(void)
                     */
                    SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV));
                    assert(SvPOK(x) || SvGMAGICAL(x));
-                   if (sv_eq(x, GvSV(curcop->cop_filegv))) {
+                   if (sv_eq(x, GvSV(PL_curcop->cop_filegv))) {
                        sv_setpvn(x, ipath, ipathend - ipath);
                        SvSETMAGIC(x);
                    }
@@ -1907,34 +2113,34 @@ yylex(void)
                if (!d &&
                    *s == '#' &&
                    ipathend > ipath &&
-                   !minus_c &&
+                   !PL_minus_c &&
                    !instr(s,"indir") &&
-                   instr(origargv[0],"perl"))
+                   instr(PL_origargv[0],"perl"))
                {
                    char **newargv;
 
                    *ipathend = '\0';
                    s = ipathend + 1;
-                   while (s < bufend && isSPACE(*s))
+                   while (s < PL_bufend && isSPACE(*s))
                        s++;
-                   if (s < bufend) {
-                       Newz(899,newargv,origargc+3,char*);
+                   if (s < PL_bufend) {
+                       Newz(899,newargv,PL_origargc+3,char*);
                        newargv[1] = s;
-                       while (s < bufend && !isSPACE(*s))
+                       while (s < PL_bufend && !isSPACE(*s))
                            s++;
                        *s = '\0';
-                       Copy(origargv+1, newargv+2, origargc+1, char*);
+                       Copy(PL_origargv+1, newargv+2, PL_origargc+1, char*);
                    }
                    else
-                       newargv = origargv;
+                       newargv = PL_origargv;
                    newargv[0] = ipath;
                    execv(ipath, newargv);
                    croak("Can't exec %s", ipath);
                }
                if (d) {
-                   U32 oldpdb = perldb;
-                   bool oldn = minus_n;
-                   bool oldp = minus_p;
+                   U32 oldpdb = PL_perldb;
+                   bool oldn = PL_minus_n;
+                   bool oldp = PL_minus_p;
 
                    while (*d && !isSPACE(*d)) d++;
                    while (*d == ' ' || *d == '\t') d++;
@@ -1950,30 +2156,30 @@ yylex(void)
                            d = moreswitches(d);
                        } while (d);
                        if (PERLDB_LINE && !oldpdb ||
-                           ( minus_n || minus_p ) && !(oldn || oldp) )
+                           ( PL_minus_n || PL_minus_p ) && !(oldn || oldp) )
                              /* if we have already added "LINE: while (<>) {",
                                 we must not do it again */
                        {
-                           sv_setpv(linestr, "");
-                           oldoldbufptr = oldbufptr = s = linestart = SvPVX(linestr);
-                           bufend = SvPVX(linestr) + SvCUR(linestr);
-                           preambled = FALSE;
+                           sv_setpv(PL_linestr, "");
+                           PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = SvPVX(PL_linestr);
+                           PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+                           PL_preambled = FALSE;
                            if (PERLDB_LINE)
-                               (void)gv_fetchfile(origfilename);
+                               (void)gv_fetchfile(PL_origfilename);
                            goto retry;
                        }
                    }
                }
            }
        }
-       if (lex_formbrack && lex_brackets <= lex_formbrack) {
-           bufptr = s;
-           lex_state = LEX_FORMLINE;
-           return yylex();
+       if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
+           PL_bufptr = s;
+           PL_lex_state = LEX_FORMLINE;
+           return yylex(PERL_YYLEX_PARAM);
        }
        goto retry;
     case '\r':
-#ifndef WIN32CHEAT
+#ifdef PERL_STRICT_CR
        warn("Illegal character \\%03o (carriage return)", '\r');
        croak(
       "(Maybe you didn't strip carriage returns after a network transfer?)\n");
@@ -1983,39 +2189,39 @@ yylex(void)
        goto retry;
     case '#':
     case '\n':
-       if (lex_state != LEX_NORMAL || (in_eval && !rsfp)) {
-           d = bufend;
+       if (PL_lex_state != LEX_NORMAL || (PL_in_eval && !PL_rsfp)) {
+           d = PL_bufend;
            while (s < d && *s != '\n')
                s++;
            if (s < d)
                s++;
            incline(s);
-           if (lex_formbrack && lex_brackets <= lex_formbrack) {
-               bufptr = s;
-               lex_state = LEX_FORMLINE;
-               return yylex();
+           if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
+               PL_bufptr = s;
+               PL_lex_state = LEX_FORMLINE;
+               return yylex(PERL_YYLEX_PARAM);
            }
        }
        else {
            *s = '\0';
-           bufend = s;
+           PL_bufend = s;
        }
        goto retry;
     case '-':
        if (s[1] && isALPHA(s[1]) && !isALNUM(s[2])) {
            s++;
-           bufptr = s;
+           PL_bufptr = s;
            tmp = *s++;
 
-           while (s < bufend && (*s == ' ' || *s == '\t'))
+           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
                s++;
 
            if (strnEQ(s,"=>",2)) {
-               s = force_word(bufptr,WORD,FALSE,FALSE,FALSE);
+               s = force_word(PL_bufptr,WORD,FALSE,FALSE,FALSE);
                OPERATOR('-');          /* unary minus */
            }
-           last_uni = oldbufptr;
-           last_lop_op = OP_FTEREAD;   /* good enough */
+           PL_last_uni = PL_oldbufptr;
+           PL_last_lop_op = OP_FTEREAD;        /* good enough */
            switch (tmp) {
            case 'r': FTST(OP_FTEREAD);
            case 'w': FTST(OP_FTEWRITE);
@@ -2052,7 +2258,7 @@ yylex(void)
        tmp = *s++;
        if (*s == tmp) {
            s++;
-           if (expect == XOPERATOR)
+           if (PL_expect == XOPERATOR)
                TERM(POSTDEC);
            else
                OPERATOR(PREDEC);
@@ -2060,7 +2266,7 @@ yylex(void)
        else if (*s == '>') {
            s++;
            s = skipspace(s);
-           if (isIDFIRST(*s)) {
+           if (isIDFIRST_lazy(s)) {
                s = force_word(s,METHOD,FALSE,TRUE,FALSE);
                TOKEN(ARROW);
            }
@@ -2069,10 +2275,10 @@ yylex(void)
            else
                TERM(ARROW);
        }
-       if (expect == XOPERATOR)
+       if (PL_expect == XOPERATOR)
            Aop(OP_SUBTRACT);
        else {
-           if (isSPACE(*s) || !isSPACE(*bufptr))
+           if (isSPACE(*s) || !isSPACE(*PL_bufptr))
                check_uni();
            OPERATOR('-');              /* unary minus */
        }
@@ -2081,25 +2287,25 @@ yylex(void)
        tmp = *s++;
        if (*s == tmp) {
            s++;
-           if (expect == XOPERATOR)
+           if (PL_expect == XOPERATOR)
                TERM(POSTINC);
            else
                OPERATOR(PREINC);
        }
-       if (expect == XOPERATOR)
+       if (PL_expect == XOPERATOR)
            Aop(OP_ADD);
        else {
-           if (isSPACE(*s) || !isSPACE(*bufptr))
+           if (isSPACE(*s) || !isSPACE(*PL_bufptr))
                check_uni();
            OPERATOR('+');
        }
 
     case '*':
-       if (expect != XOPERATOR) {
-           s = scan_ident(s, bufend, tokenbuf, sizeof tokenbuf, TRUE);
-           expect = XOPERATOR;
-           force_ident(tokenbuf, '*');
-           if (!*tokenbuf)
+       if (PL_expect != XOPERATOR) {
+           s = scan_ident(s, PL_bufend, PL_tokenbuf, sizeof PL_tokenbuf, TRUE);
+           PL_expect = XOPERATOR;
+           force_ident(PL_tokenbuf, '*');
+           if (!*PL_tokenbuf)
                PREREF('*');
            TERM('*');
        }
@@ -2111,25 +2317,25 @@ yylex(void)
        Mop(OP_MULTIPLY);
 
     case '%':
-       if (expect == XOPERATOR) {
+       if (PL_expect == XOPERATOR) {
            ++s;
            Mop(OP_MODULO);
        }
-       tokenbuf[0] = '%';
-       s = scan_ident(s, bufend, tokenbuf + 1, sizeof tokenbuf - 1, TRUE);
-       if (!tokenbuf[1]) {
-           if (s == bufend)
+       PL_tokenbuf[0] = '%';
+       s = scan_ident(s, PL_bufend, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, TRUE);
+       if (!PL_tokenbuf[1]) {
+           if (s == PL_bufend)
                yyerror("Final % should be \\% or %name");
            PREREF('%');
        }
-       pending_ident = '%';
+       PL_pending_ident = '%';
        TERM('%');
 
     case '^':
        s++;
        BOop(OP_BIT_XOR);
     case '[':
-       lex_brackets++;
+       PL_lex_brackets++;
        /* FALL THROUGH */
     case '~':
     case ',':
@@ -2144,14 +2350,14 @@ yylex(void)
        OPERATOR(':');
     case '(':
        s++;
-       if (last_lop == oldoldbufptr || last_uni == oldoldbufptr)
-           oldbufptr = oldoldbufptr;           /* allow print(STDOUT 123) */
+       if (PL_last_lop == PL_oldoldbufptr || PL_last_uni == PL_oldoldbufptr)
+           PL_oldbufptr = PL_oldoldbufptr;             /* allow print(STDOUT 123) */
        else
-           expect = XTERM;
+           PL_expect = XTERM;
        TOKEN('(');
     case ';':
-       if (curcop->cop_line < copline)
-           copline = curcop->cop_line;
+       if (PL_curcop->cop_line < PL_copline)
+           PL_copline = PL_curcop->cop_line;
        tmp = *s++;
        OPERATOR(tmp);
     case ')':
@@ -2162,56 +2368,56 @@ yylex(void)
        TERM(tmp);
     case ']':
        s++;
-       if (lex_brackets <= 0)
+       if (PL_lex_brackets <= 0)
            yyerror("Unmatched right bracket");
        else
-           --lex_brackets;
-       if (lex_state == LEX_INTERPNORMAL) {
-           if (lex_brackets == 0) {
+           --PL_lex_brackets;
+       if (PL_lex_state == LEX_INTERPNORMAL) {
+           if (PL_lex_brackets == 0) {
                if (*s != '[' && *s != '{' && (*s != '-' || s[1] != '>'))
-                   lex_state = LEX_INTERPEND;
+                   PL_lex_state = LEX_INTERPEND;
            }
        }
        TERM(']');
     case '{':
       leftbracket:
        s++;
-       if (lex_brackets > 100) {
-           char* newlb = Renew(lex_brackstack, lex_brackets + 1, char);
-           if (newlb != lex_brackstack) {
+       if (PL_lex_brackets > 100) {
+           char* newlb = Renew(PL_lex_brackstack, PL_lex_brackets + 1, char);
+           if (newlb != PL_lex_brackstack) {
                SAVEFREEPV(newlb);
-               lex_brackstack = newlb;
+               PL_lex_brackstack = newlb;
            }
        }
-       switch (expect) {
+       switch (PL_expect) {
        case XTERM:
-           if (lex_formbrack) {
+           if (PL_lex_formbrack) {
                s--;
                PRETERMBLOCK(DO);
            }
-           if (oldoldbufptr == last_lop)
-               lex_brackstack[lex_brackets++] = XTERM;
+           if (PL_oldoldbufptr == PL_last_lop)
+               PL_lex_brackstack[PL_lex_brackets++] = XTERM;
            else
-               lex_brackstack[lex_brackets++] = XOPERATOR;
+               PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
            OPERATOR(HASHBRACK);
        case XOPERATOR:
-           while (s < bufend && (*s == ' ' || *s == '\t'))
+           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
                s++;
            d = s;
-           tokenbuf[0] = '\0';
-           if (d < bufend && *d == '-') {
-               tokenbuf[0] = '-';
+           PL_tokenbuf[0] = '\0';
+           if (d < PL_bufend && *d == '-') {
+               PL_tokenbuf[0] = '-';
                d++;
-               while (d < bufend && (*d == ' ' || *d == '\t'))
+               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
                    d++;
            }
-           if (d < bufend && isIDFIRST(*d)) {
-               d = scan_word(d, tokenbuf + 1, sizeof tokenbuf - 1,
+           if (d < PL_bufend && isIDFIRST_lazy(d)) {
+               d = scan_word(d, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1,
                              FALSE, &len);
-               while (d < bufend && (*d == ' ' || *d == '\t'))
+               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
                    d++;
                if (*d == '}') {
-                   char minus = (tokenbuf[0] == '-');
+                   char minus = (PL_tokenbuf[0] == '-');
                    s = force_word(s + minus, WORD, FALSE, TRUE, FALSE);
                    if (minus)
                        force_next('-');
@@ -2219,27 +2425,22 @@ yylex(void)
            }
            /* FALL THROUGH */
        case XBLOCK:
-           lex_brackstack[lex_brackets++] = XSTATE;
-           expect = XSTATE;
+           PL_lex_brackstack[PL_lex_brackets++] = XSTATE;
+           PL_expect = XSTATE;
            break;
        case XTERMBLOCK:
-           lex_brackstack[lex_brackets++] = XOPERATOR;
-           expect = XSTATE;
+           PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
+           PL_expect = XSTATE;
            break;
        default: {
                char *t;
-               if (oldoldbufptr == last_lop)
-                   lex_brackstack[lex_brackets++] = XTERM;
+               if (PL_oldoldbufptr == PL_last_lop)
+                   PL_lex_brackstack[PL_lex_brackets++] = XTERM;
                else
-                   lex_brackstack[lex_brackets++] = XOPERATOR;
+                   PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
                s = skipspace(s);
-               if (*s == '}') {
-                   if (expect == XSTATE) {
-                       lex_brackstack[lex_brackets-1] = XSTATE;
-                       break;
-                   }
+               if (*s == '}')
                    OPERATOR(HASHBRACK);
-               }
                /* This hack serves to disambiguate a pair of curlies
                 * as being a block or an anon hash.  Normally, expectation
                 * determines that, but in cases where we're not in a
@@ -2258,21 +2459,21 @@ yylex(void)
                t = s;
                if (*s == '\'' || *s == '"' || *s == '`') {
                    /* common case: get past first string, handling escapes */
-                   for (t++; t < bufend && *t != *s;)
+                   for (t++; t < PL_bufend && *t != *s;)
                        if (*t++ == '\\' && (*t == '\\' || *t == *s))
                            t++;
                    t++;
                }
                else if (*s == 'q') {
-                   if (++t < bufend
+                   if (++t < PL_bufend
                        && (!isALNUM(*t)
-                           || ((*t == 'q' || *t == 'x') && ++t < bufend
+                           || ((*t == 'q' || *t == 'x') && ++t < PL_bufend
                                && !isALNUM(*t)))) {
                        char *tmps;
                        char open, close, term;
                        I32 brackets = 1;
 
-                       while (t < bufend && isSPACE(*t))
+                       while (t < PL_bufend && isSPACE(*t))
                            t++;
                        term = *t;
                        open = term;
@@ -2280,15 +2481,15 @@ yylex(void)
                            term = tmps[5];
                        close = term;
                        if (open == close)
-                           for (t++; t < bufend; t++) {
-                               if (*t == '\\' && t+1 < bufend && open != '\\')
+                           for (t++; t < PL_bufend; t++) {
+                               if (*t == '\\' && t+1 < PL_bufend && open != '\\')
                                    t++;
                                else if (*t == open)
                                    break;
                            }
                        else
-                           for (t++; t < bufend; t++) {
-                               if (*t == '\\' && t+1 < bufend)
+                           for (t++; t < PL_bufend; t++) {
+                               if (*t == '\\' && t+1 < PL_bufend)
                                    t++;
                                else if (*t == close && --brackets <= 0)
                                    break;
@@ -2298,55 +2499,55 @@ yylex(void)
                    }
                    t++;
                }
-               else if (isALPHA(*s)) {
-                   for (t++; t < bufend && isALNUM(*t); t++) ;
+               else if (isIDFIRST_lazy(s)) {
+                   for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ;
                }
-               while (t < bufend && isSPACE(*t))
+               while (t < PL_bufend && isSPACE(*t))
                    t++;
                /* if comma follows first term, call it an anon hash */
                /* XXX it could be a comma expression with loop modifiers */
-               if (t < bufend && ((*t == ',' && (*s == 'q' || !isLOWER(*s)))
+               if (t < PL_bufend && ((*t == ',' && (*s == 'q' || !isLOWER(*s)))
                                   || (*t == '=' && t[1] == '>')))
                    OPERATOR(HASHBRACK);
-               if (expect == XREF)
-                   expect = XTERM;
+               if (PL_expect == XREF)
+                   PL_expect = XSTATE; /* was XTERM, trying XSTATE */
                else {
-                   lex_brackstack[lex_brackets-1] = XSTATE;
-                   expect = XSTATE;
+                   PL_lex_brackstack[PL_lex_brackets-1] = XSTATE;
+                   PL_expect = XSTATE;
                }
            }
            break;
        }
-       yylval.ival = curcop->cop_line;
+       yylval.ival = PL_curcop->cop_line;
        if (isSPACE(*s) || *s == '#')
-           copline = NOLINE;   /* invalidate current command line number */
+           PL_copline = NOLINE;   /* invalidate current command line number */
        TOKEN('{');
     case '}':
       rightbracket:
        s++;
-       if (lex_brackets <= 0)
+       if (PL_lex_brackets <= 0)
            yyerror("Unmatched right bracket");
        else
-           expect = (expectation)lex_brackstack[--lex_brackets];
-       if (lex_brackets < lex_formbrack)
-           lex_formbrack = 0;
-       if (lex_state == LEX_INTERPNORMAL) {
-           if (lex_brackets == 0) {
-               if (lex_fakebrack) {
-                   lex_state = LEX_INTERPEND;
-                   bufptr = s;
-                   return yylex();             /* ignore fake brackets */
+           PL_expect = (expectation)PL_lex_brackstack[--PL_lex_brackets];
+       if (PL_lex_brackets < PL_lex_formbrack)
+           PL_lex_formbrack = 0;
+       if (PL_lex_state == LEX_INTERPNORMAL) {
+           if (PL_lex_brackets == 0) {
+               if (PL_lex_fakebrack) {
+                   PL_lex_state = LEX_INTERPEND;
+                   PL_bufptr = s;
+                   return yylex(PERL_YYLEX_PARAM);     /* ignore fake brackets */
                }
                if (*s == '-' && s[1] == '>')
-                   lex_state = LEX_INTERPENDMAYBE;
+                   PL_lex_state = LEX_INTERPENDMAYBE;
                else if (*s != '[' && *s != '{')
-                   lex_state = LEX_INTERPEND;
+                   PL_lex_state = LEX_INTERPEND;
            }
        }
-       if (lex_brackets < lex_fakebrack) {
-           bufptr = s;
-           lex_fakebrack = 0;
-           return yylex();             /* ignore fake brackets */
+       if (PL_lex_brackets < PL_lex_fakebrack) {
+           PL_bufptr = s;
+           PL_lex_fakebrack = 0;
+           return yylex(PERL_YYLEX_PARAM);             /* ignore fake brackets */
        }
        force_next('}');
        TOKEN(';');
@@ -2356,19 +2557,19 @@ yylex(void)
        if (tmp == '&')
            AOPERATOR(ANDAND);
        s--;
-       if (expect == XOPERATOR) {
-           if (dowarn && isALPHA(*s) && bufptr == linestart) {
-               curcop->cop_line--;
-               warn(warn_nosemi);
-               curcop->cop_line++;
+       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);
+               PL_curcop->cop_line++;
            }
            BAop(OP_BIT_AND);
        }
 
-       s = scan_ident(s - 1, bufend, tokenbuf, sizeof tokenbuf, TRUE);
-       if (*tokenbuf) {
-           expect = XOPERATOR;
-           force_ident(tokenbuf, '&');
+       s = scan_ident(s - 1, PL_bufend, PL_tokenbuf, sizeof PL_tokenbuf, TRUE);
+       if (*PL_tokenbuf) {
+           PL_expect = XOPERATOR;
+           force_ident(PL_tokenbuf, '&');
        }
        else
            PREREF('&');
@@ -2391,14 +2592,14 @@ yylex(void)
            OPERATOR(',');
        if (tmp == '~')
            PMop(OP_MATCH);
-       if (dowarn && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp))
-           warn("Reversed %c= operator",(int)tmp);
+       if (ckWARN(WARN_SYNTAX) && tmp && isSPACE(*s) && strchr("+-*/%.^&|<",tmp))
+           warner(WARN_SYNTAX, "Reversed %c= operator",(int)tmp);
        s--;
-       if (expect == XSTATE && isALPHA(tmp) &&
-               (s == linestart+1 || s[-2] == '\n') )
+       if (PL_expect == XSTATE && isALPHA(tmp) &&
+               (s == PL_linestart+1 || s[-2] == '\n') )
        {
-           if (in_eval && !rsfp) {
-               d = bufend;
+           if (PL_in_eval && !PL_rsfp) {
+               d = PL_bufend;
                while (s < d) {
                    if (*s++ == '\n') {
                        incline(s);
@@ -2415,16 +2616,20 @@ yylex(void)
                }
                goto retry;
            }
-           s = bufend;
-           doextract = TRUE;
+           s = PL_bufend;
+           PL_doextract = TRUE;
            goto retry;
        }
-       if (lex_brackets < lex_formbrack) {
+       if (PL_lex_brackets < PL_lex_formbrack) {
            char *t;
+#ifdef PERL_STRICT_CR
            for (t = s; *t == ' ' || *t == '\t'; t++) ;
+#else
+           for (t = s; *t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+#endif
            if (*t == '\n' || *t == '#') {
                s--;
-               expect = XBLOCK;
+               PL_expect = XBLOCK;
                goto leftbracket;
            }
        }
@@ -2440,7 +2645,7 @@ yylex(void)
        s--;
        OPERATOR('!');
     case '<':
-       if (expect != XOPERATOR) {
+       if (PL_expect != XOPERATOR) {
            if (s[1] != '<' && !strchr(s,'>'))
                check_uni();
            if (s[1] == '<')
@@ -2475,94 +2680,97 @@ yylex(void)
     case '$':
        CLINE;
 
-       if (expect == XOPERATOR) {
-           if (lex_formbrack && lex_brackets == lex_formbrack) {
-               expect = XTERM;
+       if (PL_expect == XOPERATOR) {
+           if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack) {
+               PL_expect = XTERM;
                depcom();
                return ','; /* grandfather non-comma-format format */
            }
        }
 
-       if (s[1] == '#' && (isALPHA(s[2]) || strchr("_{$:", s[2]))) {
-           if (expect == XOPERATOR)
-               no_op("Array length", bufptr);
-           tokenbuf[0] = '@';
-           s = scan_ident(s + 1, bufend, tokenbuf + 1, sizeof tokenbuf - 1,
+       if (s[1] == '#' && (isIDFIRST_lazy(s+2) || strchr("{$:+-", s[2]))) {
+           if (PL_expect == XOPERATOR)
+               no_op("Array length", PL_bufptr);
+           PL_tokenbuf[0] = '@';
+           s = scan_ident(s + 1, PL_bufend, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1,
                           FALSE);
-           if (!tokenbuf[1])
+           if (!PL_tokenbuf[1])
                PREREF(DOLSHARP);
-           expect = XOPERATOR;
-           pending_ident = '#';
+           PL_expect = XOPERATOR;
+           PL_pending_ident = '#';
            TOKEN(DOLSHARP);
        }
 
-       if (expect == XOPERATOR)
-           no_op("Scalar", bufptr);
-       tokenbuf[0] = '$';
-       s = scan_ident(s, bufend, tokenbuf + 1, sizeof tokenbuf - 1, FALSE);
-       if (!tokenbuf[1]) {
-           if (s == bufend)
+       if (PL_expect == XOPERATOR)
+           no_op("Scalar", PL_bufptr);
+       PL_tokenbuf[0] = '$';
+       s = scan_ident(s, PL_bufend, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, FALSE);
+       if (!PL_tokenbuf[1]) {
+           if (s == PL_bufend)
                yyerror("Final $ should be \\$ or $name");
            PREREF('$');
        }
 
        /* This kludge not intended to be bulletproof. */
-       if (tokenbuf[1] == '[' && !tokenbuf[2]) {
+       if (PL_tokenbuf[1] == '[' && !PL_tokenbuf[2]) {
            yylval.opval = newSVOP(OP_CONST, 0,
-                                  newSViv((IV)compiling.cop_arybase));
+                                  newSViv((IV)PL_compiling.cop_arybase));
            yylval.opval->op_private = OPpCONST_ARYBASE;
            TERM(THING);
        }
 
        d = s;
-       if (lex_state == LEX_NORMAL)
+       if (PL_lex_state == LEX_NORMAL)
            s = skipspace(s);
 
-       if ((expect != XREF || oldoldbufptr == last_lop) && intuit_more(s)) {
+       if ((PL_expect != XREF || PL_oldoldbufptr == PL_last_lop) && intuit_more(s)) {
            char *t;
            if (*s == '[') {
-               tokenbuf[0] = '@';
-               if (dowarn) {
+               PL_tokenbuf[0] = '@';
+               if (ckWARN(WARN_SYNTAX)) {
                    for(t = s + 1;
-                       isSPACE(*t) || isALNUM(*t) || *t == '$';
+                       isSPACE(*t) || isALNUM_lazy(t) || *t == '$';
                        t++) ;
                    if (*t++ == ',') {
-                       bufptr = skipspace(bufptr);
-                       while (t < bufend && *t != ']')
+                       PL_bufptr = skipspace(PL_bufptr);
+                       while (t < PL_bufend && *t != ']')
                            t++;
-                       warn("Multidimensional syntax %.*s not supported",
-                            (t - bufptr) + 1, bufptr);
+                       warner(WARN_SYNTAX,
+                               "Multidimensional syntax %.*s not supported",
+                               (t - PL_bufptr) + 1, PL_bufptr);
                    }
                }
            }
            else if (*s == '{') {
-               tokenbuf[0] = '%';
-               if (dowarn && strEQ(tokenbuf+1, "SIG") &&
+               PL_tokenbuf[0] = '%';
+               if (ckWARN(WARN_SYNTAX) && strEQ(PL_tokenbuf+1, "SIG") &&
                    (t = strchr(s, '}')) && (t = strchr(t, '=')))
                {
-                   char tmpbuf[sizeof tokenbuf];
+                   char tmpbuf[sizeof PL_tokenbuf];
                    STRLEN len;
                    for (t++; isSPACE(*t); t++) ;
-                   if (isIDFIRST(*t)) {
+                   if (isIDFIRST_lazy(t)) {
                        t = scan_word(t, tmpbuf, sizeof tmpbuf, TRUE, &len);
-                       if (*t != '(' && perl_get_cv(tmpbuf, FALSE))
-                           warn("You need to quote \"%s\"", tmpbuf);
+                       for (; isSPACE(*t); t++) ;
+                       if (*t == ';' && perl_get_cv(tmpbuf, FALSE))
+                           warner(WARN_SYNTAX,
+                               "You need to quote \"%s\"", tmpbuf);
                    }
                }
            }
        }
 
-       expect = XOPERATOR;
-       if (lex_state == LEX_NORMAL && isSPACE(*d)) {
-           bool islop = (last_lop == oldoldbufptr);
-           if (!islop || last_lop_op == OP_GREPSTART)
-               expect = XOPERATOR;
+       PL_expect = XOPERATOR;
+       if (PL_lex_state == LEX_NORMAL && isSPACE(*d)) {
+           bool islop = (PL_last_lop == PL_oldoldbufptr);
+           if (!islop || PL_last_lop_op == OP_GREPSTART)
+               PL_expect = XOPERATOR;
            else if (strchr("$@\"'`q", *s))
-               expect = XTERM;         /* e.g. print $fh "foo" */
-           else if (strchr("&*<%", *s) && isIDFIRST(s[1]))
-               expect = XTERM;         /* e.g. print $fh &sub */
-           else if (isIDFIRST(*s)) {
-               char tmpbuf[sizeof tokenbuf];
+               PL_expect = XTERM;              /* e.g. print $fh "foo" */
+           else if (strchr("&*<%", *s) && isIDFIRST_lazy(s+1))
+               PL_expect = XTERM;              /* e.g. print $fh &sub */
+           else if (isIDFIRST_lazy(s)) {
+               char tmpbuf[sizeof PL_tokenbuf];
                scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
                if (tmp = keyword(tmpbuf, len)) {
                    /* binary operators exclude handle interpretations */
@@ -2577,71 +2785,72 @@ yylex(void)
                    case -KEY_cmp:
                        break;
                    default:
-                       expect = XTERM; /* e.g. print $fh length() */
+                       PL_expect = XTERM;      /* e.g. print $fh length() */
                        break;
                    }
                }
                else {
                    GV *gv = gv_fetchpv(tmpbuf, FALSE, SVt_PVCV);
                    if (gv && GvCVu(gv))
-                       expect = XTERM; /* e.g. print $fh subr() */
+                       PL_expect = XTERM;      /* e.g. print $fh subr() */
                }
            }
            else if (isDIGIT(*s))
-               expect = XTERM;         /* e.g. print $fh 3 */
+               PL_expect = XTERM;              /* e.g. print $fh 3 */
            else if (*s == '.' && isDIGIT(s[1]))
-               expect = XTERM;         /* e.g. print $fh .3 */
-           else if (strchr("/?-+", *s) && !isSPACE(s[1]))
-               expect = XTERM;         /* e.g. print $fh -1 */
-           else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]))
-               expect = XTERM;         /* print $fh <<"EOF" */
+               PL_expect = XTERM;              /* e.g. print $fh .3 */
+           else if (strchr("/?-+", *s) && !isSPACE(s[1]) && s[1] != '=')
+               PL_expect = XTERM;              /* e.g. print $fh -1 */
+           else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]) && s[2] != '=')
+               PL_expect = XTERM;              /* print $fh <<"EOF" */
        }
-       pending_ident = '$';
+       PL_pending_ident = '$';
        TOKEN('$');
 
     case '@':
-       if (expect == XOPERATOR)
+       if (PL_expect == XOPERATOR)
            no_op("Array", s);
-       tokenbuf[0] = '@';
-       s = scan_ident(s, bufend, tokenbuf + 1, sizeof tokenbuf - 1, FALSE);
-       if (!tokenbuf[1]) {
-           if (s == bufend)
+       PL_tokenbuf[0] = '@';
+       s = scan_ident(s, PL_bufend, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1, FALSE);
+       if (!PL_tokenbuf[1]) {
+           if (s == PL_bufend)
                yyerror("Final @ should be \\@ or @name");
            PREREF('@');
        }
-       if (lex_state == LEX_NORMAL)
+       if (PL_lex_state == LEX_NORMAL)
            s = skipspace(s);
-       if ((expect != XREF || oldoldbufptr == last_lop) && intuit_more(s)) {
+       if ((PL_expect != XREF || PL_oldoldbufptr == PL_last_lop) && intuit_more(s)) {
            if (*s == '{')
-               tokenbuf[0] = '%';
+               PL_tokenbuf[0] = '%';
 
            /* Warn about @ where they meant $. */
-           if (dowarn) {
+           if (ckWARN(WARN_SYNTAX)) {
                if (*s == '[' || *s == '{') {
                    char *t = s + 1;
-                   while (*t && (isALNUM(*t) || strchr(" \t$#+-'\"", *t)))
+                   while (*t && (isALNUM_lazy(t) || strchr(" \t$#+-'\"", *t)))
                        t++;
                    if (*t == '}' || *t == ']') {
                        t++;
-                       bufptr = skipspace(bufptr);
-                       warn("Scalar value %.*s better written as $%.*s",
-                           t-bufptr, bufptr, t-bufptr-1, bufptr+1);
+                       PL_bufptr = skipspace(PL_bufptr);
+                       warner(WARN_SYNTAX,
+                           "Scalar value %.*s better written as $%.*s",
+                           t-PL_bufptr, PL_bufptr, t-PL_bufptr-1, PL_bufptr+1);
                    }
                }
            }
        }
-       pending_ident = '@';
+       PL_pending_ident = '@';
        TERM('@');
 
     case '/':                  /* may either be division or pattern */
     case '?':                  /* may either be conditional or pattern */
-       if (expect != XOPERATOR) {
+       if (PL_expect != XOPERATOR) {
            /* Disable warning on "study /blah/" */
-           if (oldoldbufptr == last_uni 
-               && (*last_uni != 's' || s - last_uni < 5 
-                   || memNE(last_uni, "study", 5) || isALNUM(last_uni[5])))
+           if (PL_oldoldbufptr == PL_last_uni 
+               && (*PL_last_uni != 's' || s - PL_last_uni < 5 
+                   || memNE(PL_last_uni, "study", 5) || isALNUM_lazy(PL_last_uni+5)))
                check_uni();
-           s = scan_pat(s);
+           s = scan_pat(s,OP_MATCH);
            TERM(sublex_start());
        }
        tmp = *s++;
@@ -2650,13 +2859,19 @@ yylex(void)
        OPERATOR(tmp);
 
     case '.':
-       if (lex_formbrack && lex_brackets == lex_formbrack && s[1] == '\n' &&
-               (s == linestart || s[-1] == '\n') ) {
-           lex_formbrack = 0;
-           expect = XSTATE;
+       if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack
+#ifdef PERL_STRICT_CR
+           && s[1] == '\n'
+#else
+           && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n'))
+#endif
+           && (s == PL_linestart || s[-1] == '\n') )
+       {
+           PL_lex_formbrack = 0;
+           PL_expect = XSTATE;
            goto rightbracket;
        }
-       if (expect == XOPERATOR || !isDIGIT(s[1])) {
+       if (PL_expect == XOPERATOR || !isDIGIT(s[1])) {
            tmp = *s++;
            if (*s == tmp) {
                s++;
@@ -2668,7 +2883,7 @@ yylex(void)
                    yylval.ival = 0;
                OPERATOR(DOTDOT);
            }
-           if (expect != XOPERATOR)
+           if (PL_expect != XOPERATOR)
                check_uni();
            Aop(OP_CONCAT);
        }
@@ -2676,15 +2891,15 @@ yylex(void)
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
        s = scan_num(s);
-       if (expect == XOPERATOR)
+       if (PL_expect == XOPERATOR)
            no_op("Number",s);
        TERM(THING);
 
     case '\'':
        s = scan_str(s);
-       if (expect == XOPERATOR) {
-           if (lex_formbrack && lex_brackets == lex_formbrack) {
-               expect = XTERM;
+       if (PL_expect == XOPERATOR) {
+           if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack) {
+               PL_expect = XTERM;
                depcom();
                return ',';     /* grandfather non-comma-format format */
            }
@@ -2698,9 +2913,9 @@ yylex(void)
 
     case '"':
        s = scan_str(s);
-       if (expect == XOPERATOR) {
-           if (lex_formbrack && lex_brackets == lex_formbrack) {
-               expect = XTERM;
+       if (PL_expect == XOPERATOR) {
+           if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack) {
+               PL_expect = XTERM;
                depcom();
                return ',';     /* grandfather non-comma-format format */
            }
@@ -2710,8 +2925,8 @@ yylex(void)
        if (!s)
            missingterm((char*)0);
        yylval.ival = OP_CONST;
-       for (d = SvPV(lex_stuff, len); len; len--, d++) {
-           if (*d == '$' || *d == '@' || *d == '\\') {
+       for (d = SvPV(PL_lex_stuff, len); len; len--, d++) {
+           if (*d == '$' || *d == '@' || *d == '\\' || *d & 0x80) {
                yylval.ival = OP_STRINGIFY;
                break;
            }
@@ -2720,7 +2935,7 @@ yylex(void)
 
     case '`':
        s = scan_str(s);
-       if (expect == XOPERATOR)
+       if (PL_expect == XOPERATOR)
            no_op("Backticks",s);
        if (!s)
            missingterm((char*)0);
@@ -2730,14 +2945,15 @@ yylex(void)
 
     case '\\':
        s++;
-       if (dowarn && lex_inwhat && isDIGIT(*s))
-           warn("Can't use \\%c to mean $%c in expression", *s, *s);
-       if (expect == XOPERATOR)
+       if (ckWARN(WARN_SYNTAX) && PL_lex_inwhat && isDIGIT(*s))
+           warner(WARN_SYNTAX,"Can't use \\%c to mean $%c in expression",
+                       *s, *s);
+       if (PL_expect == XOPERATOR)
            no_op("Backslash",s);
        OPERATOR(REFGEN);
 
     case 'x':
-       if (isDIGIT(s[1]) && expect == XOPERATOR) {
+       if (isDIGIT(s[1]) && PL_expect == XOPERATOR) {
            s++;
            Mop(OP_REPEAT);
        }
@@ -2772,64 +2988,86 @@ yylex(void)
     case 'z': case 'Z':
 
       keylookup: {
+       STRLEN n_a;
        gv = Nullgv;
        gvp = 0;
 
-       bufptr = s;
-       s = scan_word(s, tokenbuf, sizeof tokenbuf, FALSE, &len);
+       PL_bufptr = s;
+       s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len);
 
        /* Some keywords can be followed by any delimiter, including ':' */
-       tmp = (len == 1 && strchr("msyq", tokenbuf[0]) ||
-              len == 2 && ((tokenbuf[0] == 't' && tokenbuf[1] == 'r') ||
-                           (tokenbuf[0] == 'q' &&
-                            strchr("qwx", tokenbuf[1]))));
+       tmp = (len == 1 && strchr("msyq", PL_tokenbuf[0]) ||
+              len == 2 && ((PL_tokenbuf[0] == 't' && PL_tokenbuf[1] == 'r') ||
+                           (PL_tokenbuf[0] == 'q' &&
+                            strchr("qwxr", PL_tokenbuf[1]))));
 
        /* x::* is just a word, unless x is "CORE" */
-       if (!tmp && *s == ':' && s[1] == ':' && strNE(tokenbuf, "CORE"))
+       if (!tmp && *s == ':' && s[1] == ':' && strNE(PL_tokenbuf, "CORE"))
            goto just_a_word;
 
        d = s;
-       while (d < bufend && isSPACE(*d))
+       while (d < PL_bufend && isSPACE(*d))
                d++;    /* no comments skipped here, or s### is misparsed */
 
        /* Is this a label? */
-       if (!tmp && expect == XSTATE
-             && d < bufend && *d == ':' && *(d + 1) != ':') {
+       if (!tmp && PL_expect == XSTATE
+             && d < PL_bufend && *d == ':' && *(d + 1) != ':') {
            s = d + 1;
-           yylval.pval = savepv(tokenbuf);
+           yylval.pval = savepv(PL_tokenbuf);
            CLINE;
            TOKEN(LABEL);
        }
 
        /* Check for keywords */
-       tmp = keyword(tokenbuf, len);
+       tmp = keyword(PL_tokenbuf, len);
 
        /* Is this a word before a => operator? */
        if (strnEQ(d,"=>",2)) {
            CLINE;
-           yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(tokenbuf,0));
+           yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(PL_tokenbuf,0));
            yylval.opval->op_private = OPpCONST_BARE;
            TERM(WORD);
        }
 
        if (tmp < 0) {                  /* second-class keyword? */
-           if (expect != XOPERATOR && (*s != ':' || s[1] != ':') &&
-               (((gv = gv_fetchpv(tokenbuf, FALSE, SVt_PVCV)) &&
-                 GvCVu(gv) && GvIMPORTED_CV(gv)) ||
-                ((gvp = (GV**)hv_fetch(globalstash,tokenbuf,len,FALSE)) &&
-                 (gv = *gvp) != (GV*)&sv_undef &&
-                 GvCVu(gv) && GvIMPORTED_CV(gv))))
-           {
-               tmp = 0;                /* overridden by importation */
+           GV *ogv = Nullgv;   /* override (winner) */
+           GV *hgv = Nullgv;   /* hidden (loser) */
+           if (PL_expect != XOPERATOR && (*s != ':' || s[1] != ':')) {
+               CV *cv;
+               if ((gv = gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVCV)) &&
+                   (cv = GvCVu(gv)))
+               {
+                   if (GvIMPORTED_CV(gv))
+                       ogv = gv;
+                   else if (! CvMETHOD(cv))
+                       hgv = gv;
+               }
+               if (!ogv &&
+                   (gvp = (GV**)hv_fetch(PL_globalstash,PL_tokenbuf,len,FALSE)) &&
+                   (gv = *gvp) != (GV*)&PL_sv_undef &&
+                   GvCVu(gv) && GvIMPORTED_CV(gv))
+               {
+                   ogv = gv;
+               }
+           }
+           if (ogv) {
+               tmp = 0;                /* overridden by import or by GLOBAL */
            }
            else if (gv && !gvp
                     && -tmp==KEY_lock  /* XXX generalizable kludge */
-                    && !hv_fetch(GvHVn(incgv), "Thread.pm", 9, FALSE))
+                    && !hv_fetch(GvHVn(PL_incgv), "Thread.pm", 9, FALSE))
            {
                tmp = 0;                /* any sub overrides "weak" keyword */
            }
-           else {
-               tmp = -tmp; gv = Nullgv; gvp = 0;
+           else {                      /* no override */
+               tmp = -tmp;
+               gv = Nullgv;
+               gvp = 0;
+               if (ckWARN(WARN_AMBIGUOUS) && hgv
+                   && tmp != KEY_x && tmp != KEY_CORE) /* never ambiguous */
+                   warner(WARN_AMBIGUOUS,
+                       "Ambiguous call resolved as CORE::%s(), %s",
+                        GvENAME(hgv), "qualify as such or use &");
            }
        }
 
@@ -2839,24 +3077,25 @@ yylex(void)
        default:                        /* not a keyword */
          just_a_word: {
                SV *sv;
-               char lastchar = (bufptr == oldoldbufptr ? 0 : bufptr[-1]);
+               char lastchar = (PL_bufptr == PL_oldoldbufptr ? 0 : PL_bufptr[-1]);
 
                /* Get the rest if it looks like a package qualifier */
 
                if (*s == '\'' || *s == ':' && s[1] == ':') {
                    STRLEN morelen;
-                   s = scan_word(s, tokenbuf + len, sizeof tokenbuf - len,
+                   s = scan_word(s, PL_tokenbuf + len, sizeof PL_tokenbuf - len,
                                  TRUE, &morelen);
                    if (!morelen)
-                       croak("Bad name after %s::", tokenbuf);
+                       croak("Bad name after %s%s", PL_tokenbuf,
+                               *s == '\'' ? "'" : "::");
                    len += morelen;
                }
 
-               if (expect == XOPERATOR) {
-                   if (bufptr == linestart) {
-                       curcop->cop_line--;
-                       warn(warn_nosemi);
-                       curcop->cop_line++;
+               if (PL_expect == XOPERATOR) {
+                   if (PL_bufptr == PL_linestart) {
+                       PL_curcop->cop_line--;
+                       warner(WARN_SEMICOLON, PL_warn_nosemi);
+                       PL_curcop->cop_line++;
                    }
                    else
                        no_op("Bareword",s);
@@ -2867,30 +3106,31 @@ yylex(void)
                   (and a package name). */
 
                if (len > 2 &&
-                   tokenbuf[len - 2] == ':' && tokenbuf[len - 1] == ':')
+                   PL_tokenbuf[len - 2] == ':' && PL_tokenbuf[len - 1] == ':')
                {
-                   if (dowarn && ! gv_fetchpv(tokenbuf, FALSE, SVt_PVHV))
-                       warn("Bareword \"%s\" refers to nonexistent package",
-                            tokenbuf);
+                   if (ckWARN(WARN_UNSAFE) && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV))
+                       warner(WARN_UNSAFE, 
+                           "Bareword \"%s\" refers to nonexistent package",
+                            PL_tokenbuf);
                    len -= 2;
-                   tokenbuf[len] = '\0';
+                   PL_tokenbuf[len] = '\0';
                    gv = Nullgv;
                    gvp = 0;
                }
                else {
                    len = 0;
                    if (!gv)
-                       gv = gv_fetchpv(tokenbuf, FALSE, SVt_PVCV);
+                       gv = gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVCV);
                }
 
                /* if we saw a global override before, get the right name */
 
                if (gvp) {
                    sv = newSVpv("CORE::GLOBAL::",14);
-                   sv_catpv(sv,tokenbuf);
+                   sv_catpv(sv,PL_tokenbuf);
                }
                else
-                   sv = newSVpv(tokenbuf,0);
+                   sv = newSVpv(PL_tokenbuf,0);
 
                /* Presume this is going to be a bareword of some sort. */
 
@@ -2905,12 +3145,15 @@ yylex(void)
 
                /* See if it's the indirect object for a list operator. */
 
-               if (oldoldbufptr &&
-                   oldoldbufptr < bufptr &&
-                   (oldoldbufptr == last_lop || oldoldbufptr == last_uni) &&
+               if (PL_oldoldbufptr &&
+                   PL_oldoldbufptr < PL_bufptr &&
+                   (PL_oldoldbufptr == PL_last_lop || PL_oldoldbufptr == PL_last_uni) &&
                    /* NO SKIPSPACE BEFORE HERE! */
-                   (expect == XREF ||
-                    ((opargs[last_lop_op] >> OASHIFT)& 7) == OA_FILEREF) )
+                   (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] == '*')) )
                {
                    bool immediate_paren = *s == '(';
 
@@ -2919,51 +3162,55 @@ yylex(void)
 
                    /* Two barewords in a row may indicate method call. */
 
-                   if ((isALPHA(*s) || *s == '$') && (tmp=intuit_method(s,gv)))
+                   if ((isIDFIRST_lazy(s) || *s == '$') && (tmp=intuit_method(s,gv)))
                        return tmp;
 
                    /* If not a declared subroutine, it's an indirect object. */
                    /* (But it's an indir obj regardless for sort.) */
 
-                   if ((last_lop_op == OP_SORT ||
+                   if ((PL_last_lop_op == OP_SORT ||
                          (!immediate_paren && (!gv || !GvCVu(gv))) ) &&
-                        (last_lop_op != OP_MAPSTART && last_lop_op != OP_GREPSTART)){
-                       expect = (last_lop == oldoldbufptr) ? XTERM : XOPERATOR;
+                        (PL_last_lop_op != OP_MAPSTART && PL_last_lop_op != OP_GREPSTART)){
+                       PL_expect = (PL_last_lop == PL_oldoldbufptr) ? XTERM : XOPERATOR;
                        goto bareword;
                    }
                }
 
                /* If followed by a paren, it's certainly a subroutine. */
 
-               expect = XOPERATOR;
+               PL_expect = XOPERATOR;
                s = skipspace(s);
                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(GvCV(gv)))) {
+                       if (*d == ')' && (sv = cv_const_sv(cv))) {
                            s = d + 1;
                            goto its_constant;
                        }
                    }
-                   nextval[nexttoke].opval = yylval.opval;
-                   expect = XOPERATOR;
+                   PL_nextval[PL_nexttoke].opval = yylval.opval;
+                   PL_expect = XOPERATOR;
                    force_next(WORD);
                    yylval.ival = 0;
+                   PL_last_lop_op = OP_ENTERSUB;
                    TOKEN('&');
                }
 
                /* If followed by var or block, call it a method (unless sub) */
 
                if ((*s == '$' || *s == '{') && (!gv || !GvCVu(gv))) {
-                   last_lop = oldbufptr;
-                   last_lop_op = OP_METHOD;
+                   PL_last_lop = PL_oldbufptr;
+                   PL_last_lop_op = OP_METHOD;
                    PREBLOCK(METHOD);
                }
 
                /* If followed by a bareword, see if it looks like indir obj. */
 
-               if ((isALPHA(*s) || *s == '$') && (tmp = intuit_method(s,gv)))
+               if ((isIDFIRST_lazy(s) || *s == '$') && (tmp = intuit_method(s,gv)))
                    return tmp;
 
                /* Not a method, so call it a subroutine (if defined) */
@@ -2972,9 +3219,9 @@ yylex(void)
                    CV* cv;
                    if (lastchar == '-')
                        warn("Ambiguous use of -%s resolved as -&%s()",
-                               tokenbuf, tokenbuf);
-                   last_lop = oldbufptr;
-                   last_lop_op = OP_ENTERSUB;
+                               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))) {
@@ -2988,54 +3235,59 @@ yylex(void)
                    /* Resolve to GV now. */
                    op_free(yylval.opval);
                    yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
+                   PL_last_lop_op = OP_ENTERSUB;
                    /* Is there a prototype? */
                    if (SvPOK(cv)) {
                        STRLEN len;
-                       char *proto = SvPV((SV*)cv, len);
+                       PL_last_proto = SvPV((SV*)cv, len);
                        if (!len)
                            TERM(FUNC0SUB);
-                       if (strEQ(proto, "$"))
+                       if (strEQ(PL_last_proto, "$"))
                            OPERATOR(UNIOPSUB);
-                       if (*proto == '&' && *s == '{') {
-                           sv_setpv(subname,"__ANON__");
+                       if (*PL_last_proto == '&' && *s == '{') {
+                           sv_setpv(PL_subname,"__ANON__");
                            PREBLOCK(LSTOPSUB);
                        }
-                   }
-                   nextval[nexttoke].opval = yylval.opval;
-                   expect = XTERM;
+                   } else
+                       PL_last_proto = NULL;
+                   PL_nextval[PL_nexttoke].opval = yylval.opval;
+                   PL_expect = XTERM;
                    force_next(WORD);
                    TOKEN(NOAMP);
                }
 
-               if (hints & HINT_STRICT_SUBS &&
+               if (PL_hints & HINT_STRICT_SUBS &&
                    lastchar != '-' &&
                    strnNE(s,"->",2) &&
-                   last_lop_op != OP_TRUNCATE &&  /* S/F prototype in opcode.pl */
-                   last_lop_op != OP_ACCEPT &&
-                   last_lop_op != OP_PIPE_OP &&
-                   last_lop_op != OP_SOCKPAIR)
+                   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",
-                       tokenbuf);
-                   ++error_count;
+                       PL_tokenbuf);
+                   ++PL_error_count;
                }
 
                /* Call it a bare word */
 
            bareword:
-               if (dowarn) {
+               if (ckWARN(WARN_RESERVED)) {
                    if (lastchar != '-') {
-                       for (d = tokenbuf; *d && isLOWER(*d); d++) ;
+                       for (d = PL_tokenbuf; *d && isLOWER(*d); d++) ;
                        if (!*d)
-                           warn(warn_reserved, tokenbuf);
+                           warner(WARN_RESERVED, PL_warn_reserved, PL_tokenbuf);
                    }
                }
 
            safe_bareword:
                if (lastchar && strchr("*%&", lastchar)) {
                    warn("Operator or semicolon missing before %c%s",
-                       lastchar, tokenbuf);
+                       lastchar, PL_tokenbuf);
                    warn("Ambiguous use of %c resolved as operator %c",
                        lastchar, lastchar);
                }
@@ -3044,19 +3296,19 @@ yylex(void)
 
        case KEY___FILE__:
            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                       newSVsv(GvSV(curcop->cop_filegv)));
+                                       newSVsv(GvSV(PL_curcop->cop_filegv)));
            TERM(THING);
 
        case KEY___LINE__:
            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                   newSVpvf("%ld", (long)curcop->cop_line));
+                                   newSVpvf("%ld", (long)PL_curcop->cop_line));
            TERM(THING);
 
        case KEY___PACKAGE__:
            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                       (curstash
-                                        ? newSVsv(curstname)
-                                        : &sv_undef));
+                                       (PL_curstash
+                                        ? newSVsv(PL_curstname)
+                                        : &PL_sv_undef));
            TERM(THING);
 
        case KEY___DATA__:
@@ -3064,30 +3316,30 @@ yylex(void)
            GV *gv;
 
            /*SUPPRESS 560*/
-           if (rsfp && (!in_eval || tokenbuf[2] == 'D')) {
+           if (PL_rsfp && (!PL_in_eval || PL_tokenbuf[2] == 'D')) {
                char *pname = "main";
-               if (tokenbuf[2] == 'D')
-                   pname = HvNAME(curstash ? curstash : defstash);
+               if (PL_tokenbuf[2] == 'D')
+                   pname = HvNAME(PL_curstash ? PL_curstash : PL_defstash);
                gv = gv_fetchpv(form("%s::DATA", pname), TRUE, SVt_PVIO);
                GvMULTI_on(gv);
                if (!GvIO(gv))
                    GvIOp(gv) = newIO();
-               IoIFP(GvIOp(gv)) = rsfp;
+               IoIFP(GvIOp(gv)) = PL_rsfp;
 #if defined(HAS_FCNTL) && defined(F_SETFD)
                {
-                   int fd = PerlIO_fileno(rsfp);
+                   int fd = PerlIO_fileno(PL_rsfp);
                    fcntl(fd,F_SETFD,fd >= 3);
                }
 #endif
                /* Mark this internal pseudo-handle as clean */
                IoFLAGS(GvIOp(gv)) |= IOf_UNTAINT;
-               if (preprocess)
+               if (PL_preprocess)
                    IoTYPE(GvIOp(gv)) = '|';
-               else if ((PerlIO*)rsfp == PerlIO_stdin())
+               else if ((PerlIO*)PL_rsfp == PerlIO_stdin())
                    IoTYPE(GvIOp(gv)) = '-';
                else
                    IoTYPE(GvIOp(gv)) = '<';
-               rsfp = Nullfp;
+               PL_rsfp = Nullfp;
            }
            goto fake_eof;
        }
@@ -3097,8 +3349,8 @@ yylex(void)
        case KEY_BEGIN:
        case KEY_END:
        case KEY_INIT:
-           if (expect == XSTATE) {
-               s = bufptr;
+           if (PL_expect == XSTATE) {
+               s = PL_bufptr;
                goto really_sub;
            }
            goto just_a_word;
@@ -3107,8 +3359,8 @@ yylex(void)
            if (*s == ':' && s[1] == ':') {
                s += 2;
                d = s;
-               s = scan_word(s, tokenbuf, sizeof tokenbuf, FALSE, &len);
-               tmp = keyword(tokenbuf, len);
+               s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len);
+               tmp = keyword(PL_tokenbuf, len);
                if (tmp < 0)
                    tmp = -tmp;
                goto reserved_word;
@@ -3163,14 +3415,14 @@ yylex(void)
 
        case KEY_crypt:
 #ifdef FCRYPT
-           if (!cryptseen++)
+           if (!PL_cryptseen++)
                init_des();
 #endif
            LOP(OP_CRYPT,XTERM);
 
        case KEY_chmod:
-           if (dowarn) {
-               for (d = s; d < bufend && (isSPACE(*d) || *d == '('); d++) ;
+           if (ckWARN(WARN_OCTAL)) {
+               for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ;
                if (*d != '0' && isDIGIT(*d))
                    yywarn("chmod: mode argument is missing initial 0");
            }
@@ -3200,7 +3452,7 @@ yylex(void)
            OPERATOR(DO);
 
        case KEY_die:
-           hints |= HINT_BLOCK_SCOPE;
+           PL_hints |= HINT_BLOCK_SCOPE;
            LOP(OP_DIE,XTERM);
 
        case KEY_defined:
@@ -3224,7 +3476,7 @@ yylex(void)
            PREBLOCK(ELSE);
 
        case KEY_elsif:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            OPERATOR(ELSIF);
 
        case KEY_eq:
@@ -3238,7 +3490,7 @@ yylex(void)
 
        case KEY_eval:
            s = skipspace(s);
-           expect = (*s == '{') ? XTERMBLOCK : XTERM;
+           PL_expect = (*s == '{') ? XTERMBLOCK : XTERM;
            UNIBRACK(OP_ENTEREVAL);
 
        case KEY_eof:
@@ -3274,15 +3526,15 @@ yylex(void)
 
        case KEY_for:
        case KEY_foreach:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            s = skipspace(s);
-           if (expect == XSTATE && isIDFIRST(*s)) {
+           if (PL_expect == XSTATE && isIDFIRST_lazy(s)) {
                char *p = s;
-               if ((bufend - p) >= 3 &&
+               if ((PL_bufend - p) >= 3 &&
                    strnEQ(p, "my", 2) && isSPACE(*(p + 2)))
                    p += 2;
                p = skipspace(p);
-               if (isIDFIRST(*p))
+               if (isIDFIRST_lazy(p))
                    croak("Missing $ on loop variable");
            }
            OPERATOR(FOR);
@@ -3404,7 +3656,7 @@ yylex(void)
            UNI(OP_HEX);
 
        case KEY_if:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            OPERATOR(IF);
 
        case KEY_index:
@@ -3466,11 +3718,11 @@ yylex(void)
            UNI(OP_LSTAT);
 
        case KEY_m:
-           s = scan_pat(s);
+           s = scan_pat(s,OP_MATCH);
            TERM(sublex_start());
 
        case KEY_map:
-           LOP(OP_MAPSTART,XREF);
+           LOP(OP_MAPSTART, XREF);
            
        case KEY_mkdir:
            LOP(OP_MKDIR,XTERM);
@@ -3488,15 +3740,15 @@ yylex(void)
            LOP(OP_MSGSND,XTERM);
 
        case KEY_my:
-           in_my = TRUE;
+           PL_in_my = TRUE;
            s = skipspace(s);
-           if (isIDFIRST(*s)) {
-               s = scan_word(s, tokenbuf, sizeof tokenbuf, TRUE, &len);
-               in_my_stash = gv_stashpv(tokenbuf, FALSE);
-               if (!in_my_stash) {
+           if (isIDFIRST_lazy(s)) {
+               s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len);
+               PL_in_my_stash = gv_stashpv(PL_tokenbuf, FALSE);
+               if (!PL_in_my_stash) {
                    char tmpbuf[1024];
-                   bufptr = s;
-                   sprintf(tmpbuf, "No such class %.1000s", tokenbuf);
+                   PL_bufptr = s;
+                   sprintf(tmpbuf, "No such class %.1000s", PL_tokenbuf);
                    yyerror(tmpbuf);
                }
            }
@@ -3510,7 +3762,7 @@ yylex(void)
            Eop(OP_SNE);
 
        case KEY_no:
-           if (expect != XSTATE)
+           if (PL_expect != XSTATE)
                yyerror("\"no\" not allowed in expression");
            s = force_word(s,WORD,FALSE,TRUE,FALSE);
            s = force_version(s);
@@ -3522,9 +3774,9 @@ yylex(void)
 
        case KEY_open:
            s = skipspace(s);
-           if (isIDFIRST(*s)) {
+           if (isIDFIRST_lazy(s)) {
                char *t;
-               for (d = s; isALNUM(*d); d++) ;
+               for (d = s; isALNUM_lazy(d); d++) ;
                t = skipspace(d);
                if (strchr("|&*+-=!?:.", *t))
                    warn("Precedence problem: open %.*s should be open(%.*s)",
@@ -3546,11 +3798,11 @@ yylex(void)
            LOP(OP_OPEN_DIR,XTERM);
 
        case KEY_print:
-           checkcomma(s,tokenbuf,"filehandle");
+           checkcomma(s,PL_tokenbuf,"filehandle");
            LOP(OP_PRINT,XREF);
 
        case KEY_printf:
-           checkcomma(s,tokenbuf,"filehandle");
+           checkcomma(s,PL_tokenbuf,"filehandle");
            LOP(OP_PRTF,XREF);
 
        case KEY_prototype:
@@ -3589,33 +3841,35 @@ yylex(void)
            s = scan_str(s);
            if (!s)
                missingterm((char*)0);
-           if (dowarn && SvLEN(lex_stuff)) {
-               d = SvPV_force(lex_stuff, len);
+           if (ckWARN(WARN_SYNTAX) && SvLEN(PL_lex_stuff)) {
+               d = SvPV_force(PL_lex_stuff, len);
                for (; len; --len, ++d) {
                    if (*d == ',') {
-                       warn("Possible attempt to separate words with commas");
+                       warner(WARN_SYNTAX,
+                           "Possible attempt to separate words with commas");
                        break;
                    }
                    if (*d == '#') {
-                       warn("Possible attempt to put comments in qw() list");
+                       warner(WARN_SYNTAX,
+                           "Possible attempt to put comments in qw() list");
                        break;
                    }
                }
            }
            force_next(')');
-           nextval[nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, q(lex_stuff));
-           lex_stuff = Nullsv;
+           PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, tokeq(PL_lex_stuff));
+           PL_lex_stuff = Nullsv;
            force_next(THING);
            force_next(',');
-           nextval[nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(" ",1));
+           PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(" ",1));
            force_next(THING);
            force_next('(');
            yylval.ival = OP_SPLIT;
            CLINE;
-           expect = XTERM;
-           bufptr = s;
-           last_lop = oldbufptr;
-           last_lop_op = OP_SPLIT;
+           PL_expect = XTERM;
+           PL_bufptr = s;
+           PL_last_lop = PL_oldbufptr;
+           PL_last_lop_op = OP_SPLIT;
            return FUNC;
 
        case KEY_qq:
@@ -3623,8 +3877,12 @@ yylex(void)
            if (!s)
                missingterm((char*)0);
            yylval.ival = OP_STRINGIFY;
-           if (SvIVX(lex_stuff) == '\'')
-               SvIVX(lex_stuff) = 0;   /* qq'$foo' should intepolate */
+           if (SvIVX(PL_lex_stuff) == '\'')
+               SvIVX(PL_lex_stuff) = 0;        /* qq'$foo' should intepolate */
+           TERM(sublex_start());
+
+       case KEY_qr:
+           s = scan_pat(s,OP_QR);
            TERM(sublex_start());
 
        case KEY_qx:
@@ -3639,10 +3897,10 @@ yylex(void)
            OLDLOP(OP_RETURN);
 
        case KEY_require:
-           *tokenbuf = '\0';
+           *PL_tokenbuf = '\0';
            s = force_word(s,WORD,TRUE,TRUE,FALSE);
-           if (isIDFIRST(*tokenbuf))
-               gv_stashpvn(tokenbuf, strlen(tokenbuf), TRUE);
+           if (isIDFIRST_lazy(PL_tokenbuf))
+               gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE);
            else if (*s == '<')
                yyerror("<> should be quotes");
            UNI(OP_REQUIRE);
@@ -3787,11 +4045,11 @@ yylex(void)
            LOP(OP_SOCKPAIR,XTERM);
 
        case KEY_sort:
-           checkcomma(s,tokenbuf,"subroutine name");
+           checkcomma(s,PL_tokenbuf,"subroutine name");
            s = skipspace(s);
            if (*s == ';' || *s == ')')         /* probably a close */
                croak("sort is now a reserved word");
-           expect = XTERM;
+           PL_expect = XTERM;
            s = force_word(s,WORD,TRUE,TRUE,FALSE);
            LOP(OP_SORT,XREF);
 
@@ -3814,7 +4072,7 @@ yylex(void)
            UNI(OP_STAT);
 
        case KEY_study:
-           sawstudy++;
+           PL_sawstudy++;
            UNI(OP_STUDY);
 
        case KEY_substr:
@@ -3825,29 +4083,29 @@ yylex(void)
          really_sub:
            s = skipspace(s);
 
-           if (isIDFIRST(*s) || *s == '\'' || *s == ':') {
-               char tmpbuf[sizeof tokenbuf];
-               expect = XBLOCK;
+           if (isIDFIRST_lazy(s) || *s == '\'' || *s == ':') {
+               char tmpbuf[sizeof PL_tokenbuf];
+               PL_expect = XBLOCK;
                d = scan_word(s, tmpbuf, sizeof tmpbuf, TRUE, &len);
                if (strchr(tmpbuf, ':'))
-                   sv_setpv(subname, tmpbuf);
+                   sv_setpv(PL_subname, tmpbuf);
                else {
-                   sv_setsv(subname,curstname);
-                   sv_catpvn(subname,"::",2);
-                   sv_catpvn(subname,tmpbuf,len);
+                   sv_setsv(PL_subname,PL_curstname);
+                   sv_catpvn(PL_subname,"::",2);
+                   sv_catpvn(PL_subname,tmpbuf,len);
                }
                s = force_word(s,WORD,FALSE,TRUE,TRUE);
                s = skipspace(s);
            }
            else {
-               expect = XTERMBLOCK;
-               sv_setpv(subname,"?");
+               PL_expect = XTERMBLOCK;
+               sv_setpv(PL_subname,"?");
            }
 
            if (tmp == KEY_format) {
                s = skipspace(s);
                if (*s == '=')
-                   lex_formbrack = lex_brackets + 1;
+                   PL_lex_formbrack = PL_lex_brackets + 1;
                OPERATOR(FORMAT);
            }
 
@@ -3857,36 +4115,36 @@ yylex(void)
 
                s = scan_str(s);
                if (!s) {
-                   if (lex_stuff)
-                       SvREFCNT_dec(lex_stuff);
-                   lex_stuff = Nullsv;
+                   if (PL_lex_stuff)
+                       SvREFCNT_dec(PL_lex_stuff);
+                   PL_lex_stuff = Nullsv;
                    croak("Prototype not terminated");
                }
                /* strip spaces */
-               d = SvPVX(lex_stuff);
+               d = SvPVX(PL_lex_stuff);
                tmp = 0;
                for (p = d; *p; ++p) {
                    if (!isSPACE(*p))
                        d[tmp++] = *p;
                }
                d[tmp] = '\0';
-               SvCUR(lex_stuff) = tmp;
-
-               nexttoke++;
-               nextval[1] = nextval[0];
-               nexttype[1] = nexttype[0];
-               nextval[0].opval = (OP*)newSVOP(OP_CONST, 0, lex_stuff);
-               nexttype[0] = THING;
-               if (nexttoke == 1) {
-                   lex_defer = lex_state;
-                   lex_expect = expect;
-                   lex_state = LEX_KNOWNEXT;
+               SvCUR(PL_lex_stuff) = tmp;
+
+               PL_nexttoke++;
+               PL_nextval[1] = PL_nextval[0];
+               PL_nexttype[1] = PL_nexttype[0];
+               PL_nextval[0].opval = (OP*)newSVOP(OP_CONST, 0, PL_lex_stuff);
+               PL_nexttype[0] = THING;
+               if (PL_nexttoke == 1) {
+                   PL_lex_defer = PL_lex_state;
+                   PL_lex_expect = PL_expect;
+                   PL_lex_state = LEX_KNOWNEXT;
                }
-               lex_stuff = Nullsv;
+               PL_lex_stuff = Nullsv;
            }
 
-           if (*SvPV(subname,na) == '?') {
-               sv_setpv(subname,"__ANON__");
+           if (*SvPV(PL_subname,n_a) == '?') {
+               sv_setpv(PL_subname,"__ANON__");
                TOKEN(ANONSUB);
            }
            PREBLOCK(SUB);
@@ -3948,11 +4206,11 @@ yylex(void)
            UNI(OP_UNTIE);
 
        case KEY_until:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            OPERATOR(UNTIL);
 
        case KEY_unless:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            OPERATOR(UNLESS);
 
        case KEY_unlink:
@@ -3968,8 +4226,8 @@ yylex(void)
            LOP(OP_UTIME,XTERM);
 
        case KEY_umask:
-           if (dowarn) {
-               for (d = s; d < bufend && (isSPACE(*d) || *d == '('); d++) ;
+           if (ckWARN(WARN_OCTAL)) {
+               for (d = s; d < PL_bufend && (isSPACE(*d) || *d == '('); d++) ;
                if (*d != '0' && isDIGIT(*d))
                    yywarn("umask: argument is missing initial 0");
            }
@@ -3979,13 +4237,13 @@ yylex(void)
            LOP(OP_UNSHIFT,XTERM);
 
        case KEY_use:
-           if (expect != XSTATE)
+           if (PL_expect != XSTATE)
                yyerror("\"use\" not allowed in expression");
            s = skipspace(s);
            if(isDIGIT(*s)) {
                s = force_version(s);
                if(*s == ';' || (s = skipspace(s), *s == ';')) {
-                   nextval[nexttoke].opval = Nullop;
+                   PL_nextval[PL_nexttoke].opval = Nullop;
                    force_next(WORD);
                }
            }
@@ -4000,15 +4258,15 @@ yylex(void)
            UNI(OP_VALUES);
 
        case KEY_vec:
-           sawvec = TRUE;
+           PL_sawvec = TRUE;
            LOP(OP_VEC,XTERM);
 
        case KEY_while:
-           yylval.ival = curcop->cop_line;
+           yylval.ival = PL_curcop->cop_line;
            OPERATOR(WHILE);
 
        case KEY_warn:
-           hints |= HINT_BLOCK_SCOPE;
+           PL_hints |= HINT_BLOCK_SCOPE;
            LOP(OP_WARN,XTERM);
 
        case KEY_wait:
@@ -4021,11 +4279,21 @@ yylex(void)
            FUN0(OP_WANTARRAY);
 
        case KEY_write:
-           gv_fetchpv("\f",TRUE, SVt_PV);      /* Make sure $^L is defined */
+#ifdef EBCDIC
+       {
+           static char ctl_l[2];
+
+           if (ctl_l[0] == '\0') 
+               ctl_l[0] = toCTRL('L');
+           gv_fetchpv(ctl_l,TRUE, SVt_PV);
+       }
+#else
+           gv_fetchpv("\f",TRUE, SVt_PV);      /* Make sure $^L is defined */
+#endif
            UNI(OP_ENTERWRITE);
 
        case KEY_x:
-           if (expect == XOPERATOR)
+           if (PL_expect == XOPERATOR)
                Mop(OP_REPEAT);
            check_uni();
            goto just_a_word;
@@ -4386,6 +4654,8 @@ keyword(register char *d, I32 len)
        case 3:
            if (strEQ(d,"ord"))                 return -KEY_ord;
            if (strEQ(d,"oct"))                 return -KEY_oct;
+           if (strEQ(d,"our")) { deprecate("reserved word \"our\"");
+                                               return 0;}
            break;
        case 4:
            if (strEQ(d,"open"))                return -KEY_open;
@@ -4422,6 +4692,7 @@ keyword(register char *d, I32 len)
     case 'q':
        if (len <= 2) {
            if (strEQ(d,"q"))                   return KEY_q;
+           if (strEQ(d,"qr"))                  return KEY_qr;
            if (strEQ(d,"qq"))                  return KEY_qq;
            if (strEQ(d,"qw"))                  return KEY_qw;
            if (strEQ(d,"qx"))                  return KEY_qx;
@@ -4657,35 +4928,38 @@ keyword(register char *d, I32 len)
     return 0;
 }
 
-static void
+STATIC void
 checkcomma(register char *s, char *name, char *what)
 {
     char *w;
 
-    if (dowarn && *s == ' ' && s[1] == '(') {  /* XXX gotta be a better way */
-       int level = 1;
-       for (w = s+2; *w && level; w++) {
-           if (*w == '(')
-               ++level;
-           else if (*w == ')')
-               --level;
-       }
-       if (*w)
-           for (; *w && isSPACE(*w); w++) ;
-       if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */
-           warn("%s (...) interpreted as function",name);
+    if (*s == ' ' && s[1] == '(') {    /* XXX gotta be a better way */
+       dTHR;                           /* only for ckWARN */
+       if (ckWARN(WARN_SYNTAX)) {
+           int level = 1;
+           for (w = s+2; *w && level; w++) {
+               if (*w == '(')
+                   ++level;
+               else if (*w == ')')
+                   --level;
+           }
+           if (*w)
+               for (; *w && isSPACE(*w); w++) ;
+           if (!*w || !strchr(";|})]oaiuw!=", *w))     /* an advisory hack only... */
+               warner(WARN_SYNTAX, "%s (...) interpreted as function",name);
+       }
     }
-    while (s < bufend && isSPACE(*s))
+    while (s < PL_bufend && isSPACE(*s))
        s++;
     if (*s == '(')
        s++;
-    while (s < bufend && isSPACE(*s))
+    while (s < PL_bufend && isSPACE(*s))
        s++;
-    if (isIDFIRST(*s)) {
+    if (isIDFIRST_lazy(s)) {
        w = s++;
-       while (isALNUM(*s))
+       while (isALNUM_lazy(s))
            s++;
-       while (s < bufend && isSPACE(*s))
+       while (s < PL_bufend && isSPACE(*s))
            s++;
        if (*s == ',') {
            int kw;
@@ -4699,7 +4973,77 @@ checkcomma(register char *s, char *name, char *what)
     }
 }
 
-static char *
+STATIC SV *
+new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) 
+{
+    dSP;
+    HV *table = GvHV(PL_hintgv);                /* ^H */
+    BINOP myop;
+    SV *res;
+    bool oldcatch = CATCH_GET;
+    SV **cvp;
+    SV *cv, *typesv;
+           
+    if (!table) {
+       yyerror("%^H is not defined");
+       return sv;
+    }
+    cvp = hv_fetch(table, key, strlen(key), FALSE);
+    if (!cvp || !SvOK(*cvp)) {
+       char buf[128];
+       sprintf(buf,"$^H{%s} is not defined", key);
+       yyerror(buf);
+       return sv;
+    }
+    sv_2mortal(sv);                    /* Parent created it permanently */
+    cv = *cvp;
+    if (!pv)
+       pv = sv_2mortal(newSVpv(s, len));
+    if (type)
+       typesv = sv_2mortal(newSVpv(type, 0));
+    else
+       typesv = &PL_sv_undef;
+    CATCH_SET(TRUE);
+    Zero(&myop, 1, BINOP);
+    myop.op_last = (OP *) &myop;
+    myop.op_next = Nullop;
+    myop.op_flags = OPf_WANT_SCALAR | OPf_STACKED;
+
+    PUSHSTACKi(PERLSI_OVERLOAD);
+    ENTER;
+    SAVEOP();
+    PL_op = (OP *) &myop;
+    if (PERLDB_SUB && PL_curstash != PL_debstash)
+       PL_op->op_private |= OPpENTERSUB_DB;
+    PUTBACK;
+    pp_pushmark(ARGS);
+
+    EXTEND(sp, 4);
+    PUSHs(pv);
+    PUSHs(sv);
+    PUSHs(typesv);
+    PUSHs(cv);
+    PUTBACK;
+
+    if (PL_op = pp_entersub(ARGS))
+      CALLRUNOPS();
+    LEAVE;
+    SPAGAIN;
+
+    res = POPs;
+    PUTBACK;
+    CATCH_SET(oldcatch);
+    POPSTACK;
+
+    if (!SvOK(res)) {
+       char buf[128];
+       sprintf(buf,"Call to &{$^H{%s}} did not return a defined value", key);
+       yyerror(buf);
+    }
+    return SvREFCNT_inc(res);
+}
+
+STATIC char *
 scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLEN *slp)
 {
     register char *d = dest;
@@ -4707,9 +5051,9 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE
     for (;;) {
        if (d >= e)
            croak(ident_too_long);
-       if (isALNUM(*s))
+       if (isALNUM(*s))        /* UTF handled below */
            *d++ = *s++;
-       else if (*s == '\'' && allow_package && isIDFIRST(s[1])) {
+       else if (*s == '\'' && allow_package && isIDFIRST_lazy(s+1)) {
            *d++ = ':';
            *d++ = ':';
            s++;
@@ -4718,6 +5062,16 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE
            *d++ = *s++;
            *d++ = *s++;
        }
+       else if (UTF && *(U8*)s >= 0xc0 && isALNUM_utf8((U8*)s)) {
+           char *t = s + UTF8SKIP(s);
+           while (*t & 0x80 && is_utf8_mark((U8*)t))
+               t += UTF8SKIP(t);
+           if (d + (t - s) > e)
+               croak(ident_too_long);
+           Copy(s, d, t - s, char);
+           d += t - s;
+           s = t;
+       }
        else {
            *d = '\0';
            *slp = d - dest;
@@ -4726,7 +5080,7 @@ scan_word(register char *s, char *dest, STRLEN destlen, int allow_package, STRLE
     }
 }
 
-static char *
+STATIC char *
 scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I32 ck_uni)
 {
     register char *d;
@@ -4734,8 +5088,8 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
     char *bracket = 0;
     char funny = *s++;
 
-    if (lex_brackets == 0)
-       lex_fakebrack = 0;
+    if (PL_lex_brackets == 0)
+       PL_lex_fakebrack = 0;
     if (isSPACE(*s))
        s = skipspace(s);
     d = dest;
@@ -4751,9 +5105,9 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
        for (;;) {
            if (d >= e)
                croak(ident_too_long);
-           if (isALNUM(*s))
+           if (isALNUM(*s))    /* UTF handled below */
                *d++ = *s++;
-           else if (*s == '\'' && isIDFIRST(s[1])) {
+           else if (*s == '\'' && isIDFIRST_lazy(s+1)) {
                *d++ = ':';
                *d++ = ':';
                s++;
@@ -4762,6 +5116,16 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                *d++ = *s++;
                *d++ = *s++;
            }
+           else if (UTF && *(U8*)s >= 0xc0 && isALNUM_utf8((U8*)s)) {
+               char *t = s + UTF8SKIP(s);
+               while (*t & 0x80 && is_utf8_mark((U8*)t))
+                   t += UTF8SKIP(t);
+               if (d + (t - s) > e)
+                   croak(ident_too_long);
+               Copy(s, d, t - s, char);
+               d += t - s;
+               s = t;
+           }
            else
                break;
        }
@@ -4769,17 +5133,14 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
     *d = '\0';
     d = dest;
     if (*d) {
-       if (lex_state != LEX_NORMAL)
-           lex_state = LEX_INTERPENDMAYBE;
+       if (PL_lex_state != LEX_NORMAL)
+           PL_lex_state = LEX_INTERPENDMAYBE;
        return s;
     }
     if (*s == '$' && s[1] &&
-      (isALNUM(s[1]) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) )
+       (isALNUM_lazy(s+1) || strchr("${", s[1]) || strnEQ(s+1,"::",2)) )
     {
-       if (isDIGIT(s[1]) && lex_state == LEX_INTERPNORMAL)
-           deprecate("\"$$<digit>\" to mean \"${$}<digit>\"");
-       else
-           return s;
+       return s;
     }
     if (*s == '{') {
        bracket = s;
@@ -4804,42 +5165,63 @@ scan_ident(register char *s, register char *send, char *dest, STRLEN destlen, I3
                }
            }
        }
-       if (isIDFIRST(*d)) {
+       if (isIDFIRST_lazy(d)) {
            d++;
-           while (isALNUM(*s) || *s == ':')
-               *d++ = *s++;
+           if (UTF) {
+               e = s;
+               while (e < send && isALNUM_lazy(e) || *e == ':') {
+                   e += UTF8SKIP(e);
+                   while (e < send && *e & 0x80 && is_utf8_mark((U8*)e))
+                       e += UTF8SKIP(e);
+               }
+               Copy(s, d, e - s, char);
+               d += e - s;
+               s = e;
+           }
+           else {
+               while (isALNUM(*s) || *s == ':')
+                   *d++ = *s++;
+           }
            *d = '\0';
            while (s < send && (*s == ' ' || *s == '\t')) s++;
            if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
-               if (dowarn && keyword(dest, d - dest)) {
+               dTHR;                   /* only for ckWARN */
+               if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
                    char *brack = *s == '[' ? "[...]" : "{...}";
-                   warn("Ambiguous use of %c{%s%s} resolved to %c%s%s",
+                   warner(WARN_AMBIGUOUS,
+                       "Ambiguous use of %c{%s%s} resolved to %c%s%s",
                        funny, dest, brack, funny, dest, brack);
                }
-               lex_fakebrack = lex_brackets+1;
+               PL_lex_fakebrack = PL_lex_brackets+1;
                bracket++;
-               lex_brackstack[lex_brackets++] = XOPERATOR;
+               PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
                return s;
            }
        }
        if (*s == '}') {
            s++;
-           if (lex_state == LEX_INTERPNORMAL && !lex_brackets)
-               lex_state = LEX_INTERPEND;
+           if (PL_lex_state == LEX_INTERPNORMAL && !PL_lex_brackets)
+               PL_lex_state = LEX_INTERPEND;
            if (funny == '#')
                funny = '@';
-           if (dowarn && lex_state == LEX_NORMAL &&
-             (keyword(dest, d - dest) || perl_get_cv(dest, FALSE)))
-               warn("Ambiguous use of %c{%s} resolved to %c%s",
-                   funny, dest, funny, dest);
+           if (PL_lex_state == LEX_NORMAL) {
+               dTHR;                   /* only for ckWARN */
+               if (ckWARN(WARN_AMBIGUOUS) &&
+                   (keyword(dest, d - dest) || perl_get_cv(dest, FALSE)))
+               {
+                   warner(WARN_AMBIGUOUS,
+                       "Ambiguous use of %c{%s} resolved to %c%s",
+                       funny, dest, funny, dest);
+               }
+           }
        }
        else {
            s = bracket;                /* let the parser handle it */
            *dest = '\0';
        }
     }
-    else if (lex_state == LEX_INTERPNORMAL && !lex_brackets && !intuit_more(s))
-       lex_state = LEX_INTERPEND;
+    else if (PL_lex_state == LEX_INTERPNORMAL && !PL_lex_brackets && !intuit_more(s))
+       PL_lex_state = LEX_INTERPEND;
     return s;
 }
 
@@ -4861,33 +5243,39 @@ void pmflag(U16 *pmfl, int ch)
        *pmfl |= PMf_EXTENDED;
 }
 
-static char *
-scan_pat(char *start)
+STATIC char *
+scan_pat(char *start, I32 type)
 {
     PMOP *pm;
     char *s;
 
     s = scan_str(start);
     if (!s) {
-       if (lex_stuff)
-           SvREFCNT_dec(lex_stuff);
-       lex_stuff = Nullsv;
+       if (PL_lex_stuff)
+           SvREFCNT_dec(PL_lex_stuff);
+       PL_lex_stuff = Nullsv;
        croak("Search pattern not terminated");
     }
 
-    pm = (PMOP*)newPMOP(OP_MATCH, 0);
-    if (multi_open == '?')
+    pm = (PMOP*)newPMOP(type, 0);
+    if (PL_multi_open == '?')
        pm->op_pmflags |= PMf_ONCE;
-    while (*s && strchr("iogcmsx", *s))
-       pmflag(&pm->op_pmflags,*s++);
+    if(type == OP_QR) {
+       while (*s && strchr("iomsx", *s))
+           pmflag(&pm->op_pmflags,*s++);
+    }
+    else {
+       while (*s && strchr("iogcmsx", *s))
+           pmflag(&pm->op_pmflags,*s++);
+    }
     pm->op_pmpermflags = pm->op_pmflags;
 
-    lex_op = (OP*)pm;
+    PL_lex_op = (OP*)pm;
     yylval.ival = OP_MATCH;
     return s;
 }
 
-static char *
+STATIC char *
 scan_subst(char *start)
 {
     register char *s;
@@ -4900,36 +5288,38 @@ scan_subst(char *start)
     s = scan_str(start);
 
     if (!s) {
-       if (lex_stuff)
-           SvREFCNT_dec(lex_stuff);
-       lex_stuff = Nullsv;
+       if (PL_lex_stuff)
+           SvREFCNT_dec(PL_lex_stuff);
+       PL_lex_stuff = Nullsv;
        croak("Substitution pattern not terminated");
     }
 
-    if (s[-1] == multi_open)
+    if (s[-1] == PL_multi_open)
        s--;
 
-    first_start = multi_start;
+    first_start = PL_multi_start;
     s = scan_str(s);
     if (!s) {
-       if (lex_stuff)
-           SvREFCNT_dec(lex_stuff);
-       lex_stuff = Nullsv;
-       if (lex_repl)
-           SvREFCNT_dec(lex_repl);
-       lex_repl = Nullsv;
+       if (PL_lex_stuff)
+           SvREFCNT_dec(PL_lex_stuff);
+       PL_lex_stuff = Nullsv;
+       if (PL_lex_repl)
+           SvREFCNT_dec(PL_lex_repl);
+       PL_lex_repl = Nullsv;
        croak("Substitution replacement not terminated");
     }
-    multi_start = first_start; /* so whole substitution is taken together */
+    PL_multi_start = first_start;      /* so whole substitution is taken together */
 
     pm = (PMOP*)newPMOP(OP_SUBST, 0);
-    while (*s && strchr("iogcmsex", *s)) {
+    while (*s) {
        if (*s == 'e') {
            s++;
            es++;
        }
-       else
+       else if (strchr("iogcmsx", *s))
            pmflag(&pm->op_pmflags,*s++);
+       else
+           break;
     }
 
     if (es) {
@@ -4939,73 +5329,100 @@ scan_subst(char *start)
        while (es-- > 0)
            sv_catpv(repl, es ? "eval " : "do ");
        sv_catpvn(repl, "{ ", 2);
-       sv_catsv(repl, lex_repl);
+       sv_catsv(repl, PL_lex_repl);
        sv_catpvn(repl, " };", 2);
        SvCOMPILED_on(repl);
-       SvREFCNT_dec(lex_repl);
-       lex_repl = repl;
+       SvREFCNT_dec(PL_lex_repl);
+       PL_lex_repl = repl;
     }
 
     pm->op_pmpermflags = pm->op_pmflags;
-    lex_op = (OP*)pm;
+    PL_lex_op = (OP*)pm;
     yylval.ival = OP_SUBST;
     return s;
 }
 
-static char *
+STATIC char *
 scan_trans(char *start)
 {
     register char* s;
     OP *o;
     short *tbl;
     I32 squash;
-    I32 Delete;
+    I32 del;
     I32 complement;
+    I32 utf8;
+    I32 count = 0;
 
     yylval.ival = OP_NULL;
 
     s = scan_str(start);
     if (!s) {
-       if (lex_stuff)
-           SvREFCNT_dec(lex_stuff);
-       lex_stuff = Nullsv;
-       croak("Translation pattern not terminated");
+       if (PL_lex_stuff)
+           SvREFCNT_dec(PL_lex_stuff);
+       PL_lex_stuff = Nullsv;
+       croak("Transliteration pattern not terminated");
     }
-    if (s[-1] == multi_open)
+    if (s[-1] == PL_multi_open)
        s--;
 
     s = scan_str(s);
     if (!s) {
-       if (lex_stuff)
-           SvREFCNT_dec(lex_stuff);
-       lex_stuff = Nullsv;
-       if (lex_repl)
-           SvREFCNT_dec(lex_repl);
-       lex_repl = Nullsv;
-       croak("Translation replacement not terminated");
+       if (PL_lex_stuff)
+           SvREFCNT_dec(PL_lex_stuff);
+       PL_lex_stuff = Nullsv;
+       if (PL_lex_repl)
+           SvREFCNT_dec(PL_lex_repl);
+       PL_lex_repl = Nullsv;
+       croak("Transliteration replacement not terminated");
     }
 
-    New(803,tbl,256,short);
-    o = newPVOP(OP_TRANS, 0, (char*)tbl);
+    if (UTF) {
+       o = newSVOP(OP_TRANS, 0, 0);
+       utf8 = OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF;
+    }
+    else {
+       New(803,tbl,256,short);
+       o = newPVOP(OP_TRANS, 0, (char*)tbl);
+       utf8 = 0;
+    }
 
-    complement = Delete = squash = 0;
-    while (*s == 'c' || *s == 'd' || *s == 's') {
+    complement = del = squash = 0;
+    while (strchr("cdsCU", *s)) {
        if (*s == 'c')
            complement = OPpTRANS_COMPLEMENT;
        else if (*s == 'd')
-           Delete = OPpTRANS_DELETE;
-       else
+           del = OPpTRANS_DELETE;
+       else if (*s == 's')
            squash = OPpTRANS_SQUASH;
+       else {
+           switch (count++) {
+           case 0:
+               if (*s == 'C')
+                   utf8 &= ~OPpTRANS_FROM_UTF;
+               else
+                   utf8 |= OPpTRANS_FROM_UTF;
+               break;
+           case 1:
+               if (*s == 'C')
+                   utf8 &= ~OPpTRANS_TO_UTF;
+               else
+                   utf8 |= OPpTRANS_TO_UTF;
+               break;
+           default: 
+               croak("Too many /C and /U options");
+           }
+       }
        s++;
     }
-    o->op_private = Delete|squash|complement;
+    o->op_private = del|squash|complement|utf8;
 
-    lex_op = o;
+    PL_lex_op = o;
     yylval.ival = OP_TRANS;
     return s;
 }
 
-static char *
+STATIC char *
 scan_heredoc(register char *s)
 {
     dTHR;
@@ -5017,20 +5434,20 @@ scan_heredoc(register char *s)
     register char *d;
     register char *e;
     char *peek;
-    int outer = (rsfp && !(lex_inwhat == OP_SCALAR));
+    int outer = (PL_rsfp && !(PL_lex_inwhat == OP_SCALAR));
 
     s += 2;
-    d = tokenbuf;
-    e = tokenbuf + sizeof tokenbuf - 1;
+    d = PL_tokenbuf;
+    e = PL_tokenbuf + sizeof PL_tokenbuf - 1;
     if (!outer)
        *d++ = '\n';
     for (peek = s; *peek == ' ' || *peek == '\t'; peek++) ;
     if (*peek && strchr("`'\"",*peek)) {
        s = peek;
        term = *s++;
-       s = delimcpy(d, e, s, bufend, term, &len);
+       s = delimcpy(d, e, s, PL_bufend, term, &len);
        d += len;
-       if (s < bufend)
+       if (s < PL_bufend)
            s++;
     }
     else {
@@ -5038,26 +5455,50 @@ scan_heredoc(register char *s)
            s++, term = '\'';
        else
            term = '"';
-       if (!isALNUM(*s))
+       if (!isALNUM_lazy(s))
            deprecate("bare << to mean <<\"\"");
-       for (; isALNUM(*s); s++) {
+       for (; isALNUM_lazy(s); s++) {
            if (d < e)
                *d++ = *s;
        }
     }
-    if (d >= tokenbuf + sizeof tokenbuf - 1)
+    if (d >= PL_tokenbuf + sizeof PL_tokenbuf - 1)
        croak("Delimiter for here document is too long");
     *d++ = '\n';
     *d = '\0';
-    len = d - tokenbuf;
+    len = d - PL_tokenbuf;
+#ifndef PERL_STRICT_CR
+    d = strchr(s, '\r');
+    if (d) {
+       char *olds = s;
+       s = d;
+       while (s < PL_bufend) {
+           if (*s == '\r') {
+               *d++ = '\n';
+               if (*++s == '\n')
+                   s++;
+           }
+           else if (*s == '\n' && s[1] == '\r') {      /* \015\013 on a mac? */
+               *d++ = *s++;
+               s++;
+           }
+           else
+               *d++ = *s++;
+       }
+       *d = '\0';
+       PL_bufend = d;
+       SvCUR_set(PL_linestr, PL_bufend - SvPVX(PL_linestr));
+       s = olds;
+    }
+#endif
     d = "\n";
-    if (outer || !(d=ninstr(s,bufend,d,d+1)))
-       herewas = newSVpv(s,bufend-s);
+    if (outer || !(d=ninstr(s,PL_bufend,d,d+1)))
+       herewas = newSVpv(s,PL_bufend-s);
     else
        s--, herewas = newSVpv(s,d-s);
     s += SvCUR(herewas);
 
-    tmpstr = NEWSV(87,80);
+    tmpstr = NEWSV(87,79);
     sv_upgrade(tmpstr, SVt_PVIV);
     if (term == '\'') {
        op_type = OP_CONST;
@@ -5069,66 +5510,81 @@ scan_heredoc(register char *s)
     }
 
     CLINE;
-    multi_start = curcop->cop_line;
-    multi_open = multi_close = '<';
-    term = *tokenbuf;
+    PL_multi_start = PL_curcop->cop_line;
+    PL_multi_open = PL_multi_close = '<';
+    term = *PL_tokenbuf;
     if (!outer) {
        d = s;
-       while (s < bufend &&
-         (*s != term || memNE(s,tokenbuf,len)) ) {
+       while (s < PL_bufend &&
+         (*s != term || memNE(s,PL_tokenbuf,len)) ) {
            if (*s++ == '\n')
-               curcop->cop_line++;
+               PL_curcop->cop_line++;
        }
-       if (s >= bufend) {
-           curcop->cop_line = multi_start;
-           missingterm(tokenbuf);
+       if (s >= PL_bufend) {
+           PL_curcop->cop_line = PL_multi_start;
+           missingterm(PL_tokenbuf);
        }
        sv_setpvn(tmpstr,d+1,s-d);
        s += len - 1;
-       curcop->cop_line++;     /* the preceding stmt passes a newline */
+       PL_curcop->cop_line++;  /* the preceding stmt passes a newline */
 
-       sv_catpvn(herewas,s,bufend-s);
-       sv_setsv(linestr,herewas);
-       oldoldbufptr = oldbufptr = bufptr = s = linestart = SvPVX(linestr);
-       bufend = SvPVX(linestr) + SvCUR(linestr);
+       sv_catpvn(herewas,s,PL_bufend-s);
+       sv_setsv(PL_linestr,herewas);
+       PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = s = PL_linestart = SvPVX(PL_linestr);
+       PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
     }
     else
        sv_setpvn(tmpstr,"",0);   /* avoid "uninitialized" warning */
-    while (s >= bufend) {      /* multiple line string? */
+    while (s >= PL_bufend) {   /* multiple line string? */
        if (!outer ||
-        !(oldoldbufptr = oldbufptr = s = linestart = filter_gets(linestr, rsfp, 0))) {
-           curcop->cop_line = multi_start;
-           missingterm(tokenbuf);
+        !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
+           PL_curcop->cop_line = PL_multi_start;
+           missingterm(PL_tokenbuf);
+       }
+       PL_curcop->cop_line++;
+       PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
+#ifndef PERL_STRICT_CR
+       if (PL_bufend - PL_linestart >= 2) {
+           if ((PL_bufend[-2] == '\r' && PL_bufend[-1] == '\n') ||
+               (PL_bufend[-2] == '\n' && PL_bufend[-1] == '\r'))
+           {
+               PL_bufend[-2] = '\n';
+               PL_bufend--;
+               SvCUR_set(PL_linestr, PL_bufend - SvPVX(PL_linestr));
+           }
+           else if (PL_bufend[-1] == '\r')
+               PL_bufend[-1] = '\n';
        }
-       curcop->cop_line++;
-       if (PERLDB_LINE && curstash != debstash) {
+       else if (PL_bufend - PL_linestart == 1 && PL_bufend[-1] == '\r')
+           PL_bufend[-1] = '\n';
+#endif
+       if (PERLDB_LINE && PL_curstash != PL_debstash) {
            SV *sv = NEWSV(88,0);
 
            sv_upgrade(sv, SVt_PVMG);
-           sv_setsv(sv,linestr);
-           av_store(GvAV(curcop->cop_filegv),
-             (I32)curcop->cop_line,sv);
+           sv_setsv(sv,PL_linestr);
+           av_store(GvAV(PL_curcop->cop_filegv),
+             (I32)PL_curcop->cop_line,sv);
        }
-       bufend = SvPVX(linestr) + SvCUR(linestr);
-       if (*s == term && memEQ(s,tokenbuf,len)) {
-           s = bufend - 1;
+       if (*s == term && memEQ(s,PL_tokenbuf,len)) {
+           s = PL_bufend - 1;
            *s = ' ';
-           sv_catsv(linestr,herewas);
-           bufend = SvPVX(linestr) + SvCUR(linestr);
+           sv_catsv(PL_linestr,herewas);
+           PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
        }
        else {
-           s = bufend;
-           sv_catsv(tmpstr,linestr);
+           s = PL_bufend;
+           sv_catsv(tmpstr,PL_linestr);
        }
     }
-    multi_end = curcop->cop_line;
+    PL_multi_end = PL_curcop->cop_line;
     s++;
     if (SvCUR(tmpstr) + 5 < SvLEN(tmpstr)) {
        SvLEN_set(tmpstr, SvCUR(tmpstr) + 1);
        Renew(SvPVX(tmpstr), SvLEN(tmpstr), char);
     }
     SvREFCNT_dec(herewas);
-    lex_stuff = tmpstr;
+    PL_lex_stuff = tmpstr;
     yylval.ival = op_type;
     return s;
 }
@@ -5149,7 +5605,7 @@ scan_heredoc(register char *s)
 
 */
 
-static char *
+STATIC char *
 scan_inputsymbol(char *start)
 {
     register char *s = start;          /* current position in buffer */
@@ -5157,17 +5613,17 @@ scan_inputsymbol(char *start)
     register char *e;
     I32 len;
 
-    d = tokenbuf;                      /* start of temp holding space */
-    e = tokenbuf + sizeof tokenbuf;    /* end of temp holding space */
-    s = delimcpy(d, e, s + 1, bufend, '>', &len);      /* extract until > */
+    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 > */
 
     /* die if we didn't have space for the contents of the <>,
        or if it didn't end
     */
 
-    if (len >= sizeof tokenbuf)
+    if (len >= sizeof PL_tokenbuf)
        croak("Excessively long <> operator");
-    if (s >= bufend)
+    if (s >= PL_bufend)
        croak("Unterminated <> operator");
 
     s++;
@@ -5182,7 +5638,7 @@ scan_inputsymbol(char *start)
     if (*d == '$' && d[1]) d++;
 
     /* allow <Pkg'VALUE> or <Pkg::VALUE> */
-    while (*d && (isALNUM(*d) || *d == '\'' || *d == ':'))
+    while (*d && (isALNUM_lazy(d) || *d == '\'' || *d == ':'))
        d++;
 
     /* If we've tried to read what we allow filehandles to look like, and
@@ -5191,7 +5647,7 @@ scan_inputsymbol(char *start)
        as nothing more than a string.
     */
 
-    if (d - tokenbuf != len) {
+    if (d - PL_tokenbuf != len) {
        yylval.ival = OP_GLOB;
        set_csh();
        s = scan_str(start);
@@ -5201,7 +5657,7 @@ scan_inputsymbol(char *start)
     }
     else {
        /* we're in a filehandle read situation */
-       d = tokenbuf;
+       d = PL_tokenbuf;
 
        /* turn <> into <ARGV> */
        if (!len)
@@ -5219,16 +5675,16 @@ scan_inputsymbol(char *start)
            if ((tmp = pad_findmy(d)) != NOT_IN_PAD) {
                OP *o = newOP(OP_PADSV, 0);
                o->op_targ = tmp;
-               lex_op = (OP*)newUNOP(OP_READLINE, 0, newUNOP(OP_RV2GV, 0, o));
+               PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, o);
            }
            else {
                GV *gv = gv_fetchpv(d+1,TRUE, SVt_PV);
-               lex_op = (OP*)newUNOP(OP_READLINE, 0,
-                                       newUNOP(OP_RV2GV, 0,
+               PL_lex_op = (OP*)newUNOP(OP_READLINE, 0,
                                            newUNOP(OP_RV2SV, 0,
-                                               newGVOP(OP_GV, 0, gv))));
+                                               newGVOP(OP_GV, 0, gv)));
            }
-           /* we created the ops in lex_op, so make yylval.ival a null op */
+           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;
        }
 
@@ -5236,7 +5692,7 @@ scan_inputsymbol(char *start)
           (<Foo::BAR> or <FOO>) so build a simple readline OP */
        else {
            GV *gv = gv_fetchpv(d,TRUE, SVt_PVIO);
-           lex_op = (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv));
+           PL_lex_op = (OP*)newUNOP(OP_READLINE, 0, newGVOP(OP_GV, 0, gv));
            yylval.ival = OP_NULL;
        }
     }
@@ -5285,7 +5741,7 @@ scan_inputsymbol(char *start)
 
 */
 
-static char *
+STATIC char *
 scan_str(char *start)
 {
     dTHR;
@@ -5306,17 +5762,17 @@ scan_str(char *start)
     /* after skipping whitespace, the next character is the terminator */
     term = *s;
     /* mark where we are */
-    multi_start = curcop->cop_line;
-    multi_open = term;
+    PL_multi_start = PL_curcop->cop_line;
+    PL_multi_open = term;
 
     /* find corresponding closing delimiter */
     if (term && (tmps = strchr("([{< )]}> )]}>",term)))
        term = tmps[5];
-    multi_close = term;
+    PL_multi_close = term;
 
     /* create a new SV to hold the contents.  87 is leak category, I'm
-       assuming.  80 is the SV's initial length.  What a random number. */
-    sv = NEWSV(87,80);
+       assuming.  79 is the SV's initial length.  What a random number. */
+    sv = NEWSV(87,79);
     sv_upgrade(sv, SVt_PVIV);
     SvIVX(sv) = term;
     (void)SvPOK_only(sv);              /* validate pointer */
@@ -5325,18 +5781,18 @@ scan_str(char *start)
     s++;
     for (;;) {
        /* extend sv if need be */
-       SvGROW(sv, SvCUR(sv) + (bufend - s) + 1);
+       SvGROW(sv, SvCUR(sv) + (PL_bufend - s) + 1);
        /* set 'to' to the next character in the sv's string */
        to = SvPVX(sv)+SvCUR(sv);
        
        /* if open delimiter is the close delimiter read unbridle */
-       if (multi_open == multi_close) {
-           for (; s < bufend; s++,to++) {
+       if (PL_multi_open == PL_multi_close) {
+           for (; s < PL_bufend; s++,to++) {
                /* embedded newlines increment the current line number */
-               if (*s == '\n' && !rsfp)
-                   curcop->cop_line++;
+               if (*s == '\n' && !PL_rsfp)
+                   PL_curcop->cop_line++;
                /* handle quoted delimiters */
-               if (*s == '\\' && s+1 < bufend && term != '\\') {
+               if (*s == '\\' && s+1 < PL_bufend && term != '\\') {
                    if (s[1] == term)
                        s++;
                /* any other quotes are simply copied straight through */
@@ -5357,21 +5813,21 @@ scan_str(char *start)
        */
        else {
            /* read until we run out of string, or we find the terminator */
-           for (; s < bufend; s++,to++) {
+           for (; s < PL_bufend; s++,to++) {
                /* embedded newlines increment the line count */
-               if (*s == '\n' && !rsfp)
-                   curcop->cop_line++;
+               if (*s == '\n' && !PL_rsfp)
+                   PL_curcop->cop_line++;
                /* backslashes can escape the open or closing characters */
-               if (*s == '\\' && s+1 < bufend) {
-                   if ((s[1] == multi_open) || (s[1] == multi_close))
+               if (*s == '\\' && s+1 < PL_bufend) {
+                   if ((s[1] == PL_multi_open) || (s[1] == PL_multi_close))
                        s++;
                    else
                        *to++ = *s++;
                }
                /* allow nested opens and closes */
-               else if (*s == multi_close && --brackets <= 0)
+               else if (*s == PL_multi_close && --brackets <= 0)
                    break;
-               else if (*s == multi_open)
+               else if (*s == PL_multi_open)
                    brackets++;
                *to = *s;
            }
@@ -5384,37 +5840,53 @@ scan_str(char *start)
         * this next chunk reads more into the buffer if we're not done yet
         */
 
-       if (s < bufend) break;  /* handle case where we are done yet :-) */
+       if (s < PL_bufend) break;       /* handle case where we are done yet :-) */
 
+#ifndef PERL_STRICT_CR
+       if (to - SvPVX(sv) >= 2) {
+           if ((to[-2] == '\r' && to[-1] == '\n') ||
+               (to[-2] == '\n' && to[-1] == '\r'))
+           {
+               to[-2] = '\n';
+               to--;
+               SvCUR_set(sv, to - SvPVX(sv));
+           }
+           else if (to[-1] == '\r')
+               to[-1] = '\n';
+       }
+       else if (to - SvPVX(sv) == 1 && to[-1] == '\r')
+           to[-1] = '\n';
+#endif
+       
        /* if we're out of file, or a read fails, bail and reset the current
           line marker so we can report where the unterminated string began
        */
-       if (!rsfp ||
-        !(oldoldbufptr = oldbufptr = s = linestart = filter_gets(linestr, rsfp, 0))) {
+       if (!PL_rsfp ||
+        !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
            sv_free(sv);
-           curcop->cop_line = multi_start;
+           PL_curcop->cop_line = PL_multi_start;
            return Nullch;
        }
        /* we read a line, so increment our line counter */
-       curcop->cop_line++;
-       
+       PL_curcop->cop_line++;
+
        /* update debugger info */
-       if (PERLDB_LINE && curstash != debstash) {
+       if (PERLDB_LINE && PL_curstash != PL_debstash) {
            SV *sv = NEWSV(88,0);
 
            sv_upgrade(sv, SVt_PVMG);
-           sv_setsv(sv,linestr);
-           av_store(GvAV(curcop->cop_filegv),
-             (I32)curcop->cop_line, sv);
+           sv_setsv(sv,PL_linestr);
+           av_store(GvAV(PL_curcop->cop_filegv),
+             (I32)PL_curcop->cop_line, sv);
        }
-       
-       /* having changed the buffer, we must update bufend */
-       bufend = SvPVX(linestr) + SvCUR(linestr);
+
+       /* having changed the buffer, we must update PL_bufend */
+       PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
     }
     
     /* at this point, we have successfully read the delimited string */
 
-    multi_end = curcop->cop_line;
+    PL_multi_end = PL_curcop->cop_line;
     s++;
 
     /* if we allocated too much space, give some back */
@@ -5427,10 +5899,10 @@ scan_str(char *start)
        for this op
     */
     
-    if (lex_stuff)
-       lex_repl = sv;
+    if (PL_lex_stuff)
+       PL_lex_repl = sv;
     else
-       lex_stuff = sv;
+       PL_lex_stuff = sv;
     return s;
 }
 
@@ -5442,13 +5914,13 @@ scan_str(char *start)
 
   Read a number in any of the formats that Perl accepts:
 
-  0(x[0-7A-F]+)|([0-7]+)
+  0(x[0-7A-F]+)|([0-7]+)|(b[01])
   [\d_]+(\.[\d_]*)?[Ee](\d+)
 
   Underbars (_) are allowed in decimal numbers.  If -w is on,
   underbars before a decimal point must be at three digit intervals.
 
-  Like most scan_ routines, it uses the tokenbuf buffer to hold the
+  Like most scan_ routines, it uses the PL_tokenbuf buffer to hold the
   thing it reads.
 
   If it reads a number without a decimal point or an exponent, it will
@@ -5476,18 +5948,19 @@ scan_num(char *start)
       croak("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.
+       0.13 disguise, or a hexadecimal number, or a binary number.
     */
     case '0':
        {
          /* variables:
             u          holds the "number so far"
-            shift      the power of 2 of the base (hex == 4, octal == 3)
+            shift      the power of 2 of the base
+                       (hex == 4, octal == 3, binary == 1)
             overflowed was the number more than we can hold?
 
             Shift is used when we add a digit.  It also serves as an "are
-            we in octal or hex?" indicator to disallow hex characters when
-            in octal mode.
+            we in octal/hex/binary?" indicator to disallow hex characters
+            when in octal mode.
           */
            UV u;
            I32 shift;
@@ -5497,6 +5970,9 @@ scan_num(char *start)
            if (s[1] == 'x') {
                shift = 4;
                s += 2;
+           } else if (s[1] == 'b') {
+               shift = 1;
+               s += 2;
            }
            /* check for a decimal in disguise */
            else if (s[1] == '.')
@@ -5506,7 +5982,7 @@ scan_num(char *start)
                shift = 3;
            u = 0;
 
-           /* read the rest of the octal number */
+           /* read the rest of the number */
            for (;;) {
                UV n, b;        /* n is used in the overflow test, b is the digit we're adding on */
 
@@ -5523,13 +5999,21 @@ scan_num(char *start)
 
                /* 8 and 9 are not octal */
                case '8': case '9':
-                   if (shift != 4)
+                   if (shift == 3)
                        yyerror("Illegal octal digit");
+                   else
+                       if (shift == 1)
+                           yyerror("Illegal binary digit");
                    /* FALL THROUGH */
 
                /* octal digits */
-               case '0': case '1': case '2': case '3': case '4':
+               case '2': case '3': case '4':
                case '5': case '6': case '7':
+                   if (shift == 1)
+                       yyerror("Illegal binary digit");
+                   /* FALL THROUGH */
+
+               case '0': case '1':
                    b = *s++ & 15;              /* ASCII digit -> value of digit */
                    goto digit;
 
@@ -5547,9 +6031,11 @@ scan_num(char *start)
 
                  digit:
                    n = u << shift;     /* make room for the digit */
-                   if (!overflowed && (n >> shift) != u) {
+                   if (!overflowed && (n >> shift) != u
+                       && !(PL_hints & HINT_NEW_BINARY)) {
                        warn("Integer overflow in %s number",
-                            (shift == 4) ? "hex" : "octal");
+                            (shift == 4) ? "hex"
+                            : ((shift == 3) ? "octal" : "binary"));
                        overflowed = TRUE;
                    }
                    u = n | b;          /* add the digit to the end */
@@ -5563,6 +6049,8 @@ scan_num(char *start)
          out:
            sv = NEWSV(92,0);
            sv_setuv(sv, u);
+           if ( PL_hints & HINT_NEW_BINARY)
+               sv = new_constant(start, s - start, "binary", sv, Nullsv, NULL);
        }
        break;
 
@@ -5573,8 +6061,8 @@ scan_num(char *start)
     case '1': case '2': case '3': case '4': case '5':
     case '6': case '7': case '8': case '9': case '.':
       decimal:
-       d = tokenbuf;
-       e = tokenbuf + sizeof tokenbuf - 6; /* room for various punctuation */
+       d = PL_tokenbuf;
+       e = PL_tokenbuf + sizeof PL_tokenbuf - 6; /* room for various punctuation */
        floatit = FALSE;
 
        /* read next group of digits and _ and copy into d */
@@ -5583,8 +6071,9 @@ scan_num(char *start)
               if -w is on
            */
            if (*s == '_') {
-               if (dowarn && lastub && s - lastub != 3)
-                   warn("Misplaced _ in number");
+               dTHR;                   /* only for ckWARN */
+               if (ckWARN(WARN_SYNTAX) && lastub && s - lastub != 3)
+                   warner(WARN_SYNTAX, "Misplaced _ in number");
                lastub = ++s;
            }
            else {
@@ -5597,8 +6086,11 @@ scan_num(char *start)
        }
 
        /* final misplaced underbar check */
-       if (dowarn && lastub && s - lastub != 3)
-           warn("Misplaced _ in number");
+       if (lastub && s - lastub != 3) {
+           dTHR;
+           if (ckWARN(WARN_SYNTAX))
+               warner(WARN_SYNTAX, "Misplaced _ in number");
+       }
 
        /* read a decimal portion if there is one.  avoid
           3..5 being interpreted as the number 3. followed
@@ -5647,7 +6139,7 @@ scan_num(char *start)
        sv = NEWSV(92,0);
        /* reset numeric locale in case we were earlier left in Swaziland */
        SET_NUMERIC_STANDARD();
-       value = atof(tokenbuf);
+       value = atof(PL_tokenbuf);
 
        /* 
           See if we can make do with an integer value without loss of
@@ -5664,6 +6156,9 @@ scan_num(char *start)
            sv_setiv(sv, tryiv);
        else
            sv_setnv(sv, value);
+       if ( floatit ? (PL_hints & HINT_NEW_FLOAT) : (PL_hints & HINT_NEW_INTEGER) )
+           sv = new_constant(PL_tokenbuf, d - PL_tokenbuf, 
+                             (floatit ? "float" : "integer"), sv, Nullsv, NULL);
        break;
     }
 
@@ -5674,7 +6169,7 @@ scan_num(char *start)
     return s;
 }
 
-static char *
+STATIC char *
 scan_formline(register char *s)
 {
     dTHR;
@@ -5686,17 +6181,21 @@ scan_formline(register char *s)
     while (!needargs) {
        if (*s == '.' || *s == '}') {
            /*SUPPRESS 530*/
-           for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
-           if (*t == '\n')
+#ifdef PERL_STRICT_CR
+           for (t = s+1;*t == ' ' || *t == '\t'; t++) ;
+#else
+           for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+#endif
+           if (*t == '\n' || t == PL_bufend)
                break;
        }
-       if (in_eval && !rsfp) {
+       if (PL_in_eval && !PL_rsfp) {
            eol = strchr(s,'\n');
            if (!eol++)
-               eol = bufend;
+               eol = PL_bufend;
        }
        else
-           eol = bufend = SvPVX(linestr) + SvCUR(linestr);
+           eol = PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
        if (*s != '#') {
            for (t = s; t < eol; t++) {
                if (*t == '~' && t[1] == '~' && SvCUR(stuff)) {
@@ -5709,12 +6208,12 @@ scan_formline(register char *s)
            sv_catpvn(stuff, s, eol-s);
        }
        s = eol;
-       if (rsfp) {
-           s = filter_gets(linestr, rsfp, 0);
-           oldoldbufptr = oldbufptr = bufptr = linestart = SvPVX(linestr);
-           bufend = bufptr + SvCUR(linestr);
+       if (PL_rsfp) {
+           s = filter_gets(PL_linestr, PL_rsfp, 0);
+           PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = SvPVX(PL_linestr);
+           PL_bufend = PL_bufptr + SvCUR(PL_linestr);
            if (!s) {
-               s = bufptr;
+               s = PL_bufptr;
                yyerror("Format not terminated");
                break;
            }
@@ -5723,33 +6222,33 @@ scan_formline(register char *s)
     }
   enough:
     if (SvCUR(stuff)) {
-       expect = XTERM;
+       PL_expect = XTERM;
        if (needargs) {
-           lex_state = LEX_NORMAL;
-           nextval[nexttoke].ival = 0;
+           PL_lex_state = LEX_NORMAL;
+           PL_nextval[PL_nexttoke].ival = 0;
            force_next(',');
        }
        else
-           lex_state = LEX_FORMLINE;
-       nextval[nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, stuff);
+           PL_lex_state = LEX_FORMLINE;
+       PL_nextval[PL_nexttoke].opval = (OP*)newSVOP(OP_CONST, 0, stuff);
        force_next(THING);
-       nextval[nexttoke].ival = OP_FORMLINE;
+       PL_nextval[PL_nexttoke].ival = OP_FORMLINE;
        force_next(LSTOP);
     }
     else {
        SvREFCNT_dec(stuff);
-       lex_formbrack = 0;
-       bufptr = s;
+       PL_lex_formbrack = 0;
+       PL_bufptr = s;
     }
     return s;
 }
 
-static void
+STATIC void
 set_csh(void)
 {
 #ifdef CSH
-    if (!cshlen)
-       cshlen = strlen(cshname);
+    if (!PL_cshlen)
+       PL_cshlen = strlen(PL_cshname);
 #endif
 }
 
@@ -5757,57 +6256,54 @@ I32
 start_subparse(I32 is_format, U32 flags)
 {
     dTHR;
-    I32 oldsavestack_ix = savestack_ix;
-    CV* outsidecv = compcv;
+    I32 oldsavestack_ix = PL_savestack_ix;
+    CV* outsidecv = PL_compcv;
     AV* comppadlist;
 
-    if (compcv) {
-       assert(SvTYPE(compcv) == SVt_PVCV);
+    if (PL_compcv) {
+       assert(SvTYPE(PL_compcv) == SVt_PVCV);
     }
-    save_I32(&subline);
-    save_item(subname);
-    SAVEI32(padix);
-    SAVESPTR(curpad);
-    SAVESPTR(comppad);
-    SAVESPTR(comppad_name);
-    SAVESPTR(compcv);
-    SAVEI32(comppad_name_fill);
-    SAVEI32(min_intro_pending);
-    SAVEI32(max_intro_pending);
-    SAVEI32(pad_reset_pending);
-
-    compcv = (CV*)NEWSV(1104,0);
-    sv_upgrade((SV *)compcv, is_format ? SVt_PVFM : SVt_PVCV);
-    CvFLAGS(compcv) |= flags;
-
-    comppad = newAV();
-    av_push(comppad, Nullsv);
-    curpad = AvARRAY(comppad);
-    comppad_name = newAV();
-    comppad_name_fill = 0;
-    min_intro_pending = 0;
-    padix = 0;
-    subline = curcop->cop_line;
+    save_I32(&PL_subline);
+    save_item(PL_subname);
+    SAVEI32(PL_padix);
+    SAVESPTR(PL_curpad);
+    SAVESPTR(PL_comppad);
+    SAVESPTR(PL_comppad_name);
+    SAVESPTR(PL_compcv);
+    SAVEI32(PL_comppad_name_fill);
+    SAVEI32(PL_min_intro_pending);
+    SAVEI32(PL_max_intro_pending);
+    SAVEI32(PL_pad_reset_pending);
+
+    PL_compcv = (CV*)NEWSV(1104,0);
+    sv_upgrade((SV *)PL_compcv, is_format ? SVt_PVFM : SVt_PVCV);
+    CvFLAGS(PL_compcv) |= flags;
+
+    PL_comppad = newAV();
+    av_push(PL_comppad, Nullsv);
+    PL_curpad = AvARRAY(PL_comppad);
+    PL_comppad_name = newAV();
+    PL_comppad_name_fill = 0;
+    PL_min_intro_pending = 0;
+    PL_padix = 0;
+    PL_subline = PL_curcop->cop_line;
 #ifdef USE_THREADS
-    av_store(comppad_name, 0, newSVpv("@_", 2));
-    curpad[0] = (SV*)newAV();
-    SvPADMY_on(curpad[0]);     /* XXX Needed? */
-    CvOWNER(compcv) = 0;
-    New(666, CvMUTEXP(compcv), 1, perl_mutex);
-    MUTEX_INIT(CvMUTEXP(compcv));
+    av_store(PL_comppad_name, 0, newSVpv("@_", 2));
+    PL_curpad[0] = (SV*)newAV();
+    SvPADMY_on(PL_curpad[0]);  /* XXX Needed? */
 #endif /* USE_THREADS */
 
     comppadlist = newAV();
     AvREAL_off(comppadlist);
-    av_store(comppadlist, 0, (SV*)comppad_name);
-    av_store(comppadlist, 1, (SV*)comppad);
+    av_store(comppadlist, 0, (SV*)PL_comppad_name);
+    av_store(comppadlist, 1, (SV*)PL_comppad);
 
-    CvPADLIST(compcv) = comppadlist;
-    CvOUTSIDE(compcv) = (CV*)SvREFCNT_inc(outsidecv);
+    CvPADLIST(PL_compcv) = comppadlist;
+    CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc(outsidecv);
 #ifdef USE_THREADS
-    CvOWNER(compcv) = 0;
-    New(666, CvMUTEXP(compcv), 1, perl_mutex);
-    MUTEX_INIT(CvMUTEXP(compcv));
+    CvOWNER(PL_compcv) = 0;
+    New(666, CvMUTEXP(PL_compcv), 1, perl_mutex);
+    MUTEX_INIT(CvMUTEXP(PL_compcv));
 #endif /* USE_THREADS */
 
     return oldsavestack_ix;
@@ -5817,10 +6313,10 @@ int
 yywarn(char *s)
 {
     dTHR;
-    --error_count;
-    in_eval |= 2;
+    --PL_error_count;
+    PL_in_eval |= 2;
     yyerror(s);
-    in_eval &= ~2;
+    PL_in_eval &= ~2;
     return 0;
 }
 
@@ -5833,29 +6329,29 @@ yyerror(char *s)
     int contlen = -1;
     SV *msg;
 
-    if (!yychar || (yychar == ';' && !rsfp))
+    if (!yychar || (yychar == ';' && !PL_rsfp))
        where = "at EOF";
-    else if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
-      oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
-       while (isSPACE(*oldoldbufptr))
-           oldoldbufptr++;
-       context = oldoldbufptr;
-       contlen = bufptr - oldoldbufptr;
+    else if (PL_bufptr > PL_oldoldbufptr && PL_bufptr - PL_oldoldbufptr < 200 &&
+      PL_oldoldbufptr != PL_oldbufptr && PL_oldbufptr != PL_bufptr) {
+       while (isSPACE(*PL_oldoldbufptr))
+           PL_oldoldbufptr++;
+       context = PL_oldoldbufptr;
+       contlen = PL_bufptr - PL_oldoldbufptr;
     }
-    else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
-      oldbufptr != bufptr) {
-       while (isSPACE(*oldbufptr))
-           oldbufptr++;
-       context = oldbufptr;
-       contlen = bufptr - oldbufptr;
+    else if (PL_bufptr > PL_oldbufptr && PL_bufptr - PL_oldbufptr < 200 &&
+      PL_oldbufptr != PL_bufptr) {
+       while (isSPACE(*PL_oldbufptr))
+           PL_oldbufptr++;
+       context = PL_oldbufptr;
+       contlen = PL_bufptr - PL_oldbufptr;
     }
     else if (yychar > 255)
        where = "next token ???";
     else if ((yychar & 127) == 127) {
-       if (lex_state == LEX_NORMAL ||
-          (lex_state == LEX_KNOWNEXT && lex_defer == LEX_NORMAL))
+       if (PL_lex_state == LEX_NORMAL ||
+          (PL_lex_state == LEX_KNOWNEXT && PL_lex_defer == LEX_NORMAL))
            where = "at end of line";
-       else if (lex_inpat)
+       else if (PL_lex_inpat)
            where = "within pattern";
        else
            where = "within string";
@@ -5872,27 +6368,27 @@ yyerror(char *s)
     }
     msg = sv_2mortal(newSVpv(s, 0));
     sv_catpvf(msg, " at %_ line %ld, ",
-             GvSV(curcop->cop_filegv), (long)curcop->cop_line);
+             GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
     if (context)
        sv_catpvf(msg, "near \"%.*s\"\n", contlen, context);
     else
        sv_catpvf(msg, "%s\n", where);
-    if (multi_start < multi_end && (U32)(curcop->cop_line - multi_end) <= 1) {
+    if (PL_multi_start < PL_multi_end && (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) {
        sv_catpvf(msg,
        "  (Might be a runaway multi-line %c%c string starting on line %ld)\n",
-               (int)multi_open,(int)multi_close,(long)multi_start);
-        multi_end = 0;
+               (int)PL_multi_open,(int)PL_multi_close,(long)PL_multi_start);
+        PL_multi_end = 0;
     }
-    if (in_eval & 2)
+    if (PL_in_eval & 2)
        warn("%_", msg);
-    else if (in_eval)
+    else if (PL_in_eval)
        sv_catsv(ERRSV, msg);
     else
        PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
-    if (++error_count >= 10)
-       croak("%_ has too many errors.\n", GvSV(curcop->cop_filegv));
-    in_my = 0;
-    in_my_stash = Nullhv;
+    if (++PL_error_count >= 10)
+       croak("%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv));
+    PL_in_my = 0;
+    PL_in_my_stash = Nullhv;
     return 0;
 }