Test script for DynaLoader
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index 4b73d3f..f5e24fc 100644 (file)
--- a/op.c
+++ b/op.c
@@ -224,13 +224,13 @@ 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 */
 
 PADOFFSET
-Perl_allocmy(pTHX_ char *name)
+Perl_allocmy(pTHX_ const char *const name)
 {
     dVAR;
     PADOFFSET off;
@@ -245,25 +245,11 @@ Perl_allocmy(pTHX_ char *name)
     {
        /* name[2] is true if strlen(name) > 2  */
        if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) {
-           /* 1999-02-27 mjd@plover.com */
-           char *p;
-           p = strchr(name, '\0');
-           /* 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;
-           }
-           else {
-               p[1] = '\0';
-           }
-           /* Move everything else down one character */
-           for (; p-name > 2; p--)
-               *p = *(p-1);
-           name[2] = toCTRL(name[1]);
-           name[1] = '^';
+           yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"my\"",
+                             name[0], toCTRL(name[1]), name + 2));
+       } else {
+           yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
        }
-       yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name));
     }
 
     /* check for duplicate declaration */
@@ -272,7 +258,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 +271,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 +497,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 +1136,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 +1636,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 +1777,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 +1799,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 +1816,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 +2003,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 +2070,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 +2099,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");
            }
        }
@@ -2145,6 +2135,8 @@ Perl_fold_constants(pTHX_ register OP *o)
     int ret = 0;
     I32 oldscope;
     OP *old_next;
+    SV * const oldwarnhook = PL_warnhook;
+    SV * const olddiehook  = PL_diehook;
     dJMPENV;
 
     if (PL_opargs[type] & OA_RETSCALAR)
@@ -2206,6 +2198,8 @@ Perl_fold_constants(pTHX_ register OP *o)
     oldscope = PL_scopestack_ix;
     create_eval_scope(G_FAKINGEVAL);
 
+    PL_warnhook = PERL_WARNHOOK_FATAL;
+    PL_diehook  = NULL;
     JMPENV_PUSH(ret);
 
     switch (ret) {
@@ -2228,10 +2222,15 @@ Perl_fold_constants(pTHX_ register OP *o)
     default:
        JMPENV_POP;
        /* Don't expect 1 (setjmp failed) or 2 (something called my_exit)  */
+       PL_warnhook = oldwarnhook;
+       PL_diehook  = olddiehook;
+       /* XXX note that this croak may fail as we've already blown away
+        * the stack - eg any nested evals */
        Perl_croak(aTHX_ "panic: fold_constants JMPENV_PUSH returned %d", ret);
     }
-
     JMPENV_POP;
+    PL_warnhook = oldwarnhook;
+    PL_diehook  = olddiehook;
 
     if (PL_scopestack_ix > oldscope)
        delete_eval_scope();
@@ -3315,7 +3314,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;
                }
@@ -4384,7 +4383,9 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my)
        cont = append_elem(OP_LINESEQ, cont, unstack);
     }
 
+    assert(block);
     listop = append_list(OP_LINESEQ, (LISTOP*)block, (LISTOP*)cont);
+    assert(listop);
     redo = LINKLIST(listop);
 
     if (expr) {
@@ -4474,7 +4475,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);
        }
@@ -4812,9 +4813,15 @@ Perl_cv_undef(pTHX_ CV *cv)
 }
 
 void
-Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p)
-{
-    if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX_const(cv)))) && ckWARN_d(WARN_PROTOTYPE)) {
+Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p,
+                   const STRLEN len)
+{
+    /* Can't just use a strcmp on the prototype, as CONSTSUBs "cheat" by
+       relying on SvCUR, and doubling up the buffer to hold CvFILE().  */
+    if (((!p != !SvPOK(cv)) /* One has prototype, one has not.  */
+        || (p && (len != SvCUR(cv) /* Not the same length.  */
+                  || memNE(p, SvPVX_const(cv), len))))
+        && ckWARN_d(WARN_PROTOTYPE)) {
        SV* const msg = sv_newmortal();
        SV* name = NULL;
 
@@ -4822,17 +4829,17 @@ Perl_cv_ckproto(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 ");
        if (p)
-           Perl_sv_catpvf(aTHX_ msg, "(%s)", 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);
     }
 }
 
@@ -5034,7 +5041,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            {
                Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "Runaway prototype");
            }
-           cv_ckproto((CV*)gv, NULL, ps);
+           cv_ckproto_len((CV*)gv, NULL, ps, ps_len);
        }
        if (ps)
            sv_setpvn((SV*)gv, ps, ps_len);
@@ -5078,7 +5085,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
          * skipping the prototype check
          */
         if (exists || SvPOK(cv))
-           cv_ckproto(cv, gv, ps);
+           cv_ckproto_len(cv, gv, ps, ps_len);
        /* already defined (or promised)? */
        if (exists || GvASSUMECV(gv)) {
            if ((!block
@@ -5243,7 +5250,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);
                }
            }
        }
