[asperl] more changes to satisfy non-debug VC build (C-API doesn't
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index c5c475a..de4a94c 100644 (file)
--- a/op.c
+++ b/op.c
 #include "EXTERN.h"
 #include "perl.h"
 
+#ifdef PERL_OBJECT
+#define CHECKCALL this->*check
+#else
+#define CHECKCALL *check
+#endif
+
 /*
  * In the following definition, the ", Nullop" is just to make the compiler
  * think the expression is of the right type: croak actually does a Siglongjmp.
      ? ( op_free((OP*)o),                                      \
         croak("%s trapped by operation mask", op_desc[type]),  \
         Nullop )                                               \
-     : (*check[type])((OP*)o))
+     : (CHECKCALL[type])((OP*)o))
 
+static bool scalar_mod_type _((OP *o, I32 type));
+#ifndef PERL_OBJECT
 static I32 list_assignment _((OP *o));
 static void bad_type _((I32 n, char *t, char *name, OP *kid));
 static OP *modkids _((OP *o, I32 type));
 static OP *no_fh_allowed _((OP *o));
-static bool scalar_mod_type _((OP *o, I32 type));
 static OP *scalarboolean _((OP *o));
 static OP *too_few_arguments _((OP *o, char* name));
 static OP *too_many_arguments _((OP *o, char* name));
@@ -41,8 +48,10 @@ static void null _((OP* o));
 static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
        CV* startcv, I32 cx_ix));
 static OP *newDEFSVOP _((void));
+static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
+#endif
 
-static char*
+STATIC char*
 gv_ename(GV *gv)
 {
     SV* tmpsv = sv_newmortal();
@@ -50,7 +59,7 @@ gv_ename(GV *gv)
     return SvPV(tmpsv,na);
 }
 
-static OP *
+STATIC OP *
 no_fh_allowed(OP *o)
 {
     yyerror(form("Missing comma after first argument to %s function",
@@ -58,21 +67,21 @@ no_fh_allowed(OP *o)
     return o;
 }
 
-static OP *
+STATIC OP *
 too_few_arguments(OP *o, char *name)
 {
     yyerror(form("Not enough arguments for %s", name));
     return o;
 }
 
-static OP *
+STATIC OP *
 too_many_arguments(OP *o, char *name)
 {
     yyerror(form("Too many arguments for %s", name));
     return o;
 }
 
-static void
+STATIC void
 bad_type(I32 n, char *t, char *name, OP *kid)
 {
     yyerror(form("Type of arg %d to %s must be %s (not %s)",
@@ -85,9 +94,18 @@ assertref(OP *o)
     int type = o->op_type;
     if (type != OP_AELEM && type != OP_HELEM) {
        yyerror(form("Can't use subscript on %s", op_desc[type]));
-       if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV)
-           warn("(Did you mean $ or @ instead of %c?)\n",
-                type == OP_ENTERSUB ? '&' : '%');
+       if (type == OP_ENTERSUB || type == OP_RV2HV || type == OP_PADHV) {
+           dTHR;
+           SV *msg = sv_2mortal(
+                       newSVpvf("(Did you mean $ or @ instead of %c?)\n",
+                                type == OP_ENTERSUB ? '&' : '%'));
+           if (in_eval & 2)
+               warn("%_", msg);
+           else if (in_eval)
+               sv_catsv(GvSV(errgv), msg);
+           else
+               PerlIO_write(PerlIO_stderr(), SvPVX(msg), SvCUR(msg));
+       }
     }
 }
 
@@ -147,17 +165,8 @@ pad_allocmy(char *name)
     return off;
 }
 
-static PADOFFSET
-#ifndef CAN_PROTOTYPE
-pad_findlex(name, newoff, seq, startcv, cx_ix)
-char *name;
-PADOFFSET newoff;
-U32 seq;
-CV* startcv;
-I32 cx_ix;
-#else
+STATIC PADOFFSET
 pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)
-#endif
 {
     dTHR;
     CV *cv;
@@ -393,19 +402,15 @@ pad_alloc(I32 optype, U32 tmptype)
                          (unsigned long) thr, (unsigned long) curpad,
                          (long) retval, op_name[optype]));
 #else
-    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad alloc %ld for %s\n",
+    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx alloc %ld for %s\n",
+                         (unsigned long) curpad,
                          (long) retval, op_name[optype]));
 #endif /* USE_THREADS */
     return (PADOFFSET)retval;
 }
 
 SV *
