perl 3.0 patch #41 (combined patch)
[p5sagit/p5-mst-13.2.git] / doarg.c
CommitLineData
57ebbfd0 1/* $Header: doarg.c,v 3.0.1.9 90/11/10 01:14:31 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
7 *
8 * $Log: doarg.c,v $
57ebbfd0 9 * Revision 3.0.1.9 90/11/10 01:14:31 lwall
10 * patch38: random cleanup
11 * patch38: optimized join('',...)
12 * patch38: printf cleaned up
13 *
20188a90 14 * Revision 3.0.1.8 90/10/15 16:04:04 lwall
15 * patch29: @ENV = () now works
16 * patch29: added caller
17 * patch29: tr/// now understands c, d and s options, and handles nulls right
18 * patch29: *foo now prints as *package'foo
19 * patch29: added caller
20 * patch29: local() without initialization now creates undefined values
21 *
6eb13c3b 22 * Revision 3.0.1.7 90/08/13 22:14:15 lwall
23 * patch28: the NSIG hack didn't work on Xenix
24 * patch28: defined(@array) and defined(%array) didn't work right
25 *
ff8e2863 26 * Revision 3.0.1.6 90/08/09 02:48:38 lwall
27 * patch19: fixed double include of <signal.h>
28 * patch19: pack/unpack can now do native float and double
29 * patch19: pack/unpack can now have absolute and negative positioning
30 * patch19: pack/unpack can now have use * to specify all the rest of input
31 * patch19: unpack can do checksumming
32 * patch19: $< and $> better supported on machines without setreuid
33 * patch19: Added support for linked-in C subroutines
34 *
b1248f16 35 * Revision 3.0.1.5 90/03/27 15:39:03 lwall
36 * patch16: MSDOS support
37 * patch16: support for machines that can't cast negative floats to unsigned ints
38 * patch16: sprintf($s,...,$s,...) didn't work
39 *
ff2452de 40 * Revision 3.0.1.4 90/03/12 16:28:42 lwall
41 * patch13: pack of ascii strings could call str_ncat() with negative length
42 * patch13: printf("%s", *foo) was busted
43 *
afd9f252 44 * Revision 3.0.1.3 90/02/28 16:56:58 lwall
45 * patch9: split now can split into more than 10000 elements
46 * patch9: sped up pack and unpack
47 * patch9: pack of unsigned ints and longs blew up some places
48 * patch9: sun3 can't cast negative float to unsigned int or long
49 * patch9: local($.) didn't work
50 * patch9: grep(s/foo/bar/, @abc = @xyz) modified @xyz rather than @abc
51 * patch9: syscall returned stack size rather than value of system call
52 *
663a0e37 53 * Revision 3.0.1.2 89/12/21 19:52:15 lwall
54 * patch7: a pattern wouldn't match a null string before the first character
55 * patch7: certain patterns didn't match correctly at end of string
56 *
bf38876a 57 * Revision 3.0.1.1 89/11/11 04:17:20 lwall
58 * patch2: printf %c, %D, %X and %O didn't work right
59 * patch2: printf of unsigned vs signed needed separate casts on some machines
60 *
a687059c 61 * Revision 3.0 89/10/18 15:10:41 lwall
62 * 3.0 baseline
63 *
64 */
65
66#include "EXTERN.h"
67#include "perl.h"
68
6eb13c3b 69#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
a687059c 70#include <signal.h>
ff8e2863 71#endif
a687059c 72
73extern unsigned char fold[];
74
20188a90 75extern char **environ;
a687059c 76
b1248f16 77#ifdef BUGGY_MSC
78 #pragma function(memcmp)
79#endif /* BUGGY_MSC */
80
a687059c 81int
82do_subst(str,arg,sp)
83STR *str;
84ARG *arg;
85int sp;
86{
87 register SPAT *spat;
88 SPAT *rspat;
89 register STR *dstr;
90 register char *s = str_get(str);
91 char *strend = s + str->str_cur;
92 register char *m;
93 char *c;
94 register char *d;
95 int clen;
96 int iters = 0;
afd9f252 97 int maxiters = (strend - s) + 10;
a687059c 98 register int i;
99 bool once;
100 char *orig;
101 int safebase;
102
103 rspat = spat = arg[2].arg_ptr.arg_spat;
104 if (!spat || !s)
105 fatal("panic: do_subst");
106 else if (spat->spat_runtime) {
107 nointrp = "|)";
108 (void)eval(spat->spat_runtime,G_SCALAR,sp);
109 m = str_get(dstr = stack->ary_array[sp+1]);
110 nointrp = "";
111 if (spat->spat_regexp)
112 regfree(spat->spat_regexp);
113 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
ff8e2863 114 spat->spat_flags & SPAT_FOLD);
a687059c 115 if (spat->spat_flags & SPAT_KEEP) {
116 arg_free(spat->spat_runtime); /* it won't change, so */
117 spat->spat_runtime = Nullarg; /* no point compiling again */
118 }
119 }
120#ifdef DEBUGGING
121 if (debug & 8) {
122 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
123 }
124#endif
125 safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) &&
126 !sawampersand);
127 if (!*spat->spat_regexp->precomp && lastspat)
128 spat = lastspat;
129 orig = m = s;
130 if (hint) {
131 if (hint < s || hint > strend)
132 fatal("panic: hint in do_match");
133 s = hint;
134 hint = Nullch;
135 if (spat->spat_regexp->regback >= 0) {
136 s -= spat->spat_regexp->regback;
137 if (s < m)
138 s = m;
139 }
140 else
141 s = m;
142 }
143 else if (spat->spat_short) {
144 if (spat->spat_flags & SPAT_SCANFIRST) {
145 if (str->str_pok & SP_STUDIED) {
146 if (screamfirst[spat->spat_short->str_rare] < 0)
147 goto nope;
148 else if (!(s = screaminstr(str,spat->spat_short)))
149 goto nope;
150 }
151#ifndef lint
152 else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend,
153 spat->spat_short)))
154 goto nope;
155#endif
156 if (s && spat->spat_regexp->regback >= 0) {
157 ++spat->spat_short->str_u.str_useful;
158 s -= spat->spat_regexp->regback;
159 if (s < m)
160 s = m;
161 }
162 else
163 s = m;
164 }
165 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
166 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
167 goto nope;
168 if (--spat->spat_short->str_u.str_useful < 0) {
169 str_free(spat->spat_short);
170 spat->spat_short = Nullstr; /* opt is being useless */
171 }
172 }
173 once = ((rspat->spat_flags & SPAT_ONCE) != 0);
174 if (rspat->spat_flags & SPAT_CONST) { /* known replacement string? */
175 if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
176 dstr = rspat->spat_repl[1].arg_ptr.arg_str;
177 else { /* constant over loop, anyway */
178 (void)eval(rspat->spat_repl,G_SCALAR,sp);
179 dstr = stack->ary_array[sp+1];
180 }
181 c = str_get(dstr);
182 clen = dstr->str_cur;
183 if (clen <= spat->spat_slen + spat->spat_regexp->regback) {
184 /* can do inplace substitution */
663a0e37 185 if (regexec(spat->spat_regexp, s, strend, orig, 0,
a687059c 186 str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
187 if (spat->spat_regexp->subbase) /* oops, no we can't */
188 goto long_way;
189 d = s;
190 lastspat = spat;
191 str->str_pok = SP_VALID; /* disable possible screamer */
192 if (once) {
193 m = spat->spat_regexp->startp[0];
194 d = spat->spat_regexp->endp[0];
195 s = orig;
196 if (m - s > strend - d) { /* faster to shorten from end */
197 if (clen) {
198 (void)bcopy(c, m, clen);
199 m += clen;
200 }
201 i = strend - d;
202 if (i > 0) {
203 (void)bcopy(d, m, i);
204 m += i;
205 }
206 *m = '\0';
207 str->str_cur = m - s;
208 STABSET(str);
209 str_numset(arg->arg_ptr.arg_str, 1.0);
210 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
211 return sp;
212 }
213 else if (i = m - s) { /* faster from front */
214 d -= clen;
215 m = d;
216 str_chop(str,d-i);
217 s += i;
218 while (i--)
219 *--d = *--s;
220 if (clen)
221 (void)bcopy(c, m, clen);
222 STABSET(str);
223 str_numset(arg->arg_ptr.arg_str, 1.0);
224 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
225 return sp;
226 }
227 else if (clen) {
228 d -= clen;
229 str_chop(str,d);
230 (void)bcopy(c,d,clen);
231 STABSET(str);
232 str_numset(arg->arg_ptr.arg_str, 1.0);
233 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
234 return sp;
235 }
236 else {
237 str_chop(str,d);
238 STABSET(str);
239 str_numset(arg->arg_ptr.arg_str, 1.0);
240 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
241 return sp;
242 }
243 /* NOTREACHED */
244 }
245 do {
afd9f252 246 if (iters++ > maxiters)
a687059c 247 fatal("Substitution loop");
248 m = spat->spat_regexp->startp[0];
249 if (i = m - s) {
250 if (s != d)
251 (void)bcopy(s,d,i);
252 d += i;
253 }
254 if (clen) {
255 (void)bcopy(c,d,clen);
256 d += clen;
257 }
258 s = spat->spat_regexp->endp[0];
663a0e37 259 } while (regexec(spat->spat_regexp, s, strend, orig, s == m,
260 Nullstr, TRUE)); /* (don't match same null twice) */
a687059c 261 if (s != d) {
262 i = strend - s;
263 str->str_cur = d - str->str_ptr + i;
264 (void)bcopy(s,d,i+1); /* include the Null */
265 }
266 STABSET(str);
267 str_numset(arg->arg_ptr.arg_str, (double)iters);
268 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
269 return sp;
270 }
271 str_numset(arg->arg_ptr.arg_str, 0.0);
272 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
273 return sp;
274 }
275 }
276 else
277 c = Nullch;
663a0e37 278 if (regexec(spat->spat_regexp, s, strend, orig, 0,
a687059c 279 str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
280 long_way:
281 dstr = Str_new(25,str_len(str));
282 str_nset(dstr,m,s-m);
283 if (spat->spat_regexp->subbase)
284 curspat = spat;
285 lastspat = spat;
286 do {
afd9f252 287 if (iters++ > maxiters)
a687059c 288 fatal("Substitution loop");
289 if (spat->spat_regexp->subbase
290 && spat->spat_regexp->subbase != orig) {
291 m = s;
292 s = orig;
293 orig = spat->spat_regexp->subbase;
294 s = orig + (m - s);
295 strend = s + (strend - m);
296 }
297 m = spat->spat_regexp->startp[0];
298 str_ncat(dstr,s,m-s);
299 s = spat->spat_regexp->endp[0];
300 if (c) {
301 if (clen)
302 str_ncat(dstr,c,clen);
303 }
304 else {
305 (void)eval(rspat->spat_repl,G_SCALAR,sp);
306 str_scat(dstr,stack->ary_array[sp+1]);
307 }
308 if (once)
309 break;
663a0e37 310 } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,
a687059c 311 safebase));
312 str_ncat(dstr,s,strend - s);
313 str_replace(str,dstr);
314 STABSET(str);
315 str_numset(arg->arg_ptr.arg_str, (double)iters);
316 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
317 return sp;
318 }
319 str_numset(arg->arg_ptr.arg_str, 0.0);
320 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
321 return sp;
322
323nope:
324 ++spat->spat_short->str_u.str_useful;
325 str_numset(arg->arg_ptr.arg_str, 0.0);
326 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
327 return sp;
328}
b1248f16 329#ifdef BUGGY_MSC
330 #pragma intrinsic(memcmp)
331#endif /* BUGGY_MSC */
a687059c 332
333int
334do_trans(str,arg)
335STR *str;
20188a90 336ARG *arg;
a687059c 337{
20188a90 338 register short *tbl;
a687059c 339 register char *s;
340 register int matches = 0;
341 register int ch;
342 register char *send;
20188a90 343 register char *d;
344 register int squash = arg[2].arg_len & 1;
a687059c 345
20188a90 346 tbl = (short*) arg[2].arg_ptr.arg_cval;
a687059c 347 s = str_get(str);
348 send = s + str->str_cur;
349 if (!tbl || !s)
350 fatal("panic: do_trans");
351#ifdef DEBUGGING
352 if (debug & 8) {
353 deb("2.TBL\n");
354 }
355#endif
20188a90 356 if (!arg[2].arg_len) {
357 while (s < send) {
358 if ((ch = tbl[*s & 0377]) >= 0) {
359 matches++;
360 *s = ch;
361 }
362 s++;
363 }
364 }
365 else {
366 d = s;
367 while (s < send) {
368 if ((ch = tbl[*s & 0377]) >= 0) {
369 *d = ch;
370 if (matches++ && squash) {
371 if (d[-1] == *d)
372 matches--;
373 else
374 d++;
375 }
376 else
377 d++;
378 }
379 else if (ch == -1) /* -1 is unmapped character */
380 *d++ = *s; /* -2 is delete character */
381 s++;
a687059c 382 }
20188a90 383 matches += send - d; /* account for disappeared chars */
384 *d = '\0';
385 str->str_cur = d - str->str_ptr;
a687059c 386 }
387 STABSET(str);
388 return matches;
389}
390
391void
392do_join(str,arglast)
393register STR *str;
394int *arglast;
395{
396 register STR **st = stack->ary_array;
397 register int sp = arglast[1];
398 register int items = arglast[2] - sp;
399 register char *delim = str_get(st[sp]);
400 int delimlen = st[sp]->str_cur;
401
402 st += ++sp;
403 if (items-- > 0)
404 str_sset(str,*st++);
405 else
406 str_set(str,"");
57ebbfd0 407 if (delimlen) {
408 for (; items > 0; items--,st++) {
409 str_ncat(str,delim,delimlen);
410 str_scat(str,*st);
411 }
412 }
413 else {
414 for (; items > 0; items--,st++)
415 str_scat(str,*st);
a687059c 416 }
417 STABSET(str);
418}
419
420void
421do_pack(str,arglast)
422register STR *str;
423int *arglast;
424{
425 register STR **st = stack->ary_array;
426 register int sp = arglast[1];
427 register int items;
428 register char *pat = str_get(st[sp]);
429 register char *patend = pat + st[sp]->str_cur;
430 register int len;
431 int datumtype;
432 STR *fromstr;
433 static char *null10 = "\0\0\0\0\0\0\0\0\0\0";
434 static char *space10 = " ";
435
436 /* These must not be in registers: */
437 char achar;
438 short ashort;
439 int aint;
afd9f252 440 unsigned int auint;
a687059c 441 long along;
afd9f252 442 unsigned long aulong;
a687059c 443 char *aptr;
ff8e2863 444 float afloat;
445 double adouble;
a687059c 446
447 items = arglast[2] - sp;
448 st += ++sp;
449 str_nset(str,"",0);
450 while (pat < patend) {
451#define NEXTFROM (items-- > 0 ? *st++ : &str_no)
452 datumtype = *pat++;
ff8e2863 453 if (*pat == '*') {
454 len = index("@Xxu",datumtype) ? 0 : items;
455 pat++;
456 }
457 else if (isdigit(*pat)) {
afd9f252 458 len = *pat++ - '0';
a687059c 459 while (isdigit(*pat))
afd9f252 460 len = (len * 10) + (*pat++ - '0');
a687059c 461 }
462 else
463 len = 1;
464 switch(datumtype) {
465 default:
466 break;
ff8e2863 467 case '%':
468 fatal("% may only be used in unpack");
469 case '@':
470 len -= str->str_cur;
471 if (len > 0)
472 goto grow;
473 len = -len;
474 if (len > 0)
475 goto shrink;
476 break;
477 case 'X':
478 shrink:
57ebbfd0 479 if (str->str_cur < len)
ff8e2863 480 fatal("X outside of string");
57ebbfd0 481 str->str_cur -= len;
ff8e2863 482 str->str_ptr[str->str_cur] = '\0';
483 break;
a687059c 484 case 'x':
ff8e2863 485 grow:
a687059c 486 while (len >= 10) {
487 str_ncat(str,null10,10);
488 len -= 10;
489 }
490 str_ncat(str,null10,len);
491 break;
492 case 'A':
493 case 'a':
494 fromstr = NEXTFROM;
495 aptr = str_get(fromstr);
ff8e2863 496 if (pat[-1] == '*')
497 len = fromstr->str_cur;
a687059c 498 if (fromstr->str_cur > len)
499 str_ncat(str,aptr,len);
ff2452de 500 else {
a687059c 501 str_ncat(str,aptr,fromstr->str_cur);
ff2452de 502 len -= fromstr->str_cur;
503 if (datumtype == 'A') {
504 while (len >= 10) {
505 str_ncat(str,space10,10);
506 len -= 10;
507 }
508 str_ncat(str,space10,len);
a687059c 509 }
ff2452de 510 else {
511 while (len >= 10) {
512 str_ncat(str,null10,10);
513 len -= 10;
514 }
515 str_ncat(str,null10,len);
a687059c 516 }
a687059c 517 }
518 break;
519 case 'C':
520 case 'c':
521 while (len-- > 0) {
522 fromstr = NEXTFROM;
523 aint = (int)str_gnum(fromstr);
524 achar = aint;
525 str_ncat(str,&achar,sizeof(char));
526 }
527 break;
ff8e2863 528 /* Float and double added by gnb@melba.bby.oz.au 22/11/89 */
529 case 'f':
530 case 'F':
531 while (len-- > 0) {
532 fromstr = NEXTFROM;
533 afloat = (float)str_gnum(fromstr);
534 str_ncat(str, (char *)&afloat, sizeof (float));
535 }
536 break;
537 case 'd':
538 case 'D':
539 while (len-- > 0) {
540 fromstr = NEXTFROM;
541 adouble = (double)str_gnum(fromstr);
542 str_ncat(str, (char *)&adouble, sizeof (double));
543 }
544 break;
a687059c 545 case 'n':
546 while (len-- > 0) {
547 fromstr = NEXTFROM;
548 ashort = (short)str_gnum(fromstr);
549#ifdef HTONS
550 ashort = htons(ashort);
551#endif
552 str_ncat(str,(char*)&ashort,sizeof(short));
553 }
554 break;
555 case 'S':
556 case 's':
557 while (len-- > 0) {
558 fromstr = NEXTFROM;
559 ashort = (short)str_gnum(fromstr);
560 str_ncat(str,(char*)&ashort,sizeof(short));
561 }
562 break;
563 case 'I':
afd9f252 564 while (len-- > 0) {
565 fromstr = NEXTFROM;
b1248f16 566 auint = U_I(str_gnum(fromstr));
afd9f252 567 str_ncat(str,(char*)&auint,sizeof(unsigned int));
568 }
569 break;
a687059c 570 case 'i':
571 while (len-- > 0) {
572 fromstr = NEXTFROM;
573 aint = (int)str_gnum(fromstr);
574 str_ncat(str,(char*)&aint,sizeof(int));
575 }
576 break;
577 case 'N':
578 while (len-- > 0) {
579 fromstr = NEXTFROM;
580 along = (long)str_gnum(fromstr);
581#ifdef HTONL
582 along = htonl(along);
583#endif
584 str_ncat(str,(char*)&along,sizeof(long));
585 }
586 break;
587 case 'L':
afd9f252 588 while (len-- > 0) {
589 fromstr = NEXTFROM;
b1248f16 590 aulong = U_L(str_gnum(fromstr));
afd9f252 591 str_ncat(str,(char*)&aulong,sizeof(unsigned long));
592 }
593 break;
a687059c 594 case 'l':
595 while (len-- > 0) {
596 fromstr = NEXTFROM;
597 along = (long)str_gnum(fromstr);
598 str_ncat(str,(char*)&along,sizeof(long));
599 }
600 break;
601 case 'p':
602 while (len-- > 0) {
603 fromstr = NEXTFROM;
604 aptr = str_get(fromstr);
605 str_ncat(str,(char*)&aptr,sizeof(char*));
606 }
607 break;
ff8e2863 608 case 'u':
609 fromstr = NEXTFROM;
610 aptr = str_get(fromstr);
611 aint = fromstr->str_cur;
612 STR_GROW(str,aint * 4 / 3);
613 if (len <= 1)
614 len = 45;
615 else
616 len = len / 3 * 3;
617 while (aint > 0) {
618 int todo;
619
620 if (aint > len)
621 todo = len;
622 else
623 todo = aint;
624 doencodes(str, aptr, todo);
625 aint -= todo;
626 aptr += todo;
627 }
628 break;
a687059c 629 }
630 }
631 STABSET(str);
632}
633#undef NEXTFROM
634
ff8e2863 635doencodes(str, s, len)
636register STR *str;
637register char *s;
638register int len;
639{
640 char hunk[5];
641
642 *hunk = len + ' ';
643 str_ncat(str, hunk, 1);
644 hunk[4] = '\0';
645 while (len > 0) {
646 hunk[0] = ' ' + (077 & (*s >> 2));
647 hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
648 hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
649 hunk[3] = ' ' + (077 & (s[2] & 077));
650 str_ncat(str, hunk, 4);
651 s += 3;
652 len -= 3;
653 }
654 str_ncat(str, "\n", 1);
655}
656
a687059c 657void
658do_sprintf(str,len,sarg)
659register STR *str;
660register int len;
661register STR **sarg;
662{
663 register char *s;
664 register char *t;
57ebbfd0 665 register char *f;
a687059c 666 bool dolong;
667 char ch;
668 static STR *sargnull = &str_no;
669 register char *send;
670 char *xs;
671 int xlen;
afd9f252 672 double value;
b1248f16 673 char *origs;
a687059c 674
675 str_set(str,"");
676 len--; /* don't count pattern string */
57ebbfd0 677 origs = t = s = str_get(*sarg);
a687059c 678 send = s + (*sarg)->str_cur;
679 sarg++;
57ebbfd0 680 for ( ; ; len--) {
a687059c 681 if (len <= 0 || !*sarg) {
682 sarg = &sargnull;
683 len = 0;
684 }
57ebbfd0 685 for ( ; t < send && *t != '%'; t++) ;
a687059c 686 if (t >= send)
57ebbfd0 687 break; /* end of format string, ignore extra args */
688 f = t;
689 *buf = '\0';
690 xs = buf;
691 dolong = FALSE;
692 for (t++; t < send; t++) {
a687059c 693 switch (*t) {
694 default:
695 ch = *(++t);
696 *t = '\0';
57ebbfd0 697 (void)sprintf(xs,f);
a687059c 698 len++;
699 break;
700 case '0': case '1': case '2': case '3': case '4':
701 case '5': case '6': case '7': case '8': case '9':
57ebbfd0 702 case '.': case '#': case '-': case '+': case ' ':
703 continue;
a687059c 704 case 'l':
705 dolong = TRUE;
57ebbfd0 706 continue;
a687059c 707 case 'c':
bf38876a 708 ch = *(++t);
709 *t = '\0';
710 xlen = (int)str_gnum(*(sarg++));
57ebbfd0 711 if (strEQ(f,"%c")) { /* some printfs fail on null chars */
712 *xs = xlen;
713 xs[1] = '\0';
bf38876a 714 }
715 else
57ebbfd0 716 (void)sprintf(xs,f,xlen);
a687059c 717 break;
bf38876a 718 case 'D':
719 dolong = TRUE;
720 /* FALL THROUGH */
721 case 'd':
a687059c 722 ch = *(++t);
723 *t = '\0';
724 if (dolong)
57ebbfd0 725 (void)sprintf(xs,f,(long)str_gnum(*(sarg++)));
a687059c 726 else
57ebbfd0 727 (void)sprintf(xs,f,(int)str_gnum(*(sarg++)));
a687059c 728 break;
bf38876a 729 case 'X': case 'O':
730 dolong = TRUE;
731 /* FALL THROUGH */
732 case 'x': case 'o': case 'u':
733 ch = *(++t);
734 *t = '\0';
afd9f252 735 value = str_gnum(*(sarg++));
bf38876a 736 if (dolong)
57ebbfd0 737 (void)sprintf(xs,f,U_L(value));
bf38876a 738 else
57ebbfd0 739 (void)sprintf(xs,f,U_I(value));
bf38876a 740 break;
a687059c 741 case 'E': case 'e': case 'f': case 'G': case 'g':
742 ch = *(++t);
743 *t = '\0';
57ebbfd0 744 (void)sprintf(xs,f,str_gnum(*(sarg++)));
a687059c 745 break;
746 case 's':
747 ch = *(++t);
748 *t = '\0';
749 xs = str_get(*sarg);
750 xlen = (*sarg)->str_cur;
ff2452de 751 if (*xs == 'S' && xs[1] == 't' && xs[2] == 'B'
a687059c 752 && xlen == sizeof(STBP) && strlen(xs) < xlen) {
20188a90 753 STR *tmpstr = Str_new(24,0);
754
755 stab_fullname(tmpstr, ((STAB*)(*sarg))); /* a stab value! */
756 sprintf(tokenbuf,"*%s",tmpstr->str_ptr);
757 /* reformat to non-binary */
a687059c 758 xs = tokenbuf;
759 xlen = strlen(tokenbuf);
20188a90 760 str_free(tmpstr);
a687059c 761 }
a687059c 762 sarg++;
57ebbfd0 763 if (strEQ(f,"%s")) { /* some printfs fail on >128 chars */
764 break; /* so handle simple case */
765 }
766 strcpy(tokenbuf+64,f); /* sprintf($s,...$s...) */
767 *t = ch;
768 (void)sprintf(buf,tokenbuf+64,xs);
769 xs = buf;
a687059c 770 break;
771 }
57ebbfd0 772 /* end of switch, copy results */
773 *t = ch;
774 xlen = strlen(xs);
775 STR_GROW(str, str->str_cur + (f - s) + len + 1);
776 str_ncat(str, s, f - s);
777 str_ncat(str, xs, xlen);
a687059c 778 s = t;
57ebbfd0 779 break; /* break from for loop */
a687059c 780 }
a687059c 781 }
57ebbfd0 782 str_ncat(str, s, t - s);
a687059c 783 STABSET(str);
784}
785
786STR *
787do_push(ary,arglast)
788register ARRAY *ary;
789int *arglast;
790{
791 register STR **st = stack->ary_array;
792 register int sp = arglast[1];
793 register int items = arglast[2] - sp;
794 register STR *str = &str_undef;
795
796 for (st += ++sp; items > 0; items--,st++) {
797 str = Str_new(26,0);
798 if (*st)
799 str_sset(str,*st);
800 (void)apush(ary,str);
801 }
802 return str;
803}
804
805int
806do_unshift(ary,arglast)
807register ARRAY *ary;
808int *arglast;
809{
810 register STR **st = stack->ary_array;
811 register int sp = arglast[1];
812 register int items = arglast[2] - sp;
813 register STR *str;
814 register int i;
815
816 aunshift(ary,items);
817 i = 0;
818 for (st += ++sp; i < items; i++,st++) {
819 str = Str_new(27,0);
820 str_sset(str,*st);
821 (void)astore(ary,i,str);
822 }
823}
824
825int
826do_subr(arg,gimme,arglast)
827register ARG *arg;
828int gimme;
829int *arglast;
830{
831 register STR **st = stack->ary_array;
832 register int sp = arglast[1];
833 register int items = arglast[2] - sp;
834 register SUBR *sub;
20188a90 835 STR *str;
a687059c 836 STAB *stab;
a687059c 837 int oldsave = savestack->ary_fill;
838 int oldtmps_base = tmps_base;
20188a90 839 int hasargs = ((arg[2].arg_type & A_MASK) != A_NULL);
840 register CSV *csv;
a687059c 841
842 if ((arg[1].arg_type & A_MASK) == A_WORD)
843 stab = arg[1].arg_ptr.arg_stab;
844 else {
845 STR *tmpstr = stab_val(arg[1].arg_ptr.arg_stab);
846
847 if (tmpstr)
848 stab = stabent(str_get(tmpstr),TRUE);
849 else
850 stab = Nullstab;
851 }
852 if (!stab)
853 fatal("Undefined subroutine called");
20188a90 854 if (arg->arg_type == O_DBSUBR) {
855 str = stab_val(DBsub);
856 saveitem(str);
857 stab_fullname(str,stab);
858 sub = stab_sub(DBsub);
859 if (!sub)
860 fatal("No DBsub routine");
a687059c 861 }
a687059c 862 else {
20188a90 863 if (!(sub = stab_sub(stab))) {
864 STR *tmpstr = arg[0].arg_ptr.arg_str;
a687059c 865
20188a90 866 stab_fullname(tmpstr, stab);
867 fatal("Undefined subroutine \"%s\" called",tmpstr->str_ptr);
868 }
a687059c 869 }
20188a90 870 str = Str_new(15, sizeof(CSV));
871 str->str_state = SS_SCSV;
872 (void)apush(savestack,str);
873 csv = (CSV*)str->str_ptr;
874 csv->sub = sub;
875 csv->stab = stab;
876 csv->curcsv = curcsv;
877 csv->curcmd = curcmd;
878 csv->depth = sub->depth;
879 csv->wantarray = gimme;
880 csv->hasargs = hasargs;
881 curcsv = csv;
882 if (sub->usersub) {
883 st[sp] = arg->arg_ptr.arg_str;
884 if (!hasargs)
885 items = 0;
886 return (*sub->usersub)(sub->userindex,sp,items);
887 }
888 if (hasargs) {
889 csv->savearray = stab_xarray(defstab);
890 csv->argarray = afake(defstab, items, &st[sp+1]);
891 stab_xarray(defstab) = csv->argarray;
a687059c 892 }
a687059c 893 sub->depth++;
a687059c 894 if (sub->depth >= 2) { /* save temporaries on recursion? */
895 if (sub->depth == 100 && dowarn)
896 warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
897 savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
898 }
a687059c 899 tmps_base = tmps_max;
900 sp = cmd_exec(sub->cmd,gimme, --sp); /* so do it already */
901 st = stack->ary_array;
902
a687059c 903 tmps_base = oldtmps_base;
20188a90 904 for (items = arglast[0] + 1; items <= sp; items++)
905 st[items] = str_static(st[items]);
906 /* in case restore wipes old str */
907 restorelist(oldsave);
a687059c 908 return sp;
909}
910
911int
912do_assign(arg,gimme,arglast)
913register ARG *arg;
914int gimme;
915int *arglast;
916{
917
918 register STR **st = stack->ary_array;
919 STR **firstrelem = st + arglast[1] + 1;
920 STR **firstlelem = st + arglast[0] + 1;
921 STR **lastrelem = st + arglast[2];
922 STR **lastlelem = st + arglast[1];
923 register STR **relem;
924 register STR **lelem;
925
926 register STR *str;
927 register ARRAY *ary;
928 register int makelocal;
929 HASH *hash;
930 int i;
931
932 makelocal = (arg->arg_flags & AF_LOCAL);
afd9f252 933 localizing = makelocal;
a687059c 934 delaymagic = DM_DELAY; /* catch simultaneous items */
935
936 /* If there's a common identifier on both sides we have to take
937 * special care that assigning the identifier on the left doesn't
938 * clobber a value on the right that's used later in the list.
939 */
940 if (arg->arg_flags & AF_COMMON) {
941 for (relem = firstrelem; relem <= lastrelem; relem++) {
942 if (str = *relem)
943 *relem = str_static(str);
944 }
945 }
946 relem = firstrelem;
947 lelem = firstlelem;
948 ary = Null(ARRAY*);
949 hash = Null(HASH*);
950 while (lelem <= lastlelem) {
951 str = *lelem++;
952 if (str->str_state >= SS_HASH) {
953 if (str->str_state == SS_ARY) {
954 if (makelocal)
955 ary = saveary(str->str_u.str_stab);
956 else {
957 ary = stab_array(str->str_u.str_stab);
958 ary->ary_fill = -1;
959 }
960 i = 0;
961 while (relem <= lastrelem) { /* gobble up all the rest */
962 str = Str_new(28,0);
963 if (*relem)
afd9f252 964 str_sset(str,*relem);
965 *(relem++) = str;
a687059c 966 (void)astore(ary,i++,str);
967 }
968 }
969 else if (str->str_state == SS_HASH) {
970 char *tmps;
971 STR *tmpstr;
20188a90 972 int magic = 0;
973 STAB *tmpstab = str->str_u.str_stab;
a687059c 974
975 if (makelocal)
976 hash = savehash(str->str_u.str_stab);
977 else {
978 hash = stab_hash(str->str_u.str_stab);
20188a90 979 if (tmpstab == envstab) {
980 magic = 'E';
981 environ[0] = Nullch;
982 }
983 else if (tmpstab == sigstab) {
984 magic = 'S';
985#ifndef NSIG
986#define NSIG 32
987#endif
988 for (i = 1; i < NSIG; i++)
989 signal(i, SIG_DFL); /* crunch, crunch, crunch */
990 }
991#ifdef SOME_DBM
992 else if (hash->tbl_dbm)
993 magic = 'D';
994#endif
995 hclear(hash, magic == 'D'); /* wipe any dbm file too */
996
a687059c 997 }
998 while (relem < lastrelem) { /* gobble up all the rest */
999 if (*relem)
1000 str = *(relem++);
1001 else
1002 str = &str_no, relem++;
1003 tmps = str_get(str);
1004 tmpstr = Str_new(29,0);
1005 if (*relem)
afd9f252 1006 str_sset(tmpstr,*relem); /* value */
1007 *(relem++) = tmpstr;
a687059c 1008 (void)hstore(hash,tmps,str->str_cur,tmpstr,0);
20188a90 1009 if (magic) {
1010 str_magic(tmpstr, tmpstab, magic, tmps, str->str_cur);
1011 stabset(tmpstr->str_magic, tmpstr);
1012 }
a687059c 1013 }
1014 }
1015 else
1016 fatal("panic: do_assign");
1017 }
1018 else {
1019 if (makelocal)
1020 saveitem(str);
afd9f252 1021 if (relem <= lastrelem) {
1022 str_sset(str, *relem);
1023 *(relem++) = str;
1024 }
1025 else {
20188a90 1026 str_sset(str, &str_undef);
afd9f252 1027 if (gimme == G_ARRAY) {
1028 i = ++lastrelem - firstrelem;
1029 relem++; /* tacky, I suppose */
1030 astore(stack,i,str);
1031 if (st != stack->ary_array) {
1032 st = stack->ary_array;
1033 firstrelem = st + arglast[1] + 1;
1034 firstlelem = st + arglast[0] + 1;
1035 lastlelem = st + arglast[1];
1036 lastrelem = st + i;
1037 relem = lastrelem + 1;
1038 }
1039 }
1040 }
a687059c 1041 STABSET(str);
1042 }
1043 }
1044 if (delaymagic > 1) {
ff8e2863 1045 if (delaymagic & DM_REUID) {
a687059c 1046#ifdef SETREUID
a687059c 1047 setreuid(uid,euid);
ff8e2863 1048#else
1049 if (uid != euid || setuid(uid) < 0)
1050 fatal("No setreuid available");
a687059c 1051#endif
ff8e2863 1052 }
1053 if (delaymagic & DM_REGID) {
a687059c 1054#ifdef SETREGID
a687059c 1055 setregid(gid,egid);
ff8e2863 1056#else
1057 if (gid != egid || setgid(gid) < 0)
1058 fatal("No setregid available");
a687059c 1059#endif
ff8e2863 1060 }
a687059c 1061 }
1062 delaymagic = 0;
afd9f252 1063 localizing = FALSE;
a687059c 1064 if (gimme == G_ARRAY) {
1065 i = lastrelem - firstrelem + 1;
1066 if (ary || hash)
1067 Copy(firstrelem, firstlelem, i, STR*);
1068 return arglast[0] + i;
1069 }
1070 else {
1071 str_numset(arg->arg_ptr.arg_str,(double)(arglast[2] - arglast[1]));
1072 *firstlelem = arg->arg_ptr.arg_str;
1073 return arglast[0] + 1;
1074 }
1075}
1076
1077int
1078do_study(str,arg,gimme,arglast)
1079STR *str;
1080ARG *arg;
1081int gimme;
1082int *arglast;
1083{
1084 register unsigned char *s;
1085 register int pos = str->str_cur;
1086 register int ch;
1087 register int *sfirst;
1088 register int *snext;
1089 static int maxscream = -1;
1090 static STR *lastscream = Nullstr;
1091 int retval;
1092 int retarg = arglast[0] + 1;
1093
1094#ifndef lint
1095 s = (unsigned char*)(str_get(str));
1096#else
1097 s = Null(unsigned char*);
1098#endif
1099 if (lastscream)
1100 lastscream->str_pok &= ~SP_STUDIED;
1101 lastscream = str;
1102 if (pos <= 0) {
1103 retval = 0;
1104 goto ret;
1105 }
1106 if (pos > maxscream) {
1107 if (maxscream < 0) {
1108 maxscream = pos + 80;
1109 New(301,screamfirst, 256, int);
1110 New(302,screamnext, maxscream, int);
1111 }
1112 else {
1113 maxscream = pos + pos / 4;
1114 Renew(screamnext, maxscream, int);
1115 }
1116 }
1117
1118 sfirst = screamfirst;
1119 snext = screamnext;
1120
1121 if (!sfirst || !snext)
1122 fatal("do_study: out of memory");
1123
1124 for (ch = 256; ch; --ch)
1125 *sfirst++ = -1;
1126 sfirst -= 256;
1127
1128 while (--pos >= 0) {
1129 ch = s[pos];
1130 if (sfirst[ch] >= 0)
1131 snext[pos] = sfirst[ch] - pos;
1132 else
1133 snext[pos] = -pos;
1134 sfirst[ch] = pos;
1135
1136 /* If there were any case insensitive searches, we must assume they
1137 * all are. This speeds up insensitive searches much more than
1138 * it slows down sensitive ones.
1139 */
1140 if (sawi)
1141 sfirst[fold[ch]] = pos;
1142 }
1143
1144 str->str_pok |= SP_STUDIED;
1145 retval = 1;
1146 ret:
1147 str_numset(arg->arg_ptr.arg_str,(double)retval);
1148 stack->ary_array[retarg] = arg->arg_ptr.arg_str;
1149 return retarg;
1150}
1151
1152int
1153do_defined(str,arg,gimme,arglast)
1154STR *str;
1155register ARG *arg;
1156int gimme;
1157int *arglast;
1158{
1159 register int type;
1160 register int retarg = arglast[0] + 1;
1161 int retval;
6eb13c3b 1162 ARRAY *ary;
1163 HASH *hash;
a687059c 1164
1165 if ((arg[1].arg_type & A_MASK) != A_LEXPR)
1166 fatal("Illegal argument to defined()");
1167 arg = arg[1].arg_ptr.arg_arg;
1168 type = arg->arg_type;
1169
6eb13c3b 1170 if (type == O_SUBR || type == O_DBSUBR)
ff8e2863 1171 retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0;
6eb13c3b 1172 else if (type == O_ARRAY || type == O_LARRAY ||
1173 type == O_ASLICE || type == O_LASLICE )
1174 retval = ((ary = stab_xarray(arg[1].arg_ptr.arg_stab)) != 0
1175 && ary->ary_max >= 0 );
1176 else if (type == O_HASH || type == O_LHASH ||
1177 type == O_HSLICE || type == O_LHSLICE )
1178 retval = ((hash = stab_xhash(arg[1].arg_ptr.arg_stab)) != 0
1179 && hash->tbl_array);
a687059c 1180 else
1181 retval = FALSE;
1182 str_numset(str,(double)retval);
1183 stack->ary_array[retarg] = str;
1184 return retarg;
1185}
1186
1187int
1188do_undef(str,arg,gimme,arglast)
1189STR *str;
1190register ARG *arg;
1191int gimme;
1192int *arglast;
1193{
1194 register int type;
1195 register STAB *stab;
1196 int retarg = arglast[0] + 1;
1197
1198 if ((arg[1].arg_type & A_MASK) != A_LEXPR)
1199 fatal("Illegal argument to undef()");
1200 arg = arg[1].arg_ptr.arg_arg;
1201 type = arg->arg_type;
1202
1203 if (type == O_ARRAY || type == O_LARRAY) {
1204 stab = arg[1].arg_ptr.arg_stab;
1205 afree(stab_xarray(stab));
1206 stab_xarray(stab) = Null(ARRAY*);
1207 }
1208 else if (type == O_HASH || type == O_LHASH) {
1209 stab = arg[1].arg_ptr.arg_stab;
20188a90 1210 if (stab == envstab)
1211 environ[0] = Nullch;
1212 else if (stab == sigstab) {
1213 int i;
1214
1215 for (i = 1; i < NSIG; i++)
1216 signal(i, SIG_DFL); /* munch, munch, munch */
1217 }
1218 (void)hfree(stab_xhash(stab), TRUE);
a687059c 1219 stab_xhash(stab) = Null(HASH*);
1220 }
1221 else if (type == O_SUBR || type == O_DBSUBR) {
1222 stab = arg[1].arg_ptr.arg_stab;
1223 cmd_free(stab_sub(stab)->cmd);
1224 afree(stab_sub(stab)->tosave);
1225 Safefree(stab_sub(stab));
1226 stab_sub(stab) = Null(SUBR*);
1227 }
1228 else
1229 fatal("Can't undefine that kind of object");
1230 str_numset(str,0.0);
1231 stack->ary_array[retarg] = str;
1232 return retarg;
1233}
1234
1235int
1236do_vec(lvalue,astr,arglast)
1237int lvalue;
1238STR *astr;
1239int *arglast;
1240{
1241 STR **st = stack->ary_array;
1242 int sp = arglast[0];
1243 register STR *str = st[++sp];
1244 register int offset = (int)str_gnum(st[++sp]);
1245 register int size = (int)str_gnum(st[++sp]);
1246 unsigned char *s = (unsigned char*)str_get(str);
1247 unsigned long retnum;
1248 int len;
1249
1250 sp = arglast[1];
1251 offset *= size; /* turn into bit offset */
1252 len = (offset + size + 7) / 8;
1253 if (offset < 0 || size < 1)
1254 retnum = 0;
1255 else if (!lvalue && len > str->str_cur)
1256 retnum = 0;
1257 else {
1258 if (len > str->str_cur) {
1259 STR_GROW(str,len);
1260 (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
1261 str->str_cur = len;
1262 }
1263 s = (unsigned char*)str_get(str);
1264 if (size < 8)
1265 retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
1266 else {
1267 offset >>= 3;
1268 if (size == 8)
1269 retnum = s[offset];
1270 else if (size == 16)
1271 retnum = (s[offset] << 8) + s[offset+1];
1272 else if (size == 32)
1273 retnum = (s[offset] << 24) + (s[offset + 1] << 16) +
1274 (s[offset + 2] << 8) + s[offset+3];
1275 }
1276
1277 if (lvalue) { /* it's an lvalue! */
1278 struct lstring *lstr = (struct lstring*)astr;
1279
1280 astr->str_magic = str;
1281 st[sp]->str_rare = 'v';
1282 lstr->lstr_offset = offset;
1283 lstr->lstr_len = size;
1284 }
1285 }
1286
1287 str_numset(astr,(double)retnum);
1288 st[sp] = astr;
1289 return sp;
1290}
1291
1292void
1293do_vecset(mstr,str)
1294STR *mstr;
1295STR *str;
1296{
1297 struct lstring *lstr = (struct lstring*)str;
1298 register int offset;
1299 register int size;
1300 register unsigned char *s = (unsigned char*)mstr->str_ptr;
b1248f16 1301 register unsigned long lval = U_L(str_gnum(str));
a687059c 1302 int mask;
1303
1304 mstr->str_rare = 0;
1305 str->str_magic = Nullstr;
1306 offset = lstr->lstr_offset;
1307 size = lstr->lstr_len;
1308 if (size < 8) {
1309 mask = (1 << size) - 1;
1310 size = offset & 7;
1311 lval &= mask;
1312 offset >>= 3;
1313 s[offset] &= ~(mask << size);
1314 s[offset] |= lval << size;
1315 }
1316 else {
1317 if (size == 8)
1318 s[offset] = lval & 255;
1319 else if (size == 16) {
1320 s[offset] = (lval >> 8) & 255;
1321 s[offset+1] = lval & 255;
1322 }
1323 else if (size == 32) {
1324 s[offset] = (lval >> 24) & 255;
1325 s[offset+1] = (lval >> 16) & 255;
1326 s[offset+2] = (lval >> 8) & 255;
1327 s[offset+3] = lval & 255;
1328 }
1329 }
1330}
1331
1332do_chop(astr,str)
1333register STR *astr;
1334register STR *str;
1335{
1336 register char *tmps;
1337 register int i;
1338 ARRAY *ary;
1339 HASH *hash;
1340 HENT *entry;
1341
1342 if (!str)
1343 return;
1344 if (str->str_state == SS_ARY) {
1345 ary = stab_array(str->str_u.str_stab);
1346 for (i = 0; i <= ary->ary_fill; i++)
1347 do_chop(astr,ary->ary_array[i]);
1348 return;
1349 }
1350 if (str->str_state == SS_HASH) {
1351 hash = stab_hash(str->str_u.str_stab);
1352 (void)hiterinit(hash);
1353 while (entry = hiternext(hash))
1354 do_chop(astr,hiterval(hash,entry));
1355 return;
1356 }
1357 tmps = str_get(str);
1358 if (!tmps)
1359 return;
1360 tmps += str->str_cur - (str->str_cur != 0);
1361 str_nset(astr,tmps,1); /* remember last char */
1362 *tmps = '\0'; /* wipe it out */
1363 str->str_cur = tmps - str->str_ptr;
1364 str->str_nok = 0;
1365}
1366
1367do_vop(optype,str,left,right)
1368STR *str;
1369STR *left;
1370STR *right;
1371{
1372 register char *s = str_get(str);
1373 register char *l = str_get(left);
1374 register char *r = str_get(right);
1375 register int len;
1376
1377 len = left->str_cur;
1378 if (len > right->str_cur)
1379 len = right->str_cur;
1380 if (str->str_cur > len)
1381 str->str_cur = len;
1382 else if (str->str_cur < len) {
1383 STR_GROW(str,len);
1384 (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
1385 str->str_cur = len;
1386 s = str_get(str);
1387 }
1388 switch (optype) {
1389 case O_BIT_AND:
1390 while (len--)
1391 *s++ = *l++ & *r++;
1392 break;
1393 case O_XOR:
1394 while (len--)
1395 *s++ = *l++ ^ *r++;
1396 goto mop_up;
1397 case O_BIT_OR:
1398 while (len--)
1399 *s++ = *l++ | *r++;
1400 mop_up:
1401 len = str->str_cur;
1402 if (right->str_cur > len)
1403 str_ncat(str,right->str_ptr+len,right->str_cur - len);
1404 else if (left->str_cur > len)
1405 str_ncat(str,left->str_ptr+len,left->str_cur - len);
1406 break;
1407 }
1408}
1409
1410int
1411do_syscall(arglast)
1412int *arglast;
1413{
1414 register STR **st = stack->ary_array;
1415 register int sp = arglast[1];
1416 register int items = arglast[2] - sp;
1417 long arg[8];
1418 register int i = 0;
1419 int retval = -1;
1420
1421#ifdef SYSCALL
1422#ifdef TAINT
1423 for (st += ++sp; items--; st++)
1424 tainted |= (*st)->str_tainted;
1425 st = stack->ary_array;
1426 sp = arglast[1];
1427 items = arglast[2] - sp;
1428#endif
1429#ifdef TAINT
1430 taintproper("Insecure dependency in syscall");
1431#endif
1432 /* This probably won't work on machines where sizeof(long) != sizeof(int)
1433 * or where sizeof(long) != sizeof(char*). But such machines will
1434 * not likely have syscall implemented either, so who cares?
1435 */
1436 while (items--) {
1437 if (st[++sp]->str_nok || !i)
1438 arg[i++] = (long)str_gnum(st[sp]);
1439#ifndef lint
1440 else
1441 arg[i++] = (long)st[sp]->str_ptr;
1442#endif /* lint */
1443 }
1444 sp = arglast[1];
1445 items = arglast[2] - sp;
1446 switch (items) {
1447 case 0:
1448 fatal("Too few args to syscall");
1449 case 1:
1450 retval = syscall(arg[0]);
1451 break;
1452 case 2:
1453 retval = syscall(arg[0],arg[1]);
1454 break;
1455 case 3:
1456 retval = syscall(arg[0],arg[1],arg[2]);
1457 break;
1458 case 4:
1459 retval = syscall(arg[0],arg[1],arg[2],arg[3]);
1460 break;
1461 case 5:
1462 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
1463 break;
1464 case 6:
1465 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
1466 break;
1467 case 7:
1468 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
1469 break;
1470 case 8:
1471 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
1472 arg[7]);
1473 break;
1474 }
afd9f252 1475 return retval;
a687059c 1476#else
1477 fatal("syscall() unimplemented");
1478#endif
1479}
1480
1481