@@ -5389,6 +5396,15 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
 {
     dVAR;
     CV* cv;
+#ifdef USE_ITHREADS
+    const char *const temp_p = CopFILE(PL_curcop);
+    const STRLEN len = temp_p ? strlen(temp_p) : 0;
+#else
+    SV *const temp_sv = CopFILESV(PL_curcop);
+    STRLEN len;
+    const char *const temp_p = temp_sv ? SvPV_const(temp_sv, len) : NULL;
+#endif
+    char *const file = savepvn(temp_p, temp_p ? len : 0);
 
     ENTER;
 
@@ -5405,10 +5421,13 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv)
        CopSTASH_set(PL_curcop,stash);
     }
 
-    cv = newXS(name, const_sv_xsub, savepv(CopFILE(PL_curcop)));
+    /* 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.  */
+    cv = newXS_flags(name, const_sv_xsub, file, "", XS_DYNAMIC_FILENAME);
     CvXSUBANY(cv).any_ptr = sv;
     CvCONST_on(cv);
-    sv_setpvn((SV*)cv, "", 0);  /* prototype is "" */
 
 #ifdef USE_ITHREADS
     if (stash)
@@ -5419,10 +5438,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
 */
@@ -5568,7 +5633,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);
@@ -6074,8 +6139,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
@@ -6125,7 +6190,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;
@@ -6233,7 +6298,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
@@ -6256,7 +6321,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
@@ -6337,6 +6402,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) {
@@ -6346,10 +6412,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_
@@ -6503,7 +6569,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 */
@@ -6733,6 +6799,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;
 }
 
@@ -6741,7 +6817,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;
@@ -7171,6 +7247,7 @@ Perl_ck_split(pTHX_ OP *o)
 
     if (!kid->op_sibling)
        append_elem(OP_SPLIT, o, newSVOP(OP_CONST, 0, newSViv(0)));
+    assert(kid->op_sibling);
 
     kid = kid->op_sibling;
     scalar(kid);
@@ -7205,7 +7282,8 @@ Perl_ck_subr(pTHX_ OP *o)
             ? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first;
     OP *o2 = prev->op_sibling;
     OP *cvop;
-    char *proto = NULL;
+    const char *proto = NULL;
+    const char *proto_end = NULL;
     CV *cv = NULL;
     GV *namegv = NULL;
     int optional = 0;
@@ -7228,8 +7306,10 @@ Perl_ck_subr(pTHX_ OP *o)
                tmpop->op_private |= OPpEARLY_CV;
            else {
                if (SvPOK(cv)) {
+                   STRLEN len;
                    namegv = CvANON(cv) ? gv : CvGV(cv);
-                   proto = SvPV_nolen((SV*)cv);
+                   proto = SvPV((SV*)cv, len);
+                   proto_end = proto + len;
                }
                if (CvASSERTION(cv)) {
                    if (PL_hints & HINT_ASSERTING) {
@@ -7266,9 +7346,10 @@ Perl_ck_subr(pTHX_ OP *o)
        else
            o3 = o2;
        if (proto) {
-           switch (*proto) {
-           case '\0':
+           if (proto >= proto_end)
                return too_many_arguments(o, gv_ename(namegv));
+
+           switch (*proto) {
            case ';':
                optional = 1;
                proto++;
@@ -7351,15 +7432,13 @@ Perl_ck_subr(pTHX_ OP *o)
                     break;
                case ']':
                     if (contextclass) {
-                        /* XXX We shouldn't be modifying proto, so we can const proto */
-                        char *p = proto;
-                        const char s = *p;
+                        const char *p = proto;
+                        const char *const end = proto;
                         contextclass = 0;
-                        *p = '\0';
                         while (*--p != '[');
-                        bad_type(arg, Perl_form(aTHX_ "one of %s", p),
-                                gv_ename(namegv), o3);
-                        *proto = s;
+                        bad_type(arg, Perl_form(aTHX_ "one of %.*s",
+                                                (int)(end - p), p),
+                                 gv_ename(namegv), o3);
                     } else
                          goto oops;
                     break;
@@ -7425,7 +7504,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
@@ -7434,8 +7513,8 @@ Perl_ck_subr(pTHX_ OP *o)
        prev = o2;
        o2 = o2->op_sibling;
     } /* while */
-    if (proto && !optional &&
-         (*proto && *proto != '@' && *proto != '%' && *proto != ';'))
+    if (proto && !optional && proto_end > proto &&
+       (*proto != '@' && *proto != '%' && *proto != ';'))
        return too_few_arguments(o, gv_ename(namegv));
     if(delete_op) {
 #ifdef PERL_MAD
@@ -7696,7 +7775,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
@@ -7792,7 +7871,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;
@@ -7812,7 +7891,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", 
@@ -7869,7 +7948,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",
@@ -8198,7 +8277,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)));