-#ifndef CAN_PROTOTYPE
-pad_sv(po)
-PADOFFSET po;
-#else
 pad_sv(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
 {
     dTHR;
 #ifdef USE_THREADS
@@ -414,18 +419,14 @@ pad_sv(PADOFFSET po)
 #else
     if (!po)
        croak("panic: pad_sv po");
-    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad sv %d\n", po));
+    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx sv %d\n",
+                         (unsigned long) curpad, po));
 #endif /* USE_THREADS */
     return curpad[po];         /* eventually we'll turn this into a macro */
 }
 
 void
-#ifndef CAN_PROTOTYPE
-pad_free(po)
-PADOFFSET po;
-#else
 pad_free(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
 {
     dTHR;
     if (!curpad)
@@ -438,7 +439,8 @@ pad_free(PADOFFSET po)
     DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx free %d\n",
                          (unsigned long) thr, (unsigned long) curpad, po));
 #else
-    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad free %d\n", po));
+    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx free %d\n",
+                         (unsigned long) curpad, po));
 #endif /* USE_THREADS */
     if (curpad[po] && curpad[po] != &sv_undef)
        SvPADTMP_off(curpad[po]);
@@ -447,12 +449,7 @@ pad_free(PADOFFSET po)
 }
 
 void
-#ifndef CAN_PROTOTYPE
-pad_swipe(po)
-PADOFFSET po;
-#else
 pad_swipe(PADOFFSET po)
-#endif /* CAN_PROTOTYPE */
 {
     dTHR;
     if (AvARRAY(comppad) != curpad)
@@ -463,7 +460,8 @@ pad_swipe(PADOFFSET po)
     DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx swipe %d\n",
                          (unsigned long) thr, (unsigned long) curpad, po));
 #else
-    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad swipe %d\n", po));
+    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx swipe %d\n",
+                         (unsigned long) curpad, po));
 #endif /* USE_THREADS */
     SvPADTMP_off(curpad[po]);
     curpad[po] = NEWSV(1107,0);
@@ -472,9 +470,16 @@ pad_swipe(PADOFFSET po)
        padix = po - 1;
 }
 
+/* XXX pad_reset() is currently disabled because it results in serious bugs.
+ * It causes pad temp TARGs to be shared between OPs. Since TARGs are pushed
+ * on the stack by OPs that use them, there are several ways to get an alias
+ * to  a shared TARG.  Such an alias will change randomly and unpredictably.
+ * We avoid doing this until we can think of a Better Way.
+ * GSAR 97-10-29 */
 void
 pad_reset(void)
 {
+#ifdef USE_BROKEN_PAD_RESET
     dTHR;
     register I32 po;
 
@@ -484,7 +489,8 @@ pad_reset(void)
     DEBUG_X(PerlIO_printf(Perl_debug_log, "0x%lx Pad 0x%lx reset\n",
                          (unsigned long) thr, (unsigned long) curpad));
 #else
-    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad reset\n"));
+    DEBUG_X(PerlIO_printf(Perl_debug_log, "Pad 0x%lx reset\n",
+                         (unsigned long) curpad));
 #endif /* USE_THREADS */
     if (!tainting) {   /* Can't mix tainted and non-tainted temporaries. */
        for (po = AvMAX(comppad); po > padix_floor; po--) {
@@ -493,6 +499,7 @@ pad_reset(void)
        }
        padix = padix_floor;
     }
+#endif
     pad_reset_pending = FALSE;
 }
 
