cygwin support tweaks (from Eric Fifer <EFifer@sanwaint.com>)
[p5sagit/p5-mst-13.2.git] / toke.c
diff --git a/toke.c b/toke.c
index 69e2873..f35a042 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -28,8 +28,9 @@
 static char ident_too_long[] = "Identifier too long";
 
 static void restore_rsfp(pTHXo_ void *f);
-static void restore_expect(pTHXo_ void *e);
-static void restore_lex_expect(pTHXo_ void *e);
+
+#define XFAKEBRACK 128
+#define XENUMMASK 127
 
 #define UTF (PL_hints & HINT_UTF8)
 /*
@@ -49,13 +50,6 @@ static void restore_lex_expect(pTHXo_ void *e);
  * 1999-02-27 mjd-perl-patch@plover.com */
 #define isCONTROLVAR(x) (isUPPER(x) || strchr("[\\]^_?", (x)))
 
-/* On MacOS, respect nonbreaking spaces */
-#ifdef MACOS_TRADITIONAL
-#define SPACE_OR_TAB(c) ((c)==' '||(c)=='\312'||(c)=='\t')
-#else
-#define SPACE_OR_TAB(c) ((c)==' '||(c)=='\t')
-#endif
-
 /* LEX_* are values for PL_lex_state, the state of the lexer.
  * They are arranged oddly so that the guard on the switch statement
  * can get by with a single comparison (if the compiler is smart enough).
@@ -111,7 +105,7 @@ int* yychar_pointer = NULL;
 #ifdef CLINE
 #undef CLINE
 #endif
-#define CLINE (PL_copline = (PL_curcop->cop_line < PL_copline ? PL_curcop->cop_line : PL_copline))
+#define CLINE (PL_copline = (CopLINE(PL_curcop) < PL_copline ? CopLINE(PL_curcop) : PL_copline))
 
 /*
  * Convenience functions to return different tokens and prime the
@@ -310,15 +304,36 @@ S_depcom(pTHX)
  * utf16-to-utf8-reversed.
  */
 
-#ifdef WIN32
+#ifdef PERL_CR_FILTER
+static void
+strip_return(SV *sv)
+{
+    register char *s = SvPVX(sv);
+    register char *e = s + SvCUR(sv);
+    /* outer loop optimized to do nothing if there are no CR-LFs */
+    while (s < e) {
+       if (*s++ == '\r' && *s == '\n') {
+           /* hit a CR-LF, need to copy the rest */
+           register char *d = s - 1;
+           *d++ = *s++;
+           while (s < e) {
+               if (*s == '\r' && s[1] == '\n')
+                   s++;
+               *d++ = *s++;
+           }
+           SvCUR(sv) -= s - d;
+           return;
+       }
+    }
+}
 
 STATIC I32
-S_win32_textfilter(pTHX_ int idx, SV *sv, int maxlen)
+S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
- I32 count = FILTER_READ(idx+1, sv, maxlen);
- if (count > 0 && !maxlen)
-  win32_strip_return(sv);
- return count;
+    I32 count = FILTER_READ(idx+1, sv, maxlen);
+    if (count > 0 && !maxlen)
+       strip_return(sv);
+    return count;
 }
 #endif
 
@@ -367,13 +382,12 @@ Perl_lex_start(pTHX_ SV *line)
 
     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);
+    SAVEVPTR(PL_lex_inpat);
     SAVEI32(PL_lex_inwhat);
-    SAVEI16(PL_curcop->cop_line);
+    SAVECOPLINE(PL_curcop);
     SAVEPPTR(PL_bufptr);
     SAVEPPTR(PL_bufend);
     SAVEPPTR(PL_oldbufptr);
@@ -387,14 +401,13 @@ Perl_lex_start(pTHX_ SV *line)
     SAVEI32(PL_lex_defer);
     SAVEI32(PL_sublex_info.sub_inwhat);
     SAVESPTR(PL_lex_repl);
-    SAVEDESTRUCTOR_X(restore_expect, PL_tokenbuf + PL_expect); /* encode as pointer */
-    SAVEDESTRUCTOR_X(restore_lex_expect, PL_tokenbuf + PL_expect);
+    SAVEINT(PL_expect);
+    SAVEINT(PL_lex_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);
@@ -441,7 +454,7 @@ Perl_lex_end(pTHX)
  * S_incline
  * This subroutine has nothing to do with tilting, whether at windmills
  * or pinball tables.  Its name is short for "increment line".  It
- * increments the current line number in PL_curcop->cop_line and checks
+ * increments the current line number in CopLINE(PL_curcop) and checks
  * to see whether the line starts with a comment of the form
  *    # line 500 "foo.pm"
  * If so, it sets the current line number and file to the values in the comment.
@@ -456,11 +469,10 @@ S_incline(pTHX_ char *s)
     char ch;
     int sawline = 0;
 
-    PERL_ASYNC_CHECK();
-    PL_curcop->cop_line++;
+    CopLINE_inc(PL_curcop);
     if (*s++ != '#')
        return;
