X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp.c;h=3d7638e5dbcb88214b2cbbea86b8b70fdc1fb991;hb=25eaa2138d60ea820620e1b1324f90a6b4f4adcd;hp=3afd65b04d083bcf25d254d2ef954f9bcc6cf778;hpb=8ec5e241bff6550c56f30587b70b41dc3236277c;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp.c b/pp.c index 3afd65b..3d7638e 100644 --- a/pp.c +++ b/pp.c @@ -46,7 +46,7 @@ typedef unsigned UBW; * have an integral type (except char) small enough to be represented * in a double without loss; that is, it has no 32-bit type. */ -#if BYTEORDER > 0xFFFF && defined(_CRAY) && !defined(_CRAYMPP) +#if LONGSIZE > 4 && defined(_CRAY) && !defined(_CRAYMPP) # define BW_BITS 32 # define BW_MASK ((1 << BW_BITS) - 1) # define BW_SIGN (1 << (BW_BITS - 1)) @@ -69,7 +69,11 @@ typedef unsigned UBW; * If they're not right on your machine, then pack() and unpack() * wouldn't work right anyway; you'll need to apply the Cray hack. * (I'd like to check them with #if, but you can't use sizeof() in - * the preprocessor.) + * the preprocessor.) --??? + */ +/* + The appropriate SHORTSIZE, INTSIZE, LONGSIZE, and LONGLONGSIZE + defines are now in config.h. --Andy Dougherty April 1998 */ #define SIZE16 2 #define SIZE32 4 @@ -97,20 +101,26 @@ typedef unsigned UBW; # define CAT32(sv,p) sv_catpvn(sv, (char*)(p), SIZE32) #endif +#ifndef PERL_OBJECT static void doencodes _((SV* sv, char* s, I32 len)); static SV* refto _((SV* sv)); static U32 seed _((void)); +#endif static bool srand_called = FALSE; /* variations on pp_null */ -#ifdef DONT_DECLARE_STD #ifdef I_UNISTD #include #endif -#else -extern pid_t getpid (void); + +/* XXX I can't imagine anyone who doesn't have this actually _needs_ + it, since pid_t is an integral type. + --AD 2/20/1998 +*/ +#ifdef NEED_GETPID_PROTO +extern Pid_t getpid (void); #endif PP(pp_stub) @@ -314,7 +324,11 @@ PP(pp_pos) } LvTYPE(TARG) = '.'; - LvTARG(TARG) = sv; + if (LvTARG(TARG) != sv) { + if (LvTARG(TARG)) + SvREFCNT_dec(LvTARG(TARG)); + LvTARG(TARG) = SvREFCNT_inc(sv); + } PUSHs(TARG); /* no SvSETMAGIC */ RETURN; } @@ -360,9 +374,54 @@ PP(pp_prototype) SV *ret; ret = &sv_undef; + if (SvPOK(TOPs) && SvCUR(TOPs) >= 7) { + char *s = SvPVX(TOPs); + if (strnEQ(s, "CORE::", 6)) { + int code; + + code = keyword(s + 6, SvCUR(TOPs) - 6); + if (code < 0) { /* Overridable. */ +#define MAX_ARGS_OP ((sizeof(I32) - 1) * 2) + int i = 0, n = 0, seen_question = 0; + I32 oa; + char str[ MAX_ARGS_OP * 2 + 2 ]; /* One ';', one '\0' */ + + while (i < MAXO) { /* The slow way. */ + if (strEQ(s + 6, op_name[i]) || strEQ(s + 6, op_desc[i])) + goto found; + i++; + } + goto nonesuch; /* Should not happen... */ + found: + oa = opargs[i] >> OASHIFT; + while (oa) { + if (oa & OA_OPTIONAL) { + seen_question = 1; + str[n++] = ';'; + } else if (seen_question) + goto set; /* XXXX system, exec */ + if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF + && (oa & (OA_OPTIONAL - 1)) <= OA_HVREF) { + str[n++] = '\\'; + } + /* What to do with R ((un)tie, tied, (sys)read, recv)? */ + str[n++] = ("?$@@%&*$")[oa & (OA_OPTIONAL - 1)]; + oa = oa >> 4; + } + str[n++] = '\0'; + ret = sv_2mortal(newSVpv(str, n - 1)); + } else if (code) /* Non-Overridable */ + goto set; + else { /* None such */ + nonesuch: + croak("Cannot find an opnumber for \"%s\"", s+6); + } + } + } cv = sv_2cv(TOPs, &stash, &gv, FALSE); if (cv && SvPOK(cv)) ret = sv_2mortal(newSVpv(SvPVX(cv), SvCUR(cv))); + set: SETs(ret); RETURN; } @@ -389,8 +448,13 @@ PP(pp_refgen) { djSP; dMARK; if (GIMME != G_ARRAY) { - MARK[1] = *SP; - SP = MARK + 1; + if (++MARK <= SP) + *MARK = *SP; + else + *MARK = &sv_undef; + *MARK = refto(*MARK); + SP = MARK; + RETURN; } EXTEND_MORTAL(SP - MARK); while (++MARK <= SP) @@ -398,7 +462,7 @@ PP(pp_refgen) RETURN; } -static SV* +STATIC SV* refto(SV *sv) { SV* rv; @@ -449,8 +513,14 @@ PP(pp_bless) if (MAXARG == 1) stash = curcop->cop_stash; - else - stash = gv_stashsv(POPs, TRUE); + else { + SV *ssv = POPs; + STRLEN len; + char *ptr = SvPV(ssv,len); + if (dowarn && len == 0) + warn("Explicit blessing to '' (assuming package main)"); + stash = gv_stashpvn(ptr, len, TRUE); + } (void)sv_bless(TOPs, stash); RETURN; @@ -460,40 +530,40 @@ PP(pp_gelem) { GV *gv; SV *sv; - SV *ref; + SV *tmpRef; char *elem; djSP; sv = POPs; elem = SvPV(sv, na); gv = (GV*)POPs; - ref = Nullsv; + tmpRef = Nullsv; sv = Nullsv; switch (elem ? *elem : '\0') { case 'A': if (strEQ(elem, "ARRAY")) - ref = (SV*)GvAV(gv); + tmpRef = (SV*)GvAV(gv); break; case 'C': if (strEQ(elem, "CODE")) - ref = (SV*)GvCVu(gv); + tmpRef = (SV*)GvCVu(gv); break; case 'F': if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */ - ref = (SV*)GvIOp(gv); + tmpRef = (SV*)GvIOp(gv); break; case 'G': if (strEQ(elem, "GLOB")) - ref = (SV*)gv; + tmpRef = (SV*)gv; break; case 'H': if (strEQ(elem, "HASH")) - ref = (SV*)GvHV(gv); + tmpRef = (SV*)GvHV(gv); break; case 'I': if (strEQ(elem, "IO")) - ref = (SV*)GvIOp(gv); + tmpRef = (SV*)GvIOp(gv); break; case 'N': if (strEQ(elem, "NAME")) @@ -505,11 +575,11 @@ PP(pp_gelem) break; case 'S': if (strEQ(elem, "SCALAR")) - ref = GvSV(gv); + tmpRef = GvSV(gv); break; } - if (ref) - sv = newRV(ref); + if (tmpRef) + sv = newRV(tmpRef); if (sv) sv_2mortal(sv); else @@ -705,7 +775,7 @@ PP(pp_undef) hv_undef((HV*)sv); break; case SVt_PVCV: - if (cv_const_sv((CV*)sv)) + if (dowarn && cv_const_sv((CV*)sv)) warn("Constant subroutine %s undefined", CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv))); /* FALL THROUGH */ @@ -716,7 +786,17 @@ PP(pp_undef) break; case SVt_PVGV: if (SvFAKE(sv)) - sv_setsv(sv, &sv_undef); + SvSetMagicSV(sv, &sv_undef); + else { + GP *gp; + gp_free((GV*)sv); + Newz(602, gp, 1, GP); + GvGP(sv) = gp_ref(gp); + GvSV(sv) = NEWSV(72,0); + GvLINE(sv) = curcop->cop_line; + GvEGV(sv) = (GV*)sv; + GvMULTI_on(sv); + } break; default: if (SvTYPE(sv) >= SVt_PV && SvPVX(sv) && SvLEN(sv)) { @@ -841,7 +921,7 @@ PP(pp_divide) PP(pp_modulo) { - djSP; dATARGET; tryAMAGICbin(mod,opASSIGN); + djSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); { UV left; UV right; @@ -1327,7 +1407,7 @@ PP(pp_i_divide) PP(pp_i_modulo) { - djSP; dATARGET; tryAMAGICbin(mod,opASSIGN); + djSP; dATARGET; tryAMAGICbin(modulo,opASSIGN); { dPOPTOPiirl; if (!right) @@ -1523,7 +1603,7 @@ PP(pp_srand) RETPUSHYES; } -static U32 +STATIC U32 seed(void) { /* @@ -1722,47 +1802,56 @@ PP(pp_substr) I32 lvalue = op->op_flags & OPf_MOD; char *tmps; I32 arybase = curcop->cop_arybase; - - if (MAXARG > 2) + char *repl = 0; + STRLEN repl_len; + + SvTAINTED_off(TARG); /* decontaminate */ + if (MAXARG > 2) { + if (MAXARG > 3) { + sv = POPs; + repl = SvPV(sv, repl_len); + } len = POPi; + } pos = POPi; sv = POPs; + PUTBACK; tmps = SvPV(sv, curlen); if (pos >= arybase) { pos -= arybase; rem = curlen-pos; fail = rem; - if (MAXARG > 2) { - if (len < 0) { - rem += len; - if (rem < 0) - rem = 0; - } - else if (rem > len) - rem = len; - } + if (MAXARG > 2) { + if (len < 0) { + rem += len; + if (rem < 0) + rem = 0; + } + else if (rem > len) + rem = len; + } } else { - pos += curlen; - if (MAXARG < 3) - rem = curlen; - else if (len >= 0) { - rem = pos+len; - if (rem > (I32)curlen) - rem = curlen; - } - else { - rem = curlen+len; - if (rem < pos) - rem = pos; - } - if (pos < 0) - pos = 0; - fail = rem; - rem -= pos; + pos += curlen; + if (MAXARG < 3) + rem = curlen; + else if (len >= 0) { + rem = pos+len; + if (rem > (I32)curlen) + rem = curlen; + } + else { + rem = curlen+len; + if (rem < pos) + rem = pos; + } + if (pos < 0) + pos = 0; + fail = rem; + rem -= pos; } if (fail < 0) { - if (dowarn || lvalue) + if (dowarn || lvalue || repl) warn("substr outside of string"); RETPUSHUNDEF; } @@ -1788,11 +1877,18 @@ PP(pp_substr) } LvTYPE(TARG) = 'x'; - LvTARG(TARG) = sv; + if (LvTARG(TARG) != sv) { + if (LvTARG(TARG)) + SvREFCNT_dec(LvTARG(TARG)); + LvTARG(TARG) = SvREFCNT_inc(sv); + } LvTARGOFF(TARG) = pos; LvTARGLEN(TARG) = rem; } + else if (repl) + sv_insert(sv, pos, rem, repl, repl_len); } + SPAGAIN; PUSHs(TARG); /* avoid SvSETMAGIC here */ RETURN; } @@ -1809,6 +1905,7 @@ PP(pp_vec) unsigned long retnum; I32 len; + SvTAINTED_off(TARG); /* decontaminate */ offset *= size; /* turn into bit offset */ len = (offset + size + 7) / 8; if (offset < 0 || size < 1) @@ -1821,7 +1918,11 @@ PP(pp_vec) } LvTYPE(TARG) = 'v'; - LvTARG(TARG) = src; + if (LvTARG(TARG) != src) { + if (LvTARG(TARG)) + SvREFCNT_dec(LvTARG(TARG)); + LvTARG(TARG) = SvREFCNT_inc(src); + } LvTARGOFF(TARG) = offset; LvTARGLEN(TARG) = size; } @@ -1866,7 +1967,7 @@ PP(pp_vec) } } - sv_setiv(TARG, (IV)retnum); + sv_setuv(TARG, (UV)retnum); PUSHs(TARG); RETURN; } @@ -2167,7 +2268,7 @@ PP(pp_aslice) if (SvTYPE(av) == SVt_PVAV) { if (lval && op->op_private & OPpLVAL_INTRO) { I32 max = -1; - for (svp = mark + 1; svp <= sp; svp++) { + for (svp = MARK + 1; svp <= SP; svp++) { elem = SvIVx(*svp); if (elem > max) max = elem; @@ -2185,7 +2286,7 @@ PP(pp_aslice) if (!svp || *svp == &sv_undef) DIE(no_aelem, elem); if (op->op_private & OPpLVAL_INTRO) - save_svref(svp); + save_aelem(av, elem, svp); } *MARK = svp ? *svp : &sv_undef; } @@ -2308,7 +2409,6 @@ PP(pp_exists) PP(pp_hslice) { djSP; dMARK; dORIGMARK; - register HE *he; register HV *hv = (HV*)POPs; register I32 lval = op->op_flags & OPf_MOD; I32 realhv = (SvTYPE(hv) == SVt_PVHV); @@ -2318,18 +2418,18 @@ PP(pp_hslice) SV *keysv = *MARK; SV **svp; if (realhv) { - he = hv_fetch_ent(hv, keysv, lval, 0); + HE *he = hv_fetch_ent(hv, keysv, lval, 0); svp = he ? &HeVAL(he) : 0; } else { svp = avhv_fetch_ent((AV*)hv, keysv, lval, 0); } if (lval) { - if (!he || HeVAL(he) == &sv_undef) + if (!svp || *svp == &sv_undef) DIE(no_helem, SvPV(keysv, na)); if (op->op_private & OPpLVAL_INTRO) - save_svref(&HeVAL(he)); + save_helem(hv, keysv, svp); } - *MARK = he ? HeVAL(he) : &sv_undef; + *MARK = svp ? *svp : &sv_undef; } } if (GIMME != G_ARRAY) { @@ -2434,7 +2534,7 @@ PP(pp_anonhash) if (MARK < SP) sv_setsv(val, *++MARK); else if (dowarn) - warn("Odd number of elements in hash list"); + warn("Odd number of elements in hash assignment"); (void)hv_store_ent(hv,key,val,0); } SP = ORIGMARK; @@ -2480,8 +2580,11 @@ PP(pp_splice) DIE(no_aelem, i); if (++MARK < SP) { length = SvIVx(*MARK++); - if (length < 0) - length = 0; + if (length < 0) { + length += AvFILLp(ary) - offset + 1; + if (length < 0) + length = 0; + } } else length = AvMAX(ary) + 1; /* close enough to infinity */ @@ -2713,9 +2816,8 @@ PP(pp_unshift) MAGIC *mg; if (SvRMAGICAL(ary) && (mg = mg_find((SV*)ary,'P'))) { - - *MARK-- = mg->mg_obj; + PUSHMARK(MARK); PUTBACK; ENTER; perl_call_method("UNSHIFT",G_SCALAR|G_DISCARD); @@ -2777,7 +2879,7 @@ PP(pp_reverse) RETURN; } -static SV * +STATIC SV * mul128(SV *sv, U8 m) { STRLEN len; @@ -2786,11 +2888,11 @@ mul128(SV *sv, U8 m) U32 i = 0; if (!strnEQ(s, "0000", 4)) { /* need to grow sv */ - SV *New = newSVpv("0000000000", 10); + SV *tmpNew = newSVpv("0000000000", 10); - sv_catsv(New, sv); + sv_catsv(tmpNew, sv); SvREFCNT_dec(sv); /* free old sv */ - sv = New; + sv = tmpNew; s = SvPV(sv, len); } t = s + len - 1; @@ -2810,7 +2912,7 @@ PP(pp_unpack) { djSP; dPOPPOPssrl; - SV **oldsp = sp; + SV **oldsp = SP; I32 gimme = GIMME_V; SV *sv; STRLEN llen; @@ -3107,7 +3209,7 @@ PP(pp_unpack) s += SIZE16; #ifdef HAS_NTOHS if (datumtype == 'n') - aushort = ntohs(aushort); + aushort = PerlSock_ntohs(aushort); #endif #ifdef HAS_VTOHS if (datumtype == 'v') @@ -3125,7 +3227,7 @@ PP(pp_unpack) sv = NEWSV(39, 0); #ifdef HAS_NTOHS if (datumtype == 'n') - aushort = ntohs(aushort); + aushort = PerlSock_ntohs(aushort); #endif #ifdef HAS_VTOHS if (datumtype == 'v') @@ -3157,6 +3259,13 @@ PP(pp_unpack) Copy(s, &aint, 1, int); s += sizeof(int); sv = NEWSV(40, 0); +#ifdef __osf__ + /* Without the dummy below unpack("i", pack("i",-1)) + * return 0xFFffFFff instead of -1 for Digital Unix V4.0 + * cc with optimization turned on */ + (aint) ? + sv_setiv(sv, (IV)aint) : +#endif sv_setiv(sv, (IV)aint); PUSHs(sv_2mortal(sv)); } @@ -3226,7 +3335,7 @@ PP(pp_unpack) s += SIZE32; #ifdef HAS_NTOHL if (datumtype == 'N') - aulong = ntohl(aulong); + aulong = PerlSock_ntohl(aulong); #endif #ifdef HAS_VTOHL if (datumtype == 'V') @@ -3246,7 +3355,7 @@ PP(pp_unpack) s += SIZE32; #ifdef HAS_NTOHL if (datumtype == 'N') - aulong = ntohl(aulong); + aulong = PerlSock_ntohl(aulong); #endif #ifdef HAS_VTOHL if (datumtype == 'V') @@ -3333,6 +3442,9 @@ PP(pp_unpack) break; #ifdef HAS_QUAD case 'q': + along = (strend - s) / sizeof(Quad_t); + if (len > along) + len = along; EXTEND(SP, len); EXTEND_MORTAL(len); while (len-- > 0) { @@ -3351,6 +3463,9 @@ PP(pp_unpack) } break; case 'Q': + along = (strend - s) / sizeof(Quad_t); + if (len > along) + len = along; EXTEND(SP, len); EXTEND_MORTAL(len); while (len-- > 0) { @@ -3494,12 +3609,12 @@ PP(pp_unpack) checksum = 0; } } - if (sp == oldsp && gimme == G_SCALAR) + if (SP == oldsp && gimme == G_SCALAR) PUSHs(&sv_undef); RETURN; } -static void +STATIC void doencodes(register SV *sv, register char *s, register I32 len) { char hunk[5]; @@ -3523,7 +3638,7 @@ doencodes(register SV *sv, register char *s, register I32 len) sv_catpvn(sv, "\n", 1); } -static SV * +STATIC SV * is_an_int(char *s, STRLEN l) { SV *result = newSVpv("", l); @@ -3571,7 +3686,7 @@ is_an_int(char *s, STRLEN l) return (result); } -static int +STATIC int div128(SV *pnum, bool *done) /* must be '\0' terminated */ @@ -3856,7 +3971,7 @@ PP(pp_pack) fromstr = NEXTFROM; ashort = (I16)SvIV(fromstr); #ifdef HAS_HTONS - ashort = htons(ashort); + ashort = PerlSock_htons(ashort); #endif CAT16(cat, &ashort); } @@ -3968,7 +4083,7 @@ PP(pp_pack) fromstr = NEXTFROM; aulong = SvUV(fromstr); #ifdef HAS_HTONL - aulong = htonl(aulong); + aulong = PerlSock_htonl(aulong); #endif CAT32(cat, &aulong); } @@ -4388,11 +4503,11 @@ PP(pp_threadsv) { djSP; #ifdef USE_THREADS - EXTEND(sp, 1); + EXTEND(SP, 1); if (op->op_private & OPpLVAL_INTRO) PUSHs(*save_threadsv(op->op_targ)); else - PUSHs(*av_fetch(thr->threadsv, op->op_targ, FALSE)); + PUSHs(THREADSV(op->op_targ)); RETURN; #else DIE("tried to access per-thread data in non-threaded perl");