Ressurect change 27824, which plugs a resource leak in uncalled code.
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index ec4cb3a..30231d3 100644 (file)
--- a/op.c
+++ b/op.c
@@ -224,7 +224,7 @@ S_no_bareword_allowed(pTHX_ const OP *o)
        return;         /* various ok barewords are hidden in extra OP_NULL */
     qerror(Perl_mess(aTHX_
                     "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use",
-                    cSVOPo_sv));
+                    (void*)cSVOPo_sv));
 }
 
 /* "register" allocation */
@@ -248,11 +248,16 @@ Perl_allocmy(pTHX_ char *name)
            /* 1999-02-27 mjd@plover.com */
            char *p;
            p = strchr(name, '\0');
+           assert(p);
            /* The next block assumes the buffer is at least 205 chars
               long.  At present, it's always at least 256 chars. */
-           if (p-name > 200) {
-               strcpy(name+200, "...");
-               p = name+199;
+           if (p - name > 200) {
+#ifdef HAS_STRLCPY
+               strlcpy(name + 200, "...", 4);
+#else
+               strcpy(name + 200, "...");
+#endif
+               p = name + 199;
            }
            else {
                p[1] = '\0';
@@ -272,7 +277,8 @@ Perl_allocmy(pTHX_ char *name)
     if (PL_in_my_stash && *name != '$') {
        yyerror(Perl_form(aTHX_
                    "Can't declare class for non-scalar %s in \"%s\"",
-                    name, is_our ? "our" : "my"));
+                    name,
+                    is_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
     }
 
     /* allocate a spare slot and store the name in that slot */
@@ -284,7 +290,8 @@ Perl_allocmy(pTHX_ char *name)
                        ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash)
                        : NULL
                    ),
-                   0 /*  not fake */
+                   0, /*  not fake */
+                   PL_in_my == KEY_state
     );
     return off;
 }
@@ -509,7 +516,7 @@ S_cop_free(pTHX_ COP* cop)
        PerlMemShared_free(cop->cop_warnings);
     if (! specialCopIO(cop->cop_io)) {
 #ifdef USE_ITHREADS
-       /*EMPTY*/
+       NOOP;
 #else
        SvREFCNT_dec(cop->cop_io);
 #endif
@@ -1148,15 +1155,14 @@ Perl_mod(pTHX_ OP *o, I32 type)
                CV *cv;
                OP *okid;
 
-               if (kid->op_type == OP_PUSHMARK)
-                   goto skip_kids;
-               if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST)
-                   Perl_croak(aTHX_
-                              "panic: unexpected lvalue entersub "
-                              "args: type/targ %ld:%"UVuf,
-                              (long)kid->op_type, (UV)kid->op_targ);
-               kid = kLISTOP->op_first;
-             skip_kids:
+               if (kid->op_type != OP_PUSHMARK) {
+                   if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST)
+                       Perl_croak(aTHX_
+                               "panic: unexpected lvalue entersub "
+                               "args: type/targ %ld:%"UVuf,
+                               (long)kid->op_type, (UV)kid->op_targ);
+                   kid = kLISTOP->op_first;
+               }
                while (kid->op_sibling)
                    kid = kid->op_sibling;
                if (!(kid->op_type == OP_NULL && kid->op_targ == OP_RV2CV)) {
@@ -1649,7 +1655,7 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
        /* Don't force the C<use> if we don't need it. */
        SV * const * const svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE);
        if (svp && *svp != &PL_sv_undef)
-           /*EMPTY*/;          /* already in %INC */
+           NOOP;       /* already in %INC */
        else
            Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
                             newSVpvs(ATTRSMODULE), NULL);
@@ -1790,7 +1796,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
               type == OP_RV2HV) { /* XXX does this let anything illegal in? */
        if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */
            yyerror(Perl_form(aTHX_ "Can't declare %s in %s",
-                       OP_DESC(o), PL_in_my == KEY_our ? "our" : "my"));
+                       OP_DESC(o),
+                       PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
        } else if (attrs) {
            GV * const gv = cGVOPx_gv(cUNOPo->op_first);
            PL_in_my = FALSE;
@@ -1811,7 +1818,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
     {
        yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
                          OP_DESC(o),
-                         PL_in_my == KEY_our ? "our" : "my"));
+                         PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my"));
        return o;
     }
     else if (attrs && type != OP_PUSHMARK) {
@@ -1828,6 +1835,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
     }
     o->op_flags |= OPf_MOD;
     o->op_private |= OPpLVAL_INTRO;