-    while (SPACE_OR_TAB(*s)) s++;
+    while (*s == ' ' || *s == '\t') s++;
     if (strnEQ(s, "line ", 5)) {
        s += 5;
        sawline = 1;
@@ -470,7 +482,7 @@ S_incline(pTHX_ char *s)
     n = s;
     while (isDIGIT(*s))
        s++;
-    while (SPACE_OR_TAB(*s))
+    while (*s == ' ' || *s == '\t')
        s++;
     if (*s == '"' && (t = strchr(s+1, '"')))
        s++;
@@ -482,11 +494,11 @@ S_incline(pTHX_ char *s)
     ch = *t;
     *t = '\0';
     if (t - s > 0)
-       PL_curcop->cop_filegv = gv_fetchfile(s);
+       CopFILE_set(PL_curcop, s);
     else
-       PL_curcop->cop_filegv = gv_fetchfile(PL_origfilename);
+       CopFILE_set(PL_curcop, PL_origfilename);
     *t = ch;
-    PL_curcop->cop_line = atoi(n)-1;
+    CopLINE_set(PL_curcop, atoi(n)-1);
 }
 
 /*
@@ -500,7 +512,7 @@ S_skipspace(pTHX_ register char *s)
 {
     dTHR;
     if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
-       while (s < PL_bufend && SPACE_OR_TAB(*s))
+       while (s < PL_bufend && (*s == ' ' || *s == '\t'))
            s++;
        return s;
     }
@@ -598,7 +610,7 @@ S_skipspace(pTHX_ register char *s)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setpvn(sv,PL_bufptr,PL_bufend-PL_bufptr);
-           av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+           av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
        }
     }
 }
@@ -681,7 +693,7 @@ S_uni(pTHX_ I32 f, char *s)
  */
 
 STATIC I32
-S_lop(pTHX_ I32 f, expectation x, char *s)
+S_lop(pTHX_ I32 f, int x, char *s)
 {
     dTHR;
     yylval.ival = f;
@@ -812,13 +824,12 @@ S_force_version(pTHX_ char *s)
 
     s = skipspace(s);
 
-    /* default VERSION number -- GBARR */
-
-    if(isDIGIT(*s)) {
-        char *d;
-        int c;
-        for( d=s, c = 1; isDIGIT(*d) || *d == '_' || (*d == '.' && c--); d++);
-        if((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') {
+    if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
+        char *d = s;
+       if (*d == 'v')
+           d++;
+        for (; isDIGIT(*d) || *d == '_' || *d == '.'; d++);
+        if ((*d == ';' || isSPACE(*d)) && *(skipspace(d)) != ',') {
             s = scan_num(s);
             /* real VERSION number -- GBARR */
             version = yylval.opval;
@@ -971,13 +982,12 @@ S_sublex_push(pTHX)
     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);
+    SAVEVPTR(PL_lex_inpat);
     SAVEI32(PL_lex_inwhat);
-    SAVEI16(PL_curcop->cop_line);
+    SAVECOPLINE(PL_curcop);
     SAVEPPTR(PL_bufptr);
     SAVEPPTR(PL_oldbufptr);
     SAVEPPTR(PL_oldoldbufptr);
@@ -996,7 +1006,6 @@ S_sublex_push(pTHX)
 
     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);
@@ -1005,7 +1014,7 @@ S_sublex_push(pTHX)
     *PL_lex_casestack = '\0';
     PL_lex_starts = 0;
     PL_lex_state = LEX_INTERPCONCAT;
-    PL_curcop->cop_line = PL_multi_start;
+    CopLINE_set(PL_curcop, 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)
@@ -1044,7 +1053,6 @@ S_sublex_done(pTHX)
        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;
@@ -1772,7 +1780,8 @@ S_incl_perldb(pTHX)
  * store private buffers and state information.
  *
  * The supplied datasv parameter is upgraded to a PVIO type
- * and the IoDIRP field is used to store the function pointer.
+ * and the IoDIRP field is used to store the function pointer,
+ * and IOf_FAKE_DIRP is enabled on datasv to mark this as such.
  * Note that IoTOP_NAME, IoFMT_NAME, IoBOTTOM_NAME, if set for
  * private use must be set using malloc'd pointers.
  */
@@ -1790,6 +1799,7 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
     if (!SvUPGRADE(datasv, SVt_PVIO))
         Perl_die(aTHX_ "Can't upgrade filter_add data to SVt_PVIO");
     IoDIRP(datasv) = (DIR*)funcp; /* stash funcp into spare field */
+    IoFLAGS(datasv) |= IOf_FAKE_DIRP;
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_add func %p (%s)\n",
                          funcp, SvPV_nolen(datasv)));
     av_unshift(PL_rsfp_filters, 1);
@@ -1802,12 +1812,15 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
 void
 Perl_filter_del(pTHX_ filter_t funcp)
 {
+    SV *datasv;
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_del func %p", funcp));
     if (!PL_rsfp_filters || AvFILLp(PL_rsfp_filters)<0)
        return;
     /* if filter is on top of stack (usual case) just pop it off */
-    if (IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) == (DIR*)funcp){
-       IoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL;
+    datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters));
+    if (IoDIRP(datasv) == (DIR*)funcp) {
+       IoFLAGS(datasv) &= ~IOf_FAKE_DIRP;
+       IoDIRP(datasv) = (DIR*)NULL;
        sv_free(av_pop(PL_rsfp_filters));
 
         return;
@@ -1880,9 +1893,9 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
 STATIC char *
 S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
 {
-#ifdef WIN32FILTER
+#ifdef PERL_CR_FILTER
     if (!PL_rsfp_filters) {
-       filter_add(win32_textfilter,NULL);
+       filter_add(S_cr_textfilter,NULL);
     }
 #endif
     if (PL_rsfp_filters) {
@@ -2338,7 +2351,7 @@ Perl_yylex(pTHX)
 
                sv_upgrade(sv, SVt_PVMG);
                sv_setsv(sv,PL_linestr);
-               av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+               av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
            }
            goto retry;
        }
@@ -2387,10 +2400,10 @@ Perl_yylex(pTHX)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
-           av_store(GvAV(PL_curcop->cop_filegv),(I32)PL_curcop->cop_line,sv);
+           av_store(CopFILEAV(PL_curcop),(I32)CopLINE(PL_curcop),sv);
        }
        PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
