readd missing perldelta.pod changes from changes#6339,6376
[p5sagit/p5-mst-13.2.git] / toke.c
diff --git a/toke.c b/toke.c
index 75cab91..f39b3bd 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -326,7 +326,7 @@ S_cr_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 }
 #endif
 
-#if 0
+#ifdef PERL_UTF16_FILTER
 STATIC I32
 S_utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen)
 {
@@ -502,8 +502,14 @@ S_incline(pTHX_ char *s)
 
     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);
 }
@@ -981,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;
        } 
@@ -1200,6 +1208,7 @@ S_scan_const(pTHX_ char *start)
     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? */
+    bool didrange = FALSE;                     /* did we just finish a range? */
     bool has_utf = FALSE;                      /* embedded \x{} */
     I32 len;                                   /* ? */
     UV uv;
@@ -1233,6 +1242,13 @@ S_scan_const(pTHX_ char *start)
                min = (U8)*d;                   /* first char in range */
                max = (U8)d[1];                 /* last char in range  */
 
+
+                if (min > max) {
+                    Perl_croak(aTHX_
+                           "Invalid [] range \"%c-%c\" in transliteration operator",
+                           min, max);
+                }
+
 #ifndef ASCIIish
                if ((isLOWER(min) && isLOWER(max)) ||
                    (isUPPER(min) && isUPPER(max))) {
@@ -1253,11 +1269,15 @@ S_scan_const(pTHX_ char *start)
 
                /* mark the range as done, and continue */
                dorange = FALSE;
+                didrange = TRUE;
                continue;
-           }
+           } 
 
            /* range begins (ignore - as first or last char) */
            else if (*s == '-' && s+1 < send  && s != start) {
+                if (didrange) { 
+                   Perl_croak(aTHX_ "Ambiguous range in transliteration operator");
+                }
                if (utf) {
                    *d++ = (char)0xff;  /* use illegal utf8 byte--see pmtrans */
                    s++;
@@ -1265,7 +1285,9 @@ S_scan_const(pTHX_ char *start)
                }
                dorange = TRUE;
                s++;
-           }
+           } else {
+              didrange = FALSE;
+            }
        }
 
        /* if we get here, we're not doing a transliteration */
@@ -1867,7 +1889,7 @@ 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/IoANY 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.
@@ -1885,7 +1907,7 @@ Perl_filter_add(pTHX_ filter_t funcp, SV *datasv)
        datasv = NEWSV(255,0);
     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 */
+    IoANY(datasv) = (void *)funcp; /* stash funcp into spare field */
     IoFLAGS(datasv) |= IOf_FAKE_DIRP;
     DEBUG_P(PerlIO_printf(Perl_debug_log, "filter_add func %p (%s)\n",
                          funcp, SvPV_nolen(datasv)));
@@ -1905,9 +1927,9 @@ Perl_filter_del(pTHX_ filter_t funcp)
        return;
     /* if filter is on top of stack (usual case) just pop it off */
     datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters));
-    if (IoDIRP(datasv) == (DIR*)funcp) {
+    if (IoANY(datasv) == (void *)funcp) {
        IoFLAGS(datasv) &= ~IOf_FAKE_DIRP;
-       IoDIRP(datasv) = (DIR*)NULL;
+       IoANY(datasv) = (void *)NULL;
        sv_free(av_pop(PL_rsfp_filters));
 
         return;
@@ -1967,7 +1989,7 @@ Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
        return FILTER_READ(idx+1, buf_sv, maxlen); /* recurse */
     }
     /* Get function pointer hidden within datasv       */
-    funcp = (filter_t)IoDIRP(datasv);
+    funcp = (filter_t)IoANY(datasv);
     DEBUG_P(PerlIO_printf(Perl_debug_log,
                          "filter_read %d: via function %p (%s)\n",
                          idx, funcp, SvPV_nolen(datasv)));
@@ -1998,6 +2020,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[] =
@@ -2459,6 +2504,8 @@ Perl_yylex(pTHX)
            goto retry;
        }
        do {
+        bool bof;
+        bof = PL_rsfp && (PerlIO_tell(PL_rsfp)==0); /* *Before* read! */
            if ((s = filter_gets(PL_linestr, PL_rsfp, 0)) == Nullch) {
              fake_eof:
                if (PL_rsfp) {
@@ -2494,7 +2541,9 @@ Perl_yylex(pTHX)
                    PL_bufend = SvPVX(PL_linestr) + SvCUR(PL_linestr);
                    PL_doextract = FALSE;
                }
-           }
+           } 
+        if (bof)
+            s = swallow_bom(s);
            incline(s);
        } while (PL_doextract);
        PL_oldoldbufptr = PL_oldbufptr = PL_bufptr = PL_linestart = s;
