xref: /openbsd-src/gnu/usr.bin/perl/pp_pack.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*    pp_pack.c
2  *
3  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
4  *    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
5  *
6  *    You may distribute under the terms of either the GNU General Public
7  *    License or the Artistic License, as specified in the README file.
8  *
9  */
10 
11 /*
12  * He still hopefully carried some of his gear in his pack: a small tinder-box,
13  * two small shallow pans, the smaller fitting into the larger; inside them a
14  * wooden spoon, a short two-pronged fork and some skewers were stowed; and
15  * hidden at the bottom of the pack in a flat wooden box a dwindling treasure,
16  * some salt.
17  *
18  *     [p.653 of _The Lord of the Rings_, IV/iv: "Of Herbs and Stewed Rabbit"]
19  */
20 
21 /* This file contains pp ("push/pop") functions that
22  * execute the opcodes that make up a perl program. A typical pp function
23  * expects to find its arguments on the stack, and usually pushes its
24  * results onto the stack, hence the 'pp' terminology. Each OP structure
25  * contains a pointer to the relevant pp_foo() function.
26  *
27  * This particular file just contains pp_pack() and pp_unpack(). See the
28  * other pp*.c files for the rest of the pp_ functions.
29  */
30 
31 #include "EXTERN.h"
32 #define PERL_IN_PP_PACK_C
33 #include "perl.h"
34 
35 /* Types used by pack/unpack */
36 typedef enum {
37   e_no_len,     /* no length  */
38   e_number,     /* number, [] */
39   e_star        /* asterisk   */
40 } howlen_t;
41 
42 typedef struct tempsym {
43   const char*    patptr;   /* current template char */
44   const char*    patend;   /* one after last char   */
45   const char*    grpbeg;   /* 1st char of ()-group  */
46   const char*    grpend;   /* end of ()-group       */
47   I32      code;     /* template code (!<>)   */
48   I32      length;   /* length/repeat count   */
49   howlen_t howlen;   /* how length is given   */
50   int      level;    /* () nesting level      */
51   U32      flags;    /* /=4, comma=2, pack=1  */
52                      /*   and group modifiers */
53   STRLEN   strbeg;   /* offset of group start */
54   struct tempsym *previous; /* previous group */
55 } tempsym_t;
56 
57 #define TEMPSYM_INIT(symptr, p, e, f) \
58     STMT_START {	\
59 	(symptr)->patptr   = (p);	\
60 	(symptr)->patend   = (e);	\
61 	(symptr)->grpbeg   = NULL;	\
62 	(symptr)->grpend   = NULL;	\
63 	(symptr)->grpend   = NULL;	\
64 	(symptr)->code     = 0;		\
65 	(symptr)->length   = 0;		\
66 	(symptr)->howlen   = e_no_len;	\
67 	(symptr)->level    = 0;		\
68 	(symptr)->flags    = (f);	\
69 	(symptr)->strbeg   = 0;		\
70 	(symptr)->previous = NULL;	\
71    } STMT_END
72 
73 typedef union {
74     NV nv;
75     U8 bytes[sizeof(NV)];
76 } NV_bytes;
77 
78 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
79 typedef union {
80     long double ld;
81     U8 bytes[sizeof(long double)];
82 } ld_bytes;
83 #endif
84 
85 #if PERL_VERSION >= 9
86 # define PERL_PACK_CAN_BYTEORDER
87 # define PERL_PACK_CAN_SHRIEKSIGN
88 #endif
89 
90 #ifndef CHAR_BIT
91 # define CHAR_BIT	8
92 #endif
93 /* Maximum number of bytes to which a byte can grow due to upgrade */
94 #define UTF8_EXPAND	2
95 
96 /*
97  * Offset for integer pack/unpack.
98  *
99  * On architectures where I16 and I32 aren't really 16 and 32 bits,
100  * which for now are all Crays, pack and unpack have to play games.
101  */
102 
103 /*
104  * These values are required for portability of pack() output.
105  * If they're not right on your machine, then pack() and unpack()
106  * wouldn't work right anyway; you'll need to apply the Cray hack.
107  * (I'd like to check them with #if, but you can't use sizeof() in
108  * the preprocessor.)  --???
109  */
110 /*
111     The appropriate SHORTSIZE, INTSIZE, LONGSIZE, and LONGLONGSIZE
112     defines are now in config.h.  --Andy Dougherty  April 1998
113  */
114 #define SIZE16 2
115 #define SIZE32 4
116 
117 /* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
118    --jhi Feb 1999 */
119 
120 #if U16SIZE > SIZE16 || U32SIZE > SIZE32
121 #  if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678    /* little-endian */
122 #    define OFF16(p)	((char*)(p))
123 #    define OFF32(p)	((char*)(p))
124 #  else
125 #    if BYTEORDER == 0x4321 || BYTEORDER == 0x87654321  /* big-endian */
126 #      define OFF16(p)	((char*)(p) + (sizeof(U16) - SIZE16))
127 #      define OFF32(p)	((char*)(p) + (sizeof(U32) - SIZE32))
128 #    else
129        ++++ bad cray byte order
130 #    endif
131 #  endif
132 #else
133 #  define OFF16(p)     ((char *) (p))
134 #  define OFF32(p)     ((char *) (p))
135 #endif
136 
137 /* Only to be used inside a loop (see the break) */
138 #define SHIFT16(utf8, s, strend, p, datumtype) STMT_START {		\
139     if (utf8) {								\
140 	if (!uni_to_bytes(aTHX_ &(s), strend, OFF16(p), SIZE16, datumtype)) break;	\
141     } else {								\
142 	Copy(s, OFF16(p), SIZE16, char);				\
143 	(s) += SIZE16;							\
144     }									\
145 } STMT_END
146 
147 /* Only to be used inside a loop (see the break) */
148 #define SHIFT32(utf8, s, strend, p, datumtype) STMT_START {		\
149     if (utf8) {								\
150 	if (!uni_to_bytes(aTHX_ &(s), strend, OFF32(p), SIZE32, datumtype)) break;	\
151     } else {								\
152 	Copy(s, OFF32(p), SIZE32, char);				\
153 	(s) += SIZE32;							\
154     }									\
155 } STMT_END
156 
157 #define PUSH16(utf8, cur, p) PUSH_BYTES(utf8, cur, OFF16(p), SIZE16)
158 #define PUSH32(utf8, cur, p) PUSH_BYTES(utf8, cur, OFF32(p), SIZE32)
159 
160 /* Only to be used inside a loop (see the break) */
161 #define SHIFT_BYTES(utf8, s, strend, buf, len, datumtype)	\
162 STMT_START {						\
163     if (utf8) {						\
164         if (!uni_to_bytes(aTHX_ &s, strend,		\
165 	  (char *) (buf), len, datumtype)) break;	\
166     } else {						\
167         Copy(s, (char *) (buf), len, char);		\
168         s += len;					\
169     }							\
170 } STMT_END
171 
172 #define SHIFT_VAR(utf8, s, strend, var, datumtype)	\
173        SHIFT_BYTES(utf8, s, strend, &(var), sizeof(var), datumtype)
174 
175 #define PUSH_VAR(utf8, aptr, var)	\
176 	PUSH_BYTES(utf8, aptr, &(var), sizeof(var))
177 
178 /* Avoid stack overflow due to pathological templates. 100 should be plenty. */
179 #define MAX_SUB_TEMPLATE_LEVEL 100
180 
181 /* flags (note that type modifiers can also be used as flags!) */
182 #define FLAG_WAS_UTF8	      0x40
183 #define FLAG_PARSE_UTF8       0x20	/* Parse as utf8 */
184 #define FLAG_UNPACK_ONLY_ONE  0x10
185 #define FLAG_DO_UTF8          0x08	/* The underlying string is utf8 */
186 #define FLAG_SLASH            0x04
187 #define FLAG_COMMA            0x02
188 #define FLAG_PACK             0x01
189 
190 STATIC SV *
191 S_mul128(pTHX_ SV *sv, U8 m)
192 {
193   STRLEN          len;
194   char           *s = SvPV(sv, len);
195   char           *t;
196 
197   PERL_ARGS_ASSERT_MUL128;
198 
199   if (!strnEQ(s, "0000", 4)) {  /* need to grow sv */
200     SV * const tmpNew = newSVpvs("0000000000");
201 
202     sv_catsv(tmpNew, sv);
203     SvREFCNT_dec(sv);		/* free old sv */
204     sv = tmpNew;
205     s = SvPV(sv, len);
206   }
207   t = s + len - 1;
208   while (!*t)                   /* trailing '\0'? */
209     t--;
210   while (t > s) {
211     const U32 i = ((*t - '0') << 7) + m;
212     *(t--) = '0' + (char)(i % 10);
213     m = (char)(i / 10);
214   }
215   return (sv);
216 }
217 
218 /* Explosives and implosives. */
219 
220 #if 'I' == 73 && 'J' == 74
221 /* On an ASCII/ISO kind of system */
222 #define ISUUCHAR(ch)    ((ch) >= ' ' && (ch) < 'a')
223 #else
224 /*
225   Some other sort of character set - use memchr() so we don't match
226   the null byte.
227  */
228 #define ISUUCHAR(ch)    (memchr(PL_uuemap, (ch), sizeof(PL_uuemap)-1) || (ch) == ' ')
229 #endif
230 
231 /* type modifiers */
232 #define TYPE_IS_SHRIEKING	0x100
233 #define TYPE_IS_BIG_ENDIAN	0x200
234 #define TYPE_IS_LITTLE_ENDIAN	0x400
235 #define TYPE_IS_PACK		0x800
236 #define TYPE_ENDIANNESS_MASK	(TYPE_IS_BIG_ENDIAN|TYPE_IS_LITTLE_ENDIAN)
237 #define TYPE_MODIFIERS(t)	((t) & ~0xFF)
238 #define TYPE_NO_MODIFIERS(t)	((t) & 0xFF)
239 
240 #ifdef PERL_PACK_CAN_SHRIEKSIGN
241 # define SHRIEKING_ALLOWED_TYPES "sSiIlLxXnNvV@."
242 #else
243 # define SHRIEKING_ALLOWED_TYPES "sSiIlLxX"
244 #endif
245 
246 #ifndef PERL_PACK_CAN_BYTEORDER
247 /* Put "can't" first because it is shorter  */
248 # define TYPE_ENDIANNESS(t)	0
249 # define TYPE_NO_ENDIANNESS(t)	(t)
250 
251 # define ENDIANNESS_ALLOWED_TYPES   ""
252 
253 # define DO_BO_UNPACK(var, type)
254 # define DO_BO_PACK(var, type)
255 # define DO_BO_UNPACK_PTR(var, type, pre_cast, post_cast)
256 # define DO_BO_PACK_PTR(var, type, pre_cast, post_cast)
257 # define DO_BO_UNPACK_N(var, type)
258 # define DO_BO_PACK_N(var, type)
259 # define DO_BO_UNPACK_P(var)
260 # define DO_BO_PACK_P(var)
261 # define DO_BO_UNPACK_PC(var)
262 # define DO_BO_PACK_PC(var)
263 
264 #else /* PERL_PACK_CAN_BYTEORDER */
265 
266 # define TYPE_ENDIANNESS(t)	((t) & TYPE_ENDIANNESS_MASK)
267 # define TYPE_NO_ENDIANNESS(t)	((t) & ~TYPE_ENDIANNESS_MASK)
268 
269 # define ENDIANNESS_ALLOWED_TYPES   "sSiIlLqQjJfFdDpP("
270 
271 # define DO_BO_UNPACK(var, type)                                              \
272         STMT_START {                                                          \
273           switch (TYPE_ENDIANNESS(datumtype)) {                               \
274             case TYPE_IS_BIG_ENDIAN:    var = my_betoh ## type (var); break;  \
275             case TYPE_IS_LITTLE_ENDIAN: var = my_letoh ## type (var); break;  \
276             default: break;                                                   \
277           }                                                                   \
278         } STMT_END
279 
280 # define DO_BO_PACK(var, type)                                                \
281         STMT_START {                                                          \
282           switch (TYPE_ENDIANNESS(datumtype)) {                               \
283             case TYPE_IS_BIG_ENDIAN:    var = my_htobe ## type (var); break;  \
284             case TYPE_IS_LITTLE_ENDIAN: var = my_htole ## type (var); break;  \
285             default: break;                                                   \
286           }                                                                   \
287         } STMT_END
288 
289 # define DO_BO_UNPACK_PTR(var, type, pre_cast, post_cast)                     \
290         STMT_START {                                                          \
291           switch (TYPE_ENDIANNESS(datumtype)) {                               \
292             case TYPE_IS_BIG_ENDIAN:                                          \
293               var = (post_cast*) my_betoh ## type ((pre_cast) var);           \
294               break;                                                          \
295             case TYPE_IS_LITTLE_ENDIAN:                                       \
296               var = (post_cast *) my_letoh ## type ((pre_cast) var);          \
297               break;                                                          \
298             default:                                                          \
299               break;                                                          \
300           }                                                                   \
301         } STMT_END
302 
303 # define DO_BO_PACK_PTR(var, type, pre_cast, post_cast)                       \
304         STMT_START {                                                          \
305           switch (TYPE_ENDIANNESS(datumtype)) {                               \
306             case TYPE_IS_BIG_ENDIAN:                                          \
307               var = (post_cast *) my_htobe ## type ((pre_cast) var);          \
308               break;                                                          \
309             case TYPE_IS_LITTLE_ENDIAN:                                       \
310               var = (post_cast *) my_htole ## type ((pre_cast) var);          \
311               break;                                                          \
312             default:                                                          \
313               break;                                                          \
314           }                                                                   \
315         } STMT_END
316 
317 # define BO_CANT_DOIT(action, type)                                           \
318         STMT_START {                                                          \
319           switch (TYPE_ENDIANNESS(datumtype)) {                               \
320              case TYPE_IS_BIG_ENDIAN:                                         \
321                Perl_croak(aTHX_ "Can't %s big-endian %ss on this "            \
322                                 "platform", #action, #type);                  \
323                break;                                                         \
324              case TYPE_IS_LITTLE_ENDIAN:                                      \
325                Perl_croak(aTHX_ "Can't %s little-endian %ss on this "         \
326                                 "platform", #action, #type);                  \
327                break;                                                         \
328              default:                                                         \
329                break;                                                         \
330            }                                                                  \
331          } STMT_END
332 
333 # if PTRSIZE == INTSIZE
334 #  define DO_BO_UNPACK_P(var)	DO_BO_UNPACK_PTR(var, i, int, void)
335 #  define DO_BO_PACK_P(var)	DO_BO_PACK_PTR(var, i, int, void)
336 #  define DO_BO_UNPACK_PC(var)	DO_BO_UNPACK_PTR(var, i, int, char)
337 #  define DO_BO_PACK_PC(var)	DO_BO_PACK_PTR(var, i, int, char)
338 # elif PTRSIZE == LONGSIZE
339 #  if LONGSIZE < IVSIZE && IVSIZE == 8
340 #   define DO_BO_UNPACK_P(var)	DO_BO_UNPACK_PTR(var, 64, IV, void)
341 #   define DO_BO_PACK_P(var)	DO_BO_PACK_PTR(var, 64, IV, void)
342 #   define DO_BO_UNPACK_PC(var)	DO_BO_UNPACK_PTR(var, 64, IV, char)
343 #   define DO_BO_PACK_PC(var)	DO_BO_PACK_PTR(var, 64, IV, char)
344 #  else
345 #   define DO_BO_UNPACK_P(var)	DO_BO_UNPACK_PTR(var, l, IV, void)
346 #   define DO_BO_PACK_P(var)	DO_BO_PACK_PTR(var, l, IV, void)
347 #   define DO_BO_UNPACK_PC(var)	DO_BO_UNPACK_PTR(var, l, IV, char)
348 #   define DO_BO_PACK_PC(var)	DO_BO_PACK_PTR(var, l, IV, char)
349 #  endif
350 # elif PTRSIZE == IVSIZE
351 #  define DO_BO_UNPACK_P(var)	DO_BO_UNPACK_PTR(var, l, IV, void)
352 #  define DO_BO_PACK_P(var)	DO_BO_PACK_PTR(var, l, IV, void)
353 #  define DO_BO_UNPACK_PC(var)	DO_BO_UNPACK_PTR(var, l, IV, char)
354 #  define DO_BO_PACK_PC(var)	DO_BO_PACK_PTR(var, l, IV, char)
355 # else
356 #  define DO_BO_UNPACK_P(var)	BO_CANT_DOIT(unpack, pointer)
357 #  define DO_BO_PACK_P(var)	BO_CANT_DOIT(pack, pointer)
358 #  define DO_BO_UNPACK_PC(var)	BO_CANT_DOIT(unpack, pointer)
359 #  define DO_BO_PACK_PC(var)	BO_CANT_DOIT(pack, pointer)
360 # endif
361 
362 # if defined(my_htolen) && defined(my_letohn) && \
363     defined(my_htoben) && defined(my_betohn)
364 #  define DO_BO_UNPACK_N(var, type)                                           \
365          STMT_START {                                                         \
366            switch (TYPE_ENDIANNESS(datumtype)) {                              \
367              case TYPE_IS_BIG_ENDIAN:    my_betohn(&var, sizeof(type)); break;\
368              case TYPE_IS_LITTLE_ENDIAN: my_letohn(&var, sizeof(type)); break;\
369              default: break;                                                  \
370            }                                                                  \
371          } STMT_END
372 
373 #  define DO_BO_PACK_N(var, type)                                             \
374          STMT_START {                                                         \
375            switch (TYPE_ENDIANNESS(datumtype)) {                              \
376              case TYPE_IS_BIG_ENDIAN:    my_htoben(&var, sizeof(type)); break;\
377              case TYPE_IS_LITTLE_ENDIAN: my_htolen(&var, sizeof(type)); break;\
378              default: break;                                                  \
379            }                                                                  \
380          } STMT_END
381 # else
382 #  define DO_BO_UNPACK_N(var, type)	BO_CANT_DOIT(unpack, type)
383 #  define DO_BO_PACK_N(var, type)	BO_CANT_DOIT(pack, type)
384 # endif
385 
386 #endif /* PERL_PACK_CAN_BYTEORDER */
387 
388 #define PACK_SIZE_CANNOT_CSUM		0x80
389 #define PACK_SIZE_UNPREDICTABLE		0x40	/* Not a fixed size element */
390 #define PACK_SIZE_MASK			0x3F
391 
392 /* These tables are regenerated by genpacksizetables.pl (and then hand pasted
393    in).  You're unlikely ever to need to regenerate them.  */
394 
395 #if TYPE_IS_SHRIEKING != 0x100
396    ++++shriek offset should be 256
397 #endif
398 
399 typedef U8 packprops_t;
400 #if 'J'-'I' == 1
401 /* ASCII */
402 STATIC const packprops_t packprops[512] = {
403     /* normal */
404     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
406     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408     0, 0, 0,
409     /* C */ sizeof(unsigned char),
410 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
411     /* D */ LONG_DOUBLESIZE,
412 #else
413     0,
414 #endif
415     0,
416     /* F */ NVSIZE,
417     0, 0,
418     /* I */ sizeof(unsigned int),
419     /* J */ UVSIZE,
420     0,
421     /* L */ SIZE32,
422     0,
423     /* N */ SIZE32,
424     0, 0,
425 #if defined(HAS_QUAD)
426     /* Q */ sizeof(Uquad_t),
427 #else
428     0,
429 #endif
430     0,
431     /* S */ SIZE16,
432     0,
433     /* U */ sizeof(char) | PACK_SIZE_UNPREDICTABLE,
434     /* V */ SIZE32,
435     /* W */ sizeof(unsigned char) | PACK_SIZE_UNPREDICTABLE,
436     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
437     /* c */ sizeof(char),
438     /* d */ sizeof(double),
439     0,
440     /* f */ sizeof(float),
441     0, 0,
442     /* i */ sizeof(int),
443     /* j */ IVSIZE,
444     0,
445     /* l */ SIZE32,
446     0,
447     /* n */ SIZE16,
448     0,
449     /* p */ sizeof(char *) | PACK_SIZE_CANNOT_CSUM,
450 #if defined(HAS_QUAD)
451     /* q */ sizeof(Quad_t),
452 #else
453     0,
454 #endif
455     0,
456     /* s */ SIZE16,
457     0, 0,
458     /* v */ SIZE16,
459     /* w */ sizeof(char) | PACK_SIZE_UNPREDICTABLE | PACK_SIZE_CANNOT_CSUM,
460     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
461     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
462     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
463     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
464     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
465     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
466     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
467     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
468     0, 0, 0, 0, 0, 0, 0, 0,
469     /* shrieking */
470     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
471     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
472     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
473     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
474     0, 0, 0, 0, 0, 0, 0, 0, 0,
475     /* I */ sizeof(unsigned int),
476     0, 0,
477     /* L */ sizeof(unsigned long),
478     0,
479 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
480     /* N */ SIZE32,
481 #else
482     0,
483 #endif
484     0, 0, 0, 0,
485     /* S */ sizeof(unsigned short),
486     0, 0,
487 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
488     /* V */ SIZE32,
489 #else
490     0,
491 #endif
492     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
493     0, 0,
494     /* i */ sizeof(int),
495     0, 0,
496     /* l */ sizeof(long),
497     0,
498 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
499     /* n */ SIZE16,
500 #else
501     0,
502 #endif
503     0, 0, 0, 0,
504     /* s */ sizeof(short),
505     0, 0,
506 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
507     /* v */ SIZE16,
508 #else
509     0,
510 #endif
511     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
512     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
513     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
514     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
515     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
516     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
517     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
518     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
519     0, 0, 0, 0, 0, 0, 0, 0, 0
520 };
521 #else
522 /* EBCDIC (or bust) */
523 STATIC const packprops_t packprops[512] = {
524     /* normal */
525     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
526     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
527     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
528     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
529     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
530     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
531     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
532     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
533     0, 0, 0,
534     /* c */ sizeof(char),
535     /* d */ sizeof(double),
536     0,
537     /* f */ sizeof(float),
538     0, 0,
539     /* i */ sizeof(int),
540     0, 0, 0, 0, 0, 0, 0,
541     /* j */ IVSIZE,
542     0,
543     /* l */ SIZE32,
544     0,
545     /* n */ SIZE16,
546     0,
547     /* p */ sizeof(char *) | PACK_SIZE_CANNOT_CSUM,
548 #if defined(HAS_QUAD)
549     /* q */ sizeof(Quad_t),
550 #else
551     0,
552 #endif
553     0, 0, 0, 0, 0, 0, 0, 0, 0,
554     /* s */ SIZE16,
555     0, 0,
556     /* v */ SIZE16,
557     /* w */ sizeof(char) | PACK_SIZE_UNPREDICTABLE | PACK_SIZE_CANNOT_CSUM,
558     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
559     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
560     /* C */ sizeof(unsigned char),
561 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
562     /* D */ LONG_DOUBLESIZE,
563 #else
564     0,
565 #endif
566     0,
567     /* F */ NVSIZE,
568     0, 0,
569     /* I */ sizeof(unsigned int),
570     0, 0, 0, 0, 0, 0, 0,
571     /* J */ UVSIZE,
572     0,
573     /* L */ SIZE32,
574     0,
575     /* N */ SIZE32,
576     0, 0,
577 #if defined(HAS_QUAD)
578     /* Q */ sizeof(Uquad_t),
579 #else
580     0,
581 #endif
582     0, 0, 0, 0, 0, 0, 0, 0, 0,
583     /* S */ SIZE16,
584     0,
585     /* U */ sizeof(char) | PACK_SIZE_UNPREDICTABLE,
586     /* V */ SIZE32,
587     /* W */ sizeof(unsigned char) | PACK_SIZE_UNPREDICTABLE,
588     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
589     0, 0, 0, 0, 0, 0, 0, 0, 0,
590     /* shrieking */
591     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
592     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
593     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
594     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
595     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
596     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
597     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
598     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
599     0, 0, 0, 0, 0, 0, 0, 0, 0,
600     /* i */ sizeof(int),
601     0, 0, 0, 0, 0, 0, 0, 0, 0,
602     /* l */ sizeof(long),
603     0,
604 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
605     /* n */ SIZE16,
606 #else
607     0,
608 #endif
609     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
610     /* s */ sizeof(short),
611     0, 0,
612 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
613     /* v */ SIZE16,
614 #else
615     0,
616 #endif
617     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
618     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
619     0, 0, 0,
620     /* I */ sizeof(unsigned int),
621     0, 0, 0, 0, 0, 0, 0, 0, 0,
622     /* L */ sizeof(unsigned long),
623     0,
624 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
625     /* N */ SIZE32,
626 #else
627     0,
628 #endif
629     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
630     /* S */ sizeof(unsigned short),
631     0, 0,
632 #if defined(PERL_PACK_CAN_SHRIEKSIGN)
633     /* V */ SIZE32,
634 #else
635     0,
636 #endif
637     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
638     0, 0, 0, 0, 0, 0, 0, 0, 0, 0
639 };
640 #endif
641 
642 STATIC U8
643 uni_to_byte(pTHX_ const char **s, const char *end, I32 datumtype)
644 {
645     STRLEN retlen;
646     UV val = utf8n_to_uvchr((U8 *) *s, end-*s, &retlen,
647 			 ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
648     /* We try to process malformed UTF-8 as much as possible (preferably with
649        warnings), but these two mean we make no progress in the string and
650        might enter an infinite loop */
651     if (retlen == (STRLEN) -1 || retlen == 0)
652 	Perl_croak(aTHX_ "Malformed UTF-8 string in '%c' format in unpack",
653 		   (int) TYPE_NO_MODIFIERS(datumtype));
654     if (val >= 0x100) {
655 	Perl_ck_warner(aTHX_ packWARN(WARN_UNPACK),
656 		       "Character in '%c' format wrapped in unpack",
657 		       (int) TYPE_NO_MODIFIERS(datumtype));
658 	val &= 0xff;
659     }
660     *s += retlen;
661     return (U8)val;
662 }
663 
664 #define SHIFT_BYTE(utf8, s, strend, datumtype) ((utf8) ? \
665 	uni_to_byte(aTHX_ &(s), (strend), (datumtype)) : \
666 	*(U8 *)(s)++)
667 
668 STATIC bool
669 uni_to_bytes(pTHX_ const char **s, const char *end, const char *buf, int buf_len, I32 datumtype)
670 {
671     UV val;
672     STRLEN retlen;
673     const char *from = *s;
674     int bad = 0;
675     const U32 flags = ckWARN(WARN_UTF8) ?
676 	UTF8_CHECK_ONLY : (UTF8_CHECK_ONLY | UTF8_ALLOW_ANY);
677     for (;buf_len > 0; buf_len--) {
678 	if (from >= end) return FALSE;
679 	val = utf8n_to_uvchr((U8 *) from, end-from, &retlen, flags);
680 	if (retlen == (STRLEN) -1 || retlen == 0) {
681 	    from += UTF8SKIP(from);
682 	    bad |= 1;
683 	} else from += retlen;
684 	if (val >= 0x100) {
685 	    bad |= 2;
686 	    val &= 0xff;
687 	}
688 	*(U8 *)buf++ = (U8)val;
689     }
690     /* We have enough characters for the buffer. Did we have problems ? */
691     if (bad) {
692 	if (bad & 1) {
693 	    /* Rewalk the string fragment while warning */
694 	    const char *ptr;
695 	    const int flags = ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY;
696 	    for (ptr = *s; ptr < from; ptr += UTF8SKIP(ptr)) {
697 		if (ptr >= end) break;
698 		utf8n_to_uvuni((U8 *) ptr, end-ptr, &retlen, flags);
699 	    }
700 	    if (from > end) from = end;
701 	}
702 	if ((bad & 2))
703 	    Perl_ck_warner(aTHX_ packWARN(datumtype & TYPE_IS_PACK ?
704 				       WARN_PACK : WARN_UNPACK),
705 			   "Character(s) in '%c' format wrapped in %s",
706 			   (int) TYPE_NO_MODIFIERS(datumtype),
707 			   datumtype & TYPE_IS_PACK ? "pack" : "unpack");
708     }
709     *s = from;
710     return TRUE;
711 }
712 
713 STATIC bool
714 next_uni_uu(pTHX_ const char **s, const char *end, I32 *out)
715 {
716     dVAR;
717     STRLEN retlen;
718     const UV val = utf8n_to_uvchr((U8 *) *s, end-*s, &retlen, UTF8_CHECK_ONLY);
719     if (val >= 0x100 || !ISUUCHAR(val) ||
720 	retlen == (STRLEN) -1 || retlen == 0) {
721 	*out = 0;
722 	return FALSE;
723     }
724     *out = PL_uudmap[val] & 077;
725     *s += retlen;
726     return TRUE;
727 }
728 
729 STATIC char *
730 S_bytes_to_uni(const U8 *start, STRLEN len, char *dest) {
731     const U8 * const end = start + len;
732 
733     PERL_ARGS_ASSERT_BYTES_TO_UNI;
734 
735     while (start < end) {
736 	const UV uv = NATIVE_TO_ASCII(*start);
737 	if (UNI_IS_INVARIANT(uv))
738 	    *dest++ = (char)(U8)UTF_TO_NATIVE(uv);
739 	else {
740 	    *dest++ = (char)(U8)UTF8_EIGHT_BIT_HI(uv);
741 	    *dest++ = (char)(U8)UTF8_EIGHT_BIT_LO(uv);
742 	}
743 	start++;
744     }
745     return dest;
746 }
747 
748 #define PUSH_BYTES(utf8, cur, buf, len)				\
749 STMT_START {							\
750     if (utf8)							\
751 	(cur) = bytes_to_uni((U8 *) buf, len, (cur));		\
752     else {							\
753 	Copy(buf, cur, len, char);				\
754 	(cur) += (len);						\
755     }								\
756 } STMT_END
757 
758 #define GROWING(utf8, cat, start, cur, in_len)	\
759 STMT_START {					\
760     STRLEN glen = (in_len);			\
761     if (utf8) glen *= UTF8_EXPAND;		\
762     if ((cur) + glen >= (start) + SvLEN(cat)) {	\
763 	(start) = sv_exp_grow(cat, glen);	\
764 	(cur) = (start) + SvCUR(cat);		\
765     }						\
766 } STMT_END
767 
768 #define PUSH_GROWING_BYTES(utf8, cat, start, cur, buf, in_len) \
769 STMT_START {					\
770     const STRLEN glen = (in_len);		\
771     STRLEN gl = glen;				\
772     if (utf8) gl *= UTF8_EXPAND;		\
773     if ((cur) + gl >= (start) + SvLEN(cat)) {	\
774         *cur = '\0';				\
775         SvCUR_set((cat), (cur) - (start));	\
776 	(start) = sv_exp_grow(cat, gl);		\
777 	(cur) = (start) + SvCUR(cat);		\
778     }						\
779     PUSH_BYTES(utf8, cur, buf, glen);		\
780 } STMT_END
781 
782 #define PUSH_BYTE(utf8, s, byte)		\
783 STMT_START {					\
784     if (utf8) {					\
785 	const U8 au8 = (byte);			\
786 	(s) = bytes_to_uni(&au8, 1, (s));	\
787     } else *(U8 *)(s)++ = (byte);		\
788 } STMT_END
789 
790 /* Only to be used inside a loop (see the break) */
791 #define NEXT_UNI_VAL(val, cur, str, end, utf8_flags)		\
792 STMT_START {							\
793     STRLEN retlen;						\
794     if (str >= end) break;					\
795     val = utf8n_to_uvchr((U8 *) str, end-str, &retlen, utf8_flags);	\
796     if (retlen == (STRLEN) -1 || retlen == 0) {			\
797 	*cur = '\0';						\
798 	Perl_croak(aTHX_ "Malformed UTF-8 string in pack");	\
799     }								\
800     str += retlen;						\
801 } STMT_END
802 
803 static const char *_action( const tempsym_t* symptr )
804 {
805     return (const char *)(( symptr->flags & FLAG_PACK ) ? "pack" : "unpack");
806 }
807 
808 /* Returns the sizeof() struct described by pat */
809 STATIC I32
810 S_measure_struct(pTHX_ tempsym_t* symptr)
811 {
812     I32 total = 0;
813 
814     PERL_ARGS_ASSERT_MEASURE_STRUCT;
815 
816     while (next_symbol(symptr)) {
817 	I32 len;
818 	int size;
819 
820         switch (symptr->howlen) {
821 	  case e_star:
822    	    Perl_croak(aTHX_ "Within []-length '*' not allowed in %s",
823                         _action( symptr ) );
824             break;
825 	  default:
826 	    /* e_no_len and e_number */
827 	    len = symptr->length;
828 	    break;
829         }
830 
831 	size = packprops[TYPE_NO_ENDIANNESS(symptr->code)] & PACK_SIZE_MASK;
832 	if (!size) {
833             int star;
834 	    /* endianness doesn't influence the size of a type */
835 	    switch(TYPE_NO_ENDIANNESS(symptr->code)) {
836 	    default:
837 		Perl_croak(aTHX_ "Invalid type '%c' in %s",
838 			   (int)TYPE_NO_MODIFIERS(symptr->code),
839                            _action( symptr ) );
840 #ifdef PERL_PACK_CAN_SHRIEKSIGN
841 	    case '.' | TYPE_IS_SHRIEKING:
842 	    case '@' | TYPE_IS_SHRIEKING:
843 #endif
844 	    case '@':
845 	    case '.':
846 	    case '/':
847 	    case 'U':			/* XXXX Is it correct? */
848 	    case 'w':
849 	    case 'u':
850 		Perl_croak(aTHX_ "Within []-length '%c' not allowed in %s",
851 			   (int) TYPE_NO_MODIFIERS(symptr->code),
852                            _action( symptr ) );
853 	    case '%':
854 		size = 0;
855 		break;
856 	    case '(':
857 	    {
858 		tempsym_t savsym = *symptr;
859 		symptr->patptr = savsym.grpbeg;
860 		symptr->patend = savsym.grpend;
861 		/* XXXX Theoretically, we need to measure many times at
862 		   different positions, since the subexpression may contain
863 		   alignment commands, but be not of aligned length.
864 		   Need to detect this and croak().  */
865 		size = measure_struct(symptr);
866 		*symptr = savsym;
867 		break;
868 	    }
869 	    case 'X' | TYPE_IS_SHRIEKING:
870 		/* XXXX Is this useful?  Then need to treat MEASURE_BACKWARDS.
871 		 */
872 		if (!len)		/* Avoid division by 0 */
873 		    len = 1;
874 		len = total % len;	/* Assumed: the start is aligned. */
875 		/* FALL THROUGH */
876 	    case 'X':
877 		size = -1;
878 		if (total < len)
879                     Perl_croak(aTHX_ "'X' outside of string in %s", _action( symptr ) );
880 		break;
881 	    case 'x' | TYPE_IS_SHRIEKING:
882 		if (!len)		/* Avoid division by 0 */
883 		    len = 1;
884 		star = total % len;	/* Assumed: the start is aligned. */
885 		if (star)		/* Other portable ways? */
886 		    len = len - star;
887 		else
888 		    len = 0;
889 		/* FALL THROUGH */
890 	    case 'x':
891 	    case 'A':
892 	    case 'Z':
893 	    case 'a':
894 		size = 1;
895 		break;
896 	    case 'B':
897 	    case 'b':
898 		len = (len + 7)/8;
899 		size = 1;
900 		break;
901 	    case 'H':
902 	    case 'h':
903 		len = (len + 1)/2;
904 		size = 1;
905 		break;
906 
907 	    case 'P':
908 		len = 1;
909 		size = sizeof(char*);
910 		break;
911 	    }
912 	}
913 	total += len * size;
914     }
915     return total;
916 }
917 
918 
919 /* locate matching closing parenthesis or bracket
920  * returns char pointer to char after match, or NULL
921  */
922 STATIC const char *
923 S_group_end(pTHX_ const char *patptr, const char *patend, char ender)
924 {
925     PERL_ARGS_ASSERT_GROUP_END;
926 
927     while (patptr < patend) {
928 	const char c = *patptr++;
929 
930 	if (isSPACE(c))
931 	    continue;
932 	else if (c == ender)
933 	    return patptr-1;
934 	else if (c == '#') {
935 	    while (patptr < patend && *patptr != '\n')
936 		patptr++;
937 	    continue;
938 	} else if (c == '(')
939 	    patptr = group_end(patptr, patend, ')') + 1;
940 	else if (c == '[')
941 	    patptr = group_end(patptr, patend, ']') + 1;
942     }
943     Perl_croak(aTHX_ "No group ending character '%c' found in template",
944                ender);
945     return 0;
946 }
947 
948 
949 /* Convert unsigned decimal number to binary.
950  * Expects a pointer to the first digit and address of length variable
951  * Advances char pointer to 1st non-digit char and returns number
952  */
953 STATIC const char *
954 S_get_num(pTHX_ const char *patptr, I32 *lenptr )
955 {
956   I32 len = *patptr++ - '0';
957 
958   PERL_ARGS_ASSERT_GET_NUM;
959 
960   while (isDIGIT(*patptr)) {
961     if (len >= 0x7FFFFFFF/10)
962       Perl_croak(aTHX_ "pack/unpack repeat count overflow");
963     len = (len * 10) + (*patptr++ - '0');
964   }
965   *lenptr = len;
966   return patptr;
967 }
968 
969 /* The marvellous template parsing routine: Using state stored in *symptr,
970  * locates next template code and count
971  */
972 STATIC bool
973 S_next_symbol(pTHX_ tempsym_t* symptr )
974 {
975   const char* patptr = symptr->patptr;
976   const char* const patend = symptr->patend;
977 
978   PERL_ARGS_ASSERT_NEXT_SYMBOL;
979 
980   symptr->flags &= ~FLAG_SLASH;
981 
982   while (patptr < patend) {
983     if (isSPACE(*patptr))
984       patptr++;
985     else if (*patptr == '#') {
986       patptr++;
987       while (patptr < patend && *patptr != '\n')
988 	patptr++;
989       if (patptr < patend)
990 	patptr++;
991     } else {
992       /* We should have found a template code */
993       I32 code = *patptr++ & 0xFF;
994       U32 inherited_modifiers = 0;
995 
996       if (code == ','){ /* grandfather in commas but with a warning */
997 	if (((symptr->flags & FLAG_COMMA) == 0) && ckWARN(WARN_UNPACK)){
998           symptr->flags |= FLAG_COMMA;
999 	  Perl_warner(aTHX_ packWARN(WARN_UNPACK),
1000 	 	      "Invalid type ',' in %s", _action( symptr ) );
1001         }
1002 	continue;
1003       }
1004 
1005       /* for '(', skip to ')' */
1006       if (code == '(') {
1007         if( isDIGIT(*patptr) || *patptr == '*' || *patptr == '[' )
1008           Perl_croak(aTHX_ "()-group starts with a count in %s",
1009                         _action( symptr ) );
1010         symptr->grpbeg = patptr;
1011         patptr = 1 + ( symptr->grpend = group_end(patptr, patend, ')') );
1012         if( symptr->level >= MAX_SUB_TEMPLATE_LEVEL )
1013 	  Perl_croak(aTHX_ "Too deeply nested ()-groups in %s",
1014                         _action( symptr ) );
1015       }
1016 
1017       /* look for group modifiers to inherit */
1018       if (TYPE_ENDIANNESS(symptr->flags)) {
1019         if (strchr(ENDIANNESS_ALLOWED_TYPES, TYPE_NO_MODIFIERS(code)))
1020           inherited_modifiers |= TYPE_ENDIANNESS(symptr->flags);
1021       }
1022 
1023       /* look for modifiers */
1024       while (patptr < patend) {
1025         const char *allowed;
1026         I32 modifier;
1027         switch (*patptr) {
1028           case '!':
1029             modifier = TYPE_IS_SHRIEKING;
1030             allowed = SHRIEKING_ALLOWED_TYPES;
1031             break;
1032 #ifdef PERL_PACK_CAN_BYTEORDER
1033           case '>':
1034             modifier = TYPE_IS_BIG_ENDIAN;
1035             allowed = ENDIANNESS_ALLOWED_TYPES;
1036             break;
1037           case '<':
1038             modifier = TYPE_IS_LITTLE_ENDIAN;
1039             allowed = ENDIANNESS_ALLOWED_TYPES;
1040             break;
1041 #endif /* PERL_PACK_CAN_BYTEORDER */
1042           default:
1043             allowed = "";
1044             modifier = 0;
1045             break;
1046         }
1047 
1048         if (modifier == 0)
1049           break;
1050 
1051         if (!strchr(allowed, TYPE_NO_MODIFIERS(code)))
1052           Perl_croak(aTHX_ "'%c' allowed only after types %s in %s", *patptr,
1053                         allowed, _action( symptr ) );
1054 
1055         if (TYPE_ENDIANNESS(code | modifier) == TYPE_ENDIANNESS_MASK)
1056           Perl_croak(aTHX_ "Can't use both '<' and '>' after type '%c' in %s",
1057                      (int) TYPE_NO_MODIFIERS(code), _action( symptr ) );
1058         else if (TYPE_ENDIANNESS(code | modifier | inherited_modifiers) ==
1059                  TYPE_ENDIANNESS_MASK)
1060           Perl_croak(aTHX_ "Can't use '%c' in a group with different byte-order in %s",
1061                      *patptr, _action( symptr ) );
1062 
1063         if ((code & modifier)) {
1064 	    Perl_ck_warner(aTHX_ packWARN(WARN_UNPACK),
1065 			   "Duplicate modifier '%c' after '%c' in %s",
1066 			   *patptr, (int) TYPE_NO_MODIFIERS(code),
1067 			   _action( symptr ) );
1068         }
1069 
1070         code |= modifier;
1071         patptr++;
1072       }
1073 
1074       /* inherit modifiers */
1075       code |= inherited_modifiers;
1076 
1077       /* look for count and/or / */
1078       if (patptr < patend) {
1079 	if (isDIGIT(*patptr)) {
1080  	  patptr = get_num( patptr, &symptr->length );
1081           symptr->howlen = e_number;
1082 
1083         } else if (*patptr == '*') {
1084           patptr++;
1085           symptr->howlen = e_star;
1086 
1087         } else if (*patptr == '[') {
1088           const char* lenptr = ++patptr;
1089           symptr->howlen = e_number;
1090           patptr = group_end( patptr, patend, ']' ) + 1;
1091           /* what kind of [] is it? */
1092           if (isDIGIT(*lenptr)) {
1093             lenptr = get_num( lenptr, &symptr->length );
1094             if( *lenptr != ']' )
1095               Perl_croak(aTHX_ "Malformed integer in [] in %s",
1096                             _action( symptr ) );
1097           } else {
1098             tempsym_t savsym = *symptr;
1099             symptr->patend = patptr-1;
1100             symptr->patptr = lenptr;
1101             savsym.length = measure_struct(symptr);
1102             *symptr = savsym;
1103           }
1104         } else {
1105           symptr->howlen = e_no_len;
1106           symptr->length = 1;
1107         }
1108 
1109         /* try to find / */
1110         while (patptr < patend) {
1111           if (isSPACE(*patptr))
1112             patptr++;
1113           else if (*patptr == '#') {
1114             patptr++;
1115             while (patptr < patend && *patptr != '\n')
1116 	      patptr++;
1117             if (patptr < patend)
1118 	      patptr++;
1119           } else {
1120             if (*patptr == '/') {
1121               symptr->flags |= FLAG_SLASH;
1122               patptr++;
1123               if (patptr < patend &&
1124                   (isDIGIT(*patptr) || *patptr == '*' || *patptr == '['))
1125                 Perl_croak(aTHX_ "'/' does not take a repeat count in %s",
1126                             _action( symptr ) );
1127             }
1128             break;
1129 	  }
1130 	}
1131       } else {
1132         /* at end - no count, no / */
1133         symptr->howlen = e_no_len;
1134         symptr->length = 1;
1135       }
1136 
1137       symptr->code = code;
1138       symptr->patptr = patptr;
1139       return TRUE;
1140     }
1141   }
1142   symptr->patptr = patptr;
1143   return FALSE;
1144 }
1145 
1146 /*
1147    There is no way to cleanly handle the case where we should process the
1148    string per byte in its upgraded form while it's really in downgraded form
1149    (e.g. estimates like strend-s as an upper bound for the number of
1150    characters left wouldn't work). So if we foresee the need of this
1151    (pattern starts with U or contains U0), we want to work on the encoded
1152    version of the string. Users are advised to upgrade their pack string
1153    themselves if they need to do a lot of unpacks like this on it
1154 */
1155 STATIC bool
1156 need_utf8(const char *pat, const char *patend)
1157 {
1158     bool first = TRUE;
1159 
1160     PERL_ARGS_ASSERT_NEED_UTF8;
1161 
1162     while (pat < patend) {
1163 	if (pat[0] == '#') {
1164 	    pat++;
1165 	    pat = (const char *) memchr(pat, '\n', patend-pat);
1166 	    if (!pat) return FALSE;
1167 	} else if (pat[0] == 'U') {
1168 	    if (first || pat[1] == '0') return TRUE;
1169 	} else first = FALSE;
1170 	pat++;
1171     }
1172     return FALSE;
1173 }
1174 
1175 STATIC char
1176 first_symbol(const char *pat, const char *patend) {
1177     PERL_ARGS_ASSERT_FIRST_SYMBOL;
1178 
1179     while (pat < patend) {
1180 	if (pat[0] != '#') return pat[0];
1181 	pat++;
1182 	pat = (const char *) memchr(pat, '\n', patend-pat);
1183 	if (!pat) return 0;
1184 	pat++;
1185     }
1186     return 0;
1187 }
1188 
1189 /*
1190 =for apidoc unpackstring
1191 
1192 The engine implementing the unpack() Perl function.
1193 
1194 Using the template pat..patend, this function unpacks the string
1195 s..strend into a number of mortal SVs, which it pushes onto the perl
1196 argument (@_) stack (so you will need to issue a C<PUTBACK> before and
1197 C<SPAGAIN> after the call to this function). It returns the number of
1198 pushed elements.
1199 
1200 The strend and patend pointers should point to the byte following the last
1201 character of each string.
1202 
1203 Although this function returns its values on the perl argument stack, it
1204 doesn't take any parameters from that stack (and thus in particular
1205 there's no need to do a PUSHMARK before calling it, unlike L</call_pv> for
1206 example).
1207 
1208 =cut */
1209 
1210 I32
1211 Perl_unpackstring(pTHX_ const char *pat, const char *patend, const char *s, const char *strend, U32 flags)
1212 {
1213     tempsym_t sym;
1214 
1215     PERL_ARGS_ASSERT_UNPACKSTRING;
1216 
1217     if (flags & FLAG_DO_UTF8) flags |= FLAG_WAS_UTF8;
1218     else if (need_utf8(pat, patend)) {
1219 	/* We probably should try to avoid this in case a scalar context call
1220 	   wouldn't get to the "U0" */
1221 	STRLEN len = strend - s;
1222 	s = (char *) bytes_to_utf8((U8 *) s, &len);
1223 	SAVEFREEPV(s);
1224 	strend = s + len;
1225 	flags |= FLAG_DO_UTF8;
1226     }
1227 
1228     if (first_symbol(pat, patend) != 'U' && (flags & FLAG_DO_UTF8))
1229 	flags |= FLAG_PARSE_UTF8;
1230 
1231     TEMPSYM_INIT(&sym, pat, patend, flags);
1232 
1233     return unpack_rec(&sym, s, s, strend, NULL );
1234 }
1235 
1236 STATIC I32
1237 S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const char *strend, const char **new_s )
1238 {
1239     dVAR; dSP;
1240     SV *sv = NULL;
1241     const I32 start_sp_offset = SP - PL_stack_base;
1242     howlen_t howlen;
1243     I32 checksum = 0;
1244     UV cuv = 0;
1245     NV cdouble = 0.0;
1246     const int bits_in_uv = CHAR_BIT * sizeof(cuv);
1247     bool beyond = FALSE;
1248     bool explicit_length;
1249     const bool unpack_only_one = (symptr->flags & FLAG_UNPACK_ONLY_ONE) != 0;
1250     bool utf8 = (symptr->flags & FLAG_PARSE_UTF8) ? 1 : 0;
1251 
1252     PERL_ARGS_ASSERT_UNPACK_REC;
1253 
1254     symptr->strbeg = s - strbeg;
1255 
1256     while (next_symbol(symptr)) {
1257 	packprops_t props;
1258 	I32 len;
1259         I32 datumtype = symptr->code;
1260 	/* do first one only unless in list context
1261 	   / is implemented by unpacking the count, then popping it from the
1262 	   stack, so must check that we're not in the middle of a /  */
1263         if ( unpack_only_one
1264 	     && (SP - PL_stack_base == start_sp_offset + 1)
1265 	     && (datumtype != '/') )   /* XXX can this be omitted */
1266             break;
1267 
1268         switch (howlen = symptr->howlen) {
1269 	  case e_star:
1270 	    len = strend - strbeg;	/* long enough */
1271 	    break;
1272 	  default:
1273 	    /* e_no_len and e_number */
1274 	    len = symptr->length;
1275 	    break;
1276         }
1277 
1278         explicit_length = TRUE;
1279       redo_switch:
1280         beyond = s >= strend;
1281 
1282 	props = packprops[TYPE_NO_ENDIANNESS(datumtype)];
1283 	if (props) {
1284 	    /* props nonzero means we can process this letter. */
1285             const long size = props & PACK_SIZE_MASK;
1286             const long howmany = (strend - s) / size;
1287 	    if (len > howmany)
1288 		len = howmany;
1289 
1290 	    if (!checksum || (props & PACK_SIZE_CANNOT_CSUM)) {
1291 		if (len && unpack_only_one) len = 1;
1292 		EXTEND(SP, len);
1293 		EXTEND_MORTAL(len);
1294 	    }
1295 	}
1296 
1297 	switch(TYPE_NO_ENDIANNESS(datumtype)) {
1298 	default:
1299 	    Perl_croak(aTHX_ "Invalid type '%c' in unpack", (int)TYPE_NO_MODIFIERS(datumtype) );
1300 
1301 	case '%':
1302 	    if (howlen == e_no_len)
1303 		len = 16;		/* len is not specified */
1304 	    checksum = len;
1305 	    cuv = 0;
1306 	    cdouble = 0;
1307 	    continue;
1308 	    break;
1309 	case '(':
1310 	{
1311             tempsym_t savsym = *symptr;
1312             const U32 group_modifiers = TYPE_MODIFIERS(datumtype & ~symptr->flags);
1313 	    symptr->flags |= group_modifiers;
1314             symptr->patend = savsym.grpend;
1315 	    symptr->previous = &savsym;
1316             symptr->level++;
1317 	    PUTBACK;
1318 	    if (len && unpack_only_one) len = 1;
1319 	    while (len--) {
1320   	        symptr->patptr = savsym.grpbeg;
1321 		if (utf8) symptr->flags |=  FLAG_PARSE_UTF8;
1322 		else      symptr->flags &= ~FLAG_PARSE_UTF8;
1323  	        unpack_rec(symptr, s, strbeg, strend, &s);
1324                 if (s == strend && savsym.howlen == e_star)
1325 		    break; /* No way to continue */
1326 	    }
1327 	    SPAGAIN;
1328             savsym.flags = symptr->flags & ~group_modifiers;
1329             *symptr = savsym;
1330 	    break;
1331 	}
1332 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1333 	case '.' | TYPE_IS_SHRIEKING:
1334 #endif
1335 	case '.': {
1336 	    const char *from;
1337 	    SV *sv;
1338 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1339 	    const bool u8 = utf8 && !(datumtype & TYPE_IS_SHRIEKING);
1340 #else /* PERL_PACK_CAN_SHRIEKSIGN */
1341 	    const bool u8 = utf8;
1342 #endif
1343 	    if (howlen == e_star) from = strbeg;
1344 	    else if (len <= 0) from = s;
1345 	    else {
1346 		tempsym_t *group = symptr;
1347 
1348 		while (--len && group) group = group->previous;
1349 		from = group ? strbeg + group->strbeg : strbeg;
1350 	    }
1351 	    sv = from <= s ?
1352 		newSVuv(  u8 ? (UV) utf8_length((const U8*)from, (const U8*)s) : (UV) (s-from)) :
1353 		newSViv(-(u8 ? (IV) utf8_length((const U8*)s, (const U8*)from) : (IV) (from-s)));
1354 	    mXPUSHs(sv);
1355 	    break;
1356 	}
1357 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1358 	case '@' | TYPE_IS_SHRIEKING:
1359 #endif
1360 	case '@':
1361 	    s = strbeg + symptr->strbeg;
1362 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1363 	    if (utf8  && !(datumtype & TYPE_IS_SHRIEKING))
1364 #else /* PERL_PACK_CAN_SHRIEKSIGN */
1365 	    if (utf8)
1366 #endif
1367 	    {
1368 		while (len > 0) {
1369 		    if (s >= strend)
1370 			Perl_croak(aTHX_ "'@' outside of string in unpack");
1371 		    s += UTF8SKIP(s);
1372 		    len--;
1373 		}
1374 		if (s > strend)
1375 		    Perl_croak(aTHX_ "'@' outside of string with malformed UTF-8 in unpack");
1376 	    } else {
1377 		if (strend-s < len)
1378 		    Perl_croak(aTHX_ "'@' outside of string in unpack");
1379 		s += len;
1380 	    }
1381 	    break;
1382  	case 'X' | TYPE_IS_SHRIEKING:
1383  	    if (!len)			/* Avoid division by 0 */
1384  		len = 1;
1385 	    if (utf8) {
1386 		const char *hop, *last;
1387 		I32 l = len;
1388 		hop = last = strbeg;
1389 		while (hop < s) {
1390 		    hop += UTF8SKIP(hop);
1391 		    if (--l == 0) {
1392 			last = hop;
1393 			l = len;
1394 		    }
1395 		}
1396 		if (last > s)
1397 		    Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1398 		s = last;
1399 		break;
1400 	    }
1401 	    len = (s - strbeg) % len;
1402  	    /* FALL THROUGH */
1403 	case 'X':
1404 	    if (utf8) {
1405 		while (len > 0) {
1406 		    if (s <= strbeg)
1407 			Perl_croak(aTHX_ "'X' outside of string in unpack");
1408 		    while (--s, UTF8_IS_CONTINUATION(*s)) {
1409 			if (s <= strbeg)
1410 			    Perl_croak(aTHX_ "'X' outside of string in unpack");
1411 		    }
1412 		    len--;
1413 		}
1414 	    } else {
1415 		if (len > s - strbeg)
1416 		    Perl_croak(aTHX_ "'X' outside of string in unpack" );
1417 		s -= len;
1418 	    }
1419 	    break;
1420  	case 'x' | TYPE_IS_SHRIEKING: {
1421             I32 ai32;
1422  	    if (!len)			/* Avoid division by 0 */
1423  		len = 1;
1424 	    if (utf8) ai32 = utf8_length((U8 *) strbeg, (U8 *) s) % len;
1425 	    else      ai32 = (s - strbeg)                         % len;
1426 	    if (ai32 == 0) break;
1427 	    len -= ai32;
1428             }
1429  	    /* FALL THROUGH */
1430 	case 'x':
1431 	    if (utf8) {
1432 		while (len>0) {
1433 		    if (s >= strend)
1434 			Perl_croak(aTHX_ "'x' outside of string in unpack");
1435 		    s += UTF8SKIP(s);
1436 		    len--;
1437 		}
1438 	    } else {
1439 		if (len > strend - s)
1440 		    Perl_croak(aTHX_ "'x' outside of string in unpack");
1441 		s += len;
1442 	    }
1443 	    break;
1444 	case '/':
1445 	    Perl_croak(aTHX_ "'/' must follow a numeric type in unpack");
1446             break;
1447 	case 'A':
1448 	case 'Z':
1449 	case 'a':
1450 	    if (checksum) {
1451 		/* Preliminary length estimate is assumed done in 'W' */
1452 		if (len > strend - s) len = strend - s;
1453 		goto W_checksum;
1454 	    }
1455 	    if (utf8) {
1456 		I32 l;
1457 		const char *hop;
1458 		for (l=len, hop=s; l>0; l--, hop += UTF8SKIP(hop)) {
1459 		    if (hop >= strend) {
1460 			if (hop > strend)
1461 			    Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1462 			break;
1463 		    }
1464 		}
1465 		if (hop > strend)
1466 		    Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1467 		len = hop - s;
1468 	    } else if (len > strend - s)
1469 		len = strend - s;
1470 
1471 	    if (datumtype == 'Z') {
1472 		/* 'Z' strips stuff after first null */
1473 		const char *ptr, *end;
1474 		end = s + len;
1475 		for (ptr = s; ptr < end; ptr++) if (*ptr == 0) break;
1476 		sv = newSVpvn(s, ptr-s);
1477 		if (howlen == e_star) /* exact for 'Z*' */
1478 		    len = ptr-s + (ptr != strend ? 1 : 0);
1479 	    } else if (datumtype == 'A') {
1480 		/* 'A' strips both nulls and spaces */
1481 		const char *ptr;
1482 		if (utf8 && (symptr->flags & FLAG_WAS_UTF8)) {
1483 		    for (ptr = s+len-1; ptr >= s; ptr--)
1484 			if (*ptr != 0 && !UTF8_IS_CONTINUATION(*ptr) &&
1485 			    !isSPACE_utf8(ptr)) break;
1486 		    if (ptr >= s) ptr += UTF8SKIP(ptr);
1487 		    else ptr++;
1488 		    if (ptr > s+len)
1489 			Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1490 		} else {
1491 		    for (ptr = s+len-1; ptr >= s; ptr--)
1492 			if (*ptr != 0 && !isSPACE(*ptr)) break;
1493 		    ptr++;
1494 		}
1495 		sv = newSVpvn(s, ptr-s);
1496 	    } else sv = newSVpvn(s, len);
1497 
1498 	    if (utf8) {
1499 		SvUTF8_on(sv);
1500 		/* Undo any upgrade done due to need_utf8() */
1501 		if (!(symptr->flags & FLAG_WAS_UTF8))
1502 		    sv_utf8_downgrade(sv, 0);
1503 	    }
1504 	    mXPUSHs(sv);
1505 	    s += len;
1506 	    break;
1507 	case 'B':
1508 	case 'b': {
1509 	    char *str;
1510 	    if (howlen == e_star || len > (strend - s) * 8)
1511 		len = (strend - s) * 8;
1512 	    if (checksum) {
1513 		if (utf8)
1514 		    while (len >= 8 && s < strend) {
1515 			cuv += PL_bitcount[uni_to_byte(aTHX_ &s, strend, datumtype)];
1516 			len -= 8;
1517 		    }
1518 		else
1519 		    while (len >= 8) {
1520 			cuv += PL_bitcount[*(U8 *)s++];
1521 			len -= 8;
1522 		    }
1523 		if (len && s < strend) {
1524 		    U8 bits;
1525 		    bits = SHIFT_BYTE(utf8, s, strend, datumtype);
1526 		    if (datumtype == 'b')
1527 			while (len-- > 0) {
1528 			    if (bits & 1) cuv++;
1529 			    bits >>= 1;
1530 			}
1531 		    else
1532 			while (len-- > 0) {
1533 			    if (bits & 0x80) cuv++;
1534 			    bits <<= 1;
1535 			}
1536 		}
1537 		break;
1538 	    }
1539 
1540 	    sv = sv_2mortal(newSV(len ? len : 1));
1541 	    SvPOK_on(sv);
1542 	    str = SvPVX(sv);
1543 	    if (datumtype == 'b') {
1544 		U8 bits = 0;
1545 		const I32 ai32 = len;
1546 		for (len = 0; len < ai32; len++) {
1547 		    if (len & 7) bits >>= 1;
1548 		    else if (utf8) {
1549 			if (s >= strend) break;
1550 			bits = uni_to_byte(aTHX_ &s, strend, datumtype);
1551 		    } else bits = *(U8 *) s++;
1552 		    *str++ = bits & 1 ? '1' : '0';
1553 		}
1554 	    } else {
1555 		U8 bits = 0;
1556 		const I32 ai32 = len;
1557 		for (len = 0; len < ai32; len++) {
1558 		    if (len & 7) bits <<= 1;
1559 		    else if (utf8) {
1560 			if (s >= strend) break;
1561 			bits = uni_to_byte(aTHX_ &s, strend, datumtype);
1562 		    } else bits = *(U8 *) s++;
1563 		    *str++ = bits & 0x80 ? '1' : '0';
1564 		}
1565 	    }
1566 	    *str = '\0';
1567 	    SvCUR_set(sv, str - SvPVX_const(sv));
1568 	    XPUSHs(sv);
1569 	    break;
1570 	}
1571 	case 'H':
1572 	case 'h': {
1573 	    char *str = NULL;
1574 	    /* Preliminary length estimate, acceptable for utf8 too */
1575 	    if (howlen == e_star || len > (strend - s) * 2)
1576 		len = (strend - s) * 2;
1577 	    if (!checksum) {
1578 		sv = sv_2mortal(newSV(len ? len : 1));
1579 		SvPOK_on(sv);
1580 		str = SvPVX(sv);
1581 	    }
1582 	    if (datumtype == 'h') {
1583 		U8 bits = 0;
1584 		I32 ai32 = len;
1585 		for (len = 0; len < ai32; len++) {
1586 		    if (len & 1) bits >>= 4;
1587 		    else if (utf8) {
1588 			if (s >= strend) break;
1589 			bits = uni_to_byte(aTHX_ &s, strend, datumtype);
1590 		    } else bits = * (U8 *) s++;
1591 		    if (!checksum)
1592 			*str++ = PL_hexdigit[bits & 15];
1593 		}
1594 	    } else {
1595 		U8 bits = 0;
1596 		const I32 ai32 = len;
1597 		for (len = 0; len < ai32; len++) {
1598 		    if (len & 1) bits <<= 4;
1599 		    else if (utf8) {
1600 			if (s >= strend) break;
1601 			bits = uni_to_byte(aTHX_ &s, strend, datumtype);
1602 		    } else bits = *(U8 *) s++;
1603 		    if (!checksum)
1604 			*str++ = PL_hexdigit[(bits >> 4) & 15];
1605 		}
1606 	    }
1607 	    if (!checksum) {
1608 		*str = '\0';
1609 		SvCUR_set(sv, str - SvPVX_const(sv));
1610 		XPUSHs(sv);
1611 	    }
1612 	    break;
1613 	}
1614 	case 'C':
1615             if (len == 0) {
1616                 if (explicit_length)
1617 		    /* Switch to "character" mode */
1618 		    utf8 = (symptr->flags & FLAG_DO_UTF8) ? 1 : 0;
1619 		break;
1620 	    }
1621 	    /* FALL THROUGH */
1622 	case 'c':
1623 	    while (len-- > 0 && s < strend) {
1624 		int aint;
1625 		if (utf8)
1626 		  {
1627 		    STRLEN retlen;
1628 		    aint = utf8n_to_uvchr((U8 *) s, strend-s, &retlen,
1629 				 ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
1630 		    if (retlen == (STRLEN) -1 || retlen == 0)
1631 			Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1632 		    s += retlen;
1633 		  }
1634 		else
1635 		  aint = *(U8 *)(s)++;
1636 		if (aint >= 128 && datumtype != 'C')	/* fake up signed chars */
1637 		    aint -= 256;
1638 		if (!checksum)
1639 		    mPUSHi(aint);
1640 		else if (checksum > bits_in_uv)
1641 		    cdouble += (NV)aint;
1642 		else
1643 		    cuv += aint;
1644 	    }
1645 	    break;
1646 	case 'W':
1647 	  W_checksum:
1648 	    if (utf8) {
1649 		while (len-- > 0 && s < strend) {
1650 		    STRLEN retlen;
1651 		    const UV val = utf8n_to_uvchr((U8 *) s, strend-s, &retlen,
1652 					 ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
1653 		    if (retlen == (STRLEN) -1 || retlen == 0)
1654 			Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1655 		    s += retlen;
1656 		    if (!checksum)
1657 			mPUSHu(val);
1658 		    else if (checksum > bits_in_uv)
1659 			cdouble += (NV) val;
1660 		    else
1661 			cuv += val;
1662 		}
1663 	    } else if (!checksum)
1664 		while (len-- > 0) {
1665 		    const U8 ch = *(U8 *) s++;
1666 		    mPUSHu(ch);
1667 	    }
1668 	    else if (checksum > bits_in_uv)
1669 		while (len-- > 0) cdouble += (NV) *(U8 *) s++;
1670 	    else
1671 		while (len-- > 0) cuv += *(U8 *) s++;
1672 	    break;
1673 	case 'U':
1674 	    if (len == 0) {
1675                 if (explicit_length && howlen != e_star) {
1676 		    /* Switch to "bytes in UTF-8" mode */
1677 		    if (symptr->flags & FLAG_DO_UTF8) utf8 = 0;
1678 		    else
1679 			/* Should be impossible due to the need_utf8() test */
1680 			Perl_croak(aTHX_ "U0 mode on a byte string");
1681 		}
1682 		break;
1683 	    }
1684 	    if (len > strend - s) len = strend - s;
1685 	    if (!checksum) {
1686 		if (len && unpack_only_one) len = 1;
1687 		EXTEND(SP, len);
1688 		EXTEND_MORTAL(len);
1689 	    }
1690 	    while (len-- > 0 && s < strend) {
1691 		STRLEN retlen;
1692 		UV auv;
1693 		if (utf8) {
1694 		    U8 result[UTF8_MAXLEN];
1695 		    const char *ptr = s;
1696 		    STRLEN len;
1697 		    /* Bug: warns about bad utf8 even if we are short on bytes
1698 		       and will break out of the loop */
1699 		    if (!uni_to_bytes(aTHX_ &ptr, strend, (char *) result, 1,
1700 				      'U'))
1701 			break;
1702 		    len = UTF8SKIP(result);
1703 		    if (!uni_to_bytes(aTHX_ &ptr, strend,
1704 				      (char *) &result[1], len-1, 'U')) break;
1705 		    auv = utf8n_to_uvuni(result, len, &retlen, UTF8_ALLOW_DEFAULT);
1706 		    s = ptr;
1707 		} else {
1708 		    auv = utf8n_to_uvuni((U8*)s, strend - s, &retlen, UTF8_ALLOW_DEFAULT);
1709 		    if (retlen == (STRLEN) -1 || retlen == 0)
1710 			Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
1711 		    s += retlen;
1712 		}
1713 		if (!checksum)
1714 		    mPUSHu(auv);
1715 		else if (checksum > bits_in_uv)
1716 		    cdouble += (NV) auv;
1717 		else
1718 		    cuv += auv;
1719 	    }
1720 	    break;
1721 	case 's' | TYPE_IS_SHRIEKING:
1722 #if SHORTSIZE != SIZE16
1723 	    while (len-- > 0) {
1724 		short ashort;
1725 		SHIFT_VAR(utf8, s, strend, ashort, datumtype);
1726 		DO_BO_UNPACK(ashort, s);
1727 		if (!checksum)
1728 		    mPUSHi(ashort);
1729 		else if (checksum > bits_in_uv)
1730 		    cdouble += (NV)ashort;
1731 		else
1732 		    cuv += ashort;
1733 	    }
1734 	    break;
1735 #else
1736 	    /* Fallthrough! */
1737 #endif
1738 	case 's':
1739 	    while (len-- > 0) {
1740 		I16 ai16;
1741 
1742 #if U16SIZE > SIZE16
1743 		ai16 = 0;
1744 #endif
1745 		SHIFT16(utf8, s, strend, &ai16, datumtype);
1746 		DO_BO_UNPACK(ai16, 16);
1747 #if U16SIZE > SIZE16
1748 		if (ai16 > 32767)
1749 		    ai16 -= 65536;
1750 #endif
1751 		if (!checksum)
1752 		    mPUSHi(ai16);
1753 		else if (checksum > bits_in_uv)
1754 		    cdouble += (NV)ai16;
1755 		else
1756 		    cuv += ai16;
1757 	    }
1758 	    break;
1759 	case 'S' | TYPE_IS_SHRIEKING:
1760 #if SHORTSIZE != SIZE16
1761 	    while (len-- > 0) {
1762 		unsigned short aushort;
1763 		SHIFT_VAR(utf8, s, strend, aushort, datumtype);
1764 		DO_BO_UNPACK(aushort, s);
1765 		if (!checksum)
1766 		    mPUSHu(aushort);
1767 		else if (checksum > bits_in_uv)
1768 		    cdouble += (NV)aushort;
1769 		else
1770 		    cuv += aushort;
1771 	    }
1772 	    break;
1773 #else
1774             /* Fallthrough! */
1775 #endif
1776 	case 'v':
1777 	case 'n':
1778 	case 'S':
1779 	    while (len-- > 0) {
1780 		U16 au16;
1781 #if U16SIZE > SIZE16
1782 		au16 = 0;
1783 #endif
1784 		SHIFT16(utf8, s, strend, &au16, datumtype);
1785 		DO_BO_UNPACK(au16, 16);
1786 #ifdef HAS_NTOHS
1787 		if (datumtype == 'n')
1788 		    au16 = PerlSock_ntohs(au16);
1789 #endif
1790 #ifdef HAS_VTOHS
1791 		if (datumtype == 'v')
1792 		    au16 = vtohs(au16);
1793 #endif
1794 		if (!checksum)
1795 		    mPUSHu(au16);
1796 		else if (checksum > bits_in_uv)
1797 		    cdouble += (NV) au16;
1798 		else
1799 		    cuv += au16;
1800 	    }
1801 	    break;
1802 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1803 	case 'v' | TYPE_IS_SHRIEKING:
1804 	case 'n' | TYPE_IS_SHRIEKING:
1805 	    while (len-- > 0) {
1806 		I16 ai16;
1807 # if U16SIZE > SIZE16
1808 		ai16 = 0;
1809 # endif
1810 		SHIFT16(utf8, s, strend, &ai16, datumtype);
1811 # ifdef HAS_NTOHS
1812 		if (datumtype == ('n' | TYPE_IS_SHRIEKING))
1813 		    ai16 = (I16) PerlSock_ntohs((U16) ai16);
1814 # endif /* HAS_NTOHS */
1815 # ifdef HAS_VTOHS
1816 		if (datumtype == ('v' | TYPE_IS_SHRIEKING))
1817 		    ai16 = (I16) vtohs((U16) ai16);
1818 # endif /* HAS_VTOHS */
1819 		if (!checksum)
1820 		    mPUSHi(ai16);
1821 		else if (checksum > bits_in_uv)
1822 		    cdouble += (NV) ai16;
1823 		else
1824 		    cuv += ai16;
1825 	    }
1826 	    break;
1827 #endif /* PERL_PACK_CAN_SHRIEKSIGN */
1828 	case 'i':
1829 	case 'i' | TYPE_IS_SHRIEKING:
1830 	    while (len-- > 0) {
1831 		int aint;
1832 		SHIFT_VAR(utf8, s, strend, aint, datumtype);
1833 		DO_BO_UNPACK(aint, i);
1834 		if (!checksum)
1835 		    mPUSHi(aint);
1836 		else if (checksum > bits_in_uv)
1837 		    cdouble += (NV)aint;
1838 		else
1839 		    cuv += aint;
1840 	    }
1841 	    break;
1842 	case 'I':
1843 	case 'I' | TYPE_IS_SHRIEKING:
1844 	    while (len-- > 0) {
1845 		unsigned int auint;
1846 		SHIFT_VAR(utf8, s, strend, auint, datumtype);
1847 		DO_BO_UNPACK(auint, i);
1848 		if (!checksum)
1849 		    mPUSHu(auint);
1850 		else if (checksum > bits_in_uv)
1851 		    cdouble += (NV)auint;
1852 		else
1853 		    cuv += auint;
1854 	    }
1855 	    break;
1856 	case 'j':
1857 	    while (len-- > 0) {
1858 		IV aiv;
1859 		SHIFT_VAR(utf8, s, strend, aiv, datumtype);
1860 #if IVSIZE == INTSIZE
1861 		DO_BO_UNPACK(aiv, i);
1862 #elif IVSIZE == LONGSIZE
1863 		DO_BO_UNPACK(aiv, l);
1864 #elif defined(HAS_QUAD) && IVSIZE == U64SIZE
1865 		DO_BO_UNPACK(aiv, 64);
1866 #else
1867 		Perl_croak(aTHX_ "'j' not supported on this platform");
1868 #endif
1869 		if (!checksum)
1870 		    mPUSHi(aiv);
1871 		else if (checksum > bits_in_uv)
1872 		    cdouble += (NV)aiv;
1873 		else
1874 		    cuv += aiv;
1875 	    }
1876 	    break;
1877 	case 'J':
1878 	    while (len-- > 0) {
1879 		UV auv;
1880 		SHIFT_VAR(utf8, s, strend, auv, datumtype);
1881 #if IVSIZE == INTSIZE
1882 		DO_BO_UNPACK(auv, i);
1883 #elif IVSIZE == LONGSIZE
1884 		DO_BO_UNPACK(auv, l);
1885 #elif defined(HAS_QUAD) && IVSIZE == U64SIZE
1886 		DO_BO_UNPACK(auv, 64);
1887 #else
1888 		Perl_croak(aTHX_ "'J' not supported on this platform");
1889 #endif
1890 		if (!checksum)
1891 		    mPUSHu(auv);
1892 		else if (checksum > bits_in_uv)
1893 		    cdouble += (NV)auv;
1894 		else
1895 		    cuv += auv;
1896 	    }
1897 	    break;
1898 	case 'l' | TYPE_IS_SHRIEKING:
1899 #if LONGSIZE != SIZE32
1900 	    while (len-- > 0) {
1901 		long along;
1902 		SHIFT_VAR(utf8, s, strend, along, datumtype);
1903 		DO_BO_UNPACK(along, l);
1904 		if (!checksum)
1905 		    mPUSHi(along);
1906 		else if (checksum > bits_in_uv)
1907 		    cdouble += (NV)along;
1908 		else
1909 		    cuv += along;
1910 	    }
1911 	    break;
1912 #else
1913 	    /* Fallthrough! */
1914 #endif
1915 	case 'l':
1916 	    while (len-- > 0) {
1917 		I32 ai32;
1918 #if U32SIZE > SIZE32
1919 		ai32 = 0;
1920 #endif
1921 		SHIFT32(utf8, s, strend, &ai32, datumtype);
1922 		DO_BO_UNPACK(ai32, 32);
1923 #if U32SIZE > SIZE32
1924 		if (ai32 > 2147483647) ai32 -= 4294967296;
1925 #endif
1926 		if (!checksum)
1927 		    mPUSHi(ai32);
1928 		else if (checksum > bits_in_uv)
1929 		    cdouble += (NV)ai32;
1930 		else
1931 		    cuv += ai32;
1932 	    }
1933 	    break;
1934 	case 'L' | TYPE_IS_SHRIEKING:
1935 #if LONGSIZE != SIZE32
1936 	    while (len-- > 0) {
1937 		unsigned long aulong;
1938 		SHIFT_VAR(utf8, s, strend, aulong, datumtype);
1939 		DO_BO_UNPACK(aulong, l);
1940 		if (!checksum)
1941 		    mPUSHu(aulong);
1942 		else if (checksum > bits_in_uv)
1943 		    cdouble += (NV)aulong;
1944 		else
1945 		    cuv += aulong;
1946 	    }
1947 	    break;
1948 #else
1949             /* Fall through! */
1950 #endif
1951 	case 'V':
1952 	case 'N':
1953 	case 'L':
1954 	    while (len-- > 0) {
1955 		U32 au32;
1956 #if U32SIZE > SIZE32
1957 		au32 = 0;
1958 #endif
1959 		SHIFT32(utf8, s, strend, &au32, datumtype);
1960 		DO_BO_UNPACK(au32, 32);
1961 #ifdef HAS_NTOHL
1962 		if (datumtype == 'N')
1963 		    au32 = PerlSock_ntohl(au32);
1964 #endif
1965 #ifdef HAS_VTOHL
1966 		if (datumtype == 'V')
1967 		    au32 = vtohl(au32);
1968 #endif
1969 		if (!checksum)
1970 		    mPUSHu(au32);
1971 		else if (checksum > bits_in_uv)
1972 		    cdouble += (NV)au32;
1973 		else
1974 		    cuv += au32;
1975 	    }
1976 	    break;
1977 #ifdef PERL_PACK_CAN_SHRIEKSIGN
1978 	case 'V' | TYPE_IS_SHRIEKING:
1979 	case 'N' | TYPE_IS_SHRIEKING:
1980 	    while (len-- > 0) {
1981 		I32 ai32;
1982 # if U32SIZE > SIZE32
1983 		ai32 = 0;
1984 # endif
1985 		SHIFT32(utf8, s, strend, &ai32, datumtype);
1986 # ifdef HAS_NTOHL
1987 		if (datumtype == ('N' | TYPE_IS_SHRIEKING))
1988 		    ai32 = (I32)PerlSock_ntohl((U32)ai32);
1989 # endif
1990 # ifdef HAS_VTOHL
1991 		if (datumtype == ('V' | TYPE_IS_SHRIEKING))
1992 		    ai32 = (I32)vtohl((U32)ai32);
1993 # endif
1994 		if (!checksum)
1995 		    mPUSHi(ai32);
1996 		else if (checksum > bits_in_uv)
1997 		    cdouble += (NV)ai32;
1998 		else
1999 		    cuv += ai32;
2000 	    }
2001 	    break;
2002 #endif /* PERL_PACK_CAN_SHRIEKSIGN */
2003 	case 'p':
2004 	    while (len-- > 0) {
2005 		const char *aptr;
2006 		SHIFT_VAR(utf8, s, strend, aptr, datumtype);
2007 		DO_BO_UNPACK_PC(aptr);
2008 		/* newSVpv generates undef if aptr is NULL */
2009 		mPUSHs(newSVpv(aptr, 0));
2010 	    }
2011 	    break;
2012 	case 'w':
2013 	    {
2014 		UV auv = 0;
2015 		U32 bytes = 0;
2016 
2017 		while (len > 0 && s < strend) {
2018 		    U8 ch;
2019 		    ch = SHIFT_BYTE(utf8, s, strend, datumtype);
2020 		    auv = (auv << 7) | (ch & 0x7f);
2021 		    /* UTF8_IS_XXXXX not right here - using constant 0x80 */
2022 		    if (ch < 0x80) {
2023 			bytes = 0;
2024 			mPUSHu(auv);
2025 			len--;
2026 			auv = 0;
2027 			continue;
2028 		    }
2029 		    if (++bytes >= sizeof(UV)) {	/* promote to string */
2030 			const char *t;
2031 
2032 			sv = Perl_newSVpvf(aTHX_ "%.*"UVuf, (int)TYPE_DIGITS(UV), auv);
2033 			while (s < strend) {
2034 			    ch = SHIFT_BYTE(utf8, s, strend, datumtype);
2035 			    sv = mul128(sv, (U8)(ch & 0x7f));
2036 			    if (!(ch & 0x80)) {
2037 				bytes = 0;
2038 				break;
2039 			    }
2040 			}
2041 			t = SvPV_nolen_const(sv);
2042 			while (*t == '0')
2043 			    t++;
2044 			sv_chop(sv, t);
2045 			mPUSHs(sv);
2046 			len--;
2047 			auv = 0;
2048 		    }
2049 		}
2050 		if ((s >= strend) && bytes)
2051 		    Perl_croak(aTHX_ "Unterminated compressed integer in unpack");
2052 	    }
2053 	    break;
2054 	case 'P':
2055 	    if (symptr->howlen == e_star)
2056 	        Perl_croak(aTHX_ "'P' must have an explicit size in unpack");
2057 	    EXTEND(SP, 1);
2058 	    if (s + sizeof(char*) <= strend) {
2059 		char *aptr;
2060 		SHIFT_VAR(utf8, s, strend, aptr, datumtype);
2061 		DO_BO_UNPACK_PC(aptr);
2062 		/* newSVpvn generates undef if aptr is NULL */
2063 		PUSHs(newSVpvn_flags(aptr, len, SVs_TEMP));
2064 	    }
2065 	    break;
2066 #ifdef HAS_QUAD
2067 	case 'q':
2068 	    while (len-- > 0) {
2069 		Quad_t aquad;
2070 		SHIFT_VAR(utf8, s, strend, aquad, datumtype);
2071 		DO_BO_UNPACK(aquad, 64);
2072 		if (!checksum)
2073                     mPUSHs(aquad >= IV_MIN && aquad <= IV_MAX ?
2074 			   newSViv((IV)aquad) : newSVnv((NV)aquad));
2075 		else if (checksum > bits_in_uv)
2076 		    cdouble += (NV)aquad;
2077 		else
2078 		    cuv += aquad;
2079 	    }
2080 	    break;
2081 	case 'Q':
2082 	    while (len-- > 0) {
2083 		Uquad_t auquad;
2084 		SHIFT_VAR(utf8, s, strend, auquad, datumtype);
2085 		DO_BO_UNPACK(auquad, 64);
2086 		if (!checksum)
2087 		    mPUSHs(auquad <= UV_MAX ?
2088 			   newSVuv((UV)auquad) : newSVnv((NV)auquad));
2089 		else if (checksum > bits_in_uv)
2090 		    cdouble += (NV)auquad;
2091 		else
2092 		    cuv += auquad;
2093 	    }
2094 	    break;
2095 #endif /* HAS_QUAD */
2096 	/* float and double added gnb@melba.bby.oz.au 22/11/89 */
2097 	case 'f':
2098 	    while (len-- > 0) {
2099 		float afloat;
2100 		SHIFT_VAR(utf8, s, strend, afloat, datumtype);
2101 		DO_BO_UNPACK_N(afloat, float);
2102 		if (!checksum)
2103 		    mPUSHn(afloat);
2104 		else
2105 		    cdouble += afloat;
2106 	    }
2107 	    break;
2108 	case 'd':
2109 	    while (len-- > 0) {
2110 		double adouble;
2111 		SHIFT_VAR(utf8, s, strend, adouble, datumtype);
2112 		DO_BO_UNPACK_N(adouble, double);
2113 		if (!checksum)
2114 		    mPUSHn(adouble);
2115 		else
2116 		    cdouble += adouble;
2117 	    }
2118 	    break;
2119 	case 'F':
2120 	    while (len-- > 0) {
2121 		NV_bytes anv;
2122 		SHIFT_BYTES(utf8, s, strend, anv.bytes, sizeof(anv.bytes), datumtype);
2123 		DO_BO_UNPACK_N(anv.nv, NV);
2124 		if (!checksum)
2125 		    mPUSHn(anv.nv);
2126 		else
2127 		    cdouble += anv.nv;
2128 	    }
2129 	    break;
2130 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
2131 	case 'D':
2132 	    while (len-- > 0) {
2133 		ld_bytes aldouble;
2134 		SHIFT_BYTES(utf8, s, strend, aldouble.bytes, sizeof(aldouble.bytes), datumtype);
2135 		DO_BO_UNPACK_N(aldouble.ld, long double);
2136 		if (!checksum)
2137 		    mPUSHn(aldouble.ld);
2138 		else
2139 		    cdouble += aldouble.ld;
2140 	    }
2141 	    break;
2142 #endif
2143 	case 'u':
2144 	    if (!checksum) {
2145                 const STRLEN l = (STRLEN) (strend - s) * 3 / 4;
2146 		sv = sv_2mortal(newSV(l));
2147 		if (l) SvPOK_on(sv);
2148 	    }
2149 	    if (utf8) {
2150 		while (next_uni_uu(aTHX_ &s, strend, &len)) {
2151 		    I32 a, b, c, d;
2152 		    char hunk[3];
2153 
2154 		    while (len > 0) {
2155 			next_uni_uu(aTHX_ &s, strend, &a);
2156 			next_uni_uu(aTHX_ &s, strend, &b);
2157 			next_uni_uu(aTHX_ &s, strend, &c);
2158 			next_uni_uu(aTHX_ &s, strend, &d);
2159 			hunk[0] = (char)((a << 2) | (b >> 4));
2160 			hunk[1] = (char)((b << 4) | (c >> 2));
2161 			hunk[2] = (char)((c << 6) | d);
2162 			if (!checksum)
2163 			    sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
2164 			len -= 3;
2165 		    }
2166 		    if (s < strend) {
2167 			if (*s == '\n') {
2168                             s++;
2169                         }
2170 			else {
2171 			    /* possible checksum byte */
2172 			    const char *skip = s+UTF8SKIP(s);
2173 			    if (skip < strend && *skip == '\n')
2174                                 s = skip+1;
2175 			}
2176 		    }
2177 		}
2178 	    } else {
2179 		while (s < strend && *s > ' ' && ISUUCHAR(*s)) {
2180 		    I32 a, b, c, d;
2181 		    char hunk[3];
2182 
2183 		    len = PL_uudmap[*(U8*)s++] & 077;
2184 		    while (len > 0) {
2185 			if (s < strend && ISUUCHAR(*s))
2186 			    a = PL_uudmap[*(U8*)s++] & 077;
2187 			else
2188 			    a = 0;
2189 			if (s < strend && ISUUCHAR(*s))
2190 			    b = PL_uudmap[*(U8*)s++] & 077;
2191 			else
2192 			    b = 0;
2193 			if (s < strend && ISUUCHAR(*s))
2194 			    c = PL_uudmap[*(U8*)s++] & 077;
2195 			else
2196 			    c = 0;
2197 			if (s < strend && ISUUCHAR(*s))
2198 			    d = PL_uudmap[*(U8*)s++] & 077;
2199 			else
2200 			    d = 0;
2201 			hunk[0] = (char)((a << 2) | (b >> 4));
2202 			hunk[1] = (char)((b << 4) | (c >> 2));
2203 			hunk[2] = (char)((c << 6) | d);
2204 			if (!checksum)
2205 			    sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
2206 			len -= 3;
2207 		    }
2208 		    if (*s == '\n')
2209 			s++;
2210 		    else	/* possible checksum byte */
2211 			if (s + 1 < strend && s[1] == '\n')
2212 			    s += 2;
2213 		}
2214 	    }
2215 	    if (!checksum)
2216 		XPUSHs(sv);
2217 	    break;
2218 	}
2219 
2220 	if (checksum) {
2221 	    if (strchr("fFdD", TYPE_NO_MODIFIERS(datumtype)) ||
2222 	      (checksum > bits_in_uv &&
2223 	       strchr("cCsSiIlLnNUWvVqQjJ", TYPE_NO_MODIFIERS(datumtype))) ) {
2224 		NV trouble, anv;
2225 
2226                 anv = (NV) (1 << (checksum & 15));
2227 		while (checksum >= 16) {
2228 		    checksum -= 16;
2229 		    anv *= 65536.0;
2230 		}
2231 		while (cdouble < 0.0)
2232 		    cdouble += anv;
2233 		cdouble = Perl_modf(cdouble / anv, &trouble) * anv;
2234 		sv = newSVnv(cdouble);
2235 	    }
2236 	    else {
2237 		if (checksum < bits_in_uv) {
2238 		    UV mask = ((UV)1 << checksum) - 1;
2239 		    cuv &= mask;
2240 		}
2241 		sv = newSVuv(cuv);
2242 	    }
2243 	    mXPUSHs(sv);
2244 	    checksum = 0;
2245 	}
2246 
2247         if (symptr->flags & FLAG_SLASH){
2248             if (SP - PL_stack_base - start_sp_offset <= 0)
2249 		break;
2250             if( next_symbol(symptr) ){
2251               if( symptr->howlen == e_number )
2252 		Perl_croak(aTHX_ "Count after length/code in unpack" );
2253               if( beyond ){
2254          	/* ...end of char buffer then no decent length available */
2255 		Perl_croak(aTHX_ "length/code after end of string in unpack" );
2256               } else {
2257          	/* take top of stack (hope it's numeric) */
2258                 len = POPi;
2259                 if( len < 0 )
2260                     Perl_croak(aTHX_ "Negative '/' count in unpack" );
2261               }
2262             } else {
2263 		Perl_croak(aTHX_ "Code missing after '/' in unpack" );
2264             }
2265             datumtype = symptr->code;
2266             explicit_length = FALSE;
2267 	    goto redo_switch;
2268         }
2269     }
2270 
2271     if (new_s)
2272 	*new_s = s;
2273     PUTBACK;
2274     return SP - PL_stack_base - start_sp_offset;
2275 }
2276 
2277 PP(pp_unpack)
2278 {
2279     dVAR;
2280     dSP;
2281     dPOPPOPssrl;
2282     I32 gimme = GIMME_V;
2283     STRLEN llen;
2284     STRLEN rlen;
2285     const char *pat = SvPV_const(left,  llen);
2286     const char *s   = SvPV_const(right, rlen);
2287     const char *strend = s + rlen;
2288     const char *patend = pat + llen;
2289     I32 cnt;
2290 
2291     PUTBACK;
2292     cnt = unpackstring(pat, patend, s, strend,
2293 		     ((gimme == G_SCALAR) ? FLAG_UNPACK_ONLY_ONE : 0)
2294 		     | (DO_UTF8(right) ? FLAG_DO_UTF8 : 0));
2295 
2296     SPAGAIN;
2297     if ( !cnt && gimme == G_SCALAR )
2298        PUSHs(&PL_sv_undef);
2299     RETURN;
2300 }
2301 
2302 STATIC U8 *
2303 doencodes(U8 *h, const char *s, I32 len)
2304 {
2305     *h++ = PL_uuemap[len];
2306     while (len > 2) {
2307 	*h++ = PL_uuemap[(077 & (s[0] >> 2))];
2308 	*h++ = PL_uuemap[(077 & (((s[0] << 4) & 060) | ((s[1] >> 4) & 017)))];
2309 	*h++ = PL_uuemap[(077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03)))];
2310 	*h++ = PL_uuemap[(077 & (s[2] & 077))];
2311 	s += 3;
2312 	len -= 3;
2313     }
2314     if (len > 0) {
2315         const char r = (len > 1 ? s[1] : '\0');
2316 	*h++ = PL_uuemap[(077 & (s[0] >> 2))];
2317 	*h++ = PL_uuemap[(077 & (((s[0] << 4) & 060) | ((r >> 4) & 017)))];
2318 	*h++ = PL_uuemap[(077 & ((r << 2) & 074))];
2319 	*h++ = PL_uuemap[0];
2320     }
2321     *h++ = '\n';
2322     return h;
2323 }
2324 
2325 STATIC SV *
2326 S_is_an_int(pTHX_ const char *s, STRLEN l)
2327 {
2328   SV *result = newSVpvn(s, l);
2329   char *const result_c = SvPV_nolen(result);	/* convenience */
2330   char *out = result_c;
2331   bool skip = 1;
2332   bool ignore = 0;
2333 
2334   PERL_ARGS_ASSERT_IS_AN_INT;
2335 
2336   while (*s) {
2337     switch (*s) {
2338     case ' ':
2339       break;
2340     case '+':
2341       if (!skip) {
2342 	SvREFCNT_dec(result);
2343 	return (NULL);
2344       }
2345       break;
2346     case '0':
2347     case '1':
2348     case '2':
2349     case '3':
2350     case '4':
2351     case '5':
2352     case '6':
2353     case '7':
2354     case '8':
2355     case '9':
2356       skip = 0;
2357       if (!ignore) {
2358 	*(out++) = *s;
2359       }
2360       break;
2361     case '.':
2362       ignore = 1;
2363       break;
2364     default:
2365       SvREFCNT_dec(result);
2366       return (NULL);
2367     }
2368     s++;
2369   }
2370   *(out++) = '\0';
2371   SvCUR_set(result, out - result_c);
2372   return (result);
2373 }
2374 
2375 /* pnum must be '\0' terminated */
2376 STATIC int
2377 S_div128(pTHX_ SV *pnum, bool *done)
2378 {
2379     STRLEN len;
2380     char * const s = SvPV(pnum, len);
2381     char *t = s;
2382     int m = 0;
2383 
2384     PERL_ARGS_ASSERT_DIV128;
2385 
2386     *done = 1;
2387     while (*t) {
2388 	const int i = m * 10 + (*t - '0');
2389 	const int r = (i >> 7); /* r < 10 */
2390 	m = i & 0x7F;
2391 	if (r) {
2392 	    *done = 0;
2393 	}
2394 	*(t++) = '0' + r;
2395     }
2396     *(t++) = '\0';
2397     SvCUR_set(pnum, (STRLEN) (t - s));
2398     return (m);
2399 }
2400 
2401 /*
2402 =for apidoc packlist
2403 
2404 The engine implementing pack() Perl function.
2405 
2406 =cut
2407 */
2408 
2409 void
2410 Perl_packlist(pTHX_ SV *cat, const char *pat, const char *patend, SV **beglist, SV **endlist )
2411 {
2412     dVAR;
2413     tempsym_t sym;
2414 
2415     PERL_ARGS_ASSERT_PACKLIST;
2416 
2417     TEMPSYM_INIT(&sym, pat, patend, FLAG_PACK);
2418 
2419     /* We're going to do changes through SvPVX(cat). Make sure it's valid.
2420        Also make sure any UTF8 flag is loaded */
2421     SvPV_force_nolen(cat);
2422     if (DO_UTF8(cat))
2423 	sym.flags |= FLAG_PARSE_UTF8 | FLAG_DO_UTF8;
2424 
2425     (void)pack_rec( cat, &sym, beglist, endlist );
2426 }
2427 
2428 /* like sv_utf8_upgrade, but also repoint the group start markers */
2429 STATIC void
2430 marked_upgrade(pTHX_ SV *sv, tempsym_t *sym_ptr) {
2431     STRLEN len;
2432     tempsym_t *group;
2433     const char *from_ptr, *from_start, *from_end, **marks, **m;
2434     char *to_start, *to_ptr;
2435 
2436     if (SvUTF8(sv)) return;
2437 
2438     from_start = SvPVX_const(sv);
2439     from_end = from_start + SvCUR(sv);
2440     for (from_ptr = from_start; from_ptr < from_end; from_ptr++)
2441 	if (!NATIVE_IS_INVARIANT(*from_ptr)) break;
2442     if (from_ptr == from_end) {
2443 	/* Simple case: no character needs to be changed */
2444 	SvUTF8_on(sv);
2445 	return;
2446     }
2447 
2448     len = (from_end-from_ptr)*UTF8_EXPAND+(from_ptr-from_start)+1;
2449     Newx(to_start, len, char);
2450     Copy(from_start, to_start, from_ptr-from_start, char);
2451     to_ptr = to_start + (from_ptr-from_start);
2452 
2453     Newx(marks, sym_ptr->level+2, const char *);
2454     for (group=sym_ptr; group; group = group->previous)
2455 	marks[group->level] = from_start + group->strbeg;
2456     marks[sym_ptr->level+1] = from_end+1;
2457     for (m = marks; *m < from_ptr; m++)
2458 	*m = to_start + (*m-from_start);
2459 
2460     for (;from_ptr < from_end; from_ptr++) {
2461 	while (*m == from_ptr) *m++ = to_ptr;
2462 	to_ptr = (char *) uvchr_to_utf8((U8 *) to_ptr, *(U8 *) from_ptr);
2463     }
2464     *to_ptr = 0;
2465 
2466     while (*m == from_ptr) *m++ = to_ptr;
2467     if (m != marks + sym_ptr->level+1) {
2468 	Safefree(marks);
2469 	Safefree(to_start);
2470 	Perl_croak(aTHX_ "panic: marks beyond string end, m=%p, marks=%p, "
2471 		   "level=%d", m, marks, sym_ptr->level);
2472     }
2473     for (group=sym_ptr; group; group = group->previous)
2474 	group->strbeg = marks[group->level] - to_start;
2475     Safefree(marks);
2476 
2477     if (SvOOK(sv)) {
2478 	if (SvIVX(sv)) {
2479 	    SvLEN_set(sv, SvLEN(sv) + SvIVX(sv));
2480 	    from_start -= SvIVX(sv);
2481 	    SvIV_set(sv, 0);
2482 	}
2483 	SvFLAGS(sv) &= ~SVf_OOK;
2484     }
2485     if (SvLEN(sv) != 0)
2486 	Safefree(from_start);
2487     SvPV_set(sv, to_start);
2488     SvCUR_set(sv, to_ptr - to_start);
2489     SvLEN_set(sv, len);
2490     SvUTF8_on(sv);
2491 }
2492 
2493 /* Exponential string grower. Makes string extension effectively O(n)
2494    needed says how many extra bytes we need (not counting the final '\0')
2495    Only grows the string if there is an actual lack of space
2496 */
2497 STATIC char *
2498 S_sv_exp_grow(pTHX_ SV *sv, STRLEN needed) {
2499     const STRLEN cur = SvCUR(sv);
2500     const STRLEN len = SvLEN(sv);
2501     STRLEN extend;
2502 
2503     PERL_ARGS_ASSERT_SV_EXP_GROW;
2504 
2505     if (len - cur > needed) return SvPVX(sv);
2506     extend = needed > len ? needed : len;
2507     return SvGROW(sv, len+extend+1);
2508 }
2509 
2510 STATIC
2511 SV **
2512 S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
2513 {
2514     dVAR;
2515     tempsym_t lookahead;
2516     I32 items  = endlist - beglist;
2517     bool found = next_symbol(symptr);
2518     bool utf8 = (symptr->flags & FLAG_PARSE_UTF8) ? 1 : 0;
2519     bool warn_utf8 = ckWARN(WARN_UTF8);
2520 
2521     PERL_ARGS_ASSERT_PACK_REC;
2522 
2523     if (symptr->level == 0 && found && symptr->code == 'U') {
2524 	marked_upgrade(aTHX_ cat, symptr);
2525 	symptr->flags |= FLAG_DO_UTF8;
2526 	utf8 = 0;
2527     }
2528     symptr->strbeg = SvCUR(cat);
2529 
2530     while (found) {
2531 	SV *fromstr;
2532 	STRLEN fromlen;
2533 	I32 len;
2534 	SV *lengthcode = NULL;
2535         I32 datumtype = symptr->code;
2536         howlen_t howlen = symptr->howlen;
2537 	char *start = SvPVX(cat);
2538 	char *cur   = start + SvCUR(cat);
2539 
2540 #define NEXTFROM (lengthcode ? lengthcode : items-- > 0 ? *beglist++ : &PL_sv_no)
2541 
2542         switch (howlen) {
2543 	  case e_star:
2544 	    len = strchr("@Xxu", TYPE_NO_MODIFIERS(datumtype)) ?
2545 		0 : items;
2546 	    break;
2547 	  default:
2548 	    /* e_no_len and e_number */
2549 	    len = symptr->length;
2550 	    break;
2551         }
2552 
2553 	if (len) {
2554 	    packprops_t props = packprops[TYPE_NO_ENDIANNESS(datumtype)];
2555 
2556 	    if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
2557 		/* We can process this letter. */
2558 		STRLEN size = props & PACK_SIZE_MASK;
2559 		GROWING(utf8, cat, start, cur, (STRLEN) len * size);
2560 	    }
2561         }
2562 
2563         /* Look ahead for next symbol. Do we have code/code? */
2564         lookahead = *symptr;
2565         found = next_symbol(&lookahead);
2566 	if (symptr->flags & FLAG_SLASH) {
2567 	    IV count;
2568 	    if (!found) Perl_croak(aTHX_ "Code missing after '/' in pack");
2569 	    if (strchr("aAZ", lookahead.code)) {
2570 		if (lookahead.howlen == e_number) count = lookahead.length;
2571 		else {
2572 		    if (items > 0) {
2573 			count = sv_len_utf8(*beglist);
2574 		    }
2575 		    else count = 0;
2576 		    if (lookahead.code == 'Z') count++;
2577 		}
2578 	    } else {
2579 		if (lookahead.howlen == e_number && lookahead.length < items)
2580 		    count = lookahead.length;
2581 		else count = items;
2582 	    }
2583 	    lookahead.howlen = e_number;
2584 	    lookahead.length = count;
2585 	    lengthcode = sv_2mortal(newSViv(count));
2586 	}
2587 
2588 	/* Code inside the switch must take care to properly update
2589 	   cat (CUR length and '\0' termination) if it updated *cur and
2590 	   doesn't simply leave using break */
2591 	switch(TYPE_NO_ENDIANNESS(datumtype)) {
2592 	default:
2593 	    Perl_croak(aTHX_ "Invalid type '%c' in pack",
2594 		       (int) TYPE_NO_MODIFIERS(datumtype));
2595 	case '%':
2596 	    Perl_croak(aTHX_ "'%%' may not be used in pack");
2597 	{
2598 	    char *from;
2599 #ifdef PERL_PACK_CAN_SHRIEKSIGN
2600 	case '.' | TYPE_IS_SHRIEKING:
2601 #endif
2602 	case '.':
2603 	    if (howlen == e_star) from = start;
2604 	    else if (len == 0) from = cur;
2605 	    else {
2606 		tempsym_t *group = symptr;
2607 
2608 		while (--len && group) group = group->previous;
2609 		from = group ? start + group->strbeg : start;
2610 	    }
2611 	    fromstr = NEXTFROM;
2612 	    len = SvIV(fromstr);
2613 	    goto resize;
2614 #ifdef PERL_PACK_CAN_SHRIEKSIGN
2615 	case '@' | TYPE_IS_SHRIEKING:
2616 #endif
2617 	case '@':
2618 	    from = start + symptr->strbeg;
2619 	  resize:
2620 #ifdef PERL_PACK_CAN_SHRIEKSIGN
2621 	    if (utf8  && !(datumtype & TYPE_IS_SHRIEKING))
2622 #else /* PERL_PACK_CAN_SHRIEKSIGN */
2623 	    if (utf8)
2624 #endif
2625 		if (len >= 0) {
2626 		    while (len && from < cur) {
2627 			from += UTF8SKIP(from);
2628 			len--;
2629 		    }
2630 		    if (from > cur)
2631 			Perl_croak(aTHX_ "Malformed UTF-8 string in pack");
2632 		    if (len) {
2633 			/* Here we know from == cur */
2634 		      grow:
2635 			GROWING(0, cat, start, cur, len);
2636 			Zero(cur, len, char);
2637 			cur += len;
2638 		    } else if (from < cur) {
2639 			len = cur - from;
2640 			goto shrink;
2641 		    } else goto no_change;
2642 		} else {
2643 		    cur = from;
2644 		    len = -len;
2645 		    goto utf8_shrink;
2646 		}
2647 	    else {
2648 		len -= cur - from;
2649 		if (len > 0) goto grow;
2650 		if (len == 0) goto no_change;
2651 		len = -len;
2652 		goto shrink;
2653 	    }
2654 	    break;
2655 	}
2656 	case '(': {
2657             tempsym_t savsym = *symptr;
2658 	    U32 group_modifiers = TYPE_MODIFIERS(datumtype & ~symptr->flags);
2659 	    symptr->flags |= group_modifiers;
2660             symptr->patend = savsym.grpend;
2661             symptr->level++;
2662 	    symptr->previous = &lookahead;
2663 	    while (len--) {
2664 		U32 was_utf8;
2665 		if (utf8) symptr->flags |=  FLAG_PARSE_UTF8;
2666 		else      symptr->flags &= ~FLAG_PARSE_UTF8;
2667 		was_utf8 = SvUTF8(cat);
2668   	        symptr->patptr = savsym.grpbeg;
2669 		beglist = pack_rec(cat, symptr, beglist, endlist);
2670 		if (SvUTF8(cat) != was_utf8)
2671 		    /* This had better be an upgrade while in utf8==0 mode */
2672 		    utf8 = 1;
2673 
2674 		if (savsym.howlen == e_star && beglist == endlist)
2675 		    break;		/* No way to continue */
2676 	    }
2677 	    items = endlist - beglist;
2678 	    lookahead.flags  = symptr->flags & ~group_modifiers;
2679 	    goto no_change;
2680 	}
2681 	case 'X' | TYPE_IS_SHRIEKING:
2682 	    if (!len)			/* Avoid division by 0 */
2683 		len = 1;
2684 	    if (utf8) {
2685 		char *hop, *last;
2686 		I32 l = len;
2687 		hop = last = start;
2688 		while (hop < cur) {
2689 		    hop += UTF8SKIP(hop);
2690 		    if (--l == 0) {
2691 			last = hop;
2692 			l = len;
2693 		    }
2694 		}
2695 		if (last > cur)
2696 		    Perl_croak(aTHX_ "Malformed UTF-8 string in pack");
2697 		cur = last;
2698 		break;
2699 	    }
2700 	    len = (cur-start) % len;
2701 	    /* FALL THROUGH */
2702 	case 'X':
2703 	    if (utf8) {
2704 		if (len < 1) goto no_change;
2705 	      utf8_shrink:
2706 		while (len > 0) {
2707 		    if (cur <= start)
2708 			Perl_croak(aTHX_ "'%c' outside of string in pack",
2709 				   (int) TYPE_NO_MODIFIERS(datumtype));
2710 		    while (--cur, UTF8_IS_CONTINUATION(*cur)) {
2711 			if (cur <= start)
2712 			    Perl_croak(aTHX_ "'%c' outside of string in pack",
2713 				       (int) TYPE_NO_MODIFIERS(datumtype));
2714 		    }
2715 		    len--;
2716 		}
2717 	    } else {
2718 	      shrink:
2719 		if (cur - start < len)
2720 		    Perl_croak(aTHX_ "'%c' outside of string in pack",
2721 			       (int) TYPE_NO_MODIFIERS(datumtype));
2722 		cur -= len;
2723 	    }
2724 	    if (cur < start+symptr->strbeg) {
2725 		/* Make sure group starts don't point into the void */
2726 		tempsym_t *group;
2727 		const STRLEN length = cur-start;
2728 		for (group = symptr;
2729 		     group && length < group->strbeg;
2730 		     group = group->previous) group->strbeg = length;
2731 		lookahead.strbeg = length;
2732 	    }
2733 	    break;
2734 	case 'x' | TYPE_IS_SHRIEKING: {
2735 	    I32 ai32;
2736 	    if (!len)			/* Avoid division by 0 */
2737 		len = 1;
2738 	    if (utf8) ai32 = utf8_length((U8 *) start, (U8 *) cur) % len;
2739 	    else      ai32 = (cur - start) % len;
2740 	    if (ai32 == 0) goto no_change;
2741 	    len -= ai32;
2742 	}
2743 	/* FALL THROUGH */
2744 	case 'x':
2745 	    goto grow;
2746 	case 'A':
2747 	case 'Z':
2748 	case 'a': {
2749 	    const char *aptr;
2750 
2751 	    fromstr = NEXTFROM;
2752 	    aptr = SvPV_const(fromstr, fromlen);
2753 	    if (DO_UTF8(fromstr)) {
2754                 const char *end, *s;
2755 
2756 		if (!utf8 && !SvUTF8(cat)) {
2757 		    marked_upgrade(aTHX_ cat, symptr);
2758 		    lookahead.flags |= FLAG_DO_UTF8;
2759 		    lookahead.strbeg = symptr->strbeg;
2760 		    utf8 = 1;
2761 		    start = SvPVX(cat);
2762 		    cur = start + SvCUR(cat);
2763 		}
2764 		if (howlen == e_star) {
2765 		    if (utf8) goto string_copy;
2766 		    len = fromlen+1;
2767 		}
2768 		s = aptr;
2769 		end = aptr + fromlen;
2770 		fromlen = datumtype == 'Z' ? len-1 : len;
2771 		while ((I32) fromlen > 0 && s < end) {
2772 		    s += UTF8SKIP(s);
2773 		    fromlen--;
2774 		}
2775 		if (s > end)
2776 		    Perl_croak(aTHX_ "Malformed UTF-8 string in pack");
2777 		if (utf8) {
2778 		    len = fromlen;
2779 		    if (datumtype == 'Z') len++;
2780 		    fromlen = s-aptr;
2781 		    len += fromlen;
2782 
2783 		    goto string_copy;
2784 		}
2785 		fromlen = len - fromlen;
2786 		if (datumtype == 'Z') fromlen--;
2787 		if (howlen == e_star) {
2788 		    len = fromlen;
2789 		    if (datumtype == 'Z') len++;
2790 		}
2791 		GROWING(0, cat, start, cur, len);
2792 		if (!uni_to_bytes(aTHX_ &aptr, end, cur, fromlen,
2793 				  datumtype | TYPE_IS_PACK))
2794 		    Perl_croak(aTHX_ "panic: predicted utf8 length not available, "
2795 			       "for '%c', aptr=%p end=%p cur=%p, fromlen=%"UVuf,
2796 			       (int)datumtype, aptr, end, cur, (UV)fromlen);
2797 		cur += fromlen;
2798 		len -= fromlen;
2799 	    } else if (utf8) {
2800 		if (howlen == e_star) {
2801 		    len = fromlen;
2802 		    if (datumtype == 'Z') len++;
2803 		}
2804 		if (len <= (I32) fromlen) {
2805 		    fromlen = len;
2806 		    if (datumtype == 'Z' && fromlen > 0) fromlen--;
2807 		}
2808 		/* assumes a byte expands to at most UTF8_EXPAND bytes on
2809 		   upgrade, so:
2810 		   expected_length <= from_len*UTF8_EXPAND + (len-from_len) */
2811 		GROWING(0, cat, start, cur, fromlen*(UTF8_EXPAND-1)+len);
2812 		len -= fromlen;
2813 		while (fromlen > 0) {
2814 		    cur = (char *) uvchr_to_utf8((U8 *) cur, * (U8 *) aptr);
2815 		    aptr++;
2816 		    fromlen--;
2817 		}
2818 	    } else {
2819 	      string_copy:
2820 		if (howlen == e_star) {
2821 		    len = fromlen;
2822 		    if (datumtype == 'Z') len++;
2823 		}
2824 		if (len <= (I32) fromlen) {
2825 		    fromlen = len;
2826 		    if (datumtype == 'Z' && fromlen > 0) fromlen--;
2827 		}
2828 		GROWING(0, cat, start, cur, len);
2829 		Copy(aptr, cur, fromlen, char);
2830 		cur += fromlen;
2831 		len -= fromlen;
2832 	    }
2833 	    memset(cur, datumtype == 'A' ? ' ' : '\0', len);
2834 	    cur += len;
2835 	    SvTAINT(cat);
2836 	    break;
2837 	}
2838 	case 'B':
2839 	case 'b': {
2840 	    const char *str, *end;
2841 	    I32 l, field_len;
2842 	    U8 bits;
2843 	    bool utf8_source;
2844 	    U32 utf8_flags;
2845 
2846 	    fromstr = NEXTFROM;
2847 	    str = SvPV_const(fromstr, fromlen);
2848 	    end = str + fromlen;
2849 	    if (DO_UTF8(fromstr)) {
2850 		utf8_source = TRUE;
2851 		utf8_flags  = warn_utf8 ? 0 : UTF8_ALLOW_ANY;
2852 	    } else {
2853 		utf8_source = FALSE;
2854 		utf8_flags  = 0; /* Unused, but keep compilers happy */
2855 	    }
2856 	    if (howlen == e_star) len = fromlen;
2857 	    field_len = (len+7)/8;
2858 	    GROWING(utf8, cat, start, cur, field_len);
2859 	    if (len > (I32)fromlen) len = fromlen;
2860 	    bits = 0;
2861 	    l = 0;
2862 	    if (datumtype == 'B')
2863 		while (l++ < len) {
2864 		    if (utf8_source) {
2865 			UV val = 0;
2866 			NEXT_UNI_VAL(val, cur, str, end, utf8_flags);
2867 			bits |= val & 1;
2868 		    } else bits |= *str++ & 1;
2869 		    if (l & 7) bits <<= 1;
2870 		    else {
2871 			PUSH_BYTE(utf8, cur, bits);
2872 			bits = 0;
2873 		    }
2874 		}
2875 	    else
2876 		/* datumtype == 'b' */
2877 		while (l++ < len) {
2878 		    if (utf8_source) {
2879 			UV val = 0;
2880 			NEXT_UNI_VAL(val, cur, str, end, utf8_flags);
2881 			if (val & 1) bits |= 0x80;
2882 		    } else if (*str++ & 1)
2883 			bits |= 0x80;
2884 		    if (l & 7) bits >>= 1;
2885 		    else {
2886 			PUSH_BYTE(utf8, cur, bits);
2887 			bits = 0;
2888 		    }
2889 		}
2890 	    l--;
2891 	    if (l & 7) {
2892 		if (datumtype == 'B')
2893 		    bits <<= 7 - (l & 7);
2894 		else
2895 		    bits >>= 7 - (l & 7);
2896 		PUSH_BYTE(utf8, cur, bits);
2897 		l += 7;
2898 	    }
2899 	    /* Determine how many chars are left in the requested field */
2900 	    l /= 8;
2901 	    if (howlen == e_star) field_len = 0;
2902 	    else field_len -= l;
2903 	    Zero(cur, field_len, char);
2904 	    cur += field_len;
2905 	    break;
2906 	}
2907 	case 'H':
2908 	case 'h': {
2909 	    const char *str, *end;
2910 	    I32 l, field_len;
2911 	    U8 bits;
2912 	    bool utf8_source;
2913 	    U32 utf8_flags;
2914 
2915 	    fromstr = NEXTFROM;
2916 	    str = SvPV_const(fromstr, fromlen);
2917 	    end = str + fromlen;
2918 	    if (DO_UTF8(fromstr)) {
2919 		utf8_source = TRUE;
2920 		utf8_flags  = warn_utf8 ? 0 : UTF8_ALLOW_ANY;
2921 	    } else {
2922 		utf8_source = FALSE;
2923 		utf8_flags  = 0; /* Unused, but keep compilers happy */
2924 	    }
2925 	    if (howlen == e_star) len = fromlen;
2926 	    field_len = (len+1)/2;
2927 	    GROWING(utf8, cat, start, cur, field_len);
2928 	    if (!utf8 && len > (I32)fromlen) len = fromlen;
2929 	    bits = 0;
2930 	    l = 0;
2931 	    if (datumtype == 'H')
2932 		while (l++ < len) {
2933 		    if (utf8_source) {
2934 			UV val = 0;
2935 			NEXT_UNI_VAL(val, cur, str, end, utf8_flags);
2936 			if (val < 256 && isALPHA(val))
2937 			    bits |= (val + 9) & 0xf;
2938 			else
2939 			    bits |= val & 0xf;
2940 		    } else if (isALPHA(*str))
2941 			bits |= (*str++ + 9) & 0xf;
2942 		    else
2943 			bits |= *str++ & 0xf;
2944 		    if (l & 1) bits <<= 4;
2945 		    else {
2946 			PUSH_BYTE(utf8, cur, bits);
2947 			bits = 0;
2948 		    }
2949 		}
2950 	    else
2951 		while (l++ < len) {
2952 		    if (utf8_source) {
2953 			UV val = 0;
2954 			NEXT_UNI_VAL(val, cur, str, end, utf8_flags);
2955 			if (val < 256 && isALPHA(val))
2956 			    bits |= ((val + 9) & 0xf) << 4;
2957 			else
2958 			    bits |= (val & 0xf) << 4;
2959 		    } else if (isALPHA(*str))
2960 			bits |= ((*str++ + 9) & 0xf) << 4;
2961 		    else
2962 			bits |= (*str++ & 0xf) << 4;
2963 		    if (l & 1) bits >>= 4;
2964 		    else {
2965 			PUSH_BYTE(utf8, cur, bits);
2966 			bits = 0;
2967 		    }
2968 		}
2969 	    l--;
2970 	    if (l & 1) {
2971 		PUSH_BYTE(utf8, cur, bits);
2972 		l++;
2973 	    }
2974 	    /* Determine how many chars are left in the requested field */
2975 	    l /= 2;
2976 	    if (howlen == e_star) field_len = 0;
2977 	    else field_len -= l;
2978 	    Zero(cur, field_len, char);
2979 	    cur += field_len;
2980 	    break;
2981 	}
2982 	case 'c':
2983 	    while (len-- > 0) {
2984 		IV aiv;
2985 		fromstr = NEXTFROM;
2986 		aiv = SvIV(fromstr);
2987 		if ((-128 > aiv || aiv > 127))
2988 		    Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
2989 				   "Character in 'c' format wrapped in pack");
2990 		PUSH_BYTE(utf8, cur, (U8)(aiv & 0xff));
2991 	    }
2992 	    break;
2993 	case 'C':
2994 	    if (len == 0) {
2995 		utf8 = (symptr->flags & FLAG_DO_UTF8) ? 1 : 0;
2996 		break;
2997 	    }
2998 	    while (len-- > 0) {
2999 		IV aiv;
3000 		fromstr = NEXTFROM;
3001 		aiv = SvIV(fromstr);
3002 		if ((0 > aiv || aiv > 0xff))
3003 		    Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
3004 				   "Character in 'C' format wrapped in pack");
3005 		PUSH_BYTE(utf8, cur, (U8)(aiv & 0xff));
3006 	    }
3007 	    break;
3008 	case 'W': {
3009 	    char *end;
3010 	    U8 in_bytes = (U8)IN_BYTES;
3011 
3012 	    end = start+SvLEN(cat)-1;
3013 	    if (utf8) end -= UTF8_MAXLEN-1;
3014 	    while (len-- > 0) {
3015 		UV auv;
3016 		fromstr = NEXTFROM;
3017 		auv = SvUV(fromstr);
3018 		if (in_bytes) auv = auv % 0x100;
3019 		if (utf8) {
3020 		  W_utf8:
3021 		    if (cur > end) {
3022 			*cur = '\0';
3023 			SvCUR_set(cat, cur - start);
3024 
3025 			GROWING(0, cat, start, cur, len+UTF8_MAXLEN);
3026 			end = start+SvLEN(cat)-UTF8_MAXLEN;
3027 		    }
3028 		    cur = (char *) uvuni_to_utf8_flags((U8 *) cur,
3029 						       NATIVE_TO_UNI(auv),
3030 						       warn_utf8 ?
3031 						       0 : UNICODE_ALLOW_ANY);
3032 		} else {
3033 		    if (auv >= 0x100) {
3034 			if (!SvUTF8(cat)) {
3035 			    *cur = '\0';
3036 			    SvCUR_set(cat, cur - start);
3037 			    marked_upgrade(aTHX_ cat, symptr);
3038 			    lookahead.flags |= FLAG_DO_UTF8;
3039 			    lookahead.strbeg = symptr->strbeg;
3040 			    utf8 = 1;
3041 			    start = SvPVX(cat);
3042 			    cur = start + SvCUR(cat);
3043 			    end = start+SvLEN(cat)-UTF8_MAXLEN;
3044 			    goto W_utf8;
3045 			}
3046 			Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
3047 				       "Character in 'W' format wrapped in pack");
3048 			auv &= 0xff;
3049 		    }
3050 		    if (cur >= end) {
3051 			*cur = '\0';
3052 			SvCUR_set(cat, cur - start);
3053 			GROWING(0, cat, start, cur, len+1);
3054 			end = start+SvLEN(cat)-1;
3055 		    }
3056 		    *(U8 *) cur++ = (U8)auv;
3057 		}
3058 	    }
3059 	    break;
3060 	}
3061 	case 'U': {
3062 	    char *end;
3063 
3064 	    if (len == 0) {
3065 		if (!(symptr->flags & FLAG_DO_UTF8)) {
3066 		    marked_upgrade(aTHX_ cat, symptr);
3067 		    lookahead.flags |= FLAG_DO_UTF8;
3068 		    lookahead.strbeg = symptr->strbeg;
3069 		}
3070 		utf8 = 0;
3071 		goto no_change;
3072 	    }
3073 
3074 	    end = start+SvLEN(cat);
3075 	    if (!utf8) end -= UTF8_MAXLEN;
3076 	    while (len-- > 0) {
3077 		UV auv;
3078 		fromstr = NEXTFROM;
3079 		auv = SvUV(fromstr);
3080 		if (utf8) {
3081 		    U8 buffer[UTF8_MAXLEN], *endb;
3082 		    endb = uvuni_to_utf8_flags(buffer, auv,
3083 					       warn_utf8 ?
3084 					       0 : UNICODE_ALLOW_ANY);
3085 		    if (cur+(endb-buffer)*UTF8_EXPAND >= end) {
3086 			*cur = '\0';
3087 			SvCUR_set(cat, cur - start);
3088 			GROWING(0, cat, start, cur,
3089 				len+(endb-buffer)*UTF8_EXPAND);
3090 			end = start+SvLEN(cat);
3091 		    }
3092 		    cur = bytes_to_uni(buffer, endb-buffer, cur);
3093 		} else {
3094 		    if (cur >= end) {
3095 			*cur = '\0';
3096 			SvCUR_set(cat, cur - start);
3097 			GROWING(0, cat, start, cur, len+UTF8_MAXLEN);
3098 			end = start+SvLEN(cat)-UTF8_MAXLEN;
3099 		    }
3100 		    cur = (char *) uvuni_to_utf8_flags((U8 *) cur, auv,
3101 						       warn_utf8 ?
3102 						       0 : UNICODE_ALLOW_ANY);
3103 		}
3104 	    }
3105 	    break;
3106 	}
3107 	/* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
3108 	case 'f':
3109 	    while (len-- > 0) {
3110 		float afloat;
3111 		NV anv;
3112 		fromstr = NEXTFROM;
3113 		anv = SvNV(fromstr);
3114 # if defined(VMS) && !defined(_IEEE_FP)
3115 		/* IEEE fp overflow shenanigans are unavailable on VAX and optional
3116 		 * on Alpha; fake it if we don't have them.
3117 		 */
3118 		if (anv > FLT_MAX)
3119 		    afloat = FLT_MAX;
3120 		else if (anv < -FLT_MAX)
3121 		    afloat = -FLT_MAX;
3122 		else afloat = (float)anv;
3123 # else
3124 		afloat = (float)anv;
3125 # endif
3126 		DO_BO_PACK_N(afloat, float);
3127 		PUSH_VAR(utf8, cur, afloat);
3128 	    }
3129 	    break;
3130 	case 'd':
3131 	    while (len-- > 0) {
3132 		double adouble;
3133 		NV anv;
3134 		fromstr = NEXTFROM;
3135 		anv = SvNV(fromstr);
3136 # if defined(VMS) && !defined(_IEEE_FP)
3137 		/* IEEE fp overflow shenanigans are unavailable on VAX and optional
3138 		 * on Alpha; fake it if we don't have them.
3139 		 */
3140 		if (anv > DBL_MAX)
3141 		    adouble = DBL_MAX;
3142 		else if (anv < -DBL_MAX)
3143 		    adouble = -DBL_MAX;
3144 		else adouble = (double)anv;
3145 # else
3146 		adouble = (double)anv;
3147 # endif
3148 		DO_BO_PACK_N(adouble, double);
3149 		PUSH_VAR(utf8, cur, adouble);
3150 	    }
3151 	    break;
3152 	case 'F': {
3153 	    NV_bytes anv;
3154 	    Zero(&anv, 1, NV); /* can be long double with unused bits */
3155 	    while (len-- > 0) {
3156 		fromstr = NEXTFROM;
3157 #ifdef __GNUC__
3158 		/* to work round a gcc/x86 bug; don't use SvNV */
3159 		anv.nv = sv_2nv(fromstr);
3160 #else
3161 		anv.nv = SvNV(fromstr);
3162 #endif
3163 		DO_BO_PACK_N(anv, NV);
3164 		PUSH_BYTES(utf8, cur, anv.bytes, sizeof(anv.bytes));
3165 	    }
3166 	    break;
3167 	}
3168 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
3169 	case 'D': {
3170 	    ld_bytes aldouble;
3171 	    /* long doubles can have unused bits, which may be nonzero */
3172 	    Zero(&aldouble, 1, long double);
3173 	    while (len-- > 0) {
3174 		fromstr = NEXTFROM;
3175 #  ifdef __GNUC__
3176 		/* to work round a gcc/x86 bug; don't use SvNV */
3177 		aldouble.ld = (long double)sv_2nv(fromstr);
3178 #  else
3179 		aldouble.ld = (long double)SvNV(fromstr);
3180 #  endif
3181 		DO_BO_PACK_N(aldouble, long double);
3182 		PUSH_BYTES(utf8, cur, aldouble.bytes, sizeof(aldouble.bytes));
3183 	    }
3184 	    break;
3185 	}
3186 #endif
3187 #ifdef PERL_PACK_CAN_SHRIEKSIGN
3188 	case 'n' | TYPE_IS_SHRIEKING:
3189 #endif
3190 	case 'n':
3191 	    while (len-- > 0) {
3192 		I16 ai16;
3193 		fromstr = NEXTFROM;
3194 		ai16 = (I16)SvIV(fromstr);
3195 #ifdef HAS_HTONS
3196 		ai16 = PerlSock_htons(ai16);
3197 #endif
3198 		PUSH16(utf8, cur, &ai16);
3199 	    }
3200 	    break;
3201 #ifdef PERL_PACK_CAN_SHRIEKSIGN
3202 	case 'v' | TYPE_IS_SHRIEKING:
3203 #endif
3204 	case 'v':
3205 	    while (len-- > 0) {
3206 		I16 ai16;
3207 		fromstr = NEXTFROM;
3208 		ai16 = (I16)SvIV(fromstr);
3209 #ifdef HAS_HTOVS
3210 		ai16 = htovs(ai16);
3211 #endif
3212 		PUSH16(utf8, cur, &ai16);
3213 	    }
3214 	    break;
3215         case 'S' | TYPE_IS_SHRIEKING:
3216 #if SHORTSIZE != SIZE16
3217 	    while (len-- > 0) {
3218 		unsigned short aushort;
3219 		fromstr = NEXTFROM;
3220 		aushort = SvUV(fromstr);
3221 		DO_BO_PACK(aushort, s);
3222 		PUSH_VAR(utf8, cur, aushort);
3223 	    }
3224             break;
3225 #else
3226             /* Fall through! */
3227 #endif
3228 	case 'S':
3229 	    while (len-- > 0) {
3230 		U16 au16;
3231 		fromstr = NEXTFROM;
3232 		au16 = (U16)SvUV(fromstr);
3233 		DO_BO_PACK(au16, 16);
3234 		PUSH16(utf8, cur, &au16);
3235 	    }
3236 	    break;
3237 	case 's' | TYPE_IS_SHRIEKING:
3238 #if SHORTSIZE != SIZE16
3239 	    while (len-- > 0) {
3240 		short ashort;
3241 		fromstr = NEXTFROM;
3242 		ashort = SvIV(fromstr);
3243 		DO_BO_PACK(ashort, s);
3244 		PUSH_VAR(utf8, cur, ashort);
3245 	    }
3246             break;
3247 #else
3248             /* Fall through! */
3249 #endif
3250 	case 's':
3251 	    while (len-- > 0) {
3252 		I16 ai16;
3253 		fromstr = NEXTFROM;
3254 		ai16 = (I16)SvIV(fromstr);
3255 		DO_BO_PACK(ai16, 16);
3256 		PUSH16(utf8, cur, &ai16);
3257 	    }
3258 	    break;
3259 	case 'I':
3260 	case 'I' | TYPE_IS_SHRIEKING:
3261 	    while (len-- > 0) {
3262 		unsigned int auint;
3263 		fromstr = NEXTFROM;
3264 		auint = SvUV(fromstr);
3265 		DO_BO_PACK(auint, i);
3266 		PUSH_VAR(utf8, cur, auint);
3267 	    }
3268 	    break;
3269 	case 'j':
3270 	    while (len-- > 0) {
3271 		IV aiv;
3272 		fromstr = NEXTFROM;
3273 		aiv = SvIV(fromstr);
3274 #if IVSIZE == INTSIZE
3275 		DO_BO_PACK(aiv, i);
3276 #elif IVSIZE == LONGSIZE
3277 		DO_BO_PACK(aiv, l);
3278 #elif defined(HAS_QUAD) && IVSIZE == U64SIZE
3279 		DO_BO_PACK(aiv, 64);
3280 #else
3281 		Perl_croak(aTHX_ "'j' not supported on this platform");
3282 #endif
3283 		PUSH_VAR(utf8, cur, aiv);
3284 	    }
3285 	    break;
3286 	case 'J':
3287 	    while (len-- > 0) {
3288 		UV auv;
3289 		fromstr = NEXTFROM;
3290 		auv = SvUV(fromstr);
3291 #if UVSIZE == INTSIZE
3292 		DO_BO_PACK(auv, i);
3293 #elif UVSIZE == LONGSIZE
3294 		DO_BO_PACK(auv, l);
3295 #elif defined(HAS_QUAD) && UVSIZE == U64SIZE
3296 		DO_BO_PACK(auv, 64);
3297 #else
3298 		Perl_croak(aTHX_ "'J' not supported on this platform");
3299 #endif
3300 		PUSH_VAR(utf8, cur, auv);
3301 	    }
3302 	    break;
3303 	case 'w':
3304             while (len-- > 0) {
3305 		NV anv;
3306 		fromstr = NEXTFROM;
3307 		anv = SvNV(fromstr);
3308 
3309 		if (anv < 0) {
3310 		    *cur = '\0';
3311 		    SvCUR_set(cat, cur - start);
3312 		    Perl_croak(aTHX_ "Cannot compress negative numbers in pack");
3313 		}
3314 
3315                 /* 0xFFFFFFFFFFFFFFFF may cast to 18446744073709551616.0,
3316                    which is == UV_MAX_P1. IOK is fine (instead of UV_only), as
3317                    any negative IVs will have already been got by the croak()
3318                    above. IOK is untrue for fractions, so we test them
3319                    against UV_MAX_P1.  */
3320 		if (SvIOK(fromstr) || anv < UV_MAX_P1) {
3321 		    char   buf[(sizeof(UV)*CHAR_BIT)/7+1];
3322 		    char  *in = buf + sizeof(buf);
3323 		    UV     auv = SvUV(fromstr);
3324 
3325 		    do {
3326 			*--in = (char)((auv & 0x7f) | 0x80);
3327 			auv >>= 7;
3328 		    } while (auv);
3329 		    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
3330 		    PUSH_GROWING_BYTES(utf8, cat, start, cur,
3331 				       in, (buf + sizeof(buf)) - in);
3332 		} else if (SvPOKp(fromstr))
3333 		    goto w_string;
3334 		else if (SvNOKp(fromstr)) {
3335 		    /* 10**NV_MAX_10_EXP is the largest power of 10
3336 		       so 10**(NV_MAX_10_EXP+1) is definitely unrepresentable
3337 		       given 10**(NV_MAX_10_EXP+1) == 128 ** x solve for x:
3338 		       x = (NV_MAX_10_EXP+1) * log (10) / log (128)
3339 		       And with that many bytes only Inf can overflow.
3340 		       Some C compilers are strict about integral constant
3341 		       expressions so we conservatively divide by a slightly
3342 		       smaller integer instead of multiplying by the exact
3343 		       floating-point value.
3344 		    */
3345 #ifdef NV_MAX_10_EXP
3346 		    /* char   buf[1 + (int)((NV_MAX_10_EXP + 1) * 0.47456)]; -- invalid C */
3347 		    char   buf[1 + (int)((NV_MAX_10_EXP + 1) / 2)]; /* valid C */
3348 #else
3349 		    /* char   buf[1 + (int)((308 + 1) * 0.47456)]; -- invalid C */
3350 		    char   buf[1 + (int)((308 + 1) / 2)]; /* valid C */
3351 #endif
3352 		    char  *in = buf + sizeof(buf);
3353 
3354 		    anv = Perl_floor(anv);
3355 		    do {
3356 			const NV next = Perl_floor(anv / 128);
3357 			if (in <= buf)  /* this cannot happen ;-) */
3358 			    Perl_croak(aTHX_ "Cannot compress integer in pack");
3359 			*--in = (unsigned char)(anv - (next * 128)) | 0x80;
3360 			anv = next;
3361 		    } while (anv > 0);
3362 		    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
3363 		    PUSH_GROWING_BYTES(utf8, cat, start, cur,
3364 				       in, (buf + sizeof(buf)) - in);
3365 		} else {
3366 		    const char     *from;
3367 		    char           *result, *in;
3368 		    SV             *norm;
3369 		    STRLEN          len;
3370 		    bool            done;
3371 
3372 		  w_string:
3373 		    /* Copy string and check for compliance */
3374 		    from = SvPV_const(fromstr, len);
3375 		    if ((norm = is_an_int(from, len)) == NULL)
3376 			Perl_croak(aTHX_ "Can only compress unsigned integers in pack");
3377 
3378 		    Newx(result, len, char);
3379 		    in = result + len;
3380 		    done = FALSE;
3381 		    while (!done) *--in = div128(norm, &done) | 0x80;
3382 		    result[len - 1] &= 0x7F; /* clear continue bit */
3383 		    PUSH_GROWING_BYTES(utf8, cat, start, cur,
3384 				       in, (result + len) - in);
3385 		    Safefree(result);
3386 		    SvREFCNT_dec(norm);	/* free norm */
3387 		}
3388 	    }
3389             break;
3390 	case 'i':
3391 	case 'i' | TYPE_IS_SHRIEKING:
3392 	    while (len-- > 0) {
3393 		int aint;
3394 		fromstr = NEXTFROM;
3395 		aint = SvIV(fromstr);
3396 		DO_BO_PACK(aint, i);
3397 		PUSH_VAR(utf8, cur, aint);
3398 	    }
3399 	    break;
3400 #ifdef PERL_PACK_CAN_SHRIEKSIGN
3401 	case 'N' | TYPE_IS_SHRIEKING:
3402 #endif
3403 	case 'N':
3404 	    while (len-- > 0) {
3405 		U32 au32;
3406 		fromstr = NEXTFROM;
3407 		au32 = SvUV(fromstr);
3408 #ifdef HAS_HTONL
3409 		au32 = PerlSock_htonl(au32);
3410 #endif
3411 		PUSH32(utf8, cur, &au32);
3412 	    }
3413 	    break;
3414 #ifdef PERL_PACK_CAN_SHRIEKSIGN
3415 	case 'V' | TYPE_IS_SHRIEKING:
3416 #endif
3417 	case 'V':
3418 	    while (len-- > 0) {
3419 		U32 au32;
3420 		fromstr = NEXTFROM;
3421 		au32 = SvUV(fromstr);
3422 #ifdef HAS_HTOVL
3423 		au32 = htovl(au32);
3424 #endif
3425 		PUSH32(utf8, cur, &au32);
3426 	    }
3427 	    break;
3428 	case 'L' | TYPE_IS_SHRIEKING:
3429 #if LONGSIZE != SIZE32
3430 	    while (len-- > 0) {
3431 		unsigned long aulong;
3432 		fromstr = NEXTFROM;
3433 		aulong = SvUV(fromstr);
3434 		DO_BO_PACK(aulong, l);
3435 		PUSH_VAR(utf8, cur, aulong);
3436 	    }
3437 	    break;
3438 #else
3439             /* Fall though! */
3440 #endif
3441 	case 'L':
3442 	    while (len-- > 0) {
3443 		U32 au32;
3444 		fromstr = NEXTFROM;
3445 		au32 = SvUV(fromstr);
3446 		DO_BO_PACK(au32, 32);
3447 		PUSH32(utf8, cur, &au32);
3448 	    }
3449 	    break;
3450 	case 'l' | TYPE_IS_SHRIEKING:
3451 #if LONGSIZE != SIZE32
3452 	    while (len-- > 0) {
3453 		long along;
3454 		fromstr = NEXTFROM;
3455 		along = SvIV(fromstr);
3456 		DO_BO_PACK(along, l);
3457 		PUSH_VAR(utf8, cur, along);
3458 	    }
3459 	    break;
3460 #else
3461             /* Fall though! */
3462 #endif
3463 	case 'l':
3464             while (len-- > 0) {
3465 		I32 ai32;
3466 		fromstr = NEXTFROM;
3467 		ai32 = SvIV(fromstr);
3468 		DO_BO_PACK(ai32, 32);
3469 		PUSH32(utf8, cur, &ai32);
3470 	    }
3471 	    break;
3472 #ifdef HAS_QUAD
3473 	case 'Q':
3474 	    while (len-- > 0) {
3475 		Uquad_t auquad;
3476 		fromstr = NEXTFROM;
3477 		auquad = (Uquad_t) SvUV(fromstr);
3478 		DO_BO_PACK(auquad, 64);
3479 		PUSH_VAR(utf8, cur, auquad);
3480 	    }
3481 	    break;
3482 	case 'q':
3483 	    while (len-- > 0) {
3484 		Quad_t aquad;
3485 		fromstr = NEXTFROM;
3486 		aquad = (Quad_t)SvIV(fromstr);
3487 		DO_BO_PACK(aquad, 64);
3488 		PUSH_VAR(utf8, cur, aquad);
3489 	    }
3490 	    break;
3491 #endif /* HAS_QUAD */
3492 	case 'P':
3493 	    len = 1;		/* assume SV is correct length */
3494 	    GROWING(utf8, cat, start, cur, sizeof(char *));
3495 	    /* Fall through! */
3496 	case 'p':
3497 	    while (len-- > 0) {
3498 		const char *aptr;
3499 
3500 		fromstr = NEXTFROM;
3501 		SvGETMAGIC(fromstr);
3502 		if (!SvOK(fromstr)) aptr = NULL;
3503 		else {
3504 		    /* XXX better yet, could spirit away the string to
3505 		     * a safe spot and hang on to it until the result
3506 		     * of pack() (and all copies of the result) are
3507 		     * gone.
3508 		     */
3509 		    if ((SvTEMP(fromstr) || (SvPADTMP(fromstr) &&
3510 			     !SvREADONLY(fromstr)))) {
3511 			Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
3512 				       "Attempt to pack pointer to temporary value");
3513 		    }
3514 		    if (SvPOK(fromstr) || SvNIOK(fromstr))
3515 			aptr = SvPV_nomg_const_nolen(fromstr);
3516 		    else
3517 			aptr = SvPV_force_flags_nolen(fromstr, 0);
3518 		}
3519 		DO_BO_PACK_PC(aptr);
3520 		PUSH_VAR(utf8, cur, aptr);
3521 	    }
3522 	    break;
3523 	case 'u': {
3524 	    const char *aptr, *aend;
3525 	    bool from_utf8;
3526 
3527 	    fromstr = NEXTFROM;
3528 	    if (len <= 2) len = 45;
3529 	    else len = len / 3 * 3;
3530 	    if (len >= 64) {
3531 		Perl_ck_warner(aTHX_ packWARN(WARN_PACK),
3532 			       "Field too wide in 'u' format in pack");
3533 		len = 63;
3534 	    }
3535 	    aptr = SvPV_const(fromstr, fromlen);
3536 	    from_utf8 = DO_UTF8(fromstr);
3537 	    if (from_utf8) {
3538 		aend = aptr + fromlen;
3539 		fromlen = sv_len_utf8_nomg(fromstr);
3540 	    } else aend = NULL; /* Unused, but keep compilers happy */
3541 	    GROWING(utf8, cat, start, cur, (fromlen+2) / 3 * 4 + (fromlen+len-1)/len * 2);
3542 	    while (fromlen > 0) {
3543 		U8 *end;
3544 		I32 todo;
3545 		U8 hunk[1+63/3*4+1];
3546 
3547 		if ((I32)fromlen > len)
3548 		    todo = len;
3549 		else
3550 		    todo = fromlen;
3551 		if (from_utf8) {
3552 		    char buffer[64];
3553 		    if (!uni_to_bytes(aTHX_ &aptr, aend, buffer, todo,
3554 				      'u' | TYPE_IS_PACK)) {
3555 			*cur = '\0';
3556 			SvCUR_set(cat, cur - start);
3557 			Perl_croak(aTHX_ "panic: string is shorter than advertised, "
3558 				   "aptr=%p, aend=%p, buffer=%p, todo=%ld",
3559 				   aptr, aend, buffer, (long) todo);
3560 		    }
3561 		    end = doencodes(hunk, buffer, todo);
3562 		} else {
3563 		    end = doencodes(hunk, aptr, todo);
3564 		    aptr += todo;
3565 		}
3566 		PUSH_BYTES(utf8, cur, hunk, end-hunk);
3567 		fromlen -= todo;
3568 	    }
3569 	    break;
3570 	}
3571 	}
3572 	*cur = '\0';
3573 	SvCUR_set(cat, cur - start);
3574       no_change:
3575 	*symptr = lookahead;
3576     }
3577     return beglist;
3578 }
3579 #undef NEXTFROM
3580 
3581 
3582 PP(pp_pack)
3583 {
3584     dVAR; dSP; dMARK; dORIGMARK; dTARGET;
3585     SV *cat = TARG;
3586     STRLEN fromlen;
3587     SV *pat_sv = *++MARK;
3588     const char *pat = SvPV_const(pat_sv, fromlen);
3589     const char *patend = pat + fromlen;
3590 
3591     MARK++;
3592     sv_setpvs(cat, "");
3593     SvUTF8_off(cat);
3594 
3595     packlist(cat, pat, patend, MARK, SP + 1);
3596 
3597     SvSETMAGIC(cat);
3598     SP = ORIGMARK;
3599     PUSHs(cat);
3600     RETURN;
3601 }
3602 
3603 /*
3604  * Local variables:
3605  * c-indentation-style: bsd
3606  * c-basic-offset: 4
3607  * indent-tabs-mode: nil
3608  * End:
3609  *
3610  * ex: set ts=8 sts=4 sw=4 et:
3611  */
3612