xref: /titanic_52/usr/src/cmd/oawk/run.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 
27 
28 
29 /*
30  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
31  * Use is subject to license terms.
32  */
33 
34 
35 #ident	"%Z%%M%	%I%	%E% SMI"
36 #define	DEBUG
37 #define	tempfree(a)	{if (istemp(a)) {xfree(a->sval); a->tval = 0; }}
38 
39 #include	"awk.def"
40 #include	"math.h"
41 #include	"awk.h"
42 #include	"stdio.h"
43 #include "ctype.h"
44 #include "wctype.h"
45 #include "awktype.h"
46 #include <stdlib.h>
47 
48 #define	RECSIZE BUFSIZ
49 
50 #define	FILENUM	10
51 struct
52 {
53 	FILE *fp;
54 	int type;
55 	wchar_t *fname;
56 } files[FILENUM];
57 FILE *popen();
58 
59 extern CELL *execute(), *nodetoobj(), *fieldel(), *dopa2(), *gettemp();
60 
61 #define	PA2NUM	29
62 int	pairstack[PA2NUM], paircnt;
63 NODE	*winner = NULL;
64 #define	MAXTMP	20
65 CELL	tmps[MAXTMP];
66 
67 static CELL	truecell	={ OBOOL, BTRUE, 0, 0, 0.0, NUM, 0 };
68 CELL	*true	= &truecell;
69 static CELL	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM, 0 };
70 CELL	*false	= &falsecell;
71 static CELL	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM, 0 };
72 CELL	*jbreak	= &breakcell;
73 static CELL	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM, 0 };
74 CELL	*jcont	= &contcell;
75 static CELL	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM, 0 };
76 CELL	*jnext	= &nextcell;
77 static CELL	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM, 0 };
78 CELL	*jexit	= &exitcell;
79 static CELL	tempcell	={ OCELL, CTEMP, 0, 0, 0.0, NUM, 0 };
80 
81 run(a) NODE *a;
82 {
83 	register int i;
84 
85 	execute(a);
86 	/* Wait for children to complete if output to a pipe. */
87 	for (i=0; i<FILENUM; i++)
88 		if (files[i].fp && files[i].type == '|')
89 			pclose(files[i].fp);
90 }
91 
92 
93 CELL *execute(u) NODE *u;
94 {
95 	register CELL *(*proc)();
96 	register CELL *x;
97 	register NODE *a;
98 
99 	if (u == NULL)
100 		return (true);
101 	for (a = u; /* dummy */; a = a->nnext) {
102 		if (cantexec(a))
103 			return (nodetoobj(a));
104 		if (notlegal(a->nobj))
105 			error(FATAL, "illegal statement %o", a);
106 		proc = proctab[a->nobj-FIRSTTOKEN];
107 		x = (*proc)(a->narg, a->nobj);
108 		if (isfld(x))
109 			fldbld();
110 		if (isexpr(a))
111 			return (x);
112 		/* a statement, goto next statement */
113 		if (isjump(x))
114 			return (x);
115 		if (a->nnext == (NODE *)NULL)
116 			return (x);
117 		tempfree(x);
118 	}
119 }
120 
121 
122 
123 
124 CELL *program(a, n) register NODE **a;
125 {
126 	register CELL *x;
127 
128 	if (a[0] != NULL) {
129 		x = execute(a[0]);
130 		if (isexit(x))
131 			return (true);
132 		if (isjump(x))
133 			error(FATAL, "unexpected break, continue or next");
134 		tempfree(x);
135 	}
136 	while (getrec()) {
137 		x = execute(a[1]);
138 		if (isexit(x)) {
139 			tempfree(x);
140 			break;
141 		}
142 		tempfree(x);
143 	}
144 	if (a[2] != NULL) {
145 		x = execute(a[2]);
146 		if (isbreak(x) || isnext(x) || iscont(x))
147 			error(FATAL, "unexpected break, continue or next");
148 		tempfree(x);
149 	}
150 	return (true);
151 }
152 
153 
154 
155 
156 CELL *getline()
157 {
158 	register CELL *x;
159 
160 	x = gettemp();
161 	setfval(x, (awkfloat) getrec());
162 	return (x);
163 }
164 
165 
166 
167 
168 CELL *array(a, n) register NODE **a;
169 {
170 	register CELL *x, *y;
171 	extern CELL *arrayel();
172 
173 	x = execute(a[1]);
174 	y = arrayel(a[0], x);
175 	tempfree(x);
176 	return (y);
177 }
178 
179 
180 
181 
182 CELL *arrayel(a, b) NODE *a; CELL *b;
183 {
184 	register wchar_t *s;
185 	register CELL *x;
186 	register int i;
187 	register CELL *y;
188 
189 	s = getsval(b);
190 	x = (CELL *) a;
191 	if (!(x->tval&ARR)) {
192 		xfree(x->sval);
193 		x->tval &= ~STR;
194 		x->tval |= ARR;
195 		x->sval = (wchar_t *) makesymtab();
196 	}
197 	y = setsymtab(s, tostring(L_NULL), 0.0, STR|NUM, x->sval);
198 	y->ctype = OCELL;
199 	y->csub = CVAR;
200 	return (y);
201 }
202 
203 CELL *matchop(a, n) NODE **a;
204 {
205 	register CELL *x;
206 	register wchar_t *s;
207 	register int i;
208 
209 	x = execute(a[0]);
210 	s = getsval(x);
211 	tempfree(x);
212 	i = match(a[1], s);
213 	if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
214 		return (true);
215 	else
216 		return (false);
217 }
218 
219 
220 
221 
222 CELL *boolop(a, n) NODE **a;
223 {
224 	register CELL *x, *y;
225 	register int i;
226 
227 
228 
229 
230 	x = execute(a[0]);
231 	i = istrue(x);
232 	tempfree(x);
233 	switch (n) {
234 	case BOR:
235 		if (i) return (true);
236 		y = execute(a[1]);
237 		i = istrue(y);
238 		tempfree(y);
239 		if (i) return (true);
240 		else return (false);
241 	case AND:
242 		if (!i) return (false);
243 		y = execute(a[1]);
244 		i = istrue(y);
245 		tempfree(y);
246 		if (i) return (true);
247 		else return (false);
248 	case NOT:
249 		if (i) return (false);
250 		else return (true);
251 	default:
252 		error(FATAL, "unknown boolean operator %d", n);
253 	}
254 }
255 
256 
257 
258 
259 CELL *relop(a, n) NODE **a;
260 {
261 	register int i;
262 	register CELL *x, *y;
263 	awkfloat j;
264 	register wchar_t *xs, *ys;
265 
266 
267 
268 
269 	x = execute(a[0]);
270 	y = execute(a[1]);
271 	if (x->tval&NUM && y->tval&NUM) {
272 		j = x->fval - y->fval;
273 		i = j<0? -1: (j>0? 1: 0);
274 	} else {
275 		xs = getsval(x);
276 		ys = getsval(y);
277 		if (xs && ys)
278 			i = wscoll(xs, ys);
279 		else
280 			return (false);
281 	}
282 	tempfree(x);
283 	tempfree(y);
284 	switch (n) {
285 	case LT:	if (i<0) return (true);
286 			else return (false);
287 	case LE:	if (i<=0) return (true);
288 			else return (false);
289 	case NE:	if (i!=0) return (true);
290 			else return (false);
291 	case EQ:	if (i == 0) return (true);
292 			else return (false);
293 	case GE:	if (i>=0) return (true);
294 			else return (false);
295 	case GT:	if (i>0) return (true);
296 			else return (false);
297 	default:
298 		error(FATAL, "unknown relational operator %d", n);
299 	}
300 }
301 
302 
303 
304 
305 
306 
307 
308 
309 CELL *gettemp()
310 {
311 	register int i;
312 	register CELL *x;
313 
314 
315 
316 
317 	for (i=0; i<MAXTMP; i++)
318 		if (tmps[i].tval == 0)
319 			break;
320 	if (i == MAXTMP)
321 		error(FATAL, "out of temporaries in gettemp");
322 	tmps[i] = tempcell;
323 	x = &tmps[i];
324 	return (x);
325 }
326 
327 
328 
329 
330 CELL *indirect(a, n) NODE **a;
331 {
332 	register CELL *x;
333 	register int m;
334 	CELL *fieldadr();
335 
336 	x = execute(a[0]);
337 	m = getfval(x);
338 	tempfree(x);
339 	x = fieldadr(m);
340 	x->ctype = OCELL;
341 	x->csub = CFLD;
342 	return (x);
343 }
344 
345 
346 
347 
348 CELL *substr(a, nnn) NODE **a;
349 {
350 	register int k, m, n;
351 	register wchar_t *s, temp;
352 	register CELL *x, *y;
353 
354 	y = execute(a[0]);
355 	s = getsval(y);
356 	k = wslen(s) + 1;
357 	if (k <= 1) {
358 		x = gettemp();
359 		setsval(x, L_NULL);
360 		return (x);
361 	}
362 	x = execute(a[1]);
363 	m = getfval(x);
364 	if (m <= 0)
365 		m = 1;
366 	else if (m > k)
367 		m = k;
368 	tempfree(x);
369 	if (a[2] != 0) {
370 		x = execute(a[2]);
371 		n = getfval(x);
372 		tempfree(x);
373 	}
374 	else
375 		n = k - 1;
376 	if (n < 0)
377 		n = 0;
378 	else if (n > k - m)
379 		n = k - m;
380 	dprintf("substr: m=%d, n=%d, s=%ws\n", m, n, s);
381 	x = gettemp();
382 	temp = s[n+m-1];
383 	s[n+m-1] = (wchar_t)0x0;
384 	setsval(x, s + m - 1);
385 	s[n+m-1] = temp;
386 	tempfree(y);
387 	return (x);
388 }
389 
390 
391 
392 
393 CELL *sindex(a, nnn) NODE **a;
394 {
395 	register CELL *x;
396 	register wchar_t *s1, *s2, *p1, *p2, *q;
397 
398 	x = execute(a[0]);
399 	s1 = getsval(x);
400 	tempfree(x);
401 	x = execute(a[1]);
402 	s2 = getsval(x);
403 	tempfree(x);
404 
405 	x = gettemp();
406 	for (p1 = s1; *p1 != (wchar_t)0x0; p1++) {
407 		for (q=p1, p2=s2; *p2 != (wchar_t)0x0 && *q == *p2; q++, p2++)
408 			;
409 		if (*p2 == (wchar_t)0x0) {
410 			setfval(x, (awkfloat) (p1 - s1 + 1));	/* origin 1 */
411 			return (x);
412 		}
413 	}
414 	setfval(x, 0.0);
415 	return (x);
416 }
417 
418 
419 
420 
421 wchar_t *format(s, a) register wchar_t *s; NODE *a;
422 {
423 	register wchar_t *buf, *ep, *str;
424 	register wchar_t *p;
425 	register char *t;
426 	wchar_t *os;
427 	wchar_t tbuf[2*RECSIZE];
428 	char fmt[200];
429 	register CELL *x;
430 	int flag = 0;
431 	awkfloat xf;
432 
433 	os = s;
434 	p = buf= (wchar_t *)malloc(RECSIZE * sizeof (wchar_t));
435 
436 	if (p == NULL)
437 		error(FATAL, "out of space in format");
438 	ep = p + RECSIZE;
439 	while (*s) {
440 		if (*s != '%') {
441 			*p++ = *s++;
442 			continue;
443 		}
444 		if (*(s+1) == '%') {
445 			*p++ = '%';
446 			s += 2;
447 			continue;
448 		}
449 		for (t=fmt; *s != '\0'; s++)
450 		{
451 			if (*s == 's' || *s == 'c')
452 				*t++ = 'w';
453 			*t++ = *s;
454 			if (*s >= 'a' && *s <= 'z' && *s != 'l')
455 				break;
456 			if (*s == '*') {
457 				if (a == NULL) {
458 					error(FATAL,
459 			"not enough arguments in printf(%ws) or sprintf(%ws)",
460 					os, os);
461 				}
462 				x = execute(a);
463 				a = a->nnext;
464 				sprintf(t-1, "%d", (int) getfval(x));
465 				t = fmt + strlen(fmt);
466 				tempfree(x);
467 			}
468 
469 		}
470 		*t = '\0';
471 		if (t >= fmt + sizeof (fmt))
472 			error(FATAL, "format item %.20ws... too long", os);
473 		switch (*s) {
474 		case 'f': case 'e': case 'g':
475 			flag = 1;
476 			break;
477 		case 'd':
478 			flag = 2;
479 			if (*(s-1) == 'l') break;
480 			*(t-1) = 'l';
481 			*t = 'd';
482 			*++t = '\0';
483 			break;
484 		case 'o': case 'x':
485 			flag = *(s-1) == 'l' ? 2 : 3;
486 			break;
487 		case 'c':
488 			flag = 3;
489 			break;
490 		case 's':
491 			flag = 4;
492 			break;
493 		default:
494 			flag = 0;
495 			break;
496 		}
497 		if (flag == 0) {
498 			wsprintf(p, "%s", fmt);
499 			p += wslen(p);
500 			continue;
501 		}
502 		if (a == NULL) {
503 			error(FATAL,
504 	"not enough arguments in printf(%ws) or sprintf(%ws)", os, os);
505 		}
506 		x = execute(a);
507 		a = a->nnext;
508 
509 		/*
510 		 * Get the string to check length; %s is the usual problem;
511 		 * other conversions can cause overrun if they occur when
512 		 * the buffer is almost filled.
513 		 */
514 		if (flag == 4)	{ /* watch out for converting to numbers! */
515 			str = getsval(x);
516 		}
517 		else {
518 			xf = getfval(x);
519 			if (flag == 1) wsprintf(tbuf, fmt, xf);
520 			else if (flag == 2) wsprintf(tbuf, fmt, (long)xf);
521 			else if (flag == 3) wsprintf(tbuf, fmt, (int)xf);
522 			if (wslen(tbuf) >= RECSIZE)
523 				error(FATAL, "formatted item %s... too long",
524 						tbuf);
525 			str = tbuf;
526 		}
527 		/*
528 		 * If string overruns the buffer, reallocate;
529 		 * consider length of format string
530 		 */
531 		if (p + wslen(str) + wslen(s) + 1 >= ep) {
532 			int newlen, oldlen;
533 
534 			oldlen = p - buf;
535 			/* Add RECSIZE for additional space */
536 			newlen = oldlen + wslen(str) + RECSIZE;
537 			buf = realloc(buf, (unsigned) newlen * sizeof(wchar_t));
538 			if (buf == NULL)
539 				error(FATAL, "out of format space");
540 			p = buf + oldlen;
541 			ep = buf + newlen;
542 		}
543 		/* Transfer string to buffer */
544 		if (flag == 4)
545 			wsprintf(p, fmt, str);
546 		else
547 			wscpy(p, str);
548 
549 		tempfree(x);
550 		p += wslen(p);
551 		if (p >= ep)
552 			error(FATAL, "formatted string too long");
553 		s++;
554 	}
555 	*p = '\0';
556 	return (buf);
557 }
558 
559 
560 CELL *asprintf(a, n) NODE **a;
561 {
562 	register CELL *x;
563 	register NODE *y;
564 	register wchar_t *s;
565 
566 	y = a[0]->nnext;
567 	x = execute(a[0]);
568 	s = format(getsval(x), y);
569 	tempfree(x);
570 	x = gettemp();
571 	x->sval = s;
572 	x->tval = STR;
573 	return (x);
574 }
575 
576 
577 CELL *arith(a, n) NODE **a;
578 {
579 	awkfloat i, j;
580 	register CELL *x, *y, *z;
581 
582 	x = execute(a[0]);
583 	i = getfval(x);
584 	tempfree(x);
585 	if (n != UMINUS) {
586 		y = execute(a[1]);
587 		j = getfval(y);
588 		tempfree(y);
589 	}
590 	z = gettemp();
591 	switch (n) {
592 	case ADD:
593 		i += j;
594 		break;
595 	case MINUS:
596 		i -= j;
597 		break;
598 	case MULT:
599 		i *= j;
600 		break;
601 	case DIVIDE:
602 		if (j == 0)
603 			error(FATAL, "division by zero");
604 		i /= j;
605 		break;
606 	case MOD:
607 		if (j == 0)
608 			error(FATAL, "division by zero");
609 		i = i - j*(long)(i/j);
610 		break;
611 	case UMINUS:
612 		i = -i;
613 		break;
614 	default:
615 		error(FATAL, "illegal arithmetic operator %d", n);
616 	}
617 	setfval(z, i);
618 	return (z);
619 }
620 
621 
622 
623 
624 CELL *incrdecr(a, n) NODE **a;
625 {
626 	register CELL *x, *z;
627 	register int k;
628 	awkfloat xf;
629 
630 	x = execute(a[0]);
631 	xf = getfval(x);
632 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
633 	if (n == PREINCR || n == PREDECR) {
634 		setfval(x, xf + k);
635 		return (x);
636 	}
637 	z = gettemp();
638 	setfval(z, xf);
639 	setfval(x, xf + k);
640 	tempfree(x);
641 	return (z);
642 }
643 
644 
645 
646 CELL *assign(a, n) NODE **a;
647 {
648 	register CELL *x, *y;
649 	awkfloat xf, yf;
650 
651 
652 
653 
654 	x = execute(a[0]);
655 	y = execute(a[1]);
656 	if (n == ASSIGN) {	/* ordinary assignment */
657 		if ((y->tval & (STR|NUM)) == (STR|NUM)) {
658 			setsval(x, y->sval);
659 			x->fval = y->fval;
660 			x->tval |= NUM;
661 
662 		} else if (y->tval & STR)
663 			setsval(x, y->sval);
664 		else if (y->tval & NUM)
665 			setfval(x, y->fval);
666 		tempfree(y);
667 		return (x);
668 	}
669 	xf = getfval(x);
670 	yf = getfval(y);
671 	switch (n) {
672 	case ADDEQ:
673 		xf += yf;
674 		break;
675 	case SUBEQ:
676 		xf -= yf;
677 		break;
678 	case MULTEQ:
679 		xf *= yf;
680 		break;
681 	case DIVEQ:
682 		if (yf == 0)
683 			error(FATAL, "division by zero");
684 		xf /= yf;
685 		break;
686 	case MODEQ:
687 		if (yf == 0)
688 			error(FATAL, "division by zero");
689 		xf = xf - yf*(long)(xf/yf);
690 		break;
691 	default:
692 		error(FATAL, "illegal assignment operator %d", n);
693 		break;
694 	}
695 	tempfree(y);
696 	setfval(x, xf);
697 	return (x);
698 }
699 
700 
701 
702 
703 CELL *cat(a, q) NODE **a;
704 {
705 	register CELL *x, *y, *z;
706 	register int n1, n2;
707 	register wchar_t *s;
708 
709 
710 
711 
712 	x = execute(a[0]);
713 	y = execute(a[1]);
714 	getsval(x);
715 	getsval(y);
716 	n1 = wslen(x->sval);
717 	n2 = wslen(y->sval);
718 	if ((s = (wchar_t *) malloc((n1 + n2 + 1) * sizeof (wchar_t))) == NULL)
719 		error(FATAL, "out of space in cat");
720 	wscpy(s, x->sval);
721 	wscpy(s+n1, y->sval);
722 	tempfree(y);
723 	z = gettemp();
724 	z->sval = s;
725 	z->tval = STR;
726 	tempfree(x);
727 	return (z);
728 }
729 
730 
731 
732 
733 CELL *pastat(a, n) NODE **a;
734 {
735 	register CELL *x;
736 
737 
738 
739 
740 	if (a[0] == 0)
741 		x = true;
742 	else
743 		x = execute(a[0]);
744 	if (istrue(x)) {
745 		tempfree(x);
746 		x = execute(a[1]);
747 	}
748 	return (x);
749 }
750 
751 
752 
753 
754 CELL *dopa2(a, n) NODE **a;
755 {
756 	register CELL *x;
757 	register int pair;
758 
759 
760 
761 
762 	pair = (int) a[3];
763 	if (pairstack[pair] == 0) {
764 		x = execute(a[0]);
765 		if (istrue(x))
766 			pairstack[pair] = 1;
767 		tempfree(x);
768 	}
769 	if (pairstack[pair] == 1) {
770 		x = execute(a[1]);
771 		if (istrue(x))
772 			pairstack[pair] = 0;
773 		tempfree(x);
774 		x = execute(a[2]);
775 		return (x);
776 	}
777 	return (false);
778 }
779 
780 
781 
782 
783 CELL *aprintf(a, n) NODE **a;
784 {
785 	register CELL *x;
786 
787 
788 
789 
790 	x = asprintf(a, n);
791 	if (a[1] == NULL) {
792 		printf("%ws", x->sval);
793 		tempfree(x);
794 		return (true);
795 	}
796 	redirprint(x->sval, (int)a[1], a[2]);
797 	return (x);
798 }
799 
800 
801 
802 
803 CELL *split(a, nnn) NODE **a;
804 {
805 	register CELL *x;
806 	register CELL *ap;
807 	register wchar_t *s, *p, c;
808 	wchar_t *t, temp, num[5];
809 	register wchar_t sep;
810 	int n, flag;
811 
812 
813 
814 
815 	x = execute(a[0]);
816 	s = getsval(x);
817 	tempfree(x);
818 	if (a[2] == 0)
819 		sep = **FS;
820 	else {
821 		x = execute(a[2]);
822 		sep = getsval(x)[0];
823 		tempfree(x);
824 	}
825 	ap = (CELL *) a[1];
826 	freesymtab(ap);
827 	dprintf("split: s=|%ws|, a=%ws, sep=|%wc|\n", s, ap->nval, sep);
828 	ap->tval &= ~STR;
829 	ap->tval |= ARR;
830 	ap->sval = (wchar_t *) makesymtab();
831 
832 
833 
834 
835 	n = 0;
836 	if (sep == ' ')
837 		for (n = 0; /* dummy */; /* dummy */) {
838 			c = *s;
839 			while (iswblank(c) || c == '\t' || c == '\n')
840 				c = *(++s);
841 			if (*s == 0)
842 				break;
843 			n++;
844 			t = s;
845 			do
846 				c = *(++s);
847 			while (! iswblank(c) && c != '\t' &&
848 				c != '\n' && c != '\0');
849 			temp = c;
850 			*s = (wchar_t)0x0;
851 			wsprintf(num, "%d", n);
852 			if (isanumber(t))
853 				setsymtab(num, tostring(t),
854 						watof(t), STR|NUM, ap->sval);
855 			else
856 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
857 			*s = temp;
858 			if (*s != 0)
859 				s++;
860 
861 	} else if (*s != 0)
862 		for (;;) {
863 			n++;
864 			t = s;
865 			while ((c = *s) != sep && c != '\n' && c != '\0')
866 				s++;
867 			temp = c;
868 			*s = (wchar_t)0x0;
869 			wsprintf(num, "%d", n);
870 			if (isanumber(t))
871 				setsymtab(num, tostring(t),
872 						watof(t), STR|NUM, ap->sval);
873 			else
874 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
875 			*s = temp;
876 			if (*s++ == 0)
877 				break;
878 		}
879 	x = gettemp();
880 	x->tval = NUM;
881 	x->fval = n;
882 	return (x);
883 }
884 
885 
886 
887 
888 CELL *ifstat(a, n) NODE **a;
889 {
890 	register CELL *x;
891 
892 
893 
894 
895 	x = execute(a[0]);
896 	if (istrue(x)) {
897 		tempfree(x);
898 		x = execute(a[1]);
899 
900 	} else if (a[2] != 0) {
901 		tempfree(x);
902 		x = execute(a[2]);
903 	}
904 	return (x);
905 }
906 
907 
908 
909 
910 CELL *whilestat(a, n) NODE **a;
911 {
912 	register CELL *x;
913 
914 
915 
916 
917 	for (;;) {
918 		x = execute(a[0]);
919 		if (!istrue(x)) return (x);
920 		tempfree(x);
921 		x = execute(a[1]);
922 		if (isbreak(x)) {
923 			x = true;
924 			return (x);
925 		}
926 		if (isnext(x) || isexit(x))
927 			return (x);
928 		tempfree(x);
929 	}
930 }
931 
932 
933 
934 
935 CELL *forstat(a, n) NODE **a;
936 {
937 	register CELL *x;
938 	register CELL *z;
939 
940 
941 
942 
943 	z = execute(a[0]);
944 	tempfree(z);
945 	for (;;) {
946 		if (a[1]!=0) {
947 			x = execute(a[1]);
948 			if (!istrue(x)) return (x);
949 			else tempfree(x);
950 		}
951 		x = execute(a[3]);
952 		if (isbreak(x)) {	/* turn off break */
953 			x = true;
954 			return (x);
955 		}
956 		if (isnext(x) || isexit(x))
957 			return (x);
958 		tempfree(x);
959 		z = execute(a[2]);
960 		tempfree(z);
961 	}
962 }
963 
964 
965 
966 
967 CELL *instat(a, n) NODE **a;
968 {
969 	register CELL *vp, *arrayp, *cp, **tp;
970 	register CELL *x;
971 	int i;
972 
973 
974 
975 
976 	vp = (CELL *) a[0];
977 	arrayp = (CELL *) a[1];
978 	if (!(arrayp->tval & ARR))
979 		error(FATAL, "%ws is not an array", arrayp->nval);
980 	tp = (CELL **) arrayp->sval;
981 	for (i = 0; i < MAXSYM; i++) {	/* this routine knows too much */
982 		for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
983 			setsval(vp, cp->nval);
984 			x = execute(a[2]);
985 			if (isbreak(x)) {
986 				x = true;
987 				return (x);
988 			}
989 			if (isnext(x) || isexit(x))
990 				return (x);
991 			tempfree(x);
992 		}
993 	}
994 	return (true);
995 }
996 
997 
998 
999 
1000 CELL *jump(a, n) NODE **a;
1001 {
1002 	register CELL *y;
1003 
1004 
1005 
1006 
1007 	switch (n) {
1008 	case EXIT:
1009 		if (a[0] != 0) {
1010 			y = execute(a[0]);
1011 			errorflag = getfval(y);
1012 		}
1013 		return (jexit);
1014 	case NEXT:
1015 		return (jnext);
1016 	case BREAK:
1017 		return (jbreak);
1018 	case CONTINUE:
1019 		return (jcont);
1020 	default:
1021 		error(FATAL, "illegal jump type %d", n);
1022 	}
1023 }
1024 
1025 
1026 
1027 
1028 CELL *fncn(a, n) NODE **a;
1029 {
1030 	register CELL *x;
1031 	awkfloat u;
1032 	register int t;
1033 	register wchar_t *wp;
1034 
1035 	t = (int) a[0];
1036 	x = execute(a[1]);
1037 	if (t == FLENGTH)
1038 		u = (awkfloat) wslen(getsval(x));
1039 	else if (t == FLOG)
1040 		u = log(getfval(x));
1041 	else if (t == FINT)
1042 		u = (awkfloat) (long) getfval(x);
1043 	else if (t == FEXP)
1044 		u = exp(getfval(x));
1045 	else if (t == FSQRT)
1046 		u = sqrt(getfval(x));
1047 	else
1048 		error(FATAL, "illegal function type %d", t);
1049 	tempfree(x);
1050 	x = gettemp();
1051 	setfval(x, u);
1052 	return (x);
1053 }
1054 
1055 
1056 
1057 
1058 CELL *print(a, n) NODE **a;
1059 {
1060 	register NODE *x;
1061 	register CELL *y;
1062 	wchar_t s[RECSIZE];
1063 	wchar_t *ss, *bp, *ep;
1064 
1065 	s[0] = '\0';
1066 	bp = s;
1067 	ep = s + RECSIZE;
1068 	for (x=a[0]; x!=NULL; x=x->nnext) {
1069 		y = execute(x);
1070 		ss = getsval(y);
1071 		/* allocate larger buffer if needed */
1072 		if (ep < bp + wslen(bp) + wslen(ss)) {
1073 			int newlen;
1074 			wchar_t *oldbp;
1075 
1076 			newlen = wslen(bp) + wslen(ss) + 1 + 1;
1077 			oldbp = bp;
1078 			bp = malloc(newlen * sizeof(wchar_t));
1079 			if (bp == NULL)
1080 				error(FATAL, "out of space in print");
1081 			ep = bp + newlen;
1082 			wscpy(bp, oldbp);
1083 			if (oldbp != s)
1084 				free(oldbp);
1085 		}
1086 		if (ss)
1087 			wscat(bp, ss);
1088 		tempfree(y);
1089 		if (x->nnext == NULL)
1090 			wscat(bp, *ORS);
1091 		else
1092 			wscat(bp, *OFS);
1093 	}
1094 	if (a[1] == 0) {
1095 		printf("%ws", bp);
1096 		if (bp != s)
1097 			free(bp);
1098 		return (true);
1099 	}
1100 
1101 	redirprint(bp, (int)a[1], a[2]);
1102 	if (bp != s)
1103 		free(bp);
1104 	return (false);
1105 }
1106 
1107 
1108 
1109 
1110 CELL *nullproc() {}
1111 
1112 
1113 
1114 
1115 CELL *nodetoobj(a) NODE *a;
1116 {
1117 	register CELL *x;
1118 
1119 	x= (CELL *) a->nobj;
1120 	x->ctype = OCELL;
1121 	x->csub = a->subtype;
1122 	if (isfld(x))
1123 		fldbld();
1124 	return (x);
1125 }
1126 
1127 redirprint(s, a, b) wchar_t *s; NODE *b;
1128 {
1129 	register int i;
1130 	register CELL *x;
1131 
1132 	x = execute(b);
1133 	getsval(x);
1134 	for (i=0; i<FILENUM; i++)
1135 		if (files[i].fname && wscmp(x->sval, files[i].fname) == 0)
1136 			goto doit;
1137 	for (i=0; i<FILENUM; i++)
1138 		if (files[i].fp == 0)
1139 			break;
1140 	if (i >= FILENUM)
1141 		error(FATAL, "too many output files %d", i);
1142 	if (a == '|')	/* a pipe! */
1143 		files[i].fp = popen(toeuccode(x->sval), "w");
1144 	else if (a == APPEND)
1145 		files[i].fp = fopen(toeuccode(x->sval), "a");
1146 	else if (a == GT)
1147 		files[i].fp = fopen(toeuccode(x->sval), "w");
1148 	else
1149 		error(FATAL, "illegal redirection near line %lld", lineno);
1150 	if (files[i].fp == NULL)
1151 		error(FATAL, "can't open file %ws", x->sval);
1152 	files[i].fname = tostring(x->sval);
1153 	files[i].type = a;
1154 doit:
1155 	fprintf(files[i].fp, "%ws", s);
1156 #ifndef gcos
1157 	fflush(files[i].fp);	/* in case someone is waiting for the output */
1158 #endif
1159 	tempfree(x);
1160 }
1161