/* pp.c
*
- * Copyright (c) 1991-1999, Larry Wall
+ * Copyright (c) 1991-2000, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
#endif
/*
- * 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 almost everywhere.
- */
-typedef int IBW;
-typedef unsigned UBW;
-
-/*
- * Mask used after bitwise operations.
- *
- * There is at least one realm (Cray word machines) that doesn't
- * 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 LONGSIZE > 4 && defined(_CRAY)
-# define BW_BITS 32
-# define BW_MASK ((1 << BW_BITS) - 1)
-# define BW_SIGN (1 << (BW_BITS - 1))
-# define BWi(i) (((i) & BW_SIGN) ? ((i) | ~BW_MASK) : ((i) & BW_MASK))
-# define BWu(u) ((u) & BW_MASK)
-#else
-# define BWi(i) (i)
-# define BWu(u) (u)
-#endif
-
-/*
* Offset for integer pack/unpack.
*
* On architectures where I16 and I32 aren't really 16 and 32 bits,
else {
if (SvTYPE(sv) != SVt_PVGV) {
char *sym;
- STRLEN n_a;
+ STRLEN len;
if (SvGMAGICAL(sv)) {
mg_get(sv);
if (SvROK(sv))
goto wasref;
}
- if (!SvOK(sv)) {
+ if (!SvOK(sv) && sv != &PL_sv_undef) {
/* If this is a 'my' scalar and flag is set then vivify
* NI-S 1999/05/07
*/
report_uninit();
RETSETUNDEF;
}
- sym = SvPV(sv, n_a);
+ sym = SvPV(sv,len);
if ((PL_op->op_flags & OPf_SPECIAL) &&
!(PL_op->op_flags & OPf_MOD))
{
sv = (SV*)gv_fetchpv(sym, FALSE, SVt_PVGV);
- if (!sv)
+ if (!sv
+ && (!is_gv_magical(sym,len,0)
+ || !(sv = (SV*)gv_fetchpv(sym, TRUE, SVt_PVGV))))
+ {
RETSETUNDEF;
+ }
}
else {
if (PL_op->op_private & HINT_STRICT_REFS)
else {
GV *gv = (GV*)sv;
char *sym;
- STRLEN n_a;
+ STRLEN len;
if (SvTYPE(gv) != SVt_PVGV) {
if (SvGMAGICAL(sv)) {
report_uninit();
RETSETUNDEF;
}
- sym = SvPV(sv, n_a);
+ sym = SvPV(sv, len);
if ((PL_op->op_flags & OPf_SPECIAL) &&
!(PL_op->op_flags & OPf_MOD))
{
gv = (GV*)gv_fetchpv(sym, FALSE, SVt_PV);
- if (!gv)
+ if (!gv
+ && (!is_gv_magical(sym,len,0)
+ || !(gv = (GV*)gv_fetchpv(sym, TRUE, SVt_PV))))
+ {
RETSETUNDEF;
+ }
}
else {
if (PL_op->op_private & HINT_STRICT_REFS)
seen_question = 1;
str[n++] = ';';
}
- else if (seen_question)
+ else if (n && str[0] == ';' && seen_question)
goto set; /* XXXX system, exec */
if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF
&& (oa & (OA_OPTIONAL - 1)) <= OA_HVREF) {
else {
SV *ssv = POPs;
STRLEN len;
- char *ptr = SvPV(ssv,len);
- if (ckWARN(WARN_UNSAFE) && len == 0)
- Perl_warner(aTHX_ WARN_UNSAFE,
+ char *ptr;
+
+ if (ssv && !SvGMAGICAL(ssv) && !SvAMAGIC(ssv) && SvROK(ssv))
+ Perl_croak(aTHX_ "Attempt to bless into a reference");
+ ptr = SvPV(ssv,len);
+ if (ckWARN(WARN_MISC) && len == 0)
+ Perl_warner(aTHX_ WARN_MISC,
"Explicit blessing to '' (assuming package main)");
stash = gv_stashpvn(ptr, len, TRUE);
}
case 'F':
if (strEQ(elem, "FILEHANDLE")) /* XXX deprecate in 5.005 */
tmpRef = (SV*)GvIOp(gv);
+ else
+ if (strEQ(elem, "FORMAT"))
+ tmpRef = (SV*)GvFORM(gv);
break;
case 'G':
if (strEQ(elem, "GLOB"))
hv_undef((HV*)sv);
break;
case SVt_PVCV:
- if (ckWARN(WARN_UNSAFE) && cv_const_sv((CV*)sv))
- Perl_warner(aTHX_ WARN_UNSAFE, "Constant subroutine %s undefined",
+ if (ckWARN(WARN_MISC) && cv_const_sv((CV*)sv))
+ Perl_warner(aTHX_ WARN_MISC, "Constant subroutine %s undefined",
CvANON((CV*)sv) ? "(anonymous)" : GvENAME(CvGV((CV*)sv)));
/* FALL THROUGH */
case SVt_PVFM:
djSP; dATARGET; tryAMAGICbin(pow,opASSIGN);
{
dPOPTOPnnrl;
- SETn( pow( left, right) );
+ SETn( Perl_pow( left, right) );
RETURN;
}
}
NV dright;
NV dleft;
- if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+ if (SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
IV i = SvIVX(POPs);
right = (right_neg = (i < 0)) ? -i : i;
}
dright = -dright;
}
- if (!use_double && SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
+ if (!use_double && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)) {
IV i = SvIVX(POPs);
left = (left_neg = (i < 0)) ? -i : i;
}
#endif
/* Backward-compatibility clause: */
- dright = floor(dright + 0.5);
- dleft = floor(dleft + 0.5);
+ dright = Perl_floor(dright + 0.5);
+ dleft = Perl_floor(dleft + 0.5);
if (!dright)
DIE(aTHX_ "Illegal modulus zero");
{
djSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
{
- register I32 count = POPi;
+ register IV count = POPi;
if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
dMARK;
I32 items = SP - MARK;
SP -= items;
}
else { /* Note: mark already snarfed by pp_list */
- SV *tmpstr;
+ SV *tmpstr = POPs;
STRLEN len;
+ bool isutf = DO_UTF8(tmpstr);
- tmpstr = POPs;
SvSetSV(TARG, tmpstr);
SvPV_force(TARG, len);
if (count != 1) {
}
*SvEND(TARG) = '\0';
}
- (void)SvPOK_only(TARG);
+ if (isutf)
+ (void)SvPOK_only_UTF8(TARG);
+ else
+ (void)SvPOK_only(TARG);
PUSHTARG;
}
RETURN;
{
djSP; dATARGET; tryAMAGICbin(lshift,opASSIGN);
{
- IBW shift = POPi;
+ IV shift = POPi;
if (PL_op->op_private & HINT_INTEGER) {
- IBW i = TOPi;
- i = BWi(i) << shift;
- SETi(BWi(i));
+ IV i = TOPi;
+ SETi(i << shift);
}
else {
- UBW u = TOPu;
- u <<= shift;
- SETu(BWu(u));
+ UV u = TOPu;
+ SETu(u << shift);
}
RETURN;
}
{
djSP; dATARGET; tryAMAGICbin(rshift,opASSIGN);
{
- IBW shift = POPi;
+ IV shift = POPi;
if (PL_op->op_private & HINT_INTEGER) {
- IBW i = TOPi;
- i = BWi(i) >> shift;
- SETi(BWi(i));
+ IV i = TOPi;
+ SETi(i >> shift);
}
else {
- UBW u = TOPu;
- u >>= shift;
- SETu(BWu(u));
+ UV u = TOPu;
+ SETu(u >> shift);
}
RETURN;
}
dPOPTOPnnrl;
I32 value;
+#ifdef Perl_isnan
+ if (Perl_isnan(left) || Perl_isnan(right)) {
+ SETs(&PL_sv_undef);
+ RETURN;
+ }
+ value = (left > right) - (left < right);
+#else
if (left == right)
value = 0;
else if (left < right)
SETs(&PL_sv_undef);
RETURN;
}
+#endif
SETi(value);
RETURN;
}
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (PL_op->op_private & HINT_INTEGER) {
- IBW value = SvIV(left) & SvIV(right);
- SETi(BWi(value));
+ IV i = SvIV(left) & SvIV(right);
+ SETi(i);
}
else {
- UBW value = SvUV(left) & SvUV(right);
- SETu(BWu(value));
+ UV u = SvUV(left) & SvUV(right);
+ SETu(u);
}
}
else {
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (PL_op->op_private & HINT_INTEGER) {
- IBW value = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
- SETi(BWi(value));
+ IV i = (USE_LEFT(left) ? SvIV(left) : 0) ^ SvIV(right);
+ SETi(i);
}
else {
- UBW value = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
- SETu(BWu(value));
+ UV u = (USE_LEFT(left) ? SvUV(left) : 0) ^ SvUV(right);
+ SETu(u);
}
}
else {
dPOPTOPssrl;
if (SvNIOKp(left) || SvNIOKp(right)) {
if (PL_op->op_private & HINT_INTEGER) {
- IBW value = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
- SETi(BWi(value));
+ IV i = (USE_LEFT(left) ? SvIV(left) : 0) | SvIV(right);
+ SETi(i);
}
else {
- UBW value = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
- SETu(BWu(value));
+ UV u = (USE_LEFT(left) ? SvUV(left) : 0) | SvUV(right);
+ SETu(u);
}
}
else {
dTOPss;
if (SvGMAGICAL(sv))
mg_get(sv);
- if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv) && SvIVX(sv) != IV_MIN)
- SETi(-SvIVX(sv));
- else if (SvNIOKp(sv))
+ if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv)) {
+ if (SvIsUV(sv)) {
+ if (SvIVX(sv) == IV_MIN) {
+ SETi(SvIVX(sv)); /* special case: -((UV)IV_MAX+1) == IV_MIN */
+ RETURN;
+ }
+ else if (SvUVX(sv) <= IV_MAX) {
+ SETi(-SvIVX(sv));
+ RETURN;
+ }
+ }
+ else if (SvIVX(sv) != IV_MIN) {
+ SETi(-SvIVX(sv));
+ RETURN;
+ }
+ }
+ if (SvNIOKp(sv))
SETn(-SvNV(sv));
else if (SvPOKp(sv)) {
STRLEN len;
dTOPss;
if (SvNIOKp(sv)) {
if (PL_op->op_private & HINT_INTEGER) {
- IBW value = ~SvIV(sv);
- SETi(BWi(value));
+ IV i = ~SvIV(sv);
+ SETi(i);
}
else {
- UBW value = ~SvUV(sv);
- SETu(BWu(value));
+ UV u = ~SvUV(sv);
+ SETu(u);
}
}
else {
- register char *tmps;
- register long *tmpl;
+ register U8 *tmps;
register I32 anum;
STRLEN len;
SvSetSV(TARG, sv);
- tmps = SvPV_force(TARG, len);
+ tmps = (U8*)SvPV_force(TARG, len);
anum = len;
+ if (SvUTF8(TARG)) {
+ /* Calculate exact length, let's not estimate */
+ STRLEN targlen = 0;
+ U8 *result;
+ U8 *send;
+ STRLEN l;
+
+ send = tmps + len;
+ while (tmps < send) {
+ UV c = utf8_to_uv(tmps, 0, &l, UTF8_ALLOW_ANY);
+ tmps += UTF8SKIP(tmps);
+ targlen += UNISKIP(~c);
+ }
+
+ /* Now rewind strings and write them. */
+ tmps -= len;
+ Newz(0, result, targlen + 1, U8);
+ while (tmps < send) {
+ UV c = utf8_to_uv(tmps, 0, &l, UTF8_ALLOW_ANY);
+ tmps += UTF8SKIP(tmps);
+ result = uv_to_utf8(result,(UV)~c);
+ }
+ *result = '\0';
+ result -= targlen;
+ sv_setpvn(TARG, (char*)result, targlen);
+ SvUTF8_on(TARG);
+ Safefree(result);
+ SETs(TARG);
+ RETURN;
+ }
#ifdef LIBERAL
- for ( ; anum && (unsigned long)tmps % sizeof(long); anum--, tmps++)
- *tmps = ~*tmps;
- tmpl = (long*)tmps;
- for ( ; anum >= sizeof(long); anum -= sizeof(long), tmpl++)
- *tmpl = ~*tmpl;
- tmps = (char*)tmpl;
+ {
+ register long *tmpl;
+ for ( ; anum && (unsigned long)tmps % sizeof(long); anum--, tmps++)
+ *tmps = ~*tmps;
+ tmpl = (long*)tmps;
+ for ( ; anum >= sizeof(long); anum -= sizeof(long), tmpl++)
+ *tmpl = ~*tmpl;
+ tmps = (U8*)tmpl;
+ }
#endif
for ( ; anum > 0; anum--, tmps++)
*tmps = ~*tmps;
NV value;
value = POPn;
if (value <= 0.0) {
- RESTORE_NUMERIC_STANDARD();
+ SET_NUMERIC_STANDARD();
DIE(aTHX_ "Can't take log of %g", value);
}
value = Perl_log(value);
NV value;
value = POPn;
if (value < 0.0) {
- RESTORE_NUMERIC_STANDARD();
+ SET_NUMERIC_STANDARD();
DIE(aTHX_ "Can't take sqrt of %g", value);
}
value = Perl_sqrt(value);
SETi(iv);
}
else {
- if (value >= 0.0)
- (void)Perl_modf(value, &value);
+ if (value >= 0.0) {
+#if defined(HAS_MODFL) || defined(LONG_DOUBLE_EQUALS_DOUBLE)
+ (void)Perl_modf(value, &value);
+#else
+ double tmp = (double)value;
+ (void)Perl_modf(tmp, &tmp);
+ value = (NV)tmp;
+#endif
+ }
else {
- (void)Perl_modf(-value, &value);
- value = -value;
+#if defined(HAS_MODFL) || defined(LONG_DOUBLE_EQUALS_DOUBLE)
+ (void)Perl_modf(-value, &value);
+ value = -value;
+#else
+ double tmp = (double)value;
+ (void)Perl_modf(-tmp, &tmp);
+ value = -(NV)tmp;
+#endif
}
iv = I_V(value);
if (iv == value)
{
djSP; dTARGET;
char *tmps;
- I32 argtype;
+ STRLEN argtype;
STRLEN n_a;
tmps = POPpx;
+ argtype = 1; /* allow underscores */
XPUSHn(scan_hex(tmps, 99, &argtype));
RETURN;
}
{
djSP; dTARGET;
NV value;
- I32 argtype;
+ STRLEN argtype;
char *tmps;
STRLEN n_a;
tmps++;
if (*tmps == '0')
tmps++;
+ argtype = 1; /* allow underscores */
if (*tmps == 'x')
value = scan_hex(++tmps, 99, &argtype);
else if (*tmps == 'b')
rem -= pos;
}
if (fail < 0) {
- if (ckWARN(WARN_SUBSTR) || lvalue || repl)
+ if (lvalue || repl)
+ Perl_croak(aTHX_ "substr outside of string");
+ if (ckWARN(WARN_SUBSTR))
Perl_warner(aTHX_ WARN_SUBSTR, "substr outside of string");
RETPUSHUNDEF;
}
else {
- if (utfcurlen) {
+ if (utfcurlen)
sv_pos_u2b(sv, &pos, &rem);
- SvUTF8_on(TARG);
- }
tmps += pos;
sv_setpvn(TARG, tmps, rem);
+ if (utfcurlen)
+ SvUTF8_on(TARG);
if (repl)
sv_insert(sv, pos, rem, repl, repl_len);
else if (lvalue) { /* it's an lvalue! */
"Attempt to use reference as lvalue in substr");
}
if (SvOK(sv)) /* is it defined ? */
- (void)SvPOK_only(sv);
+ (void)SvPOK_only_UTF8(sv);
else
sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
}
PP(pp_vec)
{
djSP; dTARGET;
- register I32 size = POPi;
- register I32 offset = POPi;
+ register IV size = POPi;
+ register IV offset = POPi;
register SV *src = POPs;
I32 lvalue = PL_op->op_flags & OPf_MOD;
{
djSP; dTARGET;
UV value;
- STRLEN n_a;
SV *tmpsv = POPs;
- U8 *tmps = (U8*)SvPVx(tmpsv,n_a);
- I32 retlen;
+ STRLEN len;
+ U8 *tmps = (U8*)SvPVx(tmpsv, len);
+ STRLEN retlen;
if ((*tmps & 0x80) && DO_UTF8(tmpsv))
- value = utf8_to_uv(tmps, &retlen);
+ value = utf8_to_uv(tmps, len, &retlen, 0);
else
value = (UV)(*tmps & 255);
XPUSHu(value);
{
djSP; dTARGET;
char *tmps;
- U32 value = POPu;
+ UV value = POPu;
- SvUTF8_off(TARG); /* decontaminate */
(void)SvUPGRADE(TARG,SVt_PV);
- if (value >= 128 && PL_bigchar && !IN_BYTE) {
- SvGROW(TARG,8);
+ if ((value > 255 && !IN_BYTE) || (value & 0x80 && PL_hints & HINT_UTF8) ) {
+ SvGROW(TARG, UTF8_MAXLEN+1);
tmps = SvPVX(TARG);
tmps = (char*)uv_to_utf8((U8*)tmps, (UV)value);
SvCUR_set(TARG, tmps - SvPVX(TARG));
*tmps = '\0';
- SvUTF8_on(TARG);
(void)SvPOK_only(TARG);
+ SvUTF8_on(TARG);
XPUSHs(TARG);
RETURN;
}
STRLEN slen;
if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
- I32 ulen;
- U8 tmpbuf[10];
+ STRLEN ulen;
+ U8 tmpbuf[UTF8_MAXLEN];
U8 *tend;
- UV uv = utf8_to_uv(s, &ulen);
+ UV uv = utf8_to_uv(s, slen, &ulen, 0);
if (PL_op->op_private & OPpLOCALE) {
TAINT;
STRLEN slen;
if (DO_UTF8(sv) && (s = (U8*)SvPV(sv, slen)) && slen && (*s & 0xc0) == 0xc0) {
- I32 ulen;
- U8 tmpbuf[10];
+ STRLEN ulen;
+ U8 tmpbuf[UTF8_MAXLEN];
U8 *tend;
- UV uv = utf8_to_uv(s, &ulen);
+ UV uv = utf8_to_uv(s, slen, &ulen, 0);
if (PL_op->op_private & OPpLOCALE) {
TAINT;
if (DO_UTF8(sv)) {
dTARGET;
- I32 ulen;
+ STRLEN ulen;
register U8 *d;
U8 *send;
TAINT;
SvTAINTED_on(TARG);
while (s < send) {
- d = uv_to_utf8(d, toUPPER_LC_uni( utf8_to_uv(s, &ulen)));
+ d = uv_to_utf8(d, toUPPER_LC_uni( utf8_to_uv(s, len, &ulen, 0)));
s += ulen;
}
}
if (DO_UTF8(sv)) {
dTARGET;
- I32 ulen;
+ STRLEN ulen;
register U8 *d;
U8 *send;
TAINT;
SvTAINTED_on(TARG);
while (s < send) {
- d = uv_to_utf8(d, toLOWER_LC_uni( utf8_to_uv(s, &ulen)));
+ d = uv_to_utf8(d, toLOWER_LC_uni( utf8_to_uv(s, len, &ulen, 0)));
s += ulen;
}
}
}
*d = '\0';
SvCUR_set(TARG, d - SvPVX(TARG));
- (void)SvPOK_only(TARG);
+ (void)SvPOK_only_UTF8(TARG);
}
else
sv_setpvn(TARG, s, len);
SV *val = NEWSV(46, 0);
if (MARK < SP)
sv_setsv(val, *++MARK);
- else if (ckWARN(WARN_UNSAFE))
- Perl_warner(aTHX_ WARN_UNSAFE, "Odd number of elements in hash assignment");
+ else if (ckWARN(WARN_MISC))
+ Perl_warner(aTHX_ WARN_MISC, "Odd number of elements in hash assignment");
(void)hv_store_ent(hv,key,val,0);
}
SP = ORIGMARK;
SV **tmparyval = 0;
MAGIC *mg;
- if (mg = SvTIED_mg((SV*)ary, 'P')) {
+ if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
*MARK-- = SvTIED_obj((SV*)ary, mg);
PUSHMARK(MARK);
PUTBACK;
register SV *sv = &PL_sv_undef;
MAGIC *mg;
- if (mg = SvTIED_mg((SV*)ary, 'P')) {
+ if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
*MARK-- = SvTIED_obj((SV*)ary, mg);
PUSHMARK(MARK);
PUTBACK;
register I32 i = 0;
MAGIC *mg;
- if (mg = SvTIED_mg((SV*)ary, 'P')) {
+ if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
*MARK-- = SvTIED_obj((SV*)ary, mg);
PUSHMARK(MARK);
PUTBACK;
*up++ = *down;
*down-- = tmp;
}
- (void)SvPOK_only(TARG);
+ (void)SvPOK_only_UTF8(TARG);
}
SP = MARK + 1;
SETTARG;
register char *str;
/* These must not be in registers: */
- I16 ashort;
+ short ashort;
int aint;
- I32 along;
+ long along;
#ifdef HAS_QUAD
Quad_t aquad;
#endif
default:
DIE(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype);
case ',': /* grandfather in commas but with a warning */
- if (commas++ == 0 && ckWARN(WARN_UNSAFE))
- Perl_warner(aTHX_ WARN_UNSAFE,
+ if (commas++ == 0 && ckWARN(WARN_UNPACK))
+ Perl_warner(aTHX_ WARN_UNPACK,
"Invalid type in unpack: '%c'", (int)datumtype);
break;
case '%':
len = strend - s;
if (checksum) {
while (len-- > 0 && s < strend) {
- auint = utf8_to_uv((U8*)s, &along);
+ STRLEN alen;
+ auint = utf8_to_uv((U8*)s, strend - s, &alen, 0);
+ along = alen;
s += along;
if (checksum > 32)
cdouble += (NV)auint;
EXTEND(SP, len);
EXTEND_MORTAL(len);
while (len-- > 0 && s < strend) {
- auint = utf8_to_uv((U8*)s, &along);
+ STRLEN alen;
+ auint = utf8_to_uv((U8*)s, strend - s, &alen, 0);
+ along = alen;
s += along;
sv = NEWSV(37, 0);
sv_setuv(sv, (UV)auint);
char *t;
STRLEN n_a;
- sv = Perl_newSVpvf(aTHX_ "%.*Vu", (int)TYPE_DIGITS(UV), auv);
+ sv = Perl_newSVpvf(aTHX_ "%.*"UVf, (int)TYPE_DIGITS(UV), auv);
while (s < strend) {
sv = mul128(sv, *s & 0x7f);
if (!(*s++ & 0x80)) {
int i;
for (i = 0; i < sizeof(PL_uuemap); i += 1)
- PL_uudmap[PL_uuemap[i]] = i;
+ PL_uudmap[(U8)PL_uuemap[i]] = i;
/*
* Because ' ' and '`' map to the same value,
* we need to decode them both the same.
char hunk[4];
hunk[3] = '\0';
- len = PL_uudmap[*s++] & 077;
+ len = PL_uudmap[*(U8*)s++] & 077;
while (len > 0) {
if (s < strend && ISUUCHAR(*s))
- a = PL_uudmap[*s++] & 077;
+ a = PL_uudmap[*(U8*)s++] & 077;
else
a = 0;
if (s < strend && ISUUCHAR(*s))
- b = PL_uudmap[*s++] & 077;
+ b = PL_uudmap[*(U8*)s++] & 077;
else
b = 0;
if (s < strend && ISUUCHAR(*s))
- c = PL_uudmap[*s++] & 077;
+ c = PL_uudmap[*(U8*)s++] & 077;
else
c = 0;
if (s < strend && ISUUCHAR(*s))
- d = PL_uudmap[*s++] & 077;
+ d = PL_uudmap[*(U8*)s++] & 077;
else
d = 0;
hunk[0] = (a << 2) | (b >> 4);
register I32 items;
STRLEN fromlen;
register char *pat = SvPVx(*++MARK, fromlen);
+ char *patcopy;
register char *patend = pat + fromlen;
register I32 len;
I32 datumtype;
items = SP - MARK;
MARK++;
sv_setpvn(cat, "", 0);
+ patcopy = pat;
while (pat < patend) {
SV *lengthcode = Nullsv;
#define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *MARK++ : &PL_sv_no)
#ifdef PERL_NATINT_PACK
natint = 0;
#endif
- if (isSPACE(datumtype))
+ if (isSPACE(datumtype)) {
+ patcopy++;
continue;
+ }
+ if (datumtype == 'U' && pat == patcopy+1)
+ SvUTF8_on(cat);
if (datumtype == '#') {
while (pat < patend && *pat != '\n')
pat++;
len = 1;
if (*pat == '/') {
++pat;
- if (*pat != 'a' && *pat != 'A' && *pat != 'Z' || pat[1] != '*')
+ if ((*pat != 'a' && *pat != 'A' && *pat != 'Z') || pat[1] != '*')
DIE(aTHX_ "/ must be followed by a*, A* or Z*");
lengthcode = sv_2mortal(newSViv(sv_len(items > 0
- ? *MARK : &PL_sv_no)));
+ ? *MARK : &PL_sv_no)
+ + (*pat == 'Z' ? 1 : 0)));
}
switch(datumtype) {
default:
DIE(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
case ',': /* grandfather in commas but with a warning */
- if (commas++ == 0 && ckWARN(WARN_UNSAFE))
- Perl_warner(aTHX_ WARN_UNSAFE,
+ if (commas++ == 0 && ckWARN(WARN_PACK))
+ Perl_warner(aTHX_ WARN_PACK,
"Invalid type in pack: '%c'", (int)datumtype);
break;
case '%':
while (len-- > 0) {
fromstr = NEXTFROM;
auint = SvUV(fromstr);
- SvGROW(cat, SvCUR(cat) + 10);
+ SvGROW(cat, SvCUR(cat) + UTF8_MAXLEN);
SvCUR_set(cat, (char*)uv_to_utf8((U8*)SvEND(cat),auint)
- SvPVX(cat));
}
DIE(aTHX_ "Cannot compress negative numbers");
if (
-#ifdef BW_BITS
- adouble <= BW_MASK
+#if UVSIZE > 4 && UVSIZE >= NVSIZE
+ adouble <= 0xffffffff
#else
-#ifdef CXUX_BROKEN_CONSTANT_CONVERT
+# ifdef CXUX_BROKEN_CONSTANT_CONVERT
adouble <= UV_MAX_cxux
-#else
+# else
adouble <= UV_MAX
-#endif
+# endif
#endif
)
{
do {
double next = floor(adouble / 128);
*--in = (unsigned char)(adouble - (next * 128)) | 0x80;
- if (--in < buf) /* this cannot happen ;-) */
+ if (in <= buf) /* this cannot happen ;-) */
DIE(aTHX_ "Cannot compress integer");
+ in--;
adouble = next;
} while (adouble > 0);
buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
* of pack() (and all copies of the result) are
* gone.
*/
- if (ckWARN(WARN_UNSAFE) && (SvTEMP(fromstr)
+ if (ckWARN(WARN_PACK) && (SvTEMP(fromstr)
|| (SvPADTMP(fromstr)
&& !SvREADONLY(fromstr))))
{
- Perl_warner(aTHX_ WARN_UNSAFE,
+ Perl_warner(aTHX_ WARN_PACK,
"Attempt to pack pointer to temporary value");
}
if (SvPOK(fromstr) || SvNIOK(fromstr))
{
djSP; dTARG;
AV *ary;
- register I32 limit = POPi; /* note, negative is forever */
+ register IV limit = POPi; /* note, negative is forever */
SV *sv = POPs;
+ bool doutf8 = DO_UTF8(sv);
STRLEN len;
register char *s = SvPV(sv, len);
char *strend = s + len;
av_extend(ary,0);
av_clear(ary);
SPAGAIN;
- if (mg = SvTIED_mg((SV*)ary, 'P')) {
+ if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
PUSHMARK(SP);
XPUSHs(SvTIED_obj((SV*)ary, mg));
}
sv_setpvn(dstr, s, m-s);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
s = m + 1;
sv_setpvn(dstr, s, m-s);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
s = m;
}
&& !(rx->reganch & ROPT_ANCH)) {
int tail = (rx->reganch & RE_INTUIT_TAIL);
SV *csv = CALLREG_INTUIT_STRING(aTHX_ rx);
- char c;
len = rx->minlen;
if (len == 1 && !tail) {
- c = *SvPV(csv,len);
+ STRLEN n_a;
+ char c = *SvPV(csv, n_a);
while (--limit) {
/*SUPPRESS 530*/
for (m = s; m < strend && *m != c; m++) ;
sv_setpvn(dstr, s, m-s);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
- s = m + 1;
+ /* The rx->minlen is in characters but we want to step
+ * s ahead by bytes. */
+ s = m + (doutf8 ? SvCUR(csv) : len);
}
}
else {
sv_setpvn(dstr, s, m-s);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
- s = m + len; /* Fake \n at the end */
+ /* The rx->minlen is in characters but we want to step
+ * s ahead by bytes. */
+ s = m + (doutf8 ? SvCUR(csv) : len); /* Fake \n at the end */
}
}
}
sv_setpvn(dstr, s, m-s);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
if (rx->nparens) {
for (i = 1; i <= rx->nparens; i++) {
dstr = NEWSV(33, 0);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
}
}
/* keep field after final delim? */
if (s < strend || (iters && origlimit)) {
- dstr = NEWSV(34, strend-s);
- sv_setpvn(dstr, s, strend-s);
+ STRLEN l = strend - s;
+ dstr = NEWSV(34, l);
+ sv_setpvn(dstr, s, l);
if (make_mortal)
sv_2mortal(dstr);
+ if (doutf8)
+ (void)SvUTF8_on(dstr);
XPUSHs(dstr);
iters++;
}
dTOPss;
SV *retsv = sv;
#ifdef USE_THREADS
- MAGIC *mg;
-
- if (SvROK(sv))
- sv = SvRV(sv);
-
- mg = condpair_magic(sv);
- MUTEX_LOCK(MgMUTEXP(mg));
- if (MgOWNER(mg) == thr)
- MUTEX_UNLOCK(MgMUTEXP(mg));
- else {
- while (MgOWNER(mg))
- COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg));
- MgOWNER(mg) = thr;
- DEBUG_S(PerlIO_printf(Perl_debug_log, "0x%"UVxf": pp_lock lock 0x%"UVxf"\n",
- PTR2UV(thr), PTR2UV(sv));)
- MUTEX_UNLOCK(MgMUTEXP(mg));
- SAVEDESTRUCTOR_X(Perl_unlock_condpair, sv);
- }
+ sv_lock(sv);
#endif /* USE_THREADS */
if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV
|| SvTYPE(retsv) == SVt_PVCV) {
PP(pp_threadsv)
{
- djSP;
#ifdef USE_THREADS
+ djSP;
EXTEND(SP, 1);
if (PL_op->op_private & OPpLVAL_INTRO)
PUSHs(*save_threadsv(PL_op->op_targ));