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