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