@@ -533,6 +540,11 @@ find_threadsv(char *name)
            sawampersand = TRUE;
            SvREADONLY_on(sv);
            /* FALL THROUGH */
+
+       /* XXX %! tied to Errno.pm needs to be added here.
+        * See gv_fetchpv(). */
+       /* case '!': */
+
        default:
            sv_magic(sv, 0, 0, name, 1); 
        }
@@ -575,7 +587,8 @@ op_free(OP *o)
        break;
 #endif /* USE_THREADS */
     default:
-       if (!(o->op_flags & OPf_REF) || (check[o->op_type] != ck_ftst))
+       if (!(o->op_flags & OPf_REF)
+           || (check[o->op_type] != FUNC_NAME_TO_PTR(ck_ftst)))
            break;
        /* FALL THROUGH */
     case OP_GVSV:
@@ -616,7 +629,7 @@ op_free(OP *o)
     Safefree(o);
 }
 
-static void
+STATIC void
 null(OP *o)
 {
     if (o->op_type != OP_NULL && o->op_type != OP_THREADSV && o->op_targ > 0)
@@ -665,7 +678,7 @@ scalarkids(OP *o)
     return o;
 }
 
-static OP *
+STATIC OP *
 scalarboolean(OP *o)
 {
     if (dowarn &&
@@ -1035,7 +1048,7 @@ scalarseq(OP *o)
     return o;
 }
 
-static OP *
+STATIC OP *
 modkids(OP *o, I32 type)
 {
     OP *kid;
@@ -1046,8 +1059,6 @@ modkids(OP *o, I32 type)
     return o;
 }
 
-static I32 modcount;
-
 OP *
 mod(OP *o, I32 type)
 {
@@ -1242,6 +1253,7 @@ mod(OP *o, I32 type)
     else if (!type) {
        o->op_private |= OPpLVAL_INTRO;
        o->op_flags &= ~OPf_SPECIAL;
+       hints |= HINT_BLOCK_SCOPE;
     }
     else if (type != OP_GREPSTART && type != OP_ENTERSUB)
        o->op_flags |= OPf_REF;
@@ -1401,8 +1413,9 @@ my(OP *o)
     if (type == OP_LIST) {
        for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
            my(kid);
-    }
-    else if (type != OP_PADSV &&
+    } else if (type == OP_UNDEF) {
+       return o;
+    } else if (type != OP_PADSV &&
             type != OP_PADAV &&
             type != OP_PADHV &&
             type != OP_PUSHMARK)
@@ -1536,7 +1549,7 @@ block_end(I32 floor, OP *seq)
     return retval;
 }
 
-static OP *
+STATIC OP *
 newDEFSVOP(void)
 {
 #ifdef USE_THREADS
@@ -1573,7 +1586,7 @@ newPROG(OP *o)
            CV *cv = perl_get_cv("DB::postponed", FALSE);
            if (cv) {
                dSP;
-               PUSHMARK(sp);
+               PUSHMARK(SP);
                XPUSHs((SV*)compiling.cop_filegv);
                PUTBACK;
                perl_call_sv((SV*)cv, G_DISCARD);
@@ -1670,7 +1683,7 @@ fold_constants(register OP *o)
     curop = LINKLIST(o);
     o->op_next = 0;
     op = curop;
-    runops();
+    CALLRUNOPS();
     sv = *(stack_sp--);
     if (o->op_targ && sv == PAD_SV(o->op_targ))        /* grab pad temp? */
        pad_swipe(o->op_targ);
@@ -1682,9 +1695,12 @@ fold_constants(register OP *o)
     if (type == OP_RV2GV)
        return newGVOP(OP_GV, 0, (GV*)sv);
     else {
-       if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK) {
+       /* try to smush double to int, but don't smush -2.0 to -2 */
+       if ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_NOK &&
+           type != OP_NEGATE)
+       {
            IV iv = SvIV(sv);
-           if ((double)iv == SvNV(sv)) {       /* can we smush double to int */
+           if ((double)iv == SvNV(sv)) {
                SvREFCNT_dec(sv);
                sv = newSViv(iv);
            }
@@ -1732,7 +1748,7 @@ gen_constant_list(register OP *o)
     op = curop = LINKLIST(o);
     o->op_next = 0;
     pp_pushmark(ARGS);
-    runops();
+    CALLRUNOPS();
     op = curop;
     pp_anonlist(ARGS);
     tmps_floor = oldtmps_floor;
@@ -2369,7 +2385,7 @@ newSLICEOP(I32 flags, OP *subscript, OP *listval)
            list(force_list(listval)) );
 }
 
-static I32
+STATIC I32
 list_assignment(register OP *o)
 {
     if (!o)
@@ -2421,6 +2437,7 @@ newASSIGNOP(I32 flags, OP *left, I32 optype, OP *right)
     }
 
     if (list_assignment(left)) {
+       dTHR;
        modcount = 0;
        eval_start = right;     /* Grandfathering $[ assignment here.  Bletch.*/
        left = mod(left, OP_AASSIGN);
@@ -2436,7 +2453,6 @@ newASSIGNOP(I32 flags, OP *left, I32 optype, OP *right)
                list(force_list(left)) );
        o->op_private = 0 | (flags >> 8);
        if (!(left->op_private & OPpLVAL_INTRO)) {
-           static int generation = 100;
            OP *curop;
            OP *lastop = o;
            generation++;
@@ -2609,9 +2625,17 @@ intro_my(void)
 OP *
 newLOGOP(I32 type, I32 flags, OP *first, OP *other)
 {
+    return new_logop(type, flags, &first, &other);
+}
+
+STATIC OP *
+new_logop(I32 type, I32 flags, OP** firstp, OP** otherp)
+{
     dTHR;
     LOGOP *logop;
     OP *o;
+    OP *first = *firstp;
+    OP *other = *otherp;
 
     if (type == OP_XOR)                /* Not short circuit, but here by precedence. */
        return newBINOP(type, flags, scalar(first), scalar(other));
@@ -2625,7 +2649,7 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other)
            else
                type = OP_AND;
            o = first;
-           first = cUNOPo->op_first;
+           first = *firstp = cUNOPo->op_first;
            if (o->op_next)
                first->op_next = o->op_next;
            cUNOPo->op_first = Nullop;
@@ -2637,10 +2661,12 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other)
            warn("Probable precedence problem on %s", op_desc[type]);
        if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) {
            op_free(first);
+           *firstp = Nullop;
            return other;
        }
        else {
            op_free(other);
+           *otherp = Nullop;
            return first;
        }
     }
@@ -2659,7 +2685,7 @@ newLOGOP(I32 type, I32 flags, OP *first, OP *other)
        case OP_NULL:
            if (k2 && k2->op_type == OP_READLINE
                  && (k2->op_flags & OPf_STACKED)
-                 && (k1->op_type == OP_RV2SV || k1->op_type == OP_PADSV))
+                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
                warnop = k2->op_type;
            break;
 
@@ -2821,13 +2847,32 @@ newLOOPOP(I32 flags, I32 debuggable, OP *expr, OP *block)
            || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB)) {
            expr = newUNOP(OP_DEFINED, 0,
                newASSIGNOP(0, newDEFSVOP(), 0, expr) );
+       } else if (expr->op_flags & OPf_KIDS) {
+           OP *k1 = ((UNOP*)expr)->op_first;
+           OP *k2 = (k1) ? k1->op_sibling : NULL;
+           switch (expr->op_type) {
+             case OP_NULL: 
+               if (k2 && k2->op_type == OP_READLINE
+                     && (k2->op_flags & OPf_STACKED)
+                     && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
+                   expr = newUNOP(OP_DEFINED, 0, expr);
+               break;                                
+
+             case OP_SASSIGN:
+               if (k1->op_type == OP_READDIR
+                     || k1->op_type == OP_GLOB
+                     || k1->op_type == OP_EACH)
+                   expr = newUNOP(OP_DEFINED, 0, expr);
+               break;
+           }
        }
     }
 
     listop = append_elem(OP_LINESEQ, block, newOP(OP_UNSTACK, 0));
