summaryrefslogtreecommitdiff
path: root/arg.c
diff options
context:
space:
mode:
Diffstat (limited to 'arg.c')
-rw-r--r--arg.c2111
1 files changed, 2111 insertions, 0 deletions
diff --git a/arg.c b/arg.c
new file mode 100644
index 0000000000..9561bb6665
--- /dev/null
+++ b/arg.c
@@ -0,0 +1,2111 @@
+/* $Header: arg.c,v 1.0 87/12/18 13:04:33 root Exp $
+ *
+ * $Log: arg.c,v $
+ * Revision 1.0 87/12/18 13:04:33 root
+ * Initial revision
+ *
+ */
+
+#include <signal.h>
+#include "handy.h"
+#include "EXTERN.h"
+#include "search.h"
+#include "util.h"
+#include "perl.h"
+
+ARG *debarg;
+
+bool
+do_match(s,arg)
+register char *s;
+register ARG *arg;
+{
+ register SPAT *spat = arg[2].arg_ptr.arg_spat;
+ register char *d;
+ register char *t;
+
+ if (!spat || !s)
+ fatal("panic: do_match\n");
+ if (spat->spat_flags & SPAT_USED) {
+#ifdef DEBUGGING
+ if (debug & 8)
+ deb("2.SPAT USED\n");
+#endif
+ return FALSE;
+ }
+ if (spat->spat_runtime) {
+ t = str_get(eval(spat->spat_runtime,Null(STR***)));
+#ifdef DEBUGGING
+ if (debug & 8)
+ deb("2.SPAT /%s/\n",t);
+#endif
+ if (d = compile(&spat->spat_compex,t,TRUE,FALSE)) {
+#ifdef DEBUGGING
+ deb("/%s/: %s\n", t, d);
+#endif
+ return FALSE;
+ }
+ if (spat->spat_compex.complen <= 1 && curspat)
+ spat = curspat;
+ if (execute(&spat->spat_compex, s, TRUE, 0)) {
+ if (spat->spat_compex.numsubs)
+ curspat = spat;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else {
+#ifdef DEBUGGING
+ if (debug & 8) {
+ char ch;
+
+ if (spat->spat_flags & SPAT_USE_ONCE)
+ ch = '?';
+ else
+ ch = '/';
+ deb("2.SPAT %c%s%c\n",ch,spat->spat_compex.precomp,ch);
+ }
+#endif
+ if (spat->spat_compex.complen <= 1 && curspat)
+ spat = curspat;
+ if (spat->spat_first) {
+ if (spat->spat_flags & SPAT_SCANFIRST) {
+ str_free(spat->spat_first);
+ spat->spat_first = Nullstr; /* disable optimization */
+ }
+ else if (*spat->spat_first->str_ptr != *s ||
+ strnNE(spat->spat_first->str_ptr, s, spat->spat_flen) )
+ return FALSE;
+ }
+ if (execute(&spat->spat_compex, s, TRUE, 0)) {
+ if (spat->spat_compex.numsubs)
+ curspat = spat;
+ if (spat->spat_flags & SPAT_USE_ONCE)
+ spat->spat_flags |= SPAT_USED;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ /*NOTREACHED*/
+}
+
+int
+do_subst(str,arg)
+STR *str;
+register ARG *arg;
+{
+ register SPAT *spat;
+ register STR *dstr;
+ register char *s;
+ register char *m;
+
+ spat = arg[2].arg_ptr.arg_spat;
+ s = str_get(str);
+ if (!spat || !s)
+ fatal("panic: do_subst\n");
+ else if (spat->spat_runtime) {
+ char *d;
+
+ m = str_get(eval(spat->spat_runtime,Null(STR***)));
+ if (d = compile(&spat->spat_compex,m,TRUE,FALSE)) {
+#ifdef DEBUGGING
+ deb("/%s/: %s\n", m, d);
+#endif
+ return 0;
+ }
+ }
+#ifdef DEBUGGING
+ if (debug & 8) {
+ deb("2.SPAT /%s/\n",spat->spat_compex.precomp);
+ }
+#endif
+ if (spat->spat_compex.complen <= 1 && curspat)
+ spat = curspat;
+ if (spat->spat_first) {
+ if (spat->spat_flags & SPAT_SCANFIRST) {
+ str_free(spat->spat_first);
+ spat->spat_first = Nullstr; /* disable optimization */
+ }
+ else if (*spat->spat_first->str_ptr != *s ||
+ strnNE(spat->spat_first->str_ptr, s, spat->spat_flen) )
+ return 0;
+ }
+ if (m = execute(&spat->spat_compex, s, TRUE, 1)) {
+ int iters = 0;
+
+ dstr = str_new(str_len(str));
+ if (spat->spat_compex.numsubs)
+ curspat = spat;
+ do {
+ if (iters++ > 10000)
+ fatal("Substitution loop?\n");
+ if (spat->spat_compex.numsubs)
+ s = spat->spat_compex.subbase;
+ str_ncat(dstr,s,m-s);
+ s = spat->spat_compex.subend[0];
+ str_scat(dstr,eval(spat->spat_repl,Null(STR***)));
+ if (spat->spat_flags & SPAT_USE_ONCE)
+ break;
+ } while (m = execute(&spat->spat_compex, s, FALSE, 1));
+ str_cat(dstr,s);
+ str_replace(str,dstr);
+ STABSET(str);
+ return iters;
+ }
+ return 0;
+}
+
+int
+do_trans(str,arg)
+STR *str;
+register ARG *arg;
+{
+ register char *tbl;
+ register char *s;
+ register int matches = 0;
+ register int ch;
+
+ tbl = arg[2].arg_ptr.arg_cval;
+ s = str_get(str);
+ if (!tbl || !s)
+ fatal("panic: do_trans\n");
+#ifdef DEBUGGING
+ if (debug & 8) {
+ deb("2.TBL\n");
+ }
+#endif
+ while (*s) {
+ if (ch = tbl[*s & 0377]) {
+ matches++;
+ *s = ch;
+ }
+ s++;
+ }
+ STABSET(str);
+ return matches;
+}
+
+int
+do_split(s,spat,retary)
+register char *s;
+register SPAT *spat;
+STR ***retary;
+{
+ register STR *dstr;
+ register char *m;
+ register ARRAY *ary;
+ static ARRAY *myarray = Null(ARRAY*);
+ int iters = 0;
+ STR **sarg;
+ register char *e;
+ int i;
+
+ if (!spat || !s)
+ fatal("panic: do_split\n");
+ else if (spat->spat_runtime) {
+ char *d;
+
+ m = str_get(eval(spat->spat_runtime,Null(STR***)));
+ if (d = compile(&spat->spat_compex,m,TRUE,FALSE)) {
+#ifdef DEBUGGING
+ deb("/%s/: %s\n", m, d);
+#endif
+ return FALSE;
+ }
+ }
+#ifdef DEBUGGING
+ if (debug & 8) {
+ deb("2.SPAT /%s/\n",spat->spat_compex.precomp);
+ }
+#endif
+ if (retary)
+ ary = myarray;
+ else
+ ary = spat->spat_repl[1].arg_ptr.arg_stab->stab_array;
+ if (!ary)
+ myarray = ary = anew();
+ ary->ary_fill = -1;
+ while (*s && (m = execute(&spat->spat_compex, s, (iters == 0), 1))) {
+ if (spat->spat_compex.numsubs)
+ s = spat->spat_compex.subbase;
+ dstr = str_new(m-s);
+ str_nset(dstr,s,m-s);
+ astore(ary, iters++, dstr);
+ if (iters > 10000)
+ fatal("Substitution loop?\n");
+ s = spat->spat_compex.subend[0];
+ }
+ if (*s) { /* ignore field after final "whitespace" */
+ dstr = str_new(0); /* if they interpolate, it's null anyway */
+ str_set(dstr,s);
+ astore(ary, iters++, dstr);
+ }
+ else {
+ while (iters > 0 && !*str_get(afetch(ary,iters-1)))
+ iters--;
+ }
+ if (retary) {
+ sarg = (STR**)safemalloc((iters+2)*sizeof(STR*));
+
+ sarg[0] = Nullstr;
+ sarg[iters+1] = Nullstr;
+ for (i = 1; i <= iters; i++)
+ sarg[i] = afetch(ary,i-1);
+ *retary = sarg;
+ }
+ return iters;
+}
+
+void
+do_join(arg,delim,str)
+register ARG *arg;
+register char *delim;
+register STR *str;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+
+ (void)eval(arg[2].arg_ptr.arg_arg,&tmpary);
+ elem = tmpary+1;
+ if (*elem)
+ str_sset(str,*elem++);
+ for (; *elem; elem++) {
+ str_cat(str,delim);
+ str_scat(str,*elem);
+ }
+ STABSET(str);
+ safefree((char*)tmpary);
+}
+
+bool
+do_open(stab,name)
+STAB *stab;
+register char *name;
+{
+ FILE *fp;
+ int len = strlen(name);
+ register STIO *stio = stab->stab_io;
+
+ while (len && isspace(name[len-1]))
+ name[--len] = '\0';
+ if (!stio)
+ stio = stab->stab_io = stio_new();
+ if (stio->fp) {
+ if (stio->type == '|')
+ pclose(stio->fp);
+ else if (stio->type != '-')
+ fclose(stio->fp);
+ stio->fp = Nullfp;
+ }
+ stio->type = *name;
+ if (*name == '|') {
+ for (name++; isspace(*name); name++) ;
+ fp = popen(name,"w");
+ }
+ else if (*name == '>' && name[1] == '>') {
+ for (name += 2; isspace(*name); name++) ;
+ fp = fopen(name,"a");
+ }
+ else if (*name == '>') {
+ for (name++; isspace(*name); name++) ;
+ if (strEQ(name,"-")) {
+ fp = stdout;
+ stio->type = '-';
+ }
+ else
+ fp = fopen(name,"w");
+ }
+ else {
+ if (*name == '<') {
+ for (name++; isspace(*name); name++) ;
+ if (strEQ(name,"-")) {
+ fp = stdin;
+ stio->type = '-';
+ }
+ else
+ fp = fopen(name,"r");
+ }
+ else if (name[len-1] == '|') {
+ name[--len] = '\0';
+ while (len && isspace(name[len-1]))
+ name[--len] = '\0';
+ for (; isspace(*name); name++) ;
+ fp = popen(name,"r");
+ stio->type = '|';
+ }
+ else {
+ stio->type = '<';
+ for (; isspace(*name); name++) ;
+ if (strEQ(name,"-")) {
+ fp = stdin;
+ stio->type = '-';
+ }
+ else
+ fp = fopen(name,"r");
+ }
+ }
+ if (!fp)
+ return FALSE;
+ if (stio->type != '|' && stio->type != '-') {
+ if (fstat(fileno(fp),&statbuf) < 0) {
+ fclose(fp);
+ return FALSE;
+ }
+ if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
+ (statbuf.st_mode & S_IFMT) != S_IFCHR) {
+ fclose(fp);
+ return FALSE;
+ }
+ }
+ stio->fp = fp;
+ return TRUE;
+}
+
+FILE *
+nextargv(stab)
+register STAB *stab;
+{
+ register STR *str;
+ char *oldname;
+
+ while (alen(stab->stab_array) >= 0L) {
+ str = ashift(stab->stab_array);
+ str_sset(stab->stab_val,str);
+ STABSET(stab->stab_val);
+ oldname = str_get(stab->stab_val);
+ if (do_open(stab,oldname)) {
+ if (inplace) {
+ if (*inplace) {
+ str_cat(str,inplace);
+#ifdef RENAME
+ rename(oldname,str->str_ptr);
+#else
+ UNLINK(str->str_ptr);
+ link(oldname,str->str_ptr);
+ UNLINK(oldname);
+#endif
+ }
+ sprintf(tokenbuf,">%s",oldname);
+ do_open(argvoutstab,tokenbuf);
+ defoutstab = argvoutstab;
+ }
+ str_free(str);
+ return stab->stab_io->fp;
+ }
+ else
+ fprintf(stderr,"Can't open %s\n",str_get(str));
+ str_free(str);
+ }
+ if (inplace) {
+ do_close(argvoutstab,FALSE);
+ defoutstab = stabent("stdout",TRUE);
+ }
+ return Nullfp;
+}
+
+bool
+do_close(stab,explicit)
+STAB *stab;
+bool explicit;
+{
+ bool retval = FALSE;
+ register STIO *stio = stab->stab_io;
+
+ if (!stio) /* never opened */
+ return FALSE;
+ if (stio->fp) {
+ if (stio->type == '|')
+ retval = (pclose(stio->fp) >= 0);
+ else if (stio->type == '-')
+ retval = TRUE;
+ else
+ retval = (fclose(stio->fp) != EOF);
+ stio->fp = Nullfp;
+ }
+ if (explicit)
+ stio->lines = 0;
+ stio->type = ' ';
+ return retval;
+}
+
+bool
+do_eof(stab)
+STAB *stab;
+{
+ register STIO *stio;
+ int ch;
+
+ if (!stab)
+ return TRUE;
+
+ stio = stab->stab_io;
+ if (!stio)
+ return TRUE;
+
+ while (stio->fp) {
+
+#ifdef STDSTDIO /* (the code works without this) */
+ if (stio->fp->_cnt) /* cheat a little, since */
+ return FALSE; /* this is the most usual case */
+#endif
+
+ ch = getc(stio->fp);
+ if (ch != EOF) {
+ ungetc(ch, stio->fp);
+ return FALSE;
+ }
+ if (stio->flags & IOF_ARGV) { /* not necessarily a real EOF yet? */
+ if (!nextargv(stab)) /* get another fp handy */
+ return TRUE;
+ }
+ else
+ return TRUE; /* normal fp, definitely end of file */
+ }
+ return TRUE;
+}
+
+long
+do_tell(stab)
+STAB *stab;
+{
+ register STIO *stio;
+ int ch;
+
+ if (!stab)
+ return -1L;
+
+ stio = stab->stab_io;
+ if (!stio || !stio->fp)
+ return -1L;
+
+ return ftell(stio->fp);
+}
+
+bool
+do_seek(stab, pos, whence)
+STAB *stab;
+long pos;
+int whence;
+{
+ register STIO *stio;
+
+ if (!stab)
+ return FALSE;
+
+ stio = stab->stab_io;
+ if (!stio || !stio->fp)
+ return FALSE;
+
+ return fseek(stio->fp, pos, whence) >= 0;
+}
+
+do_stat(arg,sarg,retary)
+register ARG *arg;
+register STR **sarg;
+STR ***retary;
+{
+ register ARRAY *ary;
+ static ARRAY *myarray = Null(ARRAY*);
+ int max = 13;
+ register int i;
+
+ ary = myarray;
+ if (!ary)
+ myarray = ary = anew();
+ ary->ary_fill = -1;
+ if (arg[1].arg_type == A_LVAL) {
+ tmpstab = arg[1].arg_ptr.arg_stab;
+ if (!tmpstab->stab_io ||
+ fstat(fileno(tmpstab->stab_io->fp),&statbuf) < 0) {
+ max = 0;
+ }
+ }
+ else
+ if (stat(str_get(sarg[1]),&statbuf) < 0)
+ max = 0;
+
+ if (retary) {
+ if (max) {
+ apush(ary,str_nmake((double)statbuf.st_dev));
+ apush(ary,str_nmake((double)statbuf.st_ino));
+ apush(ary,str_nmake((double)statbuf.st_mode));
+ apush(ary,str_nmake((double)statbuf.st_nlink));
+ apush(ary,str_nmake((double)statbuf.st_uid));
+ apush(ary,str_nmake((double)statbuf.st_gid));
+ apush(ary,str_nmake((double)statbuf.st_rdev));
+ apush(ary,str_nmake((double)statbuf.st_size));
+ apush(ary,str_nmake((double)statbuf.st_atime));
+ apush(ary,str_nmake((double)statbuf.st_mtime));
+ apush(ary,str_nmake((double)statbuf.st_ctime));
+ apush(ary,str_nmake((double)statbuf.st_blksize));
+ apush(ary,str_nmake((double)statbuf.st_blocks));
+ }
+ sarg = (STR**)safemalloc((max+2)*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[max+1] = Nullstr;
+ for (i = 1; i <= max; i++)
+ sarg[i] = afetch(ary,i-1);
+ *retary = sarg;
+ }
+ return max;
+}
+
+do_tms(retary)
+STR ***retary;
+{
+ register ARRAY *ary;
+ static ARRAY *myarray = Null(ARRAY*);
+ register STR **sarg;
+ int max = 4;
+ register int i;
+
+ ary = myarray;
+ if (!ary)
+ myarray = ary = anew();
+ ary->ary_fill = -1;
+ if (times(&timesbuf) < 0)
+ max = 0;
+
+ if (retary) {
+ if (max) {
+ apush(ary,str_nmake(((double)timesbuf.tms_utime)/60.0));
+ apush(ary,str_nmake(((double)timesbuf.tms_stime)/60.0));
+ apush(ary,str_nmake(((double)timesbuf.tms_cutime)/60.0));
+ apush(ary,str_nmake(((double)timesbuf.tms_cstime)/60.0));
+ }
+ sarg = (STR**)safemalloc((max+2)*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[max+1] = Nullstr;
+ for (i = 1; i <= max; i++)
+ sarg[i] = afetch(ary,i-1);
+ *retary = sarg;
+ }
+ return max;
+}
+
+do_time(tmbuf,retary)
+struct tm *tmbuf;
+STR ***retary;
+{
+ register ARRAY *ary;
+ static ARRAY *myarray = Null(ARRAY*);
+ register STR **sarg;
+ int max = 9;
+ register int i;
+ STR *str;
+
+ ary = myarray;
+ if (!ary)
+ myarray = ary = anew();
+ ary->ary_fill = -1;
+ if (!tmbuf)
+ max = 0;
+
+ if (retary) {
+ if (max) {
+ apush(ary,str_nmake((double)tmbuf->tm_sec));
+ apush(ary,str_nmake((double)tmbuf->tm_min));
+ apush(ary,str_nmake((double)tmbuf->tm_hour));
+ apush(ary,str_nmake((double)tmbuf->tm_mday));
+ apush(ary,str_nmake((double)tmbuf->tm_mon));
+ apush(ary,str_nmake((double)tmbuf->tm_year));
+ apush(ary,str_nmake((double)tmbuf->tm_wday));
+ apush(ary,str_nmake((double)tmbuf->tm_yday));
+ apush(ary,str_nmake((double)tmbuf->tm_isdst));
+ }
+ sarg = (STR**)safemalloc((max+2)*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[max+1] = Nullstr;
+ for (i = 1; i <= max; i++)
+ sarg[i] = afetch(ary,i-1);
+ *retary = sarg;
+ }
+ return max;
+}
+
+void
+do_sprintf(str,len,sarg)
+register STR *str;
+register int len;
+register STR **sarg;
+{
+ register char *s;
+ register char *t;
+ bool dolong;
+ char ch;
+
+ str_set(str,"");
+ len--; /* don't count pattern string */
+ sarg++;
+ for (s = str_get(*(sarg++)); *sarg && *s && len; len--) {
+ dolong = FALSE;
+ for (t = s; *t && *t != '%'; t++) ;
+ if (!*t)
+ break; /* not enough % patterns, oh well */
+ for (t++; *sarg && *t && t != s; t++) {
+ switch (*t) {
+ case '\0':
+ break;
+ case '%':
+ ch = *(++t);
+ *t = '\0';
+ sprintf(buf,s);
+ s = t;
+ *(t--) = ch;
+ break;
+ case 'l':
+ dolong = TRUE;
+ break;
+ case 'D': case 'X': case 'O':
+ dolong = TRUE;
+ /* FALL THROUGH */
+ case 'd': case 'x': case 'o': case 'c':
+ ch = *(++t);
+ *t = '\0';
+ if (dolong)
+ sprintf(buf,s,(long)str_gnum(*(sarg++)));
+ else
+ sprintf(buf,s,(int)str_gnum(*(sarg++)));
+ s = t;
+ *(t--) = ch;
+ break;
+ case 'E': case 'e': case 'f': case 'G': case 'g':
+ ch = *(++t);
+ *t = '\0';
+ sprintf(buf,s,str_gnum(*(sarg++)));
+ s = t;
+ *(t--) = ch;
+ break;
+ case 's':
+ ch = *(++t);
+ *t = '\0';
+ sprintf(buf,s,str_get(*(sarg++)));
+ s = t;
+ *(t--) = ch;
+ break;
+ }
+ }
+ str_cat(str,buf);
+ }
+ if (*s)
+ str_cat(str,s);
+ STABSET(str);
+}
+
+bool
+do_print(s,fp)
+char *s;
+FILE *fp;
+{
+ if (!fp || !s)
+ return FALSE;
+ fputs(s,fp);
+ return TRUE;
+}
+
+bool
+do_aprint(arg,fp)
+register ARG *arg;
+register FILE *fp;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+ register bool retval;
+ double value;
+
+ (void)eval(arg[1].arg_ptr.arg_arg,&tmpary);
+ if (arg->arg_type == O_PRTF) {
+ do_sprintf(arg->arg_ptr.arg_str,32767,tmpary);
+ retval = do_print(str_get(arg->arg_ptr.arg_str),fp);
+ }
+ else {
+ retval = FALSE;
+ for (elem = tmpary+1; *elem; elem++) {
+ if (retval && ofs)
+ do_print(ofs, fp);
+ if (ofmt && fp) {
+ if ((*elem)->str_nok || str_gnum(*elem) != 0.0)
+ fprintf(fp, ofmt, str_gnum(*elem));
+ retval = TRUE;
+ }
+ else
+ retval = do_print(str_get(*elem), fp);
+ if (!retval)
+ break;
+ }
+ if (ors)
+ retval = do_print(ors, fp);
+ }
+ safefree((char*)tmpary);
+ return retval;
+}
+
+bool
+do_aexec(arg)
+register ARG *arg;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+ register char **a;
+ register int i;
+ char **argv;
+
+ (void)eval(arg[1].arg_ptr.arg_arg,&tmpary);
+ i = 0;
+ for (elem = tmpary+1; *elem; elem++)
+ i++;
+ if (i) {
+ argv = (char**)safemalloc((i+1)*sizeof(char*));
+ a = argv;
+ for (elem = tmpary+1; *elem; elem++) {
+ *a++ = str_get(*elem);
+ }
+ *a = Nullch;
+ execvp(argv[0],argv);
+ safefree((char*)argv);
+ }
+ safefree((char*)tmpary);
+ return FALSE;
+}
+
+bool
+do_exec(cmd)
+char *cmd;
+{
+ STR **tmpary; /* must not be register */
+ register char **a;
+ register char *s;
+ char **argv;
+
+ /* see if there are shell metacharacters in it */
+
+ for (s = cmd; *s; s++) {
+ if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`",*s)) {
+ execl("/bin/sh","sh","-c",cmd,0);
+ return FALSE;
+ }
+ }
+ argv = (char**)safemalloc(((s - cmd) / 2 + 2)*sizeof(char*));
+
+ a = argv;
+ for (s = cmd; *s;) {
+ while (isspace(*s)) s++;
+ if (*s)
+ *(a++) = s;
+ while (*s && !isspace(*s)) s++;
+ if (*s)
+ *s++ = '\0';
+ }
+ *a = Nullch;
+ if (argv[0])
+ execvp(argv[0],argv);
+ safefree((char*)argv);
+ return FALSE;
+}
+
+STR *
+do_push(arg,ary)
+register ARG *arg;
+register ARRAY *ary;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+ register STR *str = &str_no;
+
+ (void)eval(arg[1].arg_ptr.arg_arg,&tmpary);
+ for (elem = tmpary+1; *elem; elem++) {
+ str = str_new(0);
+ str_sset(str,*elem);
+ apush(ary,str);
+ }
+ safefree((char*)tmpary);
+ return str;
+}
+
+do_unshift(arg,ary)
+register ARG *arg;
+register ARRAY *ary;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+ register STR *str = &str_no;
+ register int i;
+
+ (void)eval(arg[1].arg_ptr.arg_arg,&tmpary);
+ i = 0;
+ for (elem = tmpary+1; *elem; elem++)
+ i++;
+ aunshift(ary,i);
+ i = 0;
+ for (elem = tmpary+1; *elem; elem++) {
+ str = str_new(0);
+ str_sset(str,*elem);
+ astore(ary,i++,str);
+ }
+ safefree((char*)tmpary);
+}
+
+apply(type,arg,sarg)
+int type;
+register ARG *arg;
+STR **sarg;
+{
+ STR **tmpary; /* must not be register */
+ register STR **elem;
+ register int i;
+ register int val;
+ register int val2;
+
+ if (sarg)
+ tmpary = sarg;
+ else
+ (void)eval(arg[1].arg_ptr.arg_arg,&tmpary);
+ i = 0;
+ for (elem = tmpary+1; *elem; elem++)
+ i++;
+ switch (type) {
+ case O_CHMOD:
+ if (--i > 0) {
+ val = (int)str_gnum(tmpary[1]);
+ for (elem = tmpary+2; *elem; elem++)
+ if (chmod(str_get(*elem),val))
+ i--;
+ }
+ break;
+ case O_CHOWN:
+ if (i > 2) {
+ i -= 2;
+ val = (int)str_gnum(tmpary[1]);
+ val2 = (int)str_gnum(tmpary[2]);
+ for (elem = tmpary+3; *elem; elem++)
+ if (chown(str_get(*elem),val,val2))
+ i--;
+ }
+ else
+ i = 0;
+ break;
+ case O_KILL:
+ if (--i > 0) {
+ val = (int)str_gnum(tmpary[1]);
+ if (val < 0)
+ val = -val;
+ for (elem = tmpary+2; *elem; elem++)
+ if (kill(atoi(str_get(*elem)),val))
+ i--;
+ }
+ break;
+ case O_UNLINK:
+ for (elem = tmpary+1; *elem; elem++)
+ if (UNLINK(str_get(*elem)))
+ i--;
+ break;
+ }
+ if (!sarg)
+ safefree((char*)tmpary);
+ return i;
+}
+
+STR *
+do_subr(arg,sarg)
+register ARG *arg;
+register char **sarg;
+{
+ ARRAY *savearray;
+ STR *str;
+
+ savearray = defstab->stab_array;
+ defstab->stab_array = anew();
+ if (arg[1].arg_flags & AF_SPECIAL)
+ (void)do_push(arg,defstab->stab_array);
+ else if (arg[1].arg_type != A_NULL) {
+ str = str_new(0);
+ str_sset(str,sarg[1]);
+ apush(defstab->stab_array,str);
+ }
+ str = cmd_exec(arg[2].arg_ptr.arg_stab->stab_sub);
+ afree(defstab->stab_array); /* put back old $_[] */
+ defstab->stab_array = savearray;
+ return str;
+}
+
+void
+do_assign(retstr,arg)
+STR *retstr;
+register ARG *arg;
+{
+ STR **tmpary; /* must not be register */
+ register ARG *larg = arg[1].arg_ptr.arg_arg;
+ register STR **elem;
+ register STR *str;
+ register ARRAY *ary;
+ register int i;
+ register int lasti;
+ char *s;
+
+ (void)eval(arg[2].arg_ptr.arg_arg,&tmpary);
+
+ if (arg->arg_flags & AF_COMMON) {
+ if (*(tmpary+1)) {
+ for (elem=tmpary+2; *elem; elem++) {
+ *elem = str_static(*elem);
+ }
+ }
+ }
+ if (larg->arg_type == O_LIST) {
+ lasti = larg->arg_len;
+ for (i=1,elem=tmpary+1; i <= lasti; i++) {
+ if (*elem)
+ s = str_get(*(elem++));
+ else
+ s = "";
+ switch (larg[i].arg_type) {
+ case A_STAB:
+ case A_LVAL:
+ str = STAB_STR(larg[i].arg_ptr.arg_stab);
+ break;
+ case A_LEXPR:
+ str = eval(larg[i].arg_ptr.arg_arg,Null(STR***));
+ break;
+ }
+ str_set(str,s);
+ STABSET(str);
+ }
+ i = elem - tmpary - 1;
+ }
+ else { /* should be an array name */
+ ary = larg[1].arg_ptr.arg_stab->stab_array;
+ for (i=0,elem=tmpary+1; *elem; i++) {
+ str = str_new(0);
+ if (*elem)
+ str_sset(str,*(elem++));
+ astore(ary,i,str);
+ }
+ ary->ary_fill = i - 1; /* they can get the extra ones back by */
+ } /* setting an element larger than old fill */
+ str_numset(retstr,(double)i);
+ STABSET(retstr);
+ safefree((char*)tmpary);
+}
+
+int
+do_kv(hash,kv,sarg,retary)
+HASH *hash;
+int kv;
+register STR **sarg;
+STR ***retary;
+{
+ register ARRAY *ary;
+ int max = 0;
+ int i;
+ static ARRAY *myarray = Null(ARRAY*);
+ register HENT *entry;
+
+ ary = myarray;
+ if (!ary)
+ myarray = ary = anew();
+ ary->ary_fill = -1;
+
+ hiterinit(hash);
+ while (entry = hiternext(hash)) {
+ max++;
+ if (kv == O_KEYS)
+ apush(ary,str_make(hiterkey(entry)));
+ else
+ apush(ary,str_make(str_get(hiterval(entry))));
+ }
+ if (retary) { /* array wanted */
+ sarg = (STR**)saferealloc((char*)sarg,(max+2)*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[max+1] = Nullstr;
+ for (i = 1; i <= max; i++)
+ sarg[i] = afetch(ary,i-1);
+ *retary = sarg;
+ }
+ return max;
+}
+
+STR *
+do_each(hash,sarg,retary)
+HASH *hash;
+register STR **sarg;
+STR ***retary;
+{
+ static STR *mystr = Nullstr;
+ STR *retstr;
+ HENT *entry = hiternext(hash);
+
+ if (mystr) {
+ str_free(mystr);
+ mystr = Nullstr;
+ }
+
+ if (retary) { /* array wanted */
+ if (entry) {
+ sarg = (STR**)saferealloc((char*)sarg,4*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[3] = Nullstr;
+ sarg[1] = mystr = str_make(hiterkey(entry));
+ retstr = sarg[2] = hiterval(entry);
+ *retary = sarg;
+ }
+ else {
+ sarg = (STR**)saferealloc((char*)sarg,2*sizeof(STR*));
+ sarg[0] = Nullstr;
+ sarg[1] = retstr = Nullstr;
+ *retary = sarg;
+ }
+ }
+ else
+ retstr = hiterval(entry);
+
+ return retstr;
+}
+
+init_eval()
+{
+ register int i;
+
+#define A(e1,e2,e3) (e1+(e2<<1)+(e3<<2))
+ opargs[O_ITEM] = A(1,0,0);
+ opargs[O_ITEM2] = A(0,0,0);
+ opargs[O_ITEM3] = A(0,0,0);
+ opargs[O_CONCAT] = A(1,1,0);
+ opargs[O_MATCH] = A(1,0,0);
+ opargs[O_NMATCH] = A(1,0,0);
+ opargs[O_SUBST] = A(1,0,0);
+ opargs[O_NSUBST] = A(1,0,0);
+ opargs[O_ASSIGN] = A(1,1,0);
+ opargs[O_MULTIPLY] = A(1,1,0);
+ opargs[O_DIVIDE] = A(1,1,0);
+ opargs[O_MODULO] = A(1,1,0);
+ opargs[O_ADD] = A(1,1,0);
+ opargs[O_SUBTRACT] = A(1,1,0);
+ opargs[O_LEFT_SHIFT] = A(1,1,0);
+ opargs[O_RIGHT_SHIFT] = A(1,1,0);
+ opargs[O_LT] = A(1,1,0);
+ opargs[O_GT] = A(1,1,0);
+ opargs[O_LE] = A(1,1,0);
+ opargs[O_GE] = A(1,1,0);
+ opargs[O_EQ] = A(1,1,0);
+ opargs[O_NE] = A(1,1,0);
+ opargs[O_BIT_AND] = A(1,1,0);
+ opargs[O_XOR] = A(1,1,0);
+ opargs[O_BIT_OR] = A(1,1,0);
+ opargs[O_AND] = A(1,0,0); /* don't eval arg 2 (yet) */
+ opargs[O_OR] = A(1,0,0); /* don't eval arg 2 (yet) */
+ opargs[O_COND_EXPR] = A(1,0,0); /* don't eval args 2 or 3 */
+ opargs[O_COMMA] = A(1,1,0);
+ opargs[O_NEGATE] = A(1,0,0);
+ opargs[O_NOT] = A(1,0,0);
+ opargs[O_COMPLEMENT] = A(1,0,0);
+ opargs[O_WRITE] = A(1,0,0);
+ opargs[O_OPEN] = A(1,1,0);
+ opargs[O_TRANS] = A(1,0,0);
+ opargs[O_NTRANS] = A(1,0,0);
+ opargs[O_CLOSE] = A(0,0,0);
+ opargs[O_ARRAY] = A(1,0,0);
+ opargs[O_HASH] = A(1,0,0);
+ opargs[O_LARRAY] = A(1,0,0);
+ opargs[O_LHASH] = A(1,0,0);
+ opargs[O_PUSH] = A(1,0,0);
+ opargs[O_POP] = A(0,0,0);
+ opargs[O_SHIFT] = A(0,0,0);
+ opargs[O_SPLIT] = A(1,0,0);
+ opargs[O_LENGTH] = A(1,0,0);
+ opargs[O_SPRINTF] = A(1,0,0);
+ opargs[O_SUBSTR] = A(1,1,1);
+ opargs[O_JOIN] = A(1,0,0);
+ opargs[O_SLT] = A(1,1,0);
+ opargs[O_SGT] = A(1,1,0);
+ opargs[O_SLE] = A(1,1,0);
+ opargs[O_SGE] = A(1,1,0);
+ opargs[O_SEQ] = A(1,1,0);
+ opargs[O_SNE] = A(1,1,0);
+ opargs[O_SUBR] = A(1,0,0);
+ opargs[O_PRINT] = A(1,0,0);
+ opargs[O_CHDIR] = A(1,0,0);
+ opargs[O_DIE] = A(1,0,0);
+ opargs[O_EXIT] = A(1,0,0);
+ opargs[O_RESET] = A(1,0,0);
+ opargs[O_LIST] = A(0,0,0);
+ opargs[O_EOF] = A(0,0,0);
+ opargs[O_TELL] = A(0,0,0);
+ opargs[O_SEEK] = A(0,1,1);
+ opargs[O_LAST] = A(1,0,0);
+ opargs[O_NEXT] = A(1,0,0);
+ opargs[O_REDO] = A(1,0,0);
+ opargs[O_GOTO] = A(1,0,0);
+ opargs[O_INDEX] = A(1,1,0);
+ opargs[O_TIME] = A(0,0,0);
+ opargs[O_TMS] = A(0,0,0);
+ opargs[O_LOCALTIME] = A(1,0,0);
+ opargs[O_GMTIME] = A(1,0,0);
+ opargs[O_STAT] = A(1,0,0);
+ opargs[O_CRYPT] = A(1,1,0);
+ opargs[O_EXP] = A(1,0,0);
+ opargs[O_LOG] = A(1,0,0);
+ opargs[O_SQRT] = A(1,0,0);
+ opargs[O_INT] = A(1,0,0);
+ opargs[O_PRTF] = A(1,0,0);
+ opargs[O_ORD] = A(1,0,0);
+ opargs[O_SLEEP] = A(1,0,0);
+ opargs[O_FLIP] = A(1,0,0);
+ opargs[O_FLOP] = A(0,1,0);
+ opargs[O_KEYS] = A(0,0,0);
+ opargs[O_VALUES] = A(0,0,0);
+ opargs[O_EACH] = A(0,0,0);
+ opargs[O_CHOP] = A(1,0,0);
+ opargs[O_FORK] = A(1,0,0);
+ opargs[O_EXEC] = A(1,0,0);
+ opargs[O_SYSTEM] = A(1,0,0);
+ opargs[O_OCT] = A(1,0,0);
+ opargs[O_HEX] = A(1,0,0);
+ opargs[O_CHMOD] = A(1,0,0);
+ opargs[O_CHOWN] = A(1,0,0);
+ opargs[O_KILL] = A(1,0,0);
+ opargs[O_RENAME] = A(1,1,0);
+ opargs[O_UNLINK] = A(1,0,0);
+ opargs[O_UMASK] = A(1,0,0);
+ opargs[O_UNSHIFT] = A(1,0,0);
+ opargs[O_LINK] = A(1,1,0);
+ opargs[O_REPEAT] = A(1,1,0);
+}
+
+static int (*ihand)();
+static int (*qhand)();
+
+STR *
+eval(arg,retary)
+register ARG *arg;
+STR ***retary; /* where to return an array to, null if nowhere */
+{
+ register STR *str;
+ register int anum;
+ register int optype;
+ register int maxarg;
+ double value;
+ STR *quicksarg[5];
+ register STR **sarg = quicksarg;
+ register char *tmps;
+ char *tmps2;
+ int argflags;
+ long tmplong;
+ FILE *fp;
+ STR *tmpstr;
+ FCMD *form;
+ STAB *stab;
+ ARRAY *ary;
+ bool assigning = FALSE;
+ double exp(), log(), sqrt(), modf();
+ char *crypt(), *getenv();
+
+ if (!arg)
+ return &str_no;
+ str = arg->arg_ptr.arg_str;
+ optype = arg->arg_type;
+ maxarg = arg->arg_len;
+ if (maxarg > 3 || retary) {
+ sarg = (STR **)safemalloc((maxarg+2) * sizeof(STR*));
+ }
+#ifdef DEBUGGING
+ if (debug & 8) {
+ deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
+ }
+ debname[dlevel] = opname[optype][0];
+ debdelim[dlevel++] = ':';
+#endif
+ for (anum = 1; anum <= maxarg; anum++) {
+ argflags = arg[anum].arg_flags;
+ if (argflags & AF_SPECIAL)
+ continue;
+ re_eval:
+ switch (arg[anum].arg_type) {
+ default:
+ sarg[anum] = &str_no;
+#ifdef DEBUGGING
+ tmps = "NULL";
+#endif
+ break;
+ case A_EXPR:
+#ifdef DEBUGGING
+ if (debug & 8) {
+ tmps = "EXPR";
+ deb("%d.EXPR =>\n",anum);
+ }
+#endif
+ sarg[anum] = eval(arg[anum].arg_ptr.arg_arg, Null(STR***));
+ break;
+ case A_CMD:
+#ifdef DEBUGGING
+ if (debug & 8) {
+ tmps = "CMD";
+ deb("%d.CMD (%lx) =>\n",anum,arg[anum].arg_ptr.arg_cmd);
+ }
+#endif
+ sarg[anum] = cmd_exec(arg[anum].arg_ptr.arg_cmd);
+ break;
+ case A_STAB:
+ sarg[anum] = STAB_STR(arg[anum].arg_ptr.arg_stab);
+#ifdef DEBUGGING
+ if (debug & 8) {
+ sprintf(buf,"STAB $%s ==",arg[anum].arg_ptr.arg_stab->stab_name);
+ tmps = buf;
+ }
+#endif
+ break;
+ case A_LEXPR:
+#ifdef DEBUGGING
+ if (debug & 8) {
+ tmps = "LEXPR";
+ deb("%d.LEXPR =>\n",anum);
+ }
+#endif
+ str = eval(arg[anum].arg_ptr.arg_arg,Null(STR***));
+ if (!str)
+ fatal("panic: A_LEXPR\n");
+ goto do_crement;
+ case A_LVAL:
+#ifdef DEBUGGING
+ if (debug & 8) {
+ sprintf(buf,"LVAL $%s ==",arg[anum].arg_ptr.arg_stab->stab_name);
+ tmps = buf;
+ }
+#endif
+ str = STAB_STR(arg[anum].arg_ptr.arg_stab);
+ if (!str)
+ fatal("panic: A_LVAL\n");
+ do_crement:
+ assigning = TRUE;
+ if (argflags & AF_PRE) {
+ if (argflags & AF_UP)
+ str_inc(str);
+ else
+ str_dec(str);
+ STABSET(str);
+ sarg[anum] = str;
+ str = arg->arg_ptr.arg_str;
+ }
+ else if (argflags & AF_POST) {
+ sarg[anum] = str_static(str);
+ if (argflags & AF_UP)
+ str_inc(str);
+ else
+ str_dec(str);
+ STABSET(str);
+ str = arg->arg_ptr.arg_str;
+ }
+ else {
+ sarg[anum] = str;
+ }
+ break;
+ case A_ARYLEN:
+ sarg[anum] = str_static(&str_no);
+ str_numset(sarg[anum],
+ (double)alen(arg[anum].arg_ptr.arg_stab->stab_array));
+#ifdef DEBUGGING
+ tmps = "ARYLEN";
+#endif
+ break;
+ case A_SINGLE:
+ sarg[anum] = arg[anum].arg_ptr.arg_str;
+#ifdef DEBUGGING
+ tmps = "SINGLE";
+#endif
+ break;
+ case A_DOUBLE:
+ (void) interp(str,str_get(arg[anum].arg_ptr.arg_str));
+ sarg[anum] = str;
+#ifdef DEBUGGING
+ tmps = "DOUBLE";
+#endif
+ break;
+ case A_BACKTICK:
+ tmps = str_get(arg[anum].arg_ptr.arg_str);
+ fp = popen(str_get(interp(str,tmps)),"r");
+ tmpstr = str_new(80);
+ str_set(str,"");
+ if (fp) {
+ while (str_gets(tmpstr,fp) != Nullch) {
+ str_scat(str,tmpstr);
+ }
+ statusvalue = pclose(fp);
+ }
+ else
+ statusvalue = -1;
+ str_free(tmpstr);
+
+ sarg[anum] = str;
+#ifdef DEBUGGING
+ tmps = "BACK";
+#endif
+ break;
+ case A_READ:
+ fp = Nullfp;
+ last_in_stab = arg[anum].arg_ptr.arg_stab;
+ if (last_in_stab->stab_io) {
+ fp = last_in_stab->stab_io->fp;
+ if (!fp && (last_in_stab->stab_io->flags & IOF_ARGV)) {
+ if (last_in_stab->stab_io->flags & IOF_START) {
+ last_in_stab->stab_io->flags &= ~IOF_START;
+ last_in_stab->stab_io->lines = 0;
+ if (alen(last_in_stab->stab_array) < 0L) {
+ tmpstr = str_make("-"); /* assume stdin */
+ apush(last_in_stab->stab_array, tmpstr);
+ }
+ }
+ fp = nextargv(last_in_stab);
+ if (!fp) /* Note: fp != last_in_stab->stab_io->fp */
+ do_close(last_in_stab,FALSE); /* now it does */
+ }
+ }
+ keepgoing:
+ if (!fp)
+ sarg[anum] = &str_no;
+ else if (!str_gets(str,fp)) {
+ if (last_in_stab->stab_io->flags & IOF_ARGV) {
+ fp = nextargv(last_in_stab);
+ if (fp)
+ goto keepgoing;
+ do_close(last_in_stab,FALSE);
+ last_in_stab->stab_io->flags |= IOF_START;
+ }
+ if (fp == stdin) {
+ clearerr(fp);
+ }
+ sarg[anum] = &str_no;
+ break;
+ }
+ else {
+ last_in_stab->stab_io->lines++;
+ sarg[anum] = str;
+ }
+#ifdef DEBUGGING
+ tmps = "READ";
+#endif
+ break;
+ }
+#ifdef DEBUGGING
+ if (debug & 8)
+ deb("%d.%s = '%s'\n",anum,tmps,str_peek(sarg[anum]));
+#endif
+ }
+ switch (optype) {
+ case O_ITEM:
+ if (str != sarg[1])
+ str_sset(str,sarg[1]);
+ STABSET(str);
+ break;
+ case O_ITEM2:
+ if (str != sarg[2])
+ str_sset(str,sarg[2]);
+ STABSET(str);
+ break;
+ case O_ITEM3:
+ if (str != sarg[3])
+ str_sset(str,sarg[3]);
+ STABSET(str);
+ break;
+ case O_CONCAT:
+ if (str != sarg[1])
+ str_sset(str,sarg[1]);
+ str_scat(str,sarg[2]);
+ STABSET(str);
+ break;
+ case O_REPEAT:
+ if (str != sarg[1])
+ str_sset(str,sarg[1]);
+ anum = (long)str_gnum(sarg[2]);
+ if (anum >= 1) {
+ tmpstr = str_new(0);
+ str_sset(tmpstr,str);
+ for (anum--; anum; anum--)
+ str_scat(str,tmpstr);
+ }
+ else
+ str_sset(str,&str_no);
+ STABSET(str);
+ break;
+ case O_MATCH:
+ str_set(str, do_match(str_get(sarg[1]),arg) ? Yes : No);
+ STABSET(str);
+ break;
+ case O_NMATCH:
+ str_set(str, do_match(str_get(sarg[1]),arg) ? No : Yes);
+ STABSET(str);
+ break;
+ case O_SUBST:
+ value = (double) do_subst(str, arg);
+ str = arg->arg_ptr.arg_str;
+ goto donumset;
+ case O_NSUBST:
+ str_set(arg->arg_ptr.arg_str, do_subst(str, arg) ? No : Yes);
+ str = arg->arg_ptr.arg_str;
+ break;
+ case O_ASSIGN:
+ if (arg[2].arg_flags & AF_SPECIAL)
+ do_assign(str,arg);
+ else {
+ if (str != sarg[2])
+ str_sset(str, sarg[2]);
+ STABSET(str);
+ }
+ break;
+ case O_CHOP:
+ tmps = str_get(str);
+ tmps += str->str_cur - (str->str_cur != 0);
+ str_set(arg->arg_ptr.arg_str,tmps); /* remember last char */
+ *tmps = '\0'; /* wipe it out */
+ str->str_cur = tmps - str->str_ptr;
+ str->str_nok = 0;
+ str = arg->arg_ptr.arg_str;
+ break;
+ case O_MULTIPLY:
+ value = str_gnum(sarg[1]);
+ value *= str_gnum(sarg[2]);
+ goto donumset;
+ case O_DIVIDE:
+ value = str_gnum(sarg[1]);
+ value /= str_gnum(sarg[2]);
+ goto donumset;
+ case O_MODULO:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) % (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_ADD:
+ value = str_gnum(sarg[1]);
+ value += str_gnum(sarg[2]);
+ goto donumset;
+ case O_SUBTRACT:
+ value = str_gnum(sarg[1]);
+ value -= str_gnum(sarg[2]);
+ goto donumset;
+ case O_LEFT_SHIFT:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) << (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_RIGHT_SHIFT:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) >> (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_LT:
+ value = str_gnum(sarg[1]);
+ value = (double)(value < str_gnum(sarg[2]));
+ goto donumset;
+ case O_GT:
+ value = str_gnum(sarg[1]);
+ value = (double)(value > str_gnum(sarg[2]));
+ goto donumset;
+ case O_LE:
+ value = str_gnum(sarg[1]);
+ value = (double)(value <= str_gnum(sarg[2]));
+ goto donumset;
+ case O_GE:
+ value = str_gnum(sarg[1]);
+ value = (double)(value >= str_gnum(sarg[2]));
+ goto donumset;
+ case O_EQ:
+ value = str_gnum(sarg[1]);
+ value = (double)(value == str_gnum(sarg[2]));
+ goto donumset;
+ case O_NE:
+ value = str_gnum(sarg[1]);
+ value = (double)(value != str_gnum(sarg[2]));
+ goto donumset;
+ case O_BIT_AND:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) & (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_XOR:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) ^ (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_BIT_OR:
+ value = str_gnum(sarg[1]);
+ value = (double)(((long)value) | (long)str_gnum(sarg[2]));
+ goto donumset;
+ case O_AND:
+ if (str_true(sarg[1])) {
+ anum = 2;
+ optype = O_ITEM2;
+ maxarg = 0;
+ argflags = arg[anum].arg_flags;
+ goto re_eval;
+ }
+ else {
+ if (assigning) {
+ str_sset(str, sarg[1]);
+ STABSET(str);
+ }
+ else
+ str = sarg[1];
+ break;
+ }
+ case O_OR:
+ if (str_true(sarg[1])) {
+ if (assigning) {
+ str_set(str, sarg[1]);
+ STABSET(str);
+ }
+ else
+ str = sarg[1];
+ break;
+ }
+ else {
+ anum = 2;
+ optype = O_ITEM2;
+ maxarg = 0;
+ argflags = arg[anum].arg_flags;
+ goto re_eval;
+ }
+ case O_COND_EXPR:
+ anum = (str_true(sarg[1]) ? 2 : 3);
+ optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
+ maxarg = 0;
+ argflags = arg[anum].arg_flags;
+ goto re_eval;
+ case O_COMMA:
+ str = sarg[2];
+ break;
+ case O_NEGATE:
+ value = -str_gnum(sarg[1]);
+ goto donumset;
+ case O_NOT:
+ value = (double) !str_true(sarg[1]);
+ goto donumset;
+ case O_COMPLEMENT:
+ value = (double) ~(long)str_gnum(sarg[1]);
+ goto donumset;
+ case O_SELECT:
+ if (arg[1].arg_type == A_LVAL)
+ defoutstab = arg[1].arg_ptr.arg_stab;
+ else
+ defoutstab = stabent(str_get(sarg[1]),TRUE);
+ if (!defoutstab->stab_io)
+ defoutstab->stab_io = stio_new();
+ curoutstab = defoutstab;
+ str_set(str,curoutstab->stab_io->fp ? Yes : No);
+ STABSET(str);
+ break;
+ case O_WRITE:
+ if (maxarg == 0)
+ stab = defoutstab;
+ else if (arg[1].arg_type == A_LVAL)
+ stab = arg[1].arg_ptr.arg_stab;
+ else
+ stab = stabent(str_get(sarg[1]),TRUE);
+ if (!stab->stab_io) {
+ str_set(str, No);
+ STABSET(str);
+ break;
+ }
+ curoutstab = stab;
+ fp = stab->stab_io->fp;
+ debarg = arg;
+ if (stab->stab_io->fmt_stab)
+ form = stab->stab_io->fmt_stab->stab_form;
+ else
+ form = stab->stab_form;
+ if (!form || !fp) {
+ str_set(str, No);
+ STABSET(str);
+ break;
+ }
+ format(&outrec,form);
+ do_write(&outrec,stab->stab_io);
+ if (stab->stab_io->flags & IOF_FLUSH)
+ fflush(fp);
+ str_set(str, Yes);
+ STABSET(str);
+ break;
+ case O_OPEN:
+ if (do_open(arg[1].arg_ptr.arg_stab,str_get(sarg[2]))) {
+ str_set(str, Yes);
+ arg[1].arg_ptr.arg_stab->stab_io->lines = 0;
+ }
+ else
+ str_set(str, No);
+ STABSET(str);
+ 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:
+ str_set(str,
+ do_close(arg[1].arg_ptr.arg_stab,TRUE) ? Yes : No );
+ STABSET(str);
+ break;
+ case O_EACH:
+ str_sset(str,do_each(arg[1].arg_ptr.arg_stab->stab_hash,sarg,retary));
+ retary = Null(STR***); /* do_each already did retary */
+ STABSET(str);
+ break;
+ case O_VALUES:
+ case O_KEYS:
+ value = (double) do_kv(arg[1].arg_ptr.arg_stab->stab_hash,
+ optype,sarg,retary);
+ retary = Null(STR***); /* do_keys already did retary */
+ goto donumset;
+ case O_ARRAY:
+ if (maxarg == 1) {
+ ary = arg[1].arg_ptr.arg_stab->stab_array;
+ maxarg = ary->ary_fill;
+ if (retary) { /* array wanted */
+ sarg =
+ (STR **)saferealloc((char*)sarg,(maxarg+3)*sizeof(STR*));
+ for (anum = 0; anum <= maxarg; anum++) {
+ sarg[anum+1] = str = afetch(ary,anum);
+ }
+ maxarg++;
+ }
+ else
+ str = afetch(ary,maxarg);
+ }
+ else
+ str = afetch(arg[2].arg_ptr.arg_stab->stab_array,
+ ((int)str_gnum(sarg[1])) - arybase);
+ if (!str)
+ return &str_no;
+ break;
+ case O_HASH:
+ tmpstab = arg[2].arg_ptr.arg_stab; /* XXX */
+ str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
+ if (!str)
+ return &str_no;
+ break;
+ case O_LARRAY:
+ anum = ((int)str_gnum(sarg[1])) - arybase;
+ str = afetch(arg[2].arg_ptr.arg_stab->stab_array,anum);
+ if (!str || str == &str_no) {
+ str = str_new(0);
+ astore(arg[2].arg_ptr.arg_stab->stab_array,anum,str);
+ }
+ break;
+ case O_LHASH:
+ tmpstab = arg[2].arg_ptr.arg_stab;
+ str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
+ if (!str) {
+ str = str_new(0);
+ hstore(tmpstab->stab_hash,str_get(sarg[1]),str);
+ }
+ if (tmpstab == envstab) { /* heavy wizardry going on here */
+ str->str_link.str_magic = tmpstab;/* str is now magic */
+ envname = savestr(str_get(sarg[1]));
+ /* he threw the brick up into the air */
+ }
+ else if (tmpstab == sigstab) { /* same thing, only different */
+ str->str_link.str_magic = tmpstab;
+ signame = savestr(str_get(sarg[1]));
+ }
+ break;
+ case O_PUSH:
+ if (arg[1].arg_flags & AF_SPECIAL)
+ str = do_push(arg,arg[2].arg_ptr.arg_stab->stab_array);
+ else {
+ str = str_new(0); /* must copy the STR */
+ str_sset(str,sarg[1]);
+ apush(arg[2].arg_ptr.arg_stab->stab_array,str);
+ }
+ break;
+ case O_POP:
+ str = apop(arg[1].arg_ptr.arg_stab->stab_array);
+ if (!str)
+ return &str_no;
+#ifdef STRUCTCOPY
+ *(arg->arg_ptr.arg_str) = *str;
+#else
+ bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
+#endif
+ safefree((char*)str);
+ str = arg->arg_ptr.arg_str;
+ break;
+ case O_SHIFT:
+ str = ashift(arg[1].arg_ptr.arg_stab->stab_array);
+ if (!str)
+ return &str_no;
+#ifdef STRUCTCOPY
+ *(arg->arg_ptr.arg_str) = *str;
+#else
+ bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
+#endif
+ safefree((char*)str);
+ str = arg->arg_ptr.arg_str;
+ break;
+ case O_SPLIT:
+ value = (double) do_split(str_get(sarg[1]),arg[2].arg_ptr.arg_spat,retary);
+ retary = Null(STR***); /* do_split already did retary */
+ goto donumset;
+ case O_LENGTH:
+ value = (double) str_len(sarg[1]);
+ goto donumset;
+ case O_SPRINTF:
+ sarg[maxarg+1] = Nullstr;
+ do_sprintf(str,arg->arg_len,sarg);
+ break;
+ case O_SUBSTR:
+ anum = ((int)str_gnum(sarg[2])) - arybase;
+ for (tmps = str_get(sarg[1]); *tmps && anum > 0; tmps++,anum--) ;
+ anum = (int)str_gnum(sarg[3]);
+ if (anum >= 0 && strlen(tmps) > anum)
+ str_nset(str, tmps, anum);
+ else
+ str_set(str, tmps);
+ break;
+ case O_JOIN:
+ if (arg[2].arg_flags & AF_SPECIAL && arg[2].arg_type == A_EXPR)
+ do_join(arg,str_get(sarg[1]),str);
+ else
+ ajoin(arg[2].arg_ptr.arg_stab->stab_array,str_get(sarg[1]),str);
+ break;
+ case O_SLT:
+ tmps = str_get(sarg[1]);
+ value = (double) strLT(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SGT:
+ tmps = str_get(sarg[1]);
+ value = (double) strGT(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SLE:
+ tmps = str_get(sarg[1]);
+ value = (double) strLE(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SGE:
+ tmps = str_get(sarg[1]);
+ value = (double) strGE(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SEQ:
+ tmps = str_get(sarg[1]);
+ value = (double) strEQ(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SNE:
+ tmps = str_get(sarg[1]);
+ value = (double) strNE(tmps,str_get(sarg[2]));
+ goto donumset;
+ case O_SUBR:
+ str_sset(str,do_subr(arg,sarg));
+ STABSET(str);
+ break;
+ case O_PRTF:
+ case O_PRINT:
+ if (maxarg <= 1)
+ stab = defoutstab;
+ else {
+ stab = arg[2].arg_ptr.arg_stab;
+ if (!stab)
+ stab = defoutstab;
+ }
+ if (!stab->stab_io)
+ value = 0.0;
+ else if (arg[1].arg_flags & AF_SPECIAL)
+ value = (double)do_aprint(arg,stab->stab_io->fp);
+ else {
+ value = (double)do_print(str_get(sarg[1]),stab->stab_io->fp);
+ if (ors && optype == O_PRINT)
+ do_print(ors, stab->stab_io->fp);
+ }
+ if (stab->stab_io->flags & IOF_FLUSH)
+ fflush(stab->stab_io->fp);
+ goto donumset;
+ case O_CHDIR:
+ tmps = str_get(sarg[1]);
+ if (!tmps || !*tmps)
+ tmps = getenv("HOME");
+ if (!tmps || !*tmps)
+ tmps = getenv("LOGDIR");
+ value = (double)(chdir(tmps) >= 0);
+ goto donumset;
+ case O_DIE:
+ tmps = str_get(sarg[1]);
+ if (!tmps || !*tmps)
+ exit(1);
+ fatal("%s\n",str_get(sarg[1]));
+ value = 0.0;
+ goto donumset;
+ case O_EXIT:
+ exit((int)str_gnum(sarg[1]));
+ value = 0.0;
+ goto donumset;
+ case O_RESET:
+ str_reset(str_get(sarg[1]));
+ value = 1.0;
+ goto donumset;
+ case O_LIST:
+ if (maxarg > 0)
+ str = sarg[maxarg]; /* unwanted list, return last item */
+ else
+ str = &str_no;
+ break;
+ case O_EOF:
+ str_set(str, do_eof(maxarg > 0 ? arg[1].arg_ptr.arg_stab : last_in_stab) ? Yes : No);
+ STABSET(str);
+ break;
+ case O_TELL:
+ value = (double)do_tell(maxarg > 0 ? arg[1].arg_ptr.arg_stab : last_in_stab);
+ goto donumset;
+ break;
+ case O_SEEK:
+ value = str_gnum(sarg[2]);
+ str_set(str, do_seek(arg[1].arg_ptr.arg_stab,
+ (long)value, (int)str_gnum(sarg[3]) ) ? Yes : No);
+ STABSET(str);
+ break;
+ case O_REDO:
+ case O_NEXT:
+ case O_LAST:
+ if (maxarg > 0) {
+ tmps = str_get(sarg[1]);
+ 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)
+ fatal("Bad label: %s\n", maxarg > 0 ? tmps : "<null>");
+ longjmp(loop_stack[loop_ptr].loop_env, optype);
+ case O_GOTO:/* shudder */
+ goto_targ = str_get(sarg[1]);
+ longjmp(top_env, 1);
+ case O_INDEX:
+ tmps = str_get(sarg[1]);
+ if (!(tmps2 = instr(tmps,str_get(sarg[2]))))
+ value = (double)(-1 + arybase);
+ else
+ value = (double)(tmps2 - tmps + arybase);
+ goto donumset;
+ case O_TIME:
+ value = (double) time(0);
+ goto donumset;
+ case O_TMS:
+ value = (double) do_tms(retary);
+ retary = Null(STR***); /* do_tms already did retary */
+ goto donumset;
+ case O_LOCALTIME:
+ tmplong = (long) str_gnum(sarg[1]);
+ value = (double) do_time(localtime(&tmplong),retary);
+ retary = Null(STR***); /* do_localtime already did retary */
+ goto donumset;
+ case O_GMTIME:
+ tmplong = (long) str_gnum(sarg[1]);
+ value = (double) do_time(gmtime(&tmplong),retary);
+ retary = Null(STR***); /* do_gmtime already did retary */
+ goto donumset;
+ case O_STAT:
+ value = (double) do_stat(arg,sarg,retary);
+ retary = Null(STR***); /* do_stat already did retary */
+ goto donumset;
+ case O_CRYPT:
+ tmps = str_get(sarg[1]);
+ str_set(str,crypt(tmps,str_get(sarg[2])));
+ break;
+ case O_EXP:
+ value = exp(str_gnum(sarg[1]));
+ goto donumset;
+ case O_LOG:
+ value = log(str_gnum(sarg[1]));
+ goto donumset;
+ case O_SQRT:
+ value = sqrt(str_gnum(sarg[1]));
+ goto donumset;
+ case O_INT:
+ modf(str_gnum(sarg[1]),&value);
+ goto donumset;
+ case O_ORD:
+ value = (double) *str_get(sarg[1]);
+ goto donumset;
+ case O_SLEEP:
+ tmps = str_get(sarg[1]);
+ time(&tmplong);
+ if (!tmps || !*tmps)
+ sleep((32767<<16)+32767);
+ else
+ sleep(atoi(tmps));
+ value = (double)tmplong;
+ time(&tmplong);
+ value = ((double)tmplong) - value;
+ goto donumset;
+ case O_FLIP:
+ if (str_true(sarg[1])) {
+ str_numset(str,0.0);
+ anum = 2;
+ arg->arg_type = optype = O_FLOP;
+ maxarg = 0;
+ arg[2].arg_flags &= ~AF_SPECIAL;
+ arg[1].arg_flags |= AF_SPECIAL;
+ argflags = arg[anum].arg_flags;
+ goto re_eval;
+ }
+ str_set(str,"");
+ break;
+ case O_FLOP:
+ str_inc(str);
+ if (str_true(sarg[2])) {
+ arg->arg_type = O_FLIP;
+ arg[1].arg_flags &= ~AF_SPECIAL;
+ arg[2].arg_flags |= AF_SPECIAL;
+ str_cat(str,"E0");
+ }
+ break;
+ case O_FORK:
+ value = (double)fork();
+ goto donumset;
+ case O_SYSTEM:
+ if (anum = vfork()) {
+ ihand = signal(SIGINT, SIG_IGN);
+ qhand = signal(SIGQUIT, SIG_IGN);
+ while ((maxarg = wait(&argflags)) != anum && maxarg != -1)
+ ;
+ if (maxarg == -1)
+ argflags = -1;
+ signal(SIGINT, ihand);
+ signal(SIGQUIT, qhand);
+ value = (double)argflags;
+ goto donumset;
+ }
+ /* FALL THROUGH */
+ case O_EXEC:
+ if (arg[1].arg_flags & AF_SPECIAL)
+ value = (double)do_aexec(arg);
+ else {
+ value = (double)do_exec(str_get(sarg[1]));
+ }
+ goto donumset;
+ case O_HEX:
+ maxarg = 4;
+ goto snarfnum;
+
+ case O_OCT:
+ maxarg = 3;
+
+ snarfnum:
+ anum = 0;
+ tmps = str_get(sarg[1]);
+ for (;;) {
+ switch (*tmps) {
+ default:
+ goto out;
+ case '8': case '9':
+ if (maxarg != 4)
+ goto out;
+ /* FALL THROUGH */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7':
+ anum <<= maxarg;
+ anum += *tmps++ & 15;
+ 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 (maxarg != 4)
+ goto out;
+ anum <<= 4;
+ anum += (*tmps++ & 7) + 9;
+ break;
+ case 'x':
+ maxarg = 4;
+ tmps++;
+ break;
+ }
+ }
+ out:
+ value = (double)anum;
+ goto donumset;
+ case O_CHMOD:
+ case O_CHOWN:
+ case O_KILL:
+ case O_UNLINK:
+ if (arg[1].arg_flags & AF_SPECIAL)
+ value = (double)apply(optype,arg,Null(STR**));
+ else {
+ sarg[2] = Nullstr;
+ value = (double)apply(optype,arg,sarg);
+ }
+ goto donumset;
+ case O_UMASK:
+ value = (double)umask((int)str_gnum(sarg[1]));
+ goto donumset;
+ case O_RENAME:
+ tmps = str_get(sarg[1]);
+#ifdef RENAME
+ value = (double)(rename(tmps,str_get(sarg[2])) >= 0);
+#else
+ tmps2 = str_get(sarg[2]);
+ UNLINK(tmps2);
+ if (!(anum = link(tmps,tmps2)))
+ anum = UNLINK(tmps);
+ value = (double)(anum >= 0);
+#endif
+ goto donumset;
+ case O_LINK:
+ tmps = str_get(sarg[1]);
+ value = (double)(link(tmps,str_get(sarg[2])) >= 0);
+ goto donumset;
+ case O_UNSHIFT:
+ ary = arg[2].arg_ptr.arg_stab->stab_array;
+ if (arg[1].arg_flags & AF_SPECIAL)
+ do_unshift(arg,ary);
+ else {
+ str = str_new(0); /* must copy the STR */
+ str_sset(str,sarg[1]);
+ aunshift(ary,1);
+ astore(ary,0,str);
+ }
+ value = (double)(ary->ary_fill + 1);
+ break;
+ }
+#ifdef DEBUGGING
+ dlevel--;
+ if (debug & 8)
+ deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
+#endif
+ goto freeargs;
+
+donumset:
+ str_numset(str,value);
+ STABSET(str);
+#ifdef DEBUGGING
+ dlevel--;
+ if (debug & 8)
+ deb("%s RETURNS \"%f\"\n",opname[optype],value);
+#endif
+
+freeargs:
+ if (sarg != quicksarg) {
+ if (retary) {
+ if (optype == O_LIST)
+ sarg[0] = &str_no;
+ else
+ sarg[0] = Nullstr;
+ sarg[maxarg+1] = Nullstr;
+ *retary = sarg; /* up to them to free it */
+ }
+ else
+ safefree(sarg);
+ }
+ return str;
+
+nullarray:
+ maxarg = 0;
+#ifdef DEBUGGING
+ dlevel--;
+ if (debug & 8)
+ deb("%s RETURNS ()\n",opname[optype],value);
+#endif
+ goto freeargs;
+}