174a4d8c2SCharles.Forsyth /****************************************************************
274a4d8c2SCharles.Forsyth Copyright (C) Lucent Technologies 1997
374a4d8c2SCharles.Forsyth All Rights Reserved
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth Permission to use, copy, modify, and distribute this software and
674a4d8c2SCharles.Forsyth its documentation for any purpose and without fee is hereby
774a4d8c2SCharles.Forsyth granted, provided that the above copyright notice appear in all
874a4d8c2SCharles.Forsyth copies and that both that the copyright notice and this
974a4d8c2SCharles.Forsyth permission notice and warranty disclaimer appear in supporting
1074a4d8c2SCharles.Forsyth documentation, and that the name Lucent Technologies or any of
1174a4d8c2SCharles.Forsyth its entities not be used in advertising or publicity pertaining
1274a4d8c2SCharles.Forsyth to distribution of the software without specific, written prior
1374a4d8c2SCharles.Forsyth permission.
1474a4d8c2SCharles.Forsyth
1574a4d8c2SCharles.Forsyth LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1674a4d8c2SCharles.Forsyth INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
1774a4d8c2SCharles.Forsyth IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
1874a4d8c2SCharles.Forsyth SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1974a4d8c2SCharles.Forsyth WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
2074a4d8c2SCharles.Forsyth IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2174a4d8c2SCharles.Forsyth ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
2274a4d8c2SCharles.Forsyth THIS SOFTWARE.
2374a4d8c2SCharles.Forsyth ****************************************************************/
2474a4d8c2SCharles.Forsyth
2574a4d8c2SCharles.Forsyth #define DEBUG
2674a4d8c2SCharles.Forsyth #include <stdio.h>
2774a4d8c2SCharles.Forsyth #include <ctype.h>
2874a4d8c2SCharles.Forsyth #include <setjmp.h>
2974a4d8c2SCharles.Forsyth #include <math.h>
3074a4d8c2SCharles.Forsyth #include <string.h>
3174a4d8c2SCharles.Forsyth #include <stdlib.h>
3274a4d8c2SCharles.Forsyth #include <time.h>
3374a4d8c2SCharles.Forsyth #include "awk.h"
3474a4d8c2SCharles.Forsyth #include "ytab.h"
3574a4d8c2SCharles.Forsyth
3674a4d8c2SCharles.Forsyth #define tempfree(x) if (istemp(x)) tfree(x); else
3774a4d8c2SCharles.Forsyth
3874a4d8c2SCharles.Forsyth /*
3974a4d8c2SCharles.Forsyth #undef tempfree
4074a4d8c2SCharles.Forsyth
4174a4d8c2SCharles.Forsyth void tempfree(Cell *p) {
4274a4d8c2SCharles.Forsyth if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
4374a4d8c2SCharles.Forsyth WARNING("bad csub %d in Cell %d %s",
4474a4d8c2SCharles.Forsyth p->csub, p->ctype, p->sval);
4574a4d8c2SCharles.Forsyth }
4674a4d8c2SCharles.Forsyth if (istemp(p))
4774a4d8c2SCharles.Forsyth tfree(p);
4874a4d8c2SCharles.Forsyth }
4974a4d8c2SCharles.Forsyth */
5074a4d8c2SCharles.Forsyth
5174a4d8c2SCharles.Forsyth #ifdef _NFILE
5274a4d8c2SCharles.Forsyth #ifndef FOPEN_MAX
5374a4d8c2SCharles.Forsyth #define FOPEN_MAX _NFILE
5474a4d8c2SCharles.Forsyth #endif
5574a4d8c2SCharles.Forsyth #endif
5674a4d8c2SCharles.Forsyth
5774a4d8c2SCharles.Forsyth #ifndef FOPEN_MAX
5874a4d8c2SCharles.Forsyth #define FOPEN_MAX 40 /* max number of open files */
5974a4d8c2SCharles.Forsyth #endif
6074a4d8c2SCharles.Forsyth
6174a4d8c2SCharles.Forsyth #ifndef RAND_MAX
6274a4d8c2SCharles.Forsyth #define RAND_MAX 32767 /* all that ansi guarantees */
6374a4d8c2SCharles.Forsyth #endif
6474a4d8c2SCharles.Forsyth
6574a4d8c2SCharles.Forsyth jmp_buf env;
6674a4d8c2SCharles.Forsyth extern int pairstack[];
6774a4d8c2SCharles.Forsyth
6874a4d8c2SCharles.Forsyth Node *winner = NULL; /* root of parse tree */
6974a4d8c2SCharles.Forsyth Cell *tmps; /* free temporary cells for execution */
7074a4d8c2SCharles.Forsyth
7174a4d8c2SCharles.Forsyth static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
7274a4d8c2SCharles.Forsyth Cell *True = &truecell;
7374a4d8c2SCharles.Forsyth static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
7474a4d8c2SCharles.Forsyth Cell *False = &falsecell;
7574a4d8c2SCharles.Forsyth static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
7674a4d8c2SCharles.Forsyth Cell *jbreak = &breakcell;
7774a4d8c2SCharles.Forsyth static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
7874a4d8c2SCharles.Forsyth Cell *jcont = &contcell;
7974a4d8c2SCharles.Forsyth static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
8074a4d8c2SCharles.Forsyth Cell *jnext = &nextcell;
8174a4d8c2SCharles.Forsyth static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
8274a4d8c2SCharles.Forsyth Cell *jnextfile = &nextfilecell;
8374a4d8c2SCharles.Forsyth static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
8474a4d8c2SCharles.Forsyth Cell *jexit = &exitcell;
8574a4d8c2SCharles.Forsyth static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
8674a4d8c2SCharles.Forsyth Cell *jret = &retcell;
8774a4d8c2SCharles.Forsyth static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
8874a4d8c2SCharles.Forsyth
8974a4d8c2SCharles.Forsyth Node *curnode = NULL; /* the node being executed, for debugging */
9074a4d8c2SCharles.Forsyth
9174a4d8c2SCharles.Forsyth /* buffer memory management */
adjbuf(char ** pbuf,int * psiz,int minlen,int quantum,char ** pbptr,char * whatrtn)9274a4d8c2SCharles.Forsyth int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
9374a4d8c2SCharles.Forsyth char *whatrtn)
9474a4d8c2SCharles.Forsyth /* pbuf: address of pointer to buffer being managed
9574a4d8c2SCharles.Forsyth * psiz: address of buffer size variable
9674a4d8c2SCharles.Forsyth * minlen: minimum length of buffer needed
9774a4d8c2SCharles.Forsyth * quantum: buffer size quantum
9874a4d8c2SCharles.Forsyth * pbptr: address of movable pointer into buffer, or 0 if none
9974a4d8c2SCharles.Forsyth * whatrtn: name of the calling routine if failure should cause fatal error
10074a4d8c2SCharles.Forsyth *
10174a4d8c2SCharles.Forsyth * return 0 for realloc failure, !=0 for success
10274a4d8c2SCharles.Forsyth */
10374a4d8c2SCharles.Forsyth {
10474a4d8c2SCharles.Forsyth if (minlen > *psiz) {
10574a4d8c2SCharles.Forsyth char *tbuf;
10674a4d8c2SCharles.Forsyth int rminlen = quantum ? minlen % quantum : 0;
10774a4d8c2SCharles.Forsyth int boff = pbptr ? *pbptr - *pbuf : 0;
10874a4d8c2SCharles.Forsyth /* round up to next multiple of quantum */
10974a4d8c2SCharles.Forsyth if (rminlen)
11074a4d8c2SCharles.Forsyth minlen += quantum - rminlen;
11174a4d8c2SCharles.Forsyth tbuf = (char *) realloc(*pbuf, minlen);
11274a4d8c2SCharles.Forsyth if (tbuf == NULL) {
11374a4d8c2SCharles.Forsyth if (whatrtn)
11474a4d8c2SCharles.Forsyth FATAL("out of memory in %s", whatrtn);
11574a4d8c2SCharles.Forsyth return 0;
11674a4d8c2SCharles.Forsyth }
11774a4d8c2SCharles.Forsyth *pbuf = tbuf;
11874a4d8c2SCharles.Forsyth *psiz = minlen;
11974a4d8c2SCharles.Forsyth if (pbptr)
12074a4d8c2SCharles.Forsyth *pbptr = tbuf + boff;
12174a4d8c2SCharles.Forsyth }
12274a4d8c2SCharles.Forsyth return 1;
12374a4d8c2SCharles.Forsyth }
12474a4d8c2SCharles.Forsyth
run(Node * a)12574a4d8c2SCharles.Forsyth void run(Node *a) /* execution of parse tree starts here */
12674a4d8c2SCharles.Forsyth {
12774a4d8c2SCharles.Forsyth extern void stdinit(void);
12874a4d8c2SCharles.Forsyth
12974a4d8c2SCharles.Forsyth stdinit();
13074a4d8c2SCharles.Forsyth execute(a);
13174a4d8c2SCharles.Forsyth closeall();
13274a4d8c2SCharles.Forsyth }
13374a4d8c2SCharles.Forsyth
execute(Node * u)13474a4d8c2SCharles.Forsyth Cell *execute(Node *u) /* execute a node of the parse tree */
13574a4d8c2SCharles.Forsyth {
13674a4d8c2SCharles.Forsyth Cell *(*proc)(Node **, int);
13774a4d8c2SCharles.Forsyth Cell *x;
13874a4d8c2SCharles.Forsyth Node *a;
13974a4d8c2SCharles.Forsyth
14074a4d8c2SCharles.Forsyth if (u == NULL)
14174a4d8c2SCharles.Forsyth return(True);
14274a4d8c2SCharles.Forsyth for (a = u; ; a = a->nnext) {
14374a4d8c2SCharles.Forsyth curnode = a;
14474a4d8c2SCharles.Forsyth if (isvalue(a)) {
14574a4d8c2SCharles.Forsyth x = (Cell *) (a->narg[0]);
14674a4d8c2SCharles.Forsyth if (isfld(x) && !donefld)
14774a4d8c2SCharles.Forsyth fldbld();
14874a4d8c2SCharles.Forsyth else if (isrec(x) && !donerec)
14974a4d8c2SCharles.Forsyth recbld();
15074a4d8c2SCharles.Forsyth return(x);
15174a4d8c2SCharles.Forsyth }
15274a4d8c2SCharles.Forsyth if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
15374a4d8c2SCharles.Forsyth FATAL("illegal statement");
15474a4d8c2SCharles.Forsyth proc = proctab[a->nobj-FIRSTTOKEN];
15574a4d8c2SCharles.Forsyth x = (*proc)(a->narg, a->nobj);
15674a4d8c2SCharles.Forsyth if (isfld(x) && !donefld)
15774a4d8c2SCharles.Forsyth fldbld();
15874a4d8c2SCharles.Forsyth else if (isrec(x) && !donerec)
15974a4d8c2SCharles.Forsyth recbld();
16074a4d8c2SCharles.Forsyth if (isexpr(a))
16174a4d8c2SCharles.Forsyth return(x);
16274a4d8c2SCharles.Forsyth if (isjump(x))
16374a4d8c2SCharles.Forsyth return(x);
16474a4d8c2SCharles.Forsyth if (a->nnext == NULL)
16574a4d8c2SCharles.Forsyth return(x);
16674a4d8c2SCharles.Forsyth tempfree(x);
16774a4d8c2SCharles.Forsyth }
16874a4d8c2SCharles.Forsyth }
16974a4d8c2SCharles.Forsyth
17074a4d8c2SCharles.Forsyth
program(Node ** a,int n)17174a4d8c2SCharles.Forsyth Cell *program(Node **a, int n) /* execute an awk program */
17274a4d8c2SCharles.Forsyth { /* a[0] = BEGIN, a[1] = body, a[2] = END */
17374a4d8c2SCharles.Forsyth Cell *x;
17474a4d8c2SCharles.Forsyth
17574a4d8c2SCharles.Forsyth if (setjmp(env) != 0)
17674a4d8c2SCharles.Forsyth goto ex;
17774a4d8c2SCharles.Forsyth if (a[0]) { /* BEGIN */
17874a4d8c2SCharles.Forsyth x = execute(a[0]);
17974a4d8c2SCharles.Forsyth if (isexit(x))
18074a4d8c2SCharles.Forsyth return(True);
18174a4d8c2SCharles.Forsyth if (isjump(x))
18274a4d8c2SCharles.Forsyth FATAL("illegal break, continue, next or nextfile from BEGIN");
18374a4d8c2SCharles.Forsyth tempfree(x);
18474a4d8c2SCharles.Forsyth }
18574a4d8c2SCharles.Forsyth if (a[1] || a[2])
18674a4d8c2SCharles.Forsyth while (getrec(&record, &recsize, 1) > 0) {
18774a4d8c2SCharles.Forsyth x = execute(a[1]);
18874a4d8c2SCharles.Forsyth if (isexit(x))
18974a4d8c2SCharles.Forsyth break;
19074a4d8c2SCharles.Forsyth tempfree(x);
19174a4d8c2SCharles.Forsyth }
19274a4d8c2SCharles.Forsyth ex:
19374a4d8c2SCharles.Forsyth if (setjmp(env) != 0) /* handles exit within END */
19474a4d8c2SCharles.Forsyth goto ex1;
19574a4d8c2SCharles.Forsyth if (a[2]) { /* END */
19674a4d8c2SCharles.Forsyth x = execute(a[2]);
19774a4d8c2SCharles.Forsyth if (isbreak(x) || isnext(x) || iscont(x))
19874a4d8c2SCharles.Forsyth FATAL("illegal break, continue, next or nextfile from END");
19974a4d8c2SCharles.Forsyth tempfree(x);
20074a4d8c2SCharles.Forsyth }
20174a4d8c2SCharles.Forsyth ex1:
20274a4d8c2SCharles.Forsyth return(True);
20374a4d8c2SCharles.Forsyth }
20474a4d8c2SCharles.Forsyth
20574a4d8c2SCharles.Forsyth struct Frame { /* stack frame for awk function calls */
20674a4d8c2SCharles.Forsyth int nargs; /* number of arguments in this call */
20774a4d8c2SCharles.Forsyth Cell *fcncell; /* pointer to Cell for function */
20874a4d8c2SCharles.Forsyth Cell **args; /* pointer to array of arguments after execute */
20974a4d8c2SCharles.Forsyth Cell *retval; /* return value */
21074a4d8c2SCharles.Forsyth };
21174a4d8c2SCharles.Forsyth
21274a4d8c2SCharles.Forsyth #define NARGS 50 /* max args in a call */
21374a4d8c2SCharles.Forsyth
21474a4d8c2SCharles.Forsyth struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
21574a4d8c2SCharles.Forsyth int nframe = 0; /* number of frames allocated */
21674a4d8c2SCharles.Forsyth struct Frame *fp = NULL; /* frame pointer. bottom level unused */
21774a4d8c2SCharles.Forsyth
call(Node ** a,int n)21874a4d8c2SCharles.Forsyth Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
21974a4d8c2SCharles.Forsyth {
22074a4d8c2SCharles.Forsyth static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
22174a4d8c2SCharles.Forsyth int i, ncall, ndef;
22274a4d8c2SCharles.Forsyth Node *x;
22374a4d8c2SCharles.Forsyth Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
22474a4d8c2SCharles.Forsyth Cell *y, *z, *fcn;
22574a4d8c2SCharles.Forsyth char *s;
22674a4d8c2SCharles.Forsyth
22774a4d8c2SCharles.Forsyth fcn = execute(a[0]); /* the function itself */
22874a4d8c2SCharles.Forsyth s = fcn->nval;
22974a4d8c2SCharles.Forsyth if (!isfcn(fcn))
23074a4d8c2SCharles.Forsyth FATAL("calling undefined function %s", s);
23174a4d8c2SCharles.Forsyth if (frame == NULL) {
23274a4d8c2SCharles.Forsyth fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
23374a4d8c2SCharles.Forsyth if (frame == NULL)
23474a4d8c2SCharles.Forsyth FATAL("out of space for stack frames calling %s", s);
23574a4d8c2SCharles.Forsyth }
23674a4d8c2SCharles.Forsyth for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
23774a4d8c2SCharles.Forsyth ncall++;
23874a4d8c2SCharles.Forsyth ndef = (int) fcn->fval; /* args in defn */
23974a4d8c2SCharles.Forsyth dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
24074a4d8c2SCharles.Forsyth if (ncall > ndef)
24174a4d8c2SCharles.Forsyth WARNING("function %s called with %d args, uses only %d",
24274a4d8c2SCharles.Forsyth s, ncall, ndef);
24374a4d8c2SCharles.Forsyth if (ncall + ndef > NARGS)
24474a4d8c2SCharles.Forsyth FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
24574a4d8c2SCharles.Forsyth for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
24674a4d8c2SCharles.Forsyth dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
24774a4d8c2SCharles.Forsyth y = execute(x);
24874a4d8c2SCharles.Forsyth oargs[i] = y;
24974a4d8c2SCharles.Forsyth dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
25074a4d8c2SCharles.Forsyth i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
25174a4d8c2SCharles.Forsyth if (isfcn(y))
25274a4d8c2SCharles.Forsyth FATAL("can't use function %s as argument in %s", y->nval, s);
25374a4d8c2SCharles.Forsyth if (isarr(y))
25474a4d8c2SCharles.Forsyth args[i] = y; /* arrays by ref */
25574a4d8c2SCharles.Forsyth else
25674a4d8c2SCharles.Forsyth args[i] = copycell(y);
25774a4d8c2SCharles.Forsyth tempfree(y);
25874a4d8c2SCharles.Forsyth }
25974a4d8c2SCharles.Forsyth for ( ; i < ndef; i++) { /* add null args for ones not provided */
26074a4d8c2SCharles.Forsyth args[i] = gettemp();
26174a4d8c2SCharles.Forsyth *args[i] = newcopycell;
26274a4d8c2SCharles.Forsyth }
26374a4d8c2SCharles.Forsyth fp++; /* now ok to up frame */
26474a4d8c2SCharles.Forsyth if (fp >= frame + nframe) {
26574a4d8c2SCharles.Forsyth int dfp = fp - frame; /* old index */
26674a4d8c2SCharles.Forsyth frame = (struct Frame *)
26774a4d8c2SCharles.Forsyth realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
26874a4d8c2SCharles.Forsyth if (frame == NULL)
26974a4d8c2SCharles.Forsyth FATAL("out of space for stack frames in %s", s);
27074a4d8c2SCharles.Forsyth fp = frame + dfp;
27174a4d8c2SCharles.Forsyth }
27274a4d8c2SCharles.Forsyth fp->fcncell = fcn;
27374a4d8c2SCharles.Forsyth fp->args = args;
27474a4d8c2SCharles.Forsyth fp->nargs = ndef; /* number defined with (excess are locals) */
27574a4d8c2SCharles.Forsyth fp->retval = gettemp();
27674a4d8c2SCharles.Forsyth
27774a4d8c2SCharles.Forsyth dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
27874a4d8c2SCharles.Forsyth y = execute((Node *)(fcn->sval)); /* execute body */
27974a4d8c2SCharles.Forsyth dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
28074a4d8c2SCharles.Forsyth
28174a4d8c2SCharles.Forsyth for (i = 0; i < ndef; i++) {
28274a4d8c2SCharles.Forsyth Cell *t = fp->args[i];
28374a4d8c2SCharles.Forsyth if (isarr(t)) {
28474a4d8c2SCharles.Forsyth if (t->csub == CCOPY) {
28574a4d8c2SCharles.Forsyth if (i >= ncall) {
28674a4d8c2SCharles.Forsyth freesymtab(t);
28774a4d8c2SCharles.Forsyth t->csub = CTEMP;
28874a4d8c2SCharles.Forsyth tempfree(t);
28974a4d8c2SCharles.Forsyth } else {
29074a4d8c2SCharles.Forsyth oargs[i]->tval = t->tval;
29174a4d8c2SCharles.Forsyth oargs[i]->tval &= ~(STR|NUM|DONTFREE);
29274a4d8c2SCharles.Forsyth oargs[i]->sval = t->sval;
29374a4d8c2SCharles.Forsyth tempfree(t);
29474a4d8c2SCharles.Forsyth }
29574a4d8c2SCharles.Forsyth }
29674a4d8c2SCharles.Forsyth } else if (t != y) { /* kludge to prevent freeing twice */
29774a4d8c2SCharles.Forsyth t->csub = CTEMP;
29874a4d8c2SCharles.Forsyth tempfree(t);
29974a4d8c2SCharles.Forsyth }
30074a4d8c2SCharles.Forsyth }
30174a4d8c2SCharles.Forsyth tempfree(fcn);
30274a4d8c2SCharles.Forsyth if (isexit(y) || isnext(y))
30374a4d8c2SCharles.Forsyth return y;
30474a4d8c2SCharles.Forsyth tempfree(y); /* this can free twice! */
30574a4d8c2SCharles.Forsyth z = fp->retval; /* return value */
30674a4d8c2SCharles.Forsyth dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
30774a4d8c2SCharles.Forsyth fp--;
30874a4d8c2SCharles.Forsyth return(z);
30974a4d8c2SCharles.Forsyth }
31074a4d8c2SCharles.Forsyth
copycell(Cell * x)31174a4d8c2SCharles.Forsyth Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
31274a4d8c2SCharles.Forsyth {
31374a4d8c2SCharles.Forsyth Cell *y;
31474a4d8c2SCharles.Forsyth
31574a4d8c2SCharles.Forsyth y = gettemp();
31674a4d8c2SCharles.Forsyth y->csub = CCOPY; /* prevents freeing until call is over */
31774a4d8c2SCharles.Forsyth y->nval = x->nval; /* BUG? */
31874a4d8c2SCharles.Forsyth if (isstr(x))
31974a4d8c2SCharles.Forsyth y->sval = tostring(x->sval);
32074a4d8c2SCharles.Forsyth y->fval = x->fval;
32174a4d8c2SCharles.Forsyth y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
32274a4d8c2SCharles.Forsyth /* is DONTFREE right? */
32374a4d8c2SCharles.Forsyth return y;
32474a4d8c2SCharles.Forsyth }
32574a4d8c2SCharles.Forsyth
arg(Node ** a,int n)32674a4d8c2SCharles.Forsyth Cell *arg(Node **a, int n) /* nth argument of a function */
32774a4d8c2SCharles.Forsyth {
32874a4d8c2SCharles.Forsyth
32974a4d8c2SCharles.Forsyth n = ptoi(a[0]); /* argument number, counting from 0 */
33074a4d8c2SCharles.Forsyth dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
33174a4d8c2SCharles.Forsyth if (n+1 > fp->nargs)
33274a4d8c2SCharles.Forsyth FATAL("argument #%d of function %s was not supplied",
33374a4d8c2SCharles.Forsyth n+1, fp->fcncell->nval);
33474a4d8c2SCharles.Forsyth return fp->args[n];
33574a4d8c2SCharles.Forsyth }
33674a4d8c2SCharles.Forsyth
jump(Node ** a,int n)33774a4d8c2SCharles.Forsyth Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
33874a4d8c2SCharles.Forsyth {
33974a4d8c2SCharles.Forsyth Cell *y;
34074a4d8c2SCharles.Forsyth
34174a4d8c2SCharles.Forsyth switch (n) {
34274a4d8c2SCharles.Forsyth case EXIT:
34374a4d8c2SCharles.Forsyth if (a[0] != NULL) {
34474a4d8c2SCharles.Forsyth y = execute(a[0]);
34574a4d8c2SCharles.Forsyth errorflag = (int) getfval(y);
34674a4d8c2SCharles.Forsyth tempfree(y);
34774a4d8c2SCharles.Forsyth }
34874a4d8c2SCharles.Forsyth longjmp(env, 1);
34974a4d8c2SCharles.Forsyth case RETURN:
35074a4d8c2SCharles.Forsyth if (a[0] != NULL) {
35174a4d8c2SCharles.Forsyth y = execute(a[0]);
35274a4d8c2SCharles.Forsyth if ((y->tval & (STR|NUM)) == (STR|NUM)) {
35374a4d8c2SCharles.Forsyth setsval(fp->retval, getsval(y));
35474a4d8c2SCharles.Forsyth fp->retval->fval = getfval(y);
35574a4d8c2SCharles.Forsyth fp->retval->tval |= NUM;
35674a4d8c2SCharles.Forsyth }
35774a4d8c2SCharles.Forsyth else if (y->tval & STR)
35874a4d8c2SCharles.Forsyth setsval(fp->retval, getsval(y));
35974a4d8c2SCharles.Forsyth else if (y->tval & NUM)
36074a4d8c2SCharles.Forsyth setfval(fp->retval, getfval(y));
36174a4d8c2SCharles.Forsyth else /* can't happen */
36274a4d8c2SCharles.Forsyth FATAL("bad type variable %d", y->tval);
36374a4d8c2SCharles.Forsyth tempfree(y);
36474a4d8c2SCharles.Forsyth }
36574a4d8c2SCharles.Forsyth return(jret);
36674a4d8c2SCharles.Forsyth case NEXT:
36774a4d8c2SCharles.Forsyth return(jnext);
36874a4d8c2SCharles.Forsyth case NEXTFILE:
36974a4d8c2SCharles.Forsyth nextfile();
37074a4d8c2SCharles.Forsyth return(jnextfile);
37174a4d8c2SCharles.Forsyth case BREAK:
37274a4d8c2SCharles.Forsyth return(jbreak);
37374a4d8c2SCharles.Forsyth case CONTINUE:
37474a4d8c2SCharles.Forsyth return(jcont);
37574a4d8c2SCharles.Forsyth default: /* can't happen */
37674a4d8c2SCharles.Forsyth FATAL("illegal jump type %d", n);
37774a4d8c2SCharles.Forsyth }
37874a4d8c2SCharles.Forsyth return 0; /* not reached */
37974a4d8c2SCharles.Forsyth }
38074a4d8c2SCharles.Forsyth
getline(Node ** a,int n)38174a4d8c2SCharles.Forsyth Cell *getline(Node **a, int n) /* get next line from specific input */
38274a4d8c2SCharles.Forsyth { /* a[0] is variable, a[1] is operator, a[2] is filename */
38374a4d8c2SCharles.Forsyth Cell *r, *x;
38474a4d8c2SCharles.Forsyth extern Cell **fldtab;
38574a4d8c2SCharles.Forsyth FILE *fp;
38674a4d8c2SCharles.Forsyth char *buf;
38774a4d8c2SCharles.Forsyth int bufsize = recsize;
38874a4d8c2SCharles.Forsyth int mode;
38974a4d8c2SCharles.Forsyth
39074a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsize)) == NULL)
39174a4d8c2SCharles.Forsyth FATAL("out of memory in getline");
39274a4d8c2SCharles.Forsyth
39374a4d8c2SCharles.Forsyth fflush(stdout); /* in case someone is waiting for a prompt */
39474a4d8c2SCharles.Forsyth r = gettemp();
39574a4d8c2SCharles.Forsyth if (a[1] != NULL) { /* getline < file */
39674a4d8c2SCharles.Forsyth x = execute(a[2]); /* filename */
39774a4d8c2SCharles.Forsyth mode = ptoi(a[1]);
39874a4d8c2SCharles.Forsyth if (mode == '|') /* input pipe */
39974a4d8c2SCharles.Forsyth mode = LE; /* arbitrary flag */
40074a4d8c2SCharles.Forsyth fp = openfile(mode, getsval(x));
40174a4d8c2SCharles.Forsyth tempfree(x);
40274a4d8c2SCharles.Forsyth if (fp == NULL)
40374a4d8c2SCharles.Forsyth n = -1;
40474a4d8c2SCharles.Forsyth else
40574a4d8c2SCharles.Forsyth n = readrec(&buf, &bufsize, fp);
40674a4d8c2SCharles.Forsyth if (n <= 0) {
40774a4d8c2SCharles.Forsyth ;
40874a4d8c2SCharles.Forsyth } else if (a[0] != NULL) { /* getline var <file */
40974a4d8c2SCharles.Forsyth x = execute(a[0]);
41074a4d8c2SCharles.Forsyth setsval(x, buf);
41174a4d8c2SCharles.Forsyth tempfree(x);
41274a4d8c2SCharles.Forsyth } else { /* getline <file */
41374a4d8c2SCharles.Forsyth setsval(fldtab[0], buf);
41474a4d8c2SCharles.Forsyth if (is_number(fldtab[0]->sval)) {
41574a4d8c2SCharles.Forsyth fldtab[0]->fval = atof(fldtab[0]->sval);
41674a4d8c2SCharles.Forsyth fldtab[0]->tval |= NUM;
41774a4d8c2SCharles.Forsyth }
41874a4d8c2SCharles.Forsyth }
41974a4d8c2SCharles.Forsyth } else { /* bare getline; use current input */
42074a4d8c2SCharles.Forsyth if (a[0] == NULL) /* getline */
42174a4d8c2SCharles.Forsyth n = getrec(&record, &recsize, 1);
42274a4d8c2SCharles.Forsyth else { /* getline var */
42374a4d8c2SCharles.Forsyth n = getrec(&buf, &bufsize, 0);
42474a4d8c2SCharles.Forsyth x = execute(a[0]);
42574a4d8c2SCharles.Forsyth setsval(x, buf);
42674a4d8c2SCharles.Forsyth tempfree(x);
42774a4d8c2SCharles.Forsyth }
42874a4d8c2SCharles.Forsyth }
42974a4d8c2SCharles.Forsyth setfval(r, (Awkfloat) n);
43074a4d8c2SCharles.Forsyth free(buf);
43174a4d8c2SCharles.Forsyth return r;
43274a4d8c2SCharles.Forsyth }
43374a4d8c2SCharles.Forsyth
getnf(Node ** a,int n)43474a4d8c2SCharles.Forsyth Cell *getnf(Node **a, int n) /* get NF */
43574a4d8c2SCharles.Forsyth {
43674a4d8c2SCharles.Forsyth if (donefld == 0)
43774a4d8c2SCharles.Forsyth fldbld();
43874a4d8c2SCharles.Forsyth return (Cell *) a[0];
43974a4d8c2SCharles.Forsyth }
44074a4d8c2SCharles.Forsyth
array(Node ** a,int n)44174a4d8c2SCharles.Forsyth Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
44274a4d8c2SCharles.Forsyth {
44374a4d8c2SCharles.Forsyth Cell *x, *y, *z;
44474a4d8c2SCharles.Forsyth char *s;
44574a4d8c2SCharles.Forsyth Node *np;
44674a4d8c2SCharles.Forsyth char *buf;
44774a4d8c2SCharles.Forsyth int bufsz = recsize;
44874a4d8c2SCharles.Forsyth int nsub = strlen(*SUBSEP);
44974a4d8c2SCharles.Forsyth
45074a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
45174a4d8c2SCharles.Forsyth FATAL("out of memory in array");
45274a4d8c2SCharles.Forsyth
45374a4d8c2SCharles.Forsyth x = execute(a[0]); /* Cell* for symbol table */
45474a4d8c2SCharles.Forsyth buf[0] = 0;
45574a4d8c2SCharles.Forsyth for (np = a[1]; np; np = np->nnext) {
45674a4d8c2SCharles.Forsyth y = execute(np); /* subscript */
45774a4d8c2SCharles.Forsyth s = getsval(y);
45874a4d8c2SCharles.Forsyth if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
45974a4d8c2SCharles.Forsyth FATAL("out of memory for %s[%s...]", x->nval, buf);
46074a4d8c2SCharles.Forsyth strcat(buf, s);
46174a4d8c2SCharles.Forsyth if (np->nnext)
46274a4d8c2SCharles.Forsyth strcat(buf, *SUBSEP);
46374a4d8c2SCharles.Forsyth tempfree(y);
46474a4d8c2SCharles.Forsyth }
46574a4d8c2SCharles.Forsyth if (!isarr(x)) {
46674a4d8c2SCharles.Forsyth dprintf( ("making %s into an array\n", x->nval) );
46774a4d8c2SCharles.Forsyth if (freeable(x))
46874a4d8c2SCharles.Forsyth xfree(x->sval);
46974a4d8c2SCharles.Forsyth x->tval &= ~(STR|NUM|DONTFREE);
47074a4d8c2SCharles.Forsyth x->tval |= ARR;
47174a4d8c2SCharles.Forsyth x->sval = (char *) makesymtab(NSYMTAB);
47274a4d8c2SCharles.Forsyth }
47374a4d8c2SCharles.Forsyth z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
47474a4d8c2SCharles.Forsyth z->ctype = OCELL;
47574a4d8c2SCharles.Forsyth z->csub = CVAR;
47674a4d8c2SCharles.Forsyth tempfree(x);
47774a4d8c2SCharles.Forsyth free(buf);
47874a4d8c2SCharles.Forsyth return(z);
47974a4d8c2SCharles.Forsyth }
48074a4d8c2SCharles.Forsyth
awkdelete(Node ** a,int n)48174a4d8c2SCharles.Forsyth Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
48274a4d8c2SCharles.Forsyth {
48374a4d8c2SCharles.Forsyth Cell *x, *y;
48474a4d8c2SCharles.Forsyth Node *np;
48574a4d8c2SCharles.Forsyth char *s;
48674a4d8c2SCharles.Forsyth int nsub = strlen(*SUBSEP);
48774a4d8c2SCharles.Forsyth
48874a4d8c2SCharles.Forsyth x = execute(a[0]); /* Cell* for symbol table */
48974a4d8c2SCharles.Forsyth if (!isarr(x))
49074a4d8c2SCharles.Forsyth return True;
49174a4d8c2SCharles.Forsyth if (a[1] == 0) { /* delete the elements, not the table */
49274a4d8c2SCharles.Forsyth freesymtab(x);
49374a4d8c2SCharles.Forsyth x->tval &= ~STR;
49474a4d8c2SCharles.Forsyth x->tval |= ARR;
49574a4d8c2SCharles.Forsyth x->sval = (char *) makesymtab(NSYMTAB);
49674a4d8c2SCharles.Forsyth } else {
49774a4d8c2SCharles.Forsyth int bufsz = recsize;
49874a4d8c2SCharles.Forsyth char *buf;
49974a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
50074a4d8c2SCharles.Forsyth FATAL("out of memory in adelete");
50174a4d8c2SCharles.Forsyth buf[0] = 0;
50274a4d8c2SCharles.Forsyth for (np = a[1]; np; np = np->nnext) {
50374a4d8c2SCharles.Forsyth y = execute(np); /* subscript */
50474a4d8c2SCharles.Forsyth s = getsval(y);
50574a4d8c2SCharles.Forsyth if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
50674a4d8c2SCharles.Forsyth FATAL("out of memory deleting %s[%s...]", x->nval, buf);
50774a4d8c2SCharles.Forsyth strcat(buf, s);
50874a4d8c2SCharles.Forsyth if (np->nnext)
50974a4d8c2SCharles.Forsyth strcat(buf, *SUBSEP);
51074a4d8c2SCharles.Forsyth tempfree(y);
51174a4d8c2SCharles.Forsyth }
51274a4d8c2SCharles.Forsyth freeelem(x, buf);
51374a4d8c2SCharles.Forsyth free(buf);
51474a4d8c2SCharles.Forsyth }
51574a4d8c2SCharles.Forsyth tempfree(x);
51674a4d8c2SCharles.Forsyth return True;
51774a4d8c2SCharles.Forsyth }
51874a4d8c2SCharles.Forsyth
intest(Node ** a,int n)51974a4d8c2SCharles.Forsyth Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
52074a4d8c2SCharles.Forsyth {
52174a4d8c2SCharles.Forsyth Cell *x, *ap, *k;
52274a4d8c2SCharles.Forsyth Node *p;
52374a4d8c2SCharles.Forsyth char *buf;
52474a4d8c2SCharles.Forsyth char *s;
52574a4d8c2SCharles.Forsyth int bufsz = recsize;
52674a4d8c2SCharles.Forsyth int nsub = strlen(*SUBSEP);
52774a4d8c2SCharles.Forsyth
52874a4d8c2SCharles.Forsyth ap = execute(a[1]); /* array name */
52974a4d8c2SCharles.Forsyth if (!isarr(ap)) {
53074a4d8c2SCharles.Forsyth dprintf( ("making %s into an array\n", ap->nval) );
53174a4d8c2SCharles.Forsyth if (freeable(ap))
53274a4d8c2SCharles.Forsyth xfree(ap->sval);
53374a4d8c2SCharles.Forsyth ap->tval &= ~(STR|NUM|DONTFREE);
53474a4d8c2SCharles.Forsyth ap->tval |= ARR;
53574a4d8c2SCharles.Forsyth ap->sval = (char *) makesymtab(NSYMTAB);
53674a4d8c2SCharles.Forsyth }
53774a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL) {
53874a4d8c2SCharles.Forsyth FATAL("out of memory in intest");
53974a4d8c2SCharles.Forsyth }
54074a4d8c2SCharles.Forsyth buf[0] = 0;
54174a4d8c2SCharles.Forsyth for (p = a[0]; p; p = p->nnext) {
54274a4d8c2SCharles.Forsyth x = execute(p); /* expr */
54374a4d8c2SCharles.Forsyth s = getsval(x);
54474a4d8c2SCharles.Forsyth if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
54574a4d8c2SCharles.Forsyth FATAL("out of memory deleting %s[%s...]", x->nval, buf);
54674a4d8c2SCharles.Forsyth strcat(buf, s);
54774a4d8c2SCharles.Forsyth tempfree(x);
54874a4d8c2SCharles.Forsyth if (p->nnext)
54974a4d8c2SCharles.Forsyth strcat(buf, *SUBSEP);
55074a4d8c2SCharles.Forsyth }
55174a4d8c2SCharles.Forsyth k = lookup(buf, (Array *) ap->sval);
55274a4d8c2SCharles.Forsyth tempfree(ap);
55374a4d8c2SCharles.Forsyth free(buf);
55474a4d8c2SCharles.Forsyth if (k == NULL)
55574a4d8c2SCharles.Forsyth return(False);
55674a4d8c2SCharles.Forsyth else
55774a4d8c2SCharles.Forsyth return(True);
55874a4d8c2SCharles.Forsyth }
55974a4d8c2SCharles.Forsyth
56074a4d8c2SCharles.Forsyth
matchop(Node ** a,int n)56174a4d8c2SCharles.Forsyth Cell *matchop(Node **a, int n) /* ~ and match() */
56274a4d8c2SCharles.Forsyth {
56374a4d8c2SCharles.Forsyth Cell *x, *y;
56474a4d8c2SCharles.Forsyth char *s, *t;
56574a4d8c2SCharles.Forsyth int i;
56674a4d8c2SCharles.Forsyth fa *pfa;
56774a4d8c2SCharles.Forsyth int (*mf)(fa *, char *) = match, mode = 0;
56874a4d8c2SCharles.Forsyth
56974a4d8c2SCharles.Forsyth if (n == MATCHFCN) {
57074a4d8c2SCharles.Forsyth mf = pmatch;
57174a4d8c2SCharles.Forsyth mode = 1;
57274a4d8c2SCharles.Forsyth }
57374a4d8c2SCharles.Forsyth x = execute(a[1]); /* a[1] = target text */
57474a4d8c2SCharles.Forsyth s = getsval(x);
57574a4d8c2SCharles.Forsyth if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
57674a4d8c2SCharles.Forsyth i = (*mf)((fa *) a[2], s);
57774a4d8c2SCharles.Forsyth else {
57874a4d8c2SCharles.Forsyth y = execute(a[2]); /* a[2] = regular expr */
57974a4d8c2SCharles.Forsyth t = getsval(y);
58074a4d8c2SCharles.Forsyth pfa = makedfa(t, mode);
58174a4d8c2SCharles.Forsyth i = (*mf)(pfa, s);
58274a4d8c2SCharles.Forsyth tempfree(y);
58374a4d8c2SCharles.Forsyth }
58474a4d8c2SCharles.Forsyth tempfree(x);
58574a4d8c2SCharles.Forsyth if (n == MATCHFCN) {
58674a4d8c2SCharles.Forsyth int start = patbeg - s + 1;
58774a4d8c2SCharles.Forsyth if (patlen < 0)
58874a4d8c2SCharles.Forsyth start = 0;
58974a4d8c2SCharles.Forsyth setfval(rstartloc, (Awkfloat) start);
59074a4d8c2SCharles.Forsyth setfval(rlengthloc, (Awkfloat) patlen);
59174a4d8c2SCharles.Forsyth x = gettemp();
59274a4d8c2SCharles.Forsyth x->tval = NUM;
59374a4d8c2SCharles.Forsyth x->fval = start;
59474a4d8c2SCharles.Forsyth return x;
59574a4d8c2SCharles.Forsyth } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
59674a4d8c2SCharles.Forsyth return(True);
59774a4d8c2SCharles.Forsyth else
59874a4d8c2SCharles.Forsyth return(False);
59974a4d8c2SCharles.Forsyth }
60074a4d8c2SCharles.Forsyth
60174a4d8c2SCharles.Forsyth
boolop(Node ** a,int n)60274a4d8c2SCharles.Forsyth Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
60374a4d8c2SCharles.Forsyth {
60474a4d8c2SCharles.Forsyth Cell *x, *y;
60574a4d8c2SCharles.Forsyth int i;
60674a4d8c2SCharles.Forsyth
60774a4d8c2SCharles.Forsyth x = execute(a[0]);
60874a4d8c2SCharles.Forsyth i = istrue(x);
60974a4d8c2SCharles.Forsyth tempfree(x);
61074a4d8c2SCharles.Forsyth switch (n) {
61174a4d8c2SCharles.Forsyth case BOR:
61274a4d8c2SCharles.Forsyth if (i) return(True);
61374a4d8c2SCharles.Forsyth y = execute(a[1]);
61474a4d8c2SCharles.Forsyth i = istrue(y);
61574a4d8c2SCharles.Forsyth tempfree(y);
61674a4d8c2SCharles.Forsyth if (i) return(True);
61774a4d8c2SCharles.Forsyth else return(False);
61874a4d8c2SCharles.Forsyth case AND:
61974a4d8c2SCharles.Forsyth if ( !i ) return(False);
62074a4d8c2SCharles.Forsyth y = execute(a[1]);
62174a4d8c2SCharles.Forsyth i = istrue(y);
62274a4d8c2SCharles.Forsyth tempfree(y);
62374a4d8c2SCharles.Forsyth if (i) return(True);
62474a4d8c2SCharles.Forsyth else return(False);
62574a4d8c2SCharles.Forsyth case NOT:
62674a4d8c2SCharles.Forsyth if (i) return(False);
62774a4d8c2SCharles.Forsyth else return(True);
62874a4d8c2SCharles.Forsyth default: /* can't happen */
62974a4d8c2SCharles.Forsyth FATAL("unknown boolean operator %d", n);
63074a4d8c2SCharles.Forsyth }
63174a4d8c2SCharles.Forsyth return 0; /*NOTREACHED*/
63274a4d8c2SCharles.Forsyth }
63374a4d8c2SCharles.Forsyth
relop(Node ** a,int n)63474a4d8c2SCharles.Forsyth Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
63574a4d8c2SCharles.Forsyth {
63674a4d8c2SCharles.Forsyth int i;
63774a4d8c2SCharles.Forsyth Cell *x, *y;
63874a4d8c2SCharles.Forsyth Awkfloat j;
63974a4d8c2SCharles.Forsyth
64074a4d8c2SCharles.Forsyth x = execute(a[0]);
64174a4d8c2SCharles.Forsyth y = execute(a[1]);
64274a4d8c2SCharles.Forsyth if (x->tval&NUM && y->tval&NUM) {
64374a4d8c2SCharles.Forsyth j = x->fval - y->fval;
64474a4d8c2SCharles.Forsyth i = j<0? -1: (j>0? 1: 0);
64574a4d8c2SCharles.Forsyth } else {
64674a4d8c2SCharles.Forsyth i = strcmp(getsval(x), getsval(y));
64774a4d8c2SCharles.Forsyth }
64874a4d8c2SCharles.Forsyth tempfree(x);
64974a4d8c2SCharles.Forsyth tempfree(y);
65074a4d8c2SCharles.Forsyth switch (n) {
65174a4d8c2SCharles.Forsyth case LT: if (i<0) return(True);
65274a4d8c2SCharles.Forsyth else return(False);
65374a4d8c2SCharles.Forsyth case LE: if (i<=0) return(True);
65474a4d8c2SCharles.Forsyth else return(False);
65574a4d8c2SCharles.Forsyth case NE: if (i!=0) return(True);
65674a4d8c2SCharles.Forsyth else return(False);
65774a4d8c2SCharles.Forsyth case EQ: if (i == 0) return(True);
65874a4d8c2SCharles.Forsyth else return(False);
65974a4d8c2SCharles.Forsyth case GE: if (i>=0) return(True);
66074a4d8c2SCharles.Forsyth else return(False);
66174a4d8c2SCharles.Forsyth case GT: if (i>0) return(True);
66274a4d8c2SCharles.Forsyth else return(False);
66374a4d8c2SCharles.Forsyth default: /* can't happen */
66474a4d8c2SCharles.Forsyth FATAL("unknown relational operator %d", n);
66574a4d8c2SCharles.Forsyth }
66674a4d8c2SCharles.Forsyth return 0; /*NOTREACHED*/
66774a4d8c2SCharles.Forsyth }
66874a4d8c2SCharles.Forsyth
tfree(Cell * a)66974a4d8c2SCharles.Forsyth void tfree(Cell *a) /* free a tempcell */
67074a4d8c2SCharles.Forsyth {
67174a4d8c2SCharles.Forsyth if (freeable(a)) {
67274a4d8c2SCharles.Forsyth dprintf( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
67374a4d8c2SCharles.Forsyth xfree(a->sval);
67474a4d8c2SCharles.Forsyth }
67574a4d8c2SCharles.Forsyth if (a == tmps)
67674a4d8c2SCharles.Forsyth FATAL("tempcell list is curdled");
67774a4d8c2SCharles.Forsyth a->cnext = tmps;
67874a4d8c2SCharles.Forsyth tmps = a;
67974a4d8c2SCharles.Forsyth }
68074a4d8c2SCharles.Forsyth
gettemp(void)68174a4d8c2SCharles.Forsyth Cell *gettemp(void) /* get a tempcell */
68274a4d8c2SCharles.Forsyth { int i;
68374a4d8c2SCharles.Forsyth Cell *x;
68474a4d8c2SCharles.Forsyth
68574a4d8c2SCharles.Forsyth if (!tmps) {
68674a4d8c2SCharles.Forsyth tmps = (Cell *) calloc(100, sizeof(Cell));
68774a4d8c2SCharles.Forsyth if (!tmps)
68874a4d8c2SCharles.Forsyth FATAL("out of space for temporaries");
68974a4d8c2SCharles.Forsyth for(i = 1; i < 100; i++)
69074a4d8c2SCharles.Forsyth tmps[i-1].cnext = &tmps[i];
69174a4d8c2SCharles.Forsyth tmps[i-1].cnext = 0;
69274a4d8c2SCharles.Forsyth }
69374a4d8c2SCharles.Forsyth x = tmps;
69474a4d8c2SCharles.Forsyth tmps = x->cnext;
69574a4d8c2SCharles.Forsyth *x = tempcell;
69674a4d8c2SCharles.Forsyth return(x);
69774a4d8c2SCharles.Forsyth }
69874a4d8c2SCharles.Forsyth
indirect(Node ** a,int n)69974a4d8c2SCharles.Forsyth Cell *indirect(Node **a, int n) /* $( a[0] ) */
70074a4d8c2SCharles.Forsyth {
70174a4d8c2SCharles.Forsyth Cell *x;
70274a4d8c2SCharles.Forsyth int m;
70374a4d8c2SCharles.Forsyth char *s;
70474a4d8c2SCharles.Forsyth
70574a4d8c2SCharles.Forsyth x = execute(a[0]);
70674a4d8c2SCharles.Forsyth m = (int) getfval(x);
70774a4d8c2SCharles.Forsyth if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
70874a4d8c2SCharles.Forsyth FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
70974a4d8c2SCharles.Forsyth /* BUG: can x->nval ever be null??? */
71074a4d8c2SCharles.Forsyth tempfree(x);
71174a4d8c2SCharles.Forsyth x = fieldadr(m);
71274a4d8c2SCharles.Forsyth x->ctype = OCELL; /* BUG? why are these needed? */
71374a4d8c2SCharles.Forsyth x->csub = CFLD;
71474a4d8c2SCharles.Forsyth return(x);
71574a4d8c2SCharles.Forsyth }
71674a4d8c2SCharles.Forsyth
substr(Node ** a,int nnn)71774a4d8c2SCharles.Forsyth Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
71874a4d8c2SCharles.Forsyth {
71974a4d8c2SCharles.Forsyth int k, m, n;
72074a4d8c2SCharles.Forsyth char *s;
72174a4d8c2SCharles.Forsyth int temp;
72274a4d8c2SCharles.Forsyth Cell *x, *y, *z = 0;
72374a4d8c2SCharles.Forsyth
72474a4d8c2SCharles.Forsyth x = execute(a[0]);
72574a4d8c2SCharles.Forsyth y = execute(a[1]);
72674a4d8c2SCharles.Forsyth if (a[2] != 0)
72774a4d8c2SCharles.Forsyth z = execute(a[2]);
72874a4d8c2SCharles.Forsyth s = getsval(x);
72974a4d8c2SCharles.Forsyth k = strlen(s) + 1;
73074a4d8c2SCharles.Forsyth if (k <= 1) {
73174a4d8c2SCharles.Forsyth tempfree(x);
73274a4d8c2SCharles.Forsyth tempfree(y);
73374a4d8c2SCharles.Forsyth if (a[2] != 0) {
73474a4d8c2SCharles.Forsyth tempfree(z);
73574a4d8c2SCharles.Forsyth }
73674a4d8c2SCharles.Forsyth x = gettemp();
73774a4d8c2SCharles.Forsyth setsval(x, "");
73874a4d8c2SCharles.Forsyth return(x);
73974a4d8c2SCharles.Forsyth }
74074a4d8c2SCharles.Forsyth m = (int) getfval(y);
74174a4d8c2SCharles.Forsyth if (m <= 0)
74274a4d8c2SCharles.Forsyth m = 1;
74374a4d8c2SCharles.Forsyth else if (m > k)
74474a4d8c2SCharles.Forsyth m = k;
74574a4d8c2SCharles.Forsyth tempfree(y);
74674a4d8c2SCharles.Forsyth if (a[2] != 0) {
74774a4d8c2SCharles.Forsyth n = (int) getfval(z);
74874a4d8c2SCharles.Forsyth tempfree(z);
74974a4d8c2SCharles.Forsyth } else
75074a4d8c2SCharles.Forsyth n = k - 1;
75174a4d8c2SCharles.Forsyth if (n < 0)
75274a4d8c2SCharles.Forsyth n = 0;
75374a4d8c2SCharles.Forsyth else if (n > k - m)
75474a4d8c2SCharles.Forsyth n = k - m;
75574a4d8c2SCharles.Forsyth dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
75674a4d8c2SCharles.Forsyth y = gettemp();
75774a4d8c2SCharles.Forsyth temp = s[n+m-1]; /* with thanks to John Linderman */
75874a4d8c2SCharles.Forsyth s[n+m-1] = '\0';
75974a4d8c2SCharles.Forsyth setsval(y, s + m - 1);
76074a4d8c2SCharles.Forsyth s[n+m-1] = temp;
76174a4d8c2SCharles.Forsyth tempfree(x);
76274a4d8c2SCharles.Forsyth return(y);
76374a4d8c2SCharles.Forsyth }
76474a4d8c2SCharles.Forsyth
sindex(Node ** a,int nnn)76574a4d8c2SCharles.Forsyth Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
76674a4d8c2SCharles.Forsyth {
76774a4d8c2SCharles.Forsyth Cell *x, *y, *z;
76874a4d8c2SCharles.Forsyth char *s1, *s2, *p1, *p2, *q;
76974a4d8c2SCharles.Forsyth Awkfloat v = 0.0;
77074a4d8c2SCharles.Forsyth
77174a4d8c2SCharles.Forsyth x = execute(a[0]);
77274a4d8c2SCharles.Forsyth s1 = getsval(x);
77374a4d8c2SCharles.Forsyth y = execute(a[1]);
77474a4d8c2SCharles.Forsyth s2 = getsval(y);
77574a4d8c2SCharles.Forsyth
77674a4d8c2SCharles.Forsyth z = gettemp();
77774a4d8c2SCharles.Forsyth for (p1 = s1; *p1 != '\0'; p1++) {
77874a4d8c2SCharles.Forsyth for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
77974a4d8c2SCharles.Forsyth ;
78074a4d8c2SCharles.Forsyth if (*p2 == '\0') {
78174a4d8c2SCharles.Forsyth v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
78274a4d8c2SCharles.Forsyth break;
78374a4d8c2SCharles.Forsyth }
78474a4d8c2SCharles.Forsyth }
78574a4d8c2SCharles.Forsyth tempfree(x);
78674a4d8c2SCharles.Forsyth tempfree(y);
78774a4d8c2SCharles.Forsyth setfval(z, v);
78874a4d8c2SCharles.Forsyth return(z);
78974a4d8c2SCharles.Forsyth }
79074a4d8c2SCharles.Forsyth
79174a4d8c2SCharles.Forsyth #define MAXNUMSIZE 50
79274a4d8c2SCharles.Forsyth
format(char ** pbuf,int * pbufsize,char * s,Node * a)79374a4d8c2SCharles.Forsyth int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */
79474a4d8c2SCharles.Forsyth {
79574a4d8c2SCharles.Forsyth char *fmt;
79674a4d8c2SCharles.Forsyth char *p, *t, *os;
79774a4d8c2SCharles.Forsyth Cell *x;
79874a4d8c2SCharles.Forsyth int flag = 0, n;
79974a4d8c2SCharles.Forsyth int fmtwd; /* format width */
80074a4d8c2SCharles.Forsyth int fmtsz = recsize;
80174a4d8c2SCharles.Forsyth char *buf = *pbuf;
80274a4d8c2SCharles.Forsyth int bufsize = *pbufsize;
80374a4d8c2SCharles.Forsyth
80474a4d8c2SCharles.Forsyth os = s;
80574a4d8c2SCharles.Forsyth p = buf;
80674a4d8c2SCharles.Forsyth if ((fmt = (char *) malloc(fmtsz)) == NULL)
80774a4d8c2SCharles.Forsyth FATAL("out of memory in format()");
80874a4d8c2SCharles.Forsyth while (*s) {
80974a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
81074a4d8c2SCharles.Forsyth if (*s != '%') {
81174a4d8c2SCharles.Forsyth *p++ = *s++;
81274a4d8c2SCharles.Forsyth continue;
81374a4d8c2SCharles.Forsyth }
81474a4d8c2SCharles.Forsyth if (*(s+1) == '%') {
81574a4d8c2SCharles.Forsyth *p++ = '%';
81674a4d8c2SCharles.Forsyth s += 2;
81774a4d8c2SCharles.Forsyth continue;
81874a4d8c2SCharles.Forsyth }
81974a4d8c2SCharles.Forsyth /* have to be real careful in case this is a huge number, eg, %100000d */
82074a4d8c2SCharles.Forsyth fmtwd = atoi(s+1);
82174a4d8c2SCharles.Forsyth if (fmtwd < 0)
82274a4d8c2SCharles.Forsyth fmtwd = -fmtwd;
82374a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
82474a4d8c2SCharles.Forsyth for (t = fmt; (*t++ = *s) != '\0'; s++) {
82574a4d8c2SCharles.Forsyth if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
82674a4d8c2SCharles.Forsyth FATAL("format item %.30s... ran format() out of memory", os);
82774a4d8c2SCharles.Forsyth if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
82874a4d8c2SCharles.Forsyth break; /* the ansi panoply */
82974a4d8c2SCharles.Forsyth if (*s == '*') {
83074a4d8c2SCharles.Forsyth x = execute(a);
83174a4d8c2SCharles.Forsyth a = a->nnext;
83274a4d8c2SCharles.Forsyth sprintf(t-1, "%d", fmtwd=(int) getfval(x));
83374a4d8c2SCharles.Forsyth if (fmtwd < 0)
83474a4d8c2SCharles.Forsyth fmtwd = -fmtwd;
83574a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
83674a4d8c2SCharles.Forsyth t = fmt + strlen(fmt);
83774a4d8c2SCharles.Forsyth tempfree(x);
83874a4d8c2SCharles.Forsyth }
83974a4d8c2SCharles.Forsyth }
84074a4d8c2SCharles.Forsyth *t = '\0';
84174a4d8c2SCharles.Forsyth if (fmtwd < 0)
84274a4d8c2SCharles.Forsyth fmtwd = -fmtwd;
84374a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
84474a4d8c2SCharles.Forsyth
84574a4d8c2SCharles.Forsyth switch (*s) {
84674a4d8c2SCharles.Forsyth case 'f': case 'e': case 'g': case 'E': case 'G':
84774a4d8c2SCharles.Forsyth flag = 1;
84874a4d8c2SCharles.Forsyth break;
84974a4d8c2SCharles.Forsyth case 'd': case 'i':
85074a4d8c2SCharles.Forsyth flag = 2;
85174a4d8c2SCharles.Forsyth if(*(s-1) == 'l') break;
85274a4d8c2SCharles.Forsyth *(t-1) = 'l';
85374a4d8c2SCharles.Forsyth *t = 'd';
85474a4d8c2SCharles.Forsyth *++t = '\0';
85574a4d8c2SCharles.Forsyth break;
85674a4d8c2SCharles.Forsyth case 'o': case 'x': case 'X': case 'u':
85774a4d8c2SCharles.Forsyth flag = *(s-1) == 'l' ? 2 : 3;
85874a4d8c2SCharles.Forsyth break;
85974a4d8c2SCharles.Forsyth case 's':
86074a4d8c2SCharles.Forsyth flag = 4;
86174a4d8c2SCharles.Forsyth break;
86274a4d8c2SCharles.Forsyth case 'c':
86374a4d8c2SCharles.Forsyth flag = 5;
86474a4d8c2SCharles.Forsyth break;
86574a4d8c2SCharles.Forsyth default:
86674a4d8c2SCharles.Forsyth WARNING("weird printf conversion %s", fmt);
86774a4d8c2SCharles.Forsyth flag = 0;
86874a4d8c2SCharles.Forsyth break;
86974a4d8c2SCharles.Forsyth }
87074a4d8c2SCharles.Forsyth if (a == NULL)
87174a4d8c2SCharles.Forsyth FATAL("not enough args in printf(%s)", os);
87274a4d8c2SCharles.Forsyth x = execute(a);
87374a4d8c2SCharles.Forsyth a = a->nnext;
87474a4d8c2SCharles.Forsyth n = MAXNUMSIZE;
87574a4d8c2SCharles.Forsyth if (fmtwd > n)
87674a4d8c2SCharles.Forsyth n = fmtwd;
87774a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
87874a4d8c2SCharles.Forsyth switch (flag) {
87974a4d8c2SCharles.Forsyth case 0: sprintf(p, "%s", fmt); /* unknown, so dump it too */
88074a4d8c2SCharles.Forsyth t = getsval(x);
88174a4d8c2SCharles.Forsyth n = strlen(t);
88274a4d8c2SCharles.Forsyth if (fmtwd > n)
88374a4d8c2SCharles.Forsyth n = fmtwd;
88474a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
88574a4d8c2SCharles.Forsyth p += strlen(p);
88674a4d8c2SCharles.Forsyth sprintf(p, "%s", t);
88774a4d8c2SCharles.Forsyth break;
88874a4d8c2SCharles.Forsyth case 1: sprintf(p, fmt, getfval(x)); break;
88974a4d8c2SCharles.Forsyth case 2: sprintf(p, fmt, (long) getfval(x)); break;
89074a4d8c2SCharles.Forsyth case 3: sprintf(p, fmt, (int) getfval(x)); break;
89174a4d8c2SCharles.Forsyth case 4:
89274a4d8c2SCharles.Forsyth t = getsval(x);
89374a4d8c2SCharles.Forsyth n = strlen(t);
89474a4d8c2SCharles.Forsyth if (fmtwd > n)
89574a4d8c2SCharles.Forsyth n = fmtwd;
89674a4d8c2SCharles.Forsyth if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
89774a4d8c2SCharles.Forsyth FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
89874a4d8c2SCharles.Forsyth sprintf(p, fmt, t);
89974a4d8c2SCharles.Forsyth break;
90074a4d8c2SCharles.Forsyth case 5:
90174a4d8c2SCharles.Forsyth if (isnum(x)) {
90274a4d8c2SCharles.Forsyth if (getfval(x))
90374a4d8c2SCharles.Forsyth sprintf(p, fmt, (int) getfval(x));
90474a4d8c2SCharles.Forsyth else
90574a4d8c2SCharles.Forsyth *p++ = '\0';
90674a4d8c2SCharles.Forsyth } else
90774a4d8c2SCharles.Forsyth sprintf(p, fmt, getsval(x)[0]);
90874a4d8c2SCharles.Forsyth break;
90974a4d8c2SCharles.Forsyth }
91074a4d8c2SCharles.Forsyth tempfree(x);
91174a4d8c2SCharles.Forsyth p += strlen(p);
91274a4d8c2SCharles.Forsyth s++;
91374a4d8c2SCharles.Forsyth }
91474a4d8c2SCharles.Forsyth *p = '\0';
91574a4d8c2SCharles.Forsyth free(fmt);
91674a4d8c2SCharles.Forsyth for ( ; a; a = a->nnext) /* evaluate any remaining args */
91774a4d8c2SCharles.Forsyth execute(a);
91874a4d8c2SCharles.Forsyth *pbuf = buf;
91974a4d8c2SCharles.Forsyth *pbufsize = bufsize;
92074a4d8c2SCharles.Forsyth return p - buf;
92174a4d8c2SCharles.Forsyth }
92274a4d8c2SCharles.Forsyth
awksprintf(Node ** a,int n)92374a4d8c2SCharles.Forsyth Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
92474a4d8c2SCharles.Forsyth {
92574a4d8c2SCharles.Forsyth Cell *x;
92674a4d8c2SCharles.Forsyth Node *y;
92774a4d8c2SCharles.Forsyth char *buf;
92874a4d8c2SCharles.Forsyth int bufsz=3*recsize;
92974a4d8c2SCharles.Forsyth
93074a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
93174a4d8c2SCharles.Forsyth FATAL("out of memory in awksprintf");
93274a4d8c2SCharles.Forsyth y = a[0]->nnext;
93374a4d8c2SCharles.Forsyth x = execute(a[0]);
93474a4d8c2SCharles.Forsyth if (format(&buf, &bufsz, getsval(x), y) == -1)
93574a4d8c2SCharles.Forsyth FATAL("sprintf string %.30s... too long. can't happen.", buf);
93674a4d8c2SCharles.Forsyth tempfree(x);
93774a4d8c2SCharles.Forsyth x = gettemp();
93874a4d8c2SCharles.Forsyth x->sval = buf;
93974a4d8c2SCharles.Forsyth x->tval = STR;
94074a4d8c2SCharles.Forsyth return(x);
94174a4d8c2SCharles.Forsyth }
94274a4d8c2SCharles.Forsyth
awkprintf(Node ** a,int n)94374a4d8c2SCharles.Forsyth Cell *awkprintf(Node **a, int n) /* printf */
94474a4d8c2SCharles.Forsyth { /* a[0] is list of args, starting with format string */
94574a4d8c2SCharles.Forsyth /* a[1] is redirection operator, a[2] is redirection file */
94674a4d8c2SCharles.Forsyth FILE *fp;
94774a4d8c2SCharles.Forsyth Cell *x;
94874a4d8c2SCharles.Forsyth Node *y;
94974a4d8c2SCharles.Forsyth char *buf;
95074a4d8c2SCharles.Forsyth int len;
95174a4d8c2SCharles.Forsyth int bufsz=3*recsize;
95274a4d8c2SCharles.Forsyth
95374a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
95474a4d8c2SCharles.Forsyth FATAL("out of memory in awkprintf");
95574a4d8c2SCharles.Forsyth y = a[0]->nnext;
95674a4d8c2SCharles.Forsyth x = execute(a[0]);
95774a4d8c2SCharles.Forsyth if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
95874a4d8c2SCharles.Forsyth FATAL("printf string %.30s... too long. can't happen.", buf);
95974a4d8c2SCharles.Forsyth tempfree(x);
96074a4d8c2SCharles.Forsyth if (a[1] == NULL) {
96174a4d8c2SCharles.Forsyth /* fputs(buf, stdout); */
96274a4d8c2SCharles.Forsyth fwrite(buf, len, 1, stdout);
96374a4d8c2SCharles.Forsyth if (ferror(stdout))
96474a4d8c2SCharles.Forsyth FATAL("write error on stdout");
96574a4d8c2SCharles.Forsyth } else {
96674a4d8c2SCharles.Forsyth fp = redirect(ptoi(a[1]), a[2]);
96774a4d8c2SCharles.Forsyth /* fputs(buf, fp); */
96874a4d8c2SCharles.Forsyth fwrite(buf, len, 1, fp);
96974a4d8c2SCharles.Forsyth fflush(fp);
97074a4d8c2SCharles.Forsyth if (ferror(fp))
97174a4d8c2SCharles.Forsyth FATAL("write error on %s", filename(fp));
97274a4d8c2SCharles.Forsyth }
97374a4d8c2SCharles.Forsyth free(buf);
97474a4d8c2SCharles.Forsyth return(True);
97574a4d8c2SCharles.Forsyth }
97674a4d8c2SCharles.Forsyth
arith(Node ** a,int n)97774a4d8c2SCharles.Forsyth Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
97874a4d8c2SCharles.Forsyth {
97974a4d8c2SCharles.Forsyth Awkfloat i, j = 0;
98074a4d8c2SCharles.Forsyth double v;
98174a4d8c2SCharles.Forsyth Cell *x, *y, *z;
98274a4d8c2SCharles.Forsyth
98374a4d8c2SCharles.Forsyth x = execute(a[0]);
98474a4d8c2SCharles.Forsyth i = getfval(x);
98574a4d8c2SCharles.Forsyth tempfree(x);
98674a4d8c2SCharles.Forsyth if (n != UMINUS) {
98774a4d8c2SCharles.Forsyth y = execute(a[1]);
98874a4d8c2SCharles.Forsyth j = getfval(y);
98974a4d8c2SCharles.Forsyth tempfree(y);
99074a4d8c2SCharles.Forsyth }
99174a4d8c2SCharles.Forsyth z = gettemp();
99274a4d8c2SCharles.Forsyth switch (n) {
99374a4d8c2SCharles.Forsyth case ADD:
99474a4d8c2SCharles.Forsyth i += j;
99574a4d8c2SCharles.Forsyth break;
99674a4d8c2SCharles.Forsyth case MINUS:
99774a4d8c2SCharles.Forsyth i -= j;
99874a4d8c2SCharles.Forsyth break;
99974a4d8c2SCharles.Forsyth case MULT:
100074a4d8c2SCharles.Forsyth i *= j;
100174a4d8c2SCharles.Forsyth break;
100274a4d8c2SCharles.Forsyth case DIVIDE:
100374a4d8c2SCharles.Forsyth if (j == 0)
100474a4d8c2SCharles.Forsyth FATAL("division by zero");
100574a4d8c2SCharles.Forsyth i /= j;
100674a4d8c2SCharles.Forsyth break;
100774a4d8c2SCharles.Forsyth case MOD:
100874a4d8c2SCharles.Forsyth if (j == 0)
100974a4d8c2SCharles.Forsyth FATAL("division by zero in mod");
101074a4d8c2SCharles.Forsyth modf(i/j, &v);
101174a4d8c2SCharles.Forsyth i = i - j * v;
101274a4d8c2SCharles.Forsyth break;
101374a4d8c2SCharles.Forsyth case UMINUS:
101474a4d8c2SCharles.Forsyth i = -i;
101574a4d8c2SCharles.Forsyth break;
101674a4d8c2SCharles.Forsyth case POWER:
101774a4d8c2SCharles.Forsyth if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
101874a4d8c2SCharles.Forsyth i = ipow(i, (int) j);
101974a4d8c2SCharles.Forsyth else
102074a4d8c2SCharles.Forsyth i = errcheck(pow(i, j), "pow");
102174a4d8c2SCharles.Forsyth break;
102274a4d8c2SCharles.Forsyth default: /* can't happen */
102374a4d8c2SCharles.Forsyth FATAL("illegal arithmetic operator %d", n);
102474a4d8c2SCharles.Forsyth }
102574a4d8c2SCharles.Forsyth setfval(z, i);
102674a4d8c2SCharles.Forsyth return(z);
102774a4d8c2SCharles.Forsyth }
102874a4d8c2SCharles.Forsyth
ipow(double x,int n)102974a4d8c2SCharles.Forsyth double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
103074a4d8c2SCharles.Forsyth {
103174a4d8c2SCharles.Forsyth double v;
103274a4d8c2SCharles.Forsyth
103374a4d8c2SCharles.Forsyth if (n <= 0)
103474a4d8c2SCharles.Forsyth return 1;
103574a4d8c2SCharles.Forsyth v = ipow(x, n/2);
103674a4d8c2SCharles.Forsyth if (n % 2 == 0)
103774a4d8c2SCharles.Forsyth return v * v;
103874a4d8c2SCharles.Forsyth else
103974a4d8c2SCharles.Forsyth return x * v * v;
104074a4d8c2SCharles.Forsyth }
104174a4d8c2SCharles.Forsyth
incrdecr(Node ** a,int n)104274a4d8c2SCharles.Forsyth Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
104374a4d8c2SCharles.Forsyth {
104474a4d8c2SCharles.Forsyth Cell *x, *z;
104574a4d8c2SCharles.Forsyth int k;
104674a4d8c2SCharles.Forsyth Awkfloat xf;
104774a4d8c2SCharles.Forsyth
104874a4d8c2SCharles.Forsyth x = execute(a[0]);
104974a4d8c2SCharles.Forsyth xf = getfval(x);
105074a4d8c2SCharles.Forsyth k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
105174a4d8c2SCharles.Forsyth if (n == PREINCR || n == PREDECR) {
105274a4d8c2SCharles.Forsyth setfval(x, xf + k);
105374a4d8c2SCharles.Forsyth return(x);
105474a4d8c2SCharles.Forsyth }
105574a4d8c2SCharles.Forsyth z = gettemp();
105674a4d8c2SCharles.Forsyth setfval(z, xf);
105774a4d8c2SCharles.Forsyth setfval(x, xf + k);
105874a4d8c2SCharles.Forsyth tempfree(x);
105974a4d8c2SCharles.Forsyth return(z);
106074a4d8c2SCharles.Forsyth }
106174a4d8c2SCharles.Forsyth
assign(Node ** a,int n)106274a4d8c2SCharles.Forsyth Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
106374a4d8c2SCharles.Forsyth { /* this is subtle; don't muck with it. */
106474a4d8c2SCharles.Forsyth Cell *x, *y;
106574a4d8c2SCharles.Forsyth Awkfloat xf, yf;
106674a4d8c2SCharles.Forsyth double v;
106774a4d8c2SCharles.Forsyth
106874a4d8c2SCharles.Forsyth y = execute(a[1]);
106974a4d8c2SCharles.Forsyth x = execute(a[0]);
107074a4d8c2SCharles.Forsyth if (n == ASSIGN) { /* ordinary assignment */
107174a4d8c2SCharles.Forsyth if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
107274a4d8c2SCharles.Forsyth ; /* leave alone unless it's a field */
107374a4d8c2SCharles.Forsyth else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
107474a4d8c2SCharles.Forsyth setsval(x, getsval(y));
107574a4d8c2SCharles.Forsyth x->fval = getfval(y);
107674a4d8c2SCharles.Forsyth x->tval |= NUM;
107774a4d8c2SCharles.Forsyth }
107874a4d8c2SCharles.Forsyth else if (isstr(y))
107974a4d8c2SCharles.Forsyth setsval(x, getsval(y));
108074a4d8c2SCharles.Forsyth else if (isnum(y))
108174a4d8c2SCharles.Forsyth setfval(x, getfval(y));
108274a4d8c2SCharles.Forsyth else
108374a4d8c2SCharles.Forsyth funnyvar(y, "read value of");
108474a4d8c2SCharles.Forsyth tempfree(y);
108574a4d8c2SCharles.Forsyth return(x);
108674a4d8c2SCharles.Forsyth }
108774a4d8c2SCharles.Forsyth xf = getfval(x);
108874a4d8c2SCharles.Forsyth yf = getfval(y);
108974a4d8c2SCharles.Forsyth switch (n) {
109074a4d8c2SCharles.Forsyth case ADDEQ:
109174a4d8c2SCharles.Forsyth xf += yf;
109274a4d8c2SCharles.Forsyth break;
109374a4d8c2SCharles.Forsyth case SUBEQ:
109474a4d8c2SCharles.Forsyth xf -= yf;
109574a4d8c2SCharles.Forsyth break;
109674a4d8c2SCharles.Forsyth case MULTEQ:
109774a4d8c2SCharles.Forsyth xf *= yf;
109874a4d8c2SCharles.Forsyth break;
109974a4d8c2SCharles.Forsyth case DIVEQ:
110074a4d8c2SCharles.Forsyth if (yf == 0)
110174a4d8c2SCharles.Forsyth FATAL("division by zero in /=");
110274a4d8c2SCharles.Forsyth xf /= yf;
110374a4d8c2SCharles.Forsyth break;
110474a4d8c2SCharles.Forsyth case MODEQ:
110574a4d8c2SCharles.Forsyth if (yf == 0)
110674a4d8c2SCharles.Forsyth FATAL("division by zero in %%=");
110774a4d8c2SCharles.Forsyth modf(xf/yf, &v);
110874a4d8c2SCharles.Forsyth xf = xf - yf * v;
110974a4d8c2SCharles.Forsyth break;
111074a4d8c2SCharles.Forsyth case POWEQ:
111174a4d8c2SCharles.Forsyth if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
111274a4d8c2SCharles.Forsyth xf = ipow(xf, (int) yf);
111374a4d8c2SCharles.Forsyth else
111474a4d8c2SCharles.Forsyth xf = errcheck(pow(xf, yf), "pow");
111574a4d8c2SCharles.Forsyth break;
111674a4d8c2SCharles.Forsyth default:
111774a4d8c2SCharles.Forsyth FATAL("illegal assignment operator %d", n);
111874a4d8c2SCharles.Forsyth break;
111974a4d8c2SCharles.Forsyth }
112074a4d8c2SCharles.Forsyth tempfree(y);
112174a4d8c2SCharles.Forsyth setfval(x, xf);
112274a4d8c2SCharles.Forsyth return(x);
112374a4d8c2SCharles.Forsyth }
112474a4d8c2SCharles.Forsyth
cat(Node ** a,int q)112574a4d8c2SCharles.Forsyth Cell *cat(Node **a, int q) /* a[0] cat a[1] */
112674a4d8c2SCharles.Forsyth {
112774a4d8c2SCharles.Forsyth Cell *x, *y, *z;
112874a4d8c2SCharles.Forsyth int n1, n2;
112974a4d8c2SCharles.Forsyth char *s;
113074a4d8c2SCharles.Forsyth
113174a4d8c2SCharles.Forsyth x = execute(a[0]);
113274a4d8c2SCharles.Forsyth y = execute(a[1]);
113374a4d8c2SCharles.Forsyth getsval(x);
113474a4d8c2SCharles.Forsyth getsval(y);
113574a4d8c2SCharles.Forsyth n1 = strlen(x->sval);
113674a4d8c2SCharles.Forsyth n2 = strlen(y->sval);
113774a4d8c2SCharles.Forsyth s = (char *) malloc(n1 + n2 + 1);
113874a4d8c2SCharles.Forsyth if (s == NULL)
113974a4d8c2SCharles.Forsyth FATAL("out of space concatenating %.15s... and %.15s...",
114074a4d8c2SCharles.Forsyth x->sval, y->sval);
114174a4d8c2SCharles.Forsyth strcpy(s, x->sval);
114274a4d8c2SCharles.Forsyth strcpy(s+n1, y->sval);
114374a4d8c2SCharles.Forsyth tempfree(y);
114474a4d8c2SCharles.Forsyth z = gettemp();
114574a4d8c2SCharles.Forsyth z->sval = s;
114674a4d8c2SCharles.Forsyth z->tval = STR;
114774a4d8c2SCharles.Forsyth tempfree(x);
114874a4d8c2SCharles.Forsyth return(z);
114974a4d8c2SCharles.Forsyth }
115074a4d8c2SCharles.Forsyth
pastat(Node ** a,int n)115174a4d8c2SCharles.Forsyth Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
115274a4d8c2SCharles.Forsyth {
115374a4d8c2SCharles.Forsyth Cell *x;
115474a4d8c2SCharles.Forsyth
115574a4d8c2SCharles.Forsyth if (a[0] == 0)
115674a4d8c2SCharles.Forsyth x = execute(a[1]);
115774a4d8c2SCharles.Forsyth else {
115874a4d8c2SCharles.Forsyth x = execute(a[0]);
115974a4d8c2SCharles.Forsyth if (istrue(x)) {
116074a4d8c2SCharles.Forsyth tempfree(x);
116174a4d8c2SCharles.Forsyth x = execute(a[1]);
116274a4d8c2SCharles.Forsyth }
116374a4d8c2SCharles.Forsyth }
116474a4d8c2SCharles.Forsyth return x;
116574a4d8c2SCharles.Forsyth }
116674a4d8c2SCharles.Forsyth
dopa2(Node ** a,int n)116774a4d8c2SCharles.Forsyth Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
116874a4d8c2SCharles.Forsyth {
116974a4d8c2SCharles.Forsyth Cell *x;
117074a4d8c2SCharles.Forsyth int pair;
117174a4d8c2SCharles.Forsyth
117274a4d8c2SCharles.Forsyth pair = ptoi(a[3]);
117374a4d8c2SCharles.Forsyth if (pairstack[pair] == 0) {
117474a4d8c2SCharles.Forsyth x = execute(a[0]);
117574a4d8c2SCharles.Forsyth if (istrue(x))
117674a4d8c2SCharles.Forsyth pairstack[pair] = 1;
117774a4d8c2SCharles.Forsyth tempfree(x);
117874a4d8c2SCharles.Forsyth }
117974a4d8c2SCharles.Forsyth if (pairstack[pair] == 1) {
118074a4d8c2SCharles.Forsyth x = execute(a[1]);
118174a4d8c2SCharles.Forsyth if (istrue(x))
118274a4d8c2SCharles.Forsyth pairstack[pair] = 0;
118374a4d8c2SCharles.Forsyth tempfree(x);
118474a4d8c2SCharles.Forsyth x = execute(a[2]);
118574a4d8c2SCharles.Forsyth return(x);
118674a4d8c2SCharles.Forsyth }
118774a4d8c2SCharles.Forsyth return(False);
118874a4d8c2SCharles.Forsyth }
118974a4d8c2SCharles.Forsyth
split(Node ** a,int nnn)119074a4d8c2SCharles.Forsyth Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
119174a4d8c2SCharles.Forsyth {
119274a4d8c2SCharles.Forsyth Cell *x = 0, *y, *ap;
119374a4d8c2SCharles.Forsyth char *s;
119474a4d8c2SCharles.Forsyth int sep;
119574a4d8c2SCharles.Forsyth char *t, temp, num[50], *fs = 0;
119674a4d8c2SCharles.Forsyth int n, tempstat, arg3type;
119774a4d8c2SCharles.Forsyth
119874a4d8c2SCharles.Forsyth y = execute(a[0]); /* source string */
119974a4d8c2SCharles.Forsyth s = getsval(y);
120074a4d8c2SCharles.Forsyth arg3type = ptoi(a[3]);
120174a4d8c2SCharles.Forsyth if (a[2] == 0) /* fs string */
120274a4d8c2SCharles.Forsyth fs = *FS;
120374a4d8c2SCharles.Forsyth else if (arg3type == STRING) { /* split(str,arr,"string") */
120474a4d8c2SCharles.Forsyth x = execute(a[2]);
120574a4d8c2SCharles.Forsyth fs = getsval(x);
120674a4d8c2SCharles.Forsyth } else if (arg3type == REGEXPR)
120774a4d8c2SCharles.Forsyth fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
120874a4d8c2SCharles.Forsyth else
120974a4d8c2SCharles.Forsyth FATAL("illegal type of split");
121074a4d8c2SCharles.Forsyth sep = *fs;
121174a4d8c2SCharles.Forsyth ap = execute(a[1]); /* array name */
121235d297e4Sforsyth n = y->tval;
121335d297e4Sforsyth y->tval |= DONTFREE; /* split(a[x], a); */
121474a4d8c2SCharles.Forsyth freesymtab(ap);
121535d297e4Sforsyth y->tval = n;
121674a4d8c2SCharles.Forsyth dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
121774a4d8c2SCharles.Forsyth ap->tval &= ~STR;
121874a4d8c2SCharles.Forsyth ap->tval |= ARR;
121974a4d8c2SCharles.Forsyth ap->sval = (char *) makesymtab(NSYMTAB);
122074a4d8c2SCharles.Forsyth
122174a4d8c2SCharles.Forsyth n = 0;
122274a4d8c2SCharles.Forsyth if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */
122374a4d8c2SCharles.Forsyth fa *pfa;
122474a4d8c2SCharles.Forsyth if (arg3type == REGEXPR) { /* it's ready already */
122574a4d8c2SCharles.Forsyth pfa = (fa *) a[2];
122674a4d8c2SCharles.Forsyth } else {
122774a4d8c2SCharles.Forsyth pfa = makedfa(fs, 1);
122874a4d8c2SCharles.Forsyth }
122974a4d8c2SCharles.Forsyth if (nematch(pfa,s)) {
123074a4d8c2SCharles.Forsyth tempstat = pfa->initstat;
123174a4d8c2SCharles.Forsyth pfa->initstat = 2;
123274a4d8c2SCharles.Forsyth do {
123374a4d8c2SCharles.Forsyth n++;
123474a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
123574a4d8c2SCharles.Forsyth temp = *patbeg;
123674a4d8c2SCharles.Forsyth *patbeg = '\0';
123774a4d8c2SCharles.Forsyth if (is_number(s))
123874a4d8c2SCharles.Forsyth setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
123974a4d8c2SCharles.Forsyth else
124074a4d8c2SCharles.Forsyth setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
124174a4d8c2SCharles.Forsyth *patbeg = temp;
124274a4d8c2SCharles.Forsyth s = patbeg + patlen;
124374a4d8c2SCharles.Forsyth if (*(patbeg+patlen-1) == 0 || *s == 0) {
124474a4d8c2SCharles.Forsyth n++;
124574a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
124674a4d8c2SCharles.Forsyth setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
124774a4d8c2SCharles.Forsyth pfa->initstat = tempstat;
124874a4d8c2SCharles.Forsyth goto spdone;
124974a4d8c2SCharles.Forsyth }
125074a4d8c2SCharles.Forsyth } while (nematch(pfa,s));
125174a4d8c2SCharles.Forsyth }
125274a4d8c2SCharles.Forsyth n++;
125374a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
125474a4d8c2SCharles.Forsyth if (is_number(s))
125574a4d8c2SCharles.Forsyth setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
125674a4d8c2SCharles.Forsyth else
125774a4d8c2SCharles.Forsyth setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
125874a4d8c2SCharles.Forsyth spdone:
125974a4d8c2SCharles.Forsyth pfa = NULL;
126074a4d8c2SCharles.Forsyth } else if (sep == ' ') {
126174a4d8c2SCharles.Forsyth for (n = 0; ; ) {
126274a4d8c2SCharles.Forsyth while (*s == ' ' || *s == '\t' || *s == '\n')
126374a4d8c2SCharles.Forsyth s++;
126474a4d8c2SCharles.Forsyth if (*s == 0)
126574a4d8c2SCharles.Forsyth break;
126674a4d8c2SCharles.Forsyth n++;
126774a4d8c2SCharles.Forsyth t = s;
126874a4d8c2SCharles.Forsyth do
126974a4d8c2SCharles.Forsyth s++;
127074a4d8c2SCharles.Forsyth while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
127174a4d8c2SCharles.Forsyth temp = *s;
127274a4d8c2SCharles.Forsyth *s = '\0';
127374a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
127474a4d8c2SCharles.Forsyth if (is_number(t))
127574a4d8c2SCharles.Forsyth setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
127674a4d8c2SCharles.Forsyth else
127774a4d8c2SCharles.Forsyth setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
127874a4d8c2SCharles.Forsyth *s = temp;
127974a4d8c2SCharles.Forsyth if (*s != 0)
128074a4d8c2SCharles.Forsyth s++;
128174a4d8c2SCharles.Forsyth }
128274a4d8c2SCharles.Forsyth } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
128374a4d8c2SCharles.Forsyth for (n = 0; *s != 0; s++) {
128474a4d8c2SCharles.Forsyth char buf[2];
128574a4d8c2SCharles.Forsyth n++;
128674a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
128774a4d8c2SCharles.Forsyth buf[0] = *s;
128874a4d8c2SCharles.Forsyth buf[1] = 0;
128974a4d8c2SCharles.Forsyth if (isdigit((uschar)buf[0]))
129074a4d8c2SCharles.Forsyth setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
129174a4d8c2SCharles.Forsyth else
129274a4d8c2SCharles.Forsyth setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
129374a4d8c2SCharles.Forsyth }
129474a4d8c2SCharles.Forsyth } else if (*s != 0) {
129574a4d8c2SCharles.Forsyth for (;;) {
129674a4d8c2SCharles.Forsyth n++;
129774a4d8c2SCharles.Forsyth t = s;
129874a4d8c2SCharles.Forsyth while (*s != sep && *s != '\n' && *s != '\0')
129974a4d8c2SCharles.Forsyth s++;
130074a4d8c2SCharles.Forsyth temp = *s;
130174a4d8c2SCharles.Forsyth *s = '\0';
130274a4d8c2SCharles.Forsyth sprintf(num, "%d", n);
130374a4d8c2SCharles.Forsyth if (is_number(t))
130474a4d8c2SCharles.Forsyth setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
130574a4d8c2SCharles.Forsyth else
130674a4d8c2SCharles.Forsyth setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
130774a4d8c2SCharles.Forsyth *s = temp;
130874a4d8c2SCharles.Forsyth if (*s++ == 0)
130974a4d8c2SCharles.Forsyth break;
131074a4d8c2SCharles.Forsyth }
131174a4d8c2SCharles.Forsyth }
131274a4d8c2SCharles.Forsyth tempfree(ap);
131374a4d8c2SCharles.Forsyth tempfree(y);
131474a4d8c2SCharles.Forsyth if (a[2] != 0 && arg3type == STRING) {
131574a4d8c2SCharles.Forsyth tempfree(x);
131674a4d8c2SCharles.Forsyth }
131774a4d8c2SCharles.Forsyth x = gettemp();
131874a4d8c2SCharles.Forsyth x->tval = NUM;
131974a4d8c2SCharles.Forsyth x->fval = n;
132074a4d8c2SCharles.Forsyth return(x);
132174a4d8c2SCharles.Forsyth }
132274a4d8c2SCharles.Forsyth
condexpr(Node ** a,int n)132374a4d8c2SCharles.Forsyth Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
132474a4d8c2SCharles.Forsyth {
132574a4d8c2SCharles.Forsyth Cell *x;
132674a4d8c2SCharles.Forsyth
132774a4d8c2SCharles.Forsyth x = execute(a[0]);
132874a4d8c2SCharles.Forsyth if (istrue(x)) {
132974a4d8c2SCharles.Forsyth tempfree(x);
133074a4d8c2SCharles.Forsyth x = execute(a[1]);
133174a4d8c2SCharles.Forsyth } else {
133274a4d8c2SCharles.Forsyth tempfree(x);
133374a4d8c2SCharles.Forsyth x = execute(a[2]);
133474a4d8c2SCharles.Forsyth }
133574a4d8c2SCharles.Forsyth return(x);
133674a4d8c2SCharles.Forsyth }
133774a4d8c2SCharles.Forsyth
ifstat(Node ** a,int n)133874a4d8c2SCharles.Forsyth Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
133974a4d8c2SCharles.Forsyth {
134074a4d8c2SCharles.Forsyth Cell *x;
134174a4d8c2SCharles.Forsyth
134274a4d8c2SCharles.Forsyth x = execute(a[0]);
134374a4d8c2SCharles.Forsyth if (istrue(x)) {
134474a4d8c2SCharles.Forsyth tempfree(x);
134574a4d8c2SCharles.Forsyth x = execute(a[1]);
134674a4d8c2SCharles.Forsyth } else if (a[2] != 0) {
134774a4d8c2SCharles.Forsyth tempfree(x);
134874a4d8c2SCharles.Forsyth x = execute(a[2]);
134974a4d8c2SCharles.Forsyth }
135074a4d8c2SCharles.Forsyth return(x);
135174a4d8c2SCharles.Forsyth }
135274a4d8c2SCharles.Forsyth
whilestat(Node ** a,int n)135374a4d8c2SCharles.Forsyth Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
135474a4d8c2SCharles.Forsyth {
135574a4d8c2SCharles.Forsyth Cell *x;
135674a4d8c2SCharles.Forsyth
135774a4d8c2SCharles.Forsyth for (;;) {
135874a4d8c2SCharles.Forsyth x = execute(a[0]);
135974a4d8c2SCharles.Forsyth if (!istrue(x))
136074a4d8c2SCharles.Forsyth return(x);
136174a4d8c2SCharles.Forsyth tempfree(x);
136274a4d8c2SCharles.Forsyth x = execute(a[1]);
136374a4d8c2SCharles.Forsyth if (isbreak(x)) {
136474a4d8c2SCharles.Forsyth x = True;
136574a4d8c2SCharles.Forsyth return(x);
136674a4d8c2SCharles.Forsyth }
136774a4d8c2SCharles.Forsyth if (isnext(x) || isexit(x) || isret(x))
136874a4d8c2SCharles.Forsyth return(x);
136974a4d8c2SCharles.Forsyth tempfree(x);
137074a4d8c2SCharles.Forsyth }
137174a4d8c2SCharles.Forsyth }
137274a4d8c2SCharles.Forsyth
dostat(Node ** a,int n)137374a4d8c2SCharles.Forsyth Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
137474a4d8c2SCharles.Forsyth {
137574a4d8c2SCharles.Forsyth Cell *x;
137674a4d8c2SCharles.Forsyth
137774a4d8c2SCharles.Forsyth for (;;) {
137874a4d8c2SCharles.Forsyth x = execute(a[0]);
137974a4d8c2SCharles.Forsyth if (isbreak(x))
138074a4d8c2SCharles.Forsyth return True;
138174a4d8c2SCharles.Forsyth if (isnext(x) || isexit(x) || isret(x))
138274a4d8c2SCharles.Forsyth return(x);
138374a4d8c2SCharles.Forsyth tempfree(x);
138474a4d8c2SCharles.Forsyth x = execute(a[1]);
138574a4d8c2SCharles.Forsyth if (!istrue(x))
138674a4d8c2SCharles.Forsyth return(x);
138774a4d8c2SCharles.Forsyth tempfree(x);
138874a4d8c2SCharles.Forsyth }
138974a4d8c2SCharles.Forsyth }
139074a4d8c2SCharles.Forsyth
forstat(Node ** a,int n)139174a4d8c2SCharles.Forsyth Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
139274a4d8c2SCharles.Forsyth {
139374a4d8c2SCharles.Forsyth Cell *x;
139474a4d8c2SCharles.Forsyth
139574a4d8c2SCharles.Forsyth x = execute(a[0]);
139674a4d8c2SCharles.Forsyth tempfree(x);
139774a4d8c2SCharles.Forsyth for (;;) {
139874a4d8c2SCharles.Forsyth if (a[1]!=0) {
139974a4d8c2SCharles.Forsyth x = execute(a[1]);
140074a4d8c2SCharles.Forsyth if (!istrue(x)) return(x);
140174a4d8c2SCharles.Forsyth else tempfree(x);
140274a4d8c2SCharles.Forsyth }
140374a4d8c2SCharles.Forsyth x = execute(a[3]);
140474a4d8c2SCharles.Forsyth if (isbreak(x)) /* turn off break */
140574a4d8c2SCharles.Forsyth return True;
140674a4d8c2SCharles.Forsyth if (isnext(x) || isexit(x) || isret(x))
140774a4d8c2SCharles.Forsyth return(x);
140874a4d8c2SCharles.Forsyth tempfree(x);
140974a4d8c2SCharles.Forsyth x = execute(a[2]);
141074a4d8c2SCharles.Forsyth tempfree(x);
141174a4d8c2SCharles.Forsyth }
141274a4d8c2SCharles.Forsyth }
141374a4d8c2SCharles.Forsyth
instat(Node ** a,int n)141474a4d8c2SCharles.Forsyth Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
141574a4d8c2SCharles.Forsyth {
141674a4d8c2SCharles.Forsyth Cell *x, *vp, *arrayp, *cp, *ncp;
141774a4d8c2SCharles.Forsyth Array *tp;
141874a4d8c2SCharles.Forsyth int i;
141974a4d8c2SCharles.Forsyth
142074a4d8c2SCharles.Forsyth vp = execute(a[0]);
142174a4d8c2SCharles.Forsyth arrayp = execute(a[1]);
142274a4d8c2SCharles.Forsyth if (!isarr(arrayp)) {
142374a4d8c2SCharles.Forsyth return True;
142474a4d8c2SCharles.Forsyth }
142574a4d8c2SCharles.Forsyth tp = (Array *) arrayp->sval;
142674a4d8c2SCharles.Forsyth tempfree(arrayp);
142774a4d8c2SCharles.Forsyth for (i = 0; i < tp->size; i++) { /* this routine knows too much */
142874a4d8c2SCharles.Forsyth for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
142974a4d8c2SCharles.Forsyth setsval(vp, cp->nval);
143074a4d8c2SCharles.Forsyth ncp = cp->cnext;
143174a4d8c2SCharles.Forsyth x = execute(a[2]);
143274a4d8c2SCharles.Forsyth if (isbreak(x)) {
143374a4d8c2SCharles.Forsyth tempfree(vp);
143474a4d8c2SCharles.Forsyth return True;
143574a4d8c2SCharles.Forsyth }
143674a4d8c2SCharles.Forsyth if (isnext(x) || isexit(x) || isret(x)) {
143774a4d8c2SCharles.Forsyth tempfree(vp);
143874a4d8c2SCharles.Forsyth return(x);
143974a4d8c2SCharles.Forsyth }
144074a4d8c2SCharles.Forsyth tempfree(x);
144174a4d8c2SCharles.Forsyth }
144274a4d8c2SCharles.Forsyth }
144374a4d8c2SCharles.Forsyth return True;
144474a4d8c2SCharles.Forsyth }
144574a4d8c2SCharles.Forsyth
bltin(Node ** a,int n)144674a4d8c2SCharles.Forsyth Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
144774a4d8c2SCharles.Forsyth {
144874a4d8c2SCharles.Forsyth Cell *x, *y;
144974a4d8c2SCharles.Forsyth Awkfloat u;
145074a4d8c2SCharles.Forsyth int t;
145174a4d8c2SCharles.Forsyth char *p, *buf;
145274a4d8c2SCharles.Forsyth Node *nextarg;
145374a4d8c2SCharles.Forsyth FILE *fp;
145474a4d8c2SCharles.Forsyth
145574a4d8c2SCharles.Forsyth t = ptoi(a[0]);
145674a4d8c2SCharles.Forsyth x = execute(a[1]);
145774a4d8c2SCharles.Forsyth nextarg = a[1]->nnext;
145874a4d8c2SCharles.Forsyth switch (t) {
145974a4d8c2SCharles.Forsyth case FLENGTH:
146074a4d8c2SCharles.Forsyth u = strlen(getsval(x)); break;
146174a4d8c2SCharles.Forsyth case FLOG:
146274a4d8c2SCharles.Forsyth u = errcheck(log(getfval(x)), "log"); break;
146374a4d8c2SCharles.Forsyth case FINT:
146474a4d8c2SCharles.Forsyth modf(getfval(x), &u); break;
146574a4d8c2SCharles.Forsyth case FEXP:
146674a4d8c2SCharles.Forsyth u = errcheck(exp(getfval(x)), "exp"); break;
146774a4d8c2SCharles.Forsyth case FSQRT:
146874a4d8c2SCharles.Forsyth u = errcheck(sqrt(getfval(x)), "sqrt"); break;
146974a4d8c2SCharles.Forsyth case FSIN:
147074a4d8c2SCharles.Forsyth u = sin(getfval(x)); break;
147174a4d8c2SCharles.Forsyth case FCOS:
147274a4d8c2SCharles.Forsyth u = cos(getfval(x)); break;
147374a4d8c2SCharles.Forsyth case FATAN:
147474a4d8c2SCharles.Forsyth if (nextarg == 0) {
147574a4d8c2SCharles.Forsyth WARNING("atan2 requires two arguments; returning 1.0");
147674a4d8c2SCharles.Forsyth u = 1.0;
147774a4d8c2SCharles.Forsyth } else {
147874a4d8c2SCharles.Forsyth y = execute(a[1]->nnext);
147974a4d8c2SCharles.Forsyth u = atan2(getfval(x), getfval(y));
148074a4d8c2SCharles.Forsyth tempfree(y);
148174a4d8c2SCharles.Forsyth nextarg = nextarg->nnext;
148274a4d8c2SCharles.Forsyth }
148374a4d8c2SCharles.Forsyth break;
148474a4d8c2SCharles.Forsyth case FSYSTEM:
148574a4d8c2SCharles.Forsyth fflush(stdout); /* in case something is buffered already */
148674a4d8c2SCharles.Forsyth u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
148774a4d8c2SCharles.Forsyth break;
148874a4d8c2SCharles.Forsyth case FRAND:
148974a4d8c2SCharles.Forsyth /* in principle, rand() returns something in 0..RAND_MAX */
149074a4d8c2SCharles.Forsyth u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
149174a4d8c2SCharles.Forsyth break;
149274a4d8c2SCharles.Forsyth case FSRAND:
149374a4d8c2SCharles.Forsyth if (isrec(x)) /* no argument provided */
149474a4d8c2SCharles.Forsyth u = time((time_t *)0);
149574a4d8c2SCharles.Forsyth else
149674a4d8c2SCharles.Forsyth u = getfval(x);
149774a4d8c2SCharles.Forsyth srand((unsigned int) u);
149874a4d8c2SCharles.Forsyth break;
149974a4d8c2SCharles.Forsyth case FTOUPPER:
150074a4d8c2SCharles.Forsyth case FTOLOWER:
150174a4d8c2SCharles.Forsyth buf = tostring(getsval(x));
150274a4d8c2SCharles.Forsyth if (t == FTOUPPER) {
150374a4d8c2SCharles.Forsyth for (p = buf; *p; p++)
150474a4d8c2SCharles.Forsyth if (islower((uschar) *p))
150574a4d8c2SCharles.Forsyth *p = toupper(*p);
150674a4d8c2SCharles.Forsyth } else {
150774a4d8c2SCharles.Forsyth for (p = buf; *p; p++)
150874a4d8c2SCharles.Forsyth if (isupper((uschar) *p))
150974a4d8c2SCharles.Forsyth *p = tolower(*p);
151074a4d8c2SCharles.Forsyth }
151174a4d8c2SCharles.Forsyth tempfree(x);
151274a4d8c2SCharles.Forsyth x = gettemp();
151374a4d8c2SCharles.Forsyth setsval(x, buf);
151474a4d8c2SCharles.Forsyth free(buf);
151574a4d8c2SCharles.Forsyth return x;
151674a4d8c2SCharles.Forsyth case FFLUSH:
151774a4d8c2SCharles.Forsyth if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
151874a4d8c2SCharles.Forsyth u = EOF;
151974a4d8c2SCharles.Forsyth else
152074a4d8c2SCharles.Forsyth u = fflush(fp);
152174a4d8c2SCharles.Forsyth break;
152274a4d8c2SCharles.Forsyth default: /* can't happen */
152374a4d8c2SCharles.Forsyth FATAL("illegal function type %d", t);
152474a4d8c2SCharles.Forsyth break;
152574a4d8c2SCharles.Forsyth }
152674a4d8c2SCharles.Forsyth tempfree(x);
152774a4d8c2SCharles.Forsyth x = gettemp();
152874a4d8c2SCharles.Forsyth setfval(x, u);
152974a4d8c2SCharles.Forsyth if (nextarg != 0) {
153074a4d8c2SCharles.Forsyth WARNING("warning: function has too many arguments");
153174a4d8c2SCharles.Forsyth for ( ; nextarg; nextarg = nextarg->nnext)
153274a4d8c2SCharles.Forsyth execute(nextarg);
153374a4d8c2SCharles.Forsyth }
153474a4d8c2SCharles.Forsyth return(x);
153574a4d8c2SCharles.Forsyth }
153674a4d8c2SCharles.Forsyth
printstat(Node ** a,int n)153774a4d8c2SCharles.Forsyth Cell *printstat(Node **a, int n) /* print a[0] */
153874a4d8c2SCharles.Forsyth {
153974a4d8c2SCharles.Forsyth Node *x;
154074a4d8c2SCharles.Forsyth Cell *y;
154174a4d8c2SCharles.Forsyth FILE *fp;
154274a4d8c2SCharles.Forsyth
154374a4d8c2SCharles.Forsyth if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
154474a4d8c2SCharles.Forsyth fp = stdout;
154574a4d8c2SCharles.Forsyth else
154674a4d8c2SCharles.Forsyth fp = redirect(ptoi(a[1]), a[2]);
154774a4d8c2SCharles.Forsyth for (x = a[0]; x != NULL; x = x->nnext) {
154874a4d8c2SCharles.Forsyth y = execute(x);
154974a4d8c2SCharles.Forsyth fputs(getsval(y), fp);
155074a4d8c2SCharles.Forsyth tempfree(y);
155174a4d8c2SCharles.Forsyth if (x->nnext == NULL)
155274a4d8c2SCharles.Forsyth fputs(*ORS, fp);
155374a4d8c2SCharles.Forsyth else
155474a4d8c2SCharles.Forsyth fputs(*OFS, fp);
155574a4d8c2SCharles.Forsyth }
155674a4d8c2SCharles.Forsyth if (a[1] != 0)
155774a4d8c2SCharles.Forsyth fflush(fp);
155874a4d8c2SCharles.Forsyth if (ferror(fp))
155974a4d8c2SCharles.Forsyth FATAL("write error on %s", filename(fp));
156074a4d8c2SCharles.Forsyth return(True);
156174a4d8c2SCharles.Forsyth }
156274a4d8c2SCharles.Forsyth
nullproc(Node ** a,int n)156374a4d8c2SCharles.Forsyth Cell *nullproc(Node **a, int n)
156474a4d8c2SCharles.Forsyth {
156574a4d8c2SCharles.Forsyth n = n;
156674a4d8c2SCharles.Forsyth a = a;
156774a4d8c2SCharles.Forsyth return 0;
156874a4d8c2SCharles.Forsyth }
156974a4d8c2SCharles.Forsyth
157074a4d8c2SCharles.Forsyth
redirect(int a,Node * b)157174a4d8c2SCharles.Forsyth FILE *redirect(int a, Node *b) /* set up all i/o redirections */
157274a4d8c2SCharles.Forsyth {
157374a4d8c2SCharles.Forsyth FILE *fp;
157474a4d8c2SCharles.Forsyth Cell *x;
157574a4d8c2SCharles.Forsyth char *fname;
157674a4d8c2SCharles.Forsyth
157774a4d8c2SCharles.Forsyth x = execute(b);
157874a4d8c2SCharles.Forsyth fname = getsval(x);
157974a4d8c2SCharles.Forsyth fp = openfile(a, fname);
158074a4d8c2SCharles.Forsyth if (fp == NULL)
158174a4d8c2SCharles.Forsyth FATAL("can't open file %s", fname);
158274a4d8c2SCharles.Forsyth tempfree(x);
158374a4d8c2SCharles.Forsyth return fp;
158474a4d8c2SCharles.Forsyth }
158574a4d8c2SCharles.Forsyth
158674a4d8c2SCharles.Forsyth struct files {
158774a4d8c2SCharles.Forsyth FILE *fp;
158874a4d8c2SCharles.Forsyth char *fname;
158974a4d8c2SCharles.Forsyth int mode; /* '|', 'a', 'w' => LE/LT, GT */
159074a4d8c2SCharles.Forsyth } files[FOPEN_MAX] ={
159174a4d8c2SCharles.Forsyth { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
159274a4d8c2SCharles.Forsyth { NULL, "/dev/stdout", GT },
159374a4d8c2SCharles.Forsyth { NULL, "/dev/stderr", GT }
159474a4d8c2SCharles.Forsyth };
159574a4d8c2SCharles.Forsyth
stdinit(void)159674a4d8c2SCharles.Forsyth void stdinit(void) /* in case stdin, etc., are not constants */
159774a4d8c2SCharles.Forsyth {
159874a4d8c2SCharles.Forsyth files[0].fp = stdin;
159974a4d8c2SCharles.Forsyth files[1].fp = stdout;
160074a4d8c2SCharles.Forsyth files[2].fp = stderr;
160174a4d8c2SCharles.Forsyth }
160274a4d8c2SCharles.Forsyth
openfile(int a,char * us)160374a4d8c2SCharles.Forsyth FILE *openfile(int a, char *us)
160474a4d8c2SCharles.Forsyth {
160574a4d8c2SCharles.Forsyth char *s = us;
160674a4d8c2SCharles.Forsyth int i, m;
160774a4d8c2SCharles.Forsyth FILE *fp = 0;
160874a4d8c2SCharles.Forsyth
160974a4d8c2SCharles.Forsyth if (*s == '\0')
161074a4d8c2SCharles.Forsyth FATAL("null file name in print or getline");
161174a4d8c2SCharles.Forsyth for (i=0; i < FOPEN_MAX; i++)
161274a4d8c2SCharles.Forsyth if (files[i].fname && strcmp(s, files[i].fname) == 0) {
161374a4d8c2SCharles.Forsyth if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
161474a4d8c2SCharles.Forsyth return files[i].fp;
161574a4d8c2SCharles.Forsyth if (a == FFLUSH)
161674a4d8c2SCharles.Forsyth return files[i].fp;
161774a4d8c2SCharles.Forsyth }
161874a4d8c2SCharles.Forsyth if (a == FFLUSH) /* didn't find it, so don't create it! */
161974a4d8c2SCharles.Forsyth return NULL;
162074a4d8c2SCharles.Forsyth
162174a4d8c2SCharles.Forsyth for (i=0; i < FOPEN_MAX; i++)
162274a4d8c2SCharles.Forsyth if (files[i].fp == 0)
162374a4d8c2SCharles.Forsyth break;
162474a4d8c2SCharles.Forsyth if (i >= FOPEN_MAX)
162574a4d8c2SCharles.Forsyth FATAL("%s makes too many open files", s);
162674a4d8c2SCharles.Forsyth fflush(stdout); /* force a semblance of order */
162774a4d8c2SCharles.Forsyth m = a;
162874a4d8c2SCharles.Forsyth if (a == GT) {
162974a4d8c2SCharles.Forsyth fp = fopen(s, "w");
163074a4d8c2SCharles.Forsyth } else if (a == APPEND) {
163174a4d8c2SCharles.Forsyth fp = fopen(s, "a");
163274a4d8c2SCharles.Forsyth m = GT; /* so can mix > and >> */
163374a4d8c2SCharles.Forsyth } else if (a == '|') { /* output pipe */
163474a4d8c2SCharles.Forsyth fp = popen(s, "w");
163574a4d8c2SCharles.Forsyth } else if (a == LE) { /* input pipe */
163674a4d8c2SCharles.Forsyth fp = popen(s, "r");
163774a4d8c2SCharles.Forsyth } else if (a == LT) { /* getline <file */
163874a4d8c2SCharles.Forsyth fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
163974a4d8c2SCharles.Forsyth } else /* can't happen */
164074a4d8c2SCharles.Forsyth FATAL("illegal redirection %d", a);
164174a4d8c2SCharles.Forsyth if (fp != NULL) {
164274a4d8c2SCharles.Forsyth files[i].fname = tostring(s);
164374a4d8c2SCharles.Forsyth files[i].fp = fp;
164474a4d8c2SCharles.Forsyth files[i].mode = m;
164574a4d8c2SCharles.Forsyth }
164674a4d8c2SCharles.Forsyth return fp;
164774a4d8c2SCharles.Forsyth }
164874a4d8c2SCharles.Forsyth
filename(FILE * fp)164974a4d8c2SCharles.Forsyth char *filename(FILE *fp)
165074a4d8c2SCharles.Forsyth {
165174a4d8c2SCharles.Forsyth int i;
165274a4d8c2SCharles.Forsyth
165374a4d8c2SCharles.Forsyth for (i = 0; i < FOPEN_MAX; i++)
165474a4d8c2SCharles.Forsyth if (fp == files[i].fp)
165574a4d8c2SCharles.Forsyth return files[i].fname;
1656*45a20ab7Sforsyth return "?";
165774a4d8c2SCharles.Forsyth }
165874a4d8c2SCharles.Forsyth
closefile(Node ** a,int n)165974a4d8c2SCharles.Forsyth Cell *closefile(Node **a, int n)
166074a4d8c2SCharles.Forsyth {
166174a4d8c2SCharles.Forsyth Cell *x;
166274a4d8c2SCharles.Forsyth int i, stat;
166374a4d8c2SCharles.Forsyth
166474a4d8c2SCharles.Forsyth n = n;
166574a4d8c2SCharles.Forsyth x = execute(a[0]);
166674a4d8c2SCharles.Forsyth getsval(x);
166774a4d8c2SCharles.Forsyth stat = -1;
166874a4d8c2SCharles.Forsyth for (i = 0; i < FOPEN_MAX; i++) {
166974a4d8c2SCharles.Forsyth if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
167074a4d8c2SCharles.Forsyth if (ferror(files[i].fp))
167174a4d8c2SCharles.Forsyth WARNING( "i/o error occurred on %s", files[i].fname );
167274a4d8c2SCharles.Forsyth if (files[i].mode == '|' || files[i].mode == LE)
167374a4d8c2SCharles.Forsyth stat = pclose(files[i].fp);
167474a4d8c2SCharles.Forsyth else
167574a4d8c2SCharles.Forsyth stat = fclose(files[i].fp);
167674a4d8c2SCharles.Forsyth if (stat == EOF)
167774a4d8c2SCharles.Forsyth WARNING( "i/o error occurred closing %s", files[i].fname );
167874a4d8c2SCharles.Forsyth if (i > 2) /* don't do /dev/std... */
167974a4d8c2SCharles.Forsyth xfree(files[i].fname);
168074a4d8c2SCharles.Forsyth files[i].fname = NULL; /* watch out for ref thru this */
168174a4d8c2SCharles.Forsyth files[i].fp = NULL;
168274a4d8c2SCharles.Forsyth }
168374a4d8c2SCharles.Forsyth }
168474a4d8c2SCharles.Forsyth tempfree(x);
168574a4d8c2SCharles.Forsyth x = gettemp();
168674a4d8c2SCharles.Forsyth setfval(x, (Awkfloat) stat);
168774a4d8c2SCharles.Forsyth return(x);
168874a4d8c2SCharles.Forsyth }
168974a4d8c2SCharles.Forsyth
closeall(void)169074a4d8c2SCharles.Forsyth void closeall(void)
169174a4d8c2SCharles.Forsyth {
169274a4d8c2SCharles.Forsyth int i, stat;
169374a4d8c2SCharles.Forsyth
169474a4d8c2SCharles.Forsyth for (i = 0; i < FOPEN_MAX; i++) {
169574a4d8c2SCharles.Forsyth if (files[i].fp) {
169674a4d8c2SCharles.Forsyth if (ferror(files[i].fp))
169774a4d8c2SCharles.Forsyth WARNING( "i/o error occurred on %s", files[i].fname );
169874a4d8c2SCharles.Forsyth if (files[i].mode == '|' || files[i].mode == LE)
169974a4d8c2SCharles.Forsyth stat = pclose(files[i].fp);
170074a4d8c2SCharles.Forsyth else
170174a4d8c2SCharles.Forsyth stat = fclose(files[i].fp);
170274a4d8c2SCharles.Forsyth if (stat == EOF && i != 0)
170374a4d8c2SCharles.Forsyth WARNING( "i/o error occurred while closing %s", files[i].fname );
170474a4d8c2SCharles.Forsyth }
170574a4d8c2SCharles.Forsyth }
170674a4d8c2SCharles.Forsyth }
170774a4d8c2SCharles.Forsyth
170874a4d8c2SCharles.Forsyth void backsub(char **pb_ptr, char **sptr_ptr);
170974a4d8c2SCharles.Forsyth
sub(Node ** a,int nnn)171074a4d8c2SCharles.Forsyth Cell *sub(Node **a, int nnn) /* substitute command */
171174a4d8c2SCharles.Forsyth {
171274a4d8c2SCharles.Forsyth char *sptr, *pb, *q;
171374a4d8c2SCharles.Forsyth Cell *x, *y, *result;
171474a4d8c2SCharles.Forsyth char *t, *buf;
171574a4d8c2SCharles.Forsyth fa *pfa;
171674a4d8c2SCharles.Forsyth int bufsz = recsize;
171774a4d8c2SCharles.Forsyth
171874a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
171974a4d8c2SCharles.Forsyth FATAL("out of memory in sub");
172074a4d8c2SCharles.Forsyth x = execute(a[3]); /* target string */
172174a4d8c2SCharles.Forsyth t = getsval(x);
172274a4d8c2SCharles.Forsyth if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
172374a4d8c2SCharles.Forsyth pfa = (fa *) a[1]; /* regular expression */
172474a4d8c2SCharles.Forsyth else {
172574a4d8c2SCharles.Forsyth y = execute(a[1]);
172674a4d8c2SCharles.Forsyth pfa = makedfa(getsval(y), 1);
172774a4d8c2SCharles.Forsyth tempfree(y);
172874a4d8c2SCharles.Forsyth }
172974a4d8c2SCharles.Forsyth y = execute(a[2]); /* replacement string */
173074a4d8c2SCharles.Forsyth result = False;
173174a4d8c2SCharles.Forsyth if (pmatch(pfa, t)) {
173274a4d8c2SCharles.Forsyth sptr = t;
173374a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
173474a4d8c2SCharles.Forsyth pb = buf;
173574a4d8c2SCharles.Forsyth while (sptr < patbeg)
173674a4d8c2SCharles.Forsyth *pb++ = *sptr++;
173774a4d8c2SCharles.Forsyth sptr = getsval(y);
173874a4d8c2SCharles.Forsyth while (*sptr != 0) {
173974a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
174074a4d8c2SCharles.Forsyth if (*sptr == '\\') {
174174a4d8c2SCharles.Forsyth backsub(&pb, &sptr);
174274a4d8c2SCharles.Forsyth } else if (*sptr == '&') {
174374a4d8c2SCharles.Forsyth sptr++;
174474a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
174574a4d8c2SCharles.Forsyth for (q = patbeg; q < patbeg+patlen; )
174674a4d8c2SCharles.Forsyth *pb++ = *q++;
174774a4d8c2SCharles.Forsyth } else
174874a4d8c2SCharles.Forsyth *pb++ = *sptr++;
174974a4d8c2SCharles.Forsyth }
175074a4d8c2SCharles.Forsyth *pb = '\0';
175174a4d8c2SCharles.Forsyth if (pb > buf + bufsz)
175274a4d8c2SCharles.Forsyth FATAL("sub result1 %.30s too big; can't happen", buf);
175374a4d8c2SCharles.Forsyth sptr = patbeg + patlen;
175474a4d8c2SCharles.Forsyth if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
175574a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
175674a4d8c2SCharles.Forsyth while ((*pb++ = *sptr++) != 0)
175774a4d8c2SCharles.Forsyth ;
175874a4d8c2SCharles.Forsyth }
175974a4d8c2SCharles.Forsyth if (pb > buf + bufsz)
176074a4d8c2SCharles.Forsyth FATAL("sub result2 %.30s too big; can't happen", buf);
176174a4d8c2SCharles.Forsyth setsval(x, buf); /* BUG: should be able to avoid copy */
176274a4d8c2SCharles.Forsyth result = True;;
176374a4d8c2SCharles.Forsyth }
176474a4d8c2SCharles.Forsyth tempfree(x);
176574a4d8c2SCharles.Forsyth tempfree(y);
176674a4d8c2SCharles.Forsyth free(buf);
176774a4d8c2SCharles.Forsyth return result;
176874a4d8c2SCharles.Forsyth }
176974a4d8c2SCharles.Forsyth
gsub(Node ** a,int nnn)177074a4d8c2SCharles.Forsyth Cell *gsub(Node **a, int nnn) /* global substitute */
177174a4d8c2SCharles.Forsyth {
177274a4d8c2SCharles.Forsyth Cell *x, *y;
177374a4d8c2SCharles.Forsyth char *rptr, *sptr, *t, *pb, *q;
177474a4d8c2SCharles.Forsyth char *buf;
177574a4d8c2SCharles.Forsyth fa *pfa;
177674a4d8c2SCharles.Forsyth int mflag, tempstat, num;
177774a4d8c2SCharles.Forsyth int bufsz = recsize;
177874a4d8c2SCharles.Forsyth
177974a4d8c2SCharles.Forsyth if ((buf = (char *) malloc(bufsz)) == NULL)
178074a4d8c2SCharles.Forsyth FATAL("out of memory in gsub");
178174a4d8c2SCharles.Forsyth mflag = 0; /* if mflag == 0, can replace empty string */
178274a4d8c2SCharles.Forsyth num = 0;
178374a4d8c2SCharles.Forsyth x = execute(a[3]); /* target string */
178474a4d8c2SCharles.Forsyth t = getsval(x);
178574a4d8c2SCharles.Forsyth if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
178674a4d8c2SCharles.Forsyth pfa = (fa *) a[1]; /* regular expression */
178774a4d8c2SCharles.Forsyth else {
178874a4d8c2SCharles.Forsyth y = execute(a[1]);
178974a4d8c2SCharles.Forsyth pfa = makedfa(getsval(y), 1);
179074a4d8c2SCharles.Forsyth tempfree(y);
179174a4d8c2SCharles.Forsyth }
179274a4d8c2SCharles.Forsyth y = execute(a[2]); /* replacement string */
179374a4d8c2SCharles.Forsyth if (pmatch(pfa, t)) {
179474a4d8c2SCharles.Forsyth tempstat = pfa->initstat;
179574a4d8c2SCharles.Forsyth pfa->initstat = 2;
179674a4d8c2SCharles.Forsyth pb = buf;
179774a4d8c2SCharles.Forsyth rptr = getsval(y);
179874a4d8c2SCharles.Forsyth do {
179974a4d8c2SCharles.Forsyth if (patlen == 0 && *patbeg != 0) { /* matched empty string */
180074a4d8c2SCharles.Forsyth if (mflag == 0) { /* can replace empty */
180174a4d8c2SCharles.Forsyth num++;
180274a4d8c2SCharles.Forsyth sptr = rptr;
180374a4d8c2SCharles.Forsyth while (*sptr != 0) {
180474a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
180574a4d8c2SCharles.Forsyth if (*sptr == '\\') {
180674a4d8c2SCharles.Forsyth backsub(&pb, &sptr);
180774a4d8c2SCharles.Forsyth } else if (*sptr == '&') {
180874a4d8c2SCharles.Forsyth sptr++;
180974a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
181074a4d8c2SCharles.Forsyth for (q = patbeg; q < patbeg+patlen; )
181174a4d8c2SCharles.Forsyth *pb++ = *q++;
181274a4d8c2SCharles.Forsyth } else
181374a4d8c2SCharles.Forsyth *pb++ = *sptr++;
181474a4d8c2SCharles.Forsyth }
181574a4d8c2SCharles.Forsyth }
181674a4d8c2SCharles.Forsyth if (*t == 0) /* at end */
181774a4d8c2SCharles.Forsyth goto done;
181874a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
181974a4d8c2SCharles.Forsyth *pb++ = *t++;
182074a4d8c2SCharles.Forsyth if (pb > buf + bufsz) /* BUG: not sure of this test */
182174a4d8c2SCharles.Forsyth FATAL("gsub result0 %.30s too big; can't happen", buf);
182274a4d8c2SCharles.Forsyth mflag = 0;
182374a4d8c2SCharles.Forsyth }
182474a4d8c2SCharles.Forsyth else { /* matched nonempty string */
182574a4d8c2SCharles.Forsyth num++;
182674a4d8c2SCharles.Forsyth sptr = t;
182774a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
182874a4d8c2SCharles.Forsyth while (sptr < patbeg)
182974a4d8c2SCharles.Forsyth *pb++ = *sptr++;
183074a4d8c2SCharles.Forsyth sptr = rptr;
183174a4d8c2SCharles.Forsyth while (*sptr != 0) {
183274a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
183374a4d8c2SCharles.Forsyth if (*sptr == '\\') {
183474a4d8c2SCharles.Forsyth backsub(&pb, &sptr);
183574a4d8c2SCharles.Forsyth } else if (*sptr == '&') {
183674a4d8c2SCharles.Forsyth sptr++;
183774a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
183874a4d8c2SCharles.Forsyth for (q = patbeg; q < patbeg+patlen; )
183974a4d8c2SCharles.Forsyth *pb++ = *q++;
184074a4d8c2SCharles.Forsyth } else
184174a4d8c2SCharles.Forsyth *pb++ = *sptr++;
184274a4d8c2SCharles.Forsyth }
184374a4d8c2SCharles.Forsyth t = patbeg + patlen;
184474a4d8c2SCharles.Forsyth if (patlen == 0 || *t == 0 || *(t-1) == 0)
184574a4d8c2SCharles.Forsyth goto done;
184674a4d8c2SCharles.Forsyth if (pb > buf + bufsz)
184774a4d8c2SCharles.Forsyth FATAL("gsub result1 %.30s too big; can't happen", buf);
184874a4d8c2SCharles.Forsyth mflag = 1;
184974a4d8c2SCharles.Forsyth }
185074a4d8c2SCharles.Forsyth } while (pmatch(pfa,t));
185174a4d8c2SCharles.Forsyth sptr = t;
185274a4d8c2SCharles.Forsyth adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
185374a4d8c2SCharles.Forsyth while ((*pb++ = *sptr++) != 0)
185474a4d8c2SCharles.Forsyth ;
185574a4d8c2SCharles.Forsyth done: if (pb > buf + bufsz)
185674a4d8c2SCharles.Forsyth FATAL("gsub result2 %.30s too big; can't happen", buf);
185774a4d8c2SCharles.Forsyth *pb = '\0';
185874a4d8c2SCharles.Forsyth setsval(x, buf); /* BUG: should be able to avoid copy + free */
185974a4d8c2SCharles.Forsyth pfa->initstat = tempstat;
186074a4d8c2SCharles.Forsyth }
186174a4d8c2SCharles.Forsyth tempfree(x);
186274a4d8c2SCharles.Forsyth tempfree(y);
186374a4d8c2SCharles.Forsyth x = gettemp();
186474a4d8c2SCharles.Forsyth x->tval = NUM;
186574a4d8c2SCharles.Forsyth x->fval = num;
186674a4d8c2SCharles.Forsyth free(buf);
186774a4d8c2SCharles.Forsyth return(x);
186874a4d8c2SCharles.Forsyth }
186974a4d8c2SCharles.Forsyth
backsub(char ** pb_ptr,char ** sptr_ptr)187074a4d8c2SCharles.Forsyth void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
187174a4d8c2SCharles.Forsyth { /* sptr[0] == '\\' */
187274a4d8c2SCharles.Forsyth char *pb = *pb_ptr, *sptr = *sptr_ptr;
187374a4d8c2SCharles.Forsyth
187474a4d8c2SCharles.Forsyth if (sptr[1] == '\\') {
187574a4d8c2SCharles.Forsyth if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
187674a4d8c2SCharles.Forsyth *pb++ = '\\';
187774a4d8c2SCharles.Forsyth *pb++ = '&';
187874a4d8c2SCharles.Forsyth sptr += 4;
187974a4d8c2SCharles.Forsyth } else if (sptr[2] == '&') { /* \\& -> \ + matched */
188074a4d8c2SCharles.Forsyth *pb++ = '\\';
188174a4d8c2SCharles.Forsyth sptr += 2;
188274a4d8c2SCharles.Forsyth } else { /* \\x -> \\x */
188374a4d8c2SCharles.Forsyth *pb++ = *sptr++;
188474a4d8c2SCharles.Forsyth *pb++ = *sptr++;
188574a4d8c2SCharles.Forsyth }
188674a4d8c2SCharles.Forsyth } else if (sptr[1] == '&') { /* literal & */
188774a4d8c2SCharles.Forsyth sptr++;
188874a4d8c2SCharles.Forsyth *pb++ = *sptr++;
188974a4d8c2SCharles.Forsyth } else /* literal \ */
189074a4d8c2SCharles.Forsyth *pb++ = *sptr++;
189174a4d8c2SCharles.Forsyth
189274a4d8c2SCharles.Forsyth *pb_ptr = pb;
189374a4d8c2SCharles.Forsyth *sptr_ptr = sptr;
189474a4d8c2SCharles.Forsyth }
1895