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