const char* grpbeg; /* 1st char of ()-group */
const char* grpend; /* end of ()-group */
I32 code; /* template code (!<>) */
- I32 length; /* length/repeat count */
- howlen_t howlen; /* how length is given */
- int level; /* () nesting level */
U32 flags; /* /=4, comma=2, pack=1 */
/* and group modifiers */
+ SSize_t length; /* length/repeat count */
+ howlen_t howlen; /* how length is given */
+ int level; /* () nesting level */
STRLEN strbeg; /* offset of group start */
struct tempsym *previous; /* previous group */
} tempsym_t;
/* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
--jhi Feb 1999 */
-#if U16SIZE > SIZE16 || U32SIZE > SIZE32
-# if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 /* little-endian */
-# define OFF16(p) ((char*)(p))
-# define OFF32(p) ((char*)(p))
-# else
-# if BYTEORDER == 0x4321 || BYTEORDER == 0x87654321 /* big-endian */
-# define OFF16(p) ((char*)(p) + (sizeof(U16) - SIZE16))
-# define OFF32(p) ((char*)(p) + (sizeof(U32) - SIZE32))
-# else
- ++++ bad cray byte order
-# endif
-# endif
-#else
+#if U16SIZE <= SIZE16 && U32SIZE <= SIZE32
# define OFF16(p) ((char *) (p))
# define OFF32(p) ((char *) (p))
+#elif BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 /* little-endian */
+# define OFF16(p) ((char*)(p))
+# define OFF32(p) ((char*)(p))
+#elif BYTEORDER == 0x4321 || BYTEORDER == 0x87654321 /* big-endian */
+# define OFF16(p) ((char*)(p) + (sizeof(U16) - SIZE16))
+# define OFF32(p) ((char*)(p) + (sizeof(U32) - SIZE32))
+#else
+# error "bad cray byte order"
#endif
#define PUSH16(utf8, cur, p, needs_swap) \
# error "Unsupported byteorder"
/* Need to add code here to re-instate mixed endian support.
NEEDS_SWAP would need to hold a flag indicating which action to
- take, and S_reverse_copy and the code in uni_to_bytes would need
+ take, and S_reverse_copy and the code in S_utf8_to_bytes would need
logic adding to deal with any mixed-endian transformations needed.
*/
#endif
/* Only to be used inside a loop (see the break) */
#define SHIFT_BYTES(utf8, s, strend, buf, len, datumtype, needs_swap) \
STMT_START { \
- if (utf8) { \
- if (!uni_to_bytes(aTHX_ &s, strend, \
+ if (UNLIKELY(utf8)) { \
+ if (!S_utf8_to_bytes(aTHX_ &s, strend, \
(char *) (buf), len, datumtype)) break; \
} else { \
- if (needs_swap) \
+ if (UNLIKELY(needs_swap)) \
S_reverse_copy(s, (char *) (buf), len); \
else \
Copy(s, (char *) (buf), len, char); \
PERL_ARGS_ASSERT_MUL128;
- if (!strnEQ(s, "0000", 4)) { /* need to grow sv */
+ if (! memBEGINs(s, len, "0000")) { /* need to grow sv */
SV * const tmpNew = newSVpvs("0000000000");
sv_catsv(tmpNew, sv);
/* Explosives and implosives. */
-#if 'I' == 73 && 'J' == 74
-/* On an ASCII/ISO kind of system */
-#define ISUUCHAR(ch) ((ch) >= ' ' && (ch) < 'a')
-#else
-/*
- Some other sort of character set - use memchr() so we don't match
- the null byte.
- */
-#define ISUUCHAR(ch) (memchr(PL_uuemap, (ch), sizeof(PL_uuemap)-1) || (ch) == ' ')
-#endif
+#define ISUUCHAR(ch) (NATIVE_TO_LATIN1(ch) >= NATIVE_TO_LATIN1(' ') \
+ && NATIVE_TO_LATIN1(ch) < NATIVE_TO_LATIN1('a'))
/* type modifiers */
#define TYPE_IS_SHRIEKING 0x100
#define PACK_SIZE_UNPREDICTABLE 0x40 /* Not a fixed size element */
#define PACK_SIZE_MASK 0x3F
-#include "packsizetables.c"
+#include "packsizetables.inc"
static void
S_reverse_copy(const char *src, char *dest, STRLEN len)
}
STATIC U8
-uni_to_byte(pTHX_ const char **s, const char *end, I32 datumtype)
+utf8_to_byte(pTHX_ const char **s, const char *end, I32 datumtype)
{
STRLEN retlen;
- UV val = utf8n_to_uvchr((U8 *) *s, end-*s, &retlen,
+ UV val;
+
+ if (*s >= end) {
+ goto croak;
+ }
+ val = utf8n_to_uvchr((U8 *) *s, end-*s, &retlen,
ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
- /* We try to process malformed UTF-8 as much as possible (preferably with
- warnings), but these two mean we make no progress in the string and
- might enter an infinite loop */
- if (retlen == (STRLEN) -1 || retlen == 0)
+ if (retlen == (STRLEN) -1)
+ croak:
Perl_croak(aTHX_ "Malformed UTF-8 string in '%c' format in unpack",
(int) TYPE_NO_MODIFIERS(datumtype));
if (val >= 0x100) {
}
#define SHIFT_BYTE(utf8, s, strend, datumtype) ((utf8) ? \
- uni_to_byte(aTHX_ &(s), (strend), (datumtype)) : \
+ utf8_to_byte(aTHX_ &(s), (strend), (datumtype)) : \
*(U8 *)(s)++)
STATIC bool
-uni_to_bytes(pTHX_ const char **s, const char *end, const char *buf, int buf_len, I32 datumtype)
+S_utf8_to_bytes(pTHX_ const char **s, const char *end, const char *buf, SSize_t buf_len, I32 datumtype)
{
UV val;
STRLEN retlen;
UTF8_CHECK_ONLY : (UTF8_CHECK_ONLY | UTF8_ALLOW_ANY);
const bool needs_swap = NEEDS_SWAP(datumtype);
- if (needs_swap)
+ if (UNLIKELY(needs_swap))
buf += buf_len;
for (;buf_len > 0; buf_len--) {
if (from >= end) return FALSE;
val = utf8n_to_uvchr((U8 *) from, end-from, &retlen, flags);
- if (retlen == (STRLEN) -1 || retlen == 0) {
+ if (retlen == (STRLEN) -1) {
from += UTF8SKIP(from);
bad |= 1;
} else from += retlen;
bad |= 2;
val &= 0xff;
}
- if (needs_swap)
+ if (UNLIKELY(needs_swap))
*(U8 *)--buf = (U8)val;
else
*(U8 *)buf++ = (U8)val;
if (bad & 1) {
/* Rewalk the string fragment while warning */
const char *ptr;
- const int flags = ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY;
+ const U32 flags = ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY;
for (ptr = *s; ptr < from; ptr += UTF8SKIP(ptr)) {
if (ptr >= end) break;
- utf8n_to_uvuni((U8 *) ptr, end-ptr, &retlen, flags);
+ utf8n_to_uvchr((U8 *) ptr, end-ptr, &retlen, flags);
}
if (from > end) from = end;
}
return TRUE;
}
-STATIC bool
-next_uni_uu(pTHX_ const char **s, const char *end, I32 *out)
-{
- dVAR;
- STRLEN retlen;
- const UV val = utf8n_to_uvchr((U8 *) *s, end-*s, &retlen, UTF8_CHECK_ONLY);
- if (val >= 0x100 || !ISUUCHAR(val) ||
- retlen == (STRLEN) -1 || retlen == 0) {
- *out = 0;
- return FALSE;
- }
- *out = PL_uudmap[val] & 077;
- *s += retlen;
- return TRUE;
-}
-
STATIC char *
-S_bytes_to_uni(const U8 *start, STRLEN len, char *dest, const bool needs_swap) {
- PERL_ARGS_ASSERT_BYTES_TO_UNI;
+S_my_bytes_to_utf8(const U8 *start, STRLEN len, char *dest, const bool needs_swap) {
+ PERL_ARGS_ASSERT_MY_BYTES_TO_UTF8;
- if (needs_swap) {
+ if (UNLIKELY(needs_swap)) {
const U8 *p = start + len;
while (p-- > start) {
- const UV uv = NATIVE_TO_ASCII(*p);
- if (UNI_IS_INVARIANT(uv))
- *dest++ = (char)(U8)UTF_TO_NATIVE(uv);
- else {
- *dest++ = (char)(U8)UTF8_EIGHT_BIT_HI(uv);
- *dest++ = (char)(U8)UTF8_EIGHT_BIT_LO(uv);
- }
+ append_utf8_from_native_byte(*p, (U8 **) & dest);
}
} else {
const U8 * const end = start + len;
while (start < end) {
- const UV uv = NATIVE_TO_ASCII(*start);
- if (UNI_IS_INVARIANT(uv))
- *dest++ = (char)(U8)UTF_TO_NATIVE(uv);
- else {
- *dest++ = (char)(U8)UTF8_EIGHT_BIT_HI(uv);
- *dest++ = (char)(U8)UTF8_EIGHT_BIT_LO(uv);
- }
+ append_utf8_from_native_byte(*start, (U8 **) & dest);
start++;
}
}
#define PUSH_BYTES(utf8, cur, buf, len, needs_swap) \
STMT_START { \
- if (utf8) \
- (cur) = S_bytes_to_uni((U8 *) buf, len, (cur), needs_swap); \
+ if (UNLIKELY(utf8)) \
+ (cur) = my_bytes_to_utf8((U8 *) buf, len, (cur), needs_swap); \
else { \
- if (needs_swap) \
+ if (UNLIKELY(needs_swap)) \
S_reverse_copy((char *)(buf), cur, len); \
else \
Copy(buf, cur, len, char); \
STMT_START { \
if (utf8) { \
const U8 au8 = (byte); \
- (s) = S_bytes_to_uni(&au8, 1, (s), 0); \
+ (s) = my_bytes_to_utf8(&au8, 1, (s), 0);\
} else *(U8 *)(s)++ = (byte); \
} STMT_END
STRLEN retlen; \
if (str >= end) break; \
val = utf8n_to_uvchr((U8 *) str, end-str, &retlen, utf8_flags); \
- if (retlen == (STRLEN) -1 || retlen == 0) { \
+ if (retlen == (STRLEN) -1) { \
*cur = '\0'; \
Perl_croak(aTHX_ "Malformed UTF-8 string in pack"); \
} \
}
/* Returns the sizeof() struct described by pat */
-STATIC I32
+STATIC SSize_t
S_measure_struct(pTHX_ tempsym_t* symptr)
{
- I32 total = 0;
+ SSize_t total = 0;
PERL_ARGS_ASSERT_MEASURE_STRUCT;
while (next_symbol(symptr)) {
- I32 len;
- int size;
+ SSize_t len, size;
switch (symptr->howlen) {
case e_star:
Perl_croak(aTHX_ "Within []-length '*' not allowed in %s",
_action( symptr ) );
- break;
+
default:
/* e_no_len and e_number */
len = symptr->length;
size = packprops[TYPE_NO_ENDIANNESS(symptr->code)] & PACK_SIZE_MASK;
if (!size) {
- int star;
+ SSize_t star;
/* endianness doesn't influence the size of a type */
switch(TYPE_NO_ENDIANNESS(symptr->code)) {
default:
if (!len) /* Avoid division by 0 */
len = 1;
len = total % len; /* Assumed: the start is aligned. */
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'X':
size = -1;
if (total < len)
len = len - star;
else
len = 0;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'x':
case 'A':
case 'Z':
}
Perl_croak(aTHX_ "No group ending character '%c' found in template",
ender);
- return 0;
+ NOT_REACHED; /* NOTREACHED */
}
* Advances char pointer to 1st non-digit char and returns number
*/
STATIC const char *
-S_get_num(pTHX_ const char *patptr, I32 *lenptr )
+S_get_num(pTHX_ const char *patptr, SSize_t *lenptr )
{
- I32 len = *patptr++ - '0';
+ SSize_t len = *patptr++ - '0';
PERL_ARGS_ASSERT_GET_NUM;
while (isDIGIT(*patptr)) {
- if (len >= 0x7FFFFFFF/10)
+ SSize_t nlen = (len * 10) + (*patptr++ - '0');
+ if (nlen < 0 || nlen/10 != len)
Perl_croak(aTHX_ "pack/unpack repeat count overflow");
- len = (len * 10) + (*patptr++ - '0');
+ len = nlen;
}
*lenptr = len;
return patptr;
}
/*
+
+=head1 Pack and Unpack
+
=for apidoc unpackstring
-The engine implementing the unpack() Perl function.
+The engine implementing the C<unpack()> Perl function.
-Using the template pat..patend, this function unpacks the string
-s..strend into a number of mortal SVs, which it pushes onto the perl
-argument (@_) stack (so you will need to issue a C<PUTBACK> before and
-C<SPAGAIN> after the call to this function). It returns the number of
+Using the template C<pat..patend>, this function unpacks the string
+C<s..strend> into a number of mortal SVs, which it pushes onto the perl
+argument (C<@_>) stack (so you will need to issue a C<PUTBACK> before and
+C<SPAGAIN> after the call to this function). It returns the number of
pushed elements.
-The strend and patend pointers should point to the byte following the last
-character of each string.
+The C<strend> and C<patend> pointers should point to the byte following the
+last character of each string.
Although this function returns its values on the perl argument stack, it
doesn't take any parameters from that stack (and thus in particular
-there's no need to do a PUSHMARK before calling it, unlike L</call_pv> for
+there's no need to do a C<PUSHMARK> before calling it, unlike L</call_pv> for
example).
=cut */
-I32
+SSize_t
Perl_unpackstring(pTHX_ const char *pat, const char *patend, const char *s, const char *strend, U32 flags)
{
tempsym_t sym;
return unpack_rec(&sym, s, s, strend, NULL );
}
-STATIC I32
+STATIC SSize_t
S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const char *strend, const char **new_s )
{
- dVAR; dSP;
+ dSP;
SV *sv = NULL;
- const I32 start_sp_offset = SP - PL_stack_base;
+ const SSize_t start_sp_offset = SP - PL_stack_base;
howlen_t howlen;
- I32 checksum = 0;
+ SSize_t checksum = 0;
UV cuv = 0;
NV cdouble = 0.0;
- const int bits_in_uv = CHAR_BIT * sizeof(cuv);
+ const SSize_t bits_in_uv = CHAR_BIT * sizeof(cuv);
bool beyond = FALSE;
bool explicit_length;
const bool unpack_only_one = (symptr->flags & FLAG_UNPACK_ONLY_ONE) != 0;
while (next_symbol(symptr)) {
packprops_t props;
- I32 len;
+ SSize_t len;
I32 datumtype = symptr->code;
bool needs_swap;
/* do first one only unless in list context
props = packprops[TYPE_NO_ENDIANNESS(datumtype)];
if (props) {
/* props nonzero means we can process this letter. */
- const long size = props & PACK_SIZE_MASK;
- const long howmany = (strend - s) / size;
+ const SSize_t size = props & PACK_SIZE_MASK;
+ const SSize_t howmany = (strend - s) / size;
if (len > howmany)
len = howmany;
cuv = 0;
cdouble = 0;
continue;
- break;
+
case '(':
{
tempsym_t savsym = *symptr;
len = 1;
if (utf8) {
const char *hop, *last;
- I32 l = len;
+ SSize_t l = len;
hop = last = strbeg;
while (hop < s) {
hop += UTF8SKIP(hop);
break;
}
len = (s - strbeg) % len;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'X':
if (utf8) {
while (len > 0) {
}
break;
case 'x' | TYPE_IS_SHRIEKING: {
- I32 ai32;
+ SSize_t ai32;
if (!len) /* Avoid division by 0 */
len = 1;
if (utf8) ai32 = utf8_length((U8 *) strbeg, (U8 *) s) % len;
if (ai32 == 0) break;
len -= ai32;
}
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'x':
if (utf8) {
while (len>0) {
break;
case '/':
Perl_croak(aTHX_ "'/' must follow a numeric type in unpack");
- break;
+
case 'A':
case 'Z':
case 'a':
goto W_checksum;
}
if (utf8) {
- I32 l;
+ SSize_t l;
const char *hop;
for (l=len, hop=s; l>0; l--, hop += UTF8SKIP(hop)) {
if (hop >= strend) {
/* 'A' strips both nulls and spaces */
const char *ptr;
if (utf8 && (symptr->flags & FLAG_WAS_UTF8)) {
- for (ptr = s+len-1; ptr >= s; ptr--)
- if (*ptr != 0 && !UTF8_IS_CONTINUATION(*ptr) &&
- !isSPACE_utf8(ptr)) break;
+ for (ptr = s+len-1; ptr >= s; ptr--) {
+ if ( *ptr != 0
+ && !UTF8_IS_CONTINUATION(*ptr)
+ && !isSPACE_utf8_safe(ptr, strend))
+ {
+ break;
+ }
+ }
if (ptr >= s) ptr += UTF8SKIP(ptr);
else ptr++;
if (ptr > s+len)
if (checksum) {
if (utf8)
while (len >= 8 && s < strend) {
- cuv += PL_bitcount[uni_to_byte(aTHX_ &s, strend, datumtype)];
+ cuv += PL_bitcount[utf8_to_byte(aTHX_ &s, strend, datumtype)];
len -= 8;
}
else
str = SvPVX(sv);
if (datumtype == 'b') {
U8 bits = 0;
- const I32 ai32 = len;
+ const SSize_t ai32 = len;
for (len = 0; len < ai32; len++) {
if (len & 7) bits >>= 1;
else if (utf8) {
if (s >= strend) break;
- bits = uni_to_byte(aTHX_ &s, strend, datumtype);
+ bits = utf8_to_byte(aTHX_ &s, strend, datumtype);
} else bits = *(U8 *) s++;
*str++ = bits & 1 ? '1' : '0';
}
} else {
U8 bits = 0;
- const I32 ai32 = len;
+ const SSize_t ai32 = len;
for (len = 0; len < ai32; len++) {
if (len & 7) bits <<= 1;
else if (utf8) {
if (s >= strend) break;
- bits = uni_to_byte(aTHX_ &s, strend, datumtype);
+ bits = utf8_to_byte(aTHX_ &s, strend, datumtype);
} else bits = *(U8 *) s++;
*str++ = bits & 0x80 ? '1' : '0';
}
}
if (datumtype == 'h') {
U8 bits = 0;
- I32 ai32 = len;
+ SSize_t ai32 = len;
for (len = 0; len < ai32; len++) {
if (len & 1) bits >>= 4;
else if (utf8) {
if (s >= strend) break;
- bits = uni_to_byte(aTHX_ &s, strend, datumtype);
+ bits = utf8_to_byte(aTHX_ &s, strend, datumtype);
} else bits = * (U8 *) s++;
if (!checksum)
*str++ = PL_hexdigit[bits & 15];
}
} else {
U8 bits = 0;
- const I32 ai32 = len;
+ const SSize_t ai32 = len;
for (len = 0; len < ai32; len++) {
if (len & 1) bits <<= 4;
else if (utf8) {
if (s >= strend) break;
- bits = uni_to_byte(aTHX_ &s, strend, datumtype);
+ bits = utf8_to_byte(aTHX_ &s, strend, datumtype);
} else bits = *(U8 *) s++;
if (!checksum)
*str++ = PL_hexdigit[(bits >> 4) & 15];
utf8 = (symptr->flags & FLAG_DO_UTF8) ? 1 : 0;
break;
}
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'c':
while (len-- > 0 && s < strend) {
int aint;
STRLEN retlen;
aint = utf8n_to_uvchr((U8 *) s, strend-s, &retlen,
ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
- if (retlen == (STRLEN) -1 || retlen == 0)
+ if (retlen == (STRLEN) -1)
Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
s += retlen;
}
STRLEN retlen;
const UV val = utf8n_to_uvchr((U8 *) s, strend-s, &retlen,
ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
- if (retlen == (STRLEN) -1 || retlen == 0)
+ if (retlen == (STRLEN) -1)
Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
s += retlen;
if (!checksum)
STRLEN retlen;
UV auv;
if (utf8) {
- U8 result[UTF8_MAXLEN];
+ U8 result[UTF8_MAXLEN+1];
const char *ptr = s;
STRLEN len;
/* Bug: warns about bad utf8 even if we are short on bytes
and will break out of the loop */
- if (!uni_to_bytes(aTHX_ &ptr, strend, (char *) result, 1,
+ if (!S_utf8_to_bytes(aTHX_ &ptr, strend, (char *) result, 1,
'U'))
break;
len = UTF8SKIP(result);
- if (!uni_to_bytes(aTHX_ &ptr, strend,
+ if (!S_utf8_to_bytes(aTHX_ &ptr, strend,
(char *) &result[1], len-1, 'U')) break;
- auv = utf8n_to_uvuni(result, len, &retlen, UTF8_ALLOW_DEFAULT);
+ auv = NATIVE_TO_UNI(utf8n_to_uvchr(result,
+ len,
+ &retlen,
+ UTF8_ALLOW_DEFAULT));
s = ptr;
} else {
- auv = utf8n_to_uvuni((U8*)s, strend - s, &retlen, UTF8_ALLOW_DEFAULT);
- if (retlen == (STRLEN) -1 || retlen == 0)
+ auv = NATIVE_TO_UNI(utf8n_to_uvchr((U8*)s,
+ strend - s,
+ &retlen,
+ UTF8_ALLOW_DEFAULT));
+ if (retlen == (STRLEN) -1)
Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
s += retlen;
}
}
break;
#else
- /* Fallthrough! */
+ /* FALLTHROUGH */
#endif
case 's':
while (len-- > 0) {
}
break;
#else
- /* Fallthrough! */
+ /* FALLTHROUGH */
#endif
case 'v':
case 'n':
}
break;
#else
- /* Fallthrough! */
+ /* FALLTHROUGH */
#endif
case 'l':
while (len-- > 0) {
}
break;
#else
- /* Fall through! */
+ /* FALLTHROUGH */
#endif
case 'V':
case 'N':
case 'w':
{
UV auv = 0;
- U32 bytes = 0;
+ size_t bytes = 0;
while (len > 0 && s < strend) {
U8 ch;
ch = SHIFT_BYTE(utf8, s, strend, datumtype);
auv = (auv << 7) | (ch & 0x7f);
- /* UTF8_IS_XXXXX not right here - using constant 0x80 */
+ /* UTF8_IS_XXXXX not right here because this is a BER, not
+ * UTF-8 format - using constant 0x80 */
if (ch < 0x80) {
bytes = 0;
mPUSHu(auv);
if (++bytes >= sizeof(UV)) { /* promote to string */
const char *t;
- sv = Perl_newSVpvf(aTHX_ "%.*"UVuf, (int)TYPE_DIGITS(UV), auv);
+ sv = Perl_newSVpvf(aTHX_ "%.*" UVuf,
+ (int)TYPE_DIGITS(UV), auv);
while (s < strend) {
ch = SHIFT_BYTE(utf8, s, strend, datumtype);
sv = mul128(sv, (U8)(ch & 0x7f));
PUSHs(newSVpvn_flags(aptr, len, SVs_TEMP));
}
break;
-#ifdef HAS_QUAD
+#if defined(HAS_QUAD) && IVSIZE >= 8
case 'q':
while (len-- > 0) {
Quad_t aquad;
SHIFT_VAR(utf8, s, strend, aquad, datumtype, needs_swap);
if (!checksum)
- mPUSHs(aquad >= IV_MIN && aquad <= IV_MAX ?
- newSViv((IV)aquad) : newSVnv((NV)aquad));
+ mPUSHs(newSViv((IV)aquad));
else if (checksum > bits_in_uv)
cdouble += (NV)aquad;
else
Uquad_t auquad;
SHIFT_VAR(utf8, s, strend, auquad, datumtype, needs_swap);
if (!checksum)
- mPUSHs(auquad <= UV_MAX ?
- newSVuv((UV)auquad) : newSVnv((NV)auquad));
+ mPUSHs(newSVuv((UV)auquad));
else if (checksum > bits_in_uv)
cdouble += (NV)auquad;
else
cuv += auquad;
}
break;
-#endif /* HAS_QUAD */
+#endif
/* float and double added gnb@melba.bby.oz.au 22/11/89 */
case 'f':
while (len-- > 0) {
ld_bytes aldouble;
SHIFT_BYTES(utf8, s, strend, aldouble.bytes,
sizeof(aldouble.bytes), datumtype, needs_swap);
+ /* The most common long double format, the x86 80-bit
+ * extended precision, has either 2 or 6 unused bytes,
+ * which may contain garbage, which may contain
+ * unintentional data. While we do zero the bytes of
+ * the long double data in pack(), here in unpack() we
+ * don't, because it's really hard to envision that
+ * reading the long double off aldouble would be
+ * affected by the unused bytes.
+ *
+ * Note that trying to unpack 'long doubles' of 'long
+ * doubles' packed in another system is in the general
+ * case doomed without having more detail. */
if (!checksum)
mPUSHn(aldouble.ld);
else
sv = sv_2mortal(newSV(l));
if (l) SvPOK_on(sv);
}
- if (utf8) {
- while (next_uni_uu(aTHX_ &s, strend, &len)) {
- I32 a, b, c, d;
- char hunk[3];
-
- while (len > 0) {
- next_uni_uu(aTHX_ &s, strend, &a);
- next_uni_uu(aTHX_ &s, strend, &b);
- next_uni_uu(aTHX_ &s, strend, &c);
- next_uni_uu(aTHX_ &s, strend, &d);
- hunk[0] = (char)((a << 2) | (b >> 4));
- hunk[1] = (char)((b << 4) | (c >> 2));
- hunk[2] = (char)((c << 6) | d);
- if (!checksum)
- sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
- len -= 3;
- }
- if (s < strend) {
- if (*s == '\n') {
- s++;
- }
- else {
- /* possible checksum byte */
- const char *skip = s+UTF8SKIP(s);
- if (skip < strend && *skip == '\n')
- s = skip+1;
- }
- }
- }
- } else {
- while (s < strend && *s > ' ' && ISUUCHAR(*s)) {
- I32 a, b, c, d;
- char hunk[3];
-
- len = PL_uudmap[*(U8*)s++] & 077;
- while (len > 0) {
- if (s < strend && ISUUCHAR(*s))
- a = PL_uudmap[*(U8*)s++] & 077;
- else
- a = 0;
- if (s < strend && ISUUCHAR(*s))
- b = PL_uudmap[*(U8*)s++] & 077;
- else
- b = 0;
- if (s < strend && ISUUCHAR(*s))
- c = PL_uudmap[*(U8*)s++] & 077;
- else
- c = 0;
- if (s < strend && ISUUCHAR(*s))
- d = PL_uudmap[*(U8*)s++] & 077;
- else
- d = 0;
- hunk[0] = (char)((a << 2) | (b >> 4));
- hunk[1] = (char)((b << 4) | (c >> 2));
- hunk[2] = (char)((c << 6) | d);
- if (!checksum)
- sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
- len -= 3;
- }
- if (*s == '\n')
- s++;
- else /* possible checksum byte */
- if (s + 1 < strend && s[1] == '\n')
- s += 2;
- }
- }
+
+ /* Note that all legal uuencoded strings are ASCII printables, so
+ * have the same representation under UTF-8 vs not. This means we
+ * can ignore UTF8ness on legal input. For illegal we stop at the
+ * first failure, and don't report where/what that is, so again we
+ * can ignore UTF8ness */
+
+ while (s < strend && *s != ' ' && ISUUCHAR(*s)) {
+ I32 a, b, c, d;
+ char hunk[3];
+
+ len = PL_uudmap[*(U8*)s++] & 077;
+ while (len > 0) {
+ if (s < strend && ISUUCHAR(*s))
+ a = PL_uudmap[*(U8*)s++] & 077;
+ else
+ a = 0;
+ if (s < strend && ISUUCHAR(*s))
+ b = PL_uudmap[*(U8*)s++] & 077;
+ else
+ b = 0;
+ if (s < strend && ISUUCHAR(*s))
+ c = PL_uudmap[*(U8*)s++] & 077;
+ else
+ c = 0;
+ if (s < strend && ISUUCHAR(*s))
+ d = PL_uudmap[*(U8*)s++] & 077;
+ else
+ d = 0;
+ hunk[0] = (char)((a << 2) | (b >> 4));
+ hunk[1] = (char)((b << 4) | (c >> 2));
+ hunk[2] = (char)((c << 6) | d);
+ if (!checksum)
+ sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
+ len -= 3;
+ }
+ if (*s == '\n')
+ s++;
+ else /* possible checksum byte */
+ if (s + 1 < strend && s[1] == '\n')
+ s += 2;
+ }
if (!checksum)
XPUSHs(sv);
break;
- }
+ } /* End of switch */
if (checksum) {
if (strchr("fFdD", TYPE_NO_MODIFIERS(datumtype)) ||
}
while (cdouble < 0.0)
cdouble += anv;
- cdouble = Perl_modf(cdouble / anv, &trouble) * anv;
+ cdouble = Perl_modf(cdouble / anv, &trouble);
+#ifdef LONGDOUBLE_DOUBLEDOUBLE
+ /* Workaround for powerpc doubledouble modfl bug:
+ * close to 1.0L and -1.0L cdouble is 0, and trouble
+ * is cdouble / anv. */
+ if (trouble != Perl_ceil(trouble)) {
+ cdouble = trouble;
+ if (cdouble > 1.0L) cdouble -= 1.0L;
+ if (cdouble < -1.0L) cdouble += 1.0L;
+ }
+#endif
+ cdouble *= anv;
sv = newSVnv(cdouble);
}
else {
PP(pp_unpack)
{
- dVAR;
dSP;
dPOPPOPssrl;
- I32 gimme = GIMME_V;
+ U8 gimme = GIMME_V;
STRLEN llen;
STRLEN rlen;
const char *pat = SvPV_const(left, llen);
const char *s = SvPV_const(right, rlen);
const char *strend = s + rlen;
const char *patend = pat + llen;
- I32 cnt;
+ SSize_t cnt;
PUTBACK;
cnt = unpackstring(pat, patend, s, strend,
}
STATIC U8 *
-doencodes(U8 *h, const char *s, I32 len)
+doencodes(U8 *h, const U8 *s, SSize_t len)
{
*h++ = PL_uuemap[len];
while (len > 2) {
len -= 3;
}
if (len > 0) {
- const char r = (len > 1 ? s[1] : '\0');
+ const U8 r = (len > 1 ? s[1] : '\0');
*h++ = PL_uuemap[(077 & (s[0] >> 2))];
*h++ = PL_uuemap[(077 & (((s[0] << 4) & 060) | ((r >> 4) & 017)))];
*h++ = PL_uuemap[(077 & ((r << 2) & 074))];
/*
=for apidoc packlist
-The engine implementing pack() Perl function.
+The engine implementing C<pack()> Perl function.
=cut
*/
void
Perl_packlist(pTHX_ SV *cat, const char *pat, const char *patend, SV **beglist, SV **endlist )
{
- dVAR;
tempsym_t sym;
PERL_ARGS_ASSERT_PACKLIST;
from_start = SvPVX_const(sv);
from_end = from_start + SvCUR(sv);
for (from_ptr = from_start; from_ptr < from_end; from_ptr++)
- if (!NATIVE_IS_INVARIANT(*from_ptr)) break;
+ if (!NATIVE_BYTE_IS_INVARIANT(*from_ptr)) break;
if (from_ptr == from_end) {
/* Simple case: no character needs to be changed */
SvUTF8_on(sv);
return SvGROW(sv, len+extend+1);
}
+static SV *
+S_sv_check_infnan(pTHX_ SV *sv, I32 datumtype)
+{
+ SvGETMAGIC(sv);
+ if (UNLIKELY(SvAMAGIC(sv)))
+ sv = sv_2num(sv);
+ if (UNLIKELY(isinfnansv(sv))) {
+ const I32 c = TYPE_NO_MODIFIERS(datumtype);
+ const NV nv = SvNV_nomg(sv);
+ if (c == 'w')
+ Perl_croak(aTHX_ "Cannot compress %" NVgf " in pack", nv);
+ else
+ Perl_croak(aTHX_ "Cannot pack %" NVgf " with '%c'", nv, (int) c);
+ }
+ return sv;
+}
+
+#define SvIV_no_inf(sv,d) \
+ ((sv) = S_sv_check_infnan(aTHX_ sv,d), SvIV_nomg(sv))
+#define SvUV_no_inf(sv,d) \
+ ((sv) = S_sv_check_infnan(aTHX_ sv,d), SvUV_nomg(sv))
+
STATIC
SV **
S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
{
- dVAR;
tempsym_t lookahead;
- I32 items = endlist - beglist;
+ SSize_t items = endlist - beglist;
bool found = next_symbol(symptr);
bool utf8 = (symptr->flags & FLAG_PARSE_UTF8) ? 1 : 0;
bool warn_utf8 = ckWARN(WARN_UTF8);
+ char* from;
PERL_ARGS_ASSERT_PACK_REC;
while (found) {
SV *fromstr;
STRLEN fromlen;
- I32 len;
+ SSize_t len;
SV *lengthcode = NULL;
I32 datumtype = symptr->code;
howlen_t howlen = symptr->howlen;
char *cur = start + SvCUR(cat);
bool needs_swap;
-#define NEXTFROM (lengthcode ? lengthcode : items-- > 0 ? *beglist++ : &PL_sv_no)
+#define NEXTFROM (lengthcode ? lengthcode : items > 0 ? (--items, *beglist++) : &PL_sv_no)
+#define PEEKFROM (lengthcode ? lengthcode : items > 0 ? *beglist : &PL_sv_no)
switch (howlen) {
case e_star:
/* Code inside the switch must take care to properly update
cat (CUR length and '\0' termination) if it updated *cur and
doesn't simply leave using break */
- switch(TYPE_NO_ENDIANNESS(datumtype)) {
+ switch (TYPE_NO_ENDIANNESS(datumtype)) {
default:
Perl_croak(aTHX_ "Invalid type '%c' in pack",
(int) TYPE_NO_MODIFIERS(datumtype));
case '%':
Perl_croak(aTHX_ "'%%' may not be used in pack");
- {
- char *from;
+
case '.' | TYPE_IS_SHRIEKING:
case '.':
if (howlen == e_star) from = start;
from = group ? start + group->strbeg : start;
}
fromstr = NEXTFROM;
- len = SvIV(fromstr);
+ len = SvIV_no_inf(fromstr, datumtype);
goto resize;
case '@' | TYPE_IS_SHRIEKING:
case '@':
goto shrink;
}
break;
- }
+
case '(': {
tempsym_t savsym = *symptr;
U32 group_modifiers = TYPE_MODIFIERS(datumtype & ~symptr->flags);
len = 1;
if (utf8) {
char *hop, *last;
- I32 l = len;
+ SSize_t l = len;
hop = last = start;
while (hop < cur) {
hop += UTF8SKIP(hop);
break;
}
len = (cur-start) % len;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'X':
if (utf8) {
if (len < 1) goto no_change;
}
break;
case 'x' | TYPE_IS_SHRIEKING: {
- I32 ai32;
+ SSize_t ai32;
if (!len) /* Avoid division by 0 */
len = 1;
if (utf8) ai32 = utf8_length((U8 *) start, (U8 *) cur) % len;
if (ai32 == 0) goto no_change;
len -= ai32;
}
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 'x':
goto grow;
case 'A':
s = aptr;
end = aptr + fromlen;
fromlen = datumtype == 'Z' ? len-1 : len;
- while ((I32) fromlen > 0 && s < end) {
+ while ((SSize_t) fromlen > 0 && s < end) {
s += UTF8SKIP(s);
fromlen--;
}
if (datumtype == 'Z') len++;
}
GROWING(0, cat, start, cur, len);
- if (!uni_to_bytes(aTHX_ &aptr, end, cur, fromlen,
+ if (!S_utf8_to_bytes(aTHX_ &aptr, end, cur, fromlen,
datumtype | TYPE_IS_PACK))
Perl_croak(aTHX_ "panic: predicted utf8 length not available, "
- "for '%c', aptr=%p end=%p cur=%p, fromlen=%"UVuf,
- (int)datumtype, aptr, end, cur, (UV)fromlen);
+ "for '%c', aptr=%p end=%p cur=%p, fromlen=%zu",
+ (int)datumtype, aptr, end, cur, fromlen);
cur += fromlen;
len -= fromlen;
} else if (utf8) {
len = fromlen;
if (datumtype == 'Z') len++;
}
- if (len <= (I32) fromlen) {
+ if (len <= (SSize_t) fromlen) {
fromlen = len;
if (datumtype == 'Z' && fromlen > 0) fromlen--;
}
len = fromlen;
if (datumtype == 'Z') len++;
}
- if (len <= (I32) fromlen) {
+ if (len <= (SSize_t) fromlen) {
fromlen = len;
if (datumtype == 'Z' && fromlen > 0) fromlen--;
}
case 'B':
case 'b': {
const char *str, *end;
- I32 l, field_len;
+ SSize_t l, field_len;
U8 bits;
bool utf8_source;
U32 utf8_flags;
if (howlen == e_star) len = fromlen;
field_len = (len+7)/8;
GROWING(utf8, cat, start, cur, field_len);
- if (len > (I32)fromlen) len = fromlen;
+ if (len > (SSize_t)fromlen) len = fromlen;
bits = 0;
l = 0;
if (datumtype == 'B')
case 'H':
case 'h': {
const char *str, *end;
- I32 l, field_len;
+ SSize_t l, field_len;
U8 bits;
bool utf8_source;
U32 utf8_flags;
if (howlen == e_star) len = fromlen;
field_len = (len+1)/2;
GROWING(utf8, cat, start, cur, field_len);
- if (!utf8 && len > (I32)fromlen) len = fromlen;
+ if (!utf8_source && len > (SSize_t)fromlen) len = fromlen;
bits = 0;
l = 0;
if (datumtype == 'H')
while (len-- > 0) {
IV aiv;
fromstr = NEXTFROM;
- aiv = SvIV(fromstr);
+ aiv = SvIV_no_inf(fromstr, datumtype);
if ((-128 > aiv || aiv > 127))
Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
"Character in 'c' format wrapped in pack");
while (len-- > 0) {
IV aiv;
fromstr = NEXTFROM;
- aiv = SvIV(fromstr);
+ aiv = SvIV_no_inf(fromstr, datumtype);
if ((0 > aiv || aiv > 0xff))
Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
"Character in 'C' format wrapped in pack");
while (len-- > 0) {
UV auv;
fromstr = NEXTFROM;
- auv = SvUV(fromstr);
+ auv = SvUV_no_inf(fromstr, datumtype);
if (in_bytes) auv = auv % 0x100;
if (utf8) {
W_utf8:
- if (cur > end) {
+ if (cur >= end) {
*cur = '\0';
SvCUR_set(cat, cur - start);
GROWING(0, cat, start, cur, len+UTF8_MAXLEN);
end = start+SvLEN(cat)-UTF8_MAXLEN;
}
- cur = (char *) uvuni_to_utf8_flags((U8 *) cur,
- NATIVE_TO_UNI(auv),
- warn_utf8 ?
- 0 : UNICODE_ALLOW_ANY);
+ cur = (char *) uvchr_to_utf8_flags((U8 *) cur, auv, 0);
} else {
if (auv >= 0x100) {
if (!SvUTF8(cat)) {
while (len-- > 0) {
UV auv;
fromstr = NEXTFROM;
- auv = SvUV(fromstr);
+ auv = SvUV_no_inf(fromstr, datumtype);
if (utf8) {
- U8 buffer[UTF8_MAXLEN], *endb;
- endb = uvuni_to_utf8_flags(buffer, auv,
- warn_utf8 ?
- 0 : UNICODE_ALLOW_ANY);
+ U8 buffer[UTF8_MAXLEN+1], *endb;
+ endb = uvchr_to_utf8_flags(buffer, UNI_TO_NATIVE(auv), 0);
if (cur+(endb-buffer)*UTF8_EXPAND >= end) {
*cur = '\0';
SvCUR_set(cat, cur - start);
len+(endb-buffer)*UTF8_EXPAND);
end = start+SvLEN(cat);
}
- cur = S_bytes_to_uni(buffer, endb-buffer, cur, 0);
+ cur = my_bytes_to_utf8(buffer, endb-buffer, cur, 0);
} else {
if (cur >= end) {
*cur = '\0';
GROWING(0, cat, start, cur, len+UTF8_MAXLEN);
end = start+SvLEN(cat)-UTF8_MAXLEN;
}
- cur = (char *) uvuni_to_utf8_flags((U8 *) cur, auv,
- warn_utf8 ?
- 0 : UNICODE_ALLOW_ANY);
+ cur = (char *) uvchr_to_utf8_flags((U8 *) cur,
+ UNI_TO_NATIVE(auv),
+ 0);
}
}
break;
NV anv;
fromstr = NEXTFROM;
anv = SvNV(fromstr);
-# if defined(VMS) && !defined(_IEEE_FP)
+# if (defined(VMS) && !defined(_IEEE_FP)) || defined(DOUBLE_IS_VAX_FLOAT)
/* IEEE fp overflow shenanigans are unavailable on VAX and optional
* on Alpha; fake it if we don't have them.
*/
afloat = -FLT_MAX;
else afloat = (float)anv;
# else
- afloat = (float)anv;
+# if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ if(Perl_isnan(anv))
+ afloat = (float)NV_NAN;
+ else
+# endif
+# ifdef NV_INF
+ /* a simple cast to float is undefined if outside
+ * the range of values that can be represented */
+ afloat = (float)(anv > FLT_MAX ? NV_INF :
+ anv < -FLT_MAX ? -NV_INF : anv);
+# endif
# endif
PUSH_VAR(utf8, cur, afloat, needs_swap);
}
NV anv;
fromstr = NEXTFROM;
anv = SvNV(fromstr);
-# if defined(VMS) && !defined(_IEEE_FP)
+# if (defined(VMS) && !defined(_IEEE_FP)) || defined(DOUBLE_IS_VAX_FLOAT)
/* IEEE fp overflow shenanigans are unavailable on VAX and optional
* on Alpha; fake it if we don't have them.
*/
#ifdef __GNUC__
/* to work round a gcc/x86 bug; don't use SvNV */
anv.nv = sv_2nv(fromstr);
+# if defined(LONGDOUBLE_X86_80_BIT) && defined(USE_LONG_DOUBLE) \
+ && LONG_DOUBLESIZE > 10
+ /* GCC sometimes overwrites the padding in the
+ assignment above */
+ Zero(anv.bytes+10, sizeof(anv.bytes) - 10, U8);
+# endif
#else
anv.nv = SvNV(fromstr);
#endif
# ifdef __GNUC__
/* to work round a gcc/x86 bug; don't use SvNV */
aldouble.ld = (long double)sv_2nv(fromstr);
+# if defined(LONGDOUBLE_X86_80_BIT) && LONG_DOUBLESIZE > 10
+ /* GCC sometimes overwrites the padding in the
+ assignment above */
+ Zero(aldouble.bytes+10, sizeof(aldouble.bytes) - 10, U8);
+# endif
# else
aldouble.ld = (long double)SvNV(fromstr);
# endif
while (len-- > 0) {
I16 ai16;
fromstr = NEXTFROM;
- ai16 = (I16)SvIV(fromstr);
+ ai16 = (I16)SvIV_no_inf(fromstr, datumtype);
ai16 = PerlSock_htons(ai16);
PUSH16(utf8, cur, &ai16, FALSE);
}
while (len-- > 0) {
I16 ai16;
fromstr = NEXTFROM;
- ai16 = (I16)SvIV(fromstr);
+ ai16 = (I16)SvIV_no_inf(fromstr, datumtype);
ai16 = htovs(ai16);
PUSH16(utf8, cur, &ai16, FALSE);
}
while (len-- > 0) {
unsigned short aushort;
fromstr = NEXTFROM;
- aushort = SvUV(fromstr);
+ aushort = SvUV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, aushort, needs_swap);
}
break;
#else
- /* Fall through! */
+ /* FALLTHROUGH */
#endif
case 'S':
while (len-- > 0) {
U16 au16;
fromstr = NEXTFROM;
- au16 = (U16)SvUV(fromstr);
+ au16 = (U16)SvUV_no_inf(fromstr, datumtype);
PUSH16(utf8, cur, &au16, needs_swap);
}
break;
while (len-- > 0) {
short ashort;
fromstr = NEXTFROM;
- ashort = SvIV(fromstr);
+ ashort = SvIV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, ashort, needs_swap);
}
break;
#else
- /* Fall through! */
+ /* FALLTHROUGH */
#endif
case 's':
while (len-- > 0) {
I16 ai16;
fromstr = NEXTFROM;
- ai16 = (I16)SvIV(fromstr);
+ ai16 = (I16)SvIV_no_inf(fromstr, datumtype);
PUSH16(utf8, cur, &ai16, needs_swap);
}
break;
while (len-- > 0) {
unsigned int auint;
fromstr = NEXTFROM;
- auint = SvUV(fromstr);
+ auint = SvUV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, auint, needs_swap);
}
break;
while (len-- > 0) {
IV aiv;
fromstr = NEXTFROM;
- aiv = SvIV(fromstr);
+ aiv = SvIV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, aiv, needs_swap);
}
break;
while (len-- > 0) {
UV auv;
fromstr = NEXTFROM;
- auv = SvUV(fromstr);
+ auv = SvUV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, auv, needs_swap);
}
break;
while (len-- > 0) {
NV anv;
fromstr = NEXTFROM;
- anv = SvNV(fromstr);
+ S_sv_check_infnan(aTHX_ fromstr, datumtype);
+ anv = SvNV_nomg(fromstr);
if (anv < 0) {
*cur = '\0';
if (SvIOK(fromstr) || anv < UV_MAX_P1) {
char buf[(sizeof(UV)*CHAR_BIT)/7+1];
char *in = buf + sizeof(buf);
- UV auv = SvUV(fromstr);
+ UV auv = SvUV_nomg(fromstr);
do {
*--in = (char)((auv & 0x7f) | 0x80);
w_string:
/* Copy string and check for compliance */
- from = SvPV_const(fromstr, len);
+ from = SvPV_nomg_const(fromstr, len);
if ((norm = is_an_int(from, len)) == NULL)
Perl_croak(aTHX_ "Can only compress unsigned integers in pack");
while (len-- > 0) {
int aint;
fromstr = NEXTFROM;
- aint = SvIV(fromstr);
+ aint = SvIV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, aint, needs_swap);
}
break;
while (len-- > 0) {
U32 au32;
fromstr = NEXTFROM;
- au32 = SvUV(fromstr);
+ au32 = SvUV_no_inf(fromstr, datumtype);
au32 = PerlSock_htonl(au32);
PUSH32(utf8, cur, &au32, FALSE);
}
while (len-- > 0) {
U32 au32;
fromstr = NEXTFROM;
- au32 = SvUV(fromstr);
+ au32 = SvUV_no_inf(fromstr, datumtype);
au32 = htovl(au32);
PUSH32(utf8, cur, &au32, FALSE);
}
while (len-- > 0) {
unsigned long aulong;
fromstr = NEXTFROM;
- aulong = SvUV(fromstr);
+ aulong = SvUV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, aulong, needs_swap);
}
break;
while (len-- > 0) {
U32 au32;
fromstr = NEXTFROM;
- au32 = SvUV(fromstr);
+ au32 = SvUV_no_inf(fromstr, datumtype);
PUSH32(utf8, cur, &au32, needs_swap);
}
break;
while (len-- > 0) {
long along;
fromstr = NEXTFROM;
- along = SvIV(fromstr);
+ along = SvIV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, along, needs_swap);
}
break;
while (len-- > 0) {
I32 ai32;
fromstr = NEXTFROM;
- ai32 = SvIV(fromstr);
+ ai32 = SvIV_no_inf(fromstr, datumtype);
PUSH32(utf8, cur, &ai32, needs_swap);
}
break;
-#ifdef HAS_QUAD
+#if defined(HAS_QUAD) && IVSIZE >= 8
case 'Q':
while (len-- > 0) {
Uquad_t auquad;
fromstr = NEXTFROM;
- auquad = (Uquad_t) SvUV(fromstr);
+ auquad = (Uquad_t) SvUV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, auquad, needs_swap);
}
break;
while (len-- > 0) {
Quad_t aquad;
fromstr = NEXTFROM;
- aquad = (Quad_t)SvIV(fromstr);
+ aquad = (Quad_t)SvIV_no_inf(fromstr, datumtype);
PUSH_VAR(utf8, cur, aquad, needs_swap);
}
break;
-#endif /* HAS_QUAD */
+#endif
case 'P':
len = 1; /* assume SV is correct length */
GROWING(utf8, cat, start, cur, sizeof(char *));
- /* Fall through! */
+ /* FALLTHROUGH */
case 'p':
while (len-- > 0) {
const char *aptr;
* of pack() (and all copies of the result) are
* gone.
*/
- if ((SvTEMP(fromstr) || (SvPADTMP(fromstr) &&
+ if (((SvTEMP(fromstr) && SvREFCNT(fromstr) == 1)
+ || (SvPADTMP(fromstr) &&
!SvREADONLY(fromstr)))) {
Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
"Attempt to pack pointer to temporary value");
GROWING(utf8, cat, start, cur, (fromlen+2) / 3 * 4 + (fromlen+len-1)/len * 2);
while (fromlen > 0) {
U8 *end;
- I32 todo;
+ SSize_t todo;
U8 hunk[1+63/3*4+1];
- if ((I32)fromlen > len)
+ if ((SSize_t)fromlen > len)
todo = len;
else
todo = fromlen;
if (from_utf8) {
char buffer[64];
- if (!uni_to_bytes(aTHX_ &aptr, aend, buffer, todo,
+ if (!S_utf8_to_bytes(aTHX_ &aptr, aend, buffer, todo,
'u' | TYPE_IS_PACK)) {
*cur = '\0';
SvCUR_set(cat, cur - start);
Perl_croak(aTHX_ "panic: string is shorter than advertised, "
- "aptr=%p, aend=%p, buffer=%p, todo=%ld",
- aptr, aend, buffer, (long) todo);
+ "aptr=%p, aend=%p, buffer=%p, todo=%zd",
+ aptr, aend, buffer, todo);
}
- end = doencodes(hunk, buffer, todo);
+ end = doencodes(hunk, (const U8 *)buffer, todo);
} else {
- end = doencodes(hunk, aptr, todo);
+ end = doencodes(hunk, (const U8 *)aptr, todo);
aptr += todo;
}
PUSH_BYTES(utf8, cur, hunk, end-hunk, 0);
PP(pp_pack)
{
- dVAR; dSP; dMARK; dORIGMARK; dTARGET;
+ dSP; dMARK; dORIGMARK; dTARGET;
SV *cat = TARG;
STRLEN fromlen;
SV *pat_sv = *++MARK;
const char *patend = pat + fromlen;
MARK++;
- sv_setpvs(cat, "");
+ SvPVCLEAR(cat);
SvUTF8_off(cat);
packlist(cat, pat, patend, MARK, SP + 1);
}
/*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
* ex: set ts=8 sts=4 sw=4 et:
*/