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