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