#include <signal.h>
#endif
-#ifdef BUGGY_MSC
- #pragma function(memcmp)
-#endif /* BUGGY_MSC */
-
-#ifdef BUGGY_MSC
- #pragma intrinsic(memcmp)
-#endif /* BUGGY_MSC */
-
I32
do_trans(sv,arg)
SV *sv;
OP *arg;
{
register short *tbl;
- register char *s;
- register I32 matches = 0;
+ register U8 *s;
+ register U8 *send;
+ register U8 *d;
register I32 ch;
- register char *send;
- register char *d;
+ register I32 matches = 0;
register I32 squash = op->op_private & OPpTRANS_SQUASH;
STRLEN len;
if (SvREADONLY(sv))
croak(no_modify);
- tbl = (short*) cPVOP->op_pv;
- s = SvPV(sv, len);
+ tbl = (short*)cPVOP->op_pv;
+ s = (U8*)SvPV(sv, len);
if (!len)
return 0;
if (!SvPOKp(sv))
- s = SvPV_force(sv, len);
+ s = (U8*)SvPV_force(sv, len);
(void)SvPOK_only(sv);
send = s + len;
if (!tbl || !s)
DEBUG_t( deb("2.TBL\n"));
if (!op->op_private) {
while (s < send) {
- if ((ch = tbl[*s & 0377]) >= 0) {
+ if ((ch = tbl[*s]) >= 0) {
matches++;
*s = ch;
}
else {
d = s;
while (s < send) {
- if ((ch = tbl[*s & 0377]) >= 0) {
+ if ((ch = tbl[*s]) >= 0) {
*d = ch;
if (matches++ && squash) {
if (d[-1] == *d)
}
matches += send - d; /* account for disappeared chars */
*d = '\0';
- SvCUR_set(sv, d - SvPVX(sv));
+ SvCUR_set(sv, d - (U8*)SvPVX(sv));
}
SvSETMAGIC(sv);
return matches;
register char *s;
register char *t;
register char *f;
- bool dolong;
-#ifdef HAS_QUAD
- bool doquad;
-#endif /* HAS_QUAD */
+ char dotype;
char ch;
register char *send;
register SV *arg;
f = t;
*buf = '\0';
xs = buf;
-#ifdef HAS_QUAD
- doquad =
-#endif /* HAS_QUAD */
- dolong = FALSE;
+ dotype = '\0';
pre = post = 0;
for (t++; t < send; t++) {
switch (*t) {
len++, sarg--;
xlen = strlen(xs);
break;
+ case 'n': case '*':
+ croak("Use of %c in printf format not supported", *t);
+
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.': case '#': case '-': case '+': case ' ':
continue;
case 'l':
#ifdef HAS_QUAD
- if (dolong) {
- dolong = FALSE;
- doquad = TRUE;
- } else
+ if (dotype == 'l')
+ dotype = 'q';
+ else
#endif
- dolong = TRUE;
+ dotype = 'l';
+ continue;
+ case 'h':
+ dotype = 's';
continue;
case 'c':
ch = *(++t);
}
break;
case 'D':
- dolong = TRUE;
+ dotype = 'l';
/* FALL THROUGH */
case 'd':
+ case 'i':
ch = *(++t);
*t = '\0';
+ switch (dotype) {
#ifdef HAS_QUAD
- if (doquad)
- (void)sprintf(buf,s,(Quad_t)SvNV(arg));
- else
+ case 'q':
+ /* perl.h says that if quad is available, IV is quad */
+ (void)sprintf(xs,f,(Quad_t)SvIV(arg));
+ break;
#endif
- if (dolong)
- (void)sprintf(xs,f,(long)SvNV(arg));
- else
- (void)sprintf(xs,f,SvIV(arg));
+ case 'l':
+ (void)sprintf(xs,f,(long)SvIV(arg));
+ break;
+ default:
+ (void)sprintf(xs,f,(int)SvIV(arg));
+ break;
+ case 's':
+ (void)sprintf(xs,f,(short)SvIV(arg));
+ break;
+ }
xlen = strlen(xs);
break;
case 'X': case 'O':
- dolong = TRUE;
+ dotype = 'l';
/* FALL THROUGH */
case 'x': case 'o': case 'u':
ch = *(++t);
*t = '\0';
- value = SvNV(arg);
+ switch (dotype) {
#ifdef HAS_QUAD
- if (doquad)
- (void)sprintf(buf,s,(unsigned Quad_t)value);
- else
+ case 'q':
+ /* perl.h says that if quad is available, UV is quad */
+ (void)sprintf(xs,f,(unsigned Quad_t)SvUV(arg));
+ break;
#endif
- if (dolong)
- (void)sprintf(xs,f,U_L(value));
- else
- (void)sprintf(xs,f,U_I(value));
+ case 'l':
+ (void)sprintf(xs,f,(unsigned long)SvUV(arg));
+ break;
+ default:
+ (void)sprintf(xs,f,(unsigned int)SvUV(arg));
+ break;
+ case 's':
+ (void)sprintf(xs,f,(unsigned short)SvUV(arg));
+ break;
+ }
xlen = strlen(xs);
break;
case 'E': case 'e': case 'f': case 'G': case 'g':
*t = '\0';
(void)sprintf(xs,f,SvNV(arg));
xlen = strlen(xs);
+#ifdef LC_NUMERIC
+ /*
+ * User-defined locales may include arbitrary characters.
+ * And, unfortunately, some system may alloc the "C" locale
+ * to be overridden by a malicious user.
+ */
+ if (op->op_type == OP_SPRINTF)
+ SvTAINTED_on(sv);
+#endif /* LC_NUMERIC */
break;
case 's':
ch = *(++t);
}
/* end of switch, copy results */
*t = ch;
+ if (xs == buf && xlen >= sizeof(buf)) { /* Ooops! */
+ PerlIO_puts(PerlIO_stderr(),"panic: sprintf overflow - memory corrupted!\n");
+ my_exit(1);
+ }
SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
sv_catpvn(sv, s, f - s);
if (pre) {
return;
}
s = SvPV(sv, len);
- if (len && !SvPOKp(sv))
+ if (len && !SvPOK(sv))
s = SvPV_force(sv, len);
if (s && len) {
s += --len;
do_chomp(sv)
register SV *sv;
{
- register I32 count = 0;
+ register I32 count;
STRLEN len;
char *s;
-
+
+ if (RsSNARF(rs))
+ return 0;
+ count = 0;
if (SvTYPE(sv) == SVt_PVAV) {
register I32 i;
I32 max;
s = SvPV_force(sv, len);
if (s && len) {
s += --len;
- if (rspara) {
+ if (RsPARA(rs)) {
if (*s != '\n')
goto nope;
++count;
++count;
}
}
- else if (rslen == 1) {
- if (*s != rschar)
- goto nope;
- ++count;
- }
else {
- if (len < rslen - 1)
- goto nope;
- len -= rslen - 1;
- s -= rslen - 1;
- if (bcmp(s, rs, rslen))
- goto nope;
- count += rslen;
+ STRLEN rslen;
+ char *rsptr = SvPV(rs, rslen);
+ if (rslen == 1) {
+ if (*s != *rsptr)
+ goto nope;
+ ++count;
+ }
+ else {
+ if (len < rslen - 1)
+ goto nope;
+ len -= rslen - 1;
+ s -= rslen - 1;
+ if (memNE(s, rsptr, rslen))
+ goto nope;
+ count += rslen;
+ }
}
-
*s = '\0';
SvCUR_set(sv, len);
SvNIOK_off(sv);
register char *dc;
STRLEN leftlen;
STRLEN rightlen;
- register char *lc = SvPV(left, leftlen);
- register char *rc = SvPV(right, rightlen);
+ register char *lc;
+ register char *rc;
register I32 len;
I32 lensave;
+ char *lsave;
+ char *rsave;
- dc = SvPV_force(sv,na);
+ if (sv != left || (optype != OP_BIT_AND && !SvOK(sv) && !SvGMAGICAL(sv)))
+ sv_setpvn(sv, "", 0); /* avoid undef warning on |= and ^= */
+ lsave = lc = SvPV(left, leftlen);
+ rsave = rc = SvPV(right, rightlen);
len = leftlen < rightlen ? leftlen : rightlen;
lensave = len;
- if (SvCUR(sv) < len) {
- dc = SvGROW(sv,len + 1);
- (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
+ if (SvOK(sv) || SvTYPE(sv) > SVt_PVMG) {
+ dc = SvPV_force(sv, na);
+ if (SvCUR(sv) < len) {
+ dc = SvGROW(sv, len + 1);
+ (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
+ }
+ }
+ else {
+ I32 needlen = ((optype == OP_BIT_AND)
+ ? len : (leftlen > rightlen ? leftlen : rightlen));
+ Newz(801, dc, needlen + 1, char);
+ (void)sv_usepvn(sv, dc, needlen);
+ dc = SvPVX(sv); /* sv_usepvn() calls Renew() */
}
SvCUR_set(sv, len);
(void)SvPOK_only(sv);
}
#endif
{
- char *lsave = lc;
- char *rsave = rc;
-
switch (optype) {
case OP_BIT_AND:
while (len--)
sv_catpvn(sv, rsave + len, rightlen - len);
else if (leftlen > len)
sv_catpvn(sv, lsave + len, leftlen - len);
+ else
+ *SvEND(sv) = '\0';
break;
}
}
{
dSP;
HV *hv = (HV*)POPs;
- I32 i;
register HE *entry;
- char *tmps;
SV *tmpstr;
I32 dokeys = (op->op_type == OP_KEYS);
I32 dovalues = (op->op_type == OP_VALUES);
if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV)
dokeys = dovalues = TRUE;
- if (!hv)
+ if (!hv) {
+ if (op->op_flags & OPf_MOD) { /* lvalue */
+ dTARGET; /* make sure to clear its target here */
+ if (SvTYPE(TARG) == SVt_PVLV)
+ LvTARG(TARG) = Nullsv;
+ PUSHs(TARG);
+ }
+ RETURN;
+ }
+
+ (void)hv_iterinit(hv); /* always reset iterator regardless */
+
+ if (op->op_private & OPpLEAVE_VOID)
RETURN;
+
if (GIMME != G_ARRAY) {
+ I32 i;
dTARGET;
+ if (op->op_flags & OPf_MOD) { /* lvalue */
+ if (SvTYPE(TARG) < SVt_PVLV) {
+ sv_upgrade(TARG, SVt_PVLV);
+ sv_magic(TARG, Nullsv, 'k', Nullch, 0);
+ }
+ LvTYPE(TARG) = 'k';
+ LvTARG(TARG) = (SV*)hv;
+ PUSHs(TARG);
+ RETURN;
+ }
+
if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
i = HvKEYS(hv);
else {
i = 0;
- (void)hv_iterinit(hv);
/*SUPPRESS 560*/
while (entry = hv_iternext(hv)) {
i++;
/* Guess how much room we need. hv_max may be a few too many. Oh well. */
EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
- (void)hv_iterinit(hv);
-
PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */
while (entry = hv_iternext(hv)) {
SPAGAIN;
- if (dokeys) {
- tmps = hv_iterkey(entry,&i); /* won't clobber stack_sp */
- if (!i)
- tmps = "";
- XPUSHs(sv_2mortal(newSVpv(tmps,i)));
- }
+ if (dokeys)
+ XPUSHs(hv_iterkeysv(entry)); /* won't clobber stack_sp */
if (dovalues) {
tmpstr = NEWSV(45,0);
PUTBACK;
sv_setsv(tmpstr,hv_iterval(hv,entry));
SPAGAIN;
DEBUG_H( {
- sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
- HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
- sv_setpv(tmpstr,buf);
+ sprintf(buf,"%d%%%d=%d\n", HeHASH(entry),
+ HvMAX(hv)+1, HeHASH(entry) & HvMAX(hv));
+ sv_setpv(tmpstr,buf);
} )
XPUSHs(sv_2mortal(tmpstr));
}