2 do_unpack(TARG,gimme,arglast)
7 STR **st = stack->ary_array;
8 register int sp = arglast[0] + 1;
9 register char *pat = str_get(st[sp++]);
10 register char *s = str_get(st[sp]);
11 char *strend = s + st[sp--]->str_cur;
13 register char *patend = pat + st[sp]->str_cur;
18 /* These must not be in registers: */
25 unsigned short aushort;
38 if (gimme != G_ARRAY) { /* arrange to do first one only */
40 for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
41 if (index("aAbBhH", *patend) || *pat == '%') {
43 while (isDIGIT(*patend) || *patend == '*')
50 while (pat < patend) {
55 else if (*pat == '*') {
56 len = strend - strbeg; /* long enough */
59 else if (isDIGIT(*pat)) {
62 len = (len * 10) + (*pat++ - '0');
65 len = (datumtype != '@');
70 if (len == 1 && pat[-1] != '1')
79 if (len > strend - strbeg)
80 fatal("@ outside of string");
85 fatal("X outside of string");
90 fatal("x outside of string");
99 TARG = Str_new(35,len);
100 str_nset(TARG,s,len);
102 if (datumtype == 'A') {
103 aptr = s; /* borrow register */
104 s = TARG->str_ptr + len - 1;
105 while (s >= TARG->str_ptr && (!*s || isSPACE(*s)))
108 TARG->str_cur = s - TARG->str_ptr;
109 s = aptr; /* unborrow register */
111 (void)astore(stack, ++sp, str_2mortal(TARG));
115 if (pat[-1] == '*' || len > (strend - s) * 8)
116 len = (strend - s) * 8;
117 TARG = Str_new(35, len + 1);
120 aptr = pat; /* borrow register */
122 if (datumtype == 'b') {
124 for (len = 0; len < aint; len++) {
125 if (len & 7) /*SUPPRESS 595*/
129 *pat++ = '0' + (bits & 1);
134 for (len = 0; len < aint; len++) {
139 *pat++ = '0' + ((bits & 128) != 0);
143 pat = aptr; /* unborrow register */
144 (void)astore(stack, ++sp, str_2mortal(TARG));
148 if (pat[-1] == '*' || len > (strend - s) * 2)
149 len = (strend - s) * 2;
150 TARG = Str_new(35, len + 1);
153 aptr = pat; /* borrow register */
155 if (datumtype == 'h') {
157 for (len = 0; len < aint; len++) {
162 *pat++ = hexdigit[bits & 15];
167 for (len = 0; len < aint; len++) {
172 *pat++ = hexdigit[(bits >> 4) & 15];
176 pat = aptr; /* unborrow register */
177 (void)astore(stack, ++sp, str_2mortal(TARG));
180 if (len > strend - s)
185 if (aint >= 128) /* fake up signed chars */
193 if (aint >= 128) /* fake up signed chars */
195 TARG = Str_new(36,0);
196 str_numset(TARG,(double)aint);
197 (void)astore(stack, ++sp, str_2mortal(TARG));
202 if (len > strend - s)
214 TARG = Str_new(37,0);
215 str_numset(TARG,(double)auint);
216 (void)astore(stack, ++sp, str_2mortal(TARG));
221 along = (strend - s) / sizeof(short);
226 Copy(s,&ashort,1,short);
233 Copy(s,&ashort,1,short);
235 TARG = Str_new(38,0);
236 str_numset(TARG,(double)ashort);
237 (void)astore(stack, ++sp, str_2mortal(TARG));
244 along = (strend - s) / sizeof(unsigned short);
249 Copy(s,&aushort,1,unsigned short);
250 s += sizeof(unsigned short);
252 if (datumtype == 'n')
253 aushort = ntohs(aushort);
256 if (datumtype == 'v')
257 aushort = vtohs(aushort);
264 Copy(s,&aushort,1,unsigned short);
265 s += sizeof(unsigned short);
266 TARG = Str_new(39,0);
268 if (datumtype == 'n')
269 aushort = ntohs(aushort);
272 if (datumtype == 'v')
273 aushort = vtohs(aushort);
275 str_numset(TARG,(double)aushort);
276 (void)astore(stack, ++sp, str_2mortal(TARG));
281 along = (strend - s) / sizeof(int);
289 cdouble += (double)aint;
298 TARG = Str_new(40,0);
299 str_numset(TARG,(double)aint);
300 (void)astore(stack, ++sp, str_2mortal(TARG));
305 along = (strend - s) / sizeof(unsigned int);
310 Copy(s,&auint,1,unsigned int);
311 s += sizeof(unsigned int);
313 cdouble += (double)auint;
320 Copy(s,&auint,1,unsigned int);
321 s += sizeof(unsigned int);
322 TARG = Str_new(41,0);
323 str_numset(TARG,(double)auint);
324 (void)astore(stack, ++sp, str_2mortal(TARG));
329 along = (strend - s) / sizeof(long);
334 Copy(s,&along,1,long);
337 cdouble += (double)along;
344 Copy(s,&along,1,long);
346 TARG = Str_new(42,0);
347 str_numset(TARG,(double)along);
348 (void)astore(stack, ++sp, str_2mortal(TARG));
355 along = (strend - s) / sizeof(unsigned long);
360 Copy(s,&aulong,1,unsigned long);
361 s += sizeof(unsigned long);
363 if (datumtype == 'N')
364 aulong = ntohl(aulong);
367 if (datumtype == 'V')
368 aulong = vtohl(aulong);
371 cdouble += (double)aulong;
378 Copy(s,&aulong,1,unsigned long);
379 s += sizeof(unsigned long);
380 TARG = Str_new(43,0);
382 if (datumtype == 'N')
383 aulong = ntohl(aulong);
386 if (datumtype == 'V')
387 aulong = vtohl(aulong);
389 str_numset(TARG,(double)aulong);
390 (void)astore(stack, ++sp, str_2mortal(TARG));
395 along = (strend - s) / sizeof(char*);
399 if (sizeof(char*) > strend - s)
402 Copy(s,&aptr,1,char*);
405 TARG = Str_new(44,0);
408 (void)astore(stack, ++sp, str_2mortal(TARG));
414 if (s + sizeof(quad) > strend)
417 Copy(s,&aquad,1,quad);
420 TARG = Str_new(42,0);
421 str_numset(TARG,(double)aquad);
422 (void)astore(stack, ++sp, str_2mortal(TARG));
427 if (s + sizeof(unsigned quad) > strend)
430 Copy(s,&auquad,1,unsigned quad);
431 s += sizeof(unsigned quad);
433 TARG = Str_new(43,0);
434 str_numset(TARG,(double)auquad);
435 (void)astore(stack, ++sp, str_2mortal(TARG));
439 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
442 along = (strend - s) / sizeof(float);
447 Copy(s, &afloat,1, float);
454 Copy(s, &afloat,1, float);
456 TARG = Str_new(47, 0);
457 str_numset(TARG, (double)afloat);
458 (void)astore(stack, ++sp, str_2mortal(TARG));
464 along = (strend - s) / sizeof(double);
469 Copy(s, &adouble,1, double);
476 Copy(s, &adouble,1, double);
478 TARG = Str_new(48, 0);
479 str_numset(TARG, (double)adouble);
480 (void)astore(stack, ++sp, str_2mortal(TARG));
485 along = (strend - s) * 3 / 4;
486 TARG = Str_new(42,along);
487 while (s < strend && *s > ' ' && *s < 'a') {
492 len = (*s++ - ' ') & 077;
494 if (s < strend && *s >= ' ')
495 a = (*s++ - ' ') & 077;
498 if (s < strend && *s >= ' ')
499 b = (*s++ - ' ') & 077;
502 if (s < strend && *s >= ' ')
503 c = (*s++ - ' ') & 077;
506 if (s < strend && *s >= ' ')
507 d = (*s++ - ' ') & 077;
510 hunk[0] = a << 2 | b >> 4;
511 hunk[1] = b << 4 | c >> 2;
512 hunk[2] = c << 6 | d;
513 str_ncat(TARG,hunk, len > 3 ? 3 : len);
518 else if (s[1] == '\n') /* possible checksum byte */
521 (void)astore(stack, ++sp, str_2mortal(TARG));
525 TARG = Str_new(42,0);
526 if (index("fFdD", datumtype) ||
527 (checksum > 32 && index("iIlLN", datumtype)) ) {
532 while (checksum >= 16) {
536 while (checksum >= 4) {
542 along = (1 << checksum) - 1;
543 while (cdouble < 0.0)
545 cdouble = modf(cdouble / adouble, &trouble) * adouble;
546 str_numset(TARG,cdouble);
550 along = (1 << checksum) - 1;
551 culong &= (unsigned long)along;
553 str_numset(TARG,(double)culong);
555 (void)astore(stack, ++sp, str_2mortal(TARG));