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