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