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