if (SvROK(sv)) {
wasref:
sv = SvRV(sv);
- if (SvTYPE(sv) != SVt_PVGV)
+ if (SvTYPE(sv) == SVt_PVIO) {
+ GV *gv = (GV*) sv_newmortal();
+ gv_init(gv, 0, "", 0, 0);
+ GvIOp(gv) = (IO *)sv;
+ SvREFCNT_inc(sv);
+ sv = (SV*) gv;
+ } else if (SvTYPE(sv) != SVt_PVGV)
DIE("Not a GLOB reference");
}
else {
if (SvTYPE(sv) != SVt_PVGV) {
+ char *sym;
+
if (SvGMAGICAL(sv)) {
mg_get(sv);
if (SvROK(sv))
DIE(no_usym, "a symbol");
RETSETUNDEF;
}
+ sym = SvPV(sv, na);
if (op->op_private & HINT_STRICT_REFS)
- DIE(no_symref, "a symbol");
- sv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PVGV);
+ DIE(no_symref, sym, "a symbol");
+ sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
}
}
if (op->op_private & OPpLVAL_INTRO) {
GP *ogp = GvGP(sv);
SSCHECK(3);
- SSPUSHPTR(sv);
+ SSPUSHPTR(SvREFCNT_inc(sv));
SSPUSHPTR(ogp);
SSPUSHINT(SAVEt_GP);
if (op->op_flags & OPf_SPECIAL) {
GvGP(sv)->gp_refcnt++; /* will soon be assigned */
- GvFLAGS(sv) |= GVf_INTRO;
+ GvINTRO_on(sv);
}
else {
GP *gp;
GvREFCNT(sv) = 1;
GvSV(sv) = NEWSV(72,0);
GvLINE(sv) = curcop->cop_line;
- GvEGV(sv) = sv;
+ GvEGV(sv) = (GV*)sv;
}
}
SETs(sv);
RETURN;
}
-PP(pp_sv2len)
-{
- dSP; dTARGET;
- dPOPss;
- PUSHi(sv_len(sv));
- RETURN;
-}
-
PP(pp_rv2sv)
{
dSP; dTOPss;
}
}
else {
- GV *gv = sv;
+ GV *gv = (GV*)sv;
+ char *sym;
+
if (SvTYPE(gv) != SVt_PVGV) {
if (SvGMAGICAL(sv)) {
mg_get(sv);
DIE(no_usym, "a SCALAR");
RETSETUNDEF;
}
+ sym = SvPV(sv, na);
if (op->op_private & HINT_STRICT_REFS)
- DIE(no_symref, "a SCALAR");
- gv = (SV*)gv_fetchpv(SvPV(sv, na), TRUE, SVt_PV);
+ DIE(no_symref, sym, "a SCALAR");
+ gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV);
}
sv = GvSV(gv);
}
if (op->op_flags & OPf_MOD) {
if (op->op_private & OPpLVAL_INTRO)
sv = save_scalar((GV*)TOPs);
- else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) {
- if (SvGMAGICAL(sv))
- mg_get(sv);
- if (!SvOK(sv)) {
- (void)SvUPGRADE(sv, SVt_RV);
- SvRV(sv) = (op->op_private & OPpDEREF_HV ?
- (SV*)newHV() : (SV*)newAV());
- SvROK_on(sv);
- SvSETMAGIC(sv);
- }
- }
+ else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV))
+ provide_ref(op, sv);
}
SETs(sv);
RETURN;
GV *gv;
HV *stash;
- /* We always try to add a non-existent subroutine in case of AUTOLOAD. */
- CV *cv = sv_2cv(TOPs, &stash, &gv, TRUE);
+ /* We usually try to add a non-existent subroutine in case of AUTOLOAD. */
+ /* (But not in defined().) */
+ CV *cv = sv_2cv(TOPs, &stash, &gv, !(op->op_flags & OPf_SPECIAL));
+ if (!cv)
+ cv = (CV*)&sv_undef;
SETs((SV*)cv);
RETURN;
}
+PP(pp_prototype)
+{
+ dSP;
+ CV *cv;
+ HV *stash;
+ GV *gv;
+ SV *ret;
+
+ ret = &sv_undef;
+ cv = sv_2cv(TOPs, &stash, &gv, FALSE);
+ if (cv && SvPOK(cv)) {
+ char *p = SvPVX(cv);
+ ret = sv_2mortal(newSVpv(p ? p : "", SvLEN(cv)));
+ }
+ SETs(ret);
+ RETURN;
+}
+
PP(pp_anoncode)
{
dSP;
- XPUSHs(cSVOP->op_sv);
+ CV* cv = (CV*)cSVOP->op_sv;
+ EXTEND(SP,1);
+
+ if (CvCLONE(cv))
+ cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+
+ PUSHs((SV*)cv);
RETURN;
}
char *pv;
sv = POPs;
+
+ if (sv && SvGMAGICAL(sv))
+ mg_get(sv);
+
if (!sv || !SvROK(sv))
- RETPUSHUNDEF;
+ RETPUSHNO;
sv = SvRV(sv);
pv = sv_reftype(sv,TRUE);
PP(pp_study)
{
- dSP; dTARGET;
+ dSP; dPOPss;
register unsigned char *s;
register I32 pos;
register I32 ch;
I32 retval;
STRLEN len;
- s = (unsigned char*)(SvPV(TARG, len));
+ s = (unsigned char*)(SvPV(sv, len));
pos = len;
- if (lastscream)
- SvSCREAM_off(lastscream);
- lastscream = TARG;
+ if (sv == lastscream)
+ SvSCREAM_off(sv);
+ else {
+ if (lastscream) {
+ SvSCREAM_off(lastscream);
+ SvREFCNT_dec(lastscream);
+ }
+ lastscream = SvREFCNT_inc(sv);
+ }
if (pos <= 0) {
retval = 0;
goto ret;
sfirst[fold[ch]] = pos;
}
- SvSCREAM_on(TARG);
+ SvSCREAM_on(sv);
+ sv_magic(sv, Nullsv, 'g', Nullch, 0); /* piggyback on m//g magic */
retval = 1;
ret:
XPUSHs(sv_2mortal(newSViv((I32)retval)));
sv = GvSV(defgv);
EXTEND(SP,1);
}
- TARG = NEWSV(27,0);
+ TARG = sv_newmortal();
PUSHi(do_trans(sv, op));
RETURN;
}
RETPUSHNO;
switch (SvTYPE(sv)) {
case SVt_PVAV:
- if (AvMAX(sv) >= 0)
+ if (AvMAX(sv) >= 0 || SvRMAGICAL(sv))
RETPUSHYES;
break;
case SVt_PVHV:
- if (HvARRAY(sv))
+ if (HvARRAY(sv) || SvRMAGICAL(sv))
RETPUSHYES;
break;
case SVt_PVCV:
cv_undef((CV*)sv);
sub_generation++;
break;
+ case SVt_PVGV:
+ if (SvFAKE(sv)) {
+ sv_setsv(sv, &sv_undef);
+ break;
+ }
default:
- if (sv != GvSV(defgv)) {
- if (SvPOK(sv) && SvLEN(sv)) {
- (void)SvOOK_off(sv);
- Safefree(SvPVX(sv));
- SvPV_set(sv, Nullch);
- SvLEN_set(sv, 0);
- }
- (void)SvOK_off(sv);
- SvSETMAGIC(sv);
+ if (SvPOK(sv) && SvLEN(sv)) {
+ (void)SvOOK_off(sv);
+ Safefree(SvPVX(sv));
+ SvPV_set(sv, Nullch);
+ SvLEN_set(sv, 0);
}
+ (void)SvOK_off(sv);
+ SvSETMAGIC(sv);
}
RETPUSHUNDEF;
PP(pp_predec)
{
dSP;
- sv_dec(TOPs);
+ if (SvIOK(TOPs)) {
+ if (SvIVX(TOPs) == IV_MIN) {
+ sv_setnv(TOPs, (double)SvIVX(TOPs) - 1.0);
+ }
+ else {
+ --SvIVX(TOPs);
+ SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
+ }
+ }
+ else
+ sv_dec(TOPs);
SvSETMAGIC(TOPs);
return NORMAL;
}
{
dSP; dTARGET;
sv_setsv(TARG, TOPs);
- sv_inc(TOPs);
+ if (SvIOK(TOPs)) {
+ if (SvIVX(TOPs) == IV_MAX) {
+ sv_setnv(TOPs, (double)SvIVX(TOPs) + 1.0);
+ }
+ else {
+ ++SvIVX(TOPs);
+ SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
+ }
+ }
+ else
+ sv_inc(TOPs);
SvSETMAGIC(TOPs);
if (!SvOK(TARG))
sv_setiv(TARG, 0);
{
dSP; dTARGET;
sv_setsv(TARG, TOPs);
- sv_dec(TOPs);
+ if (SvIOK(TOPs)) {
+ if (SvIVX(TOPs) == IV_MIN) {
+ sv_setnv(TOPs, (double)SvIVX(TOPs) - 1.0);
+ }
+ else {
+ --SvIVX(TOPs);
+ SvFLAGS(TOPs) &= ~(SVf_NOK|SVf_POK|SVp_NOK|SVp_POK);
+ }
+ }
+ else
+ sv_dec(TOPs);
SvSETMAGIC(TOPs);
SETs(TARG);
return NORMAL;
{
dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
{
- register unsigned long tmpulong;
- register long tmplong;
- I32 value;
+ register IV value;
+ register UV uval;
- tmpulong = (unsigned long) POPn;
- if (tmpulong == 0L)
+ uval = POPn;
+ if (!uval)
DIE("Illegal modulus zero");
value = TOPn;
- if (value >= 0.0)
- value = (I32)(((unsigned long)value) % tmpulong);
+ if (value >= 0)
+ value = (UV)value % uval;
else {
- tmplong = (long)value;
- value = (I32)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
+ value = (uval - ((UV)(-value - 1) % uval)) - 1;
}
SETi(value);
RETURN;
PP(pp_repeat)
{
- dSP; dATARGET;
+ dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
+ {
register I32 count = POPi;
if (GIMME == G_ARRAY && op->op_private & OPpREPEAT_DOLIST) {
dMARK;
PUSHTARG;
}
RETURN;
+ }
}
PP(pp_subtract)
{
dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
{
- dPOPTOPiirl;
- SETi( left << right );
- RETURN;
+ dPOPTOPiirl;
+ SETi( left << right );
+ RETURN;
}
}
dSP; dATARGET; tryAMAGICbin(band,opASSIGN);
{
dPOPTOPssrl;
- if (SvNIOK(left) || SvNIOK(right)) {
+ if (SvNIOKp(left) || SvNIOKp(right)) {
unsigned long value = U_L(SvNV(left));
value = value & U_L(SvNV(right));
- SETn((double)value);
+ if ((IV)value == value)
+ SETi(value);
+ else
+ SETn((double)value);
}
else {
do_vop(op->op_type, TARG, left, right);
dSP; dATARGET; tryAMAGICbin(bxor,opASSIGN);
{
dPOPTOPssrl;
- if (SvNIOK(left) || SvNIOK(right)) {
+ if (SvNIOKp(left) || SvNIOKp(right)) {
unsigned long value = U_L(SvNV(left));
value = value ^ U_L(SvNV(right));
- SETn((double)value);
+ if ((IV)value == value)
+ SETi(value);
+ else
+ SETn((double)value);
}
else {
do_vop(op->op_type, TARG, left, right);
dSP; dATARGET; tryAMAGICbin(bor,opASSIGN);
{
dPOPTOPssrl;
- if (SvNIOK(left) || SvNIOK(right)) {
+ if (SvNIOKp(left) || SvNIOKp(right)) {
unsigned long value = U_L(SvNV(left));
value = value | U_L(SvNV(right));
- SETn((double)value);
+ if ((IV)value == value)
+ SETi(value);
+ else
+ SETn((double)value);
}
else {
do_vop(op->op_type, TARG, left, right);
dSP; dTARGET; tryAMAGICun(neg);
{
dTOPss;
- if (SvNIOK(sv))
+ if (SvGMAGICAL(sv))
+ mg_get(sv);
+ if (SvNIOKp(sv))
SETn(-SvNV(sv));
- else if (SvPOK(sv)) {
+ else if (SvPOKp(sv)) {
STRLEN len;
char *s = SvPV(sv, len);
if (isALPHA(*s) || *s == '_') {
sv_setnv(TARG, -SvNV(sv));
SETTARG;
}
+ else
+ SETn(-SvNV(sv));
}
RETURN;
}
dTOPss;
register I32 anum;
- if (SvNIOK(sv)) {
- SETi( ~SvIV(sv) );
+ if (SvNIOKp(sv)) {
+ UV value = ~SvIV(sv);
+ if ((IV)value == value)
+ SETi(value);
+ else
+ SETn((double)value);
}
else {
register char *tmps;
/* integer versions of some of the above */
-PP(pp_i_preinc)
-{
-#ifndef OVERLOAD
- dSP; dTOPiv;
- sv_setiv(TOPs, value + 1);
- SvSETMAGIC(TOPs);
-#else
- dSP;
- if (SvAMAGIC(TOPs) ) {
- sv_inc(TOPs);
- } else {
- dTOPiv;
- sv_setiv(TOPs, value + 1);
- SvSETMAGIC(TOPs);
- }
-#endif /* OVERLOAD */
- return NORMAL;
-}
-
-PP(pp_i_predec)
-{
-#ifndef OVERLOAD
- dSP; dTOPiv;
- sv_setiv(TOPs, value - 1);
- SvSETMAGIC(TOPs);
-#else
- dSP;
- if (SvAMAGIC(TOPs)) {
- sv_dec(TOPs);
- } else {
- dTOPiv;
- sv_setiv(TOPs, value - 1);
- SvSETMAGIC(TOPs);
- }
-#endif /* OVERLOAD */
- return NORMAL;
-}
-
-PP(pp_i_postinc)
-{
- dSP; dTARGET;
- sv_setsv(TARG, TOPs);
-#ifndef OVERLOAD
- sv_setiv(TOPs, SvIV(TOPs) + 1);
- SvSETMAGIC(TOPs);
-#else
- if (SvAMAGIC(TOPs) ) {
- sv_inc(TOPs);
- } else {
- sv_setiv(TOPs, SvIV(TOPs) + 1);
- SvSETMAGIC(TOPs);
- }
-#endif /* OVERLOAD */
- if (!SvOK(TARG))
- sv_setiv(TARG, 0);
- SETs(TARG);
- return NORMAL;
-}
-
-PP(pp_i_postdec)
-{
- dSP; dTARGET;
- sv_setsv(TARG, TOPs);
-#ifndef OVERLOAD
- sv_setiv(TOPs, SvIV(TOPs) - 1);
- SvSETMAGIC(TOPs);
-#else
- if (SvAMAGIC(TOPs) ) {
- sv_dec(TOPs);
- } else {
- sv_setiv(TOPs, SvIV(TOPs) - 1);
- SvSETMAGIC(TOPs);
- }
-#endif /* OVERLOAD */
- SETs(TARG);
- return NORMAL;
-}
-
PP(pp_i_multiply)
{
dSP; dATARGET; tryAMAGICbin(mult,opASSIGN);
{
dSP;
I32 anum;
- Time_t when;
if (MAXARG < 1) {
+#ifdef VMS
+# include <starlet.h>
+ unsigned int when[2];
+ _ckvmssts(sys$gettim(when));
+ anum = when[0] ^ when[1];
+#else
+# if defined(I_SYS_TIME) && !defined(PLAN9)
+ struct timeval when;
+ gettimeofday(&when,(struct timezone *) 0);
+ anum = when.tv_sec ^ when.tv_usec;
+# else
+ Time_t when;
(void)time(&when);
anum = when;
+# endif
+#endif
+#if !defined(PLAN9) /* XXX Plan9 assembler chokes on this; fix coming soon */
+ /* 17-Jul-1996 bailey@genetics.upenn.edu */
+ /* What is a good hashing algorithm here? */
+ anum ^= ( ( 269 * (U32)getpid())
+ ^ (26107 * (U32)&when)
+ ^ (73819 * (U32)stack_sp));
+#endif
}
else
anum = POPi;
{
dSP; dTARGET;
char *tmps;
+ unsigned long value;
I32 argtype;
tmps = POPp;
- XPUSHi( scan_hex(tmps, 99, &argtype) );
+ value = scan_hex(tmps, 99, &argtype);
+ if ((IV)value >= 0)
+ XPUSHi(value);
+ else
+ XPUSHn(U_V(value));
RETURN;
}
PP(pp_oct)
{
dSP; dTARGET;
- I32 value;
+ unsigned long value;
I32 argtype;
char *tmps;
tmps = POPp;
- while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
+ while (*tmps && isSPACE(*tmps))
+ tmps++;
+ if (*tmps == '0')
tmps++;
if (*tmps == 'x')
- value = (I32)scan_hex(++tmps, 99, &argtype);
+ value = scan_hex(++tmps, 99, &argtype);
else
- value = (I32)scan_oct(tmps, 99, &argtype);
- XPUSHi(value);
+ value = scan_oct(tmps, 99, &argtype);
+ if ((IV)value >= 0)
+ XPUSHi(value);
+ else
+ XPUSHn(U_V(value));
RETURN;
}
if (MAXARG < 3)
len = curlen;
else if (len < 0) {
- len += curlen;
+ len += curlen - pos;
if (len < 0)
len = 0;
}
rem = len;
sv_setpvn(TARG, tmps, rem);
if (lvalue) { /* it's an lvalue! */
+ if (!SvGMAGICAL(sv)) {
+ if (SvROK(sv)) {
+ SvPV_force(sv,na);
+ if (dowarn)
+ warn("Attempt to use reference as lvalue in substr");
+ }
+ if (SvOK(sv)) /* is it defined ? */
+ (void)SvPOK_only(sv);
+ else
+ sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
+ }
if (SvTYPE(TARG) < SVt_PVLV) {
sv_upgrade(TARG, SVt_PVLV);
sv_magic(TARG, Nullsv, 'x', Nullch, 0);
retnum = 0;
else {
offset >>= 3;
- if (size == 16)
- retnum = (unsigned long) s[offset] << 8;
- else if (size == 32) {
- if (offset < len) {
- if (offset + 1 < len)
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16) +
- (s[offset + 2] << 8);
- else
- retnum = ((unsigned long) s[offset] << 24) +
- ((unsigned long) s[offset + 1] << 16);
- }
+ if (size == 16) {
+ if (offset >= srclen)
+ retnum = 0;
else
+ retnum = (unsigned long) s[offset] << 8;
+ }
+ else if (size == 32) {
+ if (offset >= srclen)
+ retnum = 0;
+ else if (offset + 1 >= srclen)
retnum = (unsigned long) s[offset] << 24;
+ else if (offset + 2 >= srclen)
+ retnum = ((unsigned long) s[offset] << 24) +
+ ((unsigned long) s[offset + 1] << 16);
+ else
+ retnum = ((unsigned long) s[offset] << 24) +
+ ((unsigned long) s[offset + 1] << 16) +
+ (s[offset + 2] << 8);
}
}
}
dSP; dTARGET;
char *tmps;
- if (!SvPOK(TARG)) {
- (void)SvUPGRADE(TARG,SVt_PV);
- SvGROW(TARG,1);
- }
+ (void)SvUPGRADE(TARG,SVt_PV);
+ SvGROW(TARG,2);
SvCUR_set(TARG, 1);
tmps = SvPVX(TARG);
- *tmps = POPi;
+ *tmps++ = POPi;
+ *tmps = '\0';
(void)SvPOK_only(TARG);
XPUSHs(TARG);
RETURN;
if (len) {
(void)SvUPGRADE(TARG, SVt_PV);
- SvGROW(TARG, len * 2);
+ SvGROW(TARG, (len * 2) + 1);
d = SvPVX(TARG);
while (len--) {
if (!isALNUM(*s))
register SV** svp;
register AV* av = (AV*)POPs;
register I32 lval = op->op_flags & OPf_MOD;
+ I32 arybase = curcop->cop_arybase;
+ I32 elem;
if (SvTYPE(av) == SVt_PVAV) {
+ if (lval && op->op_private & OPpLVAL_INTRO) {
+ I32 max = -1;
+ for (svp = mark + 1; svp <= sp; svp++) {
+ elem = SvIVx(*svp);
+ if (elem > max)
+ max = elem;
+ }
+ if (max > AvMAX(av))
+ av_extend(av, max);
+ }
while (++MARK <= SP) {
- I32 elem = SvIVx(*MARK);
+ elem = SvIVx(*MARK);
+ if (elem > 0)
+ elem -= arybase;
svp = av_fetch(av, elem, lval);
if (lval) {
if (!svp || *svp == &sv_undef)
*MARK = svp ? *svp : &sv_undef;
}
}
- else if (GIMME != G_ARRAY) {
+ if (GIMME != G_ARRAY) {
MARK = ORIGMARK;
*++MARK = *SP;
SP = MARK;
{
dSP; dTARGET;
HV *hash = (HV*)POPs;
- HE *entry = hv_iternext(hash);
- I32 i;
- char *tmps;
+ HE *entry;
+
+ PUTBACK;
+ entry = hv_iternext(hash); /* might clobber stack_sp */
+ SPAGAIN;
EXTEND(SP, 2);
if (entry) {
- tmps = hv_iterkey(entry, &i);
- if (!i)
- tmps = "";
- PUSHs(sv_2mortal(newSVpv(tmps, i)));
+ PUSHs(hv_iterkeysv(entry)); /* won't clobber stack_sp */
if (GIMME == G_ARRAY) {
- sv_setsv(TARG, hv_iterval(hash, entry));
+ PUTBACK;
+ sv_setsv(TARG, hv_iterval(hash, entry)); /* might clobber stack_sp */
+ SPAGAIN;
PUSHs(TARG);
}
}
SV *sv;
SV *tmpsv = POPs;
HV *hv = (HV*)POPs;
- char *tmps;
STRLEN len;
if (SvTYPE(hv) != SVt_PVHV) {
DIE("Not a HASH reference");
}
- tmps = SvPV(tmpsv, len);
- sv = hv_delete(hv, tmps, len);
+ sv = hv_delete_ent(hv, tmpsv,
+ (op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0), 0);
if (!sv)
RETPUSHUNDEF;
PUSHs(sv);
dSP;
SV *tmpsv = POPs;
HV *hv = (HV*)POPs;
- char *tmps;
STRLEN len;
if (SvTYPE(hv) != SVt_PVHV) {
DIE("Not a HASH reference");
}
- tmps = SvPV(tmpsv, len);
- if (hv_exists(hv, tmps, len))
+ if (hv_exists_ent(hv, tmpsv, 0))
RETPUSHYES;
RETPUSHNO;
}
PP(pp_hslice)
{
dSP; dMARK; dORIGMARK;
- register SV **svp;
+ register HE *he;
register HV *hv = (HV*)POPs;
register I32 lval = op->op_flags & OPf_MOD;
if (SvTYPE(hv) == SVt_PVHV) {
while (++MARK <= SP) {
- STRLEN keylen;
- char *key = SvPV(*MARK, keylen);
+ SV *keysv = *MARK;
- svp = hv_fetch(hv, key, keylen, lval);
+ he = hv_fetch_ent(hv, keysv, lval, 0);
if (lval) {
- if (!svp || *svp == &sv_undef)
- DIE(no_helem, key);
+ if (!he || HeVAL(he) == &sv_undef)
+ DIE(no_helem, SvPV(keysv, na));
if (op->op_private & OPpLVAL_INTRO)
- save_svref(svp);
+ save_svref(&HeVAL(he));
}
- *MARK = svp ? *svp : &sv_undef;
+ *MARK = he ? HeVAL(he) : &sv_undef;
}
}
if (GIMME != G_ARRAY) {
SV **firstlelem = stack_base + POPMARK + 1;
register SV **firstrelem = lastlelem + 1;
I32 arybase = curcop->cop_arybase;
+ I32 lval = op->op_flags & OPf_MOD;
+ I32 is_something_there = lval;
register I32 max = lastrelem - lastlelem;
register SV **lelem;
register I32 ix;
if (GIMME != G_ARRAY) {
- ix = SvIVx(*lastlelem) - arybase;
+ ix = SvIVx(*lastlelem);
+ if (ix < 0)
+ ix += max;
+ else
+ ix -= arybase;
if (ix < 0 || ix >= max)
*firstlelem = &sv_undef;
else
}
for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
- ix = SvIVx(*lelem) - arybase;
+ ix = SvIVx(*lelem);
if (ix < 0) {
ix += max;
if (ix < 0)
else if (!(*lelem = firstrelem[ix]))
*lelem = &sv_undef;
}
- else if (ix >= max || !(*lelem = firstrelem[ix]))
- *lelem = &sv_undef;
+ else {
+ ix -= arybase;
+ if (ix >= max || !(*lelem = firstrelem[ix]))
+ *lelem = &sv_undef;
+ }
+ if (!is_something_there && (SvOKp(*lelem) || SvGMAGICAL(*lelem)))
+ is_something_there = TRUE;
}
- SP = lastlelem;
+ if (is_something_there)
+ SP = lastlelem;
+ else
+ SP = firstlelem - 1;
RETURN;
}
while (MARK < SP) {
SV* key = *++MARK;
- char *tmps;
SV *val = NEWSV(46, 0);
if (MARK < SP)
sv_setsv(val, *++MARK);
else
warn("Odd number of elements in hash list");
- tmps = SvPV(key,len);
- (void)hv_store(hv,tmps,len,val,0);
+ (void)hv_store_ent(hv,key,val,0);
}
SP = ORIGMARK;
XPUSHs((SV*)hv);
if (GIMME != G_ARRAY) { /* arrange to do first one only */
/*SUPPRESS 530*/
for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
- if (strchr("aAbBhH", *patend) || *pat == '%') {
+ if (strchr("aAbBhHP", *patend) || *pat == '%') {
patend++;
while (isDIGIT(*patend) || *patend == '*')
patend++;
Copy(s, &auint, 1, unsigned int);
s += sizeof(unsigned int);
sv = NEWSV(41, 0);
- sv_setiv(sv, (I32)auint);
+ if (auint <= I32_MAX)
+ sv_setiv(sv, (I32)auint);
+ else
+ sv_setnv(sv, (double)auint);
PUSHs(sv_2mortal(sv));
}
}
PUSHs(sv_2mortal(sv));
}
break;
+ case 'w':
+ along = (strend - s) / sizeof(char);
+ if (len > along)
+ len = along;
+ EXTEND(SP, len);
+ {
+ I8 bytes = 0;
+
+ auint = 0;
+ while (len > 0) {
+ if (s >= strend) {
+ if (auint) {
+ DIE("Unterminated compressed integer");
+ } else {
+ break;
+ }
+ }
+ auint = (auint << 7) | (*s & 0x7f);
+ if (!(*s & 0x80)) {
+ sv = NEWSV(40, 0);
+ sv_setiv(sv, (I32) auint);
+ PUSHs(sv_2mortal(sv));
+ len--;
+ auint = 0;
+ bytes = 0;
+ } else if (++bytes >= sizeof(auint)) { /* promote to double */
+ adouble = auint;
+
+ while (*s & 0x80) {
+ adouble = (adouble * 128) + (*(++s) & 0x7f);
+ if (s >= strend) {
+ DIE("Unterminated compressed integer");
+ }
+ }
+ sv = NEWSV(40, 0);
+ sv_setnv(sv, adouble);
+ PUSHs(sv_2mortal(sv));
+ len--;
+ auint = 0;
+ bytes = 0;
+ }
+ s++;
+ }
+ }
+ break;
case 'P':
EXTEND(SP, 1);
if (sizeof(char*) > strend - s)
case 'u':
along = (strend - s) * 3 / 4;
sv = NEWSV(42, along);
+ if (along)
+ SvPOK_on(sv);
while (s < strend && *s > ' ' && *s < 'a') {
I32 a, b, c, d;
char hunk[4];
sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
}
break;
+ case 'w':
+ while (len-- > 0) {
+ fromstr = NEXTFROM;
+ adouble = floor((double)SvNV(fromstr));
+
+ if (adouble < 268435456) { /* we can use integers */
+ unsigned char buf[4]; /* buffer for compressed int */
+ unsigned char *in = buf + 3;
+ auint = U_I(adouble);
+ do {
+ *(in--) = (unsigned char) ((auint & 0x7f) | 0x80);
+ auint >>= 7;
+ } while (auint);
+ buf[3] &= 0x7f; /* clear continue bit */
+ sv_catpvn(cat, (char*) in+1, buf+3-in);
+ } else {
+ unsigned char buf[sizeof(double)*2]; /* buffer for compressed int */
+ I8 msize = sizeof(double)*2; /* 8/7 would be enough */
+ unsigned char *in = buf + msize -1;
+ if (adouble<0) {
+ croak("Cannot compress negative numbers");
+ }
+ do {
+ double next = adouble/128;
+ *in = (unsigned char) (adouble - floor(next)*128);
+ *in |= 0x80; /* set continue bit */
+ if (--in < buf) { /* this cannot happen ;-) */
+ croak ("Cannot compress integer");
+ }
+ adouble = next;
+ } while (floor(adouble)>0); /* floor() not necessary? */
+ buf[msize-1] &= 0x7f; /* clear continue bit */
+ sv_catpvn(cat, (char*) in+1, buf+msize-in-1);
+ }
+ }
+ break;
case 'i':
while (len-- > 0) {
fromstr = NEXTFROM;
I32 origlimit = limit;
I32 realarray = 0;
I32 base;
- AV *oldstack = stack;
+ AV *oldstack = curstack;
register REGEXP *rx = pm->op_pmregexp;
I32 gimme = GIMME;
+ I32 oldsave = savestack_ix;
if (!pm || !s)
DIE("panic: do_split");
av_extend(ary,0);
av_clear(ary);
/* temporarily switch stacks */
- SWITCHSTACK(stack, ary);
+ SWITCHSTACK(curstack, ary);
}
base = SP - stack_base;
orig = s;
while (isSPACE(*s))
s++;
}
+ if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
+ SAVEINT(multiline);
+ multiline = pm->op_pmflags & PMf_MULTILINE;
+ }
+
if (!limit)
limit = maxiters + 2;
if (pm->op_pmflags & PMf_WHITE) {
else {
maxiters += (strend - s) * rx->nparens;
while (s < strend && --limit &&
- regexec(rx, s, strend, orig, 1, Nullsv, TRUE) ) {
+ pregexec(rx, s, strend, orig, 1, Nullsv, TRUE) ) {
if (rx->subbase
&& rx->subbase != orig) {
m = s;
for (i = 1; i <= rx->nparens; i++) {
s = rx->startp[i];
m = rx->endp[i];
- dstr = NEWSV(33, m-s);
- sv_setpvn(dstr, s, m-s);
+ if (m && s) {
+ dstr = NEWSV(33, m-s);
+ sv_setpvn(dstr, s, m-s);
+ }
+ else
+ dstr = NEWSV(33, 0);
if (!realarray)
sv_2mortal(dstr);
XPUSHs(dstr);
s = rx->endp[0];
}
}
+ LEAVE_SCOPE(oldsave);
iters = (SP - stack_base) - base;
if (iters > maxiters)
DIE("Split loop");
iters++;
}
else if (!origlimit) {
- while (iters > 0 && SvCUR(TOPs) == 0)
+ while (iters > 0 && (!TOPs || !SvANY(TOPs) || SvCUR(TOPs) == 0))
iters--, SP--;
}
if (realarray) {