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