1/*    pp_pack.c
2 *
3 *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 *    2000, 2001, 2002, 2003, 2004, 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
19#include "EXTERN.h"
20#define PERL_IN_PP_PACK_C
21#include "perl.h"
22
23/*
24 * The compiler on Concurrent CX/UX systems has a subtle bug which only
25 * seems to show up when compiling pp.c - it generates the wrong double
26 * precision constant value for (double)UV_MAX when used inline in the body
27 * of the code below, so this makes a static variable up front (which the
28 * compiler seems to get correct) and uses it in place of UV_MAX below.
29 */
30#ifdef CXUX_BROKEN_CONSTANT_CONVERT
31static double UV_MAX_cxux = ((double)UV_MAX);
32#endif
33
34/*
35 * Offset for integer pack/unpack.
36 *
37 * On architectures where I16 and I32 aren't really 16 and 32 bits,
38 * which for now are all Crays, pack and unpack have to play games.
39 */
40
41/*
42 * These values are required for portability of pack() output.
43 * If they're not right on your machine, then pack() and unpack()
44 * wouldn't work right anyway; you'll need to apply the Cray hack.
45 * (I'd like to check them with #if, but you can't use sizeof() in
46 * the preprocessor.)  --???
47 */
48/*
49    The appropriate SHORTSIZE, INTSIZE, LONGSIZE, and LONGLONGSIZE
50    defines are now in config.h.  --Andy Dougherty  April 1998
51 */
52#define SIZE16 2
53#define SIZE32 4
54
55/* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
56   --jhi Feb 1999 */
57
58#if SHORTSIZE != SIZE16 || LONGSIZE != SIZE32
59#   define PERL_NATINT_PACK
60#endif
61
62#if LONGSIZE > 4 && defined(_CRAY)
63#  if BYTEORDER == 0x12345678
64#    define OFF16(p)	(char*)(p)
65#    define OFF32(p)	(char*)(p)
66#  else
67#    if BYTEORDER == 0x87654321
68#      define OFF16(p)	((char*)(p) + (sizeof(U16) - SIZE16))
69#      define OFF32(p)	((char*)(p) + (sizeof(U32) - SIZE32))
70#    else
71       }}}} bad cray byte order
72#    endif
73#  endif
74#  define COPY16(s,p)  (*(p) = 0, Copy(s, OFF16(p), SIZE16, char))
75#  define COPY32(s,p)  (*(p) = 0, Copy(s, OFF32(p), SIZE32, char))
76#  define COPYNN(s,p,n) (*(p) = 0, Copy(s, (char *)(p), n, char))
77#  define CAT16(sv,p)  sv_catpvn(sv, OFF16(p), SIZE16)
78#  define CAT32(sv,p)  sv_catpvn(sv, OFF32(p), SIZE32)
79#else
80#  define COPY16(s,p)  Copy(s, p, SIZE16, char)
81#  define COPY32(s,p)  Copy(s, p, SIZE32, char)
82#  define COPYNN(s,p,n) Copy(s, (char *)(p), n, char)
83#  define CAT16(sv,p)  sv_catpvn(sv, (char*)(p), SIZE16)
84#  define CAT32(sv,p)  sv_catpvn(sv, (char*)(p), SIZE32)
85#endif
86
87/* Avoid stack overflow due to pathological templates. 100 should be plenty. */
88#define MAX_SUB_TEMPLATE_LEVEL 100
89
90/* flags */
91#define FLAG_UNPACK_ONLY_ONE  0x10
92#define FLAG_UNPACK_DO_UTF8   0x08
93#define FLAG_SLASH            0x04
94#define FLAG_COMMA            0x02
95#define FLAG_PACK             0x01
96
97STATIC SV *
98S_mul128(pTHX_ SV *sv, U8 m)
99{
100  STRLEN          len;
101  char           *s = SvPV(sv, len);
102  char           *t;
103  U32             i = 0;
104
105  if (!strnEQ(s, "0000", 4)) {  /* need to grow sv */
106    SV             *tmpNew = newSVpvn("0000000000", 10);
107
108    sv_catsv(tmpNew, sv);
109    SvREFCNT_dec(sv);		/* free old sv */
110    sv = tmpNew;
111    s = SvPV(sv, len);
112  }
113  t = s + len - 1;
114  while (!*t)                   /* trailing '\0'? */
115    t--;
116  while (t > s) {
117    i = ((*t - '0') << 7) + m;
118    *(t--) = '0' + (char)(i % 10);
119    m = (char)(i / 10);
120  }
121  return (sv);
122}
123
124/* Explosives and implosives. */
125
126#if 'I' == 73 && 'J' == 74
127/* On an ASCII/ISO kind of system */
128#define ISUUCHAR(ch)    ((ch) >= ' ' && (ch) < 'a')
129#else
130/*
131  Some other sort of character set - use memchr() so we don't match
132  the null byte.
133 */
134#define ISUUCHAR(ch)    (memchr(PL_uuemap, (ch), sizeof(PL_uuemap)-1) || (ch) == ' ')
135#endif
136
137#define TYPE_IS_SHRIEKING	0x100
138
139/* Returns the sizeof() struct described by pat */
140STATIC I32
141S_measure_struct(pTHX_ register tempsym_t* symptr)
142{
143    register I32 len = 0;
144    register I32 total = 0;
145    int star;
146
147    register int size;
148
149    while (next_symbol(symptr)) {
150
151        switch( symptr->howlen ){
152        case e_no_len:
153	case e_number:
154	    len = symptr->length;
155	    break;
156        case e_star:
157   	    Perl_croak(aTHX_ "Within []-length '*' not allowed in %s",
158                       symptr->flags & FLAG_PACK ? "pack" : "unpack" );
159            break;
160        }
161
162	switch(symptr->code) {
163	default:
164    Perl_croak(aTHX_ "Invalid type '%c' in %s",
165                       (int)symptr->code,
166                       symptr->flags & FLAG_PACK ? "pack" : "unpack" );
167	case '@':
168	case '/':
169	case 'U':			/* XXXX Is it correct? */
170	case 'w':
171	case 'u':
172	    Perl_croak(aTHX_ "Within []-length '%c' not allowed in %s",
173                       (int)symptr->code,
174                       symptr->flags & FLAG_PACK ? "pack" : "unpack" );
175	case '%':
176	    size = 0;
177	    break;
178	case '(':
179	{
180            tempsym_t savsym = *symptr;
181  	    symptr->patptr = savsym.grpbeg;
182            symptr->patend = savsym.grpend;
183 	    /* XXXX Theoretically, we need to measure many times at different
184 	       positions, since the subexpression may contain
185 	       alignment commands, but be not of aligned length.
186 	       Need to detect this and croak().  */
187	    size = measure_struct(symptr);
188            *symptr = savsym;
189	    break;
190	}
191 	case 'X' | TYPE_IS_SHRIEKING:
192 	    /* XXXX Is this useful?  Then need to treat MEASURE_BACKWARDS. */
193 	    if (!len)			/* Avoid division by 0 */
194 		len = 1;
195 	    len = total % len;		/* Assumed: the start is aligned. */
196 	    /* FALL THROUGH */
197	case 'X':
198	    size = -1;
199	    if (total < len)
200		Perl_croak(aTHX_ "'X' outside of string in %s",
201                          symptr->flags & FLAG_PACK ? "pack" : "unpack" );
202	    break;
203 	case 'x' | TYPE_IS_SHRIEKING:
204 	    if (!len)			/* Avoid division by 0 */
205 		len = 1;
206 	    star = total % len;		/* Assumed: the start is aligned. */
207 	    if (star)			/* Other portable ways? */
208 		len = len - star;
209 	    else
210 		len = 0;
211 	    /* FALL THROUGH */
212	case 'x':
213	case 'A':
214	case 'Z':
215	case 'a':
216	case 'c':
217	case 'C':
218	    size = 1;
219	    break;
220	case 'B':
221	case 'b':
222	    len = (len + 7)/8;
223	    size = 1;
224	    break;
225	case 'H':
226	case 'h':
227	    len = (len + 1)/2;
228	    size = 1;
229	    break;
230	case 's' | TYPE_IS_SHRIEKING:
231#if SHORTSIZE != SIZE16
232	    size = sizeof(short);
233	    break;
234#else
235            /* FALL THROUGH */
236#endif
237	case 's':
238	    size = SIZE16;
239	    break;
240	case 'S' | TYPE_IS_SHRIEKING:
241#if SHORTSIZE != SIZE16
242	    size = sizeof(unsigned short);
243	    break;
244#else
245            /* FALL THROUGH */
246#endif
247	case 'v':
248	case 'n':
249	case 'S':
250	    size = SIZE16;
251	    break;
252	case 'i' | TYPE_IS_SHRIEKING:
253	case 'i':
254	    size = sizeof(int);
255	    break;
256	case 'I' | TYPE_IS_SHRIEKING:
257	case 'I':
258	    size = sizeof(unsigned int);
259	    break;
260	case 'j':
261	    size = IVSIZE;
262	    break;
263	case 'J':
264	    size = UVSIZE;
265	    break;
266	case 'l' | TYPE_IS_SHRIEKING:
267#if LONGSIZE != SIZE32
268	    size = sizeof(long);
269            break;
270#else
271            /* FALL THROUGH */
272#endif
273	case 'l':
274	    size = SIZE32;
275	    break;
276	case 'L' | TYPE_IS_SHRIEKING:
277#if LONGSIZE != SIZE32
278	    size = sizeof(unsigned long);
279	    break;
280#else
281            /* FALL THROUGH */
282#endif
283	case 'V':
284	case 'N':
285	case 'L':
286	    size = SIZE32;
287	    break;
288	case 'P':
289	    len = 1;
290	    /* FALL THROUGH */
291	case 'p':
292	    size = sizeof(char*);
293	    break;
294#ifdef HAS_QUAD
295	case 'q':
296	    size = sizeof(Quad_t);
297	    break;
298	case 'Q':
299	    size = sizeof(Uquad_t);
300	    break;
301#endif
302	case 'f':
303	    size = sizeof(float);
304	    break;
305	case 'd':
306	    size = sizeof(double);
307	    break;
308	case 'F':
309	    size = NVSIZE;
310	    break;
311#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
312	case 'D':
313	    size = LONG_DOUBLESIZE;
314	    break;
315#endif
316	}
317	total += len * size;
318    }
319    return total;
320}
321
322
323/* locate matching closing parenthesis or bracket
324 * returns char pointer to char after match, or NULL
325 */
326STATIC char *
327S_group_end(pTHX_ register char *patptr, register char *patend, char ender)
328{
329    while (patptr < patend) {
330	char c = *patptr++;
331
332	if (isSPACE(c))
333	    continue;
334	else if (c == ender)
335	    return patptr-1;
336	else if (c == '#') {
337	    while (patptr < patend && *patptr != '\n')
338		patptr++;
339	    continue;
340	} else if (c == '(')
341	    patptr = group_end(patptr, patend, ')') + 1;
342	else if (c == '[')
343	    patptr = group_end(patptr, patend, ']') + 1;
344    }
345    Perl_croak(aTHX_ "No group ending character '%c' found in template",
346               ender);
347    return 0;
348}
349
350
351/* Convert unsigned decimal number to binary.
352 * Expects a pointer to the first digit and address of length variable
353 * Advances char pointer to 1st non-digit char and returns number
354 */
355STATIC char *
356S_get_num(pTHX_ register char *patptr, I32 *lenptr )
357{
358  I32 len = *patptr++ - '0';
359  while (isDIGIT(*patptr)) {
360    if (len >= 0x7FFFFFFF/10)
361      Perl_croak(aTHX_ "pack/unpack repeat count overflow");
362    len = (len * 10) + (*patptr++ - '0');
363  }
364  *lenptr = len;
365  return patptr;
366}
367
368/* The marvellous template parsing routine: Using state stored in *symptr,
369 * locates next template code and count
370 */
371STATIC bool
372S_next_symbol(pTHX_ register tempsym_t* symptr )
373{
374  register char* patptr = symptr->patptr;
375  register char* patend = symptr->patend;
376
377  symptr->flags &= ~FLAG_SLASH;
378
379  while (patptr < patend) {
380    if (isSPACE(*patptr))
381      patptr++;
382    else if (*patptr == '#') {
383      patptr++;
384      while (patptr < patend && *patptr != '\n')
385	patptr++;
386      if (patptr < patend)
387	patptr++;
388    } else {
389      /* We should have found a template code */
390      I32 code = *patptr++ & 0xFF;
391
392      if (code == ','){ /* grandfather in commas but with a warning */
393	if (((symptr->flags & FLAG_COMMA) == 0) && ckWARN(WARN_UNPACK)){
394          symptr->flags |= FLAG_COMMA;
395	  Perl_warner(aTHX_ packWARN(WARN_UNPACK),
396	 	      "Invalid type ',' in %s",
397                      symptr->flags & FLAG_PACK ? "pack" : "unpack" );
398        }
399	continue;
400      }
401
402      /* for '(', skip to ')' */
403      if (code == '(') {
404        if( isDIGIT(*patptr) || *patptr == '*' || *patptr == '[' )
405          Perl_croak(aTHX_ "()-group starts with a count in %s",
406                     symptr->flags & FLAG_PACK ? "pack" : "unpack" );
407        symptr->grpbeg = patptr;
408        patptr = 1 + ( symptr->grpend = group_end(patptr, patend, ')') );
409        if( symptr->level >= MAX_SUB_TEMPLATE_LEVEL )
410	  Perl_croak(aTHX_ "Too deeply nested ()-groups in %s",
411                     symptr->flags & FLAG_PACK ? "pack" : "unpack" );
412      }
413
414      /* test for '!' modifier */
415      if (patptr < patend && *patptr == '!') {
416	static const char natstr[] = "sSiIlLxX";
417        patptr++;
418        if (strchr(natstr, code))
419 	  code |= TYPE_IS_SHRIEKING;
420        else
421   	  Perl_croak(aTHX_ "'!' allowed only after types %s in %s",
422                     natstr, symptr->flags & FLAG_PACK ? "pack" : "unpack" );
423      }
424
425      /* look for count and/or / */
426      if (patptr < patend) {
427	if (isDIGIT(*patptr)) {
428 	  patptr = get_num( patptr, &symptr->length );
429          symptr->howlen = e_number;
430
431        } else if (*patptr == '*') {
432          patptr++;
433          symptr->howlen = e_star;
434
435        } else if (*patptr == '[') {
436          char* lenptr = ++patptr;
437          symptr->howlen = e_number;
438          patptr = group_end( patptr, patend, ']' ) + 1;
439          /* what kind of [] is it? */
440          if (isDIGIT(*lenptr)) {
441            lenptr = get_num( lenptr, &symptr->length );
442            if( *lenptr != ']' )
443              Perl_croak(aTHX_ "Malformed integer in [] in %s",
444                         symptr->flags & FLAG_PACK ? "pack" : "unpack");
445          } else {
446            tempsym_t savsym = *symptr;
447            symptr->patend = patptr-1;
448            symptr->patptr = lenptr;
449            savsym.length = measure_struct(symptr);
450            *symptr = savsym;
451          }
452        } else {
453          symptr->howlen = e_no_len;
454          symptr->length = 1;
455        }
456
457        /* try to find / */
458        while (patptr < patend) {
459          if (isSPACE(*patptr))
460            patptr++;
461          else if (*patptr == '#') {
462            patptr++;
463            while (patptr < patend && *patptr != '\n')
464	      patptr++;
465            if (patptr < patend)
466	      patptr++;
467          } else {
468            if( *patptr == '/' ){
469              symptr->flags |= FLAG_SLASH;
470              patptr++;
471              if( patptr < patend &&
472                  (isDIGIT(*patptr) || *patptr == '*' || *patptr == '[') )
473                Perl_croak(aTHX_ "'/' does not take a repeat count in %s",
474                           symptr->flags & FLAG_PACK ? "pack" : "unpack" );
475            }
476            break;
477	  }
478	}
479      } else {
480        /* at end - no count, no / */
481        symptr->howlen = e_no_len;
482        symptr->length = 1;
483      }
484
485      symptr->code = code;
486      symptr->patptr = patptr;
487      return TRUE;
488    }
489  }
490  symptr->patptr = patptr;
491  return FALSE;
492}
493
494/*
495=for apidoc unpack_str
496
497The engine implementing unpack() Perl function. Note: parameters strbeg, new_s
498and ocnt are not used. This call should not be used, use unpackstring instead.
499
500=cut */
501
502I32
503Perl_unpack_str(pTHX_ char *pat, register char *patend, register char *s, char *strbeg, char *strend, char **new_s, I32 ocnt, U32 flags)
504{
505    tempsym_t sym = { 0 };
506    sym.patptr = pat;
507    sym.patend = patend;
508    sym.flags  = flags;
509
510    return unpack_rec(&sym, s, s, strend, NULL );
511}
512
513/*
514=for apidoc unpackstring
515
516The engine implementing unpack() Perl function. C<unpackstring> puts the
517extracted list items on the stack and returns the number of elements.
518Issue C<PUTBACK> before and C<SPAGAIN> after the call to this function.
519
520=cut */
521
522I32
523Perl_unpackstring(pTHX_ char *pat, register char *patend, register char *s, char *strend, U32 flags)
524{
525    tempsym_t sym = { 0 };
526    sym.patptr = pat;
527    sym.patend = patend;
528    sym.flags  = flags;
529
530    return unpack_rec(&sym, s, s, strend, NULL );
531}
532
533STATIC
534I32
535S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, char *strend, char **new_s )
536{
537    dSP;
538    I32 datumtype;
539    register I32 len = 0;
540    register I32 bits = 0;
541    register char *str;
542    SV *sv;
543    I32 start_sp_offset = SP - PL_stack_base;
544    howlen_t howlen;
545
546    /* These must not be in registers: */
547    short ashort;
548    int aint;
549    long along;
550#ifdef HAS_QUAD
551    Quad_t aquad;
552#endif
553    U16 aushort;
554    unsigned int auint;
555    U32 aulong;
556#ifdef HAS_QUAD
557    Uquad_t auquad;
558#endif
559    char *aptr;
560    float afloat;
561    double adouble;
562    I32 checksum = 0;
563    UV cuv = 0;
564    NV cdouble = 0.0;
565    const int bits_in_uv = 8 * sizeof(cuv);
566    char* strrelbeg = s;
567    bool beyond = FALSE;
568    bool unpack_only_one = (symptr->flags & FLAG_UNPACK_ONLY_ONE) != 0;
569
570    IV aiv;
571    UV auv;
572    NV anv;
573#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
574    long double aldouble;
575#endif
576
577    while (next_symbol(symptr)) {
578        datumtype = symptr->code;
579	/* do first one only unless in list context
580	   / is implemented by unpacking the count, then poping it from the
581	   stack, so must check that we're not in the middle of a /  */
582        if ( unpack_only_one
583	     && (SP - PL_stack_base == start_sp_offset + 1)
584	     && (datumtype != '/') )   /* XXX can this be omitted */
585            break;
586
587        switch( howlen = symptr->howlen ){
588        case e_no_len:
589	case e_number:
590	    len = symptr->length;
591	    break;
592        case e_star:
593	    len = strend - strbeg;	/* long enough */
594	    break;
595        }
596
597      redo_switch:
598        beyond = s >= strend;
599	switch(datumtype) {
600	default:
601	    Perl_croak(aTHX_ "Invalid type '%c' in unpack", (int)datumtype );
602
603	case '%':
604	    if (howlen == e_no_len)
605		len = 16;		/* len is not specified */
606	    checksum = len;
607	    cuv = 0;
608	    cdouble = 0;
609	    continue;
610	    break;
611	case '(':
612	{
613	    char *ss = s;		/* Move from register */
614            tempsym_t savsym = *symptr;
615            symptr->patend = savsym.grpend;
616            symptr->level++;
617	    PUTBACK;
618	    while (len--) {
619  	        symptr->patptr = savsym.grpbeg;
620 	        unpack_rec(symptr, ss, strbeg, strend, &ss );
621                if (ss == strend && savsym.howlen == e_star)
622		    break; /* No way to continue */
623	    }
624	    SPAGAIN;
625	    s = ss;
626            savsym.flags = symptr->flags;
627            *symptr = savsym;
628	    break;
629	}
630	case '@':
631	    if (len > strend - strrelbeg)
632		Perl_croak(aTHX_ "'@' outside of string in unpack");
633	    s = strrelbeg + len;
634	    break;
635 	case 'X' | TYPE_IS_SHRIEKING:
636 	    if (!len)			/* Avoid division by 0 */
637 		len = 1;
638 	    len = (s - strbeg) % len;
639 	    /* FALL THROUGH */
640	case 'X':
641	    if (len > s - strbeg)
642		Perl_croak(aTHX_ "'X' outside of string in unpack" );
643	    s -= len;
644	    break;
645 	case 'x' | TYPE_IS_SHRIEKING:
646 	    if (!len)			/* Avoid division by 0 */
647 		len = 1;
648 	    aint = (s - strbeg) % len;
649 	    if (aint)			/* Other portable ways? */
650 		len = len - aint;
651 	    else
652 		len = 0;
653 	    /* FALL THROUGH */
654	case 'x':
655	    if (len > strend - s)
656		Perl_croak(aTHX_ "'x' outside of string in unpack");
657	    s += len;
658	    break;
659	case '/':
660	    Perl_croak(aTHX_ "'/' must follow a numeric type in unpack");
661            break;
662	case 'A':
663	case 'Z':
664	case 'a':
665	    if (len > strend - s)
666		len = strend - s;
667	    if (checksum)
668		goto uchar_checksum;
669	    sv = NEWSV(35, len);
670	    sv_setpvn(sv, s, len);
671	    if (len > 0 && (datumtype == 'A' || datumtype == 'Z')) {
672		aptr = s;	/* borrow register */
673		if (datumtype == 'Z') {	/* 'Z' strips stuff after first null */
674		    s = SvPVX(sv);
675		    while (*s)
676			s++;
677		    if (howlen == e_star) /* exact for 'Z*' */
678		        len = s - SvPVX(sv) + 1;
679		}
680		else {		/* 'A' strips both nulls and spaces */
681		    s = SvPVX(sv) + len - 1;
682		    while (s >= SvPVX(sv) && (!*s || isSPACE(*s)))
683			s--;
684		    *++s = '\0';
685		}
686		SvCUR_set(sv, s - SvPVX(sv));
687		s = aptr;	/* unborrow register */
688	    }
689	    s += len;
690	    XPUSHs(sv_2mortal(sv));
691	    break;
692	case 'B':
693	case 'b':
694	    if (howlen == e_star || len > (strend - s) * 8)
695		len = (strend - s) * 8;
696	    if (checksum) {
697		if (!PL_bitcount) {
698		    Newz(601, PL_bitcount, 256, char);
699		    for (bits = 1; bits < 256; bits++) {
700			if (bits & 1)	PL_bitcount[bits]++;
701			if (bits & 2)	PL_bitcount[bits]++;
702			if (bits & 4)	PL_bitcount[bits]++;
703			if (bits & 8)	PL_bitcount[bits]++;
704			if (bits & 16)	PL_bitcount[bits]++;
705			if (bits & 32)	PL_bitcount[bits]++;
706			if (bits & 64)	PL_bitcount[bits]++;
707			if (bits & 128)	PL_bitcount[bits]++;
708		    }
709		}
710		while (len >= 8) {
711		    cuv += PL_bitcount[*(unsigned char*)s++];
712		    len -= 8;
713		}
714		if (len) {
715		    bits = *s;
716		    if (datumtype == 'b') {
717			while (len-- > 0) {
718			    if (bits & 1) cuv++;
719			    bits >>= 1;
720			}
721		    }
722		    else {
723			while (len-- > 0) {
724			    if (bits & 128) cuv++;
725			    bits <<= 1;
726			}
727		    }
728		}
729		break;
730	    }
731	    sv = NEWSV(35, len + 1);
732	    SvCUR_set(sv, len);
733	    SvPOK_on(sv);
734	    str = SvPVX(sv);
735	    if (datumtype == 'b') {
736		aint = len;
737		for (len = 0; len < aint; len++) {
738		    if (len & 7)		/*SUPPRESS 595*/
739			bits >>= 1;
740		    else
741			bits = *s++;
742		    *str++ = '0' + (bits & 1);
743		}
744	    }
745	    else {
746		aint = len;
747		for (len = 0; len < aint; len++) {
748		    if (len & 7)
749			bits <<= 1;
750		    else
751			bits = *s++;
752		    *str++ = '0' + ((bits & 128) != 0);
753		}
754	    }
755	    *str = '\0';
756	    XPUSHs(sv_2mortal(sv));
757	    break;
758	case 'H':
759	case 'h':
760	    if (howlen == e_star || len > (strend - s) * 2)
761		len = (strend - s) * 2;
762	    sv = NEWSV(35, len + 1);
763	    SvCUR_set(sv, len);
764	    SvPOK_on(sv);
765	    str = SvPVX(sv);
766	    if (datumtype == 'h') {
767		aint = len;
768		for (len = 0; len < aint; len++) {
769		    if (len & 1)
770			bits >>= 4;
771		    else
772			bits = *s++;
773		    *str++ = PL_hexdigit[bits & 15];
774		}
775	    }
776	    else {
777		aint = len;
778		for (len = 0; len < aint; len++) {
779		    if (len & 1)
780			bits <<= 4;
781		    else
782			bits = *s++;
783		    *str++ = PL_hexdigit[(bits >> 4) & 15];
784		}
785	    }
786	    *str = '\0';
787	    XPUSHs(sv_2mortal(sv));
788	    break;
789	case 'c':
790	    if (len > strend - s)
791		len = strend - s;
792	    if (checksum) {
793		while (len-- > 0) {
794		    aint = *s++;
795		    if (aint >= 128)	/* fake up signed chars */
796			aint -= 256;
797		    if (checksum > bits_in_uv)
798			cdouble += (NV)aint;
799		    else
800			cuv += aint;
801		}
802	    }
803	    else {
804                if (len && unpack_only_one)
805                    len = 1;
806		EXTEND(SP, len);
807		EXTEND_MORTAL(len);
808		while (len-- > 0) {
809		    aint = *s++;
810		    if (aint >= 128)	/* fake up signed chars */
811			aint -= 256;
812		    sv = NEWSV(36, 0);
813		    sv_setiv(sv, (IV)aint);
814		    PUSHs(sv_2mortal(sv));
815		}
816	    }
817	    break;
818	case 'C':
819	unpack_C: /* unpack U will jump here if not UTF-8 */
820            if (len == 0) {
821                symptr->flags &= ~FLAG_UNPACK_DO_UTF8;
822		break;
823	    }
824	    if (len > strend - s)
825		len = strend - s;
826	    if (checksum) {
827	      uchar_checksum:
828		while (len-- > 0) {
829		    auint = *s++ & 255;
830		    cuv += auint;
831		}
832	    }
833	    else {
834                if (len && unpack_only_one)
835                    len = 1;
836		EXTEND(SP, len);
837		EXTEND_MORTAL(len);
838		while (len-- > 0) {
839		    auint = *s++ & 255;
840		    sv = NEWSV(37, 0);
841		    sv_setiv(sv, (IV)auint);
842		    PUSHs(sv_2mortal(sv));
843		}
844	    }
845	    break;
846	case 'U':
847	    if (len == 0) {
848                symptr->flags |= FLAG_UNPACK_DO_UTF8;
849		break;
850	    }
851	    if ((symptr->flags & FLAG_UNPACK_DO_UTF8) == 0)
852		 goto unpack_C;
853	    if (len > strend - s)
854		len = strend - s;
855	    if (checksum) {
856		while (len-- > 0 && s < strend) {
857		    STRLEN alen;
858		    auint = NATIVE_TO_UNI(utf8n_to_uvchr((U8*)s, strend - s, &alen, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANYUV));
859		    along = alen;
860		    s += along;
861		    if (checksum > bits_in_uv)
862			cdouble += (NV)auint;
863		    else
864			cuv += auint;
865		}
866	    }
867	    else {
868                if (len && unpack_only_one)
869                    len = 1;
870		EXTEND(SP, len);
871		EXTEND_MORTAL(len);
872		while (len-- > 0 && s < strend) {
873		    STRLEN alen;
874		    auint = NATIVE_TO_UNI(utf8n_to_uvchr((U8*)s, strend - s, &alen, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANYUV));
875		    along = alen;
876		    s += along;
877		    sv = NEWSV(37, 0);
878		    sv_setuv(sv, (UV)auint);
879		    PUSHs(sv_2mortal(sv));
880		}
881	    }
882	    break;
883	case 's' | TYPE_IS_SHRIEKING:
884#if SHORTSIZE != SIZE16
885	    along = (strend - s) / sizeof(short);
886	    if (len > along)
887		len = along;
888	    if (checksum) {
889		short ashort;
890		while (len-- > 0) {
891		     COPYNN(s, &ashort, sizeof(short));
892		      s += sizeof(short);
893		      if (checksum > bits_in_uv)
894			  cdouble += (NV)ashort;
895		      else
896			  cuv += ashort;
897
898		}
899	    }
900	    else {
901		short ashort;
902                if (len && unpack_only_one)
903                    len = 1;
904		EXTEND(SP, len);
905		EXTEND_MORTAL(len);
906		while (len-- > 0) {
907		    COPYNN(s, &ashort, sizeof(short));
908		    s += sizeof(short);
909		    sv = NEWSV(38, 0);
910		    sv_setiv(sv, (IV)ashort);
911		    PUSHs(sv_2mortal(sv));
912		}
913	    }
914	    break;
915#else
916	    /* Fallthrough! */
917#endif
918	case 's':
919	    along = (strend - s) / SIZE16;
920	    if (len > along)
921		len = along;
922	    if (checksum) {
923      		while (len-- > 0) {
924		    COPY16(s, &ashort);
925#if SHORTSIZE > SIZE16
926		    if (ashort > 32767)
927			ashort -= 65536;
928#endif
929		    s += SIZE16;
930		    if (checksum > bits_in_uv)
931			cdouble += (NV)ashort;
932		    else
933			cuv += ashort;
934		}
935	    }
936	    else {
937                if (len && unpack_only_one)
938                    len = 1;
939		EXTEND(SP, len);
940		EXTEND_MORTAL(len);
941
942		while (len-- > 0) {
943		    COPY16(s, &ashort);
944#if SHORTSIZE > SIZE16
945		    if (ashort > 32767)
946			ashort -= 65536;
947#endif
948		    s += SIZE16;
949		    sv = NEWSV(38, 0);
950		    sv_setiv(sv, (IV)ashort);
951		    PUSHs(sv_2mortal(sv));
952		}
953	    }
954	    break;
955	case 'S' | TYPE_IS_SHRIEKING:
956#if SHORTSIZE != SIZE16
957	    along = (strend - s) / sizeof(unsigned short);
958	    if (len > along)
959		len = along;
960	    if (checksum) {
961		unsigned short aushort;
962		while (len-- > 0) {
963		    COPYNN(s, &aushort, sizeof(unsigned short));
964		    s += sizeof(unsigned short);
965		    if (checksum > bits_in_uv)
966			cdouble += (NV)aushort;
967		    else
968			cuv += aushort;
969		}
970	    }
971	    else {
972                if (len && unpack_only_one)
973                    len = 1;
974		EXTEND(SP, len);
975		EXTEND_MORTAL(len);
976		while (len-- > 0) {
977  		    unsigned short aushort;
978		    COPYNN(s, &aushort, sizeof(unsigned short));
979		    s += sizeof(unsigned short);
980		    sv = NEWSV(39, 0);
981		    sv_setiv(sv, (UV)aushort);
982		    PUSHs(sv_2mortal(sv));
983		}
984	    }
985	    break;
986#else
987            /* Fallhrough! */
988#endif
989	case 'v':
990	case 'n':
991	case 'S':
992	    along = (strend - s) / SIZE16;
993	    if (len > along)
994		len = along;
995	    if (checksum) {
996		while (len-- > 0) {
997		    COPY16(s, &aushort);
998		    s += SIZE16;
999#ifdef HAS_NTOHS
1000		    if (datumtype == 'n')
1001		        aushort = PerlSock_ntohs(aushort);
1002#endif
1003#ifdef HAS_VTOHS
1004		    if (datumtype == 'v')
1005			aushort = vtohs(aushort);
1006#endif
1007		    if (checksum > bits_in_uv)
1008			cdouble += (NV)aushort;
1009		    else
1010		        cuv += aushort;
1011		}
1012	    }
1013	    else {
1014                if (len && unpack_only_one)
1015                    len = 1;
1016		EXTEND(SP, len);
1017		EXTEND_MORTAL(len);
1018		while (len-- > 0) {
1019		    COPY16(s, &aushort);
1020		    s += SIZE16;
1021		    sv = NEWSV(39, 0);
1022#ifdef HAS_NTOHS
1023		    if (datumtype == 'n')
1024			aushort = PerlSock_ntohs(aushort);
1025#endif
1026#ifdef HAS_VTOHS
1027		    if (datumtype == 'v')
1028			aushort = vtohs(aushort);
1029#endif
1030		    sv_setiv(sv, (UV)aushort);
1031		    PUSHs(sv_2mortal(sv));
1032		}
1033	    }
1034	    break;
1035	case 'i':
1036	case 'i' | TYPE_IS_SHRIEKING:
1037	    along = (strend - s) / sizeof(int);
1038	    if (len > along)
1039		len = along;
1040	    if (checksum) {
1041		while (len-- > 0) {
1042		    Copy(s, &aint, 1, int);
1043		    s += sizeof(int);
1044		    if (checksum > bits_in_uv)
1045			cdouble += (NV)aint;
1046		    else
1047			cuv += aint;
1048		}
1049	    }
1050	    else {
1051                if (len && unpack_only_one)
1052                    len = 1;
1053		EXTEND(SP, len);
1054		EXTEND_MORTAL(len);
1055		while (len-- > 0) {
1056		    Copy(s, &aint, 1, int);
1057		    s += sizeof(int);
1058		    sv = NEWSV(40, 0);
1059#ifdef __osf__
1060                    /* Without the dummy below unpack("i", pack("i",-1))
1061                     * return 0xFFffFFff instead of -1 for Digital Unix V4.0
1062                     * cc with optimization turned on.
1063		     *
1064		     * The bug was detected in
1065		     * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (V4.0E)
1066		     * with optimization (-O4) turned on.
1067		     * DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (V4.0B)
1068		     * does not have this problem even with -O4.
1069		     *
1070		     * This bug was reported as DECC_BUGS 1431
1071		     * and tracked internally as GEM_BUGS 7775.
1072		     *
1073		     * The bug is fixed in
1074		     * Tru64 UNIX V5.0:      Compaq C V6.1-006 or later
1075		     * UNIX V4.0F support:   DEC C V5.9-006 or later
1076		     * UNIX V4.0E support:   DEC C V5.8-011 or later
1077		     * and also in DTK.
1078		     *
1079		     * See also few lines later for the same bug.
1080		     */
1081                    (aint) ?
1082		    	sv_setiv(sv, (IV)aint) :
1083#endif
1084		    sv_setiv(sv, (IV)aint);
1085		    PUSHs(sv_2mortal(sv));
1086		}
1087	    }
1088	    break;
1089	case 'I':
1090	case 'I' | TYPE_IS_SHRIEKING:
1091	    along = (strend - s) / sizeof(unsigned int);
1092	    if (len > along)
1093		len = along;
1094	    if (checksum) {
1095		while (len-- > 0) {
1096		    Copy(s, &auint, 1, unsigned int);
1097		    s += sizeof(unsigned int);
1098		    if (checksum > bits_in_uv)
1099			cdouble += (NV)auint;
1100		    else
1101			cuv += auint;
1102		}
1103	    }
1104	    else {
1105                if (len && unpack_only_one)
1106                    len = 1;
1107		EXTEND(SP, len);
1108		EXTEND_MORTAL(len);
1109		while (len-- > 0) {
1110		    Copy(s, &auint, 1, unsigned int);
1111		    s += sizeof(unsigned int);
1112		    sv = NEWSV(41, 0);
1113#ifdef __osf__
1114                    /* Without the dummy below unpack("I", pack("I",0xFFFFFFFF))
1115                     * returns 1.84467440737096e+19 instead of 0xFFFFFFFF.
1116		     * See details few lines earlier. */
1117                    (auint) ?
1118		        sv_setuv(sv, (UV)auint) :
1119#endif
1120		    sv_setuv(sv, (UV)auint);
1121		    PUSHs(sv_2mortal(sv));
1122		}
1123	    }
1124	    break;
1125	case 'j':
1126	    along = (strend - s) / IVSIZE;
1127	    if (len > along)
1128		len = along;
1129	    if (checksum) {
1130		while (len-- > 0) {
1131		    Copy(s, &aiv, 1, IV);
1132		    s += IVSIZE;
1133		    if (checksum > bits_in_uv)
1134			cdouble += (NV)aiv;
1135		    else
1136			cuv += aiv;
1137		}
1138	    }
1139	    else {
1140                if (len && unpack_only_one)
1141                    len = 1;
1142		EXTEND(SP, len);
1143		EXTEND_MORTAL(len);
1144		while (len-- > 0) {
1145		    Copy(s, &aiv, 1, IV);
1146		    s += IVSIZE;
1147		    sv = NEWSV(40, 0);
1148		    sv_setiv(sv, aiv);
1149		    PUSHs(sv_2mortal(sv));
1150		}
1151	    }
1152	    break;
1153	case 'J':
1154	    along = (strend - s) / UVSIZE;
1155	    if (len > along)
1156		len = along;
1157	    if (checksum) {
1158		while (len-- > 0) {
1159		    Copy(s, &auv, 1, UV);
1160		    s += UVSIZE;
1161		    if (checksum > bits_in_uv)
1162			cdouble += (NV)auv;
1163		    else
1164			cuv += auv;
1165		}
1166	    }
1167	    else {
1168                if (len && unpack_only_one)
1169                    len = 1;
1170		EXTEND(SP, len);
1171		EXTEND_MORTAL(len);
1172		while (len-- > 0) {
1173		    Copy(s, &auv, 1, UV);
1174		    s += UVSIZE;
1175		    sv = NEWSV(41, 0);
1176		    sv_setuv(sv, auv);
1177		    PUSHs(sv_2mortal(sv));
1178		}
1179	    }
1180	    break;
1181	case 'l' | TYPE_IS_SHRIEKING:
1182#if LONGSIZE != SIZE32
1183	    along = (strend - s) / sizeof(long);
1184	    if (len > along)
1185		len = along;
1186	    if (checksum) {
1187		while (len-- > 0) {
1188		    COPYNN(s, &along, sizeof(long));
1189		    s += sizeof(long);
1190		    if (checksum > bits_in_uv)
1191			cdouble += (NV)along;
1192		    else
1193			cuv += along;
1194		}
1195	    }
1196	    else {
1197                if (len && unpack_only_one)
1198                    len = 1;
1199		EXTEND(SP, len);
1200		EXTEND_MORTAL(len);
1201		while (len-- > 0) {
1202		    COPYNN(s, &along, sizeof(long));
1203		    s += sizeof(long);
1204		    sv = NEWSV(42, 0);
1205		    sv_setiv(sv, (IV)along);
1206		    PUSHs(sv_2mortal(sv));
1207		}
1208	    }
1209	    break;
1210#else
1211	    /* Fallthrough! */
1212#endif
1213	case 'l':
1214	    along = (strend - s) / SIZE32;
1215	    if (len > along)
1216		len = along;
1217	    if (checksum) {
1218		while (len-- > 0) {
1219#if LONGSIZE > SIZE32 && INTSIZE == SIZE32
1220		    I32 along;
1221#endif
1222		    COPY32(s, &along);
1223#if LONGSIZE > SIZE32
1224		    if (along > 2147483647)
1225		        along -= 4294967296;
1226#endif
1227		    s += SIZE32;
1228		    if (checksum > bits_in_uv)
1229			cdouble += (NV)along;
1230		    else
1231			cuv += along;
1232		}
1233	    }
1234	    else {
1235                if (len && unpack_only_one)
1236                    len = 1;
1237		EXTEND(SP, len);
1238		EXTEND_MORTAL(len);
1239		while (len-- > 0) {
1240#if LONGSIZE > SIZE32 && INTSIZE == SIZE32
1241		    I32 along;
1242#endif
1243		    COPY32(s, &along);
1244#if LONGSIZE > SIZE32
1245		    if (along > 2147483647)
1246		        along -= 4294967296;
1247#endif
1248		    s += SIZE32;
1249		    sv = NEWSV(42, 0);
1250		    sv_setiv(sv, (IV)along);
1251		    PUSHs(sv_2mortal(sv));
1252		}
1253	    }
1254	    break;
1255	case 'L' | TYPE_IS_SHRIEKING:
1256#if LONGSIZE != SIZE32
1257	    along = (strend - s) / sizeof(unsigned long);
1258	    if (len > along)
1259		len = along;
1260	    if (checksum) {
1261		while (len-- > 0) {
1262		    unsigned long aulong;
1263		    COPYNN(s, &aulong, sizeof(unsigned long));
1264		    s += sizeof(unsigned long);
1265		    if (checksum > bits_in_uv)
1266			cdouble += (NV)aulong;
1267		    else
1268			cuv += aulong;
1269		}
1270	    }
1271	    else {
1272                if (len && unpack_only_one)
1273                    len = 1;
1274		EXTEND(SP, len);
1275		EXTEND_MORTAL(len);
1276		while (len-- > 0) {
1277		    unsigned long aulong;
1278		    COPYNN(s, &aulong, sizeof(unsigned long));
1279		    s += sizeof(unsigned long);
1280		    sv = NEWSV(43, 0);
1281		    sv_setuv(sv, (UV)aulong);
1282		    PUSHs(sv_2mortal(sv));
1283		}
1284	    }
1285	    break;
1286#else
1287            /* Fall through! */
1288#endif
1289	case 'V':
1290	case 'N':
1291	case 'L':
1292	    along = (strend - s) / SIZE32;
1293	    if (len > along)
1294		len = along;
1295	    if (checksum) {
1296		while (len-- > 0) {
1297		    COPY32(s, &aulong);
1298		    s += SIZE32;
1299#ifdef HAS_NTOHL
1300		    if (datumtype == 'N')
1301			aulong = PerlSock_ntohl(aulong);
1302#endif
1303#ifdef HAS_VTOHL
1304		    if (datumtype == 'V')
1305			aulong = vtohl(aulong);
1306#endif
1307		    if (checksum > bits_in_uv)
1308			cdouble += (NV)aulong;
1309		    else
1310			cuv += aulong;
1311		}
1312	    }
1313	    else {
1314                if (len && unpack_only_one)
1315                    len = 1;
1316		EXTEND(SP, len);
1317		EXTEND_MORTAL(len);
1318		while (len-- > 0) {
1319		    COPY32(s, &aulong);
1320		    s += SIZE32;
1321#ifdef HAS_NTOHL
1322		    if (datumtype == 'N')
1323			aulong = PerlSock_ntohl(aulong);
1324#endif
1325#ifdef HAS_VTOHL
1326		    if (datumtype == 'V')
1327			aulong = vtohl(aulong);
1328#endif
1329		    sv = NEWSV(43, 0);
1330		    sv_setuv(sv, (UV)aulong);
1331		    PUSHs(sv_2mortal(sv));
1332		}
1333	    }
1334	    break;
1335	case 'p':
1336	    along = (strend - s) / sizeof(char*);
1337	    if (len > along)
1338		len = along;
1339	    EXTEND(SP, len);
1340	    EXTEND_MORTAL(len);
1341	    while (len-- > 0) {
1342		if (sizeof(char*) > strend - s)
1343		    break;
1344		else {
1345		    Copy(s, &aptr, 1, char*);
1346		    s += sizeof(char*);
1347		}
1348		sv = NEWSV(44, 0);
1349		if (aptr)
1350		    sv_setpv(sv, aptr);
1351		PUSHs(sv_2mortal(sv));
1352	    }
1353	    break;
1354	case 'w':
1355            if (len && unpack_only_one)
1356                len = 1;
1357	    EXTEND(SP, len);
1358	    EXTEND_MORTAL(len);
1359	    {
1360		UV auv = 0;
1361		U32 bytes = 0;
1362
1363		while ((len > 0) && (s < strend)) {
1364		    auv = (auv << 7) | (*s & 0x7f);
1365		    /* UTF8_IS_XXXXX not right here - using constant 0x80 */
1366		    if ((U8)(*s++) < 0x80) {
1367			bytes = 0;
1368			sv = NEWSV(40, 0);
1369			sv_setuv(sv, auv);
1370			PUSHs(sv_2mortal(sv));
1371			len--;
1372			auv = 0;
1373		    }
1374		    else if (++bytes >= sizeof(UV)) {	/* promote to string */
1375			char *t;
1376			STRLEN n_a;
1377
1378			sv = Perl_newSVpvf(aTHX_ "%.*"UVf, (int)TYPE_DIGITS(UV), auv);
1379			while (s < strend) {
1380			    sv = mul128(sv, (U8)(*s & 0x7f));
1381			    if (!(*s++ & 0x80)) {
1382				bytes = 0;
1383				break;
1384			    }
1385			}
1386			t = SvPV(sv, n_a);
1387			while (*t == '0')
1388			    t++;
1389			sv_chop(sv, t);
1390			PUSHs(sv_2mortal(sv));
1391			len--;
1392			auv = 0;
1393		    }
1394		}
1395		if ((s >= strend) && bytes)
1396		    Perl_croak(aTHX_ "Unterminated compressed integer in unpack");
1397	    }
1398	    break;
1399	case 'P':
1400	    if (symptr->howlen == e_star)
1401	        Perl_croak(aTHX_ "'P' must have an explicit size in unpack");
1402	    EXTEND(SP, 1);
1403	    if (sizeof(char*) > strend - s)
1404		break;
1405	    else {
1406		Copy(s, &aptr, 1, char*);
1407		s += sizeof(char*);
1408	    }
1409	    sv = NEWSV(44, 0);
1410	    if (aptr)
1411		sv_setpvn(sv, aptr, len);
1412	    PUSHs(sv_2mortal(sv));
1413	    break;
1414#ifdef HAS_QUAD
1415	case 'q':
1416	    along = (strend - s) / sizeof(Quad_t);
1417	    if (len > along)
1418		len = along;
1419	    if (checksum) {
1420		while (len-- > 0) {
1421		    Copy(s, &aquad, 1, Quad_t);
1422		    s += sizeof(Quad_t);
1423		    if (checksum > bits_in_uv)
1424			cdouble += (NV)aquad;
1425		    else
1426			cuv += aquad;
1427		}
1428	    }
1429            else {
1430                if (len && unpack_only_one)
1431                    len = 1;
1432                EXTEND(SP, len);
1433                EXTEND_MORTAL(len);
1434                while (len-- > 0) {
1435                    if (s + sizeof(Quad_t) > strend)
1436                        aquad = 0;
1437                    else {
1438		        Copy(s, &aquad, 1, Quad_t);
1439		        s += sizeof(Quad_t);
1440                    }
1441                    sv = NEWSV(42, 0);
1442                    if (aquad >= IV_MIN && aquad <= IV_MAX)
1443		        sv_setiv(sv, (IV)aquad);
1444                    else
1445                        sv_setnv(sv, (NV)aquad);
1446                    PUSHs(sv_2mortal(sv));
1447                }
1448            }
1449	    break;
1450	case 'Q':
1451	    along = (strend - s) / sizeof(Uquad_t);
1452	    if (len > along)
1453		len = along;
1454	    if (checksum) {
1455		while (len-- > 0) {
1456		    Copy(s, &auquad, 1, Uquad_t);
1457		    s += sizeof(Uquad_t);
1458		    if (checksum > bits_in_uv)
1459			cdouble += (NV)auquad;
1460		    else
1461			cuv += auquad;
1462		}
1463	    }
1464            else {
1465                if (len && unpack_only_one)
1466                    len = 1;
1467                EXTEND(SP, len);
1468                EXTEND_MORTAL(len);
1469                while (len-- > 0) {
1470                    if (s + sizeof(Uquad_t) > strend)
1471                        auquad = 0;
1472                    else {
1473                        Copy(s, &auquad, 1, Uquad_t);
1474                        s += sizeof(Uquad_t);
1475                    }
1476                    sv = NEWSV(43, 0);
1477                    if (auquad <= UV_MAX)
1478                        sv_setuv(sv, (UV)auquad);
1479                    else
1480		    sv_setnv(sv, (NV)auquad);
1481                    PUSHs(sv_2mortal(sv));
1482                }
1483            }
1484	    break;
1485#endif
1486	/* float and double added gnb@melba.bby.oz.au 22/11/89 */
1487	case 'f':
1488	    along = (strend - s) / sizeof(float);
1489	    if (len > along)
1490		len = along;
1491	    if (checksum) {
1492		while (len-- > 0) {
1493		    Copy(s, &afloat, 1, float);
1494		    s += sizeof(float);
1495		    cdouble += afloat;
1496		}
1497	    }
1498	    else {
1499                if (len && unpack_only_one)
1500                    len = 1;
1501		EXTEND(SP, len);
1502		EXTEND_MORTAL(len);
1503		while (len-- > 0) {
1504		    Copy(s, &afloat, 1, float);
1505		    s += sizeof(float);
1506		    sv = NEWSV(47, 0);
1507		    sv_setnv(sv, (NV)afloat);
1508		    PUSHs(sv_2mortal(sv));
1509		}
1510	    }
1511	    break;
1512	case 'd':
1513	    along = (strend - s) / sizeof(double);
1514	    if (len > along)
1515		len = along;
1516	    if (checksum) {
1517		while (len-- > 0) {
1518		    Copy(s, &adouble, 1, double);
1519		    s += sizeof(double);
1520		    cdouble += adouble;
1521		}
1522	    }
1523	    else {
1524                if (len && unpack_only_one)
1525                    len = 1;
1526		EXTEND(SP, len);
1527		EXTEND_MORTAL(len);
1528		while (len-- > 0) {
1529		    Copy(s, &adouble, 1, double);
1530		    s += sizeof(double);
1531		    sv = NEWSV(48, 0);
1532		    sv_setnv(sv, (NV)adouble);
1533		    PUSHs(sv_2mortal(sv));
1534		}
1535	    }
1536	    break;
1537	case 'F':
1538	    along = (strend - s) / NVSIZE;
1539	    if (len > along)
1540		len = along;
1541	    if (checksum) {
1542		while (len-- > 0) {
1543		    Copy(s, &anv, 1, NV);
1544		    s += NVSIZE;
1545		    cdouble += anv;
1546		}
1547	    }
1548	    else {
1549                if (len && unpack_only_one)
1550                    len = 1;
1551		EXTEND(SP, len);
1552		EXTEND_MORTAL(len);
1553		while (len-- > 0) {
1554		    Copy(s, &anv, 1, NV);
1555		    s += NVSIZE;
1556		    sv = NEWSV(48, 0);
1557		    sv_setnv(sv, anv);
1558		    PUSHs(sv_2mortal(sv));
1559		}
1560	    }
1561	    break;
1562#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
1563	case 'D':
1564	    along = (strend - s) / LONG_DOUBLESIZE;
1565	    if (len > along)
1566		len = along;
1567	    if (checksum) {
1568		while (len-- > 0) {
1569		    Copy(s, &aldouble, 1, long double);
1570		    s += LONG_DOUBLESIZE;
1571		    cdouble += aldouble;
1572		}
1573	    }
1574	    else {
1575                if (len && unpack_only_one)
1576                    len = 1;
1577		EXTEND(SP, len);
1578		EXTEND_MORTAL(len);
1579		while (len-- > 0) {
1580		    Copy(s, &aldouble, 1, long double);
1581		    s += LONG_DOUBLESIZE;
1582		    sv = NEWSV(48, 0);
1583		    sv_setnv(sv, (NV)aldouble);
1584		    PUSHs(sv_2mortal(sv));
1585		}
1586	    }
1587	    break;
1588#endif
1589	case 'u':
1590	    /* MKS:
1591	     * Initialise the decode mapping.  By using a table driven
1592             * algorithm, the code will be character-set independent
1593             * (and just as fast as doing character arithmetic)
1594             */
1595            if (PL_uudmap['M'] == 0) {
1596                int i;
1597
1598                for (i = 0; i < sizeof(PL_uuemap); i += 1)
1599                    PL_uudmap[(U8)PL_uuemap[i]] = i;
1600                /*
1601                 * Because ' ' and '`' map to the same value,
1602                 * we need to decode them both the same.
1603                 */
1604                PL_uudmap[' '] = 0;
1605            }
1606
1607	    along = (strend - s) * 3 / 4;
1608	    sv = NEWSV(42, along);
1609	    if (along)
1610		SvPOK_on(sv);
1611	    while (s < strend && *s > ' ' && ISUUCHAR(*s)) {
1612		I32 a, b, c, d;
1613		char hunk[4];
1614
1615		hunk[3] = '\0';
1616		len = PL_uudmap[*(U8*)s++] & 077;
1617		while (len > 0) {
1618		    if (s < strend && ISUUCHAR(*s))
1619			a = PL_uudmap[*(U8*)s++] & 077;
1620 		    else
1621 			a = 0;
1622		    if (s < strend && ISUUCHAR(*s))
1623			b = PL_uudmap[*(U8*)s++] & 077;
1624 		    else
1625 			b = 0;
1626		    if (s < strend && ISUUCHAR(*s))
1627			c = PL_uudmap[*(U8*)s++] & 077;
1628 		    else
1629 			c = 0;
1630		    if (s < strend && ISUUCHAR(*s))
1631			d = PL_uudmap[*(U8*)s++] & 077;
1632		    else
1633			d = 0;
1634		    hunk[0] = (char)((a << 2) | (b >> 4));
1635		    hunk[1] = (char)((b << 4) | (c >> 2));
1636		    hunk[2] = (char)((c << 6) | d);
1637		    sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
1638		    len -= 3;
1639		}
1640		if (*s == '\n')
1641		    s++;
1642		else	/* possible checksum byte */
1643		    if (s + 1 < strend && s[1] == '\n')
1644		        s += 2;
1645	    }
1646	    XPUSHs(sv_2mortal(sv));
1647	    break;
1648	}
1649
1650	if (checksum) {
1651	    sv = NEWSV(42, 0);
1652	    if (strchr("fFdD", datumtype) ||
1653	      (checksum > bits_in_uv &&
1654	       strchr("csSiIlLnNUvVqQjJ", datumtype&0xFF)) ) {
1655		NV trouble;
1656
1657                adouble = (NV) (1 << (checksum & 15));
1658		while (checksum >= 16) {
1659		    checksum -= 16;
1660		    adouble *= 65536.0;
1661		}
1662		while (cdouble < 0.0)
1663		    cdouble += adouble;
1664		cdouble = Perl_modf(cdouble / adouble, &trouble) * adouble;
1665		sv_setnv(sv, cdouble);
1666	    }
1667	    else {
1668		if (checksum < bits_in_uv) {
1669		    UV mask = ((UV)1 << checksum) - 1;
1670		    cuv &= mask;
1671		}
1672		sv_setuv(sv, cuv);
1673	    }
1674	    XPUSHs(sv_2mortal(sv));
1675	    checksum = 0;
1676	}
1677
1678        if (symptr->flags & FLAG_SLASH){
1679            if (SP - PL_stack_base - start_sp_offset <= 0)
1680                Perl_croak(aTHX_ "'/' must follow a numeric type in unpack");
1681            if( next_symbol(symptr) ){
1682              if( symptr->howlen == e_number )
1683		Perl_croak(aTHX_ "Count after length/code in unpack" );
1684              if( beyond ){
1685         	/* ...end of char buffer then no decent length available */
1686		Perl_croak(aTHX_ "length/code after end of string in unpack" );
1687              } else {
1688         	/* take top of stack (hope it's numeric) */
1689                len = POPi;
1690                if( len < 0 )
1691                    Perl_croak(aTHX_ "Negative '/' count in unpack" );
1692              }
1693            } else {
1694		Perl_croak(aTHX_ "Code missing after '/' in unpack" );
1695            }
1696            datumtype = symptr->code;
1697	    goto redo_switch;
1698        }
1699    }
1700
1701    if (new_s)
1702	*new_s = s;
1703    PUTBACK;
1704    return SP - PL_stack_base - start_sp_offset;
1705}
1706
1707PP(pp_unpack)
1708{
1709    dSP;
1710    dPOPPOPssrl;
1711    I32 gimme = GIMME_V;
1712    STRLEN llen;
1713    STRLEN rlen;
1714    register char *pat = SvPV(left, llen);
1715#ifdef PACKED_IS_OCTETS
1716    /* Packed side is assumed to be octets - so force downgrade if it
1717       has been UTF-8 encoded by accident
1718     */
1719    register char *s = SvPVbyte(right, rlen);
1720#else
1721    register char *s = SvPV(right, rlen);
1722#endif
1723    char *strend = s + rlen;
1724    register char *patend = pat + llen;
1725    register I32 cnt;
1726
1727    PUTBACK;
1728    cnt = unpackstring(pat, patend, s, strend,
1729		     ((gimme == G_SCALAR) ? FLAG_UNPACK_ONLY_ONE : 0)
1730		     | (DO_UTF8(right) ? FLAG_UNPACK_DO_UTF8 : 0));
1731
1732    SPAGAIN;
1733    if ( !cnt && gimme == G_SCALAR )
1734       PUSHs(&PL_sv_undef);
1735    RETURN;
1736}
1737
1738STATIC void
1739S_doencodes(pTHX_ register SV *sv, register char *s, register I32 len)
1740{
1741    char hunk[5];
1742
1743    *hunk = PL_uuemap[len];
1744    sv_catpvn(sv, hunk, 1);
1745    hunk[4] = '\0';
1746    while (len > 2) {
1747	hunk[0] = PL_uuemap[(077 & (*s >> 2))];
1748	hunk[1] = PL_uuemap[(077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017)))];
1749	hunk[2] = PL_uuemap[(077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03)))];
1750	hunk[3] = PL_uuemap[(077 & (s[2] & 077))];
1751	sv_catpvn(sv, hunk, 4);
1752	s += 3;
1753	len -= 3;
1754    }
1755    if (len > 0) {
1756	char r = (len > 1 ? s[1] : '\0');
1757	hunk[0] = PL_uuemap[(077 & (*s >> 2))];
1758	hunk[1] = PL_uuemap[(077 & (((*s << 4) & 060) | ((r >> 4) & 017)))];
1759	hunk[2] = PL_uuemap[(077 & ((r << 2) & 074))];
1760	hunk[3] = PL_uuemap[0];
1761	sv_catpvn(sv, hunk, 4);
1762    }
1763    sv_catpvn(sv, "\n", 1);
1764}
1765
1766STATIC SV *
1767S_is_an_int(pTHX_ char *s, STRLEN l)
1768{
1769  STRLEN	 n_a;
1770  SV             *result = newSVpvn(s, l);
1771  char           *result_c = SvPV(result, n_a);	/* convenience */
1772  char           *out = result_c;
1773  bool            skip = 1;
1774  bool            ignore = 0;
1775
1776  while (*s) {
1777    switch (*s) {
1778    case ' ':
1779      break;
1780    case '+':
1781      if (!skip) {
1782	SvREFCNT_dec(result);
1783	return (NULL);
1784      }
1785      break;
1786    case '0':
1787    case '1':
1788    case '2':
1789    case '3':
1790    case '4':
1791    case '5':
1792    case '6':
1793    case '7':
1794    case '8':
1795    case '9':
1796      skip = 0;
1797      if (!ignore) {
1798	*(out++) = *s;
1799      }
1800      break;
1801    case '.':
1802      ignore = 1;
1803      break;
1804    default:
1805      SvREFCNT_dec(result);
1806      return (NULL);
1807    }
1808    s++;
1809  }
1810  *(out++) = '\0';
1811  SvCUR_set(result, out - result_c);
1812  return (result);
1813}
1814
1815/* pnum must be '\0' terminated */
1816STATIC int
1817S_div128(pTHX_ SV *pnum, bool *done)
1818{
1819  STRLEN          len;
1820  char           *s = SvPV(pnum, len);
1821  int             m = 0;
1822  int             r = 0;
1823  char           *t = s;
1824
1825  *done = 1;
1826  while (*t) {
1827    int             i;
1828
1829    i = m * 10 + (*t - '0');
1830    m = i & 0x7F;
1831    r = (i >> 7);		/* r < 10 */
1832    if (r) {
1833      *done = 0;
1834    }
1835    *(t++) = '0' + r;
1836  }
1837  *(t++) = '\0';
1838  SvCUR_set(pnum, (STRLEN) (t - s));
1839  return (m);
1840}
1841
1842
1843
1844/*
1845=for apidoc pack_cat
1846
1847The engine implementing pack() Perl function. Note: parameters next_in_list and
1848flags are not used. This call should not be used; use packlist instead.
1849
1850=cut */
1851
1852
1853void
1854Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beglist, SV **endlist, SV ***next_in_list, U32 flags)
1855{
1856    tempsym_t sym = { 0 };
1857    sym.patptr = pat;
1858    sym.patend = patend;
1859    sym.flags  = FLAG_PACK;
1860
1861    (void)pack_rec( cat, &sym, beglist, endlist );
1862}
1863
1864
1865/*
1866=for apidoc packlist
1867
1868The engine implementing pack() Perl function.
1869
1870=cut */
1871
1872
1873void
1874Perl_packlist(pTHX_ SV *cat, char *pat, register char *patend, register SV **beglist, SV **endlist )
1875{
1876    tempsym_t sym = { 0 };
1877    sym.patptr = pat;
1878    sym.patend = patend;
1879    sym.flags  = FLAG_PACK;
1880
1881    (void)pack_rec( cat, &sym, beglist, endlist );
1882}
1883
1884
1885STATIC
1886SV **
1887S_pack_rec(pTHX_ SV *cat, register tempsym_t* symptr, register SV **beglist, SV **endlist )
1888{
1889    register I32 items;
1890    STRLEN fromlen;
1891    register I32 len = 0;
1892    SV *fromstr;
1893    /*SUPPRESS 442*/
1894    static char null10[] = {0,0,0,0,0,0,0,0,0,0};
1895    static char *space10 = "          ";
1896    bool found;
1897
1898    /* These must not be in registers: */
1899    char achar;
1900    I16 ashort;
1901    int aint;
1902    unsigned int auint;
1903    I32 along;
1904    U32 aulong;
1905    IV aiv;
1906    UV auv;
1907    NV anv;
1908#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
1909    long double aldouble;
1910#endif
1911#ifdef HAS_QUAD
1912    Quad_t aquad;
1913    Uquad_t auquad;
1914#endif
1915    char *aptr;
1916    float afloat;
1917    double adouble;
1918    int strrelbeg = SvCUR(cat);
1919    tempsym_t lookahead;
1920
1921    items = endlist - beglist;
1922    found = next_symbol( symptr );
1923
1924#ifndef PACKED_IS_OCTETS
1925    if (symptr->level == 0 && found && symptr->code == 'U' ){
1926	SvUTF8_on(cat);
1927    }
1928#endif
1929
1930    while (found) {
1931	SV *lengthcode = Nullsv;
1932#define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *beglist++ : &PL_sv_no)
1933
1934        I32 datumtype = symptr->code;
1935        howlen_t howlen;
1936
1937        switch( howlen = symptr->howlen ){
1938        case e_no_len:
1939	case e_number:
1940	    len = symptr->length;
1941	    break;
1942        case e_star:
1943	    len = strchr("@Xxu", datumtype) ? 0 : items;
1944	    break;
1945        }
1946
1947        /* Look ahead for next symbol. Do we have code/code? */
1948        lookahead = *symptr;
1949        found = next_symbol(&lookahead);
1950	if ( symptr->flags & FLAG_SLASH ) {
1951	    if (found){
1952 	        if ( 0 == strchr( "aAZ", lookahead.code ) ||
1953                     e_star != lookahead.howlen )
1954 		    Perl_croak(aTHX_ "'/' must be followed by 'a*', 'A*' or 'Z*' in pack");
1955	        lengthcode = sv_2mortal(newSViv(sv_len(items > 0
1956						   ? *beglist : &PL_sv_no)
1957                                           + (lookahead.code == 'Z' ? 1 : 0)));
1958	    } else {
1959 		Perl_croak(aTHX_ "Code missing after '/' in pack");
1960            }
1961	}
1962
1963	switch(datumtype) {
1964	default:
1965	    Perl_croak(aTHX_ "Invalid type '%c' in pack", (int)datumtype);
1966	case '%':
1967	    Perl_croak(aTHX_ "'%%' may not be used in pack");
1968	case '@':
1969	    len += strrelbeg - SvCUR(cat);
1970	    if (len > 0)
1971		goto grow;
1972	    len = -len;
1973	    if (len > 0)
1974		goto shrink;
1975	    break;
1976	case '(':
1977	{
1978            tempsym_t savsym = *symptr;
1979            symptr->patend = savsym.grpend;
1980            symptr->level++;
1981	    while (len--) {
1982  	        symptr->patptr = savsym.grpbeg;
1983		beglist = pack_rec(cat, symptr, beglist, endlist );
1984		if (savsym.howlen == e_star && beglist == endlist)
1985		    break;		/* No way to continue */
1986	    }
1987            lookahead.flags = symptr->flags;
1988            *symptr = savsym;
1989	    break;
1990	}
1991	case 'X' | TYPE_IS_SHRIEKING:
1992	    if (!len)			/* Avoid division by 0 */
1993		len = 1;
1994	    len = (SvCUR(cat)) % len;
1995	    /* FALL THROUGH */
1996	case 'X':
1997	  shrink:
1998	    if ((I32)SvCUR(cat) < len)
1999		Perl_croak(aTHX_ "'X' outside of string in pack");
2000	    SvCUR(cat) -= len;
2001	    *SvEND(cat) = '\0';
2002	    break;
2003	case 'x' | TYPE_IS_SHRIEKING:
2004	    if (!len)			/* Avoid division by 0 */
2005		len = 1;
2006	    aint = (SvCUR(cat)) % len;
2007	    if (aint)			/* Other portable ways? */
2008		len = len - aint;
2009	    else
2010		len = 0;
2011	    /* FALL THROUGH */
2012
2013	case 'x':
2014	  grow:
2015	    while (len >= 10) {
2016		sv_catpvn(cat, null10, 10);
2017		len -= 10;
2018	    }
2019	    sv_catpvn(cat, null10, len);
2020	    break;
2021	case 'A':
2022	case 'Z':
2023	case 'a':
2024	    fromstr = NEXTFROM;
2025	    aptr = SvPV(fromstr, fromlen);
2026	    if (howlen == e_star) {
2027		len = fromlen;
2028		if (datumtype == 'Z')
2029		    ++len;
2030	    }
2031	    if ((I32)fromlen >= len) {
2032		sv_catpvn(cat, aptr, len);
2033		if (datumtype == 'Z')
2034		    *(SvEND(cat)-1) = '\0';
2035	    }
2036	    else {
2037		sv_catpvn(cat, aptr, fromlen);
2038		len -= fromlen;
2039		if (datumtype == 'A') {
2040		    while (len >= 10) {
2041			sv_catpvn(cat, space10, 10);
2042			len -= 10;
2043		    }
2044		    sv_catpvn(cat, space10, len);
2045		}
2046		else {
2047		    while (len >= 10) {
2048			sv_catpvn(cat, null10, 10);
2049			len -= 10;
2050		    }
2051		    sv_catpvn(cat, null10, len);
2052		}
2053	    }
2054	    break;
2055	case 'B':
2056	case 'b':
2057	    {
2058		register char *str;
2059		I32 saveitems;
2060
2061		fromstr = NEXTFROM;
2062		saveitems = items;
2063		str = SvPV(fromstr, fromlen);
2064		if (howlen == e_star)
2065		    len = fromlen;
2066		aint = SvCUR(cat);
2067		SvCUR(cat) += (len+7)/8;
2068		SvGROW(cat, SvCUR(cat) + 1);
2069		aptr = SvPVX(cat) + aint;
2070		if (len > (I32)fromlen)
2071		    len = fromlen;
2072		aint = len;
2073		items = 0;
2074		if (datumtype == 'B') {
2075		    for (len = 0; len++ < aint;) {
2076			items |= *str++ & 1;
2077			if (len & 7)
2078			    items <<= 1;
2079			else {
2080			    *aptr++ = items & 0xff;
2081			    items = 0;
2082			}
2083		    }
2084		}
2085		else {
2086		    for (len = 0; len++ < aint;) {
2087			if (*str++ & 1)
2088			    items |= 128;
2089			if (len & 7)
2090			    items >>= 1;
2091			else {
2092			    *aptr++ = items & 0xff;
2093			    items = 0;
2094			}
2095		    }
2096		}
2097		if (aint & 7) {
2098		    if (datumtype == 'B')
2099			items <<= 7 - (aint & 7);
2100		    else
2101			items >>= 7 - (aint & 7);
2102		    *aptr++ = items & 0xff;
2103		}
2104		str = SvPVX(cat) + SvCUR(cat);
2105		while (aptr <= str)
2106		    *aptr++ = '\0';
2107
2108		items = saveitems;
2109	    }
2110	    break;
2111	case 'H':
2112	case 'h':
2113	    {
2114		register char *str;
2115		I32 saveitems;
2116
2117		fromstr = NEXTFROM;
2118		saveitems = items;
2119		str = SvPV(fromstr, fromlen);
2120		if (howlen == e_star)
2121		    len = fromlen;
2122		aint = SvCUR(cat);
2123		SvCUR(cat) += (len+1)/2;
2124		SvGROW(cat, SvCUR(cat) + 1);
2125		aptr = SvPVX(cat) + aint;
2126		if (len > (I32)fromlen)
2127		    len = fromlen;
2128		aint = len;
2129		items = 0;
2130		if (datumtype == 'H') {
2131		    for (len = 0; len++ < aint;) {
2132			if (isALPHA(*str))
2133			    items |= ((*str++ & 15) + 9) & 15;
2134			else
2135			    items |= *str++ & 15;
2136			if (len & 1)
2137			    items <<= 4;
2138			else {
2139			    *aptr++ = items & 0xff;
2140			    items = 0;
2141			}
2142		    }
2143		}
2144		else {
2145		    for (len = 0; len++ < aint;) {
2146			if (isALPHA(*str))
2147			    items |= (((*str++ & 15) + 9) & 15) << 4;
2148			else
2149			    items |= (*str++ & 15) << 4;
2150			if (len & 1)
2151			    items >>= 4;
2152			else {
2153			    *aptr++ = items & 0xff;
2154			    items = 0;
2155			}
2156		    }
2157		}
2158		if (aint & 1)
2159		    *aptr++ = items & 0xff;
2160		str = SvPVX(cat) + SvCUR(cat);
2161		while (aptr <= str)
2162		    *aptr++ = '\0';
2163
2164		items = saveitems;
2165	    }
2166	    break;
2167	case 'C':
2168	case 'c':
2169	    while (len-- > 0) {
2170		fromstr = NEXTFROM;
2171		switch (datumtype) {
2172		case 'C':
2173		    aint = SvIV(fromstr);
2174		    if ((aint < 0 || aint > 255) &&
2175			ckWARN(WARN_PACK))
2176		        Perl_warner(aTHX_ packWARN(WARN_PACK),
2177				    "Character in 'C' format wrapped in pack");
2178		    achar = aint & 255;
2179		    sv_catpvn(cat, &achar, sizeof(char));
2180		    break;
2181		case 'c':
2182		    aint = SvIV(fromstr);
2183		    if ((aint < -128 || aint > 127) &&
2184			ckWARN(WARN_PACK))
2185		        Perl_warner(aTHX_ packWARN(WARN_PACK),
2186				    "Character in 'c' format wrapped in pack" );
2187		    achar = aint & 255;
2188		    sv_catpvn(cat, &achar, sizeof(char));
2189		    break;
2190		}
2191	    }
2192	    break;
2193	case 'U':
2194	    while (len-- > 0) {
2195		fromstr = NEXTFROM;
2196		auint = UNI_TO_NATIVE(SvUV(fromstr));
2197		SvGROW(cat, SvCUR(cat) + UTF8_MAXLEN + 1);
2198		SvCUR_set(cat,
2199			  (char*)uvchr_to_utf8_flags((U8*)SvEND(cat),
2200						     auint,
2201						     ckWARN(WARN_UTF8) ?
2202						     0 : UNICODE_ALLOW_ANY)
2203			  - SvPVX(cat));
2204	    }
2205	    *SvEND(cat) = '\0';
2206	    break;
2207	/* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
2208	case 'f':
2209	    while (len-- > 0) {
2210		fromstr = NEXTFROM;
2211#ifdef __VOS__
2212/* VOS does not automatically map a floating-point overflow
2213   during conversion from double to float into infinity, so we
2214   do it by hand.  This code should either be generalized for
2215   any OS that needs it, or removed if and when VOS implements
2216   posix-976 (suggestion to support mapping to infinity).
2217   Paul.Green@stratus.com 02-04-02.  */
2218		if (SvNV(fromstr) > FLT_MAX)
2219		     afloat = _float_constants[0];   /* single prec. inf. */
2220		else if (SvNV(fromstr) < -FLT_MAX)
2221		     afloat = _float_constants[0];   /* single prec. inf. */
2222		else afloat = (float)SvNV(fromstr);
2223#else
2224# if defined(VMS) && !defined(__IEEE_FP)
2225/* IEEE fp overflow shenanigans are unavailable on VAX and optional
2226 * on Alpha; fake it if we don't have them.
2227 */
2228		if (SvNV(fromstr) > FLT_MAX)
2229		     afloat = FLT_MAX;
2230		else if (SvNV(fromstr) < -FLT_MAX)
2231		     afloat = -FLT_MAX;
2232		else afloat = (float)SvNV(fromstr);
2233# else
2234		afloat = (float)SvNV(fromstr);
2235# endif
2236#endif
2237		sv_catpvn(cat, (char *)&afloat, sizeof (float));
2238	    }
2239	    break;
2240	case 'd':
2241	    while (len-- > 0) {
2242		fromstr = NEXTFROM;
2243#ifdef __VOS__
2244/* VOS does not automatically map a floating-point overflow
2245   during conversion from long double to double into infinity,
2246   so we do it by hand.  This code should either be generalized
2247   for any OS that needs it, or removed if and when VOS
2248   implements posix-976 (suggestion to support mapping to
2249   infinity).  Paul.Green@stratus.com 02-04-02.  */
2250		if (SvNV(fromstr) > DBL_MAX)
2251		     adouble = _double_constants[0];   /* double prec. inf. */
2252		else if (SvNV(fromstr) < -DBL_MAX)
2253		     adouble = _double_constants[0];   /* double prec. inf. */
2254		else adouble = (double)SvNV(fromstr);
2255#else
2256# if defined(VMS) && !defined(__IEEE_FP)
2257/* IEEE fp overflow shenanigans are unavailable on VAX and optional
2258 * on Alpha; fake it if we don't have them.
2259 */
2260		if (SvNV(fromstr) > DBL_MAX)
2261		     adouble = DBL_MAX;
2262		else if (SvNV(fromstr) < -DBL_MAX)
2263		     adouble = -DBL_MAX;
2264		else adouble = (double)SvNV(fromstr);
2265# else
2266		adouble = (double)SvNV(fromstr);
2267# endif
2268#endif
2269		sv_catpvn(cat, (char *)&adouble, sizeof (double));
2270	    }
2271	    break;
2272	case 'F':
2273	    while (len-- > 0) {
2274		fromstr = NEXTFROM;
2275		anv = SvNV(fromstr);
2276		sv_catpvn(cat, (char *)&anv, NVSIZE);
2277	    }
2278	    break;
2279#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
2280	case 'D':
2281	    while (len-- > 0) {
2282		fromstr = NEXTFROM;
2283		aldouble = (long double)SvNV(fromstr);
2284		sv_catpvn(cat, (char *)&aldouble, LONG_DOUBLESIZE);
2285	    }
2286	    break;
2287#endif
2288	case 'n':
2289	    while (len-- > 0) {
2290		fromstr = NEXTFROM;
2291		ashort = (I16)SvIV(fromstr);
2292#ifdef HAS_HTONS
2293		ashort = PerlSock_htons(ashort);
2294#endif
2295		CAT16(cat, &ashort);
2296	    }
2297	    break;
2298	case 'v':
2299	    while (len-- > 0) {
2300		fromstr = NEXTFROM;
2301		ashort = (I16)SvIV(fromstr);
2302#ifdef HAS_HTOVS
2303		ashort = htovs(ashort);
2304#endif
2305		CAT16(cat, &ashort);
2306	    }
2307	    break;
2308        case 'S' | TYPE_IS_SHRIEKING:
2309#if SHORTSIZE != SIZE16
2310	    {
2311		unsigned short aushort;
2312
2313		while (len-- > 0) {
2314		    fromstr = NEXTFROM;
2315		    aushort = SvUV(fromstr);
2316		    sv_catpvn(cat, (char *)&aushort, sizeof(unsigned short));
2317		}
2318            }
2319            break;
2320#else
2321            /* Fall through! */
2322#endif
2323	case 'S':
2324            {
2325		U16 aushort;
2326
2327		while (len-- > 0) {
2328		    fromstr = NEXTFROM;
2329		    aushort = (U16)SvUV(fromstr);
2330		    CAT16(cat, &aushort);
2331		}
2332
2333	    }
2334	    break;
2335	case 's' | TYPE_IS_SHRIEKING:
2336#if SHORTSIZE != SIZE16
2337	    {
2338		short ashort;
2339
2340		while (len-- > 0) {
2341		    fromstr = NEXTFROM;
2342		    ashort = SvIV(fromstr);
2343		    sv_catpvn(cat, (char *)&ashort, sizeof(short));
2344		}
2345	    }
2346            break;
2347#else
2348            /* Fall through! */
2349#endif
2350	case 's':
2351	    while (len-- > 0) {
2352		fromstr = NEXTFROM;
2353		ashort = (I16)SvIV(fromstr);
2354		CAT16(cat, &ashort);
2355	    }
2356	    break;
2357	case 'I':
2358	case 'I' | TYPE_IS_SHRIEKING:
2359	    while (len-- > 0) {
2360		fromstr = NEXTFROM;
2361		auint = SvUV(fromstr);
2362		sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
2363	    }
2364	    break;
2365	case 'j':
2366	    while (len-- > 0) {
2367		fromstr = NEXTFROM;
2368		aiv = SvIV(fromstr);
2369		sv_catpvn(cat, (char*)&aiv, IVSIZE);
2370	    }
2371	    break;
2372	case 'J':
2373	    while (len-- > 0) {
2374		fromstr = NEXTFROM;
2375		auv = SvUV(fromstr);
2376		sv_catpvn(cat, (char*)&auv, UVSIZE);
2377	    }
2378	    break;
2379	case 'w':
2380            while (len-- > 0) {
2381		fromstr = NEXTFROM;
2382		anv = SvNV(fromstr);
2383
2384		if (anv < 0)
2385		    Perl_croak(aTHX_ "Cannot compress negative numbers in pack");
2386
2387                /* 0xFFFFFFFFFFFFFFFF may cast to 18446744073709551616.0,
2388                   which is == UV_MAX_P1. IOK is fine (instead of UV_only), as
2389                   any negative IVs will have already been got by the croak()
2390                   above. IOK is untrue for fractions, so we test them
2391                   against UV_MAX_P1.  */
2392		if (SvIOK(fromstr) || anv < UV_MAX_P1)
2393		{
2394		    char   buf[(sizeof(UV)*8)/7+1];
2395		    char  *in = buf + sizeof(buf);
2396		    UV     auv = SvUV(fromstr);
2397
2398		    do {
2399			*--in = (char)((auv & 0x7f) | 0x80);
2400			auv >>= 7;
2401		    } while (auv);
2402		    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
2403		    sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
2404		}
2405		else if (SvPOKp(fromstr)) {  /* decimal string arithmetics */
2406		    char           *from, *result, *in;
2407		    SV             *norm;
2408		    STRLEN          len;
2409		    bool            done;
2410
2411		    /* Copy string and check for compliance */
2412		    from = SvPV(fromstr, len);
2413		    if ((norm = is_an_int(from, len)) == NULL)
2414			Perl_croak(aTHX_ "Can only compress unsigned integers in pack");
2415
2416		    New('w', result, len, char);
2417		    in = result + len;
2418		    done = FALSE;
2419		    while (!done)
2420			*--in = div128(norm, &done) | 0x80;
2421		    result[len - 1] &= 0x7F; /* clear continue bit */
2422		    sv_catpvn(cat, in, (result + len) - in);
2423		    Safefree(result);
2424		    SvREFCNT_dec(norm);	/* free norm */
2425                }
2426		else if (SvNOKp(fromstr)) {
2427		    /* 10**NV_MAX_10_EXP is the largest power of 10
2428		       so 10**(NV_MAX_10_EXP+1) is definately unrepresentable
2429		       given 10**(NV_MAX_10_EXP+1) == 128 ** x solve for x:
2430		       x = (NV_MAX_10_EXP+1) * log (10) / log (128)
2431		       And with that many bytes only Inf can overflow.
2432		       Some C compilers are strict about integral constant
2433		       expressions so we conservatively divide by a slightly
2434		       smaller integer instead of multiplying by the exact
2435		       floating-point value.
2436		    */
2437#ifdef NV_MAX_10_EXP
2438/*		    char   buf[1 + (int)((NV_MAX_10_EXP + 1) * 0.47456)]; -- invalid C */
2439		    char   buf[1 + (int)((NV_MAX_10_EXP + 1) / 2)]; /* valid C */
2440#else
2441/*		    char   buf[1 + (int)((308 + 1) * 0.47456)]; -- invalid C */
2442		    char   buf[1 + (int)((308 + 1) / 2)]; /* valid C */
2443#endif
2444		    char  *in = buf + sizeof(buf);
2445
2446                    anv = Perl_floor(anv);
2447		    do {
2448			NV next = Perl_floor(anv / 128);
2449			if (in <= buf)  /* this cannot happen ;-) */
2450			    Perl_croak(aTHX_ "Cannot compress integer in pack");
2451			*--in = (unsigned char)(anv - (next * 128)) | 0x80;
2452			anv = next;
2453		    } while (anv > 0);
2454		    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
2455		    sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
2456		}
2457		else {
2458		    char           *from, *result, *in;
2459		    SV             *norm;
2460		    STRLEN          len;
2461		    bool            done;
2462
2463		    /* Copy string and check for compliance */
2464		    from = SvPV(fromstr, len);
2465		    if ((norm = is_an_int(from, len)) == NULL)
2466			Perl_croak(aTHX_ "Can only compress unsigned integers in pack");
2467
2468		    New('w', result, len, char);
2469		    in = result + len;
2470		    done = FALSE;
2471		    while (!done)
2472			*--in = div128(norm, &done) | 0x80;
2473		    result[len - 1] &= 0x7F; /* clear continue bit */
2474		    sv_catpvn(cat, in, (result + len) - in);
2475		    Safefree(result);
2476		    SvREFCNT_dec(norm);	/* free norm */
2477               }
2478	    }
2479            break;
2480	case 'i':
2481	case 'i' | TYPE_IS_SHRIEKING:
2482	    while (len-- > 0) {
2483		fromstr = NEXTFROM;
2484		aint = SvIV(fromstr);
2485		sv_catpvn(cat, (char*)&aint, sizeof(int));
2486	    }
2487	    break;
2488	case 'N':
2489	    while (len-- > 0) {
2490		fromstr = NEXTFROM;
2491		aulong = SvUV(fromstr);
2492#ifdef HAS_HTONL
2493		aulong = PerlSock_htonl(aulong);
2494#endif
2495		CAT32(cat, &aulong);
2496	    }
2497	    break;
2498	case 'V':
2499	    while (len-- > 0) {
2500		fromstr = NEXTFROM;
2501		aulong = SvUV(fromstr);
2502#ifdef HAS_HTOVL
2503		aulong = htovl(aulong);
2504#endif
2505		CAT32(cat, &aulong);
2506	    }
2507	    break;
2508	case 'L' | TYPE_IS_SHRIEKING:
2509#if LONGSIZE != SIZE32
2510	    {
2511		unsigned long aulong;
2512
2513		while (len-- > 0) {
2514		    fromstr = NEXTFROM;
2515		    aulong = SvUV(fromstr);
2516		    sv_catpvn(cat, (char *)&aulong, sizeof(unsigned long));
2517		}
2518	    }
2519	    break;
2520#else
2521            /* Fall though! */
2522#endif
2523	case 'L':
2524            {
2525		while (len-- > 0) {
2526		    fromstr = NEXTFROM;
2527		    aulong = SvUV(fromstr);
2528		    CAT32(cat, &aulong);
2529		}
2530	    }
2531	    break;
2532	case 'l' | TYPE_IS_SHRIEKING:
2533#if LONGSIZE != SIZE32
2534	    {
2535		long along;
2536
2537		while (len-- > 0) {
2538		    fromstr = NEXTFROM;
2539		    along = SvIV(fromstr);
2540		    sv_catpvn(cat, (char *)&along, sizeof(long));
2541		}
2542	    }
2543	    break;
2544#else
2545            /* Fall though! */
2546#endif
2547	case 'l':
2548            while (len-- > 0) {
2549		fromstr = NEXTFROM;
2550		along = SvIV(fromstr);
2551		CAT32(cat, &along);
2552	    }
2553	    break;
2554#ifdef HAS_QUAD
2555	case 'Q':
2556	    while (len-- > 0) {
2557		fromstr = NEXTFROM;
2558		auquad = (Uquad_t)SvUV(fromstr);
2559		sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t));
2560	    }
2561	    break;
2562	case 'q':
2563	    while (len-- > 0) {
2564		fromstr = NEXTFROM;
2565		aquad = (Quad_t)SvIV(fromstr);
2566		sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
2567	    }
2568	    break;
2569#endif
2570	case 'P':
2571	    len = 1;		/* assume SV is correct length */
2572	    /* Fall through! */
2573	case 'p':
2574	    while (len-- > 0) {
2575		fromstr = NEXTFROM;
2576		if (fromstr == &PL_sv_undef)
2577		    aptr = NULL;
2578		else {
2579		    STRLEN n_a;
2580		    /* XXX better yet, could spirit away the string to
2581		     * a safe spot and hang on to it until the result
2582		     * of pack() (and all copies of the result) are
2583		     * gone.
2584		     */
2585		    if (ckWARN(WARN_PACK) && (SvTEMP(fromstr)
2586						|| (SvPADTMP(fromstr)
2587						    && !SvREADONLY(fromstr))))
2588		    {
2589			Perl_warner(aTHX_ packWARN(WARN_PACK),
2590				"Attempt to pack pointer to temporary value");
2591		    }
2592		    if (SvPOK(fromstr) || SvNIOK(fromstr))
2593			aptr = SvPV(fromstr,n_a);
2594		    else
2595			aptr = SvPV_force(fromstr,n_a);
2596		}
2597		sv_catpvn(cat, (char*)&aptr, sizeof(char*));
2598	    }
2599	    break;
2600	case 'u':
2601	    fromstr = NEXTFROM;
2602	    aptr = SvPV(fromstr, fromlen);
2603	    SvGROW(cat, fromlen * 4 / 3);
2604	    if (len <= 2)
2605		len = 45;
2606	    else
2607		len = len / 3 * 3;
2608	    while (fromlen > 0) {
2609		I32 todo;
2610
2611		if ((I32)fromlen > len)
2612		    todo = len;
2613		else
2614		    todo = fromlen;
2615		doencodes(cat, aptr, todo);
2616		fromlen -= todo;
2617		aptr += todo;
2618	    }
2619	    break;
2620	}
2621	*symptr = lookahead;
2622    }
2623    return beglist;
2624}
2625#undef NEXTFROM
2626
2627
2628PP(pp_pack)
2629{
2630    dSP; dMARK; dORIGMARK; dTARGET;
2631    register SV *cat = TARG;
2632    STRLEN fromlen;
2633    register char *pat = SvPVx(*++MARK, fromlen);
2634    register char *patend = pat + fromlen;
2635
2636    MARK++;
2637    sv_setpvn(cat, "", 0);
2638
2639    packlist(cat, pat, patend, MARK, SP + 1);
2640
2641    SvSETMAGIC(cat);
2642    SP = ORIGMARK;
2643    PUSHs(cat);
2644    RETURN;
2645}
2646
2647