@@ -2946,8 +2995,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 ')':
@@ -3124,7 +3172,7 @@ Perl_yylex(pTHX)
            yyerror("Unmatched right curly bracket");
        else
            PL_expect = (expectation)PL_lex_brackstack[--PL_lex_brackets];
-       if (PL_lex_brackets < PL_lex_formbrack)
+       if (PL_lex_brackets < PL_lex_formbrack && PL_lex_state != LEX_INTERPNORMAL)
            PL_lex_formbrack = 0;
        if (PL_lex_state == LEX_INTERPNORMAL) {
            if (PL_lex_brackets == 0) {
@@ -4403,7 +4451,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;
@@ -6123,45 +6171,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;
@@ -7025,7 +7048,9 @@ Perl_scan_num(pTHX_ char *start)
           Strtol() and Strtoul() are used above.
 
           [1] XXX Configure test needed to check for atol()
-                  (and atoll() overflow behaviour) XXX --jhi
+                  (and atoll()) overflow behaviour XXX
+
+          --jhi
 
           We need to do this the hard way.  */
 
@@ -7039,14 +7064,16 @@ Perl_scan_num(pTHX_ char *start)
           don't need to do the conversion at all. 
 
           [1] Note that this is lossy if our NVs cannot preserve our
-          UVs.  There is a metaconfig define, NV_PRESERVES_UV, but we
-          really do hope all such platforms have strtou?ll? to do a
-          lossless IV/UV conversion.
-          XXX Configure test needed to check how many UV bits
-              do our NVs preserve, really (the current test checks
-              for the roundtrip of ~0) XXX --jhi
-              Maybe do some tricks with DBL_MANT_DIG and LDBL_MANT_DIG,
-              and DBL_DIG, LDBL_DIG (this is already available as NV_DIG)?
+          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);
@@ -7149,7 +7176,7 @@ S_scan_formline(pTHX_ register char *s)
     bool needargs = FALSE;
 
     while (!needargs) {
-       if (*s == '.' || *s == '}') {
+       if (*s == '.' || *s == /*{*/'}') {
            /*SUPPRESS 530*/
 #ifdef PERL_STRICT_CR
            for (t = s+1;SPACE_OR_TAB(*t); t++) ;
@@ -7378,6 +7405,58 @@ Perl_yyerror(pTHX_ char *s)
 }
 
 
+STATIC char*
+S_swallow_bom(pTHX_ char *s) {
+    STRLEN slen;
+    slen = SvCUR(PL_linestr);
+    switch (*s) {
+    case -1:       
+    if ((s[1] & 255) == 254) { 
+        /* UTF-16 little-endian */
+#ifdef PERL_UTF16_FILTER
+        U8 *news;
+#endif
+        s+=2;
+        if (*s == 0 && s[1] == 0)  /* UTF-32 little-endian */
+            Perl_croak(aTHX_ "Unsupported script encoding");
+#ifdef PERL_UTF16_FILTER
+        filter_add(S_utf16rev_textfilter, NULL);
+        New(898, news, (PL_bufend - s) * 3 / 2 + 1, U8);
+        PL_bufend = utf16_to_utf8((U16*)s, news, PL_bufend - s);
+        s = news;
+#else
+        Perl_croak(aTHX_ "Unsupported script encoding");
+#endif
+    }
+    break;
+
+    case -2:
+    if ((s[1] & 255) == 255) {   /* UTF-16 big-endian */
+#ifdef PERL_UTF16_FILTER
+        U8 *news;
+        filter_add(S_utf16_textfilter, NULL);
+        New(898, news, (PL_bufend - s) * 3 / 2 + 1, U8);
+        PL_bufend = utf16_to_utf8((U16*)s, news, PL_bufend - s);
+        s = news;
+#else
+        Perl_croak(aTHX_ "Unsupported script encoding");
+#endif
+   }
+   break;
+
+   case -17:
+   if ( slen>2 && (s[1] & 255) == 187 && (s[2] & 255) == 191) {
+        s+=3;                      /* UTF-8 */
+   }
+   break;
+   case 0:
+   if (slen > 3 && s[1] == 0 &&  /* UTF-32 big-endian */
+       s[2] & 255 == 254 && s[3] & 255 == 255)
+       Perl_croak(aTHX_ "Unsupported script encoding");
+} 
+return s;
+}
+
 #ifdef PERL_OBJECT
 #include "XSUB.h"
 #endif