xref: /csrg-svn/old/awk/run.c (revision 33825)
114474Ssam #ifndef lint
2*33825Sbostic static char sccsid[] = "@(#)run.c	4.8 03/29/88";
314474Ssam #endif
46676Smckusick 
5*33825Sbostic #include "sys/param.h"
66676Smckusick #include "awk.def"
731027Sbostic #include "math.h"
86676Smckusick #include "awk.h"
96676Smckusick #include "stdio.h"
1031027Sbostic #include "fcntl.h"
1113177Ssam #define RECSIZE BUFSIZ
126676Smckusick 
13*33825Sbostic #define FILENUM	NOFILE
146676Smckusick struct
156676Smckusick {
166676Smckusick 	FILE *fp;
1717457Sralph 	int type;
186676Smckusick 	char *fname;
196676Smckusick } files[FILENUM];
206676Smckusick FILE *popen();
216676Smckusick 
226676Smckusick extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp();
236676Smckusick #define PA2NUM	29
246676Smckusick int pairstack[PA2NUM], paircnt;
256676Smckusick node *winner = (node *)NULL;
266676Smckusick #define MAXTMP 20
276676Smckusick cell tmps[MAXTMP];
2810794Ssam static cell nullval ={EMPTY,EMPTY,0.0,NUM,0};
296676Smckusick obj	true	={ OBOOL, BTRUE, 0 };
306676Smckusick obj	false	={ OBOOL, BFALSE, 0 };
316676Smckusick 
326676Smckusick run()
336676Smckusick {
3417457Sralph 	register int i;
3517457Sralph 
366676Smckusick 	execute(winner);
3717457Sralph 
3817457Sralph 	/* Wait for children to complete if output to a pipe. */
3917457Sralph 	for (i=0; i<FILENUM; i++)
4017457Sralph 		if (files[i].fp && files[i].type == '|')
4117457Sralph 			pclose(files[i].fp);
426676Smckusick }
436676Smckusick 
446676Smckusick obj execute(u) node *u;
456676Smckusick {
466676Smckusick 	register obj (*proc)();
476676Smckusick 	obj x;
486676Smckusick 	node *a;
496676Smckusick 	extern char *printname[];
506676Smckusick 
516676Smckusick 	if (u==(node *)NULL)
526676Smckusick 		return(true);
536676Smckusick 	for (a = u; ; a = a->nnext) {
546676Smckusick 		if (cantexec(a))
556676Smckusick 			return(nodetoobj(a));
566676Smckusick 		if (a->ntype==NPA2)
576676Smckusick 			proc=dopa2;
586676Smckusick 		else {
596676Smckusick 			if (notlegal(a->nobj))
606676Smckusick 				error(FATAL, "illegal statement %o", a);
616676Smckusick 			proc = proctab[a->nobj-FIRSTTOKEN];
626676Smckusick 		}
636676Smckusick 		x = (*proc)(a->narg,a->nobj);
646676Smckusick 		if (isfld(x)) fldbld();
656676Smckusick 		if (isexpr(a))
666676Smckusick 			return(x);
676676Smckusick 		/* a statement, goto next statement */
686676Smckusick 		if (isjump(x))
696676Smckusick 			return(x);
706676Smckusick 		if (a->nnext == (node *)NULL)
716676Smckusick 			return(x);
726676Smckusick 		tempfree(x);
736676Smckusick 	}
746676Smckusick }
756676Smckusick 
766676Smckusick obj program(a, n) node **a;
776676Smckusick {
786676Smckusick 	obj x;
796676Smckusick 
806676Smckusick 	if (a[0] != NULL) {
816676Smckusick 		x = execute(a[0]);
826676Smckusick 		if (isexit(x))
836676Smckusick 			return(true);
846676Smckusick 		if (isjump(x))
856676Smckusick 			error(FATAL, "unexpected break, continue or next");
866676Smckusick 		tempfree(x);
876676Smckusick 	}
886676Smckusick 	while (getrec()) {
896676Smckusick 		x = execute(a[1]);
906676Smckusick 		if (isexit(x)) break;
916676Smckusick 		tempfree(x);
926676Smckusick 	}
936676Smckusick 	tempfree(x);
946676Smckusick 	if (a[2] != NULL) {
956676Smckusick 		x = execute(a[2]);
966676Smckusick 		if (isbreak(x) || isnext(x) || iscont(x))
976676Smckusick 			error(FATAL, "unexpected break, continue or next");
986676Smckusick 		tempfree(x);
996676Smckusick 	}
1006676Smckusick 	return(true);
1016676Smckusick }
1026676Smckusick 
1036676Smckusick obj getline()
1046676Smckusick {
1056676Smckusick 	obj x;
1066676Smckusick 
1076676Smckusick 	x = gettemp();
1086676Smckusick 	setfval(x.optr, (awkfloat) getrec());
1096676Smckusick 	return(x);
1106676Smckusick }
1116676Smckusick 
1126676Smckusick obj array(a,n) node **a;
1136676Smckusick {
1146676Smckusick 	obj x, y;
1156676Smckusick 	extern obj arrayel();
1166676Smckusick 
1176676Smckusick 	x = execute(a[1]);
1186676Smckusick 	y = arrayel(a[0], x);
1196676Smckusick 	tempfree(x);
1206676Smckusick 	return(y);
1216676Smckusick }
1226676Smckusick 
1236676Smckusick obj arrayel(a,b) node *a; obj b;
1246676Smckusick {
1256676Smckusick 	char *s;
1266676Smckusick 	cell *x;
1276676Smckusick 	int i;
1286676Smckusick 	obj y;
1296676Smckusick 
1306676Smckusick 	s = getsval(b.optr);
1316676Smckusick 	x = (cell *) a;
1326676Smckusick 	if (!(x->tval&ARR)) {
13310794Ssam 		strfree(x->sval);
1346676Smckusick 		x->tval &= ~STR;
1356676Smckusick 		x->tval |= ARR;
1366676Smckusick 		x->sval = (char *) makesymtab();
1376676Smckusick 	}
1386676Smckusick 	y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval);
1396676Smckusick 	y.otype = OCELL;
1406676Smckusick 	y.osub = CVAR;
1416676Smckusick 	return(y);
1426676Smckusick }
1436676Smckusick 
1446676Smckusick obj matchop(a,n) node **a;
1456676Smckusick {
1466676Smckusick 	obj x;
1476676Smckusick 	char *s;
1486676Smckusick 	int i;
1496676Smckusick 
1506676Smckusick 	x = execute(a[0]);
1516676Smckusick 	if (isstr(x)) s = x.optr->sval;
1526676Smckusick 	else	s = getsval(x.optr);
1536676Smckusick 	tempfree(x);
1546676Smckusick 	i = match(a[1], s);
1556676Smckusick 	if (n==MATCH && i==1 || n==NOTMATCH && i==0)
1566676Smckusick 		return(true);
1576676Smckusick 	else
1586676Smckusick 		return(false);
1596676Smckusick }
1606676Smckusick 
1616676Smckusick obj boolop(a,n) node **a;
1626676Smckusick {
1636676Smckusick 	obj x, y;
1646676Smckusick 	int i;
1656676Smckusick 
1666676Smckusick 	x = execute(a[0]);
1676676Smckusick 	i = istrue(x);
1686676Smckusick 	tempfree(x);
1696676Smckusick 	switch (n) {
1706676Smckusick 	default:
1716676Smckusick 		error(FATAL, "unknown boolean operator %d", n);
1726676Smckusick 	case BOR:
1736676Smckusick 		if (i) return(true);
1746676Smckusick 		y = execute(a[1]);
1756676Smckusick 		i = istrue(y);
1766676Smckusick 		tempfree(y);
1776676Smckusick 		if (i) return(true);
1786676Smckusick 		else return(false);
1796676Smckusick 	case AND:
1806676Smckusick 		if ( !i ) return(false);
1816676Smckusick 		y = execute(a[1]);
1826676Smckusick 		i = istrue(y);
1836676Smckusick 		tempfree(y);
1846676Smckusick 		if (i) return(true);
1856676Smckusick 		else return(false);
1866676Smckusick 	case NOT:
1876676Smckusick 		if (i) return(false);
1886676Smckusick 		else return(true);
1896676Smckusick 	}
1906676Smckusick }
1916676Smckusick 
1926676Smckusick obj relop(a,n) node **a;
1936676Smckusick {
1946676Smckusick 	int i;
1956676Smckusick 	obj x, y;
1966676Smckusick 	awkfloat j;
1976676Smckusick 
1986676Smckusick 	x = execute(a[0]);
1996676Smckusick 	y = execute(a[1]);
2006676Smckusick 	if (x.optr->tval&NUM && y.optr->tval&NUM) {
2016676Smckusick 		j = x.optr->fval - y.optr->fval;
2026676Smckusick 		i = j<0? -1: (j>0? 1: 0);
2036676Smckusick 	} else {
2046676Smckusick 		i = strcmp(getsval(x.optr), getsval(y.optr));
2056676Smckusick 	}
2066676Smckusick 	tempfree(x);
2076676Smckusick 	tempfree(y);
2086676Smckusick 	switch (n) {
2096676Smckusick 	default:
2106676Smckusick 		error(FATAL, "unknown relational operator %d", n);
2116676Smckusick 	case LT:	if (i<0) return(true);
2126676Smckusick 			else return(false);
2136676Smckusick 	case LE:	if (i<=0) return(true);
2146676Smckusick 			else return(false);
2156676Smckusick 	case NE:	if (i!=0) return(true);
2166676Smckusick 			else return(false);
2176676Smckusick 	case EQ:	if (i==0) return(true);
2186676Smckusick 			else return(false);
2196676Smckusick 	case GE:	if (i>=0) return(true);
2206676Smckusick 			else return(false);
2216676Smckusick 	case GT:	if (i>0) return(true);
2226676Smckusick 			else return(false);
2236676Smckusick 	}
2246676Smckusick }
2256676Smckusick 
2266676Smckusick tempfree(a) obj a;
2276676Smckusick {
2286676Smckusick 	if (!istemp(a)) return;
22910794Ssam 	strfree(a.optr->sval);
2306676Smckusick 	a.optr->tval = 0;
2316676Smckusick }
2326676Smckusick 
2336676Smckusick obj gettemp()
2346676Smckusick {
2356676Smckusick 	int i;
2366676Smckusick 	obj x;
2376676Smckusick 
2386676Smckusick 	for (i=0; i<MAXTMP; i++)
2396676Smckusick 		if (tmps[i].tval==0)
2406676Smckusick 			break;
2416676Smckusick 	if (i==MAXTMP)
2426676Smckusick 		error(FATAL, "out of temporaries in gettemp");
2436676Smckusick 	x.optr = &tmps[i];
2446676Smckusick 	tmps[i] = nullval;
2456676Smckusick 	x.otype = OCELL;
2466676Smckusick 	x.osub = CTEMP;
2476676Smckusick 	return(x);
2486676Smckusick }
2496676Smckusick 
2506676Smckusick obj indirect(a,n) node **a;
2516676Smckusick {
2526676Smckusick 	obj x;
2536676Smckusick 	int m;
2546676Smckusick 	cell *fieldadr();
2556676Smckusick 
2566676Smckusick 	x = execute(a[0]);
2576676Smckusick 	m = getfval(x.optr);
2586676Smckusick 	tempfree(x);
2596676Smckusick 	x.optr = fieldadr(m);
2606676Smckusick 	x.otype = OCELL;
2616676Smckusick 	x.osub = CFLD;
2626676Smckusick 	return(x);
2636676Smckusick }
2646676Smckusick 
2656676Smckusick obj substr(a, nnn) node **a;
2666676Smckusick {
2676676Smckusick 	char *s, temp;
2686676Smckusick 	obj x;
2696676Smckusick 	int k, m, n;
2706676Smckusick 
2716676Smckusick 	x = execute(a[0]);
2726676Smckusick 	s = getsval(x.optr);
2736676Smckusick 	k = strlen(s) + 1;
2746676Smckusick 	tempfree(x);
2756676Smckusick 	x = execute(a[1]);
2766676Smckusick 	m = getfval(x.optr);
2776676Smckusick 	if (m <= 0)
2786676Smckusick 		m = 1;
2796676Smckusick 	else if (m > k)
2806676Smckusick 		m = k;
2816676Smckusick 	tempfree(x);
2826676Smckusick 	if (a[2] != nullstat) {
2836676Smckusick 		x = execute(a[2]);
2846676Smckusick 		n = getfval(x.optr);
2856676Smckusick 		tempfree(x);
2866676Smckusick 	}
2876676Smckusick 	else
2886676Smckusick 		n = k - 1;
2896676Smckusick 	if (n < 0)
2906676Smckusick 		n = 0;
2916676Smckusick 	else if (n > k - m)
2926676Smckusick 		n = k - m;
2936676Smckusick 	dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s);
2946676Smckusick 	x = gettemp();
2956676Smckusick 	temp = s[n+m-1];	/* with thanks to John Linderman */
2966676Smckusick 	s[n+m-1] = '\0';
2976676Smckusick 	setsval(x.optr, s + m - 1);
2986676Smckusick 	s[n+m-1] = temp;
2996676Smckusick 	return(x);
3006676Smckusick }
3016676Smckusick 
3026676Smckusick obj sindex(a, nnn) node **a;
3036676Smckusick {
3046676Smckusick 	obj x;
3056676Smckusick 	char *s1, *s2, *p1, *p2, *q;
3066676Smckusick 
3076676Smckusick 	x = execute(a[0]);
3086676Smckusick 	s1 = getsval(x.optr);
3096676Smckusick 	tempfree(x);
3106676Smckusick 	x = execute(a[1]);
3116676Smckusick 	s2 = getsval(x.optr);
3126676Smckusick 	tempfree(x);
3136676Smckusick 
3146676Smckusick 	x = gettemp();
3156676Smckusick 	for (p1 = s1; *p1 != '\0'; p1++) {
3166676Smckusick 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
3176676Smckusick 			;
3186676Smckusick 		if (*p2 == '\0') {
3196676Smckusick 			setfval(x.optr, (awkfloat) (p1 - s1 + 1));	/* origin 1 */
3206676Smckusick 			return(x);
3216676Smckusick 		}
3226676Smckusick 	}
3236676Smckusick 	setfval(x.optr, 0.0);
3246676Smckusick 	return(x);
3256676Smckusick }
3266676Smckusick 
3276676Smckusick char *format(s,a) char *s; node *a;
3286676Smckusick {
3296676Smckusick 	char *buf, *p, fmt[200], *t, *os;
3306676Smckusick 	obj x;
3316676Smckusick 	int flag = 0;
3326676Smckusick 	awkfloat xf;
3336676Smckusick 
3346676Smckusick 	os = s;
3356676Smckusick 	p = buf = (char *)malloc(RECSIZE);
3366676Smckusick 	while (*s) {
3376676Smckusick 		if (*s != '%') {
3386676Smckusick 			*p++ = *s++;
3396676Smckusick 			continue;
3406676Smckusick 		}
3416676Smckusick 		if (*(s+1) == '%') {
3426676Smckusick 			*p++ = '%';
3436676Smckusick 			s += 2;
3446676Smckusick 			continue;
3456676Smckusick 		}
3466676Smckusick 		for (t=fmt; (*t++ = *s) != '\0'; s++)
3476676Smckusick 			if (*s >= 'a' && *s <= 'z' && *s != 'l')
3486676Smckusick 				break;
3496676Smckusick 		*t = '\0';
3506676Smckusick 		if (t >= fmt + sizeof(fmt))
3516676Smckusick 			error(FATAL, "format item %.20s... too long", os);
3526676Smckusick 		switch (*s) {
3536676Smckusick 		case 'f': case 'e': case 'g':
3546676Smckusick 			flag = 1;
3556676Smckusick 			break;
3566676Smckusick 		case 'd':
3576676Smckusick 			flag = 2;
3586676Smckusick 			if(*(s-1) == 'l') break;
3596676Smckusick 			*(t-1) = 'l';
3606676Smckusick 			*t = 'd';
3616676Smckusick 			*++t = '\0';
3626676Smckusick 			break;
3636676Smckusick 		case 'o': case 'x':
3646676Smckusick 			flag = *(s-1)=='l' ? 2 : 3;
3656676Smckusick 			break;
3666676Smckusick 		case 'c':
3676676Smckusick 			flag = 3;
3686676Smckusick 			break;
3696676Smckusick 		case 's':
3706676Smckusick 			flag = 4;
3716676Smckusick 			break;
3726676Smckusick 		default:
3736676Smckusick 			flag = 0;
3746676Smckusick 			break;
3756676Smckusick 		}
3766676Smckusick 		if (flag == 0) {
37732424Sbostic 			(void)sprintf(p, "%s", fmt);
3786676Smckusick 			p += strlen(p);
3796676Smckusick 			continue;
3806676Smckusick 		}
3816676Smckusick 		if (a == NULL)
3826676Smckusick 			error(FATAL, "not enough arguments in printf(%s)", os);
3836676Smckusick 		x = execute(a);
3846676Smckusick 		a = a->nnext;
3856676Smckusick 		if (flag != 4)	/* watch out for converting to numbers! */
3866676Smckusick 			xf = getfval(x.optr);
38732424Sbostic 		if (flag==1) (void)sprintf(p, fmt, xf);
38832424Sbostic 		else if (flag==2) (void)sprintf(p, fmt, (long)xf);
38932424Sbostic 		else if (flag==3) (void)sprintf(p, fmt, (int)xf);
39032424Sbostic 		else if (flag==4) (void)sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr));
3916676Smckusick 		tempfree(x);
3926676Smckusick 		p += strlen(p);
3936676Smckusick 		s++;
3946676Smckusick 	}
3956676Smckusick 	*p = '\0';
3966676Smckusick 	return(buf);
3976676Smckusick }
3986676Smckusick 
3996676Smckusick obj asprintf(a,n) node **a;
4006676Smckusick {
4016676Smckusick 	obj x;
4026676Smckusick 	node *y;
4036676Smckusick 	char *s;
4046676Smckusick 
4056676Smckusick 	y = a[0]->nnext;
4066676Smckusick 	x = execute(a[0]);
4076676Smckusick 	s = format(getsval(x.optr), y);
4086676Smckusick 	tempfree(x);
4096676Smckusick 	x = gettemp();
4106676Smckusick 	x.optr->sval = s;
4116676Smckusick 	x.optr->tval = STR;
4126676Smckusick 	return(x);
4136676Smckusick }
4146676Smckusick 
4156676Smckusick obj arith(a,n) node **a;
4166676Smckusick {
4176676Smckusick 	awkfloat i,j;
4186676Smckusick 	obj x,y,z;
4196676Smckusick 
4206676Smckusick 	x = execute(a[0]);
4216676Smckusick 	i = getfval(x.optr);
4226676Smckusick 	tempfree(x);
4236676Smckusick 	if (n != UMINUS) {
4246676Smckusick 		y = execute(a[1]);
4256676Smckusick 		j = getfval(y.optr);
4266676Smckusick 		tempfree(y);
4276676Smckusick 	}
4286676Smckusick 	z = gettemp();
4296676Smckusick 	switch (n) {
4306676Smckusick 	default:
4316676Smckusick 		error(FATAL, "illegal arithmetic operator %d", n);
4326676Smckusick 	case ADD:
4336676Smckusick 		i += j;
4346676Smckusick 		break;
4356676Smckusick 	case MINUS:
4366676Smckusick 		i -= j;
4376676Smckusick 		break;
4386676Smckusick 	case MULT:
4396676Smckusick 		i *= j;
4406676Smckusick 		break;
4416676Smckusick 	case DIVIDE:
4426676Smckusick 		if (j == 0)
4436676Smckusick 			error(FATAL, "division by zero");
4446676Smckusick 		i /= j;
4456676Smckusick 		break;
4466676Smckusick 	case MOD:
4476676Smckusick 		if (j == 0)
4486676Smckusick 			error(FATAL, "division by zero");
4496676Smckusick 		i = i - j*(long)(i/j);
4506676Smckusick 		break;
4516676Smckusick 	case UMINUS:
4526676Smckusick 		i = -i;
4536676Smckusick 		break;
4546676Smckusick 	}
4556676Smckusick 	setfval(z.optr, i);
4566676Smckusick 	return(z);
4576676Smckusick }
4586676Smckusick 
4596676Smckusick obj incrdecr(a, n) node **a;
4606676Smckusick {
4616676Smckusick 	obj x, z;
4626676Smckusick 	int k;
4636676Smckusick 	awkfloat xf;
4646676Smckusick 
4656676Smckusick 	x = execute(a[0]);
4666676Smckusick 	xf = getfval(x.optr);
4676676Smckusick 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
4686676Smckusick 	if (n == PREINCR || n == PREDECR) {
4696676Smckusick 		setfval(x.optr, xf + k);
4706676Smckusick 		return(x);
4716676Smckusick 	}
4726676Smckusick 	z = gettemp();
4736676Smckusick 	setfval(z.optr, xf);
4746676Smckusick 	setfval(x.optr, xf + k);
4756676Smckusick 	tempfree(x);
4766676Smckusick 	return(z);
4776676Smckusick }
4786676Smckusick 
4796676Smckusick 
4806676Smckusick obj assign(a,n) node **a;
4816676Smckusick {
4826676Smckusick 	obj x, y;
4836676Smckusick 	awkfloat xf, yf;
4846676Smckusick 
4856676Smckusick 	x = execute(a[0]);
4866676Smckusick 	y = execute(a[1]);
4876676Smckusick 	if (n == ASSIGN) {	/* ordinary assignment */
4886676Smckusick 		if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) {
4896676Smckusick 			setsval(x.optr, y.optr->sval);
4906676Smckusick 			x.optr->fval = y.optr->fval;
4916676Smckusick 			x.optr->tval |= NUM;
4926676Smckusick 		}
4936676Smckusick 		else if (y.optr->tval & STR)
4946676Smckusick 			setsval(x.optr, y.optr->sval);
4956676Smckusick 		else if (y.optr->tval & NUM)
4966676Smckusick 			setfval(x.optr, y.optr->fval);
4976676Smckusick 		tempfree(y);
4986676Smckusick 		return(x);
4996676Smckusick 	}
5006676Smckusick 	xf = getfval(x.optr);
5016676Smckusick 	yf = getfval(y.optr);
5026676Smckusick 	switch (n) {
5036676Smckusick 	case ADDEQ:
5046676Smckusick 		xf += yf;
5056676Smckusick 		break;
5066676Smckusick 	case SUBEQ:
5076676Smckusick 		xf -= yf;
5086676Smckusick 		break;
5096676Smckusick 	case MULTEQ:
5106676Smckusick 		xf *= yf;
5116676Smckusick 		break;
5126676Smckusick 	case DIVEQ:
5136676Smckusick 		if (yf == 0)
5146676Smckusick 			error(FATAL, "division by zero");
5156676Smckusick 		xf /= yf;
5166676Smckusick 		break;
5176676Smckusick 	case MODEQ:
5186676Smckusick 		if (yf == 0)
5196676Smckusick 			error(FATAL, "division by zero");
5206676Smckusick 		xf = xf - yf*(long)(xf/yf);
5216676Smckusick 		break;
5226676Smckusick 	default:
5236676Smckusick 		error(FATAL, "illegal assignment operator %d", n);
5246676Smckusick 		break;
5256676Smckusick 	}
5266676Smckusick 	tempfree(y);
5276676Smckusick 	setfval(x.optr, xf);
5286676Smckusick 	return(x);
5296676Smckusick }
5306676Smckusick 
5316676Smckusick obj cat(a,q) node **a;
5326676Smckusick {
5336676Smckusick 	obj x,y,z;
5346676Smckusick 	int n1, n2;
5356676Smckusick 	char *s;
5366676Smckusick 
5376676Smckusick 	x = execute(a[0]);
5386676Smckusick 	y = execute(a[1]);
5396676Smckusick 	getsval(x.optr);
5406676Smckusick 	getsval(y.optr);
5416676Smckusick 	n1 = strlen(x.optr->sval);
5426676Smckusick 	n2 = strlen(y.optr->sval);
5436676Smckusick 	s = (char *) malloc(n1 + n2 + 1);
5446676Smckusick 	strcpy(s, x.optr->sval);
5456676Smckusick 	strcpy(s+n1, y.optr->sval);
5466676Smckusick 	tempfree(y);
5476676Smckusick 	z = gettemp();
5486676Smckusick 	z.optr->sval = s;
5496676Smckusick 	z.optr->tval = STR;
5506676Smckusick 	tempfree(x);
5516676Smckusick 	return(z);
5526676Smckusick }
5536676Smckusick 
5546676Smckusick obj pastat(a,n) node **a;
5556676Smckusick {
5566676Smckusick 	obj x;
5576676Smckusick 
5586676Smckusick 	if (a[0]==nullstat)
5596676Smckusick 		x = true;
5606676Smckusick 	else
5616676Smckusick 		x = execute(a[0]);
5626676Smckusick 	if (istrue(x)) {
5636676Smckusick 		tempfree(x);
5646676Smckusick 		x = execute(a[1]);
5656676Smckusick 	}
5666676Smckusick 	return(x);
5676676Smckusick }
5686676Smckusick 
5696676Smckusick obj dopa2(a,n) node **a;
5706676Smckusick {
5716676Smckusick 	obj x;
5726676Smckusick 
5736676Smckusick 	if (pairstack[n]==0) {
5746676Smckusick 		x = execute(a[0]);
5756676Smckusick 		if (istrue(x))
5766676Smckusick 			pairstack[n] = 1;
5776676Smckusick 		tempfree(x);
5786676Smckusick 	}
5796676Smckusick 	if (pairstack[n] == 1) {
5806676Smckusick 		x = execute(a[1]);
5816676Smckusick 		if (istrue(x))
5826676Smckusick 			pairstack[n] = 0;
5836676Smckusick 		tempfree(x);
5846676Smckusick 		x = execute(a[2]);
5856676Smckusick 		return(x);
5866676Smckusick 	}
5876676Smckusick 	return(false);
5886676Smckusick }
5896676Smckusick 
5906676Smckusick obj aprintf(a,n) node **a;
5916676Smckusick {
5926676Smckusick 	obj x;
5936676Smckusick 
5946676Smckusick 	x = asprintf(a,n);
5956676Smckusick 	if (a[1]==NULL) {
5966676Smckusick 		printf("%s", x.optr->sval);
5976676Smckusick 		tempfree(x);
5986676Smckusick 		return(true);
5996676Smckusick 	}
6006676Smckusick 	redirprint(x.optr->sval, (int)a[1], a[2]);
6016676Smckusick 	return(x);
6026676Smckusick }
6036676Smckusick 
6046676Smckusick obj split(a,nnn) node **a;
6056676Smckusick {
6066676Smckusick 	obj x;
6076676Smckusick 	cell *ap;
6086676Smckusick 	register char *s, *p;
6096676Smckusick 	char *t, temp, num[5];
6106676Smckusick 	register int sep;
6116676Smckusick 	int n, flag;
6126676Smckusick 
6136676Smckusick 	x = execute(a[0]);
6146676Smckusick 	s = getsval(x.optr);
6156676Smckusick 	tempfree(x);
6166676Smckusick 	if (a[2] == nullstat)
6176676Smckusick 		sep = **FS;
6186676Smckusick 	else {
6196676Smckusick 		x = execute(a[2]);
6206676Smckusick 		sep = getsval(x.optr)[0];
6216676Smckusick 		tempfree(x);
6226676Smckusick 	}
6236676Smckusick 	ap = (cell *) a[1];
6246676Smckusick 	freesymtab(ap);
6256676Smckusick 	dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep);
6266676Smckusick 	ap->tval &= ~STR;
6276676Smckusick 	ap->tval |= ARR;
6286676Smckusick 	ap->sval = (char *) makesymtab();
6296676Smckusick 
6306676Smckusick 	n = 0;
6316676Smckusick 	if (sep == ' ')
6326676Smckusick 		for (n = 0; ; ) {
6336676Smckusick 			while (*s == ' ' || *s == '\t' || *s == '\n')
6346676Smckusick 				s++;
6356676Smckusick 			if (*s == 0)
6366676Smckusick 				break;
6376676Smckusick 			n++;
6386676Smckusick 			t = s;
6396676Smckusick 			do
6406676Smckusick 				s++;
6416676Smckusick 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
6426676Smckusick 			temp = *s;
6436676Smckusick 			*s = '\0';
64432424Sbostic 			(void)sprintf(num, "%d", n);
6456676Smckusick 			if (isnumber(t))
6466676Smckusick 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
6476676Smckusick 			else
6486676Smckusick 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
6496676Smckusick 			*s = temp;
6506676Smckusick 			if (*s != 0)
6516676Smckusick 				s++;
6526676Smckusick 		}
6536676Smckusick 	else if (*s != 0)
6546676Smckusick 		for (;;) {
6556676Smckusick 			n++;
6566676Smckusick 			t = s;
6576676Smckusick 			while (*s != sep && *s != '\n' && *s != '\0')
6586676Smckusick 				s++;
6596676Smckusick 			temp = *s;
6606676Smckusick 			*s = '\0';
66132424Sbostic 			(void)sprintf(num, "%d", n);
6626676Smckusick 			if (isnumber(t))
6636676Smckusick 				setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval);
6646676Smckusick 			else
6656676Smckusick 				setsymtab(num, tostring(t), 0.0, STR, ap->sval);
6666676Smckusick 			*s = temp;
6676676Smckusick 			if (*s++ == 0)
6686676Smckusick 				break;
6696676Smckusick 		}
6706676Smckusick 	x = gettemp();
6716676Smckusick 	x.optr->tval = NUM;
6726676Smckusick 	x.optr->fval = n;
6736676Smckusick 	return(x);
6746676Smckusick }
6756676Smckusick 
6766676Smckusick obj ifstat(a,n) node **a;
6776676Smckusick {
6786676Smckusick 	obj x;
6796676Smckusick 
6806676Smckusick 	x = execute(a[0]);
6816676Smckusick 	if (istrue(x)) {
6826676Smckusick 		tempfree(x);
6836676Smckusick 		x = execute(a[1]);
6846676Smckusick 	}
6856676Smckusick 	else if (a[2] != nullstat) {
6866676Smckusick 		tempfree(x);
6876676Smckusick 		x = execute(a[2]);
6886676Smckusick 	}
6896676Smckusick 	return(x);
6906676Smckusick }
6916676Smckusick 
6926676Smckusick obj whilestat(a,n) node **a;
6936676Smckusick {
6946676Smckusick 	obj x;
6956676Smckusick 
6966676Smckusick 	for (;;) {
6976676Smckusick 		x = execute(a[0]);
6986676Smckusick 		if (!istrue(x)) return(x);
6996676Smckusick 		tempfree(x);
7006676Smckusick 		x = execute(a[1]);
7016676Smckusick 		if (isbreak(x)) {
7026676Smckusick 			x = true;
7036676Smckusick 			return(x);
7046676Smckusick 		}
7056676Smckusick 		if (isnext(x) || isexit(x))
7066676Smckusick 			return(x);
7076676Smckusick 		tempfree(x);
7086676Smckusick 	}
7096676Smckusick }
7106676Smckusick 
7116676Smckusick obj forstat(a,n) node **a;
7126676Smckusick {
7136676Smckusick 	obj x;
7146676Smckusick 
7156676Smckusick 	tempfree(execute(a[0]));
7166676Smckusick 	for (;;) {
7176676Smckusick 		if (a[1]!=nullstat) {
7186676Smckusick 			x = execute(a[1]);
7196676Smckusick 			if (!istrue(x)) return(x);
7206676Smckusick 			else tempfree(x);
7216676Smckusick 		}
7226676Smckusick 		x = execute(a[3]);
7236676Smckusick 		if (isbreak(x)) {	/* turn off break */
7246676Smckusick 			x = true;
7256676Smckusick 			return(x);
7266676Smckusick 		}
7276676Smckusick 		if (isnext(x) || isexit(x))
7286676Smckusick 			return(x);
7296676Smckusick 		tempfree(x);
7306676Smckusick 		tempfree(execute(a[2]));
7316676Smckusick 	}
7326676Smckusick }
7336676Smckusick 
7346676Smckusick obj instat(a, n) node **a;
7356676Smckusick {
7366676Smckusick 	cell *vp, *arrayp, *cp, **tp;
7376676Smckusick 	obj x;
7386676Smckusick 	int i;
7396676Smckusick 
7406676Smckusick 	vp = (cell *) a[0];
7416676Smckusick 	arrayp = (cell *) a[1];
7426676Smckusick 	if (!(arrayp->tval & ARR))
7436676Smckusick 		error(FATAL, "%s is not an array", arrayp->nval);
7446676Smckusick 	tp = (cell **) arrayp->sval;
7456676Smckusick 	for (i = 0; i < MAXSYM; i++) {	/* this routine knows too much */
7466676Smckusick 		for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
7476676Smckusick 			setsval(vp, cp->nval);
7486676Smckusick 			x = execute(a[2]);
7496676Smckusick 			if (isbreak(x)) {
7506676Smckusick 				x = true;
7516676Smckusick 				return(x);
7526676Smckusick 			}
7536676Smckusick 			if (isnext(x) || isexit(x))
7546676Smckusick 				return(x);
7556676Smckusick 			tempfree(x);
7566676Smckusick 		}
7576676Smckusick 	}
75813177Ssam 	return (true);
7596676Smckusick }
7606676Smckusick 
7616676Smckusick obj jump(a,n) node **a;
7626676Smckusick {
7636676Smckusick 	obj x, y;
7646676Smckusick 
7656676Smckusick 	x.otype = OJUMP;
7666676Smckusick 	switch (n) {
7676676Smckusick 	default:
7686676Smckusick 		error(FATAL, "illegal jump type %d", n);
7696676Smckusick 		break;
7706676Smckusick 	case EXIT:
7716676Smckusick 		if (a[0] != 0) {
7726676Smckusick 			y = execute(a[0]);
7736676Smckusick 			errorflag = getfval(y.optr);
7746676Smckusick 		}
7756676Smckusick 		x.osub = JEXIT;
7766676Smckusick 		break;
7776676Smckusick 	case NEXT:
7786676Smckusick 		x.osub = JNEXT;
7796676Smckusick 		break;
7806676Smckusick 	case BREAK:
7816676Smckusick 		x.osub = JBREAK;
7826676Smckusick 		break;
7836676Smckusick 	case CONTINUE:
7846676Smckusick 		x.osub = JCONT;
7856676Smckusick 		break;
7866676Smckusick 	}
7876676Smckusick 	return(x);
7886676Smckusick }
7896676Smckusick 
7906676Smckusick obj fncn(a,n) node **a;
7916676Smckusick {
7926676Smckusick 	obj x;
7936676Smckusick 	awkfloat u;
7946676Smckusick 	int t;
7956676Smckusick 
7966676Smckusick 	t = (int) a[0];
7976676Smckusick 	x = execute(a[1]);
7986676Smckusick 	if (t == FLENGTH)
7996676Smckusick 		u = (awkfloat) strlen(getsval(x.optr));
8006676Smckusick 	else if (t == FLOG)
8016676Smckusick 		u = log(getfval(x.optr));
8026676Smckusick 	else if (t == FINT)
8036676Smckusick 		u = (awkfloat) (long) getfval(x.optr);
8046676Smckusick 	else if (t == FEXP)
8056676Smckusick 		u = exp(getfval(x.optr));
8066676Smckusick 	else if (t == FSQRT)
8076676Smckusick 		u = sqrt(getfval(x.optr));
8086676Smckusick 	else
8096676Smckusick 		error(FATAL, "illegal function type %d", t);
8106676Smckusick 	tempfree(x);
8116676Smckusick 	x = gettemp();
8126676Smckusick 	setfval(x.optr, u);
8136676Smckusick 	return(x);
8146676Smckusick }
8156676Smckusick 
8166676Smckusick obj print(a,n) node **a;
8176676Smckusick {
8186676Smckusick 	register node *x;
8196676Smckusick 	obj y;
8206676Smckusick 	char s[RECSIZE];
8216676Smckusick 
8226676Smckusick 	s[0] = '\0';
8236676Smckusick 	for (x=a[0]; x!=NULL; x=x->nnext) {
8246676Smckusick 		y = execute(x);
8256676Smckusick 		strcat(s, getsval(y.optr));
8266676Smckusick 		tempfree(y);
8276676Smckusick 		if (x->nnext==NULL)
8286676Smckusick 			strcat(s, *ORS);
8296676Smckusick 		else
8306676Smckusick 			strcat(s, *OFS);
8316676Smckusick 	}
8326676Smckusick 	if (strlen(s) >= RECSIZE)
8336676Smckusick 		error(FATAL, "string %.20s ... too long to print", s);
8346676Smckusick 	if (a[1]==nullstat) {
8356676Smckusick 		printf("%s", s);
8366676Smckusick 		return(true);
8376676Smckusick 	}
8386676Smckusick 	redirprint(s, (int)a[1], a[2]);
8396676Smckusick 	return(false);
8406676Smckusick }
8416676Smckusick 
8426676Smckusick obj nullproc() {}
8436676Smckusick 
8446676Smckusick obj nodetoobj(a) node *a;
8456676Smckusick {
8466676Smckusick 	obj x;
8476676Smckusick 
8486676Smckusick 	x.optr = (cell *) a->nobj;
8496676Smckusick 	x.otype = OCELL;
8506676Smckusick 	x.osub = a->subtype;
8516676Smckusick 	if (isfld(x)) fldbld();
8526676Smckusick 	return(x);
8536676Smckusick }
8546676Smckusick 
8556676Smckusick redirprint(s, a, b) char *s; node *b;
8566676Smckusick {
8576676Smckusick 	register int i;
8586676Smckusick 	obj x;
8596676Smckusick 
8606676Smckusick 	x = execute(b);
8616676Smckusick 	getsval(x.optr);
8626676Smckusick 	for (i=0; i<FILENUM; i++)
8636676Smckusick 		if (files[i].fp && strcmp(x.optr->sval, files[i].fname) == 0)
8646676Smckusick 			goto doit;
8656676Smckusick 	for (i=0; i<FILENUM; i++)
8666676Smckusick 		if (files[i].fp == 0)
8676676Smckusick 			break;
8686676Smckusick 	if (i >= FILENUM)
8696676Smckusick 		error(FATAL, "too many output files %d", i);
8706676Smckusick 	if (a == '|')	/* a pipe! */
8716676Smckusick 		files[i].fp = popen(x.optr->sval, "w");
8726676Smckusick 	else if (a == APPEND)
8736676Smckusick 		files[i].fp = fopen(x.optr->sval, "a");
8746676Smckusick 	else
8756676Smckusick 		files[i].fp = fopen(x.optr->sval, "w");
8766676Smckusick 	if (files[i].fp == NULL)
8776676Smckusick 		error(FATAL, "can't open file %s", x.optr->sval);
87831027Sbostic 	if (fcntl(fileno(files[i].fp), F_SETFD, 1) < 0)
87931027Sbostic 		error(FATAL, "close on exec failure");
8806676Smckusick 	files[i].fname = tostring(x.optr->sval);
88117457Sralph 	files[i].type = a;
8826676Smckusick doit:
8836676Smckusick 	fprintf(files[i].fp, "%s", s);
8846676Smckusick #ifndef gcos
8856676Smckusick 	fflush(files[i].fp);	/* in case someone is waiting for the output */
8866676Smckusick #endif
8876676Smckusick 	tempfree(x);
8886676Smckusick }
889