-    o = newLOGOP(OP_AND, 0, expr, listop);
+    o = new_logop(OP_AND, 0, &expr, &listop);
 
-    ((LISTOP*)listop)->op_last->op_next = LINKLIST(o);
+    if (listop)
+       ((LISTOP*)listop)->op_last->op_next = LINKLIST(o);
 
     if (once && o != listop)
        o->op_next = ((LOGOP*)cUNOPo->op_first)->op_other;
@@ -2855,6 +2900,24 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b
                 || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
        expr = newUNOP(OP_DEFINED, 0,
            newASSIGNOP(0, newDEFSVOP(), 0, expr) );
+    } else if (expr && (expr->op_flags & OPf_KIDS)) {
+       OP *k1 = ((UNOP*)expr)->op_first;
+       OP *k2 = (k1) ? k1->op_sibling : NULL;
+       switch (expr->op_type) {
+         case OP_NULL: 
+           if (k2 && k2->op_type == OP_READLINE
+                 && (k2->op_flags & OPf_STACKED)
+                 && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) 
+               expr = newUNOP(OP_DEFINED, 0, expr);
+           break;                                
+
+         case OP_SASSIGN:
+           if (k1->op_type == OP_READDIR
+                 || k1->op_type == OP_GLOB
+                 || k1->op_type == OP_EACH)
+               expr = newUNOP(OP_DEFINED, 0, expr);
+           break;
+       }
     }
 
     if (!block)
