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