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