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