perl 3.0 patch #3 Patch #2 continued
[p5sagit/p5-mst-13.2.git] / eval.c
1 /* $Header: eval.c,v 3.0.1.1 89/11/11 04:31:51 lwall Locked $
2  *
3  *    Copyright (c) 1989, Larry Wall
4  *
5  *    You may distribute under the terms of the GNU General Public License
6  *    as specified in the README file that comes with the perl 3.0 kit.
7  *
8  * $Log:        eval.c,v $
9  * Revision 3.0.1.1  89/11/11  04:31:51  lwall
10  * patch2: mkdir and rmdir needed to quote argument when passed to shell
11  * patch2: mkdir and rmdir now return better error codes
12  * patch2: fileno, seekdir, rewinddir and closedir now disallow defaults
13  * 
14  * Revision 3.0  89/10/18  15:17:04  lwall
15  * 3.0 baseline
16  * 
17  */
18
19 #include "EXTERN.h"
20 #include "perl.h"
21
22 #include <signal.h>
23 #include <errno.h>
24
25 #ifdef I_VFORK
26 #   include <vfork.h>
27 #endif
28
29 extern int errno;
30
31 #ifdef VOIDSIG
32 static void (*ihand)();
33 static void (*qhand)();
34 #else
35 static int (*ihand)();
36 static int (*qhand)();
37 #endif
38
39 ARG *debarg;
40 STR str_args;
41 static STAB *stab2;
42 static STIO *stio;
43 static struct lstring *lstr;
44 static char old_record_separator;
45
46 double sin(), cos(), atan2(), pow();
47
48 char *getlogin();
49
50 extern int sys_nerr;
51 extern char *sys_errlist[];
52
53 int
54 eval(arg,gimme,sp)
55 register ARG *arg;
56 int gimme;
57 register int sp;
58 {
59     register STR *str;
60     register int anum;
61     register int optype;
62     register STR **st;
63     int maxarg;
64     double value;
65     register char *tmps;
66     char *tmps2;
67     int argflags;
68     int argtype;
69     union argptr argptr;
70     int arglast[8];     /* highest sp for arg--valid only for non-O_LIST args */
71     unsigned long tmplong;
72     long when;
73     FILE *fp;
74     STR *tmpstr;
75     FCMD *form;
76     STAB *stab;
77     ARRAY *ary;
78     bool assigning = FALSE;
79     double exp(), log(), sqrt(), modf();
80     char *crypt(), *getenv();
81     extern void grow_dlevel();
82
83     if (!arg)
84         goto say_undef;
85     optype = arg->arg_type;
86     maxarg = arg->arg_len;
87     arglast[0] = sp;
88     str = arg->arg_ptr.arg_str;
89     if (sp + maxarg > stack->ary_max)
90         astore(stack, sp + maxarg, Nullstr);
91     st = stack->ary_array;
92
93 #ifdef DEBUGGING
94     if (debug) {
95         if (debug & 8) {
96             deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
97         }
98         debname[dlevel] = opname[optype][0];
99         debdelim[dlevel] = ':';
100         if (++dlevel >= dlmax)
101             grow_dlevel();
102     }
103 #endif
104
105 #include "evalargs.xc"
106
107     st += arglast[0];
108     switch (optype) {
109     case O_RCAT:
110         STABSET(str);
111         break;
112     case O_ITEM:
113         if (gimme == G_ARRAY)
114             goto array_return;
115         STR_SSET(str,st[1]);
116         STABSET(str);
117         break;
118     case O_ITEM2:
119         if (gimme == G_ARRAY)
120             goto array_return;
121         --anum;
122         STR_SSET(str,st[arglast[anum]-arglast[0]]);
123         STABSET(str);
124         break;
125     case O_ITEM3:
126         if (gimme == G_ARRAY)
127         goto array_return;
128         --anum;
129         STR_SSET(str,st[arglast[anum]-arglast[0]]);
130         STABSET(str);
131         break;
132     case O_CONCAT:
133         STR_SSET(str,st[1]);
134         str_scat(str,st[2]);
135         STABSET(str);
136         break;
137     case O_REPEAT:
138         STR_SSET(str,st[1]);
139         anum = (int)str_gnum(st[2]);
140         if (anum >= 1) {
141             tmpstr = Str_new(50,0);
142             str_sset(tmpstr,str);
143             while (--anum > 0)
144                 str_scat(str,tmpstr);
145         }
146         else
147             str_sset(str,&str_no);
148         STABSET(str);
149         break;
150     case O_MATCH:
151         sp = do_match(str,arg,
152           gimme,arglast);
153         if (gimme == G_ARRAY)
154             goto array_return;
155         STABSET(str);
156         break;
157     case O_NMATCH:
158         sp = do_match(str,arg,
159           gimme,arglast);
160         if (gimme == G_ARRAY)
161             goto array_return;
162         str_sset(str, str_true(str) ? &str_no : &str_yes);
163         STABSET(str);
164         break;
165     case O_SUBST:
166         sp = do_subst(str,arg,arglast[0]);
167         goto array_return;
168     case O_NSUBST:
169         sp = do_subst(str,arg,arglast[0]);
170         str = arg->arg_ptr.arg_str;
171         str_set(str, str_true(str) ? No : Yes);
172         goto array_return;
173     case O_ASSIGN:
174         if (arg[1].arg_flags & AF_ARYOK) {
175             if (arg->arg_len == 1) {
176                 arg->arg_type = O_LOCAL;
177                 goto local;
178             }
179             else {
180                 arg->arg_type = O_AASSIGN;
181                 goto aassign;
182             }
183         }
184         else {
185             arg->arg_type = O_SASSIGN;
186             goto sassign;
187         }
188     case O_LOCAL:
189       local:
190         arglast[2] = arglast[1];        /* push a null array */
191         /* FALL THROUGH */
192     case O_AASSIGN:
193       aassign:
194         sp = do_assign(arg,
195           gimme,arglast);
196         goto array_return;
197     case O_SASSIGN:
198       sassign:
199         STR_SSET(str, st[2]);
200         STABSET(str);
201         break;
202     case O_CHOP:
203         st -= arglast[0];
204         str = arg->arg_ptr.arg_str;
205         for (sp = arglast[0] + 1; sp <= arglast[1]; sp++)
206             do_chop(str,st[sp]);
207         st += arglast[0];
208         break;
209     case O_DEFINED:
210         if (arg[1].arg_type & A_DONT) {
211             sp = do_defined(str,arg,
212                   gimme,arglast);
213             goto array_return;
214         }
215         else if (str->str_pok || str->str_nok)
216             goto say_yes;
217         goto say_no;
218     case O_UNDEF:
219         if (arg[1].arg_type & A_DONT) {
220             sp = do_undef(str,arg,
221               gimme,arglast);
222             goto array_return;
223         }
224         else if (str != stab_val(defstab)) {
225             str->str_pok = str->str_nok = 0;
226             STABSET(str);
227         }
228         goto say_undef;
229     case O_STUDY:
230         sp = do_study(str,arg,
231           gimme,arglast);
232         goto array_return;
233     case O_POW:
234         value = str_gnum(st[1]);
235         value = pow(value,str_gnum(st[2]));
236         goto donumset;
237     case O_MULTIPLY:
238         value = str_gnum(st[1]);
239         value *= str_gnum(st[2]);
240         goto donumset;
241     case O_DIVIDE:
242         if ((value = str_gnum(st[2])) == 0.0)
243             fatal("Illegal division by zero");
244         value = str_gnum(st[1]) / value;
245         goto donumset;
246     case O_MODULO:
247         tmplong = (long) str_gnum(st[2]);
248         if (tmplong == 0L)
249             fatal("Illegal modulus zero");
250         when = (long)str_gnum(st[1]);
251 #ifndef lint
252         if (when >= 0)
253             value = (double)(when % tmplong);
254         else
255             value = (double)(tmplong - (-when % tmplong));
256 #endif
257         goto donumset;
258     case O_ADD:
259         value = str_gnum(st[1]);
260         value += str_gnum(st[2]);
261         goto donumset;
262     case O_SUBTRACT:
263         value = str_gnum(st[1]);
264         value -= str_gnum(st[2]);
265         goto donumset;
266     case O_LEFT_SHIFT:
267         value = str_gnum(st[1]);
268         anum = (int)str_gnum(st[2]);
269 #ifndef lint
270         value = (double)(((long)value) << anum);
271 #endif
272         goto donumset;
273     case O_RIGHT_SHIFT:
274         value = str_gnum(st[1]);
275         anum = (int)str_gnum(st[2]);
276 #ifndef lint
277         value = (double)(((long)value) >> anum);
278 #endif
279         goto donumset;
280     case O_LT:
281         value = str_gnum(st[1]);
282         value = (value < str_gnum(st[2])) ? 1.0 : 0.0;
283         goto donumset;
284     case O_GT:
285         value = str_gnum(st[1]);
286         value = (value > str_gnum(st[2])) ? 1.0 : 0.0;
287         goto donumset;
288     case O_LE:
289         value = str_gnum(st[1]);
290         value = (value <= str_gnum(st[2])) ? 1.0 : 0.0;
291         goto donumset;
292     case O_GE:
293         value = str_gnum(st[1]);
294         value = (value >= str_gnum(st[2])) ? 1.0 : 0.0;
295         goto donumset;
296     case O_EQ:
297         if (dowarn) {
298             if ((!st[1]->str_nok && !looks_like_number(st[1])) ||
299                 (!st[2]->str_nok && !looks_like_number(st[2])) )
300                 warn("Possible use of == on string value");
301         }
302         value = str_gnum(st[1]);
303         value = (value == str_gnum(st[2])) ? 1.0 : 0.0;
304         goto donumset;
305     case O_NE:
306         value = str_gnum(st[1]);
307         value = (value != str_gnum(st[2])) ? 1.0 : 0.0;
308         goto donumset;
309     case O_BIT_AND:
310         if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
311             value = str_gnum(st[1]);
312 #ifndef lint
313             value = (double)(((long)value) & (long)str_gnum(st[2]));
314 #endif
315             goto donumset;
316         }
317         else
318             do_vop(optype,str,st[1],st[2]);
319         break;
320     case O_XOR:
321         if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
322             value = str_gnum(st[1]);
323 #ifndef lint
324             value = (double)(((long)value) ^ (long)str_gnum(st[2]));
325 #endif
326             goto donumset;
327         }
328         else
329             do_vop(optype,str,st[1],st[2]);
330         break;
331     case O_BIT_OR:
332         if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
333             value = str_gnum(st[1]);
334 #ifndef lint
335             value = (double)(((long)value) | (long)str_gnum(st[2]));
336 #endif
337             goto donumset;
338         }
339         else
340             do_vop(optype,str,st[1],st[2]);
341         break;
342 /* use register in evaluating str_true() */
343     case O_AND:
344         if (str_true(st[1])) {
345             anum = 2;
346             optype = O_ITEM2;
347             argflags = arg[anum].arg_flags;
348             if (gimme == G_ARRAY)
349                 argflags |= AF_ARYOK;
350             argtype = arg[anum].arg_type & A_MASK;
351             argptr = arg[anum].arg_ptr;
352             maxarg = anum = 1;
353             sp = arglast[0];
354             st -= sp;
355             goto re_eval;
356         }
357         else {
358             if (assigning) {
359                 str_sset(str, st[1]);
360                 STABSET(str);
361             }
362             else
363                 str = st[1];
364             break;
365         }
366     case O_OR:
367         if (str_true(st[1])) {
368             if (assigning) {
369                 str_sset(str, st[1]);
370                 STABSET(str);
371             }
372             else
373                 str = st[1];
374             break;
375         }
376         else {
377             anum = 2;
378             optype = O_ITEM2;
379             argflags = arg[anum].arg_flags;
380             if (gimme == G_ARRAY)
381                 argflags |= AF_ARYOK;
382             argtype = arg[anum].arg_type & A_MASK;
383             argptr = arg[anum].arg_ptr;
384             maxarg = anum = 1;
385             sp = arglast[0];
386             st -= sp;
387             goto re_eval;
388         }
389     case O_COND_EXPR:
390         anum = (str_true(st[1]) ? 2 : 3);
391         optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
392         argflags = arg[anum].arg_flags;
393         if (gimme == G_ARRAY)
394             argflags |= AF_ARYOK;
395         argtype = arg[anum].arg_type & A_MASK;
396         argptr = arg[anum].arg_ptr;
397         maxarg = anum = 1;
398         sp = arglast[0];
399         st -= sp;
400         goto re_eval;
401     case O_COMMA:
402         if (gimme == G_ARRAY)
403             goto array_return;
404         str = st[2];
405         break;
406     case O_NEGATE:
407         value = -str_gnum(st[1]);
408         goto donumset;
409     case O_NOT:
410         value = (double) !str_true(st[1]);
411         goto donumset;
412     case O_COMPLEMENT:
413 #ifndef lint
414         value = (double) ~(long)str_gnum(st[1]);
415 #endif
416         goto donumset;
417     case O_SELECT:
418         tmps = stab_name(defoutstab);
419         if (maxarg > 0) {
420             if ((arg[1].arg_type & A_MASK) == A_WORD)
421                 defoutstab = arg[1].arg_ptr.arg_stab;
422             else
423                 defoutstab = stabent(str_get(st[1]),TRUE);
424             if (!stab_io(defoutstab))
425                 stab_io(defoutstab) = stio_new();
426             curoutstab = defoutstab;
427         }
428         str_set(str, tmps);
429         STABSET(str);
430         break;
431     case O_WRITE:
432         if (maxarg == 0)
433             stab = defoutstab;
434         else if ((arg[1].arg_type & A_MASK) == A_WORD) {
435             if (!(stab = arg[1].arg_ptr.arg_stab))
436                 stab = defoutstab;
437         }
438         else
439             stab = stabent(str_get(st[1]),TRUE);
440         if (!stab_io(stab)) {
441             str_set(str, No);
442             STABSET(str);
443             break;
444         }
445         curoutstab = stab;
446         fp = stab_io(stab)->ofp;
447         debarg = arg;
448         if (stab_io(stab)->fmt_stab)
449             form = stab_form(stab_io(stab)->fmt_stab);
450         else
451             form = stab_form(stab);
452         if (!form || !fp) {
453             if (dowarn) {
454                 if (form)
455                     warn("No format for filehandle");
456                 else {
457                     if (stab_io(stab)->ifp)
458                         warn("Filehandle only opened for input");
459                     else
460                         warn("Write on closed filehandle");
461                 }
462             }
463             str_set(str, No);
464             STABSET(str);
465             break;
466         }
467         format(&outrec,form,sp);
468         do_write(&outrec,stab_io(stab),sp);
469         if (stab_io(stab)->flags & IOF_FLUSH)
470             (void)fflush(fp);
471         str_set(str, Yes);
472         STABSET(str);
473         break;
474     case O_DBMOPEN:
475 #ifdef SOME_DBM
476         if ((arg[1].arg_type & A_MASK) == A_WORD)
477             stab = arg[1].arg_ptr.arg_stab;
478         else
479             stab = stabent(str_get(st[1]),TRUE);
480         anum = (int)str_gnum(st[3]);
481         value = (double)hdbmopen(stab_hash(stab),str_get(st[2]),anum);
482         goto donumset;
483 #else
484         fatal("No dbm or ndbm on this machine");
485 #endif
486     case O_DBMCLOSE:
487 #ifdef SOME_DBM
488         if ((arg[1].arg_type & A_MASK) == A_WORD)
489             stab = arg[1].arg_ptr.arg_stab;
490         else
491             stab = stabent(str_get(st[1]),TRUE);
492         hdbmclose(stab_hash(stab));
493         goto say_yes;
494 #else
495         fatal("No dbm or ndbm on this machine");
496 #endif
497     case O_OPEN:
498         if ((arg[1].arg_type & A_MASK) == A_WORD)
499             stab = arg[1].arg_ptr.arg_stab;
500         else
501             stab = stabent(str_get(st[1]),TRUE);
502         if (do_open(stab,str_get(st[2]))) {
503             value = (double)forkprocess;
504             stab_io(stab)->lines = 0;
505             goto donumset;
506         }
507         else
508             goto say_undef;
509         break;
510     case O_TRANS:
511         value = (double) do_trans(str,arg);
512         str = arg->arg_ptr.arg_str;
513         goto donumset;
514     case O_NTRANS:
515         str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No);
516         str = arg->arg_ptr.arg_str;
517         break;
518     case O_CLOSE:
519         if (maxarg == 0)
520             stab = defoutstab;
521         else if ((arg[1].arg_type & A_MASK) == A_WORD)
522             stab = arg[1].arg_ptr.arg_stab;
523         else
524             stab = stabent(str_get(st[1]),TRUE);
525         str_set(str, do_close(stab,TRUE) ? Yes : No );
526         STABSET(str);
527         break;
528     case O_EACH:
529         sp = do_each(str,stab_hash(arg[1].arg_ptr.arg_stab),
530           gimme,arglast);
531         goto array_return;
532     case O_VALUES:
533     case O_KEYS:
534         sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
535           gimme,arglast);
536         goto array_return;
537     case O_LARRAY:
538         str->str_nok = str->str_pok = 0;
539         str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
540         str->str_state = SS_ARY;
541         break;
542     case O_ARRAY:
543         ary = stab_array(arg[1].arg_ptr.arg_stab);
544         maxarg = ary->ary_fill + 1;
545         if (gimme == G_ARRAY) { /* array wanted */
546             sp = arglast[0];
547             st -= sp;
548             if (maxarg > 0 && sp + maxarg > stack->ary_max) {
549                 astore(stack,sp + maxarg, Nullstr);
550                 st = stack->ary_array;
551             }
552             Copy(ary->ary_array, &st[sp+1], maxarg, STR*);
553             sp += maxarg;
554             goto array_return;
555         }
556         else
557             str = afetch(ary,maxarg - 1,FALSE);
558         break;
559     case O_AELEM:
560         str = afetch(stab_array(arg[1].arg_ptr.arg_stab),
561             ((int)str_gnum(st[2])) - arybase,FALSE);
562         if (!str)
563             goto say_undef;
564         break;
565     case O_DELETE:
566         tmpstab = arg[1].arg_ptr.arg_stab;
567         tmps = str_get(st[2]);
568         str = hdelete(stab_hash(tmpstab),tmps,st[2]->str_cur);
569         if (tmpstab == envstab)
570             setenv(tmps,Nullch);
571         if (!str)
572             goto say_undef;
573         break;
574     case O_LHASH:
575         str->str_nok = str->str_pok = 0;
576         str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
577         str->str_state = SS_HASH;
578         break;
579     case O_HASH:
580         if (gimme == G_ARRAY) { /* array wanted */
581             sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
582                 gimme,arglast);
583             goto array_return;
584         }
585         else {
586             tmpstab = arg[1].arg_ptr.arg_stab;
587             sprintf(buf,"%d/%d",stab_hash(tmpstab)->tbl_fill,
588                 stab_hash(tmpstab)->tbl_max+1);
589             str_set(str,buf);
590         }
591         break;
592     case O_HELEM:
593         tmpstab = arg[1].arg_ptr.arg_stab;
594         tmps = str_get(st[2]);
595         str = hfetch(stab_hash(tmpstab),tmps,st[2]->str_cur,FALSE);
596         if (!str)
597             goto say_undef;
598         break;
599     case O_LAELEM:
600         anum = ((int)str_gnum(st[2])) - arybase;
601         str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,TRUE);
602         if (!str)
603             fatal("Assignment to non-creatable value, subscript %d",anum);
604         break;
605     case O_LHELEM:
606         tmpstab = arg[1].arg_ptr.arg_stab;
607         tmps = str_get(st[2]);
608         anum = st[2]->str_cur;
609         str = hfetch(stab_hash(tmpstab),tmps,anum,TRUE);
610         if (!str)
611             fatal("Assignment to non-creatable value, subscript \"%s\"",tmps);
612         if (tmpstab == envstab)         /* heavy wizardry going on here */
613             str_magic(str, tmpstab, 'E', tmps, anum);   /* str is now magic */
614                                         /* he threw the brick up into the air */
615         else if (tmpstab == sigstab)
616             str_magic(str, tmpstab, 'S', tmps, anum);
617 #ifdef SOME_DBM
618         else if (stab_hash(tmpstab)->tbl_dbm)
619             str_magic(str, tmpstab, 'D', tmps, anum);
620 #endif
621         break;
622     case O_ASLICE:
623         anum = TRUE;
624         argtype = FALSE;
625         goto do_slice_already;
626     case O_HSLICE:
627         anum = FALSE;
628         argtype = FALSE;
629         goto do_slice_already;
630     case O_LASLICE:
631         anum = TRUE;
632         argtype = TRUE;
633         goto do_slice_already;
634     case O_LHSLICE:
635         anum = FALSE;
636         argtype = TRUE;
637       do_slice_already:
638         sp = do_slice(arg[1].arg_ptr.arg_stab,anum,argtype,
639             gimme,arglast);
640         goto array_return;
641     case O_PUSH:
642         if (arglast[2] - arglast[1] != 1)
643             str = do_push(stab_array(arg[1].arg_ptr.arg_stab),arglast);
644         else {
645             str = Str_new(51,0);                /* must copy the STR */
646             str_sset(str,st[2]);
647             (void)apush(stab_array(arg[1].arg_ptr.arg_stab),str);
648         }
649         break;
650     case O_POP:
651         str = apop(ary = stab_array(arg[1].arg_ptr.arg_stab));
652         goto staticalization;
653     case O_SHIFT:
654         str = ashift(ary = stab_array(arg[1].arg_ptr.arg_stab));
655       staticalization:
656         if (!str)
657             goto say_undef;
658         if (ary->ary_flags & ARF_REAL)
659             (void)str_2static(str);
660         break;
661     case O_UNPACK:
662         sp = do_unpack(str,gimme,arglast);
663         goto array_return;
664     case O_SPLIT:
665         value = str_gnum(st[3]);
666         sp = do_split(str, arg[2].arg_ptr.arg_spat, (int)value,
667           gimme,arglast);
668         goto array_return;
669     case O_LENGTH:
670         if (maxarg < 1)
671             value = (double)str_len(stab_val(defstab));
672         else
673             value = (double)str_len(st[1]);
674         goto donumset;
675     case O_SPRINTF:
676         do_sprintf(str, sp-arglast[0], st+1);
677         break;
678     case O_SUBSTR:
679         anum = ((int)str_gnum(st[2])) - arybase;        /* anum=where to start*/
680         tmps = str_get(st[1]);          /* force conversion to string */
681         if (argtype = (str == st[1]))
682             str = arg->arg_ptr.arg_str;
683         if (anum < 0)
684             anum += st[1]->str_cur + arybase;
685         if (anum < 0 || anum > st[1]->str_cur)
686             str_nset(str,"",0);
687         else {
688             optype = (int)str_gnum(st[3]);
689             if (optype < 0)
690                 optype = 0;
691             tmps += anum;
692             anum = st[1]->str_cur - anum;       /* anum=how many bytes left*/
693             if (anum > optype)
694                 anum = optype;
695             str_nset(str, tmps, anum);
696             if (argtype) {                      /* it's an lvalue! */
697                 lstr = (struct lstring*)str;
698                 str->str_magic = st[1];
699                 st[1]->str_rare = 's';
700                 lstr->lstr_offset = tmps - str_get(st[1]); 
701                 lstr->lstr_len = anum; 
702             }
703         }
704         break;
705     case O_PACK:
706         (void)do_pack(str,arglast);
707         break;
708     case O_GREP:
709         sp = do_grep(arg,str,gimme,arglast);
710         goto array_return;
711     case O_JOIN:
712         do_join(str,arglast);
713         break;
714     case O_SLT:
715         tmps = str_get(st[1]);
716         value = (double) (str_cmp(st[1],st[2]) < 0);
717         goto donumset;
718     case O_SGT:
719         tmps = str_get(st[1]);
720         value = (double) (str_cmp(st[1],st[2]) > 0);
721         goto donumset;
722     case O_SLE:
723         tmps = str_get(st[1]);
724         value = (double) (str_cmp(st[1],st[2]) <= 0);
725         goto donumset;
726     case O_SGE:
727         tmps = str_get(st[1]);
728         value = (double) (str_cmp(st[1],st[2]) >= 0);
729         goto donumset;
730     case O_SEQ:
731         tmps = str_get(st[1]);
732         value = (double) str_eq(st[1],st[2]);
733         goto donumset;
734     case O_SNE:
735         tmps = str_get(st[1]);
736         value = (double) !str_eq(st[1],st[2]);
737         goto donumset;
738     case O_SUBR:
739         sp = do_subr(arg,gimme,arglast);
740         st = stack->ary_array + arglast[0];             /* maybe realloced */
741         goto array_return;
742     case O_DBSUBR:
743         sp = do_dbsubr(arg,gimme,arglast);
744         st = stack->ary_array + arglast[0];             /* maybe realloced */
745         goto array_return;
746     case O_SORT:
747         if ((arg[1].arg_type & A_MASK) == A_WORD)
748             stab = arg[1].arg_ptr.arg_stab;
749         else
750             stab = stabent(str_get(st[1]),TRUE);
751         if (!stab)
752             stab = defoutstab;
753         sp = do_sort(str,stab,
754           gimme,arglast);
755         goto array_return;
756     case O_REVERSE:
757         sp = do_reverse(str,
758           gimme,arglast);
759         goto array_return;
760     case O_WARN:
761         if (arglast[2] - arglast[1] != 1) {
762             do_join(str,arglast);
763             tmps = str_get(st[1]);
764         }
765         else {
766             str = st[2];
767             tmps = str_get(st[2]);
768         }
769         if (!tmps || !*tmps)
770             tmps = "Warning: something's wrong";
771         warn("%s",tmps);
772         goto say_yes;
773     case O_DIE:
774         if (arglast[2] - arglast[1] != 1) {
775             do_join(str,arglast);
776             tmps = str_get(st[1]);
777         }
778         else {
779             str = st[2];
780             tmps = str_get(st[2]);
781         }
782         if (!tmps || !*tmps)
783             exit(1);
784         fatal("%s",tmps);
785         goto say_zero;
786     case O_PRTF:
787     case O_PRINT:
788         if ((arg[1].arg_type & A_MASK) == A_WORD)
789             stab = arg[1].arg_ptr.arg_stab;
790         else
791             stab = stabent(str_get(st[1]),TRUE);
792         if (!stab)
793             stab = defoutstab;
794         if (!stab_io(stab)) {
795             if (dowarn)
796                 warn("Filehandle never opened");
797             goto say_zero;
798         }
799         if (!(fp = stab_io(stab)->ofp)) {
800             if (dowarn)  {
801                 if (stab_io(stab)->ifp)
802                     warn("Filehandle opened only for input");
803                 else
804                     warn("Print on closed filehandle");
805             }
806             goto say_zero;
807         }
808         else {
809             if (optype == O_PRTF || arglast[2] - arglast[1] != 1)
810                 value = (double)do_aprint(arg,fp,arglast);
811             else {
812                 value = (double)do_print(st[2],fp);
813                 if (orslen && optype == O_PRINT)
814                     if (fwrite(ors, 1, orslen, fp) == 0)
815                         goto say_zero;
816             }
817             if (stab_io(stab)->flags & IOF_FLUSH)
818                 if (fflush(fp) == EOF)
819                     goto say_zero;
820         }
821         goto donumset;
822     case O_CHDIR:
823         if (maxarg < 1)
824             tmps = str_get(stab_val(defstab));
825         else
826             tmps = str_get(st[1]);
827         if (!tmps || !*tmps) {
828             tmpstr = hfetch(stab_hash(envstab),"HOME",4,FALSE);
829             if (tmpstr)
830                 tmps = str_get(tmpstr);
831         }
832         if (!tmps || !*tmps) {
833             tmpstr = hfetch(stab_hash(envstab),"LOGDIR",6,FALSE);
834             if (tmpstr)
835                 tmps = str_get(tmpstr);
836         }
837 #ifdef TAINT
838         taintproper("Insecure dependency in chdir");
839 #endif
840         value = (double)(chdir(tmps) >= 0);
841         goto donumset;
842     case O_EXIT:
843         if (maxarg < 1)
844             anum = 0;
845         else
846             anum = (int)str_gnum(st[1]);
847         exit(anum);
848         goto say_zero;
849     case O_RESET:
850         if (maxarg < 1)
851             tmps = "";
852         else
853             tmps = str_get(st[1]);
854         str_reset(tmps,arg[2].arg_ptr.arg_hash);
855         value = 1.0;
856         goto donumset;
857     case O_LIST:
858         if (gimme == G_ARRAY)
859             goto array_return;
860         if (maxarg > 0)
861             str = st[sp - arglast[0]];  /* unwanted list, return last item */
862         else
863             str = &str_undef;
864         break;
865     case O_EOF:
866         if (maxarg <= 0)
867             stab = last_in_stab;
868         else if ((arg[1].arg_type & A_MASK) == A_WORD)
869             stab = arg[1].arg_ptr.arg_stab;
870         else
871             stab = stabent(str_get(st[1]),TRUE);
872         str_set(str, do_eof(stab) ? Yes : No);
873         STABSET(str);
874         break;
875     case O_GETC:
876         if (maxarg <= 0)
877             stab = stdinstab;
878         else if ((arg[1].arg_type & A_MASK) == A_WORD)
879             stab = arg[1].arg_ptr.arg_stab;
880         else
881             stab = stabent(str_get(st[1]),TRUE);
882         if (do_eof(stab))       /* make sure we have fp with something */
883             str_set(str, No);
884         else {
885 #ifdef TAINT
886             tainted = 1;
887 #endif
888             str_set(str," ");
889             *str->str_ptr = getc(stab_io(stab)->ifp); /* should never be EOF */
890         }
891         STABSET(str);
892         break;
893     case O_TELL:
894         if (maxarg <= 0)
895             stab = last_in_stab;
896         else if ((arg[1].arg_type & A_MASK) == A_WORD)
897             stab = arg[1].arg_ptr.arg_stab;
898         else
899             stab = stabent(str_get(st[1]),TRUE);
900 #ifndef lint
901         value = (double)do_tell(stab);
902 #else
903         (void)do_tell(stab);
904 #endif
905         goto donumset;
906     case O_RECV:
907     case O_READ:
908         if ((arg[1].arg_type & A_MASK) == A_WORD)
909             stab = arg[1].arg_ptr.arg_stab;
910         else
911             stab = stabent(str_get(st[1]),TRUE);
912         tmps = str_get(st[2]);
913         anum = (int)str_gnum(st[3]);
914         STR_GROW(st[2], anum+1), (tmps = str_get(st[2]));       /* sneaky */
915         errno = 0;
916         if (!stab_io(stab) || !stab_io(stab)->ifp)
917             goto say_zero;
918 #ifdef SOCKET
919         else if (optype == O_RECV) {
920             argtype = sizeof buf;
921             optype = (int)str_gnum(st[4]);
922             anum = recvfrom(fileno(stab_io(stab)->ifp), tmps, anum, optype,
923                 buf, &argtype);
924             if (anum >= 0) {
925                 st[2]->str_cur = anum;
926                 st[2]->str_ptr[anum] = '\0';
927                 str_nset(str,buf,argtype);
928             }
929             else
930                 str_sset(str,&str_undef);
931             break;
932         }
933         else if (stab_io(stab)->type == 's') {
934             argtype = sizeof buf;
935             anum = recvfrom(fileno(stab_io(stab)->ifp), tmps, anum, 0,
936                 buf, &argtype);
937         }
938 #else
939         else if (optype == O_RECV)
940             goto badsock;
941 #endif
942         else
943             anum = fread(tmps, 1, anum, stab_io(stab)->ifp);
944         if (anum < 0)
945             goto say_undef;
946         st[2]->str_cur = anum;
947         st[2]->str_ptr[anum] = '\0';
948         value = (double)anum;
949         goto donumset;
950     case O_SEND:
951 #ifdef SOCKET
952         if ((arg[1].arg_type & A_MASK) == A_WORD)
953             stab = arg[1].arg_ptr.arg_stab;
954         else
955             stab = stabent(str_get(st[1]),TRUE);
956         tmps = str_get(st[2]);
957         anum = (int)str_gnum(st[3]);
958         optype = sp - arglast[0];
959         errno = 0;
960         if (optype > 4)
961             warn("Too many args on send");
962         if (optype >= 4) {
963             tmps2 = str_get(st[4]);
964             anum = sendto(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur,
965               anum, tmps2, st[4]->str_cur);
966         }
967         else
968             anum = send(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur, anum);
969         if (anum < 0)
970             goto say_undef;
971         value = (double)anum;
972         goto donumset;
973 #else
974         goto badsock;
975 #endif
976     case O_SEEK:
977         if ((arg[1].arg_type & A_MASK) == A_WORD)
978             stab = arg[1].arg_ptr.arg_stab;
979         else
980             stab = stabent(str_get(st[1]),TRUE);
981         value = str_gnum(st[2]);
982         str_set(str, do_seek(stab,
983           (long)value, (int)str_gnum(st[3]) ) ? Yes : No);
984         STABSET(str);
985         break;
986     case O_RETURN:
987         tmps = "SUB";           /* just fake up a "last SUB" */
988         optype = O_LAST;
989         if (gimme == G_ARRAY) {
990             lastretstr = Nullstr;
991             lastspbase = arglast[1];
992             lastsize = arglast[2] - arglast[1];
993         }
994         else
995             lastretstr = str_static(st[arglast[2] - arglast[0]]);
996         goto dopop;
997     case O_REDO:
998     case O_NEXT:
999     case O_LAST:
1000         if (maxarg > 0) {
1001             tmps = str_get(arg[1].arg_ptr.arg_str);
1002           dopop:
1003             while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1004               strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1005 #ifdef DEBUGGING
1006                 if (debug & 4) {
1007                     deb("(Skipping label #%d %s)\n",loop_ptr,
1008                         loop_stack[loop_ptr].loop_label);
1009                 }
1010 #endif
1011                 loop_ptr--;
1012             }
1013 #ifdef DEBUGGING
1014             if (debug & 4) {
1015                 deb("(Found label #%d %s)\n",loop_ptr,
1016                     loop_stack[loop_ptr].loop_label);
1017             }
1018 #endif
1019         }
1020         if (loop_ptr < 0)
1021             fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>");
1022         if (!lastretstr && optype == O_LAST && lastsize) {
1023             st -= arglast[0];
1024             st += lastspbase + 1;
1025             optype = loop_stack[loop_ptr].loop_sp - lastspbase; /* negative */
1026             if (optype) {
1027                 for (anum = lastsize; anum > 0; anum--,st++)
1028                     st[optype] = str_static(st[0]);
1029             }
1030             longjmp(loop_stack[loop_ptr].loop_env, O_LAST);
1031         }
1032         longjmp(loop_stack[loop_ptr].loop_env, optype);
1033     case O_DUMP:
1034     case O_GOTO:/* shudder */
1035         goto_targ = str_get(arg[1].arg_ptr.arg_str);
1036         if (!*goto_targ)
1037             goto_targ = Nullch;         /* just restart from top */
1038         if (optype == O_DUMP) {
1039             do_undump = 1;
1040             abort();
1041         }
1042         longjmp(top_env, 1);
1043     case O_INDEX:
1044         tmps = str_get(st[1]);
1045 #ifndef lint
1046         if (!(tmps2 = fbminstr((unsigned char*)tmps,
1047           (unsigned char*)tmps + st[1]->str_cur, st[2])))
1048 #else
1049         if (tmps2 = fbminstr(Null(unsigned char*),Null(unsigned char*),Nullstr))
1050 #endif
1051             value = (double)(-1 + arybase);
1052         else
1053             value = (double)(tmps2 - tmps + arybase);
1054         goto donumset;
1055     case O_RINDEX:
1056         tmps = str_get(st[1]);
1057         tmps2 = str_get(st[2]);
1058 #ifndef lint
1059         if (!(tmps2 = rninstr(tmps,  tmps  + st[1]->str_cur,
1060                               tmps2, tmps2 + st[2]->str_cur)))
1061 #else
1062         if (tmps2 = rninstr(Nullch,Nullch,Nullch,Nullch))
1063 #endif
1064             value = (double)(-1 + arybase);
1065         else
1066             value = (double)(tmps2 - tmps + arybase);
1067         goto donumset;
1068     case O_TIME:
1069 #ifndef lint
1070         value = (double) time(Null(long*));
1071 #endif
1072         goto donumset;
1073     case O_TMS:
1074         sp = do_tms(str,gimme,arglast);
1075         goto array_return;
1076     case O_LOCALTIME:
1077         if (maxarg < 1)
1078             (void)time(&when);
1079         else
1080             when = (long)str_gnum(st[1]);
1081         sp = do_time(str,localtime(&when),
1082           gimme,arglast);
1083         goto array_return;
1084     case O_GMTIME:
1085         if (maxarg < 1)
1086             (void)time(&when);
1087         else
1088             when = (long)str_gnum(st[1]);
1089         sp = do_time(str,gmtime(&when),
1090           gimme,arglast);
1091         goto array_return;
1092     case O_LSTAT:
1093     case O_STAT:
1094         sp = do_stat(str,arg,
1095           gimme,arglast);
1096         goto array_return;
1097     case O_CRYPT:
1098 #ifdef CRYPT
1099         tmps = str_get(st[1]);
1100 #ifdef FCRYPT
1101         str_set(str,fcrypt(tmps,str_get(st[2])));
1102 #else
1103         str_set(str,crypt(tmps,str_get(st[2])));
1104 #endif
1105 #else
1106         fatal(
1107           "The crypt() function is unimplemented due to excessive paranoia.");
1108 #endif
1109         break;
1110     case O_ATAN2:
1111         value = str_gnum(st[1]);
1112         value = atan2(value,str_gnum(st[2]));
1113         goto donumset;
1114     case O_SIN:
1115         if (maxarg < 1)
1116             value = str_gnum(stab_val(defstab));
1117         else
1118             value = str_gnum(st[1]);
1119         value = sin(value);
1120         goto donumset;
1121     case O_COS:
1122         if (maxarg < 1)
1123             value = str_gnum(stab_val(defstab));
1124         else
1125             value = str_gnum(st[1]);
1126         value = cos(value);
1127         goto donumset;
1128     case O_RAND:
1129         if (maxarg < 1)
1130             value = 1.0;
1131         else
1132             value = str_gnum(st[1]);
1133         if (value == 0.0)
1134             value = 1.0;
1135 #if RANDBITS == 31
1136         value = rand() * value / 2147483648.0;
1137 #else
1138 #if RANDBITS == 16
1139         value = rand() * value / 65536.0;
1140 #else
1141 #if RANDBITS == 15
1142         value = rand() * value / 32768.0;
1143 #else
1144         value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
1145 #endif
1146 #endif
1147 #endif
1148         goto donumset;
1149     case O_SRAND:
1150         if (maxarg < 1) {
1151             (void)time(&when);
1152             anum = when;
1153         }
1154         else
1155             anum = (int)str_gnum(st[1]);
1156         (void)srand(anum);
1157         goto say_yes;
1158     case O_EXP:
1159         if (maxarg < 1)
1160             value = str_gnum(stab_val(defstab));
1161         else
1162             value = str_gnum(st[1]);
1163         value = exp(value);
1164         goto donumset;
1165     case O_LOG:
1166         if (maxarg < 1)
1167             value = str_gnum(stab_val(defstab));
1168         else
1169             value = str_gnum(st[1]);
1170         value = log(value);
1171         goto donumset;
1172     case O_SQRT:
1173         if (maxarg < 1)
1174             value = str_gnum(stab_val(defstab));
1175         else
1176             value = str_gnum(st[1]);
1177         value = sqrt(value);
1178         goto donumset;
1179     case O_INT:
1180         if (maxarg < 1)
1181             value = str_gnum(stab_val(defstab));
1182         else
1183             value = str_gnum(st[1]);
1184         if (value >= 0.0)
1185             (void)modf(value,&value);
1186         else {
1187             (void)modf(-value,&value);
1188             value = -value;
1189         }
1190         goto donumset;
1191     case O_ORD:
1192         if (maxarg < 1)
1193             tmps = str_get(stab_val(defstab));
1194         else
1195             tmps = str_get(st[1]);
1196 #ifndef I286
1197         value = (double) *tmps;
1198 #else
1199         anum = (int) *tmps;
1200         value = (double) anum;
1201 #endif
1202         goto donumset;
1203     case O_SLEEP:
1204         if (maxarg < 1)
1205             tmps = Nullch;
1206         else
1207             tmps = str_get(st[1]);
1208         (void)time(&when);
1209         if (!tmps || !*tmps)
1210             sleep((32767<<16)+32767);
1211         else
1212             sleep((unsigned int)atoi(tmps));
1213 #ifndef lint
1214         value = (double)when;
1215         (void)time(&when);
1216         value = ((double)when) - value;
1217 #endif
1218         goto donumset;
1219     case O_RANGE:
1220         sp = do_range(gimme,arglast);
1221         goto array_return;
1222     case O_F_OR_R:
1223         if (gimme == G_ARRAY) {         /* it's a range */
1224             /* can we optimize to constant array? */
1225             if ((arg[1].arg_type & A_MASK) == A_SINGLE &&
1226               (arg[2].arg_type & A_MASK) == A_SINGLE) {
1227                 st[2] = arg[2].arg_ptr.arg_str;
1228                 sp = do_range(gimme,arglast);
1229                 st = stack->ary_array;
1230                 maxarg = sp - arglast[0];
1231                 str_free(arg[1].arg_ptr.arg_str);
1232                 str_free(arg[2].arg_ptr.arg_str);
1233                 arg->arg_type = O_ARRAY;
1234                 arg[1].arg_type = A_STAB|A_DONT;
1235                 arg->arg_len = 1;
1236                 stab = arg[1].arg_ptr.arg_stab = aadd(genstab());
1237                 ary = stab_array(stab);
1238                 afill(ary,maxarg - 1);
1239                 st += arglast[0]+1;
1240                 while (maxarg-- > 0)
1241                     ary->ary_array[maxarg] = str_smake(st[maxarg]);
1242                 goto array_return;
1243             }
1244             arg->arg_type = optype = O_RANGE;
1245             maxarg = arg->arg_len = 2;
1246             anum = 2;
1247             arg[anum].arg_flags &= ~AF_ARYOK;
1248             argflags = arg[anum].arg_flags;
1249             argtype = arg[anum].arg_type & A_MASK;
1250             arg[anum].arg_type = argtype;
1251             argptr = arg[anum].arg_ptr;
1252             sp = arglast[0];
1253             st -= sp;
1254             sp++;
1255             goto re_eval;
1256         }
1257         arg->arg_type = O_FLIP;
1258         /* FALL THROUGH */
1259     case O_FLIP:
1260         if ((arg[1].arg_type & A_MASK) == A_SINGLE ?
1261           last_in_stab && (int)str_gnum(st[1]) == stab_io(last_in_stab)->lines
1262           :
1263           str_true(st[1]) ) {
1264             str_numset(str,0.0);
1265             anum = 2;
1266             arg->arg_type = optype = O_FLOP;
1267             arg[2].arg_type &= ~A_DONT;
1268             arg[1].arg_type |= A_DONT;
1269             argflags = arg[2].arg_flags;
1270             argtype = arg[2].arg_type & A_MASK;
1271             argptr = arg[2].arg_ptr;
1272             sp = arglast[0];
1273             st -= sp;
1274             goto re_eval;
1275         }
1276         str_set(str,"");
1277         break;
1278     case O_FLOP:
1279         str_inc(str);
1280         if ((arg[2].arg_type & A_MASK) == A_SINGLE ?
1281           last_in_stab && (int)str_gnum(st[2]) == stab_io(last_in_stab)->lines
1282           :
1283           str_true(st[2]) ) {
1284             arg->arg_type = O_FLIP;
1285             arg[1].arg_type &= ~A_DONT;
1286             arg[2].arg_type |= A_DONT;
1287             str_cat(str,"E0");
1288         }
1289         break;
1290     case O_FORK:
1291         anum = fork();
1292         if (!anum && (tmpstab = stabent("$",allstabs)))
1293             str_numset(STAB_STR(tmpstab),(double)getpid());
1294         value = (double)anum;
1295         goto donumset;
1296     case O_WAIT:
1297 #ifndef lint
1298         ihand = signal(SIGINT, SIG_IGN);
1299         qhand = signal(SIGQUIT, SIG_IGN);
1300         anum = wait(&argflags);
1301         if (anum > 0)
1302             pidgone(anum,argflags);
1303         value = (double)anum;
1304 #else
1305         ihand = qhand = 0;
1306 #endif
1307         (void)signal(SIGINT, ihand);
1308         (void)signal(SIGQUIT, qhand);
1309         statusvalue = (unsigned short)argflags;
1310         goto donumset;
1311     case O_SYSTEM:
1312 #ifdef TAINT
1313         if (arglast[2] - arglast[1] == 1) {
1314             taintenv();
1315             tainted |= st[2]->str_tainted;
1316             taintproper("Insecure dependency in system");
1317         }
1318 #endif
1319         while ((anum = vfork()) == -1) {
1320             if (errno != EAGAIN) {
1321                 value = -1.0;
1322                 goto donumset;
1323             }
1324             sleep(5);
1325         }
1326         if (anum > 0) {
1327 #ifndef lint
1328             ihand = signal(SIGINT, SIG_IGN);
1329             qhand = signal(SIGQUIT, SIG_IGN);
1330             while ((argtype = wait(&argflags)) != anum && argtype >= 0)
1331                 pidgone(argtype,argflags);
1332 #else
1333             ihand = qhand = 0;
1334 #endif
1335             (void)signal(SIGINT, ihand);
1336             (void)signal(SIGQUIT, qhand);
1337             statusvalue = (unsigned short)argflags;
1338             if (argtype == -1)
1339                 value = -1.0;
1340             else {
1341                 value = (double)((unsigned int)argflags & 0xffff);
1342             }
1343             goto donumset;
1344         }
1345         if ((arg[1].arg_type & A_MASK) == A_STAB)
1346             value = (double)do_aexec(st[1],arglast);
1347         else if (arglast[2] - arglast[1] != 1)
1348             value = (double)do_aexec(Nullstr,arglast);
1349         else {
1350             value = (double)do_exec(str_get(str_static(st[2])));
1351         }
1352         _exit(-1);
1353     case O_EXEC:
1354         if ((arg[1].arg_type & A_MASK) == A_STAB)
1355             value = (double)do_aexec(st[1],arglast);
1356         else if (arglast[2] - arglast[1] != 1)
1357             value = (double)do_aexec(Nullstr,arglast);
1358         else {
1359             value = (double)do_exec(str_get(str_static(st[2])));
1360         }
1361         goto donumset;
1362     case O_HEX:
1363         argtype = 4;
1364         goto snarfnum;
1365
1366     case O_OCT:
1367         argtype = 3;
1368
1369       snarfnum:
1370         anum = 0;
1371         if (maxarg < 1)
1372             tmps = str_get(stab_val(defstab));
1373         else
1374             tmps = str_get(st[1]);
1375         for (;;) {
1376             switch (*tmps) {
1377             default:
1378                 goto out;
1379             case '8': case '9':
1380                 if (argtype != 4)
1381                     goto out;
1382                 /* FALL THROUGH */
1383             case '0': case '1': case '2': case '3': case '4':
1384             case '5': case '6': case '7':
1385                 anum <<= argtype;
1386                 anum += *tmps++ & 15;
1387                 break;
1388             case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1389             case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1390                 if (argtype != 4)
1391                     goto out;
1392                 anum <<= 4;
1393                 anum += (*tmps++ & 7) + 9;
1394                 break;
1395             case 'x':
1396                 argtype = 4;
1397                 tmps++;
1398                 break;
1399             }
1400         }
1401       out:
1402         value = (double)anum;
1403         goto donumset;
1404     case O_CHMOD:
1405     case O_CHOWN:
1406     case O_KILL:
1407     case O_UNLINK:
1408     case O_UTIME:
1409         value = (double)apply(optype,arglast);
1410         goto donumset;
1411     case O_UMASK:
1412         if (maxarg < 1) {
1413             anum = umask(0);
1414             (void)umask(anum);
1415         }
1416         else
1417             anum = umask((int)str_gnum(st[1]));
1418         value = (double)anum;
1419 #ifdef TAINT
1420         taintproper("Insecure dependency in umask");
1421 #endif
1422         goto donumset;
1423     case O_RENAME:
1424         tmps = str_get(st[1]);
1425         tmps2 = str_get(st[2]);
1426 #ifdef TAINT
1427         taintproper("Insecure dependency in rename");
1428 #endif
1429 #ifdef RENAME
1430         value = (double)(rename(tmps,tmps2) >= 0);
1431 #else
1432         if (euid || stat(tmps2,&statbuf) < 0 ||
1433           (statbuf.st_mode & S_IFMT) != S_IFDIR )
1434             (void)UNLINK(tmps2);        /* avoid unlinking a directory */
1435         if (!(anum = link(tmps,tmps2)))
1436             anum = UNLINK(tmps);
1437         value = (double)(anum >= 0);
1438 #endif
1439         goto donumset;
1440     case O_LINK:
1441         tmps = str_get(st[1]);
1442         tmps2 = str_get(st[2]);
1443 #ifdef TAINT
1444         taintproper("Insecure dependency in link");
1445 #endif
1446         value = (double)(link(tmps,tmps2) >= 0);
1447         goto donumset;
1448     case O_MKDIR:
1449         tmps = str_get(st[1]);
1450         anum = (int)str_gnum(st[2]);
1451 #ifdef TAINT
1452         taintproper("Insecure dependency in mkdir");
1453 #endif
1454 #ifdef MKDIR
1455         value = (double)(mkdir(tmps,anum) >= 0);
1456         goto donumset;
1457 #else
1458         (void)strcpy(buf,"mkdir ");
1459 #endif
1460 #if !defined(MKDIR) || !defined(RMDIR)
1461       one_liner:
1462         for (tmps2 = buf+6; *tmps; ) {
1463             *tmps2++ = '\\';
1464             *tmps2++ = *tmps++;
1465         }
1466         (void)strcpy(tmps2," 2>&1");
1467         rsfp = mypopen(buf,"r");
1468         if (rsfp) {
1469             *buf = '\0';
1470             tmps2 = fgets(buf,sizeof buf,rsfp);
1471             (void)mypclose(rsfp);
1472             if (tmps2 != Nullch) {
1473                 for (errno = 1; errno < sys_nerr; errno++) {
1474                     if (instr(buf,sys_errlist[errno]))  /* you don't see this */
1475                         goto say_zero;
1476                 }
1477                 errno = 0;
1478 #ifndef EACCES
1479 #define EACCES EPERM
1480 #endif
1481                 if (instr(buf,"cannot make"))
1482                     errno = EEXIST;
1483                 else if (instr(buf,"non-exist"))
1484                     errno = ENOENT;
1485                 else if (instr(buf,"not empty"))
1486                     errno = EBUSY;
1487                 else if (instr(buf,"cannot access"))
1488                     errno = EACCES;
1489                 else
1490                     errno = EPERM;
1491                 goto say_zero;
1492             }
1493             else {      /* some mkdirs return no failure indication */
1494                 tmps = str_get(st[1]);
1495                 anum = (stat(tmps,&statbuf) >= 0);
1496                 if (optype == O_RMDIR)
1497                     anum = !anum;
1498                 if (anum)
1499                     errno = 0;
1500                 else
1501                     errno = EACCES;     /* a guess */
1502                 value = (double)anum;
1503             }
1504             goto donumset;
1505         }
1506         else
1507             goto say_zero;
1508 #endif
1509     case O_RMDIR:
1510         if (maxarg < 1)
1511             tmps = str_get(stab_val(defstab));
1512         else
1513             tmps = str_get(st[1]);
1514 #ifdef TAINT
1515         taintproper("Insecure dependency in rmdir");
1516 #endif
1517 #ifdef RMDIR
1518         value = (double)(rmdir(tmps) >= 0);
1519         goto donumset;
1520 #else
1521         (void)strcpy(buf,"rmdir ");
1522         goto one_liner;         /* see above in MKDIR */
1523 #endif
1524     case O_GETPPID:
1525         value = (double)getppid();
1526         goto donumset;
1527     case O_GETPGRP:
1528 #ifdef GETPGRP
1529         if (maxarg < 1)
1530             anum = 0;
1531         else
1532             anum = (int)str_gnum(st[1]);
1533         value = (double)getpgrp(anum);
1534         goto donumset;
1535 #else
1536         fatal("The getpgrp() function is unimplemented on this machine");
1537         break;
1538 #endif
1539     case O_SETPGRP:
1540 #ifdef SETPGRP
1541         argtype = (int)str_gnum(st[1]);
1542         anum = (int)str_gnum(st[2]);
1543 #ifdef TAINT
1544         taintproper("Insecure dependency in setpgrp");
1545 #endif
1546         value = (double)(setpgrp(argtype,anum) >= 0);
1547         goto donumset;
1548 #else
1549         fatal("The setpgrp() function is unimplemented on this machine");
1550         break;
1551 #endif
1552     case O_GETPRIORITY:
1553 #ifdef GETPRIORITY
1554         argtype = (int)str_gnum(st[1]);
1555         anum = (int)str_gnum(st[2]);
1556         value = (double)getpriority(argtype,anum);
1557         goto donumset;
1558 #else
1559         fatal("The getpriority() function is unimplemented on this machine");
1560         break;
1561 #endif
1562     case O_SETPRIORITY:
1563 #ifdef SETPRIORITY
1564         argtype = (int)str_gnum(st[1]);
1565         anum = (int)str_gnum(st[2]);
1566         optype = (int)str_gnum(st[3]);
1567 #ifdef TAINT
1568         taintproper("Insecure dependency in setpriority");
1569 #endif
1570         value = (double)(setpriority(argtype,anum,optype) >= 0);
1571         goto donumset;
1572 #else
1573         fatal("The setpriority() function is unimplemented on this machine");
1574         break;
1575 #endif
1576     case O_CHROOT:
1577         if (maxarg < 1)
1578             tmps = str_get(stab_val(defstab));
1579         else
1580             tmps = str_get(st[1]);
1581 #ifdef TAINT
1582         taintproper("Insecure dependency in chroot");
1583 #endif
1584         value = (double)(chroot(tmps) >= 0);
1585         goto donumset;
1586     case O_FCNTL:
1587     case O_IOCTL:
1588         if (maxarg <= 0)
1589             stab = last_in_stab;
1590         else if ((arg[1].arg_type & A_MASK) == A_WORD)
1591             stab = arg[1].arg_ptr.arg_stab;
1592         else
1593             stab = stabent(str_get(st[1]),TRUE);
1594         argtype = (int)str_gnum(st[2]);
1595 #ifdef TAINT
1596         taintproper("Insecure dependency in ioctl");
1597 #endif
1598         anum = do_ctl(optype,stab,argtype,st[3]);
1599         if (anum == -1)
1600             goto say_undef;
1601         if (anum != 0)
1602             goto donumset;
1603         str_set(str,"0 but true");
1604         STABSET(str);
1605         break;
1606     case O_FLOCK:
1607 #ifdef FLOCK
1608         if (maxarg <= 0)
1609             stab = last_in_stab;
1610         else if ((arg[1].arg_type & A_MASK) == A_WORD)
1611             stab = arg[1].arg_ptr.arg_stab;
1612         else
1613             stab = stabent(str_get(st[1]),TRUE);
1614         if (stab && stab_io(stab))
1615             fp = stab_io(stab)->ifp;
1616         else
1617             fp = Nullfp;
1618         if (fp) {
1619             argtype = (int)str_gnum(st[2]);
1620             value = (double)(flock(fileno(fp),argtype) >= 0);
1621         }
1622         else
1623             value = 0;
1624         goto donumset;
1625 #else
1626         fatal("The flock() function is unimplemented on this machine");
1627         break;
1628 #endif
1629     case O_UNSHIFT:
1630         ary = stab_array(arg[1].arg_ptr.arg_stab);
1631         if (arglast[2] - arglast[1] != 1)
1632             do_unshift(ary,arglast);
1633         else {
1634             str = Str_new(52,0);                /* must copy the STR */
1635             str_sset(str,st[2]);
1636             aunshift(ary,1);
1637             (void)astore(ary,0,str);
1638         }
1639         value = (double)(ary->ary_fill + 1);
1640         break;
1641     case O_DOFILE:
1642     case O_EVAL:
1643         if (maxarg < 1)
1644             tmpstr = stab_val(defstab);
1645         else
1646             tmpstr =
1647               (arg[1].arg_type & A_MASK) != A_NULL ? st[1] : stab_val(defstab);
1648 #ifdef TAINT
1649         tainted |= tmpstr->str_tainted;
1650         taintproper("Insecure dependency in eval");
1651 #endif
1652         sp = do_eval(tmpstr, optype, arg[2].arg_ptr.arg_hash,
1653             gimme,arglast);
1654         goto array_return;
1655
1656     case O_FTRREAD:
1657         argtype = 0;
1658         anum = S_IREAD;
1659         goto check_perm;
1660     case O_FTRWRITE:
1661         argtype = 0;
1662         anum = S_IWRITE;
1663         goto check_perm;
1664     case O_FTREXEC:
1665         argtype = 0;
1666         anum = S_IEXEC;
1667         goto check_perm;
1668     case O_FTEREAD:
1669         argtype = 1;
1670         anum = S_IREAD;
1671         goto check_perm;
1672     case O_FTEWRITE:
1673         argtype = 1;
1674         anum = S_IWRITE;
1675         goto check_perm;
1676     case O_FTEEXEC:
1677         argtype = 1;
1678         anum = S_IEXEC;
1679       check_perm:
1680         if (mystat(arg,st[1]) < 0)
1681             goto say_undef;
1682         if (cando(anum,argtype,&statcache))
1683             goto say_yes;
1684         goto say_no;
1685
1686     case O_FTIS:
1687         if (mystat(arg,st[1]) < 0)
1688             goto say_undef;
1689         goto say_yes;
1690     case O_FTEOWNED:
1691     case O_FTROWNED:
1692         if (mystat(arg,st[1]) < 0)
1693             goto say_undef;
1694         if (statcache.st_uid == (optype == O_FTEOWNED ? euid : uid) )
1695             goto say_yes;
1696         goto say_no;
1697     case O_FTZERO:
1698         if (mystat(arg,st[1]) < 0)
1699             goto say_undef;
1700         if (!statcache.st_size)
1701             goto say_yes;
1702         goto say_no;
1703     case O_FTSIZE:
1704         if (mystat(arg,st[1]) < 0)
1705             goto say_undef;
1706         if (statcache.st_size)
1707             goto say_yes;
1708         goto say_no;
1709
1710     case O_FTSOCK:
1711 #ifdef S_IFSOCK
1712         anum = S_IFSOCK;
1713         goto check_file_type;
1714 #else
1715         goto say_no;
1716 #endif
1717     case O_FTCHR:
1718         anum = S_IFCHR;
1719         goto check_file_type;
1720     case O_FTBLK:
1721         anum = S_IFBLK;
1722         goto check_file_type;
1723     case O_FTFILE:
1724         anum = S_IFREG;
1725         goto check_file_type;
1726     case O_FTDIR:
1727         anum = S_IFDIR;
1728       check_file_type:
1729         if (mystat(arg,st[1]) < 0)
1730             goto say_undef;
1731         if ((statcache.st_mode & S_IFMT) == anum )
1732             goto say_yes;
1733         goto say_no;
1734     case O_FTPIPE:
1735 #ifdef S_IFIFO
1736         anum = S_IFIFO;
1737         goto check_file_type;
1738 #else
1739         goto say_no;
1740 #endif
1741     case O_FTLINK:
1742 #ifdef SYMLINK
1743         if (lstat(str_get(st[1]),&statcache) < 0)
1744             goto say_undef;
1745         if ((statcache.st_mode & S_IFMT) == S_IFLNK )
1746             goto say_yes;
1747 #endif
1748         goto say_no;
1749     case O_SYMLINK:
1750 #ifdef SYMLINK
1751         tmps = str_get(st[1]);
1752         tmps2 = str_get(st[2]);
1753 #ifdef TAINT
1754         taintproper("Insecure dependency in symlink");
1755 #endif
1756         value = (double)(symlink(tmps,tmps2) >= 0);
1757         goto donumset;
1758 #else
1759         fatal("Unsupported function symlink()");
1760 #endif
1761     case O_READLINK:
1762 #ifdef SYMLINK
1763         if (maxarg < 1)
1764             tmps = str_get(stab_val(defstab));
1765         else
1766             tmps = str_get(st[1]);
1767         anum = readlink(tmps,buf,sizeof buf);
1768         if (anum < 0)
1769             goto say_undef;
1770         str_nset(str,buf,anum);
1771         break;
1772 #else
1773         fatal("Unsupported function readlink()");
1774 #endif
1775     case O_FTSUID:
1776         anum = S_ISUID;
1777         goto check_xid;
1778     case O_FTSGID:
1779         anum = S_ISGID;
1780         goto check_xid;
1781     case O_FTSVTX:
1782         anum = S_ISVTX;
1783       check_xid:
1784         if (mystat(arg,st[1]) < 0)
1785             goto say_undef;
1786         if (statcache.st_mode & anum)
1787             goto say_yes;
1788         goto say_no;
1789     case O_FTTTY:
1790         if (arg[1].arg_type & A_DONT) {
1791             stab = arg[1].arg_ptr.arg_stab;
1792             tmps = "";
1793         }
1794         else
1795             stab = stabent(tmps = str_get(st[1]),FALSE);
1796         if (stab && stab_io(stab) && stab_io(stab)->ifp)
1797             anum = fileno(stab_io(stab)->ifp);
1798         else if (isdigit(*tmps))
1799             anum = atoi(tmps);
1800         else
1801             goto say_undef;
1802         if (isatty(anum))
1803             goto say_yes;
1804         goto say_no;
1805     case O_FTTEXT:
1806     case O_FTBINARY:
1807         str = do_fttext(arg,st[1]);
1808         break;
1809 #ifdef SOCKET
1810     case O_SOCKET:
1811         if ((arg[1].arg_type & A_MASK) == A_WORD)
1812             stab = arg[1].arg_ptr.arg_stab;
1813         else
1814             stab = stabent(str_get(st[1]),TRUE);
1815 #ifndef lint
1816         value = (double)do_socket(stab,arglast);
1817 #else
1818         (void)do_socket(stab,arglast);
1819 #endif
1820         goto donumset;
1821     case O_BIND:
1822         if ((arg[1].arg_type & A_MASK) == A_WORD)
1823             stab = arg[1].arg_ptr.arg_stab;
1824         else
1825             stab = stabent(str_get(st[1]),TRUE);
1826 #ifndef lint
1827         value = (double)do_bind(stab,arglast);
1828 #else
1829         (void)do_bind(stab,arglast);
1830 #endif
1831         goto donumset;
1832     case O_CONNECT:
1833         if ((arg[1].arg_type & A_MASK) == A_WORD)
1834             stab = arg[1].arg_ptr.arg_stab;
1835         else
1836             stab = stabent(str_get(st[1]),TRUE);
1837 #ifndef lint
1838         value = (double)do_connect(stab,arglast);
1839 #else
1840         (void)do_connect(stab,arglast);
1841 #endif
1842         goto donumset;
1843     case O_LISTEN:
1844         if ((arg[1].arg_type & A_MASK) == A_WORD)
1845             stab = arg[1].arg_ptr.arg_stab;
1846         else
1847             stab = stabent(str_get(st[1]),TRUE);
1848 #ifndef lint
1849         value = (double)do_listen(stab,arglast);
1850 #else
1851         (void)do_listen(stab,arglast);
1852 #endif
1853         goto donumset;
1854     case O_ACCEPT:
1855         if ((arg[1].arg_type & A_MASK) == A_WORD)
1856             stab = arg[1].arg_ptr.arg_stab;
1857         else
1858             stab = stabent(str_get(st[1]),TRUE);
1859         if ((arg[2].arg_type & A_MASK) == A_WORD)
1860             stab2 = arg[2].arg_ptr.arg_stab;
1861         else
1862             stab2 = stabent(str_get(st[2]),TRUE);
1863         do_accept(str,stab,stab2);
1864         STABSET(str);
1865         break;
1866     case O_GHBYNAME:
1867         if (maxarg < 1)
1868             goto say_undef;
1869     case O_GHBYADDR:
1870     case O_GHOSTENT:
1871         sp = do_ghent(optype,
1872           gimme,arglast);
1873         goto array_return;
1874     case O_GNBYNAME:
1875         if (maxarg < 1)
1876             goto say_undef;
1877     case O_GNBYADDR:
1878     case O_GNETENT:
1879         sp = do_gnent(optype,
1880           gimme,arglast);
1881         goto array_return;
1882     case O_GPBYNAME:
1883         if (maxarg < 1)
1884             goto say_undef;
1885     case O_GPBYNUMBER:
1886     case O_GPROTOENT:
1887         sp = do_gpent(optype,
1888           gimme,arglast);
1889         goto array_return;
1890     case O_GSBYNAME:
1891         if (maxarg < 1)
1892             goto say_undef;
1893     case O_GSBYPORT:
1894     case O_GSERVENT:
1895         sp = do_gsent(optype,
1896           gimme,arglast);
1897         goto array_return;
1898     case O_SHOSTENT:
1899         value = (double) sethostent((int)str_gnum(st[1]));
1900         goto donumset;
1901     case O_SNETENT:
1902         value = (double) setnetent((int)str_gnum(st[1]));
1903         goto donumset;
1904     case O_SPROTOENT:
1905         value = (double) setprotoent((int)str_gnum(st[1]));
1906         goto donumset;
1907     case O_SSERVENT:
1908         value = (double) setservent((int)str_gnum(st[1]));
1909         goto donumset;
1910     case O_EHOSTENT:
1911         value = (double) endhostent();
1912         goto donumset;
1913     case O_ENETENT:
1914         value = (double) endnetent();
1915         goto donumset;
1916     case O_EPROTOENT:
1917         value = (double) endprotoent();
1918         goto donumset;
1919     case O_ESERVENT:
1920         value = (double) endservent();
1921         goto donumset;
1922     case O_SSELECT:
1923         sp = do_select(gimme,arglast);
1924         goto array_return;
1925     case O_SOCKETPAIR:
1926         if ((arg[1].arg_type & A_MASK) == A_WORD)
1927             stab = arg[1].arg_ptr.arg_stab;
1928         else
1929             stab = stabent(str_get(st[1]),TRUE);
1930         if ((arg[2].arg_type & A_MASK) == A_WORD)
1931             stab2 = arg[2].arg_ptr.arg_stab;
1932         else
1933             stab2 = stabent(str_get(st[2]),TRUE);
1934 #ifndef lint
1935         value = (double)do_spair(stab,stab2,arglast);
1936 #else
1937         (void)do_spair(stab,stab2,arglast);
1938 #endif
1939         goto donumset;
1940     case O_SHUTDOWN:
1941         if ((arg[1].arg_type & A_MASK) == A_WORD)
1942             stab = arg[1].arg_ptr.arg_stab;
1943         else
1944             stab = stabent(str_get(st[1]),TRUE);
1945 #ifndef lint
1946         value = (double)do_shutdown(stab,arglast);
1947 #else
1948         (void)do_shutdown(stab,arglast);
1949 #endif
1950         goto donumset;
1951     case O_GSOCKOPT:
1952     case O_SSOCKOPT:
1953         if ((arg[1].arg_type & A_MASK) == A_WORD)
1954             stab = arg[1].arg_ptr.arg_stab;
1955         else
1956             stab = stabent(str_get(st[1]),TRUE);
1957         sp = do_sopt(optype,stab,arglast);
1958         goto array_return;
1959     case O_GETSOCKNAME:
1960     case O_GETPEERNAME:
1961         if ((arg[1].arg_type & A_MASK) == A_WORD)
1962             stab = arg[1].arg_ptr.arg_stab;
1963         else
1964             stab = stabent(str_get(st[1]),TRUE);
1965         sp = do_getsockname(optype,stab,arglast);
1966         goto array_return;
1967
1968 #else /* SOCKET not defined */
1969     case O_SOCKET:
1970     case O_BIND:
1971     case O_CONNECT:
1972     case O_LISTEN:
1973     case O_ACCEPT:
1974     case O_SSELECT:
1975     case O_SOCKETPAIR:
1976     case O_GHBYNAME:
1977     case O_GHBYADDR:
1978     case O_GHOSTENT:
1979     case O_GNBYNAME:
1980     case O_GNBYADDR:
1981     case O_GNETENT:
1982     case O_GPBYNAME:
1983     case O_GPBYNUMBER:
1984     case O_GPROTOENT:
1985     case O_GSBYNAME:
1986     case O_GSBYPORT:
1987     case O_GSERVENT:
1988     case O_SHOSTENT:
1989     case O_SNETENT:
1990     case O_SPROTOENT:
1991     case O_SSERVENT:
1992     case O_EHOSTENT:
1993     case O_ENETENT:
1994     case O_EPROTOENT:
1995     case O_ESERVENT:
1996     case O_SHUTDOWN:
1997     case O_GSOCKOPT:
1998     case O_SSOCKOPT:
1999     case O_GETSOCKNAME:
2000     case O_GETPEERNAME:
2001       badsock:
2002         fatal("Unsupported socket function");
2003 #endif /* SOCKET */
2004     case O_FILENO:
2005         if (maxarg < 1)
2006             goto say_undef;
2007         if ((arg[1].arg_type & A_MASK) == A_WORD)
2008             stab = arg[1].arg_ptr.arg_stab;
2009         else
2010             stab = stabent(str_get(st[1]),TRUE);
2011         if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
2012             goto say_undef;
2013         value = fileno(fp);
2014         goto donumset;
2015     case O_VEC:
2016         sp = do_vec(str == st[1], arg->arg_ptr.arg_str, arglast);
2017         goto array_return;
2018     case O_GPWNAM:
2019     case O_GPWUID:
2020     case O_GPWENT:
2021         sp = do_gpwent(optype,
2022           gimme,arglast);
2023         goto array_return;
2024     case O_SPWENT:
2025         value = (double) setpwent();
2026         goto donumset;
2027     case O_EPWENT:
2028         value = (double) endpwent();
2029         goto donumset;
2030     case O_GGRNAM:
2031     case O_GGRGID:
2032     case O_GGRENT:
2033         sp = do_ggrent(optype,
2034           gimme,arglast);
2035         goto array_return;
2036     case O_SGRENT:
2037         value = (double) setgrent();
2038         goto donumset;
2039     case O_EGRENT:
2040         value = (double) endgrent();
2041         goto donumset;
2042     case O_GETLOGIN:
2043         if (!(tmps = getlogin()))
2044             goto say_undef;
2045         str_set(str,tmps);
2046         break;
2047     case O_OPENDIR:
2048     case O_READDIR:
2049     case O_TELLDIR:
2050     case O_SEEKDIR:
2051     case O_REWINDDIR:
2052     case O_CLOSEDIR:
2053         if (maxarg < 1)
2054             goto say_undef;
2055         if ((arg[1].arg_type & A_MASK) == A_WORD)
2056             stab = arg[1].arg_ptr.arg_stab;
2057         else
2058             stab = stabent(str_get(st[1]),TRUE);
2059         sp = do_dirop(optype,stab,gimme,arglast);
2060         goto array_return;
2061     case O_SYSCALL:
2062         value = (double)do_syscall(arglast);
2063         goto donumset;
2064     }
2065
2066   normal_return:
2067     st[1] = str;
2068 #ifdef DEBUGGING
2069     if (debug) {
2070         dlevel--;
2071         if (debug & 8)
2072             deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
2073     }
2074 #endif
2075     return arglast[0] + 1;
2076
2077 array_return:
2078 #ifdef DEBUGGING
2079     if (debug) {
2080         dlevel--;
2081         if (debug & 8)
2082             deb("%s RETURNS ARRAY OF %d ARGS\n",opname[optype],sp - arglast[0]);
2083     }
2084 #endif
2085     return sp;
2086
2087 say_yes:
2088     str = &str_yes;
2089     goto normal_return;
2090
2091 say_no:
2092     str = &str_no;
2093     goto normal_return;
2094
2095 say_undef:
2096     str = &str_undef;
2097     goto normal_return;
2098
2099 say_zero:
2100     value = 0.0;
2101     /* FALL THROUGH */
2102
2103 donumset:
2104     str_numset(str,value);
2105     STABSET(str);
2106     st[1] = str;
2107 #ifdef DEBUGGING
2108     if (debug) {
2109         dlevel--;
2110         if (debug & 8)
2111             deb("%s RETURNS \"%f\"\n",opname[optype],value);
2112     }
2113 #endif
2114     return arglast[0] + 1;
2115 }