+    if (PL_in_my == KEY_state)
+       o->op_private |= OPpPAD_STATE;
     return o;
 }
 
@@ -2013,7 +2022,7 @@ STATIC OP *
 S_newDEFSVOP(pTHX)
 {
     dVAR;
-    const I32 offset = pad_findmy("$_");
+    const PADOFFSET offset = pad_findmy("$_");
     if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) {
        return newSVREF(newGVOP(OP_GV, 0, PL_defgv));
     }
@@ -2080,7 +2089,7 @@ Perl_localize(pTHX_ OP *o, I32 lex)
 #if 0
        list(o);
 #else
-       /*EMPTY*/;
+       NOOP;
 #endif
     else {
        if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ','
@@ -2109,7 +2118,7 @@ Perl_localize(pTHX_ OP *o, I32 lex)
            if (sigil && (*s == ';' || *s == '=')) {
                Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS),
                                "Parentheses missing around \"%s\" list",
-                               lex ? (PL_in_my == KEY_our ? "our" : "my")
+                               lex ? (PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")
                                : "local");
            }
        }
@@ -2219,6 +2228,11 @@ Perl_fold_constants(pTHX_ register OP *o)
            SvTEMP_off(sv);
        }
        break;
+    case 2:
+       /* my_exit() was called; propagate it */
+       JMPENV_POP;
+       JMPENV_JUMP(2);
+       /* NOTREACHED */
     case 3:
        /* Something tried to die.  Abandon constant folding.  */
        /* Pretend the error never happened.  */
@@ -2227,7 +2241,7 @@ Perl_fold_constants(pTHX_ register OP *o)
        break;
     default:
        JMPENV_POP;
-       /* Don't expect 1 (setjmp failed) or 2 (something called my_exit)  */
+       /* Don't expect 1 (setjmp failed) */
        Perl_croak(aTHX_ "panic: fold_constants JMPENV_PUSH returned %d", ret);
     }
 
@@ -3315,7 +3329,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
                        repl_has_vars = 1;
                    }
                    else if (curop->op_type == OP_PUSHRE)
-                       /*EMPTY*/; /* Okay here, dangerous in newASSIGNOP */
+                       NOOP; /* Okay here, dangerous in newASSIGNOP */
                    else
                        break;
                }
@@ -4476,7 +4490,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
            iterpflags |= OPpITER_DEF;
     }
     else {
-        const I32 offset = pad_findmy("$_");
+        const PADOFFSET offset = pad_findmy("$_");
        if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) {
            sv = newGVOP(OP_GV, 0, PL_defgv);
        }
@@ -4830,9 +4844,9 @@ Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
            gv_efullname3(name = sv_newmortal(), gv, NULL);
        sv_setpv(msg, "Prototype mismatch:");
        if (name)
-           Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name);
+           Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, (void*)name);
        if (SvPOK(cv))
-           Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv);
+           Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (void*)cv);
        else
            sv_catpvs(msg, ": none");
        sv_catpvs(msg, " vs ");
@@ -4840,7 +4854,7 @@ Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
            Perl_sv_catpvf(aTHX_ msg, "(%.*s)", (int) len, p);
        else
            sv_catpvs(msg, "none");
-       Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, msg);
+       Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, (void*)msg);
     }
 }
 
@@ -5251,7 +5265,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                else {
                    /* force display of errors found but not reported */
                    sv_catpv(ERRSV, not_safe);
-                   Perl_croak(aTHX_ "%"SVf, ERRSV);
+                   Perl_croak(aTHX_ "%"SVf, (void*)ERRSV);
                }
            }
        }
@@ -5425,15 +5439,10 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
     /* file becomes the CvFILE. For an XS, it's supposed to be static storage,
        and so doesn't get free()d.  (It's expected to be from the C pre-
        processor __FILE__ directive). But we need a dynamically allocated one,
-       and we need it to get freed.  So we cheat, and take advantage of the
-       fact that the first 0 bytes of any string always look the same.  */
-    cv = newXS(name, const_sv_xsub, file);
+       and we need it to get freed.  */
+    cv = newXS_flags(name, const_sv_xsub, file, "", XS_DYNAMIC_FILENAME);
     CvXSUBANY(cv).any_ptr = sv;
     CvCONST_on(cv);
