Clarifying comment to #12164.
[p5sagit/p5-mst-13.2.git] / pp_pack.c
CommitLineData
a6ec74c1 1/* pp_pack.c
2 *
3 * Copyright (c) 1991-2001, Larry Wall
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10#include "EXTERN.h"
11#define PERL_IN_PP_PACK_C
12#include "perl.h"
13
14/*
15 * The compiler on Concurrent CX/UX systems has a subtle bug which only
16 * seems to show up when compiling pp.c - it generates the wrong double
17 * precision constant value for (double)UV_MAX when used inline in the body
18 * of the code below, so this makes a static variable up front (which the
19 * compiler seems to get correct) and uses it in place of UV_MAX below.
20 */
21#ifdef CXUX_BROKEN_CONSTANT_CONVERT
22static double UV_MAX_cxux = ((double)UV_MAX);
23#endif
24
25/*
26 * Offset for integer pack/unpack.
27 *
28 * On architectures where I16 and I32 aren't really 16 and 32 bits,
29 * which for now are all Crays, pack and unpack have to play games.
30 */
31
32/*
33 * These values are required for portability of pack() output.
34 * If they're not right on your machine, then pack() and unpack()
35 * wouldn't work right anyway; you'll need to apply the Cray hack.
36 * (I'd like to check them with #if, but you can't use sizeof() in
37 * the preprocessor.) --???
38 */
39/*
40 The appropriate SHORTSIZE, INTSIZE, LONGSIZE, and LONGLONGSIZE
41 defines are now in config.h. --Andy Dougherty April 1998
42 */
43#define SIZE16 2
44#define SIZE32 4
45
46/* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
47 --jhi Feb 1999 */
48
49#if SHORTSIZE != SIZE16 || LONGSIZE != SIZE32
50# define PERL_NATINT_PACK
51#endif
52
53#if LONGSIZE > 4 && defined(_CRAY)
54# if BYTEORDER == 0x12345678
55# define OFF16(p) (char*)(p)
56# define OFF32(p) (char*)(p)
57# else
58# if BYTEORDER == 0x87654321
59# define OFF16(p) ((char*)(p) + (sizeof(U16) - SIZE16))
60# define OFF32(p) ((char*)(p) + (sizeof(U32) - SIZE32))
61# else
62 }}}} bad cray byte order
63# endif
64# endif
65# define COPY16(s,p) (*(p) = 0, Copy(s, OFF16(p), SIZE16, char))
66# define COPY32(s,p) (*(p) = 0, Copy(s, OFF32(p), SIZE32, char))
67# define COPYNN(s,p,n) (*(p) = 0, Copy(s, (char *)(p), n, char))
68# define CAT16(sv,p) sv_catpvn(sv, OFF16(p), SIZE16)
69# define CAT32(sv,p) sv_catpvn(sv, OFF32(p), SIZE32)
70#else
71# define COPY16(s,p) Copy(s, p, SIZE16, char)
72# define COPY32(s,p) Copy(s, p, SIZE32, char)
73# define COPYNN(s,p,n) Copy(s, (char *)(p), n, char)
74# define CAT16(sv,p) sv_catpvn(sv, (char*)(p), SIZE16)
75# define CAT32(sv,p) sv_catpvn(sv, (char*)(p), SIZE32)
76#endif
77
78STATIC SV *
79S_mul128(pTHX_ SV *sv, U8 m)
80{
81 STRLEN len;
82 char *s = SvPV(sv, len);
83 char *t;
84 U32 i = 0;
85
86 if (!strnEQ(s, "0000", 4)) { /* need to grow sv */
87 SV *tmpNew = newSVpvn("0000000000", 10);
88
89 sv_catsv(tmpNew, sv);
90 SvREFCNT_dec(sv); /* free old sv */
91 sv = tmpNew;
92 s = SvPV(sv, len);
93 }
94 t = s + len - 1;
95 while (!*t) /* trailing '\0'? */
96 t--;
97 while (t > s) {
98 i = ((*t - '0') << 7) + m;
99 *(t--) = '0' + (i % 10);
100 m = i / 10;
101 }
102 return (sv);
103}
104
105/* Explosives and implosives. */
106
107#if 'I' == 73 && 'J' == 74
108/* On an ASCII/ISO kind of system */
109#define ISUUCHAR(ch) ((ch) >= ' ' && (ch) < 'a')
110#else
111/*
112 Some other sort of character set - use memchr() so we don't match
113 the null byte.
114 */
115#define ISUUCHAR(ch) (memchr(PL_uuemap, (ch), sizeof(PL_uuemap)-1) || (ch) == ' ')
116#endif
117
118
119PP(pp_unpack)
120{
121 dSP;
122 dPOPPOPssrl;
123 I32 start_sp_offset = SP - PL_stack_base;
124 I32 gimme = GIMME_V;
125 SV *sv;
126 STRLEN llen;
127 STRLEN rlen;
128 register char *pat = SvPV(left, llen);
129#ifdef PACKED_IS_OCTETS
130 /* Packed side is assumed to be octets - so force downgrade if it
131 has been UTF-8 encoded by accident
132 */
133 register char *s = SvPVbyte(right, rlen);
134#else
135 register char *s = SvPV(right, rlen);
136#endif
137 char *strend = s + rlen;
138 char *strbeg = s;
139 register char *patend = pat + llen;
140 I32 datumtype;
141 register I32 len;
142 register I32 bits = 0;
143 register char *str;
144
145 /* These must not be in registers: */
146 short ashort;
147 int aint;
148 long along;
149#ifdef HAS_QUAD
150 Quad_t aquad;
151#endif
152 U16 aushort;
153 unsigned int auint;
154 U32 aulong;
155#ifdef HAS_QUAD
156 Uquad_t auquad;
157#endif
158 char *aptr;
159 float afloat;
160 double adouble;
161 I32 checksum = 0;
fa8ec7c1 162 UV culong = 0;
a6ec74c1 163 NV cdouble = 0.0;
fa8ec7c1 164 const int bits_in_uv = 8 * sizeof(culong);
a6ec74c1 165 int commas = 0;
166 int star;
167#ifdef PERL_NATINT_PACK
168 int natint; /* native integer */
169 int unatint; /* unsigned native integer */
170#endif
35bcd338 171 bool do_utf8 = DO_UTF8(right);
a6ec74c1 172
a6ec74c1 173 while (pat < patend) {
174 reparse:
175 datumtype = *pat++ & 0xFF;
176#ifdef PERL_NATINT_PACK
177 natint = 0;
178#endif
179 if (isSPACE(datumtype))
180 continue;
181 if (datumtype == '#') {
182 while (pat < patend && *pat != '\n')
183 pat++;
184 continue;
185 }
186 if (*pat == '!') {
187 char *natstr = "sSiIlL";
188
189 if (strchr(natstr, datumtype)) {
190#ifdef PERL_NATINT_PACK
191 natint = 1;
192#endif
193 pat++;
194 }
195 else
196 DIE(aTHX_ "'!' allowed only after types %s", natstr);
197 }
198 star = 0;
fa8ec7c1 199 if (pat >= patend)
a6ec74c1 200 len = 1;
201 else if (*pat == '*') {
202 len = strend - strbeg; /* long enough */
203 pat++;
204 star = 1;
205 }
206 else if (isDIGIT(*pat)) {
207 len = *pat++ - '0';
208 while (isDIGIT(*pat)) {
209 len = (len * 10) + (*pat++ - '0');
210 if (len < 0)
211 DIE(aTHX_ "Repeat count in unpack overflows");
212 }
213 }
214 else
215 len = (datumtype != '@');
216 redo_switch:
217 switch(datumtype) {
218 default:
219 DIE(aTHX_ "Invalid type in unpack: '%c'", (int)datumtype);
220 case ',': /* grandfather in commas but with a warning */
221 if (commas++ == 0 && ckWARN(WARN_UNPACK))
222 Perl_warner(aTHX_ WARN_UNPACK,
223 "Invalid type in unpack: '%c'", (int)datumtype);
224 break;
225 case '%':
226 if (len == 1 && pat[-1] != '1')
227 len = 16;
228 checksum = len;
229 culong = 0;
230 cdouble = 0;
231 if (pat < patend)
232 goto reparse;
233 break;
234 case '@':
235 if (len > strend - strbeg)
236 DIE(aTHX_ "@ outside of string");
237 s = strbeg + len;
238 break;
239 case 'X':
240 if (len > s - strbeg)
241 DIE(aTHX_ "X outside of string");
242 s -= len;
243 break;
244 case 'x':
245 if (len > strend - s)
246 DIE(aTHX_ "x outside of string");
247 s += len;
248 break;
249 case '/':
250 if (start_sp_offset >= SP - PL_stack_base)
251 DIE(aTHX_ "/ must follow a numeric type");
252 datumtype = *pat++;
253 if (*pat == '*')
254 pat++; /* ignore '*' for compatibility with pack */
255 if (isDIGIT(*pat))
256 DIE(aTHX_ "/ cannot take a count" );
257 len = POPi;
258 star = 0;
259 goto redo_switch;
260 case 'A':
261 case 'Z':
262 case 'a':
263 if (len > strend - s)
264 len = strend - s;
265 if (checksum)
266 goto uchar_checksum;
267 sv = NEWSV(35, len);
268 sv_setpvn(sv, s, len);
269 s += len;
270 if (datumtype == 'A' || datumtype == 'Z') {
271 aptr = s; /* borrow register */
272 if (datumtype == 'Z') { /* 'Z' strips stuff after first null */
273 s = SvPVX(sv);
274 while (*s)
275 s++;
276 }
277 else { /* 'A' strips both nulls and spaces */
278 s = SvPVX(sv) + len - 1;
279 while (s >= SvPVX(sv) && (!*s || isSPACE(*s)))
280 s--;
281 *++s = '\0';
282 }
283 SvCUR_set(sv, s - SvPVX(sv));
284 s = aptr; /* unborrow register */
285 }
286 XPUSHs(sv_2mortal(sv));
287 break;
288 case 'B':
289 case 'b':
290 if (star || len > (strend - s) * 8)
291 len = (strend - s) * 8;
292 if (checksum) {
293 if (!PL_bitcount) {
294 Newz(601, PL_bitcount, 256, char);
295 for (bits = 1; bits < 256; bits++) {
296 if (bits & 1) PL_bitcount[bits]++;
297 if (bits & 2) PL_bitcount[bits]++;
298 if (bits & 4) PL_bitcount[bits]++;
299 if (bits & 8) PL_bitcount[bits]++;
300 if (bits & 16) PL_bitcount[bits]++;
301 if (bits & 32) PL_bitcount[bits]++;
302 if (bits & 64) PL_bitcount[bits]++;
303 if (bits & 128) PL_bitcount[bits]++;
304 }
305 }
306 while (len >= 8) {
307 culong += PL_bitcount[*(unsigned char*)s++];
308 len -= 8;
309 }
310 if (len) {
311 bits = *s;
312 if (datumtype == 'b') {
313 while (len-- > 0) {
314 if (bits & 1) culong++;
315 bits >>= 1;
316 }
317 }
318 else {
319 while (len-- > 0) {
320 if (bits & 128) culong++;
321 bits <<= 1;
322 }
323 }
324 }
325 break;
326 }
327 sv = NEWSV(35, len + 1);
328 SvCUR_set(sv, len);
329 SvPOK_on(sv);
330 str = SvPVX(sv);
331 if (datumtype == 'b') {
332 aint = len;
333 for (len = 0; len < aint; len++) {
334 if (len & 7) /*SUPPRESS 595*/
335 bits >>= 1;
336 else
337 bits = *s++;
338 *str++ = '0' + (bits & 1);
339 }
340 }
341 else {
342 aint = len;
343 for (len = 0; len < aint; len++) {
344 if (len & 7)
345 bits <<= 1;
346 else
347 bits = *s++;
348 *str++ = '0' + ((bits & 128) != 0);
349 }
350 }
351 *str = '\0';
352 XPUSHs(sv_2mortal(sv));
353 break;
354 case 'H':
355 case 'h':
356 if (star || len > (strend - s) * 2)
357 len = (strend - s) * 2;
358 sv = NEWSV(35, len + 1);
359 SvCUR_set(sv, len);
360 SvPOK_on(sv);
361 str = SvPVX(sv);
362 if (datumtype == 'h') {
363 aint = len;
364 for (len = 0; len < aint; len++) {
365 if (len & 1)
366 bits >>= 4;
367 else
368 bits = *s++;
369 *str++ = PL_hexdigit[bits & 15];
370 }
371 }
372 else {
373 aint = len;
374 for (len = 0; len < aint; len++) {
375 if (len & 1)
376 bits <<= 4;
377 else
378 bits = *s++;
379 *str++ = PL_hexdigit[(bits >> 4) & 15];
380 }
381 }
382 *str = '\0';
383 XPUSHs(sv_2mortal(sv));
384 break;
385 case 'c':
386 if (len > strend - s)
387 len = strend - s;
388 if (checksum) {
389 while (len-- > 0) {
390 aint = *s++;
391 if (aint >= 128) /* fake up signed chars */
392 aint -= 256;
fa8ec7c1 393 if (checksum > bits_in_uv)
394 cdouble += (NV)aint;
395 else
396 culong += aint;
a6ec74c1 397 }
398 }
399 else {
400 EXTEND(SP, len);
401 EXTEND_MORTAL(len);
402 while (len-- > 0) {
403 aint = *s++;
404 if (aint >= 128) /* fake up signed chars */
405 aint -= 256;
406 sv = NEWSV(36, 0);
407 sv_setiv(sv, (IV)aint);
408 PUSHs(sv_2mortal(sv));
409 }
410 }
411 break;
412 case 'C':
35bcd338 413 unpack_C: /* unpack U will jump here if not UTF-8 */
414 if (len == 0) {
415 do_utf8 = FALSE;
416 break;
417 }
a6ec74c1 418 if (len > strend - s)
419 len = strend - s;
420 if (checksum) {
421 uchar_checksum:
422 while (len-- > 0) {
423 auint = *s++ & 255;
424 culong += auint;
425 }
426 }
427 else {
428 EXTEND(SP, len);
429 EXTEND_MORTAL(len);
430 while (len-- > 0) {
431 auint = *s++ & 255;
432 sv = NEWSV(37, 0);
433 sv_setiv(sv, (IV)auint);
434 PUSHs(sv_2mortal(sv));
435 }
436 }
437 break;
438 case 'U':
35bcd338 439 if (len == 0) {
440 do_utf8 = TRUE;
441 break;
442 }
443 if (!do_utf8)
444 goto unpack_C;
a6ec74c1 445 if (len > strend - s)
446 len = strend - s;
447 if (checksum) {
448 while (len-- > 0 && s < strend) {
449 STRLEN alen;
450 auint = utf8n_to_uvchr((U8*)s, strend - s, &alen, 0);
451 along = alen;
452 s += along;
fa8ec7c1 453 if (checksum > bits_in_uv)
a6ec74c1 454 cdouble += (NV)auint;
455 else
456 culong += auint;
457 }
458 }
459 else {
460 EXTEND(SP, len);
461 EXTEND_MORTAL(len);
462 while (len-- > 0 && s < strend) {
463 STRLEN alen;
464 auint = utf8n_to_uvchr((U8*)s, strend - s, &alen, 0);
465 along = alen;
466 s += along;
467 sv = NEWSV(37, 0);
468 sv_setuv(sv, (UV)auint);
469 PUSHs(sv_2mortal(sv));
470 }
471 }
472 break;
473 case 's':
474#if SHORTSIZE == SIZE16
475 along = (strend - s) / SIZE16;
476#else
477 along = (strend - s) / (natint ? sizeof(short) : SIZE16);
478#endif
479 if (len > along)
480 len = along;
481 if (checksum) {
482#if SHORTSIZE != SIZE16
483 if (natint) {
484 short ashort;
485 while (len-- > 0) {
486 COPYNN(s, &ashort, sizeof(short));
487 s += sizeof(short);
fa8ec7c1 488 if (checksum > bits_in_uv)
489 cdouble += (NV)ashort;
490 else
491 culong += ashort;
a6ec74c1 492
493 }
494 }
495 else
496#endif
497 {
498 while (len-- > 0) {
499 COPY16(s, &ashort);
500#if SHORTSIZE > SIZE16
501 if (ashort > 32767)
502 ashort -= 65536;
503#endif
504 s += SIZE16;
fa8ec7c1 505 if (checksum > bits_in_uv)
506 cdouble += (NV)ashort;
507 else
508 culong += ashort;
a6ec74c1 509 }
510 }
511 }
512 else {
513 EXTEND(SP, len);
514 EXTEND_MORTAL(len);
515#if SHORTSIZE != SIZE16
516 if (natint) {
517 short ashort;
518 while (len-- > 0) {
519 COPYNN(s, &ashort, sizeof(short));
520 s += sizeof(short);
521 sv = NEWSV(38, 0);
522 sv_setiv(sv, (IV)ashort);
523 PUSHs(sv_2mortal(sv));
524 }
525 }
526 else
527#endif
528 {
529 while (len-- > 0) {
530 COPY16(s, &ashort);
531#if SHORTSIZE > SIZE16
532 if (ashort > 32767)
533 ashort -= 65536;
534#endif
535 s += SIZE16;
536 sv = NEWSV(38, 0);
537 sv_setiv(sv, (IV)ashort);
538 PUSHs(sv_2mortal(sv));
539 }
540 }
541 }
542 break;
543 case 'v':
544 case 'n':
545 case 'S':
546#if SHORTSIZE == SIZE16
547 along = (strend - s) / SIZE16;
548#else
549 unatint = natint && datumtype == 'S';
550 along = (strend - s) / (unatint ? sizeof(unsigned short) : SIZE16);
551#endif
552 if (len > along)
553 len = along;
554 if (checksum) {
555#if SHORTSIZE != SIZE16
556 if (unatint) {
557 unsigned short aushort;
558 while (len-- > 0) {
559 COPYNN(s, &aushort, sizeof(unsigned short));
560 s += sizeof(unsigned short);
fa8ec7c1 561 if (checksum > bits_in_uv)
562 cdouble += (NV)aushort;
563 else
564 culong += aushort;
a6ec74c1 565 }
566 }
567 else
568#endif
569 {
570 while (len-- > 0) {
571 COPY16(s, &aushort);
572 s += SIZE16;
573#ifdef HAS_NTOHS
574 if (datumtype == 'n')
575 aushort = PerlSock_ntohs(aushort);
576#endif
577#ifdef HAS_VTOHS
578 if (datumtype == 'v')
579 aushort = vtohs(aushort);
580#endif
fa8ec7c1 581 if (checksum > bits_in_uv)
582 cdouble += (NV)aushort;
583 else
584 culong += aushort;
a6ec74c1 585 }
586 }
587 }
588 else {
589 EXTEND(SP, len);
590 EXTEND_MORTAL(len);
591#if SHORTSIZE != SIZE16
592 if (unatint) {
593 unsigned short aushort;
594 while (len-- > 0) {
595 COPYNN(s, &aushort, sizeof(unsigned short));
596 s += sizeof(unsigned short);
597 sv = NEWSV(39, 0);
598 sv_setiv(sv, (UV)aushort);
599 PUSHs(sv_2mortal(sv));
600 }
601 }
602 else
603#endif
604 {
605 while (len-- > 0) {
606 COPY16(s, &aushort);
607 s += SIZE16;
608 sv = NEWSV(39, 0);
609#ifdef HAS_NTOHS
610 if (datumtype == 'n')
611 aushort = PerlSock_ntohs(aushort);
612#endif
613#ifdef HAS_VTOHS
614 if (datumtype == 'v')
615 aushort = vtohs(aushort);
616#endif
617 sv_setiv(sv, (UV)aushort);
618 PUSHs(sv_2mortal(sv));
619 }
620 }
621 }
622 break;
623 case 'i':
624 along = (strend - s) / sizeof(int);
625 if (len > along)
626 len = along;
627 if (checksum) {
628 while (len-- > 0) {
629 Copy(s, &aint, 1, int);
630 s += sizeof(int);
fa8ec7c1 631 if (checksum > bits_in_uv)
a6ec74c1 632 cdouble += (NV)aint;
633 else
634 culong += aint;
635 }
636 }
637 else {
638 EXTEND(SP, len);
639 EXTEND_MORTAL(len);
640 while (len-- > 0) {
641 Copy(s, &aint, 1, int);
642 s += sizeof(int);
643 sv = NEWSV(40, 0);
644#ifdef __osf__
645 /* Without the dummy below unpack("i", pack("i",-1))
646 * return 0xFFffFFff instead of -1 for Digital Unix V4.0
647 * cc with optimization turned on.
648 *
649 * The bug was detected in
650 * DEC C V5.8-009 on Digital UNIX V4.0 (Rev. 1091) (V4.0E)
651 * with optimization (-O4) turned on.
652 * DEC C V5.2-040 on Digital UNIX V4.0 (Rev. 564) (V4.0B)
653 * does not have this problem even with -O4.
654 *
655 * This bug was reported as DECC_BUGS 1431
656 * and tracked internally as GEM_BUGS 7775.
657 *
658 * The bug is fixed in
659 * Tru64 UNIX V5.0: Compaq C V6.1-006 or later
660 * UNIX V4.0F support: DEC C V5.9-006 or later
661 * UNIX V4.0E support: DEC C V5.8-011 or later
662 * and also in DTK.
663 *
664 * See also few lines later for the same bug.
665 */
666 (aint) ?
667 sv_setiv(sv, (IV)aint) :
668#endif
669 sv_setiv(sv, (IV)aint);
670 PUSHs(sv_2mortal(sv));
671 }
672 }
673 break;
674 case 'I':
675 along = (strend - s) / sizeof(unsigned int);
676 if (len > along)
677 len = along;
678 if (checksum) {
679 while (len-- > 0) {
680 Copy(s, &auint, 1, unsigned int);
681 s += sizeof(unsigned int);
fa8ec7c1 682 if (checksum > bits_in_uv)
a6ec74c1 683 cdouble += (NV)auint;
684 else
685 culong += auint;
686 }
687 }
688 else {
689 EXTEND(SP, len);
690 EXTEND_MORTAL(len);
691 while (len-- > 0) {
692 Copy(s, &auint, 1, unsigned int);
693 s += sizeof(unsigned int);
694 sv = NEWSV(41, 0);
695#ifdef __osf__
696 /* Without the dummy below unpack("I", pack("I",0xFFFFFFFF))
697 * returns 1.84467440737096e+19 instead of 0xFFFFFFFF.
698 * See details few lines earlier. */
699 (auint) ?
700 sv_setuv(sv, (UV)auint) :
701#endif
702 sv_setuv(sv, (UV)auint);
703 PUSHs(sv_2mortal(sv));
704 }
705 }
706 break;
707 case 'l':
708#if LONGSIZE == SIZE32
709 along = (strend - s) / SIZE32;
710#else
711 along = (strend - s) / (natint ? sizeof(long) : SIZE32);
712#endif
713 if (len > along)
714 len = along;
715 if (checksum) {
716#if LONGSIZE != SIZE32
717 if (natint) {
718 while (len-- > 0) {
719 COPYNN(s, &along, sizeof(long));
720 s += sizeof(long);
fa8ec7c1 721 if (checksum > bits_in_uv)
a6ec74c1 722 cdouble += (NV)along;
723 else
724 culong += along;
725 }
726 }
727 else
728#endif
729 {
730 while (len-- > 0) {
731#if LONGSIZE > SIZE32 && INTSIZE == SIZE32
732 I32 along;
733#endif
734 COPY32(s, &along);
735#if LONGSIZE > SIZE32
736 if (along > 2147483647)
737 along -= 4294967296;
738#endif
739 s += SIZE32;
fa8ec7c1 740 if (checksum > bits_in_uv)
a6ec74c1 741 cdouble += (NV)along;
742 else
743 culong += along;
744 }
745 }
746 }
747 else {
748 EXTEND(SP, len);
749 EXTEND_MORTAL(len);
750#if LONGSIZE != SIZE32
751 if (natint) {
752 while (len-- > 0) {
753 COPYNN(s, &along, sizeof(long));
754 s += sizeof(long);
755 sv = NEWSV(42, 0);
756 sv_setiv(sv, (IV)along);
757 PUSHs(sv_2mortal(sv));
758 }
759 }
760 else
761#endif
762 {
763 while (len-- > 0) {
764#if LONGSIZE > SIZE32 && INTSIZE == SIZE32
765 I32 along;
766#endif
767 COPY32(s, &along);
768#if LONGSIZE > SIZE32
769 if (along > 2147483647)
770 along -= 4294967296;
771#endif
772 s += SIZE32;
773 sv = NEWSV(42, 0);
774 sv_setiv(sv, (IV)along);
775 PUSHs(sv_2mortal(sv));
776 }
777 }
778 }
779 break;
780 case 'V':
781 case 'N':
782 case 'L':
783#if LONGSIZE == SIZE32
784 along = (strend - s) / SIZE32;
785#else
786 unatint = natint && datumtype == 'L';
787 along = (strend - s) / (unatint ? sizeof(unsigned long) : SIZE32);
788#endif
789 if (len > along)
790 len = along;
791 if (checksum) {
792#if LONGSIZE != SIZE32
793 if (unatint) {
794 unsigned long aulong;
795 while (len-- > 0) {
796 COPYNN(s, &aulong, sizeof(unsigned long));
797 s += sizeof(unsigned long);
fa8ec7c1 798 if (checksum > bits_in_uv)
a6ec74c1 799 cdouble += (NV)aulong;
800 else
801 culong += aulong;
802 }
803 }
804 else
805#endif
806 {
807 while (len-- > 0) {
808 COPY32(s, &aulong);
809 s += SIZE32;
810#ifdef HAS_NTOHL
811 if (datumtype == 'N')
812 aulong = PerlSock_ntohl(aulong);
813#endif
814#ifdef HAS_VTOHL
815 if (datumtype == 'V')
816 aulong = vtohl(aulong);
817#endif
fa8ec7c1 818 if (checksum > bits_in_uv)
a6ec74c1 819 cdouble += (NV)aulong;
820 else
821 culong += aulong;
822 }
823 }
824 }
825 else {
826 EXTEND(SP, len);
827 EXTEND_MORTAL(len);
828#if LONGSIZE != SIZE32
829 if (unatint) {
830 unsigned long aulong;
831 while (len-- > 0) {
832 COPYNN(s, &aulong, sizeof(unsigned long));
833 s += sizeof(unsigned long);
834 sv = NEWSV(43, 0);
835 sv_setuv(sv, (UV)aulong);
836 PUSHs(sv_2mortal(sv));
837 }
838 }
839 else
840#endif
841 {
842 while (len-- > 0) {
843 COPY32(s, &aulong);
844 s += SIZE32;
845#ifdef HAS_NTOHL
846 if (datumtype == 'N')
847 aulong = PerlSock_ntohl(aulong);
848#endif
849#ifdef HAS_VTOHL
850 if (datumtype == 'V')
851 aulong = vtohl(aulong);
852#endif
853 sv = NEWSV(43, 0);
854 sv_setuv(sv, (UV)aulong);
855 PUSHs(sv_2mortal(sv));
856 }
857 }
858 }
859 break;
860 case 'p':
861 along = (strend - s) / sizeof(char*);
862 if (len > along)
863 len = along;
864 EXTEND(SP, len);
865 EXTEND_MORTAL(len);
866 while (len-- > 0) {
867 if (sizeof(char*) > strend - s)
868 break;
869 else {
870 Copy(s, &aptr, 1, char*);
871 s += sizeof(char*);
872 }
873 sv = NEWSV(44, 0);
874 if (aptr)
875 sv_setpv(sv, aptr);
876 PUSHs(sv_2mortal(sv));
877 }
878 break;
879 case 'w':
880 EXTEND(SP, len);
881 EXTEND_MORTAL(len);
882 {
883 UV auv = 0;
884 U32 bytes = 0;
885
886 while ((len > 0) && (s < strend)) {
887 auv = (auv << 7) | (*s & 0x7f);
888 /* UTF8_IS_XXXXX not right here - using constant 0x80 */
889 if ((U8)(*s++) < 0x80) {
890 bytes = 0;
891 sv = NEWSV(40, 0);
892 sv_setuv(sv, auv);
893 PUSHs(sv_2mortal(sv));
894 len--;
895 auv = 0;
896 }
897 else if (++bytes >= sizeof(UV)) { /* promote to string */
898 char *t;
899 STRLEN n_a;
900
901 sv = Perl_newSVpvf(aTHX_ "%.*"UVf, (int)TYPE_DIGITS(UV), auv);
902 while (s < strend) {
903 sv = mul128(sv, *s & 0x7f);
904 if (!(*s++ & 0x80)) {
905 bytes = 0;
906 break;
907 }
908 }
909 t = SvPV(sv, n_a);
910 while (*t == '0')
911 t++;
912 sv_chop(sv, t);
913 PUSHs(sv_2mortal(sv));
914 len--;
915 auv = 0;
916 }
917 }
918 if ((s >= strend) && bytes)
919 DIE(aTHX_ "Unterminated compressed integer");
920 }
921 break;
922 case 'P':
923 EXTEND(SP, 1);
924 if (sizeof(char*) > strend - s)
925 break;
926 else {
927 Copy(s, &aptr, 1, char*);
928 s += sizeof(char*);
929 }
930 sv = NEWSV(44, 0);
931 if (aptr)
932 sv_setpvn(sv, aptr, len);
933 PUSHs(sv_2mortal(sv));
934 break;
935#ifdef HAS_QUAD
936 case 'q':
937 along = (strend - s) / sizeof(Quad_t);
938 if (len > along)
939 len = along;
fa8ec7c1 940 if (checksum) {
941 while (len-- > 0) {
a6ec74c1 942 Copy(s, &aquad, 1, Quad_t);
943 s += sizeof(Quad_t);
fa8ec7c1 944 if (checksum > bits_in_uv)
945 cdouble += (NV)aquad;
946 else
947 culong += aquad;
a6ec74c1 948 }
a6ec74c1 949 }
fa8ec7c1 950 else {
951 EXTEND(SP, len);
952 EXTEND_MORTAL(len);
953 while (len-- > 0) {
954 if (s + sizeof(Quad_t) > strend)
955 aquad = 0;
956 else {
957 Copy(s, &aquad, 1, Quad_t);
958 s += sizeof(Quad_t);
959 }
960 sv = NEWSV(42, 0);
961 if (aquad >= IV_MIN && aquad <= IV_MAX)
962 sv_setiv(sv, (IV)aquad);
963 else
964 sv_setnv(sv, (NV)aquad);
965 PUSHs(sv_2mortal(sv));
966 }
967 }
a6ec74c1 968 break;
969 case 'Q':
970 along = (strend - s) / sizeof(Quad_t);
971 if (len > along)
972 len = along;
fa8ec7c1 973 if (checksum) {
974 while (len-- > 0) {
a6ec74c1 975 Copy(s, &auquad, 1, Uquad_t);
976 s += sizeof(Uquad_t);
fa8ec7c1 977 if (checksum > bits_in_uv)
978 cdouble += (NV)auquad;
979 else
980 culong += auquad;
a6ec74c1 981 }
a6ec74c1 982 }
fa8ec7c1 983 else {
984 EXTEND(SP, len);
985 EXTEND_MORTAL(len);
986 while (len-- > 0) {
987 if (s + sizeof(Uquad_t) > strend)
988 auquad = 0;
989 else {
990 Copy(s, &auquad, 1, Uquad_t);
991 s += sizeof(Uquad_t);
992 }
993 sv = NEWSV(43, 0);
994 if (auquad <= UV_MAX)
995 sv_setuv(sv, (UV)auquad);
996 else
997 sv_setnv(sv, (NV)auquad);
998 PUSHs(sv_2mortal(sv));
999 }
1000 }
a6ec74c1 1001 break;
1002#endif
1003 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
1004 case 'f':
1005 case 'F':
1006 along = (strend - s) / sizeof(float);
1007 if (len > along)
1008 len = along;
1009 if (checksum) {
1010 while (len-- > 0) {
1011 Copy(s, &afloat, 1, float);
1012 s += sizeof(float);
1013 cdouble += afloat;
1014 }
1015 }
1016 else {
1017 EXTEND(SP, len);
1018 EXTEND_MORTAL(len);
1019 while (len-- > 0) {
1020 Copy(s, &afloat, 1, float);
1021 s += sizeof(float);
1022 sv = NEWSV(47, 0);
1023 sv_setnv(sv, (NV)afloat);
1024 PUSHs(sv_2mortal(sv));
1025 }
1026 }
1027 break;
1028 case 'd':
1029 case 'D':
1030 along = (strend - s) / sizeof(double);
1031 if (len > along)
1032 len = along;
1033 if (checksum) {
1034 while (len-- > 0) {
1035 Copy(s, &adouble, 1, double);
1036 s += sizeof(double);
1037 cdouble += adouble;
1038 }
1039 }
1040 else {
1041 EXTEND(SP, len);
1042 EXTEND_MORTAL(len);
1043 while (len-- > 0) {
1044 Copy(s, &adouble, 1, double);
1045 s += sizeof(double);
1046 sv = NEWSV(48, 0);
1047 sv_setnv(sv, (NV)adouble);
1048 PUSHs(sv_2mortal(sv));
1049 }
1050 }
1051 break;
1052 case 'u':
1053 /* MKS:
1054 * Initialise the decode mapping. By using a table driven
1055 * algorithm, the code will be character-set independent
1056 * (and just as fast as doing character arithmetic)
1057 */
1058 if (PL_uudmap['M'] == 0) {
1059 int i;
1060
1061 for (i = 0; i < sizeof(PL_uuemap); i += 1)
1062 PL_uudmap[(U8)PL_uuemap[i]] = i;
1063 /*
1064 * Because ' ' and '`' map to the same value,
1065 * we need to decode them both the same.
1066 */
1067 PL_uudmap[' '] = 0;
1068 }
1069
1070 along = (strend - s) * 3 / 4;
1071 sv = NEWSV(42, along);
1072 if (along)
1073 SvPOK_on(sv);
1074 while (s < strend && *s > ' ' && ISUUCHAR(*s)) {
1075 I32 a, b, c, d;
1076 char hunk[4];
1077
1078 hunk[3] = '\0';
1079 len = PL_uudmap[*(U8*)s++] & 077;
1080 while (len > 0) {
1081 if (s < strend && ISUUCHAR(*s))
1082 a = PL_uudmap[*(U8*)s++] & 077;
1083 else
1084 a = 0;
1085 if (s < strend && ISUUCHAR(*s))
1086 b = PL_uudmap[*(U8*)s++] & 077;
1087 else
1088 b = 0;
1089 if (s < strend && ISUUCHAR(*s))
1090 c = PL_uudmap[*(U8*)s++] & 077;
1091 else
1092 c = 0;
1093 if (s < strend && ISUUCHAR(*s))
1094 d = PL_uudmap[*(U8*)s++] & 077;
1095 else
1096 d = 0;
1097 hunk[0] = (a << 2) | (b >> 4);
1098 hunk[1] = (b << 4) | (c >> 2);
1099 hunk[2] = (c << 6) | d;
1100 sv_catpvn(sv, hunk, (len > 3) ? 3 : len);
1101 len -= 3;
1102 }
1103 if (*s == '\n')
1104 s++;
1105 else if (s[1] == '\n') /* possible checksum byte */
1106 s += 2;
1107 }
1108 XPUSHs(sv_2mortal(sv));
1109 break;
1110 }
1111 if (checksum) {
1112 sv = NEWSV(42, 0);
1113 if (strchr("fFdD", datumtype) ||
fa8ec7c1 1114 (checksum > bits_in_uv && strchr("csSiIlLnNUvVqQ", datumtype)) ) {
a6ec74c1 1115 NV trouble;
1116
fa8ec7c1 1117 adouble = (NV) (1 << (checksum & 15));
a6ec74c1 1118 while (checksum >= 16) {
1119 checksum -= 16;
1120 adouble *= 65536.0;
1121 }
a6ec74c1 1122 while (cdouble < 0.0)
1123 cdouble += adouble;
1124 cdouble = Perl_modf(cdouble / adouble, &trouble) * adouble;
1125 sv_setnv(sv, cdouble);
1126 }
1127 else {
fa8ec7c1 1128 if (checksum < bits_in_uv) {
1129 UV mask = ((UV)1 << checksum) - 1;
1130 culong &= mask;
a6ec74c1 1131 }
1132 sv_setuv(sv, (UV)culong);
1133 }
1134 XPUSHs(sv_2mortal(sv));
1135 checksum = 0;
1136 }
b85d93de 1137 if (gimme != G_ARRAY &&
1138 SP - PL_stack_base == start_sp_offset + 1) {
1139 /* do first one only unless in list context
1140 / is implmented by unpacking the count, then poping it from the
1141 stack, so must check that we're not in the middle of a / */
1142 if ((pat >= patend) || *pat != '/')
1143 RETURN;
1144 }
a6ec74c1 1145 }
1146 if (SP - PL_stack_base == start_sp_offset && gimme == G_SCALAR)
1147 PUSHs(&PL_sv_undef);
1148 RETURN;
1149}
1150
1151STATIC void
1152S_doencodes(pTHX_ register SV *sv, register char *s, register I32 len)
1153{
1154 char hunk[5];
1155
1156 *hunk = PL_uuemap[len];
1157 sv_catpvn(sv, hunk, 1);
1158 hunk[4] = '\0';
1159 while (len > 2) {
1160 hunk[0] = PL_uuemap[(077 & (*s >> 2))];
1161 hunk[1] = PL_uuemap[(077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017)))];
1162 hunk[2] = PL_uuemap[(077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03)))];
1163 hunk[3] = PL_uuemap[(077 & (s[2] & 077))];
1164 sv_catpvn(sv, hunk, 4);
1165 s += 3;
1166 len -= 3;
1167 }
1168 if (len > 0) {
1169 char r = (len > 1 ? s[1] : '\0');
1170 hunk[0] = PL_uuemap[(077 & (*s >> 2))];
1171 hunk[1] = PL_uuemap[(077 & (((*s << 4) & 060) | ((r >> 4) & 017)))];
1172 hunk[2] = PL_uuemap[(077 & ((r << 2) & 074))];
1173 hunk[3] = PL_uuemap[0];
1174 sv_catpvn(sv, hunk, 4);
1175 }
1176 sv_catpvn(sv, "\n", 1);
1177}
1178
1179STATIC SV *
1180S_is_an_int(pTHX_ char *s, STRLEN l)
1181{
1182 STRLEN n_a;
1183 SV *result = newSVpvn(s, l);
1184 char *result_c = SvPV(result, n_a); /* convenience */
1185 char *out = result_c;
1186 bool skip = 1;
1187 bool ignore = 0;
1188
1189 while (*s) {
1190 switch (*s) {
1191 case ' ':
1192 break;
1193 case '+':
1194 if (!skip) {
1195 SvREFCNT_dec(result);
1196 return (NULL);
1197 }
1198 break;
1199 case '0':
1200 case '1':
1201 case '2':
1202 case '3':
1203 case '4':
1204 case '5':
1205 case '6':
1206 case '7':
1207 case '8':
1208 case '9':
1209 skip = 0;
1210 if (!ignore) {
1211 *(out++) = *s;
1212 }
1213 break;
1214 case '.':
1215 ignore = 1;
1216 break;
1217 default:
1218 SvREFCNT_dec(result);
1219 return (NULL);
1220 }
1221 s++;
1222 }
1223 *(out++) = '\0';
1224 SvCUR_set(result, out - result_c);
1225 return (result);
1226}
1227
1228/* pnum must be '\0' terminated */
1229STATIC int
1230S_div128(pTHX_ SV *pnum, bool *done)
1231{
1232 STRLEN len;
1233 char *s = SvPV(pnum, len);
1234 int m = 0;
1235 int r = 0;
1236 char *t = s;
1237
1238 *done = 1;
1239 while (*t) {
1240 int i;
1241
1242 i = m * 10 + (*t - '0');
1243 m = i & 0x7F;
1244 r = (i >> 7); /* r < 10 */
1245 if (r) {
1246 *done = 0;
1247 }
1248 *(t++) = '0' + r;
1249 }
1250 *(t++) = '\0';
1251 SvCUR_set(pnum, (STRLEN) (t - s));
1252 return (m);
1253}
1254
1255
1256PP(pp_pack)
1257{
1258 dSP; dMARK; dORIGMARK; dTARGET;
1259 register SV *cat = TARG;
1260 register I32 items;
1261 STRLEN fromlen;
1262 register char *pat = SvPVx(*++MARK, fromlen);
1263 char *patcopy;
1264 register char *patend = pat + fromlen;
1265 register I32 len;
1266 I32 datumtype;
1267 SV *fromstr;
1268 /*SUPPRESS 442*/
1269 static char null10[] = {0,0,0,0,0,0,0,0,0,0};
1270 static char *space10 = " ";
1271
1272 /* These must not be in registers: */
1273 char achar;
1274 I16 ashort;
1275 int aint;
1276 unsigned int auint;
1277 I32 along;
1278 U32 aulong;
1279#ifdef HAS_QUAD
1280 Quad_t aquad;
1281 Uquad_t auquad;
1282#endif
1283 char *aptr;
1284 float afloat;
1285 double adouble;
1286 int commas = 0;
1287#ifdef PERL_NATINT_PACK
1288 int natint; /* native integer */
1289#endif
1290
1291 items = SP - MARK;
1292 MARK++;
1293 sv_setpvn(cat, "", 0);
1294 patcopy = pat;
1295 while (pat < patend) {
1296 SV *lengthcode = Nullsv;
1297#define NEXTFROM ( lengthcode ? lengthcode : items-- > 0 ? *MARK++ : &PL_sv_no)
1298 datumtype = *pat++ & 0xFF;
1299#ifdef PERL_NATINT_PACK
1300 natint = 0;
1301#endif
1302 if (isSPACE(datumtype)) {
1303 patcopy++;
1304 continue;
1305 }
1306#ifndef PACKED_IS_OCTETS
1307 if (datumtype == 'U' && pat == patcopy+1)
1308 SvUTF8_on(cat);
1309#endif
1310 if (datumtype == '#') {
1311 while (pat < patend && *pat != '\n')
1312 pat++;
1313 continue;
1314 }
1315 if (*pat == '!') {
1316 char *natstr = "sSiIlL";
1317
1318 if (strchr(natstr, datumtype)) {
1319#ifdef PERL_NATINT_PACK
1320 natint = 1;
1321#endif
1322 pat++;
1323 }
1324 else
1325 DIE(aTHX_ "'!' allowed only after types %s", natstr);
1326 }
1327 if (*pat == '*') {
1328 len = strchr("@Xxu", datumtype) ? 0 : items;
1329 pat++;
1330 }
1331 else if (isDIGIT(*pat)) {
1332 len = *pat++ - '0';
1333 while (isDIGIT(*pat)) {
1334 len = (len * 10) + (*pat++ - '0');
1335 if (len < 0)
1336 DIE(aTHX_ "Repeat count in pack overflows");
1337 }
1338 }
1339 else
1340 len = 1;
1341 if (*pat == '/') {
1342 ++pat;
1343 if ((*pat != 'a' && *pat != 'A' && *pat != 'Z') || pat[1] != '*')
1344 DIE(aTHX_ "/ must be followed by a*, A* or Z*");
1345 lengthcode = sv_2mortal(newSViv(sv_len(items > 0
1346 ? *MARK : &PL_sv_no)
1347 + (*pat == 'Z' ? 1 : 0)));
1348 }
1349 switch(datumtype) {
1350 default:
1351 DIE(aTHX_ "Invalid type in pack: '%c'", (int)datumtype);
1352 case ',': /* grandfather in commas but with a warning */
1353 if (commas++ == 0 && ckWARN(WARN_PACK))
1354 Perl_warner(aTHX_ WARN_PACK,
1355 "Invalid type in pack: '%c'", (int)datumtype);
1356 break;
1357 case '%':
1358 DIE(aTHX_ "%% may only be used in unpack");
1359 case '@':
1360 len -= SvCUR(cat);
1361 if (len > 0)
1362 goto grow;
1363 len = -len;
1364 if (len > 0)
1365 goto shrink;
1366 break;
1367 case 'X':
1368 shrink:
1369 if (SvCUR(cat) < len)
1370 DIE(aTHX_ "X outside of string");
1371 SvCUR(cat) -= len;
1372 *SvEND(cat) = '\0';
1373 break;
1374 case 'x':
1375 grow:
1376 while (len >= 10) {
1377 sv_catpvn(cat, null10, 10);
1378 len -= 10;
1379 }
1380 sv_catpvn(cat, null10, len);
1381 break;
1382 case 'A':
1383 case 'Z':
1384 case 'a':
1385 fromstr = NEXTFROM;
1386 aptr = SvPV(fromstr, fromlen);
1387 if (pat[-1] == '*') {
1388 len = fromlen;
1389 if (datumtype == 'Z')
1390 ++len;
1391 }
1392 if (fromlen >= len) {
1393 sv_catpvn(cat, aptr, len);
1394 if (datumtype == 'Z')
1395 *(SvEND(cat)-1) = '\0';
1396 }
1397 else {
1398 sv_catpvn(cat, aptr, fromlen);
1399 len -= fromlen;
1400 if (datumtype == 'A') {
1401 while (len >= 10) {
1402 sv_catpvn(cat, space10, 10);
1403 len -= 10;
1404 }
1405 sv_catpvn(cat, space10, len);
1406 }
1407 else {
1408 while (len >= 10) {
1409 sv_catpvn(cat, null10, 10);
1410 len -= 10;
1411 }
1412 sv_catpvn(cat, null10, len);
1413 }
1414 }
1415 break;
1416 case 'B':
1417 case 'b':
1418 {
1419 register char *str;
1420 I32 saveitems;
1421
1422 fromstr = NEXTFROM;
1423 saveitems = items;
1424 str = SvPV(fromstr, fromlen);
1425 if (pat[-1] == '*')
1426 len = fromlen;
1427 aint = SvCUR(cat);
1428 SvCUR(cat) += (len+7)/8;
1429 SvGROW(cat, SvCUR(cat) + 1);
1430 aptr = SvPVX(cat) + aint;
1431 if (len > fromlen)
1432 len = fromlen;
1433 aint = len;
1434 items = 0;
1435 if (datumtype == 'B') {
1436 for (len = 0; len++ < aint;) {
1437 items |= *str++ & 1;
1438 if (len & 7)
1439 items <<= 1;
1440 else {
1441 *aptr++ = items & 0xff;
1442 items = 0;
1443 }
1444 }
1445 }
1446 else {
1447 for (len = 0; len++ < aint;) {
1448 if (*str++ & 1)
1449 items |= 128;
1450 if (len & 7)
1451 items >>= 1;
1452 else {
1453 *aptr++ = items & 0xff;
1454 items = 0;
1455 }
1456 }
1457 }
1458 if (aint & 7) {
1459 if (datumtype == 'B')
1460 items <<= 7 - (aint & 7);
1461 else
1462 items >>= 7 - (aint & 7);
1463 *aptr++ = items & 0xff;
1464 }
1465 str = SvPVX(cat) + SvCUR(cat);
1466 while (aptr <= str)
1467 *aptr++ = '\0';
1468
1469 items = saveitems;
1470 }
1471 break;
1472 case 'H':
1473 case 'h':
1474 {
1475 register char *str;
1476 I32 saveitems;
1477
1478 fromstr = NEXTFROM;
1479 saveitems = items;
1480 str = SvPV(fromstr, fromlen);
1481 if (pat[-1] == '*')
1482 len = fromlen;
1483 aint = SvCUR(cat);
1484 SvCUR(cat) += (len+1)/2;
1485 SvGROW(cat, SvCUR(cat) + 1);
1486 aptr = SvPVX(cat) + aint;
1487 if (len > fromlen)
1488 len = fromlen;
1489 aint = len;
1490 items = 0;
1491 if (datumtype == 'H') {
1492 for (len = 0; len++ < aint;) {
1493 if (isALPHA(*str))
1494 items |= ((*str++ & 15) + 9) & 15;
1495 else
1496 items |= *str++ & 15;
1497 if (len & 1)
1498 items <<= 4;
1499 else {
1500 *aptr++ = items & 0xff;
1501 items = 0;
1502 }
1503 }
1504 }
1505 else {
1506 for (len = 0; len++ < aint;) {
1507 if (isALPHA(*str))
1508 items |= (((*str++ & 15) + 9) & 15) << 4;
1509 else
1510 items |= (*str++ & 15) << 4;
1511 if (len & 1)
1512 items >>= 4;
1513 else {
1514 *aptr++ = items & 0xff;
1515 items = 0;
1516 }
1517 }
1518 }
1519 if (aint & 1)
1520 *aptr++ = items & 0xff;
1521 str = SvPVX(cat) + SvCUR(cat);
1522 while (aptr <= str)
1523 *aptr++ = '\0';
1524
1525 items = saveitems;
1526 }
1527 break;
1528 case 'C':
1529 case 'c':
1530 while (len-- > 0) {
1531 fromstr = NEXTFROM;
1532 switch (datumtype) {
1533 case 'C':
1534 aint = SvIV(fromstr);
1535 if ((aint < 0 || aint > 255) &&
1536 ckWARN(WARN_PACK))
1537 Perl_warner(aTHX_ WARN_PACK,
1538 "Character in \"C\" format wrapped");
1539 achar = aint & 255;
1540 sv_catpvn(cat, &achar, sizeof(char));
1541 break;
1542 case 'c':
1543 aint = SvIV(fromstr);
1544 if ((aint < -128 || aint > 127) &&
1545 ckWARN(WARN_PACK))
1546 Perl_warner(aTHX_ WARN_PACK,
1547 "Character in \"c\" format wrapped");
1548 achar = aint & 255;
1549 sv_catpvn(cat, &achar, sizeof(char));
1550 break;
1551 }
1552 }
1553 break;
1554 case 'U':
1555 while (len-- > 0) {
1556 fromstr = NEXTFROM;
1557 auint = SvUV(fromstr);
1558 SvGROW(cat, SvCUR(cat) + UTF8_MAXLEN + 1);
1559 SvCUR_set(cat, (char*)uvchr_to_utf8((U8*)SvEND(cat),auint)
1560 - SvPVX(cat));
1561 }
1562 *SvEND(cat) = '\0';
1563 break;
1564 /* Float and double added by gnb@melba.bby.oz.au 22/11/89 */
1565 case 'f':
1566 case 'F':
1567 while (len-- > 0) {
1568 fromstr = NEXTFROM;
1569 afloat = (float)SvNV(fromstr);
1570 sv_catpvn(cat, (char *)&afloat, sizeof (float));
1571 }
1572 break;
1573 case 'd':
1574 case 'D':
1575 while (len-- > 0) {
1576 fromstr = NEXTFROM;
1577 adouble = (double)SvNV(fromstr);
1578 sv_catpvn(cat, (char *)&adouble, sizeof (double));
1579 }
1580 break;
1581 case 'n':
1582 while (len-- > 0) {
1583 fromstr = NEXTFROM;
1584 ashort = (I16)SvIV(fromstr);
1585#ifdef HAS_HTONS
1586 ashort = PerlSock_htons(ashort);
1587#endif
1588 CAT16(cat, &ashort);
1589 }
1590 break;
1591 case 'v':
1592 while (len-- > 0) {
1593 fromstr = NEXTFROM;
1594 ashort = (I16)SvIV(fromstr);
1595#ifdef HAS_HTOVS
1596 ashort = htovs(ashort);
1597#endif
1598 CAT16(cat, &ashort);
1599 }
1600 break;
1601 case 'S':
1602#if SHORTSIZE != SIZE16
1603 if (natint) {
1604 unsigned short aushort;
1605
1606 while (len-- > 0) {
1607 fromstr = NEXTFROM;
1608 aushort = SvUV(fromstr);
1609 sv_catpvn(cat, (char *)&aushort, sizeof(unsigned short));
1610 }
1611 }
1612 else
1613#endif
1614 {
1615 U16 aushort;
1616
1617 while (len-- > 0) {
1618 fromstr = NEXTFROM;
1619 aushort = (U16)SvUV(fromstr);
1620 CAT16(cat, &aushort);
1621 }
1622
1623 }
1624 break;
1625 case 's':
1626#if SHORTSIZE != SIZE16
1627 if (natint) {
1628 short ashort;
1629
1630 while (len-- > 0) {
1631 fromstr = NEXTFROM;
1632 ashort = SvIV(fromstr);
1633 sv_catpvn(cat, (char *)&ashort, sizeof(short));
1634 }
1635 }
1636 else
1637#endif
1638 {
1639 while (len-- > 0) {
1640 fromstr = NEXTFROM;
1641 ashort = (I16)SvIV(fromstr);
1642 CAT16(cat, &ashort);
1643 }
1644 }
1645 break;
1646 case 'I':
1647 while (len-- > 0) {
1648 fromstr = NEXTFROM;
1649 auint = SvUV(fromstr);
1650 sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
1651 }
1652 break;
1653 case 'w':
1654 while (len-- > 0) {
1655 fromstr = NEXTFROM;
1656 adouble = Perl_floor(SvNV(fromstr));
1657
1658 if (adouble < 0)
1659 DIE(aTHX_ "Cannot compress negative numbers");
1660
1661 if (
1662#if UVSIZE > 4 && UVSIZE >= NVSIZE
1663 adouble <= 0xffffffff
1664#else
1665# ifdef CXUX_BROKEN_CONSTANT_CONVERT
1666 adouble <= UV_MAX_cxux
1667# else
1668 adouble <= UV_MAX
1669# endif
1670#endif
1671 )
1672 {
1673 char buf[1 + sizeof(UV)];
1674 char *in = buf + sizeof(buf);
1675 UV auv = U_V(adouble);
1676
1677 do {
1678 *--in = (auv & 0x7f) | 0x80;
1679 auv >>= 7;
1680 } while (auv);
1681 buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
1682 sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
1683 }
1684 else if (SvPOKp(fromstr)) { /* decimal string arithmetics */
1685 char *from, *result, *in;
1686 SV *norm;
1687 STRLEN len;
1688 bool done;
1689
1690 /* Copy string and check for compliance */
1691 from = SvPV(fromstr, len);
1692 if ((norm = is_an_int(from, len)) == NULL)
1693 DIE(aTHX_ "can compress only unsigned integer");
1694
1695 New('w', result, len, char);
1696 in = result + len;
1697 done = FALSE;
1698 while (!done)
1699 *--in = div128(norm, &done) | 0x80;
1700 result[len - 1] &= 0x7F; /* clear continue bit */
1701 sv_catpvn(cat, in, (result + len) - in);
1702 Safefree(result);
1703 SvREFCNT_dec(norm); /* free norm */
1704 }
1705 else if (SvNOKp(fromstr)) {
1706 char buf[sizeof(double) * 2]; /* 8/7 <= 2 */
1707 char *in = buf + sizeof(buf);
1708
1709 do {
1710 double next = floor(adouble / 128);
1711 *--in = (unsigned char)(adouble - (next * 128)) | 0x80;
1712 if (in <= buf) /* this cannot happen ;-) */
1713 DIE(aTHX_ "Cannot compress integer");
a6ec74c1 1714 adouble = next;
1715 } while (adouble > 0);
1716 buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
1717 sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
1718 }
1719 else
1720 DIE(aTHX_ "Cannot compress non integer");
1721 }
1722 break;
1723 case 'i':
1724 while (len-- > 0) {
1725 fromstr = NEXTFROM;
1726 aint = SvIV(fromstr);
1727 sv_catpvn(cat, (char*)&aint, sizeof(int));
1728 }
1729 break;
1730 case 'N':
1731 while (len-- > 0) {
1732 fromstr = NEXTFROM;
1733 aulong = SvUV(fromstr);
1734#ifdef HAS_HTONL
1735 aulong = PerlSock_htonl(aulong);
1736#endif
1737 CAT32(cat, &aulong);
1738 }
1739 break;
1740 case 'V':
1741 while (len-- > 0) {
1742 fromstr = NEXTFROM;
1743 aulong = SvUV(fromstr);
1744#ifdef HAS_HTOVL
1745 aulong = htovl(aulong);
1746#endif
1747 CAT32(cat, &aulong);
1748 }
1749 break;
1750 case 'L':
1751#if LONGSIZE != SIZE32
1752 if (natint) {
1753 unsigned long aulong;
1754
1755 while (len-- > 0) {
1756 fromstr = NEXTFROM;
1757 aulong = SvUV(fromstr);
1758 sv_catpvn(cat, (char *)&aulong, sizeof(unsigned long));
1759 }
1760 }
1761 else
1762#endif
1763 {
1764 while (len-- > 0) {
1765 fromstr = NEXTFROM;
1766 aulong = SvUV(fromstr);
1767 CAT32(cat, &aulong);
1768 }
1769 }
1770 break;
1771 case 'l':
1772#if LONGSIZE != SIZE32
1773 if (natint) {
1774 long along;
1775
1776 while (len-- > 0) {
1777 fromstr = NEXTFROM;
1778 along = SvIV(fromstr);
1779 sv_catpvn(cat, (char *)&along, sizeof(long));
1780 }
1781 }
1782 else
1783#endif
1784 {
1785 while (len-- > 0) {
1786 fromstr = NEXTFROM;
1787 along = SvIV(fromstr);
1788 CAT32(cat, &along);
1789 }
1790 }
1791 break;
1792#ifdef HAS_QUAD
1793 case 'Q':
1794 while (len-- > 0) {
1795 fromstr = NEXTFROM;
1796 auquad = (Uquad_t)SvUV(fromstr);
1797 sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t));
1798 }
1799 break;
1800 case 'q':
1801 while (len-- > 0) {
1802 fromstr = NEXTFROM;
1803 aquad = (Quad_t)SvIV(fromstr);
1804 sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
1805 }
1806 break;
1807#endif
1808 case 'P':
1809 len = 1; /* assume SV is correct length */
1810 /* FALL THROUGH */
1811 case 'p':
1812 while (len-- > 0) {
1813 fromstr = NEXTFROM;
1814 if (fromstr == &PL_sv_undef)
1815 aptr = NULL;
1816 else {
1817 STRLEN n_a;
1818 /* XXX better yet, could spirit away the string to
1819 * a safe spot and hang on to it until the result
1820 * of pack() (and all copies of the result) are
1821 * gone.
1822 */
1823 if (ckWARN(WARN_PACK) && (SvTEMP(fromstr)
1824 || (SvPADTMP(fromstr)
1825 && !SvREADONLY(fromstr))))
1826 {
1827 Perl_warner(aTHX_ WARN_PACK,
1828 "Attempt to pack pointer to temporary value");
1829 }
1830 if (SvPOK(fromstr) || SvNIOK(fromstr))
1831 aptr = SvPV(fromstr,n_a);
1832 else
1833 aptr = SvPV_force(fromstr,n_a);
1834 }
1835 sv_catpvn(cat, (char*)&aptr, sizeof(char*));
1836 }
1837 break;
1838 case 'u':
1839 fromstr = NEXTFROM;
1840 aptr = SvPV(fromstr, fromlen);
1841 SvGROW(cat, fromlen * 4 / 3);
1842 if (len <= 1)
1843 len = 45;
1844 else
1845 len = len / 3 * 3;
1846 while (fromlen > 0) {
1847 I32 todo;
1848
1849 if (fromlen > len)
1850 todo = len;
1851 else
1852 todo = fromlen;
1853 doencodes(cat, aptr, todo);
1854 fromlen -= todo;
1855 aptr += todo;
1856 }
1857 break;
1858 }
1859 }
1860 SvSETMAGIC(cat);
1861 SP = ORIGMARK;
1862 PUSHs(cat);
1863 RETURN;
1864}
1865#undef NEXTFROM
1866