This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
added patch, tweaked PERL_OBJECT things
[perl5.git] / toke.c
diff --git a/toke.c b/toke.c
index c24f878..db87758 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -11,6 +11,8 @@
  *   "It all comes from here, the stench and the peril."  --Frodo
  */
 
+#define TMP_CRLF_PATCH
+
 #include "EXTERN.h"
 #include "perl.h"
 
@@ -26,7 +28,7 @@ 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));
@@ -50,6 +52,7 @@ 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 */
@@ -181,7 +184,7 @@ missingterm(char *s)
     char q;
     if (s) {
        char *nl = strrchr(s,'\n');
-       if (nl) 
+       if (nl)
            *nl = '\0';
     }
     else if (multi_close < 32 || multi_close == 127) {
@@ -403,8 +406,6 @@ skipspace(register char *s)
                PerlIO_clearerr(rsfp);
            else
                (void)PerlIO_close(rsfp);
-           if (e_fp == rsfp)
-               e_fp = Nullfp;
            rsfp = Nullfp;
            return s;
        }
@@ -545,7 +546,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 | 8) : TRUE,
+           gv_fetchpv(s, in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : TRUE,
                kind == '$' ? SVt_PV :
                kind == '@' ? SVt_PVAV :
                kind == '%' ? SVt_PVHV :
@@ -588,20 +589,23 @@ 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 ( hints & HINT_NEW_STRING )
+       pv = sv_2mortal(newSVpv(SvPVX(pv), len));
     while (s < send) {
        if (*s == '\\') {
            if (s + 1 < send && (s[1] == '\\'))
@@ -611,7 +615,9 @@ tokeq(SV *sv)
     }
     *d = '\0';
     SvCUR_set(sv, d - SvPVX(sv));
-
+  finish:
+    if ( hints & HINT_NEW_STRING )
+       return new_constant(NULL, 0, "q", sv, pv, "q");
     return sv;
 }
 
@@ -627,10 +633,19 @@ sublex_start(void)
     }
     if (op_type == OP_CONST || op_type == OP_READLINE) {
        SV *sv = tokeq(lex_stuff);
-       STRLEN len;
-       char *p = SvPV(sv, len);
-       yylval.opval = (OP*)newSVOP(op_type, 0, newSVpv(p, len));
-       SvREFCNT_dec(sv);
+
+       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);
        lex_stuff = Nullsv;
        return THING;
     }
@@ -695,7 +710,7 @@ sublex_push(void)
     curcop->cop_line = multi_start;
 
     lex_inwhat = sublex_info.sub_inwhat;
-    if (lex_inwhat == OP_MATCH || lex_inwhat == OP_SUBST)
+    if (lex_inwhat == OP_MATCH || lex_inwhat == OP_QR || lex_inwhat == OP_SUBST)
        lex_inpat = sublex_info.sub_op;
     else
        lex_inpat = Nullop;
@@ -758,6 +773,12 @@ sublex_done(void)
   processing a pattern (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,17 +846,11 @@ scan_const(char *start)
     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.
-    */
+    /* leaveit is the set of acceptably-backslashed characters */
     char *leaveit =
        lex_inpat
-           ? "\\.^$@AGZdDwWsSbB+*?|()-nrtfeaxc0123456789[{]} \t\n\r\f\v#"
-           : (lex_inwhat & OP_TRANS)
-               ? ""
-               : "";
+           ? "\\.^$@AGZdDwWsSbB+*?|()-nrtfeaxcz0123456789[{]} \t\n\r\f\v#"
+           : "";
 
     while (s < send || dorange) {
         /* get transliterations out of the way (they're most literal) */
@@ -876,23 +891,23 @@ scan_const(char *start)
                    *d++ = *s++;
            } else if (s[2] == '{') {   /* This should march regcomp.c */
                I32 count = 1;
-               char *pregparse = s + 3;
+               char *regparse = s + 3;
                char c;
 
-               while (count && (c = *pregparse)) {
-                   if (c == '\\' && pregparse[1])
-                       pregparse++;
+               while (count && (c = *regparse)) {
+                   if (c == '\\' && regparse[1])
+                       regparse++;
                    else if (c == '{') 
                        count++;
                    else if (c == '}') 
                        count--;
-                   pregparse++;
+                   regparse++;
                }
-               if (*pregparse == ')')
-                   pregparse++;
+               if (*regparse == ')')
+                   regparse++;
                else
                    yyerror("Sequence (?{...}) not terminated or not {}-balanced");
-               while (s < pregparse && *s != ')')
+               while (s < regparse && *s != ')')
                    *d++ = *s++;
            }
        }
@@ -1022,10 +1037,18 @@ 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 > bufptr) {
+       if ( hints & ( lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) )
+           sv = new_constant(start, s - start, (lex_inpat ? "qr" : "q"), 
+                             sv, Nullsv,
+                             ( lex_inwhat == OP_TRANS 
+                               ? "tr"
+                               : ( (lex_inwhat == OP_SUBST && !lex_inpat)
+                                   ? "s"
+                                   : "qq")));
        yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
-    else
+    else
        SvREFCNT_dec(sv);
     return s;
 }