-    /* prototype is "".  But this gets free()d.  :-)  */
-    sv_usepvn_flags((SV*)cv, file, len, SV_HAS_TRAILING_NUL); 
-    /* This gives us a prototype of "", rather than the file name.  */
-    SvCUR_set(cv, 0);
 
 #ifdef USE_ITHREADS
     if (stash)
@@ -5444,10 +5453,56 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
     return cv;
 }
 
+CV *
+Perl_newXS_flags(pTHX_ const char *name, XSUBADDR_t subaddr,
+                const char *const filename, const char *const proto,
+                U32 flags)
+{
+    CV *cv = newXS(name, subaddr, filename);
+
+    if (flags & XS_DYNAMIC_FILENAME) {
+       /* We need to "make arrangements" (ie cheat) to ensure that the
+          filename lasts as long as the PVCV we just created, but also doesn't
+          leak  */
+       STRLEN filename_len = strlen(filename);
+       STRLEN proto_and_file_len = filename_len;
+       char *proto_and_file;
+       STRLEN proto_len;
+
+       if (proto) {
+           proto_len = strlen(proto);
+           proto_and_file_len += proto_len;
+
+           Newx(proto_and_file, proto_and_file_len + 1, char);
+           Copy(proto, proto_and_file, proto_len, char);
+           Copy(filename, proto_and_file + proto_len, filename_len + 1, char);
+       } else {
+           proto_len = 0;
+           proto_and_file = savepvn(filename, filename_len);
+       }
+
+       /* This gets free()d.  :-)  */
+       sv_usepvn_flags((SV*)cv, proto_and_file, proto_and_file_len,
+                       SV_HAS_TRAILING_NUL);
+       if (proto) {
+           /* This gives us the correct prototype, rather than one with the
+              file name appended.  */
+           SvCUR_set(cv, proto_len);
+       } else {
+           SvPOK_off(cv);
+       }
+       CvFILE(cv) = proto_and_file + proto_len;
+    } else {
+       sv_setpv((SV *)cv, proto);
+    }
+    return cv;
+}
+
 /*
 =for apidoc U||newXS
 
-Used by C<xsubpp> to hook up XSUBs as Perl subs.
+Used by C<xsubpp> to hook up XSUBs as Perl subs.  I<filename> needs to be
+static storage, as it is used directly as CvFILE(), without a copy being made.
 
 =cut
 */
@@ -5593,7 +5648,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
                CopLINE_set(PL_curcop, PL_copline);
            Perl_warner(aTHX_ packWARN(WARN_REDEFINE),
                        o ? "Format %"SVf" redefined"
-                       : "Format STDOUT redefined" ,cSVOPo->op_sv);
+                       : "Format STDOUT redefined", (void*)cSVOPo->op_sv);
            CopLINE_set(PL_curcop, oldline);
        }
        SvREFCNT_dec(cv);