@@ -2875,14 +2938,17 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b
     redo = LINKLIST(listop);
 
     if (expr) {
-       o = newLOGOP(OP_AND, 0, expr, scalar(listop));
+       copline = whileline;
+       scalar(listop);
+       o = new_logop(OP_AND, 0, &expr, &listop);
        if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) {
            op_free(expr);              /* oops, it's a while (0) */
            op_free((OP*)loop);
-           return Nullop;              /* (listop already freed by newLOGOP) */
+           return Nullop;              /* listop already freed by new_logop */
        }
-       ((LISTOP*)listop)->op_last->op_next = condop =
-           (o == listop ? redo : LINKLIST(o));
+       if (listop)
+           ((LISTOP*)listop)->op_last->op_next = condop =
+               (o == listop ? redo : LINKLIST(o));
        if (!next)
            next = condop;
     }
@@ -2913,18 +2979,7 @@ newWHILEOP(I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *b
 }
 
 OP *
-#ifndef CAN_PROTOTYPE
-newFOROP(flags,label,forline,sv,expr,block,cont)
-I32 flags;
-char *label;
-line_t forline;
-OP* sv;
-OP* expr;
-OP*block;
-OP*cont;
-#else
 newFOROP(I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont)
-#endif /* CAN_PROTOTYPE */
 {
     LOOP *loop;
     OP *wop;
@@ -3058,7 +3113,7 @@ cv_undef(CV *cv)
 }
 
 #ifdef DEBUG_CLOSURES
-static void
+STATIC void
 cv_dump(cv)
 CV* cv;
 {
@@ -3103,7 +3158,7 @@ CV* cv;
 }
 #endif /* DEBUG_CLOSURES */
 
