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