13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier Copyright (c) 1989 AT&T 33e12c5d1SDavid du Colombier All Rights Reserved 43e12c5d1SDavid du Colombier 53e12c5d1SDavid du Colombier THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier The copyright notice above does not evidence any 83e12c5d1SDavid du Colombier actual or intended publication of such source code. 93e12c5d1SDavid du Colombier */ 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier #define tempfree(x) if (istemp(x)) tfree(x); else 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier #define DEBUG 143e12c5d1SDavid du Colombier #include <stdio.h> 153e12c5d1SDavid du Colombier #include <ctype.h> 163e12c5d1SDavid du Colombier #include <setjmp.h> 173e12c5d1SDavid du Colombier #include <math.h> 183e12c5d1SDavid du Colombier #include <string.h> 193e12c5d1SDavid du Colombier #include <stdlib.h> 203e12c5d1SDavid du Colombier #include <time.h> 213e12c5d1SDavid du Colombier #include <libv.h> 223e12c5d1SDavid du Colombier #include "awk.h" 233e12c5d1SDavid du Colombier #include "y.tab.h" 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier #ifdef _NFILE 263e12c5d1SDavid du Colombier #ifndef FOPEN_MAX 273e12c5d1SDavid du Colombier #define FOPEN_MAX _NFILE 283e12c5d1SDavid du Colombier #endif 293e12c5d1SDavid du Colombier #endif 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier #ifndef FOPEN_MAX 323e12c5d1SDavid du Colombier #define FOPEN_MAX 40 /* max number of open files */ 333e12c5d1SDavid du Colombier #endif 343e12c5d1SDavid du Colombier 353e12c5d1SDavid du Colombier #ifndef RAND_MAX 363e12c5d1SDavid du Colombier #define RAND_MAX 32767 /* all that ansi guarantees */ 373e12c5d1SDavid du Colombier #endif 383e12c5d1SDavid du Colombier 393e12c5d1SDavid du Colombier jmp_buf env; 403e12c5d1SDavid du Colombier 41*219b2ee8SDavid du Colombier /* an attempt to go a bit faster: */ 42*219b2ee8SDavid du Colombier 43*219b2ee8SDavid du Colombier /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */ 44*219b2ee8SDavid du Colombier #define execute(p) r_execute(p) 45*219b2ee8SDavid du Colombier 463e12c5d1SDavid du Colombier #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) 473e12c5d1SDavid du Colombier #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier 50*219b2ee8SDavid du Colombier #define PA2NUM 29 /* max number of pat,pat patterns allowed */ 51*219b2ee8SDavid du Colombier int paircnt; /* number of them in use */ 52*219b2ee8SDavid du Colombier int pairstack[PA2NUM]; /* state of each pat,pat */ 53*219b2ee8SDavid du Colombier 54*219b2ee8SDavid du Colombier Node *winner = NULL; /* root of parse tree */ 55*219b2ee8SDavid du Colombier Cell *tmps; /* free temporary cells for execution */ 563e12c5d1SDavid du Colombier 573e12c5d1SDavid du Colombier static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM }; 583e12c5d1SDavid du Colombier Cell *true = &truecell; 593e12c5d1SDavid du Colombier static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM }; 603e12c5d1SDavid du Colombier Cell *false = &falsecell; 613e12c5d1SDavid du Colombier static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM }; 623e12c5d1SDavid du Colombier Cell *jbreak = &breakcell; 633e12c5d1SDavid du Colombier static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM }; 643e12c5d1SDavid du Colombier Cell *jcont = &contcell; 653e12c5d1SDavid du Colombier static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM }; 663e12c5d1SDavid du Colombier Cell *jnext = &nextcell; 673e12c5d1SDavid du Colombier static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; 683e12c5d1SDavid du Colombier Cell *jexit = &exitcell; 693e12c5d1SDavid du Colombier static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; 703e12c5d1SDavid du Colombier Cell *jret = &retcell; 713e12c5d1SDavid du Colombier static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM }; 723e12c5d1SDavid du Colombier 733e12c5d1SDavid du Colombier Node *curnode = NULL; /* the node being executed, for debugging */ 743e12c5d1SDavid du Colombier 75*219b2ee8SDavid du Colombier void run(Node *a) /* execution of parse tree starts here */ 763e12c5d1SDavid du Colombier { 773e12c5d1SDavid du Colombier execute(a); 783e12c5d1SDavid du Colombier closeall(); 793e12c5d1SDavid du Colombier } 803e12c5d1SDavid du Colombier 81*219b2ee8SDavid du Colombier Cell *r_execute(Node *u) /* execute a node of the parse tree */ 823e12c5d1SDavid du Colombier { 833e12c5d1SDavid du Colombier register Cell *(*proc)(Node **, int); 843e12c5d1SDavid du Colombier register Cell *x; 853e12c5d1SDavid du Colombier register Node *a; 863e12c5d1SDavid du Colombier 873e12c5d1SDavid du Colombier if (u == NULL) 883e12c5d1SDavid du Colombier return(true); 893e12c5d1SDavid du Colombier for (a = u; ; a = a->nnext) { 903e12c5d1SDavid du Colombier curnode = a; 913e12c5d1SDavid du Colombier if (isvalue(a)) { 923e12c5d1SDavid du Colombier x = (Cell *) (a->narg[0]); 933e12c5d1SDavid du Colombier if ((x->tval & FLD) && !donefld) 943e12c5d1SDavid du Colombier fldbld(); 953e12c5d1SDavid du Colombier else if ((x->tval & REC) && !donerec) 963e12c5d1SDavid du Colombier recbld(); 973e12c5d1SDavid du Colombier return(x); 983e12c5d1SDavid du Colombier } 993e12c5d1SDavid du Colombier if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */ 1003e12c5d1SDavid du Colombier ERROR "illegal statement" FATAL; 1013e12c5d1SDavid du Colombier proc = proctab[a->nobj-FIRSTTOKEN]; 1023e12c5d1SDavid du Colombier x = (*proc)(a->narg, a->nobj); 1033e12c5d1SDavid du Colombier if ((x->tval & FLD) && !donefld) 1043e12c5d1SDavid du Colombier fldbld(); 1053e12c5d1SDavid du Colombier else if ((x->tval & REC) && !donerec) 1063e12c5d1SDavid du Colombier recbld(); 1073e12c5d1SDavid du Colombier if (isexpr(a)) 1083e12c5d1SDavid du Colombier return(x); 1093e12c5d1SDavid du Colombier if (isjump(x)) 1103e12c5d1SDavid du Colombier return(x); 1113e12c5d1SDavid du Colombier if (a->nnext == NULL) 1123e12c5d1SDavid du Colombier return(x); 1133e12c5d1SDavid du Colombier tempfree(x); 1143e12c5d1SDavid du Colombier } 1153e12c5d1SDavid du Colombier } 1163e12c5d1SDavid du Colombier 1173e12c5d1SDavid du Colombier 118*219b2ee8SDavid du Colombier Cell *program(Node **a, int n) /* execute an awk program */ 119*219b2ee8SDavid du Colombier { /* a[0] = BEGIN, a[1] = body, a[2] = END */ 1203e12c5d1SDavid du Colombier register Cell *x; 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier if (setjmp(env) != 0) 1233e12c5d1SDavid du Colombier goto ex; 1243e12c5d1SDavid du Colombier if (a[0]) { /* BEGIN */ 1253e12c5d1SDavid du Colombier x = execute(a[0]); 1263e12c5d1SDavid du Colombier if (isexit(x)) 1273e12c5d1SDavid du Colombier return(true); 1283e12c5d1SDavid du Colombier if (isjump(x)) 1293e12c5d1SDavid du Colombier ERROR "illegal break, continue or next from BEGIN" FATAL; 1303e12c5d1SDavid du Colombier tempfree(x); 1313e12c5d1SDavid du Colombier } 1323e12c5d1SDavid du Colombier loop: 1333e12c5d1SDavid du Colombier if (a[1] || a[2]) 1343e12c5d1SDavid du Colombier while (getrec(record) > 0) { 1353e12c5d1SDavid du Colombier x = execute(a[1]); 1363e12c5d1SDavid du Colombier if (isexit(x)) 1373e12c5d1SDavid du Colombier break; 1383e12c5d1SDavid du Colombier tempfree(x); 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier ex: 1413e12c5d1SDavid du Colombier if (setjmp(env) != 0) /* handles exit within END */ 1423e12c5d1SDavid du Colombier goto ex1; 1433e12c5d1SDavid du Colombier if (a[2]) { /* END */ 1443e12c5d1SDavid du Colombier x = execute(a[2]); 1453e12c5d1SDavid du Colombier if (isbreak(x) || isnext(x) || iscont(x)) 1463e12c5d1SDavid du Colombier ERROR "illegal break, next, or continue from END" FATAL; 1473e12c5d1SDavid du Colombier tempfree(x); 1483e12c5d1SDavid du Colombier } 1493e12c5d1SDavid du Colombier ex1: 1503e12c5d1SDavid du Colombier return(true); 1513e12c5d1SDavid du Colombier } 1523e12c5d1SDavid du Colombier 153*219b2ee8SDavid du Colombier struct Frame { /* stack frame for awk function calls */ 1543e12c5d1SDavid du Colombier int nargs; /* number of arguments in this call */ 1553e12c5d1SDavid du Colombier Cell *fcncell; /* pointer to Cell for function */ 1563e12c5d1SDavid du Colombier Cell **args; /* pointer to array of arguments after execute */ 1573e12c5d1SDavid du Colombier Cell *retval; /* return value */ 1583e12c5d1SDavid du Colombier }; 1593e12c5d1SDavid du Colombier 160*219b2ee8SDavid du Colombier #define NARGS 50 /* max args in a call */ 1613e12c5d1SDavid du Colombier 1623e12c5d1SDavid du Colombier struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ 1633e12c5d1SDavid du Colombier int nframe = 0; /* number of frames allocated */ 1643e12c5d1SDavid du Colombier struct Frame *fp = NULL; /* frame pointer. bottom level unused */ 1653e12c5d1SDavid du Colombier 166*219b2ee8SDavid du Colombier Cell *call(Node **a, int n) /* function call. very kludgy and fragile */ 1673e12c5d1SDavid du Colombier { 1683e12c5d1SDavid du Colombier static Cell newcopycell = { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE }; 1693e12c5d1SDavid du Colombier int i, ncall, ndef; 1703e12c5d1SDavid du Colombier Node *x; 1713e12c5d1SDavid du Colombier Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; 1723e12c5d1SDavid du Colombier uchar *s; 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier fcn = execute(a[0]); /* the function itself */ 1753e12c5d1SDavid du Colombier s = fcn->nval; 1763e12c5d1SDavid du Colombier if (!isfunc(fcn)) 1773e12c5d1SDavid du Colombier ERROR "calling undefined function %s", s FATAL; 1783e12c5d1SDavid du Colombier if (frame == NULL) { 1793e12c5d1SDavid du Colombier fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); 1803e12c5d1SDavid du Colombier if (frame == NULL) 1813e12c5d1SDavid du Colombier ERROR "out of space for stack frames calling %s", s FATAL; 1823e12c5d1SDavid du Colombier } 1833e12c5d1SDavid du Colombier for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 1843e12c5d1SDavid du Colombier ncall++; 1853e12c5d1SDavid du Colombier ndef = (int) fcn->fval; /* args in defn */ 1863e12c5d1SDavid du Colombier dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); 1873e12c5d1SDavid du Colombier if (ncall > ndef) 1883e12c5d1SDavid du Colombier ERROR "function %s called with %d args, uses only %d", 1893e12c5d1SDavid du Colombier s, ncall, ndef WARNING; 1903e12c5d1SDavid du Colombier if (ncall + ndef > NARGS) 1913e12c5d1SDavid du Colombier ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL; 1923e12c5d1SDavid du Colombier for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ 1933e12c5d1SDavid du Colombier dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); 1943e12c5d1SDavid du Colombier y = execute(x); 1953e12c5d1SDavid du Colombier oargs[i] = y; 1963e12c5d1SDavid du Colombier dprintf( ("args[%d]: %s %f <%s>, t=%o\n", 1973e12c5d1SDavid du Colombier i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) ); 1983e12c5d1SDavid du Colombier if (isfunc(y)) 1993e12c5d1SDavid du Colombier ERROR "can't use function %s as argument in %s", y->nval, s FATAL; 2003e12c5d1SDavid du Colombier if (isarr(y)) 2013e12c5d1SDavid du Colombier args[i] = y; /* arrays by ref */ 2023e12c5d1SDavid du Colombier else 2033e12c5d1SDavid du Colombier args[i] = copycell(y); 2043e12c5d1SDavid du Colombier tempfree(y); 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier for ( ; i < ndef; i++) { /* add null args for ones not provided */ 2073e12c5d1SDavid du Colombier args[i] = gettemp(); 2083e12c5d1SDavid du Colombier *args[i] = newcopycell; 2093e12c5d1SDavid du Colombier } 2103e12c5d1SDavid du Colombier fp++; /* now ok to up frame */ 2113e12c5d1SDavid du Colombier if (fp >= frame + nframe) { 2123e12c5d1SDavid du Colombier int dfp = fp - frame; /* old index */ 2133e12c5d1SDavid du Colombier frame = (struct Frame *) 214*219b2ee8SDavid du Colombier realloc((char *) frame, (nframe += 100) * sizeof(struct Frame)); 2153e12c5d1SDavid du Colombier if (frame == NULL) 2163e12c5d1SDavid du Colombier ERROR "out of space for stack frames in %s", s FATAL; 2173e12c5d1SDavid du Colombier fp = frame + dfp; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier fp->fcncell = fcn; 2203e12c5d1SDavid du Colombier fp->args = args; 2213e12c5d1SDavid du Colombier fp->nargs = ndef; /* number defined with (excess are locals) */ 2223e12c5d1SDavid du Colombier fp->retval = gettemp(); 2233e12c5d1SDavid du Colombier 2243e12c5d1SDavid du Colombier dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); 2253e12c5d1SDavid du Colombier y = execute((Node *)(fcn->sval)); /* execute body */ 2263e12c5d1SDavid du Colombier dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); 2273e12c5d1SDavid du Colombier 2283e12c5d1SDavid du Colombier for (i = 0; i < ndef; i++) { 2293e12c5d1SDavid du Colombier Cell *t = fp->args[i]; 2303e12c5d1SDavid du Colombier if (isarr(t)) { 2313e12c5d1SDavid du Colombier if (t->csub == CCOPY) { 2323e12c5d1SDavid du Colombier if (i >= ncall) { 2333e12c5d1SDavid du Colombier freesymtab(t); 2343e12c5d1SDavid du Colombier t->csub = CTEMP; 2353e12c5d1SDavid du Colombier } else { 2363e12c5d1SDavid du Colombier oargs[i]->tval = t->tval; 2373e12c5d1SDavid du Colombier oargs[i]->tval &= ~(STR|NUM|DONTFREE); 2383e12c5d1SDavid du Colombier oargs[i]->sval = t->sval; 2393e12c5d1SDavid du Colombier tempfree(t); 2403e12c5d1SDavid du Colombier } 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier } else if (t != y) { /* kludge to prevent freeing twice */ 2433e12c5d1SDavid du Colombier t->csub = CTEMP; 2443e12c5d1SDavid du Colombier tempfree(t); 2453e12c5d1SDavid du Colombier } 2463e12c5d1SDavid du Colombier } 2473e12c5d1SDavid du Colombier tempfree(fcn); 2483e12c5d1SDavid du Colombier if (isexit(y) || isnext(y)) 2493e12c5d1SDavid du Colombier return y; 2503e12c5d1SDavid du Colombier tempfree(y); /* this can free twice! */ 2513e12c5d1SDavid du Colombier z = fp->retval; /* return value */ 2523e12c5d1SDavid du Colombier dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); 2533e12c5d1SDavid du Colombier fp--; 2543e12c5d1SDavid du Colombier return(z); 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier 2573e12c5d1SDavid du Colombier Cell *copycell(Cell *x) /* make a copy of a cell in a temp */ 2583e12c5d1SDavid du Colombier { 2593e12c5d1SDavid du Colombier Cell *y; 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier y = gettemp(); 2623e12c5d1SDavid du Colombier y->csub = CCOPY; /* prevents freeing until call is over */ 2633e12c5d1SDavid du Colombier y->nval = x->nval; 2643e12c5d1SDavid du Colombier y->sval = x->sval ? tostring(x->sval) : NULL; 2653e12c5d1SDavid du Colombier y->fval = x->fval; 2663e12c5d1SDavid du Colombier y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ 2673e12c5d1SDavid du Colombier /* is DONTFREE right? */ 2683e12c5d1SDavid du Colombier return y; 2693e12c5d1SDavid du Colombier } 2703e12c5d1SDavid du Colombier 271*219b2ee8SDavid du Colombier Cell *arg(Node **a, int n) /* nth argument of a function */ 2723e12c5d1SDavid du Colombier { 2733e12c5d1SDavid du Colombier 2743e12c5d1SDavid du Colombier n = (int) a[0]; /* argument number, counting from 0 */ 2753e12c5d1SDavid du Colombier dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); 2763e12c5d1SDavid du Colombier if (n+1 > fp->nargs) 2773e12c5d1SDavid du Colombier ERROR "argument #%d of function %s was not supplied", 2783e12c5d1SDavid du Colombier n+1, fp->fcncell->nval FATAL; 2793e12c5d1SDavid du Colombier return fp->args[n]; 2803e12c5d1SDavid du Colombier } 2813e12c5d1SDavid du Colombier 282*219b2ee8SDavid du Colombier Cell *jump(Node **a, int n) /* break, continue, next, continue, return */ 2833e12c5d1SDavid du Colombier { 2843e12c5d1SDavid du Colombier register Cell *y; 2853e12c5d1SDavid du Colombier 2863e12c5d1SDavid du Colombier switch (n) { 2873e12c5d1SDavid du Colombier case EXIT: 2883e12c5d1SDavid du Colombier if (a[0] != NULL) { 2893e12c5d1SDavid du Colombier y = execute(a[0]); 2903e12c5d1SDavid du Colombier errorflag = getfval(y); 2913e12c5d1SDavid du Colombier tempfree(y); 2923e12c5d1SDavid du Colombier } 2933e12c5d1SDavid du Colombier longjmp(env, 1); 2943e12c5d1SDavid du Colombier case RETURN: 2953e12c5d1SDavid du Colombier if (a[0] != NULL) { 2963e12c5d1SDavid du Colombier y = execute(a[0]); 2973e12c5d1SDavid du Colombier if ((y->tval & (STR|NUM)) == (STR|NUM)) { 2983e12c5d1SDavid du Colombier setsval(fp->retval, getsval(y)); 2993e12c5d1SDavid du Colombier fp->retval->fval = getfval(y); 3003e12c5d1SDavid du Colombier fp->retval->tval |= NUM; 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier else if (y->tval & STR) 3033e12c5d1SDavid du Colombier setsval(fp->retval, getsval(y)); 3043e12c5d1SDavid du Colombier else if (y->tval & NUM) 3053e12c5d1SDavid du Colombier setfval(fp->retval, getfval(y)); 3063e12c5d1SDavid du Colombier else /* can't happen */ 3073e12c5d1SDavid du Colombier ERROR "bad type variable %d", y->tval FATAL; 3083e12c5d1SDavid du Colombier tempfree(y); 3093e12c5d1SDavid du Colombier } 3103e12c5d1SDavid du Colombier return(jret); 3113e12c5d1SDavid du Colombier case NEXT: 3123e12c5d1SDavid du Colombier return(jnext); 3133e12c5d1SDavid du Colombier case BREAK: 3143e12c5d1SDavid du Colombier return(jbreak); 3153e12c5d1SDavid du Colombier case CONTINUE: 3163e12c5d1SDavid du Colombier return(jcont); 3173e12c5d1SDavid du Colombier default: /* can't happen */ 3183e12c5d1SDavid du Colombier ERROR "illegal jump type %d", n FATAL; 3193e12c5d1SDavid du Colombier } 3203e12c5d1SDavid du Colombier return 0; /* not reached */ 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier 323*219b2ee8SDavid du Colombier Cell *getline(Node **a, int n) /* get next line from specific input */ 324*219b2ee8SDavid du Colombier { /* a[0] is variable, a[1] is operator, a[2] is filename */ 3253e12c5d1SDavid du Colombier register Cell *r, *x; 3263e12c5d1SDavid du Colombier uchar buf[RECSIZE]; 3273e12c5d1SDavid du Colombier FILE *fp; 3283e12c5d1SDavid du Colombier 3293e12c5d1SDavid du Colombier fflush(stdout); /* in case someone is waiting for a prompt */ 3303e12c5d1SDavid du Colombier r = gettemp(); 3313e12c5d1SDavid du Colombier if (a[1] != NULL) { /* getline < file */ 3323e12c5d1SDavid du Colombier x = execute(a[2]); /* filename */ 3333e12c5d1SDavid du Colombier if ((int) a[1] == '|') /* input pipe */ 3343e12c5d1SDavid du Colombier a[1] = (Node *) LE; /* arbitrary flag */ 3353e12c5d1SDavid du Colombier fp = openfile((int) a[1], getsval(x)); 3363e12c5d1SDavid du Colombier tempfree(x); 3373e12c5d1SDavid du Colombier if (fp == NULL) 3383e12c5d1SDavid du Colombier n = -1; 3393e12c5d1SDavid du Colombier else 3403e12c5d1SDavid du Colombier n = readrec(buf, sizeof(buf), fp); 3413e12c5d1SDavid du Colombier if (n <= 0) { 3423e12c5d1SDavid du Colombier ; 3433e12c5d1SDavid du Colombier } else if (a[0] != NULL) { /* getline var <file */ 3443e12c5d1SDavid du Colombier setsval(execute(a[0]), buf); 3453e12c5d1SDavid du Colombier } else { /* getline <file */ 3463e12c5d1SDavid du Colombier if (!(recloc->tval & DONTFREE)) 3473e12c5d1SDavid du Colombier xfree(recloc->sval); 3483e12c5d1SDavid du Colombier strcpy(record, buf); 3493e12c5d1SDavid du Colombier recloc->sval = record; 3503e12c5d1SDavid du Colombier recloc->tval = REC | STR | DONTFREE; 3513e12c5d1SDavid du Colombier if (isnumber(recloc->sval)) { 3523e12c5d1SDavid du Colombier recloc->fval = atof(recloc->sval); 3533e12c5d1SDavid du Colombier recloc->tval |= NUM; 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier donerec = 1; donefld = 0; 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier } else { /* bare getline; use current input */ 3583e12c5d1SDavid du Colombier if (a[0] == NULL) /* getline */ 3593e12c5d1SDavid du Colombier n = getrec(record); 3603e12c5d1SDavid du Colombier else { /* getline var */ 3613e12c5d1SDavid du Colombier n = getrec(buf); 3623e12c5d1SDavid du Colombier setsval(execute(a[0]), buf); 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier } 3653e12c5d1SDavid du Colombier setfval(r, (Awkfloat) n); 3663e12c5d1SDavid du Colombier return r; 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier 369*219b2ee8SDavid du Colombier Cell *getnf(Node **a, int n) /* get NF */ 3703e12c5d1SDavid du Colombier { 3713e12c5d1SDavid du Colombier if (donefld == 0) 3723e12c5d1SDavid du Colombier fldbld(); 3733e12c5d1SDavid du Colombier return (Cell *) a[0]; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier 376*219b2ee8SDavid du Colombier Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 3773e12c5d1SDavid du Colombier { 3783e12c5d1SDavid du Colombier register Cell *x, *y, *z; 3793e12c5d1SDavid du Colombier register uchar *s; 3803e12c5d1SDavid du Colombier register Node *np; 3813e12c5d1SDavid du Colombier uchar buf[RECSIZE]; 3823e12c5d1SDavid du Colombier 3833e12c5d1SDavid du Colombier x = execute(a[0]); /* Cell* for symbol table */ 3843e12c5d1SDavid du Colombier buf[0] = 0; 3853e12c5d1SDavid du Colombier for (np = a[1]; np; np = np->nnext) { 3863e12c5d1SDavid du Colombier y = execute(np); /* subscript */ 3873e12c5d1SDavid du Colombier s = getsval(y); 3883e12c5d1SDavid du Colombier strcat(buf, s); 3893e12c5d1SDavid du Colombier if (np->nnext) 3903e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 3913e12c5d1SDavid du Colombier tempfree(y); 3923e12c5d1SDavid du Colombier } 3933e12c5d1SDavid du Colombier if (!isarr(x)) { 3943e12c5d1SDavid du Colombier dprintf( ("making %s into an array\n", x->nval) ); 3953e12c5d1SDavid du Colombier if (freeable(x)) 3963e12c5d1SDavid du Colombier xfree(x->sval); 3973e12c5d1SDavid du Colombier x->tval &= ~(STR|NUM|DONTFREE); 3983e12c5d1SDavid du Colombier x->tval |= ARR; 3993e12c5d1SDavid du Colombier x->sval = (uchar *) makesymtab(NSYMTAB); 4003e12c5d1SDavid du Colombier } 4013e12c5d1SDavid du Colombier z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); 4023e12c5d1SDavid du Colombier z->ctype = OCELL; 4033e12c5d1SDavid du Colombier z->csub = CVAR; 4043e12c5d1SDavid du Colombier tempfree(x); 4053e12c5d1SDavid du Colombier return(z); 4063e12c5d1SDavid du Colombier } 4073e12c5d1SDavid du Colombier 408*219b2ee8SDavid du Colombier Cell *adelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 4093e12c5d1SDavid du Colombier { 4103e12c5d1SDavid du Colombier Cell *x, *y; 4113e12c5d1SDavid du Colombier Node *np; 4123e12c5d1SDavid du Colombier uchar buf[RECSIZE], *s; 4133e12c5d1SDavid du Colombier 4143e12c5d1SDavid du Colombier x = execute(a[0]); /* Cell* for symbol table */ 4153e12c5d1SDavid du Colombier if (!isarr(x)) 4163e12c5d1SDavid du Colombier return true; 4173e12c5d1SDavid du Colombier buf[0] = 0; 4183e12c5d1SDavid du Colombier for (np = a[1]; np; np = np->nnext) { 4193e12c5d1SDavid du Colombier y = execute(np); /* subscript */ 4203e12c5d1SDavid du Colombier s = getsval(y); 4213e12c5d1SDavid du Colombier strcat(buf, s); 4223e12c5d1SDavid du Colombier if (np->nnext) 4233e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 4243e12c5d1SDavid du Colombier tempfree(y); 4253e12c5d1SDavid du Colombier } 4263e12c5d1SDavid du Colombier freeelem(x, buf); 4273e12c5d1SDavid du Colombier tempfree(x); 4283e12c5d1SDavid du Colombier return true; 4293e12c5d1SDavid du Colombier } 4303e12c5d1SDavid du Colombier 431*219b2ee8SDavid du Colombier Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ 4323e12c5d1SDavid du Colombier { 4333e12c5d1SDavid du Colombier register Cell *x, *ap, *k; 4343e12c5d1SDavid du Colombier Node *p; 4353e12c5d1SDavid du Colombier char buf[RECSIZE]; 4363e12c5d1SDavid du Colombier uchar *s; 4373e12c5d1SDavid du Colombier 4383e12c5d1SDavid du Colombier ap = execute(a[1]); /* array name */ 4393e12c5d1SDavid du Colombier if (!isarr(ap)) { 4403e12c5d1SDavid du Colombier dprintf( ("making %s into an array\n", ap->nval) ); 4413e12c5d1SDavid du Colombier if (freeable(ap)) 4423e12c5d1SDavid du Colombier xfree(ap->sval); 4433e12c5d1SDavid du Colombier ap->tval &= ~(STR|NUM|DONTFREE); 4443e12c5d1SDavid du Colombier ap->tval |= ARR; 4453e12c5d1SDavid du Colombier ap->sval = (uchar *) makesymtab(NSYMTAB); 4463e12c5d1SDavid du Colombier } 4473e12c5d1SDavid du Colombier buf[0] = 0; 4483e12c5d1SDavid du Colombier for (p = a[0]; p; p = p->nnext) { 4493e12c5d1SDavid du Colombier x = execute(p); /* expr */ 4503e12c5d1SDavid du Colombier s = getsval(x); 4513e12c5d1SDavid du Colombier strcat(buf, s); 4523e12c5d1SDavid du Colombier tempfree(x); 4533e12c5d1SDavid du Colombier if (p->nnext) 4543e12c5d1SDavid du Colombier strcat(buf, *SUBSEP); 4553e12c5d1SDavid du Colombier } 4563e12c5d1SDavid du Colombier k = lookup(buf, (Array *) ap->sval); 4573e12c5d1SDavid du Colombier tempfree(ap); 4583e12c5d1SDavid du Colombier if (k == NULL) 4593e12c5d1SDavid du Colombier return(false); 4603e12c5d1SDavid du Colombier else 4613e12c5d1SDavid du Colombier return(true); 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier 4643e12c5d1SDavid du Colombier 465*219b2ee8SDavid du Colombier Cell *matchop(Node **a, int n) /* ~ and match() */ 4663e12c5d1SDavid du Colombier { 4673e12c5d1SDavid du Colombier register Cell *x, *y; 4683e12c5d1SDavid du Colombier register uchar *s, *t; 4693e12c5d1SDavid du Colombier register int i; 4703e12c5d1SDavid du Colombier void *p; 4713e12c5d1SDavid du Colombier 472*219b2ee8SDavid du Colombier x = execute(a[1]); /* a[1] = target text */ 4733e12c5d1SDavid du Colombier s = getsval(x); 474*219b2ee8SDavid du Colombier if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */ 4753e12c5d1SDavid du Colombier p = (void *) a[2]; 4763e12c5d1SDavid du Colombier else { 477*219b2ee8SDavid du Colombier y = execute(a[2]); /* a[2] = regular expr */ 4783e12c5d1SDavid du Colombier t = getsval(y); 4793e12c5d1SDavid du Colombier p = compre(t); 4803e12c5d1SDavid du Colombier tempfree(y); 4813e12c5d1SDavid du Colombier } 4823e12c5d1SDavid du Colombier if (n == MATCHFCN) 4833e12c5d1SDavid du Colombier i = pmatch(p, s, s); 4843e12c5d1SDavid du Colombier else 4853e12c5d1SDavid du Colombier i = match(p, s, s); 4863e12c5d1SDavid du Colombier tempfree(x); 4873e12c5d1SDavid du Colombier if (n == MATCHFCN) { 4883e12c5d1SDavid du Colombier int start = patbeg - s + 1; 4893e12c5d1SDavid du Colombier if (patlen < 0) 4903e12c5d1SDavid du Colombier start = 0; 4913e12c5d1SDavid du Colombier setfval(rstartloc, (Awkfloat) start); 4923e12c5d1SDavid du Colombier setfval(rlengthloc, (Awkfloat) countposn(patbeg, patlen)); 4933e12c5d1SDavid du Colombier x = gettemp(); 4943e12c5d1SDavid du Colombier x->tval = NUM; 4953e12c5d1SDavid du Colombier x->fval = start; 4963e12c5d1SDavid du Colombier return x; 4973e12c5d1SDavid du Colombier } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) 4983e12c5d1SDavid du Colombier return(true); 4993e12c5d1SDavid du Colombier else 5003e12c5d1SDavid du Colombier return(false); 5013e12c5d1SDavid du Colombier } 5023e12c5d1SDavid du Colombier 5033e12c5d1SDavid du Colombier 504*219b2ee8SDavid du Colombier Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ 5053e12c5d1SDavid du Colombier { 5063e12c5d1SDavid du Colombier register Cell *x, *y; 5073e12c5d1SDavid du Colombier register int i; 5083e12c5d1SDavid du Colombier 5093e12c5d1SDavid du Colombier x = execute(a[0]); 5103e12c5d1SDavid du Colombier i = istrue(x); 5113e12c5d1SDavid du Colombier tempfree(x); 5123e12c5d1SDavid du Colombier switch (n) { 5133e12c5d1SDavid du Colombier case BOR: 5143e12c5d1SDavid du Colombier if (i) return(true); 5153e12c5d1SDavid du Colombier y = execute(a[1]); 5163e12c5d1SDavid du Colombier i = istrue(y); 5173e12c5d1SDavid du Colombier tempfree(y); 5183e12c5d1SDavid du Colombier if (i) return(true); 5193e12c5d1SDavid du Colombier else return(false); 5203e12c5d1SDavid du Colombier case AND: 5213e12c5d1SDavid du Colombier if ( !i ) return(false); 5223e12c5d1SDavid du Colombier y = execute(a[1]); 5233e12c5d1SDavid du Colombier i = istrue(y); 5243e12c5d1SDavid du Colombier tempfree(y); 5253e12c5d1SDavid du Colombier if (i) return(true); 5263e12c5d1SDavid du Colombier else return(false); 5273e12c5d1SDavid du Colombier case NOT: 5283e12c5d1SDavid du Colombier if (i) return(false); 5293e12c5d1SDavid du Colombier else return(true); 5303e12c5d1SDavid du Colombier default: /* can't happen */ 5313e12c5d1SDavid du Colombier ERROR "unknown boolean operator %d", n FATAL; 5323e12c5d1SDavid du Colombier } 5333e12c5d1SDavid du Colombier return 0; /*NOTREACHED*/ 5343e12c5d1SDavid du Colombier } 5353e12c5d1SDavid du Colombier 536*219b2ee8SDavid du Colombier Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */ 5373e12c5d1SDavid du Colombier { 5383e12c5d1SDavid du Colombier register int i; 5393e12c5d1SDavid du Colombier register Cell *x, *y; 5403e12c5d1SDavid du Colombier Awkfloat j; 5413e12c5d1SDavid du Colombier 5423e12c5d1SDavid du Colombier x = execute(a[0]); 5433e12c5d1SDavid du Colombier y = execute(a[1]); 5443e12c5d1SDavid du Colombier if (x->tval&NUM && y->tval&NUM) { 5453e12c5d1SDavid du Colombier j = x->fval - y->fval; 5463e12c5d1SDavid du Colombier i = j<0? -1: (j>0? 1: 0); 5473e12c5d1SDavid du Colombier } else { 5483e12c5d1SDavid du Colombier i = strcmp(getsval(x), getsval(y)); 5493e12c5d1SDavid du Colombier } 5503e12c5d1SDavid du Colombier tempfree(x); 5513e12c5d1SDavid du Colombier tempfree(y); 5523e12c5d1SDavid du Colombier switch (n) { 5533e12c5d1SDavid du Colombier case LT: if (i<0) return(true); 5543e12c5d1SDavid du Colombier else return(false); 5553e12c5d1SDavid du Colombier case LE: if (i<=0) return(true); 5563e12c5d1SDavid du Colombier else return(false); 5573e12c5d1SDavid du Colombier case NE: if (i!=0) return(true); 5583e12c5d1SDavid du Colombier else return(false); 5593e12c5d1SDavid du Colombier case EQ: if (i == 0) return(true); 5603e12c5d1SDavid du Colombier else return(false); 5613e12c5d1SDavid du Colombier case GE: if (i>=0) return(true); 5623e12c5d1SDavid du Colombier else return(false); 5633e12c5d1SDavid du Colombier case GT: if (i>0) return(true); 5643e12c5d1SDavid du Colombier else return(false); 5653e12c5d1SDavid du Colombier default: /* can't happen */ 5663e12c5d1SDavid du Colombier ERROR "unknown relational operator %d", n FATAL; 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier return 0; /*NOTREACHED*/ 5693e12c5d1SDavid du Colombier } 5703e12c5d1SDavid du Colombier 571*219b2ee8SDavid du Colombier void tfree(Cell *a) /* free a tempcell */ 5723e12c5d1SDavid du Colombier { 5733e12c5d1SDavid du Colombier if (freeable(a)) 5743e12c5d1SDavid du Colombier xfree(a->sval); 5753e12c5d1SDavid du Colombier if (a == tmps) 5763e12c5d1SDavid du Colombier ERROR "tempcell list is curdled" FATAL; 5773e12c5d1SDavid du Colombier a->cnext = tmps; 5783e12c5d1SDavid du Colombier tmps = a; 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier 581*219b2ee8SDavid du Colombier Cell *gettemp(void) /* get a tempcell */ 5823e12c5d1SDavid du Colombier { int i; 5833e12c5d1SDavid du Colombier register Cell *x; 5843e12c5d1SDavid du Colombier 5853e12c5d1SDavid du Colombier if (!tmps) { 5863e12c5d1SDavid du Colombier tmps = (Cell *) calloc(100, sizeof(Cell)); 5873e12c5d1SDavid du Colombier if (!tmps) 588*219b2ee8SDavid du Colombier ERROR "out of space for temporaries" FATAL; 5893e12c5d1SDavid du Colombier for(i = 1; i < 100; i++) 5903e12c5d1SDavid du Colombier tmps[i-1].cnext = &tmps[i]; 5913e12c5d1SDavid du Colombier tmps[i-1].cnext = 0; 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier x = tmps; 5943e12c5d1SDavid du Colombier tmps = x->cnext; 5953e12c5d1SDavid du Colombier *x = tempcell; 5963e12c5d1SDavid du Colombier return(x); 5973e12c5d1SDavid du Colombier } 5983e12c5d1SDavid du Colombier 599*219b2ee8SDavid du Colombier Cell *indirect(Node **a, int n) /* $( a[0] ) */ 6003e12c5d1SDavid du Colombier { 6013e12c5d1SDavid du Colombier register Cell *x; 6023e12c5d1SDavid du Colombier register int m; 6033e12c5d1SDavid du Colombier register uchar *s; 6043e12c5d1SDavid du Colombier 6053e12c5d1SDavid du Colombier x = execute(a[0]); 6063e12c5d1SDavid du Colombier m = getfval(x); 6073e12c5d1SDavid du Colombier if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */ 608*219b2ee8SDavid du Colombier ERROR "illegal field $(%s), name \"%s\"", s, x->nval FATAL; 609*219b2ee8SDavid du Colombier /* can x->nval ever be null??? */ 610*219b2ee8SDavid du Colombier /* ERROR "illegal field $(%s)", s FATAL; */ 6113e12c5d1SDavid du Colombier tempfree(x); 6123e12c5d1SDavid du Colombier x = fieldadr(m); 6133e12c5d1SDavid du Colombier x->ctype = OCELL; 6143e12c5d1SDavid du Colombier x->csub = CFLD; 6153e12c5d1SDavid du Colombier return(x); 6163e12c5d1SDavid du Colombier } 6173e12c5d1SDavid du Colombier 618*219b2ee8SDavid du Colombier Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ 6193e12c5d1SDavid du Colombier { 6203e12c5d1SDavid du Colombier register int k, m, n; 6213e12c5d1SDavid du Colombier register uchar *s, *p; 6223e12c5d1SDavid du Colombier int temp; 6233e12c5d1SDavid du Colombier register Cell *x, *y, *z; 6243e12c5d1SDavid du Colombier 6253e12c5d1SDavid du Colombier x = execute(a[0]); 6263e12c5d1SDavid du Colombier y = execute(a[1]); 6273e12c5d1SDavid du Colombier if (a[2] != 0) 6283e12c5d1SDavid du Colombier z = execute(a[2]); 6293e12c5d1SDavid du Colombier s = getsval(x); 6303e12c5d1SDavid du Colombier k = countposn(s, strlen(s)) + 1; 6313e12c5d1SDavid du Colombier if (k <= 1) { 6323e12c5d1SDavid du Colombier tempfree(x); 6333e12c5d1SDavid du Colombier tempfree(y); 6343e12c5d1SDavid du Colombier if (a[2] != 0) 6353e12c5d1SDavid du Colombier tempfree(z); 6363e12c5d1SDavid du Colombier x = gettemp(); 6373e12c5d1SDavid du Colombier setsval(x, ""); 6383e12c5d1SDavid du Colombier return(x); 6393e12c5d1SDavid du Colombier } 6403e12c5d1SDavid du Colombier m = getfval(y); 6413e12c5d1SDavid du Colombier if (m <= 0) 6423e12c5d1SDavid du Colombier m = 1; 6433e12c5d1SDavid du Colombier else if (m > k) 6443e12c5d1SDavid du Colombier m = k; 6453e12c5d1SDavid du Colombier tempfree(y); 6463e12c5d1SDavid du Colombier if (a[2] != 0) { 6473e12c5d1SDavid du Colombier n = getfval(z); 6483e12c5d1SDavid du Colombier tempfree(z); 6493e12c5d1SDavid du Colombier } else 6503e12c5d1SDavid du Colombier n = k - 1; 6513e12c5d1SDavid du Colombier if (n < 0) 6523e12c5d1SDavid du Colombier n = 0; 6533e12c5d1SDavid du Colombier else if (n > k - m) 6543e12c5d1SDavid du Colombier n = k - m; 6553e12c5d1SDavid du Colombier dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); 6563e12c5d1SDavid du Colombier y = gettemp(); 6573e12c5d1SDavid du Colombier while (*s && --m) 6583e12c5d1SDavid du Colombier s += mblen(s, k); 6593e12c5d1SDavid du Colombier for (p = s; *p && n--; p += mblen(p, k)) 6603e12c5d1SDavid du Colombier ; 6613e12c5d1SDavid du Colombier temp = *p; /* with thanks to John Linderman */ 6623e12c5d1SDavid du Colombier *p = '\0'; 6633e12c5d1SDavid du Colombier setsval(y, s); 6643e12c5d1SDavid du Colombier *p = temp; 6653e12c5d1SDavid du Colombier tempfree(x); 6663e12c5d1SDavid du Colombier return(y); 6673e12c5d1SDavid du Colombier } 6683e12c5d1SDavid du Colombier 669*219b2ee8SDavid du Colombier Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */ 6703e12c5d1SDavid du Colombier { 6713e12c5d1SDavid du Colombier register Cell *x, *y, *z; 6723e12c5d1SDavid du Colombier register uchar *s1, *s2, *p1, *p2, *q; 6733e12c5d1SDavid du Colombier Awkfloat v = 0.0; 6743e12c5d1SDavid du Colombier 6753e12c5d1SDavid du Colombier x = execute(a[0]); 6763e12c5d1SDavid du Colombier s1 = getsval(x); 6773e12c5d1SDavid du Colombier y = execute(a[1]); 6783e12c5d1SDavid du Colombier s2 = getsval(y); 6793e12c5d1SDavid du Colombier 6803e12c5d1SDavid du Colombier z = gettemp(); 6813e12c5d1SDavid du Colombier for (p1 = s1; *p1 != '\0'; p1++) { 6823e12c5d1SDavid du Colombier for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) 6833e12c5d1SDavid du Colombier ; 6843e12c5d1SDavid du Colombier if (*p2 == '\0') { 6853e12c5d1SDavid du Colombier v = (Awkfloat) countposn(s1, p1-s1) + 1;/* origin 1 */ 6863e12c5d1SDavid du Colombier break; 6873e12c5d1SDavid du Colombier } 6883e12c5d1SDavid du Colombier } 6893e12c5d1SDavid du Colombier tempfree(x); 6903e12c5d1SDavid du Colombier tempfree(y); 6913e12c5d1SDavid du Colombier setfval(z, v); 6923e12c5d1SDavid du Colombier return(z); 6933e12c5d1SDavid du Colombier } 6943e12c5d1SDavid du Colombier 695*219b2ee8SDavid du Colombier double 696*219b2ee8SDavid du Colombier boundfloat(Cell *x) 697*219b2ee8SDavid du Colombier { 698*219b2ee8SDavid du Colombier double v; 699*219b2ee8SDavid du Colombier 700*219b2ee8SDavid du Colombier v = getfval(x); 701*219b2ee8SDavid du Colombier if(v > 2147483647.0) 702*219b2ee8SDavid du Colombier return 2147483647.0; 703*219b2ee8SDavid du Colombier if(v < -2147483647.0) 704*219b2ee8SDavid du Colombier return -2147483647.0; 705*219b2ee8SDavid du Colombier return v; 706*219b2ee8SDavid du Colombier } 707*219b2ee8SDavid du Colombier 708*219b2ee8SDavid du Colombier format(uchar *buf, int bufsize, uchar *s, Node *a) /* printf-like conversions */ 7093e12c5d1SDavid du Colombier { 7103e12c5d1SDavid du Colombier uchar fmt[RECSIZE]; 7113e12c5d1SDavid du Colombier register uchar *p, *t, *os; 7123e12c5d1SDavid du Colombier register Cell *x; 7133e12c5d1SDavid du Colombier int flag = 0, n; 7143e12c5d1SDavid du Colombier 7153e12c5d1SDavid du Colombier os = s; 7163e12c5d1SDavid du Colombier p = buf; 7173e12c5d1SDavid du Colombier while (*s) { 7183e12c5d1SDavid du Colombier if (p - buf >= bufsize) 7193e12c5d1SDavid du Colombier return -1; 7203e12c5d1SDavid du Colombier if (*s != '%') { 7213e12c5d1SDavid du Colombier *p++ = *s++; 7223e12c5d1SDavid du Colombier continue; 7233e12c5d1SDavid du Colombier } 7243e12c5d1SDavid du Colombier if (*(s+1) == '%') { 7253e12c5d1SDavid du Colombier *p++ = '%'; 7263e12c5d1SDavid du Colombier s += 2; 7273e12c5d1SDavid du Colombier continue; 7283e12c5d1SDavid du Colombier } 7293e12c5d1SDavid du Colombier for (t=fmt; (*t++ = *s) != '\0'; s++) { 7303e12c5d1SDavid du Colombier if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') 7313e12c5d1SDavid du Colombier break; /* the ansi panoply */ 7323e12c5d1SDavid du Colombier if (*s == '*') { 7333e12c5d1SDavid du Colombier x = execute(a); 7343e12c5d1SDavid du Colombier a = a->nnext; 7353e12c5d1SDavid du Colombier sprintf((char *)t-1, "%d", (int) getfval(x)); 7363e12c5d1SDavid du Colombier t = fmt + strlen(fmt); 7373e12c5d1SDavid du Colombier tempfree(x); 7383e12c5d1SDavid du Colombier } 7393e12c5d1SDavid du Colombier } 7403e12c5d1SDavid du Colombier *t = '\0'; 7413e12c5d1SDavid du Colombier if (t >= fmt + sizeof(fmt)) 742*219b2ee8SDavid du Colombier ERROR "format item %.30s... too long", os FATAL; 7433e12c5d1SDavid du Colombier switch (*s) { 7443e12c5d1SDavid du Colombier case 'f': case 'e': case 'g': case 'E': case 'G': 7453e12c5d1SDavid du Colombier flag = 1; 7463e12c5d1SDavid du Colombier break; 7473e12c5d1SDavid du Colombier case 'd': case 'i': 7483e12c5d1SDavid du Colombier flag = 2; 7493e12c5d1SDavid du Colombier if(*(s-1) == 'l') break; 7503e12c5d1SDavid du Colombier *(t-1) = 'l'; 7513e12c5d1SDavid du Colombier *t = 'd'; 7523e12c5d1SDavid du Colombier *++t = '\0'; 7533e12c5d1SDavid du Colombier break; 7543e12c5d1SDavid du Colombier case 'o': case 'x': case 'X': case 'u': 7553e12c5d1SDavid du Colombier flag = *(s-1) == 'l' ? 2 : 3; 7563e12c5d1SDavid du Colombier break; 7573e12c5d1SDavid du Colombier case 's': 7583e12c5d1SDavid du Colombier flag = 4; 7593e12c5d1SDavid du Colombier break; 7603e12c5d1SDavid du Colombier case 'c': 7613e12c5d1SDavid du Colombier flag = 5; 7623e12c5d1SDavid du Colombier break; 7633e12c5d1SDavid du Colombier default: 7643e12c5d1SDavid du Colombier ERROR "weird printf conversion %s", fmt WARNING; 7653e12c5d1SDavid du Colombier flag = 0; 7663e12c5d1SDavid du Colombier break; 7673e12c5d1SDavid du Colombier } 7683e12c5d1SDavid du Colombier if (a == NULL) 7693e12c5d1SDavid du Colombier ERROR "not enough args in printf(%s)", os FATAL; 7703e12c5d1SDavid du Colombier x = execute(a); 7713e12c5d1SDavid du Colombier a = a->nnext; 7723e12c5d1SDavid du Colombier switch (flag) { 7733e12c5d1SDavid du Colombier case 0: sprintf((char *)p, "%s", fmt); /* unknown, so dump it too */ 7743e12c5d1SDavid du Colombier p += strlen(p); 7753e12c5d1SDavid du Colombier sprintf((char *)p, "%s", getsval(x)); 7763e12c5d1SDavid du Colombier break; 7773e12c5d1SDavid du Colombier case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break; 778*219b2ee8SDavid du Colombier case 2: sprintf((char *)p, (char *)fmt, (long) boundfloat(x)); 779*219b2ee8SDavid du Colombier break; 780*219b2ee8SDavid du Colombier case 3: sprintf((char *)p, (char *)fmt, (int) boundfloat(x)); break; 7813e12c5d1SDavid du Colombier case 4: 7823e12c5d1SDavid du Colombier t = getsval(x); 7833e12c5d1SDavid du Colombier n = strlen(t); 7843e12c5d1SDavid du Colombier if (n >= bufsize) 7853e12c5d1SDavid du Colombier ERROR "huge string (%d chars) in printf %.30s...", 7863e12c5d1SDavid du Colombier n, t FATAL; 7873e12c5d1SDavid du Colombier sprintf((char *)p, (char *)fmt, t); 7883e12c5d1SDavid du Colombier break; 789*219b2ee8SDavid du Colombier case 5: 790*219b2ee8SDavid du Colombier isnum(x) ? sprintf((char *)p, (char *)fmt, (int) boundfloat(x)) 7913e12c5d1SDavid du Colombier : sprintf((char *)p, (char *)fmt, getsval(x)[0]); 7923e12c5d1SDavid du Colombier break; 7933e12c5d1SDavid du Colombier } 7943e12c5d1SDavid du Colombier tempfree(x); 7953e12c5d1SDavid du Colombier p += strlen(p); 7963e12c5d1SDavid du Colombier s++; 7973e12c5d1SDavid du Colombier } 7983e12c5d1SDavid du Colombier *p = '\0'; 7993e12c5d1SDavid du Colombier for ( ; a; a = a->nnext) /* evaluate any remaining args */ 8003e12c5d1SDavid du Colombier execute(a); 8013e12c5d1SDavid du Colombier return 0; 8023e12c5d1SDavid du Colombier } 8033e12c5d1SDavid du Colombier 804*219b2ee8SDavid du Colombier Cell *asprintf(Node **a, int n) /* sprintf(a[0]) */ 8053e12c5d1SDavid du Colombier { 8063e12c5d1SDavid du Colombier register Cell *x; 8073e12c5d1SDavid du Colombier register Node *y; 8083e12c5d1SDavid du Colombier uchar buf[3*RECSIZE]; 8093e12c5d1SDavid du Colombier 8103e12c5d1SDavid du Colombier y = a[0]->nnext; 8113e12c5d1SDavid du Colombier x = execute(a[0]); 8123e12c5d1SDavid du Colombier if (format(buf, sizeof buf, getsval(x), y) == -1) 813*219b2ee8SDavid du Colombier ERROR "sprintf string %.30s... too long", buf FATAL; 8143e12c5d1SDavid du Colombier tempfree(x); 8153e12c5d1SDavid du Colombier x = gettemp(); 8163e12c5d1SDavid du Colombier x->sval = tostring(buf); 8173e12c5d1SDavid du Colombier x->tval = STR; 8183e12c5d1SDavid du Colombier return(x); 8193e12c5d1SDavid du Colombier } 8203e12c5d1SDavid du Colombier 821*219b2ee8SDavid du Colombier Cell *aprintf(Node **a, int n) /* printf */ 822*219b2ee8SDavid du Colombier { /* a[0] is list of args, starting with format string */ 823*219b2ee8SDavid du Colombier /* a[1] is redirection operator, a[2] is redirection file */ 8243e12c5d1SDavid du Colombier FILE *fp; 8253e12c5d1SDavid du Colombier register Cell *x; 8263e12c5d1SDavid du Colombier register Node *y; 8273e12c5d1SDavid du Colombier uchar buf[3*RECSIZE]; 8283e12c5d1SDavid du Colombier 8293e12c5d1SDavid du Colombier y = a[0]->nnext; 8303e12c5d1SDavid du Colombier x = execute(a[0]); 8313e12c5d1SDavid du Colombier if (format(buf, sizeof buf, getsval(x), y) == -1) 832*219b2ee8SDavid du Colombier ERROR "printf string %.30s... too long", buf FATAL; 8333e12c5d1SDavid du Colombier tempfree(x); 8343e12c5d1SDavid du Colombier if (a[1] == NULL) { 8353e12c5d1SDavid du Colombier fputs((char *)buf, stdout); 8363e12c5d1SDavid du Colombier if (ferror(stdout)) 8373e12c5d1SDavid du Colombier ERROR "write error on stdout" FATAL; 8383e12c5d1SDavid du Colombier } else { 8393e12c5d1SDavid du Colombier fp = redirect((int)a[1], a[2]); 8403e12c5d1SDavid du Colombier fputs((char *)buf, fp); 8413e12c5d1SDavid du Colombier fflush(fp); 8423e12c5d1SDavid du Colombier if (ferror(fp)) 8433e12c5d1SDavid du Colombier ERROR "write error on %s", filename(fp) FATAL; 8443e12c5d1SDavid du Colombier } 8453e12c5d1SDavid du Colombier return(true); 8463e12c5d1SDavid du Colombier } 8473e12c5d1SDavid du Colombier 848*219b2ee8SDavid du Colombier Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 8493e12c5d1SDavid du Colombier { 8503e12c5d1SDavid du Colombier Awkfloat i, j; 8513e12c5d1SDavid du Colombier double v; 8523e12c5d1SDavid du Colombier register Cell *x, *y, *z; 8533e12c5d1SDavid du Colombier 8543e12c5d1SDavid du Colombier x = execute(a[0]); 8553e12c5d1SDavid du Colombier i = getfval(x); 8563e12c5d1SDavid du Colombier tempfree(x); 8573e12c5d1SDavid du Colombier if (n != UMINUS) { 8583e12c5d1SDavid du Colombier y = execute(a[1]); 8593e12c5d1SDavid du Colombier j = getfval(y); 8603e12c5d1SDavid du Colombier tempfree(y); 8613e12c5d1SDavid du Colombier } 8623e12c5d1SDavid du Colombier z = gettemp(); 8633e12c5d1SDavid du Colombier switch (n) { 8643e12c5d1SDavid du Colombier case ADD: 8653e12c5d1SDavid du Colombier i += j; 8663e12c5d1SDavid du Colombier break; 8673e12c5d1SDavid du Colombier case MINUS: 8683e12c5d1SDavid du Colombier i -= j; 8693e12c5d1SDavid du Colombier break; 8703e12c5d1SDavid du Colombier case MULT: 8713e12c5d1SDavid du Colombier i *= j; 8723e12c5d1SDavid du Colombier break; 8733e12c5d1SDavid du Colombier case DIVIDE: 8743e12c5d1SDavid du Colombier if (j == 0) 8753e12c5d1SDavid du Colombier ERROR "division by zero" FATAL; 8763e12c5d1SDavid du Colombier i /= j; 8773e12c5d1SDavid du Colombier break; 8783e12c5d1SDavid du Colombier case MOD: 8793e12c5d1SDavid du Colombier if (j == 0) 8803e12c5d1SDavid du Colombier ERROR "division by zero in mod" FATAL; 8813e12c5d1SDavid du Colombier modf(i/j, &v); 8823e12c5d1SDavid du Colombier i = i - j * v; 8833e12c5d1SDavid du Colombier break; 8843e12c5d1SDavid du Colombier case UMINUS: 8853e12c5d1SDavid du Colombier i = -i; 8863e12c5d1SDavid du Colombier break; 8873e12c5d1SDavid du Colombier case POWER: 8883e12c5d1SDavid du Colombier if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 8893e12c5d1SDavid du Colombier i = ipow(i, (int) j); 8903e12c5d1SDavid du Colombier else 8913e12c5d1SDavid du Colombier i = errcheck(pow(i, j), "pow"); 8923e12c5d1SDavid du Colombier break; 8933e12c5d1SDavid du Colombier default: /* can't happen */ 8943e12c5d1SDavid du Colombier ERROR "illegal arithmetic operator %d", n FATAL; 8953e12c5d1SDavid du Colombier } 8963e12c5d1SDavid du Colombier setfval(z, i); 8973e12c5d1SDavid du Colombier return(z); 8983e12c5d1SDavid du Colombier } 8993e12c5d1SDavid du Colombier 900*219b2ee8SDavid du Colombier double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 9013e12c5d1SDavid du Colombier { 9023e12c5d1SDavid du Colombier double v; 9033e12c5d1SDavid du Colombier 9043e12c5d1SDavid du Colombier if (n <= 0) 9053e12c5d1SDavid du Colombier return 1; 9063e12c5d1SDavid du Colombier v = ipow(x, n/2); 9073e12c5d1SDavid du Colombier if (n % 2 == 0) 9083e12c5d1SDavid du Colombier return v * v; 9093e12c5d1SDavid du Colombier else 9103e12c5d1SDavid du Colombier return x * v * v; 9113e12c5d1SDavid du Colombier } 9123e12c5d1SDavid du Colombier 913*219b2ee8SDavid du Colombier Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */ 9143e12c5d1SDavid du Colombier { 9153e12c5d1SDavid du Colombier register Cell *x, *z; 9163e12c5d1SDavid du Colombier register int k; 9173e12c5d1SDavid du Colombier Awkfloat xf; 9183e12c5d1SDavid du Colombier 9193e12c5d1SDavid du Colombier x = execute(a[0]); 9203e12c5d1SDavid du Colombier xf = getfval(x); 9213e12c5d1SDavid du Colombier k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 9223e12c5d1SDavid du Colombier if (n == PREINCR || n == PREDECR) { 9233e12c5d1SDavid du Colombier setfval(x, xf + k); 9243e12c5d1SDavid du Colombier return(x); 9253e12c5d1SDavid du Colombier } 9263e12c5d1SDavid du Colombier z = gettemp(); 9273e12c5d1SDavid du Colombier setfval(z, xf); 9283e12c5d1SDavid du Colombier setfval(x, xf + k); 9293e12c5d1SDavid du Colombier tempfree(x); 9303e12c5d1SDavid du Colombier return(z); 9313e12c5d1SDavid du Colombier } 9323e12c5d1SDavid du Colombier 933*219b2ee8SDavid du Colombier Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ 934*219b2ee8SDavid du Colombier { /* this is subtle; don't muck with it. */ 9353e12c5d1SDavid du Colombier register Cell *x, *y; 9363e12c5d1SDavid du Colombier Awkfloat xf, yf; 9373e12c5d1SDavid du Colombier double v; 9383e12c5d1SDavid du Colombier 9393e12c5d1SDavid du Colombier y = execute(a[1]); 9403e12c5d1SDavid du Colombier x = execute(a[0]); 9413e12c5d1SDavid du Colombier if (n == ASSIGN) { /* ordinary assignment */ 942*219b2ee8SDavid du Colombier if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ 943*219b2ee8SDavid du Colombier ; /* leave alone unless it's a field */ 9443e12c5d1SDavid du Colombier else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 9453e12c5d1SDavid du Colombier setsval(x, getsval(y)); 9463e12c5d1SDavid du Colombier x->fval = getfval(y); 9473e12c5d1SDavid du Colombier x->tval |= NUM; 9483e12c5d1SDavid du Colombier } 9493e12c5d1SDavid du Colombier else if (y->tval & STR) 9503e12c5d1SDavid du Colombier setsval(x, getsval(y)); 9513e12c5d1SDavid du Colombier else if (y->tval & NUM) 9523e12c5d1SDavid du Colombier setfval(x, getfval(y)); 9533e12c5d1SDavid du Colombier else 9543e12c5d1SDavid du Colombier funnyvar(y, "read value of"); 9553e12c5d1SDavid du Colombier tempfree(y); 9563e12c5d1SDavid du Colombier return(x); 9573e12c5d1SDavid du Colombier } 9583e12c5d1SDavid du Colombier xf = getfval(x); 9593e12c5d1SDavid du Colombier yf = getfval(y); 9603e12c5d1SDavid du Colombier switch (n) { 9613e12c5d1SDavid du Colombier case ADDEQ: 9623e12c5d1SDavid du Colombier xf += yf; 9633e12c5d1SDavid du Colombier break; 9643e12c5d1SDavid du Colombier case SUBEQ: 9653e12c5d1SDavid du Colombier xf -= yf; 9663e12c5d1SDavid du Colombier break; 9673e12c5d1SDavid du Colombier case MULTEQ: 9683e12c5d1SDavid du Colombier xf *= yf; 9693e12c5d1SDavid du Colombier break; 9703e12c5d1SDavid du Colombier case DIVEQ: 9713e12c5d1SDavid du Colombier if (yf == 0) 9723e12c5d1SDavid du Colombier ERROR "division by zero in /=" FATAL; 9733e12c5d1SDavid du Colombier xf /= yf; 9743e12c5d1SDavid du Colombier break; 9753e12c5d1SDavid du Colombier case MODEQ: 9763e12c5d1SDavid du Colombier if (yf == 0) 9773e12c5d1SDavid du Colombier ERROR "division by zero in %%=" FATAL; 9783e12c5d1SDavid du Colombier modf(xf/yf, &v); 9793e12c5d1SDavid du Colombier xf = xf - yf * v; 9803e12c5d1SDavid du Colombier break; 9813e12c5d1SDavid du Colombier case POWEQ: 9823e12c5d1SDavid du Colombier if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 9833e12c5d1SDavid du Colombier xf = ipow(xf, (int) yf); 9843e12c5d1SDavid du Colombier else 9853e12c5d1SDavid du Colombier xf = errcheck(pow(xf, yf), "pow"); 9863e12c5d1SDavid du Colombier break; 9873e12c5d1SDavid du Colombier default: 9883e12c5d1SDavid du Colombier ERROR "illegal assignment operator %d", n FATAL; 9893e12c5d1SDavid du Colombier break; 9903e12c5d1SDavid du Colombier } 9913e12c5d1SDavid du Colombier tempfree(y); 9923e12c5d1SDavid du Colombier setfval(x, xf); 9933e12c5d1SDavid du Colombier return(x); 9943e12c5d1SDavid du Colombier } 9953e12c5d1SDavid du Colombier 996*219b2ee8SDavid du Colombier Cell *cat(Node **a, int q) /* a[0] cat a[1] */ 9973e12c5d1SDavid du Colombier { 9983e12c5d1SDavid du Colombier register Cell *x, *y, *z; 9993e12c5d1SDavid du Colombier register int n1, n2; 10003e12c5d1SDavid du Colombier register uchar *s; 10013e12c5d1SDavid du Colombier 10023e12c5d1SDavid du Colombier x = execute(a[0]); 10033e12c5d1SDavid du Colombier y = execute(a[1]); 10043e12c5d1SDavid du Colombier getsval(x); 10053e12c5d1SDavid du Colombier getsval(y); 10063e12c5d1SDavid du Colombier n1 = strlen(x->sval); 10073e12c5d1SDavid du Colombier n2 = strlen(y->sval); 10083e12c5d1SDavid du Colombier s = (uchar *) malloc(n1 + n2 + 1); 10093e12c5d1SDavid du Colombier if (s == NULL) 1010*219b2ee8SDavid du Colombier ERROR "out of space concatenating %.15s... and %.15s...", 10113e12c5d1SDavid du Colombier x->sval, y->sval FATAL; 10123e12c5d1SDavid du Colombier strcpy(s, x->sval); 10133e12c5d1SDavid du Colombier strcpy(s+n1, y->sval); 10143e12c5d1SDavid du Colombier tempfree(y); 10153e12c5d1SDavid du Colombier z = gettemp(); 10163e12c5d1SDavid du Colombier z->sval = s; 10173e12c5d1SDavid du Colombier z->tval = STR; 10183e12c5d1SDavid du Colombier tempfree(x); 10193e12c5d1SDavid du Colombier return(z); 10203e12c5d1SDavid du Colombier } 10213e12c5d1SDavid du Colombier 10223e12c5d1SDavid du Colombier Cell *pastat(Node **a, int n) /* a[0] { a[1] } */ 10233e12c5d1SDavid du Colombier { 10243e12c5d1SDavid du Colombier register Cell *x; 10253e12c5d1SDavid du Colombier 10263e12c5d1SDavid du Colombier if (a[0] == 0) 10273e12c5d1SDavid du Colombier x = execute(a[1]); 10283e12c5d1SDavid du Colombier else { 10293e12c5d1SDavid du Colombier x = execute(a[0]); 10303e12c5d1SDavid du Colombier if (istrue(x)) { 10313e12c5d1SDavid du Colombier tempfree(x); 10323e12c5d1SDavid du Colombier x = execute(a[1]); 10333e12c5d1SDavid du Colombier } 10343e12c5d1SDavid du Colombier } 10353e12c5d1SDavid du Colombier return x; 10363e12c5d1SDavid du Colombier } 10373e12c5d1SDavid du Colombier 10383e12c5d1SDavid du Colombier Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 10393e12c5d1SDavid du Colombier { 10403e12c5d1SDavid du Colombier register Cell *x; 10413e12c5d1SDavid du Colombier register int pair; 10423e12c5d1SDavid du Colombier 10433e12c5d1SDavid du Colombier pair = (int) a[3]; 10443e12c5d1SDavid du Colombier if (pairstack[pair] == 0) { 10453e12c5d1SDavid du Colombier x = execute(a[0]); 10463e12c5d1SDavid du Colombier if (istrue(x)) 10473e12c5d1SDavid du Colombier pairstack[pair] = 1; 10483e12c5d1SDavid du Colombier tempfree(x); 10493e12c5d1SDavid du Colombier } 10503e12c5d1SDavid du Colombier if (pairstack[pair] == 1) { 10513e12c5d1SDavid du Colombier x = execute(a[1]); 10523e12c5d1SDavid du Colombier if (istrue(x)) 10533e12c5d1SDavid du Colombier pairstack[pair] = 0; 10543e12c5d1SDavid du Colombier tempfree(x); 10553e12c5d1SDavid du Colombier x = execute(a[2]); 10563e12c5d1SDavid du Colombier return(x); 10573e12c5d1SDavid du Colombier } 10583e12c5d1SDavid du Colombier return(false); 10593e12c5d1SDavid du Colombier } 10603e12c5d1SDavid du Colombier 10613e12c5d1SDavid du Colombier Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 10623e12c5d1SDavid du Colombier { 10633e12c5d1SDavid du Colombier Cell *x, *y, *ap; 10643e12c5d1SDavid du Colombier register uchar *s; 10653e12c5d1SDavid du Colombier register int sep; 1066*219b2ee8SDavid du Colombier uchar *t, temp, num[10], *fs; 10673e12c5d1SDavid du Colombier int n; 10683e12c5d1SDavid du Colombier 10693e12c5d1SDavid du Colombier y = execute(a[0]); /* source string */ 10703e12c5d1SDavid du Colombier s = getsval(y); 10713e12c5d1SDavid du Colombier if (a[2] == 0) /* fs string */ 10723e12c5d1SDavid du Colombier fs = *FS; 10733e12c5d1SDavid du Colombier else if ((int) a[3] == STRING) { /* split(str,arr,"string") */ 10743e12c5d1SDavid du Colombier x = execute(a[2]); 10753e12c5d1SDavid du Colombier fs = getsval(x); 10763e12c5d1SDavid du Colombier } else if ((int) a[3] == REGEXPR) 10773e12c5d1SDavid du Colombier fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */ 10783e12c5d1SDavid du Colombier else 10793e12c5d1SDavid du Colombier ERROR "illegal type of split()" FATAL; 10803e12c5d1SDavid du Colombier sep = *fs; 10813e12c5d1SDavid du Colombier ap = execute(a[1]); /* array name */ 10823e12c5d1SDavid du Colombier freesymtab(ap); 10833e12c5d1SDavid du Colombier dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); 10843e12c5d1SDavid du Colombier ap->tval &= ~STR; 10853e12c5d1SDavid du Colombier ap->tval |= ARR; 10863e12c5d1SDavid du Colombier ap->sval = (uchar *) makesymtab(NSYMTAB); 10873e12c5d1SDavid du Colombier 10883e12c5d1SDavid du Colombier n = 0; 10893e12c5d1SDavid du Colombier if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */ 10903e12c5d1SDavid du Colombier void *p; 10913e12c5d1SDavid du Colombier if ((int) a[3] == REGEXPR) { /* it's ready already */ 10923e12c5d1SDavid du Colombier p = (void *) a[2]; 10933e12c5d1SDavid du Colombier } else { 10943e12c5d1SDavid du Colombier p = compre(fs); 10953e12c5d1SDavid du Colombier } 10963e12c5d1SDavid du Colombier t = s; 10973e12c5d1SDavid du Colombier if (nematch(p,s,t)) { 10983e12c5d1SDavid du Colombier do { 10993e12c5d1SDavid du Colombier n++; 11003e12c5d1SDavid du Colombier sprintf((char *)num, "%d", n); 11013e12c5d1SDavid du Colombier temp = *patbeg; 11023e12c5d1SDavid du Colombier *patbeg = '\0'; 11033e12c5d1SDavid du Colombier if (isnumber(t)) 11043e12c5d1SDavid du Colombier setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 11053e12c5d1SDavid du Colombier else 11063e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 11073e12c5d1SDavid du Colombier *patbeg = temp; 11083e12c5d1SDavid du Colombier t = patbeg + patlen; 11093e12c5d1SDavid du Colombier if (t[-1] == 0 || *t == 0) { 11103e12c5d1SDavid du Colombier n++; 11113e12c5d1SDavid du Colombier sprintf((char *)num, "%d", n); 11123e12c5d1SDavid du Colombier setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 11133e12c5d1SDavid du Colombier goto spdone; 11143e12c5d1SDavid du Colombier } 11153e12c5d1SDavid du Colombier } while (nematch(p,s,t)); 11163e12c5d1SDavid du Colombier } 11173e12c5d1SDavid du Colombier n++; 11183e12c5d1SDavid du Colombier sprintf((char *)num, "%d", n); 11193e12c5d1SDavid du Colombier if (isnumber(t)) 11203e12c5d1SDavid du Colombier setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 11213e12c5d1SDavid du Colombier else 11223e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 11233e12c5d1SDavid du Colombier spdone: 11243e12c5d1SDavid du Colombier p = NULL; 11253e12c5d1SDavid du Colombier } else if (sep == ' ') { 11263e12c5d1SDavid du Colombier for (n = 0; ; ) { 11273e12c5d1SDavid du Colombier while (*s == ' ' || *s == '\t' || *s == '\n') 11283e12c5d1SDavid du Colombier s++; 11293e12c5d1SDavid du Colombier if (*s == 0) 11303e12c5d1SDavid du Colombier break; 11313e12c5d1SDavid du Colombier n++; 11323e12c5d1SDavid du Colombier t = s; 11333e12c5d1SDavid du Colombier do 11343e12c5d1SDavid du Colombier s++; 11353e12c5d1SDavid du Colombier while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 11363e12c5d1SDavid du Colombier temp = *s; 11373e12c5d1SDavid du Colombier *s = '\0'; 11383e12c5d1SDavid du Colombier sprintf((char *)num, "%d", n); 11393e12c5d1SDavid du Colombier if (isnumber(t)) 11403e12c5d1SDavid du Colombier setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 11413e12c5d1SDavid du Colombier else 11423e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 11433e12c5d1SDavid du Colombier *s = temp; 11443e12c5d1SDavid du Colombier if (*s != 0) 11453e12c5d1SDavid du Colombier s++; 11463e12c5d1SDavid du Colombier } 11473e12c5d1SDavid du Colombier } else if (*s != 0) { 11483e12c5d1SDavid du Colombier for (;;) { 11493e12c5d1SDavid du Colombier n++; 11503e12c5d1SDavid du Colombier t = s; 11513e12c5d1SDavid du Colombier while (*s != sep && *s != '\n' && *s != '\0') 11523e12c5d1SDavid du Colombier s++; 11533e12c5d1SDavid du Colombier temp = *s; 11543e12c5d1SDavid du Colombier *s = '\0'; 11553e12c5d1SDavid du Colombier sprintf((char *)num, "%d", n); 11563e12c5d1SDavid du Colombier if (isnumber(t)) 11573e12c5d1SDavid du Colombier setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 11583e12c5d1SDavid du Colombier else 11593e12c5d1SDavid du Colombier setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 11603e12c5d1SDavid du Colombier *s = temp; 11613e12c5d1SDavid du Colombier if (*s++ == 0) 11623e12c5d1SDavid du Colombier break; 11633e12c5d1SDavid du Colombier } 11643e12c5d1SDavid du Colombier } 11653e12c5d1SDavid du Colombier tempfree(ap); 11663e12c5d1SDavid du Colombier tempfree(y); 11673e12c5d1SDavid du Colombier if (a[2] != 0 && (int) a[3] == STRING) 11683e12c5d1SDavid du Colombier tempfree(x); 11693e12c5d1SDavid du Colombier x = gettemp(); 11703e12c5d1SDavid du Colombier x->tval = NUM; 11713e12c5d1SDavid du Colombier x->fval = n; 11723e12c5d1SDavid du Colombier return(x); 11733e12c5d1SDavid du Colombier } 11743e12c5d1SDavid du Colombier 11753e12c5d1SDavid du Colombier Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 11763e12c5d1SDavid du Colombier { 11773e12c5d1SDavid du Colombier register Cell *x; 11783e12c5d1SDavid du Colombier 11793e12c5d1SDavid du Colombier x = execute(a[0]); 11803e12c5d1SDavid du Colombier if (istrue(x)) { 11813e12c5d1SDavid du Colombier tempfree(x); 11823e12c5d1SDavid du Colombier x = execute(a[1]); 11833e12c5d1SDavid du Colombier } else { 11843e12c5d1SDavid du Colombier tempfree(x); 11853e12c5d1SDavid du Colombier x = execute(a[2]); 11863e12c5d1SDavid du Colombier } 11873e12c5d1SDavid du Colombier return(x); 11883e12c5d1SDavid du Colombier } 11893e12c5d1SDavid du Colombier 11903e12c5d1SDavid du Colombier Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 11913e12c5d1SDavid du Colombier { 11923e12c5d1SDavid du Colombier register Cell *x; 11933e12c5d1SDavid du Colombier 11943e12c5d1SDavid du Colombier x = execute(a[0]); 11953e12c5d1SDavid du Colombier if (istrue(x)) { 11963e12c5d1SDavid du Colombier tempfree(x); 11973e12c5d1SDavid du Colombier x = execute(a[1]); 11983e12c5d1SDavid du Colombier } else if (a[2] != 0) { 11993e12c5d1SDavid du Colombier tempfree(x); 12003e12c5d1SDavid du Colombier x = execute(a[2]); 12013e12c5d1SDavid du Colombier } 12023e12c5d1SDavid du Colombier return(x); 12033e12c5d1SDavid du Colombier } 12043e12c5d1SDavid du Colombier 12053e12c5d1SDavid du Colombier Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */ 12063e12c5d1SDavid du Colombier { 12073e12c5d1SDavid du Colombier register Cell *x; 12083e12c5d1SDavid du Colombier 12093e12c5d1SDavid du Colombier for (;;) { 12103e12c5d1SDavid du Colombier x = execute(a[0]); 12113e12c5d1SDavid du Colombier if (!istrue(x)) 12123e12c5d1SDavid du Colombier return(x); 12133e12c5d1SDavid du Colombier tempfree(x); 12143e12c5d1SDavid du Colombier x = execute(a[1]); 12153e12c5d1SDavid du Colombier if (isbreak(x)) { 12163e12c5d1SDavid du Colombier x = true; 12173e12c5d1SDavid du Colombier return(x); 12183e12c5d1SDavid du Colombier } 12193e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) 12203e12c5d1SDavid du Colombier return(x); 12213e12c5d1SDavid du Colombier tempfree(x); 12223e12c5d1SDavid du Colombier } 12233e12c5d1SDavid du Colombier } 12243e12c5d1SDavid du Colombier 12253e12c5d1SDavid du Colombier Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 12263e12c5d1SDavid du Colombier { 12273e12c5d1SDavid du Colombier register Cell *x; 12283e12c5d1SDavid du Colombier 12293e12c5d1SDavid du Colombier for (;;) { 12303e12c5d1SDavid du Colombier x = execute(a[0]); 12313e12c5d1SDavid du Colombier if (isbreak(x)) 12323e12c5d1SDavid du Colombier return true; 12333e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) 12343e12c5d1SDavid du Colombier return(x); 12353e12c5d1SDavid du Colombier tempfree(x); 12363e12c5d1SDavid du Colombier x = execute(a[1]); 12373e12c5d1SDavid du Colombier if (!istrue(x)) 12383e12c5d1SDavid du Colombier return(x); 12393e12c5d1SDavid du Colombier tempfree(x); 12403e12c5d1SDavid du Colombier } 12413e12c5d1SDavid du Colombier } 12423e12c5d1SDavid du Colombier 12433e12c5d1SDavid du Colombier Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 12443e12c5d1SDavid du Colombier { 12453e12c5d1SDavid du Colombier register Cell *x; 12463e12c5d1SDavid du Colombier 12473e12c5d1SDavid du Colombier x = execute(a[0]); 12483e12c5d1SDavid du Colombier tempfree(x); 12493e12c5d1SDavid du Colombier for (;;) { 12503e12c5d1SDavid du Colombier if (a[1]!=0) { 12513e12c5d1SDavid du Colombier x = execute(a[1]); 12523e12c5d1SDavid du Colombier if (!istrue(x)) return(x); 12533e12c5d1SDavid du Colombier else tempfree(x); 12543e12c5d1SDavid du Colombier } 12553e12c5d1SDavid du Colombier x = execute(a[3]); 12563e12c5d1SDavid du Colombier if (isbreak(x)) /* turn off break */ 12573e12c5d1SDavid du Colombier return true; 12583e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) 12593e12c5d1SDavid du Colombier return(x); 12603e12c5d1SDavid du Colombier tempfree(x); 12613e12c5d1SDavid du Colombier x = execute(a[2]); 12623e12c5d1SDavid du Colombier tempfree(x); 12633e12c5d1SDavid du Colombier } 12643e12c5d1SDavid du Colombier } 12653e12c5d1SDavid du Colombier 12663e12c5d1SDavid du Colombier Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 12673e12c5d1SDavid du Colombier { 12683e12c5d1SDavid du Colombier register Cell *x, *vp, *arrayp, *cp, *ncp; 12693e12c5d1SDavid du Colombier Array *tp; 12703e12c5d1SDavid du Colombier int i; 12713e12c5d1SDavid du Colombier 12723e12c5d1SDavid du Colombier vp = execute(a[0]); 12733e12c5d1SDavid du Colombier arrayp = execute(a[1]); 12743e12c5d1SDavid du Colombier if (!isarr(arrayp)) { 12753e12c5d1SDavid du Colombier return true; 12763e12c5d1SDavid du Colombier } 12773e12c5d1SDavid du Colombier tp = (Array *) arrayp->sval; 12783e12c5d1SDavid du Colombier tempfree(arrayp); 12793e12c5d1SDavid du Colombier for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 12803e12c5d1SDavid du Colombier for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 12813e12c5d1SDavid du Colombier setsval(vp, cp->nval); 12823e12c5d1SDavid du Colombier ncp = cp->cnext; 12833e12c5d1SDavid du Colombier x = execute(a[2]); 12843e12c5d1SDavid du Colombier if (isbreak(x)) { 12853e12c5d1SDavid du Colombier tempfree(vp); 12863e12c5d1SDavid du Colombier return true; 12873e12c5d1SDavid du Colombier } 12883e12c5d1SDavid du Colombier if (isnext(x) || isexit(x) || isret(x)) { 12893e12c5d1SDavid du Colombier tempfree(vp); 12903e12c5d1SDavid du Colombier return(x); 12913e12c5d1SDavid du Colombier } 12923e12c5d1SDavid du Colombier tempfree(x); 12933e12c5d1SDavid du Colombier } 12943e12c5d1SDavid du Colombier } 12953e12c5d1SDavid du Colombier return true; 12963e12c5d1SDavid du Colombier } 12973e12c5d1SDavid du Colombier 1298*219b2ee8SDavid du Colombier /* if someone ever wants to run over the arrays in sorted order, */ 1299*219b2ee8SDavid du Colombier /* here it is. but it will likely run slower, not faster. */ 13003e12c5d1SDavid du Colombier 13013e12c5d1SDavid du Colombier /* 13023e12c5d1SDavid du Colombier *int qstrcmp(p, q) 13033e12c5d1SDavid du Colombier * uchar **p, **q; 13043e12c5d1SDavid du Colombier *{ 13053e12c5d1SDavid du Colombier * return strcmp(*p, *q); 13063e12c5d1SDavid du Colombier *} 13073e12c5d1SDavid du Colombier */ 13083e12c5d1SDavid du Colombier 13093e12c5d1SDavid du Colombier /*Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 13103e12c5d1SDavid du Colombier /*{ 13113e12c5d1SDavid du Colombier /* register Cell *x, *vp, *arrayp, *cp, *ncp, *ret; 13123e12c5d1SDavid du Colombier /* Array *tp; 13133e12c5d1SDavid du Colombier /* int i, ne; 13143e12c5d1SDavid du Colombier /*#define BIGENOUGH 1000 13153e12c5d1SDavid du Colombier /* uchar *elems[BIGENOUGH], **ep; 13163e12c5d1SDavid du Colombier /* 13173e12c5d1SDavid du Colombier /* vp = execute(a[0]); 13183e12c5d1SDavid du Colombier /* arrayp = execute(a[1]); 13193e12c5d1SDavid du Colombier /* if (!isarr(arrayp)) 13203e12c5d1SDavid du Colombier /* ERROR "%s is not an array", arrayp->nval FATAL; 13213e12c5d1SDavid du Colombier /* tp = (Array *) arrayp->sval; 13223e12c5d1SDavid du Colombier /* tempfree(arrayp); 13233e12c5d1SDavid du Colombier /* ep = elems; 13243e12c5d1SDavid du Colombier /* ret = true; 13253e12c5d1SDavid du Colombier /* if (tp->nelem >= BIGENOUGH) 13263e12c5d1SDavid du Colombier /* ep = (uchar **) malloc(tp->nelem * sizeof(char *)); 13273e12c5d1SDavid du Colombier /* 13283e12c5d1SDavid du Colombier /* for (i = ne = 0; i < tp->size; i++) 13293e12c5d1SDavid du Colombier /* for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext) 13303e12c5d1SDavid du Colombier /* ep[ne++] = cp->nval; 13313e12c5d1SDavid du Colombier /* if (ne != tp->nelem) 13323e12c5d1SDavid du Colombier /* ERROR "can't happen: lost elems %d vs. %d", ne, tp->nelem FATAL; 13333e12c5d1SDavid du Colombier /* qsort(ep, ne, sizeof(char *), qstrcmp); 13343e12c5d1SDavid du Colombier /* for (i = 0; i < ne; i++) { 13353e12c5d1SDavid du Colombier /* setsval(vp, ep[i]); 13363e12c5d1SDavid du Colombier /* x = execute(a[2]); 13373e12c5d1SDavid du Colombier /* if (isbreak(x)) { 13383e12c5d1SDavid du Colombier /* tempfree(vp); 13393e12c5d1SDavid du Colombier /* break; 13403e12c5d1SDavid du Colombier /* } 13413e12c5d1SDavid du Colombier /* if (isnext(x) || isexit(x) || isret(x)) { 13423e12c5d1SDavid du Colombier /* tempfree(vp); 13433e12c5d1SDavid du Colombier /* ret = x; 13443e12c5d1SDavid du Colombier /* break; 13453e12c5d1SDavid du Colombier /* } 13463e12c5d1SDavid du Colombier /* tempfree(x); 13473e12c5d1SDavid du Colombier /* } 13483e12c5d1SDavid du Colombier /* if (ep != elems) 13493e12c5d1SDavid du Colombier /* free(ep); 13503e12c5d1SDavid du Colombier /* return ret; 13513e12c5d1SDavid du Colombier /*} 13523e12c5d1SDavid du Colombier */ 13533e12c5d1SDavid du Colombier 13543e12c5d1SDavid du Colombier 1355*219b2ee8SDavid du Colombier Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 13563e12c5d1SDavid du Colombier { 13573e12c5d1SDavid du Colombier register Cell *x, *y; 13583e12c5d1SDavid du Colombier Awkfloat u; 13593e12c5d1SDavid du Colombier register int t; 1360*219b2ee8SDavid du Colombier wchar_t wc; 13613e12c5d1SDavid du Colombier uchar *p, buf[RECSIZE]; 1362*219b2ee8SDavid du Colombier char mbc[10]; 13633e12c5d1SDavid du Colombier Node *nextarg; 13643e12c5d1SDavid du Colombier FILE *fp; 13653e12c5d1SDavid du Colombier 13663e12c5d1SDavid du Colombier t = (int) a[0]; 13673e12c5d1SDavid du Colombier x = execute(a[1]); 13683e12c5d1SDavid du Colombier nextarg = a[1]->nnext; 13693e12c5d1SDavid du Colombier switch (t) { 13703e12c5d1SDavid du Colombier case FLENGTH: 13713e12c5d1SDavid du Colombier p = getsval(x); 13723e12c5d1SDavid du Colombier u = (Awkfloat) countposn(p, strlen(p)); break; 13733e12c5d1SDavid du Colombier case FLOG: 13743e12c5d1SDavid du Colombier u = errcheck(log(getfval(x)), "log"); break; 13753e12c5d1SDavid du Colombier case FINT: 13763e12c5d1SDavid du Colombier modf(getfval(x), &u); break; 13773e12c5d1SDavid du Colombier case FEXP: 13783e12c5d1SDavid du Colombier u = errcheck(exp(getfval(x)), "exp"); break; 13793e12c5d1SDavid du Colombier case FSQRT: 13803e12c5d1SDavid du Colombier u = errcheck(sqrt(getfval(x)), "sqrt"); break; 13813e12c5d1SDavid du Colombier case FSIN: 13823e12c5d1SDavid du Colombier u = sin(getfval(x)); break; 13833e12c5d1SDavid du Colombier case FCOS: 13843e12c5d1SDavid du Colombier u = cos(getfval(x)); break; 13853e12c5d1SDavid du Colombier case FATAN: 13863e12c5d1SDavid du Colombier if (nextarg == 0) { 13873e12c5d1SDavid du Colombier ERROR "atan2 requires two arguments; returning 1.0" WARNING; 13883e12c5d1SDavid du Colombier u = 1.0; 13893e12c5d1SDavid du Colombier } else { 13903e12c5d1SDavid du Colombier y = execute(a[1]->nnext); 13913e12c5d1SDavid du Colombier u = atan2(getfval(x), getfval(y)); 13923e12c5d1SDavid du Colombier tempfree(y); 13933e12c5d1SDavid du Colombier nextarg = nextarg->nnext; 13943e12c5d1SDavid du Colombier } 13953e12c5d1SDavid du Colombier break; 13963e12c5d1SDavid du Colombier case FSYSTEM: 13973e12c5d1SDavid du Colombier fflush(stdout); /* in case something is buffered already */ 13983e12c5d1SDavid du Colombier u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */ 13993e12c5d1SDavid du Colombier break; 14003e12c5d1SDavid du Colombier case FRAND: 14013e12c5d1SDavid du Colombier /* in principle, rand() returns something in 0..RAND_MAX */ 14023e12c5d1SDavid du Colombier u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; 14033e12c5d1SDavid du Colombier break; 14043e12c5d1SDavid du Colombier case FSRAND: 14053e12c5d1SDavid du Colombier if (x->tval & REC) /* no argument provided */ 14063e12c5d1SDavid du Colombier u = time((long *)0); 14073e12c5d1SDavid du Colombier else 14083e12c5d1SDavid du Colombier u = getfval(x); 14093e12c5d1SDavid du Colombier srand((int) u); u = (int) u; 14103e12c5d1SDavid du Colombier break; 14113e12c5d1SDavid du Colombier case FTOUPPER: 14123e12c5d1SDavid du Colombier case FTOLOWER: 14133e12c5d1SDavid du Colombier strcpy(buf, getsval(x)); 14143e12c5d1SDavid du Colombier if (t == FTOUPPER) { 14153e12c5d1SDavid du Colombier for (p = buf; *p; p++) 14163e12c5d1SDavid du Colombier if (islower(*p)) 14173e12c5d1SDavid du Colombier *p = toupper(*p); 14183e12c5d1SDavid du Colombier } else { 14193e12c5d1SDavid du Colombier for (p = buf; *p; p++) 14203e12c5d1SDavid du Colombier if (isupper(*p)) 14213e12c5d1SDavid du Colombier *p = tolower(*p); 14223e12c5d1SDavid du Colombier } 14233e12c5d1SDavid du Colombier tempfree(x); 14243e12c5d1SDavid du Colombier x = gettemp(); 14253e12c5d1SDavid du Colombier setsval(x, buf); 14263e12c5d1SDavid du Colombier return x; 14273e12c5d1SDavid du Colombier case FFLUSH: 14283e12c5d1SDavid du Colombier if ((fp = openfile(GT, getsval(x))) == NULL) 14293e12c5d1SDavid du Colombier u = EOF; 14303e12c5d1SDavid du Colombier else 14313e12c5d1SDavid du Colombier u = fflush(fp); 14323e12c5d1SDavid du Colombier break; 1433*219b2ee8SDavid du Colombier case FUTF: 1434*219b2ee8SDavid du Colombier wc = (int)getfval(x); 1435*219b2ee8SDavid du Colombier mbc[wctomb(mbc, wc)] = 0; 1436*219b2ee8SDavid du Colombier tempfree(x); 1437*219b2ee8SDavid du Colombier x = gettemp(); 1438*219b2ee8SDavid du Colombier setsval(x, mbc); 1439*219b2ee8SDavid du Colombier return x; 14403e12c5d1SDavid du Colombier default: /* can't happen */ 14413e12c5d1SDavid du Colombier ERROR "illegal function type %d", t FATAL; 14423e12c5d1SDavid du Colombier break; 14433e12c5d1SDavid du Colombier } 14443e12c5d1SDavid du Colombier tempfree(x); 14453e12c5d1SDavid du Colombier x = gettemp(); 14463e12c5d1SDavid du Colombier setfval(x, u); 14473e12c5d1SDavid du Colombier if (nextarg != 0) { 14483e12c5d1SDavid du Colombier ERROR "warning: function has too many arguments" WARNING; 14493e12c5d1SDavid du Colombier for ( ; nextarg; nextarg = nextarg->nnext) 14503e12c5d1SDavid du Colombier execute(nextarg); 14513e12c5d1SDavid du Colombier } 14523e12c5d1SDavid du Colombier return(x); 14533e12c5d1SDavid du Colombier } 14543e12c5d1SDavid du Colombier 1455*219b2ee8SDavid du Colombier Cell *printstat(Node **a, int n) /* print a[0] */ 14563e12c5d1SDavid du Colombier { 14573e12c5d1SDavid du Colombier register Node *x; 14583e12c5d1SDavid du Colombier register Cell *y; 14593e12c5d1SDavid du Colombier FILE *fp; 14603e12c5d1SDavid du Colombier 1461*219b2ee8SDavid du Colombier if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */ 14623e12c5d1SDavid du Colombier fp = stdout; 14633e12c5d1SDavid du Colombier else 14643e12c5d1SDavid du Colombier fp = redirect((int)a[1], a[2]); 14653e12c5d1SDavid du Colombier for (x = a[0]; x != NULL; x = x->nnext) { 14663e12c5d1SDavid du Colombier y = execute(x); 14673e12c5d1SDavid du Colombier fputs((char *)getsval(y), fp); 14683e12c5d1SDavid du Colombier tempfree(y); 14693e12c5d1SDavid du Colombier if (x->nnext == NULL) 14703e12c5d1SDavid du Colombier fputs((char *)*ORS, fp); 14713e12c5d1SDavid du Colombier else 14723e12c5d1SDavid du Colombier fputs((char *)*OFS, fp); 14733e12c5d1SDavid du Colombier } 14743e12c5d1SDavid du Colombier if (a[1] != 0) 14753e12c5d1SDavid du Colombier fflush(fp); 14763e12c5d1SDavid du Colombier if (ferror(fp)) 14773e12c5d1SDavid du Colombier ERROR "write error on %s", filename(fp) FATAL; 14783e12c5d1SDavid du Colombier return(true); 14793e12c5d1SDavid du Colombier } 14803e12c5d1SDavid du Colombier 14813e12c5d1SDavid du Colombier Cell *nullproc(Node **a, int n) 14823e12c5d1SDavid du Colombier { 14833e12c5d1SDavid du Colombier n; 14843e12c5d1SDavid du Colombier a; 14853e12c5d1SDavid du Colombier return 0; 14863e12c5d1SDavid du Colombier } 14873e12c5d1SDavid du Colombier 14883e12c5d1SDavid du Colombier 1489*219b2ee8SDavid du Colombier FILE *redirect(int a, Node *b) /* set up all i/o redirections */ 14903e12c5d1SDavid du Colombier { 14913e12c5d1SDavid du Colombier FILE *fp; 14923e12c5d1SDavid du Colombier Cell *x; 14933e12c5d1SDavid du Colombier uchar *fname; 14943e12c5d1SDavid du Colombier 14953e12c5d1SDavid du Colombier x = execute(b); 14963e12c5d1SDavid du Colombier fname = getsval(x); 14973e12c5d1SDavid du Colombier fp = openfile(a, fname); 14983e12c5d1SDavid du Colombier if (fp == NULL) 14993e12c5d1SDavid du Colombier ERROR "can't open file %s", fname FATAL; 15003e12c5d1SDavid du Colombier tempfree(x); 15013e12c5d1SDavid du Colombier return fp; 15023e12c5d1SDavid du Colombier } 15033e12c5d1SDavid du Colombier 1504*219b2ee8SDavid du Colombier struct files { 1505*219b2ee8SDavid du Colombier FILE *fp; 1506*219b2ee8SDavid du Colombier uchar *fname; 1507*219b2ee8SDavid du Colombier int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1508*219b2ee8SDavid du Colombier } files[FOPEN_MAX] ={ 1509*219b2ee8SDavid du Colombier { stdin, "/dev/stdin", LT }, /* watch out: don't free this! */ 1510*219b2ee8SDavid du Colombier { stdout, "/dev/stdout", GT }, 1511*219b2ee8SDavid du Colombier { stderr, "/dev/stderr", GT } 1512*219b2ee8SDavid du Colombier }; 1513*219b2ee8SDavid du Colombier 15143e12c5d1SDavid du Colombier FILE *openfile(int a, uchar *s) 15153e12c5d1SDavid du Colombier { 15163e12c5d1SDavid du Colombier register int i, m; 15173e12c5d1SDavid du Colombier register FILE *fp; 15183e12c5d1SDavid du Colombier 15193e12c5d1SDavid du Colombier if (*s == '\0') 15203e12c5d1SDavid du Colombier ERROR "null file name in print or getline" FATAL; 15213e12c5d1SDavid du Colombier for (i=0; i < FOPEN_MAX; i++) 15223e12c5d1SDavid du Colombier if (files[i].fname && strcmp(s, files[i].fname) == 0) 1523*219b2ee8SDavid du Colombier if (a == files[i].mode || a==APPEND && files[i].mode==GT) 15243e12c5d1SDavid du Colombier return files[i].fp; 15253e12c5d1SDavid du Colombier for (i=0; i < FOPEN_MAX; i++) 15263e12c5d1SDavid du Colombier if (files[i].fp == 0) 15273e12c5d1SDavid du Colombier break; 15283e12c5d1SDavid du Colombier if (i >= FOPEN_MAX) 15293e12c5d1SDavid du Colombier ERROR "%s makes too many open files", s FATAL; 15303e12c5d1SDavid du Colombier fflush(stdout); /* force a semblance of order */ 15313e12c5d1SDavid du Colombier m = a; 15323e12c5d1SDavid du Colombier if (a == GT) { 1533*219b2ee8SDavid du Colombier fp = fopen(s, "w"); 15343e12c5d1SDavid du Colombier } else if (a == APPEND) { 1535*219b2ee8SDavid du Colombier fp = fopen(s, "a"); 15363e12c5d1SDavid du Colombier m = GT; /* so can mix > and >> */ 15373e12c5d1SDavid du Colombier } else if (a == '|') { /* output pipe */ 1538*219b2ee8SDavid du Colombier fp = popen(s, "w"); 15393e12c5d1SDavid du Colombier } else if (a == LE) { /* input pipe */ 1540*219b2ee8SDavid du Colombier fp = popen(s, "r"); 15413e12c5d1SDavid du Colombier } else if (a == LT) { /* getline <file */ 1542*219b2ee8SDavid du Colombier fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */ 15433e12c5d1SDavid du Colombier } else /* can't happen */ 15443e12c5d1SDavid du Colombier ERROR "illegal redirection %d", a FATAL; 15453e12c5d1SDavid du Colombier if (fp != NULL) { 15463e12c5d1SDavid du Colombier files[i].fname = tostring(s); 15473e12c5d1SDavid du Colombier files[i].fp = fp; 15483e12c5d1SDavid du Colombier files[i].mode = m; 15493e12c5d1SDavid du Colombier } 15503e12c5d1SDavid du Colombier return fp; 15513e12c5d1SDavid du Colombier } 15523e12c5d1SDavid du Colombier 15533e12c5d1SDavid du Colombier uchar *filename(FILE *fp) 15543e12c5d1SDavid du Colombier { 15553e12c5d1SDavid du Colombier int i; 15563e12c5d1SDavid du Colombier 15573e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 15583e12c5d1SDavid du Colombier if (fp == files[i].fp) 15593e12c5d1SDavid du Colombier return files[i].fname; 1560*219b2ee8SDavid du Colombier return "???"; 15613e12c5d1SDavid du Colombier } 15623e12c5d1SDavid du Colombier 15633e12c5d1SDavid du Colombier Cell *closefile(Node **a, int n) 15643e12c5d1SDavid du Colombier { 15653e12c5d1SDavid du Colombier register Cell *x; 15663e12c5d1SDavid du Colombier int i, stat; 15673e12c5d1SDavid du Colombier 15683e12c5d1SDavid du Colombier n; 15693e12c5d1SDavid du Colombier x = execute(a[0]); 15703e12c5d1SDavid du Colombier getsval(x); 15713e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 15723e12c5d1SDavid du Colombier if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 15733e12c5d1SDavid du Colombier if (ferror(files[i].fp)) 15743e12c5d1SDavid du Colombier ERROR "i/o error occurred on %s", files[i].fname WARNING; 15753e12c5d1SDavid du Colombier if (files[i].mode == '|' || files[i].mode == LE) 15763e12c5d1SDavid du Colombier stat = pclose(files[i].fp); 15773e12c5d1SDavid du Colombier else 15783e12c5d1SDavid du Colombier stat = fclose(files[i].fp); 15793e12c5d1SDavid du Colombier if (stat == EOF) 15803e12c5d1SDavid du Colombier ERROR "i/o error occurred closing %s", files[i].fname WARNING; 1581*219b2ee8SDavid du Colombier if (i > 2) /* don't do /dev/std... */ 15823e12c5d1SDavid du Colombier xfree(files[i].fname); 15833e12c5d1SDavid du Colombier files[i].fname = NULL; /* watch out for ref thru this */ 15843e12c5d1SDavid du Colombier files[i].fp = NULL; 15853e12c5d1SDavid du Colombier } 15863e12c5d1SDavid du Colombier tempfree(x); 15873e12c5d1SDavid du Colombier return(true); 15883e12c5d1SDavid du Colombier } 15893e12c5d1SDavid du Colombier 15903e12c5d1SDavid du Colombier void closeall(void) 15913e12c5d1SDavid du Colombier { 15923e12c5d1SDavid du Colombier int i, stat; 15933e12c5d1SDavid du Colombier 15943e12c5d1SDavid du Colombier for (i = 0; i < FOPEN_MAX; i++) 15953e12c5d1SDavid du Colombier if (files[i].fp) { 15963e12c5d1SDavid du Colombier if (ferror(files[i].fp)) 15973e12c5d1SDavid du Colombier ERROR "i/o error occurred on %s", files[i].fname WARNING; 15983e12c5d1SDavid du Colombier if (files[i].mode == '|' || files[i].mode == LE) 15993e12c5d1SDavid du Colombier stat = pclose(files[i].fp); 16003e12c5d1SDavid du Colombier else 16013e12c5d1SDavid du Colombier stat = fclose(files[i].fp); 16023e12c5d1SDavid du Colombier if (stat == EOF) 16033e12c5d1SDavid du Colombier ERROR "i/o error occurred while closing %s", files[i].fname WARNING; 16043e12c5d1SDavid du Colombier } 16053e12c5d1SDavid du Colombier } 16063e12c5d1SDavid du Colombier 16073e12c5d1SDavid du Colombier #define SUBSIZE (20 * RECSIZE) 16083e12c5d1SDavid du Colombier 1609*219b2ee8SDavid du Colombier Cell *sub(Node **a, int nnn) /* substitute command */ 16103e12c5d1SDavid du Colombier { 16113e12c5d1SDavid du Colombier register uchar *sptr, *pb, *q; 16123e12c5d1SDavid du Colombier register Cell *x, *y, *result; 16133e12c5d1SDavid du Colombier uchar buf[SUBSIZE], *t; 16143e12c5d1SDavid du Colombier void *p; 16153e12c5d1SDavid du Colombier 16163e12c5d1SDavid du Colombier x = execute(a[3]); /* target string */ 16173e12c5d1SDavid du Colombier t = getsval(x); 1618*219b2ee8SDavid du Colombier if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 16193e12c5d1SDavid du Colombier p = (void *) a[1]; /* regular expression */ 16203e12c5d1SDavid du Colombier else { 16213e12c5d1SDavid du Colombier y = execute(a[1]); 16223e12c5d1SDavid du Colombier p = compre(getsval(y)); 16233e12c5d1SDavid du Colombier tempfree(y); 16243e12c5d1SDavid du Colombier } 16253e12c5d1SDavid du Colombier y = execute(a[2]); /* replacement string */ 16263e12c5d1SDavid du Colombier result = false; 16273e12c5d1SDavid du Colombier if (pmatch(p, t, t)) { 16283e12c5d1SDavid du Colombier pb = buf; 16293e12c5d1SDavid du Colombier sptr = t; 16303e12c5d1SDavid du Colombier while (sptr < patbeg) 16313e12c5d1SDavid du Colombier *pb++ = *sptr++; 16323e12c5d1SDavid du Colombier sptr = getsval(y); 16333e12c5d1SDavid du Colombier while (*sptr != 0 && pb < buf + SUBSIZE - 1) 16343e12c5d1SDavid du Colombier if (*sptr == '\\' && *(sptr+1) == '&') { 16353e12c5d1SDavid du Colombier sptr++; /* skip \, */ 16363e12c5d1SDavid du Colombier *pb++ = *sptr++; /* add & */ 16373e12c5d1SDavid du Colombier } else if (*sptr == '&') { 16383e12c5d1SDavid du Colombier sptr++; 16393e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 16403e12c5d1SDavid du Colombier *pb++ = *q++; 16413e12c5d1SDavid du Colombier } else 16423e12c5d1SDavid du Colombier *pb++ = *sptr++; 16433e12c5d1SDavid du Colombier *pb = '\0'; 16443e12c5d1SDavid du Colombier if (pb >= buf + SUBSIZE) 1645*219b2ee8SDavid du Colombier ERROR "sub() result %.30s too big", buf FATAL; 16463e12c5d1SDavid du Colombier sptr = patbeg + patlen; 16473e12c5d1SDavid du Colombier if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) 16483e12c5d1SDavid du Colombier while (*pb++ = *sptr++) 16493e12c5d1SDavid du Colombier ; 16503e12c5d1SDavid du Colombier if (pb >= buf + SUBSIZE) 1651*219b2ee8SDavid du Colombier ERROR "sub() result %.30s too big", buf FATAL; 16523e12c5d1SDavid du Colombier setsval(x, buf); 16533e12c5d1SDavid du Colombier result = true;; 16543e12c5d1SDavid du Colombier } 16553e12c5d1SDavid du Colombier tempfree(x); 16563e12c5d1SDavid du Colombier tempfree(y); 16573e12c5d1SDavid du Colombier return result; 16583e12c5d1SDavid du Colombier } 16593e12c5d1SDavid du Colombier 1660*219b2ee8SDavid du Colombier Cell *gsub(Node **a, int nnn) /* global substitute */ 16613e12c5d1SDavid du Colombier { 16623e12c5d1SDavid du Colombier register Cell *x, *y; 16633e12c5d1SDavid du Colombier register uchar *rptr, *sptr, *t, *pb, *c; 16643e12c5d1SDavid du Colombier uchar buf[SUBSIZE]; 16653e12c5d1SDavid du Colombier register void *p; 16663e12c5d1SDavid du Colombier int mflag, num; 16673e12c5d1SDavid du Colombier 16683e12c5d1SDavid du Colombier mflag = 0; /* if mflag == 0, can replace empty string */ 16693e12c5d1SDavid du Colombier num = 0; 16703e12c5d1SDavid du Colombier x = execute(a[3]); /* target string */ 16713e12c5d1SDavid du Colombier c = t = getsval(x); 1672*219b2ee8SDavid du Colombier if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */ 16733e12c5d1SDavid du Colombier p = (void *) a[1]; /* regular expression */ 16743e12c5d1SDavid du Colombier else { 16753e12c5d1SDavid du Colombier y = execute(a[1]); 16763e12c5d1SDavid du Colombier p = compre(getsval(y)); 16773e12c5d1SDavid du Colombier tempfree(y); 16783e12c5d1SDavid du Colombier } 16793e12c5d1SDavid du Colombier y = execute(a[2]); /* replacement string */ 16803e12c5d1SDavid du Colombier if (pmatch(p, t, c)) { 16813e12c5d1SDavid du Colombier pb = buf; 16823e12c5d1SDavid du Colombier rptr = getsval(y); 16833e12c5d1SDavid du Colombier do { 16843e12c5d1SDavid du Colombier /* 16853e12c5d1SDavid du Colombier uchar *p; 16863e12c5d1SDavid du Colombier int i; 16873e12c5d1SDavid du Colombier printf("target string: %s, *patbeg = %o, patlen = %d\n", 16883e12c5d1SDavid du Colombier t, *patbeg, patlen); 16893e12c5d1SDavid du Colombier printf(" match found: "); 16903e12c5d1SDavid du Colombier p=patbeg; 16913e12c5d1SDavid du Colombier for (i=0; i<patlen; i++) 16923e12c5d1SDavid du Colombier printf("%c", *p++); 16933e12c5d1SDavid du Colombier printf("\n"); 16943e12c5d1SDavid du Colombier */ 16953e12c5d1SDavid du Colombier if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 16963e12c5d1SDavid du Colombier if (mflag == 0) { /* can replace empty */ 16973e12c5d1SDavid du Colombier num++; 16983e12c5d1SDavid du Colombier sptr = rptr; 16993e12c5d1SDavid du Colombier while (*sptr != 0 && pb < buf + SUBSIZE-1) 17003e12c5d1SDavid du Colombier if (*sptr == '\\' && *(sptr+1) == '&') { 17013e12c5d1SDavid du Colombier sptr++; 17023e12c5d1SDavid du Colombier *pb++ = *sptr++; 17033e12c5d1SDavid du Colombier } else if (*sptr == '&') { 17043e12c5d1SDavid du Colombier uchar *q; 17053e12c5d1SDavid du Colombier sptr++; 17063e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 17073e12c5d1SDavid du Colombier *pb++ = *q++; 17083e12c5d1SDavid du Colombier } else 17093e12c5d1SDavid du Colombier *pb++ = *sptr++; 17103e12c5d1SDavid du Colombier } 17113e12c5d1SDavid du Colombier if (*c == 0) /* at end */ 17123e12c5d1SDavid du Colombier goto done; 17133e12c5d1SDavid du Colombier *pb++ = *c++; 17143e12c5d1SDavid du Colombier if (pb >= buf + SUBSIZE-1) 1715*219b2ee8SDavid du Colombier ERROR "gsub() result %.30s too big", buf FATAL; 17163e12c5d1SDavid du Colombier mflag = 0; 17173e12c5d1SDavid du Colombier } 17183e12c5d1SDavid du Colombier else { /* matched nonempty string */ 17193e12c5d1SDavid du Colombier num++; 17203e12c5d1SDavid du Colombier sptr = c; 17213e12c5d1SDavid du Colombier while (sptr < patbeg && pb < buf + SUBSIZE-1) 17223e12c5d1SDavid du Colombier *pb++ = *sptr++; 17233e12c5d1SDavid du Colombier sptr = rptr; 17243e12c5d1SDavid du Colombier while (*sptr != 0 && pb < buf + SUBSIZE-1) 17253e12c5d1SDavid du Colombier if (*sptr == '\\' && *(sptr+1) == '&') { 17263e12c5d1SDavid du Colombier sptr++; 17273e12c5d1SDavid du Colombier *pb++ = *sptr++; 17283e12c5d1SDavid du Colombier } else if (*sptr == '&') { 17293e12c5d1SDavid du Colombier uchar *q; 17303e12c5d1SDavid du Colombier sptr++; 17313e12c5d1SDavid du Colombier for (q = patbeg; q < patbeg+patlen; ) 17323e12c5d1SDavid du Colombier *pb++ = *q++; 17333e12c5d1SDavid du Colombier } else 17343e12c5d1SDavid du Colombier *pb++ = *sptr++; 17353e12c5d1SDavid du Colombier c = patbeg + patlen; 17363e12c5d1SDavid du Colombier if ((c[-1] == 0) || (*c == 0)) 17373e12c5d1SDavid du Colombier goto done; 17383e12c5d1SDavid du Colombier if (pb >= buf + SUBSIZE-1) 1739*219b2ee8SDavid du Colombier ERROR "gsub() result %.30s too big", buf FATAL; 17403e12c5d1SDavid du Colombier mflag = 1; 17413e12c5d1SDavid du Colombier } 17423e12c5d1SDavid du Colombier } while (pmatch(p, t, c)); 17433e12c5d1SDavid du Colombier sptr = c; 17443e12c5d1SDavid du Colombier while (*pb++ = *sptr++) 17453e12c5d1SDavid du Colombier ; 17463e12c5d1SDavid du Colombier done: if (pb >= buf + SUBSIZE-1) 1747*219b2ee8SDavid du Colombier ERROR "gsub() result %.30s too big", buf FATAL; 17483e12c5d1SDavid du Colombier *pb = '\0'; 17493e12c5d1SDavid du Colombier setsval(x, buf); 17503e12c5d1SDavid du Colombier } 17513e12c5d1SDavid du Colombier tempfree(x); 17523e12c5d1SDavid du Colombier tempfree(y); 17533e12c5d1SDavid du Colombier x = gettemp(); 17543e12c5d1SDavid du Colombier x->tval = NUM; 17553e12c5d1SDavid du Colombier x->fval = num; 17563e12c5d1SDavid du Colombier return(x); 17573e12c5d1SDavid du Colombier } 1758