17dd7cddfSDavid du Colombier /**************************************************************** 27dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997 33e12c5d1SDavid du Colombier All Rights Reserved 43e12c5d1SDavid du Colombier 57dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and 67dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby 77dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all 87dd7cddfSDavid du Colombier copies and that both that the copyright notice and this 97dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting 107dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of 117dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining 127dd7cddfSDavid du Colombier to distribution of the software without specific, written prior 137dd7cddfSDavid du Colombier permission. 143e12c5d1SDavid du Colombier 157dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 167dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 177dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 187dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 197dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 207dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 217dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 227dd7cddfSDavid du Colombier THIS SOFTWARE. 237dd7cddfSDavid du Colombier ****************************************************************/ 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier #define DEBUG 263e12c5d1SDavid du Colombier #include <stdio.h> 273e12c5d1SDavid du Colombier #include <ctype.h> 283e12c5d1SDavid du Colombier #include <setjmp.h> 293e12c5d1SDavid du Colombier #include <math.h> 303e12c5d1SDavid du Colombier #include <string.h> 313e12c5d1SDavid du Colombier #include <stdlib.h> 323e12c5d1SDavid du Colombier #include <time.h> 333e12c5d1SDavid du Colombier #include "awk.h" 343e12c5d1SDavid du Colombier #include "y.tab.h" 353e12c5d1SDavid du Colombier 367dd7cddfSDavid du Colombier #define tempfree(x) if (istemp(x)) tfree(x); else 377dd7cddfSDavid du Colombier 387dd7cddfSDavid du Colombier /* 397dd7cddfSDavid du Colombier #undef tempfree 407dd7cddfSDavid du Colombier 417dd7cddfSDavid du Colombier void tempfree(Cell *p) { 427dd7cddfSDavid du Colombier if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) { 437dd7cddfSDavid du Colombier WARNING("bad csub %d in Cell %d %s", 447dd7cddfSDavid du Colombier p->csub, p->ctype, p->sval); 457dd7cddfSDavid du Colombier } 467dd7cddfSDavid du Colombier if (istemp(p)) 477dd7cddfSDavid du Colombier tfree(p); 487dd7cddfSDavid du Colombier } 497dd7cddfSDavid du Colombier */ 507dd7cddfSDavid du Colombier 513e12c5d1SDavid du Colombier #ifdef _NFILE 523e12c5d1SDavid du Colombier #ifndef FOPEN_MAX 533e12c5d1SDavid du Colombier #define FOPEN_MAX _NFILE 543e12c5d1SDavid du Colombier #endif 553e12c5d1SDavid du Colombier #endif 563e12c5d1SDavid du Colombier 573e12c5d1SDavid du Colombier #ifndef FOPEN_MAX 583e12c5d1SDavid du Colombier #define FOPEN_MAX 40 /* max number of open files */ 593e12c5d1SDavid du Colombier #endif 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier #ifndef RAND_MAX 623e12c5d1SDavid du Colombier #define RAND_MAX 32767 /* all that ansi guarantees */ 633e12c5d1SDavid du Colombier #endif 643e12c5d1SDavid du Colombier 653e12c5d1SDavid du Colombier jmp_buf env; 667dd7cddfSDavid du Colombier extern int pairstack[]; 67219b2ee8SDavid du Colombier 68219b2ee8SDavid du Colombier Node *winner = NULL; /* root of parse tree */ 69219b2ee8SDavid du Colombier Cell *tmps; /* free temporary cells for execution */ 703e12c5d1SDavid du Colombier 713e12c5d1SDavid du Colombier static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM }; 727dd7cddfSDavid du Colombier Cell *True = &truecell; 733e12c5d1SDavid du Colombier static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM }; 747dd7cddfSDavid du Colombier Cell *False = &falsecell; 753e12c5d1SDavid du Colombier static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM }; 763e12c5d1SDavid du Colombier Cell *jbreak = &breakcell; 773e12c5d1SDavid du Colombier static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM }; 783e12c5d1SDavid du Colombier Cell *jcont = &contcell; 793e12c5d1SDavid du Colombier static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM }; 803e12c5d1SDavid du Colombier Cell *jnext = &nextcell; 817dd7cddfSDavid du Colombier static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM }; 827dd7cddfSDavid du Colombier Cell *jnextfile = &nextfilecell; 833e12c5d1SDavid du Colombier static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; 843e12c5d1SDavid du Colombier Cell *jexit = &exitcell; 853e12c5d1SDavid du Colombier static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; 863e12c5d1SDavid du Colombier Cell *jret = &retcell; 877dd7cddfSDavid du Colombier static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE }; 883e12c5d1SDavid du Colombier 893e12c5d1SDavid du Colombier Node *curnode = NULL; /* the node being executed, for debugging */ 903e12c5d1SDavid du Colombier 917dd7cddfSDavid du Colombier /* buffer memory management */ 927dd7cddfSDavid du Colombier int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr, 937dd7cddfSDavid du Colombier char *whatrtn) 947dd7cddfSDavid du Colombier /* pbuf: address of pointer to buffer being managed 957dd7cddfSDavid du Colombier * psiz: address of buffer size variable 967dd7cddfSDavid du Colombier * minlen: minimum length of buffer needed 977dd7cddfSDavid du Colombier * quantum: buffer size quantum 987dd7cddfSDavid du Colombier * pbptr: address of movable pointer into buffer, or 0 if none 997dd7cddfSDavid du Colombier * whatrtn: name of the calling routine if failure should cause fatal error 1007dd7cddfSDavid du Colombier * 1017dd7cddfSDavid du Colombier * return 0 for realloc failure, !=0 for success 1027dd7cddfSDavid du Colombier */ 1037dd7cddfSDavid du Colombier { 1047dd7cddfSDavid du Colombier if (minlen > *psiz) { 1057dd7cddfSDavid du Colombier char *tbuf; 1067dd7cddfSDavid du Colombier int rminlen = quantum ? minlen % quantum : 0; 1077dd7cddfSDavid du Colombier int boff = pbptr ? *pbptr - *pbuf : 0; 1087dd7cddfSDavid du Colombier /* round up to next multiple of quantum */ 1097dd7cddfSDavid du Colombier if (rminlen) 1107dd7cddfSDavid du Colombier minlen += quantum - rminlen; 1117dd7cddfSDavid du Colombier tbuf = (char *) realloc(*pbuf, minlen); 1127dd7cddfSDavid du Colombier if (tbuf == NULL) { 1137dd7cddfSDavid du Colombier if (whatrtn) 1147dd7cddfSDavid du Colombier FATAL("out of memory in %s", whatrtn); 1157dd7cddfSDavid du Colombier return 0; 1167dd7cddfSDavid du Colombier } 1177dd7cddfSDavid du Colombier *pbuf = tbuf; 1187dd7cddfSDavid du Colombier *psiz = minlen; 1197dd7cddfSDavid du Colombier if (pbptr) 1207dd7cddfSDavid du Colombier *pbptr = tbuf + boff; 1217dd7cddfSDavid du Colombier } 1227dd7cddfSDavid du Colombier return 1; 1237dd7cddfSDavid du Colombier } 1247dd7cddfSDavid du Colombier 125219b2ee8SDavid du Colombier void run(Node *a) /* execution of parse tree starts here */ 1263e12c5d1SDavid du Colombier { 1277dd7cddfSDavid du Colombier extern void stdinit(void); 1287dd7cddfSDavid du Colombier 1297dd7cddfSDavid du Colombier stdinit(); 1303e12c5d1SDavid du Colombier execute(a); 1313e12c5d1SDavid du Colombier closeall(); 1323e12c5d1SDavid du Colombier } 1333e12c5d1SDavid du Colombier 1347dd7cddfSDavid du Colombier Cell *execute(Node *u) /* execute a node of the parse tree */ 1353e12c5d1SDavid du Colombier { 136*05bfb676SDavid du Colombier int nobj; 1377dd7cddfSDavid du Colombier Cell *(*proc)(Node **, int); 1387dd7cddfSDavid du Colombier Cell *x; 1397dd7cddfSDavid du Colombier Node *a; 1403e12c5d1SDavid du Colombier 1413e12c5d1SDavid du Colombier if (u == NULL) 1427dd7cddfSDavid du Colombier return(True); 1433e12c5d1SDavid du Colombier for (a = u; ; a = a->nnext) { 1443e12c5d1SDavid du Colombier curnode = a; 1453e12c5d1SDavid du Colombier if (isvalue(a)) { 1463e12c5d1SDavid du Colombier x = (Cell *) (a->narg[0]); 1477dd7cddfSDavid du Colombier if (isfld(x) && !donefld) 1483e12c5d1SDavid du Colombier fldbld(); 1497dd7cddfSDavid du Colombier else if (isrec(x) && !donerec) 1503e12c5d1SDavid du Colombier recbld(); 1513e12c5d1SDavid du Colombier return(x); 1523e12c5d1SDavid du Colombier } 153*05bfb676SDavid du Colombier nobj = a->nobj; 154*05bfb676SDavid du Colombier if (notlegal(nobj)) /* probably a Cell* but too risky to print */ 1557dd7cddfSDavid du Colombier FATAL("illegal statement"); 156*05bfb676SDavid du Colombier proc = proctab[nobj-FIRSTTOKEN]; 157*05bfb676SDavid du Colombier x = (*proc)(a->narg, nobj); 1587dd7cddfSDavid du Colombier if (isfld(x) && !donefld) 1593e12c5d1SDavid du Colombier fldbld(); 1607dd7cddfSDavid du Colombier else if (isrec(x) && !donerec) 1613e12c5d1SDavid du Colombier recbld(); 1623e12c5d1SDavid du Colombier if (isexpr(a)) 1633e12c5d1SDavid du Colombier return(x); 1643e12c5d1SDavid du Colombier if (isjump(x)) 1653e12c5d1SDavid du Colombier return(x); 1663e12c5d1SDavid du Colombier if (a->nnext == NULL) 1673e12c5d1SDavid du Colombier return(x); 1683e12c5d1SDavid du Colombier tempfree(x); 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier } 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier 173219b2ee8SDavid du Colombier Cell *program(Node **a, int n) /* execute an awk program */ 174219b2ee8SDavid du Colombier { /* a[0] = BEGIN, a[1] = body, a[2] = END */ 1757dd7cddfSDavid du Colombier Cell *x; 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier if (setjmp(env) != 0) 1783e12c5d1SDavid du Colombier goto ex; 1793e12c5d1SDavid du Colombier if (a[0]) { /* BEGIN */ 1803e12c5d1SDavid du Colombier x = execute(a[0]); 1813e12c5d1SDavid du Colombier if (isexit(x)) 1827dd7cddfSDavid du Colombier return(True); 1833e12c5d1SDavid du Colombier if (isjump(x)) 1847dd7cddfSDavid du Colombier FATAL("illegal break, continue, next or nextfile from BEGIN"); 1853e12c5d1SDavid du Colombier tempfree(x); 1863e12c5d1SDavid du Colombier } 1873e12c5d1SDavid du Colombier if (a[1] || a[2]) 1887dd7cddfSDavid du Colombier while (getrec(&record, &recsize, 1) > 0) { 1893e12c5d1SDavid du Colombier x = execute(a[1]); 1903e12c5d1SDavid du Colombier if (isexit(x)) 1913e12c5d1SDavid du Colombier break; 1923e12c5d1SDavid du Colombier tempfree(x); 1933e12c5d1SDavid du Colombier } 1943e12c5d1SDavid du Colombier ex: 1953e12c5d1SDavid du Colombier if (setjmp(env) != 0) /* handles exit within END */ 1963e12c5d1SDavid du Colombier goto ex1; 1973e12c5d1SDavid du Colombier if (a[2]) { /* END */ 1983e12c5d1SDavid du Colombier x = execute(a[2]); 1993e12c5d1SDavid du Colombier if (isbreak(x) || isnext(x) || iscont(x)) 2007dd7cddfSDavid du Colombier FATAL("illegal break, continue, next or nextfile from END"); 2013e12c5d1SDavid du Colombier tempfree(x); 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier ex1: 2047dd7cddfSDavid du Colombier return(True); 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier 207219b2ee8SDavid du Colombier struct Frame { /* stack frame for awk function calls */ 2083e12c5d1SDavid du Colombier int nargs; /* number of arguments in this call */ 2093e12c5d1SDavid du Colombier Cell *fcncell; /* pointer to Cell for function */ 2103e12c5d1SDavid du Colombier Cell **args; /* pointer to array of arguments after execute */ 2113e12c5d1SDavid du Colombier Cell *retval; /* return value */ 2123e12c5d1SDavid du Colombier }; 2133e12c5d1SDavid du Colombier 214219b2ee8SDavid du Colombier #define NARGS 50 /* max args in a call */ 2153e12c5d1SDavid du Colombier 2163e12c5d1SDavid du Colombier struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ 2173e12c5d1SDavid du Colombier int nframe = 0; /* number of frames allocated */ 2183e12c5d1SDavid du Colombier struct Frame *fp = NULL; /* frame pointer. bottom level unused */ 2193e12c5d1SDavid du Colombier 220219b2ee8SDavid du Colombier Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ 2213e12c5d1SDavid du Colombier { 2227dd7cddfSDavid du Colombier static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE }; 2233e12c5d1SDavid du Colombier int i, ncall, ndef; 2243e12c5d1SDavid du Colombier Node *x; 2257dd7cddfSDavid du Colombier Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */ 2267dd7cddfSDavid du Colombier Cell *y, *z, *fcn; 2277dd7cddfSDavid du Colombier char *s; 2283e12c5d1SDavid du Colombier 2293e12c5d1SDavid du Colombier fcn = execute(a[0]); /* the function itself */ 2303e12c5d1SDavid du Colombier s = fcn->nval; 2317dd7cddfSDavid du Colombier if (!isfcn(fcn)) 2327dd7cddfSDavid du Colombier FATAL("calling undefined function %s", s); 2333e12c5d1SDavid du Colombier if (frame == NULL) { 2343e12c5d1SDavid du Colombier fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); 2353e12c5d1SDavid du Colombier if (frame == NULL) 2367dd7cddfSDavid du Colombier FATAL("out of space for stack frames calling %s", s); 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 2393e12c5d1SDavid du Colombier ncall++; 2403e12c5d1SDavid du Colombier ndef = (int) fcn->fval; /* args in defn */ 2417dd7cddfSDavid du Colombier dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) ); 2423e12c5d1SDavid du Colombier if (ncall > ndef) 2437dd7cddfSDavid du Colombier WARNING("function %s called with %d args, uses only %d", 2447dd7cddfSDavid du Colombier s, ncall, ndef); 2453e12c5d1SDavid du Colombier if (ncall + ndef > NARGS) 2467dd7cddfSDavid du Colombier FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS); 2473e12c5d1SDavid du Colombier for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ 2487dd7cddfSDavid du Colombier dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) ); 2493e12c5d1SDavid du Colombier y = execute(x); 2503e12c5d1SDavid du Colombier oargs[i] = y; 2513e12c5d1SDavid du Colombier dprintf( ("args[%d]: %s %f <%s>, t=%o\n", 2527dd7cddfSDavid du Colombier i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) ); 2537dd7cddfSDavid du Colombier if (isfcn(y)) 2547dd7cddfSDavid du Colombier FATAL("can't use function %s as argument in %s", y->nval, s); 2553e12c5d1SDavid du Colombier if (isarr(y)) 2563e12c5d1SDavid du Colombier args[i] = y; /* arrays by ref */ 2573e12c5d1SDavid du Colombier else 2583e12c5d1SDavid du Colombier args[i] = copycell(y); 2593e12c5d1SDavid du Colombier tempfree(y); 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier for ( ; i < ndef; i++) { /* add null args for ones not provided */ 2623e12c5d1SDavid du Colombier args[i] = gettemp(); 2633e12c5d1SDavid du Colombier *args[i] = newcopycell; 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier fp++; /* now ok to up frame */ 2663e12c5d1SDavid du Colombier if (fp >= frame + nframe) { 2673e12c5d1SDavid du Colombier int dfp = fp - frame; /* old index */ 2683e12c5d1SDavid du Colombier frame = (struct Frame *) 269219b2ee8SDavid du Colombier realloc((char *) frame, (nframe += 100) * sizeof(struct Frame)); 2703e12c5d1SDavid du Colombier if (frame == NULL) 2717dd7cddfSDavid du Colombier FATAL("out of space for stack frames in %s", s); 2723e12c5d1SDavid du Colombier fp = frame + dfp; 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier fp->fcncell = fcn; 2753e12c5d1SDavid du Colombier fp->args = args; 2763e12c5d1SDavid du Colombier fp->nargs = ndef; /* number defined with (excess are locals) */ 2773e12c5d1SDavid du Colombier fp->retval = gettemp(); 2783e12c5d1SDavid du Colombier 2797dd7cddfSDavid du Colombier dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) ); 2803e12c5d1SDavid du Colombier y = execute((Node *)(fcn->sval)); /* execute body */ 2817dd7cddfSDavid du Colombier dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) ); 2823e12c5d1SDavid du Colombier 2833e12c5d1SDavid du Colombier for (i = 0; i < ndef; i++) { 2843e12c5d1SDavid du Colombier Cell *t = fp->args[i]; 2853e12c5d1SDavid du Colombier if (isarr(t)) { 2863e12c5d1SDavid du Colombier if (t->csub == CCOPY) { 2873e12c5d1SDavid du Colombier if (i >= ncall) { 2883e12c5d1SDavid du Colombier freesymtab(t); 2893e12c5d1SDavid du Colombier t->csub = CTEMP; 2907dd7cddfSDavid du Colombier tempfree(t); 2913e12c5d1SDavid du Colombier } else { 2923e12c5d1SDavid du Colombier oargs[i]->tval = t->tval; 2933e12c5d1SDavid du Colombier oargs[i]->tval &= ~(STR|NUM|DONTFREE); 2943e12c5d1SDavid du Colombier oargs[i]->sval = t->sval; 2953e12c5d1SDavid du Colombier tempfree(t); 2963e12c5d1SDavid du Colombier } 2973e12c5d1SDavid du Colombier } 2983e12c5d1SDavid du Colombier } else if (t != y) { /* kludge to prevent freeing twice */ 2993e12c5d1SDavid du Colombier t->csub = CTEMP; 3003e12c5d1SDavid du Colombier tempfree(t); 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier } 3033e12c5d1SDavid du Colombier tempfree(fcn); 3047dd7cddfSDavid du Colombier if (isexit(y) || isnext(y) || isnextfile(y)) 3053e12c5d1SDavid du Colombier return y; 3063e12c5d1SDavid du Colombier tempfree(y); /* this can free twice! */ 3073e12c5d1SDavid du Colombier z = fp->retval; /* return value */ 3083e12c5d1SDavid du Colombier dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); 3093e12c5d1SDavid du Colombier fp--; 3103e12c5d1SDavid du Colombier return(z); 3113e12c5d1SDavid du Colombier } 3123e12c5d1SDavid du Colombier 3133e12c5d1SDavid du Colombier Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ 3143e12c5d1SDavid du Colombier { 3153e12c5d1SDavid du Colombier Cell *y; 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier y = gettemp(); 3183e12c5d1SDavid du Colombier y->csub = CCOPY; /* prevents freeing until call is over */ 3197dd7cddfSDavid du Colombier y->nval = x->nval; /* BUG? */ 3203e12c5d1SDavid du Colombier y->sval = x->sval ? tostring(x->sval) : NULL; 3213e12c5d1SDavid du Colombier y->fval = x->fval; 3223e12c5d1SDavid du Colombier y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ 3233e12c5d1SDavid du Colombier /* is DONTFREE right? */ 3243e12c5d1SDavid du Colombier return y; 3253e12c5d1SDavid du Colombier } 3263e12c5d1SDavid du Colombier 327219b2ee8SDavid du Colombier Cell *arg(Node **a, int n) /* nth argument of a function */ 3283e12c5d1SDavid du Colombier { 3293e12c5d1SDavid du Colombier 3307dd7cddfSDavid du Colombier n = ptoi(a[0]); /* argument number, counting from 0 */ 3313e12c5d1SDavid du Colombier dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); 3323e12c5d1SDavid du Colombier if (n+1 > fp->nargs) 3337dd7cddfSDavid du Colombier FATAL("argument #%d of function %s was not supplied", 3347dd7cddfSDavid du Colombier n+1, fp->fcncell->nval); 3353e12c5d1SDavid du Colombier return fp->args[n]; 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier 3387dd7cddfSDavid du Colombier Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */ 3393e12c5d1SDavid du Colombier { 3407dd7cddfSDavid du Colombier Cell *y; 3413e12c5d1SDavid du Colombier 3423e12c5d1SDavid du Colombier switch (n) { 3433e12c5d1SDavid du Colombier case EXIT: 3443e12c5d1SDavid du Colombier if (a[0] != NULL) { 3453e12c5d1SDavid du Colombier y = execute(a[0]); 3467dd7cddfSDavid du Colombier errorflag = (int) getfval(y); 3473e12c5d1SDavid du Colombier tempfree(y); 3483e12c5d1SDavid du Colombier } 3493e12c5d1SDavid du Colombier longjmp(env, 1); 3503e12c5d1SDavid du Colombier case RETURN: 3513e12c5d1SDavid du Colombier if (a[0] != NULL) { 3523e12c5d1SDavid du Colombier y = execute(a[0]); 3533e12c5d1SDavid du Colombier if ((y->tval & (STR|NUM)) == (STR|NUM)) { 3543e12c5d1SDavid du Colombier setsval(fp->retval, getsval(y)); 3553e12c5d1SDavid du Colombier fp->retval->fval = getfval(y); 3563e12c5d1SDavid du Colombier fp->retval->tval |= NUM; 3573e12c5d1SDavid du Colombier } 3583e12c5d1SDavid du Colombier else if (y->tval & STR) 3593e12c5d1SDavid du Colombier setsval(fp->retval, getsval(y)); 3603e12c5d1SDavid du Colombier else if (y->tval & NUM) 3613e12c5d1SDavid du Colombier setfval(fp->retval, getfval(y)); 3623e12c5d1SDavid du Colombier else /* can't happen */ 3637dd7cddfSDavid du Colombier FATAL("bad type variable %d", y->tval); 3643e12c5d1SDavid du Colombier tempfree(y); 3653e12c5d1SDavid du Colombier } 3663e12c5d1SDavid du Colombier return(jret); 3673e12c5d1SDavid du Colombier case NEXT: 3683e12c5d1SDavid du Colombier return(jnext); 3697dd7cddfSDavid du Colombier case NEXTFILE: 3707dd7cddfSDavid du Colombier nextfile(); 3717dd7cddfSDavid du Colombier return(jnextfile); 3723e12c5d1SDavid du Colombier case BREAK: 3733e12c5d1SDavid du Colombier return(jbreak); 3743e12c5d1SDavid du Colombier case CONTINUE: 3753e12c5d1SDavid du Colombier return(jcont); 3763e12c5d1SDavid du Colombier default: /* can't happen */ 3777dd7cddfSDavid du Colombier FATAL("illegal jump type %d", n); 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier return 0; /* not reached */ 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier 382219b2ee8SDavid du Colombier Cell *getline(Node **a, int n) /* get next line from specific input */ 383219b2ee8SDavid du Colombier { /* a[0] is variable, a[1] is operator, a[2] is filename */ 3847dd7cddfSDavid du Colombier Cell *r, *x; 3857dd7cddfSDavid du Colombier extern Cell **fldtab; 3863e12c5d1SDavid du Colombier FILE *fp; 3877dd7cddfSDavid du Colombier char *buf; 3887dd7cddfSDavid du Colombier int bufsize = recsize; 3897dd7cddfSDavid du Colombier int mode; 3907dd7cddfSDavid du Colombier 3917dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsize)) == NULL) 3927dd7cddfSDavid du Colombier FATAL("out of memory in getline"); 3933e12c5d1SDavid du Colombier 3943e12c5d1SDavid du Colombier fflush(stdout); /* in case someone is waiting for a prompt */ 3953e12c5d1SDavid du Colombier r = gettemp(); 3963e12c5d1SDavid du Colombier if (a[1] != NULL) { /* getline < file */ 3973e12c5d1SDavid du Colombier x = execute(a[2]); /* filename */ 3987dd7cddfSDavid du Colombier mode = ptoi(a[1]); 3997dd7cddfSDavid du Colombier if (mode == '|') /* input pipe */ 4007dd7cddfSDavid du Colombier mode = LE; /* arbitrary flag */ 4017dd7cddfSDavid du Colombier fp = openfile(mode, getsval(x)); 4023e12c5d1SDavid du Colombier tempfree(x); 4033e12c5d1SDavid du Colombier if (fp == NULL) 4043e12c5d1SDavid du Colombier n = -1; 4053e12c5d1SDavid du Colombier else 4067dd7cddfSDavid du Colombier n = readrec(&buf, &bufsize, fp); 4073e12c5d1SDavid du Colombier if (n <= 0) { 4083e12c5d1SDavid du Colombier ; 4093e12c5d1SDavid du Colombier } else if (a[0] != NULL) { /* getline var <file */ 4107dd7cddfSDavid du Colombier x = execute(a[0]); 4117dd7cddfSDavid du Colombier setsval(x, buf); 4127dd7cddfSDavid du Colombier tempfree(x); 4133e12c5d1SDavid du Colombier } else { /* getline <file */ 4147dd7cddfSDavid du Colombier setsval(fldtab[0], buf); 4157dd7cddfSDavid du Colombier if (is_number(fldtab[0]->sval)) { 4167dd7cddfSDavid du Colombier fldtab[0]->fval = atof(fldtab[0]->sval); 4177dd7cddfSDavid du Colombier fldtab[0]->tval |= NUM; 4183e12c5d1SDavid du Colombier } 4193e12c5d1SDavid du Colombier } 4203e12c5d1SDavid du Colombier } else { /* bare getline; use current input */ 4213e12c5d1SDavid du Colombier if (a[0] == NULL) /* getline */ 4227dd7cddfSDavid du Colombier n = getrec(&record, &recsize, 1); 4233e12c5d1SDavid du Colombier else { /* getline var */ 4247dd7cddfSDavid du Colombier n = getrec(&buf, &bufsize, 0); 4257dd7cddfSDavid du Colombier x = execute(a[0]); 4267dd7cddfSDavid du Colombier setsval(x, buf); 4277dd7cddfSDavid du Colombier tempfree(x); 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier } 4303e12c5d1SDavid du Colombier setfval(r, (Awkfloat) n); 4317dd7cddfSDavid du Colombier free(buf); 4323e12c5d1SDavid du Colombier return r; 4333e12c5d1SDavid du Colombier } 4343e12c5d1SDavid du Colombier 435219b2ee8SDavid du Colombier Cell *getnf(Node **a, int n) /* get NF */ 4363e12c5d1SDavid du Colombier { 4373e12c5d1SDavid du Colombier if (donefld == 0) 4383e12c5d1SDavid du Colombier fldbld(); 4393e12c5d1SDavid du Colombier return (Cell *) a[0]; 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier 442219b2ee8SDavid du Colombier Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 4433e12c5d1SDavid du Colombier { 4447dd7cddfSDavid du Colombier Cell *x, *y, *z; 4457dd7cddfSDavid du Colombier char *s; 4467dd7cddfSDavid du Colombier Node *np; 4477dd7cddfSDavid du Colombier char *buf; 4487dd7cddfSDavid du Colombier int bufsz = recsize; 4497dd7cddfSDavid du Colombier int nsub = strlen(*SUBSEP); 4507dd7cddfSDavid du Colombier 4517dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) 4527dd7cddfSDavid du Colombier FATAL("out of memory in array"); 4533e12c5d1SDavid du Colombier 4543e12c5d1SDavid du Colombier x = execute(a[0]); /* Cell* for symbol table */ 4553e12c5d1SDavid du Colombier buf[0] = 0; 4563e12c5d1SDavid du Colombier for (np = a[1]; np; np = np->nnext) { 4573e12c5d1SDavid du Colombier y = execute(np); /* subscript */ 4583e12c5d1SDavid du Colombier s = getsval(y); 4597dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) 4607dd7cddfSDavid du Colombier FATAL("out of memory for %s[%s...]", x->nval, buf); 4613e12c5d1SDavid du Colombier strcat(buf, s); 4623e12c5d1SDavid du Colombier if (np->nnext) 4633e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 4643e12c5d1SDavid du Colombier tempfree(y); 4653e12c5d1SDavid du Colombier } 4663e12c5d1SDavid du Colombier if (!isarr(x)) { 4673e12c5d1SDavid du Colombier dprintf( ("making %s into an array\n", x->nval) ); 4683e12c5d1SDavid du Colombier if (freeable(x)) 4693e12c5d1SDavid du Colombier xfree(x->sval); 4703e12c5d1SDavid du Colombier x->tval &= ~(STR|NUM|DONTFREE); 4713e12c5d1SDavid du Colombier x->tval |= ARR; 4727dd7cddfSDavid du Colombier x->sval = (char *) makesymtab(NSYMTAB); 4733e12c5d1SDavid du Colombier } 4743e12c5d1SDavid du Colombier z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); 4753e12c5d1SDavid du Colombier z->ctype = OCELL; 4763e12c5d1SDavid du Colombier z->csub = CVAR; 4773e12c5d1SDavid du Colombier tempfree(x); 4787dd7cddfSDavid du Colombier free(buf); 4793e12c5d1SDavid du Colombier return(z); 4803e12c5d1SDavid du Colombier } 4813e12c5d1SDavid du Colombier 4827dd7cddfSDavid du Colombier Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 4833e12c5d1SDavid du Colombier { 4843e12c5d1SDavid du Colombier Cell *x, *y; 4853e12c5d1SDavid du Colombier Node *np; 4867dd7cddfSDavid du Colombier char *s; 4877dd7cddfSDavid du Colombier int nsub = strlen(*SUBSEP); 4883e12c5d1SDavid du Colombier 4893e12c5d1SDavid du Colombier x = execute(a[0]); /* Cell* for symbol table */ 4903e12c5d1SDavid du Colombier if (!isarr(x)) 4917dd7cddfSDavid du Colombier return True; 4927dd7cddfSDavid du Colombier if (a[1] == 0) { /* delete the elements, not the table */ 4937dd7cddfSDavid du Colombier freesymtab(x); 4947dd7cddfSDavid du Colombier x->tval &= ~STR; 4957dd7cddfSDavid du Colombier x->tval |= ARR; 4967dd7cddfSDavid du Colombier x->sval = (char *) makesymtab(NSYMTAB); 4977dd7cddfSDavid du Colombier } else { 4987dd7cddfSDavid du Colombier int bufsz = recsize; 4997dd7cddfSDavid du Colombier char *buf; 5007dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) 5017dd7cddfSDavid du Colombier FATAL("out of memory in adelete"); 5023e12c5d1SDavid du Colombier buf[0] = 0; 5033e12c5d1SDavid du Colombier for (np = a[1]; np; np = np->nnext) { 5043e12c5d1SDavid du Colombier y = execute(np); /* subscript */ 5053e12c5d1SDavid du Colombier s = getsval(y); 5067dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) 5077dd7cddfSDavid du Colombier FATAL("out of memory deleting %s[%s...]", x->nval, buf); 5083e12c5d1SDavid du Colombier strcat(buf, s); 5093e12c5d1SDavid du Colombier if (np->nnext) 5103e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 5113e12c5d1SDavid du Colombier tempfree(y); 5123e12c5d1SDavid du Colombier } 5133e12c5d1SDavid du Colombier freeelem(x, buf); 5147dd7cddfSDavid du Colombier free(buf); 5157dd7cddfSDavid du Colombier } 5163e12c5d1SDavid du Colombier tempfree(x); 5177dd7cddfSDavid du Colombier return True; 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier 520219b2ee8SDavid du Colombier Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ 5213e12c5d1SDavid du Colombier { 5227dd7cddfSDavid du Colombier Cell *x, *ap, *k; 5233e12c5d1SDavid du Colombier Node *p; 5247dd7cddfSDavid du Colombier char *buf; 5257dd7cddfSDavid du Colombier char *s; 5267dd7cddfSDavid du Colombier int bufsz = recsize; 5277dd7cddfSDavid du Colombier int nsub = strlen(*SUBSEP); 5283e12c5d1SDavid du Colombier 5293e12c5d1SDavid du Colombier ap = execute(a[1]); /* array name */ 5303e12c5d1SDavid du Colombier if (!isarr(ap)) { 5313e12c5d1SDavid du Colombier dprintf( ("making %s into an array\n", ap->nval) ); 5323e12c5d1SDavid du Colombier if (freeable(ap)) 5333e12c5d1SDavid du Colombier xfree(ap->sval); 5343e12c5d1SDavid du Colombier ap->tval &= ~(STR|NUM|DONTFREE); 5353e12c5d1SDavid du Colombier ap->tval |= ARR; 5367dd7cddfSDavid du Colombier ap->sval = (char *) makesymtab(NSYMTAB); 5377dd7cddfSDavid du Colombier } 5387dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) { 5397dd7cddfSDavid du Colombier FATAL("out of memory in intest"); 5403e12c5d1SDavid du Colombier } 5413e12c5d1SDavid du Colombier buf[0] = 0; 5423e12c5d1SDavid du Colombier for (p = a[0]; p; p = p->nnext) { 5433e12c5d1SDavid du Colombier x = execute(p); /* expr */ 5443e12c5d1SDavid du Colombier s = getsval(x); 5457dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0)) 5467dd7cddfSDavid du Colombier FATAL("out of memory deleting %s[%s...]", x->nval, buf); 5473e12c5d1SDavid du Colombier strcat(buf, s); 5483e12c5d1SDavid du Colombier tempfree(x); 5493e12c5d1SDavid du Colombier if (p->nnext) 5503e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 5513e12c5d1SDavid du Colombier } 5523e12c5d1SDavid du Colombier k = lookup(buf, (Array *) ap->sval); 5533e12c5d1SDavid du Colombier tempfree(ap); 5547dd7cddfSDavid du Colombier free(buf); 5553e12c5d1SDavid du Colombier if (k == NULL) 5567dd7cddfSDavid du Colombier return(False); 5573e12c5d1SDavid du Colombier else 5587dd7cddfSDavid du Colombier return(True); 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier 562219b2ee8SDavid du Colombier Cell *matchop(Node **a, int n) /* ~ and match() */ 5633e12c5d1SDavid du Colombier { 5647dd7cddfSDavid du Colombier Cell *x, *y; 5657dd7cddfSDavid du Colombier char *s, *t; 5667dd7cddfSDavid du Colombier int i; 5673e12c5d1SDavid du Colombier void *p; 5683e12c5d1SDavid du Colombier 569219b2ee8SDavid du Colombier x = execute(a[1]); /* a[1] = target text */ 5703e12c5d1SDavid du Colombier s = getsval(x); 571219b2ee8SDavid du Colombier if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */ 5723e12c5d1SDavid du Colombier p = (void *) a[2]; 5733e12c5d1SDavid du Colombier else { 574219b2ee8SDavid du Colombier y = execute(a[2]); /* a[2] = regular expr */ 5753e12c5d1SDavid du Colombier t = getsval(y); 5763e12c5d1SDavid du Colombier p = compre(t); 5773e12c5d1SDavid du Colombier tempfree(y); 5783e12c5d1SDavid du Colombier } 5793e12c5d1SDavid du Colombier if (n == MATCHFCN) 5803e12c5d1SDavid du Colombier i = pmatch(p, s, s); 5813e12c5d1SDavid du Colombier else 5823e12c5d1SDavid du Colombier i = match(p, s, s); 5833e12c5d1SDavid du Colombier tempfree(x); 5843e12c5d1SDavid du Colombier if (n == MATCHFCN) { 585d9306527SDavid du Colombier int start = countposn(s, patbeg-s)+1; 5863e12c5d1SDavid du Colombier if (patlen < 0) 5873e12c5d1SDavid du Colombier start = 0; 5883e12c5d1SDavid du Colombier setfval(rstartloc, (Awkfloat) start); 5893e12c5d1SDavid du Colombier setfval(rlengthloc, (Awkfloat) countposn(patbeg, patlen)); 5903e12c5d1SDavid du Colombier x = gettemp(); 5913e12c5d1SDavid du Colombier x->tval = NUM; 5923e12c5d1SDavid du Colombier x->fval = start; 5933e12c5d1SDavid du Colombier return x; 5947dd7cddfSDavid du Colombier } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) 5957dd7cddfSDavid du Colombier return(True); 5963e12c5d1SDavid du Colombier else 5977dd7cddfSDavid du Colombier return(False); 5983e12c5d1SDavid du Colombier } 5993e12c5d1SDavid du Colombier 6003e12c5d1SDavid du Colombier 601219b2ee8SDavid du Colombier Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ 6023e12c5d1SDavid du Colombier { 6037dd7cddfSDavid du Colombier Cell *x, *y; 6047dd7cddfSDavid du Colombier int i; 6053e12c5d1SDavid du Colombier 6063e12c5d1SDavid du Colombier x = execute(a[0]); 6073e12c5d1SDavid du Colombier i = istrue(x); 6083e12c5d1SDavid du Colombier tempfree(x); 6093e12c5d1SDavid du Colombier switch (n) { 6103e12c5d1SDavid du Colombier case BOR: 6117dd7cddfSDavid du Colombier if (i) return(True); 6123e12c5d1SDavid du Colombier y = execute(a[1]); 6133e12c5d1SDavid du Colombier i = istrue(y); 6143e12c5d1SDavid du Colombier tempfree(y); 6157dd7cddfSDavid du Colombier if (i) return(True); 6167dd7cddfSDavid du Colombier else return(False); 6173e12c5d1SDavid du Colombier case AND: 6187dd7cddfSDavid du Colombier if ( !i ) return(False); 6193e12c5d1SDavid du Colombier y = execute(a[1]); 6203e12c5d1SDavid du Colombier i = istrue(y); 6213e12c5d1SDavid du Colombier tempfree(y); 6227dd7cddfSDavid du Colombier if (i) return(True); 6237dd7cddfSDavid du Colombier else return(False); 6243e12c5d1SDavid du Colombier case NOT: 6257dd7cddfSDavid du Colombier if (i) return(False); 6267dd7cddfSDavid du Colombier else return(True); 6273e12c5d1SDavid du Colombier default: /* can't happen */ 6287dd7cddfSDavid du Colombier FATAL("unknown boolean operator %d", n); 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier return 0; /*NOTREACHED*/ 6313e12c5d1SDavid du Colombier } 6323e12c5d1SDavid du Colombier 633219b2ee8SDavid du Colombier Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ 6343e12c5d1SDavid du Colombier { 6357dd7cddfSDavid du Colombier int i; 6367dd7cddfSDavid du Colombier Cell *x, *y; 6373e12c5d1SDavid du Colombier Awkfloat j; 6383e12c5d1SDavid du Colombier 6393e12c5d1SDavid du Colombier x = execute(a[0]); 6403e12c5d1SDavid du Colombier y = execute(a[1]); 6413e12c5d1SDavid du Colombier if (x->tval&NUM && y->tval&NUM) { 6423e12c5d1SDavid du Colombier j = x->fval - y->fval; 6433e12c5d1SDavid du Colombier i = j<0? -1: (j>0? 1: 0); 6443e12c5d1SDavid du Colombier } else { 6453e12c5d1SDavid du Colombier i = strcmp(getsval(x), getsval(y)); 6463e12c5d1SDavid du Colombier } 6473e12c5d1SDavid du Colombier tempfree(x); 6483e12c5d1SDavid du Colombier tempfree(y); 6493e12c5d1SDavid du Colombier switch (n) { 6507dd7cddfSDavid du Colombier case LT: if (i<0) return(True); 6517dd7cddfSDavid du Colombier else return(False); 6527dd7cddfSDavid du Colombier case LE: if (i<=0) return(True); 6537dd7cddfSDavid du Colombier else return(False); 6547dd7cddfSDavid du Colombier case NE: if (i!=0) return(True); 6557dd7cddfSDavid du Colombier else return(False); 6567dd7cddfSDavid du Colombier case EQ: if (i == 0) return(True); 6577dd7cddfSDavid du Colombier else return(False); 6587dd7cddfSDavid du Colombier case GE: if (i>=0) return(True); 6597dd7cddfSDavid du Colombier else return(False); 6607dd7cddfSDavid du Colombier case GT: if (i>0) return(True); 6617dd7cddfSDavid du Colombier else return(False); 6623e12c5d1SDavid du Colombier default: /* can't happen */ 6637dd7cddfSDavid du Colombier FATAL("unknown relational operator %d", n); 6643e12c5d1SDavid du Colombier } 6653e12c5d1SDavid du Colombier return 0; /*NOTREACHED*/ 6663e12c5d1SDavid du Colombier } 6673e12c5d1SDavid du Colombier 668219b2ee8SDavid du Colombier void tfree(Cell *a) /* free a tempcell */ 6693e12c5d1SDavid du Colombier { 6707dd7cddfSDavid du Colombier if (freeable(a)) { 6717dd7cddfSDavid du Colombier dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) ); 6723e12c5d1SDavid du Colombier xfree(a->sval); 6737dd7cddfSDavid du Colombier } 6743e12c5d1SDavid du Colombier if (a == tmps) 6757dd7cddfSDavid du Colombier FATAL("tempcell list is curdled"); 6763e12c5d1SDavid du Colombier a->cnext = tmps; 6773e12c5d1SDavid du Colombier tmps = a; 6783e12c5d1SDavid du Colombier } 6793e12c5d1SDavid du Colombier 680219b2ee8SDavid du Colombier Cell *gettemp(void) /* get a tempcell */ 6813e12c5d1SDavid du Colombier { int i; 6827dd7cddfSDavid du Colombier Cell *x; 6833e12c5d1SDavid du Colombier 6843e12c5d1SDavid du Colombier if (!tmps) { 6853e12c5d1SDavid du Colombier tmps = (Cell *) calloc(100, sizeof(Cell)); 6863e12c5d1SDavid du Colombier if (!tmps) 6877dd7cddfSDavid du Colombier FATAL("out of space for temporaries"); 6883e12c5d1SDavid du Colombier for(i = 1; i < 100; i++) 6893e12c5d1SDavid du Colombier tmps[i-1].cnext = &tmps[i]; 6903e12c5d1SDavid du Colombier tmps[i-1].cnext = 0; 6913e12c5d1SDavid du Colombier } 6923e12c5d1SDavid du Colombier x = tmps; 6933e12c5d1SDavid du Colombier tmps = x->cnext; 6943e12c5d1SDavid du Colombier *x = tempcell; 6953e12c5d1SDavid du Colombier return(x); 6963e12c5d1SDavid du Colombier } 6973e12c5d1SDavid du Colombier 698219b2ee8SDavid du Colombier Cell *indirect(Node **a, int n) /* $( a[0] ) */ 6993e12c5d1SDavid du Colombier { 7007dd7cddfSDavid du Colombier Cell *x; 7017dd7cddfSDavid du Colombier int m; 7027dd7cddfSDavid du Colombier char *s; 7033e12c5d1SDavid du Colombier 7043e12c5d1SDavid du Colombier x = execute(a[0]); 7057dd7cddfSDavid du Colombier m = (int) getfval(x); 7067dd7cddfSDavid du Colombier if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ 7077dd7cddfSDavid du Colombier FATAL("illegal field $(%s), name \"%s\"", s, x->nval); 7087dd7cddfSDavid du Colombier /* BUG: can x->nval ever be null??? */ 7093e12c5d1SDavid du Colombier tempfree(x); 7103e12c5d1SDavid du Colombier x = fieldadr(m); 7117dd7cddfSDavid du Colombier x->ctype = OCELL; /* BUG? why are these needed? */ 7123e12c5d1SDavid du Colombier x->csub = CFLD; 7133e12c5d1SDavid du Colombier return(x); 7143e12c5d1SDavid du Colombier } 7153e12c5d1SDavid du Colombier 716219b2ee8SDavid du Colombier Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ 7173e12c5d1SDavid du Colombier { 7187dd7cddfSDavid du Colombier int k, m, n; 7197dd7cddfSDavid du Colombier char *s, *p; 7203e12c5d1SDavid du Colombier int temp; 7217dd7cddfSDavid du Colombier Cell *x, *y, *z = 0; 7223e12c5d1SDavid du Colombier 7233e12c5d1SDavid du Colombier x = execute(a[0]); 7243e12c5d1SDavid du Colombier y = execute(a[1]); 7253e12c5d1SDavid du Colombier if (a[2] != 0) 7263e12c5d1SDavid du Colombier z = execute(a[2]); 7273e12c5d1SDavid du Colombier s = getsval(x); 7283e12c5d1SDavid du Colombier k = countposn(s, strlen(s)) + 1; 7293e12c5d1SDavid du Colombier if (k <= 1) { 7303e12c5d1SDavid du Colombier tempfree(x); 7313e12c5d1SDavid du Colombier tempfree(y); 7323e12c5d1SDavid du Colombier if (a[2] != 0) 7333e12c5d1SDavid du Colombier tempfree(z); 7343e12c5d1SDavid du Colombier x = gettemp(); 7353e12c5d1SDavid du Colombier setsval(x, ""); 7363e12c5d1SDavid du Colombier return(x); 7373e12c5d1SDavid du Colombier } 7387dd7cddfSDavid du Colombier m = (int) getfval(y); 7393e12c5d1SDavid du Colombier if (m <= 0) 7403e12c5d1SDavid du Colombier m = 1; 7413e12c5d1SDavid du Colombier else if (m > k) 7423e12c5d1SDavid du Colombier m = k; 7433e12c5d1SDavid du Colombier tempfree(y); 7443e12c5d1SDavid du Colombier if (a[2] != 0) { 7457dd7cddfSDavid du Colombier n = (int) getfval(z); 7463e12c5d1SDavid du Colombier tempfree(z); 7473e12c5d1SDavid du Colombier } else 7483e12c5d1SDavid du Colombier n = k - 1; 7493e12c5d1SDavid du Colombier if (n < 0) 7503e12c5d1SDavid du Colombier n = 0; 7513e12c5d1SDavid du Colombier else if (n > k - m) 7523e12c5d1SDavid du Colombier n = k - m; 7533e12c5d1SDavid du Colombier dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); 7543e12c5d1SDavid du Colombier y = gettemp(); 7553e12c5d1SDavid du Colombier while (*s && --m) 7563e12c5d1SDavid du Colombier s += mblen(s, k); 7573e12c5d1SDavid du Colombier for (p = s; *p && n--; p += mblen(p, k)) 7583e12c5d1SDavid du Colombier ; 7593e12c5d1SDavid du Colombier temp = *p; /* with thanks to John Linderman */ 7603e12c5d1SDavid du Colombier *p = '\0'; 7613e12c5d1SDavid du Colombier setsval(y, s); 7623e12c5d1SDavid du Colombier *p = temp; 7633e12c5d1SDavid du Colombier tempfree(x); 7643e12c5d1SDavid du Colombier return(y); 7653e12c5d1SDavid du Colombier } 7663e12c5d1SDavid du Colombier 767219b2ee8SDavid du Colombier Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ 7683e12c5d1SDavid du Colombier { 7697dd7cddfSDavid du Colombier Cell *x, *y, *z; 7707dd7cddfSDavid du Colombier char *s1, *s2, *p1, *p2, *q; 7713e12c5d1SDavid du Colombier Awkfloat v = 0.0; 7723e12c5d1SDavid du Colombier 7733e12c5d1SDavid du Colombier x = execute(a[0]); 7743e12c5d1SDavid du Colombier s1 = getsval(x); 7753e12c5d1SDavid du Colombier y = execute(a[1]); 7763e12c5d1SDavid du Colombier s2 = getsval(y); 7773e12c5d1SDavid du Colombier 7783e12c5d1SDavid du Colombier z = gettemp(); 7793e12c5d1SDavid du Colombier for (p1 = s1; *p1 != '\0'; p1++) { 7803e12c5d1SDavid du Colombier for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) 7813e12c5d1SDavid du Colombier ; 7823e12c5d1SDavid du Colombier if (*p2 == '\0') { 7833e12c5d1SDavid du Colombier v = (Awkfloat) countposn(s1, p1-s1) + 1; /* origin 1 */ 7843e12c5d1SDavid du Colombier break; 7853e12c5d1SDavid du Colombier } 7863e12c5d1SDavid du Colombier } 7873e12c5d1SDavid du Colombier tempfree(x); 7883e12c5d1SDavid du Colombier tempfree(y); 7893e12c5d1SDavid du Colombier setfval(z, v); 7903e12c5d1SDavid du Colombier return(z); 7913e12c5d1SDavid du Colombier } 7923e12c5d1SDavid du Colombier 7937dd7cddfSDavid du Colombier #define MAXNUMSIZE 50 794219b2ee8SDavid du Colombier 7957dd7cddfSDavid du Colombier int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */ 7963e12c5d1SDavid du Colombier { 7977dd7cddfSDavid du Colombier char *fmt; 7987dd7cddfSDavid du Colombier char *p, *t, *os; 7997dd7cddfSDavid du Colombier Cell *x; 8003e12c5d1SDavid du Colombier int flag = 0, n; 8017dd7cddfSDavid du Colombier int fmtwd; /* format width */ 8027dd7cddfSDavid du Colombier int fmtsz = recsize; 8037dd7cddfSDavid du Colombier char *buf = *pbuf; 8047dd7cddfSDavid du Colombier int bufsize = *pbufsize; 8053e12c5d1SDavid du Colombier 8063e12c5d1SDavid du Colombier os = s; 8073e12c5d1SDavid du Colombier p = buf; 8087dd7cddfSDavid du Colombier if ((fmt = (char *) malloc(fmtsz)) == NULL) 8097dd7cddfSDavid du Colombier FATAL("out of memory in format()"); 8103e12c5d1SDavid du Colombier while (*s) { 8117dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format"); 8123e12c5d1SDavid du Colombier if (*s != '%') { 8133e12c5d1SDavid du Colombier *p++ = *s++; 8143e12c5d1SDavid du Colombier continue; 8153e12c5d1SDavid du Colombier } 8163e12c5d1SDavid du Colombier if (*(s+1) == '%') { 8173e12c5d1SDavid du Colombier *p++ = '%'; 8183e12c5d1SDavid du Colombier s += 2; 8193e12c5d1SDavid du Colombier continue; 8203e12c5d1SDavid du Colombier } 8217dd7cddfSDavid du Colombier /* have to be real careful in case this is a huge number, eg, %100000d */ 8227dd7cddfSDavid du Colombier fmtwd = atoi(s+1); 8237dd7cddfSDavid du Colombier if (fmtwd < 0) 8247dd7cddfSDavid du Colombier fmtwd = -fmtwd; 8257dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 8263e12c5d1SDavid du Colombier for (t = fmt; (*t++ = *s) != '\0'; s++) { 8277dd7cddfSDavid du Colombier if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0)) 8287dd7cddfSDavid du Colombier FATAL("format item %.30s... ran format() out of memory", os); 8293e12c5d1SDavid du Colombier if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') 8303e12c5d1SDavid du Colombier break; /* the ansi panoply */ 8313e12c5d1SDavid du Colombier if (*s == '*') { 8323e12c5d1SDavid du Colombier x = execute(a); 8333e12c5d1SDavid du Colombier a = a->nnext; 8347dd7cddfSDavid du Colombier sprintf(t-1, "%d", fmtwd=(int) getfval(x)); 8357dd7cddfSDavid du Colombier if (fmtwd < 0) 8367dd7cddfSDavid du Colombier fmtwd = -fmtwd; 8377dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 8383e12c5d1SDavid du Colombier t = fmt + strlen(fmt); 8393e12c5d1SDavid du Colombier tempfree(x); 8403e12c5d1SDavid du Colombier } 8413e12c5d1SDavid du Colombier } 8423e12c5d1SDavid du Colombier *t = '\0'; 8437dd7cddfSDavid du Colombier if (fmtwd < 0) 8447dd7cddfSDavid du Colombier fmtwd = -fmtwd; 8457dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format"); 8467dd7cddfSDavid du Colombier 8473e12c5d1SDavid du Colombier switch (*s) { 8483e12c5d1SDavid du Colombier case 'f': case 'e': case 'g': case 'E': case 'G': 8493e12c5d1SDavid du Colombier flag = 1; 8503e12c5d1SDavid du Colombier break; 8513e12c5d1SDavid du Colombier case 'd': case 'i': 8523e12c5d1SDavid du Colombier flag = 2; 8533e12c5d1SDavid du Colombier if(*(s-1) == 'l') break; 8543e12c5d1SDavid du Colombier *(t-1) = 'l'; 8553e12c5d1SDavid du Colombier *t = 'd'; 8563e12c5d1SDavid du Colombier *++t = '\0'; 8573e12c5d1SDavid du Colombier break; 8583e12c5d1SDavid du Colombier case 'o': case 'x': case 'X': case 'u': 8593e12c5d1SDavid du Colombier flag = *(s-1) == 'l' ? 2 : 3; 8603e12c5d1SDavid du Colombier break; 8613e12c5d1SDavid du Colombier case 's': 8623e12c5d1SDavid du Colombier flag = 4; 8633e12c5d1SDavid du Colombier break; 8643e12c5d1SDavid du Colombier case 'c': 8653e12c5d1SDavid du Colombier flag = 5; 8663e12c5d1SDavid du Colombier break; 8673e12c5d1SDavid du Colombier default: 8687dd7cddfSDavid du Colombier WARNING("weird printf conversion %s", fmt); 8693e12c5d1SDavid du Colombier flag = 0; 8703e12c5d1SDavid du Colombier break; 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier if (a == NULL) 8737dd7cddfSDavid du Colombier FATAL("not enough args in printf(%s)", os); 8743e12c5d1SDavid du Colombier x = execute(a); 8753e12c5d1SDavid du Colombier a = a->nnext; 8767dd7cddfSDavid du Colombier n = MAXNUMSIZE; 8777dd7cddfSDavid du Colombier if (fmtwd > n) 8787dd7cddfSDavid du Colombier n = fmtwd; 8797dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format"); 8803e12c5d1SDavid du Colombier switch (flag) { 8817dd7cddfSDavid du Colombier case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */ 8827dd7cddfSDavid du Colombier t = getsval(x); 8837dd7cddfSDavid du Colombier n = strlen(t); 8847dd7cddfSDavid du Colombier if (fmtwd > n) 8857dd7cddfSDavid du Colombier n = fmtwd; 8867dd7cddfSDavid du Colombier adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format"); 8873e12c5d1SDavid du Colombier p += strlen(p); 8887dd7cddfSDavid du Colombier sprintf(p, "%s", t); 8893e12c5d1SDavid du Colombier break; 8907dd7cddfSDavid du Colombier case 1: sprintf(p, fmt, getfval(x)); break; 8917dd7cddfSDavid du Colombier case 2: sprintf(p, fmt, (long) getfval(x)); break; 8927dd7cddfSDavid du Colombier case 3: sprintf(p, fmt, (int) getfval(x)); break; 8933e12c5d1SDavid du Colombier case 4: 8943e12c5d1SDavid du Colombier t = getsval(x); 8953e12c5d1SDavid du Colombier n = strlen(t); 8967dd7cddfSDavid du Colombier if (fmtwd > n) 8977dd7cddfSDavid du Colombier n = fmtwd; 8987dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0)) 8997dd7cddfSDavid du Colombier FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t); 9007dd7cddfSDavid du Colombier sprintf(p, fmt, t); 9013e12c5d1SDavid du Colombier break; 902219b2ee8SDavid du Colombier case 5: 9037dd7cddfSDavid du Colombier if (isnum(x)) { 9047dd7cddfSDavid du Colombier if (getfval(x)) 9057dd7cddfSDavid du Colombier sprintf(p, fmt, (int) getfval(x)); 9067dd7cddfSDavid du Colombier else 9077dd7cddfSDavid du Colombier *p++ = '\0'; 9087dd7cddfSDavid du Colombier } else 9097dd7cddfSDavid du Colombier sprintf(p, fmt, getsval(x)[0]); 9103e12c5d1SDavid du Colombier break; 9113e12c5d1SDavid du Colombier } 9123e12c5d1SDavid du Colombier tempfree(x); 9133e12c5d1SDavid du Colombier p += strlen(p); 9143e12c5d1SDavid du Colombier s++; 9153e12c5d1SDavid du Colombier } 9163e12c5d1SDavid du Colombier *p = '\0'; 9177dd7cddfSDavid du Colombier free(fmt); 9183e12c5d1SDavid du Colombier for ( ; a; a = a->nnext) /* evaluate any remaining args */ 9193e12c5d1SDavid du Colombier execute(a); 9207dd7cddfSDavid du Colombier *pbuf = buf; 9217dd7cddfSDavid du Colombier *pbufsize = bufsize; 9227dd7cddfSDavid du Colombier return p - buf; 9233e12c5d1SDavid du Colombier } 9243e12c5d1SDavid du Colombier 9257dd7cddfSDavid du Colombier Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */ 9263e12c5d1SDavid du Colombier { 9277dd7cddfSDavid du Colombier Cell *x; 9287dd7cddfSDavid du Colombier Node *y; 9297dd7cddfSDavid du Colombier char *buf; 9307dd7cddfSDavid du Colombier int bufsz=3*recsize; 9313e12c5d1SDavid du Colombier 9327dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) 9337dd7cddfSDavid du Colombier FATAL("out of memory in awksprintf"); 9343e12c5d1SDavid du Colombier y = a[0]->nnext; 9353e12c5d1SDavid du Colombier x = execute(a[0]); 9367dd7cddfSDavid du Colombier if (format(&buf, &bufsz, getsval(x), y) == -1) 9377dd7cddfSDavid du Colombier FATAL("sprintf string %.30s... too long. can't happen.", buf); 9383e12c5d1SDavid du Colombier tempfree(x); 9393e12c5d1SDavid du Colombier x = gettemp(); 9407dd7cddfSDavid du Colombier x->sval = buf; 9413e12c5d1SDavid du Colombier x->tval = STR; 9423e12c5d1SDavid du Colombier return(x); 9433e12c5d1SDavid du Colombier } 9443e12c5d1SDavid du Colombier 9457dd7cddfSDavid du Colombier Cell *awkprintf(Node **a, int n) /* printf */ 946219b2ee8SDavid du Colombier { /* a[0] is list of args, starting with format string */ 947219b2ee8SDavid du Colombier /* a[1] is redirection operator, a[2] is redirection file */ 9483e12c5d1SDavid du Colombier FILE *fp; 9497dd7cddfSDavid du Colombier Cell *x; 9507dd7cddfSDavid du Colombier Node *y; 9517dd7cddfSDavid du Colombier char *buf; 9527dd7cddfSDavid du Colombier int len; 9537dd7cddfSDavid du Colombier int bufsz=3*recsize; 9543e12c5d1SDavid du Colombier 9557dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) 9567dd7cddfSDavid du Colombier FATAL("out of memory in awkprintf"); 9573e12c5d1SDavid du Colombier y = a[0]->nnext; 9583e12c5d1SDavid du Colombier x = execute(a[0]); 9597dd7cddfSDavid du Colombier if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 9607dd7cddfSDavid du Colombier FATAL("printf string %.30s... too long. can't happen.", buf); 9613e12c5d1SDavid du Colombier tempfree(x); 9623e12c5d1SDavid du Colombier if (a[1] == NULL) { 9637dd7cddfSDavid du Colombier /* fputs(buf, stdout); */ 9647dd7cddfSDavid du Colombier fwrite(buf, len, 1, stdout); 9653e12c5d1SDavid du Colombier if (ferror(stdout)) 9667dd7cddfSDavid du Colombier FATAL("write error on stdout"); 9673e12c5d1SDavid du Colombier } else { 9687dd7cddfSDavid du Colombier fp = redirect(ptoi(a[1]), a[2]); 9697dd7cddfSDavid du Colombier /* fputs(buf, fp); */ 9707dd7cddfSDavid du Colombier fwrite(buf, len, 1, fp); 9713e12c5d1SDavid du Colombier fflush(fp); 9723e12c5d1SDavid du Colombier if (ferror(fp)) 9737dd7cddfSDavid du Colombier FATAL("write error on %s", filename(fp)); 9743e12c5d1SDavid du Colombier } 9757dd7cddfSDavid du Colombier free(buf); 9767dd7cddfSDavid du Colombier return(True); 9773e12c5d1SDavid du Colombier } 9783e12c5d1SDavid du Colombier 979219b2ee8SDavid du Colombier Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 9803e12c5d1SDavid du Colombier { 9817dd7cddfSDavid du Colombier Awkfloat i, j = 0; 9823e12c5d1SDavid du Colombier double v; 9837dd7cddfSDavid du Colombier Cell *x, *y, *z; 9843e12c5d1SDavid du Colombier 9853e12c5d1SDavid du Colombier x = execute(a[0]); 9863e12c5d1SDavid du Colombier i = getfval(x); 9873e12c5d1SDavid du Colombier tempfree(x); 9883e12c5d1SDavid du Colombier if (n != UMINUS) { 9893e12c5d1SDavid du Colombier y = execute(a[1]); 9903e12c5d1SDavid du Colombier j = getfval(y); 9913e12c5d1SDavid du Colombier tempfree(y); 9923e12c5d1SDavid du Colombier } 9933e12c5d1SDavid du Colombier z = gettemp(); 9943e12c5d1SDavid du Colombier switch (n) { 9953e12c5d1SDavid du Colombier case ADD: 9963e12c5d1SDavid du Colombier i += j; 9973e12c5d1SDavid du Colombier break; 9983e12c5d1SDavid du Colombier case MINUS: 9993e12c5d1SDavid du Colombier i -= j; 10003e12c5d1SDavid du Colombier break; 10013e12c5d1SDavid du Colombier case MULT: 10023e12c5d1SDavid du Colombier i *= j; 10033e12c5d1SDavid du Colombier break; 10043e12c5d1SDavid du Colombier case DIVIDE: 10053e12c5d1SDavid du Colombier if (j == 0) 10067dd7cddfSDavid du Colombier FATAL("division by zero"); 10073e12c5d1SDavid du Colombier i /= j; 10083e12c5d1SDavid du Colombier break; 10093e12c5d1SDavid du Colombier case MOD: 10103e12c5d1SDavid du Colombier if (j == 0) 10117dd7cddfSDavid du Colombier FATAL("division by zero in mod"); 10123e12c5d1SDavid du Colombier modf(i/j, &v); 10133e12c5d1SDavid du Colombier i = i - j * v; 10143e12c5d1SDavid du Colombier break; 10153e12c5d1SDavid du Colombier case UMINUS: 10163e12c5d1SDavid du Colombier i = -i; 10173e12c5d1SDavid du Colombier break; 10183e12c5d1SDavid du Colombier case POWER: 10193e12c5d1SDavid du Colombier if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 10203e12c5d1SDavid du Colombier i = ipow(i, (int) j); 10213e12c5d1SDavid du Colombier else 10223e12c5d1SDavid du Colombier i = errcheck(pow(i, j), "pow"); 10233e12c5d1SDavid du Colombier break; 10243e12c5d1SDavid du Colombier default: /* can't happen */ 10257dd7cddfSDavid du Colombier FATAL("illegal arithmetic operator %d", n); 10263e12c5d1SDavid du Colombier } 10273e12c5d1SDavid du Colombier setfval(z, i); 10283e12c5d1SDavid du Colombier return(z); 10293e12c5d1SDavid du Colombier } 10303e12c5d1SDavid du Colombier 1031219b2ee8SDavid du Colombier double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 10323e12c5d1SDavid du Colombier { 10333e12c5d1SDavid du Colombier double v; 10343e12c5d1SDavid du Colombier 10353e12c5d1SDavid du Colombier if (n <= 0) 10363e12c5d1SDavid du Colombier return 1; 10373e12c5d1SDavid du Colombier v = ipow(x, n/2); 10383e12c5d1SDavid du Colombier if (n % 2 == 0) 10393e12c5d1SDavid du Colombier return v * v; 10403e12c5d1SDavid du Colombier else 10413e12c5d1SDavid du Colombier return x * v * v; 10423e12c5d1SDavid du Colombier } 10433e12c5d1SDavid du Colombier 1044219b2ee8SDavid du Colombier Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 10453e12c5d1SDavid du Colombier { 10467dd7cddfSDavid du Colombier Cell *x, *z; 10477dd7cddfSDavid du Colombier int k; 10483e12c5d1SDavid du Colombier Awkfloat xf; 10493e12c5d1SDavid du Colombier 10503e12c5d1SDavid du Colombier x = execute(a[0]); 10513e12c5d1SDavid du Colombier xf = getfval(x); 10523e12c5d1SDavid du Colombier k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 10533e12c5d1SDavid du Colombier if (n == PREINCR || n == PREDECR) { 10543e12c5d1SDavid du Colombier setfval(x, xf + k); 10553e12c5d1SDavid du Colombier return(x); 10563e12c5d1SDavid du Colombier } 10573e12c5d1SDavid du Colombier z = gettemp(); 10583e12c5d1SDavid du Colombier setfval(z, xf); 10593e12c5d1SDavid du Colombier setfval(x, xf + k); 10603e12c5d1SDavid du Colombier tempfree(x); 10613e12c5d1SDavid du Colombier return(z); 10623e12c5d1SDavid du Colombier } 10633e12c5d1SDavid du Colombier 1064219b2ee8SDavid du Colombier Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 1065219b2ee8SDavid du Colombier { /* this is subtle; don't muck with it. */ 10667dd7cddfSDavid du Colombier Cell *x, *y; 10673e12c5d1SDavid du Colombier Awkfloat xf, yf; 10683e12c5d1SDavid du Colombier double v; 10693e12c5d1SDavid du Colombier 10703e12c5d1SDavid du Colombier y = execute(a[1]); 10713e12c5d1SDavid du Colombier x = execute(a[0]); 10723e12c5d1SDavid du Colombier if (n == ASSIGN) { /* ordinary assignment */ 1073219b2ee8SDavid du Colombier if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ 1074219b2ee8SDavid du Colombier ; /* leave alone unless it's a field */ 10753e12c5d1SDavid du Colombier else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 10763e12c5d1SDavid du Colombier setsval(x, getsval(y)); 10773e12c5d1SDavid du Colombier x->fval = getfval(y); 10783e12c5d1SDavid du Colombier x->tval |= NUM; 10793e12c5d1SDavid du Colombier } 10807dd7cddfSDavid du Colombier else if (isstr(y)) 10813e12c5d1SDavid du Colombier setsval(x, getsval(y)); 10827dd7cddfSDavid du Colombier else if (isnum(y)) 10833e12c5d1SDavid du Colombier setfval(x, getfval(y)); 10843e12c5d1SDavid du Colombier else 10853e12c5d1SDavid du Colombier funnyvar(y, "read value of"); 10863e12c5d1SDavid du Colombier tempfree(y); 10873e12c5d1SDavid du Colombier return(x); 10883e12c5d1SDavid du Colombier } 10893e12c5d1SDavid du Colombier xf = getfval(x); 10903e12c5d1SDavid du Colombier yf = getfval(y); 10913e12c5d1SDavid du Colombier switch (n) { 10923e12c5d1SDavid du Colombier case ADDEQ: 10933e12c5d1SDavid du Colombier xf += yf; 10943e12c5d1SDavid du Colombier break; 10953e12c5d1SDavid du Colombier case SUBEQ: 10963e12c5d1SDavid du Colombier xf -= yf; 10973e12c5d1SDavid du Colombier break; 10983e12c5d1SDavid du Colombier case MULTEQ: 10993e12c5d1SDavid du Colombier xf *= yf; 11003e12c5d1SDavid du Colombier break; 11013e12c5d1SDavid du Colombier case DIVEQ: 11023e12c5d1SDavid du Colombier if (yf == 0) 11037dd7cddfSDavid du Colombier FATAL("division by zero in /="); 11043e12c5d1SDavid du Colombier xf /= yf; 11053e12c5d1SDavid du Colombier break; 11063e12c5d1SDavid du Colombier case MODEQ: 11073e12c5d1SDavid du Colombier if (yf == 0) 11087dd7cddfSDavid du Colombier FATAL("division by zero in %%="); 11093e12c5d1SDavid du Colombier modf(xf/yf, &v); 11103e12c5d1SDavid du Colombier xf = xf - yf * v; 11113e12c5d1SDavid du Colombier break; 11123e12c5d1SDavid du Colombier case POWEQ: 11133e12c5d1SDavid du Colombier if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 11143e12c5d1SDavid du Colombier xf = ipow(xf, (int) yf); 11153e12c5d1SDavid du Colombier else 11163e12c5d1SDavid du Colombier xf = errcheck(pow(xf, yf), "pow"); 11173e12c5d1SDavid du Colombier break; 11183e12c5d1SDavid du Colombier default: 11197dd7cddfSDavid du Colombier FATAL("illegal assignment operator %d", n); 11203e12c5d1SDavid du Colombier break; 11213e12c5d1SDavid du Colombier } 11223e12c5d1SDavid du Colombier tempfree(y); 11233e12c5d1SDavid du Colombier setfval(x, xf); 11243e12c5d1SDavid du Colombier return(x); 11253e12c5d1SDavid du Colombier } 11263e12c5d1SDavid du Colombier 1127219b2ee8SDavid du Colombier Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 11283e12c5d1SDavid du Colombier { 11297dd7cddfSDavid du Colombier Cell *x, *y, *z; 11307dd7cddfSDavid du Colombier int n1, n2; 11317dd7cddfSDavid du Colombier char *s; 11323e12c5d1SDavid du Colombier 11333e12c5d1SDavid du Colombier x = execute(a[0]); 11343e12c5d1SDavid du Colombier y = execute(a[1]); 11353e12c5d1SDavid du Colombier getsval(x); 11363e12c5d1SDavid du Colombier getsval(y); 11373e12c5d1SDavid du Colombier n1 = strlen(x->sval); 11383e12c5d1SDavid du Colombier n2 = strlen(y->sval); 11397dd7cddfSDavid du Colombier s = (char *) malloc(n1 + n2 + 1); 11403e12c5d1SDavid du Colombier if (s == NULL) 11417dd7cddfSDavid du Colombier FATAL("out of space concatenating %.15s... and %.15s...", 11427dd7cddfSDavid du Colombier x->sval, y->sval); 11433e12c5d1SDavid du Colombier strcpy(s, x->sval); 11443e12c5d1SDavid du Colombier strcpy(s+n1, y->sval); 11453e12c5d1SDavid du Colombier tempfree(y); 11463e12c5d1SDavid du Colombier z = gettemp(); 11473e12c5d1SDavid du Colombier z->sval = s; 11483e12c5d1SDavid du Colombier z->tval = STR; 11493e12c5d1SDavid du Colombier tempfree(x); 11503e12c5d1SDavid du Colombier return(z); 11513e12c5d1SDavid du Colombier } 11523e12c5d1SDavid du Colombier 11533e12c5d1SDavid du Colombier Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 11543e12c5d1SDavid du Colombier { 11557dd7cddfSDavid du Colombier Cell *x; 11563e12c5d1SDavid du Colombier 11573e12c5d1SDavid du Colombier if (a[0] == 0) 11583e12c5d1SDavid du Colombier x = execute(a[1]); 11593e12c5d1SDavid du Colombier else { 11603e12c5d1SDavid du Colombier x = execute(a[0]); 11613e12c5d1SDavid du Colombier if (istrue(x)) { 11623e12c5d1SDavid du Colombier tempfree(x); 11633e12c5d1SDavid du Colombier x = execute(a[1]); 11643e12c5d1SDavid du Colombier } 11653e12c5d1SDavid du Colombier } 11663e12c5d1SDavid du Colombier return x; 11673e12c5d1SDavid du Colombier } 11683e12c5d1SDavid du Colombier 11693e12c5d1SDavid du Colombier Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 11703e12c5d1SDavid du Colombier { 11717dd7cddfSDavid du Colombier Cell *x; 11727dd7cddfSDavid du Colombier int pair; 11733e12c5d1SDavid du Colombier 11747dd7cddfSDavid du Colombier pair = ptoi(a[3]); 11753e12c5d1SDavid du Colombier if (pairstack[pair] == 0) { 11763e12c5d1SDavid du Colombier x = execute(a[0]); 11773e12c5d1SDavid du Colombier if (istrue(x)) 11783e12c5d1SDavid du Colombier pairstack[pair] = 1; 11793e12c5d1SDavid du Colombier tempfree(x); 11803e12c5d1SDavid du Colombier } 11813e12c5d1SDavid du Colombier if (pairstack[pair] == 1) { 11823e12c5d1SDavid du Colombier x = execute(a[1]); 11833e12c5d1SDavid du Colombier if (istrue(x)) 11843e12c5d1SDavid du Colombier pairstack[pair] = 0; 11853e12c5d1SDavid du Colombier tempfree(x); 11863e12c5d1SDavid du Colombier x = execute(a[2]); 11873e12c5d1SDavid du Colombier return(x); 11883e12c5d1SDavid du Colombier } 11897dd7cddfSDavid du Colombier return(False); 11903e12c5d1SDavid du Colombier } 11913e12c5d1SDavid du Colombier 11923e12c5d1SDavid du Colombier Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 11933e12c5d1SDavid du Colombier { 11947dd7cddfSDavid du Colombier Cell *x = 0, *y, *ap; 11957dd7cddfSDavid du Colombier char *s; 11967dd7cddfSDavid du Colombier int sep; 11977dd7cddfSDavid du Colombier char *t, temp, num[50], *fs = 0; 11987dd7cddfSDavid du Colombier int n, tempstat, arg3type; 11993e12c5d1SDavid du Colombier 12003e12c5d1SDavid du Colombier y = execute(a[0]); /* source string */ 12013e12c5d1SDavid du Colombier s = getsval(y); 12027dd7cddfSDavid du Colombier arg3type = ptoi(a[3]); 12033e12c5d1SDavid du Colombier if (a[2] == 0) /* fs string */ 12043e12c5d1SDavid du Colombier fs = *FS; 12057dd7cddfSDavid du Colombier else if (arg3type == STRING) { /* split(str,arr,"string") */ 12063e12c5d1SDavid du Colombier x = execute(a[2]); 12073e12c5d1SDavid du Colombier fs = getsval(x); 12087dd7cddfSDavid du Colombier } else if (arg3type == REGEXPR) 12097dd7cddfSDavid du Colombier fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 12103e12c5d1SDavid du Colombier else 12117dd7cddfSDavid du Colombier FATAL("illegal type of split"); 12123e12c5d1SDavid du Colombier sep = *fs; 12133e12c5d1SDavid du Colombier ap = execute(a[1]); /* array name */ 12143e12c5d1SDavid du Colombier freesymtab(ap); 12153e12c5d1SDavid du Colombier dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); 12163e12c5d1SDavid du Colombier ap->tval &= ~STR; 12173e12c5d1SDavid du Colombier ap->tval |= ARR; 12187dd7cddfSDavid du Colombier ap->sval = (char *) makesymtab(NSYMTAB); 12193e12c5d1SDavid du Colombier 12203e12c5d1SDavid du Colombier n = 0; 12217dd7cddfSDavid du Colombier if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */ 12223e12c5d1SDavid du Colombier void *p; 12237dd7cddfSDavid du Colombier if (arg3type == REGEXPR) { /* it's ready already */ 12243e12c5d1SDavid du Colombier p = (void *) a[2]; 12253e12c5d1SDavid du Colombier } else { 12263e12c5d1SDavid du Colombier p = compre(fs); 12273e12c5d1SDavid du Colombier } 12283e12c5d1SDavid du Colombier t = s; 12293e12c5d1SDavid du Colombier if (nematch(p,s,t)) { 12303e12c5d1SDavid du Colombier do { 12313e12c5d1SDavid du Colombier n++; 12327dd7cddfSDavid du Colombier sprintf(num, "%d", n); 12333e12c5d1SDavid du Colombier temp = *patbeg; 12343e12c5d1SDavid du Colombier *patbeg = '\0'; 12357dd7cddfSDavid du Colombier if (is_number(t)) 12367dd7cddfSDavid du Colombier setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 12373e12c5d1SDavid du Colombier else 12383e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 12393e12c5d1SDavid du Colombier *patbeg = temp; 12403e12c5d1SDavid du Colombier t = patbeg + patlen; 12413e12c5d1SDavid du Colombier if (t[-1] == 0 || *t == 0) { 12423e12c5d1SDavid du Colombier n++; 12437dd7cddfSDavid du Colombier sprintf(num, "%d", n); 12443e12c5d1SDavid du Colombier setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 12453e12c5d1SDavid du Colombier goto spdone; 12463e12c5d1SDavid du Colombier } 12473e12c5d1SDavid du Colombier } while (nematch(p,s,t)); 12483e12c5d1SDavid du Colombier } 12493e12c5d1SDavid du Colombier n++; 12507dd7cddfSDavid du Colombier sprintf(num, "%d", n); 12517dd7cddfSDavid du Colombier if (is_number(t)) 12527dd7cddfSDavid du Colombier setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 12533e12c5d1SDavid du Colombier else 12543e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 12553e12c5d1SDavid du Colombier spdone: 12563e12c5d1SDavid du Colombier p = NULL; 12573e12c5d1SDavid du Colombier } else if (sep == ' ') { 12583e12c5d1SDavid du Colombier for (n = 0; ; ) { 12593e12c5d1SDavid du Colombier while (*s == ' ' || *s == '\t' || *s == '\n') 12603e12c5d1SDavid du Colombier s++; 12613e12c5d1SDavid du Colombier if (*s == 0) 12623e12c5d1SDavid du Colombier break; 12633e12c5d1SDavid du Colombier n++; 12643e12c5d1SDavid du Colombier t = s; 12653e12c5d1SDavid du Colombier do 12663e12c5d1SDavid du Colombier s++; 12673e12c5d1SDavid du Colombier while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 12683e12c5d1SDavid du Colombier temp = *s; 12693e12c5d1SDavid du Colombier *s = '\0'; 12707dd7cddfSDavid du Colombier sprintf(num, "%d", n); 12717dd7cddfSDavid du Colombier if (is_number(t)) 12727dd7cddfSDavid du Colombier setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 12733e12c5d1SDavid du Colombier else 12743e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 12753e12c5d1SDavid du Colombier *s = temp; 12763e12c5d1SDavid du Colombier if (*s != 0) 12773e12c5d1SDavid du Colombier s++; 12783e12c5d1SDavid du Colombier } 12797dd7cddfSDavid du Colombier } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */ 12807dd7cddfSDavid du Colombier for (n = 0; *s != 0; s++) { 12817dd7cddfSDavid du Colombier char buf[2]; 12827dd7cddfSDavid du Colombier n++; 12837dd7cddfSDavid du Colombier sprintf(num, "%d", n); 12847dd7cddfSDavid du Colombier buf[0] = *s; 12857dd7cddfSDavid du Colombier buf[1] = 0; 12867dd7cddfSDavid du Colombier if (isdigit(buf[0])) 12877dd7cddfSDavid du Colombier setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval); 12887dd7cddfSDavid du Colombier else 12897dd7cddfSDavid du Colombier setsymtab(num, buf, 0.0, STR, (Array *) ap->sval); 12907dd7cddfSDavid du Colombier } 12913e12c5d1SDavid du Colombier } else if (*s != 0) { 12923e12c5d1SDavid du Colombier for (;;) { 12933e12c5d1SDavid du Colombier n++; 12943e12c5d1SDavid du Colombier t = s; 12953e12c5d1SDavid du Colombier while (*s != sep && *s != '\n' && *s != '\0') 12963e12c5d1SDavid du Colombier s++; 12973e12c5d1SDavid du Colombier temp = *s; 12983e12c5d1SDavid du Colombier *s = '\0'; 12997dd7cddfSDavid du Colombier sprintf(num, "%d", n); 13007dd7cddfSDavid du Colombier if (is_number(t)) 13017dd7cddfSDavid du Colombier setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval); 13023e12c5d1SDavid du Colombier else 13033e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 13043e12c5d1SDavid du Colombier *s = temp; 13053e12c5d1SDavid du Colombier if (*s++ == 0) 13063e12c5d1SDavid du Colombier break; 13073e12c5d1SDavid du Colombier } 13083e12c5d1SDavid du Colombier } 13093e12c5d1SDavid du Colombier tempfree(ap); 13103e12c5d1SDavid du Colombier tempfree(y); 13117dd7cddfSDavid du Colombier if (a[2] != 0 && arg3type == STRING) 13123e12c5d1SDavid du Colombier tempfree(x); 13133e12c5d1SDavid du Colombier x = gettemp(); 13143e12c5d1SDavid du Colombier x->tval = NUM; 13153e12c5d1SDavid du Colombier x->fval = n; 13163e12c5d1SDavid du Colombier return(x); 13173e12c5d1SDavid du Colombier } 13183e12c5d1SDavid du Colombier 13193e12c5d1SDavid du Colombier Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 13203e12c5d1SDavid du Colombier { 13217dd7cddfSDavid du Colombier Cell *x; 13223e12c5d1SDavid du Colombier 13233e12c5d1SDavid du Colombier x = execute(a[0]); 13243e12c5d1SDavid du Colombier if (istrue(x)) { 13253e12c5d1SDavid du Colombier tempfree(x); 13263e12c5d1SDavid du Colombier x = execute(a[1]); 13273e12c5d1SDavid du Colombier } else { 13283e12c5d1SDavid du Colombier tempfree(x); 13293e12c5d1SDavid du Colombier x = execute(a[2]); 13303e12c5d1SDavid du Colombier } 13313e12c5d1SDavid du Colombier return(x); 13323e12c5d1SDavid du Colombier } 13333e12c5d1SDavid du Colombier 13343e12c5d1SDavid du Colombier Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 13353e12c5d1SDavid du Colombier { 13367dd7cddfSDavid du Colombier Cell *x; 13373e12c5d1SDavid du Colombier 13383e12c5d1SDavid du Colombier x = execute(a[0]); 13393e12c5d1SDavid du Colombier if (istrue(x)) { 13403e12c5d1SDavid du Colombier tempfree(x); 13413e12c5d1SDavid du Colombier x = execute(a[1]); 13423e12c5d1SDavid du Colombier } else if (a[2] != 0) { 13433e12c5d1SDavid du Colombier tempfree(x); 13443e12c5d1SDavid du Colombier x = execute(a[2]); 13453e12c5d1SDavid du Colombier } 13463e12c5d1SDavid du Colombier return(x); 13473e12c5d1SDavid du Colombier } 13483e12c5d1SDavid du Colombier 13493e12c5d1SDavid du Colombier Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 13503e12c5d1SDavid du Colombier { 13517dd7cddfSDavid du Colombier Cell *x; 13523e12c5d1SDavid du Colombier 13533e12c5d1SDavid du Colombier for (;;) { 13543e12c5d1SDavid du Colombier x = execute(a[0]); 13553e12c5d1SDavid du Colombier if (!istrue(x)) 13563e12c5d1SDavid du Colombier return(x); 13573e12c5d1SDavid du Colombier tempfree(x); 13583e12c5d1SDavid du Colombier x = execute(a[1]); 13593e12c5d1SDavid du Colombier if (isbreak(x)) { 13607dd7cddfSDavid du Colombier x = True; 13613e12c5d1SDavid du Colombier return(x); 13623e12c5d1SDavid du Colombier } 13633e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) 13643e12c5d1SDavid du Colombier return(x); 13653e12c5d1SDavid du Colombier tempfree(x); 13663e12c5d1SDavid du Colombier } 13673e12c5d1SDavid du Colombier } 13683e12c5d1SDavid du Colombier 13693e12c5d1SDavid du Colombier Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 13703e12c5d1SDavid du Colombier { 13717dd7cddfSDavid du Colombier Cell *x; 13723e12c5d1SDavid du Colombier 13733e12c5d1SDavid du Colombier for (;;) { 13743e12c5d1SDavid du Colombier x = execute(a[0]); 13753e12c5d1SDavid du Colombier if (isbreak(x)) 13767dd7cddfSDavid du Colombier return True; 13777dd7cddfSDavid du Colombier if (isnext(x) || isnextfile(x) || isexit(x) || isret(x)) 13783e12c5d1SDavid du Colombier return(x); 13793e12c5d1SDavid du Colombier tempfree(x); 13803e12c5d1SDavid du Colombier x = execute(a[1]); 13813e12c5d1SDavid du Colombier if (!istrue(x)) 13823e12c5d1SDavid du Colombier return(x); 13833e12c5d1SDavid du Colombier tempfree(x); 13843e12c5d1SDavid du Colombier } 13853e12c5d1SDavid du Colombier } 13863e12c5d1SDavid du Colombier 13873e12c5d1SDavid du Colombier Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 13883e12c5d1SDavid du Colombier { 13897dd7cddfSDavid du Colombier Cell *x; 13903e12c5d1SDavid du Colombier 13913e12c5d1SDavid du Colombier x = execute(a[0]); 13923e12c5d1SDavid du Colombier tempfree(x); 13933e12c5d1SDavid du Colombier for (;;) { 13943e12c5d1SDavid du Colombier if (a[1]!=0) { 13953e12c5d1SDavid du Colombier x = execute(a[1]); 13963e12c5d1SDavid du Colombier if (!istrue(x)) return(x); 13973e12c5d1SDavid du Colombier else tempfree(x); 13983e12c5d1SDavid du Colombier } 13993e12c5d1SDavid du Colombier x = execute(a[3]); 14003e12c5d1SDavid du Colombier if (isbreak(x)) /* turn off break */ 14017dd7cddfSDavid du Colombier return True; 14023e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) 14033e12c5d1SDavid du Colombier return(x); 14043e12c5d1SDavid du Colombier tempfree(x); 14053e12c5d1SDavid du Colombier x = execute(a[2]); 14063e12c5d1SDavid du Colombier tempfree(x); 14073e12c5d1SDavid du Colombier } 14083e12c5d1SDavid du Colombier } 14093e12c5d1SDavid du Colombier 14103e12c5d1SDavid du Colombier Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 14113e12c5d1SDavid du Colombier { 14127dd7cddfSDavid du Colombier Cell *x, *vp, *arrayp, *cp, *ncp; 14133e12c5d1SDavid du Colombier Array *tp; 14143e12c5d1SDavid du Colombier int i; 14153e12c5d1SDavid du Colombier 14163e12c5d1SDavid du Colombier vp = execute(a[0]); 14173e12c5d1SDavid du Colombier arrayp = execute(a[1]); 14183e12c5d1SDavid du Colombier if (!isarr(arrayp)) { 14197dd7cddfSDavid du Colombier return True; 14203e12c5d1SDavid du Colombier } 14213e12c5d1SDavid du Colombier tp = (Array *) arrayp->sval; 14223e12c5d1SDavid du Colombier tempfree(arrayp); 14233e12c5d1SDavid du Colombier for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 14243e12c5d1SDavid du Colombier for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 14253e12c5d1SDavid du Colombier setsval(vp, cp->nval); 14263e12c5d1SDavid du Colombier ncp = cp->cnext; 14273e12c5d1SDavid du Colombier x = execute(a[2]); 14283e12c5d1SDavid du Colombier if (isbreak(x)) { 14293e12c5d1SDavid du Colombier tempfree(vp); 14307dd7cddfSDavid du Colombier return True; 14313e12c5d1SDavid du Colombier } 14323e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) { 14333e12c5d1SDavid du Colombier tempfree(vp); 14343e12c5d1SDavid du Colombier return(x); 14353e12c5d1SDavid du Colombier } 14363e12c5d1SDavid du Colombier tempfree(x); 14373e12c5d1SDavid du Colombier } 14383e12c5d1SDavid du Colombier } 14397dd7cddfSDavid du Colombier return True; 14403e12c5d1SDavid du Colombier } 14413e12c5d1SDavid du Colombier 1442219b2ee8SDavid du Colombier Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 14433e12c5d1SDavid du Colombier { 14447dd7cddfSDavid du Colombier Cell *x, *y; 14453e12c5d1SDavid du Colombier Awkfloat u; 14467dd7cddfSDavid du Colombier int t; 1447219b2ee8SDavid du Colombier wchar_t wc; 14487dd7cddfSDavid du Colombier char *p, *buf; 14497dd7cddfSDavid du Colombier char mbc[50]; 14503e12c5d1SDavid du Colombier Node *nextarg; 14513e12c5d1SDavid du Colombier FILE *fp; 14523e12c5d1SDavid du Colombier 14537dd7cddfSDavid du Colombier t = ptoi(a[0]); 14543e12c5d1SDavid du Colombier x = execute(a[1]); 14553e12c5d1SDavid du Colombier nextarg = a[1]->nnext; 14563e12c5d1SDavid du Colombier switch (t) { 14573e12c5d1SDavid du Colombier case FLENGTH: 14583e12c5d1SDavid du Colombier p = getsval(x); 14593e12c5d1SDavid du Colombier u = (Awkfloat) countposn(p, strlen(p)); break; 14603e12c5d1SDavid du Colombier case FLOG: 14613e12c5d1SDavid du Colombier u = errcheck(log(getfval(x)), "log"); break; 14623e12c5d1SDavid du Colombier case FINT: 14633e12c5d1SDavid du Colombier modf(getfval(x), &u); break; 14643e12c5d1SDavid du Colombier case FEXP: 14653e12c5d1SDavid du Colombier u = errcheck(exp(getfval(x)), "exp"); break; 14663e12c5d1SDavid du Colombier case FSQRT: 14673e12c5d1SDavid du Colombier u = errcheck(sqrt(getfval(x)), "sqrt"); break; 14683e12c5d1SDavid du Colombier case FSIN: 14693e12c5d1SDavid du Colombier u = sin(getfval(x)); break; 14703e12c5d1SDavid du Colombier case FCOS: 14713e12c5d1SDavid du Colombier u = cos(getfval(x)); break; 14723e12c5d1SDavid du Colombier case FATAN: 14733e12c5d1SDavid du Colombier if (nextarg == 0) { 14747dd7cddfSDavid du Colombier WARNING("atan2 requires two arguments; returning 1.0"); 14753e12c5d1SDavid du Colombier u = 1.0; 14763e12c5d1SDavid du Colombier } else { 14773e12c5d1SDavid du Colombier y = execute(a[1]->nnext); 14783e12c5d1SDavid du Colombier u = atan2(getfval(x), getfval(y)); 14793e12c5d1SDavid du Colombier tempfree(y); 14803e12c5d1SDavid du Colombier nextarg = nextarg->nnext; 14813e12c5d1SDavid du Colombier } 14823e12c5d1SDavid du Colombier break; 14833e12c5d1SDavid du Colombier case FSYSTEM: 14843e12c5d1SDavid du Colombier fflush(stdout); /* in case something is buffered already */ 14857dd7cddfSDavid du Colombier u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */ 14863e12c5d1SDavid du Colombier break; 14873e12c5d1SDavid du Colombier case FRAND: 14883e12c5d1SDavid du Colombier /* in principle, rand() returns something in 0..RAND_MAX */ 14893e12c5d1SDavid du Colombier u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; 14903e12c5d1SDavid du Colombier break; 14913e12c5d1SDavid du Colombier case FSRAND: 14927dd7cddfSDavid du Colombier if (isrec(x)) /* no argument provided */ 14937dd7cddfSDavid du Colombier u = time((time_t *)0); 14943e12c5d1SDavid du Colombier else 14953e12c5d1SDavid du Colombier u = getfval(x); 14967dd7cddfSDavid du Colombier srand((unsigned int) u); 14973e12c5d1SDavid du Colombier break; 14983e12c5d1SDavid du Colombier case FTOUPPER: 14993e12c5d1SDavid du Colombier case FTOLOWER: 15007dd7cddfSDavid du Colombier buf = tostring(getsval(x)); 15013e12c5d1SDavid du Colombier if (t == FTOUPPER) { 15023e12c5d1SDavid du Colombier for (p = buf; *p; p++) 15033e12c5d1SDavid du Colombier if (islower(*p)) 15043e12c5d1SDavid du Colombier *p = toupper(*p); 15053e12c5d1SDavid du Colombier } else { 15063e12c5d1SDavid du Colombier for (p = buf; *p; p++) 15073e12c5d1SDavid du Colombier if (isupper(*p)) 15083e12c5d1SDavid du Colombier *p = tolower(*p); 15093e12c5d1SDavid du Colombier } 15103e12c5d1SDavid du Colombier tempfree(x); 15113e12c5d1SDavid du Colombier x = gettemp(); 15123e12c5d1SDavid du Colombier setsval(x, buf); 15137dd7cddfSDavid du Colombier free(buf); 15143e12c5d1SDavid du Colombier return x; 15153e12c5d1SDavid du Colombier case FFLUSH: 15167dd7cddfSDavid du Colombier if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 15173e12c5d1SDavid du Colombier u = EOF; 15183e12c5d1SDavid du Colombier else 15193e12c5d1SDavid du Colombier u = fflush(fp); 15203e12c5d1SDavid du Colombier break; 1521219b2ee8SDavid du Colombier case FUTF: 1522219b2ee8SDavid du Colombier wc = (int)getfval(x); 1523219b2ee8SDavid du Colombier mbc[wctomb(mbc, wc)] = 0; 1524219b2ee8SDavid du Colombier tempfree(x); 1525219b2ee8SDavid du Colombier x = gettemp(); 1526219b2ee8SDavid du Colombier setsval(x, mbc); 1527219b2ee8SDavid du Colombier return x; 15283e12c5d1SDavid du Colombier default: /* can't happen */ 15297dd7cddfSDavid du Colombier FATAL("illegal function type %d", t); 15303e12c5d1SDavid du Colombier break; 15313e12c5d1SDavid du Colombier } 15323e12c5d1SDavid du Colombier tempfree(x); 15333e12c5d1SDavid du Colombier x = gettemp(); 15343e12c5d1SDavid du Colombier setfval(x, u); 15353e12c5d1SDavid du Colombier if (nextarg != 0) { 15367dd7cddfSDavid du Colombier WARNING("warning: function has too many arguments"); 15373e12c5d1SDavid du Colombier for ( ; nextarg; nextarg = nextarg->nnext) 15383e12c5d1SDavid du Colombier execute(nextarg); 15393e12c5d1SDavid du Colombier } 15403e12c5d1SDavid du Colombier return(x); 15413e12c5d1SDavid du Colombier } 15423e12c5d1SDavid du Colombier 1543219b2ee8SDavid du Colombier Cell *printstat(Node **a, int n) /* print a[0] */ 15443e12c5d1SDavid du Colombier { 1545*05bfb676SDavid du Colombier int r; 15467dd7cddfSDavid du Colombier Node *x; 15477dd7cddfSDavid du Colombier Cell *y; 15483e12c5d1SDavid du Colombier FILE *fp; 15493e12c5d1SDavid du Colombier 1550219b2ee8SDavid du Colombier if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 15513e12c5d1SDavid du Colombier fp = stdout; 15523e12c5d1SDavid du Colombier else 15537dd7cddfSDavid du Colombier fp = redirect(ptoi(a[1]), a[2]); 15543e12c5d1SDavid du Colombier for (x = a[0]; x != NULL; x = x->nnext) { 15553e12c5d1SDavid du Colombier y = execute(x); 15567dd7cddfSDavid du Colombier fputs(getsval(y), fp); 15573e12c5d1SDavid du Colombier tempfree(y); 15583e12c5d1SDavid du Colombier if (x->nnext == NULL) 1559*05bfb676SDavid du Colombier r = fputs(*ORS, fp); 15603e12c5d1SDavid du Colombier else 1561*05bfb676SDavid du Colombier r = fputs(*OFS, fp); 1562*05bfb676SDavid du Colombier if (r == EOF) 1563*05bfb676SDavid du Colombier FATAL("write error on %s", filename(fp)); 15643e12c5d1SDavid du Colombier } 15653e12c5d1SDavid du Colombier if (a[1] != 0) 1566*05bfb676SDavid du Colombier if (fflush(fp) == EOF) 15677dd7cddfSDavid du Colombier FATAL("write error on %s", filename(fp)); 15687dd7cddfSDavid du Colombier return(True); 15693e12c5d1SDavid du Colombier } 15703e12c5d1SDavid du Colombier 15713e12c5d1SDavid du Colombier Cell *nullproc(Node **a, int n) 15723e12c5d1SDavid du Colombier { 15737dd7cddfSDavid du Colombier n = n; 15747dd7cddfSDavid du Colombier a = a; 15753e12c5d1SDavid du Colombier return 0; 15763e12c5d1SDavid du Colombier } 15773e12c5d1SDavid du Colombier 15783e12c5d1SDavid du Colombier 1579219b2ee8SDavid du Colombier FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 15803e12c5d1SDavid du Colombier { 15813e12c5d1SDavid du Colombier FILE *fp; 15823e12c5d1SDavid du Colombier Cell *x; 15837dd7cddfSDavid du Colombier char *fname; 15843e12c5d1SDavid du Colombier 15853e12c5d1SDavid du Colombier x = execute(b); 15863e12c5d1SDavid du Colombier fname = getsval(x); 15873e12c5d1SDavid du Colombier fp = openfile(a, fname); 15883e12c5d1SDavid du Colombier if (fp == NULL) 15897dd7cddfSDavid du Colombier FATAL("can't open file %s", fname); 15903e12c5d1SDavid du Colombier tempfree(x); 15913e12c5d1SDavid du Colombier return fp; 15923e12c5d1SDavid du Colombier } 15933e12c5d1SDavid du Colombier 1594219b2ee8SDavid du Colombier struct files { 1595219b2ee8SDavid du Colombier FILE *fp; 15967dd7cddfSDavid du Colombier char *fname; 1597219b2ee8SDavid du Colombier int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1598219b2ee8SDavid du Colombier } files[FOPEN_MAX] ={ 15997dd7cddfSDavid du Colombier { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */ 16007dd7cddfSDavid du Colombier { NULL, "/dev/stdout", GT }, 16017dd7cddfSDavid du Colombier { NULL, "/dev/stderr", GT } 1602219b2ee8SDavid du Colombier }; 1603219b2ee8SDavid du Colombier 16047dd7cddfSDavid du Colombier void stdinit(void) /* in case stdin, etc., are not constants */ 16053e12c5d1SDavid du Colombier { 16067dd7cddfSDavid du Colombier files[0].fp = stdin; 16077dd7cddfSDavid du Colombier files[1].fp = stdout; 16087dd7cddfSDavid du Colombier files[2].fp = stderr; 16097dd7cddfSDavid du Colombier } 16107dd7cddfSDavid du Colombier 16117dd7cddfSDavid du Colombier FILE *openfile(int a, char *us) 16127dd7cddfSDavid du Colombier { 16137dd7cddfSDavid du Colombier char *s = us; 16147dd7cddfSDavid du Colombier int i, m; 16157dd7cddfSDavid du Colombier FILE *fp = 0; 16163e12c5d1SDavid du Colombier 16173e12c5d1SDavid du Colombier if (*s == '\0') 16187dd7cddfSDavid du Colombier FATAL("null file name in print or getline"); 16193e12c5d1SDavid du Colombier for (i=0; i < FOPEN_MAX; i++) 16207dd7cddfSDavid du Colombier if (files[i].fname && strcmp(s, files[i].fname) == 0) { 16217dd7cddfSDavid du Colombier if (a == files[i].mode || (a==APPEND && files[i].mode==GT)) 16223e12c5d1SDavid du Colombier return files[i].fp; 16237dd7cddfSDavid du Colombier if (a == FFLUSH) 16247dd7cddfSDavid du Colombier return files[i].fp; 16257dd7cddfSDavid du Colombier } 16267dd7cddfSDavid du Colombier if (a == FFLUSH) /* didn't find it, so don't create it! */ 16277dd7cddfSDavid du Colombier return NULL; 16287dd7cddfSDavid du Colombier 16293e12c5d1SDavid du Colombier for (i=0; i < FOPEN_MAX; i++) 16303e12c5d1SDavid du Colombier if (files[i].fp == 0) 16313e12c5d1SDavid du Colombier break; 16323e12c5d1SDavid du Colombier if (i >= FOPEN_MAX) 16337dd7cddfSDavid du Colombier FATAL("%s makes too many open files", s); 16343e12c5d1SDavid du Colombier fflush(stdout); /* force a semblance of order */ 16353e12c5d1SDavid du Colombier m = a; 16363e12c5d1SDavid du Colombier if (a == GT) { 1637219b2ee8SDavid du Colombier fp = fopen(s, "w"); 16383e12c5d1SDavid du Colombier } else if (a == APPEND) { 1639219b2ee8SDavid du Colombier fp = fopen(s, "a"); 16403e12c5d1SDavid du Colombier m = GT; /* so can mix > and >> */ 16413e12c5d1SDavid du Colombier } else if (a == '|') { /* output pipe */ 1642219b2ee8SDavid du Colombier fp = popen(s, "w"); 16433e12c5d1SDavid du Colombier } else if (a == LE) { /* input pipe */ 1644219b2ee8SDavid du Colombier fp = popen(s, "r"); 16453e12c5d1SDavid du Colombier } else if (a == LT) { /* getline <file */ 1646219b2ee8SDavid du Colombier fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 16473e12c5d1SDavid du Colombier } else /* can't happen */ 16487dd7cddfSDavid du Colombier FATAL("illegal redirection %d", a); 16493e12c5d1SDavid du Colombier if (fp != NULL) { 16503e12c5d1SDavid du Colombier files[i].fname = tostring(s); 16513e12c5d1SDavid du Colombier files[i].fp = fp; 16523e12c5d1SDavid du Colombier files[i].mode = m; 16533e12c5d1SDavid du Colombier } 16543e12c5d1SDavid du Colombier return fp; 16553e12c5d1SDavid du Colombier } 16563e12c5d1SDavid du Colombier 16577dd7cddfSDavid du Colombier char *filename(FILE *fp) 16583e12c5d1SDavid du Colombier { 16593e12c5d1SDavid du Colombier int i; 16603e12c5d1SDavid du Colombier 16613e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 16623e12c5d1SDavid du Colombier if (fp == files[i].fp) 16633e12c5d1SDavid du Colombier return files[i].fname; 1664219b2ee8SDavid du Colombier return "???"; 16653e12c5d1SDavid du Colombier } 16663e12c5d1SDavid du Colombier 16673e12c5d1SDavid du Colombier Cell *closefile(Node **a, int n) 16683e12c5d1SDavid du Colombier { 16697dd7cddfSDavid du Colombier Cell *x; 16703e12c5d1SDavid du Colombier int i, stat; 16713e12c5d1SDavid du Colombier 16727dd7cddfSDavid du Colombier n = n; 16733e12c5d1SDavid du Colombier x = execute(a[0]); 16743e12c5d1SDavid du Colombier getsval(x); 16753e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 16763e12c5d1SDavid du Colombier if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 16773e12c5d1SDavid du Colombier if (ferror(files[i].fp)) 16787dd7cddfSDavid du Colombier WARNING( "i/o error occurred on %s", files[i].fname ); 16793e12c5d1SDavid du Colombier if (files[i].mode == '|' || files[i].mode == LE) 16803e12c5d1SDavid du Colombier stat = pclose(files[i].fp); 16813e12c5d1SDavid du Colombier else 16823e12c5d1SDavid du Colombier stat = fclose(files[i].fp); 16833e12c5d1SDavid du Colombier if (stat == EOF) 16847dd7cddfSDavid du Colombier WARNING( "i/o error occurred closing %s", files[i].fname ); 1685219b2ee8SDavid du Colombier if (i > 2) /* don't do /dev/std... */ 16863e12c5d1SDavid du Colombier xfree(files[i].fname); 16873e12c5d1SDavid du Colombier files[i].fname = NULL; /* watch out for ref thru this */ 16883e12c5d1SDavid du Colombier files[i].fp = NULL; 16893e12c5d1SDavid du Colombier } 16903e12c5d1SDavid du Colombier tempfree(x); 16917dd7cddfSDavid du Colombier return(True); 16923e12c5d1SDavid du Colombier } 16933e12c5d1SDavid du Colombier 16943e12c5d1SDavid du Colombier void closeall(void) 16953e12c5d1SDavid du Colombier { 16963e12c5d1SDavid du Colombier int i, stat; 16973e12c5d1SDavid du Colombier 16983e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 16993e12c5d1SDavid du Colombier if (files[i].fp) { 17003e12c5d1SDavid du Colombier if (ferror(files[i].fp)) 17017dd7cddfSDavid du Colombier WARNING( "i/o error occurred on %s", files[i].fname ); 17023e12c5d1SDavid du Colombier if (files[i].mode == '|' || files[i].mode == LE) 17033e12c5d1SDavid du Colombier stat = pclose(files[i].fp); 17043e12c5d1SDavid du Colombier else 17053e12c5d1SDavid du Colombier stat = fclose(files[i].fp); 17063e12c5d1SDavid du Colombier if (stat == EOF) 17077dd7cddfSDavid du Colombier WARNING( "i/o error occurred while closing %s", files[i].fname ); 17083e12c5d1SDavid du Colombier } 17093e12c5d1SDavid du Colombier } 17103e12c5d1SDavid du Colombier 17117dd7cddfSDavid du Colombier void backsub(char **pb_ptr, char **sptr_ptr); 17123e12c5d1SDavid du Colombier 1713219b2ee8SDavid du Colombier Cell *sub(Node **a, int nnn) /* substitute command */ 17143e12c5d1SDavid du Colombier { 17157dd7cddfSDavid du Colombier char *sptr, *pb, *q; 17167dd7cddfSDavid du Colombier Cell *x, *y, *result; 17177dd7cddfSDavid du Colombier char *t, *buf; 17183e12c5d1SDavid du Colombier void *p; 17197dd7cddfSDavid du Colombier int bufsz = recsize; 17203e12c5d1SDavid du Colombier 17217dd7cddfSDavid du Colombier if ((buf = (char *) malloc(bufsz)) == NULL) 17227dd7cddfSDavid du Colombier FATAL("out of memory in sub"); 17233e12c5d1SDavid du Colombier x = execute(a[3]); /* target string */ 17243e12c5d1SDavid du Colombier t = getsval(x); 1725219b2ee8SDavid du Colombier if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 17263e12c5d1SDavid du Colombier p = (void *) a[1]; /* regular expression */ 17273e12c5d1SDavid du Colombier else { 17283e12c5d1SDavid du Colombier y = execute(a[1]); 17293e12c5d1SDavid du Colombier p = compre(getsval(y)); 17303e12c5d1SDavid du Colombier tempfree(y); 17313e12c5d1SDavid du Colombier } 17323e12c5d1SDavid du Colombier y = execute(a[2]); /* replacement string */ 17337dd7cddfSDavid du Colombier result = False; 17343e12c5d1SDavid du Colombier if (pmatch(p, t, t)) { 17353e12c5d1SDavid du Colombier sptr = t; 17367dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub"); 17377dd7cddfSDavid du Colombier pb = buf; 17383e12c5d1SDavid du Colombier while (sptr < patbeg) 17393e12c5d1SDavid du Colombier *pb++ = *sptr++; 17403e12c5d1SDavid du Colombier sptr = getsval(y); 17417dd7cddfSDavid du Colombier while (*sptr != 0) { 17427dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub"); 17437dd7cddfSDavid du Colombier if (*sptr == '\\') { 17447dd7cddfSDavid du Colombier backsub(&pb, &sptr); 17453e12c5d1SDavid du Colombier } else if (*sptr == '&') { 17463e12c5d1SDavid du Colombier sptr++; 17477dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub"); 17483e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 17493e12c5d1SDavid du Colombier *pb++ = *q++; 17503e12c5d1SDavid du Colombier } else 17513e12c5d1SDavid du Colombier *pb++ = *sptr++; 17527dd7cddfSDavid du Colombier } 17533e12c5d1SDavid du Colombier *pb = '\0'; 17547dd7cddfSDavid du Colombier if (pb > buf + bufsz) 17557dd7cddfSDavid du Colombier FATAL("sub result1 %.30s too big; can't happen", buf); 17563e12c5d1SDavid du Colombier sptr = patbeg + patlen; 17577dd7cddfSDavid du Colombier if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 17587dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub"); 17597dd7cddfSDavid du Colombier while ((*pb++ = *sptr++) != 0) 17603e12c5d1SDavid du Colombier ; 17617dd7cddfSDavid du Colombier } 17627dd7cddfSDavid du Colombier if (pb > buf + bufsz) 17637dd7cddfSDavid du Colombier FATAL("sub result2 %.30s too big; can't happen", buf); 17647dd7cddfSDavid du Colombier setsval(x, buf); /* BUG: should be able to avoid copy */ 17657dd7cddfSDavid du Colombier result = True;; 17663e12c5d1SDavid du Colombier } 17673e12c5d1SDavid du Colombier tempfree(x); 17683e12c5d1SDavid du Colombier tempfree(y); 17697dd7cddfSDavid du Colombier free(buf); 17703e12c5d1SDavid du Colombier return result; 17713e12c5d1SDavid du Colombier } 17723e12c5d1SDavid du Colombier 1773219b2ee8SDavid du Colombier Cell *gsub(Node **a, int nnn) /* global substitute */ 17743e12c5d1SDavid du Colombier { 17757dd7cddfSDavid du Colombier Cell *x, *y; 17767dd7cddfSDavid du Colombier char *rptr, *sptr, *t, *pb, *c; 17777dd7cddfSDavid du Colombier char *buf; 17787dd7cddfSDavid du Colombier void *p; 17793e12c5d1SDavid du Colombier int mflag, num; 17807dd7cddfSDavid du Colombier int bufsz = recsize; 17813e12c5d1SDavid du Colombier 17827dd7cddfSDavid du Colombier if ((buf = (char *)malloc(bufsz)) == NULL) 17837dd7cddfSDavid du Colombier FATAL("out of memory in gsub"); 17843e12c5d1SDavid du Colombier mflag = 0; /* if mflag == 0, can replace empty string */ 17853e12c5d1SDavid du Colombier num = 0; 17863e12c5d1SDavid du Colombier x = execute(a[3]); /* target string */ 17873e12c5d1SDavid du Colombier c = t = getsval(x); 1788219b2ee8SDavid du Colombier if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 17893e12c5d1SDavid du Colombier p = (void *) a[1]; /* regular expression */ 17903e12c5d1SDavid du Colombier else { 17913e12c5d1SDavid du Colombier y = execute(a[1]); 17923e12c5d1SDavid du Colombier p = compre(getsval(y)); 17933e12c5d1SDavid du Colombier tempfree(y); 17943e12c5d1SDavid du Colombier } 17953e12c5d1SDavid du Colombier y = execute(a[2]); /* replacement string */ 17963e12c5d1SDavid du Colombier if (pmatch(p, t, c)) { 17973e12c5d1SDavid du Colombier pb = buf; 17983e12c5d1SDavid du Colombier rptr = getsval(y); 17993e12c5d1SDavid du Colombier do { 18003e12c5d1SDavid du Colombier if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 18013e12c5d1SDavid du Colombier if (mflag == 0) { /* can replace empty */ 18023e12c5d1SDavid du Colombier num++; 18033e12c5d1SDavid du Colombier sptr = rptr; 18047dd7cddfSDavid du Colombier while (*sptr != 0) { 18057dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 18067dd7cddfSDavid du Colombier if (*sptr == '\\') { 18077dd7cddfSDavid du Colombier backsub(&pb, &sptr); 18083e12c5d1SDavid du Colombier } else if (*sptr == '&') { 18097dd7cddfSDavid du Colombier char *q; 18103e12c5d1SDavid du Colombier sptr++; 18117dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 18123e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 18133e12c5d1SDavid du Colombier *pb++ = *q++; 18143e12c5d1SDavid du Colombier } else 18153e12c5d1SDavid du Colombier *pb++ = *sptr++; 18163e12c5d1SDavid du Colombier } 18177dd7cddfSDavid du Colombier } 18183e12c5d1SDavid du Colombier if (*c == 0) /* at end */ 18193e12c5d1SDavid du Colombier goto done; 18207dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub"); 18213e12c5d1SDavid du Colombier *pb++ = *c++; 18227dd7cddfSDavid du Colombier if (pb > buf + bufsz) /* BUG: not sure of this test */ 18237dd7cddfSDavid du Colombier FATAL("gsub result0 %.30s too big; can't happen", buf); 18243e12c5d1SDavid du Colombier mflag = 0; 18253e12c5d1SDavid du Colombier } 18263e12c5d1SDavid du Colombier else { /* matched nonempty string */ 18273e12c5d1SDavid du Colombier num++; 18283e12c5d1SDavid du Colombier sptr = c; 18297dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub"); 18307dd7cddfSDavid du Colombier while (sptr < patbeg) 18313e12c5d1SDavid du Colombier *pb++ = *sptr++; 18323e12c5d1SDavid du Colombier sptr = rptr; 18337dd7cddfSDavid du Colombier while (*sptr != 0) { 18347dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub"); 18357dd7cddfSDavid du Colombier if (*sptr == '\\') { 18367dd7cddfSDavid du Colombier backsub(&pb, &sptr); 18373e12c5d1SDavid du Colombier } else if (*sptr == '&') { 18387dd7cddfSDavid du Colombier char *q; 18393e12c5d1SDavid du Colombier sptr++; 18407dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub"); 18413e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 18423e12c5d1SDavid du Colombier *pb++ = *q++; 18433e12c5d1SDavid du Colombier } else 18443e12c5d1SDavid du Colombier *pb++ = *sptr++; 18457dd7cddfSDavid du Colombier } 18463e12c5d1SDavid du Colombier c = patbeg + patlen; 18473e12c5d1SDavid du Colombier if ((c[-1] == 0) || (*c == 0)) 18483e12c5d1SDavid du Colombier goto done; 18497dd7cddfSDavid du Colombier if (pb > buf + bufsz) 18507dd7cddfSDavid du Colombier FATAL("gsub result1 %.30s too big; can't happen", buf); 18513e12c5d1SDavid du Colombier mflag = 1; 18523e12c5d1SDavid du Colombier } 18533e12c5d1SDavid du Colombier } while (pmatch(p, t, c)); 18543e12c5d1SDavid du Colombier sptr = c; 18557dd7cddfSDavid du Colombier adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub"); 18567dd7cddfSDavid du Colombier while ((*pb++ = *sptr++) != 0) 18573e12c5d1SDavid du Colombier ; 18587dd7cddfSDavid du Colombier done: if (pb > buf + bufsz) 18597dd7cddfSDavid du Colombier FATAL("gsub result2 %.30s too big; can't happen", buf); 18603e12c5d1SDavid du Colombier *pb = '\0'; 18617dd7cddfSDavid du Colombier setsval(x, buf); /* BUG: should be able to avoid copy + free */ 18623e12c5d1SDavid du Colombier } 18633e12c5d1SDavid du Colombier tempfree(x); 18643e12c5d1SDavid du Colombier tempfree(y); 18653e12c5d1SDavid du Colombier x = gettemp(); 18663e12c5d1SDavid du Colombier x->tval = NUM; 18673e12c5d1SDavid du Colombier x->fval = num; 18687dd7cddfSDavid du Colombier free(buf); 18693e12c5d1SDavid du Colombier return(x); 18703e12c5d1SDavid du Colombier } 18717dd7cddfSDavid du Colombier 18727dd7cddfSDavid du Colombier void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */ 18737dd7cddfSDavid du Colombier { /* sptr[0] == '\\' */ 18747dd7cddfSDavid du Colombier char *pb = *pb_ptr, *sptr = *sptr_ptr; 18757dd7cddfSDavid du Colombier 18767dd7cddfSDavid du Colombier if (sptr[1] == '\\') { 18777dd7cddfSDavid du Colombier if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 18787dd7cddfSDavid du Colombier *pb++ = '\\'; 18797dd7cddfSDavid du Colombier *pb++ = '&'; 18807dd7cddfSDavid du Colombier sptr += 4; 18817dd7cddfSDavid du Colombier } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 18827dd7cddfSDavid du Colombier *pb++ = '\\'; 18837dd7cddfSDavid du Colombier sptr += 2; 18847dd7cddfSDavid du Colombier } else { /* \\x -> \\x */ 18857dd7cddfSDavid du Colombier *pb++ = *sptr++; 18867dd7cddfSDavid du Colombier *pb++ = *sptr++; 18877dd7cddfSDavid du Colombier } 18887dd7cddfSDavid du Colombier } else if (sptr[1] == '&') { /* literal & */ 18897dd7cddfSDavid du Colombier sptr++; 18907dd7cddfSDavid du Colombier *pb++ = *sptr++; 18917dd7cddfSDavid du Colombier } else /* literal \ */ 18927dd7cddfSDavid du Colombier *pb++ = *sptr++; 18937dd7cddfSDavid du Colombier 18947dd7cddfSDavid du Colombier *pb_ptr = pb; 18957dd7cddfSDavid du Colombier *sptr_ptr = sptr; 18967dd7cddfSDavid du Colombier } 1897