Commit | Line | Data |
9bb9d9f7 |
1 | /* $Header: arg.c,v 1.0.1.6 88/02/01 17:32:26 root Exp $ |
8d063cd8 |
2 | * |
3 | * $Log: arg.c,v $ |
9bb9d9f7 |
4 | * Revision 1.0.1.6 88/02/01 17:32:26 root |
5 | * patch12: made split(' ') behave like awk in ignoring leading white space. |
6 | * |
d96024cf |
7 | * Revision 1.0.1.5 88/01/30 08:53:16 root |
8 | * patch9: fixed some missing right parens introduced (?) by patch 2 |
9 | * |
a559c259 |
10 | * Revision 1.0.1.4 88/01/28 10:22:06 root |
11 | * patch8: added eval operator. |
f9ad7436 |
12 | * |
135863df |
13 | * Revision 1.0.1.2 88/01/24 03:52:34 root |
14 | * patch 2: added STATBLKS dependencies. |
15 | * |
36ce8bec |
16 | * Revision 1.0.1.1 88/01/21 21:27:10 root |
17 | * Now defines signal return values correctly using VOIDSIG. |
18 | * |
8d063cd8 |
19 | * Revision 1.0 87/12/18 13:04:33 root |
20 | * Initial revision |
21 | * |
22 | */ |
23 | |
24 | #include <signal.h> |
25 | #include "handy.h" |
26 | #include "EXTERN.h" |
27 | #include "search.h" |
28 | #include "util.h" |
29 | #include "perl.h" |
30 | |
31 | ARG *debarg; |
32 | |
33 | bool |
34 | do_match(s,arg) |
35 | register char *s; |
36 | register ARG *arg; |
37 | { |
38 | register SPAT *spat = arg[2].arg_ptr.arg_spat; |
39 | register char *d; |
40 | register char *t; |
41 | |
42 | if (!spat || !s) |
43 | fatal("panic: do_match\n"); |
44 | if (spat->spat_flags & SPAT_USED) { |
45 | #ifdef DEBUGGING |
46 | if (debug & 8) |
47 | deb("2.SPAT USED\n"); |
48 | #endif |
49 | return FALSE; |
50 | } |
51 | if (spat->spat_runtime) { |
52 | t = str_get(eval(spat->spat_runtime,Null(STR***))); |
53 | #ifdef DEBUGGING |
54 | if (debug & 8) |
55 | deb("2.SPAT /%s/\n",t); |
56 | #endif |
57 | if (d = compile(&spat->spat_compex,t,TRUE,FALSE)) { |
58 | #ifdef DEBUGGING |
59 | deb("/%s/: %s\n", t, d); |
60 | #endif |
61 | return FALSE; |
62 | } |
63 | if (spat->spat_compex.complen <= 1 && curspat) |
64 | spat = curspat; |
65 | if (execute(&spat->spat_compex, s, TRUE, 0)) { |
66 | if (spat->spat_compex.numsubs) |
67 | curspat = spat; |
68 | return TRUE; |
69 | } |
70 | else |
71 | return FALSE; |
72 | } |
73 | else { |
74 | #ifdef DEBUGGING |
75 | if (debug & 8) { |
76 | char ch; |
77 | |
78 | if (spat->spat_flags & SPAT_USE_ONCE) |
79 | ch = '?'; |
80 | else |
81 | ch = '/'; |
82 | deb("2.SPAT %c%s%c\n",ch,spat->spat_compex.precomp,ch); |
83 | } |
84 | #endif |
85 | if (spat->spat_compex.complen <= 1 && curspat) |
86 | spat = curspat; |
87 | if (spat->spat_first) { |
88 | if (spat->spat_flags & SPAT_SCANFIRST) { |
89 | str_free(spat->spat_first); |
90 | spat->spat_first = Nullstr; /* disable optimization */ |
91 | } |
92 | else if (*spat->spat_first->str_ptr != *s || |
93 | strnNE(spat->spat_first->str_ptr, s, spat->spat_flen) ) |
94 | return FALSE; |
95 | } |
96 | if (execute(&spat->spat_compex, s, TRUE, 0)) { |
97 | if (spat->spat_compex.numsubs) |
98 | curspat = spat; |
99 | if (spat->spat_flags & SPAT_USE_ONCE) |
100 | spat->spat_flags |= SPAT_USED; |
101 | return TRUE; |
102 | } |
103 | else |
104 | return FALSE; |
105 | } |
106 | /*NOTREACHED*/ |
107 | } |
108 | |
109 | int |
110 | do_subst(str,arg) |
111 | STR *str; |
112 | register ARG *arg; |
113 | { |
114 | register SPAT *spat; |
115 | register STR *dstr; |
116 | register char *s; |
117 | register char *m; |
118 | |
119 | spat = arg[2].arg_ptr.arg_spat; |
120 | s = str_get(str); |
121 | if (!spat || !s) |
122 | fatal("panic: do_subst\n"); |
123 | else if (spat->spat_runtime) { |
124 | char *d; |
125 | |
126 | m = str_get(eval(spat->spat_runtime,Null(STR***))); |
127 | if (d = compile(&spat->spat_compex,m,TRUE,FALSE)) { |
128 | #ifdef DEBUGGING |
129 | deb("/%s/: %s\n", m, d); |
130 | #endif |
131 | return 0; |
132 | } |
133 | } |
134 | #ifdef DEBUGGING |
135 | if (debug & 8) { |
136 | deb("2.SPAT /%s/\n",spat->spat_compex.precomp); |
137 | } |
138 | #endif |
139 | if (spat->spat_compex.complen <= 1 && curspat) |
140 | spat = curspat; |
141 | if (spat->spat_first) { |
142 | if (spat->spat_flags & SPAT_SCANFIRST) { |
143 | str_free(spat->spat_first); |
144 | spat->spat_first = Nullstr; /* disable optimization */ |
145 | } |
146 | else if (*spat->spat_first->str_ptr != *s || |
147 | strnNE(spat->spat_first->str_ptr, s, spat->spat_flen) ) |
148 | return 0; |
149 | } |
150 | if (m = execute(&spat->spat_compex, s, TRUE, 1)) { |
151 | int iters = 0; |
152 | |
153 | dstr = str_new(str_len(str)); |
154 | if (spat->spat_compex.numsubs) |
155 | curspat = spat; |
156 | do { |
157 | if (iters++ > 10000) |
158 | fatal("Substitution loop?\n"); |
159 | if (spat->spat_compex.numsubs) |
160 | s = spat->spat_compex.subbase; |
161 | str_ncat(dstr,s,m-s); |
162 | s = spat->spat_compex.subend[0]; |
163 | str_scat(dstr,eval(spat->spat_repl,Null(STR***))); |
164 | if (spat->spat_flags & SPAT_USE_ONCE) |
165 | break; |
166 | } while (m = execute(&spat->spat_compex, s, FALSE, 1)); |
167 | str_cat(dstr,s); |
168 | str_replace(str,dstr); |
169 | STABSET(str); |
170 | return iters; |
171 | } |
172 | return 0; |
173 | } |
174 | |
175 | int |
176 | do_trans(str,arg) |
177 | STR *str; |
178 | register ARG *arg; |
179 | { |
180 | register char *tbl; |
181 | register char *s; |
182 | register int matches = 0; |
183 | register int ch; |
184 | |
185 | tbl = arg[2].arg_ptr.arg_cval; |
186 | s = str_get(str); |
187 | if (!tbl || !s) |
188 | fatal("panic: do_trans\n"); |
189 | #ifdef DEBUGGING |
190 | if (debug & 8) { |
191 | deb("2.TBL\n"); |
192 | } |
193 | #endif |
194 | while (*s) { |
195 | if (ch = tbl[*s & 0377]) { |
196 | matches++; |
197 | *s = ch; |
198 | } |
199 | s++; |
200 | } |
201 | STABSET(str); |
202 | return matches; |
203 | } |
204 | |
205 | int |
206 | do_split(s,spat,retary) |
207 | register char *s; |
208 | register SPAT *spat; |
209 | STR ***retary; |
210 | { |
211 | register STR *dstr; |
212 | register char *m; |
213 | register ARRAY *ary; |
214 | static ARRAY *myarray = Null(ARRAY*); |
215 | int iters = 0; |
216 | STR **sarg; |
217 | register char *e; |
218 | int i; |
219 | |
220 | if (!spat || !s) |
221 | fatal("panic: do_split\n"); |
222 | else if (spat->spat_runtime) { |
223 | char *d; |
224 | |
225 | m = str_get(eval(spat->spat_runtime,Null(STR***))); |
9bb9d9f7 |
226 | if (!*m || (*m == ' ' && !m[1])) { |
227 | m = "[ \\t\\n]+"; |
228 | while (isspace(*s)) s++; |
229 | } |
230 | if (spat->spat_runtime->arg_type == O_ITEM && |
231 | spat->spat_runtime[1].arg_type == A_SINGLE) { |
232 | arg_free(spat->spat_runtime); /* it won't change, so */ |
233 | spat->spat_runtime = Nullarg; /* no point compiling again */ |
234 | } |
8d063cd8 |
235 | if (d = compile(&spat->spat_compex,m,TRUE,FALSE)) { |
236 | #ifdef DEBUGGING |
237 | deb("/%s/: %s\n", m, d); |
238 | #endif |
239 | return FALSE; |
240 | } |
241 | } |
242 | #ifdef DEBUGGING |
243 | if (debug & 8) { |
244 | deb("2.SPAT /%s/\n",spat->spat_compex.precomp); |
245 | } |
246 | #endif |
247 | if (retary) |
248 | ary = myarray; |
249 | else |
250 | ary = spat->spat_repl[1].arg_ptr.arg_stab->stab_array; |
251 | if (!ary) |
252 | myarray = ary = anew(); |
253 | ary->ary_fill = -1; |
254 | while (*s && (m = execute(&spat->spat_compex, s, (iters == 0), 1))) { |
255 | if (spat->spat_compex.numsubs) |
256 | s = spat->spat_compex.subbase; |
257 | dstr = str_new(m-s); |
258 | str_nset(dstr,s,m-s); |
259 | astore(ary, iters++, dstr); |
260 | if (iters > 10000) |
261 | fatal("Substitution loop?\n"); |
262 | s = spat->spat_compex.subend[0]; |
263 | } |
264 | if (*s) { /* ignore field after final "whitespace" */ |
265 | dstr = str_new(0); /* if they interpolate, it's null anyway */ |
266 | str_set(dstr,s); |
267 | astore(ary, iters++, dstr); |
268 | } |
269 | else { |
270 | while (iters > 0 && !*str_get(afetch(ary,iters-1))) |
271 | iters--; |
272 | } |
273 | if (retary) { |
274 | sarg = (STR**)safemalloc((iters+2)*sizeof(STR*)); |
275 | |
276 | sarg[0] = Nullstr; |
277 | sarg[iters+1] = Nullstr; |
278 | for (i = 1; i <= iters; i++) |
279 | sarg[i] = afetch(ary,i-1); |
280 | *retary = sarg; |
281 | } |
282 | return iters; |
283 | } |
284 | |
285 | void |
286 | do_join(arg,delim,str) |
287 | register ARG *arg; |
288 | register char *delim; |
289 | register STR *str; |
290 | { |
291 | STR **tmpary; /* must not be register */ |
292 | register STR **elem; |
293 | |
294 | (void)eval(arg[2].arg_ptr.arg_arg,&tmpary); |
295 | elem = tmpary+1; |
296 | if (*elem) |
297 | str_sset(str,*elem++); |
298 | for (; *elem; elem++) { |
299 | str_cat(str,delim); |
300 | str_scat(str,*elem); |
301 | } |
302 | STABSET(str); |
303 | safefree((char*)tmpary); |
304 | } |
305 | |
306 | bool |
307 | do_open(stab,name) |
308 | STAB *stab; |
309 | register char *name; |
310 | { |
311 | FILE *fp; |
312 | int len = strlen(name); |
313 | register STIO *stio = stab->stab_io; |
314 | |
315 | while (len && isspace(name[len-1])) |
316 | name[--len] = '\0'; |
317 | if (!stio) |
318 | stio = stab->stab_io = stio_new(); |
319 | if (stio->fp) { |
320 | if (stio->type == '|') |
321 | pclose(stio->fp); |
322 | else if (stio->type != '-') |
323 | fclose(stio->fp); |
324 | stio->fp = Nullfp; |
325 | } |
326 | stio->type = *name; |
327 | if (*name == '|') { |
328 | for (name++; isspace(*name); name++) ; |
329 | fp = popen(name,"w"); |
330 | } |
331 | else if (*name == '>' && name[1] == '>') { |
332 | for (name += 2; isspace(*name); name++) ; |
333 | fp = fopen(name,"a"); |
334 | } |
335 | else if (*name == '>') { |
336 | for (name++; isspace(*name); name++) ; |
337 | if (strEQ(name,"-")) { |
338 | fp = stdout; |
339 | stio->type = '-'; |
340 | } |
341 | else |
342 | fp = fopen(name,"w"); |
343 | } |
344 | else { |
345 | if (*name == '<') { |
346 | for (name++; isspace(*name); name++) ; |
347 | if (strEQ(name,"-")) { |
348 | fp = stdin; |
349 | stio->type = '-'; |
350 | } |
351 | else |
352 | fp = fopen(name,"r"); |
353 | } |
354 | else if (name[len-1] == '|') { |
355 | name[--len] = '\0'; |
356 | while (len && isspace(name[len-1])) |
357 | name[--len] = '\0'; |
358 | for (; isspace(*name); name++) ; |
359 | fp = popen(name,"r"); |
360 | stio->type = '|'; |
361 | } |
362 | else { |
363 | stio->type = '<'; |
364 | for (; isspace(*name); name++) ; |
365 | if (strEQ(name,"-")) { |
366 | fp = stdin; |
367 | stio->type = '-'; |
368 | } |
369 | else |
370 | fp = fopen(name,"r"); |
371 | } |
372 | } |
373 | if (!fp) |
374 | return FALSE; |
375 | if (stio->type != '|' && stio->type != '-') { |
376 | if (fstat(fileno(fp),&statbuf) < 0) { |
377 | fclose(fp); |
378 | return FALSE; |
379 | } |
380 | if ((statbuf.st_mode & S_IFMT) != S_IFREG && |
381 | (statbuf.st_mode & S_IFMT) != S_IFCHR) { |
382 | fclose(fp); |
383 | return FALSE; |
384 | } |
385 | } |
386 | stio->fp = fp; |
387 | return TRUE; |
388 | } |
389 | |
390 | FILE * |
391 | nextargv(stab) |
392 | register STAB *stab; |
393 | { |
394 | register STR *str; |
395 | char *oldname; |
396 | |
397 | while (alen(stab->stab_array) >= 0L) { |
398 | str = ashift(stab->stab_array); |
399 | str_sset(stab->stab_val,str); |
400 | STABSET(stab->stab_val); |
401 | oldname = str_get(stab->stab_val); |
402 | if (do_open(stab,oldname)) { |
403 | if (inplace) { |
404 | if (*inplace) { |
405 | str_cat(str,inplace); |
406 | #ifdef RENAME |
407 | rename(oldname,str->str_ptr); |
408 | #else |
409 | UNLINK(str->str_ptr); |
410 | link(oldname,str->str_ptr); |
411 | UNLINK(oldname); |
412 | #endif |
413 | } |
414 | sprintf(tokenbuf,">%s",oldname); |
415 | do_open(argvoutstab,tokenbuf); |
416 | defoutstab = argvoutstab; |
417 | } |
418 | str_free(str); |
419 | return stab->stab_io->fp; |
420 | } |
421 | else |
422 | fprintf(stderr,"Can't open %s\n",str_get(str)); |
423 | str_free(str); |
424 | } |
425 | if (inplace) { |
426 | do_close(argvoutstab,FALSE); |
427 | defoutstab = stabent("stdout",TRUE); |
428 | } |
429 | return Nullfp; |
430 | } |
431 | |
432 | bool |
433 | do_close(stab,explicit) |
434 | STAB *stab; |
435 | bool explicit; |
436 | { |
437 | bool retval = FALSE; |
438 | register STIO *stio = stab->stab_io; |
439 | |
440 | if (!stio) /* never opened */ |
441 | return FALSE; |
442 | if (stio->fp) { |
443 | if (stio->type == '|') |
444 | retval = (pclose(stio->fp) >= 0); |
445 | else if (stio->type == '-') |
446 | retval = TRUE; |
447 | else |
448 | retval = (fclose(stio->fp) != EOF); |
449 | stio->fp = Nullfp; |
450 | } |
451 | if (explicit) |
452 | stio->lines = 0; |
453 | stio->type = ' '; |
454 | return retval; |
455 | } |
456 | |
457 | bool |
458 | do_eof(stab) |
459 | STAB *stab; |
460 | { |
461 | register STIO *stio; |
462 | int ch; |
463 | |
464 | if (!stab) |
465 | return TRUE; |
466 | |
467 | stio = stab->stab_io; |
468 | if (!stio) |
469 | return TRUE; |
470 | |
471 | while (stio->fp) { |
472 | |
473 | #ifdef STDSTDIO /* (the code works without this) */ |
474 | if (stio->fp->_cnt) /* cheat a little, since */ |
475 | return FALSE; /* this is the most usual case */ |
476 | #endif |
477 | |
478 | ch = getc(stio->fp); |
479 | if (ch != EOF) { |
480 | ungetc(ch, stio->fp); |
481 | return FALSE; |
482 | } |
483 | if (stio->flags & IOF_ARGV) { /* not necessarily a real EOF yet? */ |
484 | if (!nextargv(stab)) /* get another fp handy */ |
485 | return TRUE; |
486 | } |
487 | else |
488 | return TRUE; /* normal fp, definitely end of file */ |
489 | } |
490 | return TRUE; |
491 | } |
492 | |
493 | long |
494 | do_tell(stab) |
495 | STAB *stab; |
496 | { |
497 | register STIO *stio; |
498 | int ch; |
499 | |
500 | if (!stab) |
501 | return -1L; |
502 | |
503 | stio = stab->stab_io; |
504 | if (!stio || !stio->fp) |
505 | return -1L; |
506 | |
507 | return ftell(stio->fp); |
508 | } |
509 | |
510 | bool |
511 | do_seek(stab, pos, whence) |
512 | STAB *stab; |
513 | long pos; |
514 | int whence; |
515 | { |
516 | register STIO *stio; |
517 | |
518 | if (!stab) |
519 | return FALSE; |
520 | |
521 | stio = stab->stab_io; |
522 | if (!stio || !stio->fp) |
523 | return FALSE; |
524 | |
525 | return fseek(stio->fp, pos, whence) >= 0; |
526 | } |
527 | |
528 | do_stat(arg,sarg,retary) |
529 | register ARG *arg; |
530 | register STR **sarg; |
531 | STR ***retary; |
532 | { |
533 | register ARRAY *ary; |
534 | static ARRAY *myarray = Null(ARRAY*); |
535 | int max = 13; |
536 | register int i; |
537 | |
538 | ary = myarray; |
539 | if (!ary) |
540 | myarray = ary = anew(); |
541 | ary->ary_fill = -1; |
542 | if (arg[1].arg_type == A_LVAL) { |
543 | tmpstab = arg[1].arg_ptr.arg_stab; |
544 | if (!tmpstab->stab_io || |
545 | fstat(fileno(tmpstab->stab_io->fp),&statbuf) < 0) { |
546 | max = 0; |
547 | } |
548 | } |
549 | else |
550 | if (stat(str_get(sarg[1]),&statbuf) < 0) |
551 | max = 0; |
552 | |
553 | if (retary) { |
554 | if (max) { |
555 | apush(ary,str_nmake((double)statbuf.st_dev)); |
556 | apush(ary,str_nmake((double)statbuf.st_ino)); |
557 | apush(ary,str_nmake((double)statbuf.st_mode)); |
558 | apush(ary,str_nmake((double)statbuf.st_nlink)); |
559 | apush(ary,str_nmake((double)statbuf.st_uid)); |
560 | apush(ary,str_nmake((double)statbuf.st_gid)); |
561 | apush(ary,str_nmake((double)statbuf.st_rdev)); |
562 | apush(ary,str_nmake((double)statbuf.st_size)); |
563 | apush(ary,str_nmake((double)statbuf.st_atime)); |
564 | apush(ary,str_nmake((double)statbuf.st_mtime)); |
565 | apush(ary,str_nmake((double)statbuf.st_ctime)); |
135863df |
566 | #ifdef STATBLOCKS |
8d063cd8 |
567 | apush(ary,str_nmake((double)statbuf.st_blksize)); |
568 | apush(ary,str_nmake((double)statbuf.st_blocks)); |
135863df |
569 | #else |
d96024cf |
570 | apush(ary,str_make("")); |
571 | apush(ary,str_make("")); |
135863df |
572 | #endif |
8d063cd8 |
573 | } |
574 | sarg = (STR**)safemalloc((max+2)*sizeof(STR*)); |
575 | sarg[0] = Nullstr; |
576 | sarg[max+1] = Nullstr; |
577 | for (i = 1; i <= max; i++) |
578 | sarg[i] = afetch(ary,i-1); |
579 | *retary = sarg; |
580 | } |
581 | return max; |
582 | } |
583 | |
584 | do_tms(retary) |
585 | STR ***retary; |
586 | { |
587 | register ARRAY *ary; |
588 | static ARRAY *myarray = Null(ARRAY*); |
589 | register STR **sarg; |
590 | int max = 4; |
591 | register int i; |
592 | |
593 | ary = myarray; |
594 | if (!ary) |
595 | myarray = ary = anew(); |
596 | ary->ary_fill = -1; |
597 | if (times(×buf) < 0) |
598 | max = 0; |
599 | |
600 | if (retary) { |
601 | if (max) { |
602 | apush(ary,str_nmake(((double)timesbuf.tms_utime)/60.0)); |
603 | apush(ary,str_nmake(((double)timesbuf.tms_stime)/60.0)); |
604 | apush(ary,str_nmake(((double)timesbuf.tms_cutime)/60.0)); |
605 | apush(ary,str_nmake(((double)timesbuf.tms_cstime)/60.0)); |
606 | } |
607 | sarg = (STR**)safemalloc((max+2)*sizeof(STR*)); |
608 | sarg[0] = Nullstr; |
609 | sarg[max+1] = Nullstr; |
610 | for (i = 1; i <= max; i++) |
611 | sarg[i] = afetch(ary,i-1); |
612 | *retary = sarg; |
613 | } |
614 | return max; |
615 | } |
616 | |
617 | do_time(tmbuf,retary) |
618 | struct tm *tmbuf; |
619 | STR ***retary; |
620 | { |
621 | register ARRAY *ary; |
622 | static ARRAY *myarray = Null(ARRAY*); |
623 | register STR **sarg; |
624 | int max = 9; |
625 | register int i; |
626 | STR *str; |
627 | |
628 | ary = myarray; |
629 | if (!ary) |
630 | myarray = ary = anew(); |
631 | ary->ary_fill = -1; |
632 | if (!tmbuf) |
633 | max = 0; |
634 | |
635 | if (retary) { |
636 | if (max) { |
637 | apush(ary,str_nmake((double)tmbuf->tm_sec)); |
638 | apush(ary,str_nmake((double)tmbuf->tm_min)); |
639 | apush(ary,str_nmake((double)tmbuf->tm_hour)); |
640 | apush(ary,str_nmake((double)tmbuf->tm_mday)); |
641 | apush(ary,str_nmake((double)tmbuf->tm_mon)); |
642 | apush(ary,str_nmake((double)tmbuf->tm_year)); |
643 | apush(ary,str_nmake((double)tmbuf->tm_wday)); |
644 | apush(ary,str_nmake((double)tmbuf->tm_yday)); |
645 | apush(ary,str_nmake((double)tmbuf->tm_isdst)); |
646 | } |
647 | sarg = (STR**)safemalloc((max+2)*sizeof(STR*)); |
648 | sarg[0] = Nullstr; |
649 | sarg[max+1] = Nullstr; |
650 | for (i = 1; i <= max; i++) |
651 | sarg[i] = afetch(ary,i-1); |
652 | *retary = sarg; |
653 | } |
654 | return max; |
655 | } |
656 | |
657 | void |
658 | do_sprintf(str,len,sarg) |
659 | register STR *str; |
660 | register int len; |
661 | register STR **sarg; |
662 | { |
663 | register char *s; |
664 | register char *t; |
665 | bool dolong; |
666 | char ch; |
f9ad7436 |
667 | static STR *sargnull = &str_no; |
8d063cd8 |
668 | |
669 | str_set(str,""); |
670 | len--; /* don't count pattern string */ |
671 | sarg++; |
f9ad7436 |
672 | for (s = str_get(*(sarg++)); *s; len--) { |
673 | if (len <= 0 || !*sarg) { |
674 | sarg = &sargnull; |
675 | len = 0; |
676 | } |
8d063cd8 |
677 | dolong = FALSE; |
678 | for (t = s; *t && *t != '%'; t++) ; |
679 | if (!*t) |
680 | break; /* not enough % patterns, oh well */ |
681 | for (t++; *sarg && *t && t != s; t++) { |
682 | switch (*t) { |
683 | case '\0': |
684 | break; |
685 | case '%': |
686 | ch = *(++t); |
687 | *t = '\0'; |
688 | sprintf(buf,s); |
689 | s = t; |
690 | *(t--) = ch; |
691 | break; |
692 | case 'l': |
693 | dolong = TRUE; |
694 | break; |
695 | case 'D': case 'X': case 'O': |
696 | dolong = TRUE; |
697 | /* FALL THROUGH */ |
698 | case 'd': case 'x': case 'o': case 'c': |
699 | ch = *(++t); |
700 | *t = '\0'; |
701 | if (dolong) |
702 | sprintf(buf,s,(long)str_gnum(*(sarg++))); |
703 | else |
704 | sprintf(buf,s,(int)str_gnum(*(sarg++))); |
705 | s = t; |
706 | *(t--) = ch; |
707 | break; |
708 | case 'E': case 'e': case 'f': case 'G': case 'g': |
709 | ch = *(++t); |
710 | *t = '\0'; |
711 | sprintf(buf,s,str_gnum(*(sarg++))); |
712 | s = t; |
713 | *(t--) = ch; |
714 | break; |
715 | case 's': |
716 | ch = *(++t); |
717 | *t = '\0'; |
718 | sprintf(buf,s,str_get(*(sarg++))); |
719 | s = t; |
720 | *(t--) = ch; |
721 | break; |
722 | } |
723 | } |
724 | str_cat(str,buf); |
725 | } |
726 | if (*s) |
727 | str_cat(str,s); |
728 | STABSET(str); |
729 | } |
730 | |
731 | bool |
732 | do_print(s,fp) |
733 | char *s; |
734 | FILE *fp; |
735 | { |
736 | if (!fp || !s) |
737 | return FALSE; |
738 | fputs(s,fp); |
739 | return TRUE; |
740 | } |
741 | |
742 | bool |
743 | do_aprint(arg,fp) |
744 | register ARG *arg; |
745 | register FILE *fp; |
746 | { |
747 | STR **tmpary; /* must not be register */ |
748 | register STR **elem; |
749 | register bool retval; |
750 | double value; |
751 | |
752 | (void)eval(arg[1].arg_ptr.arg_arg,&tmpary); |
753 | if (arg->arg_type == O_PRTF) { |
754 | do_sprintf(arg->arg_ptr.arg_str,32767,tmpary); |
755 | retval = do_print(str_get(arg->arg_ptr.arg_str),fp); |
756 | } |
757 | else { |
758 | retval = FALSE; |
759 | for (elem = tmpary+1; *elem; elem++) { |
760 | if (retval && ofs) |
761 | do_print(ofs, fp); |
762 | if (ofmt && fp) { |
763 | if ((*elem)->str_nok || str_gnum(*elem) != 0.0) |
764 | fprintf(fp, ofmt, str_gnum(*elem)); |
765 | retval = TRUE; |
766 | } |
767 | else |
768 | retval = do_print(str_get(*elem), fp); |
769 | if (!retval) |
770 | break; |
771 | } |
772 | if (ors) |
773 | retval = do_print(ors, fp); |
774 | } |
775 | safefree((char*)tmpary); |
776 | return retval; |
777 | } |
778 | |
779 | bool |
780 | do_aexec(arg) |
781 | register ARG *arg; |
782 | { |
783 | STR **tmpary; /* must not be register */ |
784 | register STR **elem; |
785 | register char **a; |
786 | register int i; |
787 | char **argv; |
788 | |
789 | (void)eval(arg[1].arg_ptr.arg_arg,&tmpary); |
790 | i = 0; |
791 | for (elem = tmpary+1; *elem; elem++) |
792 | i++; |
793 | if (i) { |
794 | argv = (char**)safemalloc((i+1)*sizeof(char*)); |
795 | a = argv; |
796 | for (elem = tmpary+1; *elem; elem++) { |
797 | *a++ = str_get(*elem); |
798 | } |
799 | *a = Nullch; |
800 | execvp(argv[0],argv); |
801 | safefree((char*)argv); |
802 | } |
803 | safefree((char*)tmpary); |
804 | return FALSE; |
805 | } |
806 | |
807 | bool |
808 | do_exec(cmd) |
809 | char *cmd; |
810 | { |
811 | STR **tmpary; /* must not be register */ |
812 | register char **a; |
813 | register char *s; |
814 | char **argv; |
815 | |
816 | /* see if there are shell metacharacters in it */ |
817 | |
818 | for (s = cmd; *s; s++) { |
819 | if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`",*s)) { |
820 | execl("/bin/sh","sh","-c",cmd,0); |
821 | return FALSE; |
822 | } |
823 | } |
824 | argv = (char**)safemalloc(((s - cmd) / 2 + 2)*sizeof(char*)); |
825 | |
826 | a = argv; |
827 | for (s = cmd; *s;) { |
828 | while (isspace(*s)) s++; |
829 | if (*s) |
830 | *(a++) = s; |
831 | while (*s && !isspace(*s)) s++; |
832 | if (*s) |
833 | *s++ = '\0'; |
834 | } |
835 | *a = Nullch; |
836 | if (argv[0]) |
837 | execvp(argv[0],argv); |
838 | safefree((char*)argv); |
839 | return FALSE; |
840 | } |
841 | |
842 | STR * |
843 | do_push(arg,ary) |
844 | register ARG *arg; |
845 | register ARRAY *ary; |
846 | { |
847 | STR **tmpary; /* must not be register */ |
848 | register STR **elem; |
849 | register STR *str = &str_no; |
850 | |
851 | (void)eval(arg[1].arg_ptr.arg_arg,&tmpary); |
852 | for (elem = tmpary+1; *elem; elem++) { |
853 | str = str_new(0); |
854 | str_sset(str,*elem); |
855 | apush(ary,str); |
856 | } |
857 | safefree((char*)tmpary); |
858 | return str; |
859 | } |
860 | |
861 | do_unshift(arg,ary) |
862 | register ARG *arg; |
863 | register ARRAY *ary; |
864 | { |
865 | STR **tmpary; /* must not be register */ |
866 | register STR **elem; |
867 | register STR *str = &str_no; |
868 | register int i; |
869 | |
870 | (void)eval(arg[1].arg_ptr.arg_arg,&tmpary); |
871 | i = 0; |
872 | for (elem = tmpary+1; *elem; elem++) |
873 | i++; |
874 | aunshift(ary,i); |
875 | i = 0; |
876 | for (elem = tmpary+1; *elem; elem++) { |
877 | str = str_new(0); |
878 | str_sset(str,*elem); |
879 | astore(ary,i++,str); |
880 | } |
881 | safefree((char*)tmpary); |
882 | } |
883 | |
884 | apply(type,arg,sarg) |
885 | int type; |
886 | register ARG *arg; |
887 | STR **sarg; |
888 | { |
889 | STR **tmpary; /* must not be register */ |
890 | register STR **elem; |
891 | register int i; |
892 | register int val; |
893 | register int val2; |
894 | |
895 | if (sarg) |
896 | tmpary = sarg; |
897 | else |
898 | (void)eval(arg[1].arg_ptr.arg_arg,&tmpary); |
899 | i = 0; |
900 | for (elem = tmpary+1; *elem; elem++) |
901 | i++; |
902 | switch (type) { |
903 | case O_CHMOD: |
904 | if (--i > 0) { |
905 | val = (int)str_gnum(tmpary[1]); |
906 | for (elem = tmpary+2; *elem; elem++) |
907 | if (chmod(str_get(*elem),val)) |
908 | i--; |
909 | } |
910 | break; |
911 | case O_CHOWN: |
912 | if (i > 2) { |
913 | i -= 2; |
914 | val = (int)str_gnum(tmpary[1]); |
915 | val2 = (int)str_gnum(tmpary[2]); |
916 | for (elem = tmpary+3; *elem; elem++) |
917 | if (chown(str_get(*elem),val,val2)) |
918 | i--; |
919 | } |
920 | else |
921 | i = 0; |
922 | break; |
923 | case O_KILL: |
924 | if (--i > 0) { |
925 | val = (int)str_gnum(tmpary[1]); |
926 | if (val < 0) |
927 | val = -val; |
928 | for (elem = tmpary+2; *elem; elem++) |
929 | if (kill(atoi(str_get(*elem)),val)) |
930 | i--; |
931 | } |
932 | break; |
933 | case O_UNLINK: |
934 | for (elem = tmpary+1; *elem; elem++) |
935 | if (UNLINK(str_get(*elem))) |
936 | i--; |
937 | break; |
938 | } |
939 | if (!sarg) |
940 | safefree((char*)tmpary); |
941 | return i; |
942 | } |
943 | |
944 | STR * |
945 | do_subr(arg,sarg) |
946 | register ARG *arg; |
947 | register char **sarg; |
948 | { |
949 | ARRAY *savearray; |
950 | STR *str; |
951 | |
952 | savearray = defstab->stab_array; |
953 | defstab->stab_array = anew(); |
954 | if (arg[1].arg_flags & AF_SPECIAL) |
955 | (void)do_push(arg,defstab->stab_array); |
956 | else if (arg[1].arg_type != A_NULL) { |
957 | str = str_new(0); |
958 | str_sset(str,sarg[1]); |
959 | apush(defstab->stab_array,str); |
960 | } |
961 | str = cmd_exec(arg[2].arg_ptr.arg_stab->stab_sub); |
962 | afree(defstab->stab_array); /* put back old $_[] */ |
963 | defstab->stab_array = savearray; |
964 | return str; |
965 | } |
966 | |
967 | void |
968 | do_assign(retstr,arg) |
969 | STR *retstr; |
970 | register ARG *arg; |
971 | { |
972 | STR **tmpary; /* must not be register */ |
973 | register ARG *larg = arg[1].arg_ptr.arg_arg; |
974 | register STR **elem; |
975 | register STR *str; |
976 | register ARRAY *ary; |
977 | register int i; |
978 | register int lasti; |
979 | char *s; |
980 | |
981 | (void)eval(arg[2].arg_ptr.arg_arg,&tmpary); |
982 | |
983 | if (arg->arg_flags & AF_COMMON) { |
984 | if (*(tmpary+1)) { |
985 | for (elem=tmpary+2; *elem; elem++) { |
986 | *elem = str_static(*elem); |
987 | } |
988 | } |
989 | } |
990 | if (larg->arg_type == O_LIST) { |
991 | lasti = larg->arg_len; |
992 | for (i=1,elem=tmpary+1; i <= lasti; i++) { |
993 | if (*elem) |
994 | s = str_get(*(elem++)); |
995 | else |
996 | s = ""; |
997 | switch (larg[i].arg_type) { |
998 | case A_STAB: |
999 | case A_LVAL: |
1000 | str = STAB_STR(larg[i].arg_ptr.arg_stab); |
1001 | break; |
1002 | case A_LEXPR: |
1003 | str = eval(larg[i].arg_ptr.arg_arg,Null(STR***)); |
1004 | break; |
1005 | } |
1006 | str_set(str,s); |
1007 | STABSET(str); |
1008 | } |
1009 | i = elem - tmpary - 1; |
1010 | } |
1011 | else { /* should be an array name */ |
1012 | ary = larg[1].arg_ptr.arg_stab->stab_array; |
1013 | for (i=0,elem=tmpary+1; *elem; i++) { |
1014 | str = str_new(0); |
1015 | if (*elem) |
1016 | str_sset(str,*(elem++)); |
1017 | astore(ary,i,str); |
1018 | } |
1019 | ary->ary_fill = i - 1; /* they can get the extra ones back by */ |
1020 | } /* setting an element larger than old fill */ |
1021 | str_numset(retstr,(double)i); |
1022 | STABSET(retstr); |
1023 | safefree((char*)tmpary); |
1024 | } |
1025 | |
1026 | int |
1027 | do_kv(hash,kv,sarg,retary) |
1028 | HASH *hash; |
1029 | int kv; |
1030 | register STR **sarg; |
1031 | STR ***retary; |
1032 | { |
1033 | register ARRAY *ary; |
1034 | int max = 0; |
1035 | int i; |
1036 | static ARRAY *myarray = Null(ARRAY*); |
1037 | register HENT *entry; |
1038 | |
1039 | ary = myarray; |
1040 | if (!ary) |
1041 | myarray = ary = anew(); |
1042 | ary->ary_fill = -1; |
1043 | |
1044 | hiterinit(hash); |
1045 | while (entry = hiternext(hash)) { |
1046 | max++; |
1047 | if (kv == O_KEYS) |
1048 | apush(ary,str_make(hiterkey(entry))); |
1049 | else |
1050 | apush(ary,str_make(str_get(hiterval(entry)))); |
1051 | } |
1052 | if (retary) { /* array wanted */ |
1053 | sarg = (STR**)saferealloc((char*)sarg,(max+2)*sizeof(STR*)); |
1054 | sarg[0] = Nullstr; |
1055 | sarg[max+1] = Nullstr; |
1056 | for (i = 1; i <= max; i++) |
1057 | sarg[i] = afetch(ary,i-1); |
1058 | *retary = sarg; |
1059 | } |
1060 | return max; |
1061 | } |
1062 | |
1063 | STR * |
1064 | do_each(hash,sarg,retary) |
1065 | HASH *hash; |
1066 | register STR **sarg; |
1067 | STR ***retary; |
1068 | { |
1069 | static STR *mystr = Nullstr; |
1070 | STR *retstr; |
1071 | HENT *entry = hiternext(hash); |
1072 | |
1073 | if (mystr) { |
1074 | str_free(mystr); |
1075 | mystr = Nullstr; |
1076 | } |
1077 | |
1078 | if (retary) { /* array wanted */ |
1079 | if (entry) { |
1080 | sarg = (STR**)saferealloc((char*)sarg,4*sizeof(STR*)); |
1081 | sarg[0] = Nullstr; |
1082 | sarg[3] = Nullstr; |
1083 | sarg[1] = mystr = str_make(hiterkey(entry)); |
1084 | retstr = sarg[2] = hiterval(entry); |
1085 | *retary = sarg; |
1086 | } |
1087 | else { |
1088 | sarg = (STR**)saferealloc((char*)sarg,2*sizeof(STR*)); |
1089 | sarg[0] = Nullstr; |
1090 | sarg[1] = retstr = Nullstr; |
1091 | *retary = sarg; |
1092 | } |
1093 | } |
1094 | else |
1095 | retstr = hiterval(entry); |
1096 | |
1097 | return retstr; |
1098 | } |
1099 | |
1100 | init_eval() |
1101 | { |
1102 | register int i; |
1103 | |
1104 | #define A(e1,e2,e3) (e1+(e2<<1)+(e3<<2)) |
1105 | opargs[O_ITEM] = A(1,0,0); |
1106 | opargs[O_ITEM2] = A(0,0,0); |
1107 | opargs[O_ITEM3] = A(0,0,0); |
1108 | opargs[O_CONCAT] = A(1,1,0); |
1109 | opargs[O_MATCH] = A(1,0,0); |
1110 | opargs[O_NMATCH] = A(1,0,0); |
1111 | opargs[O_SUBST] = A(1,0,0); |
1112 | opargs[O_NSUBST] = A(1,0,0); |
1113 | opargs[O_ASSIGN] = A(1,1,0); |
1114 | opargs[O_MULTIPLY] = A(1,1,0); |
1115 | opargs[O_DIVIDE] = A(1,1,0); |
1116 | opargs[O_MODULO] = A(1,1,0); |
1117 | opargs[O_ADD] = A(1,1,0); |
1118 | opargs[O_SUBTRACT] = A(1,1,0); |
1119 | opargs[O_LEFT_SHIFT] = A(1,1,0); |
1120 | opargs[O_RIGHT_SHIFT] = A(1,1,0); |
1121 | opargs[O_LT] = A(1,1,0); |
1122 | opargs[O_GT] = A(1,1,0); |
1123 | opargs[O_LE] = A(1,1,0); |
1124 | opargs[O_GE] = A(1,1,0); |
1125 | opargs[O_EQ] = A(1,1,0); |
1126 | opargs[O_NE] = A(1,1,0); |
1127 | opargs[O_BIT_AND] = A(1,1,0); |
1128 | opargs[O_XOR] = A(1,1,0); |
1129 | opargs[O_BIT_OR] = A(1,1,0); |
1130 | opargs[O_AND] = A(1,0,0); /* don't eval arg 2 (yet) */ |
1131 | opargs[O_OR] = A(1,0,0); /* don't eval arg 2 (yet) */ |
1132 | opargs[O_COND_EXPR] = A(1,0,0); /* don't eval args 2 or 3 */ |
1133 | opargs[O_COMMA] = A(1,1,0); |
1134 | opargs[O_NEGATE] = A(1,0,0); |
1135 | opargs[O_NOT] = A(1,0,0); |
1136 | opargs[O_COMPLEMENT] = A(1,0,0); |
1137 | opargs[O_WRITE] = A(1,0,0); |
1138 | opargs[O_OPEN] = A(1,1,0); |
1139 | opargs[O_TRANS] = A(1,0,0); |
1140 | opargs[O_NTRANS] = A(1,0,0); |
1141 | opargs[O_CLOSE] = A(0,0,0); |
1142 | opargs[O_ARRAY] = A(1,0,0); |
1143 | opargs[O_HASH] = A(1,0,0); |
1144 | opargs[O_LARRAY] = A(1,0,0); |
1145 | opargs[O_LHASH] = A(1,0,0); |
1146 | opargs[O_PUSH] = A(1,0,0); |
1147 | opargs[O_POP] = A(0,0,0); |
1148 | opargs[O_SHIFT] = A(0,0,0); |
1149 | opargs[O_SPLIT] = A(1,0,0); |
1150 | opargs[O_LENGTH] = A(1,0,0); |
1151 | opargs[O_SPRINTF] = A(1,0,0); |
1152 | opargs[O_SUBSTR] = A(1,1,1); |
1153 | opargs[O_JOIN] = A(1,0,0); |
1154 | opargs[O_SLT] = A(1,1,0); |
1155 | opargs[O_SGT] = A(1,1,0); |
1156 | opargs[O_SLE] = A(1,1,0); |
1157 | opargs[O_SGE] = A(1,1,0); |
1158 | opargs[O_SEQ] = A(1,1,0); |
1159 | opargs[O_SNE] = A(1,1,0); |
1160 | opargs[O_SUBR] = A(1,0,0); |
1161 | opargs[O_PRINT] = A(1,0,0); |
1162 | opargs[O_CHDIR] = A(1,0,0); |
1163 | opargs[O_DIE] = A(1,0,0); |
1164 | opargs[O_EXIT] = A(1,0,0); |
1165 | opargs[O_RESET] = A(1,0,0); |
1166 | opargs[O_LIST] = A(0,0,0); |
1167 | opargs[O_EOF] = A(0,0,0); |
1168 | opargs[O_TELL] = A(0,0,0); |
1169 | opargs[O_SEEK] = A(0,1,1); |
1170 | opargs[O_LAST] = A(1,0,0); |
1171 | opargs[O_NEXT] = A(1,0,0); |
1172 | opargs[O_REDO] = A(1,0,0); |
1173 | opargs[O_GOTO] = A(1,0,0); |
1174 | opargs[O_INDEX] = A(1,1,0); |
1175 | opargs[O_TIME] = A(0,0,0); |
1176 | opargs[O_TMS] = A(0,0,0); |
1177 | opargs[O_LOCALTIME] = A(1,0,0); |
1178 | opargs[O_GMTIME] = A(1,0,0); |
1179 | opargs[O_STAT] = A(1,0,0); |
1180 | opargs[O_CRYPT] = A(1,1,0); |
1181 | opargs[O_EXP] = A(1,0,0); |
1182 | opargs[O_LOG] = A(1,0,0); |
1183 | opargs[O_SQRT] = A(1,0,0); |
1184 | opargs[O_INT] = A(1,0,0); |
1185 | opargs[O_PRTF] = A(1,0,0); |
1186 | opargs[O_ORD] = A(1,0,0); |
1187 | opargs[O_SLEEP] = A(1,0,0); |
1188 | opargs[O_FLIP] = A(1,0,0); |
1189 | opargs[O_FLOP] = A(0,1,0); |
1190 | opargs[O_KEYS] = A(0,0,0); |
1191 | opargs[O_VALUES] = A(0,0,0); |
1192 | opargs[O_EACH] = A(0,0,0); |
1193 | opargs[O_CHOP] = A(1,0,0); |
1194 | opargs[O_FORK] = A(1,0,0); |
1195 | opargs[O_EXEC] = A(1,0,0); |
1196 | opargs[O_SYSTEM] = A(1,0,0); |
1197 | opargs[O_OCT] = A(1,0,0); |
1198 | opargs[O_HEX] = A(1,0,0); |
1199 | opargs[O_CHMOD] = A(1,0,0); |
1200 | opargs[O_CHOWN] = A(1,0,0); |
1201 | opargs[O_KILL] = A(1,0,0); |
1202 | opargs[O_RENAME] = A(1,1,0); |
1203 | opargs[O_UNLINK] = A(1,0,0); |
1204 | opargs[O_UMASK] = A(1,0,0); |
1205 | opargs[O_UNSHIFT] = A(1,0,0); |
1206 | opargs[O_LINK] = A(1,1,0); |
1207 | opargs[O_REPEAT] = A(1,1,0); |
a559c259 |
1208 | opargs[O_EVAL] = A(1,0,0); |
8d063cd8 |
1209 | } |
1210 | |
36ce8bec |
1211 | #ifdef VOIDSIG |
1212 | static void (*ihand)(); |
1213 | static void (*qhand)(); |
1214 | #else |
8d063cd8 |
1215 | static int (*ihand)(); |
1216 | static int (*qhand)(); |
36ce8bec |
1217 | #endif |
8d063cd8 |
1218 | |
1219 | STR * |
1220 | eval(arg,retary) |
1221 | register ARG *arg; |
1222 | STR ***retary; /* where to return an array to, null if nowhere */ |
1223 | { |
1224 | register STR *str; |
1225 | register int anum; |
1226 | register int optype; |
1227 | register int maxarg; |
1228 | double value; |
1229 | STR *quicksarg[5]; |
1230 | register STR **sarg = quicksarg; |
1231 | register char *tmps; |
1232 | char *tmps2; |
1233 | int argflags; |
1234 | long tmplong; |
1235 | FILE *fp; |
1236 | STR *tmpstr; |
1237 | FCMD *form; |
1238 | STAB *stab; |
1239 | ARRAY *ary; |
1240 | bool assigning = FALSE; |
1241 | double exp(), log(), sqrt(), modf(); |
1242 | char *crypt(), *getenv(); |
1243 | |
1244 | if (!arg) |
1245 | return &str_no; |
1246 | str = arg->arg_ptr.arg_str; |
1247 | optype = arg->arg_type; |
1248 | maxarg = arg->arg_len; |
1249 | if (maxarg > 3 || retary) { |
1250 | sarg = (STR **)safemalloc((maxarg+2) * sizeof(STR*)); |
1251 | } |
1252 | #ifdef DEBUGGING |
1253 | if (debug & 8) { |
1254 | deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg); |
1255 | } |
1256 | debname[dlevel] = opname[optype][0]; |
1257 | debdelim[dlevel++] = ':'; |
1258 | #endif |
1259 | for (anum = 1; anum <= maxarg; anum++) { |
1260 | argflags = arg[anum].arg_flags; |
1261 | if (argflags & AF_SPECIAL) |
1262 | continue; |
1263 | re_eval: |
1264 | switch (arg[anum].arg_type) { |
1265 | default: |
1266 | sarg[anum] = &str_no; |
1267 | #ifdef DEBUGGING |
1268 | tmps = "NULL"; |
1269 | #endif |
1270 | break; |
1271 | case A_EXPR: |
1272 | #ifdef DEBUGGING |
1273 | if (debug & 8) { |
1274 | tmps = "EXPR"; |
1275 | deb("%d.EXPR =>\n",anum); |
1276 | } |
1277 | #endif |
1278 | sarg[anum] = eval(arg[anum].arg_ptr.arg_arg, Null(STR***)); |
1279 | break; |
1280 | case A_CMD: |
1281 | #ifdef DEBUGGING |
1282 | if (debug & 8) { |
1283 | tmps = "CMD"; |
1284 | deb("%d.CMD (%lx) =>\n",anum,arg[anum].arg_ptr.arg_cmd); |
1285 | } |
1286 | #endif |
1287 | sarg[anum] = cmd_exec(arg[anum].arg_ptr.arg_cmd); |
1288 | break; |
1289 | case A_STAB: |
1290 | sarg[anum] = STAB_STR(arg[anum].arg_ptr.arg_stab); |
1291 | #ifdef DEBUGGING |
1292 | if (debug & 8) { |
1293 | sprintf(buf,"STAB $%s ==",arg[anum].arg_ptr.arg_stab->stab_name); |
1294 | tmps = buf; |
1295 | } |
1296 | #endif |
1297 | break; |
1298 | case A_LEXPR: |
1299 | #ifdef DEBUGGING |
1300 | if (debug & 8) { |
1301 | tmps = "LEXPR"; |
1302 | deb("%d.LEXPR =>\n",anum); |
1303 | } |
1304 | #endif |
1305 | str = eval(arg[anum].arg_ptr.arg_arg,Null(STR***)); |
1306 | if (!str) |
1307 | fatal("panic: A_LEXPR\n"); |
1308 | goto do_crement; |
1309 | case A_LVAL: |
1310 | #ifdef DEBUGGING |
1311 | if (debug & 8) { |
1312 | sprintf(buf,"LVAL $%s ==",arg[anum].arg_ptr.arg_stab->stab_name); |
1313 | tmps = buf; |
1314 | } |
1315 | #endif |
1316 | str = STAB_STR(arg[anum].arg_ptr.arg_stab); |
1317 | if (!str) |
1318 | fatal("panic: A_LVAL\n"); |
1319 | do_crement: |
1320 | assigning = TRUE; |
1321 | if (argflags & AF_PRE) { |
1322 | if (argflags & AF_UP) |
1323 | str_inc(str); |
1324 | else |
1325 | str_dec(str); |
1326 | STABSET(str); |
1327 | sarg[anum] = str; |
1328 | str = arg->arg_ptr.arg_str; |
1329 | } |
1330 | else if (argflags & AF_POST) { |
1331 | sarg[anum] = str_static(str); |
1332 | if (argflags & AF_UP) |
1333 | str_inc(str); |
1334 | else |
1335 | str_dec(str); |
1336 | STABSET(str); |
1337 | str = arg->arg_ptr.arg_str; |
1338 | } |
1339 | else { |
1340 | sarg[anum] = str; |
1341 | } |
1342 | break; |
1343 | case A_ARYLEN: |
1344 | sarg[anum] = str_static(&str_no); |
1345 | str_numset(sarg[anum], |
1346 | (double)alen(arg[anum].arg_ptr.arg_stab->stab_array)); |
1347 | #ifdef DEBUGGING |
1348 | tmps = "ARYLEN"; |
1349 | #endif |
1350 | break; |
1351 | case A_SINGLE: |
1352 | sarg[anum] = arg[anum].arg_ptr.arg_str; |
1353 | #ifdef DEBUGGING |
1354 | tmps = "SINGLE"; |
1355 | #endif |
1356 | break; |
1357 | case A_DOUBLE: |
1358 | (void) interp(str,str_get(arg[anum].arg_ptr.arg_str)); |
1359 | sarg[anum] = str; |
1360 | #ifdef DEBUGGING |
1361 | tmps = "DOUBLE"; |
1362 | #endif |
1363 | break; |
1364 | case A_BACKTICK: |
1365 | tmps = str_get(arg[anum].arg_ptr.arg_str); |
1366 | fp = popen(str_get(interp(str,tmps)),"r"); |
1367 | tmpstr = str_new(80); |
1368 | str_set(str,""); |
1369 | if (fp) { |
1370 | while (str_gets(tmpstr,fp) != Nullch) { |
1371 | str_scat(str,tmpstr); |
1372 | } |
1373 | statusvalue = pclose(fp); |
1374 | } |
1375 | else |
1376 | statusvalue = -1; |
1377 | str_free(tmpstr); |
1378 | |
1379 | sarg[anum] = str; |
1380 | #ifdef DEBUGGING |
1381 | tmps = "BACK"; |
1382 | #endif |
1383 | break; |
1384 | case A_READ: |
1385 | fp = Nullfp; |
1386 | last_in_stab = arg[anum].arg_ptr.arg_stab; |
1387 | if (last_in_stab->stab_io) { |
1388 | fp = last_in_stab->stab_io->fp; |
1389 | if (!fp && (last_in_stab->stab_io->flags & IOF_ARGV)) { |
1390 | if (last_in_stab->stab_io->flags & IOF_START) { |
1391 | last_in_stab->stab_io->flags &= ~IOF_START; |
1392 | last_in_stab->stab_io->lines = 0; |
1393 | if (alen(last_in_stab->stab_array) < 0L) { |
1394 | tmpstr = str_make("-"); /* assume stdin */ |
1395 | apush(last_in_stab->stab_array, tmpstr); |
1396 | } |
1397 | } |
1398 | fp = nextargv(last_in_stab); |
1399 | if (!fp) /* Note: fp != last_in_stab->stab_io->fp */ |
1400 | do_close(last_in_stab,FALSE); /* now it does */ |
1401 | } |
1402 | } |
1403 | keepgoing: |
1404 | if (!fp) |
1405 | sarg[anum] = &str_no; |
1406 | else if (!str_gets(str,fp)) { |
1407 | if (last_in_stab->stab_io->flags & IOF_ARGV) { |
1408 | fp = nextargv(last_in_stab); |
1409 | if (fp) |
1410 | goto keepgoing; |
1411 | do_close(last_in_stab,FALSE); |
1412 | last_in_stab->stab_io->flags |= IOF_START; |
1413 | } |
1414 | if (fp == stdin) { |
1415 | clearerr(fp); |
1416 | } |
1417 | sarg[anum] = &str_no; |
1418 | break; |
1419 | } |
1420 | else { |
1421 | last_in_stab->stab_io->lines++; |
1422 | sarg[anum] = str; |
1423 | } |
1424 | #ifdef DEBUGGING |
1425 | tmps = "READ"; |
1426 | #endif |
1427 | break; |
1428 | } |
1429 | #ifdef DEBUGGING |
1430 | if (debug & 8) |
1431 | deb("%d.%s = '%s'\n",anum,tmps,str_peek(sarg[anum])); |
1432 | #endif |
1433 | } |
1434 | switch (optype) { |
1435 | case O_ITEM: |
1436 | if (str != sarg[1]) |
1437 | str_sset(str,sarg[1]); |
1438 | STABSET(str); |
1439 | break; |
1440 | case O_ITEM2: |
1441 | if (str != sarg[2]) |
1442 | str_sset(str,sarg[2]); |
1443 | STABSET(str); |
1444 | break; |
1445 | case O_ITEM3: |
1446 | if (str != sarg[3]) |
1447 | str_sset(str,sarg[3]); |
1448 | STABSET(str); |
1449 | break; |
1450 | case O_CONCAT: |
1451 | if (str != sarg[1]) |
1452 | str_sset(str,sarg[1]); |
1453 | str_scat(str,sarg[2]); |
1454 | STABSET(str); |
1455 | break; |
1456 | case O_REPEAT: |
1457 | if (str != sarg[1]) |
1458 | str_sset(str,sarg[1]); |
1459 | anum = (long)str_gnum(sarg[2]); |
1460 | if (anum >= 1) { |
1461 | tmpstr = str_new(0); |
1462 | str_sset(tmpstr,str); |
1463 | for (anum--; anum; anum--) |
1464 | str_scat(str,tmpstr); |
1465 | } |
1466 | else |
1467 | str_sset(str,&str_no); |
1468 | STABSET(str); |
1469 | break; |
1470 | case O_MATCH: |
1471 | str_set(str, do_match(str_get(sarg[1]),arg) ? Yes : No); |
1472 | STABSET(str); |
1473 | break; |
1474 | case O_NMATCH: |
1475 | str_set(str, do_match(str_get(sarg[1]),arg) ? No : Yes); |
1476 | STABSET(str); |
1477 | break; |
1478 | case O_SUBST: |
1479 | value = (double) do_subst(str, arg); |
1480 | str = arg->arg_ptr.arg_str; |
1481 | goto donumset; |
1482 | case O_NSUBST: |
1483 | str_set(arg->arg_ptr.arg_str, do_subst(str, arg) ? No : Yes); |
1484 | str = arg->arg_ptr.arg_str; |
1485 | break; |
1486 | case O_ASSIGN: |
1487 | if (arg[2].arg_flags & AF_SPECIAL) |
1488 | do_assign(str,arg); |
1489 | else { |
1490 | if (str != sarg[2]) |
1491 | str_sset(str, sarg[2]); |
1492 | STABSET(str); |
1493 | } |
1494 | break; |
1495 | case O_CHOP: |
1496 | tmps = str_get(str); |
1497 | tmps += str->str_cur - (str->str_cur != 0); |
1498 | str_set(arg->arg_ptr.arg_str,tmps); /* remember last char */ |
1499 | *tmps = '\0'; /* wipe it out */ |
1500 | str->str_cur = tmps - str->str_ptr; |
1501 | str->str_nok = 0; |
1502 | str = arg->arg_ptr.arg_str; |
1503 | break; |
1504 | case O_MULTIPLY: |
1505 | value = str_gnum(sarg[1]); |
1506 | value *= str_gnum(sarg[2]); |
1507 | goto donumset; |
1508 | case O_DIVIDE: |
1509 | value = str_gnum(sarg[1]); |
1510 | value /= str_gnum(sarg[2]); |
1511 | goto donumset; |
1512 | case O_MODULO: |
1513 | value = str_gnum(sarg[1]); |
1514 | value = (double)(((long)value) % (long)str_gnum(sarg[2])); |
1515 | goto donumset; |
1516 | case O_ADD: |
1517 | value = str_gnum(sarg[1]); |
1518 | value += str_gnum(sarg[2]); |
1519 | goto donumset; |
1520 | case O_SUBTRACT: |
1521 | value = str_gnum(sarg[1]); |
1522 | value -= str_gnum(sarg[2]); |
1523 | goto donumset; |
1524 | case O_LEFT_SHIFT: |
1525 | value = str_gnum(sarg[1]); |
1526 | value = (double)(((long)value) << (long)str_gnum(sarg[2])); |
1527 | goto donumset; |
1528 | case O_RIGHT_SHIFT: |
1529 | value = str_gnum(sarg[1]); |
1530 | value = (double)(((long)value) >> (long)str_gnum(sarg[2])); |
1531 | goto donumset; |
1532 | case O_LT: |
1533 | value = str_gnum(sarg[1]); |
1534 | value = (double)(value < str_gnum(sarg[2])); |
1535 | goto donumset; |
1536 | case O_GT: |
1537 | value = str_gnum(sarg[1]); |
1538 | value = (double)(value > str_gnum(sarg[2])); |
1539 | goto donumset; |
1540 | case O_LE: |
1541 | value = str_gnum(sarg[1]); |
1542 | value = (double)(value <= str_gnum(sarg[2])); |
1543 | goto donumset; |
1544 | case O_GE: |
1545 | value = str_gnum(sarg[1]); |
1546 | value = (double)(value >= str_gnum(sarg[2])); |
1547 | goto donumset; |
1548 | case O_EQ: |
1549 | value = str_gnum(sarg[1]); |
1550 | value = (double)(value == str_gnum(sarg[2])); |
1551 | goto donumset; |
1552 | case O_NE: |
1553 | value = str_gnum(sarg[1]); |
1554 | value = (double)(value != str_gnum(sarg[2])); |
1555 | goto donumset; |
1556 | case O_BIT_AND: |
1557 | value = str_gnum(sarg[1]); |
1558 | value = (double)(((long)value) & (long)str_gnum(sarg[2])); |
1559 | goto donumset; |
1560 | case O_XOR: |
1561 | value = str_gnum(sarg[1]); |
1562 | value = (double)(((long)value) ^ (long)str_gnum(sarg[2])); |
1563 | goto donumset; |
1564 | case O_BIT_OR: |
1565 | value = str_gnum(sarg[1]); |
1566 | value = (double)(((long)value) | (long)str_gnum(sarg[2])); |
1567 | goto donumset; |
1568 | case O_AND: |
1569 | if (str_true(sarg[1])) { |
1570 | anum = 2; |
1571 | optype = O_ITEM2; |
1572 | maxarg = 0; |
1573 | argflags = arg[anum].arg_flags; |
1574 | goto re_eval; |
1575 | } |
1576 | else { |
1577 | if (assigning) { |
1578 | str_sset(str, sarg[1]); |
1579 | STABSET(str); |
1580 | } |
1581 | else |
1582 | str = sarg[1]; |
1583 | break; |
1584 | } |
1585 | case O_OR: |
1586 | if (str_true(sarg[1])) { |
1587 | if (assigning) { |
1588 | str_set(str, sarg[1]); |
1589 | STABSET(str); |
1590 | } |
1591 | else |
1592 | str = sarg[1]; |
1593 | break; |
1594 | } |
1595 | else { |
1596 | anum = 2; |
1597 | optype = O_ITEM2; |
1598 | maxarg = 0; |
1599 | argflags = arg[anum].arg_flags; |
1600 | goto re_eval; |
1601 | } |
1602 | case O_COND_EXPR: |
1603 | anum = (str_true(sarg[1]) ? 2 : 3); |
1604 | optype = (anum == 2 ? O_ITEM2 : O_ITEM3); |
1605 | maxarg = 0; |
1606 | argflags = arg[anum].arg_flags; |
1607 | goto re_eval; |
1608 | case O_COMMA: |
1609 | str = sarg[2]; |
1610 | break; |
1611 | case O_NEGATE: |
1612 | value = -str_gnum(sarg[1]); |
1613 | goto donumset; |
1614 | case O_NOT: |
1615 | value = (double) !str_true(sarg[1]); |
1616 | goto donumset; |
1617 | case O_COMPLEMENT: |
1618 | value = (double) ~(long)str_gnum(sarg[1]); |
1619 | goto donumset; |
1620 | case O_SELECT: |
1621 | if (arg[1].arg_type == A_LVAL) |
1622 | defoutstab = arg[1].arg_ptr.arg_stab; |
1623 | else |
1624 | defoutstab = stabent(str_get(sarg[1]),TRUE); |
1625 | if (!defoutstab->stab_io) |
1626 | defoutstab->stab_io = stio_new(); |
1627 | curoutstab = defoutstab; |
1628 | str_set(str,curoutstab->stab_io->fp ? Yes : No); |
1629 | STABSET(str); |
1630 | break; |
1631 | case O_WRITE: |
1632 | if (maxarg == 0) |
1633 | stab = defoutstab; |
1634 | else if (arg[1].arg_type == A_LVAL) |
1635 | stab = arg[1].arg_ptr.arg_stab; |
1636 | else |
1637 | stab = stabent(str_get(sarg[1]),TRUE); |
1638 | if (!stab->stab_io) { |
1639 | str_set(str, No); |
1640 | STABSET(str); |
1641 | break; |
1642 | } |
1643 | curoutstab = stab; |
1644 | fp = stab->stab_io->fp; |
1645 | debarg = arg; |
1646 | if (stab->stab_io->fmt_stab) |
1647 | form = stab->stab_io->fmt_stab->stab_form; |
1648 | else |
1649 | form = stab->stab_form; |
1650 | if (!form || !fp) { |
1651 | str_set(str, No); |
1652 | STABSET(str); |
1653 | break; |
1654 | } |
1655 | format(&outrec,form); |
1656 | do_write(&outrec,stab->stab_io); |
1657 | if (stab->stab_io->flags & IOF_FLUSH) |
1658 | fflush(fp); |
1659 | str_set(str, Yes); |
1660 | STABSET(str); |
1661 | break; |
1662 | case O_OPEN: |
1663 | if (do_open(arg[1].arg_ptr.arg_stab,str_get(sarg[2]))) { |
1664 | str_set(str, Yes); |
1665 | arg[1].arg_ptr.arg_stab->stab_io->lines = 0; |
1666 | } |
1667 | else |
1668 | str_set(str, No); |
1669 | STABSET(str); |
1670 | break; |
1671 | case O_TRANS: |
1672 | value = (double) do_trans(str,arg); |
1673 | str = arg->arg_ptr.arg_str; |
1674 | goto donumset; |
1675 | case O_NTRANS: |
1676 | str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No); |
1677 | str = arg->arg_ptr.arg_str; |
1678 | break; |
1679 | case O_CLOSE: |
1680 | str_set(str, |
1681 | do_close(arg[1].arg_ptr.arg_stab,TRUE) ? Yes : No ); |
1682 | STABSET(str); |
1683 | break; |
1684 | case O_EACH: |
1685 | str_sset(str,do_each(arg[1].arg_ptr.arg_stab->stab_hash,sarg,retary)); |
1686 | retary = Null(STR***); /* do_each already did retary */ |
1687 | STABSET(str); |
1688 | break; |
1689 | case O_VALUES: |
1690 | case O_KEYS: |
1691 | value = (double) do_kv(arg[1].arg_ptr.arg_stab->stab_hash, |
1692 | optype,sarg,retary); |
1693 | retary = Null(STR***); /* do_keys already did retary */ |
1694 | goto donumset; |
1695 | case O_ARRAY: |
1696 | if (maxarg == 1) { |
1697 | ary = arg[1].arg_ptr.arg_stab->stab_array; |
1698 | maxarg = ary->ary_fill; |
1699 | if (retary) { /* array wanted */ |
1700 | sarg = |
1701 | (STR **)saferealloc((char*)sarg,(maxarg+3)*sizeof(STR*)); |
1702 | for (anum = 0; anum <= maxarg; anum++) { |
1703 | sarg[anum+1] = str = afetch(ary,anum); |
1704 | } |
1705 | maxarg++; |
1706 | } |
1707 | else |
1708 | str = afetch(ary,maxarg); |
1709 | } |
1710 | else |
1711 | str = afetch(arg[2].arg_ptr.arg_stab->stab_array, |
1712 | ((int)str_gnum(sarg[1])) - arybase); |
1713 | if (!str) |
1714 | return &str_no; |
1715 | break; |
1716 | case O_HASH: |
1717 | tmpstab = arg[2].arg_ptr.arg_stab; /* XXX */ |
1718 | str = hfetch(tmpstab->stab_hash,str_get(sarg[1])); |
1719 | if (!str) |
1720 | return &str_no; |
1721 | break; |
1722 | case O_LARRAY: |
1723 | anum = ((int)str_gnum(sarg[1])) - arybase; |
1724 | str = afetch(arg[2].arg_ptr.arg_stab->stab_array,anum); |
1725 | if (!str || str == &str_no) { |
1726 | str = str_new(0); |
1727 | astore(arg[2].arg_ptr.arg_stab->stab_array,anum,str); |
1728 | } |
1729 | break; |
1730 | case O_LHASH: |
1731 | tmpstab = arg[2].arg_ptr.arg_stab; |
1732 | str = hfetch(tmpstab->stab_hash,str_get(sarg[1])); |
1733 | if (!str) { |
1734 | str = str_new(0); |
1735 | hstore(tmpstab->stab_hash,str_get(sarg[1]),str); |
1736 | } |
1737 | if (tmpstab == envstab) { /* heavy wizardry going on here */ |
1738 | str->str_link.str_magic = tmpstab;/* str is now magic */ |
1739 | envname = savestr(str_get(sarg[1])); |
1740 | /* he threw the brick up into the air */ |
1741 | } |
1742 | else if (tmpstab == sigstab) { /* same thing, only different */ |
1743 | str->str_link.str_magic = tmpstab; |
1744 | signame = savestr(str_get(sarg[1])); |
1745 | } |
1746 | break; |
1747 | case O_PUSH: |
1748 | if (arg[1].arg_flags & AF_SPECIAL) |
1749 | str = do_push(arg,arg[2].arg_ptr.arg_stab->stab_array); |
1750 | else { |
1751 | str = str_new(0); /* must copy the STR */ |
1752 | str_sset(str,sarg[1]); |
1753 | apush(arg[2].arg_ptr.arg_stab->stab_array,str); |
1754 | } |
1755 | break; |
1756 | case O_POP: |
1757 | str = apop(arg[1].arg_ptr.arg_stab->stab_array); |
1758 | if (!str) |
1759 | return &str_no; |
1760 | #ifdef STRUCTCOPY |
1761 | *(arg->arg_ptr.arg_str) = *str; |
1762 | #else |
1763 | bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str); |
1764 | #endif |
1765 | safefree((char*)str); |
1766 | str = arg->arg_ptr.arg_str; |
1767 | break; |
1768 | case O_SHIFT: |
1769 | str = ashift(arg[1].arg_ptr.arg_stab->stab_array); |
1770 | if (!str) |
1771 | return &str_no; |
1772 | #ifdef STRUCTCOPY |
1773 | *(arg->arg_ptr.arg_str) = *str; |
1774 | #else |
1775 | bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str); |
1776 | #endif |
1777 | safefree((char*)str); |
1778 | str = arg->arg_ptr.arg_str; |
1779 | break; |
1780 | case O_SPLIT: |
1781 | value = (double) do_split(str_get(sarg[1]),arg[2].arg_ptr.arg_spat,retary); |
1782 | retary = Null(STR***); /* do_split already did retary */ |
1783 | goto donumset; |
1784 | case O_LENGTH: |
1785 | value = (double) str_len(sarg[1]); |
1786 | goto donumset; |
1787 | case O_SPRINTF: |
1788 | sarg[maxarg+1] = Nullstr; |
1789 | do_sprintf(str,arg->arg_len,sarg); |
1790 | break; |
1791 | case O_SUBSTR: |
1792 | anum = ((int)str_gnum(sarg[2])) - arybase; |
1793 | for (tmps = str_get(sarg[1]); *tmps && anum > 0; tmps++,anum--) ; |
1794 | anum = (int)str_gnum(sarg[3]); |
1795 | if (anum >= 0 && strlen(tmps) > anum) |
1796 | str_nset(str, tmps, anum); |
1797 | else |
1798 | str_set(str, tmps); |
1799 | break; |
1800 | case O_JOIN: |
1801 | if (arg[2].arg_flags & AF_SPECIAL && arg[2].arg_type == A_EXPR) |
1802 | do_join(arg,str_get(sarg[1]),str); |
1803 | else |
1804 | ajoin(arg[2].arg_ptr.arg_stab->stab_array,str_get(sarg[1]),str); |
1805 | break; |
1806 | case O_SLT: |
1807 | tmps = str_get(sarg[1]); |
1808 | value = (double) strLT(tmps,str_get(sarg[2])); |
1809 | goto donumset; |
1810 | case O_SGT: |
1811 | tmps = str_get(sarg[1]); |
1812 | value = (double) strGT(tmps,str_get(sarg[2])); |
1813 | goto donumset; |
1814 | case O_SLE: |
1815 | tmps = str_get(sarg[1]); |
1816 | value = (double) strLE(tmps,str_get(sarg[2])); |
1817 | goto donumset; |
1818 | case O_SGE: |
1819 | tmps = str_get(sarg[1]); |
1820 | value = (double) strGE(tmps,str_get(sarg[2])); |
1821 | goto donumset; |
1822 | case O_SEQ: |
1823 | tmps = str_get(sarg[1]); |
1824 | value = (double) strEQ(tmps,str_get(sarg[2])); |
1825 | goto donumset; |
1826 | case O_SNE: |
1827 | tmps = str_get(sarg[1]); |
1828 | value = (double) strNE(tmps,str_get(sarg[2])); |
1829 | goto donumset; |
1830 | case O_SUBR: |
1831 | str_sset(str,do_subr(arg,sarg)); |
1832 | STABSET(str); |
1833 | break; |
1834 | case O_PRTF: |
1835 | case O_PRINT: |
1836 | if (maxarg <= 1) |
1837 | stab = defoutstab; |
1838 | else { |
1839 | stab = arg[2].arg_ptr.arg_stab; |
1840 | if (!stab) |
1841 | stab = defoutstab; |
1842 | } |
1843 | if (!stab->stab_io) |
1844 | value = 0.0; |
1845 | else if (arg[1].arg_flags & AF_SPECIAL) |
1846 | value = (double)do_aprint(arg,stab->stab_io->fp); |
1847 | else { |
1848 | value = (double)do_print(str_get(sarg[1]),stab->stab_io->fp); |
1849 | if (ors && optype == O_PRINT) |
1850 | do_print(ors, stab->stab_io->fp); |
1851 | } |
1852 | if (stab->stab_io->flags & IOF_FLUSH) |
1853 | fflush(stab->stab_io->fp); |
1854 | goto donumset; |
1855 | case O_CHDIR: |
1856 | tmps = str_get(sarg[1]); |
1857 | if (!tmps || !*tmps) |
1858 | tmps = getenv("HOME"); |
1859 | if (!tmps || !*tmps) |
1860 | tmps = getenv("LOGDIR"); |
1861 | value = (double)(chdir(tmps) >= 0); |
1862 | goto donumset; |
1863 | case O_DIE: |
1864 | tmps = str_get(sarg[1]); |
1865 | if (!tmps || !*tmps) |
1866 | exit(1); |
1867 | fatal("%s\n",str_get(sarg[1])); |
1868 | value = 0.0; |
1869 | goto donumset; |
1870 | case O_EXIT: |
1871 | exit((int)str_gnum(sarg[1])); |
1872 | value = 0.0; |
1873 | goto donumset; |
1874 | case O_RESET: |
1875 | str_reset(str_get(sarg[1])); |
1876 | value = 1.0; |
1877 | goto donumset; |
1878 | case O_LIST: |
1879 | if (maxarg > 0) |
1880 | str = sarg[maxarg]; /* unwanted list, return last item */ |
1881 | else |
1882 | str = &str_no; |
1883 | break; |
1884 | case O_EOF: |
1885 | str_set(str, do_eof(maxarg > 0 ? arg[1].arg_ptr.arg_stab : last_in_stab) ? Yes : No); |
1886 | STABSET(str); |
1887 | break; |
1888 | case O_TELL: |
1889 | value = (double)do_tell(maxarg > 0 ? arg[1].arg_ptr.arg_stab : last_in_stab); |
1890 | goto donumset; |
1891 | break; |
1892 | case O_SEEK: |
1893 | value = str_gnum(sarg[2]); |
1894 | str_set(str, do_seek(arg[1].arg_ptr.arg_stab, |
1895 | (long)value, (int)str_gnum(sarg[3]) ) ? Yes : No); |
1896 | STABSET(str); |
1897 | break; |
1898 | case O_REDO: |
1899 | case O_NEXT: |
1900 | case O_LAST: |
1901 | if (maxarg > 0) { |
1902 | tmps = str_get(sarg[1]); |
1903 | while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label || |
1904 | strNE(tmps,loop_stack[loop_ptr].loop_label) )) { |
1905 | #ifdef DEBUGGING |
1906 | if (debug & 4) { |
1907 | deb("(Skipping label #%d %s)\n",loop_ptr, |
1908 | loop_stack[loop_ptr].loop_label); |
1909 | } |
1910 | #endif |
1911 | loop_ptr--; |
1912 | } |
1913 | #ifdef DEBUGGING |
1914 | if (debug & 4) { |
1915 | deb("(Found label #%d %s)\n",loop_ptr, |
1916 | loop_stack[loop_ptr].loop_label); |
1917 | } |
1918 | #endif |
1919 | } |
1920 | if (loop_ptr < 0) |
1921 | fatal("Bad label: %s\n", maxarg > 0 ? tmps : "<null>"); |
1922 | longjmp(loop_stack[loop_ptr].loop_env, optype); |
1923 | case O_GOTO:/* shudder */ |
1924 | goto_targ = str_get(sarg[1]); |
1925 | longjmp(top_env, 1); |
1926 | case O_INDEX: |
1927 | tmps = str_get(sarg[1]); |
1928 | if (!(tmps2 = instr(tmps,str_get(sarg[2])))) |
1929 | value = (double)(-1 + arybase); |
1930 | else |
1931 | value = (double)(tmps2 - tmps + arybase); |
1932 | goto donumset; |
1933 | case O_TIME: |
1934 | value = (double) time(0); |
1935 | goto donumset; |
1936 | case O_TMS: |
1937 | value = (double) do_tms(retary); |
1938 | retary = Null(STR***); /* do_tms already did retary */ |
1939 | goto donumset; |
1940 | case O_LOCALTIME: |
1941 | tmplong = (long) str_gnum(sarg[1]); |
1942 | value = (double) do_time(localtime(&tmplong),retary); |
1943 | retary = Null(STR***); /* do_localtime already did retary */ |
1944 | goto donumset; |
1945 | case O_GMTIME: |
1946 | tmplong = (long) str_gnum(sarg[1]); |
1947 | value = (double) do_time(gmtime(&tmplong),retary); |
1948 | retary = Null(STR***); /* do_gmtime already did retary */ |
1949 | goto donumset; |
1950 | case O_STAT: |
1951 | value = (double) do_stat(arg,sarg,retary); |
1952 | retary = Null(STR***); /* do_stat already did retary */ |
1953 | goto donumset; |
1954 | case O_CRYPT: |
1955 | tmps = str_get(sarg[1]); |
1956 | str_set(str,crypt(tmps,str_get(sarg[2]))); |
1957 | break; |
1958 | case O_EXP: |
1959 | value = exp(str_gnum(sarg[1])); |
1960 | goto donumset; |
1961 | case O_LOG: |
1962 | value = log(str_gnum(sarg[1])); |
1963 | goto donumset; |
1964 | case O_SQRT: |
1965 | value = sqrt(str_gnum(sarg[1])); |
1966 | goto donumset; |
1967 | case O_INT: |
1968 | modf(str_gnum(sarg[1]),&value); |
1969 | goto donumset; |
1970 | case O_ORD: |
1971 | value = (double) *str_get(sarg[1]); |
1972 | goto donumset; |
1973 | case O_SLEEP: |
1974 | tmps = str_get(sarg[1]); |
1975 | time(&tmplong); |
1976 | if (!tmps || !*tmps) |
1977 | sleep((32767<<16)+32767); |
1978 | else |
1979 | sleep(atoi(tmps)); |
1980 | value = (double)tmplong; |
1981 | time(&tmplong); |
1982 | value = ((double)tmplong) - value; |
1983 | goto donumset; |
1984 | case O_FLIP: |
1985 | if (str_true(sarg[1])) { |
1986 | str_numset(str,0.0); |
1987 | anum = 2; |
1988 | arg->arg_type = optype = O_FLOP; |
1989 | maxarg = 0; |
1990 | arg[2].arg_flags &= ~AF_SPECIAL; |
1991 | arg[1].arg_flags |= AF_SPECIAL; |
1992 | argflags = arg[anum].arg_flags; |
1993 | goto re_eval; |
1994 | } |
1995 | str_set(str,""); |
1996 | break; |
1997 | case O_FLOP: |
1998 | str_inc(str); |
1999 | if (str_true(sarg[2])) { |
2000 | arg->arg_type = O_FLIP; |
2001 | arg[1].arg_flags &= ~AF_SPECIAL; |
2002 | arg[2].arg_flags |= AF_SPECIAL; |
2003 | str_cat(str,"E0"); |
2004 | } |
2005 | break; |
2006 | case O_FORK: |
2007 | value = (double)fork(); |
2008 | goto donumset; |
2009 | case O_SYSTEM: |
2010 | if (anum = vfork()) { |
2011 | ihand = signal(SIGINT, SIG_IGN); |
2012 | qhand = signal(SIGQUIT, SIG_IGN); |
2013 | while ((maxarg = wait(&argflags)) != anum && maxarg != -1) |
2014 | ; |
2015 | if (maxarg == -1) |
2016 | argflags = -1; |
2017 | signal(SIGINT, ihand); |
2018 | signal(SIGQUIT, qhand); |
2019 | value = (double)argflags; |
2020 | goto donumset; |
2021 | } |
2022 | /* FALL THROUGH */ |
2023 | case O_EXEC: |
2024 | if (arg[1].arg_flags & AF_SPECIAL) |
2025 | value = (double)do_aexec(arg); |
2026 | else { |
2027 | value = (double)do_exec(str_get(sarg[1])); |
2028 | } |
2029 | goto donumset; |
2030 | case O_HEX: |
2031 | maxarg = 4; |
2032 | goto snarfnum; |
2033 | |
2034 | case O_OCT: |
2035 | maxarg = 3; |
2036 | |
2037 | snarfnum: |
2038 | anum = 0; |
2039 | tmps = str_get(sarg[1]); |
2040 | for (;;) { |
2041 | switch (*tmps) { |
2042 | default: |
2043 | goto out; |
2044 | case '8': case '9': |
2045 | if (maxarg != 4) |
2046 | goto out; |
2047 | /* FALL THROUGH */ |
2048 | case '0': case '1': case '2': case '3': case '4': |
2049 | case '5': case '6': case '7': |
2050 | anum <<= maxarg; |
2051 | anum += *tmps++ & 15; |
2052 | break; |
2053 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': |
2054 | case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': |
2055 | if (maxarg != 4) |
2056 | goto out; |
2057 | anum <<= 4; |
2058 | anum += (*tmps++ & 7) + 9; |
2059 | break; |
2060 | case 'x': |
2061 | maxarg = 4; |
2062 | tmps++; |
2063 | break; |
2064 | } |
2065 | } |
2066 | out: |
2067 | value = (double)anum; |
2068 | goto donumset; |
2069 | case O_CHMOD: |
2070 | case O_CHOWN: |
2071 | case O_KILL: |
2072 | case O_UNLINK: |
2073 | if (arg[1].arg_flags & AF_SPECIAL) |
2074 | value = (double)apply(optype,arg,Null(STR**)); |
2075 | else { |
2076 | sarg[2] = Nullstr; |
2077 | value = (double)apply(optype,arg,sarg); |
2078 | } |
2079 | goto donumset; |
2080 | case O_UMASK: |
2081 | value = (double)umask((int)str_gnum(sarg[1])); |
2082 | goto donumset; |
2083 | case O_RENAME: |
2084 | tmps = str_get(sarg[1]); |
2085 | #ifdef RENAME |
2086 | value = (double)(rename(tmps,str_get(sarg[2])) >= 0); |
2087 | #else |
2088 | tmps2 = str_get(sarg[2]); |
2089 | UNLINK(tmps2); |
2090 | if (!(anum = link(tmps,tmps2))) |
2091 | anum = UNLINK(tmps); |
2092 | value = (double)(anum >= 0); |
2093 | #endif |
2094 | goto donumset; |
2095 | case O_LINK: |
2096 | tmps = str_get(sarg[1]); |
2097 | value = (double)(link(tmps,str_get(sarg[2])) >= 0); |
2098 | goto donumset; |
2099 | case O_UNSHIFT: |
2100 | ary = arg[2].arg_ptr.arg_stab->stab_array; |
2101 | if (arg[1].arg_flags & AF_SPECIAL) |
2102 | do_unshift(arg,ary); |
2103 | else { |
2104 | str = str_new(0); /* must copy the STR */ |
2105 | str_sset(str,sarg[1]); |
2106 | aunshift(ary,1); |
2107 | astore(ary,0,str); |
2108 | } |
2109 | value = (double)(ary->ary_fill + 1); |
2110 | break; |
a559c259 |
2111 | case O_EVAL: |
2112 | str_sset(str, |
2113 | do_eval(arg[1].arg_type != A_NULL ? sarg[1] : defstab->stab_val) ); |
2114 | STABSET(str); |
2115 | break; |
8d063cd8 |
2116 | } |
2117 | #ifdef DEBUGGING |
2118 | dlevel--; |
2119 | if (debug & 8) |
2120 | deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str)); |
2121 | #endif |
2122 | goto freeargs; |
2123 | |
2124 | donumset: |
2125 | str_numset(str,value); |
2126 | STABSET(str); |
2127 | #ifdef DEBUGGING |
2128 | dlevel--; |
2129 | if (debug & 8) |
2130 | deb("%s RETURNS \"%f\"\n",opname[optype],value); |
2131 | #endif |
2132 | |
2133 | freeargs: |
2134 | if (sarg != quicksarg) { |
2135 | if (retary) { |
2136 | if (optype == O_LIST) |
2137 | sarg[0] = &str_no; |
2138 | else |
2139 | sarg[0] = Nullstr; |
2140 | sarg[maxarg+1] = Nullstr; |
2141 | *retary = sarg; /* up to them to free it */ |
2142 | } |
2143 | else |
2144 | safefree(sarg); |
2145 | } |
2146 | return str; |
2147 | |
2148 | nullarray: |
2149 | maxarg = 0; |
2150 | #ifdef DEBUGGING |
2151 | dlevel--; |
2152 | if (debug & 8) |
2153 | deb("%s RETURNS ()\n",opname[optype],value); |
2154 | #endif |
2155 | goto freeargs; |
2156 | } |