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