-static CV *
+STATIC CV *
 cv_clone2(CV *proto, CV *outside)
 {
     dTHR;
@@ -3304,7 +3359,8 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
 {
     dTHR;
     char *name = o ? SvPVx(cSVOPo->op_sv, na) : Nullch;
-    GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
+    GV *gv = gv_fetchpv(name ? name : "__ANON__",
+                       GV_ADDMULTI | (block ? 0 : GV_NOINIT), SVt_PVCV);
     char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch;
     register CV *cv;
     I32 ix;
@@ -3314,6 +3370,23 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
     if (proto)
        SAVEFREEOP(proto);
 
+    if (SvTYPE(gv) != SVt_PVGV) {      /* Prototype now, and had
+                                          maximum a prototype before. */
+       if (SvTYPE(gv) > SVt_NULL) {
+           if (!SvPOK((SV*)gv) && !(SvIOK((SV*)gv) && SvIVX((SV*)gv) == -1))
+               warn("Runaway prototype");
+           cv_ckproto((CV*)gv, NULL, ps);
+       }
+       if (ps)
+           sv_setpv((SV*)gv, ps);
+       else
+           sv_setiv((SV*)gv, -1);
+       SvREFCNT_dec(compcv);
+       compcv = NULL;
+       sub_generation++;
+       goto noblock;
+    }
+
     if (!name || GvCVGEN(gv))
        cv = Nullcv;
     else if (cv = GvCV(gv)) {
@@ -3327,10 +3400,13 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
                goto done;
            }
            /* ahem, death to those who redefine active sort subs */
-           if (curstack == sortstack && sortcop == CvSTART(cv))
+           if (curstackinfo->si_type == SI_SORT && sortcop == CvSTART(cv))
                croak("Can't redefine active sort subroutine %s", name);
            const_sv = cv_const_sv(cv);
-           if (const_sv || dowarn) {
+           if (const_sv || dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv))
+                                       && HvNAME(GvSTASH(CvGV(cv)))
+                                       && strEQ(HvNAME(GvSTASH(CvGV(cv))),
+                                                "autouse"))) {
                line_t oldline = curcop->cop_line;
                curcop->cop_line = copline;
                warn(const_sv ? "Constant subroutine %s redefined"
@@ -3392,6 +3468,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
        }
     }
     if (!block) {
+      noblock:
        copline = NOLINE;
        LEAVE_SCOPE(floor);
        return cv;
@@ -3460,7 +3537,7 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
            if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr))
                  && (cv = GvCV(db_postponed))) {
                dSP;
-               PUSHMARK(sp);
+               PUSHMARK(SP);
                XPUSHs(tmpstr);
                PUTBACK;
                perl_call_sv((SV*)cv, G_DISCARD);
@@ -3476,7 +3553,6 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
            ENTER;
            SAVESPTR(compiling.cop_filegv);
            SAVEI16(compiling.cop_line);
-           SAVEI32(perldb);
            save_svref(&rs);
            sv_setsv(rs, nrs);
 
@@ -3510,8 +3586,35 @@ newSUB(I32 floor, OP *o, OP *proto, OP *block)
     return cv;
 }
 
+void
+newCONSTSUB(HV *stash, char *name, SV *sv)
+{
+    dTHR;
+    U32 oldhints = hints;
+    HV *old_cop_stash = curcop->cop_stash;
+    HV *old_curstash = curstash;
+    line_t oldline = curcop->cop_line;
+    curcop->cop_line = copline;
+
+    hints &= ~HINT_BLOCK_SCOPE;
+    if(stash)
+       curstash = curcop->cop_stash = stash;
+
+    newSUB(
+       start_subparse(FALSE, 0),
+       newSVOP(OP_CONST, 0, newSVpv(name,0)),
+       newSVOP(OP_CONST, 0, &sv_no),   /* SvPV(&sv_no) == "" -- GMB */
+       newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+    );
+
+    hints = oldhints;
+    curcop->cop_stash = old_cop_stash;
+    curstash = old_curstash;
+    curcop->cop_line = oldline;
+}
+
 CV *