@@ -6099,8 +6154,8 @@ Perl_ck_rvconst(pTHX_ register OP *o)
            }
            if (badthing)
                Perl_croak(aTHX_
-         "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use",
-                     kidsv, badthing);
+                          "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use",
+                          (void*)kidsv, badthing);
        }
        /*
         * This is a little tricky.  We only want to add the symbol if we
@@ -6150,7 +6205,7 @@ Perl_ck_ftst(pTHX_ OP *o)
     const I32 type = o->op_type;
 
     if (o->op_flags & OPf_REF) {
-       /*EMPTY*/;
+       NOOP;
     }
     else if (o->op_flags & OPf_KIDS && cUNOPo->op_first->op_type != OP_STUB) {
        SVOP * const kid = (SVOP*)cUNOPo->op_first;
@@ -6258,7 +6313,7 @@ Perl_ck_fun(pTHX_ OP *o)
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
                            "Array @%"SVf" missing the @ in argument %"IVdf" of %s()",
-                           ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
+                           (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
 #ifdef PERL_MAD
                    op_getmad(kid,newop,'K');
 #else
@@ -6281,7 +6336,7 @@ Perl_ck_fun(pTHX_ OP *o)
                    if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
                        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
                            "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()",
-                           ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
+                           (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]);
 #ifdef PERL_MAD
                    op_getmad(kid,newop,'K');
 #else
@@ -6362,6 +6417,7 @@ Perl_ck_fun(pTHX_ OP *o)
                            else if (kid->op_type == OP_AELEM
                                     || kid->op_type == OP_HELEM)
                            {
+                                OP *firstop;
                                 OP *op = ((BINOP*)kid)->op_first;
                                 name = NULL;
                                 if (op) {
@@ -6371,10 +6427,10 @@ Perl_ck_fun(pTHX_ OP *o)
                                           "[]" : "{}";
                                      if (((op->op_type == OP_RV2AV) ||
                                           (op->op_type == OP_RV2HV)) &&
-                                         (op = ((UNOP*)op)->op_first) &&
-                                         (op->op_type == OP_GV)) {
+                                         (firstop = ((UNOP*)op)->op_first) &&
+                                         (firstop->op_type == OP_GV)) {
                                           /* packagevar $a[] or $h{} */
-                                          GV * const gv = cGVOPx_gv(op);
+                                          GV * const gv = cGVOPx_gv(firstop);
                                           if (gv)
                                                tmpstr =
                                                     Perl_newSVpvf(aTHX_
@@ -6528,7 +6584,7 @@ Perl_ck_grep(pTHX_ OP *o)
     LOGOP *gwop = NULL;
     OP *kid;
     const OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE;
-    I32 offset;
+    PADOFFSET offset;
 
     o->op_ppaddr = PL_ppaddr[OP_GREPSTART];
     /* don't allocate gwop here, as we may leak it if PL_error_count > 0 */
@@ -6758,6 +6814,16 @@ Perl_ck_sassign(pTHX_ OP *o)
            return kid;
        }
     }
+    if (kid->op_sibling) {
+       OP *kkid = kid->op_sibling;
+       if (kkid->op_type == OP_PADSV
+               && (kkid->op_private & OPpLVAL_INTRO)
+               && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) {
+           o->op_private |= OPpASSIGN_STATE;
+           /* hijacking PADSTALE for uninitialized state variables */
+           SvPADSTALE_on(PAD_SVl(kkid->op_targ));
+       }
+    }
     return o;
 }
 
@@ -6766,7 +6832,7 @@ Perl_ck_match(pTHX_ OP *o)
 {
     dVAR;
     if (o->op_type != OP_QR && PL_compcv) {
-       const I32 offset = pad_findmy("$_");
+       const PADOFFSET offset = pad_findmy("$_");
        if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) {
            o->op_targ = offset;
            o->op_private |= OPpTARGET_MY;
@@ -7453,7 +7519,7 @@ Perl_ck_subr(pTHX_ OP *o)
            default:
              oops:
                Perl_croak(aTHX_ "Malformed prototype for %s: %"SVf,
-                          gv_ename(namegv), cv);
+                          gv_ename(namegv), (void*)cv);
            }
        }
        else
@@ -7724,7 +7790,7 @@ Perl_peep(pTHX_ register OP *o)
                    gv_efullname3(sv, gv, NULL);
                    Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
                                "%"SVf"() called too early to check prototype",
-                               sv);
+                               (void*)sv);
                }
            }
            else if (o->op_next->op_type == OP_READLINE
@@ -7820,7 +7886,7 @@ Perl_peep(pTHX_ register OP *o)
            if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) {
                key = SvPV_const(sv, keylen);
                lexname = newSVpvn_share(key,
-                                        SvUTF8(sv) ? -(I32)keylen : keylen,
+                                        SvUTF8(sv) ? -(I32)keylen : (I32)keylen,
                                         0);
                SvREFCNT_dec(sv);
                *svp = lexname;
@@ -7840,7 +7906,7 @@ Perl_peep(pTHX_ register OP *o)
                break;
            key = SvPV_const(*svp, keylen);
            if (!hv_fetch(GvHV(*fields), key,
-                       SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE))
+                       SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
            {
                Perl_croak(aTHX_ "No such class field \"%s\" " 
                           "in variable %s of type %s", 
@@ -7897,7 +7963,7 @@ Perl_peep(pTHX_ register OP *o)
                svp = cSVOPx_svp(key_op);
                key = SvPV_const(*svp, keylen);
                if (!hv_fetch(GvHV(*fields), key, 
-                           SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE))
+                           SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
                {
                    Perl_croak(aTHX_ "No such class field \"%s\" "
                               "in variable %s of type %s",
@@ -8226,7 +8292,7 @@ const_sv_xsub(pTHX_ CV* cv)
     dVAR;
     dXSARGS;
     if (items != 0) {
-       /*EMPTY*/;
+       NOOP;
 #if 0
         Perl_croak(aTHX_ "usage: %s::%s()",
                    HvNAME_get(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv)));