home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-09 | 40.1 KB | 1,687 lines |
- /* $Header: eval.c,v 3.0.1.11 91/01/11 17:58:30 lwall Locked $
- *
- * Copyright (c) 1989, Larry Wall
- *
- * You may distribute under the terms of the GNU General Public License
- * as specified in the README file that comes with the perl 3.0 kit.
- *
- * $Log: eval.c,v $
- * Revision 3.0.1.11 91/01/11 17:58:30 lwall
- * patch42: ANSIfied the stat mode checking
- * patch42: perl -D14 crashed on ..
- * patch42: waitpid() emulation was useless because of #ifdef WAITPID
- *
- * Revision 3.0.1.10 90/11/10 01:33:22 lwall
- * patch38: random cleanup
- * patch38: couldn't return from sort routine
- * patch38: added hooks for unexec()
- * patch38: added alarm function
- *
- * Revision 3.0.1.9 90/10/15 16:46:13 lwall
- * patch29: added caller
- * patch29: added scalar
- * patch29: added cmp and <=>
- * patch29: added sysread and syswrite
- * patch29: added -M, -A and -C
- * patch29: index and substr now have optional 3rd args
- * patch29: you can now read into the middle string
- * patch29: ~ now works on vector string
- * patch29: non-existent array values no longer cause core dumps
- * patch29: eof; core dumped
- * patch29: oct and hex now produce unsigned result
- * patch29: unshift did not return the documented value
- *
- * Revision 3.0.1.8 90/08/13 22:17:14 lwall
- * patch28: the NSIG hack didn't work right on Xenix
- * patch28: defined(@array) and defined(%array) didn't work right
- * patch28: rename was busted on systems without rename system call
- *
- * Revision 3.0.1.7 90/08/09 03:33:44 lwall
- * patch19: made ~ do vector operation on strings like &, | and ^
- * patch19: dbmopen(%name...) didn't work right
- * patch19: dbmopen(name, 'filename', undef) now refrains from creating
- * patch19: empty %array now returns 0 in scalar context
- * patch19: die with no arguments no longer exits unconditionally
- * patch19: return outside a subroutine now returns a reasonable message
- * patch19: rename done with unlink()/link()/unlink() now checks for clobbering
- * patch19: -s now returns size of file
- *
- * Revision 3.0.1.6 90/03/27 15:53:51 lwall
- * patch16: MSDOS support
- * patch16: support for machines that can't cast negative floats to unsigned ints
- * patch16: ioctl didn't return values correctly
- *
- * Revision 3.0.1.5 90/03/12 16:37:40 lwall
- * patch13: undef $/ didn't work as advertised
- * patch13: added list slice operator (LIST)[LIST]
- * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
- *
- * Revision 3.0.1.4 90/02/28 17:36:59 lwall
- * patch9: added pipe function
- * patch9: a return in scalar context wouldn't return array
- * patch9: !~ now always returns scalar even in array context
- * patch9: some machines can't cast float to long with high bit set
- * patch9: piped opens returned undef in child
- * patch9: @array in scalar context now returns length of array
- * patch9: chdir; coredumped
- * patch9: wait no longer ignores signals
- * patch9: mkdir now handles odd versions of /bin/mkdir
- * patch9: -l FILEHANDLE now disallowed
- *
- * Revision 3.0.1.3 89/12/21 20:03:05 lwall
- * patch7: errno may now be a macro with an lvalue
- * patch7: ANSI strerror() is now supported
- * patch7: send() didn't allow a TO argument
- * patch7: ord() now always returns positive even on signed char machines
- *
- * Revision 3.0.1.2 89/11/17 15:19:34 lwall
- * patch5: constant numeric subscripts get lost inside ?:
- *
- * Revision 3.0.1.1 89/11/11 04:31:51 lwall
- * patch2: mkdir and rmdir needed to quote argument when passed to shell
- * patch2: mkdir and rmdir now return better error codes
- * patch2: fileno, seekdir, rewinddir and closedir now disallow defaults
- *
- * Revision 3.0 89/10/18 15:17:04 lwall
- * 3.0 baseline
- *
- */
-
- #include "EXTERN.h"
- #include "perl.h"
-
- #include <math.h>
- #include <signal.h>
-
- #ifdef I_FCNTL
- #include <fcntl.h>
- #endif
- #ifdef I_VFORK
- # include <vfork.h>
- #endif
-
- ARG *debarg;
- STR str_args;
- static struct lstring *lstr;
- static int old_record_separator;
-
- char *getlogin PROTO((void));
-
- 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;
- char *tmps3;
- int argflags;
- int argtype;
- union argptr argptr;
- int arglast[8]; /* highest sp for arg--valid only for non-O_LIST args */
- unsigned long tmplong;
- long tmplong2;
- TIME_T when;
- FILE *fp;
- STR *tmpstr;
- FCMD *form;
- STAB *stab;
- ARRAY *ary;
- bool assigning = FALSE;
-
- 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
-
- #include "xc.evalargs"
-
- st += arglast[0];
- 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:
- STR_SSET(str,st[1]);
- anum = (int)str_gnum(st[2]);
- if (anum >= 1) {
- tmpstr = Str_new(50, 0);
- str_sset(tmpstr,str);
- 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';
- }
- else
- 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:
- 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)) {
- 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");
- value = str_gnum(st[1]) / value;
- goto donumset;
- case O_MODULO:
- tmplong = (long) str_gnum(st[2]);
- if (tmplong == 0L)
- fatal("Illegal modulus zero");
- tmplong2 = (long)str_gnum(st[1]);
- #ifndef lint
- if (tmplong2 >= 0)
- value = (double)(tmplong2 % tmplong);
- else
- value = (double)(tmplong - ((-tmplong2 - 1) % tmplong)) - 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:
- value = (double) !str_true(st[1]);
- 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_fullname(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) == Nullstab)
- 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;
- debarg = arg;
- 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_io(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
- stab = arg[1].arg_ptr.arg_stab;
- 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
- stab = arg[1].arg_ptr.arg_stab;
- 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 = 1.0;
- stab_io(stab)->lines = 0;
- goto donumset;
- }
- 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)
- 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 (perldb && 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_2static(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 */
- if ((argtype = (str == st[1])) != 0)
- 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! */
- lstr = (struct 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:
- (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:
- 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_sort(str,stab,
- 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(st[1]);
- }
- 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(st[1]);
- }
- 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) == Nullfp) {
- 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) {
- tmps = "&"; /* User root directory */
- }
- #ifdef TAINT
- taintproper("Insecure dependency in chdir");
- #endif
- value = (double)(chdir(tmps) >= 0);
- goto donumset;
- case O_EXIT:
- if (maxarg < 1)
- anum = 0;
- else
- anum = (int)str_gnum(st[1]);
- 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_READ:
- 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;
- STR_GROW(st[2], anum+maxarg+1), (tmps = str_get(st[2])); /* sneaky */
- anum = fread(tmps+maxarg, 1, anum, stab_io(stab)->ifp);
- if (anum < 0)
- goto say_undef;
- st[2]->str_cur = anum;
- st[2]->str_ptr[anum] = '\0';
- 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_static(st[arglast[2] - arglast[0]]);
- goto dopop;
- case O_REDO:
- case O_NEXT:
- case O_LAST:
- 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_static(st[0]);
- }
- longjmp(loop_stack[loop_ptr].loop_env, O_LAST);
- }
- longjmp(loop_stack[loop_ptr].loop_env, optype);
- case O_GOTO:/* shudder */
- goto_targ = str_get(arg[1].arg_ptr.arg_str);
- if (!*goto_targ)
- goto_targ = Nullch; /* just restart from top */
- 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])) == Nullch)
- #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)) == Nullch)
- #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(TIME_T*));
- #endif
- goto donumset;
- case O_LOCALTIME:
- if (maxarg < 1)
- (void)time(&when);
- else
- when = (TIME_T)str_gnum(st[1]);
- {
- /* Under RISC OS, the localtime() function does not take
- * summer time into account. We therefore assume the system
- * time is localtime(), but if the OS variable Time$DST is
- * set, we flag it as daylight saving time.
- */
- struct tm *localtm;
- char *dst = getenv("Time$DST");
-
- localtm = localtime(&when);
- localtm->tm_isdst = (dst && *dst) ? 1 : 0;
-
- sp = do_time(str,localtm,gimme,arglast);
- }
- goto array_return;
- case O_GMTIME:
- if (maxarg < 1)
- (void)time(&when);
- else
- when = (TIME_T)str_gnum(st[1]);
- {
- /* Under RISC OS, there is no gmtime() function!! We
- * therefore use localtime(), but if the OS variable
- * Time$DST is set, we subtract 1 hour.
- */
- struct tm *gmtm;
- time_t when_adj = when;
- char *dst = getenv("Time$DST");
-
- if (dst && *dst)
- {
- when_adj -= 3600;
- }
-
- gmtm = localtime(&when_adj);
- gmtm->tm_isdst = 0;
-
- sp = do_time(str,gmtm,gimme,arglast);
- }
- goto array_return;
- case O_TRUNCATE:
- sp = do_truncate(str,arg,
- gimme,arglast);
- goto array_return;
- case O_STAT:
- sp = do_stat(str,arg,
- gimme,arglast);
- goto array_return;
- case O_CRYPT:
- #ifdef 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]);
- value = log(value);
- goto donumset;
- case O_SQRT:
- if (maxarg < 1)
- value = str_gnum(stab_val(defstab));
- else
- value = str_gnum(st[1]);
- 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_KILL:
- if (maxarg < 1)
- anum = SIGTERM;
- else {
- tmps = str_get(st[1]);
-
- if (isupper(*tmps)) {
- if (*tmps == 'S' && tmps[1] == 'I' && tmps[2] == 'G')
- tmps += 3;
- if ((anum = whichsig(tmps)) == 0)
- fatal("Unrecognized signal name \"%s\"",tmps);
- }
- else
- anum = (int)str_gnum(st[1]);
- }
- anum = raise(anum);
-
- if (anum == 0)
- goto say_yes;
- else
- goto say_no;
- 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);
- str_free(arg[2].arg_ptr.arg_str);
- 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]) ) {
- str_numset(str,0.0);
- anum = 2;
- arg->arg_type = optype = O_FLOP;
- arg[2].arg_type &= ~A_DONT;
- arg[1].arg_type |= A_DONT;
- 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;
- }
- 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_SYSTEM:
- 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_static(st[2])));
- }
- goto donumset;
- 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 {
- value = (double)do_exec(str_get(str_static(st[2])));
- }
- goto donumset;
- case O_HEX:
- argtype = 4;
- goto snarfnum;
-
- case O_OCT:
- argtype = 3;
-
- snarfnum:
- tmplong = 0;
- if (maxarg < 1)
- tmps = str_get(stab_val(defstab));
- else
- tmps = str_get(st[1]);
- for (;;) {
- switch (*tmps) {
- default:
- goto out;
- case '8': case '9':
- if (argtype != 4)
- goto out;
- /* FALL THROUGH */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- tmplong <<= argtype;
- tmplong += *tmps++ & 15L;
- break;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- if (argtype != 4)
- goto out;
- tmplong <<= 4;
- tmplong += (*tmps++ & 7L) + 9L;
- break;
- case 'x':
- argtype = 4;
- tmps++;
- break;
- }
- }
- out:
- value = (double)tmplong;
- goto donumset;
- case O_UNLINK:
- value = (double)do_unlink(arglast);
- goto donumset;
- case O_RENAME:
- tmps = str_get(st[1]);
- tmps2 = str_get(st[2]);
- #ifdef TAINT
- taintproper("Insecure dependency in rename");
- #endif
- value = (double)(rename(tmps,tmps2) >= 0);
- goto donumset;
- case O_MKDIR:
- if (maxarg < 1)
- tmps = str_get(stab_val(defstab));
- else
- tmps = str_get(st[1]);
- #ifdef TAINT
- taintproper("Insecure dependency in mkdir");
- #endif
- value = (double)(mkdir(tmps) >= 0);
- goto donumset;
- case O_RMDIR:
- if (maxarg < 1)
- tmps = str_get(stab_val(defstab));
- else
- tmps = str_get(st[1]);
- #ifdef TAINT
- taintproper("Insecure dependency in rmdir");
- #endif
- value = (double)(rmdir(tmps) >= 0);
- goto donumset;
- 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_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;
- taintproper("Insecure dependency in eval");
- #endif
- sp = do_eval(tmpstr, optype, curcmd->c_stash,
- gimme,arglast);
- goto array_return;
-
- case O_FTREAD:
- anum = S_READ;
- goto check_attr;
- case O_FTWRITE:
- anum = S_WRITE;
- goto check_attr;
- case O_FTLOCK:
- anum = S_LOCK;
- goto check_attr;
- case O_FTPREAD:
- anum = S_PREAD;
- goto check_attr;
- case O_FTPWRITE:
- anum = S_PWRITE;
- check_attr:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- if (anum & statcache.st_attr)
- goto say_yes;
- goto say_no;
- case O_FTIS:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- goto say_yes;
- case O_FTZERO:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- if (!statcache.st_length)
- goto say_yes;
- goto say_no;
- case O_FTSIZE:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- value = (double)statcache.st_length;
- goto donumset;
- case O_FTTIME:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- value = (basetime - statcache.st_time) / 8640000.0;
- goto donumset;
- case O_FTFILE:
- anum = T_FILE;
- goto check_file_type;
- case O_FTDIR:
- anum = T_DIRECTORY;
- check_file_type:
- if (mystat(arg,st[1]) < 0)
- goto say_undef;
- if (statcache.st_type == 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)
- fp = stab_io(stab)->ifp;
- else if (isdigit(*tmps)) {
- anum = atoi(tmps);
- switch (anum)
- {
- case 0: fp = stdin; break;
- case 1: fp = stdout; break;
- case 2: fp = stderr; break;
- default: goto say_undef;
- }
- }
- else
- goto say_undef;
- if (isatty(fp))
- goto say_yes;
- goto say_no;
- case O_FTTEXT:
- case O_FTBINARY:
- str = do_fttext(arg,st[1]);
- break;
- case O_VEC:
- sp = do_vec(str == st[1], arg->arg_ptr.arg_str, arglast);
- goto array_return;
- case O_OPENDIR:
- 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:
- str = do_syscall(arglast);
- if (!str)
- goto say_undef;
- 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
- return arglast[0] + 1;
-
- 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],str_get(st[1]));
- break;
- default:
- tmps = str_get(st[1]);
- deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype],
- anum,tmps,anum==2?"":"...,",str_get(st[anum]));
- break;
- }
- }
- }
- #endif
- 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
- return arglast[0] + 1;
- }
-