Re: [PATCH] support 'my __PACKAGE__ $obj = ...'
[p5sagit/p5-mst-13.2.git] / toke.c
diff --git a/toke.c b/toke.c
index 5c1b945..4a54f72 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -39,6 +39,13 @@ static void restore_rsfp(pTHXo_ void *f);
  * 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).
@@ -463,7 +470,7 @@ S_incline(pTHX_ char *s)
     CopLINE_inc(PL_curcop);
     if (*s++ != '#')
        return;
-    while (*s == ' ' || *s == '\t') s++;
+    while (SPACE_OR_TAB(*s)) s++;
     if (strnEQ(s, "line", 4))
        s += 4;
     else
@@ -472,13 +479,13 @@ S_incline(pTHX_ char *s)
        s++;
     else 
        return;
-    while (*s == ' ' || *s == '\t') s++;
+    while (SPACE_OR_TAB(*s)) s++;
     if (!isDIGIT(*s))
        return;
     n = s;
     while (isDIGIT(*s))
        s++;
-    while (*s == ' ' || *s == '\t')
+    while (SPACE_OR_TAB(*s))
        s++;
     if (*s == '"' && (t = strchr(s+1, '"'))) {
        s++;
@@ -488,15 +495,21 @@ S_incline(pTHX_ char *s)
        for (t = s; !isSPACE(*t); t++) ;
        e = t;
     }
-    while (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\f')
+    while (SPACE_OR_TAB(*e) || *e == '\r' || *e == '\f')
        e++;
     if (*e != '\n' && *e != '\0')
        return;         /* false alarm */
 
     ch = *t;
     *t = '\0';
-    if (t - s > 0)
+    if (t - s > 0) {
+#ifdef USE_ITHREADS
+       Safefree(CopFILE(PL_curcop));
+#else
+       SvREFCNT_dec(CopFILEGV(PL_curcop));
+#endif
        CopFILE_set(PL_curcop, s);
+    }
     *t = ch;
     CopLINE_set(PL_curcop, atoi(n)-1);
 }
@@ -512,7 +525,7 @@ S_skipspace(pTHX_ register char *s)
 {
     dTHR;
     if (PL_lex_formbrack && PL_lex_brackets <= PL_lex_formbrack) {
-       while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+       while (s < PL_bufend && SPACE_OR_TAB(*s))
            s++;
        return s;
     }
@@ -819,7 +832,7 @@ Perl_str_to_version(pTHX_ SV *sv)
     NV nshift = 1.0;
     STRLEN len;
     char *start = SvPVx(sv,len);
-    bool utf = SvUTF8(sv);
+    bool utf = SvUTF8(sv) ? TRUE : FALSE;
     char *end = start + len;
     while (start < end) {
        I32 skip;
@@ -896,7 +909,7 @@ S_tokeq(pTHX_ SV *sv)
        goto finish;
 
     s = SvPV_force(sv, len);
-    if (SvIVX(sv) == -1)
+    if (SvTYPE(sv) >= SVt_PVIV && SvIVX(sv) == -1)
        goto finish;
     send = s + len;
     while (s < send && *s != '\\')
@@ -974,6 +987,8 @@ S_sublex_start(pTHX)
 
            p = SvPV(sv, len);
            nsv = newSVpvn(p, len);
+            if (SvUTF8(sv))
+               SvUTF8_on(nsv);
            SvREFCNT_dec(sv);
            sv = nsv;
        } 
@@ -1377,7 +1392,7 @@ S_scan_const(pTHX_ char *start)
            default:
                {
                    dTHR;
-                   if (ckWARN(WARN_MISC) && isALPHA(*s))
+                   if (ckWARN(WARN_MISC) && isALNUM(*s) && *s != '_')
                        Perl_warner(aTHX_ WARN_MISC, 
                               "Unrecognized escape \\%c passed through",
                               *s);
@@ -1389,6 +1404,7 @@ S_scan_const(pTHX_ char *start)
            /* \132 indicates an octal constant */
            case '0': case '1': case '2': case '3':
            case '4': case '5': case '6': case '7':
+               len = 0;        /* disallow underscores */
                uv = (UV)scan_oct(s, 3, &len);
                s += len;
                goto NUM_ESCAPE_INSERT;
@@ -1402,10 +1418,12 @@ S_scan_const(pTHX_ char *start)
                        yyerror("Missing right brace on \\x{}");
                        e = s;
                    }
+                   len = 1;            /* allow underscores */
                     uv = (UV)scan_hex(s + 1, e - s - 1, &len);
                     s = e + 1;
                }
                else {
+                   len = 0;            /* disallow underscores */
                    uv = (UV)scan_hex(s, 2, &len);
                    s += len;
                }
