/****************************************************************Copyright (C) Lucent Technologies 1997All Rights Reserved Permission to use, copy, modify, and distribute this software andits documentation for any purpose and without fee is herebygranted, provided that the above copyright notice appear in allcopies and that both that the copyright notice and thispermission notice and warranty disclaimer appear in supportingdocumentation, and that the name Lucent Technologies or any ofits entities not be used in advertising or publicity pertainingto distribution of the software without specific, written priorpermission. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANYSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGESWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHERIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OFTHIS SOFTWARE.****************************************************************/ #include <u.h>#include <libc.h>#include <ctype.h>#include <bio.h>#include "awk.h"#include "y.tab.h" jmp_buf env;extern int pairstack[];extern Awkfloat srand_seed; Node *winner = nil; /* root of parse tree */Cell *tmps; /* free temporary cells for execution */ static Cell truecell ={ OBOOL, BTRUE, NUM, 0, 0, 1.0 };Cell *True = &truecell;static Cell falsecell ={ OBOOL, BFALSE, NUM, 0, 0, 0.0 };Cell *False = &falsecell;static Cell breakcell ={ OJUMP, JBREAK, NUM, 0, 0, 0.0 };Cell *jbreak = &breakcell;static Cell contcell ={ OJUMP, JCONT, NUM, 0, 0, 0.0 };Cell *jcont = &contcell;static Cell nextcell ={ OJUMP, JNEXT, NUM, 0, 0, 0.0 };Cell *jnext = &nextcell;static Cell nextfilecell ={ OJUMP, JNEXTFILE, NUM, 0, 0, 0.0 };Cell *jnextfile = &nextfilecell;static Cell exitcell ={ OJUMP, JEXIT, NUM, 0, 0, 0.0 };Cell *jexit = &exitcell;static Cell retcell ={ OJUMP, JRET, NUM, 0, 0, 0.0 };Cell *jret = &retcell;static Cell tempcell ={ OCELL, CTEMP, NUM|STR|DONTFREE, 0, EMPTY, 0.0 }; Node *curnode = nil; /* the node being executed, for debugging */ intsystem(const char *s){ Waitmsg *status; int pid; if(s == nil) return 1; pid = fork(); if(pid == 0) { execl("/bin/rc", "rc", "-c", s, nil); exits("exec"); } if(pid < 0){ return -1; } for(;;) { status = wait(); if(status == nil) FATAL("Out of memory"); if(status->pid == pid) break; free(status); } if(status->msg[0] != '\0') { free(status); return 1; } free(status); return 0;} /* buffer memory management */int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, char *whatrtn)/* pbuf: address of pointer to buffer being managed * psiz: address of buffer size variable * minlen: minimum length of buffer needed * quantum: buffer size quantum * pbptr: address of movable pointer into buffer, or 0 if none * whatrtn: name of the calling routine if failure should cause fatal error * * return 0 for realloc failure, !=0 for success */{ if (minlen > *psiz) { char *tbuf; int rminlen = quantum ? minlen % quantum : 0; int boff = pbptr ? *pbptr - *pbuf : 0; /* round up to next multiple of quantum */ if (rminlen) minlen += quantum - rminlen; tbuf = (char *) realloc(*pbuf, minlen); if (tbuf == nil) { if (whatrtn) FATAL("out of memory in %s", whatrtn); return 0; } *pbuf = tbuf; *psiz = minlen; if (pbptr) *pbptr = tbuf + boff; } return 1;} void run(Node *a) /* execution of parse tree starts here */{ extern void stdinit(void); stdinit(); execute(a); closeall();} Cell *execute(Node *u) /* execute a node of the parse tree */{ int nobj; Cell *(*proc)(Node **, int); Cell *x; Node *a; if (u == nil) return(True); for (a = u; ; a = a->nnext) { curnode = a; if (isvalue(a)) { x = (Cell *) (a->narg[0]); if (isfld(x) && !donefld) fldbld(); else if (isrec(x) && !donerec) recbld(); return(x); } nobj = a->nobj; if (notlegal(nobj)) /* probably a Cell* but too risky to print */ FATAL("illegal statement"); proc = proctab[nobj-FIRSTTOKEN]; x = (*proc)(a->narg, nobj); if (isfld(x) && !donefld) fldbld(); else if (isrec(x) && !donerec) recbld(); if (isexpr(a)) return(x); if (isjump(x)) return(x); if (a->nnext == nil) return(x); if(istemp(x)) tfree(x); }} Cell *program(Node **a, int) /* execute an awk program */{ /* a[0] = BEGIN, a[1] = body, a[2] = END */ Cell *x; if (setjmp(env) != 0) goto ex; if (a[0]) { /* BEGIN */ x = execute(a[0]); if (isexit(x)) return(True); if (isjump(x)) FATAL("illegal break, continue, next or nextfile from BEGIN"); if (istemp(x)) tfree(x); } if (a[1] || a[2]) while (getrec(&record, &recsize, 1) > 0) { x = execute(a[1]); if (isexit(x)) break; if (istemp(x)) tfree(x); } ex: if (setjmp(env) != 0) /* handles exit within END */ goto ex1; if (a[2]) { /* END */ x = execute(a[2]); if (isbreak(x) || isnext(x) || iscont(x)) FATAL("illegal break, continue, next or nextfile from END"); if (istemp(x)) tfree(x); } ex1: return(True);} struct Frame { /* stack frame for awk function calls */ int nargs; /* number of arguments in this call */ Cell *fcncell; /* pointer to Cell for function */ Cell **args; /* pointer to array of arguments after execute */ Cell *retval; /* return value */}; #define NARGS 50 /* max args in a call */ struct Frame *fp = nil; /* frame pointer. bottom level unused */ Cell *call(Node **a, int) /* function call. very kludgy and fragile */{ static Cell newcopycell = { OCELL, CCOPY, NUM|STR|DONTFREE, 0, EMPTY, 0.0 }; int i, ncall, ndef; Node *x; Cell *args[NARGS], **oargs; Cell *y, *z, *fcn; struct Frame frame, *up; char *s; fcn = execute(a[0]); /* the function itself */ s = fcn->nval; if (!isfcn(fcn)) FATAL("calling undefined function %s", s); for (ncall = 0, x = a[1]; x != nil; x = x->nnext) /* args in call */ ncall++; ndef = (int) fcn->fval; /* args in defn */ dprint( ("calling %s, %d args (%d in defn)\n", s, ncall, ndef) ); if (ncall > ndef) { WARNING("function %s called with %d args, uses only %d", s, ncall, ndef); ncall = ndef; } if (ndef+ncall > NARGS) FATAL("function %s has %d arguments, limit %d", s, ndef+ncall, NARGS); oargs = args+ndef; for (i = 0, x = a[1]; i < ncall && x != nil; i++, x = x->nnext) { /* get call args */ dprint( ("evaluate args[%d]:\n", i) ); y = execute(x); dprint( ("args[%d]: %s %f <%s>, t=%o\n", i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) ); if (isfcn(y)) FATAL("can't use function %s as argument in %s", y->nval, s); if (isarr(y)) { args[i] = y; /* arrays by ref */ y = nil; } else if (istemp(y)) { y->csub = CCOPY; args[i] = y; } else args[i] = copycell(y); oargs[i] = y; /* potential output arg for arrays */ } for ( ; i < ndef; i++) { /* add null args for ones not provided */ args[i] = gettemp(); *args[i] = newcopycell; } /* now ok to up frame */ up = fp; fp = &frame; fp->fcncell = fcn; fp->args = args; fp->nargs = ndef; /* number defined with (excess are locals) */ fp->retval = gettemp(); dprint( ("start exec of %s\n", s) ); y = execute((Node *)(fcn->sval)); /* execute body */ dprint( ("finished exec of %s\n", s) ); for (i = 0; i < ndef; i++) { Cell *t = args[i]; if (isarr(t)) { if (t->csub == CCOPY) { if (i >= ncall) { freesymtab(t); tfree(t); } else if(oargs[i] != nil) { oargs[i]->tval = t->tval; oargs[i]->tval &= ~(STR|NUM|DONTFREE); oargs[i]->sval = t->sval; } } } else if (t != y) /* kludge to prevent freeing twice */ tfree(t); } if (istemp(fcn)) tfree(fcn); if (isexit(y) || isnext(y) || isnextfile(y)) return y; if (istemp(y)) tfree(y); /* this can free twice! */ z = fp->retval; /* return value */ dprint( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); fp = up; return(z);} Cell *copycell(Cell *x) /* make a copy of a cell in a temp */{ Cell *y; y = gettemp(); y->csub = CCOPY; /* prevents freeing until call is over */ y->nval = x->nval; /* BUG? */ y->sval = x->sval != nil && *x->sval ? tostring(x->sval) : EMPTY; y->fval = x->fval; y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ if (y->sval == EMPTY) y->tval |= DONTFREE; return y;} Cell *arg(Node **a, int n) /* nth argument of a function */{ n = ptoi(a[0]); /* argument number, counting from 0 */ dprint( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); if (n >= fp->nargs) FATAL("argument #%d of function %s was not supplied", n+1, fp->fcncell->nval); return fp->args[n];} Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */{ Cell *y; switch (n) { case EXIT: if (a[0] != nil) { y = execute(a[0]); if ((y->tval & (NUM|STR)) == STR) { exitstatus = getsval(y); } else if((int) getfval(y) != 0) { exitstatus = "error"; } } longjmp(env, 1); case RETURN: if (a[0] != nil) { y = execute(a[0]); if ((y->tval & (STR|NUM)) == (STR|NUM)) { setsval(fp->retval, getsval(y)); fp->retval->fval = getfval(y); fp->retval->tval |= NUM; } else if (y->tval & STR) setsval(fp->retval, getsval(y)); else if (y->tval & NUM) setfval(fp->retval, getfval(y)); else /* can't happen */ FATAL("bad type variable %d", y->tval); if (istemp(y)) tfree(y); } return(jret); case NEXT: return(jnext); case NEXTFILE: nextfile(); return(jnextfile); case BREAK: return(jbreak); case CONTINUE: return(jcont); default: /* can't happen */ FATAL("illegal jump type %d", n); } return 0; /* not reached */} Cell *getline(Node **a, int n) /* get next line from specific input */{ /* a[0] is variable, a[1] is operator, a[2] is filename */ Cell *r, *x; extern Cell **fldtab; Biobuf *fp; char *buf; int bufsize = recsize; int mode; if ((buf = (char *) malloc(bufsize)) == nil) FATAL("out of memory in getline"); Bflush(&stdout); /* in case someone is waiting for a prompt */ r = gettemp(); if (a[1] != nil) { /* getline < file */ x = execute(a[2]); /* filename */ mode = ptoi(a[1]); if (mode == '|') /* input pipe */ mode = LE; /* arbitrary flag */ fp = openfile(mode, getsval(x)); if (istemp(x)) tfree(x); if (fp == nil) n = -1; else n = readrec(&buf, &bufsize, fp); if (n <= 0) { ; } else if (a[0] != nil) { /* getline var <file */ x = execute(a[0]); setsval(x, buf); if (istemp(x)) tfree(x); } else { /* getline <file */ setsval(fldtab[0], buf); if (to_number(fldtab[0]->sval, &fldtab[0]->fval, nil)) fldtab[0]->tval |= NUM; } } else { /* bare getline; use current input */ if (a[0] == nil) /* getline */ n = getrec(&record, &recsize, 1); else { /* getline var */ n = getrec(&buf, &bufsize, 0); if (n > 0) { x = execute(a[0]); setsval(x, buf); if (istemp(x)) tfree(x); } } } setfval(r, (Awkfloat) n); free(buf); return r;} Cell *getnf(Node **a, int) /* get NF */{ if (donefld == 0) fldbld(); return (Cell *) a[0];} Cell *array(Node **a, int) /* 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)) == nil) 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, 0)) FATAL("out of memory for %s[%s...]", x->nval, buf); strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); if (istemp(y)) tfree(y); } if (!isarr(x)) { dprint( ("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, EMPTY, 0.0, STR|NUM, (Array *) x->sval); z->ctype = OCELL; z->csub = CVAR; if (istemp(x)) tfree(x); free(buf); return(z);} Cell *awkdelete(Node **a, int) /* 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);Lines 1–500 of 2011. Load more
/**************************************************************** Copyright (C) Lucent Technologies 1997 All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name Lucent Technologies or any of its entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ #include <u.h> #include <libc.h> #include <ctype.h> #include <bio.h> #include "awk.h" #include "y.tab.h" jmp_buf env; extern int pairstack[]; extern Awkfloat srand_seed; Node *winner = nil; /* root of parse tree */ Cell *tmps; /* free temporary cells for execution */ static Cell truecell ={ OBOOL, BTRUE, NUM, 0, 0, 1.0 }; Cell *True = &truecell; static Cell falsecell ={ OBOOL, BFALSE, NUM, 0, 0, 0.0 }; Cell *False = &falsecell; static Cell breakcell ={ OJUMP, JBREAK, NUM, 0, 0, 0.0 }; Cell *jbreak = &breakcell; static Cell contcell ={ OJUMP, JCONT, NUM, 0, 0, 0.0 }; Cell *jcont = &contcell; static Cell nextcell ={ OJUMP, JNEXT, NUM, 0, 0, 0.0 }; Cell *jnext = &nextcell; static Cell nextfilecell ={ OJUMP, JNEXTFILE, NUM, 0, 0, 0.0 }; Cell *jnextfile = &nextfilecell; static Cell exitcell ={ OJUMP, JEXIT, NUM, 0, 0, 0.0 }; Cell *jexit = &exitcell; static Cell retcell ={ OJUMP, JRET, NUM, 0, 0, 0.0 }; Cell *jret = &retcell; static Cell tempcell ={ OCELL, CTEMP, NUM|STR|DONTFREE, 0, EMPTY, 0.0 }; Node *curnode = nil; /* the node being executed, for debugging */ int system(const char *s) { Waitmsg *status; int pid; if(s == nil) return 1; pid = fork(); if(pid == 0) { execl("/bin/rc", "rc", "-c", s, nil); exits("exec"); } if(pid < 0){ return -1; } for(;;) { status = wait(); if(status == nil) FATAL("Out of memory"); if(status->pid == pid) break; free(status); } if(status->msg[0] != '\0') { free(status); return 1; } free(status); return 0; } /* buffer memory management */ int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, char *whatrtn) /* pbuf: address of pointer to buffer being managed * psiz: address of buffer size variable * minlen: minimum length of buffer needed * quantum: buffer size quantum * pbptr: address of movable pointer into buffer, or 0 if none * whatrtn: name of the calling routine if failure should cause fatal error * * return 0 for realloc failure, !=0 for success */ { if (minlen > *psiz) { char *tbuf; int rminlen = quantum ? minlen % quantum : 0; int boff = pbptr ? *pbptr - *pbuf : 0; /* round up to next multiple of quantum */ if (rminlen) minlen += quantum - rminlen; tbuf = (char *) realloc(*pbuf, minlen); if (tbuf == nil) { if (whatrtn) FATAL("out of memory in %s", whatrtn); return 0; } *pbuf = tbuf; *psiz = minlen; if (pbptr) *pbptr = tbuf + boff; } return 1; } void run(Node *a) /* execution of parse tree starts here */ { extern void stdinit(void); stdinit(); execute(a); closeall(); } Cell *execute(Node *u) /* execute a node of the parse tree */ { int nobj; Cell *(*proc)(Node **, int); Cell *x; Node *a; if (u == nil) return(True); for (a = u; ; a = a->nnext) { curnode = a; if (isvalue(a)) { x = (Cell *) (a->narg[0]); if (isfld(x) && !donefld) fldbld(); else if (isrec(x) && !donerec) recbld(); return(x); } nobj = a->nobj; if (notlegal(nobj)) /* probably a Cell* but too risky to print */ FATAL("illegal statement"); proc = proctab[nobj-FIRSTTOKEN]; x = (*proc)(a->narg, nobj); if (isfld(x) && !donefld) fldbld(); else if (isrec(x) && !donerec) recbld(); if (isexpr(a)) return(x); if (isjump(x)) return(x); if (a->nnext == nil) return(x); if(istemp(x)) tfree(x); } } Cell *program(Node **a, int) /* execute an awk program */ { /* a[0] = BEGIN, a[1] = body, a[2] = END */ Cell *x; if (setjmp(env) != 0) goto ex; if (a[0]) { /* BEGIN */ x = execute(a[0]); if (isexit(x)) return(True); if (isjump(x)) FATAL("illegal break, continue, next or nextfile from BEGIN"); if (istemp(x)) tfree(x); } if (a[1] || a[2]) while (getrec(&record, &recsize, 1) > 0) { x = execute(a[1]); if (isexit(x)) break; if (istemp(x)) tfree(x); } ex: if (setjmp(env) != 0) /* handles exit within END */ goto ex1; if (a[2]) { /* END */ x = execute(a[2]); if (isbreak(x) || isnext(x) || iscont(x)) FATAL("illegal break, continue, next or nextfile from END"); if (istemp(x)) tfree(x); } ex1: return(True); } struct Frame { /* stack frame for awk function calls */ int nargs; /* number of arguments in this call */ Cell *fcncell; /* pointer to Cell for function */ Cell **args; /* pointer to array of arguments after execute */ Cell *retval; /* return value */ }; #define NARGS 50 /* max args in a call */ struct Frame *fp = nil; /* frame pointer. bottom level unused */ Cell *call(Node **a, int) /* function call. very kludgy and fragile */ { static Cell newcopycell = { OCELL, CCOPY, NUM|STR|DONTFREE, 0, EMPTY, 0.0 }; int i, ncall, ndef; Node *x; Cell *args[NARGS], **oargs; Cell *y, *z, *fcn; struct Frame frame, *up; char *s; fcn = execute(a[0]); /* the function itself */ s = fcn->nval; if (!isfcn(fcn)) FATAL("calling undefined function %s", s); for (ncall = 0, x = a[1]; x != nil; x = x->nnext) /* args in call */ ncall++; ndef = (int) fcn->fval; /* args in defn */ dprint( ("calling %s, %d args (%d in defn)\n", s, ncall, ndef) ); if (ncall > ndef) { WARNING("function %s called with %d args, uses only %d", s, ncall, ndef); ncall = ndef; } if (ndef+ncall > NARGS) FATAL("function %s has %d arguments, limit %d", s, ndef+ncall, NARGS); oargs = args+ndef; for (i = 0, x = a[1]; i < ncall && x != nil; i++, x = x->nnext) { /* get call args */ dprint( ("evaluate args[%d]:\n", i) ); y = execute(x); dprint( ("args[%d]: %s %f <%s>, t=%o\n", i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) ); if (isfcn(y)) FATAL("can't use function %s as argument in %s", y->nval, s); if (isarr(y)) { args[i] = y; /* arrays by ref */ y = nil; } else if (istemp(y)) { y->csub = CCOPY; args[i] = y; } else args[i] = copycell(y); oargs[i] = y; /* potential output arg for arrays */ } for ( ; i < ndef; i++) { /* add null args for ones not provided */ args[i] = gettemp(); *args[i] = newcopycell; } /* now ok to up frame */ up = fp; fp = &frame; fp->fcncell = fcn; fp->args = args; fp->nargs = ndef; /* number defined with (excess are locals) */ fp->retval = gettemp(); dprint( ("start exec of %s\n", s) ); y = execute((Node *)(fcn->sval)); /* execute body */ dprint( ("finished exec of %s\n", s) ); for (i = 0; i < ndef; i++) { Cell *t = args[i]; if (isarr(t)) { if (t->csub == CCOPY) { if (i >= ncall) { freesymtab(t); tfree(t); } else if(oargs[i] != nil) { oargs[i]->tval = t->tval; oargs[i]->tval &= ~(STR|NUM|DONTFREE); oargs[i]->sval = t->sval; } } } else if (t != y) /* kludge to prevent freeing twice */ tfree(t); } if (istemp(fcn)) tfree(fcn); if (isexit(y) || isnext(y) || isnextfile(y)) return y; if (istemp(y)) tfree(y); /* this can free twice! */ z = fp->retval; /* return value */ dprint( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); fp = up; return(z); } Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ { Cell *y; y = gettemp(); y->csub = CCOPY; /* prevents freeing until call is over */ y->nval = x->nval; /* BUG? */ y->sval = x->sval != nil && *x->sval ? tostring(x->sval) : EMPTY; y->fval = x->fval; y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ if (y->sval == EMPTY) y->tval |= DONTFREE; return y; } Cell *arg(Node **a, int n) /* nth argument of a function */ { n = ptoi(a[0]); /* argument number, counting from 0 */ dprint( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); if (n >= fp->nargs) FATAL("argument #%d of function %s was not supplied", n+1, fp->fcncell->nval); return fp->args[n]; } Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ { Cell *y; switch (n) { case EXIT: if (a[0] != nil) { y = execute(a[0]); if ((y->tval & (NUM|STR)) == STR) { exitstatus = getsval(y); } else if((int) getfval(y) != 0) { exitstatus = "error"; } } longjmp(env, 1); case RETURN: if (a[0] != nil) { y = execute(a[0]); if ((y->tval & (STR|NUM)) == (STR|NUM)) { setsval(fp->retval, getsval(y)); fp->retval->fval = getfval(y); fp->retval->tval |= NUM; } else if (y->tval & STR) setsval(fp->retval, getsval(y)); else if (y->tval & NUM) setfval(fp->retval, getfval(y)); else /* can't happen */ FATAL("bad type variable %d", y->tval); if (istemp(y)) tfree(y); } return(jret); case NEXT: return(jnext); case NEXTFILE: nextfile(); return(jnextfile); case BREAK: return(jbreak); case CONTINUE: return(jcont); default: /* can't happen */ FATAL("illegal jump type %d", n); } return 0; /* not reached */ } Cell *getline(Node **a, int n) /* get next line from specific input */ { /* a[0] is variable, a[1] is operator, a[2] is filename */ Cell *r, *x; extern Cell **fldtab; Biobuf *fp; char *buf; int bufsize = recsize; int mode; if ((buf = (char *) malloc(bufsize)) == nil) FATAL("out of memory in getline"); Bflush(&stdout); /* in case someone is waiting for a prompt */ r = gettemp(); if (a[1] != nil) { /* getline < file */ x = execute(a[2]); /* filename */ mode = ptoi(a[1]); if (mode == '|') /* input pipe */ mode = LE; /* arbitrary flag */ fp = openfile(mode, getsval(x)); if (istemp(x)) tfree(x); if (fp == nil) n = -1; else n = readrec(&buf, &bufsize, fp); if (n <= 0) { ; } else if (a[0] != nil) { /* getline var <file */ x = execute(a[0]); setsval(x, buf); if (istemp(x)) tfree(x); } else { /* getline <file */ setsval(fldtab[0], buf); if (to_number(fldtab[0]->sval, &fldtab[0]->fval, nil)) fldtab[0]->tval |= NUM; } } else { /* bare getline; use current input */ if (a[0] == nil) /* getline */ n = getrec(&record, &recsize, 1); else { /* getline var */ n = getrec(&buf, &bufsize, 0); if (n > 0) { x = execute(a[0]); setsval(x, buf); if (istemp(x)) tfree(x); } } } setfval(r, (Awkfloat) n); free(buf); return r; } Cell *getnf(Node **a, int) /* get NF */ { if (donefld == 0) fldbld(); return (Cell *) a[0]; } Cell *array(Node **a, int) /* 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)) == nil) 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, 0)) FATAL("out of memory for %s[%s...]", x->nval, buf); strcat(buf, s); if (np->nnext) strcat(buf, *SUBSEP); if (istemp(y)) tfree(y); } if (!isarr(x)) { dprint( ("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, EMPTY, 0.0, STR|NUM, (Array *) x->sval); z->ctype = OCELL; z->csub = CVAR; if (istemp(x)) tfree(x); free(buf); return(z); } Cell *awkdelete(Node **a, int) /* 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);