morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

run.c (46552B)


      1 /*	$OpenBSD: run.c,v 1.35 2014/10/11 03:07:29 doug Exp $	*/
      2 /****************************************************************
      3 Copyright (C) Lucent Technologies 1997
      4 All Rights Reserved
      5 
      6 Permission to use, copy, modify, and distribute this software and
      7 its documentation for any purpose and without fee is hereby
      8 granted, provided that the above copyright notice appear in all
      9 copies and that both that the copyright notice and this
     10 permission notice and warranty disclaimer appear in supporting
     11 documentation, and that the name Lucent Technologies or any of
     12 its entities not be used in advertising or publicity pertaining
     13 to distribution of the software without specific, written prior
     14 permission.
     15 
     16 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     18 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
     19 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     21 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     23 THIS SOFTWARE.
     24 ****************************************************************/
     25 
     26 #define DEBUG
     27 #include <stdio.h>
     28 #include <ctype.h>
     29 #include <setjmp.h>
     30 #include <limits.h>
     31 #include <math.h>
     32 #include <string.h>
     33 #include <stdlib.h>
     34 #include <time.h>
     35 #include "awk.h"
     36 #include "util.h"
     37 #include "ytab.h"
     38 
     39 #define tempfree(x)	if (istemp(x)) tfree(x); else
     40 
     41 /*
     42 #undef tempfree
     43 
     44 void tempfree(Cell *p) {
     45 	if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
     46 		WARNING("bad csub %d in Cell %d %s",
     47 			p->csub, p->ctype, p->sval);
     48 	}
     49 	if (istemp(p))
     50 		tfree(p);
     51 }
     52 */
     53 
     54 /* do we really need these? */
     55 /* #ifdef _NFILE */
     56 /* #ifndef FOPEN_MAX */
     57 /* #define FOPEN_MAX _NFILE */
     58 /* #endif */
     59 /* #endif */
     60 /*  */
     61 /* #ifndef	FOPEN_MAX */
     62 /* #define	FOPEN_MAX	40 */	/* max number of open files */
     63 /* #endif */
     64 /*  */
     65 /* #ifndef RAND_MAX */
     66 /* #define RAND_MAX	32767 */	/* all that ansi guarantees */
     67 /* #endif */
     68 
     69 jmp_buf env;
     70 int use_srandom;
     71 extern	int	pairstack[];
     72 extern	Awkfloat	srand_seed;
     73 
     74 Node	*winner = NULL;	/* root of parse tree */
     75 Cell	*tmps;		/* free temporary cells for execution */
     76 
     77 static Cell	truecell	={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
     78 Cell	*True	= &truecell;
     79 static Cell	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
     80 Cell	*False	= &falsecell;
     81 static Cell	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
     82 Cell	*jbreak	= &breakcell;
     83 static Cell	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM };
     84 Cell	*jcont	= &contcell;
     85 static Cell	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
     86 Cell	*jnext	= &nextcell;
     87 static Cell	nextfilecell	={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
     88 Cell	*jnextfile	= &nextfilecell;
     89 static Cell	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
     90 Cell	*jexit	= &exitcell;
     91 static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM };
     92 Cell	*jret	= &retcell;
     93 static Cell	tempcell	={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
     94 
     95 Node	*curnode = NULL;	/* the node being executed, for debugging */
     96 
     97 void	stdinit(void);
     98 void	flush_all(void);
     99 
    100 /* buffer memory management */
    101 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
    102 	const char *whatrtn)
    103 /* pbuf:    address of pointer to buffer being managed
    104  * psiz:    address of buffer size variable
    105  * minlen:  minimum length of buffer needed
    106  * quantum: buffer size quantum
    107  * pbptr:   address of movable pointer into buffer, or 0 if none
    108  * whatrtn: name of the calling routine if failure should cause fatal error
    109  *
    110  * return   0 for realloc failure, !=0 for success
    111  */
    112 {
    113 	if (minlen > *psiz) {
    114 		char *tbuf;
    115 		int rminlen = quantum ? minlen % quantum : 0;
    116 		int boff = pbptr ? *pbptr - *pbuf : 0;
    117 		/* round up to next multiple of quantum */
    118 		if (rminlen)
    119 			minlen += quantum - rminlen;
    120 		tbuf = (char *) realloc(*pbuf, minlen);
    121 		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
    122 		if (tbuf == NULL) {
    123 			if (whatrtn)
    124 				FATAL("out of memory in %s", whatrtn);
    125 			return 0;
    126 		}
    127 		*pbuf = tbuf;
    128 		*psiz = minlen;
    129 		if (pbptr)
    130 			*pbptr = tbuf + boff;
    131 	}
    132 	return 1;
    133 }
    134 
    135 void run(Node *a)	/* execution of parse tree starts here */
    136 {
    137 	stdinit();
    138 	execute(a);
    139 	closeall();
    140 }
    141 
    142 Cell *execute(Node *u)	/* execute a node of the parse tree */
    143 {
    144 	Cell *(*proc)(Node **, int);
    145 	Cell *x;
    146 	Node *a;
    147 
    148 	if (u == NULL)
    149 		return(True);
    150 	for (a = u; ; a = a->nnext) {
    151 		curnode = a;
    152 		if (isvalue(a)) {
    153 			x = (Cell *) (a->narg[0]);
    154 			if (isfld(x) && !donefld)
    155 				fldbld();
    156 			else if (isrec(x) && !donerec)
    157 				recbld();
    158 			return(x);
    159 		}
    160 		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
    161 			FATAL("illegal statement");
    162 		proc = proctab[a->nobj-FIRSTTOKEN];
    163 		x = (*proc)(a->narg, a->nobj);
    164 		if (isfld(x) && !donefld)
    165 			fldbld();
    166 		else if (isrec(x) && !donerec)
    167 			recbld();
    168 		if (isexpr(a))
    169 			return(x);
    170 		if (isjump(x))
    171 			return(x);
    172 		if (a->nnext == NULL)
    173 			return(x);
    174 		tempfree(x);
    175 	}
    176 }
    177 
    178 
    179 Cell *program(Node **a, int n)	/* execute an awk program */
    180 {				/* a[0] = BEGIN, a[1] = body, a[2] = END */
    181 	Cell *x;
    182 
    183 	if (setjmp(env) != 0)
    184 		goto ex;
    185 	if (a[0]) {		/* BEGIN */
    186 		x = execute(a[0]);
    187 		if (isexit(x))
    188 			return(True);
    189 		if (isjump(x))
    190 			FATAL("illegal break, continue, next or nextfile from BEGIN");
    191 		tempfree(x);
    192 	}
    193 	if (a[1] || a[2])
    194 		while (getrec(&record, &recsize, 1) > 0) {
    195 			x = execute(a[1]);
    196 			if (isexit(x))
    197 				break;
    198 			tempfree(x);
    199 		}
    200   ex:
    201 	if (setjmp(env) != 0)	/* handles exit within END */
    202 		goto ex1;
    203 	if (a[2]) {		/* END */
    204 		x = execute(a[2]);
    205 		if (isbreak(x) || isnext(x) || iscont(x))
    206 			FATAL("illegal break, continue, next or nextfile from END");
    207 		tempfree(x);
    208 	}
    209   ex1:
    210 	return(True);
    211 }
    212 
    213 struct Frame {	/* stack frame for awk function calls */
    214 	int nargs;	/* number of arguments in this call */
    215 	Cell *fcncell;	/* pointer to Cell for function */
    216 	Cell **args;	/* pointer to array of arguments after execute */
    217 	Cell *retval;	/* return value */
    218 };
    219 
    220 #define	NARGS	50	/* max args in a call */
    221 
    222 struct Frame *frame = NULL;	/* base of stack frames; dynamically allocated */
    223 int	nframe = 0;		/* number of frames allocated */
    224 struct Frame *fp = NULL;	/* frame pointer. bottom level unused */
    225 
    226 Cell *call(Node **a, int n)	/* function call.  very kludgy and fragile */
    227 {
    228 	static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
    229 	int i, ncall, ndef;
    230 	int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
    231 	Node *x;
    232 	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
    233 	Cell *y, *z, *fcn;
    234 	char *s;
    235 
    236 	fcn = execute(a[0]);	/* the function itself */
    237 	s = fcn->nval;
    238 	if (!isfcn(fcn))
    239 		FATAL("calling undefined function %s", s);
    240 	if (frame == NULL) {
    241 		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
    242 		if (frame == NULL)
    243 			FATAL("out of space for stack frames calling %s", s);
    244 	}
    245 	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
    246 		ncall++;
    247 	ndef = (int) fcn->fval;			/* args in defn */
    248 	   dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
    249 	if (ncall > ndef)
    250 		WARNING("function %s called with %d args, uses only %d",
    251 			s, ncall, ndef);
    252 	if (ncall + ndef > NARGS)
    253 		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
    254 	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
    255 		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
    256 		y = execute(x);
    257 		oargs[i] = y;
    258 		   dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
    259 			   i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
    260 		if (isfcn(y))
    261 			FATAL("can't use function %s as argument in %s", y->nval, s);
    262 		if (isarr(y))
    263 			args[i] = y;	/* arrays by ref */
    264 		else
    265 			args[i] = copycell(y);
    266 		tempfree(y);
    267 	}
    268 	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
    269 		args[i] = gettemp();
    270 		*args[i] = newcopycell;
    271 	}
    272 	fp++;	/* now ok to up frame */
    273 	if (fp >= frame + nframe) {
    274 		int dfp = fp - frame;	/* old index */
    275 		frame = (struct Frame *)
    276 			realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
    277 		if (frame == NULL)
    278 			FATAL("out of space for stack frames in %s", s);
    279 		fp = frame + dfp;
    280 	}
    281 	fp->fcncell = fcn;
    282 	fp->args = args;
    283 	fp->nargs = ndef;	/* number defined with (excess are locals) */
    284 	fp->retval = gettemp();
    285 
    286 	   dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
    287 	y = execute((Node *)(fcn->sval));	/* execute body */
    288 	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
    289 
    290 	for (i = 0; i < ndef; i++) {
    291 		Cell *t = fp->args[i];
    292 		if (isarr(t)) {
    293 			if (t->csub == CCOPY) {
    294 				if (i >= ncall) {
    295 					freesymtab(t);
    296 					t->csub = CTEMP;
    297 					tempfree(t);
    298 				} else {
    299 					oargs[i]->tval = t->tval;
    300 					oargs[i]->tval &= ~(STR|NUM|DONTFREE);
    301 					oargs[i]->sval = t->sval;
    302 					tempfree(t);
    303 				}
    304 			}
    305 		} else if (t != y) {	/* kludge to prevent freeing twice */
    306 			t->csub = CTEMP;
    307 			tempfree(t);
    308 		} else if (t == y && t->csub == CCOPY) {
    309 			t->csub = CTEMP;
    310 			tempfree(t);
    311 			freed = 1;
    312 		}
    313 	}
    314 	tempfree(fcn);
    315 	if (isexit(y) || isnext(y))
    316 		return y;
    317 	if (freed == 0) {
    318 		tempfree(y);	/* don't free twice! */
    319 	}
    320 	z = fp->retval;			/* return value */
    321 	   dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
    322 	fp--;
    323 	return(z);
    324 }
    325 
    326 Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */
    327 {
    328 	Cell *y;
    329 
    330 	y = gettemp();
    331 	y->csub = CCOPY;	/* prevents freeing until call is over */
    332 	y->nval = x->nval;	/* BUG? */
    333 	if (isstr(x))
    334 		y->sval = tostring(x->sval);
    335 	y->fval = x->fval;
    336 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
    337 							/* is DONTFREE right? */
    338 	return y;
    339 }
    340 
    341 Cell *arg(Node **a, int n)	/* nth argument of a function */
    342 {
    343 
    344 	n = ptoi(a[0]);	/* argument number, counting from 0 */
    345 	   dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
    346 	if (n+1 > fp->nargs)
    347 		FATAL("argument #%d of function %s was not supplied",
    348 			n+1, fp->fcncell->nval);
    349 	return fp->args[n];
    350 }
    351 
    352 Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */
    353 {
    354 	Cell *y;
    355 
    356 	switch (n) {
    357 	case EXIT:
    358 		if (a[0] != NULL) {
    359 			y = execute(a[0]);
    360 			errorflag = (int) getfval(y);
    361 			tempfree(y);
    362 		}
    363 		longjmp(env, 1);
    364 	case RETURN:
    365 		if (a[0] != NULL) {
    366 			y = execute(a[0]);
    367 			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
    368 				setsval(fp->retval, getsval(y));
    369 				fp->retval->fval = getfval(y);
    370 				fp->retval->tval |= NUM;
    371 			}
    372 			else if (y->tval & STR)
    373 				setsval(fp->retval, getsval(y));
    374 			else if (y->tval & NUM)
    375 				setfval(fp->retval, getfval(y));
    376 			else		/* can't happen */
    377 				FATAL("bad type variable %d", y->tval);
    378 			tempfree(y);
    379 		}
    380 		return(jret);
    381 	case NEXT:
    382 		return(jnext);
    383 	case NEXTFILE:
    384 		nextfile();
    385 		return(jnextfile);
    386 	case BREAK:
    387 		return(jbreak);
    388 	case CONTINUE:
    389 		return(jcont);
    390 	default:	/* can't happen */
    391 		FATAL("illegal jump type %d", n);
    392 	}
    393 	return 0;	/* not reached */
    394 }
    395 
    396 Cell *awkgetline(Node **a, int n)	/* get next line from specific input */
    397 {		/* a[0] is variable, a[1] is operator, a[2] is filename */
    398 	Cell *r, *x;
    399 	extern Cell **fldtab;
    400 	FILE *fp;
    401 	char *buf;
    402 	int bufsize = recsize;
    403 	int mode;
    404 
    405 	if ((buf = (char *) malloc(bufsize)) == NULL)
    406 		FATAL("out of memory in getline");
    407 
    408 	fflush(stdout);	/* in case someone is waiting for a prompt */
    409 	r = gettemp();
    410 	if (a[1] != NULL) {		/* getline < file */
    411 		x = execute(a[2]);		/* filename */
    412 		mode = ptoi(a[1]);
    413 		if (mode == '|')		/* input pipe */
    414 			mode = LE;	/* arbitrary flag */
    415 		fp = openfile(mode, getsval(x));
    416 		tempfree(x);
    417 		if (fp == NULL)
    418 			n = -1;
    419 		else
    420 			n = readrec(&buf, &bufsize, fp);
    421 		if (n <= 0) {
    422 			;
    423 		} else if (a[0] != NULL) {	/* getline var <file */
    424 			x = execute(a[0]);
    425 			setsval(x, buf);
    426 			tempfree(x);
    427 		} else {			/* getline <file */
    428 			setsval(fldtab[0], buf);
    429 			if (is_number(fldtab[0]->sval)) {
    430 				fldtab[0]->fval = atof(fldtab[0]->sval);
    431 				fldtab[0]->tval |= NUM;
    432 			}
    433 		}
    434 	} else {			/* bare getline; use current input */
    435 		if (a[0] == NULL)	/* getline */
    436 			n = getrec(&record, &recsize, 1);
    437 		else {			/* getline var */
    438 			n = getrec(&buf, &bufsize, 0);
    439 			x = execute(a[0]);
    440 			setsval(x, buf);
    441 			tempfree(x);
    442 		}
    443 	}
    444 	setfval(r, (Awkfloat) n);
    445 	free(buf);
    446 	return r;
    447 }
    448 
    449 Cell *getnf(Node **a, int n)	/* get NF */
    450 {
    451 	if (donefld == 0)
    452 		fldbld();
    453 	return (Cell *) a[0];
    454 }
    455 
    456 Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
    457 {
    458 	Cell *x, *y, *z;
    459 	char *s;
    460 	Node *np;
    461 	char *buf;
    462 	int bufsz = recsize;
    463 	int nsub = strlen(*SUBSEP);
    464 
    465 	if ((buf = (char *) malloc(bufsz)) == NULL)
    466 		FATAL("out of memory in array");
    467 
    468 	x = execute(a[0]);	/* Cell* for symbol table */
    469 	buf[0] = 0;
    470 	for (np = a[1]; np; np = np->nnext) {
    471 		y = execute(np);	/* subscript */
    472 		s = getsval(y);
    473 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
    474 			FATAL("out of memory for %s[%s...]", x->nval, buf);
    475 		strlcat(buf, s, bufsz);
    476 		if (np->nnext)
    477 			strlcat(buf, *SUBSEP, bufsz);
    478 		tempfree(y);
    479 	}
    480 	if (!isarr(x)) {
    481 		   dprintf( ("making %s into an array\n", NN(x->nval)) );
    482 		if (freeable(x))
    483 			xfree(x->sval);
    484 		x->tval &= ~(STR|NUM|DONTFREE);
    485 		x->tval |= ARR;
    486 		x->sval = (char *) makesymtab(NSYMTAB);
    487 	}
    488 	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
    489 	z->ctype = OCELL;
    490 	z->csub = CVAR;
    491 	tempfree(x);
    492 	free(buf);
    493 	return(z);
    494 }
    495 
    496 Cell *awkdelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
    497 {
    498 	Cell *x, *y;
    499 	Node *np;
    500 	char *s;
    501 	int nsub = strlen(*SUBSEP);
    502 
    503 	x = execute(a[0]);	/* Cell* for symbol table */
    504 	if (!isarr(x))
    505 		return True;
    506 	if (a[1] == 0) {	/* delete the elements, not the table */
    507 		freesymtab(x);
    508 		x->tval &= ~STR;
    509 		x->tval |= ARR;
    510 		x->sval = (char *) makesymtab(NSYMTAB);
    511 	} else {
    512 		int bufsz = recsize;
    513 		char *buf;
    514 		if ((buf = (char *) malloc(bufsz)) == NULL)
    515 			FATAL("out of memory in adelete");
    516 		buf[0] = 0;
    517 		for (np = a[1]; np; np = np->nnext) {
    518 			y = execute(np);	/* subscript */
    519 			s = getsval(y);
    520 			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
    521 				FATAL("out of memory deleting %s[%s...]", x->nval, buf);
    522 			strlcat(buf, s, bufsz);	
    523 			if (np->nnext)
    524 				strlcat(buf, *SUBSEP, bufsz);
    525 			tempfree(y);
    526 		}
    527 		freeelem(x, buf);
    528 		free(buf);
    529 	}
    530 	tempfree(x);
    531 	return True;
    532 }
    533 
    534 Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */
    535 {
    536 	Cell *x, *ap, *k;
    537 	Node *p;
    538 	char *buf;
    539 	char *s;
    540 	int bufsz = recsize;
    541 	int nsub = strlen(*SUBSEP);
    542 
    543 	ap = execute(a[1]);	/* array name */
    544 	if (!isarr(ap)) {
    545 		   dprintf( ("making %s into an array\n", ap->nval) );
    546 		if (freeable(ap))
    547 			xfree(ap->sval);
    548 		ap->tval &= ~(STR|NUM|DONTFREE);
    549 		ap->tval |= ARR;
    550 		ap->sval = (char *) makesymtab(NSYMTAB);
    551 	}
    552 	if ((buf = (char *) malloc(bufsz)) == NULL) {
    553 		FATAL("out of memory in intest");
    554 	}
    555 	buf[0] = 0;
    556 	for (p = a[0]; p; p = p->nnext) {
    557 		x = execute(p);	/* expr */
    558 		s = getsval(x);
    559 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
    560 			FATAL("out of memory deleting %s[%s...]", x->nval, buf);
    561 		strlcat(buf, s, bufsz);
    562 		tempfree(x);
    563 		if (p->nnext)
    564 			strlcat(buf, *SUBSEP, bufsz);
    565 	}
    566 	k = lookup(buf, (Array *) ap->sval);
    567 	tempfree(ap);
    568 	free(buf);
    569 	if (k == NULL)
    570 		return(False);
    571 	else
    572 		return(True);
    573 }
    574 
    575 
    576 Cell *matchop(Node **a, int n)	/* ~ and match() */
    577 {
    578 	Cell *x, *y;
    579 	char *s, *t;
    580 	int i;
    581 	fa *pfa;
    582 	int (*mf)(fa *, const char *) = match, mode = 0;
    583 
    584 	if (n == MATCHFCN) {
    585 		mf = pmatch;
    586 		mode = 1;
    587 	}
    588 	x = execute(a[1]);	/* a[1] = target text */
    589 	s = getsval(x);
    590 	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
    591 		i = (*mf)((fa *) a[2], s);
    592 	else {
    593 		y = execute(a[2]);	/* a[2] = regular expr */
    594 		t = getsval(y);
    595 		pfa = makedfa(t, mode);
    596 		i = (*mf)(pfa, s);
    597 		tempfree(y);
    598 	}
    599 	tempfree(x);
    600 	if (n == MATCHFCN) {
    601 		int start = patbeg - s + 1;
    602 		if (patlen < 0)
    603 			start = 0;
    604 		setfval(rstartloc, (Awkfloat) start);
    605 		setfval(rlengthloc, (Awkfloat) patlen);
    606 		x = gettemp();
    607 		x->tval = NUM;
    608 		x->fval = start;
    609 		return x;
    610 	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
    611 		return(True);
    612 	else
    613 		return(False);
    614 }
    615 
    616 
    617 Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */
    618 {
    619 	Cell *x, *y;
    620 	int i;
    621 
    622 	x = execute(a[0]);
    623 	i = istrue(x);
    624 	tempfree(x);
    625 	switch (n) {
    626 	case BOR:
    627 		if (i) return(True);
    628 		y = execute(a[1]);
    629 		i = istrue(y);
    630 		tempfree(y);
    631 		if (i) return(True);
    632 		else return(False);
    633 	case AND:
    634 		if ( !i ) return(False);
    635 		y = execute(a[1]);
    636 		i = istrue(y);
    637 		tempfree(y);
    638 		if (i) return(True);
    639 		else return(False);
    640 	case NOT:
    641 		if (i) return(False);
    642 		else return(True);
    643 	default:	/* can't happen */
    644 		FATAL("unknown boolean operator %d", n);
    645 	}
    646 	return 0;	/*NOTREACHED*/
    647 }
    648 
    649 Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */
    650 {
    651 	int i;
    652 	Cell *x, *y;
    653 	Awkfloat j;
    654 
    655 	x = execute(a[0]);
    656 	y = execute(a[1]);
    657 	if (x->tval&NUM && y->tval&NUM) {
    658 		j = x->fval - y->fval;
    659 		i = j<0? -1: (j>0? 1: 0);
    660 	} else {
    661 		i = strcmp(getsval(x), getsval(y));
    662 	}
    663 	tempfree(x);
    664 	tempfree(y);
    665 	switch (n) {
    666 	case LT:	if (i<0) return(True);
    667 			else return(False);
    668 	case LE:	if (i<=0) return(True);
    669 			else return(False);
    670 	case NE:	if (i!=0) return(True);
    671 			else return(False);
    672 	case EQ:	if (i == 0) return(True);
    673 			else return(False);
    674 	case GE:	if (i>=0) return(True);
    675 			else return(False);
    676 	case GT:	if (i>0) return(True);
    677 			else return(False);
    678 	default:	/* can't happen */
    679 		FATAL("unknown relational operator %d", n);
    680 	}
    681 	return 0;	/*NOTREACHED*/
    682 }
    683 
    684 void tfree(Cell *a)	/* free a tempcell */
    685 {
    686 	if (freeable(a)) {
    687 		   dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
    688 		xfree(a->sval);
    689 	}
    690 	if (a == tmps)
    691 		FATAL("tempcell list is curdled");
    692 	a->cnext = tmps;
    693 	tmps = a;
    694 }
    695 
    696 Cell *gettemp(void)	/* get a tempcell */
    697 {	int i;
    698 	Cell *x;
    699 
    700 	if (!tmps) {
    701 		tmps = (Cell *) calloc(100, sizeof(Cell));
    702 		if (!tmps)
    703 			FATAL("out of space for temporaries");
    704 		for(i = 1; i < 100; i++)
    705 			tmps[i-1].cnext = &tmps[i];
    706 		tmps[i-1].cnext = 0;
    707 	}
    708 	x = tmps;
    709 	tmps = x->cnext;
    710 	*x = tempcell;
    711 	return(x);
    712 }
    713 
    714 Cell *indirect(Node **a, int n)	/* $( a[0] ) */
    715 {
    716 	Awkfloat val;
    717 	Cell *x;
    718 	int m;
    719 	char *s;
    720 
    721 	x = execute(a[0]);
    722 	val = getfval(x);	/* freebsd: defend against super large field numbers */
    723 	if ((Awkfloat)INT_MAX < val)
    724 		FATAL("trying to access out of range field %s", x->nval);
    725 	m = (int) val;
    726 	if (m == 0 && !is_number(s = getsval(x)))	/* suspicion! */
    727 		FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
    728 		/* BUG: can x->nval ever be null??? */
    729 	tempfree(x);
    730 	x = fieldadr(m);
    731 	x->ctype = OCELL;	/* BUG?  why are these needed? */
    732 	x->csub = CFLD;
    733 	return(x);
    734 }
    735 
    736 Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
    737 {
    738 	int k, m, n;
    739 	char *s;
    740 	int temp;
    741 	Cell *x, *y, *z = 0;
    742 
    743 	x = execute(a[0]);
    744 	y = execute(a[1]);
    745 	if (a[2] != 0)
    746 		z = execute(a[2]);
    747 	s = getsval(x);
    748 	k = strlen(s) + 1;
    749 	if (k <= 1) {
    750 		tempfree(x);
    751 		tempfree(y);
    752 		if (a[2] != 0) {
    753 			tempfree(z);
    754 		}
    755 		x = gettemp();
    756 		setsval(x, "");
    757 		return(x);
    758 	}
    759 	m = (int) getfval(y);
    760 	if (m <= 0)
    761 		m = 1;
    762 	else if (m > k)
    763 		m = k;
    764 	tempfree(y);
    765 	if (a[2] != 0) {
    766 		n = (int) getfval(z);
    767 		tempfree(z);
    768 	} else
    769 		n = k - 1;
    770 	if (n < 0)
    771 		n = 0;
    772 	else if (n > k - m)
    773 		n = k - m;
    774 	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
    775 	y = gettemp();
    776 	temp = s[n+m-1];	/* with thanks to John Linderman */
    777 	s[n+m-1] = '\0';
    778 	setsval(y, s + m - 1);
    779 	s[n+m-1] = temp;
    780 	tempfree(x);
    781 	return(y);
    782 }
    783 
    784 Cell *sindex(Node **a, int nnn)		/* index(a[0], a[1]) */
    785 {
    786 	Cell *x, *y, *z;
    787 	char *s1, *s2, *p1, *p2, *q;
    788 	Awkfloat v = 0.0;
    789 
    790 	x = execute(a[0]);
    791 	s1 = getsval(x);
    792 	y = execute(a[1]);
    793 	s2 = getsval(y);
    794 
    795 	z = gettemp();
    796 	for (p1 = s1; *p1 != '\0'; p1++) {
    797 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
    798 			;
    799 		if (*p2 == '\0') {
    800 			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
    801 			break;
    802 		}
    803 	}
    804 	tempfree(x);
    805 	tempfree(y);
    806 	setfval(z, v);
    807 	return(z);
    808 }
    809 
    810 #define	MAXNUMSIZE	50
    811 
    812 int format(char **pbuf, int *pbufsize, const char *s, Node *a)	/* printf-like conversions */
    813 {
    814 	char *fmt;
    815 	char *p, *t;
    816 	const char *os;
    817 	Cell *x;
    818 	int flag = 0, n;
    819 	int fmtwd; /* format width */
    820 	int fmtsz = recsize;
    821 	char *buf = *pbuf;
    822 	int bufsize = *pbufsize;
    823 
    824 	os = s;
    825 	p = buf;
    826 	if ((fmt = (char *) malloc(fmtsz)) == NULL)
    827 		FATAL("out of memory in format()");
    828 	while (*s) {
    829 		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
    830 		if (*s != '%') {
    831 			*p++ = *s++;
    832 			continue;
    833 		}
    834 		if (*(s+1) == '%') {
    835 			*p++ = '%';
    836 			s += 2;
    837 			continue;
    838 		}
    839 		/* have to be real careful in case this is a huge number, eg, %100000d */
    840 		fmtwd = atoi(s+1);
    841 		if (fmtwd < 0)
    842 			fmtwd = -fmtwd;
    843 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
    844 		for (t = fmt; (*t++ = *s) != '\0'; s++) {
    845 			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
    846 				FATAL("format item %.30s... ran format() out of memory", os);
    847 			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
    848 				break;	/* the ansi panoply */
    849 			if (*s == '*') {
    850 				if (a == NULL)
    851 					FATAL("not enough args in printf(%s)", os);
    852 				x = execute(a);
    853 				a = a->nnext;
    854 				snprintf(t-1, fmt + fmtsz - (t-1), "%d", fmtwd=(int) getfval(x));
    855 				if (fmtwd < 0)
    856 					fmtwd = -fmtwd;
    857 				adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
    858 				t = fmt + strlen(fmt);
    859 				tempfree(x);
    860 			}
    861 		}
    862 		*t = '\0';
    863 		if (fmtwd < 0)
    864 			fmtwd = -fmtwd;
    865 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
    866 
    867 		switch (*s) {
    868 		case 'f': case 'e': case 'g': case 'E': case 'G':
    869 			flag = 'f';
    870 			break;
    871 		case 'd': case 'i':
    872 			flag = 'd';
    873 			if(*(s-1) == 'l') break;
    874 			*(t-1) = 'l';
    875 			*t = 'd';
    876 			*++t = '\0';
    877 			break;
    878 		case 'o': case 'x': case 'X': case 'u':
    879 			flag = *(s-1) == 'l' ? 'd' : 'u';
    880 			break;
    881 		case 's':
    882 			flag = 's';
    883 			break;
    884 		case 'c':
    885 			flag = 'c';
    886 			break;
    887 		default:
    888 			WARNING("weird printf conversion %s", fmt);
    889 			flag = '?';
    890 			break;
    891 		}
    892 		if (a == NULL)
    893 			FATAL("not enough args in printf(%s)", os);
    894 		x = execute(a);
    895 		a = a->nnext;
    896 		n = MAXNUMSIZE;
    897 		if (fmtwd > n)
    898 			n = fmtwd;
    899 		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
    900 		switch (flag) {
    901 		case '?':	/* unknown, so dump it too */
    902 			snprintf(p, buf + bufsize - p, "%s", fmt);
    903 			t = getsval(x);
    904 			n = strlen(t);
    905 			if (fmtwd > n)
    906 				n = fmtwd;
    907 			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
    908 			p += strlen(p);
    909 			snprintf(p, buf + bufsize - p, "%s", t);
    910 			break;
    911 		case 'f':	snprintf(p, buf + bufsize - p, fmt, getfval(x)); break;
    912 		case 'd':	snprintf(p, buf + bufsize - p, fmt, (long) getfval(x)); break;
    913 		case 'u':	snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); break;
    914 		case 's':
    915 			t = getsval(x);
    916 			n = strlen(t);
    917 			if (fmtwd > n)
    918 				n = fmtwd;
    919 			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
    920 				FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
    921 			snprintf(p, buf + bufsize - p, fmt, t);
    922 			break;
    923 		case 'c':
    924 			if (isnum(x)) {
    925 				if (getfval(x))
    926 					snprintf(p, buf + bufsize - p, fmt, (int) getfval(x));
    927 				else {
    928 					*p++ = '\0'; /* explicit null byte */
    929 					*p = '\0';   /* next output will start here */
    930 				}
    931 			} else
    932 				snprintf(p, buf + bufsize - p, fmt, getsval(x)[0]);
    933 			break;
    934 		default:
    935 			FATAL("can't happen: bad conversion %c in format()", flag);
    936 		}
    937 		tempfree(x);
    938 		p += strlen(p);
    939 		s++;
    940 	}
    941 	*p = '\0';
    942 	free(fmt);
    943 	for ( ; a; a = a->nnext)		/* evaluate any remaining args */
    944 		execute(a);
    945 	*pbuf = buf;
    946 	*pbufsize = bufsize;
    947 	return p - buf;
    948 }
    949 
    950 Cell *awksprintf(Node **a, int n)		/* sprintf(a[0]) */
    951 {
    952 	Cell *x;
    953 	Node *y;
    954 	char *buf;
    955 	int bufsz=3*recsize;
    956 
    957 	if ((buf = (char *) malloc(bufsz)) == NULL)
    958 		FATAL("out of memory in awksprintf");
    959 	y = a[0]->nnext;
    960 	x = execute(a[0]);
    961 	if (format(&buf, &bufsz, getsval(x), y) == -1)
    962 		FATAL("sprintf string %.30s... too long.  can't happen.", buf);
    963 	tempfree(x);
    964 	x = gettemp();
    965 	x->sval = buf;
    966 	x->tval = STR;
    967 	return(x);
    968 }
    969 
    970 Cell *awkprintf(Node **a, int n)		/* printf */
    971 {	/* a[0] is list of args, starting with format string */
    972 	/* a[1] is redirection operator, a[2] is redirection file */
    973 	FILE *fp;
    974 	Cell *x;
    975 	Node *y;
    976 	char *buf;
    977 	int len;
    978 	int bufsz=3*recsize;
    979 
    980 	if ((buf = (char *) malloc(bufsz)) == NULL)
    981 		FATAL("out of memory in awkprintf");
    982 	y = a[0]->nnext;
    983 	x = execute(a[0]);
    984 	if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
    985 		FATAL("printf string %.30s... too long.  can't happen.", buf);
    986 	tempfree(x);
    987 	if (a[1] == NULL) {
    988 		/* fputs(buf, stdout); */
    989 		fwrite(buf, len, 1, stdout);
    990 		if (ferror(stdout))
    991 			FATAL("write error on stdout");
    992 	} else {
    993 		fp = redirect(ptoi(a[1]), a[2]);
    994 		/* fputs(buf, fp); */
    995 		fwrite(buf, len, 1, fp);
    996 		fflush(fp);
    997 		if (ferror(fp))
    998 			FATAL("write error on %s", filename(fp));
    999 	}
   1000 	free(buf);
   1001 	return(True);
   1002 }
   1003 
   1004 Cell *arith(Node **a, int n)	/* a[0] + a[1], etc.  also -a[0] */
   1005 {
   1006 	Awkfloat i, j = 0;
   1007 	double v;
   1008 	Cell *x, *y, *z;
   1009 
   1010 	x = execute(a[0]);
   1011 	i = getfval(x);
   1012 	tempfree(x);
   1013 	if (n != UMINUS) {
   1014 		y = execute(a[1]);
   1015 		j = getfval(y);
   1016 		tempfree(y);
   1017 	}
   1018 	z = gettemp();
   1019 	switch (n) {
   1020 	case ADD:
   1021 		i += j;
   1022 		break;
   1023 	case MINUS:
   1024 		i -= j;
   1025 		break;
   1026 	case MULT:
   1027 		i *= j;
   1028 		break;
   1029 	case DIVIDE:
   1030 		if (j == 0)
   1031 			FATAL("division by zero");
   1032 		i /= j;
   1033 		break;
   1034 	case MOD:
   1035 		if (j == 0)
   1036 			FATAL("division by zero in mod");
   1037 		modf(i/j, &v);
   1038 		i = i - j * v;
   1039 		break;
   1040 	case UMINUS:
   1041 		i = -i;
   1042 		break;
   1043 	case POWER:
   1044 		if (j >= 0 && modf(j, &v) == 0.0)	/* pos integer exponent */
   1045 			i = ipow(i, (int) j);
   1046 		else
   1047 			i = errcheck(pow(i, j), "pow");
   1048 		break;
   1049 	default:	/* can't happen */
   1050 		FATAL("illegal arithmetic operator %d", n);
   1051 	}
   1052 	setfval(z, i);
   1053 	return(z);
   1054 }
   1055 
   1056 double ipow(double x, int n)	/* x**n.  ought to be done by pow, but isn't always */
   1057 {
   1058 	double v;
   1059 
   1060 	if (n <= 0)
   1061 		return 1;
   1062 	v = ipow(x, n/2);
   1063 	if (n % 2 == 0)
   1064 		return v * v;
   1065 	else
   1066 		return x * v * v;
   1067 }
   1068 
   1069 Cell *incrdecr(Node **a, int n)		/* a[0]++, etc. */
   1070 {
   1071 	Cell *x, *z;
   1072 	int k;
   1073 	Awkfloat xf;
   1074 
   1075 	x = execute(a[0]);
   1076 	xf = getfval(x);
   1077 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
   1078 	if (n == PREINCR || n == PREDECR) {
   1079 		setfval(x, xf + k);
   1080 		return(x);
   1081 	}
   1082 	z = gettemp();
   1083 	setfval(z, xf);
   1084 	setfval(x, xf + k);
   1085 	tempfree(x);
   1086 	return(z);
   1087 }
   1088 
   1089 Cell *assign(Node **a, int n)	/* a[0] = a[1], a[0] += a[1], etc. */
   1090 {		/* this is subtle; don't muck with it. */
   1091 	Cell *x, *y;
   1092 	Awkfloat xf, yf;
   1093 	double v;
   1094 
   1095 	y = execute(a[1]);
   1096 	x = execute(a[0]);
   1097 	if (n == ASSIGN) {	/* ordinary assignment */
   1098 		if (x == y && !(x->tval & (FLD|REC)))	/* self-assignment: */
   1099 			;		/* leave alone unless it's a field */
   1100 		else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
   1101 			setsval(x, getsval(y));
   1102 			x->fval = getfval(y);
   1103 			x->tval |= NUM;
   1104 		}
   1105 		else if (isstr(y))
   1106 			setsval(x, getsval(y));
   1107 		else if (isnum(y))
   1108 			setfval(x, getfval(y));
   1109 		else
   1110 			funnyvar(y, "read value of");
   1111 		tempfree(y);
   1112 		return(x);
   1113 	}
   1114 	xf = getfval(x);
   1115 	yf = getfval(y);
   1116 	switch (n) {
   1117 	case ADDEQ:
   1118 		xf += yf;
   1119 		break;
   1120 	case SUBEQ:
   1121 		xf -= yf;
   1122 		break;
   1123 	case MULTEQ:
   1124 		xf *= yf;
   1125 		break;
   1126 	case DIVEQ:
   1127 		if (yf == 0)
   1128 			FATAL("division by zero in /=");
   1129 		xf /= yf;
   1130 		break;
   1131 	case MODEQ:
   1132 		if (yf == 0)
   1133 			FATAL("division by zero in %%=");
   1134 		modf(xf/yf, &v);
   1135 		xf = xf - yf * v;
   1136 		break;
   1137 	case POWEQ:
   1138 		if (yf >= 0 && modf(yf, &v) == 0.0)	/* pos integer exponent */
   1139 			xf = ipow(xf, (int) yf);
   1140 		else
   1141 			xf = errcheck(pow(xf, yf), "pow");
   1142 		break;
   1143 	default:
   1144 		FATAL("illegal assignment operator %d", n);
   1145 		break;
   1146 	}
   1147 	tempfree(y);
   1148 	setfval(x, xf);
   1149 	return(x);
   1150 }
   1151 
   1152 Cell *cat(Node **a, int q)	/* a[0] cat a[1] */
   1153 {
   1154 	Cell *x, *y, *z;
   1155 	int n1, n2;
   1156 	char *s;
   1157 	size_t len;
   1158 
   1159 	x = execute(a[0]);
   1160 	y = execute(a[1]);
   1161 	getsval(x);
   1162 	getsval(y);
   1163 	n1 = strlen(x->sval);
   1164 	n2 = strlen(y->sval);
   1165 	len = n1 + n2 + 1;
   1166 	s = (char *) malloc(len);
   1167 	if (s == NULL)
   1168 		FATAL("out of space concatenating %.15s... and %.15s...",
   1169 			x->sval, y->sval);
   1170 	strlcpy(s, x->sval, len);
   1171 	strlcpy(s+n1, y->sval, len - n1);
   1172 	tempfree(x);
   1173 	tempfree(y);
   1174 	z = gettemp();
   1175 	z->sval = s;
   1176 	z->tval = STR;
   1177 	return(z);
   1178 }
   1179 
   1180 Cell *pastat(Node **a, int n)	/* a[0] { a[1] } */
   1181 {
   1182 	Cell *x;
   1183 
   1184 	if (a[0] == 0)
   1185 		x = execute(a[1]);
   1186 	else {
   1187 		x = execute(a[0]);
   1188 		if (istrue(x)) {
   1189 			tempfree(x);
   1190 			x = execute(a[1]);
   1191 		}
   1192 	}
   1193 	return x;
   1194 }
   1195 
   1196 Cell *dopa2(Node **a, int n)	/* a[0], a[1] { a[2] } */
   1197 {
   1198 	Cell *x;
   1199 	int pair;
   1200 
   1201 	pair = ptoi(a[3]);
   1202 	if (pairstack[pair] == 0) {
   1203 		x = execute(a[0]);
   1204 		if (istrue(x))
   1205 			pairstack[pair] = 1;
   1206 		tempfree(x);
   1207 	}
   1208 	if (pairstack[pair] == 1) {
   1209 		x = execute(a[1]);
   1210 		if (istrue(x))
   1211 			pairstack[pair] = 0;
   1212 		tempfree(x);
   1213 		x = execute(a[2]);
   1214 		return(x);
   1215 	}
   1216 	return(False);
   1217 }
   1218 
   1219 Cell *split(Node **a, int nnn)	/* split(a[0], a[1], a[2]); a[3] is type */
   1220 {
   1221 	Cell *x = 0, *y, *ap;
   1222 	char *s;
   1223 	int sep;
   1224 	char *t, temp, num[50], *fs = 0;
   1225 	int n, tempstat, arg3type;
   1226 
   1227 	y = execute(a[0]);	/* source string */
   1228 	s = getsval(y);
   1229 	arg3type = ptoi(a[3]);
   1230 	if (a[2] == 0)		/* fs string */
   1231 		fs = *FS;
   1232 	else if (arg3type == STRING) {	/* split(str,arr,"string") */
   1233 		x = execute(a[2]);
   1234 		fs = getsval(x);
   1235 	} else if (arg3type == REGEXPR)
   1236 		fs = "(regexpr)";	/* split(str,arr,/regexpr/) */
   1237 	else
   1238 		FATAL("illegal type of split");
   1239 	sep = *fs;
   1240 	ap = execute(a[1]);	/* array name */
   1241 	freesymtab(ap);
   1242 	   dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
   1243 	ap->tval &= ~STR;
   1244 	ap->tval |= ARR;
   1245 	ap->sval = (char *) makesymtab(NSYMTAB);
   1246 
   1247 	n = 0;
   1248         if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
   1249 		/* split(s, a, //); have to arrange that it looks like empty sep */
   1250 		arg3type = 0;
   1251 		fs = "";
   1252 		sep = 0;
   1253 	}
   1254 	if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {	/* reg expr */
   1255 		fa *pfa;
   1256 		if (arg3type == REGEXPR) {	/* it's ready already */
   1257 			pfa = (fa *) a[2];
   1258 		} else {
   1259 			pfa = makedfa(fs, 1);
   1260 		}
   1261 		if (nematch(pfa,s)) {
   1262 			tempstat = pfa->initstat;
   1263 			pfa->initstat = 2;
   1264 			do {
   1265 				n++;
   1266 				snprintf(num, sizeof num, "%d", n);
   1267 				temp = *patbeg;
   1268 				*patbeg = '\0';
   1269 				if (is_number(s))
   1270 					setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
   1271 				else
   1272 					setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
   1273 				*patbeg = temp;
   1274 				s = patbeg + patlen;
   1275 				if (*(patbeg+patlen-1) == 0 || *s == 0) {
   1276 					n++;
   1277 					snprintf(num, sizeof num, "%d", n);
   1278 					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
   1279 					pfa->initstat = tempstat;
   1280 					goto spdone;
   1281 				}
   1282 			} while (nematch(pfa,s));
   1283 			pfa->initstat = tempstat; 	/* bwk: has to be here to reset */
   1284 							/* cf gsub and refldbld */
   1285 		}
   1286 		n++;
   1287 		snprintf(num, sizeof num, "%d", n);
   1288 		if (is_number(s))
   1289 			setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
   1290 		else
   1291 			setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
   1292   spdone:
   1293 		pfa = NULL;
   1294 	} else if (sep == ' ') {
   1295 		for (n = 0; ; ) {
   1296 			while (*s == ' ' || *s == '\t' || *s == '\n')
   1297 				s++;
   1298 			if (*s == 0)
   1299 				break;
   1300 			n++;
   1301 			t = s;
   1302 			do
   1303 				s++;
   1304 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
   1305 			temp = *s;
   1306 			*s = '\0';
   1307 			snprintf(num, sizeof num, "%d", n);
   1308 			if (is_number(t))
   1309 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
   1310 			else
   1311 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
   1312 			*s = temp;
   1313 			if (*s != 0)
   1314 				s++;
   1315 		}
   1316 	} else if (sep == 0) {	/* new: split(s, a, "") => 1 char/elem */
   1317 		for (n = 0; *s != 0; s++) {
   1318 			char buf[2];
   1319 			n++;
   1320 			snprintf(num, sizeof num, "%d", n);
   1321 			buf[0] = *s;
   1322 			buf[1] = 0;
   1323 			if (isdigit((uschar)buf[0]))
   1324 				setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
   1325 			else
   1326 				setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
   1327 		}
   1328 	} else if (*s != 0) {
   1329 		for (;;) {
   1330 			n++;
   1331 			t = s;
   1332 			while (*s != sep && *s != '\n' && *s != '\0')
   1333 				s++;
   1334 			temp = *s;
   1335 			*s = '\0';
   1336 			snprintf(num, sizeof num, "%d", n);
   1337 			if (is_number(t))
   1338 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
   1339 			else
   1340 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
   1341 			*s = temp;
   1342 			if (*s++ == 0)
   1343 				break;
   1344 		}
   1345 	}
   1346 	tempfree(ap);
   1347 	tempfree(y);
   1348 	if (a[2] != 0 && arg3type == STRING) {
   1349 		tempfree(x);
   1350 	}
   1351 	x = gettemp();
   1352 	x->tval = NUM;
   1353 	x->fval = n;
   1354 	return(x);
   1355 }
   1356 
   1357 Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
   1358 {
   1359 	Cell *x;
   1360 
   1361 	x = execute(a[0]);
   1362 	if (istrue(x)) {
   1363 		tempfree(x);
   1364 		x = execute(a[1]);
   1365 	} else {
   1366 		tempfree(x);
   1367 		x = execute(a[2]);
   1368 	}
   1369 	return(x);
   1370 }
   1371 
   1372 Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
   1373 {
   1374 	Cell *x;
   1375 
   1376 	x = execute(a[0]);
   1377 	if (istrue(x)) {
   1378 		tempfree(x);
   1379 		x = execute(a[1]);
   1380 	} else if (a[2] != 0) {
   1381 		tempfree(x);
   1382 		x = execute(a[2]);
   1383 	}
   1384 	return(x);
   1385 }
   1386 
   1387 Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
   1388 {
   1389 	Cell *x;
   1390 
   1391 	for (;;) {
   1392 		x = execute(a[0]);
   1393 		if (!istrue(x))
   1394 			return(x);
   1395 		tempfree(x);
   1396 		x = execute(a[1]);
   1397 		if (isbreak(x)) {
   1398 			x = True;
   1399 			return(x);
   1400 		}
   1401 		if (isnext(x) || isexit(x) || isret(x))
   1402 			return(x);
   1403 		tempfree(x);
   1404 	}
   1405 }
   1406 
   1407 Cell *dostat(Node **a, int n)	/* do a[0]; while(a[1]) */
   1408 {
   1409 	Cell *x;
   1410 
   1411 	for (;;) {
   1412 		x = execute(a[0]);
   1413 		if (isbreak(x))
   1414 			return True;
   1415 		if (isnext(x) || isexit(x) || isret(x))
   1416 			return(x);
   1417 		tempfree(x);
   1418 		x = execute(a[1]);
   1419 		if (!istrue(x))
   1420 			return(x);
   1421 		tempfree(x);
   1422 	}
   1423 }
   1424 
   1425 Cell *forstat(Node **a, int n)	/* for (a[0]; a[1]; a[2]) a[3] */
   1426 {
   1427 	Cell *x;
   1428 
   1429 	x = execute(a[0]);
   1430 	tempfree(x);
   1431 	for (;;) {
   1432 		if (a[1]!=0) {
   1433 			x = execute(a[1]);
   1434 			if (!istrue(x)) return(x);
   1435 			else tempfree(x);
   1436 		}
   1437 		x = execute(a[3]);
   1438 		if (isbreak(x))		/* turn off break */
   1439 			return True;
   1440 		if (isnext(x) || isexit(x) || isret(x))
   1441 			return(x);
   1442 		tempfree(x);
   1443 		x = execute(a[2]);
   1444 		tempfree(x);
   1445 	}
   1446 }
   1447 
   1448 Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
   1449 {
   1450 	Cell *x, *vp, *arrayp, *cp, *ncp;
   1451 	Array *tp;
   1452 	int i;
   1453 
   1454 	vp = execute(a[0]);
   1455 	arrayp = execute(a[1]);
   1456 	if (!isarr(arrayp)) {
   1457 		return True;
   1458 	}
   1459 	tp = (Array *) arrayp->sval;
   1460 	tempfree(arrayp);
   1461 	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
   1462 		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
   1463 			setsval(vp, cp->nval);
   1464 			ncp = cp->cnext;
   1465 			x = execute(a[2]);
   1466 			if (isbreak(x)) {
   1467 				tempfree(vp);
   1468 				return True;
   1469 			}
   1470 			if (isnext(x) || isexit(x) || isret(x)) {
   1471 				tempfree(vp);
   1472 				return(x);
   1473 			}
   1474 			tempfree(x);
   1475 		}
   1476 	}
   1477 	return True;
   1478 }
   1479 
   1480 Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
   1481 {
   1482 	Cell *x, *y;
   1483 	Awkfloat u;
   1484 	int t;
   1485 	Awkfloat tmp;
   1486 	char *p, *buf;
   1487 	Node *nextarg;
   1488 	FILE *fp;
   1489 
   1490 	t = ptoi(a[0]);
   1491 	x = execute(a[1]);
   1492 	nextarg = a[1]->nnext;
   1493 	switch (t) {
   1494 	case FLENGTH:
   1495 		if (isarr(x))
   1496 			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
   1497 		else
   1498 			u = strlen(getsval(x));
   1499 		break;
   1500 	case FLOG:
   1501 		u = errcheck(log(getfval(x)), "log"); break;
   1502 	case FINT:
   1503 		modf(getfval(x), &u); break;
   1504 	case FEXP:
   1505 		u = errcheck(exp(getfval(x)), "exp"); break;
   1506 	case FSQRT:
   1507 		u = errcheck(sqrt(getfval(x)), "sqrt"); break;
   1508 	case FSIN:
   1509 		u = sin(getfval(x)); break;
   1510 	case FCOS:
   1511 		u = cos(getfval(x)); break;
   1512 	case FATAN:
   1513 		if (nextarg == 0) {
   1514 			WARNING("atan2 requires two arguments; returning 1.0");
   1515 			u = 1.0;
   1516 		} else {
   1517 			y = execute(a[1]->nnext);
   1518 			u = atan2(getfval(x), getfval(y));
   1519 			tempfree(y);
   1520 			nextarg = nextarg->nnext;
   1521 		}
   1522 		break;
   1523 	case FCOMPL:
   1524 		u = ~((int)getfval(x));
   1525 		break;
   1526 	case FAND:
   1527 		if (nextarg == 0) {
   1528 			WARNING("and requires two arguments; returning 0");
   1529 			u = 0;
   1530 			break;
   1531 		}
   1532 		y = execute(a[1]->nnext);
   1533 		u = ((int)getfval(x)) & ((int)getfval(y));
   1534 		tempfree(y);
   1535 		nextarg = nextarg->nnext;
   1536 		break;
   1537 	case FFOR:
   1538 		if (nextarg == 0) {
   1539 			WARNING("or requires two arguments; returning 0");
   1540 			u = 0;
   1541 			break;
   1542 		}
   1543 		y = execute(a[1]->nnext);
   1544 		u = ((int)getfval(x)) | ((int)getfval(y));
   1545 		tempfree(y);
   1546 		nextarg = nextarg->nnext;
   1547 		break;
   1548 	case FXOR:
   1549 		if (nextarg == 0) {
   1550 			WARNING("or requires two arguments; returning 0");
   1551 			u = 0;
   1552 			break;
   1553 		}
   1554 		y = execute(a[1]->nnext);
   1555 		u = ((int)getfval(x)) ^ ((int)getfval(y));
   1556 		tempfree(y);
   1557 		nextarg = nextarg->nnext;
   1558 		break;
   1559 	case FLSHIFT:
   1560 		if (nextarg == 0) {
   1561 			WARNING("or requires two arguments; returning 0");
   1562 			u = 0;
   1563 			break;
   1564 		}
   1565 		y = execute(a[1]->nnext);
   1566 		u = ((int)getfval(x)) << ((int)getfval(y));
   1567 		tempfree(y);
   1568 		nextarg = nextarg->nnext;
   1569 		break;
   1570 	case FRSHIFT:
   1571 		if (nextarg == 0) {
   1572 			WARNING("or requires two arguments; returning 0");
   1573 			u = 0;
   1574 			break;
   1575 		}
   1576 		y = execute(a[1]->nnext);
   1577 		u = ((int)getfval(x)) >> ((int)getfval(y));
   1578 		tempfree(y);
   1579 		nextarg = nextarg->nnext;
   1580 		break;
   1581 	case FSYSTEM:
   1582 		fflush(stdout);		/* in case something is buffered already */
   1583 		u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
   1584 		break;
   1585 	case FRAND:
   1586 		if (use_srandom)
   1587 			u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;
   1588 		else
   1589 			u = (Awkfloat)arc4random() / 0xffffffff;
   1590 		break;
   1591 	case FSRAND:
   1592 		if (isrec(x))	/* no argument provided, want arc4random() */
   1593 			use_srandom = 0;
   1594 		else {
   1595 			use_srandom = 1;
   1596 			u = getfval(x);
   1597 			tmp = u;
   1598 			srandom((unsigned int) u);
   1599 			u = srand_seed;
   1600 			srand_seed = tmp;
   1601 		}
   1602 		break;
   1603 	case FTOUPPER:
   1604 	case FTOLOWER:
   1605 		buf = tostring(getsval(x));
   1606 		if (t == FTOUPPER) {
   1607 			for (p = buf; *p; p++)
   1608 				if (islower((uschar) *p))
   1609 					*p = toupper((uschar)*p);
   1610 		} else {
   1611 			for (p = buf; *p; p++)
   1612 				if (isupper((uschar) *p))
   1613 					*p = tolower((uschar)*p);
   1614 		}
   1615 		tempfree(x);
   1616 		x = gettemp();
   1617 		setsval(x, buf);
   1618 		free(buf);
   1619 		return x;
   1620 	case FFLUSH:
   1621 		if (isrec(x) || strlen(getsval(x)) == 0) {
   1622 			flush_all();	/* fflush() or fflush("") -> all */
   1623 			u = 0;
   1624 		} else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
   1625 			u = EOF;
   1626 		else
   1627 			u = fflush(fp);
   1628 		break;
   1629 	default:	/* can't happen */
   1630 		FATAL("illegal function type %d", t);
   1631 		break;
   1632 	}
   1633 	tempfree(x);
   1634 	x = gettemp();
   1635 	setfval(x, u);
   1636 	if (nextarg != 0) {
   1637 		WARNING("warning: function has too many arguments");
   1638 		for ( ; nextarg; nextarg = nextarg->nnext)
   1639 			execute(nextarg);
   1640 	}
   1641 	return(x);
   1642 }
   1643 
   1644 Cell *printstat(Node **a, int n)	/* print a[0] */
   1645 {
   1646 	Node *x;
   1647 	Cell *y;
   1648 	FILE *fp;
   1649 
   1650 	if (a[1] == 0)	/* a[1] is redirection operator, a[2] is file */
   1651 		fp = stdout;
   1652 	else
   1653 		fp = redirect(ptoi(a[1]), a[2]);
   1654 	for (x = a[0]; x != NULL; x = x->nnext) {
   1655 		y = execute(x);
   1656 		fputs(getpssval(y), fp);
   1657 		tempfree(y);
   1658 		if (x->nnext == NULL)
   1659 			fputs(*ORS, fp);
   1660 		else
   1661 			fputs(*OFS, fp);
   1662 	}
   1663 	if (a[1] != 0)
   1664 		fflush(fp);
   1665 	if (ferror(fp))
   1666 		FATAL("write error on %s", filename(fp));
   1667 	return(True);
   1668 }
   1669 
   1670 Cell *nullproc(Node **a, int n)
   1671 {
   1672 	n = n;
   1673 	a = a;
   1674 	return 0;
   1675 }
   1676 
   1677 
   1678 FILE *redirect(int a, Node *b)	/* set up all i/o redirections */
   1679 {
   1680 	FILE *fp;
   1681 	Cell *x;
   1682 	char *fname;
   1683 
   1684 	x = execute(b);
   1685 	fname = getsval(x);
   1686 	fp = openfile(a, fname);
   1687 	if (fp == NULL)
   1688 		FATAL("can't open file %s", fname);
   1689 	tempfree(x);
   1690 	return fp;
   1691 }
   1692 
   1693 struct files {
   1694 	FILE	*fp;
   1695 	const char	*fname;
   1696 	int	mode;	/* '|', 'a', 'w' => LE/LT, GT */
   1697 } *files;
   1698 
   1699 int nfiles;
   1700 
   1701 void stdinit(void)	/* in case stdin, etc., are not constants */
   1702 {
   1703 	nfiles = FOPEN_MAX;
   1704 	files = calloc(nfiles, sizeof(*files));
   1705 	if (files == NULL)
   1706 		FATAL("can't allocate file memory for %u files", nfiles);
   1707         files[0].fp = stdin;
   1708 	files[0].fname = "/dev/stdin";
   1709 	files[0].mode = LT;
   1710         files[1].fp = stdout;
   1711 	files[1].fname = "/dev/stdout";
   1712 	files[1].mode = GT;
   1713         files[2].fp = stderr;
   1714 	files[2].fname = "/dev/stderr";
   1715 	files[2].mode = GT;
   1716 }
   1717 
   1718 FILE *openfile(int a, const char *us)
   1719 {
   1720 	const char *s = us;
   1721 	int i, m;
   1722 	FILE *fp = 0;
   1723 
   1724 	if (*s == '\0')
   1725 		FATAL("null file name in print or getline");
   1726 	for (i=0; i < nfiles; i++)
   1727 		if (files[i].fname && strcmp(s, files[i].fname) == 0) {
   1728 			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
   1729 				return files[i].fp;
   1730 			if (a == FFLUSH)
   1731 				return files[i].fp;
   1732 		}
   1733 	if (a == FFLUSH)	/* didn't find it, so don't create it! */
   1734 		return NULL;
   1735 
   1736 	for (i=0; i < nfiles; i++)
   1737 		if (files[i].fp == 0)
   1738 			break;
   1739 	if (i >= nfiles) {
   1740 		struct files *nf;
   1741 		int nnf = nfiles + FOPEN_MAX;
   1742 		nf = reallocarray(files, nnf, sizeof(*nf));
   1743 		if (nf == NULL)
   1744 			FATAL("cannot grow files for %s and %d files", s, nnf);
   1745 		memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
   1746 		nfiles = nnf;
   1747 		files = nf;
   1748 	}
   1749 	fflush(stdout);	/* force a semblance of order */
   1750 	m = a;
   1751 	if (a == GT) {
   1752 		fp = fopen(s, "w");
   1753 	} else if (a == APPEND) {
   1754 		fp = fopen(s, "a");
   1755 		m = GT;	/* so can mix > and >> */
   1756 	} else if (a == '|') {	/* output pipe */
   1757 		fp = popen(s, "w");
   1758 	} else if (a == LE) {	/* input pipe */
   1759 		fp = popen(s, "r");
   1760 	} else if (a == LT) {	/* getline <file */
   1761 		fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r");	/* "-" is stdin */
   1762 	} else	/* can't happen */
   1763 		FATAL("illegal redirection %d", a);
   1764 	if (fp != NULL) {
   1765 		files[i].fname = tostring(s);
   1766 		files[i].fp = fp;
   1767 		files[i].mode = m;
   1768 	}
   1769 	return fp;
   1770 }
   1771 
   1772 const char *filename(FILE *fp)
   1773 {
   1774 	int i;
   1775 
   1776 	for (i = 0; i < nfiles; i++)
   1777 		if (fp == files[i].fp)
   1778 			return files[i].fname;
   1779 	return "???";
   1780 }
   1781 
   1782 Cell *closefile(Node **a, int n)
   1783 {
   1784 	Cell *x;
   1785 	int i, stat;
   1786 
   1787 	n = n;
   1788 	x = execute(a[0]);
   1789 	getsval(x);
   1790 	stat = -1;
   1791 	for (i = 0; i < nfiles; i++) {
   1792 		if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
   1793 			if (ferror(files[i].fp))
   1794 				WARNING( "i/o error occurred on %s", files[i].fname );
   1795 			if (files[i].mode == '|' || files[i].mode == LE)
   1796 				stat = pclose(files[i].fp);
   1797 			else
   1798 				stat = fclose(files[i].fp);
   1799 			if (stat == EOF)
   1800 				WARNING( "i/o error occurred closing %s", files[i].fname );
   1801 			if (i > 2)	/* don't do /dev/std... */
   1802 				xfree(files[i].fname);
   1803 			files[i].fname = NULL;	/* watch out for ref thru this */
   1804 			files[i].fp = NULL;
   1805 		}
   1806 	}
   1807 	tempfree(x);
   1808 	x = gettemp();
   1809 	setfval(x, (Awkfloat) stat);
   1810 	return(x);
   1811 }
   1812 
   1813 void closeall(void)
   1814 {
   1815 	int i, stat;
   1816 
   1817 	for (i = 0; i < FOPEN_MAX; i++) {
   1818 		if (files[i].fp) {
   1819 			if (ferror(files[i].fp))
   1820 				WARNING( "i/o error occurred on %s", files[i].fname );
   1821 			if (files[i].mode == '|' || files[i].mode == LE)
   1822 				stat = pclose(files[i].fp);
   1823 			else
   1824 				stat = fclose(files[i].fp);
   1825 			if (stat == EOF)
   1826 				WARNING( "i/o error occurred while closing %s", files[i].fname );
   1827 		}
   1828 	}
   1829 }
   1830 
   1831 void flush_all(void)
   1832 {
   1833 	int i;
   1834 
   1835 	for (i = 0; i < nfiles; i++)
   1836 		if (files[i].fp)
   1837 			fflush(files[i].fp);
   1838 }
   1839 
   1840 void backsub(char **pb_ptr, char **sptr_ptr);
   1841 
   1842 Cell *sub(Node **a, int nnn)	/* substitute command */
   1843 {
   1844 	char *sptr, *pb, *q;
   1845 	Cell *x, *y, *result;
   1846 	char *t, *buf;
   1847 	fa *pfa;
   1848 	int bufsz = recsize;
   1849 
   1850 	if ((buf = (char *) malloc(bufsz)) == NULL)
   1851 		FATAL("out of memory in sub");
   1852 	x = execute(a[3]);	/* target string */
   1853 	t = getsval(x);
   1854 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
   1855 		pfa = (fa *) a[1];	/* regular expression */
   1856 	else {
   1857 		y = execute(a[1]);
   1858 		pfa = makedfa(getsval(y), 1);
   1859 		tempfree(y);
   1860 	}
   1861 	y = execute(a[2]);	/* replacement string */
   1862 	result = False;
   1863 	if (pmatch(pfa, t)) {
   1864 		sptr = t;
   1865 		adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
   1866 		pb = buf;
   1867 		while (sptr < patbeg)
   1868 			*pb++ = *sptr++;
   1869 		sptr = getsval(y);
   1870 		while (*sptr != 0) {
   1871 			adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
   1872 			if (*sptr == '\\') {
   1873 				backsub(&pb, &sptr);
   1874 			} else if (*sptr == '&') {
   1875 				sptr++;
   1876 				adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
   1877 				for (q = patbeg; q < patbeg+patlen; )
   1878 					*pb++ = *q++;
   1879 			} else
   1880 				*pb++ = *sptr++;
   1881 		}
   1882 		*pb = '\0';
   1883 		if (pb > buf + bufsz)
   1884 			FATAL("sub result1 %.30s too big; can't happen", buf);
   1885 		sptr = patbeg + patlen;
   1886 		if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
   1887 			adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
   1888 			while ((*pb++ = *sptr++) != 0)
   1889 				;
   1890 		}
   1891 		if (pb > buf + bufsz)
   1892 			FATAL("sub result2 %.30s too big; can't happen", buf);
   1893 		setsval(x, buf);	/* BUG: should be able to avoid copy */
   1894 		result = True;
   1895 	}
   1896 	tempfree(x);
   1897 	tempfree(y);
   1898 	free(buf);
   1899 	return result;
   1900 }
   1901 
   1902 Cell *gsub(Node **a, int nnn)	/* global substitute */
   1903 {
   1904 	Cell *x, *y;
   1905 	char *rptr, *sptr, *t, *pb, *q;
   1906 	char *buf;
   1907 	fa *pfa;
   1908 	int mflag, tempstat, num;
   1909 	int bufsz = recsize;
   1910 
   1911 	if ((buf = (char *) malloc(bufsz)) == NULL)
   1912 		FATAL("out of memory in gsub");
   1913 	mflag = 0;	/* if mflag == 0, can replace empty string */
   1914 	num = 0;
   1915 	x = execute(a[3]);	/* target string */
   1916 	t = getsval(x);
   1917 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
   1918 		pfa = (fa *) a[1];	/* regular expression */
   1919 	else {
   1920 		y = execute(a[1]);
   1921 		pfa = makedfa(getsval(y), 1);
   1922 		tempfree(y);
   1923 	}
   1924 	y = execute(a[2]);	/* replacement string */
   1925 	if (pmatch(pfa, t)) {
   1926 		tempstat = pfa->initstat;
   1927 		pfa->initstat = 2;
   1928 		pb = buf;
   1929 		rptr = getsval(y);
   1930 		do {
   1931 			if (patlen == 0 && *patbeg != 0) {	/* matched empty string */
   1932 				if (mflag == 0) {	/* can replace empty */
   1933 					num++;
   1934 					sptr = rptr;
   1935 					while (*sptr != 0) {
   1936 						adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
   1937 						if (*sptr == '\\') {
   1938 							backsub(&pb, &sptr);
   1939 						} else if (*sptr == '&') {
   1940 							sptr++;
   1941 							adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
   1942 							for (q = patbeg; q < patbeg+patlen; )
   1943 								*pb++ = *q++;
   1944 						} else
   1945 							*pb++ = *sptr++;
   1946 					}
   1947 				}
   1948 				if (*t == 0)	/* at end */
   1949 					goto done;
   1950 				adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
   1951 				*pb++ = *t++;
   1952 				if (pb > buf + bufsz)	/* BUG: not sure of this test */
   1953 					FATAL("gsub result0 %.30s too big; can't happen", buf);
   1954 				mflag = 0;
   1955 			}
   1956 			else {	/* matched nonempty string */
   1957 				num++;
   1958 				sptr = t;
   1959 				adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
   1960 				while (sptr < patbeg)
   1961 					*pb++ = *sptr++;
   1962 				sptr = rptr;
   1963 				while (*sptr != 0) {
   1964 					adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
   1965 					if (*sptr == '\\') {
   1966 						backsub(&pb, &sptr);
   1967 					} else if (*sptr == '&') {
   1968 						sptr++;
   1969 						adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
   1970 						for (q = patbeg; q < patbeg+patlen; )
   1971 							*pb++ = *q++;
   1972 					} else
   1973 						*pb++ = *sptr++;
   1974 				}
   1975 				t = patbeg + patlen;
   1976 				if (patlen == 0 || *t == 0 || *(t-1) == 0)
   1977 					goto done;
   1978 				if (pb > buf + bufsz)
   1979 					FATAL("gsub result1 %.30s too big; can't happen", buf);
   1980 				mflag = 1;
   1981 			}
   1982 		} while (pmatch(pfa,t));
   1983 		sptr = t;
   1984 		adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
   1985 		while ((*pb++ = *sptr++) != 0)
   1986 			;
   1987 	done:	if (pb < buf + bufsz)
   1988 			*pb = '\0';
   1989 		else if (*(pb-1) != '\0')
   1990 			FATAL("gsub result2 %.30s truncated; can't happen", buf);
   1991 		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
   1992 		pfa->initstat = tempstat;
   1993 	}
   1994 	tempfree(x);
   1995 	tempfree(y);
   1996 	x = gettemp();
   1997 	x->tval = NUM;
   1998 	x->fval = num;
   1999 	free(buf);
   2000 	return(x);
   2001 }
   2002 
   2003 void backsub(char **pb_ptr, char **sptr_ptr)	/* handle \\& variations */
   2004 {						/* sptr[0] == '\\' */
   2005 	char *pb = *pb_ptr, *sptr = *sptr_ptr;
   2006 
   2007 	if (sptr[1] == '\\') {
   2008 		if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
   2009 			*pb++ = '\\';
   2010 			*pb++ = '&';
   2011 			sptr += 4;
   2012 		} else if (sptr[2] == '&') {	/* \\& -> \ + matched */
   2013 			*pb++ = '\\';
   2014 			sptr += 2;
   2015 		} else {			/* \\x -> \\x */
   2016 			*pb++ = *sptr++;
   2017 			*pb++ = *sptr++;
   2018 		}
   2019 	} else if (sptr[1] == '&') {	/* literal & */
   2020 		sptr++;
   2021 		*pb++ = *sptr++;
   2022 	} else				/* literal \ */
   2023 		*pb++ = *sptr++;
   2024 
   2025 	*pb_ptr = pb;
   2026 	*sptr_ptr = sptr;
   2027 }