@@ -1988,6 +2006,29 @@ S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
         return (sv_gets(sv, fp, append));
 }
 
+STATIC HV *S_find_in_my_stash(pTHX_ char *pkgname, I32 len)
+{
+    GV *gv;
+
+    if (*pkgname == '_' && strEQ(pkgname, "__PACKAGE__"))
+        return PL_curstash;
+
+    if (len > 2 &&
+        (pkgname[len - 2] == ':' && pkgname[len - 1] == ':') &&
+        (gv = gv_fetchpv(pkgname, FALSE, SVt_PVHV))) {
+        return GvHV(gv); /* Foo:: */
+    }
+
+    /* use constant CLASS => 'MyClass' */
+    if ((gv = gv_fetchpv(pkgname, FALSE, SVt_PVCV))) {
+        SV *sv;
+        if (GvCV(gv) && (sv = cv_const_sv(GvCV(gv)))) {
+            pkgname = SvPV_nolen(sv);
+        }
+    }
+
+    return gv_stashpv(pkgname, FALSE);
+}
 
 #ifdef DEBUGGING
     static char* exp_name[] =
@@ -2021,6 +2062,9 @@ S_filter_gets(pTHX_ register SV *sv, register PerlIO *fp, STRLEN append)
       if we already built the token before, use it.
 */
 
+#ifdef __SC__
+#pragma segment Perl_yylex
+#endif
 int
 #ifdef USE_PURE_BISON
 Perl_yylex(pTHX_ YYSTYPE *lvalp, int *lcharp)
@@ -2146,9 +2190,14 @@ Perl_yylex(pTHX)
        */
        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(Perl_form(aTHX_ "In string, %s now must be written as \\%s",
-                            PL_tokenbuf, PL_tokenbuf));
+           if ((!gv || ((PL_tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)))
+                && ckWARN(WARN_AMBIGUOUS))
+           {
+                /* Downgraded from fatal to warning 20000522 mjd */
+               Perl_warner(aTHX_ WARN_AMBIGUOUS,
+                           "Possible unintended interpolation of %s in string",
+                            PL_tokenbuf);
+           }
        }
 
        /* build ops for a bareword */
@@ -2576,6 +2625,7 @@ Perl_yylex(pTHX)
                        *s = '#';       /* Don't try to parse shebang line */
                }
 #endif /* ALTERNATE_SHEBANG */
