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