@@ -1068,7 +1091,7 @@ 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];
 
@@ -1134,6 +1157,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) &&
@@ -1347,7 +1372,7 @@ filter_read(int idx, SV *buf_sv, int maxlen)
     /* 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 *
@@ -1499,7 +1524,7 @@ yylex(void)
        /* build ops for a bareword */
        yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(tokenbuf+1, 0));
        yylval.opval->op_private = OPpCONST_ENTERED;
-       gv_fetchpv(tokenbuf+1, in_eval ? (GV_ADDMULTI | 8) : TRUE,
+       gv_fetchpv(tokenbuf+1, in_eval ? (GV_ADDMULTI | GV_ADDINEVAL) : TRUE,
                   ((tokenbuf[0] == '$') ? SVt_PV
                    : (tokenbuf[0] == '@') ? SVt_PVAV
                    : SVt_PVHV));
@@ -1657,6 +1682,8 @@ yylex(void)
            SV *sv = newSVsv(linestr);
            if (!lex_inpat)
                sv = tokeq(sv);
+           else if ( hints & HINT_NEW_RE )
+               sv = new_constant(NULL, 0, "qr", sv, sv, "q");
            yylval.opval = (OP*)newSVOP(OP_CONST, 0, sv);
            s = bufend;
        }
@@ -1783,8 +1810,6 @@ yylex(void)
                        PerlIO_clearerr(rsfp);
                    else
                        (void)PerlIO_close(rsfp);
-                   if (e_fp == rsfp)
-                       e_fp = Nullfp;
                    rsfp = Nullfp;
                }
                if (!in_eval && (minus_n || minus_p)) {
@@ -1963,7 +1988,7 @@ yylex(void)
        }
        goto retry;
     case '\r':
-#ifndef WIN32CHEAT
+#ifndef TMP_CRLF_PATCH
        warn("Illegal character \\%03o (carriage return)", '\r');
        croak(
       "(Maybe you didn't strip carriage returns after a network transfer?)\n");
@@ -2223,13 +2248,8 @@ yylex(void)
                else
                    lex_brackstack[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
@@ -2631,7 +2651,7 @@ yylex(void)
                && (*last_uni != 's' || s - last_uni < 5 
                    || memNE(last_uni, "study", 5) || isALNUM(last_uni[5])))
                check_uni();
-           s = scan_pat(s);
+           s = scan_pat(s,OP_MATCH);
            TERM(sublex_start());
        }
        tmp = *s++;
@@ -2772,7 +2792,7 @@ yylex(void)
        tmp = (len == 1 && strchr("msyq", tokenbuf[0]) ||
               len == 2 && ((tokenbuf[0] == 't' && tokenbuf[1] == 'r') ||
                            (tokenbuf[0] == 'q' &&
-                            strchr("qwx", tokenbuf[1]))));
+                            strchr("qwxr", tokenbuf[1]))));
 
        /* x::* is just a word, unless x is "CORE" */
        if (!tmp && *s == ':' && s[1] == ':' && strNE(tokenbuf, "CORE"))
