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