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