diff options
Diffstat (limited to 'eval.c.save')
-rw-r--r-- | eval.c.save | 3048 |
1 files changed, 3048 insertions, 0 deletions
diff --git a/eval.c.save b/eval.c.save new file mode 100644 index 0000000000..964bc0301f --- /dev/null +++ b/eval.c.save @@ -0,0 +1,3048 @@ +/* $RCSfile: eval.c,v $$Revision: 4.1 $$Date: 92/08/07 18:20:29 $ + * + * Copyright (c) 1991, Larry Wall + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + * $Log: eval.c,v $ + * Revision 4.1 92/08/07 18:20:29 lwall + * + * Revision 4.0.1.4 92/06/08 13:20:20 lwall + * patch20: added explicit time_t support + * patch20: fixed confusion between a *var's real name and its effective name + * patch20: added Atari ST portability + * patch20: new warning for use of x with non-numeric right operand + * patch20: modulus with highest bit in left operand set didn't always work + * patch20: dbmclose(%array) didn't work + * patch20: added ... as variant on .. + * patch20: O_PIPE conflicted with Atari + * + * Revision 4.0.1.3 91/11/05 17:15:21 lwall + * patch11: prepared for ctype implementations that don't define isascii() + * patch11: various portability fixes + * patch11: added sort {} LIST + * patch11: added eval {} + * patch11: sysread() in socket was substituting recv() + * patch11: a last statement outside any block caused occasional core dumps + * patch11: missing arguments caused core dump in -D8 code + * patch11: eval 'stuff' now optimized to eval {stuff} + * + * Revision 4.0.1.2 91/06/07 11:07:23 lwall + * patch4: new copyright notice + * patch4: length($`), length($&), length($') now optimized to avoid string copy + * patch4: assignment wasn't correctly de-tainting the assigned variable. + * patch4: default top-of-form format is now FILEHANDLE_TOP + * patch4: added $^P variable to control calling of perldb routines + * patch4: taintchecks could improperly modify parent in vfork() + * patch4: many, many itty-bitty portability fixes + * + * Revision 4.0.1.1 91/04/11 17:43:48 lwall + * patch1: fixed failed fork to return undef as documented + * patch1: reduced maximum branch distance in eval.c + * + * Revision 4.0 91/03/20 01:16:48 lwall + * 4.0 baseline. + * + */ + +#include "EXTERN.h" +#include "perl.h" + +extern int (*ppaddr[])(); +extern int mark[]; + +#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) +#include <signal.h> +#endif + +#ifdef I_FCNTL +#include <fcntl.h> +#endif +#ifdef MSDOS +/* I_FCNTL *MUST* not be defined for MS-DOS and OS/2 + but fcntl.h is required for O_BINARY */ +#include <fcntl.h> +#endif +#ifdef I_SYS_FILE +#include <sys/file.h> +#endif +#ifdef I_VFORK +# include <vfork.h> +#endif + +double sin(), cos(), atan2(), pow(); + +char *getlogin(); + +int +eval(arg,gimme,sp) +register ARG *arg; +int gimme; +register int sp; +{ + register STR *str; + register int anum; + register int optype; + register STR **st; + int maxarg; + double value; + register char *tmps; + char *tmps2; + int argflags; + int argtype; + union argptr argptr; + int arglast[8]; /* highest sp for arg--valid only for non-O_LIST args */ + unsigned long tmpulong; + long tmplong; + time_t when; + STRLEN tmplen; + FILE *fp; + STR *tmpstr; + FCMD *form; + STAB *stab; + STAB *stab2; + STIO *stio; + ARRAY *ary; + int old_rslen; + int old_rschar; + VOIDRET (*ihand)(); /* place to save signal during system() */ + VOIDRET (*qhand)(); /* place to save signal during system() */ + bool assigning = FALSE; + int mymarkbase = savestack->ary_fill; + + if (!arg) + goto say_undef; + optype = arg->arg_type; + maxarg = arg->arg_len; + arglast[0] = sp; + str = arg->arg_ptr.arg_str; + if (sp + maxarg > stack->ary_max) + astore(stack, sp + maxarg, Nullstr); + st = stack->ary_array; + +#ifdef DEBUGGING + if (debug) { + if (debug & 8) { + deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg); + } + debname[dlevel] = opname[optype][0]; + debdelim[dlevel] = ':'; + if (++dlevel >= dlmax) + grow_dlevel(); + } +#endif + + if (mark[optype]) { + saveint(&markbase); + markbase = mymarkbase; + saveint(&stack_mark); + stack_mark = sp; + } + for (anum = 1; anum <= maxarg; anum++) { + argflags = arg[anum].arg_flags; + argtype = arg[anum].arg_type; + argptr = arg[anum].arg_ptr; + re_eval: + switch (argtype) { + default: + if (!ppaddr[optype] || optype == O_SUBR || optype == O_DBSUBR) { + st[++sp] = &str_undef; + } +#ifdef DEBUGGING + tmps = "NULL"; +#endif + break; + case A_EXPR: +#ifdef DEBUGGING + if (debug & 8) { + tmps = "EXPR"; + deb("%d.EXPR =>\n",anum); + } +#endif + sp = eval(argptr.arg_arg, + (argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, sp); + if (sp + (maxarg - anum) > stack->ary_max) + astore(stack, sp + (maxarg - anum), Nullstr); + st = stack->ary_array; /* possibly reallocated */ + break; + case A_CMD: +#ifdef DEBUGGING + if (debug & 8) { + tmps = "CMD"; + deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd); + } +#endif + sp = cmd_exec(argptr.arg_cmd, gimme, sp); + if (sp + (maxarg - anum) > stack->ary_max) + astore(stack, sp + (maxarg - anum), Nullstr); + st = stack->ary_array; /* possibly reallocated */ + break; + case A_LARYSTAB: + ++sp; + switch (optype) { + case O_ITEM2: argtype = 2; break; + case O_ITEM3: argtype = 3; break; + default: argtype = anum; break; + } + str = afetch(stab_array(argptr.arg_stab), + arg[argtype].arg_len - arybase, TRUE); +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(argptr.arg_stab), + arg[argtype].arg_len); + tmps = buf; + } +#endif + goto do_crement; + case A_ARYSTAB: + switch (optype) { + case O_ITEM2: argtype = 2; break; + case O_ITEM3: argtype = 3; break; + default: argtype = anum; break; + } + st[++sp] = afetch(stab_array(argptr.arg_stab), + arg[argtype].arg_len - arybase, FALSE); +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(argptr.arg_stab), + arg[argtype].arg_len); + tmps = buf; + } +#endif + break; + case A_STAR: + stab = argptr.arg_stab; + st[++sp] = (STR*)stab; + if (!stab_xarray(stab)) + aadd(stab); + if (!stab_xhash(stab)) + hadd(stab); + if (!stab_io(stab)) + stab_io(stab) = stio_new(); +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"STAR *%s -> *%s", + stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab)); + tmps = buf; + } +#endif + break; + case A_LSTAR: + str = st[++sp] = (STR*)argptr.arg_stab; +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"LSTAR *%s -> *%s", + stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab)); + tmps = buf; + } +#endif + break; + case A_STAB: + st[++sp] = STAB_STR(argptr.arg_stab); +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"STAB $%s",stab_name(argptr.arg_stab)); + tmps = buf; + } +#endif + break; + case A_LENSTAB: + str_numset(str, (double)STAB_LEN(argptr.arg_stab)); + st[++sp] = str; +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"LENSTAB $%s",stab_name(argptr.arg_stab)); + tmps = buf; + } +#endif + break; + case A_LEXPR: +#ifdef DEBUGGING + if (debug & 8) { + tmps = "LEXPR"; + deb("%d.LEXPR =>\n",anum); + } +#endif + if (argflags & AF_ARYOK) { + sp = eval(argptr.arg_arg, G_ARRAY, sp); + if (sp + (maxarg - anum) > stack->ary_max) + astore(stack, sp + (maxarg - anum), Nullstr); + st = stack->ary_array; /* possibly reallocated */ + } + else { + sp = eval(argptr.arg_arg, G_SCALAR, sp); + st = stack->ary_array; /* possibly reallocated */ + str = st[sp]; + goto do_crement; + } + break; + case A_LVAL: +#ifdef DEBUGGING + if (debug & 8) { + (void)sprintf(buf,"LVAL $%s",stab_name(argptr.arg_stab)); + tmps = buf; + } +#endif + ++sp; + str = STAB_STR(argptr.arg_stab); + if (!str) + fatal("panic: A_LVAL"); + do_crement: + assigning = TRUE; + if (argflags & AF_PRE) { + if (argflags & AF_UP) + str_inc(str); + else + str_dec(str); + STABSET(str); + st[sp] = str; + str = arg->arg_ptr.arg_str; + } + else if (argflags & AF_POST) { + st[sp] = str_mortal(str); + if (argflags & AF_UP) + str_inc(str); + else + str_dec(str); + STABSET(str); + str = arg->arg_ptr.arg_str; + } + else + st[sp] = str; + break; + case A_LARYLEN: + ++sp; + stab = argptr.arg_stab; + str = stab_array(argptr.arg_stab)->ary_magic; + if (optype != O_SASSIGN || argflags & (AF_PRE|AF_POST)) + str_numset(str,(double)(stab_array(stab)->ary_fill+arybase)); +#ifdef DEBUGGING + tmps = "LARYLEN"; +#endif + if (!str) + fatal("panic: A_LEXPR"); + goto do_crement; + case A_ARYLEN: + stab = argptr.arg_stab; + st[++sp] = stab_array(stab)->ary_magic; + str_numset(st[sp],(double)(stab_array(stab)->ary_fill+arybase)); +#ifdef DEBUGGING + tmps = "ARYLEN"; +#endif + break; + case A_SINGLE: + st[++sp] = argptr.arg_str; +#ifdef DEBUGGING + tmps = "SINGLE"; +#endif + break; + case A_DOUBLE: + (void) interp(str,argptr.arg_str,sp); + st = stack->ary_array; + st[++sp] = str; +#ifdef DEBUGGING + tmps = "DOUBLE"; +#endif + break; + case A_BACKTICK: + tmps = str_get(interp(str,argptr.arg_str,sp)); + st = stack->ary_array; +#ifdef TAINT + TAINT_PROPER("``"); +#endif + fp = mypopen(tmps,"r"); + str_set(str,""); + if (fp) { + if (gimme == G_SCALAR) { + while (str_gets(str,fp,str->str_cur) != Nullch) + /*SUPPRESS 530*/ + ; + } + else { + for (;;) { + if (++sp > stack->ary_max) { + astore(stack, sp, Nullstr); + st = stack->ary_array; + } + str = st[sp] = Str_new(56,80); + if (str_gets(str,fp,0) == Nullch) { + sp--; + break; + } + if (str->str_len - str->str_cur > 20) { + str->str_len = str->str_cur+1; + Renew(str->str_ptr, str->str_len, char); + } + str_2mortal(str); + } + } + statusvalue = mypclose(fp); + } + else + statusvalue = -1; + + if (gimme == G_SCALAR) + st[++sp] = str; +#ifdef DEBUGGING + tmps = "BACK"; +#endif + break; + case A_WANTARRAY: + { + if (curcsv->wantarray == G_ARRAY) + st[++sp] = &str_yes; + else + st[++sp] = &str_no; + } +#ifdef DEBUGGING + tmps = "WANTARRAY"; +#endif + break; + case A_INDREAD: + last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE); + old_rschar = rschar; + old_rslen = rslen; + goto do_read; + case A_GLOB: + argflags |= AF_POST; /* enable newline chopping */ + last_in_stab = argptr.arg_stab; + old_rschar = rschar; + old_rslen = rslen; + rslen = 1; +#ifdef DOSISH + rschar = 0; +#else +#ifdef CSH + rschar = 0; +#else + rschar = '\n'; +#endif /* !CSH */ +#endif /* !MSDOS */ + goto do_read; + case A_READ: + last_in_stab = argptr.arg_stab; + old_rschar = rschar; + old_rslen = rslen; + do_read: + if (anum > 1) /* assign to scalar */ + gimme = G_SCALAR; /* force context to scalar */ + if (gimme == G_ARRAY) + str = Str_new(57,0); + ++sp; + fp = Nullfp; + if (stab_io(last_in_stab)) { + fp = stab_io(last_in_stab)->ifp; + if (!fp) { + if (stab_io(last_in_stab)->flags & IOF_ARGV) { + if (stab_io(last_in_stab)->flags & IOF_START) { + stab_io(last_in_stab)->flags &= ~IOF_START; + stab_io(last_in_stab)->lines = 0; + if (alen(stab_array(last_in_stab)) < 0) { + tmpstr = str_make("-",1); /* assume stdin */ + (void)apush(stab_array(last_in_stab), tmpstr); + } + } + fp = nextargv(last_in_stab); + if (!fp) { /* Note: fp != stab_io(last_in_stab)->ifp */ + (void)do_close(last_in_stab,FALSE); /* now it does*/ + stab_io(last_in_stab)->flags |= IOF_START; + } + } + else if (argtype == A_GLOB) { + (void) interp(str,stab_val(last_in_stab),sp); + st = stack->ary_array; + tmpstr = Str_new(55,0); +#ifdef DOSISH + str_set(tmpstr, "perlglob "); + str_scat(tmpstr,str); + str_cat(tmpstr," |"); +#else +#ifdef CSH + str_nset(tmpstr,cshname,cshlen); + str_cat(tmpstr," -cf 'set nonomatch; glob "); + str_scat(tmpstr,str); + str_cat(tmpstr,"'|"); +#else + str_set(tmpstr, "echo "); + str_scat(tmpstr,str); + str_cat(tmpstr, + "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|"); +#endif /* !CSH */ +#endif /* !MSDOS */ + (void)do_open(last_in_stab,tmpstr->str_ptr, + tmpstr->str_cur); + fp = stab_io(last_in_stab)->ifp; + str_free(tmpstr); + } + } + } + if (!fp && dowarn) + warn("Read on closed filehandle <%s>",stab_ename(last_in_stab)); + tmplen = str->str_len; /* remember if already alloced */ + if (!tmplen) + Str_Grow(str,80); /* try short-buffering it */ + keepgoing: + if (!fp) + st[sp] = &str_undef; + else if (!str_gets(str,fp, optype == O_RCAT ? str->str_cur : 0)) { + clearerr(fp); + if (stab_io(last_in_stab)->flags & IOF_ARGV) { + fp = nextargv(last_in_stab); + if (fp) + goto keepgoing; + (void)do_close(last_in_stab,FALSE); + stab_io(last_in_stab)->flags |= IOF_START; + } + else if (argflags & AF_POST) { + (void)do_close(last_in_stab,FALSE); + } + st[sp] = &str_undef; + rschar = old_rschar; + rslen = old_rslen; + if (gimme == G_ARRAY) { + --sp; + str_2mortal(str); + goto array_return; + } + break; + } + else { + stab_io(last_in_stab)->lines++; + st[sp] = str; +#ifdef TAINT + str->str_tainted = 1; /* Anything from the outside world...*/ +#endif + if (argflags & AF_POST) { + if (str->str_cur > 0) + str->str_cur--; + if (str->str_ptr[str->str_cur] == rschar) + str->str_ptr[str->str_cur] = '\0'; + else + str->str_cur++; + for (tmps = str->str_ptr; *tmps; tmps++) + if (!isALPHA(*tmps) && !isDIGIT(*tmps) && + index("$&*(){}[]'\";\\|?<>~`",*tmps)) + break; + if (*tmps && stat(str->str_ptr,&statbuf) < 0) + goto keepgoing; /* unmatched wildcard? */ + } + if (gimme == G_ARRAY) { + if (str->str_len - str->str_cur > 20) { + str->str_len = str->str_cur+1; + Renew(str->str_ptr, str->str_len, char); + } + str_2mortal(str); + if (++sp > stack->ary_max) { + astore(stack, sp, Nullstr); + st = stack->ary_array; + } + str = Str_new(58,80); + goto keepgoing; + } + else if (!tmplen && str->str_len - str->str_cur > 80) { + /* try to reclaim a bit of scalar space on 1st alloc */ + if (str->str_cur < 60) + str->str_len = 80; + else + str->str_len = str->str_cur+40; /* allow some slop */ + Renew(str->str_ptr, str->str_len, char); + } + } + rschar = old_rschar; + rslen = old_rslen; +#ifdef DEBUGGING + tmps = "READ"; +#endif + break; + } +#ifdef DEBUGGING + if (debug & 8) { + if (strEQ(tmps, "NULL")) + deb("%d.%s\n",anum,tmps); + else + deb("%d.%s = '%s'\n",anum,tmps,str_peek(st[sp])); + } +#endif + if (anum < 8) + arglast[anum] = sp; + } + + if (ppaddr[optype]) { + int status; + + /* pretend like we've been maintaining stack_* all along */ + stack_ary = stack->ary_array; + stack_sp = stack_ary + sp; + if (mark[optype] && stack_mark != arglast[0]) + warn("Inconsistent stack mark %d != %d", stack_mark, arglast[0]); + stack_max = stack_ary + stack->ary_max; + + status = (*ppaddr[optype])(str, arg, gimme); + + if (savestack->ary_fill > mymarkbase) { + warn("Inconsistent stack base"); + restorelist(mymarkbase); + } + sp = stack_sp - stack_ary; + if (sp < arglast[0]) + warn("TOO MANY POPS"); + st += arglast[0]; + goto array_return; + } + + st += arglast[0]; + +#ifdef SMALLSWITCHES + if (optype < O_CHOWN) +#endif + switch (optype) { + case O_RCAT: + STABSET(str); + break; + case O_ITEM: + if (gimme == G_ARRAY) + goto array_return; + /* FALL THROUGH */ + case O_SCALAR: + STR_SSET(str,st[1]); + STABSET(str); + break; + case O_ITEM2: + if (gimme == G_ARRAY) + goto array_return; + --anum; + STR_SSET(str,st[arglast[anum]-arglast[0]]); + STABSET(str); + break; + case O_ITEM3: + if (gimme == G_ARRAY) + goto array_return; + --anum; + STR_SSET(str,st[arglast[anum]-arglast[0]]); + STABSET(str); + break; + case O_CONCAT: + STR_SSET(str,st[1]); + str_scat(str,st[2]); + STABSET(str); + break; + case O_REPEAT: + if (gimme == G_ARRAY && arg[1].arg_flags & AF_ARYOK) { + sp = do_repeatary(arglast); + goto array_return; + } + STR_SSET(str,st[1]); + anum = (int)str_gnum(st[2]); + if (anum >= 1) { + tmpstr = Str_new(50, 0); + tmps = str_get(str); + str_nset(tmpstr,tmps,str->str_cur); + tmps = str_get(tmpstr); /* force to be string */ + STR_GROW(str, (anum * str->str_cur) + 1); + repeatcpy(str->str_ptr, tmps, tmpstr->str_cur, anum); + str->str_cur *= anum; + str->str_ptr[str->str_cur] = '\0'; + str->str_nok = 0; + str_free(tmpstr); + } + else { + if (dowarn && st[2]->str_pok && !looks_like_number(st[2])) + warn("Right operand of x is not numeric"); + str_sset(str,&str_no); + } + STABSET(str); + break; + case O_MATCH: + sp = do_match(str,arg, + gimme,arglast); + if (gimme == G_ARRAY) + goto array_return; + STABSET(str); + break; + case O_NMATCH: + sp = do_match(str,arg, + G_SCALAR,arglast); + str_sset(str, str_true(str) ? &str_no : &str_yes); + STABSET(str); + break; + case O_SUBST: + sp = do_subst(str,arg,arglast[0]); + goto array_return; + case O_NSUBST: + sp = do_subst(str,arg,arglast[0]); + str = arg->arg_ptr.arg_str; + str_set(str, str_true(str) ? No : Yes); + goto array_return; + case O_ASSIGN: + if (arg[1].arg_flags & AF_ARYOK) { + if (arg->arg_len == 1) { + arg->arg_type = O_LOCAL; + goto local; + } + else { + arg->arg_type = O_AASSIGN; + goto aassign; + } + } + else { + arg->arg_type = O_SASSIGN; + goto sassign; + } + case O_LOCAL: + local: + arglast[2] = arglast[1]; /* push a null array */ + /* FALL THROUGH */ + case O_AASSIGN: + aassign: + sp = do_assign(arg, + gimme,arglast); + goto array_return; + case O_SASSIGN: + sassign: +#ifdef TAINT + if (tainted && !st[2]->str_tainted) + tainted = 0; +#endif + STR_SSET(str, st[2]); + STABSET(str); + break; + case O_CHOP: + st -= arglast[0]; + str = arg->arg_ptr.arg_str; + for (sp = arglast[0] + 1; sp <= arglast[1]; sp++) + do_chop(str,st[sp]); + st += arglast[0]; + break; + case O_DEFINED: + if (arg[1].arg_type & A_DONT) { + sp = do_defined(str,arg, + gimme,arglast); + goto array_return; + } + else if (str->str_pok || str->str_nok) + goto say_yes; + goto say_no; + case O_UNDEF: + if (arg[1].arg_type & A_DONT) { + sp = do_undef(str,arg, + gimme,arglast); + goto array_return; + } + else if (str != stab_val(defstab)) { + if (str->str_len) { + if (str->str_state == SS_INCR) + Str_Grow(str,0); + Safefree(str->str_ptr); + str->str_ptr = Nullch; + str->str_len = 0; + } + str->str_pok = str->str_nok = 0; + STABSET(str); + } + goto say_undef; + case O_STUDY: + sp = do_study(str,arg, + gimme,arglast); + goto array_return; + case O_POW: + value = str_gnum(st[1]); + value = pow(value,str_gnum(st[2])); + goto donumset; + case O_MULTIPLY: + value = str_gnum(st[1]); + value *= str_gnum(st[2]); + goto donumset; + case O_DIVIDE: + if ((value = str_gnum(st[2])) == 0.0) + fatal("Illegal division by zero"); +#ifdef SLOPPYDIVIDE + /* insure that 20./5. == 4. */ + { + double x; + int k; + x = str_gnum(st[1]); + if ((double)(int)x == x && + (double)(int)value == value && + (k = (int)x/(int)value)*(int)value == (int)x) { + value = k; + } else { + value = x/value; + } + } +#else + value = str_gnum(st[1]) / value; +#endif + goto donumset; + case O_MODULO: + tmpulong = (unsigned long) str_gnum(st[2]); + if (tmpulong == 0L) + fatal("Illegal modulus zero"); +#ifndef lint + value = str_gnum(st[1]); + if (value >= 0.0) + value = (double)(((unsigned long)value) % tmpulong); + else { + tmplong = (long)value; + value = (double)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1; + } +#endif + goto donumset; + case O_ADD: + value = str_gnum(st[1]); + value += str_gnum(st[2]); + goto donumset; + case O_SUBTRACT: + value = str_gnum(st[1]); + value -= str_gnum(st[2]); + goto donumset; + case O_LEFT_SHIFT: + value = str_gnum(st[1]); + anum = (int)str_gnum(st[2]); +#ifndef lint + value = (double)(U_L(value) << anum); +#endif + goto donumset; + case O_RIGHT_SHIFT: + value = str_gnum(st[1]); + anum = (int)str_gnum(st[2]); +#ifndef lint + value = (double)(U_L(value) >> anum); +#endif + goto donumset; + case O_LT: + value = str_gnum(st[1]); + value = (value < str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_GT: + value = str_gnum(st[1]); + value = (value > str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_LE: + value = str_gnum(st[1]); + value = (value <= str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_GE: + value = str_gnum(st[1]); + value = (value >= str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_EQ: + if (dowarn) { + if ((!st[1]->str_nok && !looks_like_number(st[1])) || + (!st[2]->str_nok && !looks_like_number(st[2])) ) + warn("Possible use of == on string value"); + } + value = str_gnum(st[1]); + value = (value == str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_NE: + value = str_gnum(st[1]); + value = (value != str_gnum(st[2])) ? 1.0 : 0.0; + goto donumset; + case O_NCMP: + value = str_gnum(st[1]); + value -= str_gnum(st[2]); + if (value > 0.0) + value = 1.0; + else if (value < 0.0) + value = -1.0; + goto donumset; + case O_BIT_AND: + if (!sawvec || st[1]->str_nok || st[2]->str_nok) { + value = str_gnum(st[1]); +#ifndef lint + value = (double)(U_L(value) & U_L(str_gnum(st[2]))); +#endif + goto donumset; + } + else + do_vop(optype,str,st[1],st[2]); + break; + case O_XOR: + if (!sawvec || st[1]->str_nok || st[2]->str_nok) { + value = str_gnum(st[1]); +#ifndef lint + value = (double)(U_L(value) ^ U_L(str_gnum(st[2]))); +#endif + goto donumset; + } + else + do_vop(optype,str,st[1],st[2]); + break; + case O_BIT_OR: + if (!sawvec || st[1]->str_nok || st[2]->str_nok) { + value = str_gnum(st[1]); +#ifndef lint + value = (double)(U_L(value) | U_L(str_gnum(st[2]))); +#endif + goto donumset; + } + else + do_vop(optype,str,st[1],st[2]); + break; +/* use register in evaluating str_true() */ + case O_AND: + if (str_true(st[1])) { + anum = 2; + optype = O_ITEM2; + argflags = arg[anum].arg_flags; + if (gimme == G_ARRAY) + argflags |= AF_ARYOK; + argtype = arg[anum].arg_type & A_MASK; + argptr = arg[anum].arg_ptr; + maxarg = anum = 1; + sp = arglast[0]; + st -= sp; + goto re_eval; + } + else { + if (assigning) { + str_sset(str, st[1]); + STABSET(str); + } + else + str = st[1]; + break; + } + case O_OR: + if (str_true(st[1])) { + if (assigning) { + str_sset(str, st[1]); + STABSET(str); + } + else + str = st[1]; + break; + } + else { + anum = 2; + optype = O_ITEM2; + argflags = arg[anum].arg_flags; + if (gimme == G_ARRAY) + argflags |= AF_ARYOK; + argtype = arg[anum].arg_type & A_MASK; + argptr = arg[anum].arg_ptr; + maxarg = anum = 1; + sp = arglast[0]; + st -= sp; + goto re_eval; + } + case O_COND_EXPR: + anum = (str_true(st[1]) ? 2 : 3); + optype = (anum == 2 ? O_ITEM2 : O_ITEM3); + argflags = arg[anum].arg_flags; + if (gimme == G_ARRAY) + argflags |= AF_ARYOK; + argtype = arg[anum].arg_type & A_MASK; + argptr = arg[anum].arg_ptr; + maxarg = anum = 1; + sp = arglast[0]; + st -= sp; + goto re_eval; + case O_COMMA: + if (gimme == G_ARRAY) + goto array_return; + str = st[2]; + break; + case O_NEGATE: + value = -str_gnum(st[1]); + goto donumset; + case O_NOT: +#ifdef NOTNOT + { char xxx = str_true(st[1]); value = (double) !xxx; } +#else + value = (double) !str_true(st[1]); +#endif + goto donumset; + case O_COMPLEMENT: + if (!sawvec || st[1]->str_nok) { +#ifndef lint + value = (double) ~U_L(str_gnum(st[1])); +#endif + goto donumset; + } + else { + STR_SSET(str,st[1]); + tmps = str_get(str); + for (anum = str->str_cur; anum; anum--, tmps++) + *tmps = ~*tmps; + } + break; + case O_SELECT: + stab_efullname(str,defoutstab); + if (maxarg > 0) { + if ((arg[1].arg_type & A_MASK) == A_WORD) + defoutstab = arg[1].arg_ptr.arg_stab; + else + defoutstab = stabent(str_get(st[1]),TRUE); + if (!stab_io(defoutstab)) + stab_io(defoutstab) = stio_new(); + curoutstab = defoutstab; + } + STABSET(str); + break; + case O_WRITE: + if (maxarg == 0) + stab = defoutstab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) { + if (!(stab = arg[1].arg_ptr.arg_stab)) + stab = defoutstab; + } + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab_io(stab)) { + str_set(str, No); + STABSET(str); + break; + } + curoutstab = stab; + fp = stab_io(stab)->ofp; + if (stab_io(stab)->fmt_stab) + form = stab_form(stab_io(stab)->fmt_stab); + else + form = stab_form(stab); + if (!form || !fp) { + if (dowarn) { + if (form) + warn("No format for filehandle"); + else { + if (stab_io(stab)->ifp) + warn("Filehandle only opened for input"); + else + warn("Write on closed filehandle"); + } + } + str_set(str, No); + STABSET(str); + break; + } + format(&outrec,form,sp); + do_write(&outrec,stab,sp); + if (stab_io(stab)->flags & IOF_FLUSH) + (void)fflush(fp); + str_set(str, Yes); + STABSET(str); + break; + case O_DBMOPEN: +#ifdef SOME_DBM + anum = arg[1].arg_type & A_MASK; + if (anum == A_WORD || anum == A_STAB) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (st[3]->str_nok || st[3]->str_pok) + anum = (int)str_gnum(st[3]); + else + anum = -1; + value = (double)hdbmopen(stab_hash(stab),str_get(st[2]),anum); + goto donumset; +#else + fatal("No dbm or ndbm on this machine"); +#endif + case O_DBMCLOSE: +#ifdef SOME_DBM + anum = arg[1].arg_type & A_MASK; + if (anum == A_WORD || anum == A_STAB) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + hdbmclose(stab_hash(stab)); + goto say_yes; +#else + fatal("No dbm or ndbm on this machine"); +#endif + case O_OPEN: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + tmps = str_get(st[2]); + if (do_open(stab,tmps,st[2]->str_cur)) { + value = (double)forkprocess; + stab_io(stab)->lines = 0; + goto donumset; + } + else if (forkprocess == 0) /* we are a new child */ + goto say_zero; + else + goto say_undef; + /* break; */ + case O_TRANS: + value = (double) do_trans(str,arg); + str = arg->arg_ptr.arg_str; + goto donumset; + case O_NTRANS: + str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No); + str = arg->arg_ptr.arg_str; + break; + case O_CLOSE: + if (maxarg == 0) + stab = defoutstab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + str_set(str, do_close(stab,TRUE) ? Yes : No ); + STABSET(str); + break; + case O_EACH: + sp = do_each(str,stab_hash(arg[1].arg_ptr.arg_stab), + gimme,arglast); + goto array_return; + case O_VALUES: + case O_KEYS: + sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype, + gimme,arglast); + goto array_return; + case O_LARRAY: + str->str_nok = str->str_pok = 0; + str->str_u.str_stab = arg[1].arg_ptr.arg_stab; + str->str_state = SS_ARY; + break; + case O_ARRAY: + ary = stab_array(arg[1].arg_ptr.arg_stab); + maxarg = ary->ary_fill + 1; + if (gimme == G_ARRAY) { /* array wanted */ + sp = arglast[0]; + st -= sp; + if (maxarg > 0 && sp + maxarg > stack->ary_max) { + astore(stack,sp + maxarg, Nullstr); + st = stack->ary_array; + } + st += sp; + Copy(ary->ary_array, &st[1], maxarg, STR*); + sp += maxarg; + goto array_return; + } + else { + value = (double)maxarg; + goto donumset; + } + case O_AELEM: + anum = ((int)str_gnum(st[2])) - arybase; + str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,FALSE); + break; + case O_DELETE: + tmpstab = arg[1].arg_ptr.arg_stab; + tmps = str_get(st[2]); + str = hdelete(stab_hash(tmpstab),tmps,st[2]->str_cur); + if (tmpstab == envstab) + my_setenv(tmps,Nullch); + if (!str) + goto say_undef; + break; + case O_LHASH: + str->str_nok = str->str_pok = 0; + str->str_u.str_stab = arg[1].arg_ptr.arg_stab; + str->str_state = SS_HASH; + break; + case O_HASH: + if (gimme == G_ARRAY) { /* array wanted */ + sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype, + gimme,arglast); + goto array_return; + } + else { + tmpstab = arg[1].arg_ptr.arg_stab; + if (!stab_hash(tmpstab)->tbl_fill) + goto say_zero; + sprintf(buf,"%d/%d",stab_hash(tmpstab)->tbl_fill, + stab_hash(tmpstab)->tbl_max+1); + str_set(str,buf); + } + break; + case O_HELEM: + tmpstab = arg[1].arg_ptr.arg_stab; + tmps = str_get(st[2]); + str = hfetch(stab_hash(tmpstab),tmps,st[2]->str_cur,FALSE); + break; + case O_LAELEM: + anum = ((int)str_gnum(st[2])) - arybase; + str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,TRUE); + if (!str || str == &str_undef) + fatal("Assignment to non-creatable value, subscript %d",anum); + break; + case O_LHELEM: + tmpstab = arg[1].arg_ptr.arg_stab; + tmps = str_get(st[2]); + anum = st[2]->str_cur; + str = hfetch(stab_hash(tmpstab),tmps,anum,TRUE); + if (!str || str == &str_undef) + fatal("Assignment to non-creatable value, subscript \"%s\"",tmps); + if (tmpstab == envstab) /* heavy wizardry going on here */ + str_magic(str, tmpstab, 'E', tmps, anum); /* str is now magic */ + /* he threw the brick up into the air */ + else if (tmpstab == sigstab) + str_magic(str, tmpstab, 'S', tmps, anum); +#ifdef SOME_DBM + else if (stab_hash(tmpstab)->tbl_dbm) + str_magic(str, tmpstab, 'D', tmps, anum); +#endif + else if (tmpstab == DBline) + str_magic(str, tmpstab, 'L', tmps, anum); + break; + case O_LSLICE: + anum = 2; + argtype = FALSE; + goto do_slice_already; + case O_ASLICE: + anum = 1; + argtype = FALSE; + goto do_slice_already; + case O_HSLICE: + anum = 0; + argtype = FALSE; + goto do_slice_already; + case O_LASLICE: + anum = 1; + argtype = TRUE; + goto do_slice_already; + case O_LHSLICE: + anum = 0; + argtype = TRUE; + do_slice_already: + sp = do_slice(arg[1].arg_ptr.arg_stab,str,anum,argtype, + gimme,arglast); + goto array_return; + case O_SPLICE: + sp = do_splice(stab_array(arg[1].arg_ptr.arg_stab),gimme,arglast); + goto array_return; + case O_PUSH: + if (arglast[2] - arglast[1] != 1) + str = do_push(stab_array(arg[1].arg_ptr.arg_stab),arglast); + else { + str = Str_new(51,0); /* must copy the STR */ + str_sset(str,st[2]); + (void)apush(stab_array(arg[1].arg_ptr.arg_stab),str); + } + break; + case O_POP: + str = apop(ary = stab_array(arg[1].arg_ptr.arg_stab)); + goto staticalization; + case O_SHIFT: + str = ashift(ary = stab_array(arg[1].arg_ptr.arg_stab)); + staticalization: + if (!str) + goto say_undef; + if (ary->ary_flags & ARF_REAL) + (void)str_2mortal(str); + break; + case O_UNPACK: + sp = do_unpack(str,gimme,arglast); + goto array_return; + case O_SPLIT: + value = str_gnum(st[3]); + sp = do_split(str, arg[2].arg_ptr.arg_spat, (int)value, + gimme,arglast); + goto array_return; + case O_LENGTH: + if (maxarg < 1) + value = (double)str_len(stab_val(defstab)); + else + value = (double)str_len(st[1]); + goto donumset; + case O_SPRINTF: + do_sprintf(str, sp-arglast[0], st+1); + break; + case O_SUBSTR: + anum = ((int)str_gnum(st[2])) - arybase; /* anum=where to start*/ + tmps = str_get(st[1]); /* force conversion to string */ + /*SUPPRESS 560*/ + if (argtype = (str == st[1])) + str = arg->arg_ptr.arg_str; + if (anum < 0) + anum += st[1]->str_cur + arybase; + if (anum < 0 || anum > st[1]->str_cur) + str_nset(str,"",0); + else { + optype = maxarg < 3 ? st[1]->str_cur : (int)str_gnum(st[3]); + if (optype < 0) + optype = 0; + tmps += anum; + anum = st[1]->str_cur - anum; /* anum=how many bytes left*/ + if (anum > optype) + anum = optype; + str_nset(str, tmps, anum); + if (argtype) { /* it's an lvalue! */ + Lstring *lstr = (Lstring*)str; + + str->str_magic = st[1]; + st[1]->str_rare = 's'; + lstr->lstr_offset = tmps - str_get(st[1]); + lstr->lstr_len = anum; + } + } + break; + case O_PACK: + /*SUPPRESS 701*/ + (void)do_pack(str,arglast); + break; + case O_GREP: + sp = do_grep(arg,str,gimme,arglast); + goto array_return; + case O_JOIN: + do_join(str,arglast); + break; + case O_SLT: + tmps = str_get(st[1]); + value = (double) (str_cmp(st[1],st[2]) < 0); + goto donumset; + case O_SGT: + tmps = str_get(st[1]); + value = (double) (str_cmp(st[1],st[2]) > 0); + goto donumset; + case O_SLE: + tmps = str_get(st[1]); + value = (double) (str_cmp(st[1],st[2]) <= 0); + goto donumset; + case O_SGE: + tmps = str_get(st[1]); + value = (double) (str_cmp(st[1],st[2]) >= 0); + goto donumset; + case O_SEQ: + tmps = str_get(st[1]); + value = (double) str_eq(st[1],st[2]); + goto donumset; + case O_SNE: + tmps = str_get(st[1]); + value = (double) !str_eq(st[1],st[2]); + goto donumset; + case O_SCMP: + tmps = str_get(st[1]); + value = (double) str_cmp(st[1],st[2]); + goto donumset; + case O_SUBR: + sp = do_subr(arg,gimme,arglast); + st = stack->ary_array + arglast[0]; /* maybe realloced */ + goto array_return; + case O_DBSUBR: + sp = do_subr(arg,gimme,arglast); + st = stack->ary_array + arglast[0]; /* maybe realloced */ + goto array_return; + case O_CALLER: + sp = do_caller(arg,maxarg,gimme,arglast); + st = stack->ary_array + arglast[0]; /* maybe realloced */ + goto array_return; + case O_SORT: + sp = do_sort(str,arg, + gimme,arglast); + goto array_return; + case O_REVERSE: + if (gimme == G_ARRAY) + sp = do_reverse(arglast); + else + sp = do_sreverse(str, arglast); + goto array_return; + case O_WARN: + if (arglast[2] - arglast[1] != 1) { + do_join(str,arglast); + tmps = str_get(str); + } + else { + str = st[2]; + tmps = str_get(st[2]); + } + if (!tmps || !*tmps) + tmps = "Warning: something's wrong"; + warn("%s",tmps); + goto say_yes; + case O_DIE: + if (arglast[2] - arglast[1] != 1) { + do_join(str,arglast); + tmps = str_get(str); + } + else { + str = st[2]; + tmps = str_get(st[2]); + } + if (!tmps || !*tmps) + tmps = "Died"; + fatal("%s",tmps); + goto say_zero; + case O_PRTF: + case O_PRINT: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab) + stab = defoutstab; + if (!stab_io(stab)) { + if (dowarn) + warn("Filehandle never opened"); + goto say_zero; + } + if (!(fp = stab_io(stab)->ofp)) { + if (dowarn) { + if (stab_io(stab)->ifp) + warn("Filehandle opened only for input"); + else + warn("Print on closed filehandle"); + } + goto say_zero; + } + else { + if (optype == O_PRTF || arglast[2] - arglast[1] != 1) + value = (double)do_aprint(arg,fp,arglast); + else { + value = (double)do_print(st[2],fp); + if (orslen && optype == O_PRINT) + if (fwrite(ors, 1, orslen, fp) == 0) + goto say_zero; + } + if (stab_io(stab)->flags & IOF_FLUSH) + if (fflush(fp) == EOF) + goto say_zero; + } + goto donumset; + case O_CHDIR: + if (maxarg < 1) + tmps = Nullch; + else + tmps = str_get(st[1]); + if (!tmps || !*tmps) { + tmpstr = hfetch(stab_hash(envstab),"HOME",4,FALSE); + tmps = str_get(tmpstr); + } + if (!tmps || !*tmps) { + tmpstr = hfetch(stab_hash(envstab),"LOGDIR",6,FALSE); + tmps = str_get(tmpstr); + } +#ifdef TAINT + TAINT_PROPER("chdir"); +#endif + value = (double)(chdir(tmps) >= 0); + goto donumset; + case O_EXIT: + if (maxarg < 1) + anum = 0; + else + anum = (int)str_gnum(st[1]); + my_exit(anum); + goto say_zero; + case O_RESET: + if (maxarg < 1) + tmps = ""; + else + tmps = str_get(st[1]); + str_reset(tmps,curcmd->c_stash); + value = 1.0; + goto donumset; + case O_LIST: + if (gimme == G_ARRAY) + goto array_return; + if (maxarg > 0) + str = st[sp - arglast[0]]; /* unwanted list, return last item */ + else + str = &str_undef; + break; + case O_EOF: + if (maxarg <= 0) + stab = last_in_stab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + str_set(str, do_eof(stab) ? Yes : No); + STABSET(str); + break; + case O_GETC: + if (maxarg <= 0) + stab = stdinstab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab) + stab = argvstab; + if (!stab || do_eof(stab)) /* make sure we have fp with something */ + goto say_undef; + else { +#ifdef TAINT + tainted = 1; +#endif + str_set(str," "); + *str->str_ptr = getc(stab_io(stab)->ifp); /* should never be EOF */ + } + STABSET(str); + break; + case O_TELL: + if (maxarg <= 0) + stab = last_in_stab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_tell(stab); +#else + (void)do_tell(stab); +#endif + goto donumset; + case O_RECV: + case O_READ: + case O_SYSREAD: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + tmps = str_get(st[2]); + anum = (int)str_gnum(st[3]); + errno = 0; + maxarg = sp - arglast[0]; + if (maxarg > 4) + warn("Too many args on read"); + if (maxarg == 4) + maxarg = (int)str_gnum(st[4]); + else + maxarg = 0; + if (!stab_io(stab) || !stab_io(stab)->ifp) + goto say_undef; +#ifdef HAS_SOCKET + if (optype == O_RECV) { + argtype = sizeof buf; + STR_GROW(st[2], anum+1), (tmps = str_get(st[2])); /* sneaky */ + anum = recvfrom(fileno(stab_io(stab)->ifp), tmps, anum, maxarg, + buf, &argtype); + if (anum >= 0) { + st[2]->str_cur = anum; + st[2]->str_ptr[anum] = '\0'; + str_nset(str,buf,argtype); + } + else + str_sset(str,&str_undef); + break; + } +#else + if (optype == O_RECV) + goto badsock; +#endif + STR_GROW(st[2], anum+maxarg+1), (tmps = str_get(st[2])); /* sneaky */ + if (optype == O_SYSREAD) { + anum = read(fileno(stab_io(stab)->ifp), tmps+maxarg, anum); + } + else +#ifdef HAS_SOCKET + if (stab_io(stab)->type == 's') { + argtype = sizeof buf; + anum = recvfrom(fileno(stab_io(stab)->ifp), tmps+maxarg, anum, 0, + buf, &argtype); + } + else +#endif + anum = fread(tmps+maxarg, 1, anum, stab_io(stab)->ifp); + if (anum < 0) + goto say_undef; + st[2]->str_cur = anum+maxarg; + st[2]->str_ptr[anum+maxarg] = '\0'; + value = (double)anum; + goto donumset; + case O_SYSWRITE: + case O_SEND: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + tmps = str_get(st[2]); + anum = (int)str_gnum(st[3]); + errno = 0; + stio = stab_io(stab); + maxarg = sp - arglast[0]; + if (!stio || !stio->ifp) { + anum = -1; + if (dowarn) { + if (optype == O_SYSWRITE) + warn("Syswrite on closed filehandle"); + else + warn("Send on closed socket"); + } + } + else if (optype == O_SYSWRITE) { + if (maxarg > 4) + warn("Too many args on syswrite"); + if (maxarg == 4) + optype = (int)str_gnum(st[4]); + else + optype = 0; + anum = write(fileno(stab_io(stab)->ifp), tmps+optype, anum); + } +#ifdef HAS_SOCKET + else if (maxarg >= 4) { + if (maxarg > 4) + warn("Too many args on send"); + tmps2 = str_get(st[4]); + anum = sendto(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur, + anum, tmps2, st[4]->str_cur); + } + else + anum = send(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur, anum); +#else + else + goto badsock; +#endif + if (anum < 0) + goto say_undef; + value = (double)anum; + goto donumset; + case O_SEEK: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + value = str_gnum(st[2]); + str_set(str, do_seek(stab, + (long)value, (int)str_gnum(st[3]) ) ? Yes : No); + STABSET(str); + break; + case O_RETURN: + tmps = "_SUB_"; /* just fake up a "last _SUB_" */ + optype = O_LAST; + if (curcsv && curcsv->wantarray == G_ARRAY) { + lastretstr = Nullstr; + lastspbase = arglast[1]; + lastsize = arglast[2] - arglast[1]; + } + else + lastretstr = str_mortal(st[arglast[2] - arglast[0]]); + goto dopop; + case O_REDO: + case O_NEXT: + case O_LAST: + tmps = Nullch; + if (maxarg > 0) { + tmps = str_get(arg[1].arg_ptr.arg_str); + dopop: + while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label || + strNE(tmps,loop_stack[loop_ptr].loop_label) )) { +#ifdef DEBUGGING + if (debug & 4) { + deb("(Skipping label #%d %s)\n",loop_ptr, + loop_stack[loop_ptr].loop_label); + } +#endif + loop_ptr--; + } +#ifdef DEBUGGING + if (debug & 4) { + deb("(Found label #%d %s)\n",loop_ptr, + loop_stack[loop_ptr].loop_label); + } +#endif + } + if (loop_ptr < 0) { + if (tmps && strEQ(tmps, "_SUB_")) + fatal("Can't return outside a subroutine"); + fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>"); + } + if (!lastretstr && optype == O_LAST && lastsize) { + st -= arglast[0]; + st += lastspbase + 1; + optype = loop_stack[loop_ptr].loop_sp - lastspbase; /* negative */ + if (optype) { + for (anum = lastsize; anum > 0; anum--,st++) + st[optype] = str_mortal(st[0]); + } + longjmp(loop_stack[loop_ptr].loop_env, O_LAST); + } + longjmp(loop_stack[loop_ptr].loop_env, optype); + case O_DUMP: + case O_GOTO:/* shudder */ + goto_targ = str_get(arg[1].arg_ptr.arg_str); + if (!*goto_targ) + goto_targ = Nullch; /* just restart from top */ + if (optype == O_DUMP) { + do_undump = TRUE; + my_unexec(); + } + longjmp(top_env, 1); + case O_INDEX: + tmps = str_get(st[1]); + if (maxarg < 3) + anum = 0; + else { + anum = (int) str_gnum(st[3]) - arybase; + if (anum < 0) + anum = 0; + else if (anum > st[1]->str_cur) + anum = st[1]->str_cur; + } +#ifndef lint + if (!(tmps2 = fbminstr((unsigned char*)tmps + anum, + (unsigned char*)tmps + st[1]->str_cur, st[2]))) +#else + if (tmps2 = fbminstr(Null(unsigned char*),Null(unsigned char*),Nullstr)) +#endif + value = (double)(-1 + arybase); + else + value = (double)(tmps2 - tmps + arybase); + goto donumset; + case O_RINDEX: + tmps = str_get(st[1]); + tmps2 = str_get(st[2]); + if (maxarg < 3) + anum = st[1]->str_cur; + else { + anum = (int) str_gnum(st[3]) - arybase + st[2]->str_cur; + if (anum < 0) + anum = 0; + else if (anum > st[1]->str_cur) + anum = st[1]->str_cur; + } +#ifndef lint + if (!(tmps2 = rninstr(tmps, tmps + anum, + tmps2, tmps2 + st[2]->str_cur))) +#else + if (tmps2 = rninstr(Nullch,Nullch,Nullch,Nullch)) +#endif + value = (double)(-1 + arybase); + else + value = (double)(tmps2 - tmps + arybase); + goto donumset; + case O_TIME: +#ifndef lint + value = (double) time(Null(long*)); +#endif + goto donumset; + case O_TMS: + sp = do_tms(str,gimme,arglast); + goto array_return; + case O_LOCALTIME: + if (maxarg < 1) + (void)time(&when); + else + when = (time_t)str_gnum(st[1]); + sp = do_time(str,localtime(&when), + gimme,arglast); + goto array_return; + case O_GMTIME: + if (maxarg < 1) + (void)time(&when); + else + when = (time_t)str_gnum(st[1]); + sp = do_time(str,gmtime(&when), + gimme,arglast); + goto array_return; + case O_TRUNCATE: + sp = do_truncate(str,arg, + gimme,arglast); + goto array_return; + case O_LSTAT: + case O_STAT: + sp = do_stat(str,arg, + gimme,arglast); + goto array_return; + case O_CRYPT: +#ifdef HAS_CRYPT + tmps = str_get(st[1]); +#ifdef FCRYPT + str_set(str,fcrypt(tmps,str_get(st[2]))); +#else + str_set(str,crypt(tmps,str_get(st[2]))); +#endif +#else + fatal( + "The crypt() function is unimplemented due to excessive paranoia."); +#endif + break; + case O_ATAN2: + value = str_gnum(st[1]); + value = atan2(value,str_gnum(st[2])); + goto donumset; + case O_SIN: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + value = sin(value); + goto donumset; + case O_COS: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + value = cos(value); + goto donumset; + case O_RAND: + if (maxarg < 1) + value = 1.0; + else + value = str_gnum(st[1]); + if (value == 0.0) + value = 1.0; +#if RANDBITS == 31 + value = rand() * value / 2147483648.0; +#else +#if RANDBITS == 16 + value = rand() * value / 65536.0; +#else +#if RANDBITS == 15 + value = rand() * value / 32768.0; +#else + value = rand() * value / (double)(((unsigned long)1) << RANDBITS); +#endif +#endif +#endif + goto donumset; + case O_SRAND: + if (maxarg < 1) { + (void)time(&when); + anum = when; + } + else + anum = (int)str_gnum(st[1]); + (void)srand(anum); + goto say_yes; + case O_EXP: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + value = exp(value); + goto donumset; + case O_LOG: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + if (value <= 0.0) + fatal("Can't take log of %g\n", value); + value = log(value); + goto donumset; + case O_SQRT: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + if (value < 0.0) + fatal("Can't take sqrt of %g\n", value); + value = sqrt(value); + goto donumset; + case O_INT: + if (maxarg < 1) + value = str_gnum(stab_val(defstab)); + else + value = str_gnum(st[1]); + if (value >= 0.0) + (void)modf(value,&value); + else { + (void)modf(-value,&value); + value = -value; + } + goto donumset; + case O_ORD: + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); +#ifndef I286 + value = (double) (*tmps & 255); +#else + anum = (int) *tmps; + value = (double) (anum & 255); +#endif + goto donumset; + case O_ALARM: +#ifdef HAS_ALARM + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); + if (!tmps) + tmps = "0"; + anum = alarm((unsigned int)atoi(tmps)); + if (anum < 0) + goto say_undef; + value = (double)anum; + goto donumset; +#else + fatal("Unsupported function alarm"); + break; +#endif + case O_SLEEP: + if (maxarg < 1) + tmps = Nullch; + else + tmps = str_get(st[1]); + (void)time(&when); + if (!tmps || !*tmps) + sleep((32767<<16)+32767); + else + sleep((unsigned int)atoi(tmps)); +#ifndef lint + value = (double)when; + (void)time(&when); + value = ((double)when) - value; +#endif + goto donumset; + case O_RANGE: + sp = do_range(gimme,arglast); + goto array_return; + case O_F_OR_R: + if (gimme == G_ARRAY) { /* it's a range */ + /* can we optimize to constant array? */ + if ((arg[1].arg_type & A_MASK) == A_SINGLE && + (arg[2].arg_type & A_MASK) == A_SINGLE) { + st[2] = arg[2].arg_ptr.arg_str; + sp = do_range(gimme,arglast); + st = stack->ary_array; + maxarg = sp - arglast[0]; + str_free(arg[1].arg_ptr.arg_str); + arg[1].arg_ptr.arg_str = Nullstr; + str_free(arg[2].arg_ptr.arg_str); + arg[2].arg_ptr.arg_str = Nullstr; + arg->arg_type = O_ARRAY; + arg[1].arg_type = A_STAB|A_DONT; + arg->arg_len = 1; + stab = arg[1].arg_ptr.arg_stab = aadd(genstab()); + ary = stab_array(stab); + afill(ary,maxarg - 1); + anum = maxarg; + st += arglast[0]+1; + while (maxarg-- > 0) + ary->ary_array[maxarg] = str_smake(st[maxarg]); + st -= arglast[0]+1; + goto array_return; + } + arg->arg_type = optype = O_RANGE; + maxarg = arg->arg_len = 2; + anum = 2; + arg[anum].arg_flags &= ~AF_ARYOK; + argflags = arg[anum].arg_flags; + argtype = arg[anum].arg_type & A_MASK; + arg[anum].arg_type = argtype; + argptr = arg[anum].arg_ptr; + sp = arglast[0]; + st -= sp; + sp++; + goto re_eval; + } + arg->arg_type = O_FLIP; + /* FALL THROUGH */ + case O_FLIP: + if ((arg[1].arg_type & A_MASK) == A_SINGLE ? + last_in_stab && (int)str_gnum(st[1]) == stab_io(last_in_stab)->lines + : + str_true(st[1]) ) { + arg[2].arg_type &= ~A_DONT; + arg[1].arg_type |= A_DONT; + arg->arg_type = optype = O_FLOP; + if (arg->arg_flags & AF_COMMON) { + str_numset(str,0.0); + anum = 2; + argflags = arg[2].arg_flags; + argtype = arg[2].arg_type & A_MASK; + argptr = arg[2].arg_ptr; + sp = arglast[0]; + st -= sp++; + goto re_eval; + } + else { + str_numset(str,1.0); + break; + } + } + str_set(str,""); + break; + case O_FLOP: + str_inc(str); + if ((arg[2].arg_type & A_MASK) == A_SINGLE ? + last_in_stab && (int)str_gnum(st[2]) == stab_io(last_in_stab)->lines + : + str_true(st[2]) ) { + arg->arg_type = O_FLIP; + arg[1].arg_type &= ~A_DONT; + arg[2].arg_type |= A_DONT; + str_cat(str,"E0"); + } + break; + case O_FORK: +#ifdef HAS_FORK + anum = fork(); + if (anum < 0) + goto say_undef; + if (!anum) { + /*SUPPRESS 560*/ + if (tmpstab = stabent("$",allstabs)) + str_numset(STAB_STR(tmpstab),(double)getpid()); + hclear(pidstatus, FALSE); /* no kids, so don't wait for 'em */ + } + value = (double)anum; + goto donumset; +#else + fatal("Unsupported function fork"); + break; +#endif + case O_WAIT: +#ifdef HAS_WAIT +#ifndef lint + anum = wait(&argflags); + if (anum > 0) + pidgone(anum,argflags); + value = (double)anum; +#endif + statusvalue = (unsigned short)argflags; + goto donumset; +#else + fatal("Unsupported function wait"); + break; +#endif + case O_WAITPID: +#ifdef HAS_WAIT +#ifndef lint + anum = (int)str_gnum(st[1]); + optype = (int)str_gnum(st[2]); + anum = wait4pid(anum, &argflags,optype); + value = (double)anum; +#endif + statusvalue = (unsigned short)argflags; + goto donumset; +#else + fatal("Unsupported function wait"); + break; +#endif + case O_SYSTEM: +#ifdef HAS_FORK +#ifdef TAINT + if (arglast[2] - arglast[1] == 1) { + taintenv(); + tainted |= st[2]->str_tainted; + TAINT_PROPER("system"); + } +#endif + while ((anum = vfork()) == -1) { + if (errno != EAGAIN) { + value = -1.0; + goto donumset; + } + sleep(5); + } + if (anum > 0) { +#ifndef lint + ihand = signal(SIGINT, SIG_IGN); + qhand = signal(SIGQUIT, SIG_IGN); + argtype = wait4pid(anum, &argflags, 0); +#else + ihand = qhand = 0; +#endif + (void)signal(SIGINT, ihand); + (void)signal(SIGQUIT, qhand); + statusvalue = (unsigned short)argflags; + if (argtype < 0) + value = -1.0; + else { + value = (double)((unsigned int)argflags & 0xffff); + } + do_execfree(); /* free any memory child malloced on vfork */ + goto donumset; + } + if ((arg[1].arg_type & A_MASK) == A_STAB) + value = (double)do_aexec(st[1],arglast); + else if (arglast[2] - arglast[1] != 1) + value = (double)do_aexec(Nullstr,arglast); + else { + value = (double)do_exec(str_get(str_mortal(st[2]))); + } + _exit(-1); +#else /* ! FORK */ + if ((arg[1].arg_type & A_MASK) == A_STAB) + value = (double)do_aspawn(st[1],arglast); + else if (arglast[2] - arglast[1] != 1) + value = (double)do_aspawn(Nullstr,arglast); + else { + value = (double)do_spawn(str_get(str_mortal(st[2]))); + } + goto donumset; +#endif /* FORK */ + case O_EXEC_OP: + if ((arg[1].arg_type & A_MASK) == A_STAB) + value = (double)do_aexec(st[1],arglast); + else if (arglast[2] - arglast[1] != 1) + value = (double)do_aexec(Nullstr,arglast); + else { +#ifdef TAINT + taintenv(); + tainted |= st[2]->str_tainted; + TAINT_PROPER("exec"); +#endif + value = (double)do_exec(str_get(str_mortal(st[2]))); + } + goto donumset; + case O_HEX: + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); + value = (double)scanhex(tmps, 99, &argtype); + goto donumset; + + case O_OCT: + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); + while (*tmps && (isSPACE(*tmps) || *tmps == '0')) + tmps++; + if (*tmps == 'x') + value = (double)scanhex(++tmps, 99, &argtype); + else + value = (double)scanoct(tmps, 99, &argtype); + goto donumset; + +/* These common exits are hidden here in the middle of the switches for the + benefit of those machines with limited branch addressing. Sigh. */ + +array_return: +#ifdef DEBUGGING + if (debug) { + dlevel--; + if (debug & 8) { + anum = sp - arglast[0]; + switch (anum) { + case 0: + deb("%s RETURNS ()\n",opname[optype]); + break; + case 1: + deb("%s RETURNS (\"%s\")\n",opname[optype], + st[1] ? str_get(st[1]) : ""); + break; + default: + tmps = st[1] ? str_get(st[1]) : ""; + deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype], + anum,tmps,anum==2?"":"...,", + st[anum] ? str_get(st[anum]) : ""); + break; + } + } + } +#endif + stack_ary = stack->ary_array; + stack_max = stack_ary + stack->ary_max; + stack_sp = stack_ary + sp; + return sp; + +say_yes: + str = &str_yes; + goto normal_return; + +say_no: + str = &str_no; + goto normal_return; + +say_undef: + str = &str_undef; + goto normal_return; + +say_zero: + value = 0.0; + /* FALL THROUGH */ + +donumset: + str_numset(str,value); + STABSET(str); + st[1] = str; +#ifdef DEBUGGING + if (debug) { + dlevel--; + if (debug & 8) + deb("%s RETURNS \"%f\"\n",opname[optype],value); + } +#endif + stack_ary = stack->ary_array; + stack_max = stack_ary + stack->ary_max; + stack_sp = stack_ary + arglast[0] + 1; + return arglast[0] + 1; +#ifdef SMALLSWITCHES + } + else + switch (optype) { +#endif + case O_CHOWN: +#ifdef HAS_CHOWN + value = (double)apply(optype,arglast); + goto donumset; +#else + fatal("Unsupported function chown"); + break; +#endif + case O_KILL: +#ifdef HAS_KILL + value = (double)apply(optype,arglast); + goto donumset; +#else + fatal("Unsupported function kill"); + break; +#endif + case O_UNLINK: + case O_CHMOD: + case O_UTIME: + value = (double)apply(optype,arglast); + goto donumset; + case O_UMASK: +#ifdef HAS_UMASK + if (maxarg < 1) { + anum = umask(0); + (void)umask(anum); + } + else + anum = umask((int)str_gnum(st[1])); + value = (double)anum; +#ifdef TAINT + TAINT_PROPER("umask"); +#endif + goto donumset; +#else + fatal("Unsupported function umask"); + break; +#endif +#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM) + case O_MSGGET: + case O_SHMGET: + case O_SEMGET: + if ((anum = do_ipcget(optype, arglast)) == -1) + goto say_undef; + value = (double)anum; + goto donumset; + case O_MSGCTL: + case O_SHMCTL: + case O_SEMCTL: + anum = do_ipcctl(optype, arglast); + if (anum == -1) + goto say_undef; + if (anum != 0) { + value = (double)anum; + goto donumset; + } + str_set(str,"0 but true"); + STABSET(str); + break; + case O_MSGSND: + value = (double)(do_msgsnd(arglast) >= 0); + goto donumset; + case O_MSGRCV: + value = (double)(do_msgrcv(arglast) >= 0); + goto donumset; + case O_SEMOP: + value = (double)(do_semop(arglast) >= 0); + goto donumset; + case O_SHMREAD: + case O_SHMWRITE: + value = (double)(do_shmio(optype, arglast) >= 0); + goto donumset; +#else /* not SYSVIPC */ + case O_MSGGET: + case O_MSGCTL: + case O_MSGSND: + case O_MSGRCV: + case O_SEMGET: + case O_SEMCTL: + case O_SEMOP: + case O_SHMGET: + case O_SHMCTL: + case O_SHMREAD: + case O_SHMWRITE: + fatal("System V IPC is not implemented on this machine"); +#endif /* not SYSVIPC */ + case O_RENAME: + tmps = str_get(st[1]); + tmps2 = str_get(st[2]); +#ifdef TAINT + TAINT_PROPER("rename"); +#endif +#ifdef HAS_RENAME + value = (double)(rename(tmps,tmps2) >= 0); +#else + if (same_dirent(tmps2, tmps)) /* can always rename to same name */ + anum = 1; + else { + if (euid || stat(tmps2,&statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) + (void)UNLINK(tmps2); + if (!(anum = link(tmps,tmps2))) + anum = UNLINK(tmps); + } + value = (double)(anum >= 0); +#endif + goto donumset; + case O_LINK: +#ifdef HAS_LINK + tmps = str_get(st[1]); + tmps2 = str_get(st[2]); +#ifdef TAINT + TAINT_PROPER("link"); +#endif + value = (double)(link(tmps,tmps2) >= 0); + goto donumset; +#else + fatal("Unsupported function link"); + break; +#endif + case O_MKDIR: + tmps = str_get(st[1]); + anum = (int)str_gnum(st[2]); +#ifdef TAINT + TAINT_PROPER("mkdir"); +#endif +#ifdef HAS_MKDIR + value = (double)(mkdir(tmps,anum) >= 0); + goto donumset; +#else + (void)strcpy(buf,"mkdir "); +#endif +#if !defined(HAS_MKDIR) || !defined(HAS_RMDIR) + one_liner: + for (tmps2 = buf+6; *tmps; ) { + *tmps2++ = '\\'; + *tmps2++ = *tmps++; + } + (void)strcpy(tmps2," 2>&1"); + rsfp = mypopen(buf,"r"); + if (rsfp) { + *buf = '\0'; + tmps2 = fgets(buf,sizeof buf,rsfp); + (void)mypclose(rsfp); + if (tmps2 != Nullch) { + for (errno = 1; errno < sys_nerr; errno++) { + if (instr(buf,sys_errlist[errno])) /* you don't see this */ + goto say_zero; + } + errno = 0; +#ifndef EACCES +#define EACCES EPERM +#endif + if (instr(buf,"cannot make")) + errno = EEXIST; + else if (instr(buf,"existing file")) + errno = EEXIST; + else if (instr(buf,"ile exists")) + errno = EEXIST; + else if (instr(buf,"non-exist")) + errno = ENOENT; + else if (instr(buf,"does not exist")) + errno = ENOENT; + else if (instr(buf,"not empty")) + errno = EBUSY; + else if (instr(buf,"cannot access")) + errno = EACCES; + else + errno = EPERM; + goto say_zero; + } + else { /* some mkdirs return no failure indication */ + tmps = str_get(st[1]); + anum = (stat(tmps,&statbuf) >= 0); + if (optype == O_RMDIR) + anum = !anum; + if (anum) + errno = 0; + else + errno = EACCES; /* a guess */ + value = (double)anum; + } + goto donumset; + } + else + goto say_zero; +#endif + case O_RMDIR: + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); +#ifdef TAINT + TAINT_PROPER("rmdir"); +#endif +#ifdef HAS_RMDIR + value = (double)(rmdir(tmps) >= 0); + goto donumset; +#else + (void)strcpy(buf,"rmdir "); + goto one_liner; /* see above in HAS_MKDIR */ +#endif + case O_GETPPID: +#ifdef HAS_GETPPID + value = (double)getppid(); + goto donumset; +#else + fatal("Unsupported function getppid"); + break; +#endif + case O_GETPGRP: +#ifdef HAS_GETPGRP + if (maxarg < 1) + anum = 0; + else + anum = (int)str_gnum(st[1]); +#ifdef _POSIX_SOURCE + if (anum != 0) + fatal("POSIX getpgrp can't take an argument"); + value = (double)getpgrp(); +#else + value = (double)getpgrp(anum); +#endif + goto donumset; +#else + fatal("The getpgrp() function is unimplemented on this machine"); + break; +#endif + case O_SETPGRP: +#ifdef HAS_SETPGRP + argtype = (int)str_gnum(st[1]); + anum = (int)str_gnum(st[2]); +#ifdef TAINT + TAINT_PROPER("setpgrp"); +#endif + value = (double)(setpgrp(argtype,anum) >= 0); + goto donumset; +#else + fatal("The setpgrp() function is unimplemented on this machine"); + break; +#endif + case O_GETPRIORITY: +#ifdef HAS_GETPRIORITY + argtype = (int)str_gnum(st[1]); + anum = (int)str_gnum(st[2]); + value = (double)getpriority(argtype,anum); + goto donumset; +#else + fatal("The getpriority() function is unimplemented on this machine"); + break; +#endif + case O_SETPRIORITY: +#ifdef HAS_SETPRIORITY + argtype = (int)str_gnum(st[1]); + anum = (int)str_gnum(st[2]); + optype = (int)str_gnum(st[3]); +#ifdef TAINT + TAINT_PROPER("setpriority"); +#endif + value = (double)(setpriority(argtype,anum,optype) >= 0); + goto donumset; +#else + fatal("The setpriority() function is unimplemented on this machine"); + break; +#endif + case O_CHROOT: +#ifdef HAS_CHROOT + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); +#ifdef TAINT + TAINT_PROPER("chroot"); +#endif + value = (double)(chroot(tmps) >= 0); + goto donumset; +#else + fatal("Unsupported function chroot"); + break; +#endif + case O_FCNTL: + case O_IOCTL: + if (maxarg <= 0) + stab = last_in_stab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + argtype = U_I(str_gnum(st[2])); +#ifdef TAINT + TAINT_PROPER("ioctl"); +#endif + anum = do_ctl(optype,stab,argtype,st[3]); + if (anum == -1) + goto say_undef; + if (anum != 0) { + value = (double)anum; + goto donumset; + } + str_set(str,"0 but true"); + STABSET(str); + break; + case O_FLOCK: +#ifdef HAS_FLOCK + if (maxarg <= 0) + stab = last_in_stab; + else if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (stab && stab_io(stab)) + fp = stab_io(stab)->ifp; + else + fp = Nullfp; + if (fp) { + argtype = (int)str_gnum(st[2]); + value = (double)(flock(fileno(fp),argtype) >= 0); + } + else + value = 0; + goto donumset; +#else + fatal("The flock() function is unimplemented on this machine"); + break; +#endif + case O_UNSHIFT: + ary = stab_array(arg[1].arg_ptr.arg_stab); + if (arglast[2] - arglast[1] != 1) + do_unshift(ary,arglast); + else { + STR *tmpstr = Str_new(52,0); /* must copy the STR */ + str_sset(tmpstr,st[2]); + aunshift(ary,1); + (void)astore(ary,0,tmpstr); + } + value = (double)(ary->ary_fill + 1); + goto donumset; + + case O_TRY: + sp = do_try(arg[1].arg_ptr.arg_cmd, + gimme,arglast); + goto array_return; + + case O_EVALONCE: + sp = do_eval(st[1], O_EVAL, curcmd->c_stash, TRUE, + gimme,arglast); + if (eval_root) { + str_free(arg[1].arg_ptr.arg_str); + arg[1].arg_ptr.arg_cmd = eval_root; + arg[1].arg_type = (A_CMD|A_DONT); + arg[0].arg_type = O_TRY; + } + goto array_return; + + case O_REQUIRE: + case O_DOFILE: + case O_EVAL: + if (maxarg < 1) + tmpstr = stab_val(defstab); + else + tmpstr = + (arg[1].arg_type & A_MASK) != A_NULL ? st[1] : stab_val(defstab); +#ifdef TAINT + tainted |= tmpstr->str_tainted; + TAINT_PROPER("eval"); +#endif + sp = do_eval(tmpstr, optype, curcmd->c_stash, FALSE, + gimme,arglast); + goto array_return; + + case O_FTRREAD: + argtype = 0; + anum = S_IRUSR; + goto check_perm; + case O_FTRWRITE: + argtype = 0; + anum = S_IWUSR; + goto check_perm; + case O_FTREXEC: + argtype = 0; + anum = S_IXUSR; + goto check_perm; + case O_FTEREAD: + argtype = 1; + anum = S_IRUSR; + goto check_perm; + case O_FTEWRITE: + argtype = 1; + anum = S_IWUSR; + goto check_perm; + case O_FTEEXEC: + argtype = 1; + anum = S_IXUSR; + check_perm: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (cando(anum,argtype,&statcache)) + goto say_yes; + goto say_no; + + case O_FTIS: + if (mystat(arg,st[1]) < 0) + goto say_undef; + goto say_yes; + case O_FTEOWNED: + case O_FTROWNED: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (statcache.st_uid == (optype == O_FTEOWNED ? euid : uid) ) + goto say_yes; + goto say_no; + case O_FTZERO: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (!statcache.st_size) + goto say_yes; + goto say_no; + case O_FTSIZE: + if (mystat(arg,st[1]) < 0) + goto say_undef; + value = (double)statcache.st_size; + goto donumset; + + case O_FTMTIME: + if (mystat(arg,st[1]) < 0) + goto say_undef; + value = (double)(basetime - statcache.st_mtime) / 86400.0; + goto donumset; + case O_FTATIME: + if (mystat(arg,st[1]) < 0) + goto say_undef; + value = (double)(basetime - statcache.st_atime) / 86400.0; + goto donumset; + case O_FTCTIME: + if (mystat(arg,st[1]) < 0) + goto say_undef; + value = (double)(basetime - statcache.st_ctime) / 86400.0; + goto donumset; + + case O_FTSOCK: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISSOCK(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTCHR: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISCHR(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTBLK: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISBLK(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTFILE: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISREG(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTDIR: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISDIR(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTPIPE: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (S_ISFIFO(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_FTLINK: + if (mylstat(arg,st[1]) < 0) + goto say_undef; + if (S_ISLNK(statcache.st_mode)) + goto say_yes; + goto say_no; + case O_SYMLINK: +#ifdef HAS_SYMLINK + tmps = str_get(st[1]); + tmps2 = str_get(st[2]); +#ifdef TAINT + TAINT_PROPER("symlink"); +#endif + value = (double)(symlink(tmps,tmps2) >= 0); + goto donumset; +#else + fatal("Unsupported function symlink"); +#endif + case O_READLINK: +#ifdef HAS_SYMLINK + if (maxarg < 1) + tmps = str_get(stab_val(defstab)); + else + tmps = str_get(st[1]); + anum = readlink(tmps,buf,sizeof buf); + if (anum < 0) + goto say_undef; + str_nset(str,buf,anum); + break; +#else + goto say_undef; /* just pretend it's a normal file */ +#endif + case O_FTSUID: +#ifdef S_ISUID + anum = S_ISUID; + goto check_xid; +#else + goto say_no; +#endif + case O_FTSGID: +#ifdef S_ISGID + anum = S_ISGID; + goto check_xid; +#else + goto say_no; +#endif + case O_FTSVTX: +#ifdef S_ISVTX + anum = S_ISVTX; +#else + goto say_no; +#endif + check_xid: + if (mystat(arg,st[1]) < 0) + goto say_undef; + if (statcache.st_mode & anum) + goto say_yes; + goto say_no; + case O_FTTTY: + if (arg[1].arg_type & A_DONT) { + stab = arg[1].arg_ptr.arg_stab; + tmps = ""; + } + else + stab = stabent(tmps = str_get(st[1]),FALSE); + if (stab && stab_io(stab) && stab_io(stab)->ifp) + anum = fileno(stab_io(stab)->ifp); + else if (isDIGIT(*tmps)) + anum = atoi(tmps); + else + goto say_undef; + if (isatty(anum)) + goto say_yes; + goto say_no; + case O_FTTEXT: + case O_FTBINARY: + str = do_fttext(arg,st[1]); + break; +#ifdef HAS_SOCKET + case O_SOCKET: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_socket(stab,arglast); +#else + (void)do_socket(stab,arglast); +#endif + goto donumset; + case O_BIND: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_bind(stab,arglast); +#else + (void)do_bind(stab,arglast); +#endif + goto donumset; + case O_CONNECT: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_connect(stab,arglast); +#else + (void)do_connect(stab,arglast); +#endif + goto donumset; + case O_LISTEN: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_listen(stab,arglast); +#else + (void)do_listen(stab,arglast); +#endif + goto donumset; + case O_ACCEPT: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if ((arg[2].arg_type & A_MASK) == A_WORD) + stab2 = arg[2].arg_ptr.arg_stab; + else + stab2 = stabent(str_get(st[2]),TRUE); + do_accept(str,stab,stab2); + STABSET(str); + break; + case O_GHBYNAME: + if (maxarg < 1) + goto say_undef; + case O_GHBYADDR: + case O_GHOSTENT: + sp = do_ghent(optype, + gimme,arglast); + goto array_return; + case O_GNBYNAME: + if (maxarg < 1) + goto say_undef; + case O_GNBYADDR: + case O_GNETENT: + sp = do_gnent(optype, + gimme,arglast); + goto array_return; + case O_GPBYNAME: + if (maxarg < 1) + goto say_undef; + case O_GPBYNUMBER: + case O_GPROTOENT: + sp = do_gpent(optype, + gimme,arglast); + goto array_return; + case O_GSBYNAME: + if (maxarg < 1) + goto say_undef; + case O_GSBYPORT: + case O_GSERVENT: + sp = do_gsent(optype, + gimme,arglast); + goto array_return; + case O_SHOSTENT: + value = (double) sethostent((int)str_gnum(st[1])); + goto donumset; + case O_SNETENT: + value = (double) setnetent((int)str_gnum(st[1])); + goto donumset; + case O_SPROTOENT: + value = (double) setprotoent((int)str_gnum(st[1])); + goto donumset; + case O_SSERVENT: + value = (double) setservent((int)str_gnum(st[1])); + goto donumset; + case O_EHOSTENT: + value = (double) endhostent(); + goto donumset; + case O_ENETENT: + value = (double) endnetent(); + goto donumset; + case O_EPROTOENT: + value = (double) endprotoent(); + goto donumset; + case O_ESERVENT: + value = (double) endservent(); + goto donumset; + case O_SOCKPAIR: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if ((arg[2].arg_type & A_MASK) == A_WORD) + stab2 = arg[2].arg_ptr.arg_stab; + else + stab2 = stabent(str_get(st[2]),TRUE); +#ifndef lint + value = (double)do_spair(stab,stab2,arglast); +#else + (void)do_spair(stab,stab2,arglast); +#endif + goto donumset; + case O_SHUTDOWN: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); +#ifndef lint + value = (double)do_shutdown(stab,arglast); +#else + (void)do_shutdown(stab,arglast); +#endif + goto donumset; + case O_GSOCKOPT: + case O_SSOCKOPT: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + sp = do_sopt(optype,stab,arglast); + goto array_return; + case O_GETSOCKNAME: + case O_GETPEERNAME: + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab) + goto say_undef; + sp = do_getsockname(optype,stab,arglast); + goto array_return; + +#else /* HAS_SOCKET not defined */ + case O_SOCKET: + case O_BIND: + case O_CONNECT: + case O_LISTEN: + case O_ACCEPT: + case O_SOCKPAIR: + case O_GHBYNAME: + case O_GHBYADDR: + case O_GHOSTENT: + case O_GNBYNAME: + case O_GNBYADDR: + case O_GNETENT: + case O_GPBYNAME: + case O_GPBYNUMBER: + case O_GPROTOENT: + case O_GSBYNAME: + case O_GSBYPORT: + case O_GSERVENT: + case O_SHOSTENT: + case O_SNETENT: + case O_SPROTOENT: + case O_SSERVENT: + case O_EHOSTENT: + case O_ENETENT: + case O_EPROTOENT: + case O_ESERVENT: + case O_SHUTDOWN: + case O_GSOCKOPT: + case O_SSOCKOPT: + case O_GETSOCKNAME: + case O_GETPEERNAME: + badsock: + fatal("Unsupported socket function"); +#endif /* HAS_SOCKET */ + case O_SSELECT: +#ifdef HAS_SELECT + sp = do_select(gimme,arglast); + goto array_return; +#else + fatal("select not implemented"); +#endif + case O_FILENO: + if (maxarg < 1) + goto say_undef; + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp)) + goto say_undef; + value = fileno(fp); + goto donumset; + case O_BINMODE: + if (maxarg < 1) + goto say_undef; + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp)) + goto say_undef; +#ifdef DOSISH +#ifdef atarist + if(fflush(fp)) + str_set(str, No); + else + { + fp->_flag |= _IOBIN; + str_set(str, Yes); + } +#else + str_set(str, (setmode(fileno(fp), O_BINARY) != -1) ? Yes : No); +#endif +#else + str_set(str, Yes); +#endif + STABSET(str); + break; + case O_VEC: + sp = do_vec(str == st[1], arg->arg_ptr.arg_str, arglast); + goto array_return; + case O_GPWNAM: + case O_GPWUID: + case O_GPWENT: +#ifdef HAS_PASSWD + sp = do_gpwent(optype, + gimme,arglast); + goto array_return; + case O_SPWENT: + value = (double) setpwent(); + goto donumset; + case O_EPWENT: + value = (double) endpwent(); + goto donumset; +#else + case O_EPWENT: + case O_SPWENT: + fatal("Unsupported password function"); + break; +#endif + case O_GGRNAM: + case O_GGRGID: + case O_GGRENT: +#ifdef HAS_GROUP + sp = do_ggrent(optype, + gimme,arglast); + goto array_return; + case O_SGRENT: + value = (double) setgrent(); + goto donumset; + case O_EGRENT: + value = (double) endgrent(); + goto donumset; +#else + case O_EGRENT: + case O_SGRENT: + fatal("Unsupported group function"); + break; +#endif + case O_GETLOGIN: +#ifdef HAS_GETLOGIN + if (!(tmps = getlogin())) + goto say_undef; + str_set(str,tmps); +#else + fatal("Unsupported function getlogin"); +#endif + break; + case O_OPEN_DIR: + case O_READDIR: + case O_TELLDIR: + case O_SEEKDIR: + case O_REWINDDIR: + case O_CLOSEDIR: + if (maxarg < 1) + goto say_undef; + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if (!stab) + goto say_undef; + sp = do_dirop(optype,stab,gimme,arglast); + goto array_return; + case O_SYSCALL: + value = (double)do_syscall(arglast); + goto donumset; + case O_PIPE_OP: +#ifdef HAS_PIPE + if ((arg[1].arg_type & A_MASK) == A_WORD) + stab = arg[1].arg_ptr.arg_stab; + else + stab = stabent(str_get(st[1]),TRUE); + if ((arg[2].arg_type & A_MASK) == A_WORD) + stab2 = arg[2].arg_ptr.arg_stab; + else + stab2 = stabent(str_get(st[2]),TRUE); + do_pipe(str,stab,stab2); + STABSET(str); +#else + fatal("Unsupported function pipe"); +#endif + break; + } + + normal_return: + st[1] = str; +#ifdef DEBUGGING + if (debug) { + dlevel--; + if (debug & 8) + deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str)); + } +#endif + stack_ary = stack->ary_array; + stack_max = stack_ary + stack->ary_max; + stack_sp = stack_ary + arglast[0] + 1; + return arglast[0] + 1; +} |