-newXS(char *name, void (*subaddr) (CV *), char *filename)
+newXS(char *name, void (*subaddr) (CV * _CPERLproto), char *filename)
 {
     dTHR;
     GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
@@ -3525,7 +3628,9 @@ newXS(char *name, void (*subaddr) (CV *), char *filename)
        }
        else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) {
            /* already defined (or promised) */
-           if (dowarn) {
+           if (dowarn && !(CvGV(cv) && GvSTASH(CvGV(cv))
+                           && HvNAME(GvSTASH(CvGV(cv)))
+                           && strEQ(HvNAME(GvSTASH(CvGV(cv))), "autouse"))) {
                line_t oldline = curcop->cop_line;
                curcop->cop_line = copline;
                warn("Subroutine %s redefined",name);
@@ -3963,17 +4068,16 @@ ck_rvconst(register OP *o)
          "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use",
                      name, badthing);
        }
-       kid->op_type = OP_GV;
+       /*
+        * This is a little tricky.  We only want to add the symbol if we
+        * didn't add it in the lexer.  Otherwise we get duplicate strict
+        * warnings.  But if we didn't add it in the lexer, we must at
+        * least pretend like we wanted to add it even if it existed before,
+        * or we get possible typo warnings.  OPpCONST_ENTERED says
+        * whether the lexer already added THIS instance of this symbol.
+        */
        iscv = (o->op_type == OP_RV2CV) * 2;
-       for (gv = 0; !gv; iscv++) {
-           /*
-            * This is a little tricky.  We only want to add the symbol if we
-            * didn't add it in the lexer.  Otherwise we get duplicate strict
-            * warnings.  But if we didn't add it in the lexer, we must at
-            * least pretend like we wanted to add it even if it existed before,
-            * or we get possible typo warnings.  OPpCONST_ENTERED says
-            * whether the lexer already added THIS instance of this symbol.
-            */
+       do {
            gv = gv_fetchpv(name,
                iscv | !(kid->op_private & OPpCONST_ENTERED),
                iscv
@@ -3985,9 +4089,12 @@ ck_rvconst(register OP *o)
                            : o->op_type == OP_RV2HV
                                ? SVt_PVHV
                                : SVt_PVGV);
+       } while (!gv && !(kid->op_private & OPpCONST_ENTERED) && !iscv++);
+       if (gv) {
+           kid->op_type = OP_GV;
+           SvREFCNT_dec(kid->op_sv);
+           kid->op_sv = SvREFCNT_inc(gv);
        }
-       SvREFCNT_dec(kid->op_sv);
-       kid->op_sv = SvREFCNT_inc(gv);
     }
     return o;
 }
@@ -4252,7 +4359,7 @@ ck_index(OP *o)
     if (o->op_flags & OPf_KIDS) {
        OP *kid = cLISTOPo->op_first->op_sibling;       /* get past pushmark */
        if (kid && kid->op_type == OP_CONST)
-           fbm_compile(((SVOP*)kid)->op_sv);
+           fbm_compile(((SVOP*)kid)->op_sv, 0);
     }
     return ck_fun(o);
 }
@@ -4739,7 +4846,7 @@ peep(register OP *o)
            goto nothin;
        case OP_NULL:
            if (o->op_targ == OP_NEXTSTATE || o->op_targ == OP_DBSTATE)
-               curcop = ((COP*)op);
+               curcop = ((COP*)o);
            goto nothin;
        case OP_SCALAR:
        case OP_LINESEQ:
@@ -4812,6 +4919,8 @@ peep(register OP *o)
        case OP_AND:
        case OP_OR:
            o->op_seq = op_seqmax++;
+           while (cLOGOP->op_other->op_type == OP_NULL)
+               cLOGOP->op_other = cLOGOP->op_other->op_next;
            peep(cLOGOP->op_other);
            break;
 
@@ -4838,6 +4947,8 @@ peep(register OP *o)
            o->op_seq = op_seqmax++;
            if (dowarn && o->op_next && o->op_next->op_type == OP_NEXTSTATE) {
                if (o->op_next->op_sibling &&
+                       o->op_next->op_sibling->op_type != OP_EXIT &&
+                       o->op_next->op_sibling->op_type != OP_WARN &&
                        o->op_next->op_sibling->op_type != OP_DIE) {
                    line_t oldline = curcop->cop_line;