#include "EXTERN.h"
#include "perl.h"
-static void doencodes _((SV *sv, char *s, I32 len));
+/*
+ * Types used in bitwise operations.
+ *
+ * Normally we'd just use IV and UV. However, some hardware and
+ * software combinations (e.g. Alpha and current OSF/1) don't have a
+ * floating-point type to use for NV that has adequate bits to fully
+ * hold an IV/UV. (In other words, sizeof(long) == sizeof(double).)
+ *
+ * It just so happens that "int" is the right size everywhere, at
+ * least today.
+ */
+typedef int IBW;
+typedef unsigned UBW;
+
+static SV* refto _((SV* sv));
+static void doencodes _((SV* sv, char* s, I32 len));
/* variations on pp_null */
sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV);
}
}
- if (op->op_private & OPpLVAL_INTRO) {
- GP *ogp = GvGP(sv);
-
- SSCHECK(3);
- SSPUSHPTR(SvREFCNT_inc(sv));
- SSPUSHPTR(ogp);
- SSPUSHINT(SAVEt_GP);
-
- if (op->op_flags & OPf_SPECIAL) {
- GvGP(sv)->gp_refcnt++; /* will soon be assigned */
- GvINTRO_on(sv);
- }
- else {
- GP *gp;
- Newz(602,gp, 1, GP);
- GvGP(sv) = gp;
- GvREFCNT(sv) = 1;
- GvSV(sv) = NEWSV(72,0);
- GvLINE(sv) = curcop->cop_line;
- GvEGV(sv) = (GV*)sv;
- }
- }
+ if (op->op_private & OPpLVAL_INTRO)
+ save_gp((GV*)sv, !(op->op_flags & OPf_SPECIAL));
SETs(sv);
RETURN;
}
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))
+ else if (op->op_private & OPpDEREF)
provide_ref(op, sv);
}
SETs(sv);
dSP; dTARGET; dPOPss;
if (op->op_flags & OPf_MOD) {
- LvTYPE(TARG) = '<';
+ if (SvTYPE(TARG) < SVt_PVLV) {
+ sv_upgrade(TARG, SVt_PVLV);
+ sv_magic(TARG, Nullsv, '.', Nullch, 0);
+ }
+
+ LvTYPE(TARG) = '.';
LvTARG(TARG) = sv;
PUSHs(TARG); /* no SvSETMAGIC */
RETURN;
/* 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)
+ if (cv) {
+ if (CvCLONE(cv))
+ cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+ }
+ else
cv = (CV*)&sv_undef;
SETs((SV*)cv);
RETURN;
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)));
- }
+ if (cv && SvPOK(cv))
+ ret = sv_2mortal(newSVpv(SvPVX(cv), SvCUR(cv)));
SETs(ret);
RETURN;
}
PP(pp_anoncode)
{
dSP;
- CV* cv = (CV*)cSVOP->op_sv;
- EXTEND(SP,1);
-
+ CV* cv = (CV*)curpad[op->op_targ];
if (CvCLONE(cv))
cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
-
+ EXTEND(SP,1);
PUSHs((SV*)cv);
RETURN;
}
PP(pp_srefgen)
{
- dSP; dTOPss;
- SV* rv;
- rv = sv_newmortal();
- sv_upgrade(rv, SVt_RV);
- if (SvPADTMP(sv))
- sv = newSVsv(sv);
- else {
- SvTEMP_off(sv);
- (void)SvREFCNT_inc(sv);
- }
- SvRV(rv) = sv;
- SvROK_on(rv);
- SETs(rv);
+ dSP;
+ *SP = refto(*SP);
RETURN;
}
PP(pp_refgen)
{
dSP; dMARK;
- SV* sv;
- SV* rv;
if (GIMME != G_ARRAY) {
MARK[1] = *SP;
SP = MARK + 1;
}
EXTEND_MORTAL(SP - MARK);
- while (MARK < SP) {
- sv = *++MARK;
- rv = sv_newmortal();
- sv_upgrade(rv, SVt_RV);
- if (SvPADTMP(sv))
- sv = newSVsv(sv);
- else {
- SvTEMP_off(sv);
- (void)SvREFCNT_inc(sv);
- }
- SvRV(rv) = sv;
- SvROK_on(rv);
- *MARK = rv;
- }
+ while (++MARK <= SP)
+ *MARK = refto(*MARK);
RETURN;
}
+static SV*
+refto(sv)
+SV* sv;
+{
+ SV* rv;
+
+ if (SvTYPE(sv) == SVt_PVLV && LvTYPE(sv) == 'y') {
+ if (LvTARGLEN(sv))
+ vivify_itervar(sv);
+ if (LvTARG(sv))
+ sv = LvTARG(sv);
+ }
+ else if (SvPADTMP(sv))
+ sv = newSVsv(sv);
+ else {
+ SvTEMP_off(sv);
+ (void)SvREFCNT_inc(sv);
+ }
+ rv = sv_newmortal();
+ sv_upgrade(rv, SVt_RV);
+ SvRV(rv) = sv;
+ SvROK_on(rv);
+ return rv;
+}
+
PP(pp_ref)
{
dSP; dTARGET;
{
dSP; dATARGET; tryAMAGICbin(div,opASSIGN);
{
- dPOPnv;
- if (value == 0.0)
+ dPOPPOPnnrl;
+ double value;
+ if (right == 0.0)
DIE("Illegal division by zero");
#ifdef SLOPPYDIVIDE
/* insure that 20./5. == 4. */
{
- double x;
- I32 k;
- x = POPn;
- if ((double)I_32(x) == x &&
- (double)I_32(value) == value &&
- (k = I_32(x)/I_32(value))*I_32(value) == I_32(x)) {
+ IV k;
+ if ((double)I_V(left) == left &&
+ (double)I_V(right) == right &&
+ (k = I_V(left)/I_V(right))*I_V(right) == I_V(left)) {
value = k;
} else {
- value = x/value;
+ value = left / right;
}
}
#else
- value = POPn / value;
+ value = left / right;
#endif
PUSHn( value );
RETURN;
{
dSP; dATARGET; tryAMAGICbin(mod,opASSIGN);
{
- register IV value;
- register UV uval;
+ register UV right;
- uval = POPn;
- if (!uval)
+ right = POPu;
+ if (!right)
DIE("Illegal modulus zero");
- value = TOPn;
- if (value >= 0)
- value = (UV)value % uval;
+
+ if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+ register IV left = SvIVX(TOPs);
+ if (left < 0)
+ SETu( (right - ((UV)(-left) - 1) % right) - 1 );
+ else
+ SETi( left % right );
+ }
else {
- value = (uval - ((UV)(-value - 1) % uval)) - 1;
+ register double left = TOPn;
+ if (left < 0.0)
+ SETu( (right - (U_V(-left) - 1) % right) - 1 );
+ else
+ SETu( U_V(left) % right );
}
- SETi(value);
RETURN;
}
}
if (SvROK(tmpstr))
sv_unref(tmpstr);
}
- SvSetSV(TARG, tmpstr);
- SvPV_force(TARG, len);
- if (count >= 1) {
- SvGROW(TARG, (count * len) + 1);
- if (count > 1)
- repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
- SvCUR(TARG) *= count;
- *SvEND(TARG) = '\0';
+ if (USE_LEFT(tmpstr) || SvTYPE(tmpstr) > SVt_PVMG) {
+ SvSetSV(TARG, tmpstr);
+ SvPV_force(TARG, len);
+ if (count != 1) {
+ if (count < 1)
+ SvCUR_set(TARG, 0);
+ else {
+ SvGROW(TARG, (count * len) + 1);
+ repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
+ SvCUR(TARG) *= count;
+ }
+ *SvEND(TARG) = '\0';
+ }
(void)SvPOK_only(TARG);
}
else
{
dSP; dATARGET; tryAMAGICbin(subtr,opASSIGN);
{
- dPOPTOPnnrl;
+ dPOPTOPnnrl_ul;
SETn( left - right );
RETURN;
}
{
dSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
{
- dPOPTOPiirl;
- if (op->op_private & HINT_INTEGER)
- SETi( left << right );
- else
- SETu( (UV)left << right );
+ IBW shift = POPi;
+ if (op->op_private & HINT_INTEGER) {
+ IBW i = TOPi;
+ SETi( i << shift );
+ }
+ else {
+ UBW u = TOPu;
+ SETu( u << shift );
+ }
RETURN;
}
}
{
dSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
{
- dPOPTOPiirl;
- if (op->op_private & HINT_INTEGER)
- SETi( left >> right );
- else
- SETu( (UV)left >> right );
+ IBW shift = POPi;
+ if (op->op_private & HINT_INTEGER) {
+ IBW i = TOPi;
+ SETi( i >> shift );
+ }
+ else {
+ UBW u = TOPu;
+ SETu( u >> shift );
+ }
RETURN;
}
}
}
}
+PP(pp_seq)
+{
+ dSP; tryAMAGICbinSET(seq,0);
+ {
+ dPOPTOPssrl;
+ SETs( sv_eq(left, right) ? &sv_yes : &sv_no );
+ RETURN;
+ }
+}
+
PP(pp_sne)
{
dSP; tryAMAGICbinSET(sne,0);
{
dPOPTOPssrl;
- bool ne = ((op->op_private & OPpLOCALE)
- ? (sv_cmp_locale(left, right) != 0)
- : !sv_eq(left, right));
- SETs( ne ? &sv_yes : &sv_no );
+ SETs( !sv_eq(left, right) ? &sv_yes : &sv_no );
RETURN;
}
}
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
- UV value = SvIV(left) & SvIV(right);
- if (op->op_private & HINT_INTEGER)
- SETi( (IV)value );
- else
+ if (op->op_private & HINT_INTEGER) {
+ IBW value = SvIV(left) & SvIV(right);
+ SETi( value );
+ }
+ else {
+ UBW value = SvUV(left) & SvUV(right);
SETu( value );
+ }
}
else {
do_vop(op->op_type, TARG, left, right);
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
- UV value = SvIV(left) ^ SvIV(right);
- if (op->op_private & HINT_INTEGER)
- SETi( (IV)value );
- else
+ if (op->op_private & HINT_INTEGER) {
+ IBW value = SvIV(left) ^ SvIV(right);
+ SETi( value );
+ }
+ else {
+ UBW value = SvUV(left) ^ SvUV(right);
SETu( value );
+ }
}
else {
do_vop(op->op_type, TARG, left, right);
{
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
- UV value = SvIV(left) | SvIV(right);
- if (op->op_private & HINT_INTEGER)
- SETi( (IV)value );
- else
+ if (op->op_private & HINT_INTEGER) {
+ IBW value = SvIV(left) | SvIV(right);
+ SETi( value );
+ }
+ else {
+ UBW value = SvUV(left) | SvUV(right);
SETu( value );
+ }
}
else {
do_vop(op->op_type, TARG, left, right);
{
dTOPss;
if (SvNIOKp(sv)) {
- UV value = ~(UV)SvIV(sv);
- if (op->op_private & HINT_INTEGER)
- SETi( (IV)value );
- else
+ if (op->op_private & HINT_INTEGER) {
+ IBW value = ~SvIV(sv);
+ SETi( value );
+ }
+ else {
+ UBW value = ~SvUV(sv);
SETu( value );
+ }
}
else {
register char *tmps;
_ckvmssts(sys$gettim(when));
anum = when[0] ^ when[1];
#else
-# if defined(I_SYS_TIME) && !defined(PLAN9)
+# ifdef HAS_GETTIMEOFDAY
struct timeval when;
gettimeofday(&when,(struct timezone *) 0);
anum = when.tv_sec ^ when.tv_usec;
double value;
value = POPn;
if (value <= 0.0) {
- NUMERIC_STANDARD();
+ SET_NUMERIC_STANDARD();
DIE("Can't take log of %g", value);
}
value = log(value);
double value;
value = POPn;
if (value < 0.0) {
- NUMERIC_STANDARD();
+ SET_NUMERIC_STANDARD();
DIE("Can't take sqrt of %g", value);
}
value = sqrt(value);
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);
}
- LvTYPE(TARG) = 's';
+ LvTYPE(TARG) = 'x';
LvTARG(TARG) = sv;
LvTARGOFF(TARG) = pos;
LvTARGLEN(TARG) = rem;
PP(pp_sprintf)
{
dSP; dMARK; dORIGMARK; dTARGET;
-#ifdef LC_NUMERIC
+#ifdef USE_LOCALE_NUMERIC
if (op->op_private & OPpLOCALE)
- NUMERIC_LOCAL();
+ SET_NUMERIC_LOCAL();
else
- NUMERIC_STANDARD();
-#endif /* LC_NUMERIC */
+ SET_NUMERIC_STANDARD();
+#endif
do_sprintf(TARG, SP-MARK, MARK+1);
TAINT_IF(SvTAINTED(TARG));
SP = ORIGMARK;
{
dSP;
SV *sv;
- SV *tmpsv = POPs;
- HV *hv = (HV*)POPs;
- STRLEN len;
- if (SvTYPE(hv) != SVt_PVHV) {
- DIE("Not a HASH reference");
+ HV *hv;
+
+ if (op->op_private & OPpSLICE) {
+ dMARK; dORIGMARK;
+ hv = (HV*)POPs;
+ if (SvTYPE(hv) != SVt_PVHV)
+ DIE("Not a HASH reference");
+ while (++MARK <= SP) {
+ sv = hv_delete_ent(hv, *MARK,
+ (op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0), 0);
+ *MARK = sv ? sv : &sv_undef;
+ }
+ if (GIMME != G_ARRAY) {
+ MARK = ORIGMARK;
+ *++MARK = *SP;
+ SP = MARK;
+ }
+ }
+ else {
+ SV *keysv = POPs;
+ hv = (HV*)POPs;
+ if (SvTYPE(hv) != SVt_PVHV)
+ DIE("Not a HASH reference");
+ sv = hv_delete_ent(hv, keysv,
+ (op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0), 0);
+ if (!sv)
+ sv = &sv_undef;
+ PUSHs(sv);
}
- sv = hv_delete_ent(hv, tmpsv,
- (op->op_private & OPpLEAVE_VOID ? G_DISCARD : 0), 0);
- if (!sv)
- RETPUSHUNDEF;
- PUSHs(sv);
RETURN;
}
PP(pp_anonhash)
{
dSP; dMARK; dORIGMARK;
- STRLEN len;
HV* hv = (HV*)sv_2mortal((SV*)newHV());
while (MARK < SP) {
Copy(AvARRAY(ary)+offset, MARK, length, SV*);
if (AvREAL(ary)) {
EXTEND_MORTAL(length);
- for (i = length, dst = MARK; i; i--)
- sv_2mortal(*dst++); /* free them eventualy */
+ for (i = length, dst = MARK; i; i--) {
+ if (!SvIMMORTAL(*dst))
+ sv_2mortal(*dst); /* free them eventualy */
+ dst++;
+ }
}
MARK += length - 1;
}
else {
*MARK = AvARRAY(ary)[offset+length-1];
if (AvREAL(ary)) {
- sv_2mortal(*MARK);
+ if (!SvIMMORTAL(*MARK))
+ sv_2mortal(*MARK);
for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
SvREFCNT_dec(*dst++); /* free them now */
}
Copy(tmparyval, MARK, length, SV*);
if (AvREAL(ary)) {
EXTEND_MORTAL(length);
- for (i = length, dst = MARK; i; i--)
- sv_2mortal(*dst++); /* free them eventualy */
+ for (i = length, dst = MARK; i; i--) {
+ if (!SvIMMORTAL(*dst))
+ sv_2mortal(*dst); /* free them eventualy */
+ dst++;
+ }
}
Safefree(tmparyval);
}
else if (length--) {
*MARK = tmparyval[length];
if (AvREAL(ary)) {
- sv_2mortal(*MARK);
+ if (!SvIMMORTAL(*MARK))
+ sv_2mortal(*MARK);
while (length-- > 0)
SvREFCNT_dec(tmparyval[length]);
}
dSP;
AV *av = (AV*)POPs;
SV *sv = av_pop(av);
- if (sv != &sv_undef && AvREAL(av))
+ if (!SvIMMORTAL(sv) && AvREAL(av))
(void)sv_2mortal(sv);
PUSHs(sv);
RETURN;
EXTEND(SP, 1);
if (!sv)
RETPUSHUNDEF;
- if (sv != &sv_undef && AvREAL(av))
+ if (!SvIMMORTAL(sv) && AvREAL(av))
(void)sv_2mortal(sv);
PUSHs(sv);
RETURN;
{
dSP;
dPOPPOPssrl;
+ SV **oldsp = sp;
SV *sv;
STRLEN llen;
STRLEN rlen;
checksum = 0;
}
}
+ if (sp == oldsp && GIMME != G_ARRAY)
+ PUSHs(&sv_undef);
RETURN;
}
*--in = div128(norm, &done) | 0x80;
result[len - 1] &= 0x7F; /* clear continue bit */
sv_catpvn(cat, in, (result + len) - in);
+ Safefree(result);
SvREFCNT_dec(norm); /* free norm */
}
else if (SvNOKp(fromstr)) {