-/* $RCSfile: op.c,v $$Revision: 4.1 $$Date: 92/08/07 17:19:16 $
+/* scope.c
*
- * Copyright (c) 1991, Larry Wall
+ * Copyright (c) 1991-1994, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
- * $Log: op.c,v $
+ */
+
+/*
+ * "For the fashion of Minas Tirith was such that it was built on seven
+ * levels..."
*/
#include "EXTERN.h"
#include "perl.h"
+SV**
+stack_grow(sp, p, n)
+SV** sp;
+SV** p;
+int n;
+{
+ stack_sp = sp;
+ av_extend(stack, (p - stack_base) + (n) + 128);
+ return stack_sp;
+}
+
I32
cxinc()
{
cxstack_max = cxstack_max * 3 / 2;
- Renew(cxstack, cxstack_max, CONTEXT);
+ Renew(cxstack, cxstack_max + 1, CONTEXT); /* XXX should fix CXINC macro */
return cxstack_ix + 1;
}
}
void
+markstack_grow()
+{
+ I32 oldmax = markstack_max - markstack;
+ I32 newmax = oldmax * 3 / 2;
+
+ Renew(markstack, newmax, I32);
+ markstack_ptr = markstack + oldmax;
+ markstack_max = markstack + newmax;
+}
+
+void
savestack_grow()
{
savestack_max = savestack_max * 3 / 2;
SSPUSHINT(SAVEt_SV);
sv = GvSV(gv) = NEWSV(0,0);
- if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv)) {
+ if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv) && SvTYPE(osv) != SVt_PVGV) {
sv_upgrade(sv, SvTYPE(osv));
- mg_get(osv);
- SvFLAGS(osv) |= (SvFLAGS(osv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+ if (SvGMAGICAL(osv)) {
+ MAGIC* mg;
+ bool oldtainted = tainted;
+ mg_get(osv);
+ if (tainting && tainted && (mg = mg_find(osv, 't'))) {
+ SAVESPTR(mg->mg_obj);
+ mg->mg_obj = osv;
+ }
+ SvFLAGS(osv) |= (SvFLAGS(osv) &
+ (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+ tainted = oldtainted;
+ }
SvMAGIC(sv) = SvMAGIC(osv);
- localizing = TRUE;
+ SvFLAGS(sv) |= SvMAGICAL(osv);
+ localizing = 1;
SvSETMAGIC(sv);
- localizing = FALSE;
+ localizing = 0;
}
return sv;
}
GP *ogp = GvGP(gv);
SSCHECK(3);
- SSPUSHPTR(gv);
+ SSPUSHPTR(SvREFCNT_inc(gv));
SSPUSHPTR(ogp);
SSPUSHINT(SAVEt_GP);
SSPUSHINT(SAVEt_SVREF);
sv = *sptr = NEWSV(0,0);
- if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(sv)) {
+ if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv) && SvTYPE(osv) != SVt_PVGV) {
sv_upgrade(sv, SvTYPE(osv));
+ if (SvGMAGICAL(osv)) {
+ MAGIC* mg;
+ bool oldtainted = tainted;
+ mg_get(osv);
+ if (tainting && tainted && (mg = mg_find(osv, 't'))) {
+ SAVESPTR(mg->mg_obj);
+ mg->mg_obj = osv;
+ }
+ SvFLAGS(osv) |= (SvFLAGS(osv) &
+ (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+ tainted = oldtainted;
+ }
SvMAGIC(sv) = SvMAGIC(osv);
- localizing = TRUE;
+ SvFLAGS(sv) |= SvMAGICAL(osv);
+ localizing = 1;
SvSETMAGIC(sv);
- localizing = FALSE;
+ localizing = 0;
}
return sv;
}
SSPUSHINT(SAVEt_I32);
}
+void
+save_iv(ivp)
+IV *ivp;
+{
+ SSCHECK(3);
+ SSPUSHIV(*ivp);
+ SSPUSHPTR(ivp);
+ SSPUSHINT(SAVEt_IV);
+}
+
/* Cannot use save_sptr() to store a char* since the SV** cast will
* force word-alignment and we'll miss the pointer.
*/
SV** svp;
{
SSCHECK(2);
- SSPUSHPTR(svp);
+ SSPUSHLONG((long)(svp-curpad));
SSPUSHINT(SAVEt_CLEARSV);
}
}
void
+save_destructor(f,p)
+void (*f) _((void*));
+void* p;
+{
+ SSCHECK(3);
+ SSPUSHDPTR(f);
+ SSPUSHPTR(p);
+ SSPUSHINT(SAVEt_DESTRUCTOR);
+}
+
+void
leave_scope(base)
I32 base;
{
value = (SV*)SSPOPPTR;
sv = (SV*)SSPOPPTR;
sv_replace(sv,value);
+ localizing = 2;
SvSETMAGIC(sv);
+ localizing = 0;
break;
case SAVEt_SV: /* scalar reference */
value = (SV*)SSPOPPTR;
gv = (GV*)SSPOPPTR;
sv = GvSV(gv);
- if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv) &&
+ SvTYPE(sv) != SVt_PVGV)
+ {
+ (void)SvUPGRADE(value, SvTYPE(sv));
SvMAGIC(value) = SvMAGIC(sv);
+ SvFLAGS(value) |= SvMAGICAL(sv);
+ SvMAGICAL_off(sv);
SvMAGIC(sv) = 0;
}
SvREFCNT_dec(sv);
- GvSV(gv) = sv = value;
- SvSETMAGIC(sv);
+ GvSV(gv) = value;
+ localizing = 2;
+ SvSETMAGIC(value);
+ localizing = 0;
break;
case SAVEt_SVREF: /* scalar reference */
ptr = SSPOPPTR;
sv = *(SV**)ptr;
- if (SvTYPE(sv) >= SVt_PVMG)
+ value = (SV*)SSPOPPTR;
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv) &&
+ SvTYPE(sv) != SVt_PVGV)
+ {
+ (void)SvUPGRADE(value, SvTYPE(sv));
+ SvMAGIC(value) = SvMAGIC(sv);
+ SvFLAGS(value) |= SvMAGICAL(sv);
+ SvMAGICAL_off(sv);
SvMAGIC(sv) = 0;
+ }
SvREFCNT_dec(sv);
- *(SV**)ptr = sv = (SV*)SSPOPPTR;
- SvSETMAGIC(sv);
+ *(SV**)ptr = value;
+ localizing = 2;
+ SvSETMAGIC(value);
+ localizing = 0;
break;
case SAVEt_AV: /* array reference */
av = (AV*)SSPOPPTR;
ptr = SSPOPPTR;
*(I32*)ptr = (I32)SSPOPINT;
break;
+ case SAVEt_IV: /* IV reference */
+ ptr = SSPOPPTR;
+ *(IV*)ptr = (IV)SSPOPIV;
+ break;
case SAVEt_SPTR: /* SV* reference */
ptr = SSPOPPTR;
*(SV**)ptr = (SV*)SSPOPPTR;
gv = (GV*)SSPOPPTR;
gp_free(gv);
GvGP(gv) = (GP*)ptr;
+ SvREFCNT_dec(gv);
break;
case SAVEt_FREESV:
ptr = SSPOPPTR;
Safefree((char*)ptr);
break;
case SAVEt_CLEARSV:
- ptr = SSPOPPTR;
+ ptr = (void*)&curpad[SSPOPLONG];
sv = *(SV**)ptr;
- if (SvREFCNT(sv) <= 1) { /* Can clear pad variable in place. */
+ if (SvREFCNT(sv) <= 1) { /* Can clear pad variable in place. */
if (SvTHINKFIRST(sv)) {
if (SvREADONLY(sv))
croak("panic: leave_scope clearsv");
if (SvROK(sv))
sv_unref(sv);
}
+ if (SvMAGICAL(sv))
+ mg_free(sv);
switch (SvTYPE(sv)) {
case SVt_NULL:
break;
default:
if (SvPOK(sv) && SvLEN(sv))
- SvOOK_off(sv);
- SvOK_off(sv);
- SvSETMAGIC(sv);
+ (void)SvOOK_off(sv);
+ (void)SvOK_off(sv);
break;
}
}
else { /* Someone has a claim on this, so abandon it. */
+ U32 padflags = SvFLAGS(sv) & (SVs_PADBUSY|SVs_PADMY|SVs_PADTMP);
SvREFCNT_dec(sv); /* Cast current value to the winds. */
switch (SvTYPE(sv)) { /* Console ourselves with a new value */
case SVt_PVAV: *(SV**)ptr = (SV*)newAV(); break;
case SVt_PVHV: *(SV**)ptr = (SV*)newHV(); break;
default: *(SV**)ptr = NEWSV(0,0); break;
}
+ SvFLAGS(*(SV**)ptr) |= padflags; /* preserve pad nature */
}
break;
case SAVEt_DELETE:
ptr = SSPOPPTR;
hv = (HV*)ptr;
ptr = SSPOPPTR;
- hv_delete(hv, (char*)ptr, (U32)SSPOPINT);
+ (void)hv_delete(hv, (char*)ptr, (U32)SSPOPINT, G_DISCARD);
+ Safefree(ptr);
+ break;
+ case SAVEt_DESTRUCTOR:
+ ptr = SSPOPPTR;
+ (*SSPOPDPTR)(ptr);
+ break;
+ case SAVEt_REGCONTEXT:
+ {
+ I32 delta = SSPOPINT;
+ savestack_ix -= delta; /* regexp must have croaked */
+ }
break;
default:
croak("panic: leave_scope inconsistency");
case CXt_EVAL:
fprintf(stderr, "BLK_EVAL.OLD_IN_EVAL = %ld\n",
(long)cx->blk_eval.old_in_eval);
- fprintf(stderr, "BLK_EVAL.OLD_OP_TYPE = %s\n",
- op_name[cx->blk_eval.old_op_type]);
+ fprintf(stderr, "BLK_EVAL.OLD_OP_TYPE = %s (%s)\n",
+ op_name[cx->blk_eval.old_op_type],
+ op_desc[cx->blk_eval.old_op_type]);
fprintf(stderr, "BLK_EVAL.OLD_NAME = %s\n",
cx->blk_eval.old_name);
fprintf(stderr, "BLK_EVAL.OLD_EVAL_ROOT = 0x%lx\n",