X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=gv.c;h=ff278ccc0838668b3d546743db60d4f8d06ac65c;hb=2680586ee66b8de4d2b5f26a2013220f2bec9d5f;hp=a8ae6bd69cbd0be9d07483fef9e0a6456828886a;hpb=533c011aecf9bca2c9ad025efccd7b74ad222cda;p=p5sagit%2Fp5-mst-13.2.git diff --git a/gv.c b/gv.c index a8ae6bd..ff278cc 100644 --- a/gv.c +++ b/gv.c @@ -19,8 +19,6 @@ #include "EXTERN.h" #include "perl.h" -EXT char rcsid[]; - GV * gv_AVadd(register GV *gv) { @@ -52,7 +50,7 @@ gv_IOadd(register GV *gv) } GV * -gv_fetchfile(char *name) +gv_fetchfile(const char *name) { dTHR; char smallbuf[256]; @@ -82,7 +80,7 @@ gv_fetchfile(char *name) } void -gv_init(GV *gv, HV *stash, char *name, STRLEN len, int multi) +gv_init(GV *gv, HV *stash, const char *name, STRLEN len, int multi) { dTHR; register GP *gp; @@ -109,11 +107,12 @@ gv_init(GV *gv, HV *stash, char *name, STRLEN len, int multi) GvSTASH(gv) = (HV*)SvREFCNT_inc(stash); GvNAME(gv) = savepvn(name, len); GvNAMELEN(gv) = len; - if (multi) + if (multi || doproto) /* doproto means it _was_ mentioned */ GvMULTI_on(gv); if (doproto) { /* Replicate part of newSUB here. */ SvIOK_off(gv); ENTER; + /* XXX unsafe for threads if eval_owner isn't held */ start_subparse(0,0); /* Create CV in compcv. */ GvCV(gv) = PL_compcv; LEAVE; @@ -124,9 +123,10 @@ gv_init(GV *gv, HV *stash, char *name, STRLEN len, int multi) CvSTASH(GvCV(gv)) = PL_curstash; #ifdef USE_THREADS CvOWNER(GvCV(gv)) = 0; - if (!CvMUTEXP(GvCV(gv))) + if (!CvMUTEXP(GvCV(gv))) { New(666, CvMUTEXP(GvCV(gv)), 1, perl_mutex); - MUTEX_INIT(CvMUTEXP(GvCV(gv))); + MUTEX_INIT(CvMUTEXP(GvCV(gv))); + } #endif /* USE_THREADS */ if (proto) { sv_setpv((SV*)GvCV(gv), proto); @@ -152,7 +152,7 @@ gv_init_sv(GV *gv, I32 sv_type) } GV * -gv_fetchmeth(HV *stash, char *name, STRLEN len, I32 level) +gv_fetchmeth(HV *stash, const char *name, STRLEN len, I32 level) { AV* av; GV* topgv; @@ -223,8 +223,9 @@ gv_fetchmeth(HV *stash, char *name, STRLEN len, I32 level) SV* sv = *svp++; HV* basestash = gv_stashsv(sv, FALSE); if (!basestash) { - if (PL_dowarn) - warn("Can't locate package %s for @%s::ISA", + dTHR; /* just for ckWARN */ + if (ckWARN(WARN_MISC)) + warner(WARN_MISC, "Can't locate package %s for @%s::ISA", SvPVX(sv), HvNAME(stash)); continue; } @@ -272,17 +273,17 @@ gv_fetchmeth(HV *stash, char *name, STRLEN len, I32 level) } GV * -gv_fetchmethod(HV *stash, char *name) +gv_fetchmethod(HV *stash, const char *name) { return gv_fetchmethod_autoload(stash, name, TRUE); } GV * -gv_fetchmethod_autoload(HV *stash, char *name, I32 autoload) +gv_fetchmethod_autoload(HV *stash, const char *name, I32 autoload) { dTHR; - register char *nend; - char *nsplit = 0; + register const char *nend; + const char *nsplit = 0; GV* gv; for (nend = name; *nend; nend++) { @@ -292,7 +293,7 @@ gv_fetchmethod_autoload(HV *stash, char *name, I32 autoload) nsplit = ++nend; } if (nsplit) { - char *origname = name; + const char *origname = name; name = nsplit + 1; if (*nsplit == ':') --nsplit; @@ -339,8 +340,9 @@ gv_fetchmethod_autoload(HV *stash, char *name, I32 autoload) } GV* -gv_autoload4(HV *stash, char *name, STRLEN len, I32 method) +gv_autoload4(HV *stash, const char *name, STRLEN len, I32 method) { + dTHR; static char autoload[] = "AUTOLOAD"; static STRLEN autolen = 8; GV* gv; @@ -358,8 +360,9 @@ gv_autoload4(HV *stash, char *name, STRLEN len, I32 method) /* * Inheriting AUTOLOAD for non-methods works ... for now. */ - if (PL_dowarn && !method && (GvCVGEN(gv) || GvSTASH(gv) != stash)) - warn( + if (ckWARN(WARN_DEPRECATED) && !method && + (GvCVGEN(gv) || GvSTASH(gv) != stash)) + warner(WARN_DEPRECATED, "Use of inherited AUTOLOAD for non-method %s::%.*s() is deprecated", HvNAME(stash), (int)len, name); @@ -382,13 +385,13 @@ gv_autoload4(HV *stash, char *name, STRLEN len, I32 method) } HV* -gv_stashpv(char *name, I32 create) +gv_stashpv(const char *name, I32 create) { return gv_stashpvn(name, strlen(name), create); } HV* -gv_stashpvn(char *name, U32 namelen, I32 create) +gv_stashpvn(const char *name, U32 namelen, I32 create) { char smallbuf[256]; char *tmpbuf; @@ -427,14 +430,14 @@ gv_stashsv(SV *sv, I32 create) GV * -gv_fetchpv(char *nambeg, I32 add, I32 sv_type) +gv_fetchpv(const char *nambeg, I32 add, I32 sv_type) { dTHR; - register char *name = nambeg; + register const char *name = nambeg; register GV *gv = 0; GV**gvp; I32 len; - register char *namend; + register const char *namend; HV *stash = 0; U32 add_gvflags = 0; @@ -498,29 +501,25 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) /* No stash in name, so see how we can default */ if (!stash) { - if (isIDFIRST(*name)) { + if (isIDFIRST(*name) + || (IN_UTF8 && ((*name & 0xc0) == 0xc0) && isIDFIRST_utf8((U8*)name))) + { bool global = FALSE; if (isUPPER(*name)) { - if (*name > 'I') { - if (*name == 'S' && ( - strEQ(name, "SIG") || - strEQ(name, "STDIN") || - strEQ(name, "STDOUT") || - strEQ(name, "STDERR") )) - global = TRUE; - } - else if (*name > 'E') { - if (*name == 'I' && strEQ(name, "INC")) - global = TRUE; - } - else if (*name > 'A') { - if (*name == 'E' && strEQ(name, "ENV")) - global = TRUE; - } + if (*name == 'S' && ( + strEQ(name, "SIG") || + strEQ(name, "STDIN") || + strEQ(name, "STDOUT") || + strEQ(name, "STDERR"))) + global = TRUE; + else if (*name == 'I' && strEQ(name, "INC")) + global = TRUE; + else if (*name == 'E' && strEQ(name, "ENV")) + global = TRUE; else if (*name == 'A' && ( strEQ(name, "ARGV") || - strEQ(name, "ARGVOUT") )) + strEQ(name, "ARGVOUT"))) global = TRUE; } else if (*name == '_' && !name[1]) @@ -570,7 +569,7 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) if (!stash) { if (!add) return Nullgv; - if (add & ~GV_ADDMULTI) { + { char sv_type_char = ((sv_type == SVt_PV) ? '$' : (sv_type == SVt_PVAV) ? '@' : (sv_type == SVt_PVHV) ? '%' @@ -655,7 +654,6 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) } } break; -#ifdef OVERLOAD case 'O': if (strEQ(name, "OVERLOAD")) { HV* hv = GvHVn(gv); @@ -663,7 +661,6 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) hv_magic(hv, gv, 'A'); } break; -#endif /* OVERLOAD */ case 'S': if (strEQ(name, "SIG")) { HV *hv; @@ -672,13 +669,13 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) GvMULTI_on(PL_siggv); hv = GvHVn(PL_siggv); hv_magic(hv, PL_siggv, 'S'); - for(i=1;sig_name[i];i++) { + for(i=1;PL_sig_name[i];i++) { SV ** init; - init=hv_fetch(hv,sig_name[i],strlen(sig_name[i]),1); + init=hv_fetch(hv,PL_sig_name[i],strlen(PL_sig_name[i]),1); if(init) sv_setsv(*init,&PL_sv_undef); - psig_ptr[i] = 0; - psig_name[i] = 0; + PL_psig_ptr[i] = 0; + PL_psig_name[i] = 0; } } break; @@ -714,7 +711,7 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) if (len > 1) break; #ifdef COMPLEX_STATUS - sv_upgrade(GvSV(gv), SVt_PVLV); + (void)SvUPGRADE(GvSV(gv), SVt_PVLV); #endif goto magicalize; @@ -734,16 +731,23 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) } } goto magicalize; + case '-': + if (len > 1) + break; + else { + AV* av = GvAVn(gv); + sv_magic((SV*)av, Nullsv, 'D', Nullch, 0); + } + goto magicalize; case '#': case '*': - if (PL_dowarn && len == 1 && sv_type == SVt_PV) - warn("Use of $%s is deprecated", name); + if (ckWARN(WARN_DEPRECATED) && len == 1 && sv_type == SVt_PV) + warner(WARN_DEPRECATED, "Use of $%s is deprecated", name); /* FALL THROUGH */ case '[': case '^': case '~': case '=': - case '-': case '%': case '.': case '(': @@ -755,20 +759,33 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) case '/': case '|': case '\001': + case '\002': + case '\003': case '\004': case '\005': case '\006': case '\010': + case '\011': /* NOT \t in EBCDIC */ case '\017': - case '\t': case '\020': case '\024': case '\027': if (len > 1) break; goto magicalize; + case '\023': + if (len > 1) + break; + goto ro_magicalize; case '+': + if (len > 1) + break; + else { + AV* av = GvAVn(gv); + sv_magic((SV*)av, (SV*)av, 'D', Nullch, 0); + } + /* FALL THROUGH */ case '1': case '2': case '3': @@ -778,7 +795,6 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) case '7': case '8': case '9': - case '\023': ro_magicalize: SvREADONLY_on(GvSV(gv)); magicalize: @@ -799,7 +815,7 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) case ']': if (len == 1) { SV *sv = GvSV(gv); - sv_upgrade(sv, SVt_PVNV); + (void)SvUPGRADE(sv, SVt_PVNV); sv_setpv(sv, PL_patchlevel); (void)sv_2nv(sv); SvREADONLY_on(sv); @@ -810,7 +826,7 @@ gv_fetchpv(char *nambeg, I32 add, I32 sv_type) } void -gv_fullname3(SV *sv, GV *gv, char *prefix) +gv_fullname3(SV *sv, GV *gv, const char *prefix) { HV *hv = GvSTASH(gv); if (!hv) { @@ -824,7 +840,7 @@ gv_fullname3(SV *sv, GV *gv, char *prefix) } void -gv_efullname3(SV *sv, GV *gv, char *prefix) +gv_efullname3(SV *sv, GV *gv, const char *prefix) { GV *egv = GvEGV(gv); if (!egv) @@ -858,7 +874,8 @@ newIO(void) SvREFCNT(io) = 1; SvOBJECT_on(io); iogv = gv_fetchpv("FileHandle::", FALSE, SVt_PVHV); - if (!iogv) + /* unless exists($main::{FileHandle}) and defined(%main::FileHandle::) */ + if (!(iogv && GvHV(iogv) && HvARRAY(GvHV(iogv)))) iogv = gv_fetchpv("IO::Handle::", TRUE, SVt_PVHV); SvSTASH(io) = (HV*)SvREFCNT_inc(GvHV(iogv)); return io; @@ -893,7 +910,8 @@ gv_check(HV *stash) PL_curcop->cop_filegv = filegv; if (filegv && GvMULTI(filegv)) /* Filename began with slash */ continue; - warn("Name \"%s::%s\" used only once: possible typo", + warner(WARN_ONCE, + "Name \"%s::%s\" used only once: possible typo", HvNAME(stash), GvNAME(gv)); } } @@ -985,7 +1003,6 @@ register GV *gv; } #endif /* Microport 2.4 hack */ -#ifdef OVERLOAD /* Updates and caches the CV's */ bool @@ -999,6 +1016,7 @@ Gv_AMupdate(HV *stash) MAGIC* mg=mg_find((SV*)stash,'c'); AMT *amtp = (mg) ? (AMT*)mg->mg_ptr: (AMT *) NULL; AMT amt; + STRLEN n_a; if (mg && amtp->was_ok_am == PL_amagic_generation && amtp->was_ok_sub == PL_sub_generation) @@ -1029,16 +1047,16 @@ Gv_AMupdate(HV *stash) SV* sv; SV** svp; - /* Work with "fallback" key, which we assume to be first in AMG_names */ + /* Work with "fallback" key, which we assume to be first in PL_AMG_names */ - if (( cp = (char *)AMG_names[0] ) && + if (( cp = (char *)PL_AMG_names[0] ) && (svp = (SV**)hv_fetch(hv,cp,strlen(cp),FALSE)) && (sv = *svp)) { if (SvTRUE(sv)) amt.fallback=AMGfallYES; else if (SvOK(sv)) amt.fallback=AMGfallNEVER; } for (i = 1; i < NofAMmeth; i++) { cv = 0; - cp = (char *)AMG_names[i]; + cp = (char *)PL_AMG_names[i]; svp = (SV**)hv_fetch(hv, cp, strlen(cp), FALSE); if (svp && ((sv = *svp) != &PL_sv_undef)) { @@ -1046,7 +1064,7 @@ Gv_AMupdate(HV *stash) default: if (!SvROK(sv)) { if (!SvOK(sv)) break; - gv = gv_fetchmethod(stash, SvPV(sv, na)); + gv = gv_fetchmethod(stash, SvPV(sv, n_a)); if (gv) cv = GvCV(gv); break; } @@ -1081,9 +1099,9 @@ Gv_AMupdate(HV *stash) SV* sv = NULL; SV** svp; - /* Work with "fallback" key, which we assume to be first in AMG_names */ + /* Work with "fallback" key, which we assume to be first in PL_AMG_names */ - if ( cp = AMG_names[0] ) { + if ( cp = PL_AMG_names[0] ) { /* Try to find via inheritance. */ gv = gv_fetchmeth(stash, "()", 2, -1); /* A cookie: "()". */ if (gv) sv = GvSV(gv); @@ -1094,7 +1112,7 @@ Gv_AMupdate(HV *stash) } for (i = 1; i < NofAMmeth; i++) { - SV *cookie = sv_2mortal(newSVpvf("(%s", cp = AMG_names[i])); + SV *cookie = sv_2mortal(newSVpvf("(%s", cp = PL_AMG_names[i])); DEBUG_o( deb("Checking overloading of `%s' in package `%.256s'\n", cp, HvNAME(stash)) ); /* don't fill the cache while looking up! */ @@ -1107,7 +1125,7 @@ Gv_AMupdate(HV *stash) GV *ngv; DEBUG_o( deb("Resolving method `%.256s' for overloaded `%s' in package `%.256s'\n", - SvPV(GvSV(gv), PL_na), cp, HvNAME(stash)) ); + SvPV(GvSV(gv), n_a), cp, HvNAME(stash)) ); if (!SvPOK(GvSV(gv)) || !(ngv = gv_fetchmethod_autoload(stash, SvPVX(GvSV(gv)), FALSE))) @@ -1154,7 +1172,7 @@ amagic_call(SV *left, SV *right, int method, int flags) CV **cvp=NULL, **ocvp=NULL; AMT *amtp, *oamtp; int fl=0, off, off1, lr=0, assign=AMGf_assign & flags, notfound=0; - int postpr=0, inc_dec_ass=0, assignshift=assign?1:0; + int postpr = 0, force_cpy = 0, assignshift = assign ? 1 : 0; HV* stash; if (!(AMGf_noleft & flags) && SvAMAGIC(left) && (mg = mg_find((SV*)(stash=SvSTASH(SvRV(left))),'c')) @@ -1171,16 +1189,19 @@ amagic_call(SV *left, SV *right, int method, int flags) int logic; /* look for substituted methods */ + /* In all the covered cases we should be called with assign==0. */ switch (method) { case inc_amg: - if (((cv = cvp[off=add_ass_amg]) && (inc_dec_ass=1)) - || ((cv = cvp[off=add_amg]) && (postpr=1))) { + force_cpy = 1; + if ((cv = cvp[off=add_ass_amg]) + || ((cv = cvp[off = add_amg]) && (force_cpy = 0, postpr = 1))) { right = &PL_sv_yes; lr = -1; assign = 1; } break; case dec_amg: - if (((cv = cvp[off=subtr_ass_amg]) && (inc_dec_ass=1)) - || ((cv = cvp[off=subtr_amg]) && (postpr=1))) { + force_cpy = 1; + if ((cv = cvp[off = subtr_ass_amg]) + || ((cv = cvp[off = subtr_amg]) && (force_cpy = 0, postpr=1))) { right = &PL_sv_yes; lr = -1; assign = 1; } break; @@ -1249,6 +1270,15 @@ amagic_call(SV *left, SV *right, int method, int flags) lr = 1; } break; + case iter_amg: /* XXXX Eventually should do to_gv. */ + case to_sv_amg: + case to_av_amg: + case to_hv_amg: + case to_gv_amg: + case to_cv_amg: + /* FAIL safe */ + return NULL; /* Delegate operation to standard mechanisms. */ + break; default: goto not_found; } @@ -1304,7 +1334,7 @@ amagic_call(SV *left, SV *right, int method, int flags) if (off==-1) off=method; msg = sv_2mortal(newSVpvf( "Operation `%s': no method found,%sargument %s%s%s%s", - AMG_names[method + assignshift], + PL_AMG_names[method + assignshift], (flags & AMGf_unary ? " " : "\n\tleft "), SvAMAGIC(left)? "in overloaded package ": @@ -1327,30 +1357,50 @@ amagic_call(SV *left, SV *right, int method, int flags) } return NULL; } + force_cpy = force_cpy || assign; } } if (!notfound) { DEBUG_o( deb( "Overloaded operator `%s'%s%s%s:\n\tmethod%s found%s in package %s%s\n", - AMG_names[off], + PL_AMG_names[off], method+assignshift==off? "" : " (initially `", method+assignshift==off? "" : - AMG_names[method+assignshift], + PL_AMG_names[method+assignshift], method+assignshift==off? "" : "')", flags & AMGf_unary? "" : lr==1 ? " for right argument": " for left argument", flags & AMGf_unary? " for argument" : "", HvNAME(stash), fl? ",\n\tassignment variant used": "") ); + } /* Since we use shallow copy during assignment, we need * to dublicate the contents, probably calling user-supplied * version of copy operator */ - if ((method + assignshift==off - && (assign || method==inc_amg || method==dec_amg)) - || inc_dec_ass) RvDEEPCP(left); - } + /* We need to copy in following cases: + * a) Assignment form was called. + * assignshift==1, assign==T, method + 1 == off + * b) Increment or decrement, called directly. + * assignshift==0, assign==0, method + 0 == off + * c) Increment or decrement, translated to assignment add/subtr. + * assignshift==0, assign==T, + * force_cpy == T + * d) Increment or decrement, translated to nomethod. + * assignshift==0, assign==0, + * force_cpy == T + * e) Assignment form translated to nomethod. + * assignshift==1, assign==T, method + 1 != off + * force_cpy == T + */ + /* off is method, method+assignshift, or a result of opcode substitution. + * In the latter case assignshift==0, so only notfound case is important. + */ + if (( (method + assignshift == off) + && (assign || (method == inc_amg) || (method == dec_amg))) + || force_cpy) + RvDEEPCP(left); { dSP; BINOP myop; @@ -1377,7 +1427,7 @@ amagic_call(SV *left, SV *right, int method, int flags) PUSHs(lr>0? left: right); PUSHs( lr > 0 ? &PL_sv_yes : ( assign ? &PL_sv_undef : &PL_sv_no )); if (notfound) { - PUSHs( sv_2mortal(newSVpv((char *)AMG_names[method + assignshift],0)) ); + PUSHs( sv_2mortal(newSVpv((char *)PL_AMG_names[method + assignshift],0))); } PUSHs((SV*)cv); PUTBACK; @@ -1388,6 +1438,7 @@ amagic_call(SV *left, SV *right, int method, int flags) SPAGAIN; res=POPs; + PUTBACK; POPSTACK; CATCH_SET(oldcatch); @@ -1429,5 +1480,3 @@ amagic_call(SV *left, SV *right, int method, int flags) } } } -#endif /* OVERLOAD */ -