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