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;
RETURN;
}
-PP(pp_sv2len)
-{
- dSP; dTARGET;
- dPOPss;
- PUSHi(sv_len(sv));
- RETURN;
-}
-
PP(pp_rv2sv)
{
dSP; dTOPss;
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;
CV* cv = (CV*)cSVOP->op_sv;
EXTEND(SP,1);
- if (SvFLAGS(cv) & SVpcv_CLONE) {
- cv = cv_clone(cv);
- }
+ if (CvCLONE(cv))
+ cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
PUSHs((SV*)cv);
RETURN;
sv = POPs;
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)));
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;
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);
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);
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);
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)) {
+ if (SvNIOKp(sv)) {
IV iv = ~SvIV(sv);
if (iv < 0)
SETn( (double) ~U_L(SvNV(sv)) );
{
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;
}
rem = len;
sv_setpvn(TARG, tmps, rem);
if (lvalue) { /* it's an lvalue! */
- (void)SvPOK_only(sv);
+ if (!SvGMAGICAL(sv))
+ (void)SvPOK_only(sv);
if (SvTYPE(TARG) < SVt_PVLV) {
sv_upgrade(TARG, SVt_PVLV);
sv_magic(TARG, Nullsv, 'x', Nullch, 0);
if (len) {
(void)SvUPGRADE(TARG, SVt_PV);
- SvGROW(TARG, len * 2);
+ SvGROW(TARG, (len * 2) + 1);
d = SvPVX(TARG);
while (len--) {
if (!isALNUM(*s))
{
dSP; dTARGET;
HV *hash = (HV*)POPs;
- HE *entry = hv_iternext(hash);
+ HE *entry;
I32 i;
char *tmps;
+
+ PUTBACK;
+ entry = hv_iternext(hash); /* might clobber stack_sp */
+ SPAGAIN;
EXTEND(SP, 2);
if (entry) {
- tmps = hv_iterkey(entry, &i);
+ tmps = hv_iterkey(entry, &i); /* won't clobber stack_sp */
if (!i)
tmps = "";
PUSHs(sv_2mortal(newSVpv(tmps, i)));
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 **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;
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;
}
AV *oldstack = stack;
register REGEXP *rx = pm->op_pmregexp;
I32 gimme = GIMME;
+ I32 oldsave = savestack_ix;
if (!pm || !s)
DIE("panic: do_split");
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;
s = rx->endp[0];
}
}
+ LEAVE_SCOPE(oldsave);
iters = (SP - stack_base) - base;
if (iters > maxiters)
DIE("Split loop");