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