+#ifndef MACOS_TRADITIONAL
                if (!d &&
                    *s == '#' &&
                    ipathend > ipath &&
@@ -2603,13 +2653,14 @@ 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 (*d == ' ' || *d == '\t') d++;
+                   while (SPACE_OR_TAB(*d)) d++;
 
                    if (*d++ == '-') {
                        do {
@@ -2651,11 +2702,19 @@ Perl_yylex(pTHX)
       "\t(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':
+#endif
        s++;
        goto retry;
     case '#':
     case '\n':
        if (PL_lex_state != LEX_NORMAL || (PL_in_eval && !PL_rsfp)) {
+           if (*s == '#' && s == PL_linestart && PL_in_eval && !PL_rsfp) {
+               /* handle eval qq[#line 1 "foo"\n ...] */
+               CopLINE_dec(PL_curcop);
+               incline(s);
+           }
            d = PL_bufend;
            while (s < d && *s != '\n')
                s++;
@@ -2679,7 +2738,7 @@ Perl_yylex(pTHX)
            PL_bufptr = s;
            tmp = *s++;
 
-           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+           while (s < PL_bufend && SPACE_OR_TAB(*s))
                s++;
 
            if (strnEQ(s,"=>",2)) {
@@ -2918,8 +2977,7 @@ Perl_yylex(pTHX)
            PL_expect = XTERM;
        TOKEN('(');
     case ';':
-       if (CopLINE(PL_curcop) < PL_copline)
-           PL_copline = CopLINE(PL_curcop);
+       CLINE;
        tmp = *s++;
        OPERATOR(tmp);
     case ')':
@@ -2963,20 +3021,20 @@ Perl_yylex(pTHX)
                PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
            OPERATOR(HASHBRACK);
        case XOPERATOR:
-           while (s < PL_bufend && (*s == ' ' || *s == '\t'))
+           while (s < PL_bufend && SPACE_OR_TAB(*s))
                s++;
            d = s;
            PL_tokenbuf[0] = '\0';
            if (d < PL_bufend && *d == '-') {
                PL_tokenbuf[0] = '-';
                d++;
-               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
+               while (d < PL_bufend && SPACE_OR_TAB(*d))
                    d++;
            }
            if (d < PL_bufend && isIDFIRST_lazy_if(d,UTF)) {
                d = scan_word(d, PL_tokenbuf + 1, sizeof PL_tokenbuf - 1,
                              FALSE, &len);
-               while (d < PL_bufend && (*d == ' ' || *d == '\t'))
+               while (d < PL_bufend && SPACE_OR_TAB(*d))
                    d++;
                if (*d == '}') {
                    char minus = (PL_tokenbuf[0] == '-');
@@ -3193,9 +3251,9 @@ Perl_yylex(pTHX)
        if (PL_lex_brackets < PL_lex_formbrack) {
            char *t;
 #ifdef PERL_STRICT_CR
-           for (t = s; *t == ' ' || *t == '\t'; t++) ;
+           for (t = s; SPACE_OR_TAB(*t); t++) ;
 #else
-           for (t = s; *t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+           for (t = s; SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
 #endif
            if (*t == '\n' || *t == '#') {
                s--;
@@ -3789,7 +3847,7 @@ Perl_yylex(pTHX)
                if (*s == '(') {
                    CLINE;
                    if (gv && GvCVu(gv)) {
-                       for (d = s + 1; *d == ' ' || *d == '\t'; d++) ;
+                       for (d = s + 1; SPACE_OR_TAB(*d); d++) ;
                        if (*d == ')' && (sv = cv_const_sv(GvCV(gv)))) {
                            s = d + 1;
                            goto its_constant;
@@ -4375,7 +4433,7 @@ Perl_yylex(pTHX)
                s = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len);
                if (len == 3 && strnEQ(PL_tokenbuf, "sub", 3))
                    goto really_sub;
-               PL_in_my_stash = gv_stashpv(PL_tokenbuf, FALSE);
+               PL_in_my_stash = find_in_my_stash(PL_tokenbuf, len);
                if (!PL_in_my_stash) {
                    char tmpbuf[1024];
                    PL_bufptr = s;
@@ -4983,6 +5041,9 @@ Perl_yylex(pTHX)
        }
     }}
 }
+#ifdef __SC__
+#pragma segment Main
+#endif
 
 I32
 Perl_keyword(pTHX_ register char *d, I32 len)
@@ -5856,7 +5917,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 (ch != ' ' && ch != '\t') {
+               if (!SPACE_OR_TAB(ch)) {
                    *d = ch;
                    break;
                }
@@ -5882,7 +5943,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 && (*s == ' ' || *s == '\t')) s++;
+           while (s < send && SPACE_OR_TAB(*s)) s++;
            if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
                dTHR;                   /* only for ckWARN */
                if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest)) {
@@ -6092,45 +6153,20 @@ S_scan_trans(pTHX_ char *start)
        Perl_croak(aTHX_ "Transliteration replacement not terminated");
     }
 
-    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 = del = squash = 0;
-    while (strchr("cdsCU", *s)) {
+    while (strchr("cds", *s)) {
        if (*s == 'c')
            complement = OPpTRANS_COMPLEMENT;
        else if (*s == 'd')
            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: 
-               Perl_croak(aTHX_ "Too many /C and /U options");
-           }
-       }
        s++;
     }
-    o->op_private = del|squash|complement|utf8;
+    o->op_private = del|squash|complement;
 
     PL_lex_op = o;
     yylval.ival = OP_TRANS;
@@ -6156,7 +6192,7 @@ S_scan_heredoc(pTHX_ register char *s)
     e = PL_tokenbuf + sizeof PL_tokenbuf - 1;
     if (!outer)
        *d++ = '\n';
-    for (peek = s; *peek == ' ' || *peek == '\t'; peek++) ;
+    for (peek = s; SPACE_OR_TAB(*peek); peek++) ;
     if (*peek && strchr("`'\"",*peek)) {
        s = peek;
        term = *s++;
@@ -6697,7 +6733,7 @@ Perl_scan_num(pTHX_ char *start)
     register char *s = start;          /* current position in buffer */
     register char *d;                  /* destination in temp buffer */
     register char *e;                  /* end of temp buffer */
-    NV value;                          /* number read, as a double */
+    NV nv;                             /* number read, as a double */
     SV *sv = Nullsv;                   /* place to put the converted number */
     bool floatit;                      /* boolean: int or float? */
     char *lastub = 0;                  /* position of last underbar */
@@ -6954,39 +6990,8 @@ Perl_scan_num(pTHX_ char *start)
        /* make an sv from the string */
        sv = NEWSV(92,0);
 
-       /* unfortunately this monster needs to be on one line or
-          makedepend will be confused. */
-#if (defined(USE_64_BIT_INT) && (!defined(HAS_STRTOLL)|| !defined(HAS_STRTOULL))) || (!defined(USE_64_BIT_INT) && (!defined(HAS_STRTOL) || !defined(HAS_STRTOUL)))
-
-       /*
-          No working strto[u]l[l]. Since atoi() doesn't do range checks,
-          we need to do this the hard way.
-        */
-
-       value = Atof(PL_tokenbuf);
-
-       /* 
-          See if we can make do with an integer value without loss of
-          precision.  We use I_V to cast to an int, because some
-          compilers have issues.  Then we try casting it back and see
-          if it was the same.  We only do this if we know we
-          specifically read an integer.
+#if defined(Strtol) && defined(Strtoul)
 
-          Note: if floatit is true, then we don't need to do the
-          conversion at all.
-       */
-       {
-           UV tryuv = U_V(value);
-           if (!floatit && (NV)tryuv == value) {
-               if (tryuv <= IV_MAX)
-                   sv_setiv(sv, (IV)tryuv);
-               else
-                   sv_setuv(sv, tryuv);
-           }
-           else
-               sv_setnv(sv, value);
-       }
-#else
        /*
           strtol/strtoll sets errno to ERANGE if the number is too big
           for an integer. We try to do an integer conversion first
@@ -7002,15 +7007,66 @@ Perl_scan_num(pTHX_ char *start)
            else
                uv = Strtoul(PL_tokenbuf, (char**)NULL, 10);
            if (errno)
-               floatit = TRUE; /* probably just too large */
+               floatit = TRUE; /* Probably just too large. */
            else if (*PL_tokenbuf == '-')
                sv_setiv(sv, iv);
+           else if (uv <= IV_MAX)
+               sv_setiv(sv, uv); /* Prefer IVs over UVs. */
            else
                sv_setuv(sv, uv);
        }
        if (floatit) {
-           value = Atof(PL_tokenbuf);
-           sv_setnv(sv, value);
+           nv = Atof(PL_tokenbuf);
+           sv_setnv(sv, nv);
+       }
+#else
+       /*
+          No working strtou?ll?.
+
+          Unfortunately atol() doesn't do range checks (returning
+          LONG_MIN/LONG_MAX, and setting errno to ERANGE on overflows)
+          everywhere [1], so we cannot use use atol() (or atoll()).
+          If we could, they would be used, as Atol(), very much like
+          Strtol() and Strtoul() are used above.
+
+          [1] XXX Configure test needed to check for atol()
+                  (and atoll()) overflow behaviour XXX
+
+          --jhi
+
+          We need to do this the hard way.  */
+
+       nv = Atof(PL_tokenbuf);
+
+       /* See if we can make do with an integer value without loss of
+          precision.  We use U_V to cast to a UV, because some
+          compilers have issues.  Then we try casting it back and see
+          if it was the same [1].  We only do this if we know we
+          specifically read an integer.  If floatit is true, then we
+          don't need to do the conversion at all. 
+
+          [1] Note that this is lossy if our NVs cannot preserve our
+          UVs.  There are metaconfig defines NV_PRESERVES_UV (a boolean)
+          and NV_PRESERVES_UV_BITS (a number), but in general we really
+          do hope all such potentially lossy platforms have strtou?ll?
+          to do a lossless IV/UV conversion.
+
+          Maybe could do some tricks with DBL_DIG, LDBL_DIG and
+          DBL_MANT_DIG and LDBL_MANT_DIG (these are already available
+          as NV_DIG and NV_MANT_DIG)?
+          
+          --jhi
+          */
+       {
+           UV uv = U_V(nv);
+           if (!floatit && (NV)uv == nv) {
+               if (uv <= IV_MAX)
+                   sv_setiv(sv, uv); /* Prefer IVs over UVs. */
+               else
+                   sv_setuv(sv, uv);
+           }
+           else
+               sv_setnv(sv, nv);
        }
 #endif
        if ( floatit ? (PL_hints & HINT_NEW_FLOAT) :
@@ -7105,9 +7161,9 @@ S_scan_formline(pTHX_ register char *s)
        if (*s == '.' || *s == '}') {
            /*SUPPRESS 530*/
 #ifdef PERL_STRICT_CR
-           for (t = s+1;*t == ' ' || *t == '\t'; t++) ;
+           for (t = s+1;SPACE_OR_TAB(*t); t++) ;
 #else
-           for (t = s+1;*t == ' ' || *t == '\t' || *t == '\r'; t++) ;
+           for (t = s+1;SPACE_OR_TAB(*t) || *t == '\r'; t++) ;
 #endif
            if (*t == '\n' || t == PL_bufend)
                break;