@@ -2803,14 +2823,28 @@ yylex(void)
        }
 
        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 (expect != XOPERATOR && (*s != ':' || s[1] != ':')) {
+               CV *cv;
+               if ((gv = gv_fetchpv(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(globalstash,tokenbuf,len,FALSE)) &&
+                   (gv = *gvp) != (GV*)&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 */
@@ -2818,8 +2852,13 @@ yylex(void)
            {
                tmp = 0;                /* any sub overrides "weak" keyword */
            }
-           else {
-               tmp = -tmp; gv = Nullgv; gvp = 0;
+           else {                      /* no override */
+               tmp = -tmp;
+               gv = Nullgv;
+               gvp = 0;
+               if (dowarn && hgv)
+                   warn("Ambiguous call resolved as CORE::%s(), "
+                        "qualify as such or use &", GvENAME(hgv));
            }
        }
 
@@ -2838,7 +2877,8 @@ yylex(void)
                    s = scan_word(s, tokenbuf + len, sizeof tokenbuf - len,
                                  TRUE, &morelen);
                    if (!morelen)
-                       croak("Bad name after %s::", tokenbuf);
+                       croak("Bad name after %s%s", tokenbuf,
+                               *s == '\'' ? "'" : "::");
                    len += morelen;
                }
 
@@ -2899,8 +2939,11 @@ yylex(void)
                    oldoldbufptr < bufptr &&
                    (oldoldbufptr == last_lop || oldoldbufptr == last_uni) &&
                    /* NO SKIPSPACE BEFORE HERE! */
-                   (expect == XREF ||
-                    ((opargs[last_lop_op] >> OASHIFT)& 7) == OA_FILEREF) )
+                   (expect == XREF 
+                    || ((opargs[last_lop_op] >> OASHIFT)& 7) == OA_FILEREF
+                    || (last_lop_op == OP_ENTERSUB 
+                        && last_proto 
+                        && last_proto[last_proto[0] == ';' ? 1 : 0] == '*')) )
                {
                    bool immediate_paren = *s == '(';
 
@@ -2981,16 +3024,17 @@ yylex(void)
                    /* Is there a prototype? */
                    if (SvPOK(cv)) {
                        STRLEN len;
-                       char *proto = SvPV((SV*)cv, len);
+                       last_proto = SvPV((SV*)cv, len);
                        if (!len)
                            TERM(FUNC0SUB);
-                       if (strEQ(proto, "$"))
+                       if (strEQ(last_proto, "$"))
                            OPERATOR(UNIOPSUB);
-                       if (*proto == '&' && *s == '{') {
+                       if (*last_proto == '&' && *s == '{') {
                            sv_setpv(subname,"__ANON__");
                            PREBLOCK(LSTOPSUB);
                        }
-                   }
+                   } else
+                       last_proto = NULL;
                    nextval[nexttoke].opval = yylval.opval;
                    expect = XTERM;
                    force_next(WORD);
@@ -3456,7 +3500,7 @@ yylex(void)
            UNI(OP_LSTAT);
 
        case KEY_m:
-           s = scan_pat(s);
+           s = scan_pat(s,OP_MATCH);
            TERM(sublex_start());
 
        case KEY_map:
@@ -3617,6 +3661,10 @@ yylex(void)
                SvIVX(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:
            s = scan_str(s);
            if (!s)
@@ -4376,6 +4424,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;
@@ -4412,6 +4462,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;
@@ -4689,6 +4740,75 @@ checkcomma(register char *s, char *name, char *what)
     }
 }
 
