void freesymtab(Cell *ap) /* free a symbol table */ { Cell *cp, *temp; Array *tp; int i; if (!isarr(ap)) return; tp = (Array *) ap->sval; if (tp == NULL) return; for (i = 0; i < tp->size; i++) { for (cp = tp->tab[i]; cp != NULL; cp = temp) { xfree(cp->nval); if (freeable(cp)) xfree(cp->sval); temp = cp->cnext; /* avoids freeing then using */ free(cp); tp->nelem--; } tp->tab[i] = 0; } if (tp->nelem != 0) WARNING("can't happen: inconsistent element count freeing %s", ap->nval); free(tp->tab); free(tp); }
Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ { Cell *x, *ap, *k; Node *p; char buf[RECSIZE]; char *s; ap = execute(a[1]); /* array name */ if (!isarr(ap)) { dprintf( ("making %s into an array\n", ap->nval) ); if (freeable(ap)) xfree(ap->sval); ap->tval &= ~(STR|NUM|DONTFREE); ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); } buf[0] = 0; for (p = a[0]; p; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); strcat(buf, s); tempfree(x); if (p->nnext) strcat(buf, *SUBSEP); } k = lookup(buf, (Array *) ap->sval); tempfree(ap); if (k == NULL) return(false); else return(true); }
Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y, *z; char *s; Node *np; char buf[RECSIZE]; x = execute(a[0]); /* Cell* for symbol table */ buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); strcat(buf, s); /* BUG: unchecked! */ if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } if (!isarr(x)) { dprintf( ("making %s into an array\n", x->nval) ); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); z->ctype = OCELL; z->csub = CVAR; tempfree(x); return(z); }
Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y; Node *np; char buf[RECSIZE], *s; x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) return true; if (a[1] == 0) { /* delete the elements, not the table */ freesymtab(x); x->tval &= ~STR; x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } else { buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } freeelem(x, buf); } tempfree(x); return true; }
Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ { Cell *x, *vp, *arrayp, *cp, *ncp; Array *tp; int i; vp = execute(a[0]); arrayp = execute(a[1]); if (!isarr(arrayp)) { return true; } tp = (Array *) arrayp->sval; tempfree(arrayp); for (i = 0; i < tp->size; i++) { /* this routine knows too much */ for (cp = tp->tab[i]; cp != NULL; cp = ncp) { setsval(vp, cp->nval); ncp = cp->cnext; x = execute(a[2]); if (isbreak(x)) { tempfree(vp); return true; } if (isnext(x) || isexit(x) || isret(x)) { tempfree(vp); return(x); } tempfree(x); } } return true; }
void funnyvar(Cell *vp, const char *rw) { if (isarr(vp)) FATAL("can't %s %s; it's an array name.", rw, vp->nval); if (vp->tval & FCN) FATAL("can't %s %s; it's a function.", rw, vp->nval); WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", vp, vp->nval, vp->sval, vp->fval, vp->tval); }
Node *makearr(Node *p) { Cell *cp; if (isvalue(p)) { cp = (Cell *) (p->narg[0]); if (isfcn(cp)) SYNTAX( "%s is a function, not an array", cp->nval ); else if (!isarr(cp)) { xfree(cp->sval); cp->sval = (char *) makesymtab(NSYMTAB); cp->tval = ARR; } } return p; }
void defn(Cell *v, Node *vl, Node *st) /* turn on FCN bit in definition, */ { /* body of function, arglist */ Node *p; int n; if (isarr(v)) { SYNTAX( "`%s' is an array name and a function name", v->nval ); return; } v->tval = FCN; v->sval = (char *) st; n = 0; /* count arguments */ for (p = vl; p; p = p->nnext) n++; v->fval = n; dprintf( ("defining func %s (%d args)\n", v->nval, n) ); }
Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ { Cell *x, *ap, *k; Node *p; char *buf; char *s; int bufsz = recsize; int nsub = strlen(*SUBSEP); ap = execute(a[1]); /* array name */ if (!isarr(ap)) { dprintf( ("making %s into an array\n", ap->nval) ); if (freeable(ap)) xfree(ap->sval); ap->tval &= ~(STR|NUM|DONTFREE); ap->tval |= ARR; ap->sval = (char *) makesymtab(NSYMTAB); } if ((buf = (char *) malloc(bufsz)) == NULL) { FATAL("out of memory in intest"); } buf[0] = 0; for (p = a[0]; p; p = p->nnext) { x = execute(p); /* expr */ s = getsval(x); 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); tempfree(x); if (p->nnext) strcat(buf, *SUBSEP); } k = lookup(buf, (Array *) ap->sval); tempfree(ap); free(buf); if (k == NULL) return(False); else return(True); }
Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y, *z; char *s; Node *np; char *buf; int bufsz = recsize; int nsub = strlen(*SUBSEP); if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in array"); x = execute(a[0]); /* Cell* for symbol table */ buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); 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); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } if (!isarr(x)) { dprintf( ("making %s into an array\n", NN(x->nval)) ); if (freeable(x)) xfree(x->sval); x->tval &= ~(STR|NUM|DONTFREE); x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); z->ctype = OCELL; z->csub = CVAR; tempfree(x); free(buf); return(z); }
Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ { Cell *x, *y; Node *np; uchar buf[RECSIZE], *s; x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) return true; buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } freeelem(x, buf); tempfree(x); return true; }
void freesymtab(Cell *ap) /* free symbol table */ { Cell *cp, *temp; Array *tp; int i; if (!isarr(ap)) return; tp = (Array *) ap->sval; if (tp == NULL) return; for (i = 0; i < tp->size; i++) { for (cp = tp->tab[i]; cp != NULL; cp = temp) { xfree(cp->nval); if (freeable(cp)) xfree(cp->sval); temp = cp->cnext; /* avoids freeing then using */ free((char *) cp); } } free((char *) (tp->tab)); free((char *) tp); }
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); x = execute(a[0]); /* Cell* for symbol table */ if (!isarr(x)) return True; if (a[1] == 0) { /* delete the elements, not the table */ freesymtab(x); x->tval &= ~STR; x->tval |= ARR; x->sval = (char *) makesymtab(NSYMTAB); } else { int bufsz = recsize; char *buf; if ((buf = (char *) malloc(bufsz)) == NULL) FATAL("out of memory in adelete"); buf[0] = 0; for (np = a[1]; np; np = np->nnext) { y = execute(np); /* subscript */ s = getsval(y); 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); if (np->nnext) strcat(buf, *SUBSEP); tempfree(y); } freeelem(x, buf); free(buf); } tempfree(x); return True; }
Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ { static Cell newcopycell = { OCELL, CCOPY, 0, (char *) "", 0.0, NUM|STR|DONTFREE }; int i, ncall, ndef; Node *x; Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; char *s; fcn = execute(a[0]); /* the function itself */ s = fcn->nval; if (!isfunc(fcn)) ERROR "calling undefined function %s", s FATAL; if (frame == NULL) { fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); if (frame == NULL) ERROR "out of space for stack frames calling %s", s FATAL; } for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ ncall++; ndef = (int) fcn->fval; /* args in defn */ dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); if (ncall > ndef) ERROR "function %s called with %d args, uses only %d", s, ncall, ndef WARNING; if (ncall + ndef > NARGS) ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL; for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); y = execute(x); oargs[i] = y; dprintf( ("args[%d]: %s %f <%s>, t=%o\n", i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) ); if (isfunc(y)) ERROR "can't use function %s as argument in %s", y->nval, s FATAL; if (isarr(y)) args[i] = y; /* arrays by ref */ else args[i] = copycell(y); tempfree(y); } for ( ; i < ndef; i++) { /* add null args for ones not provided */ args[i] = gettemp(); *args[i] = newcopycell; } fp++; /* now ok to up frame */ if (fp >= frame + nframe) { int dfp = fp - frame; /* old index */ frame = (struct Frame *) realloc((char *) frame, (nframe += 100) * sizeof(struct Frame)); if (frame == NULL) ERROR "out of space for stack frames in %s", s FATAL; fp = frame + dfp; } fp->fcncell = fcn; fp->args = args; fp->nargs = ndef; /* number defined with (excess are locals) */ fp->retval = gettemp(); dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); y = execute((Node *)(fcn->sval)); /* execute body */ dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); for (i = 0; i < ndef; i++) { Cell *t = fp->args[i]; if (isarr(t)) { if (t->csub == CCOPY) { if (i >= ncall) { freesymtab(t); t->csub = CTEMP; } else { oargs[i]->tval = t->tval; oargs[i]->tval &= ~(STR|NUM|DONTFREE); oargs[i]->sval = t->sval; tempfree(t); } } } else if (t != y) { /* kludge to prevent freeing twice */ t->csub = CTEMP; tempfree(t); } } tempfree(fcn); if (isexit(y) || isnext(y) || isnextfile(y)) return y; tempfree(y); /* this can free twice! */ z = fp->retval; /* return value */ dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); fp--; return(z); }
Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ { Cell *x, *y; Awkfloat u; int t; Awkfloat tmp; char *p, *buf; Node *nextarg; FILE *fp; void flush_all(void); t = ptoi(a[0]); x = execute(a[1]); nextarg = a[1]->nnext; switch (t) { case FLENGTH: if (isarr(x)) u = ((Array *) x->sval)->nelem; /* GROT. should be function*/ else u = strlen(getsval(x)); break; case FLOG: u = errcheck(log(getfval(x)), "log"); break; case FINT: modf(getfval(x), &u); break; case FEXP: u = errcheck(exp(getfval(x)), "exp"); break; case FSQRT: u = errcheck(sqrt(getfval(x)), "sqrt"); break; case FSIN: u = sin(getfval(x)); break; case FCOS: u = cos(getfval(x)); break; case FATAN: if (nextarg == 0) { WARNING("atan2 requires two arguments; returning 1.0"); u = 1.0; } else { y = execute(a[1]->nnext); u = atan2(getfval(x), getfval(y)); tempfree(y); nextarg = nextarg->nnext; } break; case FSYSTEM: fflush(stdout); /* in case something is buffered already */ u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ break; case FRAND: /* in principle, rand() returns something in 0..RAND_MAX */ u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; break; case FSRAND: if (isrec(x)) /* no argument provided */ u = time((time_t *)0); else u = getfval(x); tmp = u; srand((unsigned int) u); u = srand_seed; srand_seed = tmp; break; case FTOUPPER: case FTOLOWER: buf = tostring(getsval(x)); if (t == FTOUPPER) { for (p = buf; *p; p++) if (islower((uschar) *p)) *p = toupper((uschar)*p); } else { for (p = buf; *p; p++) if (isupper((uschar) *p)) *p = tolower((uschar)*p); } tempfree(x); x = gettemp(); setsval(x, buf); free(buf); return x; case FFLUSH: if (isrec(x) || strlen(getsval(x)) == 0) { flush_all(); /* fflush() or fflush("") -> all */ u = 0; } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) u = EOF; else u = fflush(fp); break; default: /* can't happen */ FATAL("illegal function type %d", t); break; } tempfree(x); x = gettemp(); setfval(x, u); if (nextarg != 0) { WARNING("warning: function has too many arguments"); for ( ; nextarg; nextarg = nextarg->nnext) execute(nextarg); } return(x); }