diff options
Diffstat (limited to 'run.c')
-rw-r--r-- | run.c | 187 |
1 files changed, 121 insertions, 66 deletions
@@ -31,6 +31,8 @@ THIS SOFTWARE. #include <string.h> #include <stdlib.h> #include <time.h> +#include <sys/types.h> +#include <sys/wait.h> #include "awk.h" #include "ytab.h" @@ -71,23 +73,23 @@ extern Awkfloat srand_seed; Node *winner = NULL; /* root of parse tree */ Cell *tmps; /* free temporary cells for execution */ -static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM }; +static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL }; Cell *True = &truecell; -static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM }; +static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL }; Cell *False = &falsecell; -static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM }; +static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL }; Cell *jbreak = &breakcell; -static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM }; +static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL }; Cell *jcont = &contcell; -static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM }; +static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL }; Cell *jnext = &nextcell; -static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM }; +static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL }; Cell *jnextfile = &nextfilecell; -static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; +static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL }; Cell *jexit = &exitcell; -static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; +static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL }; Cell *jret = &retcell; -static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE }; +static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; Node *curnode = NULL; /* the node being executed, for debugging */ @@ -112,7 +114,7 @@ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, if (rminlen) minlen += quantum - rminlen; tbuf = (char *) realloc(*pbuf, minlen); - dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) ); + dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, (void *) *pbuf, (void *) tbuf) ); if (tbuf == NULL) { if (whatrtn) FATAL("out of memory in %s", whatrtn); @@ -221,7 +223,7 @@ struct Frame *fp = NULL; /* frame pointer. bottom level unused */ Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ { - static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE }; + static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; int i, ncall, ndef; int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */ Node *x; @@ -323,14 +325,18 @@ Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ { Cell *y; + /* copy is not constant or field */ + y = gettemp(); + y->tval = x->tval & ~(CON|FLD|REC); y->csub = CCOPY; /* prevents freeing until call is over */ y->nval = x->nval; /* BUG? */ - if (isstr(x)) + if (isstr(x) /* || x->ctype == OCELL */) { y->sval = tostring(x->sval); + y->tval &= ~DONTFREE; + } else + y->tval |= DONTFREE; y->fval = x->fval; - y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ - /* is DONTFREE right? */ return y; } @@ -419,6 +425,10 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */ } else if (a[0] != NULL) { /* getline var <file */ x = execute(a[0]); setsval(x, buf); + if (is_number(x->sval)) { + x->fval = atof(x->sval); + x->tval |= NUM; + } tempfree(x); } else { /* getline <file */ setsval(fldtab[0], buf); @@ -434,6 +444,10 @@ Cell *awkgetline(Node **a, int n) /* get next line from specific input */ n = getrec(&buf, &bufsize, 0); x = execute(a[0]); setsval(x, buf); + if (is_number(x->sval)) { + x->fval = atof(x->sval); + x->tval |= NUM; + } tempfree(x); } } @@ -456,7 +470,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ Node *np; char *buf; int bufsz = recsize; - int nsub = strlen(*SUBSEP); + int nsub; if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in array"); @@ -466,6 +480,7 @@ Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); + nsub = strlen(getsval(subseploc)); if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array")) FATAL("out of memory for %s[%s...]", x->nval, buf); strcat(buf, s); @@ -494,12 +509,12 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts * Cell *x, *y; Node *np; char *s; - int nsub = strlen(*SUBSEP); + int nsub; x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) return True; - if (a[1] == NULL) { /* delete the elements, not the table */ + if (a[1] == 0) { /* delete the elements, not the table */ freesymtab(x); x->tval &= ~STR; x->tval |= ARR; @@ -513,9 +528,10 @@ Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts * for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); + nsub = strlen(getsval(subseploc)); if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete")) FATAL("out of memory deleting %s[%s...]", x->nval, buf); - strcat(buf, s); + strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); @@ -534,7 +550,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ char *buf; char *s; int bufsz = recsize; - int nsub = strlen(*SUBSEP); + int nsub; ap = execute(a[1]); /* array name */ if (!isarr(ap)) { @@ -552,6 +568,7 @@ Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ for (p = a[0]; p; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); + nsub = strlen(getsval(subseploc)); if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest")) FATAL("out of memory deleting %s[%s...]", x->nval, buf); strcat(buf, s); @@ -583,7 +600,7 @@ Cell *matchop(Node **a, int n) /* ~ and match() */ } x = execute(a[1]); /* a[1] = target text */ s = getsval(x); - if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */ + if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */ i = (*mf)((fa *) a[2], s); else { y = execute(a[2]); /* a[2] = regular expr */ @@ -699,7 +716,7 @@ Cell *gettemp(void) /* get a tempcell */ FATAL("out of space for temporaries"); for(i = 1; i < 100; i++) tmps[i-1].cnext = &tmps[i]; - tmps[i-1].cnext = NULL; + tmps[i-1].cnext = 0; } x = tmps; tmps = x->cnext; @@ -734,18 +751,18 @@ Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ int k, m, n; char *s; int temp; - Cell *x, *y, *z = NULL; + Cell *x, *y, *z = 0; x = execute(a[0]); y = execute(a[1]); - if (a[2] != NULL) + if (a[2] != 0) z = execute(a[2]); s = getsval(x); k = strlen(s) + 1; if (k <= 1) { tempfree(x); tempfree(y); - if (a[2] != NULL) { + if (a[2] != 0) { tempfree(z); } x = gettemp(); @@ -758,7 +775,7 @@ Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ else if (m > k) m = k; tempfree(y); - if (a[2] != NULL) { + if (a[2] != 0) { n = (int) getfval(z); tempfree(z); } else @@ -817,6 +834,17 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co char *buf = *pbuf; int bufsize = *pbufsize; + static int first = 1; + static int have_a_format = 0; + + if (first) { + char buf[100]; + + sprintf(buf, "%a", 42.0); + have_a_format = (strcmp(buf, "0x1.5p+5") == 0); + first = 0; + } + os = s; p = buf; if ((fmt = (char *) malloc(fmtsz)) == NULL) @@ -842,7 +870,13 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co FATAL("format item %.30s... ran format() out of memory", os); if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L') break; /* the ansi panoply */ + if (*s == '$') { + FATAL("'$' not permitted in awk formats"); + } if (*s == '*') { + if (a == NULL) { + FATAL("not enough args in printf(%s)", os); + } x = execute(a); a = a->nnext; sprintf(t-1, "%d", fmtwd=(int) getfval(x)); @@ -857,8 +891,13 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co if (fmtwd < 0) fmtwd = -fmtwd; adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4"); - switch (*s) { + case 'a': case 'A': + if (have_a_format) + flag = *s; + else + flag = 'f'; + break; case 'f': case 'e': case 'g': case 'E': case 'G': flag = 'f'; break; @@ -901,6 +940,8 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co p += strlen(p); sprintf(p, "%s", t); break; + case 'a': + case 'A': case 'f': sprintf(p, fmt, getfval(x)); break; case 'd': sprintf(p, fmt, (long) getfval(x)); break; case 'u': sprintf(p, fmt, (int) getfval(x)); break; @@ -1003,7 +1044,7 @@ Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ x = execute(a[0]); i = getfval(x); tempfree(x); - if (n != UMINUS) { + if (n != UMINUS && n != UPLUS) { y = execute(a[1]); j = getfval(y); tempfree(y); @@ -1033,6 +1074,8 @@ Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ case UMINUS: i = -i; break; + case UPLUS: /* handled by getfval(), above */ + break; case POWER: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ i = ipow(i, (int) j); @@ -1088,8 +1131,8 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ y = execute(a[1]); x = execute(a[0]); if (n == ASSIGN) { /* ordinary assignment */ - if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ - ; /* leave alone unless it's a field */ + if (x == y && !(x->tval & (FLD|REC)) && x != nfloc) + ; /* self-assignment: leave alone unless it's a field or NF */ else if ((y->tval & (STR|NUM)) == (STR|NUM)) { setsval(x, getsval(y)); x->fval = getfval(y); @@ -1146,25 +1189,26 @@ Cell *cat(Node **a, int q) /* a[0] cat a[1] */ { Cell *x, *y, *z; int n1, n2; - char *s; + char *s = NULL; + int ssz = 0; x = execute(a[0]); + n1 = strlen(getsval(x)); + adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1"); + (void) strncpy(s, x->sval, ssz); + y = execute(a[1]); - getsval(x); - getsval(y); - n1 = strlen(x->sval); - n2 = strlen(y->sval); - s = (char *) malloc(n1 + n2 + 1); - if (s == NULL) - FATAL("out of space concatenating %.15s... and %.15s...", - x->sval, y->sval); - strcpy(s, x->sval); - strcpy(s+n1, y->sval); + n2 = strlen(getsval(y)); + adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2"); + (void) strncpy(s + n1, y->sval, ssz - n1); + tempfree(x); tempfree(y); + z = gettemp(); z->sval = s; z->tval = STR; + return(z); } @@ -1172,7 +1216,7 @@ Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ { Cell *x; - if (a[0] == NULL) + if (a[0] == 0) x = execute(a[1]); else { x = execute(a[0]); @@ -1209,20 +1253,22 @@ Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ { - Cell *x = NULL, *y, *ap; + Cell *x = 0, *y, *ap; char *s, *origs; + char *fs, *origfs = NULL; int sep; - char *t, temp, num[50], *fs = NULL; + char *t, temp, num[50]; int n, tempstat, arg3type; y = execute(a[0]); /* source string */ origs = s = strdup(getsval(y)); arg3type = ptoi(a[3]); - if (a[2] == NULL) /* fs string */ - fs = *FS; + if (a[2] == 0) /* fs string */ + fs = getsval(fsloc); else if (arg3type == STRING) { /* split(str,arr,"string") */ x = execute(a[2]); - fs = getsval(x); + origfs = fs = strdup(getsval(x)); + tempfree(x); } else if (arg3type == REGEXPR) fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ else @@ -1337,9 +1383,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ tempfree(ap); tempfree(y); free(origs); - if (a[2] != NULL && arg3type == STRING) { - tempfree(x); - } + free(origfs); x = gettemp(); x->tval = NUM; x->fval = n; @@ -1369,7 +1413,7 @@ Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ if (istrue(x)) { tempfree(x); x = execute(a[1]); - } else if (a[2] != NULL) { + } else if (a[2] != 0) { tempfree(x); x = execute(a[2]); } @@ -1421,7 +1465,7 @@ Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ x = execute(a[0]); tempfree(x); for (;;) { - if (a[1]!=NULL) { + if (a[1]!=0) { x = execute(a[1]); if (!istrue(x)) return(x); else tempfree(x); @@ -1479,6 +1523,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis Node *nextarg; FILE *fp; void flush_all(void); + int status = 0; t = ptoi(a[0]); x = execute(a[1]); @@ -1503,7 +1548,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis case FCOS: u = cos(getfval(x)); break; case FATAN: - if (nextarg == NULL) { + if (nextarg == 0) { WARNING("atan2 requires two arguments; returning 1.0"); u = 1.0; } else { @@ -1515,7 +1560,20 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis break; case FSYSTEM: fflush(stdout); /* in case something is buffered already */ - u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ + status = system(getsval(x)); + u = status; + if (status != -1) { + if (WIFEXITED(status)) { + u = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + u = WTERMSIG(status) + 256; +#ifdef WCOREDUMP + if (WCOREDUMP(status)) + u += 256; +#endif + } else /* something else?!? */ + u = 0; + } break; case FRAND: /* in principle, rand() returns something in 0..RAND_MAX */ @@ -1564,7 +1622,7 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis tempfree(x); x = gettemp(); setfval(x, u); - if (nextarg != NULL) { + if (nextarg != 0) { WARNING("warning: function has too many arguments"); for ( ; nextarg; nextarg = nextarg->nnext) execute(nextarg); @@ -1578,7 +1636,7 @@ Cell *printstat(Node **a, int n) /* print a[0] */ Cell *y; FILE *fp; - if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */ + if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ fp = stdout; else fp = redirect(ptoi(a[1]), a[2]); @@ -1587,11 +1645,11 @@ Cell *printstat(Node **a, int n) /* print a[0] */ fputs(getpssval(y), fp); tempfree(y); if (x->nnext == NULL) - fputs(*ORS, fp); + fputs(getsval(orsloc), fp); else - fputs(*OFS, fp); + fputs(getsval(ofsloc), fp); } - if (a[1] != NULL) + if (a[1] != 0) fflush(fp); if (ferror(fp)) FATAL("write error on %s", filename(fp)); @@ -1600,8 +1658,6 @@ Cell *printstat(Node **a, int n) /* print a[0] */ Cell *nullproc(Node **a, int n) { - n = n; - a = a; return 0; } @@ -1650,7 +1706,7 @@ FILE *openfile(int a, const char *us) { const char *s = us; int i, m; - FILE *fp = NULL; + FILE *fp = 0; if (*s == '\0') FATAL("null file name in print or getline"); @@ -1665,7 +1721,7 @@ FILE *openfile(int a, const char *us) return NULL; for (i=0; i < nfiles; i++) - if (files[i].fp == NULL) + if (files[i].fp == 0) break; if (i >= nfiles) { struct files *nf; @@ -1715,7 +1771,6 @@ Cell *closefile(Node **a, int n) Cell *x; int i, stat; - n = n; x = execute(a[0]); getsval(x); stat = -1; @@ -1782,7 +1837,7 @@ Cell *sub(Node **a, int nnn) /* substitute command */ FATAL("out of memory in sub"); x = execute(a[3]); /* target string */ t = getsval(x); - if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ + if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ pfa = (fa *) a[1]; /* regular expression */ else { y = execute(a[1]); @@ -1822,7 +1877,7 @@ Cell *sub(Node **a, int nnn) /* substitute command */ if (pb > buf + bufsz) FATAL("sub result2 %.30s too big; can't happen", buf); setsval(x, buf); /* BUG: should be able to avoid copy */ - result = True; + result = True;; } tempfree(x); tempfree(y); @@ -1845,7 +1900,7 @@ Cell *gsub(Node **a, int nnn) /* global substitute */ num = 0; x = execute(a[3]); /* target string */ t = getsval(x); - if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ + if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ pfa = (fa *) a[1]; /* regular expression */ else { y = execute(a[1]); |