X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=2906a4c17311952e4b1fbda317ec60cca767a8df;hb=606932feba6a7c07d368ce4e766975b0fe622bfc;hp=9dfbd4ffb19c0812e5b28b9179783f317241931e;hpb=8b73bbec3102cdf25a35c954eb1aab85acc07808;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index 9dfbd4f..2906a4c 100644 --- a/mg.c +++ b/mg.c @@ -26,34 +26,38 @@ # endif #endif +#ifdef PERL_OBJECT +# define VTBL this->*vtbl +#else +# define VTBL *vtbl +static void restore_magic _((void *p)); +static int magic_methcall(SV *sv, MAGIC *mg, char *meth, I32 f, int n, SV *val); +#endif + /* * Use the "DESTRUCTOR" scope cleanup to reinstate magic. */ -#ifdef PERL_OBJECT - -#define VTBL this->*vtbl - -#else struct magic_state { SV* mgs_sv; U32 mgs_flags; + I32 mgs_ss_ix; }; -typedef struct magic_state MGS; - -static void restore_magic _((void *p)); -#define VTBL *vtbl - -#endif +/* MGS is typedef'ed to struct magic_state in perl.h */ STATIC void -save_magic(MGS *mgs, SV *sv) +save_magic(I32 mgs_ix, SV *sv) { + dTHR; + MGS* mgs; assert(SvMAGICAL(sv)); + SAVEDESTRUCTOR(restore_magic, (void*)mgs_ix); + + mgs = SSPTR(mgs_ix, MGS*); mgs->mgs_sv = sv; mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv); - SAVEDESTRUCTOR(restore_magic, mgs); + mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */ SvMAGICAL_off(sv); SvREADONLY_off(sv); @@ -63,9 +67,13 @@ save_magic(MGS *mgs, SV *sv) STATIC void restore_magic(void *p) { - MGS* mgs = (MGS*)p; + dTHR; + MGS* mgs = SSPTR((I32)p, MGS*); SV* sv = mgs->mgs_sv; + if (!sv) + return; + if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { if (mgs->mgs_flags) @@ -75,6 +83,27 @@ restore_magic(void *p) if (SvGMAGICAL(sv)) SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); } + + mgs->mgs_sv = NULL; /* mark the MGS structure as restored */ + + /* If we're still on top of the stack, pop us off. (That condition + * will be satisfied if restore_magic was called explicitly, but *not* + * if it's being called via leave_scope.) + * The reason for doing this is that otherwise, things like sv_2cv() + * may leave alloc gunk on the savestack, and some code + * (e.g. sighandler) doesn't expect that... + */ + if (PL_savestack_ix == mgs->mgs_ss_ix) + { + I32 popval = SSPOPINT; + assert(popval == SAVEt_DESTRUCTOR); + PL_savestack_ix -= 2; + popval = SSPOPINT; + assert(popval == SAVEt_ALLOC); + popval = SSPOPINT; + PL_savestack_ix -= popval; + } + } void @@ -97,13 +126,14 @@ mg_magical(SV *sv) int mg_get(SV *sv) { - MGS mgs; + dTHR; + I32 mgs_ix; MAGIC* mg; MAGIC** mgp; int mgp_valid = 0; - ENTER; - save_magic(&mgs, sv); + mgs_ix = SSNEW(sizeof(MGS)); + save_magic(mgs_ix, sv); mgp = &SvMAGIC(sv); while ((mg = *mgp) != 0) { @@ -113,7 +143,7 @@ mg_get(SV *sv) /* Ignore this magic if it's been deleted */ if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) && (mg->mg_flags & MGf_GSKIP)) - mgs.mgs_flags = 0; + (SSPTR(mgs_ix, MGS*))->mgs_flags = 0; } /* Advance to next magic (complicated by possible deletion) */ if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) { @@ -124,32 +154,33 @@ mg_get(SV *sv) mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */ } - LEAVE; + restore_magic((void*)mgs_ix); return 0; } int mg_set(SV *sv) { - MGS mgs; + dTHR; + I32 mgs_ix; MAGIC* mg; MAGIC* nextmg; - ENTER; - save_magic(&mgs, sv); + mgs_ix = SSNEW(sizeof(MGS)); + save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = nextmg) { MGVTBL* vtbl = mg->mg_virtual; nextmg = mg->mg_moremagic; /* it may delete itself */ if (mg->mg_flags & MGf_GSKIP) { mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */ - mgs.mgs_flags = 0; + (SSPTR(mgs_ix, MGS*))->mgs_flags = 0; } if (vtbl && (vtbl->svt_set != NULL)) (VTBL->svt_set)(sv, mg); } - LEAVE; + restore_magic((void*)mgs_ix); return 0; } @@ -163,13 +194,13 @@ mg_length(SV *sv) for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { MGVTBL* vtbl = mg->mg_virtual; if (vtbl && (vtbl->svt_len != NULL)) { - MGS mgs; + I32 mgs_ix; - ENTER; - save_magic(&mgs, sv); + mgs_ix = SSNEW(sizeof(MGS)); + save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = (VTBL->svt_len)(sv, mg); - LEAVE; + restore_magic((void*)mgs_ix); return len; } } @@ -187,11 +218,13 @@ mg_size(SV *sv) for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { MGVTBL* vtbl = mg->mg_virtual; if (vtbl && (vtbl->svt_len != NULL)) { - MGS mgs; - ENTER; + I32 mgs_ix; + + mgs_ix = SSNEW(sizeof(MGS)); + save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = (VTBL->svt_len)(sv, mg); - LEAVE; + restore_magic((void*)mgs_ix); return len; } } @@ -212,11 +245,11 @@ mg_size(SV *sv) int mg_clear(SV *sv) { - MGS mgs; + I32 mgs_ix; MAGIC* mg; - ENTER; - save_magic(&mgs, sv); + mgs_ix = SSNEW(sizeof(MGS)); + save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { MGVTBL* vtbl = mg->mg_virtual; @@ -226,7 +259,7 @@ mg_clear(SV *sv) (VTBL->svt_clear)(sv, mg); } - LEAVE; + restore_magic((void*)mgs_ix); return 0; } @@ -248,7 +281,9 @@ mg_copy(SV *sv, SV *nsv, char *key, I32 klen) MAGIC* mg; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { if (isUPPER(mg->mg_type)) { - sv_magic(nsv, mg->mg_obj, toLOWER(mg->mg_type), key, klen); + sv_magic(nsv, + mg->mg_type == 'P' ? SvTIED_obj(sv, mg) : mg->mg_obj, + toLOWER(mg->mg_type), key, klen); count++; } } @@ -283,6 +318,48 @@ mg_free(SV *sv) #endif U32 +magic_regdata_cnt(SV *sv, MAGIC *mg) +{ + dTHR; + register char *s; + register I32 i; + register REGEXP *rx; + char *t; + + if (PL_curpm && (rx = PL_curpm->op_pmregexp)) + return rx->lastparen; + return (U32)-1; +} + +int +magic_regdatum_get(SV *sv, MAGIC *mg) +{ + dTHR; + register I32 paren; + register char *s; + register I32 i; + register REGEXP *rx; + char *t; + + if (PL_curpm && (rx = PL_curpm->op_pmregexp)) { + paren = mg->mg_len; + if (paren < 0) + return 0; + if (paren <= rx->nparens && + (s = rx->startp[paren]) && + (t = rx->endp[paren])) + { + if (mg->mg_obj) /* @+ */ + i = t - rx->subbase; + else /* @- */ + i = s - rx->subbase; + sv_setiv(sv,i); + } + } + return 0; +} + +U32 magic_len(SV *sv, MAGIC *mg) { dTHR; @@ -346,6 +423,34 @@ magic_len(SV *sv, MAGIC *mg) return 0; } +#if 0 +static char * +printW(sv) +SV * sv ; +{ +#if 1 + return "" ; + +#else + int i ; + static char buffer[50] ; + char buf1[20] ; + char * p ; + + + sprintf(buffer, "Buffer %d, Length = %d - ", sv, SvCUR(sv)) ; + p = SvPVX(sv) ; + for (i = 0; i < SvCUR(sv) ; ++ i) { + sprintf (buf1, " %x [%x]", (p+i), *(p+i)) ; + strcat(buffer, buf1) ; + } + + return buffer ; + +#endif +} +#endif + int magic_get(SV *sv, MAGIC *mg) { @@ -360,6 +465,18 @@ magic_get(SV *sv, MAGIC *mg) case '\001': /* ^A */ sv_setsv(sv, PL_bodytarget); break; + case '\002': /* ^B */ + /* printf("magic_get $^B: ") ; */ + if (PL_curcop->cop_warnings == WARN_NONE) + /* printf("WARN_NONE\n"), */ + sv_setpvn(sv, WARN_NONEstring, WARNsize) ; + else if (PL_curcop->cop_warnings == WARN_ALL) + /* printf("WARN_ALL\n"), */ + sv_setpvn(sv, WARN_ALLstring, WARNsize) ; + else + /* printf("some %s\n", printW(PL_curcop->cop_warnings)), */ + sv_setsv(sv, PL_curcop->cop_warnings); + break; case '\004': /* ^D */ sv_setiv(sv, (IV)(PL_debug & 32767)); break; @@ -382,8 +499,11 @@ magic_get(SV *sv, MAGIC *mg) sv_setnv(sv, (double)errno); sv_setpv(sv, errno ? Strerror(errno) : ""); } else { - if (errno != errno_isOS2) - Perl_rc = _syserrno(); + if (errno != errno_isOS2) { + int tmp = _syserrno(); + if (tmp) /* 2nd call to _syserrno() makes it 0 */ + Perl_rc = tmp; + } sv_setnv(sv, (double)Perl_rc); sv_setpv(sv, os2error(Perl_rc)); } @@ -453,7 +573,7 @@ magic_get(SV *sv, MAGIC *mg) #endif break; case '\027': /* ^W */ - sv_setiv(sv, (IV)PL_dowarn); + sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) == G_WARN_ON)); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '&': @@ -847,8 +967,8 @@ magic_setsig(SV *sv, MAGIC *mg) else { i = whichsig(s); /* ...no, a brick */ if (!i) { - if (PL_dowarn || strEQ(s,"ALARM")) - warn("No such signal: SIG%s", s); + if (ckWARN(WARN_SIGNAL) || strEQ(s,"ALARM")) + warner(WARN_SIGNAL, "No such signal: SIG%s", s); return 0; } SvREFCNT_dec(psig_name[i]); @@ -922,7 +1042,7 @@ magic_getnkeys(SV *sv, MAGIC *mg) if (hv) { (void) hv_iterinit(hv); - if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P')) + if (! SvTIED_mg((SV*)hv, 'P')) i = HvKEYS(hv); else { /*SUPPRESS 560*/ @@ -947,13 +1067,13 @@ magic_setnkeys(SV *sv, MAGIC *mg) /* caller is responsible for stack switching/cleanup */ STATIC int -magic_methcall(MAGIC *mg, char *meth, I32 flags, int n, SV *val) +magic_methcall(SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val) { dSP; PUSHMARK(SP); EXTEND(SP, n); - PUSHs(mg->mg_obj); + PUSHs(SvTIED_obj(sv, mg)); if (n > 1) { if (mg->mg_ptr) { if (mg->mg_len >= 0) @@ -982,7 +1102,7 @@ magic_methpack(SV *sv, MAGIC *mg, char *meth) SAVETMPS; PUSHSTACKi(PERLSI_MAGIC); - if (magic_methcall(mg, meth, G_SCALAR, 2, NULL)) { + if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) { sv_setsv(sv, *PL_stack_sp--); } @@ -1007,7 +1127,7 @@ magic_setpack(SV *sv, MAGIC *mg) dSP; ENTER; PUSHSTACKi(PERLSI_MAGIC); - magic_methcall(mg, "STORE", G_SCALAR|G_DISCARD, 3, sv); + magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv); POPSTACK; LEAVE; return 0; @@ -1029,7 +1149,7 @@ magic_sizepack(SV *sv, MAGIC *mg) ENTER; SAVETMPS; PUSHSTACKi(PERLSI_MAGIC); - if (magic_methcall(mg, "FETCHSIZE", G_SCALAR, 2, NULL)) { + if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) { sv = *PL_stack_sp--; retval = (U32) SvIV(sv)-1; } @@ -1046,7 +1166,7 @@ int magic_wipepack(SV *sv, MAGIC *mg) ENTER; PUSHSTACKi(PERLSI_MAGIC); PUSHMARK(SP); - XPUSHs(mg->mg_obj); + XPUSHs(SvTIED_obj(sv, mg)); PUTBACK; perl_call_method("CLEAR", G_SCALAR|G_DISCARD); POPSTACK; @@ -1065,7 +1185,7 @@ magic_nextpack(SV *sv, MAGIC *mg, SV *key) PUSHSTACKi(PERLSI_MAGIC); PUSHMARK(SP); EXTEND(SP, 2); - PUSHs(mg->mg_obj); + PUSHs(SvTIED_obj(sv, mg)); if (SvOK(key)) PUSHs(key); PUTBACK; @@ -1130,7 +1250,10 @@ magic_getpos(SV *sv, MAGIC *mg) mg = mg_find(lsv, 'g'); if (mg && mg->mg_len >= 0) { dTHR; - sv_setiv(sv, mg->mg_len + PL_curcop->cop_arybase); + I32 i = mg->mg_len; + if (IN_UTF8) + sv_pos_b2u(lsv, &i); + sv_setiv(sv, i + PL_curcop->cop_arybase); return 0; } } @@ -1144,6 +1267,8 @@ magic_setpos(SV *sv, MAGIC *mg) SV* lsv = LvTARG(sv); SSize_t pos; STRLEN len; + STRLEN ulen; + dTHR; mg = 0; @@ -1161,7 +1286,16 @@ magic_setpos(SV *sv, MAGIC *mg) } len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv); - WITH_THR(pos = SvIV(sv) - PL_curcop->cop_arybase); + pos = SvIV(sv) - PL_curcop->cop_arybase; + + if (IN_UTF8) { + ulen = sv_len_utf8(lsv); + if (ulen) + len = ulen; + else + ulen = 0; + } + if (pos < 0) { pos += len; if (pos < 0) @@ -1169,6 +1303,13 @@ magic_setpos(SV *sv, MAGIC *mg) } else if (pos > len) pos = len; + + if (ulen) { + I32 p = pos; + sv_pos_u2b(lsv, &p, 0); + pos = p; + } + mg->mg_len = pos; mg->mg_flags &= ~MGf_MINMATCH; @@ -1475,7 +1616,7 @@ int magic_setcollxfrm(SV *sv, MAGIC *mg) { /* - * René Descartes said "I think not." + * RenE Descartes said "I think not." * and vanished with a faint plop. */ if (mg->mg_ptr) { @@ -1498,6 +1639,21 @@ magic_set(SV *sv, MAGIC *mg) case '\001': /* ^A */ sv_setsv(PL_bodytarget, sv); break; + case '\002': /* ^B */ + if ( ! (PL_dowarn & G_WARN_ALL_MASK)) { + if (memEQ(SvPVX(sv), WARN_ALLstring, WARNsize)) + PL_compiling.cop_warnings = WARN_ALL; + else if (memEQ(SvPVX(sv), WARN_NONEstring, WARNsize)) + PL_compiling.cop_warnings = WARN_NONE; + else { + if (PL_compiling.cop_warnings != WARN_NONE && + PL_compiling.cop_warnings != WARN_ALL) + sv_setsv(PL_compiling.cop_warnings, sv); + else + PL_compiling.cop_warnings = newSVsv(sv) ; + } + } + break; case '\004': /* ^D */ PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000; DEBUG_x(dump_all()); @@ -1547,7 +1703,10 @@ magic_set(SV *sv, MAGIC *mg) #endif break; case '\027': /* ^W */ - PL_dowarn = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + if ( ! (PL_dowarn & G_WARN_ALL_MASK)) { + i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ; + } break; case '.': if (PL_localizing) { @@ -1851,7 +2010,6 @@ magic_mutexfree(SV *sv, MAGIC *mg) croak("panic: magic_mutexfree"); MUTEX_DESTROY(MgMUTEXP(mg)); COND_DESTROY(MgCONDP(mg)); - SvREFCNT_dec(sv); return 0; } #endif /* USE_THREADS */ @@ -1937,8 +2095,8 @@ sighandler(int sig) cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE); if (!cv || !CvROOT(cv)) { - if (PL_dowarn) - warn("SIG%s handler \"%s\" not defined.\n", + if (ckWARN(WARN_SIGNAL)) + warner(WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n", sig_name[sig], (gv ? GvENAME(gv) : ((cv && CvGV(cv)) ? GvENAME(CvGV(cv))