xref: /openbsd/usr.bin/awk/run.c (revision 91f110e0)
1 /*	$OpenBSD: run.c,v 1.34 2013/09/29 15:42:25 deraadt 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 int use_srandom;
70 extern	int	pairstack[];
71 extern	Awkfloat	srand_seed;
72 
73 Node	*winner = NULL;	/* root of parse tree */
74 Cell	*tmps;		/* free temporary cells for execution */
75 
76 static Cell	truecell	={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
77 Cell	*True	= &truecell;
78 static Cell	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
79 Cell	*False	= &falsecell;
80 static Cell	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
81 Cell	*jbreak	= &breakcell;
82 static Cell	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM };
83 Cell	*jcont	= &contcell;
84 static Cell	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
85 Cell	*jnext	= &nextcell;
86 static Cell	nextfilecell	={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
87 Cell	*jnextfile	= &nextfilecell;
88 static Cell	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
89 Cell	*jexit	= &exitcell;
90 static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM };
91 Cell	*jret	= &retcell;
92 static Cell	tempcell	={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
93 
94 Node	*curnode = NULL;	/* the node being executed, for debugging */
95 
96 void	stdinit(void);
97 void	flush_all(void);
98 
99 /* buffer memory management */
100 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
101 	const char *whatrtn)
102 /* pbuf:    address of pointer to buffer being managed
103  * psiz:    address of buffer size variable
104  * minlen:  minimum length of buffer needed
105  * quantum: buffer size quantum
106  * pbptr:   address of movable pointer into buffer, or 0 if none
107  * whatrtn: name of the calling routine if failure should cause fatal error
108  *
109  * return   0 for realloc failure, !=0 for success
110  */
111 {
112 	if (minlen > *psiz) {
113 		char *tbuf;
114 		int rminlen = quantum ? minlen % quantum : 0;
115 		int boff = pbptr ? *pbptr - *pbuf : 0;
116 		/* round up to next multiple of quantum */
117 		if (rminlen)
118 			minlen += quantum - rminlen;
119 		tbuf = (char *) realloc(*pbuf, minlen);
120 		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
121 		if (tbuf == NULL) {
122 			if (whatrtn)
123 				FATAL("out of memory in %s", whatrtn);
124 			return 0;
125 		}
126 		*pbuf = tbuf;
127 		*psiz = minlen;
128 		if (pbptr)
129 			*pbptr = tbuf + boff;
130 	}
131 	return 1;
132 }
133 
134 void run(Node *a)	/* execution of parse tree starts here */
135 {
136 	stdinit();
137 	execute(a);
138 	closeall();
139 }
140 
141 Cell *execute(Node *u)	/* execute a node of the parse tree */
142 {
143 	Cell *(*proc)(Node **, int);
144 	Cell *x;
145 	Node *a;
146 
147 	if (u == NULL)
148 		return(True);
149 	for (a = u; ; a = a->nnext) {
150 		curnode = a;
151 		if (isvalue(a)) {
152 			x = (Cell *) (a->narg[0]);
153 			if (isfld(x) && !donefld)
154 				fldbld();
155 			else if (isrec(x) && !donerec)
156 				recbld();
157 			return(x);
158 		}
159 		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
160 			FATAL("illegal statement");
161 		proc = proctab[a->nobj-FIRSTTOKEN];
162 		x = (*proc)(a->narg, a->nobj);
163 		if (isfld(x) && !donefld)
164 			fldbld();
165 		else if (isrec(x) && !donerec)
166 			recbld();
167 		if (isexpr(a))
168 			return(x);
169 		if (isjump(x))
170 			return(x);
171 		if (a->nnext == NULL)
172 			return(x);
173 		tempfree(x);
174 	}
175 }
176 
177 
178 Cell *program(Node **a, int n)	/* execute an awk program */
179 {				/* a[0] = BEGIN, a[1] = body, a[2] = END */
180 	Cell *x;
181 
182 	if (setjmp(env) != 0)
183 		goto ex;
184 	if (a[0]) {		/* BEGIN */
185 		x = execute(a[0]);
186 		if (isexit(x))
187 			return(True);
188 		if (isjump(x))
189 			FATAL("illegal break, continue, next or nextfile from BEGIN");
190 		tempfree(x);
191 	}
192 	if (a[1] || a[2])
193 		while (getrec(&record, &recsize, 1) > 0) {
194 			x = execute(a[1]);
195 			if (isexit(x))
196 				break;
197 			tempfree(x);
198 		}
199   ex:
200 	if (setjmp(env) != 0)	/* handles exit within END */
201 		goto ex1;
202 	if (a[2]) {		/* END */
203 		x = execute(a[2]);
204 		if (isbreak(x) || isnext(x) || iscont(x))
205 			FATAL("illegal break, continue, next or nextfile from END");
206 		tempfree(x);
207 	}
208   ex1:
209 	return(True);
210 }
211 
212 struct Frame {	/* stack frame for awk function calls */
213 	int nargs;	/* number of arguments in this call */
214 	Cell *fcncell;	/* pointer to Cell for function */
215 	Cell **args;	/* pointer to array of arguments after execute */
216 	Cell *retval;	/* return value */
217 };
218 
219 #define	NARGS	50	/* max args in a call */
220 
221 struct Frame *frame = NULL;	/* base of stack frames; dynamically allocated */
222 int	nframe = 0;		/* number of frames allocated */
223 struct Frame *fp = NULL;	/* frame pointer. bottom level unused */
224 
225 Cell *call(Node **a, int n)	/* function call.  very kludgy and fragile */
226 {
227 	static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
228 	int i, ncall, ndef;
229 	int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
230 	Node *x;
231 	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
232 	Cell *y, *z, *fcn;
233 	char *s;
234 
235 	fcn = execute(a[0]);	/* the function itself */
236 	s = fcn->nval;
237 	if (!isfcn(fcn))
238 		FATAL("calling undefined function %s", s);
239 	if (frame == NULL) {
240 		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
241 		if (frame == NULL)
242 			FATAL("out of space for stack frames calling %s", s);
243 	}
244 	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
245 		ncall++;
246 	ndef = (int) fcn->fval;			/* args in defn */
247 	   dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
248 	if (ncall > ndef)
249 		WARNING("function %s called with %d args, uses only %d",
250 			s, ncall, ndef);
251 	if (ncall + ndef > NARGS)
252 		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
253 	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
254 		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
255 		y = execute(x);
256 		oargs[i] = y;
257 		   dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
258 			   i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
259 		if (isfcn(y))
260 			FATAL("can't use function %s as argument in %s", y->nval, s);
261 		if (isarr(y))
262 			args[i] = y;	/* arrays by ref */
263 		else
264 			args[i] = copycell(y);
265 		tempfree(y);
266 	}
267 	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
268 		args[i] = gettemp();
269 		*args[i] = newcopycell;
270 	}
271 	fp++;	/* now ok to up frame */
272 	if (fp >= frame + nframe) {
273 		int dfp = fp - frame;	/* old index */
274 		frame = (struct Frame *)
275 			realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
276 		if (frame == NULL)
277 			FATAL("out of space for stack frames in %s", s);
278 		fp = frame + dfp;
279 	}
280 	fp->fcncell = fcn;
281 	fp->args = args;
282 	fp->nargs = ndef;	/* number defined with (excess are locals) */
283 	fp->retval = gettemp();
284 
285 	   dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
286 	y = execute((Node *)(fcn->sval));	/* execute body */
287 	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
288 
289 	for (i = 0; i < ndef; i++) {
290 		Cell *t = fp->args[i];
291 		if (isarr(t)) {
292 			if (t->csub == CCOPY) {
293 				if (i >= ncall) {
294 					freesymtab(t);
295 					t->csub = CTEMP;
296 					tempfree(t);
297 				} else {
298 					oargs[i]->tval = t->tval;
299 					oargs[i]->tval &= ~(STR|NUM|DONTFREE);
300 					oargs[i]->sval = t->sval;
301 					tempfree(t);
302 				}
303 			}
304 		} else if (t != y) {	/* kludge to prevent freeing twice */
305 			t->csub = CTEMP;
306 			tempfree(t);
307 		} else if (t == y && t->csub == CCOPY) {
308 			t->csub = CTEMP;
309 			tempfree(t);
310 			freed = 1;
311 		}
312 	}
313 	tempfree(fcn);
314 	if (isexit(y) || isnext(y))
315 		return y;
316 	if (freed == 0) {
317 		tempfree(y);	/* don't free twice! */
318 	}
319 	z = fp->retval;			/* return value */
320 	   dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
321 	fp--;
322 	return(z);
323 }
324 
325 Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */
326 {
327 	Cell *y;
328 
329 	y = gettemp();
330 	y->csub = CCOPY;	/* prevents freeing until call is over */
331 	y->nval = x->nval;	/* BUG? */
332 	if (isstr(x))
333 		y->sval = tostring(x->sval);
334 	y->fval = x->fval;
335 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
336 							/* is DONTFREE right? */
337 	return y;
338 }
339 
340 Cell *arg(Node **a, int n)	/* nth argument of a function */
341 {
342 
343 	n = ptoi(a[0]);	/* argument number, counting from 0 */
344 	   dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
345 	if (n+1 > fp->nargs)
346 		FATAL("argument #%d of function %s was not supplied",
347 			n+1, fp->fcncell->nval);
348 	return fp->args[n];
349 }
350 
351 Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */
352 {
353 	Cell *y;
354 
355 	switch (n) {
356 	case EXIT:
357 		if (a[0] != NULL) {
358 			y = execute(a[0]);
359 			errorflag = (int) getfval(y);
360 			tempfree(y);
361 		}
362 		longjmp(env, 1);
363 	case RETURN:
364 		if (a[0] != NULL) {
365 			y = execute(a[0]);
366 			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
367 				setsval(fp->retval, getsval(y));
368 				fp->retval->fval = getfval(y);
369 				fp->retval->tval |= NUM;
370 			}
371 			else if (y->tval & STR)
372 				setsval(fp->retval, getsval(y));
373 			else if (y->tval & NUM)
374 				setfval(fp->retval, getfval(y));
375 			else		/* can't happen */
376 				FATAL("bad type variable %d", y->tval);
377 			tempfree(y);
378 		}
379 		return(jret);
380 	case NEXT:
381 		return(jnext);
382 	case NEXTFILE:
383 		nextfile();
384 		return(jnextfile);
385 	case BREAK:
386 		return(jbreak);
387 	case CONTINUE:
388 		return(jcont);
389 	default:	/* can't happen */
390 		FATAL("illegal jump type %d", n);
391 	}
392 	return 0;	/* not reached */
393 }
394 
395 Cell *awkgetline(Node **a, int n)	/* get next line from specific input */
396 {		/* a[0] is variable, a[1] is operator, a[2] is filename */
397 	Cell *r, *x;
398 	extern Cell **fldtab;
399 	FILE *fp;
400 	char *buf;
401 	int bufsize = recsize;
402 	int mode;
403 
404 	if ((buf = (char *) malloc(bufsize)) == NULL)
405 		FATAL("out of memory in getline");
406 
407 	fflush(stdout);	/* in case someone is waiting for a prompt */
408 	r = gettemp();
409 	if (a[1] != NULL) {		/* getline < file */
410 		x = execute(a[2]);		/* filename */
411 		mode = ptoi(a[1]);
412 		if (mode == '|')		/* input pipe */
413 			mode = LE;	/* arbitrary flag */
414 		fp = openfile(mode, getsval(x));
415 		tempfree(x);
416 		if (fp == NULL)
417 			n = -1;
418 		else
419 			n = readrec(&buf, &bufsize, fp);
420 		if (n <= 0) {
421 			;
422 		} else if (a[0] != NULL) {	/* getline var <file */
423 			x = execute(a[0]);
424 			setsval(x, buf);
425 			tempfree(x);
426 		} else {			/* getline <file */
427 			setsval(fldtab[0], buf);
428 			if (is_number(fldtab[0]->sval)) {
429 				fldtab[0]->fval = atof(fldtab[0]->sval);
430 				fldtab[0]->tval |= NUM;
431 			}
432 		}
433 	} else {			/* bare getline; use current input */
434 		if (a[0] == NULL)	/* getline */
435 			n = getrec(&record, &recsize, 1);
436 		else {			/* getline var */
437 			n = getrec(&buf, &bufsize, 0);
438 			x = execute(a[0]);
439 			setsval(x, buf);
440 			tempfree(x);
441 		}
442 	}
443 	setfval(r, (Awkfloat) n);
444 	free(buf);
445 	return r;
446 }
447 
448 Cell *getnf(Node **a, int n)	/* get NF */
449 {
450 	if (donefld == 0)
451 		fldbld();
452 	return (Cell *) a[0];
453 }
454 
455 Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
456 {
457 	Cell *x, *y, *z;
458 	char *s;
459 	Node *np;
460 	char *buf;
461 	int bufsz = recsize;
462 	int nsub = strlen(*SUBSEP);
463 
464 	if ((buf = (char *) malloc(bufsz)) == NULL)
465 		FATAL("out of memory in array");
466 
467 	x = execute(a[0]);	/* Cell* for symbol table */
468 	buf[0] = 0;
469 	for (np = a[1]; np; np = np->nnext) {
470 		y = execute(np);	/* subscript */
471 		s = getsval(y);
472 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
473 			FATAL("out of memory for %s[%s...]", x->nval, buf);
474 		strlcat(buf, s, bufsz);
475 		if (np->nnext)
476 			strlcat(buf, *SUBSEP, bufsz);
477 		tempfree(y);
478 	}
479 	if (!isarr(x)) {
480 		   dprintf( ("making %s into an array\n", NN(x->nval)) );
481 		if (freeable(x))
482 			xfree(x->sval);
483 		x->tval &= ~(STR|NUM|DONTFREE);
484 		x->tval |= ARR;
485 		x->sval = (char *) makesymtab(NSYMTAB);
486 	}
487 	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
488 	z->ctype = OCELL;
489 	z->csub = CVAR;
490 	tempfree(x);
491 	free(buf);
492 	return(z);
493 }
494 
495 Cell *awkdelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
496 {
497 	Cell *x, *y;
498 	Node *np;
499 	char *s;
500 	int nsub = strlen(*SUBSEP);
501 
502 	x = execute(a[0]);	/* Cell* for symbol table */
503 	if (!isarr(x))
504 		return True;
505 	if (a[1] == 0) {	/* delete the elements, not the table */
506 		freesymtab(x);
507 		x->tval &= ~STR;
508 		x->tval |= ARR;
509 		x->sval = (char *) makesymtab(NSYMTAB);
510 	} else {
511 		int bufsz = recsize;
512 		char *buf;
513 		if ((buf = (char *) malloc(bufsz)) == NULL)
514 			FATAL("out of memory in adelete");
515 		buf[0] = 0;
516 		for (np = a[1]; np; np = np->nnext) {
517 			y = execute(np);	/* subscript */
518 			s = getsval(y);
519 			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
520 				FATAL("out of memory deleting %s[%s...]", x->nval, buf);
521 			strlcat(buf, s, bufsz);
522 			if (np->nnext)
523 				strlcat(buf, *SUBSEP, bufsz);
524 			tempfree(y);
525 		}
526 		freeelem(x, buf);
527 		free(buf);
528 	}
529 	tempfree(x);
530 	return True;
531 }
532 
533 Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */
534 {
535 	Cell *x, *ap, *k;
536 	Node *p;
537 	char *buf;
538 	char *s;
539 	int bufsz = recsize;
540 	int nsub = strlen(*SUBSEP);
541 
542 	ap = execute(a[1]);	/* array name */
543 	if (!isarr(ap)) {
544 		   dprintf( ("making %s into an array\n", ap->nval) );
545 		if (freeable(ap))
546 			xfree(ap->sval);
547 		ap->tval &= ~(STR|NUM|DONTFREE);
548 		ap->tval |= ARR;
549 		ap->sval = (char *) makesymtab(NSYMTAB);
550 	}
551 	if ((buf = (char *) malloc(bufsz)) == NULL) {
552 		FATAL("out of memory in intest");
553 	}
554 	buf[0] = 0;
555 	for (p = a[0]; p; p = p->nnext) {
556 		x = execute(p);	/* expr */
557 		s = getsval(x);
558 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
559 			FATAL("out of memory deleting %s[%s...]", x->nval, buf);
560 		strlcat(buf, s, bufsz);
561 		tempfree(x);
562 		if (p->nnext)
563 			strlcat(buf, *SUBSEP, bufsz);
564 	}
565 	k = lookup(buf, (Array *) ap->sval);
566 	tempfree(ap);
567 	free(buf);
568 	if (k == NULL)
569 		return(False);
570 	else
571 		return(True);
572 }
573 
574 
575 Cell *matchop(Node **a, int n)	/* ~ and match() */
576 {
577 	Cell *x, *y;
578 	char *s, *t;
579 	int i;
580 	fa *pfa;
581 	int (*mf)(fa *, const char *) = match, mode = 0;
582 
583 	if (n == MATCHFCN) {
584 		mf = pmatch;
585 		mode = 1;
586 	}
587 	x = execute(a[1]);	/* a[1] = target text */
588 	s = getsval(x);
589 	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
590 		i = (*mf)((fa *) a[2], s);
591 	else {
592 		y = execute(a[2]);	/* a[2] = regular expr */
593 		t = getsval(y);
594 		pfa = makedfa(t, mode);
595 		i = (*mf)(pfa, s);
596 		tempfree(y);
597 	}
598 	tempfree(x);
599 	if (n == MATCHFCN) {
600 		int start = patbeg - s + 1;
601 		if (patlen < 0)
602 			start = 0;
603 		setfval(rstartloc, (Awkfloat) start);
604 		setfval(rlengthloc, (Awkfloat) patlen);
605 		x = gettemp();
606 		x->tval = NUM;
607 		x->fval = start;
608 		return x;
609 	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
610 		return(True);
611 	else
612 		return(False);
613 }
614 
615 
616 Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */
617 {
618 	Cell *x, *y;
619 	int i;
620 
621 	x = execute(a[0]);
622 	i = istrue(x);
623 	tempfree(x);
624 	switch (n) {
625 	case BOR:
626 		if (i) return(True);
627 		y = execute(a[1]);
628 		i = istrue(y);
629 		tempfree(y);
630 		if (i) return(True);
631 		else return(False);
632 	case AND:
633 		if ( !i ) return(False);
634 		y = execute(a[1]);
635 		i = istrue(y);
636 		tempfree(y);
637 		if (i) return(True);
638 		else return(False);
639 	case NOT:
640 		if (i) return(False);
641 		else return(True);
642 	default:	/* can't happen */
643 		FATAL("unknown boolean operator %d", n);
644 	}
645 	return 0;	/*NOTREACHED*/
646 }
647 
648 Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */
649 {
650 	int i;
651 	Cell *x, *y;
652 	Awkfloat j;
653 
654 	x = execute(a[0]);
655 	y = execute(a[1]);
656 	if (x->tval&NUM && y->tval&NUM) {
657 		j = x->fval - y->fval;
658 		i = j<0? -1: (j>0? 1: 0);
659 	} else {
660 		i = strcmp(getsval(x), getsval(y));
661 	}
662 	tempfree(x);
663 	tempfree(y);
664 	switch (n) {
665 	case LT:	if (i<0) return(True);
666 			else return(False);
667 	case LE:	if (i<=0) return(True);
668 			else return(False);
669 	case NE:	if (i!=0) return(True);
670 			else return(False);
671 	case EQ:	if (i == 0) return(True);
672 			else return(False);
673 	case GE:	if (i>=0) return(True);
674 			else return(False);
675 	case GT:	if (i>0) return(True);
676 			else return(False);
677 	default:	/* can't happen */
678 		FATAL("unknown relational operator %d", n);
679 	}
680 	return 0;	/*NOTREACHED*/
681 }
682 
683 void tfree(Cell *a)	/* free a tempcell */
684 {
685 	if (freeable(a)) {
686 		   dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
687 		xfree(a->sval);
688 	}
689 	if (a == tmps)
690 		FATAL("tempcell list is curdled");
691 	a->cnext = tmps;
692 	tmps = a;
693 }
694 
695 Cell *gettemp(void)	/* get a tempcell */
696 {	int i;
697 	Cell *x;
698 
699 	if (!tmps) {
700 		tmps = (Cell *) calloc(100, sizeof(Cell));
701 		if (!tmps)
702 			FATAL("out of space for temporaries");
703 		for(i = 1; i < 100; i++)
704 			tmps[i-1].cnext = &tmps[i];
705 		tmps[i-1].cnext = 0;
706 	}
707 	x = tmps;
708 	tmps = x->cnext;
709 	*x = tempcell;
710 	return(x);
711 }
712 
713 Cell *indirect(Node **a, int n)	/* $( a[0] ) */
714 {
715 	Awkfloat val;
716 	Cell *x;
717 	int m;
718 	char *s;
719 
720 	x = execute(a[0]);
721 	val = getfval(x);	/* freebsd: defend against super large field numbers */
722 	if ((Awkfloat)INT_MAX < val)
723 		FATAL("trying to access out of range field %s", x->nval);
724 	m = (int) val;
725 	if (m == 0 && !is_number(s = getsval(x)))	/* suspicion! */
726 		FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
727 		/* BUG: can x->nval ever be null??? */
728 	tempfree(x);
729 	x = fieldadr(m);
730 	x->ctype = OCELL;	/* BUG?  why are these needed? */
731 	x->csub = CFLD;
732 	return(x);
733 }
734 
735 Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
736 {
737 	int k, m, n;
738 	char *s;
739 	int temp;
740 	Cell *x, *y, *z = 0;
741 
742 	x = execute(a[0]);
743 	y = execute(a[1]);
744 	if (a[2] != 0)
745 		z = execute(a[2]);
746 	s = getsval(x);
747 	k = strlen(s) + 1;
748 	if (k <= 1) {
749 		tempfree(x);
750 		tempfree(y);
751 		if (a[2] != 0) {
752 			tempfree(z);
753 		}
754 		x = gettemp();
755 		setsval(x, "");
756 		return(x);
757 	}
758 	m = (int) getfval(y);
759 	if (m <= 0)
760 		m = 1;
761 	else if (m > k)
762 		m = k;
763 	tempfree(y);
764 	if (a[2] != 0) {
765 		n = (int) getfval(z);
766 		tempfree(z);
767 	} else
768 		n = k - 1;
769 	if (n < 0)
770 		n = 0;
771 	else if (n > k - m)
772 		n = k - m;
773 	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
774 	y = gettemp();
775 	temp = s[n+m-1];	/* with thanks to John Linderman */
776 	s[n+m-1] = '\0';
777 	setsval(y, s + m - 1);
778 	s[n+m-1] = temp;
779 	tempfree(x);
780 	return(y);
781 }
782 
783 Cell *sindex(Node **a, int nnn)		/* index(a[0], a[1]) */
784 {
785 	Cell *x, *y, *z;
786 	char *s1, *s2, *p1, *p2, *q;
787 	Awkfloat v = 0.0;
788 
789 	x = execute(a[0]);
790 	s1 = getsval(x);
791 	y = execute(a[1]);
792 	s2 = getsval(y);
793 
794 	z = gettemp();
795 	for (p1 = s1; *p1 != '\0'; p1++) {
796 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
797 			;
798 		if (*p2 == '\0') {
799 			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
800 			break;
801 		}
802 	}
803 	tempfree(x);
804 	tempfree(y);
805 	setfval(z, v);
806 	return(z);
807 }
808 
809 #define	MAXNUMSIZE	50
810 
811 int format(char **pbuf, int *pbufsize, const char *s, Node *a)	/* printf-like conversions */
812 {
813 	char *fmt;
814 	char *p, *t;
815 	const char *os;
816 	Cell *x;
817 	int flag = 0, n;
818 	int fmtwd; /* format width */
819 	int fmtsz = recsize;
820 	char *buf = *pbuf;
821 	int bufsize = *pbufsize;
822 
823 	os = s;
824 	p = buf;
825 	if ((fmt = (char *) malloc(fmtsz)) == NULL)
826 		FATAL("out of memory in format()");
827 	while (*s) {
828 		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
829 		if (*s != '%') {
830 			*p++ = *s++;
831 			continue;
832 		}
833 		if (*(s+1) == '%') {
834 			*p++ = '%';
835 			s += 2;
836 			continue;
837 		}
838 		/* have to be real careful in case this is a huge number, eg, %100000d */
839 		fmtwd = atoi(s+1);
840 		if (fmtwd < 0)
841 			fmtwd = -fmtwd;
842 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
843 		for (t = fmt; (*t++ = *s) != '\0'; s++) {
844 			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
845 				FATAL("format item %.30s... ran format() out of memory", os);
846 			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
847 				break;	/* the ansi panoply */
848 			if (*s == '*') {
849 				if (a == NULL)
850 					FATAL("not enough args in printf(%s)", os);
851 				x = execute(a);
852 				a = a->nnext;
853 				snprintf(t-1, fmt + fmtsz - (t-1), "%d", fmtwd=(int) getfval(x));
854 				if (fmtwd < 0)
855 					fmtwd = -fmtwd;
856 				adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
857 				t = fmt + strlen(fmt);
858 				tempfree(x);
859 			}
860 		}
861 		*t = '\0';
862 		if (fmtwd < 0)
863 			fmtwd = -fmtwd;
864 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
865 
866 		switch (*s) {
867 		case 'f': case 'e': case 'g': case 'E': case 'G':
868 			flag = 'f';
869 			break;
870 		case 'd': case 'i':
871 			flag = 'd';
872 			if(*(s-1) == 'l') break;
873 			*(t-1) = 'l';
874 			*t = 'd';
875 			*++t = '\0';
876 			break;
877 		case 'o': case 'x': case 'X': case 'u':
878 			flag = *(s-1) == 'l' ? 'd' : 'u';
879 			break;
880 		case 's':
881 			flag = 's';
882 			break;
883 		case 'c':
884 			flag = 'c';
885 			break;
886 		default:
887 			WARNING("weird printf conversion %s", fmt);
888 			flag = '?';
889 			break;
890 		}
891 		if (a == NULL)
892 			FATAL("not enough args in printf(%s)", os);
893 		x = execute(a);
894 		a = a->nnext;
895 		n = MAXNUMSIZE;
896 		if (fmtwd > n)
897 			n = fmtwd;
898 		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
899 		switch (flag) {
900 		case '?':	/* unknown, so dump it too */
901 			snprintf(p, buf + bufsize - p, "%s", fmt);
902 			t = getsval(x);
903 			n = strlen(t);
904 			if (fmtwd > n)
905 				n = fmtwd;
906 			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
907 			p += strlen(p);
908 			snprintf(p, buf + bufsize - p, "%s", t);
909 			break;
910 		case 'f':	snprintf(p, buf + bufsize - p, fmt, getfval(x)); break;
911 		case 'd':	snprintf(p, buf + bufsize - p, fmt, (long) getfval(x)); break;
912 		case 'u':	snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); break;
913 		case 's':
914 			t = getsval(x);
915 			n = strlen(t);
916 			if (fmtwd > n)
917 				n = fmtwd;
918 			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
919 				FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
920 			snprintf(p, buf + bufsize - p, fmt, t);
921 			break;
922 		case 'c':
923 			if (isnum(x)) {
924 				if (getfval(x))
925 					snprintf(p, buf + bufsize - p, fmt, (int) getfval(x));
926 				else {
927 					*p++ = '\0'; /* explicit null byte */
928 					*p = '\0';   /* next output will start here */
929 				}
930 			} else
931 				snprintf(p, buf + bufsize - p, fmt, getsval(x)[0]);
932 			break;
933 		default:
934 			FATAL("can't happen: bad conversion %c in format()", flag);
935 		}
936 		tempfree(x);
937 		p += strlen(p);
938 		s++;
939 	}
940 	*p = '\0';
941 	free(fmt);
942 	for ( ; a; a = a->nnext)		/* evaluate any remaining args */
943 		execute(a);
944 	*pbuf = buf;
945 	*pbufsize = bufsize;
946 	return p - buf;
947 }
948 
949 Cell *awksprintf(Node **a, int n)		/* sprintf(a[0]) */
950 {
951 	Cell *x;
952 	Node *y;
953 	char *buf;
954 	int bufsz=3*recsize;
955 
956 	if ((buf = (char *) malloc(bufsz)) == NULL)
957 		FATAL("out of memory in awksprintf");
958 	y = a[0]->nnext;
959 	x = execute(a[0]);
960 	if (format(&buf, &bufsz, getsval(x), y) == -1)
961 		FATAL("sprintf string %.30s... too long.  can't happen.", buf);
962 	tempfree(x);
963 	x = gettemp();
964 	x->sval = buf;
965 	x->tval = STR;
966 	return(x);
967 }
968 
969 Cell *awkprintf(Node **a, int n)		/* printf */
970 {	/* a[0] is list of args, starting with format string */
971 	/* a[1] is redirection operator, a[2] is redirection file */
972 	FILE *fp;
973 	Cell *x;
974 	Node *y;
975 	char *buf;
976 	int len;
977 	int bufsz=3*recsize;
978 
979 	if ((buf = (char *) malloc(bufsz)) == NULL)
980 		FATAL("out of memory in awkprintf");
981 	y = a[0]->nnext;
982 	x = execute(a[0]);
983 	if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
984 		FATAL("printf string %.30s... too long.  can't happen.", buf);
985 	tempfree(x);
986 	if (a[1] == NULL) {
987 		/* fputs(buf, stdout); */
988 		fwrite(buf, len, 1, stdout);
989 		if (ferror(stdout))
990 			FATAL("write error on stdout");
991 	} else {
992 		fp = redirect(ptoi(a[1]), a[2]);
993 		/* fputs(buf, fp); */
994 		fwrite(buf, len, 1, fp);
995 		fflush(fp);
996 		if (ferror(fp))
997 			FATAL("write error on %s", filename(fp));
998 	}
999 	free(buf);
1000 	return(True);
1001 }
1002 
1003 Cell *arith(Node **a, int n)	/* a[0] + a[1], etc.  also -a[0] */
1004 {
1005 	Awkfloat i, j = 0;
1006 	double v;
1007 	Cell *x, *y, *z;
1008 
1009 	x = execute(a[0]);
1010 	i = getfval(x);
1011 	tempfree(x);
1012 	if (n != UMINUS) {
1013 		y = execute(a[1]);
1014 		j = getfval(y);
1015 		tempfree(y);
1016 	}
1017 	z = gettemp();
1018 	switch (n) {
1019 	case ADD:
1020 		i += j;
1021 		break;
1022 	case MINUS:
1023 		i -= j;
1024 		break;
1025 	case MULT:
1026 		i *= j;
1027 		break;
1028 	case DIVIDE:
1029 		if (j == 0)
1030 			FATAL("division by zero");
1031 		i /= j;
1032 		break;
1033 	case MOD:
1034 		if (j == 0)
1035 			FATAL("division by zero in mod");
1036 		modf(i/j, &v);
1037 		i = i - j * v;
1038 		break;
1039 	case UMINUS:
1040 		i = -i;
1041 		break;
1042 	case POWER:
1043 		if (j >= 0 && modf(j, &v) == 0.0)	/* pos integer exponent */
1044 			i = ipow(i, (int) j);
1045 		else
1046 			i = errcheck(pow(i, j), "pow");
1047 		break;
1048 	default:	/* can't happen */
1049 		FATAL("illegal arithmetic operator %d", n);
1050 	}
1051 	setfval(z, i);
1052 	return(z);
1053 }
1054 
1055 double ipow(double x, int n)	/* x**n.  ought to be done by pow, but isn't always */
1056 {
1057 	double v;
1058 
1059 	if (n <= 0)
1060 		return 1;
1061 	v = ipow(x, n/2);
1062 	if (n % 2 == 0)
1063 		return v * v;
1064 	else
1065 		return x * v * v;
1066 }
1067 
1068 Cell *incrdecr(Node **a, int n)		/* a[0]++, etc. */
1069 {
1070 	Cell *x, *z;
1071 	int k;
1072 	Awkfloat xf;
1073 
1074 	x = execute(a[0]);
1075 	xf = getfval(x);
1076 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1077 	if (n == PREINCR || n == PREDECR) {
1078 		setfval(x, xf + k);
1079 		return(x);
1080 	}
1081 	z = gettemp();
1082 	setfval(z, xf);
1083 	setfval(x, xf + k);
1084 	tempfree(x);
1085 	return(z);
1086 }
1087 
1088 Cell *assign(Node **a, int n)	/* a[0] = a[1], a[0] += a[1], etc. */
1089 {		/* this is subtle; don't muck with it. */
1090 	Cell *x, *y;
1091 	Awkfloat xf, yf;
1092 	double v;
1093 
1094 	y = execute(a[1]);
1095 	x = execute(a[0]);
1096 	if (n == ASSIGN) {	/* ordinary assignment */
1097 		if (x == y && !(x->tval & (FLD|REC)))	/* self-assignment: */
1098 			;		/* leave alone unless it's a field */
1099 		else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1100 			setsval(x, getsval(y));
1101 			x->fval = getfval(y);
1102 			x->tval |= NUM;
1103 		}
1104 		else if (isstr(y))
1105 			setsval(x, getsval(y));
1106 		else if (isnum(y))
1107 			setfval(x, getfval(y));
1108 		else
1109 			funnyvar(y, "read value of");
1110 		tempfree(y);
1111 		return(x);
1112 	}
1113 	xf = getfval(x);
1114 	yf = getfval(y);
1115 	switch (n) {
1116 	case ADDEQ:
1117 		xf += yf;
1118 		break;
1119 	case SUBEQ:
1120 		xf -= yf;
1121 		break;
1122 	case MULTEQ:
1123 		xf *= yf;
1124 		break;
1125 	case DIVEQ:
1126 		if (yf == 0)
1127 			FATAL("division by zero in /=");
1128 		xf /= yf;
1129 		break;
1130 	case MODEQ:
1131 		if (yf == 0)
1132 			FATAL("division by zero in %%=");
1133 		modf(xf/yf, &v);
1134 		xf = xf - yf * v;
1135 		break;
1136 	case POWEQ:
1137 		if (yf >= 0 && modf(yf, &v) == 0.0)	/* pos integer exponent */
1138 			xf = ipow(xf, (int) yf);
1139 		else
1140 			xf = errcheck(pow(xf, yf), "pow");
1141 		break;
1142 	default:
1143 		FATAL("illegal assignment operator %d", n);
1144 		break;
1145 	}
1146 	tempfree(y);
1147 	setfval(x, xf);
1148 	return(x);
1149 }
1150 
1151 Cell *cat(Node **a, int q)	/* a[0] cat a[1] */
1152 {
1153 	Cell *x, *y, *z;
1154 	int n1, n2;
1155 	char *s;
1156 	size_t len;
1157 
1158 	x = execute(a[0]);
1159 	y = execute(a[1]);
1160 	getsval(x);
1161 	getsval(y);
1162 	n1 = strlen(x->sval);
1163 	n2 = strlen(y->sval);
1164 	len = n1 + n2 + 1;
1165 	s = (char *) malloc(len);
1166 	if (s == NULL)
1167 		FATAL("out of space concatenating %.15s... and %.15s...",
1168 			x->sval, y->sval);
1169 	strlcpy(s, x->sval, len);
1170 	strlcpy(s+n1, y->sval, len - n1);
1171 	tempfree(x);
1172 	tempfree(y);
1173 	z = gettemp();
1174 	z->sval = s;
1175 	z->tval = STR;
1176 	return(z);
1177 }
1178 
1179 Cell *pastat(Node **a, int n)	/* a[0] { a[1] } */
1180 {
1181 	Cell *x;
1182 
1183 	if (a[0] == 0)
1184 		x = execute(a[1]);
1185 	else {
1186 		x = execute(a[0]);
1187 		if (istrue(x)) {
1188 			tempfree(x);
1189 			x = execute(a[1]);
1190 		}
1191 	}
1192 	return x;
1193 }
1194 
1195 Cell *dopa2(Node **a, int n)	/* a[0], a[1] { a[2] } */
1196 {
1197 	Cell *x;
1198 	int pair;
1199 
1200 	pair = ptoi(a[3]);
1201 	if (pairstack[pair] == 0) {
1202 		x = execute(a[0]);
1203 		if (istrue(x))
1204 			pairstack[pair] = 1;
1205 		tempfree(x);
1206 	}
1207 	if (pairstack[pair] == 1) {
1208 		x = execute(a[1]);
1209 		if (istrue(x))
1210 			pairstack[pair] = 0;
1211 		tempfree(x);
1212 		x = execute(a[2]);
1213 		return(x);
1214 	}
1215 	return(False);
1216 }
1217 
1218 Cell *split(Node **a, int nnn)	/* split(a[0], a[1], a[2]); a[3] is type */
1219 {
1220 	Cell *x = 0, *y, *ap;
1221 	char *s;
1222 	int sep;
1223 	char *t, temp, num[50], *fs = 0;
1224 	int n, tempstat, arg3type;
1225 
1226 	y = execute(a[0]);	/* source string */
1227 	s = getsval(y);
1228 	arg3type = ptoi(a[3]);
1229 	if (a[2] == 0)		/* fs string */
1230 		fs = *FS;
1231 	else if (arg3type == STRING) {	/* split(str,arr,"string") */
1232 		x = execute(a[2]);
1233 		fs = getsval(x);
1234 	} else if (arg3type == REGEXPR)
1235 		fs = "(regexpr)";	/* split(str,arr,/regexpr/) */
1236 	else
1237 		FATAL("illegal type of split");
1238 	sep = *fs;
1239 	ap = execute(a[1]);	/* array name */
1240 	freesymtab(ap);
1241 	   dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1242 	ap->tval &= ~STR;
1243 	ap->tval |= ARR;
1244 	ap->sval = (char *) makesymtab(NSYMTAB);
1245 
1246 	n = 0;
1247         if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1248 		/* split(s, a, //); have to arrange that it looks like empty sep */
1249 		arg3type = 0;
1250 		fs = "";
1251 		sep = 0;
1252 	}
1253 	if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {	/* reg expr */
1254 		fa *pfa;
1255 		if (arg3type == REGEXPR) {	/* it's ready already */
1256 			pfa = (fa *) a[2];
1257 		} else {
1258 			pfa = makedfa(fs, 1);
1259 		}
1260 		if (nematch(pfa,s)) {
1261 			tempstat = pfa->initstat;
1262 			pfa->initstat = 2;
1263 			do {
1264 				n++;
1265 				snprintf(num, sizeof num, "%d", n);
1266 				temp = *patbeg;
1267 				*patbeg = '\0';
1268 				if (is_number(s))
1269 					setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1270 				else
1271 					setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1272 				*patbeg = temp;
1273 				s = patbeg + patlen;
1274 				if (*(patbeg+patlen-1) == 0 || *s == 0) {
1275 					n++;
1276 					snprintf(num, sizeof num, "%d", n);
1277 					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1278 					pfa->initstat = tempstat;
1279 					goto spdone;
1280 				}
1281 			} while (nematch(pfa,s));
1282 			pfa->initstat = tempstat; 	/* bwk: has to be here to reset */
1283 							/* cf gsub and refldbld */
1284 		}
1285 		n++;
1286 		snprintf(num, sizeof num, "%d", n);
1287 		if (is_number(s))
1288 			setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1289 		else
1290 			setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1291   spdone:
1292 		pfa = NULL;
1293 	} else if (sep == ' ') {
1294 		for (n = 0; ; ) {
1295 			while (*s == ' ' || *s == '\t' || *s == '\n')
1296 				s++;
1297 			if (*s == 0)
1298 				break;
1299 			n++;
1300 			t = s;
1301 			do
1302 				s++;
1303 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1304 			temp = *s;
1305 			*s = '\0';
1306 			snprintf(num, sizeof num, "%d", n);
1307 			if (is_number(t))
1308 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1309 			else
1310 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1311 			*s = temp;
1312 			if (*s != 0)
1313 				s++;
1314 		}
1315 	} else if (sep == 0) {	/* new: split(s, a, "") => 1 char/elem */
1316 		for (n = 0; *s != 0; s++) {
1317 			char buf[2];
1318 			n++;
1319 			snprintf(num, sizeof num, "%d", n);
1320 			buf[0] = *s;
1321 			buf[1] = 0;
1322 			if (isdigit((uschar)buf[0]))
1323 				setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1324 			else
1325 				setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1326 		}
1327 	} else if (*s != 0) {
1328 		for (;;) {
1329 			n++;
1330 			t = s;
1331 			while (*s != sep && *s != '\n' && *s != '\0')
1332 				s++;
1333 			temp = *s;
1334 			*s = '\0';
1335 			snprintf(num, sizeof num, "%d", n);
1336 			if (is_number(t))
1337 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1338 			else
1339 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1340 			*s = temp;
1341 			if (*s++ == 0)
1342 				break;
1343 		}
1344 	}
1345 	tempfree(ap);
1346 	tempfree(y);
1347 	if (a[2] != 0 && arg3type == STRING) {
1348 		tempfree(x);
1349 	}
1350 	x = gettemp();
1351 	x->tval = NUM;
1352 	x->fval = n;
1353 	return(x);
1354 }
1355 
1356 Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1357 {
1358 	Cell *x;
1359 
1360 	x = execute(a[0]);
1361 	if (istrue(x)) {
1362 		tempfree(x);
1363 		x = execute(a[1]);
1364 	} else {
1365 		tempfree(x);
1366 		x = execute(a[2]);
1367 	}
1368 	return(x);
1369 }
1370 
1371 Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
1372 {
1373 	Cell *x;
1374 
1375 	x = execute(a[0]);
1376 	if (istrue(x)) {
1377 		tempfree(x);
1378 		x = execute(a[1]);
1379 	} else if (a[2] != 0) {
1380 		tempfree(x);
1381 		x = execute(a[2]);
1382 	}
1383 	return(x);
1384 }
1385 
1386 Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1387 {
1388 	Cell *x;
1389 
1390 	for (;;) {
1391 		x = execute(a[0]);
1392 		if (!istrue(x))
1393 			return(x);
1394 		tempfree(x);
1395 		x = execute(a[1]);
1396 		if (isbreak(x)) {
1397 			x = True;
1398 			return(x);
1399 		}
1400 		if (isnext(x) || isexit(x) || isret(x))
1401 			return(x);
1402 		tempfree(x);
1403 	}
1404 }
1405 
1406 Cell *dostat(Node **a, int n)	/* do a[0]; while(a[1]) */
1407 {
1408 	Cell *x;
1409 
1410 	for (;;) {
1411 		x = execute(a[0]);
1412 		if (isbreak(x))
1413 			return True;
1414 		if (isnext(x) || isexit(x) || isret(x))
1415 			return(x);
1416 		tempfree(x);
1417 		x = execute(a[1]);
1418 		if (!istrue(x))
1419 			return(x);
1420 		tempfree(x);
1421 	}
1422 }
1423 
1424 Cell *forstat(Node **a, int n)	/* for (a[0]; a[1]; a[2]) a[3] */
1425 {
1426 	Cell *x;
1427 
1428 	x = execute(a[0]);
1429 	tempfree(x);
1430 	for (;;) {
1431 		if (a[1]!=0) {
1432 			x = execute(a[1]);
1433 			if (!istrue(x)) return(x);
1434 			else tempfree(x);
1435 		}
1436 		x = execute(a[3]);
1437 		if (isbreak(x))		/* turn off break */
1438 			return True;
1439 		if (isnext(x) || isexit(x) || isret(x))
1440 			return(x);
1441 		tempfree(x);
1442 		x = execute(a[2]);
1443 		tempfree(x);
1444 	}
1445 }
1446 
1447 Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
1448 {
1449 	Cell *x, *vp, *arrayp, *cp, *ncp;
1450 	Array *tp;
1451 	int i;
1452 
1453 	vp = execute(a[0]);
1454 	arrayp = execute(a[1]);
1455 	if (!isarr(arrayp)) {
1456 		return True;
1457 	}
1458 	tp = (Array *) arrayp->sval;
1459 	tempfree(arrayp);
1460 	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1461 		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1462 			setsval(vp, cp->nval);
1463 			ncp = cp->cnext;
1464 			x = execute(a[2]);
1465 			if (isbreak(x)) {
1466 				tempfree(vp);
1467 				return True;
1468 			}
1469 			if (isnext(x) || isexit(x) || isret(x)) {
1470 				tempfree(vp);
1471 				return(x);
1472 			}
1473 			tempfree(x);
1474 		}
1475 	}
1476 	return True;
1477 }
1478 
1479 Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
1480 {
1481 	Cell *x, *y;
1482 	Awkfloat u;
1483 	int t;
1484 	Awkfloat tmp;
1485 	char *p, *buf;
1486 	Node *nextarg;
1487 	FILE *fp;
1488 
1489 	t = ptoi(a[0]);
1490 	x = execute(a[1]);
1491 	nextarg = a[1]->nnext;
1492 	switch (t) {
1493 	case FLENGTH:
1494 		if (isarr(x))
1495 			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
1496 		else
1497 			u = strlen(getsval(x));
1498 		break;
1499 	case FLOG:
1500 		u = errcheck(log(getfval(x)), "log"); break;
1501 	case FINT:
1502 		modf(getfval(x), &u); break;
1503 	case FEXP:
1504 		u = errcheck(exp(getfval(x)), "exp"); break;
1505 	case FSQRT:
1506 		u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1507 	case FSIN:
1508 		u = sin(getfval(x)); break;
1509 	case FCOS:
1510 		u = cos(getfval(x)); break;
1511 	case FATAN:
1512 		if (nextarg == 0) {
1513 			WARNING("atan2 requires two arguments; returning 1.0");
1514 			u = 1.0;
1515 		} else {
1516 			y = execute(a[1]->nnext);
1517 			u = atan2(getfval(x), getfval(y));
1518 			tempfree(y);
1519 			nextarg = nextarg->nnext;
1520 		}
1521 		break;
1522 	case FCOMPL:
1523 		u = ~((int)getfval(x));
1524 		break;
1525 	case FAND:
1526 		if (nextarg == 0) {
1527 			WARNING("and requires two arguments; returning 0");
1528 			u = 0;
1529 			break;
1530 		}
1531 		y = execute(a[1]->nnext);
1532 		u = ((int)getfval(x)) & ((int)getfval(y));
1533 		tempfree(y);
1534 		nextarg = nextarg->nnext;
1535 		break;
1536 	case FFOR:
1537 		if (nextarg == 0) {
1538 			WARNING("or requires two arguments; returning 0");
1539 			u = 0;
1540 			break;
1541 		}
1542 		y = execute(a[1]->nnext);
1543 		u = ((int)getfval(x)) | ((int)getfval(y));
1544 		tempfree(y);
1545 		nextarg = nextarg->nnext;
1546 		break;
1547 	case FXOR:
1548 		if (nextarg == 0) {
1549 			WARNING("or requires two arguments; returning 0");
1550 			u = 0;
1551 			break;
1552 		}
1553 		y = execute(a[1]->nnext);
1554 		u = ((int)getfval(x)) ^ ((int)getfval(y));
1555 		tempfree(y);
1556 		nextarg = nextarg->nnext;
1557 		break;
1558 	case FLSHIFT:
1559 		if (nextarg == 0) {
1560 			WARNING("or requires two arguments; returning 0");
1561 			u = 0;
1562 			break;
1563 		}
1564 		y = execute(a[1]->nnext);
1565 		u = ((int)getfval(x)) << ((int)getfval(y));
1566 		tempfree(y);
1567 		nextarg = nextarg->nnext;
1568 		break;
1569 	case FRSHIFT:
1570 		if (nextarg == 0) {
1571 			WARNING("or requires two arguments; returning 0");
1572 			u = 0;
1573 			break;
1574 		}
1575 		y = execute(a[1]->nnext);
1576 		u = ((int)getfval(x)) >> ((int)getfval(y));
1577 		tempfree(y);
1578 		nextarg = nextarg->nnext;
1579 		break;
1580 	case FSYSTEM:
1581 		fflush(stdout);		/* in case something is buffered already */
1582 		u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
1583 		break;
1584 	case FRAND:
1585 		if (use_srandom)
1586 			u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;
1587 		else
1588 			u = (Awkfloat)arc4random() / 0xffffffff;
1589 		break;
1590 	case FSRAND:
1591 		if (isrec(x))	/* no argument provided, want arc4random() */
1592 			use_srandom = 0;
1593 		else {
1594 			use_srandom = 1;
1595 			u = getfval(x);
1596 			tmp = u;
1597 			srandom((unsigned int) u);
1598 			u = srand_seed;
1599 			srand_seed = tmp;
1600 		}
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 = realloc(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