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