xref: /inferno-os/utils/awk/tran.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth /****************************************************************
2*74a4d8c2SCharles.Forsyth Copyright (C) Lucent Technologies 1997
3*74a4d8c2SCharles.Forsyth All Rights Reserved
4*74a4d8c2SCharles.Forsyth 
5*74a4d8c2SCharles.Forsyth Permission to use, copy, modify, and distribute this software and
6*74a4d8c2SCharles.Forsyth its documentation for any purpose and without fee is hereby
7*74a4d8c2SCharles.Forsyth granted, provided that the above copyright notice appear in all
8*74a4d8c2SCharles.Forsyth copies and that both that the copyright notice and this
9*74a4d8c2SCharles.Forsyth permission notice and warranty disclaimer appear in supporting
10*74a4d8c2SCharles.Forsyth documentation, and that the name Lucent Technologies or any of
11*74a4d8c2SCharles.Forsyth its entities not be used in advertising or publicity pertaining
12*74a4d8c2SCharles.Forsyth to distribution of the software without specific, written prior
13*74a4d8c2SCharles.Forsyth permission.
14*74a4d8c2SCharles.Forsyth 
15*74a4d8c2SCharles.Forsyth LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*74a4d8c2SCharles.Forsyth INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17*74a4d8c2SCharles.Forsyth IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18*74a4d8c2SCharles.Forsyth SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*74a4d8c2SCharles.Forsyth WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20*74a4d8c2SCharles.Forsyth IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*74a4d8c2SCharles.Forsyth ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22*74a4d8c2SCharles.Forsyth THIS SOFTWARE.
23*74a4d8c2SCharles.Forsyth ****************************************************************/
24*74a4d8c2SCharles.Forsyth 
25*74a4d8c2SCharles.Forsyth #define	DEBUG
26*74a4d8c2SCharles.Forsyth #include <stdio.h>
27*74a4d8c2SCharles.Forsyth #include <math.h>
28*74a4d8c2SCharles.Forsyth #include <ctype.h>
29*74a4d8c2SCharles.Forsyth #include <string.h>
30*74a4d8c2SCharles.Forsyth #include <stdlib.h>
31*74a4d8c2SCharles.Forsyth #include "awk.h"
32*74a4d8c2SCharles.Forsyth #include "ytab.h"
33*74a4d8c2SCharles.Forsyth 
34*74a4d8c2SCharles.Forsyth #define	FULLTAB	2	/* rehash when table gets this x full */
35*74a4d8c2SCharles.Forsyth #define	GROWTAB 4	/* grow table by this factor */
36*74a4d8c2SCharles.Forsyth 
37*74a4d8c2SCharles.Forsyth Array	*symtab;	/* main symbol table */
38*74a4d8c2SCharles.Forsyth 
39*74a4d8c2SCharles.Forsyth char	**FS;		/* initial field sep */
40*74a4d8c2SCharles.Forsyth char	**RS;		/* initial record sep */
41*74a4d8c2SCharles.Forsyth char	**OFS;		/* output field sep */
42*74a4d8c2SCharles.Forsyth char	**ORS;		/* output record sep */
43*74a4d8c2SCharles.Forsyth char	**OFMT;		/* output format for numbers */
44*74a4d8c2SCharles.Forsyth char	**CONVFMT;	/* format for conversions in getsval */
45*74a4d8c2SCharles.Forsyth Awkfloat *NF;		/* number of fields in current record */
46*74a4d8c2SCharles.Forsyth Awkfloat *NR;		/* number of current record */
47*74a4d8c2SCharles.Forsyth Awkfloat *FNR;		/* number of current record in current file */
48*74a4d8c2SCharles.Forsyth char	**FILENAME;	/* current filename argument */
49*74a4d8c2SCharles.Forsyth Awkfloat *ARGC;		/* number of arguments from command line */
50*74a4d8c2SCharles.Forsyth char	**SUBSEP;	/* subscript separator for a[i,j,k]; default \034 */
51*74a4d8c2SCharles.Forsyth Awkfloat *RSTART;	/* start of re matched with ~; origin 1 (!) */
52*74a4d8c2SCharles.Forsyth Awkfloat *RLENGTH;	/* length of same */
53*74a4d8c2SCharles.Forsyth 
54*74a4d8c2SCharles.Forsyth Cell	*nrloc;		/* NR */
55*74a4d8c2SCharles.Forsyth Cell	*nfloc;		/* NF */
56*74a4d8c2SCharles.Forsyth Cell	*fnrloc;	/* FNR */
57*74a4d8c2SCharles.Forsyth Array	*ARGVtab;	/* symbol table containing ARGV[...] */
58*74a4d8c2SCharles.Forsyth Array	*ENVtab;	/* symbol table containing ENVIRON[...] */
59*74a4d8c2SCharles.Forsyth Cell	*rstartloc;	/* RSTART */
60*74a4d8c2SCharles.Forsyth Cell	*rlengthloc;	/* RLENGTH */
61*74a4d8c2SCharles.Forsyth Cell	*symtabloc;	/* SYMTAB */
62*74a4d8c2SCharles.Forsyth 
63*74a4d8c2SCharles.Forsyth Cell	*nullloc;	/* a guaranteed empty cell */
64*74a4d8c2SCharles.Forsyth Node	*nullnode;	/* zero&null, converted into a node for comparisons */
65*74a4d8c2SCharles.Forsyth Cell	*literal0;
66*74a4d8c2SCharles.Forsyth 
67*74a4d8c2SCharles.Forsyth extern Cell **fldtab;
68*74a4d8c2SCharles.Forsyth 
syminit(void)69*74a4d8c2SCharles.Forsyth void syminit(void)	/* initialize symbol table with builtin vars */
70*74a4d8c2SCharles.Forsyth {
71*74a4d8c2SCharles.Forsyth 	literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
72*74a4d8c2SCharles.Forsyth 	/* this is used for if(x)... tests: */
73*74a4d8c2SCharles.Forsyth 	nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
74*74a4d8c2SCharles.Forsyth 	nullnode = celltonode(nullloc, CCON);
75*74a4d8c2SCharles.Forsyth 
76*74a4d8c2SCharles.Forsyth 	FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
77*74a4d8c2SCharles.Forsyth 	RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
78*74a4d8c2SCharles.Forsyth 	OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
79*74a4d8c2SCharles.Forsyth 	ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
80*74a4d8c2SCharles.Forsyth 	OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
81*74a4d8c2SCharles.Forsyth 	CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
82*74a4d8c2SCharles.Forsyth 	FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
83*74a4d8c2SCharles.Forsyth 	nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
84*74a4d8c2SCharles.Forsyth 	NF = &nfloc->fval;
85*74a4d8c2SCharles.Forsyth 	nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
86*74a4d8c2SCharles.Forsyth 	NR = &nrloc->fval;
87*74a4d8c2SCharles.Forsyth 	fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
88*74a4d8c2SCharles.Forsyth 	FNR = &fnrloc->fval;
89*74a4d8c2SCharles.Forsyth 	SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
90*74a4d8c2SCharles.Forsyth 	rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
91*74a4d8c2SCharles.Forsyth 	RSTART = &rstartloc->fval;
92*74a4d8c2SCharles.Forsyth 	rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
93*74a4d8c2SCharles.Forsyth 	RLENGTH = &rlengthloc->fval;
94*74a4d8c2SCharles.Forsyth 	symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
95*74a4d8c2SCharles.Forsyth 	symtabloc->sval = (char *) symtab;
96*74a4d8c2SCharles.Forsyth }
97*74a4d8c2SCharles.Forsyth 
arginit(int ac,char ** av)98*74a4d8c2SCharles.Forsyth void arginit(int ac, char **av)	/* set up ARGV and ARGC */
99*74a4d8c2SCharles.Forsyth {
100*74a4d8c2SCharles.Forsyth 	Cell *cp;
101*74a4d8c2SCharles.Forsyth 	int i;
102*74a4d8c2SCharles.Forsyth 	char temp[50];
103*74a4d8c2SCharles.Forsyth 
104*74a4d8c2SCharles.Forsyth 	ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
105*74a4d8c2SCharles.Forsyth 	cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
106*74a4d8c2SCharles.Forsyth 	ARGVtab = makesymtab(NSYMTAB);	/* could be (int) ARGC as well */
107*74a4d8c2SCharles.Forsyth 	cp->sval = (char *) ARGVtab;
108*74a4d8c2SCharles.Forsyth 	for (i = 0; i < ac; i++) {
109*74a4d8c2SCharles.Forsyth 		sprintf(temp, "%d", i);
110*74a4d8c2SCharles.Forsyth 		if (is_number(*av))
111*74a4d8c2SCharles.Forsyth 			setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
112*74a4d8c2SCharles.Forsyth 		else
113*74a4d8c2SCharles.Forsyth 			setsymtab(temp, *av, 0.0, STR, ARGVtab);
114*74a4d8c2SCharles.Forsyth 		av++;
115*74a4d8c2SCharles.Forsyth 	}
116*74a4d8c2SCharles.Forsyth }
117*74a4d8c2SCharles.Forsyth 
envinit(char ** envp)118*74a4d8c2SCharles.Forsyth void envinit(char **envp)	/* set up ENVIRON variable */
119*74a4d8c2SCharles.Forsyth {
120*74a4d8c2SCharles.Forsyth 	Cell *cp;
121*74a4d8c2SCharles.Forsyth 	char *p;
122*74a4d8c2SCharles.Forsyth 
123*74a4d8c2SCharles.Forsyth 	cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
124*74a4d8c2SCharles.Forsyth 	ENVtab = makesymtab(NSYMTAB);
125*74a4d8c2SCharles.Forsyth 	cp->sval = (char *) ENVtab;
126*74a4d8c2SCharles.Forsyth 	for ( ; *envp; envp++) {
127*74a4d8c2SCharles.Forsyth 		if ((p = strchr(*envp, '=')) == NULL)
128*74a4d8c2SCharles.Forsyth 			continue;
129*74a4d8c2SCharles.Forsyth 		if( p == *envp ) /* no left hand side name in env string */
130*74a4d8c2SCharles.Forsyth 			continue;
131*74a4d8c2SCharles.Forsyth 		*p++ = 0;	/* split into two strings at = */
132*74a4d8c2SCharles.Forsyth 		if (is_number(p))
133*74a4d8c2SCharles.Forsyth 			setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
134*74a4d8c2SCharles.Forsyth 		else
135*74a4d8c2SCharles.Forsyth 			setsymtab(*envp, p, 0.0, STR, ENVtab);
136*74a4d8c2SCharles.Forsyth 		p[-1] = '=';	/* restore in case env is passed down to a shell */
137*74a4d8c2SCharles.Forsyth 	}
138*74a4d8c2SCharles.Forsyth }
139*74a4d8c2SCharles.Forsyth 
makesymtab(int n)140*74a4d8c2SCharles.Forsyth Array *makesymtab(int n)	/* make a new symbol table */
141*74a4d8c2SCharles.Forsyth {
142*74a4d8c2SCharles.Forsyth 	Array *ap;
143*74a4d8c2SCharles.Forsyth 	Cell **tp;
144*74a4d8c2SCharles.Forsyth 
145*74a4d8c2SCharles.Forsyth 	ap = (Array *) malloc(sizeof(Array));
146*74a4d8c2SCharles.Forsyth 	tp = (Cell **) calloc(n, sizeof(Cell *));
147*74a4d8c2SCharles.Forsyth 	if (ap == NULL || tp == NULL)
148*74a4d8c2SCharles.Forsyth 		FATAL("out of space in makesymtab");
149*74a4d8c2SCharles.Forsyth 	ap->nelem = 0;
150*74a4d8c2SCharles.Forsyth 	ap->size = n;
151*74a4d8c2SCharles.Forsyth 	ap->tab = tp;
152*74a4d8c2SCharles.Forsyth 	return(ap);
153*74a4d8c2SCharles.Forsyth }
154*74a4d8c2SCharles.Forsyth 
freesymtab(Cell * ap)155*74a4d8c2SCharles.Forsyth void freesymtab(Cell *ap)	/* free a symbol table */
156*74a4d8c2SCharles.Forsyth {
157*74a4d8c2SCharles.Forsyth 	Cell *cp, *temp;
158*74a4d8c2SCharles.Forsyth 	Array *tp;
159*74a4d8c2SCharles.Forsyth 	int i;
160*74a4d8c2SCharles.Forsyth 
161*74a4d8c2SCharles.Forsyth 	if (!isarr(ap))
162*74a4d8c2SCharles.Forsyth 		return;
163*74a4d8c2SCharles.Forsyth 	tp = (Array *) ap->sval;
164*74a4d8c2SCharles.Forsyth 	if (tp == NULL)
165*74a4d8c2SCharles.Forsyth 		return;
166*74a4d8c2SCharles.Forsyth 	for (i = 0; i < tp->size; i++) {
167*74a4d8c2SCharles.Forsyth 		for (cp = tp->tab[i]; cp != NULL; cp = temp) {
168*74a4d8c2SCharles.Forsyth 			xfree(cp->nval);
169*74a4d8c2SCharles.Forsyth 			if (freeable(cp))
170*74a4d8c2SCharles.Forsyth 				xfree(cp->sval);
171*74a4d8c2SCharles.Forsyth 			temp = cp->cnext;	/* avoids freeing then using */
172*74a4d8c2SCharles.Forsyth 			free(cp);
173*74a4d8c2SCharles.Forsyth 		}
174*74a4d8c2SCharles.Forsyth 		tp->tab[i] = 0;
175*74a4d8c2SCharles.Forsyth 	}
176*74a4d8c2SCharles.Forsyth 	free(tp->tab);
177*74a4d8c2SCharles.Forsyth 	free(tp);
178*74a4d8c2SCharles.Forsyth }
179*74a4d8c2SCharles.Forsyth 
freeelem(Cell * ap,char * s)180*74a4d8c2SCharles.Forsyth void freeelem(Cell *ap, char *s)	/* free elem s from ap (i.e., ap["s"] */
181*74a4d8c2SCharles.Forsyth {
182*74a4d8c2SCharles.Forsyth 	Array *tp;
183*74a4d8c2SCharles.Forsyth 	Cell *p, *prev = NULL;
184*74a4d8c2SCharles.Forsyth 	int h;
185*74a4d8c2SCharles.Forsyth 
186*74a4d8c2SCharles.Forsyth 	tp = (Array *) ap->sval;
187*74a4d8c2SCharles.Forsyth 	h = hash(s, tp->size);
188*74a4d8c2SCharles.Forsyth 	for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
189*74a4d8c2SCharles.Forsyth 		if (strcmp(s, p->nval) == 0) {
190*74a4d8c2SCharles.Forsyth 			if (prev == NULL)	/* 1st one */
191*74a4d8c2SCharles.Forsyth 				tp->tab[h] = p->cnext;
192*74a4d8c2SCharles.Forsyth 			else			/* middle somewhere */
193*74a4d8c2SCharles.Forsyth 				prev->cnext = p->cnext;
194*74a4d8c2SCharles.Forsyth 			if (freeable(p))
195*74a4d8c2SCharles.Forsyth 				xfree(p->sval);
196*74a4d8c2SCharles.Forsyth 			free(p->nval);
197*74a4d8c2SCharles.Forsyth 			free(p);
198*74a4d8c2SCharles.Forsyth 			tp->nelem--;
199*74a4d8c2SCharles.Forsyth 			return;
200*74a4d8c2SCharles.Forsyth 		}
201*74a4d8c2SCharles.Forsyth }
202*74a4d8c2SCharles.Forsyth 
setsymtab(char * n,char * s,Awkfloat f,unsigned t,Array * tp)203*74a4d8c2SCharles.Forsyth Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp)
204*74a4d8c2SCharles.Forsyth {
205*74a4d8c2SCharles.Forsyth 	int h;
206*74a4d8c2SCharles.Forsyth 	Cell *p;
207*74a4d8c2SCharles.Forsyth 
208*74a4d8c2SCharles.Forsyth 	if (n != NULL && (p = lookup(n, tp)) != NULL) {
209*74a4d8c2SCharles.Forsyth 		   dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
210*74a4d8c2SCharles.Forsyth 			p, p->nval, p->sval, p->fval, p->tval) );
211*74a4d8c2SCharles.Forsyth 		return(p);
212*74a4d8c2SCharles.Forsyth 	}
213*74a4d8c2SCharles.Forsyth 	p = (Cell *) malloc(sizeof(Cell));
214*74a4d8c2SCharles.Forsyth 	if (p == NULL)
215*74a4d8c2SCharles.Forsyth 		FATAL("out of space for symbol table at %s", n);
216*74a4d8c2SCharles.Forsyth 	p->nval = tostring(n);
217*74a4d8c2SCharles.Forsyth 	p->sval = s ? tostring(s) : tostring("");
218*74a4d8c2SCharles.Forsyth 	p->fval = f;
219*74a4d8c2SCharles.Forsyth 	p->tval = t;
220*74a4d8c2SCharles.Forsyth 	p->csub = CUNK;
221*74a4d8c2SCharles.Forsyth 	p->ctype = OCELL;
222*74a4d8c2SCharles.Forsyth 	tp->nelem++;
223*74a4d8c2SCharles.Forsyth 	if (tp->nelem > FULLTAB * tp->size)
224*74a4d8c2SCharles.Forsyth 		rehash(tp);
225*74a4d8c2SCharles.Forsyth 	h = hash(n, tp->size);
226*74a4d8c2SCharles.Forsyth 	p->cnext = tp->tab[h];
227*74a4d8c2SCharles.Forsyth 	tp->tab[h] = p;
228*74a4d8c2SCharles.Forsyth 	   dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
229*74a4d8c2SCharles.Forsyth 		p, p->nval, p->sval, p->fval, p->tval) );
230*74a4d8c2SCharles.Forsyth 	return(p);
231*74a4d8c2SCharles.Forsyth }
232*74a4d8c2SCharles.Forsyth 
hash(char * s,int n)233*74a4d8c2SCharles.Forsyth int hash(char *s, int n)	/* form hash value for string s */
234*74a4d8c2SCharles.Forsyth {
235*74a4d8c2SCharles.Forsyth 	unsigned hashval;
236*74a4d8c2SCharles.Forsyth 
237*74a4d8c2SCharles.Forsyth 	for (hashval = 0; *s != '\0'; s++)
238*74a4d8c2SCharles.Forsyth 		hashval = (*s + 31 * hashval);
239*74a4d8c2SCharles.Forsyth 	return hashval % n;
240*74a4d8c2SCharles.Forsyth }
241*74a4d8c2SCharles.Forsyth 
rehash(Array * tp)242*74a4d8c2SCharles.Forsyth void rehash(Array *tp)	/* rehash items in small table into big one */
243*74a4d8c2SCharles.Forsyth {
244*74a4d8c2SCharles.Forsyth 	int i, nh, nsz;
245*74a4d8c2SCharles.Forsyth 	Cell *cp, *op, **np;
246*74a4d8c2SCharles.Forsyth 
247*74a4d8c2SCharles.Forsyth 	nsz = GROWTAB * tp->size;
248*74a4d8c2SCharles.Forsyth 	np = (Cell **) calloc(nsz, sizeof(Cell *));
249*74a4d8c2SCharles.Forsyth 	if (np == NULL)		/* can't do it, but can keep running. */
250*74a4d8c2SCharles.Forsyth 		return;		/* someone else will run out later. */
251*74a4d8c2SCharles.Forsyth 	for (i = 0; i < tp->size; i++) {
252*74a4d8c2SCharles.Forsyth 		for (cp = tp->tab[i]; cp; cp = op) {
253*74a4d8c2SCharles.Forsyth 			op = cp->cnext;
254*74a4d8c2SCharles.Forsyth 			nh = hash(cp->nval, nsz);
255*74a4d8c2SCharles.Forsyth 			cp->cnext = np[nh];
256*74a4d8c2SCharles.Forsyth 			np[nh] = cp;
257*74a4d8c2SCharles.Forsyth 		}
258*74a4d8c2SCharles.Forsyth 	}
259*74a4d8c2SCharles.Forsyth 	free(tp->tab);
260*74a4d8c2SCharles.Forsyth 	tp->tab = np;
261*74a4d8c2SCharles.Forsyth 	tp->size = nsz;
262*74a4d8c2SCharles.Forsyth }
263*74a4d8c2SCharles.Forsyth 
lookup(char * s,Array * tp)264*74a4d8c2SCharles.Forsyth Cell *lookup(char *s, Array *tp)	/* look for s in tp */
265*74a4d8c2SCharles.Forsyth {
266*74a4d8c2SCharles.Forsyth 	Cell *p;
267*74a4d8c2SCharles.Forsyth 	int h;
268*74a4d8c2SCharles.Forsyth 
269*74a4d8c2SCharles.Forsyth 	h = hash(s, tp->size);
270*74a4d8c2SCharles.Forsyth 	for (p = tp->tab[h]; p != NULL; p = p->cnext)
271*74a4d8c2SCharles.Forsyth 		if (strcmp(s, p->nval) == 0)
272*74a4d8c2SCharles.Forsyth 			return(p);	/* found it */
273*74a4d8c2SCharles.Forsyth 	return(NULL);			/* not found */
274*74a4d8c2SCharles.Forsyth }
275*74a4d8c2SCharles.Forsyth 
setfval(Cell * vp,Awkfloat f)276*74a4d8c2SCharles.Forsyth Awkfloat setfval(Cell *vp, Awkfloat f)	/* set float val of a Cell */
277*74a4d8c2SCharles.Forsyth {
278*74a4d8c2SCharles.Forsyth 	int fldno;
279*74a4d8c2SCharles.Forsyth 
280*74a4d8c2SCharles.Forsyth 	if ((vp->tval & (NUM | STR)) == 0)
281*74a4d8c2SCharles.Forsyth 		funnyvar(vp, "assign to");
282*74a4d8c2SCharles.Forsyth 	if (isfld(vp)) {
283*74a4d8c2SCharles.Forsyth 		donerec = 0;	/* mark $0 invalid */
284*74a4d8c2SCharles.Forsyth 		fldno = atoi(vp->nval);
285*74a4d8c2SCharles.Forsyth 		if (fldno > *NF)
286*74a4d8c2SCharles.Forsyth 			newfld(fldno);
287*74a4d8c2SCharles.Forsyth 		   dprintf( ("setting field %d to %g\n", fldno, f) );
288*74a4d8c2SCharles.Forsyth 	} else if (isrec(vp)) {
289*74a4d8c2SCharles.Forsyth 		donefld = 0;	/* mark $1... invalid */
290*74a4d8c2SCharles.Forsyth 		donerec = 1;
291*74a4d8c2SCharles.Forsyth 	}
292*74a4d8c2SCharles.Forsyth 	if (freeable(vp))
293*74a4d8c2SCharles.Forsyth 		xfree(vp->sval); /* free any previous string */
294*74a4d8c2SCharles.Forsyth 	vp->tval &= ~STR;	/* mark string invalid */
295*74a4d8c2SCharles.Forsyth 	vp->tval |= NUM;	/* mark number ok */
296*74a4d8c2SCharles.Forsyth 	   dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) );
297*74a4d8c2SCharles.Forsyth 	return vp->fval = f;
298*74a4d8c2SCharles.Forsyth }
299*74a4d8c2SCharles.Forsyth 
funnyvar(Cell * vp,char * rw)300*74a4d8c2SCharles.Forsyth void funnyvar(Cell *vp, char *rw)
301*74a4d8c2SCharles.Forsyth {
302*74a4d8c2SCharles.Forsyth 	if (isarr(vp))
303*74a4d8c2SCharles.Forsyth 		FATAL("can't %s %s; it's an array name.", rw, vp->nval);
304*74a4d8c2SCharles.Forsyth 	if (vp->tval & FCN)
305*74a4d8c2SCharles.Forsyth 		FATAL("can't %s %s; it's a function.", rw, vp->nval);
306*74a4d8c2SCharles.Forsyth 	WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
307*74a4d8c2SCharles.Forsyth 		vp, vp->nval, vp->sval, vp->fval, vp->tval);
308*74a4d8c2SCharles.Forsyth }
309*74a4d8c2SCharles.Forsyth 
setsval(Cell * vp,char * s)310*74a4d8c2SCharles.Forsyth char *setsval(Cell *vp, char *s)	/* set string val of a Cell */
311*74a4d8c2SCharles.Forsyth {
312*74a4d8c2SCharles.Forsyth 	char *t;
313*74a4d8c2SCharles.Forsyth 	int fldno;
314*74a4d8c2SCharles.Forsyth 
315*74a4d8c2SCharles.Forsyth 	   dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
316*74a4d8c2SCharles.Forsyth 	if ((vp->tval & (NUM | STR)) == 0)
317*74a4d8c2SCharles.Forsyth 		funnyvar(vp, "assign to");
318*74a4d8c2SCharles.Forsyth 	if (isfld(vp)) {
319*74a4d8c2SCharles.Forsyth 		donerec = 0;	/* mark $0 invalid */
320*74a4d8c2SCharles.Forsyth 		fldno = atoi(vp->nval);
321*74a4d8c2SCharles.Forsyth 		if (fldno > *NF)
322*74a4d8c2SCharles.Forsyth 			newfld(fldno);
323*74a4d8c2SCharles.Forsyth 		   dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) );
324*74a4d8c2SCharles.Forsyth 	} else if (isrec(vp)) {
325*74a4d8c2SCharles.Forsyth 		donefld = 0;	/* mark $1... invalid */
326*74a4d8c2SCharles.Forsyth 		donerec = 1;
327*74a4d8c2SCharles.Forsyth 	}
328*74a4d8c2SCharles.Forsyth 	t = tostring(s);	/* in case it's self-assign */
329*74a4d8c2SCharles.Forsyth 	vp->tval &= ~NUM;
330*74a4d8c2SCharles.Forsyth 	vp->tval |= STR;
331*74a4d8c2SCharles.Forsyth 	if (freeable(vp))
332*74a4d8c2SCharles.Forsyth 		xfree(vp->sval);
333*74a4d8c2SCharles.Forsyth 	vp->tval &= ~DONTFREE;
334*74a4d8c2SCharles.Forsyth 	   dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) );
335*74a4d8c2SCharles.Forsyth 	return(vp->sval = t);
336*74a4d8c2SCharles.Forsyth }
337*74a4d8c2SCharles.Forsyth 
getfval(Cell * vp)338*74a4d8c2SCharles.Forsyth Awkfloat getfval(Cell *vp)	/* get float val of a Cell */
339*74a4d8c2SCharles.Forsyth {
340*74a4d8c2SCharles.Forsyth 	if ((vp->tval & (NUM | STR)) == 0)
341*74a4d8c2SCharles.Forsyth 		funnyvar(vp, "read value of");
342*74a4d8c2SCharles.Forsyth 	if (isfld(vp) && donefld == 0)
343*74a4d8c2SCharles.Forsyth 		fldbld();
344*74a4d8c2SCharles.Forsyth 	else if (isrec(vp) && donerec == 0)
345*74a4d8c2SCharles.Forsyth 		recbld();
346*74a4d8c2SCharles.Forsyth 	if (!isnum(vp)) {	/* not a number */
347*74a4d8c2SCharles.Forsyth 		vp->fval = atof(vp->sval);	/* best guess */
348*74a4d8c2SCharles.Forsyth 		if (is_number(vp->sval) && !(vp->tval&CON))
349*74a4d8c2SCharles.Forsyth 			vp->tval |= NUM;	/* make NUM only sparingly */
350*74a4d8c2SCharles.Forsyth 	}
351*74a4d8c2SCharles.Forsyth 	   dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
352*74a4d8c2SCharles.Forsyth 	return(vp->fval);
353*74a4d8c2SCharles.Forsyth }
354*74a4d8c2SCharles.Forsyth 
getsval(Cell * vp)355*74a4d8c2SCharles.Forsyth char *getsval(Cell *vp)	/* get string val of a Cell */
356*74a4d8c2SCharles.Forsyth {
357*74a4d8c2SCharles.Forsyth 	char s[100];	/* BUG: unchecked */
358*74a4d8c2SCharles.Forsyth 	double dtemp;
359*74a4d8c2SCharles.Forsyth 
360*74a4d8c2SCharles.Forsyth 	if ((vp->tval & (NUM | STR)) == 0)
361*74a4d8c2SCharles.Forsyth 		funnyvar(vp, "read value of");
362*74a4d8c2SCharles.Forsyth 	if (isfld(vp) && donefld == 0)
363*74a4d8c2SCharles.Forsyth 		fldbld();
364*74a4d8c2SCharles.Forsyth 	else if (isrec(vp) && donerec == 0)
365*74a4d8c2SCharles.Forsyth 		recbld();
366*74a4d8c2SCharles.Forsyth 	if (isstr(vp) == 0) {
367*74a4d8c2SCharles.Forsyth 		if (freeable(vp))
368*74a4d8c2SCharles.Forsyth 			xfree(vp->sval);
369*74a4d8c2SCharles.Forsyth 		if (modf(vp->fval, &dtemp) == 0)	/* it's integral */
370*74a4d8c2SCharles.Forsyth 			sprintf(s, "%.30g", vp->fval);
371*74a4d8c2SCharles.Forsyth 		else
372*74a4d8c2SCharles.Forsyth 			sprintf(s, *CONVFMT, vp->fval);
373*74a4d8c2SCharles.Forsyth 		vp->sval = tostring(s);
374*74a4d8c2SCharles.Forsyth 		vp->tval &= ~DONTFREE;
375*74a4d8c2SCharles.Forsyth 		vp->tval |= STR;
376*74a4d8c2SCharles.Forsyth 	}
377*74a4d8c2SCharles.Forsyth 	   dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) );
378*74a4d8c2SCharles.Forsyth 	return(vp->sval);
379*74a4d8c2SCharles.Forsyth }
380*74a4d8c2SCharles.Forsyth 
tostring(char * s)381*74a4d8c2SCharles.Forsyth char *tostring(char *s)	/* make a copy of string s */
382*74a4d8c2SCharles.Forsyth {
383*74a4d8c2SCharles.Forsyth 	char *p;
384*74a4d8c2SCharles.Forsyth 
385*74a4d8c2SCharles.Forsyth 	p = (char *) malloc(strlen(s)+1);
386*74a4d8c2SCharles.Forsyth 	if (p == NULL)
387*74a4d8c2SCharles.Forsyth 		FATAL("out of space in tostring on %s", s);
388*74a4d8c2SCharles.Forsyth 	strcpy(p, s);
389*74a4d8c2SCharles.Forsyth 	return(p);
390*74a4d8c2SCharles.Forsyth }
391*74a4d8c2SCharles.Forsyth 
qstring(char * is,int delim)392*74a4d8c2SCharles.Forsyth char *qstring(char *is, int delim)	/* collect string up to next delim */
393*74a4d8c2SCharles.Forsyth {
394*74a4d8c2SCharles.Forsyth 	char *os = is;
395*74a4d8c2SCharles.Forsyth 	int c, n;
396*74a4d8c2SCharles.Forsyth 	uschar *s = (uschar *) is;
397*74a4d8c2SCharles.Forsyth 	uschar *buf, *bp;
398*74a4d8c2SCharles.Forsyth 
399*74a4d8c2SCharles.Forsyth 	if ((buf = (uschar *) malloc(strlen(s)+3)) == NULL)
400*74a4d8c2SCharles.Forsyth 		FATAL( "out of space in qstring(%s)", s);
401*74a4d8c2SCharles.Forsyth 	for (bp = buf; (c = *s) != delim; s++) {
402*74a4d8c2SCharles.Forsyth 		if (c == '\n')
403*74a4d8c2SCharles.Forsyth 			SYNTAX( "newline in string %.20s...", os );
404*74a4d8c2SCharles.Forsyth 		else if (c != '\\')
405*74a4d8c2SCharles.Forsyth 			*bp++ = c;
406*74a4d8c2SCharles.Forsyth 		else {	/* \something */
407*74a4d8c2SCharles.Forsyth 			c = *++s;
408*74a4d8c2SCharles.Forsyth 			if (c == 0) {	/* \ at end */
409*74a4d8c2SCharles.Forsyth 				*bp++ = '\\';
410*74a4d8c2SCharles.Forsyth 				break;	/* for loop */
411*74a4d8c2SCharles.Forsyth 			}
412*74a4d8c2SCharles.Forsyth 			switch (c) {
413*74a4d8c2SCharles.Forsyth 			case '\\':	*bp++ = '\\'; break;
414*74a4d8c2SCharles.Forsyth 			case 'n':	*bp++ = '\n'; break;
415*74a4d8c2SCharles.Forsyth 			case 't':	*bp++ = '\t'; break;
416*74a4d8c2SCharles.Forsyth 			case 'b':	*bp++ = '\b'; break;
417*74a4d8c2SCharles.Forsyth 			case 'f':	*bp++ = '\f'; break;
418*74a4d8c2SCharles.Forsyth 			case 'r':	*bp++ = '\r'; break;
419*74a4d8c2SCharles.Forsyth 			default:
420*74a4d8c2SCharles.Forsyth 				if (!isdigit(c)) {
421*74a4d8c2SCharles.Forsyth 					*bp++ = c;
422*74a4d8c2SCharles.Forsyth 					break;
423*74a4d8c2SCharles.Forsyth 				}
424*74a4d8c2SCharles.Forsyth 				n = c - '0';
425*74a4d8c2SCharles.Forsyth 				if (isdigit(s[1])) {
426*74a4d8c2SCharles.Forsyth 					n = 8 * n + *++s - '0';
427*74a4d8c2SCharles.Forsyth 					if (isdigit(s[1]))
428*74a4d8c2SCharles.Forsyth 						n = 8 * n + *++s - '0';
429*74a4d8c2SCharles.Forsyth 				}
430*74a4d8c2SCharles.Forsyth 				*bp++ = n;
431*74a4d8c2SCharles.Forsyth 				break;
432*74a4d8c2SCharles.Forsyth 			}
433*74a4d8c2SCharles.Forsyth 		}
434*74a4d8c2SCharles.Forsyth 	}
435*74a4d8c2SCharles.Forsyth 	*bp++ = 0;
436*74a4d8c2SCharles.Forsyth 	return (char *) buf;
437*74a4d8c2SCharles.Forsyth }
438