+ 0,
+ /* s */ SIZE16,
+ 0, 0,
+ /* v */ SIZE16,
+ /* w */ sizeof(char) | PACK_SIZE_UNPREDICTABLE | PACK_SIZE_CANNOT_CSUM,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* shrieking */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* I */ sizeof(unsigned int),
+ 0, 0,
+ /* L */ sizeof(unsigned long),
+ 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* N */ SIZE32,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0,
+ /* S */ sizeof(unsigned short),
+ 0, 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* V */ SIZE32,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ /* i */ sizeof(int),
+ 0, 0,
+ /* l */ sizeof(long),
+ 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* n */ SIZE16,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0,
+ /* s */ sizeof(short),
+ 0, 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* v */ SIZE16,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+#else
+/* EBCDIC (or bust) */
+const packprops_t packprops[512] = {
+ /* normal */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+ /* c */ sizeof(char),
+ /* d */ sizeof(double),
+ 0,
+ /* f */ sizeof(float),
+ 0, 0,
+ /* i */ sizeof(int),
+ 0, 0, 0, 0, 0, 0, 0,
+ /* j */ IVSIZE,
+ 0,
+ /* l */ SIZE32,
+ 0,
+ /* n */ SIZE16,
+ 0,
+ /* p */ sizeof(char *) | PACK_SIZE_CANNOT_CSUM,
+#if defined(HAS_QUAD)
+ /* q */ sizeof(Quad_t),
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* s */ SIZE16,
+ 0, 0,
+ /* v */ SIZE16,
+ /* w */ sizeof(char) | PACK_SIZE_UNPREDICTABLE | PACK_SIZE_CANNOT_CSUM,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* C */ sizeof(unsigned char) | PACK_SIZE_UNPREDICTABLE,
+#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
+ /* D */ LONG_DOUBLESIZE,
+#else
+ 0,
+#endif
+ 0,
+ /* F */ NVSIZE,
+ 0, 0,
+ /* I */ sizeof(unsigned int),
+ 0, 0, 0, 0, 0, 0, 0,
+ /* J */ UVSIZE,
+ 0,
+ /* L */ SIZE32,
+ 0,
+ /* N */ SIZE32,
+ 0, 0,
+#if defined(HAS_QUAD)
+ /* Q */ sizeof(Uquad_t),
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* S */ SIZE16,
+ 0,
+ /* U */ sizeof(char) | PACK_SIZE_UNPREDICTABLE,
+ /* V */ SIZE32,
+ /* W */ sizeof(unsigned char) | PACK_SIZE_UNPREDICTABLE,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* shrieking */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* i */ sizeof(int),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* l */ sizeof(long),
+ 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* n */ SIZE16,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* s */ sizeof(short),
+ 0, 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* v */ SIZE16,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+ /* I */ sizeof(unsigned int),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* L */ sizeof(unsigned long),
+ 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* N */ SIZE32,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* S */ sizeof(unsigned short),
+ 0, 0,
+#if defined(PERL_PACK_CAN_SHRIEKSIGN)
+ /* V */ SIZE32,
+#else
+ 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+#endif
+
+STATIC U8
+uni_to_byte(pTHX_ const char **s, const char *end, I32 datumtype)
+{
+ UV val;
+ STRLEN retlen;
+ 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 (preferrably 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)
+ Perl_croak(aTHX_ "Malformed UTF-8 string in '%c' format in unpack",
+ (int) TYPE_NO_MODIFIERS(datumtype));
+ if (val >= 0x100) {
+ if (ckWARN(WARN_UNPACK))
+ Perl_warner(aTHX_ packWARN(WARN_UNPACK),
+ "Character in '%c' format wrapped in unpack",
+ (int) TYPE_NO_MODIFIERS(datumtype));
+ val &= 0xff;
+ }
+ *s += retlen;
+ return (U8)val;
+}
+
+#define SHIFT_BYTE(utf8, s, strend, datumtype) ((utf8) ? \
+ uni_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)
+{
+ UV val;
+ STRLEN retlen;
+ const char *from = *s;
+ int bad = 0;
+ const U32 flags = ckWARN(WARN_UTF8) ?
+ UTF8_CHECK_ONLY : (UTF8_CHECK_ONLY | UTF8_ALLOW_ANY);
+ 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) {
+ from += UTF8SKIP(from);
+ bad |= 1;
+ } else from += retlen;
+ if (val >= 0x100) {
+ bad |= 2;
+ val &= 0xff;
+ }
+ *(U8 *)buf++ = (U8)val;
+ }
+ /* We have enough characters for the buffer. Did we have problems ? */
+ if (bad) {
+ if (bad & 1) {
+ /* Rewalk the string fragment while warning */
+ const char *ptr;
+ const int 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);
+ }
+ if (from > end) from = end;