+STATIC SV *
+new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) 
+{
+    dSP;
+    HV *table = GvHV(hintgv);           /* ^H */
+    BINOP myop;
+    SV *res;
+    bool oldcatch = CATCH_GET;
+    SV **cvp;
+    SV *cv, *typesv;
+    char buf[128];
+           
+    if (!table) {
+       yyerror("%^H is not defined");
+       return sv;
+    }
+    cvp = hv_fetch(table, key, strlen(key), FALSE);
+    if (!cvp || !SvOK(*cvp)) {
+       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 = &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();
+    op = (OP *) &myop;
+    if (PERLDB_SUB && curstash != debstash)
+       op->op_private |= OPpENTERSUB_DB;
+    PUTBACK;
+    pp_pushmark(ARGS);
+
+    EXTEND(sp, 4);
+    PUSHs(pv);
+    PUSHs(sv);
+    PUSHs(typesv);
+    PUSHs(cv);
+    PUTBACK;
+
+    if (op = pp_entersub(ARGS))
+      CALLRUNOPS();
+    LEAVE;
+    SPAGAIN;
+
+    res = POPs;
+    PUTBACK;
+    CATCH_SET(oldcatch);
+    POPSTACK;
+
+    if (!SvOK(res)) {
+       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)
 {
@@ -4852,7 +4972,7 @@ void pmflag(U16 *pmfl, int ch)
 }
 
 STATIC char *
-scan_pat(char *start)
+scan_pat(char *start, I32 type)
 {
     PMOP *pm;
     char *s;
@@ -4865,11 +4985,17 @@ scan_pat(char *start)
        croak("Search pattern not terminated");
     }
 
-    pm = (PMOP*)newPMOP(OP_MATCH, 0);
+    pm = (PMOP*)newPMOP(type, 0);
     if (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;
@@ -4913,13 +5039,15 @@ scan_subst(char *start)
     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) {
@@ -5040,6 +5168,30 @@ scan_heredoc(register char *s)
     *d++ = '\n';
     *d = '\0';
     len = d - tokenbuf;
+#ifdef TMP_CRLF_PATCH
+    d = strchr(s, '\r');
+    if (d) {
+       char *olds = s;
+       s = d;
+       while (s < 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';
+       bufend = d;
+       SvCUR_set(linestr, bufend - SvPVX(linestr));
+       s = olds;
+    }
+#endif
     d = "\n";
     if (outer || !(d=ninstr(s,bufend,d,d+1)))
        herewas = newSVpv(s,bufend-s);
@@ -5047,7 +5199,7 @@ scan_heredoc(register char *s)
        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;
@@ -5075,7 +5227,7 @@ scan_heredoc(register char *s)
        }
        sv_setpvn(tmpstr,d+1,s-d);
        s += len - 1;
-       curcop->cop_line++;     /* the preceding stmt passes a newline */
+       curcop->cop_line++;     /* the preceding stmt passes a newline */
 
        sv_catpvn(herewas,s,bufend-s);
        sv_setsv(linestr,herewas);
@@ -5091,6 +5243,20 @@ scan_heredoc(register char *s)
            missingterm(tokenbuf);
        }
        curcop->cop_line++;
+       bufend = SvPVX(linestr) + SvCUR(linestr);
+#ifdef TMP_CRLF_PATCH
+       if (bufend - linestart >= 2) {
+           if (bufend[-2] == '\r' || bufend[-2] == '\n') {
+               bufend[-2] = '\n';
+               bufend--;
+               SvCUR_set(linestr, bufend - SvPVX(linestr));
+           }
+           else if (bufend[-1] == '\r')
+               bufend[-1] = '\n';
+       }
+       else if (bufend - linestart == 1 && bufend[-1] == '\r')
+           bufend[-1] = '\n';
+#endif
        if (PERLDB_LINE && curstash != debstash) {
            SV *sv = NEWSV(88,0);
 
@@ -5099,7 +5265,6 @@ scan_heredoc(register char *s)
            av_store(GvAV(curcop->cop_filegv),
              (I32)curcop->cop_line,sv);
        }
-       bufend = SvPVX(linestr) + SvCUR(linestr);
        if (*s == term && memEQ(s,tokenbuf,len)) {
            s = bufend - 1;
            *s = ' ';
@@ -5305,8 +5470,8 @@ scan_str(char *start)
     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 */
@@ -5376,6 +5541,20 @@ scan_str(char *start)
 
        if (s < bufend) break;  /* handle case where we are done yet :-) */
 
+#ifdef TMP_CRLF_PATCH
+       if (to - SvPVX(sv) >= 2) {
+           if (to[-2] == '\r' || to[-2] == '\n') {
+               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
        */
@@ -5537,7 +5716,8 @@ scan_num(char *start)
 
                  digit:
                    n = u << shift;     /* make room for the digit */
-                   if (!overflowed && (n >> shift) != u) {
+                   if (!overflowed && (n >> shift) != u
+                       && !(hints & HINT_NEW_BINARY)) {
                        warn("Integer overflow in %s number",
                             (shift == 4) ? "hex" : "octal");
                        overflowed = TRUE;
@@ -5553,6 +5733,8 @@ scan_num(char *start)
          out:
            sv = NEWSV(92,0);
            sv_setuv(sv, u);
+           if ( hints & HINT_NEW_BINARY)
+               sv = new_constant(start, s - start, "binary", sv, Nullsv, NULL);
        }
        break;
 
@@ -5654,6 +5836,9 @@ scan_num(char *start)
            sv_setiv(sv, tryiv);
        else
            sv_setnv(sv, value);
+       if ( floatit ? (hints & HINT_NEW_FLOAT) : (hints & HINT_NEW_INTEGER) )
+           sv = new_constant(tokenbuf, d - tokenbuf, 
+                             (floatit ? "float" : "integer"), sv, Nullsv, NULL);
        break;
     }