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