xref: /openbsd-src/usr.bin/awk/run.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: run.c,v 1.30 2008/10/06 20:38:33 millert 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_arc4 = 1;
70 extern	int	pairstack[];
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 = (struct Frame *)
274 			realloc((char *) frame, (nframe += 100) * 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 *getline(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 (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(y);
1171 	z = gettemp();
1172 	z->sval = s;
1173 	z->tval = STR;
1174 	tempfree(x);
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;
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 	s = getsval(y);
1227 	arg3type = ptoi(a[3]);
1228 	if (a[2] == 0)		/* fs string */
1229 		fs = *FS;
1230 	else if (arg3type == STRING) {	/* split(str,arr,"string") */
1231 		x = execute(a[2]);
1232 		fs = getsval(x);
1233 	} else if (arg3type == REGEXPR)
1234 		fs = "(regexpr)";	/* split(str,arr,/regexpr/) */
1235 	else
1236 		FATAL("illegal type of split");
1237 	sep = *fs;
1238 	ap = execute(a[1]);	/* array name */
1239 	freesymtab(ap);
1240 	   dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1241 	ap->tval &= ~STR;
1242 	ap->tval |= ARR;
1243 	ap->sval = (char *) makesymtab(NSYMTAB);
1244 
1245 	n = 0;
1246 	if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {	/* reg expr */
1247 		fa *pfa;
1248 		if (arg3type == REGEXPR) {	/* it's ready already */
1249 			pfa = (fa *) a[2];
1250 		} else {
1251 			pfa = makedfa(fs, 1);
1252 		}
1253 		if (nematch(pfa,s)) {
1254 			tempstat = pfa->initstat;
1255 			pfa->initstat = 2;
1256 			do {
1257 				n++;
1258 				snprintf(num, sizeof num, "%d", n);
1259 				temp = *patbeg;
1260 				*patbeg = '\0';
1261 				if (is_number(s))
1262 					setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1263 				else
1264 					setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1265 				*patbeg = temp;
1266 				s = patbeg + patlen;
1267 				if (*(patbeg+patlen-1) == 0 || *s == 0) {
1268 					n++;
1269 					snprintf(num, sizeof num, "%d", n);
1270 					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1271 					pfa->initstat = tempstat;
1272 					goto spdone;
1273 				}
1274 			} while (nematch(pfa,s));
1275 			pfa->initstat = tempstat; 	/* bwk: has to be here to reset */
1276 							/* cf gsub and refldbld */
1277 		}
1278 		n++;
1279 		snprintf(num, sizeof num, "%d", n);
1280 		if (is_number(s))
1281 			setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1282 		else
1283 			setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1284   spdone:
1285 		pfa = NULL;
1286 	} else if (sep == ' ') {
1287 		for (n = 0; ; ) {
1288 			while (*s == ' ' || *s == '\t' || *s == '\n')
1289 				s++;
1290 			if (*s == 0)
1291 				break;
1292 			n++;
1293 			t = s;
1294 			do
1295 				s++;
1296 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1297 			temp = *s;
1298 			*s = '\0';
1299 			snprintf(num, sizeof num, "%d", n);
1300 			if (is_number(t))
1301 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1302 			else
1303 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1304 			*s = temp;
1305 			if (*s != 0)
1306 				s++;
1307 		}
1308 	} else if (sep == 0) {	/* new: split(s, a, "") => 1 char/elem */
1309 		for (n = 0; *s != 0; s++) {
1310 			char buf[2];
1311 			n++;
1312 			snprintf(num, sizeof num, "%d", n);
1313 			buf[0] = *s;
1314 			buf[1] = 0;
1315 			if (isdigit((uschar)buf[0]))
1316 				setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1317 			else
1318 				setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1319 		}
1320 	} else if (*s != 0) {
1321 		for (;;) {
1322 			n++;
1323 			t = s;
1324 			while (*s != sep && *s != '\n' && *s != '\0')
1325 				s++;
1326 			temp = *s;
1327 			*s = '\0';
1328 			snprintf(num, sizeof num, "%d", n);
1329 			if (is_number(t))
1330 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1331 			else
1332 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1333 			*s = temp;
1334 			if (*s++ == 0)
1335 				break;
1336 		}
1337 	}
1338 	tempfree(ap);
1339 	tempfree(y);
1340 	if (a[2] != 0 && arg3type == STRING) {
1341 		tempfree(x);
1342 	}
1343 	x = gettemp();
1344 	x->tval = NUM;
1345 	x->fval = n;
1346 	return(x);
1347 }
1348 
1349 Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1350 {
1351 	Cell *x;
1352 
1353 	x = execute(a[0]);
1354 	if (istrue(x)) {
1355 		tempfree(x);
1356 		x = execute(a[1]);
1357 	} else {
1358 		tempfree(x);
1359 		x = execute(a[2]);
1360 	}
1361 	return(x);
1362 }
1363 
1364 Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
1365 {
1366 	Cell *x;
1367 
1368 	x = execute(a[0]);
1369 	if (istrue(x)) {
1370 		tempfree(x);
1371 		x = execute(a[1]);
1372 	} else if (a[2] != 0) {
1373 		tempfree(x);
1374 		x = execute(a[2]);
1375 	}
1376 	return(x);
1377 }
1378 
1379 Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1380 {
1381 	Cell *x;
1382 
1383 	for (;;) {
1384 		x = execute(a[0]);
1385 		if (!istrue(x))
1386 			return(x);
1387 		tempfree(x);
1388 		x = execute(a[1]);
1389 		if (isbreak(x)) {
1390 			x = True;
1391 			return(x);
1392 		}
1393 		if (isnext(x) || isexit(x) || isret(x))
1394 			return(x);
1395 		tempfree(x);
1396 	}
1397 }
1398 
1399 Cell *dostat(Node **a, int n)	/* do a[0]; while(a[1]) */
1400 {
1401 	Cell *x;
1402 
1403 	for (;;) {
1404 		x = execute(a[0]);
1405 		if (isbreak(x))
1406 			return True;
1407 		if (isnext(x) || isexit(x) || isret(x))
1408 			return(x);
1409 		tempfree(x);
1410 		x = execute(a[1]);
1411 		if (!istrue(x))
1412 			return(x);
1413 		tempfree(x);
1414 	}
1415 }
1416 
1417 Cell *forstat(Node **a, int n)	/* for (a[0]; a[1]; a[2]) a[3] */
1418 {
1419 	Cell *x;
1420 
1421 	x = execute(a[0]);
1422 	tempfree(x);
1423 	for (;;) {
1424 		if (a[1]!=0) {
1425 			x = execute(a[1]);
1426 			if (!istrue(x)) return(x);
1427 			else tempfree(x);
1428 		}
1429 		x = execute(a[3]);
1430 		if (isbreak(x))		/* turn off break */
1431 			return True;
1432 		if (isnext(x) || isexit(x) || isret(x))
1433 			return(x);
1434 		tempfree(x);
1435 		x = execute(a[2]);
1436 		tempfree(x);
1437 	}
1438 }
1439 
1440 Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
1441 {
1442 	Cell *x, *vp, *arrayp, *cp, *ncp;
1443 	Array *tp;
1444 	int i;
1445 
1446 	vp = execute(a[0]);
1447 	arrayp = execute(a[1]);
1448 	if (!isarr(arrayp)) {
1449 		return True;
1450 	}
1451 	tp = (Array *) arrayp->sval;
1452 	tempfree(arrayp);
1453 	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1454 		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1455 			setsval(vp, cp->nval);
1456 			ncp = cp->cnext;
1457 			x = execute(a[2]);
1458 			if (isbreak(x)) {
1459 				tempfree(vp);
1460 				return True;
1461 			}
1462 			if (isnext(x) || isexit(x) || isret(x)) {
1463 				tempfree(vp);
1464 				return(x);
1465 			}
1466 			tempfree(x);
1467 		}
1468 	}
1469 	return True;
1470 }
1471 
1472 Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
1473 {
1474 	Cell *x, *y;
1475 	Awkfloat u;
1476 	int t;
1477 	char *p, *buf;
1478 	Node *nextarg;
1479 	FILE *fp;
1480 
1481 	t = ptoi(a[0]);
1482 	x = execute(a[1]);
1483 	nextarg = a[1]->nnext;
1484 	switch (t) {
1485 	case FLENGTH:
1486 		if (isarr(x))
1487 			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
1488 		else
1489 			u = strlen(getsval(x));
1490 		break;
1491 	case FLOG:
1492 		u = errcheck(log(getfval(x)), "log"); break;
1493 	case FINT:
1494 		modf(getfval(x), &u); break;
1495 	case FEXP:
1496 		u = errcheck(exp(getfval(x)), "exp"); break;
1497 	case FSQRT:
1498 		u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1499 	case FSIN:
1500 		u = sin(getfval(x)); break;
1501 	case FCOS:
1502 		u = cos(getfval(x)); break;
1503 	case FATAN:
1504 		if (nextarg == 0) {
1505 			WARNING("atan2 requires two arguments; returning 1.0");
1506 			u = 1.0;
1507 		} else {
1508 			y = execute(a[1]->nnext);
1509 			u = atan2(getfval(x), getfval(y));
1510 			tempfree(y);
1511 			nextarg = nextarg->nnext;
1512 		}
1513 		break;
1514 	case FCOMPL:
1515 		u = ~((int)getfval(x));
1516 		break;
1517 	case FAND:
1518 		if (nextarg == 0) {
1519 			WARNING("and requires two arguments; returning 0");
1520 			u = 0;
1521 			break;
1522 		}
1523 		y = execute(a[1]->nnext);
1524 		u = ((int)getfval(x)) & ((int)getfval(y));
1525 		tempfree(y);
1526 		nextarg = nextarg->nnext;
1527 		break;
1528 	case FFOR:
1529 		if (nextarg == 0) {
1530 			WARNING("or requires two arguments; returning 0");
1531 			u = 0;
1532 			break;
1533 		}
1534 		y = execute(a[1]->nnext);
1535 		u = ((int)getfval(x)) | ((int)getfval(y));
1536 		tempfree(y);
1537 		nextarg = nextarg->nnext;
1538 		break;
1539 	case FXOR:
1540 		if (nextarg == 0) {
1541 			WARNING("or requires two arguments; returning 0");
1542 			u = 0;
1543 			break;
1544 		}
1545 		y = execute(a[1]->nnext);
1546 		u = ((int)getfval(x)) ^ ((int)getfval(y));
1547 		tempfree(y);
1548 		nextarg = nextarg->nnext;
1549 		break;
1550 	case FLSHIFT:
1551 		if (nextarg == 0) {
1552 			WARNING("or requires two arguments; returning 0");
1553 			u = 0;
1554 			break;
1555 		}
1556 		y = execute(a[1]->nnext);
1557 		u = ((int)getfval(x)) << ((int)getfval(y));
1558 		tempfree(y);
1559 		nextarg = nextarg->nnext;
1560 		break;
1561 	case FRSHIFT:
1562 		if (nextarg == 0) {
1563 			WARNING("or requires two arguments; returning 0");
1564 			u = 0;
1565 			break;
1566 		}
1567 		y = execute(a[1]->nnext);
1568 		u = ((int)getfval(x)) >> ((int)getfval(y));
1569 		tempfree(y);
1570 		nextarg = nextarg->nnext;
1571 		break;
1572 	case FSYSTEM:
1573 		fflush(stdout);		/* in case something is buffered already */
1574 		u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
1575 		break;
1576 	case FRAND:
1577 		if (use_arc4)
1578 			u = (Awkfloat)arc4random() / 0xffffffff;
1579 		else
1580 			u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;
1581 		break;
1582 	case FSRAND:
1583 		if (isrec(x))	/* no argument provided, want arc4random() */
1584 			use_arc4 = 1;
1585 		else {
1586 			u = getfval(x);
1587 			srandom((unsigned int) u);
1588 			use_arc4 = 0;
1589 		}
1590 		break;
1591 	case FTOUPPER:
1592 	case FTOLOWER:
1593 		buf = tostring(getsval(x));
1594 		if (t == FTOUPPER) {
1595 			for (p = buf; *p; p++)
1596 				if (islower((uschar) *p))
1597 					*p = toupper((uschar)*p);
1598 		} else {
1599 			for (p = buf; *p; p++)
1600 				if (isupper((uschar) *p))
1601 					*p = tolower((uschar)*p);
1602 		}
1603 		tempfree(x);
1604 		x = gettemp();
1605 		setsval(x, buf);
1606 		free(buf);
1607 		return x;
1608 	case FFLUSH:
1609 		if (isrec(x) || strlen(getsval(x)) == 0) {
1610 			flush_all();	/* fflush() or fflush("") -> all */
1611 			u = 0;
1612 		} else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1613 			u = EOF;
1614 		else
1615 			u = fflush(fp);
1616 		break;
1617 	default:	/* can't happen */
1618 		FATAL("illegal function type %d", t);
1619 		break;
1620 	}
1621 	tempfree(x);
1622 	x = gettemp();
1623 	setfval(x, u);
1624 	if (nextarg != 0) {
1625 		WARNING("warning: function has too many arguments");
1626 		for ( ; nextarg; nextarg = nextarg->nnext)
1627 			execute(nextarg);
1628 	}
1629 	return(x);
1630 }
1631 
1632 Cell *printstat(Node **a, int n)	/* print a[0] */
1633 {
1634 	Node *x;
1635 	Cell *y;
1636 	FILE *fp;
1637 
1638 	if (a[1] == 0)	/* a[1] is redirection operator, a[2] is file */
1639 		fp = stdout;
1640 	else
1641 		fp = redirect(ptoi(a[1]), a[2]);
1642 	for (x = a[0]; x != NULL; x = x->nnext) {
1643 		y = execute(x);
1644 		fputs(getpssval(y), fp);
1645 		tempfree(y);
1646 		if (x->nnext == NULL)
1647 			fputs(*ORS, fp);
1648 		else
1649 			fputs(*OFS, fp);
1650 	}
1651 	if (a[1] != 0)
1652 		fflush(fp);
1653 	if (ferror(fp))
1654 		FATAL("write error on %s", filename(fp));
1655 	return(True);
1656 }
1657 
1658 Cell *nullproc(Node **a, int n)
1659 {
1660 	n = n;
1661 	a = a;
1662 	return 0;
1663 }
1664 
1665 
1666 FILE *redirect(int a, Node *b)	/* set up all i/o redirections */
1667 {
1668 	FILE *fp;
1669 	Cell *x;
1670 	char *fname;
1671 
1672 	x = execute(b);
1673 	fname = getsval(x);
1674 	fp = openfile(a, fname);
1675 	if (fp == NULL)
1676 		FATAL("can't open file %s", fname);
1677 	tempfree(x);
1678 	return fp;
1679 }
1680 
1681 struct files {
1682 	FILE	*fp;
1683 	const char	*fname;
1684 	int	mode;	/* '|', 'a', 'w' => LE/LT, GT */
1685 } files[FOPEN_MAX] ={
1686 	{ NULL,  "/dev/stdin",  LT },	/* watch out: don't free this! */
1687 	{ NULL, "/dev/stdout", GT },
1688 	{ NULL, "/dev/stderr", GT }
1689 };
1690 
1691 void stdinit(void)	/* in case stdin, etc., are not constants */
1692 {
1693 	files[0].fp = stdin;
1694 	files[1].fp = stdout;
1695 	files[2].fp = stderr;
1696 }
1697 
1698 FILE *openfile(int a, const char *us)
1699 {
1700 	const char *s = us;
1701 	int i, m;
1702 	FILE *fp = 0;
1703 
1704 	if (*s == '\0')
1705 		FATAL("null file name in print or getline");
1706 	for (i=0; i < FOPEN_MAX; i++)
1707 		if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1708 			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1709 				return files[i].fp;
1710 			if (a == FFLUSH)
1711 				return files[i].fp;
1712 		}
1713 	if (a == FFLUSH)	/* didn't find it, so don't create it! */
1714 		return NULL;
1715 
1716 	for (i=0; i < FOPEN_MAX; i++)
1717 		if (files[i].fp == 0)
1718 			break;
1719 	if (i >= FOPEN_MAX)
1720 		FATAL("%s makes too many open files", s);
1721 	fflush(stdout);	/* force a semblance of order */
1722 	m = a;
1723 	if (a == GT) {
1724 		fp = fopen(s, "w");
1725 	} else if (a == APPEND) {
1726 		fp = fopen(s, "a");
1727 		m = GT;	/* so can mix > and >> */
1728 	} else if (a == '|') {	/* output pipe */
1729 		fp = popen(s, "w");
1730 	} else if (a == LE) {	/* input pipe */
1731 		fp = popen(s, "r");
1732 	} else if (a == LT) {	/* getline <file */
1733 		fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r");	/* "-" is stdin */
1734 	} else	/* can't happen */
1735 		FATAL("illegal redirection %d", a);
1736 	if (fp != NULL) {
1737 		files[i].fname = tostring(s);
1738 		files[i].fp = fp;
1739 		files[i].mode = m;
1740 	}
1741 	return fp;
1742 }
1743 
1744 const char *filename(FILE *fp)
1745 {
1746 	int i;
1747 
1748 	for (i = 0; i < FOPEN_MAX; i++)
1749 		if (fp == files[i].fp)
1750 			return files[i].fname;
1751 	return "???";
1752 }
1753 
1754 Cell *closefile(Node **a, int n)
1755 {
1756 	Cell *x;
1757 	int i, stat;
1758 
1759 	n = n;
1760 	x = execute(a[0]);
1761 	getsval(x);
1762 	stat = -1;
1763 	for (i = 0; i < FOPEN_MAX; i++) {
1764 		if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1765 			if (ferror(files[i].fp))
1766 				WARNING( "i/o error occurred on %s", files[i].fname );
1767 			if (files[i].mode == '|' || files[i].mode == LE)
1768 				stat = pclose(files[i].fp);
1769 			else
1770 				stat = fclose(files[i].fp);
1771 			if (stat == EOF)
1772 				WARNING( "i/o error occurred closing %s", files[i].fname );
1773 			if (i > 2)	/* don't do /dev/std... */
1774 				xfree(files[i].fname);
1775 			files[i].fname = NULL;	/* watch out for ref thru this */
1776 			files[i].fp = NULL;
1777 		}
1778 	}
1779 	tempfree(x);
1780 	x = gettemp();
1781 	setfval(x, (Awkfloat) stat);
1782 	return(x);
1783 }
1784 
1785 void closeall(void)
1786 {
1787 	int i, stat;
1788 
1789 	for (i = 0; i < FOPEN_MAX; i++) {
1790 		if (files[i].fp) {
1791 			if (ferror(files[i].fp))
1792 				WARNING( "i/o error occurred on %s", files[i].fname );
1793 			if (files[i].mode == '|' || files[i].mode == LE)
1794 				stat = pclose(files[i].fp);
1795 			else
1796 				stat = fclose(files[i].fp);
1797 			if (stat == EOF)
1798 				WARNING( "i/o error occurred while closing %s", files[i].fname );
1799 		}
1800 	}
1801 }
1802 
1803 void flush_all(void)
1804 {
1805 	int i;
1806 
1807 	for (i = 0; i < FOPEN_MAX; i++)
1808 		if (files[i].fp)
1809 			fflush(files[i].fp);
1810 }
1811 
1812 void backsub(char **pb_ptr, char **sptr_ptr);
1813 
1814 Cell *sub(Node **a, int nnn)	/* substitute command */
1815 {
1816 	char *sptr, *pb, *q;
1817 	Cell *x, *y, *result;
1818 	char *t, *buf;
1819 	fa *pfa;
1820 	int bufsz = recsize;
1821 
1822 	if ((buf = (char *) malloc(bufsz)) == NULL)
1823 		FATAL("out of memory in sub");
1824 	x = execute(a[3]);	/* target string */
1825 	t = getsval(x);
1826 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1827 		pfa = (fa *) a[1];	/* regular expression */
1828 	else {
1829 		y = execute(a[1]);
1830 		pfa = makedfa(getsval(y), 1);
1831 		tempfree(y);
1832 	}
1833 	y = execute(a[2]);	/* replacement string */
1834 	result = False;
1835 	if (pmatch(pfa, t)) {
1836 		sptr = t;
1837 		adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1838 		pb = buf;
1839 		while (sptr < patbeg)
1840 			*pb++ = *sptr++;
1841 		sptr = getsval(y);
1842 		while (*sptr != 0) {
1843 			adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1844 			if (*sptr == '\\') {
1845 				backsub(&pb, &sptr);
1846 			} else if (*sptr == '&') {
1847 				sptr++;
1848 				adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1849 				for (q = patbeg; q < patbeg+patlen; )
1850 					*pb++ = *q++;
1851 			} else
1852 				*pb++ = *sptr++;
1853 		}
1854 		*pb = '\0';
1855 		if (pb > buf + bufsz)
1856 			FATAL("sub result1 %.30s too big; can't happen", buf);
1857 		sptr = patbeg + patlen;
1858 		if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1859 			adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1860 			while ((*pb++ = *sptr++) != 0)
1861 				;
1862 		}
1863 		if (pb > buf + bufsz)
1864 			FATAL("sub result2 %.30s too big; can't happen", buf);
1865 		setsval(x, buf);	/* BUG: should be able to avoid copy */
1866 		result = True;
1867 	}
1868 	tempfree(x);
1869 	tempfree(y);
1870 	free(buf);
1871 	return result;
1872 }
1873 
1874 Cell *gsub(Node **a, int nnn)	/* global substitute */
1875 {
1876 	Cell *x, *y;
1877 	char *rptr, *sptr, *t, *pb, *q;
1878 	char *buf;
1879 	fa *pfa;
1880 	int mflag, tempstat, num;
1881 	int bufsz = recsize;
1882 
1883 	if ((buf = (char *) malloc(bufsz)) == NULL)
1884 		FATAL("out of memory in gsub");
1885 	mflag = 0;	/* if mflag == 0, can replace empty string */
1886 	num = 0;
1887 	x = execute(a[3]);	/* target string */
1888 	t = getsval(x);
1889 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1890 		pfa = (fa *) a[1];	/* regular expression */
1891 	else {
1892 		y = execute(a[1]);
1893 		pfa = makedfa(getsval(y), 1);
1894 		tempfree(y);
1895 	}
1896 	y = execute(a[2]);	/* replacement string */
1897 	if (pmatch(pfa, t)) {
1898 		tempstat = pfa->initstat;
1899 		pfa->initstat = 2;
1900 		pb = buf;
1901 		rptr = getsval(y);
1902 		do {
1903 			if (patlen == 0 && *patbeg != 0) {	/* matched empty string */
1904 				if (mflag == 0) {	/* can replace empty */
1905 					num++;
1906 					sptr = rptr;
1907 					while (*sptr != 0) {
1908 						adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1909 						if (*sptr == '\\') {
1910 							backsub(&pb, &sptr);
1911 						} else if (*sptr == '&') {
1912 							sptr++;
1913 							adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1914 							for (q = patbeg; q < patbeg+patlen; )
1915 								*pb++ = *q++;
1916 						} else
1917 							*pb++ = *sptr++;
1918 					}
1919 				}
1920 				if (*t == 0)	/* at end */
1921 					goto done;
1922 				adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1923 				*pb++ = *t++;
1924 				if (pb > buf + bufsz)	/* BUG: not sure of this test */
1925 					FATAL("gsub result0 %.30s too big; can't happen", buf);
1926 				mflag = 0;
1927 			}
1928 			else {	/* matched nonempty string */
1929 				num++;
1930 				sptr = t;
1931 				adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1932 				while (sptr < patbeg)
1933 					*pb++ = *sptr++;
1934 				sptr = rptr;
1935 				while (*sptr != 0) {
1936 					adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1937 					if (*sptr == '\\') {
1938 						backsub(&pb, &sptr);
1939 					} else if (*sptr == '&') {
1940 						sptr++;
1941 						adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1942 						for (q = patbeg; q < patbeg+patlen; )
1943 							*pb++ = *q++;
1944 					} else
1945 						*pb++ = *sptr++;
1946 				}
1947 				t = patbeg + patlen;
1948 				if (patlen == 0 || *t == 0 || *(t-1) == 0)
1949 					goto done;
1950 				if (pb > buf + bufsz)
1951 					FATAL("gsub result1 %.30s too big; can't happen", buf);
1952 				mflag = 1;
1953 			}
1954 		} while (pmatch(pfa,t));
1955 		sptr = t;
1956 		adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1957 		while ((*pb++ = *sptr++) != 0)
1958 			;
1959 	done:	if (pb > buf + bufsz)
1960 			FATAL("gsub result2 %.30s too big; can't happen", buf);
1961 		*pb = '\0';
1962 		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
1963 		pfa->initstat = tempstat;
1964 	}
1965 	tempfree(x);
1966 	tempfree(y);
1967 	x = gettemp();
1968 	x->tval = NUM;
1969 	x->fval = num;
1970 	free(buf);
1971 	return(x);
1972 }
1973 
1974 void backsub(char **pb_ptr, char **sptr_ptr)	/* handle \\& variations */
1975 {						/* sptr[0] == '\\' */
1976 	char *pb = *pb_ptr, *sptr = *sptr_ptr;
1977 
1978 	if (sptr[1] == '\\') {
1979 		if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1980 			*pb++ = '\\';
1981 			*pb++ = '&';
1982 			sptr += 4;
1983 		} else if (sptr[2] == '&') {	/* \\& -> \ + matched */
1984 			*pb++ = '\\';
1985 			sptr += 2;
1986 		} else {			/* \\x -> \\x */
1987 			*pb++ = *sptr++;
1988 			*pb++ = *sptr++;
1989 		}
1990 	} else if (sptr[1] == '&') {	/* literal & */
1991 		sptr++;
1992 		*pb++ = *sptr++;
1993 	} else				/* literal \ */
1994 		*pb++ = *sptr++;
1995 
1996 	*pb_ptr = pb;
1997 	*sptr_ptr = sptr;
1998 }
1999