summaryrefslogtreecommitdiff
path: root/run.c
diff options
context:
space:
mode:
Diffstat (limited to 'run.c')
-rw-r--r--run.c187
1 files changed, 121 insertions, 66 deletions
diff --git a/run.c b/run.c
index 5342fe0d0f8b..2dfb3e6c383d 100644
--- a/run.c
+++ b/run.c
@@ -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]);