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