xref: /csrg-svn/old/awk/run.c (revision 6676)
1*6676Smckusick /*	run.c	4.1	82/05/07	*/
2*6676Smckusick 
3*6676Smckusick #include "awk.def"
4*6676Smckusick #include	"math.h"
5*6676Smckusick #define RECSIZE 512
6*6676Smckusick #include "awk.h"
7*6676Smckusick #include "stdio.h"
8*6676Smckusick 
9*6676Smckusick #define FILENUM	10
10*6676Smckusick struct
11*6676Smckusick {
12*6676Smckusick 	FILE *fp;
13*6676Smckusick 	char *fname;
14*6676Smckusick } files[FILENUM];
15*6676Smckusick FILE *popen();
16*6676Smckusick 
17*6676Smckusick extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp();
18*6676Smckusick #define PA2NUM	29
19*6676Smckusick int pairstack[PA2NUM], paircnt;
20*6676Smckusick node *winner = (node *)NULL;
21*6676Smckusick #define MAXTMP 20
22*6676Smckusick cell tmps[MAXTMP];
23*6676Smckusick static cell nullval ={0,0,0.0,NUM,0};
24*6676Smckusick obj	true	={ OBOOL, BTRUE, 0 };
25*6676Smckusick obj	false	={ OBOOL, BFALSE, 0 };
26*6676Smckusick 
27*6676Smckusick run()
28*6676Smckusick {
29*6676Smckusick 	execute(winner);
30*6676Smckusick }
31*6676Smckusick 
32*6676Smckusick obj execute(u) node *u;
33*6676Smckusick {
34*6676Smckusick 	register obj (*proc)();
35*6676Smckusick 	obj x;
36*6676Smckusick 	node *a;
37*6676Smckusick 	extern char *printname[];
38*6676Smckusick 
39*6676Smckusick 	if (u==(node *)NULL)
40*6676Smckusick 		return(true);
41*6676Smckusick 	for (a = u; ; a = a->nnext) {
42*6676Smckusick 		if (cantexec(a))
43*6676Smckusick 			return(nodetoobj(a));
44*6676Smckusick 		if (a->ntype==NPA2)
45*6676Smckusick 			proc=dopa2;
46*6676Smckusick 		else {
47*6676Smckusick 			if (notlegal(a->nobj))
48*6676Smckusick 				error(FATAL, "illegal statement %o", a);
49*6676Smckusick 			proc = proctab[a->nobj-FIRSTTOKEN];
50*6676Smckusick 		}
51*6676Smckusick 		x = (*proc)(a->narg,a->nobj);
52*6676Smckusick 		if (isfld(x)) fldbld();
53*6676Smckusick 		if (isexpr(a))
54*6676Smckusick 			return(x);
55*6676Smckusick 		/* a statement, goto next statement */
56*6676Smckusick 		if (isjump(x))
57*6676Smckusick 			return(x);
58*6676Smckusick 		if (a->nnext == (node *)NULL)
59*6676Smckusick 			return(x);
60*6676Smckusick 		tempfree(x);
61*6676Smckusick 	}
62*6676Smckusick }
63*6676Smckusick 
64*6676Smckusick obj program(a, n) node **a;
65*6676Smckusick {
66*6676Smckusick 	obj x;
67*6676Smckusick 
68*6676Smckusick 	if (a[0] != NULL) {
69*6676Smckusick 		x = execute(a[0]);
70*6676Smckusick 		if (isexit(x))
71*6676Smckusick 			return(true);
72*6676Smckusick 		if (isjump(x))
73*6676Smckusick 			error(FATAL, "unexpected break, continue or next");
74*6676Smckusick 		tempfree(x);
75*6676Smckusick 	}
76*6676Smckusick 	while (getrec()) {
77*6676Smckusick 		x = execute(a[1]);
78*6676Smckusick 		if (isexit(x)) break;
79*6676Smckusick 		tempfree(x);
80*6676Smckusick 	}
81*6676Smckusick 	tempfree(x);
82*6676Smckusick 	if (a[2] != NULL) {
83*6676Smckusick 		x = execute(a[2]);
84*6676Smckusick 		if (isbreak(x) || isnext(x) || iscont(x))
85*6676Smckusick 			error(FATAL, "unexpected break, continue or next");
86*6676Smckusick 		tempfree(x);
87*6676Smckusick 	}
88*6676Smckusick 	return(true);
89*6676Smckusick }
90*6676Smckusick 
91*6676Smckusick obj getline()
92*6676Smckusick {
93*6676Smckusick 	obj x;
94*6676Smckusick 
95*6676Smckusick 	x = gettemp();
96*6676Smckusick 	setfval(x.optr, (awkfloat) getrec());
97*6676Smckusick 	return(x);
98*6676Smckusick }
99*6676Smckusick 
100*6676Smckusick obj array(a,n) node **a;
101*6676Smckusick {
102*6676Smckusick 	obj x, y;
103*6676Smckusick 	extern obj arrayel();
104*6676Smckusick 
105*6676Smckusick 	x = execute(a[1]);
106*6676Smckusick 	y = arrayel(a[0], x);
107*6676Smckusick 	tempfree(x);
108*6676Smckusick 	return(y);
109*6676Smckusick }
110*6676Smckusick 
111*6676Smckusick obj arrayel(a,b) node *a; obj b;
112*6676Smckusick {
113*6676Smckusick 	char *s;
114*6676Smckusick 	cell *x;
115*6676Smckusick 	int i;
116*6676Smckusick 	obj y;
117*6676Smckusick 
118*6676Smckusick 	s = getsval(b.optr);
119*6676Smckusick 	x = (cell *) a;
120*6676Smckusick 	if (!(x->tval&ARR)) {
121*6676Smckusick 		xfree(x->sval);
122*6676Smckusick 		x->tval &= ~STR;
123*6676Smckusick 		x->tval |= ARR;
124*6676Smckusick 		x->sval = (char *) makesymtab();
125*6676Smckusick 	}
126*6676Smckusick 	y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval);
127*6676Smckusick 	y.otype = OCELL;
128*6676Smckusick 	y.osub = CVAR;
129*6676Smckusick 	return(y);
130*6676Smckusick }
131*6676Smckusick 
132*6676Smckusick obj matchop(a,n) node **a;
133*6676Smckusick {
134*6676Smckusick 	obj x;
135*6676Smckusick 	char *s;
136*6676Smckusick 	int i;
137*6676Smckusick 
138*6676Smckusick 	x = execute(a[0]);
139*6676Smckusick 	if (isstr(x)) s = x.optr->sval;
140*6676Smckusick 	else	s = getsval(x.optr);
141*6676Smckusick 	tempfree(x);
142*6676Smckusick 	i = match(a[1], s);
143*6676Smckusick 	if (n==MATCH && i==1 || n==NOTMATCH && i==0)
144*6676Smckusick 		return(true);
145*6676Smckusick 	else
146*6676Smckusick 		return(false);
147*6676Smckusick }
148*6676Smckusick 
149*6676Smckusick obj boolop(a,n) node **a;
150*6676Smckusick {
151*6676Smckusick 	obj x, y;
152*6676Smckusick 	int i;
153*6676Smckusick 
154*6676Smckusick 	x = execute(a[0]);
155*6676Smckusick 	i = istrue(x);
156*6676Smckusick 	tempfree(x);
157*6676Smckusick 	switch (n) {
158*6676Smckusick 	default:
159*6676Smckusick 		error(FATAL, "unknown boolean operator %d", n);
160*6676Smckusick 	case BOR:
161*6676Smckusick 		if (i) return(true);
162*6676Smckusick 		y = execute(a[1]);
163*6676Smckusick 		i = istrue(y);
164*6676Smckusick 		tempfree(y);
165*6676Smckusick 		if (i) return(true);
166*6676Smckusick 		else return(false);
167*6676Smckusick 	case AND:
168*6676Smckusick 		if ( !i ) return(false);
169*6676Smckusick 		y = execute(a[1]);
170*6676Smckusick 		i = istrue(y);
171*6676Smckusick 		tempfree(y);
172*6676Smckusick 		if (i) return(true);
173*6676Smckusick 		else return(false);
174*6676Smckusick 	case NOT:
175*6676Smckusick 		if (i) return(false);
176*6676Smckusick 		else return(true);
177*6676Smckusick 	}
178*6676Smckusick }
179*6676Smckusick 
180*6676Smckusick obj relop(a,n) node **a;
181*6676Smckusick {
182*6676Smckusick 	int i;
183*6676Smckusick 	obj x, y;
184*6676Smckusick 	awkfloat j;
185*6676Smckusick 
186*6676Smckusick 	x = execute(a[0]);
187*6676Smckusick 	y = execute(a[1]);
188*6676Smckusick 	if (x.optr->tval&NUM && y.optr->tval&NUM) {
189*6676Smckusick 		j = x.optr->fval - y.optr->fval;
190*6676Smckusick 		i = j<0? -1: (j>0? 1: 0);
191*6676Smckusick 	} else {
192*6676Smckusick 		i = strcmp(getsval(x.optr), getsval(y.optr));
193*6676Smckusick 	}
194*6676Smckusick 	tempfree(x);
195*6676Smckusick 	tempfree(y);
196*6676Smckusick 	switch (n) {
197*6676Smckusick 	default:
198*6676Smckusick 		error(FATAL, "unknown relational operator %d", n);
199*6676Smckusick 	case LT:	if (i<0) return(true);
200*6676Smckusick 			else return(false);
201*6676Smckusick 	case LE:	if (i<=0) return(true);
202*6676Smckusick 			else return(false);
203*6676Smckusick 	case NE:	if (i!=0) return(true);
204*6676Smckusick 			else return(false);
205*6676Smckusick 	case EQ:	if (i==0) return(true);
206*6676Smckusick 			else return(false);
207*6676Smckusick 	case GE:	if (i>=0) return(true);
208*6676Smckusick 			else return(false);
209*6676Smckusick 	case GT:	if (i>0) return(true);
210*6676Smckusick 			else return(false);
211*6676Smckusick 	}
212*6676Smckusick }
213*6676Smckusick 
214*6676Smckusick tempfree(a) obj a;
215*6676Smckusick {
216*6676Smckusick 	if (!istemp(a)) return;
217*6676Smckusick 	xfree(a.optr->sval);
218*6676Smckusick 	a.optr->tval = 0;
219*6676Smckusick }
220*6676Smckusick 
221*6676Smckusick obj gettemp()
222*6676Smckusick {
223*6676Smckusick 	int i;
224*6676Smckusick 	obj x;
225*6676Smckusick 
226*6676Smckusick 	for (i=0; i<MAXTMP; i++)
227*6676Smckusick 		if (tmps[i].tval==0)
228*6676Smckusick 			break;
229*6676Smckusick 	if (i==MAXTMP)
230*6676Smckusick 		error(FATAL, "out of temporaries in gettemp");
231*6676Smckusick 	x.optr = &tmps[i];
232*6676Smckusick 	tmps[i] = nullval;
233*6676Smckusick 	x.otype = OCELL;
234*6676Smckusick 	x.osub = CTEMP;
235*6676Smckusick 	return(x);
236*6676Smckusick }
237*6676Smckusick 
238*6676Smckusick obj indirect(a,n) node **a;
239*6676Smckusick {
240*6676Smckusick 	obj x;
241*6676Smckusick 	int m;
242*6676Smckusick 	cell *fieldadr();
243*6676Smckusick 
244*6676Smckusick 	x = execute(a[0]);
245*6676Smckusick 	m = getfval(x.optr);
246*6676Smckusick 	tempfree(x);
247*6676Smckusick 	x.optr = fieldadr(m);
248*6676Smckusick 	x.otype = OCELL;
249*6676Smckusick 	x.osub = CFLD;
250*6676Smckusick 	return(x);
251*6676Smckusick }
252*6676Smckusick 
253*6676Smckusick obj substr(a, nnn) node **a;
254*6676Smckusick {
255*6676Smckusick 	char *s, temp;
256*6676Smckusick 	obj x;
257*6676Smckusick 	int k, m, n;
258*6676Smckusick 
259*6676Smckusick 	x = execute(a[0]);
260*6676Smckusick 	s = getsval(x.optr);
261*6676Smckusick 	k = strlen(s) + 1;
262*6676Smckusick 	tempfree(x);
263*6676Smckusick 	x = execute(a[1]);
264*6676Smckusick 	m = getfval(x.optr);
265*6676Smckusick 	if (m <= 0)
266*6676Smckusick 		m = 1;
267*6676Smckusick 	else if (m > k)
268*6676Smckusick 		m = k;
269*6676Smckusick 	tempfree(x);
270*6676Smckusick 	if (a[2] != nullstat) {
271*6676Smckusick 		x = execute(a[2]);
272*6676Smckusick 		n = getfval(x.optr);
273*6676Smckusick 		tempfree(x);
274*6676Smckusick 	}
275*6676Smckusick 	else
276*6676Smckusick 		n = k - 1;
277*6676Smckusick 	if (n < 0)
278*6676Smckusick 		n = 0;
279*6676Smckusick 	else if (n > k - m)
280*6676Smckusick 		n = k - m;
281*6676Smckusick 	dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s);
282*6676Smckusick 	x = gettemp();
283*6676Smckusick 	temp = s[n+m-1];	/* with thanks to John Linderman */
284*6676Smckusick 	s[n+m-1] = '\0';
285*6676Smckusick 	setsval(x.optr, s + m - 1);
286*6676Smckusick 	s[n+m-1] = temp;
287*6676Smckusick 	return(x);
288*6676Smckusick }
289*6676Smckusick 
290*6676Smckusick obj sindex(a, nnn) node **a;
291*6676Smckusick {
292*6676Smckusick 	obj x;
293*6676Smckusick 	char *s1, *s2, *p1, *p2, *q;
294*6676Smckusick 
295*6676Smckusick 	x = execute(a[0]);
296*6676Smckusick 	s1 = getsval(x.optr);
297*6676Smckusick 	tempfree(x);
298*6676Smckusick 	x = execute(a[1]);
299*6676Smckusick 	s2 = getsval(x.optr);
300*6676Smckusick 	tempfree(x);
301*6676Smckusick 
302*6676Smckusick 	x = gettemp();
303*6676Smckusick 	for (p1 = s1; *p1 != '\0'; p1++) {
304*6676Smckusick 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
305*6676Smckusick 			;
306*6676Smckusick 		if (*p2 == '\0') {
307*6676Smckusick 			setfval(x.optr, (awkfloat) (p1 - s1 + 1));	/* origin 1 */
308*6676Smckusick 			return(x);
309*6676Smckusick 		}
310*6676Smckusick 	}
311*6676Smckusick 	setfval(x.optr, 0.0);
312*6676Smckusick 	return(x);
313*6676Smckusick }
314*6676Smckusick 
315*6676Smckusick char *format(s,a) char *s; node *a;
316*6676Smckusick {
317*6676Smckusick 	char *buf, *p, fmt[200], *t, *os;
318*6676Smckusick 	obj x;
319*6676Smckusick 	int flag = 0;
320*6676Smckusick 	awkfloat xf;
321*6676Smckusick 
322*6676Smckusick 	os = s;
323*6676Smckusick 	p = buf = (char *)malloc(RECSIZE);
324*6676Smckusick 	while (*s) {
325*6676Smckusick 		if (*s != '%') {
326*6676Smckusick 			*p++ = *s++;
327*6676Smckusick 			continue;
328*6676Smckusick 		}
329*6676Smckusick 		if (*(s+1) == '%') {
330*6676Smckusick 			*p++ = '%';
331*6676Smckusick 			s += 2;
332*6676Smckusick 			continue;
333*6676Smckusick 		}
334*6676Smckusick 		for (t=fmt; (*t++ = *s) != '\0'; s++)
335*6676Smckusick 			if (*s >= 'a' && *s <= 'z' && *s != 'l')
336*6676Smckusick 				break;
337*6676Smckusick 		*t = '\0';
338*6676Smckusick 		if (t >= fmt + sizeof(fmt))
339*6676Smckusick 			error(FATAL, "format item %.20s... too long", os);
340*6676Smckusick 		switch (*s) {
341*6676Smckusick 		case 'f': case 'e': case 'g':
342*6676Smckusick 			flag = 1;
343*6676Smckusick 			break;
344*6676Smckusick 		case 'd':
345*6676Smckusick 			flag = 2;
346*6676Smckusick 			if(*(s-1) == 'l') break;
347*6676Smckusick 			*(t-1) = 'l';
348*6676Smckusick 			*t = 'd';
349*6676Smckusick 			*++t = '\0';
350*6676Smckusick 			break;
351*6676Smckusick 		case 'o': case 'x':
352*6676Smckusick 			flag = *(s-1)=='l' ? 2 : 3;
353*6676Smckusick 			break;
354*6676Smckusick 		case 'c':
355*6676Smckusick 			flag = 3;
356*6676Smckusick 			break;
357*6676Smckusick 		case 's':
358*6676Smckusick 			flag = 4;
359*6676Smckusick 			break;
360*6676Smckusick 		default:
361*6676Smckusick 			flag = 0;
362*6676Smckusick 			break;
363*6676Smckusick 		}
364*6676Smckusick 		if (flag == 0) {
365*6676Smckusick 			sprintf(p, "%s", fmt);
366*6676Smckusick 			p += strlen(p);
367*6676Smckusick 			continue;
368*6676Smckusick 		}
369*6676Smckusick 		if (a == NULL)
370*6676Smckusick 			error(FATAL, "not enough arguments in printf(%s)", os);
371*6676Smckusick 		x = execute(a);
372*6676Smckusick 		a = a->nnext;
373*6676Smckusick 		if (flag != 4)	/* watch out for converting to numbers! */
374*6676Smckusick 			xf = getfval(x.optr);
375*6676Smckusick 		if (flag==1) sprintf(p, fmt, xf);
376*6676Smckusick 		else if (flag==2) sprintf(p, fmt, (long)xf);
377*6676Smckusick 		else if (flag==3) sprintf(p, fmt, (int)xf);
378*6676Smckusick 		else if (flag==4) sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr));
379*6676Smckusick 		tempfree(x);
380*6676Smckusick 		p += strlen(p);
381*6676Smckusick 		s++;
382*6676Smckusick 	}
383*6676Smckusick 	*p = '\0';
384*6676Smckusick 	return(buf);
385*6676Smckusick }
386*6676Smckusick 
387*6676Smckusick obj asprintf(a,n) node **a;
388*6676Smckusick {
389*6676Smckusick 	obj x;
390*6676Smckusick 	node *y;
391*6676Smckusick 	char *s;
392*6676Smckusick 
393*6676Smckusick 	y = a[0]->nnext;
394*6676Smckusick 	x = execute(a[0]);
395*6676Smckusick 	s = format(getsval(x.optr), y);
396*6676Smckusick 	tempfree(x);
397*6676Smckusick 	x = gettemp();
398*6676Smckusick 	x.optr->sval = s;
399*6676Smckusick 	x.optr->tval = STR;
400*6676Smckusick 	return(x);
401*6676Smckusick }
402*6676Smckusick 
403*6676Smckusick obj arith(a,n) node **a;
404*6676Smckusick {
405*6676Smckusick 	awkfloat i,j;
406*6676Smckusick 	obj x,y,z;
407*6676Smckusick 
408*6676Smckusick 	x = execute(a[0]);
409*6676Smckusick 	i = getfval(x.optr);
410*6676Smckusick 	tempfree(x);
411*6676Smckusick 	if (n != UMINUS) {
412*6676Smckusick 		y = execute(a[1]);
413*6676Smckusick 		j = getfval(y.optr);
414*6676Smckusick 		tempfree(y);
415*6676Smckusick 	}
416*6676Smckusick 	z = gettemp();
417*6676Smckusick 	switch (n) {
418*6676Smckusick 	default:
419*6676Smckusick 		error(FATAL, "illegal arithmetic operator %d", n);
420*6676Smckusick 	case ADD:
421*6676Smckusick 		i += j;
422*6676Smckusick 		break;
423*6676Smckusick 	case MINUS:
424*6676Smckusick 		i -= j;
425*6676Smckusick 		break;
426*6676Smckusick 	case MULT:
427*6676Smckusick 		i *= j;
428*6676Smckusick 		break;
429*6676Smckusick 	case DIVIDE:
430*6676Smckusick 		if (j == 0)
431*6676Smckusick 			error(FATAL, "division by zero");
432*6676Smckusick 		i /= j;
433*6676Smckusick 		break;
434*6676Smckusick 	case MOD:
435*6676Smckusick 		if (j == 0)
436*6676Smckusick 			error(FATAL, "division by zero");
437*6676Smckusick 		i = i - j*(long)(i/j);
438*6676Smckusick 		break;
439*6676Smckusick 	case UMINUS:
440*6676Smckusick 		i = -i;
441*6676Smckusick 		break;
442*6676Smckusick 	}
443*6676Smckusick 	setfval(z.optr, i);
444*6676Smckusick 	return(z);
445*6676Smckusick }
446*6676Smckusick 
447*6676Smckusick obj incrdecr(a, n) node **a;
448*6676Smckusick {
449*6676Smckusick 	obj x, z;
450*6676Smckusick 	int k;
451*6676Smckusick 	awkfloat xf;
452*6676Smckusick 
453*6676Smckusick 	x = execute(a[0]);
454*6676Smckusick 	xf = getfval(x.optr);
455*6676Smckusick 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
456*6676Smckusick 	if (n == PREINCR || n == PREDECR) {
457*6676Smckusick 		setfval(x.optr, xf + k);
458*6676Smckusick 		return(x);
459*6676Smckusick 	}
460*6676Smckusick 	z = gettemp();
461*6676Smckusick 	setfval(z.optr, xf);
462*6676Smckusick 	setfval(x.optr, xf + k);
463*6676Smckusick 	tempfree(x);
464*6676Smckusick 	return(z);
465*6676Smckusick }
466*6676Smckusick 
467*6676Smckusick 
468*6676Smckusick obj assign(a,n) node **a;
469*6676Smckusick {
470*6676Smckusick 	obj x, y;
471*6676Smckusick 	awkfloat xf, yf;
472*6676Smckusick 
473*6676Smckusick 	x = execute(a[0]);
474*6676Smckusick 	y = execute(a[1]);
475*6676Smckusick 	if (n == ASSIGN) {	/* ordinary assignment */
476*6676Smckusick 		if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) {
477*6676Smckusick 			setsval(x.optr, y.optr->sval);
478*6676Smckusick 			x.optr->fval = y.optr->fval;
479*6676Smckusick 			x.optr->tval |= NUM;
480*6676Smckusick 		}
481*6676Smckusick 		else if (y.optr->tval & STR)
482*6676Smckusick 			setsval(x.optr, y.optr->sval);
483*6676Smckusick 		else if (y.optr->tval & NUM)
484*6676Smckusick 			setfval(x.optr, y.optr->fval);
485*6676Smckusick 		tempfree(y);
486*6676Smckusick 		return(x);
487*6676Smckusick 	}
488*6676Smckusick 	xf = getfval(x.optr);
489*6676Smckusick 	yf = getfval(y.optr);
490*6676Smckusick 	switch (n) {
491*6676Smckusick 	case ADDEQ:
492*6676Smckusick 		xf += yf;
493*6676Smckusick 		break;
494*6676Smckusick 	case SUBEQ:
495*6676Smckusick 		xf -= yf;
496*6676Smckusick 		break;
497*6676Smckusick 	case MULTEQ:
498*6676Smckusick 		xf *= yf;
499*6676Smckusick 		break;
500*6676Smckusick 	case DIVEQ:
501*6676Smckusick 		if (yf == 0)
502*6676Smckusick 			error(FATAL, "division by zero");
503*6676Smckusick 		xf /= yf;
504*6676Smckusick 		break;
505*6676Smckusick 	case MODEQ:
506*6676Smckusick 		if (yf == 0)
507*6676Smckusick 			error(FATAL, "division by zero");
508*6676Smckusick 		xf = xf - yf*(long)(xf/yf);
509*6676Smckusick 		break;
510*6676Smckusick 	default:
511*6676Smckusick 		error(FATAL, "illegal assignment operator %d", n);
512*6676Smckusick 		break;
513*6676Smckusick 	}
514*6676Smckusick 	tempfree(y);
515*6676Smckusick 	setfval(x.optr, xf);
516*6676Smckusick 	return(x);
517*6676Smckusick }
518*6676Smckusick 
519*6676Smckusick obj cat(a,q) node **a;
520*6676Smckusick {
521*6676Smckusick 	obj x,y,z;
522*6676Smckusick 	int n1, n2;
523*6676Smckusick 	char *s;
524*6676Smckusick 
525*6676Smckusick 	x = execute(a[0]);
526*6676Smckusick 	y = execute(a[1]);
527*6676Smckusick 	getsval(x.optr);
528*6676Smckusick 	getsval(y.optr);
529*6676Smckusick 	n1 = strlen(x.optr->sval);
530*6676Smckusick 	n2 = strlen(y.optr->sval);
531*6676Smckusick 	s = (char *) malloc(n1 + n2 + 1);
532*6676Smckusick 	strcpy(s, x.optr->sval);
533*6676Smckusick 	strcpy(s+n1, y.optr->sval);
534*6676Smckusick 	tempfree(y);
535*6676Smckusick 	z = gettemp();
536*6676Smckusick 	z.optr->sval = s;
537*6676Smckusick 	z.optr->tval = STR;
538*6676Smckusick 	tempfree(x);
539*6676Smckusick 	return(z);
540*6676Smckusick }
541*6676Smckusick 
542*6676Smckusick obj pastat(a,n) node **a;
543*6676Smckusick {
544*6676Smckusick 	obj x;
545*6676Smckusick 
546*6676Smckusick 	if (a[0]==nullstat)
547*6676Smckusick 		x = true;
548*6676Smckusick 	else
549*6676Smckusick 		x = execute(a[0]);
550*6676Smckusick 	if (istrue(x)) {
551*6676Smckusick 		tempfree(x);
552*6676Smckusick 		x = execute(a[1]);
553*6676Smckusick 	}
554*6676Smckusick 	return(x);
555*6676Smckusick }
556*6676Smckusick 
557*6676Smckusick obj dopa2(a,n) node **a;
558*6676Smckusick {
559*6676Smckusick 	obj x;
560*6676Smckusick 
561*6676Smckusick 	if (pairstack[n]==0) {
562*6676Smckusick 		x = execute(a[0]);
563*6676Smckusick 		if (istrue(x))
564*6676Smckusick 			pairstack[n] = 1;
565*6676Smckusick 		tempfree(x);
566*6676Smckusick 	}
567*6676Smckusick 	if (pairstack[n] == 1) {
568*6676Smckusick 		x = execute(a[1]);
569*6676Smckusick 		if (istrue(x))
570*6676Smckusick 			pairstack[n] = 0;
571*6676Smckusick 		tempfree(x);
572*6676Smckusick 		x = execute(a[2]);
573*6676Smckusick 		return(x);
574*6676Smckusick 	}
575*6676Smckusick 	return(false);
576*6676Smckusick }
577*6676Smckusick 
578*6676Smckusick obj aprintf(a,n) node **a;
579*6676Smckusick {
580*6676Smckusick 	obj x;
581*6676Smckusick 
582*6676Smckusick 	x = asprintf(a,n);
583*6676Smckusick 	if (a[1]==NULL) {
584*6676Smckusick 		printf("%s", x.optr->sval);
585*6676Smckusick 		tempfree(x);
586*6676Smckusick 		return(true);
587*6676Smckusick 	}
588*6676Smckusick 	redirprint(x.optr->sval, (int)a[1], a[2]);
589*6676Smckusick 	return(x);
590*6676Smckusick }
591*6676Smckusick 
592*6676Smckusick obj split(a,nnn) node **a;
593*6676Smckusick {
594*6676Smckusick 	obj x;
595*6676Smckusick 	cell *ap;
596*6676Smckusick 	register char *s, *p;
597*6676Smckusick 	char *t, temp, num[5];
598*6676Smckusick 	register int sep;
599*6676Smckusick 	int n, flag;
600*6676Smckusick 
601*6676Smckusick 	x = execute(a[0]);
602*6676Smckusick 	s = getsval(x.optr);
603*6676Smckusick 	tempfree(x);
604*6676Smckusick 	if (a[2] == nullstat)
605*6676Smckusick 		sep = **FS;
606*6676Smckusick 	else {
607*6676Smckusick 		x = execute(a[2]);
608*6676Smckusick 		sep = getsval(x.optr)[0];
609*6676Smckusick 		tempfree(x);
610*6676Smckusick 	}
611*6676Smckusick 	ap = (cell *) a[1];
612*6676Smckusick 	freesymtab(ap);
613*6676Smckusick 	dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep);
614*6676Smckusick 	ap->tval &= ~STR;
615*6676Smckusick 	ap->tval |= ARR;
616*6676Smckusick 	ap->sval = (char *) makesymtab();
617*6676Smckusick 
618*6676Smckusick 	n = 0;
619*6676Smckusick 	if (sep == ' ')
620*6676Smckusick 		for (n = 0; ; ) {
621*6676Smckusick 			while (*s == ' ' || *s == '\t' || *s == '\n')
622*6676Smckusick 				s++;
623*6676Smckusick 			if (*s == 0)
624*6676Smckusick 				break;
625*6676Smckusick 			n++;
626*6676Smckusick 			t = s;
627*6676Smckusick 			do
628*6676Smckusick 				s++;
629*6676Smckusick 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
630*6676Smckusick 			temp = *s;
631*6676Smckusick 			*s = '\0';
632*6676Smckusick 			sprintf(num, "%d", n);
633*6676Smckusick 			if (isnumber(t))
634*6676Smckusick 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
635*6676Smckusick 			else
636*6676Smckusick 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
637*6676Smckusick 			*s = temp;
638*6676Smckusick 			if (*s != 0)
639*6676Smckusick 				s++;
640*6676Smckusick 		}
641*6676Smckusick 	else if (*s != 0)
642*6676Smckusick 		for (;;) {
643*6676Smckusick 			n++;
644*6676Smckusick 			t = s;
645*6676Smckusick 			while (*s != sep && *s != '\n' && *s != '\0')
646*6676Smckusick 				s++;
647*6676Smckusick 			temp = *s;
648*6676Smckusick 			*s = '\0';
649*6676Smckusick 			sprintf(num, "%d", n);
650*6676Smckusick 			if (isnumber(t))
651*6676Smckusick 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
652*6676Smckusick 			else
653*6676Smckusick 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
654*6676Smckusick 			*s = temp;
655*6676Smckusick 			if (*s++ == 0)
656*6676Smckusick 				break;
657*6676Smckusick 		}
658*6676Smckusick 	x = gettemp();
659*6676Smckusick 	x.optr->tval = NUM;
660*6676Smckusick 	x.optr->fval = n;
661*6676Smckusick 	return(x);
662*6676Smckusick }
663*6676Smckusick 
664*6676Smckusick obj ifstat(a,n) node **a;
665*6676Smckusick {
666*6676Smckusick 	obj x;
667*6676Smckusick 
668*6676Smckusick 	x = execute(a[0]);
669*6676Smckusick 	if (istrue(x)) {
670*6676Smckusick 		tempfree(x);
671*6676Smckusick 		x = execute(a[1]);
672*6676Smckusick 	}
673*6676Smckusick 	else if (a[2] != nullstat) {
674*6676Smckusick 		tempfree(x);
675*6676Smckusick 		x = execute(a[2]);
676*6676Smckusick 	}
677*6676Smckusick 	return(x);
678*6676Smckusick }
679*6676Smckusick 
680*6676Smckusick obj whilestat(a,n) node **a;
681*6676Smckusick {
682*6676Smckusick 	obj x;
683*6676Smckusick 
684*6676Smckusick 	for (;;) {
685*6676Smckusick 		x = execute(a[0]);
686*6676Smckusick 		if (!istrue(x)) return(x);
687*6676Smckusick 		tempfree(x);
688*6676Smckusick 		x = execute(a[1]);
689*6676Smckusick 		if (isbreak(x)) {
690*6676Smckusick 			x = true;
691*6676Smckusick 			return(x);
692*6676Smckusick 		}
693*6676Smckusick 		if (isnext(x) || isexit(x))
694*6676Smckusick 			return(x);
695*6676Smckusick 		tempfree(x);
696*6676Smckusick 	}
697*6676Smckusick }
698*6676Smckusick 
699*6676Smckusick obj forstat(a,n) node **a;
700*6676Smckusick {
701*6676Smckusick 	obj x;
702*6676Smckusick 
703*6676Smckusick 	tempfree(execute(a[0]));
704*6676Smckusick 	for (;;) {
705*6676Smckusick 		if (a[1]!=nullstat) {
706*6676Smckusick 			x = execute(a[1]);
707*6676Smckusick 			if (!istrue(x)) return(x);
708*6676Smckusick 			else tempfree(x);
709*6676Smckusick 		}
710*6676Smckusick 		x = execute(a[3]);
711*6676Smckusick 		if (isbreak(x)) {	/* turn off break */
712*6676Smckusick 			x = true;
713*6676Smckusick 			return(x);
714*6676Smckusick 		}
715*6676Smckusick 		if (isnext(x) || isexit(x))
716*6676Smckusick 			return(x);
717*6676Smckusick 		tempfree(x);
718*6676Smckusick 		tempfree(execute(a[2]));
719*6676Smckusick 	}
720*6676Smckusick }
721*6676Smckusick 
722*6676Smckusick obj instat(a, n) node **a;
723*6676Smckusick {
724*6676Smckusick 	cell *vp, *arrayp, *cp, **tp;
725*6676Smckusick 	obj x;
726*6676Smckusick 	int i;
727*6676Smckusick 
728*6676Smckusick 	vp = (cell *) a[0];
729*6676Smckusick 	arrayp = (cell *) a[1];
730*6676Smckusick 	if (!(arrayp->tval & ARR))
731*6676Smckusick 		error(FATAL, "%s is not an array", arrayp->nval);
732*6676Smckusick 	tp = (cell **) arrayp->sval;
733*6676Smckusick 	for (i = 0; i < MAXSYM; i++) {	/* this routine knows too much */
734*6676Smckusick 		for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
735*6676Smckusick 			setsval(vp, cp->nval);
736*6676Smckusick 			x = execute(a[2]);
737*6676Smckusick 			if (isbreak(x)) {
738*6676Smckusick 				x = true;
739*6676Smckusick 				return(x);
740*6676Smckusick 			}
741*6676Smckusick 			if (isnext(x) || isexit(x))
742*6676Smckusick 				return(x);
743*6676Smckusick 			tempfree(x);
744*6676Smckusick 		}
745*6676Smckusick 	}
746*6676Smckusick }
747*6676Smckusick 
748*6676Smckusick obj jump(a,n) node **a;
749*6676Smckusick {
750*6676Smckusick 	obj x, y;
751*6676Smckusick 
752*6676Smckusick 	x.otype = OJUMP;
753*6676Smckusick 	switch (n) {
754*6676Smckusick 	default:
755*6676Smckusick 		error(FATAL, "illegal jump type %d", n);
756*6676Smckusick 		break;
757*6676Smckusick 	case EXIT:
758*6676Smckusick 		if (a[0] != 0) {
759*6676Smckusick 			y = execute(a[0]);
760*6676Smckusick 			errorflag = getfval(y.optr);
761*6676Smckusick 		}
762*6676Smckusick 		x.osub = JEXIT;
763*6676Smckusick 		break;
764*6676Smckusick 	case NEXT:
765*6676Smckusick 		x.osub = JNEXT;
766*6676Smckusick 		break;
767*6676Smckusick 	case BREAK:
768*6676Smckusick 		x.osub = JBREAK;
769*6676Smckusick 		break;
770*6676Smckusick 	case CONTINUE:
771*6676Smckusick 		x.osub = JCONT;
772*6676Smckusick 		break;
773*6676Smckusick 	}
774*6676Smckusick 	return(x);
775*6676Smckusick }
776*6676Smckusick 
777*6676Smckusick obj fncn(a,n) node **a;
778*6676Smckusick {
779*6676Smckusick 	obj x;
780*6676Smckusick 	awkfloat u;
781*6676Smckusick 	int t;
782*6676Smckusick 
783*6676Smckusick 	t = (int) a[0];
784*6676Smckusick 	x = execute(a[1]);
785*6676Smckusick 	if (t == FLENGTH)
786*6676Smckusick 		u = (awkfloat) strlen(getsval(x.optr));
787*6676Smckusick 	else if (t == FLOG)
788*6676Smckusick 		u = log(getfval(x.optr));
789*6676Smckusick 	else if (t == FINT)
790*6676Smckusick 		u = (awkfloat) (long) getfval(x.optr);
791*6676Smckusick 	else if (t == FEXP)
792*6676Smckusick 		u = exp(getfval(x.optr));
793*6676Smckusick 	else if (t == FSQRT)
794*6676Smckusick 		u = sqrt(getfval(x.optr));
795*6676Smckusick 	else
796*6676Smckusick 		error(FATAL, "illegal function type %d", t);
797*6676Smckusick 	tempfree(x);
798*6676Smckusick 	x = gettemp();
799*6676Smckusick 	setfval(x.optr, u);
800*6676Smckusick 	return(x);
801*6676Smckusick }
802*6676Smckusick 
803*6676Smckusick obj print(a,n) node **a;
804*6676Smckusick {
805*6676Smckusick 	register node *x;
806*6676Smckusick 	obj y;
807*6676Smckusick 	char s[RECSIZE];
808*6676Smckusick 
809*6676Smckusick 	s[0] = '\0';
810*6676Smckusick 	for (x=a[0]; x!=NULL; x=x->nnext) {
811*6676Smckusick 		y = execute(x);
812*6676Smckusick 		strcat(s, getsval(y.optr));
813*6676Smckusick 		tempfree(y);
814*6676Smckusick 		if (x->nnext==NULL)
815*6676Smckusick 			strcat(s, *ORS);
816*6676Smckusick 		else
817*6676Smckusick 			strcat(s, *OFS);
818*6676Smckusick 	}
819*6676Smckusick 	if (strlen(s) >= RECSIZE)
820*6676Smckusick 		error(FATAL, "string %.20s ... too long to print", s);
821*6676Smckusick 	if (a[1]==nullstat) {
822*6676Smckusick 		printf("%s", s);
823*6676Smckusick 		return(true);
824*6676Smckusick 	}
825*6676Smckusick 	redirprint(s, (int)a[1], a[2]);
826*6676Smckusick 	return(false);
827*6676Smckusick }
828*6676Smckusick 
829*6676Smckusick obj nullproc() {}
830*6676Smckusick 
831*6676Smckusick obj nodetoobj(a) node *a;
832*6676Smckusick {
833*6676Smckusick 	obj x;
834*6676Smckusick 
835*6676Smckusick 	x.optr = (cell *) a->nobj;
836*6676Smckusick 	x.otype = OCELL;
837*6676Smckusick 	x.osub = a->subtype;
838*6676Smckusick 	if (isfld(x)) fldbld();
839*6676Smckusick 	return(x);
840*6676Smckusick }
841*6676Smckusick 
842*6676Smckusick redirprint(s, a, b) char *s; node *b;
843*6676Smckusick {
844*6676Smckusick 	register int i;
845*6676Smckusick 	obj x;
846*6676Smckusick 
847*6676Smckusick 	x = execute(b);
848*6676Smckusick 	getsval(x.optr);
849*6676Smckusick 	for (i=0; i<FILENUM; i++)
850*6676Smckusick 		if (files[i].fp && strcmp(x.optr->sval, files[i].fname) == 0)
851*6676Smckusick 			goto doit;
852*6676Smckusick 	for (i=0; i<FILENUM; i++)
853*6676Smckusick 		if (files[i].fp == 0)
854*6676Smckusick 			break;
855*6676Smckusick 	if (i >= FILENUM)
856*6676Smckusick 		error(FATAL, "too many output files %d", i);
857*6676Smckusick 	if (a == '|')	/* a pipe! */
858*6676Smckusick 		files[i].fp = popen(x.optr->sval, "w");
859*6676Smckusick 	else if (a == APPEND)
860*6676Smckusick 		files[i].fp = fopen(x.optr->sval, "a");
861*6676Smckusick 	else
862*6676Smckusick 		files[i].fp = fopen(x.optr->sval, "w");
863*6676Smckusick 	if (files[i].fp == NULL)
864*6676Smckusick 		error(FATAL, "can't open file %s", x.optr->sval);
865*6676Smckusick 	files[i].fname = tostring(x.optr->sval);
866*6676Smckusick doit:
867*6676Smckusick 	fprintf(files[i].fp, "%s", s);
868*6676Smckusick #ifndef gcos
869*6676Smckusick 	fflush(files[i].fp);	/* in case someone is waiting for the output */
870*6676Smckusick #endif
871*6676Smckusick 	tempfree(x);
872*6676Smckusick }
873