perl 5.0 alpha 9
[p5sagit/p5-mst-13.2.git] / eval.c.save
CommitLineData
2304df62 1/* $RCSfile: eval.c,v $$Revision: 4.1 $$Date: 92/08/07 18:20:29 $
2 *
3 * Copyright (c) 1991, Larry Wall
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 * $Log: eval.c,v $
9 * Revision 4.1 92/08/07 18:20:29 lwall
10 *
11 * Revision 4.0.1.4 92/06/08 13:20:20 lwall
12 * patch20: added explicit time_t support
13 * patch20: fixed confusion between a *var's real name and its effective name
14 * patch20: added Atari ST portability
15 * patch20: new warning for use of x with non-numeric right operand
16 * patch20: modulus with highest bit in left operand set didn't always work
17 * patch20: dbmclose(%array) didn't work
18 * patch20: added ... as variant on ..
19 * patch20: O_PIPE conflicted with Atari
20 *
21 * Revision 4.0.1.3 91/11/05 17:15:21 lwall
22 * patch11: prepared for ctype implementations that don't define isascii()
23 * patch11: various portability fixes
24 * patch11: added sort {} LIST
25 * patch11: added eval {}
26 * patch11: sysread() in socket was substituting recv()
27 * patch11: a last statement outside any block caused occasional core dumps
28 * patch11: missing arguments caused core dump in -D8 code
29 * patch11: eval 'stuff' now optimized to eval {stuff}
30 *
31 * Revision 4.0.1.2 91/06/07 11:07:23 lwall
32 * patch4: new copyright notice
33 * patch4: length($`), length($&), length($') now optimized to avoid string copy
34 * patch4: assignment wasn't correctly de-tainting the assigned variable.
35 * patch4: default top-of-form format is now FILEHANDLE_TOP
36 * patch4: added $^P variable to control calling of perldb routines
37 * patch4: taintchecks could improperly modify parent in vfork()
38 * patch4: many, many itty-bitty portability fixes
39 *
40 * Revision 4.0.1.1 91/04/11 17:43:48 lwall
41 * patch1: fixed failed fork to return undef as documented
42 * patch1: reduced maximum branch distance in eval.c
43 *
44 * Revision 4.0 91/03/20 01:16:48 lwall
45 * 4.0 baseline.
46 *
47 */
48
49#include "EXTERN.h"
50#include "perl.h"
51
52extern int (*ppaddr[])();
53extern int mark[];
54
55#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
56#include <signal.h>
57#endif
58
59#ifdef I_FCNTL
60#include <fcntl.h>
61#endif
62#ifdef MSDOS
63/* I_FCNTL *MUST* not be defined for MS-DOS and OS/2
64 but fcntl.h is required for O_BINARY */
65#include <fcntl.h>
66#endif
67#ifdef I_SYS_FILE
68#include <sys/file.h>
69#endif
70#ifdef I_VFORK
71# include <vfork.h>
72#endif
73
74double sin(), cos(), atan2(), pow();
75
76char *getlogin();
77
78int
79eval(arg,gimme,sp)
80register ARG *arg;
81int gimme;
82register int sp;
83{
84 register STR *str;
85 register int anum;
86 register int optype;
87 register STR **st;
88 int maxarg;
89 double value;
90 register char *tmps;
91 char *tmps2;
92 int argflags;
93 int argtype;
94 union argptr argptr;
95 int arglast[8]; /* highest sp for arg--valid only for non-O_LIST args */
96 unsigned long tmpulong;
97 long tmplong;
98 time_t when;
99 STRLEN tmplen;
100 FILE *fp;
101 STR *tmpstr;
102 FCMD *form;
103 STAB *stab;
104 STAB *stab2;
105 STIO *stio;
106 ARRAY *ary;
107 int old_rslen;
108 int old_rschar;
109 VOIDRET (*ihand)(); /* place to save signal during system() */
110 VOIDRET (*qhand)(); /* place to save signal during system() */
111 bool assigning = FALSE;
112 int mymarkbase = savestack->ary_fill;
113
114 if (!arg)
115 goto say_undef;
116 optype = arg->arg_type;
117 maxarg = arg->arg_len;
118 arglast[0] = sp;
119 str = arg->arg_ptr.arg_str;
120 if (sp + maxarg > stack->ary_max)
121 astore(stack, sp + maxarg, Nullstr);
122 st = stack->ary_array;
123
124#ifdef DEBUGGING
125 if (debug) {
126 if (debug & 8) {
127 deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
128 }
129 debname[dlevel] = opname[optype][0];
130 debdelim[dlevel] = ':';
131 if (++dlevel >= dlmax)
132 grow_dlevel();
133 }
134#endif
135
136 if (mark[optype]) {
137 saveint(&markbase);
138 markbase = mymarkbase;
139 saveint(&stack_mark);
140 stack_mark = sp;
141 }
142 for (anum = 1; anum <= maxarg; anum++) {
143 argflags = arg[anum].arg_flags;
144 argtype = arg[anum].arg_type;
145 argptr = arg[anum].arg_ptr;
146 re_eval:
147 switch (argtype) {
148 default:
149 if (!ppaddr[optype] || optype == O_SUBR || optype == O_DBSUBR) {
150 st[++sp] = &str_undef;
151 }
152#ifdef DEBUGGING
153 tmps = "NULL";
154#endif
155 break;
156 case A_EXPR:
157#ifdef DEBUGGING
158 if (debug & 8) {
159 tmps = "EXPR";
160 deb("%d.EXPR =>\n",anum);
161 }
162#endif
163 sp = eval(argptr.arg_arg,
164 (argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, sp);
165 if (sp + (maxarg - anum) > stack->ary_max)
166 astore(stack, sp + (maxarg - anum), Nullstr);
167 st = stack->ary_array; /* possibly reallocated */
168 break;
169 case A_CMD:
170#ifdef DEBUGGING
171 if (debug & 8) {
172 tmps = "CMD";
173 deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
174 }
175#endif
176 sp = cmd_exec(argptr.arg_cmd, gimme, sp);
177 if (sp + (maxarg - anum) > stack->ary_max)
178 astore(stack, sp + (maxarg - anum), Nullstr);
179 st = stack->ary_array; /* possibly reallocated */
180 break;
181 case A_LARYSTAB:
182 ++sp;
183 switch (optype) {
184 case O_ITEM2: argtype = 2; break;
185 case O_ITEM3: argtype = 3; break;
186 default: argtype = anum; break;
187 }
188 str = afetch(stab_array(argptr.arg_stab),
189 arg[argtype].arg_len - arybase, TRUE);
190#ifdef DEBUGGING
191 if (debug & 8) {
192 (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
193 arg[argtype].arg_len);
194 tmps = buf;
195 }
196#endif
197 goto do_crement;
198 case A_ARYSTAB:
199 switch (optype) {
200 case O_ITEM2: argtype = 2; break;
201 case O_ITEM3: argtype = 3; break;
202 default: argtype = anum; break;
203 }
204 st[++sp] = afetch(stab_array(argptr.arg_stab),
205 arg[argtype].arg_len - arybase, FALSE);
206#ifdef DEBUGGING
207 if (debug & 8) {
208 (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
209 arg[argtype].arg_len);
210 tmps = buf;
211 }
212#endif
213 break;
214 case A_STAR:
215 stab = argptr.arg_stab;
216 st[++sp] = (STR*)stab;
217 if (!stab_xarray(stab))
218 aadd(stab);
219 if (!stab_xhash(stab))
220 hadd(stab);
221 if (!stab_io(stab))
222 stab_io(stab) = stio_new();
223#ifdef DEBUGGING
224 if (debug & 8) {
225 (void)sprintf(buf,"STAR *%s -> *%s",
226 stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab));
227 tmps = buf;
228 }
229#endif
230 break;
231 case A_LSTAR:
232 str = st[++sp] = (STR*)argptr.arg_stab;
233#ifdef DEBUGGING
234 if (debug & 8) {
235 (void)sprintf(buf,"LSTAR *%s -> *%s",
236 stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab));
237 tmps = buf;
238 }
239#endif
240 break;
241 case A_STAB:
242 st[++sp] = STAB_STR(argptr.arg_stab);
243#ifdef DEBUGGING
244 if (debug & 8) {
245 (void)sprintf(buf,"STAB $%s",stab_name(argptr.arg_stab));
246 tmps = buf;
247 }
248#endif
249 break;
250 case A_LENSTAB:
251 str_numset(str, (double)STAB_LEN(argptr.arg_stab));
252 st[++sp] = str;
253#ifdef DEBUGGING
254 if (debug & 8) {
255 (void)sprintf(buf,"LENSTAB $%s",stab_name(argptr.arg_stab));
256 tmps = buf;
257 }
258#endif
259 break;
260 case A_LEXPR:
261#ifdef DEBUGGING
262 if (debug & 8) {
263 tmps = "LEXPR";
264 deb("%d.LEXPR =>\n",anum);
265 }
266#endif
267 if (argflags & AF_ARYOK) {
268 sp = eval(argptr.arg_arg, G_ARRAY, sp);
269 if (sp + (maxarg - anum) > stack->ary_max)
270 astore(stack, sp + (maxarg - anum), Nullstr);
271 st = stack->ary_array; /* possibly reallocated */
272 }
273 else {
274 sp = eval(argptr.arg_arg, G_SCALAR, sp);
275 st = stack->ary_array; /* possibly reallocated */
276 str = st[sp];
277 goto do_crement;
278 }
279 break;
280 case A_LVAL:
281#ifdef DEBUGGING
282 if (debug & 8) {
283 (void)sprintf(buf,"LVAL $%s",stab_name(argptr.arg_stab));
284 tmps = buf;
285 }
286#endif
287 ++sp;
288 str = STAB_STR(argptr.arg_stab);
289 if (!str)
290 fatal("panic: A_LVAL");
291 do_crement:
292 assigning = TRUE;
293 if (argflags & AF_PRE) {
294 if (argflags & AF_UP)
295 str_inc(str);
296 else
297 str_dec(str);
298 STABSET(str);
299 st[sp] = str;
300 str = arg->arg_ptr.arg_str;
301 }
302 else if (argflags & AF_POST) {
303 st[sp] = str_mortal(str);
304 if (argflags & AF_UP)
305 str_inc(str);
306 else
307 str_dec(str);
308 STABSET(str);
309 str = arg->arg_ptr.arg_str;
310 }
311 else
312 st[sp] = str;
313 break;
314 case A_LARYLEN:
315 ++sp;
316 stab = argptr.arg_stab;
317 str = stab_array(argptr.arg_stab)->ary_magic;
318 if (optype != O_SASSIGN || argflags & (AF_PRE|AF_POST))
319 str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
320#ifdef DEBUGGING
321 tmps = "LARYLEN";
322#endif
323 if (!str)
324 fatal("panic: A_LEXPR");
325 goto do_crement;
326 case A_ARYLEN:
327 stab = argptr.arg_stab;
328 st[++sp] = stab_array(stab)->ary_magic;
329 str_numset(st[sp],(double)(stab_array(stab)->ary_fill+arybase));
330#ifdef DEBUGGING
331 tmps = "ARYLEN";
332#endif
333 break;
334 case A_SINGLE:
335 st[++sp] = argptr.arg_str;
336#ifdef DEBUGGING
337 tmps = "SINGLE";
338#endif
339 break;
340 case A_DOUBLE:
341 (void) interp(str,argptr.arg_str,sp);
342 st = stack->ary_array;
343 st[++sp] = str;
344#ifdef DEBUGGING
345 tmps = "DOUBLE";
346#endif
347 break;
348 case A_BACKTICK:
349 tmps = str_get(interp(str,argptr.arg_str,sp));
350 st = stack->ary_array;
351#ifdef TAINT
352 TAINT_PROPER("``");
353#endif
354 fp = mypopen(tmps,"r");
355 str_set(str,"");
356 if (fp) {
357 if (gimme == G_SCALAR) {
358 while (str_gets(str,fp,str->str_cur) != Nullch)
359 /*SUPPRESS 530*/
360 ;
361 }
362 else {
363 for (;;) {
364 if (++sp > stack->ary_max) {
365 astore(stack, sp, Nullstr);
366 st = stack->ary_array;
367 }
368 str = st[sp] = Str_new(56,80);
369 if (str_gets(str,fp,0) == Nullch) {
370 sp--;
371 break;
372 }
373 if (str->str_len - str->str_cur > 20) {
374 str->str_len = str->str_cur+1;
375 Renew(str->str_ptr, str->str_len, char);
376 }
377 str_2mortal(str);
378 }
379 }
380 statusvalue = mypclose(fp);
381 }
382 else
383 statusvalue = -1;
384
385 if (gimme == G_SCALAR)
386 st[++sp] = str;
387#ifdef DEBUGGING
388 tmps = "BACK";
389#endif
390 break;
391 case A_WANTARRAY:
392 {
393 if (curcsv->wantarray == G_ARRAY)
394 st[++sp] = &str_yes;
395 else
396 st[++sp] = &str_no;
397 }
398#ifdef DEBUGGING
399 tmps = "WANTARRAY";
400#endif
401 break;
402 case A_INDREAD:
403 last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
404 old_rschar = rschar;
405 old_rslen = rslen;
406 goto do_read;
407 case A_GLOB:
408 argflags |= AF_POST; /* enable newline chopping */
409 last_in_stab = argptr.arg_stab;
410 old_rschar = rschar;
411 old_rslen = rslen;
412 rslen = 1;
413#ifdef DOSISH
414 rschar = 0;
415#else
416#ifdef CSH
417 rschar = 0;
418#else
419 rschar = '\n';
420#endif /* !CSH */
421#endif /* !MSDOS */
422 goto do_read;
423 case A_READ:
424 last_in_stab = argptr.arg_stab;
425 old_rschar = rschar;
426 old_rslen = rslen;
427 do_read:
428 if (anum > 1) /* assign to scalar */
429 gimme = G_SCALAR; /* force context to scalar */
430 if (gimme == G_ARRAY)
431 str = Str_new(57,0);
432 ++sp;
433 fp = Nullfp;
434 if (stab_io(last_in_stab)) {
435 fp = stab_io(last_in_stab)->ifp;
436 if (!fp) {
437 if (stab_io(last_in_stab)->flags & IOF_ARGV) {
438 if (stab_io(last_in_stab)->flags & IOF_START) {
439 stab_io(last_in_stab)->flags &= ~IOF_START;
440 stab_io(last_in_stab)->lines = 0;
441 if (alen(stab_array(last_in_stab)) < 0) {
442 tmpstr = str_make("-",1); /* assume stdin */
443 (void)apush(stab_array(last_in_stab), tmpstr);
444 }
445 }
446 fp = nextargv(last_in_stab);
447 if (!fp) { /* Note: fp != stab_io(last_in_stab)->ifp */
448 (void)do_close(last_in_stab,FALSE); /* now it does*/
449 stab_io(last_in_stab)->flags |= IOF_START;
450 }
451 }
452 else if (argtype == A_GLOB) {
453 (void) interp(str,stab_val(last_in_stab),sp);
454 st = stack->ary_array;
455 tmpstr = Str_new(55,0);
456#ifdef DOSISH
457 str_set(tmpstr, "perlglob ");
458 str_scat(tmpstr,str);
459 str_cat(tmpstr," |");
460#else
461#ifdef CSH
462 str_nset(tmpstr,cshname,cshlen);
463 str_cat(tmpstr," -cf 'set nonomatch; glob ");
464 str_scat(tmpstr,str);
465 str_cat(tmpstr,"'|");
466#else
467 str_set(tmpstr, "echo ");
468 str_scat(tmpstr,str);
469 str_cat(tmpstr,
470 "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
471#endif /* !CSH */
472#endif /* !MSDOS */
473 (void)do_open(last_in_stab,tmpstr->str_ptr,
474 tmpstr->str_cur);
475 fp = stab_io(last_in_stab)->ifp;
476 str_free(tmpstr);
477 }
478 }
479 }
480 if (!fp && dowarn)
481 warn("Read on closed filehandle <%s>",stab_ename(last_in_stab));
482 tmplen = str->str_len; /* remember if already alloced */
483 if (!tmplen)
484 Str_Grow(str,80); /* try short-buffering it */
485 keepgoing:
486 if (!fp)
487 st[sp] = &str_undef;
488 else if (!str_gets(str,fp, optype == O_RCAT ? str->str_cur : 0)) {
489 clearerr(fp);
490 if (stab_io(last_in_stab)->flags & IOF_ARGV) {
491 fp = nextargv(last_in_stab);
492 if (fp)
493 goto keepgoing;
494 (void)do_close(last_in_stab,FALSE);
495 stab_io(last_in_stab)->flags |= IOF_START;
496 }
497 else if (argflags & AF_POST) {
498 (void)do_close(last_in_stab,FALSE);
499 }
500 st[sp] = &str_undef;
501 rschar = old_rschar;
502 rslen = old_rslen;
503 if (gimme == G_ARRAY) {
504 --sp;
505 str_2mortal(str);
506 goto array_return;
507 }
508 break;
509 }
510 else {
511 stab_io(last_in_stab)->lines++;
512 st[sp] = str;
513#ifdef TAINT
514 str->str_tainted = 1; /* Anything from the outside world...*/
515#endif
516 if (argflags & AF_POST) {
517 if (str->str_cur > 0)
518 str->str_cur--;
519 if (str->str_ptr[str->str_cur] == rschar)
520 str->str_ptr[str->str_cur] = '\0';
521 else
522 str->str_cur++;
523 for (tmps = str->str_ptr; *tmps; tmps++)
524 if (!isALPHA(*tmps) && !isDIGIT(*tmps) &&
525 index("$&*(){}[]'\";\\|?<>~`",*tmps))
526 break;
527 if (*tmps && stat(str->str_ptr,&statbuf) < 0)
528 goto keepgoing; /* unmatched wildcard? */
529 }
530 if (gimme == G_ARRAY) {
531 if (str->str_len - str->str_cur > 20) {
532 str->str_len = str->str_cur+1;
533 Renew(str->str_ptr, str->str_len, char);
534 }
535 str_2mortal(str);
536 if (++sp > stack->ary_max) {
537 astore(stack, sp, Nullstr);
538 st = stack->ary_array;
539 }
540 str = Str_new(58,80);
541 goto keepgoing;
542 }
543 else if (!tmplen && str->str_len - str->str_cur > 80) {
544 /* try to reclaim a bit of scalar space on 1st alloc */
545 if (str->str_cur < 60)
546 str->str_len = 80;
547 else
548 str->str_len = str->str_cur+40; /* allow some slop */
549 Renew(str->str_ptr, str->str_len, char);
550 }
551 }
552 rschar = old_rschar;
553 rslen = old_rslen;
554#ifdef DEBUGGING
555 tmps = "READ";
556#endif
557 break;
558 }
559#ifdef DEBUGGING
560 if (debug & 8) {
561 if (strEQ(tmps, "NULL"))
562 deb("%d.%s\n",anum,tmps);
563 else
564 deb("%d.%s = '%s'\n",anum,tmps,str_peek(st[sp]));
565 }
566#endif
567 if (anum < 8)
568 arglast[anum] = sp;
569 }
570
571 if (ppaddr[optype]) {
572 int status;
573
574 /* pretend like we've been maintaining stack_* all along */
575 stack_ary = stack->ary_array;
576 stack_sp = stack_ary + sp;
577 if (mark[optype] && stack_mark != arglast[0])
578 warn("Inconsistent stack mark %d != %d", stack_mark, arglast[0]);
579 stack_max = stack_ary + stack->ary_max;
580
581 status = (*ppaddr[optype])(str, arg, gimme);
582
583 if (savestack->ary_fill > mymarkbase) {
584 warn("Inconsistent stack base");
585 restorelist(mymarkbase);
586 }
587 sp = stack_sp - stack_ary;
588 if (sp < arglast[0])
589 warn("TOO MANY POPS");
590 st += arglast[0];
591 goto array_return;
592 }
593
594 st += arglast[0];
595
596#ifdef SMALLSWITCHES
597 if (optype < O_CHOWN)
598#endif
599 switch (optype) {
600 case O_RCAT:
601 STABSET(str);
602 break;
603 case O_ITEM:
604 if (gimme == G_ARRAY)
605 goto array_return;
606 /* FALL THROUGH */
607 case O_SCALAR:
608 STR_SSET(str,st[1]);
609 STABSET(str);
610 break;
611 case O_ITEM2:
612 if (gimme == G_ARRAY)
613 goto array_return;
614 --anum;
615 STR_SSET(str,st[arglast[anum]-arglast[0]]);
616 STABSET(str);
617 break;
618 case O_ITEM3:
619 if (gimme == G_ARRAY)
620 goto array_return;
621 --anum;
622 STR_SSET(str,st[arglast[anum]-arglast[0]]);
623 STABSET(str);
624 break;
625 case O_CONCAT:
626 STR_SSET(str,st[1]);
627 str_scat(str,st[2]);
628 STABSET(str);
629 break;
630 case O_REPEAT:
631 if (gimme == G_ARRAY && arg[1].arg_flags & AF_ARYOK) {
632 sp = do_repeatary(arglast);
633 goto array_return;
634 }
635 STR_SSET(str,st[1]);
636 anum = (int)str_gnum(st[2]);
637 if (anum >= 1) {
638 tmpstr = Str_new(50, 0);
639 tmps = str_get(str);
640 str_nset(tmpstr,tmps,str->str_cur);
641 tmps = str_get(tmpstr); /* force to be string */
642 STR_GROW(str, (anum * str->str_cur) + 1);
643 repeatcpy(str->str_ptr, tmps, tmpstr->str_cur, anum);
644 str->str_cur *= anum;
645 str->str_ptr[str->str_cur] = '\0';
646 str->str_nok = 0;
647 str_free(tmpstr);
648 }
649 else {
650 if (dowarn && st[2]->str_pok && !looks_like_number(st[2]))
651 warn("Right operand of x is not numeric");
652 str_sset(str,&str_no);
653 }
654 STABSET(str);
655 break;
656 case O_MATCH:
657 sp = do_match(str,arg,
658 gimme,arglast);
659 if (gimme == G_ARRAY)
660 goto array_return;
661 STABSET(str);
662 break;
663 case O_NMATCH:
664 sp = do_match(str,arg,
665 G_SCALAR,arglast);
666 str_sset(str, str_true(str) ? &str_no : &str_yes);
667 STABSET(str);
668 break;
669 case O_SUBST:
670 sp = do_subst(str,arg,arglast[0]);
671 goto array_return;
672 case O_NSUBST:
673 sp = do_subst(str,arg,arglast[0]);
674 str = arg->arg_ptr.arg_str;
675 str_set(str, str_true(str) ? No : Yes);
676 goto array_return;
677 case O_ASSIGN:
678 if (arg[1].arg_flags & AF_ARYOK) {
679 if (arg->arg_len == 1) {
680 arg->arg_type = O_LOCAL;
681 goto local;
682 }
683 else {
684 arg->arg_type = O_AASSIGN;
685 goto aassign;
686 }
687 }
688 else {
689 arg->arg_type = O_SASSIGN;
690 goto sassign;
691 }
692 case O_LOCAL:
693 local:
694 arglast[2] = arglast[1]; /* push a null array */
695 /* FALL THROUGH */
696 case O_AASSIGN:
697 aassign:
698 sp = do_assign(arg,
699 gimme,arglast);
700 goto array_return;
701 case O_SASSIGN:
702 sassign:
703#ifdef TAINT
704 if (tainted && !st[2]->str_tainted)
705 tainted = 0;
706#endif
707 STR_SSET(str, st[2]);
708 STABSET(str);
709 break;
710 case O_CHOP:
711 st -= arglast[0];
712 str = arg->arg_ptr.arg_str;
713 for (sp = arglast[0] + 1; sp <= arglast[1]; sp++)
714 do_chop(str,st[sp]);
715 st += arglast[0];
716 break;
717 case O_DEFINED:
718 if (arg[1].arg_type & A_DONT) {
719 sp = do_defined(str,arg,
720 gimme,arglast);
721 goto array_return;
722 }
723 else if (str->str_pok || str->str_nok)
724 goto say_yes;
725 goto say_no;
726 case O_UNDEF:
727 if (arg[1].arg_type & A_DONT) {
728 sp = do_undef(str,arg,
729 gimme,arglast);
730 goto array_return;
731 }
732 else if (str != stab_val(defstab)) {
733 if (str->str_len) {
734 if (str->str_state == SS_INCR)
735 Str_Grow(str,0);
736 Safefree(str->str_ptr);
737 str->str_ptr = Nullch;
738 str->str_len = 0;
739 }
740 str->str_pok = str->str_nok = 0;
741 STABSET(str);
742 }
743 goto say_undef;
744 case O_STUDY:
745 sp = do_study(str,arg,
746 gimme,arglast);
747 goto array_return;
748 case O_POW:
749 value = str_gnum(st[1]);
750 value = pow(value,str_gnum(st[2]));
751 goto donumset;
752 case O_MULTIPLY:
753 value = str_gnum(st[1]);
754 value *= str_gnum(st[2]);
755 goto donumset;
756 case O_DIVIDE:
757 if ((value = str_gnum(st[2])) == 0.0)
758 fatal("Illegal division by zero");
759#ifdef SLOPPYDIVIDE
760 /* insure that 20./5. == 4. */
761 {
762 double x;
763 int k;
764 x = str_gnum(st[1]);
765 if ((double)(int)x == x &&
766 (double)(int)value == value &&
767 (k = (int)x/(int)value)*(int)value == (int)x) {
768 value = k;
769 } else {
770 value = x/value;
771 }
772 }
773#else
774 value = str_gnum(st[1]) / value;
775#endif
776 goto donumset;
777 case O_MODULO:
778 tmpulong = (unsigned long) str_gnum(st[2]);
779 if (tmpulong == 0L)
780 fatal("Illegal modulus zero");
781#ifndef lint
782 value = str_gnum(st[1]);
783 if (value >= 0.0)
784 value = (double)(((unsigned long)value) % tmpulong);
785 else {
786 tmplong = (long)value;
787 value = (double)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
788 }
789#endif
790 goto donumset;
791 case O_ADD:
792 value = str_gnum(st[1]);
793 value += str_gnum(st[2]);
794 goto donumset;
795 case O_SUBTRACT:
796 value = str_gnum(st[1]);
797 value -= str_gnum(st[2]);
798 goto donumset;
799 case O_LEFT_SHIFT:
800 value = str_gnum(st[1]);
801 anum = (int)str_gnum(st[2]);
802#ifndef lint
803 value = (double)(U_L(value) << anum);
804#endif
805 goto donumset;
806 case O_RIGHT_SHIFT:
807 value = str_gnum(st[1]);
808 anum = (int)str_gnum(st[2]);
809#ifndef lint
810 value = (double)(U_L(value) >> anum);
811#endif
812 goto donumset;
813 case O_LT:
814 value = str_gnum(st[1]);
815 value = (value < str_gnum(st[2])) ? 1.0 : 0.0;
816 goto donumset;
817 case O_GT:
818 value = str_gnum(st[1]);
819 value = (value > str_gnum(st[2])) ? 1.0 : 0.0;
820 goto donumset;
821 case O_LE:
822 value = str_gnum(st[1]);
823 value = (value <= str_gnum(st[2])) ? 1.0 : 0.0;
824 goto donumset;
825 case O_GE:
826 value = str_gnum(st[1]);
827 value = (value >= str_gnum(st[2])) ? 1.0 : 0.0;
828 goto donumset;
829 case O_EQ:
830 if (dowarn) {
831 if ((!st[1]->str_nok && !looks_like_number(st[1])) ||
832 (!st[2]->str_nok && !looks_like_number(st[2])) )
833 warn("Possible use of == on string value");
834 }
835 value = str_gnum(st[1]);
836 value = (value == str_gnum(st[2])) ? 1.0 : 0.0;
837 goto donumset;
838 case O_NE:
839 value = str_gnum(st[1]);
840 value = (value != str_gnum(st[2])) ? 1.0 : 0.0;
841 goto donumset;
842 case O_NCMP:
843 value = str_gnum(st[1]);
844 value -= str_gnum(st[2]);
845 if (value > 0.0)
846 value = 1.0;
847 else if (value < 0.0)
848 value = -1.0;
849 goto donumset;
850 case O_BIT_AND:
851 if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
852 value = str_gnum(st[1]);
853#ifndef lint
854 value = (double)(U_L(value) & U_L(str_gnum(st[2])));
855#endif
856 goto donumset;
857 }
858 else
859 do_vop(optype,str,st[1],st[2]);
860 break;
861 case O_XOR:
862 if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
863 value = str_gnum(st[1]);
864#ifndef lint
865 value = (double)(U_L(value) ^ U_L(str_gnum(st[2])));
866#endif
867 goto donumset;
868 }
869 else
870 do_vop(optype,str,st[1],st[2]);
871 break;
872 case O_BIT_OR:
873 if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
874 value = str_gnum(st[1]);
875#ifndef lint
876 value = (double)(U_L(value) | U_L(str_gnum(st[2])));
877#endif
878 goto donumset;
879 }
880 else
881 do_vop(optype,str,st[1],st[2]);
882 break;
883/* use register in evaluating str_true() */
884 case O_AND:
885 if (str_true(st[1])) {
886 anum = 2;
887 optype = O_ITEM2;
888 argflags = arg[anum].arg_flags;
889 if (gimme == G_ARRAY)
890 argflags |= AF_ARYOK;
891 argtype = arg[anum].arg_type & A_MASK;
892 argptr = arg[anum].arg_ptr;
893 maxarg = anum = 1;
894 sp = arglast[0];
895 st -= sp;
896 goto re_eval;
897 }
898 else {
899 if (assigning) {
900 str_sset(str, st[1]);
901 STABSET(str);
902 }
903 else
904 str = st[1];
905 break;
906 }
907 case O_OR:
908 if (str_true(st[1])) {
909 if (assigning) {
910 str_sset(str, st[1]);
911 STABSET(str);
912 }
913 else
914 str = st[1];
915 break;
916 }
917 else {
918 anum = 2;
919 optype = O_ITEM2;
920 argflags = arg[anum].arg_flags;
921 if (gimme == G_ARRAY)
922 argflags |= AF_ARYOK;
923 argtype = arg[anum].arg_type & A_MASK;
924 argptr = arg[anum].arg_ptr;
925 maxarg = anum = 1;
926 sp = arglast[0];
927 st -= sp;
928 goto re_eval;
929 }
930 case O_COND_EXPR:
931 anum = (str_true(st[1]) ? 2 : 3);
932 optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
933 argflags = arg[anum].arg_flags;
934 if (gimme == G_ARRAY)
935 argflags |= AF_ARYOK;
936 argtype = arg[anum].arg_type & A_MASK;
937 argptr = arg[anum].arg_ptr;
938 maxarg = anum = 1;
939 sp = arglast[0];
940 st -= sp;
941 goto re_eval;
942 case O_COMMA:
943 if (gimme == G_ARRAY)
944 goto array_return;
945 str = st[2];
946 break;
947 case O_NEGATE:
948 value = -str_gnum(st[1]);
949 goto donumset;
950 case O_NOT:
951#ifdef NOTNOT
952 { char xxx = str_true(st[1]); value = (double) !xxx; }
953#else
954 value = (double) !str_true(st[1]);
955#endif
956 goto donumset;
957 case O_COMPLEMENT:
958 if (!sawvec || st[1]->str_nok) {
959#ifndef lint
960 value = (double) ~U_L(str_gnum(st[1]));
961#endif
962 goto donumset;
963 }
964 else {
965 STR_SSET(str,st[1]);
966 tmps = str_get(str);
967 for (anum = str->str_cur; anum; anum--, tmps++)
968 *tmps = ~*tmps;
969 }
970 break;
971 case O_SELECT:
972 stab_efullname(str,defoutstab);
973 if (maxarg > 0) {
974 if ((arg[1].arg_type & A_MASK) == A_WORD)
975 defoutstab = arg[1].arg_ptr.arg_stab;
976 else
977 defoutstab = stabent(str_get(st[1]),TRUE);
978 if (!stab_io(defoutstab))
979 stab_io(defoutstab) = stio_new();
980 curoutstab = defoutstab;
981 }
982 STABSET(str);
983 break;
984 case O_WRITE:
985 if (maxarg == 0)
986 stab = defoutstab;
987 else if ((arg[1].arg_type & A_MASK) == A_WORD) {
988 if (!(stab = arg[1].arg_ptr.arg_stab))
989 stab = defoutstab;
990 }
991 else
992 stab = stabent(str_get(st[1]),TRUE);
993 if (!stab_io(stab)) {
994 str_set(str, No);
995 STABSET(str);
996 break;
997 }
998 curoutstab = stab;
999 fp = stab_io(stab)->ofp;
1000 if (stab_io(stab)->fmt_stab)
1001 form = stab_form(stab_io(stab)->fmt_stab);
1002 else
1003 form = stab_form(stab);
1004 if (!form || !fp) {
1005 if (dowarn) {
1006 if (form)
1007 warn("No format for filehandle");
1008 else {
1009 if (stab_io(stab)->ifp)
1010 warn("Filehandle only opened for input");
1011 else
1012 warn("Write on closed filehandle");
1013 }
1014 }
1015 str_set(str, No);
1016 STABSET(str);
1017 break;
1018 }
1019 format(&outrec,form,sp);
1020 do_write(&outrec,stab,sp);
1021 if (stab_io(stab)->flags & IOF_FLUSH)
1022 (void)fflush(fp);
1023 str_set(str, Yes);
1024 STABSET(str);
1025 break;
1026 case O_DBMOPEN:
1027#ifdef SOME_DBM
1028 anum = arg[1].arg_type & A_MASK;
1029 if (anum == A_WORD || anum == A_STAB)
1030 stab = arg[1].arg_ptr.arg_stab;
1031 else
1032 stab = stabent(str_get(st[1]),TRUE);
1033 if (st[3]->str_nok || st[3]->str_pok)
1034 anum = (int)str_gnum(st[3]);
1035 else
1036 anum = -1;
1037 value = (double)hdbmopen(stab_hash(stab),str_get(st[2]),anum);
1038 goto donumset;
1039#else
1040 fatal("No dbm or ndbm on this machine");
1041#endif
1042 case O_DBMCLOSE:
1043#ifdef SOME_DBM
1044 anum = arg[1].arg_type & A_MASK;
1045 if (anum == A_WORD || anum == A_STAB)
1046 stab = arg[1].arg_ptr.arg_stab;
1047 else
1048 stab = stabent(str_get(st[1]),TRUE);
1049 hdbmclose(stab_hash(stab));
1050 goto say_yes;
1051#else
1052 fatal("No dbm or ndbm on this machine");
1053#endif
1054 case O_OPEN:
1055 if ((arg[1].arg_type & A_MASK) == A_WORD)
1056 stab = arg[1].arg_ptr.arg_stab;
1057 else
1058 stab = stabent(str_get(st[1]),TRUE);
1059 tmps = str_get(st[2]);
1060 if (do_open(stab,tmps,st[2]->str_cur)) {
1061 value = (double)forkprocess;
1062 stab_io(stab)->lines = 0;
1063 goto donumset;
1064 }
1065 else if (forkprocess == 0) /* we are a new child */
1066 goto say_zero;
1067 else
1068 goto say_undef;
1069 /* break; */
1070 case O_TRANS:
1071 value = (double) do_trans(str,arg);
1072 str = arg->arg_ptr.arg_str;
1073 goto donumset;
1074 case O_NTRANS:
1075 str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No);
1076 str = arg->arg_ptr.arg_str;
1077 break;
1078 case O_CLOSE:
1079 if (maxarg == 0)
1080 stab = defoutstab;
1081 else if ((arg[1].arg_type & A_MASK) == A_WORD)
1082 stab = arg[1].arg_ptr.arg_stab;
1083 else
1084 stab = stabent(str_get(st[1]),TRUE);
1085 str_set(str, do_close(stab,TRUE) ? Yes : No );
1086 STABSET(str);
1087 break;
1088 case O_EACH:
1089 sp = do_each(str,stab_hash(arg[1].arg_ptr.arg_stab),
1090 gimme,arglast);
1091 goto array_return;
1092 case O_VALUES:
1093 case O_KEYS:
1094 sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
1095 gimme,arglast);
1096 goto array_return;
1097 case O_LARRAY:
1098 str->str_nok = str->str_pok = 0;
1099 str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
1100 str->str_state = SS_ARY;
1101 break;
1102 case O_ARRAY:
1103 ary = stab_array(arg[1].arg_ptr.arg_stab);
1104 maxarg = ary->ary_fill + 1;
1105 if (gimme == G_ARRAY) { /* array wanted */
1106 sp = arglast[0];
1107 st -= sp;
1108 if (maxarg > 0 && sp + maxarg > stack->ary_max) {
1109 astore(stack,sp + maxarg, Nullstr);
1110 st = stack->ary_array;
1111 }
1112 st += sp;
1113 Copy(ary->ary_array, &st[1], maxarg, STR*);
1114 sp += maxarg;
1115 goto array_return;
1116 }
1117 else {
1118 value = (double)maxarg;
1119 goto donumset;
1120 }
1121 case O_AELEM:
1122 anum = ((int)str_gnum(st[2])) - arybase;
1123 str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,FALSE);
1124 break;
1125 case O_DELETE:
1126 tmpstab = arg[1].arg_ptr.arg_stab;
1127 tmps = str_get(st[2]);
1128 str = hdelete(stab_hash(tmpstab),tmps,st[2]->str_cur);
1129 if (tmpstab == envstab)
1130 my_setenv(tmps,Nullch);
1131 if (!str)
1132 goto say_undef;
1133 break;
1134 case O_LHASH:
1135 str->str_nok = str->str_pok = 0;
1136 str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
1137 str->str_state = SS_HASH;
1138 break;
1139 case O_HASH:
1140 if (gimme == G_ARRAY) { /* array wanted */
1141 sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
1142 gimme,arglast);
1143 goto array_return;
1144 }
1145 else {
1146 tmpstab = arg[1].arg_ptr.arg_stab;
1147 if (!stab_hash(tmpstab)->tbl_fill)
1148 goto say_zero;
1149 sprintf(buf,"%d/%d",stab_hash(tmpstab)->tbl_fill,
1150 stab_hash(tmpstab)->tbl_max+1);
1151 str_set(str,buf);
1152 }
1153 break;
1154 case O_HELEM:
1155 tmpstab = arg[1].arg_ptr.arg_stab;
1156 tmps = str_get(st[2]);
1157 str = hfetch(stab_hash(tmpstab),tmps,st[2]->str_cur,FALSE);
1158 break;
1159 case O_LAELEM:
1160 anum = ((int)str_gnum(st[2])) - arybase;
1161 str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,TRUE);
1162 if (!str || str == &str_undef)
1163 fatal("Assignment to non-creatable value, subscript %d",anum);
1164 break;
1165 case O_LHELEM:
1166 tmpstab = arg[1].arg_ptr.arg_stab;
1167 tmps = str_get(st[2]);
1168 anum = st[2]->str_cur;
1169 str = hfetch(stab_hash(tmpstab),tmps,anum,TRUE);
1170 if (!str || str == &str_undef)
1171 fatal("Assignment to non-creatable value, subscript \"%s\"",tmps);
1172 if (tmpstab == envstab) /* heavy wizardry going on here */
1173 str_magic(str, tmpstab, 'E', tmps, anum); /* str is now magic */
1174 /* he threw the brick up into the air */
1175 else if (tmpstab == sigstab)
1176 str_magic(str, tmpstab, 'S', tmps, anum);
1177#ifdef SOME_DBM
1178 else if (stab_hash(tmpstab)->tbl_dbm)
1179 str_magic(str, tmpstab, 'D', tmps, anum);
1180#endif
1181 else if (tmpstab == DBline)
1182 str_magic(str, tmpstab, 'L', tmps, anum);
1183 break;
1184 case O_LSLICE:
1185 anum = 2;
1186 argtype = FALSE;
1187 goto do_slice_already;
1188 case O_ASLICE:
1189 anum = 1;
1190 argtype = FALSE;
1191 goto do_slice_already;
1192 case O_HSLICE:
1193 anum = 0;
1194 argtype = FALSE;
1195 goto do_slice_already;
1196 case O_LASLICE:
1197 anum = 1;
1198 argtype = TRUE;
1199 goto do_slice_already;
1200 case O_LHSLICE:
1201 anum = 0;
1202 argtype = TRUE;
1203 do_slice_already:
1204 sp = do_slice(arg[1].arg_ptr.arg_stab,str,anum,argtype,
1205 gimme,arglast);
1206 goto array_return;
1207 case O_SPLICE:
1208 sp = do_splice(stab_array(arg[1].arg_ptr.arg_stab),gimme,arglast);
1209 goto array_return;
1210 case O_PUSH:
1211 if (arglast[2] - arglast[1] != 1)
1212 str = do_push(stab_array(arg[1].arg_ptr.arg_stab),arglast);
1213 else {
1214 str = Str_new(51,0); /* must copy the STR */
1215 str_sset(str,st[2]);
1216 (void)apush(stab_array(arg[1].arg_ptr.arg_stab),str);
1217 }
1218 break;
1219 case O_POP:
1220 str = apop(ary = stab_array(arg[1].arg_ptr.arg_stab));
1221 goto staticalization;
1222 case O_SHIFT:
1223 str = ashift(ary = stab_array(arg[1].arg_ptr.arg_stab));
1224 staticalization:
1225 if (!str)
1226 goto say_undef;
1227 if (ary->ary_flags & ARF_REAL)
1228 (void)str_2mortal(str);
1229 break;
1230 case O_UNPACK:
1231 sp = do_unpack(str,gimme,arglast);
1232 goto array_return;
1233 case O_SPLIT:
1234 value = str_gnum(st[3]);
1235 sp = do_split(str, arg[2].arg_ptr.arg_spat, (int)value,
1236 gimme,arglast);
1237 goto array_return;
1238 case O_LENGTH:
1239 if (maxarg < 1)
1240 value = (double)str_len(stab_val(defstab));
1241 else
1242 value = (double)str_len(st[1]);
1243 goto donumset;
1244 case O_SPRINTF:
1245 do_sprintf(str, sp-arglast[0], st+1);
1246 break;
1247 case O_SUBSTR:
1248 anum = ((int)str_gnum(st[2])) - arybase; /* anum=where to start*/
1249 tmps = str_get(st[1]); /* force conversion to string */
1250 /*SUPPRESS 560*/
1251 if (argtype = (str == st[1]))
1252 str = arg->arg_ptr.arg_str;
1253 if (anum < 0)
1254 anum += st[1]->str_cur + arybase;
1255 if (anum < 0 || anum > st[1]->str_cur)
1256 str_nset(str,"",0);
1257 else {
1258 optype = maxarg < 3 ? st[1]->str_cur : (int)str_gnum(st[3]);
1259 if (optype < 0)
1260 optype = 0;
1261 tmps += anum;
1262 anum = st[1]->str_cur - anum; /* anum=how many bytes left*/
1263 if (anum > optype)
1264 anum = optype;
1265 str_nset(str, tmps, anum);
1266 if (argtype) { /* it's an lvalue! */
1267 Lstring *lstr = (Lstring*)str;
1268
1269 str->str_magic = st[1];
1270 st[1]->str_rare = 's';
1271 lstr->lstr_offset = tmps - str_get(st[1]);
1272 lstr->lstr_len = anum;
1273 }
1274 }
1275 break;
1276 case O_PACK:
1277 /*SUPPRESS 701*/
1278 (void)do_pack(str,arglast);
1279 break;
1280 case O_GREP:
1281 sp = do_grep(arg,str,gimme,arglast);
1282 goto array_return;
1283 case O_JOIN:
1284 do_join(str,arglast);
1285 break;
1286 case O_SLT:
1287 tmps = str_get(st[1]);
1288 value = (double) (str_cmp(st[1],st[2]) < 0);
1289 goto donumset;
1290 case O_SGT:
1291 tmps = str_get(st[1]);
1292 value = (double) (str_cmp(st[1],st[2]) > 0);
1293 goto donumset;
1294 case O_SLE:
1295 tmps = str_get(st[1]);
1296 value = (double) (str_cmp(st[1],st[2]) <= 0);
1297 goto donumset;
1298 case O_SGE:
1299 tmps = str_get(st[1]);
1300 value = (double) (str_cmp(st[1],st[2]) >= 0);
1301 goto donumset;
1302 case O_SEQ:
1303 tmps = str_get(st[1]);
1304 value = (double) str_eq(st[1],st[2]);
1305 goto donumset;
1306 case O_SNE:
1307 tmps = str_get(st[1]);
1308 value = (double) !str_eq(st[1],st[2]);
1309 goto donumset;
1310 case O_SCMP:
1311 tmps = str_get(st[1]);
1312 value = (double) str_cmp(st[1],st[2]);
1313 goto donumset;
1314 case O_SUBR:
1315 sp = do_subr(arg,gimme,arglast);
1316 st = stack->ary_array + arglast[0]; /* maybe realloced */
1317 goto array_return;
1318 case O_DBSUBR:
1319 sp = do_subr(arg,gimme,arglast);
1320 st = stack->ary_array + arglast[0]; /* maybe realloced */
1321 goto array_return;
1322 case O_CALLER:
1323 sp = do_caller(arg,maxarg,gimme,arglast);
1324 st = stack->ary_array + arglast[0]; /* maybe realloced */
1325 goto array_return;
1326 case O_SORT:
1327 sp = do_sort(str,arg,
1328 gimme,arglast);
1329 goto array_return;
1330 case O_REVERSE:
1331 if (gimme == G_ARRAY)
1332 sp = do_reverse(arglast);
1333 else
1334 sp = do_sreverse(str, arglast);
1335 goto array_return;
1336 case O_WARN:
1337 if (arglast[2] - arglast[1] != 1) {
1338 do_join(str,arglast);
1339 tmps = str_get(str);
1340 }
1341 else {
1342 str = st[2];
1343 tmps = str_get(st[2]);
1344 }
1345 if (!tmps || !*tmps)
1346 tmps = "Warning: something's wrong";
1347 warn("%s",tmps);
1348 goto say_yes;
1349 case O_DIE:
1350 if (arglast[2] - arglast[1] != 1) {
1351 do_join(str,arglast);
1352 tmps = str_get(str);
1353 }
1354 else {
1355 str = st[2];
1356 tmps = str_get(st[2]);
1357 }
1358 if (!tmps || !*tmps)
1359 tmps = "Died";
1360 fatal("%s",tmps);
1361 goto say_zero;
1362 case O_PRTF:
1363 case O_PRINT:
1364 if ((arg[1].arg_type & A_MASK) == A_WORD)
1365 stab = arg[1].arg_ptr.arg_stab;
1366 else
1367 stab = stabent(str_get(st[1]),TRUE);
1368 if (!stab)
1369 stab = defoutstab;
1370 if (!stab_io(stab)) {
1371 if (dowarn)
1372 warn("Filehandle never opened");
1373 goto say_zero;
1374 }
1375 if (!(fp = stab_io(stab)->ofp)) {
1376 if (dowarn) {
1377 if (stab_io(stab)->ifp)
1378 warn("Filehandle opened only for input");
1379 else
1380 warn("Print on closed filehandle");
1381 }
1382 goto say_zero;
1383 }
1384 else {
1385 if (optype == O_PRTF || arglast[2] - arglast[1] != 1)
1386 value = (double)do_aprint(arg,fp,arglast);
1387 else {
1388 value = (double)do_print(st[2],fp);
1389 if (orslen && optype == O_PRINT)
1390 if (fwrite(ors, 1, orslen, fp) == 0)
1391 goto say_zero;
1392 }
1393 if (stab_io(stab)->flags & IOF_FLUSH)
1394 if (fflush(fp) == EOF)
1395 goto say_zero;
1396 }
1397 goto donumset;
1398 case O_CHDIR:
1399 if (maxarg < 1)
1400 tmps = Nullch;
1401 else
1402 tmps = str_get(st[1]);
1403 if (!tmps || !*tmps) {
1404 tmpstr = hfetch(stab_hash(envstab),"HOME",4,FALSE);
1405 tmps = str_get(tmpstr);
1406 }
1407 if (!tmps || !*tmps) {
1408 tmpstr = hfetch(stab_hash(envstab),"LOGDIR",6,FALSE);
1409 tmps = str_get(tmpstr);
1410 }
1411#ifdef TAINT
1412 TAINT_PROPER("chdir");
1413#endif
1414 value = (double)(chdir(tmps) >= 0);
1415 goto donumset;
1416 case O_EXIT:
1417 if (maxarg < 1)
1418 anum = 0;
1419 else
1420 anum = (int)str_gnum(st[1]);
1421 my_exit(anum);
1422 goto say_zero;
1423 case O_RESET:
1424 if (maxarg < 1)
1425 tmps = "";
1426 else
1427 tmps = str_get(st[1]);
1428 str_reset(tmps,curcmd->c_stash);
1429 value = 1.0;
1430 goto donumset;
1431 case O_LIST:
1432 if (gimme == G_ARRAY)
1433 goto array_return;
1434 if (maxarg > 0)
1435 str = st[sp - arglast[0]]; /* unwanted list, return last item */
1436 else
1437 str = &str_undef;
1438 break;
1439 case O_EOF:
1440 if (maxarg <= 0)
1441 stab = last_in_stab;
1442 else if ((arg[1].arg_type & A_MASK) == A_WORD)
1443 stab = arg[1].arg_ptr.arg_stab;
1444 else
1445 stab = stabent(str_get(st[1]),TRUE);
1446 str_set(str, do_eof(stab) ? Yes : No);
1447 STABSET(str);
1448 break;
1449 case O_GETC:
1450 if (maxarg <= 0)
1451 stab = stdinstab;
1452 else if ((arg[1].arg_type & A_MASK) == A_WORD)
1453 stab = arg[1].arg_ptr.arg_stab;
1454 else
1455 stab = stabent(str_get(st[1]),TRUE);
1456 if (!stab)
1457 stab = argvstab;
1458 if (!stab || do_eof(stab)) /* make sure we have fp with something */
1459 goto say_undef;
1460 else {
1461#ifdef TAINT
1462 tainted = 1;
1463#endif
1464 str_set(str," ");
1465 *str->str_ptr = getc(stab_io(stab)->ifp); /* should never be EOF */
1466 }
1467 STABSET(str);
1468 break;
1469 case O_TELL:
1470 if (maxarg <= 0)
1471 stab = last_in_stab;
1472 else if ((arg[1].arg_type & A_MASK) == A_WORD)
1473 stab = arg[1].arg_ptr.arg_stab;
1474 else
1475 stab = stabent(str_get(st[1]),TRUE);
1476#ifndef lint
1477 value = (double)do_tell(stab);
1478#else
1479 (void)do_tell(stab);
1480#endif
1481 goto donumset;
1482 case O_RECV:
1483 case O_READ:
1484 case O_SYSREAD:
1485 if ((arg[1].arg_type & A_MASK) == A_WORD)
1486 stab = arg[1].arg_ptr.arg_stab;
1487 else
1488 stab = stabent(str_get(st[1]),TRUE);
1489 tmps = str_get(st[2]);
1490 anum = (int)str_gnum(st[3]);
1491 errno = 0;
1492 maxarg = sp - arglast[0];
1493 if (maxarg > 4)
1494 warn("Too many args on read");
1495 if (maxarg == 4)
1496 maxarg = (int)str_gnum(st[4]);
1497 else
1498 maxarg = 0;
1499 if (!stab_io(stab) || !stab_io(stab)->ifp)
1500 goto say_undef;
1501#ifdef HAS_SOCKET
1502 if (optype == O_RECV) {
1503 argtype = sizeof buf;
1504 STR_GROW(st[2], anum+1), (tmps = str_get(st[2])); /* sneaky */
1505 anum = recvfrom(fileno(stab_io(stab)->ifp), tmps, anum, maxarg,
1506 buf, &argtype);
1507 if (anum >= 0) {
1508 st[2]->str_cur = anum;
1509 st[2]->str_ptr[anum] = '\0';
1510 str_nset(str,buf,argtype);
1511 }
1512 else
1513 str_sset(str,&str_undef);
1514 break;
1515 }
1516#else
1517 if (optype == O_RECV)
1518 goto badsock;
1519#endif
1520 STR_GROW(st[2], anum+maxarg+1), (tmps = str_get(st[2])); /* sneaky */
1521 if (optype == O_SYSREAD) {
1522 anum = read(fileno(stab_io(stab)->ifp), tmps+maxarg, anum);
1523 }
1524 else
1525#ifdef HAS_SOCKET
1526 if (stab_io(stab)->type == 's') {
1527 argtype = sizeof buf;
1528 anum = recvfrom(fileno(stab_io(stab)->ifp), tmps+maxarg, anum, 0,
1529 buf, &argtype);
1530 }
1531 else
1532#endif
1533 anum = fread(tmps+maxarg, 1, anum, stab_io(stab)->ifp);
1534 if (anum < 0)
1535 goto say_undef;
1536 st[2]->str_cur = anum+maxarg;
1537 st[2]->str_ptr[anum+maxarg] = '\0';
1538 value = (double)anum;
1539 goto donumset;
1540 case O_SYSWRITE:
1541 case O_SEND:
1542 if ((arg[1].arg_type & A_MASK) == A_WORD)
1543 stab = arg[1].arg_ptr.arg_stab;
1544 else
1545 stab = stabent(str_get(st[1]),TRUE);
1546 tmps = str_get(st[2]);
1547 anum = (int)str_gnum(st[3]);
1548 errno = 0;
1549 stio = stab_io(stab);
1550 maxarg = sp - arglast[0];
1551 if (!stio || !stio->ifp) {
1552 anum = -1;
1553 if (dowarn) {
1554 if (optype == O_SYSWRITE)
1555 warn("Syswrite on closed filehandle");
1556 else
1557 warn("Send on closed socket");
1558 }
1559 }
1560 else if (optype == O_SYSWRITE) {
1561 if (maxarg > 4)
1562 warn("Too many args on syswrite");
1563 if (maxarg == 4)
1564 optype = (int)str_gnum(st[4]);
1565 else
1566 optype = 0;
1567 anum = write(fileno(stab_io(stab)->ifp), tmps+optype, anum);
1568 }
1569#ifdef HAS_SOCKET
1570 else if (maxarg >= 4) {
1571 if (maxarg > 4)
1572 warn("Too many args on send");
1573 tmps2 = str_get(st[4]);
1574 anum = sendto(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur,
1575 anum, tmps2, st[4]->str_cur);
1576 }
1577 else
1578 anum = send(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur, anum);
1579#else
1580 else
1581 goto badsock;
1582#endif
1583 if (anum < 0)
1584 goto say_undef;
1585 value = (double)anum;
1586 goto donumset;
1587 case O_SEEK:
1588 if ((arg[1].arg_type & A_MASK) == A_WORD)
1589 stab = arg[1].arg_ptr.arg_stab;
1590 else
1591 stab = stabent(str_get(st[1]),TRUE);
1592 value = str_gnum(st[2]);
1593 str_set(str, do_seek(stab,
1594 (long)value, (int)str_gnum(st[3]) ) ? Yes : No);
1595 STABSET(str);
1596 break;
1597 case O_RETURN:
1598 tmps = "_SUB_"; /* just fake up a "last _SUB_" */
1599 optype = O_LAST;
1600 if (curcsv && curcsv->wantarray == G_ARRAY) {
1601 lastretstr = Nullstr;
1602 lastspbase = arglast[1];
1603 lastsize = arglast[2] - arglast[1];
1604 }
1605 else
1606 lastretstr = str_mortal(st[arglast[2] - arglast[0]]);
1607 goto dopop;
1608 case O_REDO:
1609 case O_NEXT:
1610 case O_LAST:
1611 tmps = Nullch;
1612 if (maxarg > 0) {
1613 tmps = str_get(arg[1].arg_ptr.arg_str);
1614 dopop:
1615 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1616 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1617#ifdef DEBUGGING
1618 if (debug & 4) {
1619 deb("(Skipping label #%d %s)\n",loop_ptr,
1620 loop_stack[loop_ptr].loop_label);
1621 }
1622#endif
1623 loop_ptr--;
1624 }
1625#ifdef DEBUGGING
1626 if (debug & 4) {
1627 deb("(Found label #%d %s)\n",loop_ptr,
1628 loop_stack[loop_ptr].loop_label);
1629 }
1630#endif
1631 }
1632 if (loop_ptr < 0) {
1633 if (tmps && strEQ(tmps, "_SUB_"))
1634 fatal("Can't return outside a subroutine");
1635 fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>");
1636 }
1637 if (!lastretstr && optype == O_LAST && lastsize) {
1638 st -= arglast[0];
1639 st += lastspbase + 1;
1640 optype = loop_stack[loop_ptr].loop_sp - lastspbase; /* negative */
1641 if (optype) {
1642 for (anum = lastsize; anum > 0; anum--,st++)
1643 st[optype] = str_mortal(st[0]);
1644 }
1645 longjmp(loop_stack[loop_ptr].loop_env, O_LAST);
1646 }
1647 longjmp(loop_stack[loop_ptr].loop_env, optype);
1648 case O_DUMP:
1649 case O_GOTO:/* shudder */
1650 goto_targ = str_get(arg[1].arg_ptr.arg_str);
1651 if (!*goto_targ)
1652 goto_targ = Nullch; /* just restart from top */
1653 if (optype == O_DUMP) {
1654 do_undump = TRUE;
1655 my_unexec();
1656 }
1657 longjmp(top_env, 1);
1658 case O_INDEX:
1659 tmps = str_get(st[1]);
1660 if (maxarg < 3)
1661 anum = 0;
1662 else {
1663 anum = (int) str_gnum(st[3]) - arybase;
1664 if (anum < 0)
1665 anum = 0;
1666 else if (anum > st[1]->str_cur)
1667 anum = st[1]->str_cur;
1668 }
1669#ifndef lint
1670 if (!(tmps2 = fbminstr((unsigned char*)tmps + anum,
1671 (unsigned char*)tmps + st[1]->str_cur, st[2])))
1672#else
1673 if (tmps2 = fbminstr(Null(unsigned char*),Null(unsigned char*),Nullstr))
1674#endif
1675 value = (double)(-1 + arybase);
1676 else
1677 value = (double)(tmps2 - tmps + arybase);
1678 goto donumset;
1679 case O_RINDEX:
1680 tmps = str_get(st[1]);
1681 tmps2 = str_get(st[2]);
1682 if (maxarg < 3)
1683 anum = st[1]->str_cur;
1684 else {
1685 anum = (int) str_gnum(st[3]) - arybase + st[2]->str_cur;
1686 if (anum < 0)
1687 anum = 0;
1688 else if (anum > st[1]->str_cur)
1689 anum = st[1]->str_cur;
1690 }
1691#ifndef lint
1692 if (!(tmps2 = rninstr(tmps, tmps + anum,
1693 tmps2, tmps2 + st[2]->str_cur)))
1694#else
1695 if (tmps2 = rninstr(Nullch,Nullch,Nullch,Nullch))
1696#endif
1697 value = (double)(-1 + arybase);
1698 else
1699 value = (double)(tmps2 - tmps + arybase);
1700 goto donumset;
1701 case O_TIME:
1702#ifndef lint
1703 value = (double) time(Null(long*));
1704#endif
1705 goto donumset;
1706 case O_TMS:
1707 sp = do_tms(str,gimme,arglast);
1708 goto array_return;
1709 case O_LOCALTIME:
1710 if (maxarg < 1)
1711 (void)time(&when);
1712 else
1713 when = (time_t)str_gnum(st[1]);
1714 sp = do_time(str,localtime(&when),
1715 gimme,arglast);
1716 goto array_return;
1717 case O_GMTIME:
1718 if (maxarg < 1)
1719 (void)time(&when);
1720 else
1721 when = (time_t)str_gnum(st[1]);
1722 sp = do_time(str,gmtime(&when),
1723 gimme,arglast);
1724 goto array_return;
1725 case O_TRUNCATE:
1726 sp = do_truncate(str,arg,
1727 gimme,arglast);
1728 goto array_return;
1729 case O_LSTAT:
1730 case O_STAT:
1731 sp = do_stat(str,arg,
1732 gimme,arglast);
1733 goto array_return;
1734 case O_CRYPT:
1735#ifdef HAS_CRYPT
1736 tmps = str_get(st[1]);
1737#ifdef FCRYPT
1738 str_set(str,fcrypt(tmps,str_get(st[2])));
1739#else
1740 str_set(str,crypt(tmps,str_get(st[2])));
1741#endif
1742#else
1743 fatal(
1744 "The crypt() function is unimplemented due to excessive paranoia.");
1745#endif
1746 break;
1747 case O_ATAN2:
1748 value = str_gnum(st[1]);
1749 value = atan2(value,str_gnum(st[2]));
1750 goto donumset;
1751 case O_SIN:
1752 if (maxarg < 1)
1753 value = str_gnum(stab_val(defstab));
1754 else
1755 value = str_gnum(st[1]);
1756 value = sin(value);
1757 goto donumset;
1758 case O_COS:
1759 if (maxarg < 1)
1760 value = str_gnum(stab_val(defstab));
1761 else
1762 value = str_gnum(st[1]);
1763 value = cos(value);
1764 goto donumset;
1765 case O_RAND:
1766 if (maxarg < 1)
1767 value = 1.0;
1768 else
1769 value = str_gnum(st[1]);
1770 if (value == 0.0)
1771 value = 1.0;
1772#if RANDBITS == 31
1773 value = rand() * value / 2147483648.0;
1774#else
1775#if RANDBITS == 16
1776 value = rand() * value / 65536.0;
1777#else
1778#if RANDBITS == 15
1779 value = rand() * value / 32768.0;
1780#else
1781 value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
1782#endif
1783#endif
1784#endif
1785 goto donumset;
1786 case O_SRAND:
1787 if (maxarg < 1) {
1788 (void)time(&when);
1789 anum = when;
1790 }
1791 else
1792 anum = (int)str_gnum(st[1]);
1793 (void)srand(anum);
1794 goto say_yes;
1795 case O_EXP:
1796 if (maxarg < 1)
1797 value = str_gnum(stab_val(defstab));
1798 else
1799 value = str_gnum(st[1]);
1800 value = exp(value);
1801 goto donumset;
1802 case O_LOG:
1803 if (maxarg < 1)
1804 value = str_gnum(stab_val(defstab));
1805 else
1806 value = str_gnum(st[1]);
1807 if (value <= 0.0)
1808 fatal("Can't take log of %g\n", value);
1809 value = log(value);
1810 goto donumset;
1811 case O_SQRT:
1812 if (maxarg < 1)
1813 value = str_gnum(stab_val(defstab));
1814 else
1815 value = str_gnum(st[1]);
1816 if (value < 0.0)
1817 fatal("Can't take sqrt of %g\n", value);
1818 value = sqrt(value);
1819 goto donumset;
1820 case O_INT:
1821 if (maxarg < 1)
1822 value = str_gnum(stab_val(defstab));
1823 else
1824 value = str_gnum(st[1]);
1825 if (value >= 0.0)
1826 (void)modf(value,&value);
1827 else {
1828 (void)modf(-value,&value);
1829 value = -value;
1830 }
1831 goto donumset;
1832 case O_ORD:
1833 if (maxarg < 1)
1834 tmps = str_get(stab_val(defstab));
1835 else
1836 tmps = str_get(st[1]);
1837#ifndef I286
1838 value = (double) (*tmps & 255);
1839#else
1840 anum = (int) *tmps;
1841 value = (double) (anum & 255);
1842#endif
1843 goto donumset;
1844 case O_ALARM:
1845#ifdef HAS_ALARM
1846 if (maxarg < 1)
1847 tmps = str_get(stab_val(defstab));
1848 else
1849 tmps = str_get(st[1]);
1850 if (!tmps)
1851 tmps = "0";
1852 anum = alarm((unsigned int)atoi(tmps));
1853 if (anum < 0)
1854 goto say_undef;
1855 value = (double)anum;
1856 goto donumset;
1857#else
1858 fatal("Unsupported function alarm");
1859 break;
1860#endif
1861 case O_SLEEP:
1862 if (maxarg < 1)
1863 tmps = Nullch;
1864 else
1865 tmps = str_get(st[1]);
1866 (void)time(&when);
1867 if (!tmps || !*tmps)
1868 sleep((32767<<16)+32767);
1869 else
1870 sleep((unsigned int)atoi(tmps));
1871#ifndef lint
1872 value = (double)when;
1873 (void)time(&when);
1874 value = ((double)when) - value;
1875#endif
1876 goto donumset;
1877 case O_RANGE:
1878 sp = do_range(gimme,arglast);
1879 goto array_return;
1880 case O_F_OR_R:
1881 if (gimme == G_ARRAY) { /* it's a range */
1882 /* can we optimize to constant array? */
1883 if ((arg[1].arg_type & A_MASK) == A_SINGLE &&
1884 (arg[2].arg_type & A_MASK) == A_SINGLE) {
1885 st[2] = arg[2].arg_ptr.arg_str;
1886 sp = do_range(gimme,arglast);
1887 st = stack->ary_array;
1888 maxarg = sp - arglast[0];
1889 str_free(arg[1].arg_ptr.arg_str);
1890 arg[1].arg_ptr.arg_str = Nullstr;
1891 str_free(arg[2].arg_ptr.arg_str);
1892 arg[2].arg_ptr.arg_str = Nullstr;
1893 arg->arg_type = O_ARRAY;
1894 arg[1].arg_type = A_STAB|A_DONT;
1895 arg->arg_len = 1;
1896 stab = arg[1].arg_ptr.arg_stab = aadd(genstab());
1897 ary = stab_array(stab);
1898 afill(ary,maxarg - 1);
1899 anum = maxarg;
1900 st += arglast[0]+1;
1901 while (maxarg-- > 0)
1902 ary->ary_array[maxarg] = str_smake(st[maxarg]);
1903 st -= arglast[0]+1;
1904 goto array_return;
1905 }
1906 arg->arg_type = optype = O_RANGE;
1907 maxarg = arg->arg_len = 2;
1908 anum = 2;
1909 arg[anum].arg_flags &= ~AF_ARYOK;
1910 argflags = arg[anum].arg_flags;
1911 argtype = arg[anum].arg_type & A_MASK;
1912 arg[anum].arg_type = argtype;
1913 argptr = arg[anum].arg_ptr;
1914 sp = arglast[0];
1915 st -= sp;
1916 sp++;
1917 goto re_eval;
1918 }
1919 arg->arg_type = O_FLIP;
1920 /* FALL THROUGH */
1921 case O_FLIP:
1922 if ((arg[1].arg_type & A_MASK) == A_SINGLE ?
1923 last_in_stab && (int)str_gnum(st[1]) == stab_io(last_in_stab)->lines
1924 :
1925 str_true(st[1]) ) {
1926 arg[2].arg_type &= ~A_DONT;
1927 arg[1].arg_type |= A_DONT;
1928 arg->arg_type = optype = O_FLOP;
1929 if (arg->arg_flags & AF_COMMON) {
1930 str_numset(str,0.0);
1931 anum = 2;
1932 argflags = arg[2].arg_flags;
1933 argtype = arg[2].arg_type & A_MASK;
1934 argptr = arg[2].arg_ptr;
1935 sp = arglast[0];
1936 st -= sp++;
1937 goto re_eval;
1938 }
1939 else {
1940 str_numset(str,1.0);
1941 break;
1942 }
1943 }
1944 str_set(str,"");
1945 break;
1946 case O_FLOP:
1947 str_inc(str);
1948 if ((arg[2].arg_type & A_MASK) == A_SINGLE ?
1949 last_in_stab && (int)str_gnum(st[2]) == stab_io(last_in_stab)->lines
1950 :
1951 str_true(st[2]) ) {
1952 arg->arg_type = O_FLIP;
1953 arg[1].arg_type &= ~A_DONT;
1954 arg[2].arg_type |= A_DONT;
1955 str_cat(str,"E0");
1956 }
1957 break;
1958 case O_FORK:
1959#ifdef HAS_FORK
1960 anum = fork();
1961 if (anum < 0)
1962 goto say_undef;
1963 if (!anum) {
1964 /*SUPPRESS 560*/
1965 if (tmpstab = stabent("$",allstabs))
1966 str_numset(STAB_STR(tmpstab),(double)getpid());
1967 hclear(pidstatus, FALSE); /* no kids, so don't wait for 'em */
1968 }
1969 value = (double)anum;
1970 goto donumset;
1971#else
1972 fatal("Unsupported function fork");
1973 break;
1974#endif
1975 case O_WAIT:
1976#ifdef HAS_WAIT
1977#ifndef lint
1978 anum = wait(&argflags);
1979 if (anum > 0)
1980 pidgone(anum,argflags);
1981 value = (double)anum;
1982#endif
1983 statusvalue = (unsigned short)argflags;
1984 goto donumset;
1985#else
1986 fatal("Unsupported function wait");
1987 break;
1988#endif
1989 case O_WAITPID:
1990#ifdef HAS_WAIT
1991#ifndef lint
1992 anum = (int)str_gnum(st[1]);
1993 optype = (int)str_gnum(st[2]);
1994 anum = wait4pid(anum, &argflags,optype);
1995 value = (double)anum;
1996#endif
1997 statusvalue = (unsigned short)argflags;
1998 goto donumset;
1999#else
2000 fatal("Unsupported function wait");
2001 break;
2002#endif
2003 case O_SYSTEM:
2004#ifdef HAS_FORK
2005#ifdef TAINT
2006 if (arglast[2] - arglast[1] == 1) {
2007 taintenv();
2008 tainted |= st[2]->str_tainted;
2009 TAINT_PROPER("system");
2010 }
2011#endif
2012 while ((anum = vfork()) == -1) {
2013 if (errno != EAGAIN) {
2014 value = -1.0;
2015 goto donumset;
2016 }
2017 sleep(5);
2018 }
2019 if (anum > 0) {
2020#ifndef lint
2021 ihand = signal(SIGINT, SIG_IGN);
2022 qhand = signal(SIGQUIT, SIG_IGN);
2023 argtype = wait4pid(anum, &argflags, 0);
2024#else
2025 ihand = qhand = 0;
2026#endif
2027 (void)signal(SIGINT, ihand);
2028 (void)signal(SIGQUIT, qhand);
2029 statusvalue = (unsigned short)argflags;
2030 if (argtype < 0)
2031 value = -1.0;
2032 else {
2033 value = (double)((unsigned int)argflags & 0xffff);
2034 }
2035 do_execfree(); /* free any memory child malloced on vfork */
2036 goto donumset;
2037 }
2038 if ((arg[1].arg_type & A_MASK) == A_STAB)
2039 value = (double)do_aexec(st[1],arglast);
2040 else if (arglast[2] - arglast[1] != 1)
2041 value = (double)do_aexec(Nullstr,arglast);
2042 else {
2043 value = (double)do_exec(str_get(str_mortal(st[2])));
2044 }
2045 _exit(-1);
2046#else /* ! FORK */
2047 if ((arg[1].arg_type & A_MASK) == A_STAB)
2048 value = (double)do_aspawn(st[1],arglast);
2049 else if (arglast[2] - arglast[1] != 1)
2050 value = (double)do_aspawn(Nullstr,arglast);
2051 else {
2052 value = (double)do_spawn(str_get(str_mortal(st[2])));
2053 }
2054 goto donumset;
2055#endif /* FORK */
2056 case O_EXEC_OP:
2057 if ((arg[1].arg_type & A_MASK) == A_STAB)
2058 value = (double)do_aexec(st[1],arglast);
2059 else if (arglast[2] - arglast[1] != 1)
2060 value = (double)do_aexec(Nullstr,arglast);
2061 else {
2062#ifdef TAINT
2063 taintenv();
2064 tainted |= st[2]->str_tainted;
2065 TAINT_PROPER("exec");
2066#endif
2067 value = (double)do_exec(str_get(str_mortal(st[2])));
2068 }
2069 goto donumset;
2070 case O_HEX:
2071 if (maxarg < 1)
2072 tmps = str_get(stab_val(defstab));
2073 else
2074 tmps = str_get(st[1]);
2075 value = (double)scanhex(tmps, 99, &argtype);
2076 goto donumset;
2077
2078 case O_OCT:
2079 if (maxarg < 1)
2080 tmps = str_get(stab_val(defstab));
2081 else
2082 tmps = str_get(st[1]);
2083 while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
2084 tmps++;
2085 if (*tmps == 'x')
2086 value = (double)scanhex(++tmps, 99, &argtype);
2087 else
2088 value = (double)scanoct(tmps, 99, &argtype);
2089 goto donumset;
2090
2091/* These common exits are hidden here in the middle of the switches for the
2092 benefit of those machines with limited branch addressing. Sigh. */
2093
2094array_return:
2095#ifdef DEBUGGING
2096 if (debug) {
2097 dlevel--;
2098 if (debug & 8) {
2099 anum = sp - arglast[0];
2100 switch (anum) {
2101 case 0:
2102 deb("%s RETURNS ()\n",opname[optype]);
2103 break;
2104 case 1:
2105 deb("%s RETURNS (\"%s\")\n",opname[optype],
2106 st[1] ? str_get(st[1]) : "");
2107 break;
2108 default:
2109 tmps = st[1] ? str_get(st[1]) : "";
2110 deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype],
2111 anum,tmps,anum==2?"":"...,",
2112 st[anum] ? str_get(st[anum]) : "");
2113 break;
2114 }
2115 }
2116 }
2117#endif
2118 stack_ary = stack->ary_array;
2119 stack_max = stack_ary + stack->ary_max;
2120 stack_sp = stack_ary + sp;
2121 return sp;
2122
2123say_yes:
2124 str = &str_yes;
2125 goto normal_return;
2126
2127say_no:
2128 str = &str_no;
2129 goto normal_return;
2130
2131say_undef:
2132 str = &str_undef;
2133 goto normal_return;
2134
2135say_zero:
2136 value = 0.0;
2137 /* FALL THROUGH */
2138
2139donumset:
2140 str_numset(str,value);
2141 STABSET(str);
2142 st[1] = str;
2143#ifdef DEBUGGING
2144 if (debug) {
2145 dlevel--;
2146 if (debug & 8)
2147 deb("%s RETURNS \"%f\"\n",opname[optype],value);
2148 }
2149#endif
2150 stack_ary = stack->ary_array;
2151 stack_max = stack_ary + stack->ary_max;
2152 stack_sp = stack_ary + arglast[0] + 1;
2153 return arglast[0] + 1;
2154#ifdef SMALLSWITCHES
2155 }
2156 else
2157 switch (optype) {
2158#endif
2159 case O_CHOWN:
2160#ifdef HAS_CHOWN
2161 value = (double)apply(optype,arglast);
2162 goto donumset;
2163#else
2164 fatal("Unsupported function chown");
2165 break;
2166#endif
2167 case O_KILL:
2168#ifdef HAS_KILL
2169 value = (double)apply(optype,arglast);
2170 goto donumset;
2171#else
2172 fatal("Unsupported function kill");
2173 break;
2174#endif
2175 case O_UNLINK:
2176 case O_CHMOD:
2177 case O_UTIME:
2178 value = (double)apply(optype,arglast);
2179 goto donumset;
2180 case O_UMASK:
2181#ifdef HAS_UMASK
2182 if (maxarg < 1) {
2183 anum = umask(0);
2184 (void)umask(anum);
2185 }
2186 else
2187 anum = umask((int)str_gnum(st[1]));
2188 value = (double)anum;
2189#ifdef TAINT
2190 TAINT_PROPER("umask");
2191#endif
2192 goto donumset;
2193#else
2194 fatal("Unsupported function umask");
2195 break;
2196#endif
2197#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2198 case O_MSGGET:
2199 case O_SHMGET:
2200 case O_SEMGET:
2201 if ((anum = do_ipcget(optype, arglast)) == -1)
2202 goto say_undef;
2203 value = (double)anum;
2204 goto donumset;
2205 case O_MSGCTL:
2206 case O_SHMCTL:
2207 case O_SEMCTL:
2208 anum = do_ipcctl(optype, arglast);
2209 if (anum == -1)
2210 goto say_undef;
2211 if (anum != 0) {
2212 value = (double)anum;
2213 goto donumset;
2214 }
2215 str_set(str,"0 but true");
2216 STABSET(str);
2217 break;
2218 case O_MSGSND:
2219 value = (double)(do_msgsnd(arglast) >= 0);
2220 goto donumset;
2221 case O_MSGRCV:
2222 value = (double)(do_msgrcv(arglast) >= 0);
2223 goto donumset;
2224 case O_SEMOP:
2225 value = (double)(do_semop(arglast) >= 0);
2226 goto donumset;
2227 case O_SHMREAD:
2228 case O_SHMWRITE:
2229 value = (double)(do_shmio(optype, arglast) >= 0);
2230 goto donumset;
2231#else /* not SYSVIPC */
2232 case O_MSGGET:
2233 case O_MSGCTL:
2234 case O_MSGSND:
2235 case O_MSGRCV:
2236 case O_SEMGET:
2237 case O_SEMCTL:
2238 case O_SEMOP:
2239 case O_SHMGET:
2240 case O_SHMCTL:
2241 case O_SHMREAD:
2242 case O_SHMWRITE:
2243 fatal("System V IPC is not implemented on this machine");
2244#endif /* not SYSVIPC */
2245 case O_RENAME:
2246 tmps = str_get(st[1]);
2247 tmps2 = str_get(st[2]);
2248#ifdef TAINT
2249 TAINT_PROPER("rename");
2250#endif
2251#ifdef HAS_RENAME
2252 value = (double)(rename(tmps,tmps2) >= 0);
2253#else
2254 if (same_dirent(tmps2, tmps)) /* can always rename to same name */
2255 anum = 1;
2256 else {
2257 if (euid || stat(tmps2,&statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
2258 (void)UNLINK(tmps2);
2259 if (!(anum = link(tmps,tmps2)))
2260 anum = UNLINK(tmps);
2261 }
2262 value = (double)(anum >= 0);
2263#endif
2264 goto donumset;
2265 case O_LINK:
2266#ifdef HAS_LINK
2267 tmps = str_get(st[1]);
2268 tmps2 = str_get(st[2]);
2269#ifdef TAINT
2270 TAINT_PROPER("link");
2271#endif
2272 value = (double)(link(tmps,tmps2) >= 0);
2273 goto donumset;
2274#else
2275 fatal("Unsupported function link");
2276 break;
2277#endif
2278 case O_MKDIR:
2279 tmps = str_get(st[1]);
2280 anum = (int)str_gnum(st[2]);
2281#ifdef TAINT
2282 TAINT_PROPER("mkdir");
2283#endif
2284#ifdef HAS_MKDIR
2285 value = (double)(mkdir(tmps,anum) >= 0);
2286 goto donumset;
2287#else
2288 (void)strcpy(buf,"mkdir ");
2289#endif
2290#if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
2291 one_liner:
2292 for (tmps2 = buf+6; *tmps; ) {
2293 *tmps2++ = '\\';
2294 *tmps2++ = *tmps++;
2295 }
2296 (void)strcpy(tmps2," 2>&1");
2297 rsfp = mypopen(buf,"r");
2298 if (rsfp) {
2299 *buf = '\0';
2300 tmps2 = fgets(buf,sizeof buf,rsfp);
2301 (void)mypclose(rsfp);
2302 if (tmps2 != Nullch) {
2303 for (errno = 1; errno < sys_nerr; errno++) {
2304 if (instr(buf,sys_errlist[errno])) /* you don't see this */
2305 goto say_zero;
2306 }
2307 errno = 0;
2308#ifndef EACCES
2309#define EACCES EPERM
2310#endif
2311 if (instr(buf,"cannot make"))
2312 errno = EEXIST;
2313 else if (instr(buf,"existing file"))
2314 errno = EEXIST;
2315 else if (instr(buf,"ile exists"))
2316 errno = EEXIST;
2317 else if (instr(buf,"non-exist"))
2318 errno = ENOENT;
2319 else if (instr(buf,"does not exist"))
2320 errno = ENOENT;
2321 else if (instr(buf,"not empty"))
2322 errno = EBUSY;
2323 else if (instr(buf,"cannot access"))
2324 errno = EACCES;
2325 else
2326 errno = EPERM;
2327 goto say_zero;
2328 }
2329 else { /* some mkdirs return no failure indication */
2330 tmps = str_get(st[1]);
2331 anum = (stat(tmps,&statbuf) >= 0);
2332 if (optype == O_RMDIR)
2333 anum = !anum;
2334 if (anum)
2335 errno = 0;
2336 else
2337 errno = EACCES; /* a guess */
2338 value = (double)anum;
2339 }
2340 goto donumset;
2341 }
2342 else
2343 goto say_zero;
2344#endif
2345 case O_RMDIR:
2346 if (maxarg < 1)
2347 tmps = str_get(stab_val(defstab));
2348 else
2349 tmps = str_get(st[1]);
2350#ifdef TAINT
2351 TAINT_PROPER("rmdir");
2352#endif
2353#ifdef HAS_RMDIR
2354 value = (double)(rmdir(tmps) >= 0);
2355 goto donumset;
2356#else
2357 (void)strcpy(buf,"rmdir ");
2358 goto one_liner; /* see above in HAS_MKDIR */
2359#endif
2360 case O_GETPPID:
2361#ifdef HAS_GETPPID
2362 value = (double)getppid();
2363 goto donumset;
2364#else
2365 fatal("Unsupported function getppid");
2366 break;
2367#endif
2368 case O_GETPGRP:
2369#ifdef HAS_GETPGRP
2370 if (maxarg < 1)
2371 anum = 0;
2372 else
2373 anum = (int)str_gnum(st[1]);
2374#ifdef _POSIX_SOURCE
2375 if (anum != 0)
2376 fatal("POSIX getpgrp can't take an argument");
2377 value = (double)getpgrp();
2378#else
2379 value = (double)getpgrp(anum);
2380#endif
2381 goto donumset;
2382#else
2383 fatal("The getpgrp() function is unimplemented on this machine");
2384 break;
2385#endif
2386 case O_SETPGRP:
2387#ifdef HAS_SETPGRP
2388 argtype = (int)str_gnum(st[1]);
2389 anum = (int)str_gnum(st[2]);
2390#ifdef TAINT
2391 TAINT_PROPER("setpgrp");
2392#endif
2393 value = (double)(setpgrp(argtype,anum) >= 0);
2394 goto donumset;
2395#else
2396 fatal("The setpgrp() function is unimplemented on this machine");
2397 break;
2398#endif
2399 case O_GETPRIORITY:
2400#ifdef HAS_GETPRIORITY
2401 argtype = (int)str_gnum(st[1]);
2402 anum = (int)str_gnum(st[2]);
2403 value = (double)getpriority(argtype,anum);
2404 goto donumset;
2405#else
2406 fatal("The getpriority() function is unimplemented on this machine");
2407 break;
2408#endif
2409 case O_SETPRIORITY:
2410#ifdef HAS_SETPRIORITY
2411 argtype = (int)str_gnum(st[1]);
2412 anum = (int)str_gnum(st[2]);
2413 optype = (int)str_gnum(st[3]);
2414#ifdef TAINT
2415 TAINT_PROPER("setpriority");
2416#endif
2417 value = (double)(setpriority(argtype,anum,optype) >= 0);
2418 goto donumset;
2419#else
2420 fatal("The setpriority() function is unimplemented on this machine");
2421 break;
2422#endif
2423 case O_CHROOT:
2424#ifdef HAS_CHROOT
2425 if (maxarg < 1)
2426 tmps = str_get(stab_val(defstab));
2427 else
2428 tmps = str_get(st[1]);
2429#ifdef TAINT
2430 TAINT_PROPER("chroot");
2431#endif
2432 value = (double)(chroot(tmps) >= 0);
2433 goto donumset;
2434#else
2435 fatal("Unsupported function chroot");
2436 break;
2437#endif
2438 case O_FCNTL:
2439 case O_IOCTL:
2440 if (maxarg <= 0)
2441 stab = last_in_stab;
2442 else if ((arg[1].arg_type & A_MASK) == A_WORD)
2443 stab = arg[1].arg_ptr.arg_stab;
2444 else
2445 stab = stabent(str_get(st[1]),TRUE);
2446 argtype = U_I(str_gnum(st[2]));
2447#ifdef TAINT
2448 TAINT_PROPER("ioctl");
2449#endif
2450 anum = do_ctl(optype,stab,argtype,st[3]);
2451 if (anum == -1)
2452 goto say_undef;
2453 if (anum != 0) {
2454 value = (double)anum;
2455 goto donumset;
2456 }
2457 str_set(str,"0 but true");
2458 STABSET(str);
2459 break;
2460 case O_FLOCK:
2461#ifdef HAS_FLOCK
2462 if (maxarg <= 0)
2463 stab = last_in_stab;
2464 else if ((arg[1].arg_type & A_MASK) == A_WORD)
2465 stab = arg[1].arg_ptr.arg_stab;
2466 else
2467 stab = stabent(str_get(st[1]),TRUE);
2468 if (stab && stab_io(stab))
2469 fp = stab_io(stab)->ifp;
2470 else
2471 fp = Nullfp;
2472 if (fp) {
2473 argtype = (int)str_gnum(st[2]);
2474 value = (double)(flock(fileno(fp),argtype) >= 0);
2475 }
2476 else
2477 value = 0;
2478 goto donumset;
2479#else
2480 fatal("The flock() function is unimplemented on this machine");
2481 break;
2482#endif
2483 case O_UNSHIFT:
2484 ary = stab_array(arg[1].arg_ptr.arg_stab);
2485 if (arglast[2] - arglast[1] != 1)
2486 do_unshift(ary,arglast);
2487 else {
2488 STR *tmpstr = Str_new(52,0); /* must copy the STR */
2489 str_sset(tmpstr,st[2]);
2490 aunshift(ary,1);
2491 (void)astore(ary,0,tmpstr);
2492 }
2493 value = (double)(ary->ary_fill + 1);
2494 goto donumset;
2495
2496 case O_TRY:
2497 sp = do_try(arg[1].arg_ptr.arg_cmd,
2498 gimme,arglast);
2499 goto array_return;
2500
2501 case O_EVALONCE:
2502 sp = do_eval(st[1], O_EVAL, curcmd->c_stash, TRUE,
2503 gimme,arglast);
2504 if (eval_root) {
2505 str_free(arg[1].arg_ptr.arg_str);
2506 arg[1].arg_ptr.arg_cmd = eval_root;
2507 arg[1].arg_type = (A_CMD|A_DONT);
2508 arg[0].arg_type = O_TRY;
2509 }
2510 goto array_return;
2511
2512 case O_REQUIRE:
2513 case O_DOFILE:
2514 case O_EVAL:
2515 if (maxarg < 1)
2516 tmpstr = stab_val(defstab);
2517 else
2518 tmpstr =
2519 (arg[1].arg_type & A_MASK) != A_NULL ? st[1] : stab_val(defstab);
2520#ifdef TAINT
2521 tainted |= tmpstr->str_tainted;
2522 TAINT_PROPER("eval");
2523#endif
2524 sp = do_eval(tmpstr, optype, curcmd->c_stash, FALSE,
2525 gimme,arglast);
2526 goto array_return;
2527
2528 case O_FTRREAD:
2529 argtype = 0;
2530 anum = S_IRUSR;
2531 goto check_perm;
2532 case O_FTRWRITE:
2533 argtype = 0;
2534 anum = S_IWUSR;
2535 goto check_perm;
2536 case O_FTREXEC:
2537 argtype = 0;
2538 anum = S_IXUSR;
2539 goto check_perm;
2540 case O_FTEREAD:
2541 argtype = 1;
2542 anum = S_IRUSR;
2543 goto check_perm;
2544 case O_FTEWRITE:
2545 argtype = 1;
2546 anum = S_IWUSR;
2547 goto check_perm;
2548 case O_FTEEXEC:
2549 argtype = 1;
2550 anum = S_IXUSR;
2551 check_perm:
2552 if (mystat(arg,st[1]) < 0)
2553 goto say_undef;
2554 if (cando(anum,argtype,&statcache))
2555 goto say_yes;
2556 goto say_no;
2557
2558 case O_FTIS:
2559 if (mystat(arg,st[1]) < 0)
2560 goto say_undef;
2561 goto say_yes;
2562 case O_FTEOWNED:
2563 case O_FTROWNED:
2564 if (mystat(arg,st[1]) < 0)
2565 goto say_undef;
2566 if (statcache.st_uid == (optype == O_FTEOWNED ? euid : uid) )
2567 goto say_yes;
2568 goto say_no;
2569 case O_FTZERO:
2570 if (mystat(arg,st[1]) < 0)
2571 goto say_undef;
2572 if (!statcache.st_size)
2573 goto say_yes;
2574 goto say_no;
2575 case O_FTSIZE:
2576 if (mystat(arg,st[1]) < 0)
2577 goto say_undef;
2578 value = (double)statcache.st_size;
2579 goto donumset;
2580
2581 case O_FTMTIME:
2582 if (mystat(arg,st[1]) < 0)
2583 goto say_undef;
2584 value = (double)(basetime - statcache.st_mtime) / 86400.0;
2585 goto donumset;
2586 case O_FTATIME:
2587 if (mystat(arg,st[1]) < 0)
2588 goto say_undef;
2589 value = (double)(basetime - statcache.st_atime) / 86400.0;
2590 goto donumset;
2591 case O_FTCTIME:
2592 if (mystat(arg,st[1]) < 0)
2593 goto say_undef;
2594 value = (double)(basetime - statcache.st_ctime) / 86400.0;
2595 goto donumset;
2596
2597 case O_FTSOCK:
2598 if (mystat(arg,st[1]) < 0)
2599 goto say_undef;
2600 if (S_ISSOCK(statcache.st_mode))
2601 goto say_yes;
2602 goto say_no;
2603 case O_FTCHR:
2604 if (mystat(arg,st[1]) < 0)
2605 goto say_undef;
2606 if (S_ISCHR(statcache.st_mode))
2607 goto say_yes;
2608 goto say_no;
2609 case O_FTBLK:
2610 if (mystat(arg,st[1]) < 0)
2611 goto say_undef;
2612 if (S_ISBLK(statcache.st_mode))
2613 goto say_yes;
2614 goto say_no;
2615 case O_FTFILE:
2616 if (mystat(arg,st[1]) < 0)
2617 goto say_undef;
2618 if (S_ISREG(statcache.st_mode))
2619 goto say_yes;
2620 goto say_no;
2621 case O_FTDIR:
2622 if (mystat(arg,st[1]) < 0)
2623 goto say_undef;
2624 if (S_ISDIR(statcache.st_mode))
2625 goto say_yes;
2626 goto say_no;
2627 case O_FTPIPE:
2628 if (mystat(arg,st[1]) < 0)
2629 goto say_undef;
2630 if (S_ISFIFO(statcache.st_mode))
2631 goto say_yes;
2632 goto say_no;
2633 case O_FTLINK:
2634 if (mylstat(arg,st[1]) < 0)
2635 goto say_undef;
2636 if (S_ISLNK(statcache.st_mode))
2637 goto say_yes;
2638 goto say_no;
2639 case O_SYMLINK:
2640#ifdef HAS_SYMLINK
2641 tmps = str_get(st[1]);
2642 tmps2 = str_get(st[2]);
2643#ifdef TAINT
2644 TAINT_PROPER("symlink");
2645#endif
2646 value = (double)(symlink(tmps,tmps2) >= 0);
2647 goto donumset;
2648#else
2649 fatal("Unsupported function symlink");
2650#endif
2651 case O_READLINK:
2652#ifdef HAS_SYMLINK
2653 if (maxarg < 1)
2654 tmps = str_get(stab_val(defstab));
2655 else
2656 tmps = str_get(st[1]);
2657 anum = readlink(tmps,buf,sizeof buf);
2658 if (anum < 0)
2659 goto say_undef;
2660 str_nset(str,buf,anum);
2661 break;
2662#else
2663 goto say_undef; /* just pretend it's a normal file */
2664#endif
2665 case O_FTSUID:
2666#ifdef S_ISUID
2667 anum = S_ISUID;
2668 goto check_xid;
2669#else
2670 goto say_no;
2671#endif
2672 case O_FTSGID:
2673#ifdef S_ISGID
2674 anum = S_ISGID;
2675 goto check_xid;
2676#else
2677 goto say_no;
2678#endif
2679 case O_FTSVTX:
2680#ifdef S_ISVTX
2681 anum = S_ISVTX;
2682#else
2683 goto say_no;
2684#endif
2685 check_xid:
2686 if (mystat(arg,st[1]) < 0)
2687 goto say_undef;
2688 if (statcache.st_mode & anum)
2689 goto say_yes;
2690 goto say_no;
2691 case O_FTTTY:
2692 if (arg[1].arg_type & A_DONT) {
2693 stab = arg[1].arg_ptr.arg_stab;
2694 tmps = "";
2695 }
2696 else
2697 stab = stabent(tmps = str_get(st[1]),FALSE);
2698 if (stab && stab_io(stab) && stab_io(stab)->ifp)
2699 anum = fileno(stab_io(stab)->ifp);
2700 else if (isDIGIT(*tmps))
2701 anum = atoi(tmps);
2702 else
2703 goto say_undef;
2704 if (isatty(anum))
2705 goto say_yes;
2706 goto say_no;
2707 case O_FTTEXT:
2708 case O_FTBINARY:
2709 str = do_fttext(arg,st[1]);
2710 break;
2711#ifdef HAS_SOCKET
2712 case O_SOCKET:
2713 if ((arg[1].arg_type & A_MASK) == A_WORD)
2714 stab = arg[1].arg_ptr.arg_stab;
2715 else
2716 stab = stabent(str_get(st[1]),TRUE);
2717#ifndef lint
2718 value = (double)do_socket(stab,arglast);
2719#else
2720 (void)do_socket(stab,arglast);
2721#endif
2722 goto donumset;
2723 case O_BIND:
2724 if ((arg[1].arg_type & A_MASK) == A_WORD)
2725 stab = arg[1].arg_ptr.arg_stab;
2726 else
2727 stab = stabent(str_get(st[1]),TRUE);
2728#ifndef lint
2729 value = (double)do_bind(stab,arglast);
2730#else
2731 (void)do_bind(stab,arglast);
2732#endif
2733 goto donumset;
2734 case O_CONNECT:
2735 if ((arg[1].arg_type & A_MASK) == A_WORD)
2736 stab = arg[1].arg_ptr.arg_stab;
2737 else
2738 stab = stabent(str_get(st[1]),TRUE);
2739#ifndef lint
2740 value = (double)do_connect(stab,arglast);
2741#else
2742 (void)do_connect(stab,arglast);
2743#endif
2744 goto donumset;
2745 case O_LISTEN:
2746 if ((arg[1].arg_type & A_MASK) == A_WORD)
2747 stab = arg[1].arg_ptr.arg_stab;
2748 else
2749 stab = stabent(str_get(st[1]),TRUE);
2750#ifndef lint
2751 value = (double)do_listen(stab,arglast);
2752#else
2753 (void)do_listen(stab,arglast);
2754#endif
2755 goto donumset;
2756 case O_ACCEPT:
2757 if ((arg[1].arg_type & A_MASK) == A_WORD)
2758 stab = arg[1].arg_ptr.arg_stab;
2759 else
2760 stab = stabent(str_get(st[1]),TRUE);
2761 if ((arg[2].arg_type & A_MASK) == A_WORD)
2762 stab2 = arg[2].arg_ptr.arg_stab;
2763 else
2764 stab2 = stabent(str_get(st[2]),TRUE);
2765 do_accept(str,stab,stab2);
2766 STABSET(str);
2767 break;
2768 case O_GHBYNAME:
2769 if (maxarg < 1)
2770 goto say_undef;
2771 case O_GHBYADDR:
2772 case O_GHOSTENT:
2773 sp = do_ghent(optype,
2774 gimme,arglast);
2775 goto array_return;
2776 case O_GNBYNAME:
2777 if (maxarg < 1)
2778 goto say_undef;
2779 case O_GNBYADDR:
2780 case O_GNETENT:
2781 sp = do_gnent(optype,
2782 gimme,arglast);
2783 goto array_return;
2784 case O_GPBYNAME:
2785 if (maxarg < 1)
2786 goto say_undef;
2787 case O_GPBYNUMBER:
2788 case O_GPROTOENT:
2789 sp = do_gpent(optype,
2790 gimme,arglast);
2791 goto array_return;
2792 case O_GSBYNAME:
2793 if (maxarg < 1)
2794 goto say_undef;
2795 case O_GSBYPORT:
2796 case O_GSERVENT:
2797 sp = do_gsent(optype,
2798 gimme,arglast);
2799 goto array_return;
2800 case O_SHOSTENT:
2801 value = (double) sethostent((int)str_gnum(st[1]));
2802 goto donumset;
2803 case O_SNETENT:
2804 value = (double) setnetent((int)str_gnum(st[1]));
2805 goto donumset;
2806 case O_SPROTOENT:
2807 value = (double) setprotoent((int)str_gnum(st[1]));
2808 goto donumset;
2809 case O_SSERVENT:
2810 value = (double) setservent((int)str_gnum(st[1]));
2811 goto donumset;
2812 case O_EHOSTENT:
2813 value = (double) endhostent();
2814 goto donumset;
2815 case O_ENETENT:
2816 value = (double) endnetent();
2817 goto donumset;
2818 case O_EPROTOENT:
2819 value = (double) endprotoent();
2820 goto donumset;
2821 case O_ESERVENT:
2822 value = (double) endservent();
2823 goto donumset;
2824 case O_SOCKPAIR:
2825 if ((arg[1].arg_type & A_MASK) == A_WORD)
2826 stab = arg[1].arg_ptr.arg_stab;
2827 else
2828 stab = stabent(str_get(st[1]),TRUE);
2829 if ((arg[2].arg_type & A_MASK) == A_WORD)
2830 stab2 = arg[2].arg_ptr.arg_stab;
2831 else
2832 stab2 = stabent(str_get(st[2]),TRUE);
2833#ifndef lint
2834 value = (double)do_spair(stab,stab2,arglast);
2835#else
2836 (void)do_spair(stab,stab2,arglast);
2837#endif
2838 goto donumset;
2839 case O_SHUTDOWN:
2840 if ((arg[1].arg_type & A_MASK) == A_WORD)
2841 stab = arg[1].arg_ptr.arg_stab;
2842 else
2843 stab = stabent(str_get(st[1]),TRUE);
2844#ifndef lint
2845 value = (double)do_shutdown(stab,arglast);
2846#else
2847 (void)do_shutdown(stab,arglast);
2848#endif
2849 goto donumset;
2850 case O_GSOCKOPT:
2851 case O_SSOCKOPT:
2852 if ((arg[1].arg_type & A_MASK) == A_WORD)
2853 stab = arg[1].arg_ptr.arg_stab;
2854 else
2855 stab = stabent(str_get(st[1]),TRUE);
2856 sp = do_sopt(optype,stab,arglast);
2857 goto array_return;
2858 case O_GETSOCKNAME:
2859 case O_GETPEERNAME:
2860 if ((arg[1].arg_type & A_MASK) == A_WORD)
2861 stab = arg[1].arg_ptr.arg_stab;
2862 else
2863 stab = stabent(str_get(st[1]),TRUE);
2864 if (!stab)
2865 goto say_undef;
2866 sp = do_getsockname(optype,stab,arglast);
2867 goto array_return;
2868
2869#else /* HAS_SOCKET not defined */
2870 case O_SOCKET:
2871 case O_BIND:
2872 case O_CONNECT:
2873 case O_LISTEN:
2874 case O_ACCEPT:
2875 case O_SOCKPAIR:
2876 case O_GHBYNAME:
2877 case O_GHBYADDR:
2878 case O_GHOSTENT:
2879 case O_GNBYNAME:
2880 case O_GNBYADDR:
2881 case O_GNETENT:
2882 case O_GPBYNAME:
2883 case O_GPBYNUMBER:
2884 case O_GPROTOENT:
2885 case O_GSBYNAME:
2886 case O_GSBYPORT:
2887 case O_GSERVENT:
2888 case O_SHOSTENT:
2889 case O_SNETENT:
2890 case O_SPROTOENT:
2891 case O_SSERVENT:
2892 case O_EHOSTENT:
2893 case O_ENETENT:
2894 case O_EPROTOENT:
2895 case O_ESERVENT:
2896 case O_SHUTDOWN:
2897 case O_GSOCKOPT:
2898 case O_SSOCKOPT:
2899 case O_GETSOCKNAME:
2900 case O_GETPEERNAME:
2901 badsock:
2902 fatal("Unsupported socket function");
2903#endif /* HAS_SOCKET */
2904 case O_SSELECT:
2905#ifdef HAS_SELECT
2906 sp = do_select(gimme,arglast);
2907 goto array_return;
2908#else
2909 fatal("select not implemented");
2910#endif
2911 case O_FILENO:
2912 if (maxarg < 1)
2913 goto say_undef;
2914 if ((arg[1].arg_type & A_MASK) == A_WORD)
2915 stab = arg[1].arg_ptr.arg_stab;
2916 else
2917 stab = stabent(str_get(st[1]),TRUE);
2918 if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
2919 goto say_undef;
2920 value = fileno(fp);
2921 goto donumset;
2922 case O_BINMODE:
2923 if (maxarg < 1)
2924 goto say_undef;
2925 if ((arg[1].arg_type & A_MASK) == A_WORD)
2926 stab = arg[1].arg_ptr.arg_stab;
2927 else
2928 stab = stabent(str_get(st[1]),TRUE);
2929 if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
2930 goto say_undef;
2931#ifdef DOSISH
2932#ifdef atarist
2933 if(fflush(fp))
2934 str_set(str, No);
2935 else
2936 {
2937 fp->_flag |= _IOBIN;
2938 str_set(str, Yes);
2939 }
2940#else
2941 str_set(str, (setmode(fileno(fp), O_BINARY) != -1) ? Yes : No);
2942#endif
2943#else
2944 str_set(str, Yes);
2945#endif
2946 STABSET(str);
2947 break;
2948 case O_VEC:
2949 sp = do_vec(str == st[1], arg->arg_ptr.arg_str, arglast);
2950 goto array_return;
2951 case O_GPWNAM:
2952 case O_GPWUID:
2953 case O_GPWENT:
2954#ifdef HAS_PASSWD
2955 sp = do_gpwent(optype,
2956 gimme,arglast);
2957 goto array_return;
2958 case O_SPWENT:
2959 value = (double) setpwent();
2960 goto donumset;
2961 case O_EPWENT:
2962 value = (double) endpwent();
2963 goto donumset;
2964#else
2965 case O_EPWENT:
2966 case O_SPWENT:
2967 fatal("Unsupported password function");
2968 break;
2969#endif
2970 case O_GGRNAM:
2971 case O_GGRGID:
2972 case O_GGRENT:
2973#ifdef HAS_GROUP
2974 sp = do_ggrent(optype,
2975 gimme,arglast);
2976 goto array_return;
2977 case O_SGRENT:
2978 value = (double) setgrent();
2979 goto donumset;
2980 case O_EGRENT:
2981 value = (double) endgrent();
2982 goto donumset;
2983#else
2984 case O_EGRENT:
2985 case O_SGRENT:
2986 fatal("Unsupported group function");
2987 break;
2988#endif
2989 case O_GETLOGIN:
2990#ifdef HAS_GETLOGIN
2991 if (!(tmps = getlogin()))
2992 goto say_undef;
2993 str_set(str,tmps);
2994#else
2995 fatal("Unsupported function getlogin");
2996#endif
2997 break;
2998 case O_OPEN_DIR:
2999 case O_READDIR:
3000 case O_TELLDIR:
3001 case O_SEEKDIR:
3002 case O_REWINDDIR:
3003 case O_CLOSEDIR:
3004 if (maxarg < 1)
3005 goto say_undef;
3006 if ((arg[1].arg_type & A_MASK) == A_WORD)
3007 stab = arg[1].arg_ptr.arg_stab;
3008 else
3009 stab = stabent(str_get(st[1]),TRUE);
3010 if (!stab)
3011 goto say_undef;
3012 sp = do_dirop(optype,stab,gimme,arglast);
3013 goto array_return;
3014 case O_SYSCALL:
3015 value = (double)do_syscall(arglast);
3016 goto donumset;
3017 case O_PIPE_OP:
3018#ifdef HAS_PIPE
3019 if ((arg[1].arg_type & A_MASK) == A_WORD)
3020 stab = arg[1].arg_ptr.arg_stab;
3021 else
3022 stab = stabent(str_get(st[1]),TRUE);
3023 if ((arg[2].arg_type & A_MASK) == A_WORD)
3024 stab2 = arg[2].arg_ptr.arg_stab;
3025 else
3026 stab2 = stabent(str_get(st[2]),TRUE);
3027 do_pipe(str,stab,stab2);
3028 STABSET(str);
3029#else
3030 fatal("Unsupported function pipe");
3031#endif
3032 break;
3033 }
3034
3035 normal_return:
3036 st[1] = str;
3037#ifdef DEBUGGING
3038 if (debug) {
3039 dlevel--;
3040 if (debug & 8)
3041 deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
3042 }
3043#endif
3044 stack_ary = stack->ary_array;
3045 stack_max = stack_ary + stack->ary_max;
3046 stack_sp = stack_ary + arglast[0] + 1;
3047 return arglast[0] + 1;
3048}