-       if (PL_curcop->cop_line == 1) {
+       if (CopLINE(PL_curcop) == 1) {
            while (s < PL_bufend && isSPACE(*s))
                s++;
            if (*s == ':' && s[1] != ':') /* for csh execing sh scripts */
@@ -2428,7 +2441,7 @@ Perl_yylex(pTHX)
                     */
                    SV *x = GvSV(gv_fetchpv("\030", TRUE, SVt_PV));
                    assert(SvPOK(x) || SvGMAGICAL(x));
-                   if (sv_eq(x, GvSV(PL_curcop->cop_filegv))) {
+                   if (sv_eq(x, CopFILESV(PL_curcop))) {
                        sv_setpvn(x, ipath, ipathend - ipath);
                        SvSETMAGIC(x);
                    }
@@ -2478,7 +2491,6 @@ Perl_yylex(pTHX)
                        *s = '#';       /* Don't try to parse shebang line */
                }
 #endif /* ALTERNATE_SHEBANG */
-#ifndef MACOS_TRADITIONAL
                if (!d &&
                    *s == '#' &&
                    ipathend > ipath &&
@@ -2506,14 +2518,13 @@ Perl_yylex(pTHX)
                    PerlProc_execv(ipath, newargv);
                    Perl_croak(aTHX_ "Can't exec %s", ipath);
                }
-#endif
                if (d) {
                    U32 oldpdb = PL_perldb;
                    bool oldn = PL_minus_n;
                    bool oldp = PL_minus_p;
 
                    while (*d && !isSPACE(*d)) d++;
-                   while (SPACE_OR_TAB(*d)) d++;
+                   while (*d == ' ' || *d == '\t') d++;
 
                    if (*d++ == '-') {
                        do {
@@ -2555,9 +2566,6 @@ Perl_yylex(pTHX)
       "(Maybe you didn't strip carriage returns after a network transfer?)\n");
 #endif
     case ' ': case '\t': case '\f': case 013:
-#ifdef MACOS_TRADITIONAL
-    case '\312': /* Them nonbreaking spaces again */
-#endif
        s++;
        goto retry;
     case '#':
@@ -2586,7 +2594,7 @@ Perl_yylex(pTHX)
            PL_bufptr = s;
            tmp = *s++;
 
-           while (s < PL_bufend && SPACE_OR_TAB(*s))
+           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
                s++;
 
            if (strnEQ(s,"=>",2)) {
@@ -2807,8 +2815,8 @@ Perl_yylex(pTHX)
            PL_expect = XTERM;
        TOKEN('(');
     case ';':
-       if (PL_curcop->cop_line < PL_copline)
-           PL_copline = PL_curcop->cop_line;
+       if (CopLINE(PL_curcop) < PL_copline)
+           PL_copline = CopLINE(PL_curcop);
        tmp = *s++;
        OPERATOR(tmp);
     case ')':
@@ -2852,20 +2860,20 @@ Perl_yylex(pTHX)
                PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
            OPERATOR(HASHBRACK);
        case XOPERATOR:
-           while (s < PL_bufend && SPACE_OR_TAB(*s))
+           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
                s++;
            d = s;
            PL_tokenbuf[0] = '\0';
            if (d < PL_bufend && *d == '-') {
                PL_tokenbuf[0] = '-';
                d++;
-               while (d < PL_bufend && SPACE_OR_TAB(*d))
+               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
                    d++;
            }
            if (d < PL_bufend && isIDFIRST_lazy(d)) {
                d = scan_word(d, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1,
                              FALSE, &len);
-               while (d < PL_bufend && SPACE_OR_TAB(*d))
+               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
                    d++;
                if (*d == '}') {
                    char minus = (PL_tokenbuf[0] == '-');
@@ -2921,7 +2929,8 @@ Perl_yylex(pTHX)
                    if (++t < PL_bufend
                        && (!isALNUM(*t)
                            || ((*t == 'q' || *t == 'x') && ++t < PL_bufend
-                               && !isALNUM(*t)))) {
+                               && !isALNUM(*t))))
+                   {
                        char *tmps;
                        char open, close, term;
                        I32 brackets = 1;
@@ -2952,8 +2961,10 @@ Perl_yylex(pTHX)
                    }
                    t++;
                }
-               else if (isIDFIRST_lazy(s)) {
-                   for (t++; t < PL_bufend && isALNUM_lazy(t); t++) ;
+               else if (isALNUM_lazy(t)) {
+                   t += UTF8SKIP(t);
+                   while (t < PL_bufend && isALNUM_lazy(t))
+                        t += UTF8SKIP(t);
                }
                while (t < PL_bufend && isSPACE(*t))
                    t++;
@@ -2971,7 +2982,7 @@ Perl_yylex(pTHX)
            }
            break;
        }
-       yylval.ival = PL_curcop->cop_line;
+       yylval.ival = CopLINE(PL_curcop);
        if (isSPACE(*s) || *s == '#')
            PL_copline = NOLINE;   /* invalidate current command line number */
        TOKEN('{');
@@ -2986,7 +2997,8 @@ Perl_yylex(pTHX)
            PL_lex_formbrack = 0;
        if (PL_lex_state == LEX_INTERPNORMAL) {
            if (PL_lex_brackets == 0) {
-               if (PL_lex_fakebrack) {
+               if (PL_expect & XFAKEBRACK) {
+                   PL_expect &= XENUMMASK;
                    PL_lex_state = LEX_INTERPEND;
                    PL_bufptr = s;
                    return yylex();     /* ignore fake brackets */
@@ -2997,9 +3009,9 @@ Perl_yylex(pTHX)
                    PL_lex_state = LEX_INTERPEND;
            }
        }
-       if (PL_lex_brackets < PL_lex_fakebrack) {
+       if (PL_expect & XFAKEBRACK) {
+           PL_expect &= XENUMMASK;
            PL_bufptr = s;
-           PL_lex_fakebrack = 0;
            return yylex();             /* ignore fake brackets */
        }
        force_next('}');
@@ -3012,9 +3024,9 @@ Perl_yylex(pTHX)
        s--;
        if (PL_expect == XOPERATOR) {
            if (ckWARN(WARN_SEMICOLON) && isIDFIRST_lazy(s) && PL_bufptr == PL_linestart) {
-               PL_curcop->cop_line--;
+               CopLINE_dec(PL_curcop);
                Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
-               PL_curcop->cop_line++;
+               CopLINE_inc(PL_curcop);
            }
            BAop(OP_BIT_AND);
        }
@@ -3076,9 +3088,9 @@ Perl_yylex(pTHX)
        if (PL_lex_brackets < PL_lex_formbrack) {
            char *t;
 #ifdef PERL_STRICT_CR
-           for (t = s; SPACE_OR_TAB(*t); t++) ;
+           for (t = s; *t == ' ' || *t == '\t'; t++) ;
 #else
-           for (t = s; SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
+           for (t = s; *t == ' ' || *t == '\t' || *t == '\r'; t++) ;
 #endif
            if (*t == '\n' || *t == '#') {
                s--;
@@ -3407,6 +3419,19 @@ Perl_yylex(pTHX)
            no_op("Backslash",s);
        OPERATOR(REFGEN);
 
+    case 'v':
+       if (isDIGIT(s[1]) && PL_expect == XTERM) {
+           char *start = s;
+           start++;
+           start++;
+           while (isDIGIT(*start))
+               start++;
+           if (*start == '.' && isDIGIT(start[1])) {
+               s = scan_num(s);
+               TERM(THING);
+           }
+       }
+       goto keylookup;
     case 'x':
        if (isDIGIT(s[1]) && PL_expect == XOPERATOR) {
            s++;
@@ -3436,7 +3461,7 @@ Perl_yylex(pTHX)
     case 's': case 'S':
     case 't': case 'T':
     case 'u': case 'U':
-    case 'v': case 'V':
+             case 'V':
     case 'w': case 'W':
              case 'X':
     case 'y': case 'Y':
@@ -3510,6 +3535,7 @@ Perl_yylex(pTHX)
            }
            else if (gv && !gvp
                     && -tmp==KEY_lock  /* XXX generalizable kludge */
+                    && GvCVu(gv)
                     && !hv_fetch(GvHVn(PL_incgv), "Thread.pm", 9, FALSE))
            {
                tmp = 0;                /* any sub overrides "weak" keyword */
@@ -3548,9 +3574,9 @@ Perl_yylex(pTHX)
 
                if (PL_expect == XOPERATOR) {
                    if (PL_bufptr == PL_linestart) {
-                       PL_curcop->cop_line--;
+                       CopLINE_dec(PL_curcop);
                        Perl_warner(aTHX_ WARN_SEMICOLON, PL_warn_nosemi);
-                       PL_curcop->cop_line++;
+                       CopLINE_inc(PL_curcop);
                    }
                    else
                        no_op("Bareword",s);
@@ -3638,7 +3664,7 @@ Perl_yylex(pTHX)
                if (*s == '(') {
                    CLINE;
                    if (gv && GvCVu(gv)) {
-                       for (d = s + 1; SPACE_OR_TAB(*d); d++) ;
+                       for (d = s + 1; *d == ' ' || *d == '\t'; d++) ;
                        if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) {
                            s = d + 1;
                            goto its_constant;
@@ -3737,12 +3763,12 @@ Perl_yylex(pTHX)
 
        case KEY___FILE__:
            yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                       newSVsv(GvSV(PL_curcop->cop_filegv)));
+                                       newSVpv(CopFILE(PL_curcop),0));
            TERM(THING);
 
        case KEY___LINE__:
             yylval.opval = (OP*)newSVOP(OP_CONST, 0,
-                                    Perl_newSVpvf(aTHX_ "%"IVdf, (IV)PL_curcop->cop_line));
+                                    Perl_newSVpvf(aTHX_ "%"IVdf, (IV)CopLINE(PL_curcop)));
            TERM(THING);
 
        case KEY___PACKAGE__:
@@ -3780,6 +3806,28 @@ Perl_yylex(pTHX)
                    IoTYPE(GvIOp(gv)) = '-';
                else
                    IoTYPE(GvIOp(gv)) = '<';
+#if defined(WIN32) && !defined(PERL_TEXTMODE_SCRIPTS)
+               /* if the script was opened in binmode, we need to revert
+                * it to text mode for compatibility; but only iff it has CRs
+                * XXX this is a questionable hack at best. */
+               if (PL_bufend-PL_bufptr > 2
+                   && PL_bufend[-1] == '\n' && PL_bufend[-2] == '\r')
+               {
+                   Off_t loc = 0;
+                   if (IoTYPE(GvIOp(gv)) == '<') {
+                       loc = PerlIO_tell(PL_rsfp);
+                       (void)PerlIO_seek(PL_rsfp, 0L, 0);
+                   }
+                   if (PerlLIO_setmode(PerlIO_fileno(PL_rsfp), O_TEXT) != -1) {
+#if defined(__BORLANDC__)
+                       /* XXX see note in do_binmode() */
+                       ((FILE*)PL_rsfp)->flags |= _F_BIN;
+#endif
+                       if (loc > 0)
+                           PerlIO_seek(PL_rsfp, loc, 0);
+                   }
+               }
+#endif
                PL_rsfp = Nullfp;
            }
            goto fake_eof;
@@ -3789,6 +3837,7 @@ Perl_yylex(pTHX)
        case KEY_DESTROY:
        case KEY_BEGIN:
        case KEY_END:
+       case KEY_STOP:
        case KEY_INIT:
            if (PL_expect == XSTATE) {
                s = PL_bufptr;
@@ -3920,7 +3969,7 @@ Perl_yylex(pTHX)
            PREBLOCK(ELSE);
 
        case KEY_elsif:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            OPERATOR(ELSIF);
 
        case KEY_eq:
@@ -3970,7 +4019,7 @@ Perl_yylex(pTHX)
 
        case KEY_for:
        case KEY_foreach:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            s = skipspace(s);
            if (PL_expect == XSTATE && isIDFIRST_lazy(s)) {
                char *p = s;
@@ -4108,7 +4157,7 @@ Perl_yylex(pTHX)
            UNI(OP_HEX);
 
        case KEY_if:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            OPERATOR(IF);
 
        case KEY_index:
@@ -4368,12 +4417,18 @@ Perl_yylex(pTHX)
            OLDLOP(OP_RETURN);
 
        case KEY_require:
-           *PL_tokenbuf = '\0';
-           s = force_word(s,WORD,TRUE,TRUE,FALSE);
-           if (isIDFIRST_lazy(PL_tokenbuf))
-               gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE);
-           else if (*s == '<')
-               yyerror("<> should be quotes");
+           s = skipspace(s);
+           if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
+               s = force_version(s);
+           }
+           else {
+               *PL_tokenbuf = '\0';
+               s = force_word(s,WORD,TRUE,TRUE,FALSE);
+               if (isIDFIRST_lazy(PL_tokenbuf))
+                   gv_stashpvn(PL_tokenbuf, strlen(PL_tokenbuf), TRUE);
+               else if (*s == '<')
+                   yyerror("<> should be quotes");
+           }
            UNI(OP_REQUIRE);
 
        case KEY_reset:
@@ -4700,11 +4755,11 @@ Perl_yylex(pTHX)
            UNI(OP_UNTIE);
 
        case KEY_until:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            OPERATOR(UNTIL);
 
        case KEY_unless:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            OPERATOR(UNLESS);
 
        case KEY_unlink:
@@ -4735,9 +4790,9 @@ Perl_yylex(pTHX)
            if (PL_expect != XSTATE)
                yyerror("\"use\" not allowed in expression");
            s = skipspace(s);
-           if(isDIGIT(*s)) {
+           if (isDIGIT(*s) || (*s == 'v' && isDIGIT(s[1]))) {
                s = force_version(s);
-               if(*s == ';' || (s = skipspace(s), *s == ';')) {
+               if (*s == ';' || (s = skipspace(s), *s == ';')) {
                    PL_nextval[PL_nexttoke].opval = Nullop;
                    force_next(WORD);
                }
@@ -4756,7 +4811,7 @@ Perl_yylex(pTHX)
            LOP(OP_VEC,XTERM);
 
        case KEY_while:
-           yylval.ival = PL_curcop->cop_line;
+           yylval.ival = CopLINE(PL_curcop);
            OPERATOR(WHILE);
 
        case KEY_warn:
@@ -5227,6 +5282,9 @@ Perl_keyword(pTHX_ register char *d, I32 len)
            break;
        }
        break;
+    case 'S':
+       if (strEQ(d,"STOP"))                    return KEY_STOP;
+       break;
     case 's':
        switch (d[1]) {
        case 0:                                 return KEY_s;
@@ -5608,8 +5666,6 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
     char *bracket = 0;
     char funny = *s++;
 
-    if (PL_lex_brackets == 0)
-       PL_lex_fakebrack = 0;
     if (isSPACE(*s))
        s = skipspace(s);
     d = dest;
@@ -5679,7 +5735,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
        if (isSPACE(s[-1])) {
            while (s < send) {
                char ch = *s++;
-               if (!SPACE_OR_TAB(ch)) {
+               if (ch != ' ' && ch != '\t') {
                    *d = ch;
                    break;
                }
@@ -5705,7 +5761,7 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
                    Perl_croak(aTHX_ ident_too_long);
            }
            *d = '\0';
-           while (s < send && SPACE_OR_TAB(*s)) s++;
+           while (s < send && (*s == ' ' || *s == '\t')) s++;
            if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
@@ -5714,9 +5770,8 @@ S_scan_ident(pTHX_ register char *s, register char *send, char *dest, STRLEN des
                        "Ambiguous use of %c{%s%s} resolved to %c%s%s",
                        funny, dest, brack, funny, dest, brack);
                }
-               PL_lex_fakebrack = PL_lex_brackets+1;
                bracket++;
-               PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
+               PL_lex_brackstack[PL_lex_brackets++] = (char)(XOPERATOR | XFAKEBRACK);
                return s;
            }
        } 
@@ -5980,7 +6035,7 @@ S_scan_heredoc(pTHX_ register char *s)
     e = PL_tokenbuf + sizeof PL_tokenbuf - 1;
     if (!outer)
        *d++ = '\n';
-    for (peek = s; SPACE_OR_TAB(*peek); peek++) ;
+    for (peek = s; *peek == ' ' || *peek == '\t'; peek++) ;
     if (*peek && strchr("`'\"",*peek)) {
        s = peek;
        term = *s++;
@@ -6049,7 +6104,7 @@ S_scan_heredoc(pTHX_ register char *s)
     }
 
     CLINE;
-    PL_multi_start = PL_curcop->cop_line;
+    PL_multi_start = CopLINE(PL_curcop);
     PL_multi_open = PL_multi_close = '<';
     term = *PL_tokenbuf;
     if (PL_lex_inwhat == OP_SUBST && PL_in_eval && !PL_rsfp) {
@@ -6063,10 +6118,10 @@ S_scan_heredoc(pTHX_ register char *s)
        while (s < bufend &&
          (*s != term || memNE(s,PL_tokenbuf,len)) ) {
            if (*s++ == '\n')
-               PL_curcop->cop_line++;
+               CopLINE_inc(PL_curcop);
        }
        if (s >= bufend) {
-           PL_curcop->cop_line = PL_multi_start;
+           CopLINE_set(PL_curcop, PL_multi_start);
            missingterm(PL_tokenbuf);
        }
        sv_setpvn(herewas,bufptr,d-bufptr+1);
@@ -6083,15 +6138,15 @@ S_scan_heredoc(pTHX_ register char *s)
        while (s < PL_bufend &&
          (*s != term || memNE(s,PL_tokenbuf,len)) ) {
            if (*s++ == '\n')
-               PL_curcop->cop_line++;
+               CopLINE_inc(PL_curcop);
        }
        if (s >= PL_bufend) {
-           PL_curcop->cop_line = PL_multi_start;
+           CopLINE_set(PL_curcop, PL_multi_start);
            missingterm(PL_tokenbuf);
        }
        sv_setpvn(tmpstr,d+1,s-d);
        s += len - 1;
-       PL_curcop->cop_line++;  /* the preceding stmt passes a newline */
+       CopLINE_inc(PL_curcop); /* the preceding stmt passes a newline */
 
        sv_catpvn(herewas,s,PL_bufend-s);
        sv_setsv(PL_linestr,herewas);
@@ -6103,10 +6158,10 @@ S_scan_heredoc(pTHX_ register char *s)
     while (s >= PL_bufend) {   /* multiple line string? */
        if (!outer ||
         !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
-           PL_curcop->cop_line = PL_multi_start;
+           CopLINE_set(PL_curcop, PL_multi_start);
            missingterm(PL_tokenbuf);
        }
-       PL_curcop->cop_line++;
+       CopLINE_inc(PL_curcop);
        PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
 #ifndef PERL_STRICT_CR
        if (PL_bufend - PL_linestart >= 2) {
@@ -6128,8 +6183,7 @@ S_scan_heredoc(pTHX_ register char *s)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
-           av_store(GvAV(PL_curcop->cop_filegv),
-             (I32)PL_curcop->cop_line,sv);
+           av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop),sv);
        }
        if (*s == term && memEQ(s,PL_tokenbuf,len)) {
            s = PL_bufend - 1;
@@ -6144,7 +6198,7 @@ S_scan_heredoc(pTHX_ register char *s)
     }
     s++;
 retval:
-    PL_multi_end = PL_curcop->cop_line;
+    PL_multi_end = CopLINE(PL_curcop);
     if (SvCUR(tmpstr) + 5 < SvLEN(tmpstr)) {
        SvLEN_set(tmpstr, SvCUR(tmpstr) + 1);
        Renew(SvPVX(tmpstr), SvLEN(tmpstr), char);
@@ -6335,7 +6389,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
     /* after skipping whitespace, the next character is the terminator */
     term = *s;
     /* mark where we are */
-    PL_multi_start = PL_curcop->cop_line;
+    PL_multi_start = CopLINE(PL_curcop);
     PL_multi_open = term;
 
     /* find corresponding closing delimiter */
@@ -6365,7 +6419,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
            for (; s < PL_bufend; s++,to++) {
                /* embedded newlines increment the current line number */
                if (*s == '\n' && !PL_rsfp)
-                   PL_curcop->cop_line++;
+                   CopLINE_inc(PL_curcop);
                /* handle quoted delimiters */
                if (*s == '\\' && s+1 < PL_bufend && term != '\\') {
                    if (!keep_quoted && s[1] == term)
@@ -6391,7 +6445,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
            for (; s < PL_bufend; s++,to++) {
                /* embedded newlines increment the line count */
                if (*s == '\n' && !PL_rsfp)
-                   PL_curcop->cop_line++;
+                   CopLINE_inc(PL_curcop);
                /* backslashes can escape the open or closing characters */
                if (*s == '\\' && s+1 < PL_bufend) {
                    if (!keep_quoted &&
@@ -6440,11 +6494,11 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
        if (!PL_rsfp ||
         !(PL_oldoldbufptr = PL_oldbufptr = s = PL_linestart = filter_gets(PL_linestr, PL_rsfp, 0))) {
            sv_free(sv);
-           PL_curcop->cop_line = PL_multi_start;
+           CopLINE_set(PL_curcop, PL_multi_start);
            return Nullch;
        }
        /* we read a line, so increment our line counter */
-       PL_curcop->cop_line++;
+       CopLINE_inc(PL_curcop);
 
        /* update debugger info */
        if (PERLDB_LINE && PL_curstash != PL_debstash) {
@@ -6452,8 +6506,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
 
            sv_upgrade(sv, SVt_PVMG);
            sv_setsv(sv,PL_linestr);
-           av_store(GvAV(PL_curcop->cop_filegv),
-             (I32)PL_curcop->cop_line, sv);
+           av_store(CopFILEAV(PL_curcop), (I32)CopLINE(PL_curcop), sv);
        }
 
        /* having changed the buffer, we must update PL_bufend */
@@ -6464,7 +6517,7 @@ S_scan_str(pTHX_ char *start, int keep_quoted, int keep_delims)
 
     if (keep_delims)
        sv_catpvn(sv, s, 1);
-    PL_multi_end = PL_curcop->cop_line;
+    PL_multi_end = CopLINE(PL_curcop);
     s++;
 
     /* if we allocated too much space, give some back */
@@ -6514,7 +6567,7 @@ Perl_scan_num(pTHX_ char *start)
     register char *e;                  /* end of temp buffer */
     IV tryiv;                          /* used to see if it can be an IV */
     NV value;                          /* number read, as a double */
-    SV *sv;                            /* place to put the converted number */
+    SV *sv = Nullsv;                   /* place to put the converted number */
     bool floatit;                      /* boolean: int or float? */
     char *lastub = 0;                  /* position of last underbar */
     static char number_too_long[] = "Number too long";
@@ -6526,8 +6579,7 @@ Perl_scan_num(pTHX_ char *start)
       Perl_croak(aTHX_ "panic: scan_num");
       
     /* if it starts with a 0, it could be an octal number, a decimal in
-       0.13 disguise, or a hexadecimal number, or a binary number.
-    */
+       0.13 disguise, or a hexadecimal number, or a binary number. */
     case '0':
        {
          /* variables:
@@ -6789,11 +6841,61 @@ Perl_scan_num(pTHX_ char *start)
                              (floatit ? "float" : "integer"),
                              sv, Nullsv, NULL);
        break;
+    /* if it starts with a v, it could be a version number */
+    case 'v':
+       {
+           char *pos = s;
+           pos++;
+           while (isDIGIT(*pos))
+               pos++;
+           if (*pos == '.' && isDIGIT(pos[1])) {
+               UV rev;
+               U8 tmpbuf[10];
+               U8 *tmpend;
+               NV nshift = 1.0;
+               s++;                            /* get past 'v' */
+
+               sv = NEWSV(92,5);
+               SvUPGRADE(sv, SVt_PVNV);
+               sv_setpvn(sv, "", 0);
+
+               do {
+                   rev = atoi(s);
+                   s = ++pos;
+                   while (isDIGIT(*pos))
+                       pos++;
+
+                   tmpend = uv_to_utf8(tmpbuf, rev);
+                   *tmpend = '\0';
+                   sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
+                   if (rev > 0)
+                       SvNVX(sv) += (NV)rev/nshift;
+                   nshift *= 1000;
+               } while (*pos == '.' && isDIGIT(pos[1]));
+
+               rev = atoi(s);
+               s = pos;
+               tmpend = uv_to_utf8(tmpbuf, rev);
+               *tmpend = '\0';
+               sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
+               if (rev > 0)
+                   SvNVX(sv) += (NV)rev/nshift;
+
+               SvPOK_on(sv);
+               SvNOK_on(sv);
+               SvREADONLY_on(sv);
+               SvUTF8_on(sv);
+           }
+       }
+       break;
     }
 
     /* make the op for the constant and return */
 
-    yylval.opval = newSVOP(OP_CONST, 0, sv);
+    if (sv)
+       yylval.opval = newSVOP(OP_CONST, 0, sv);
+    else
+       yylval.opval = Nullop;
 
     return s;
 }
@@ -6811,9 +6913,9 @@ S_scan_formline(pTHX_ register char *s)
        if (*s == '.' || *s == '}') {
            /*SUPPRESS 530*/
 #ifdef PERL_STRICT_CR
-           for (t = s+1;SPACE_OR_TAB(*t); t++) ;
+           for (t = s+1;*t == ' ' || *t == '\t'; t++) ;
 #else
-           for (t = s+1;SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
+           for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ;
 #endif
            if (*t == '\n' || t == PL_bufend)
                break;
@@ -6835,6 +6937,14 @@ S_scan_formline(pTHX_ register char *s)
                    needargs = TRUE;
            }
            sv_catpvn(stuff, s, eol-s);
+#ifndef PERL_STRICT_CR
+           if (eol-s > 1 && eol[-2] == '\r' && eol[-1] == '\n') {
+               char *end = SvPVX(stuff) + SvCUR(stuff);
+               end[-2] = '\n';
+               end[-1] = '\0';
+               SvCUR(stuff)--;
+           }
+#endif
        }
        s = eol;
        if (PL_rsfp) {
@@ -6892,10 +7002,10 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
     if (PL_compcv) {
        assert(SvTYPE(PL_compcv) == SVt_PVCV);
     }
-    save_I32(&PL_subline);
+    SAVEI32(PL_subline);
     save_item(PL_subname);
     SAVEI32(PL_padix);
-    SAVESPTR(PL_curpad);
+    SAVEVPTR(PL_curpad);
     SAVESPTR(PL_comppad);
     SAVESPTR(PL_comppad_name);
     SAVESPTR(PL_compcv);
@@ -6915,7 +7025,7 @@ Perl_start_subparse(pTHX_ I32 is_format, U32 flags)
     PL_comppad_name_fill = 0;
     PL_min_intro_pending = 0;
     PL_padix = 0;
-    PL_subline = PL_curcop->cop_line;
+    PL_subline = CopLINE(PL_curcop);
 #ifdef USE_THREADS
     av_store(PL_comppad_name, 0, newSVpvn("@_", 2));
     PL_curpad[0] = (SV*)newAV();
@@ -6995,16 +7105,15 @@ Perl_yyerror(pTHX_ char *s)
        where = SvPVX(where_sv);
     }
     msg = sv_2mortal(newSVpv(s, 0));
-    Perl_sv_catpvf(aTHX_ msg, " at %_ line %"IVdf", ",
-              GvSV(PL_curcop->cop_filegv), (IV)PL_curcop->cop_line);
+    Perl_sv_catpvf(aTHX_ msg, " at %s line %"IVdf", ",
+                  CopFILE(PL_curcop), (IV)CopLINE(PL_curcop));
     if (context)
        Perl_sv_catpvf(aTHX_ msg, "near \"%.*s\"\n", contlen, context);
     else
        Perl_sv_catpvf(aTHX_ msg, "%s\n", where);
-    if (PL_multi_start < PL_multi_end &&
-       (U32)(PL_curcop->cop_line - PL_multi_end) <= 1) {
+    if (PL_multi_start < PL_multi_end && (U32)(CopLINE(PL_curcop) - PL_multi_end) <= 1) {
         Perl_sv_catpvf(aTHX_ msg,
-        "   (Might be a runaway multi-line %c%c string starting on line %"IVdf")\n",
+        "  (Might be a runaway multi-line %c%c string starting on line %"IVdf")\n",
                 (int)PL_multi_open,(int)PL_multi_close,(IV)PL_multi_start);
         PL_multi_end = 0;
     }
@@ -7013,7 +7122,7 @@ Perl_yyerror(pTHX_ char *s)
     else
        qerror(msg);
     if (PL_error_count >= 10)
-       Perl_croak(aTHX_ "%_ has too many errors.\n", GvSV(PL_curcop->cop_filegv));
+       Perl_croak(aTHX_ "%s has too many errors.\n", CopFILE(PL_curcop));
     PL_in_my = 0;
     PL_in_my_stash = Nullhv;
     return 0;
@@ -7021,7 +7130,6 @@ Perl_yyerror(pTHX_ char *s)
 
 
 #ifdef PERL_OBJECT
-#define NO_XSLOCKS
 #include "XSUB.h"
 #endif
 
@@ -7041,29 +7149,3 @@ restore_rsfp(pTHXo_ void *f)
        PerlIO_close(PL_rsfp);
     PL_rsfp = fp;
 }
-
-/*
- * restore_expect
- * Restores the state of PL_expect when the lexing that begun with a
- * start_lex() call has ended.
- */ 
-
-static void
-restore_expect(pTHXo_ void *e)
-{
-    /* a safe way to store a small integer in a pointer */
-    PL_expect = (expectation)((char *)e - PL_tokenbuf);
-}
-
-/*
- * restore_lex_expect
- * Restores the state of PL_lex_expect when the lexing that begun with a
- * start_lex() call has ended.
- */ 
-
-static void
-restore_lex_expect(pTHXo_ void *e)
-{
-    /* a safe way to store a small integer in a pointer */
-    PL_lex_expect = (expectation)((char *)e - PL_tokenbuf);
-}