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