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