xref: /titanic_54/usr/src/cmd/awk/tran.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 2.13	*/
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #define	DEBUG
35*7c478bd9Sstevel@tonic-gate #include <stdio.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #include <string.h>
38*7c478bd9Sstevel@tonic-gate #include "awk.h"
39*7c478bd9Sstevel@tonic-gate #include "y.tab.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #define	FULLTAB	2	/* rehash when table gets this x full */
42*7c478bd9Sstevel@tonic-gate #define	GROWTAB 4	/* grow table by this factor */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate Array	*symtab;	/* main symbol table */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate uchar	**FS;		/* initial field sep */
47*7c478bd9Sstevel@tonic-gate uchar	**RS;		/* initial record sep */
48*7c478bd9Sstevel@tonic-gate uchar	**OFS;		/* output field sep */
49*7c478bd9Sstevel@tonic-gate uchar	**ORS;		/* output record sep */
50*7c478bd9Sstevel@tonic-gate uchar	**OFMT;		/* output format for numbers*/
51*7c478bd9Sstevel@tonic-gate Awkfloat *NF;		/* number of fields in current record */
52*7c478bd9Sstevel@tonic-gate Awkfloat *NR;		/* number of current record */
53*7c478bd9Sstevel@tonic-gate Awkfloat *FNR;		/* number of current record in current file */
54*7c478bd9Sstevel@tonic-gate uchar	**FILENAME;	/* current filename argument */
55*7c478bd9Sstevel@tonic-gate Awkfloat *ARGC;		/* number of arguments from command line */
56*7c478bd9Sstevel@tonic-gate uchar	**SUBSEP;	/* subscript separator for a[i,j,k]; default \034 */
57*7c478bd9Sstevel@tonic-gate Awkfloat *RSTART;	/* start of re matched with ~; origin 1 (!) */
58*7c478bd9Sstevel@tonic-gate Awkfloat *RLENGTH;	/* length of same */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate Cell	*recloc;	/* location of record */
61*7c478bd9Sstevel@tonic-gate Cell	*nrloc;		/* NR */
62*7c478bd9Sstevel@tonic-gate Cell	*nfloc;		/* NF */
63*7c478bd9Sstevel@tonic-gate Cell	*fnrloc;	/* FNR */
64*7c478bd9Sstevel@tonic-gate Array	*ARGVtab;	/* symbol table containing ARGV[...] */
65*7c478bd9Sstevel@tonic-gate Array	*ENVtab;	/* symbol table containing ENVIRON[...] */
66*7c478bd9Sstevel@tonic-gate Cell	*rstartloc;	/* RSTART */
67*7c478bd9Sstevel@tonic-gate Cell	*rlengthloc;	/* RLENGTH */
68*7c478bd9Sstevel@tonic-gate Cell	*symtabloc;	/* SYMTAB */
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate Cell	*nullloc;
71*7c478bd9Sstevel@tonic-gate Node	*nullnode;	/* zero&null, converted into a node for comparisons */
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate extern Node *valtonode();
74*7c478bd9Sstevel@tonic-gate extern Cell fldtab[];
75*7c478bd9Sstevel@tonic-gate extern uchar recdata[];
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate syminit()
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate 	int i;
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	fldtab[0].ctype = OCELL;
82*7c478bd9Sstevel@tonic-gate 	fldtab[0].csub = CFLD;
83*7c478bd9Sstevel@tonic-gate 	fldtab[0].nval = (uchar*) "$0";
84*7c478bd9Sstevel@tonic-gate 	fldtab[0].sval = recdata;
85*7c478bd9Sstevel@tonic-gate 	fldtab[0].fval = 0.0;
86*7c478bd9Sstevel@tonic-gate 	fldtab[0].tval = REC|STR|DONTFREE;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate 	for (i = 1; i < MAXFLD; i++) {
89*7c478bd9Sstevel@tonic-gate 		fldtab[i].ctype = OCELL;
90*7c478bd9Sstevel@tonic-gate 		fldtab[i].csub = CFLD;
91*7c478bd9Sstevel@tonic-gate 		fldtab[i].nval = NULL;
92*7c478bd9Sstevel@tonic-gate 		fldtab[i].sval = (uchar*) "";
93*7c478bd9Sstevel@tonic-gate 		fldtab[i].fval = 0.0;
94*7c478bd9Sstevel@tonic-gate 		fldtab[i].tval = FLD|STR|DONTFREE;
95*7c478bd9Sstevel@tonic-gate 	}
96*7c478bd9Sstevel@tonic-gate 	symtab = makesymtab(NSYMTAB);
97*7c478bd9Sstevel@tonic-gate 	setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
98*7c478bd9Sstevel@tonic-gate 	/* this is used for if(x)... tests: */
99*7c478bd9Sstevel@tonic-gate 	nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
100*7c478bd9Sstevel@tonic-gate 	nullnode = valtonode(nullloc, CCON);
101*7c478bd9Sstevel@tonic-gate 	/* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */
102*7c478bd9Sstevel@tonic-gate 	recloc = &fldtab[0];
103*7c478bd9Sstevel@tonic-gate 	FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
104*7c478bd9Sstevel@tonic-gate 	RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
105*7c478bd9Sstevel@tonic-gate 	OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
106*7c478bd9Sstevel@tonic-gate 	ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
107*7c478bd9Sstevel@tonic-gate 	OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
108*7c478bd9Sstevel@tonic-gate 	FILENAME = &setsymtab("FILENAME", "-", 0.0, STR|DONTFREE, symtab)->sval;
109*7c478bd9Sstevel@tonic-gate 	nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
110*7c478bd9Sstevel@tonic-gate 	NF = &nfloc->fval;
111*7c478bd9Sstevel@tonic-gate 	nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
112*7c478bd9Sstevel@tonic-gate 	NR = &nrloc->fval;
113*7c478bd9Sstevel@tonic-gate 	fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
114*7c478bd9Sstevel@tonic-gate 	FNR = &fnrloc->fval;
115*7c478bd9Sstevel@tonic-gate 	SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
116*7c478bd9Sstevel@tonic-gate 	rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
117*7c478bd9Sstevel@tonic-gate 	RSTART = &rstartloc->fval;
118*7c478bd9Sstevel@tonic-gate 	rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
119*7c478bd9Sstevel@tonic-gate 	RLENGTH = &rlengthloc->fval;
120*7c478bd9Sstevel@tonic-gate 	symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
121*7c478bd9Sstevel@tonic-gate 	symtabloc->sval = (uchar *) symtab;
122*7c478bd9Sstevel@tonic-gate }
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate arginit(ac, av)
125*7c478bd9Sstevel@tonic-gate 	int ac;
126*7c478bd9Sstevel@tonic-gate 	uchar *av[];
127*7c478bd9Sstevel@tonic-gate {
128*7c478bd9Sstevel@tonic-gate 	Cell *cp;
129*7c478bd9Sstevel@tonic-gate 	Array *makesymtab();
130*7c478bd9Sstevel@tonic-gate 	int i;
131*7c478bd9Sstevel@tonic-gate 	uchar temp[5];
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	for (i = 1; i < ac; i++)	/* first make FILENAME first real argument */
134*7c478bd9Sstevel@tonic-gate 		if (!isclvar(av[i])) {
135*7c478bd9Sstevel@tonic-gate 			setsval(lookup("FILENAME", symtab), av[i]);
136*7c478bd9Sstevel@tonic-gate 			break;
137*7c478bd9Sstevel@tonic-gate 		}
138*7c478bd9Sstevel@tonic-gate 	ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
139*7c478bd9Sstevel@tonic-gate 	cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
140*7c478bd9Sstevel@tonic-gate 	ARGVtab = makesymtab(NSYMTAB);	/* could be (int) ARGC as well */
141*7c478bd9Sstevel@tonic-gate 	cp->sval = (uchar *) ARGVtab;
142*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ac; i++) {
143*7c478bd9Sstevel@tonic-gate 		sprintf((char *)temp, "%d", i);
144*7c478bd9Sstevel@tonic-gate 		if (isnumber(*av))
145*7c478bd9Sstevel@tonic-gate 			setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
146*7c478bd9Sstevel@tonic-gate 		else
147*7c478bd9Sstevel@tonic-gate 			setsymtab(temp, *av, 0.0, STR, ARGVtab);
148*7c478bd9Sstevel@tonic-gate 		av++;
149*7c478bd9Sstevel@tonic-gate 	}
150*7c478bd9Sstevel@tonic-gate }
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate envinit(envp)
153*7c478bd9Sstevel@tonic-gate 	uchar *envp[];
154*7c478bd9Sstevel@tonic-gate {
155*7c478bd9Sstevel@tonic-gate 	Cell *cp;
156*7c478bd9Sstevel@tonic-gate 	Array *makesymtab();
157*7c478bd9Sstevel@tonic-gate 	uchar *p;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
160*7c478bd9Sstevel@tonic-gate 	ENVtab = makesymtab(NSYMTAB);
161*7c478bd9Sstevel@tonic-gate 	cp->sval = (uchar *) ENVtab;
162*7c478bd9Sstevel@tonic-gate 	for ( ; *envp; envp++) {
163*7c478bd9Sstevel@tonic-gate 		if ((p = (uchar *) strchr((char *) *envp, '=')) == NULL)	/* index() on bsd */
164*7c478bd9Sstevel@tonic-gate 			continue;
165*7c478bd9Sstevel@tonic-gate 		*p++ = 0;	/* split into two strings at = */
166*7c478bd9Sstevel@tonic-gate 		if (isnumber(p))
167*7c478bd9Sstevel@tonic-gate 			setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
168*7c478bd9Sstevel@tonic-gate 		else
169*7c478bd9Sstevel@tonic-gate 			setsymtab(*envp, p, 0.0, STR, ENVtab);
170*7c478bd9Sstevel@tonic-gate 		p[-1] = '=';	/* restore in case env is passed down to a shell */
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate }
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate Array *makesymtab(n)
175*7c478bd9Sstevel@tonic-gate 	int n;
176*7c478bd9Sstevel@tonic-gate {
177*7c478bd9Sstevel@tonic-gate 	Array *ap;
178*7c478bd9Sstevel@tonic-gate 	Cell **tp;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	ap = (Array *) malloc(sizeof(Array));
181*7c478bd9Sstevel@tonic-gate 	tp = (Cell **) calloc(n, sizeof(Cell *));
182*7c478bd9Sstevel@tonic-gate 	if (ap == NULL || tp == NULL)
183*7c478bd9Sstevel@tonic-gate 		ERROR "out of space in makesymtab" FATAL;
184*7c478bd9Sstevel@tonic-gate 	ap->nelem = 0;
185*7c478bd9Sstevel@tonic-gate 	ap->size = n;
186*7c478bd9Sstevel@tonic-gate 	ap->tab = tp;
187*7c478bd9Sstevel@tonic-gate 	return(ap);
188*7c478bd9Sstevel@tonic-gate }
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate freesymtab(ap)	/* free symbol table */
191*7c478bd9Sstevel@tonic-gate 	Cell *ap;
192*7c478bd9Sstevel@tonic-gate {
193*7c478bd9Sstevel@tonic-gate 	Cell *cp, *next;
194*7c478bd9Sstevel@tonic-gate 	Array *tp;
195*7c478bd9Sstevel@tonic-gate 	int i;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 	if (!isarr(ap))
198*7c478bd9Sstevel@tonic-gate 		return;
199*7c478bd9Sstevel@tonic-gate 	tp = (Array *) ap->sval;
200*7c478bd9Sstevel@tonic-gate 	if (tp == NULL)
201*7c478bd9Sstevel@tonic-gate 		return;
202*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < tp->size; i++) {
203*7c478bd9Sstevel@tonic-gate 		for (cp = tp->tab[i]; cp != NULL; cp = next) {
204*7c478bd9Sstevel@tonic-gate 			next = cp->cnext;
205*7c478bd9Sstevel@tonic-gate 			xfree(cp->nval);
206*7c478bd9Sstevel@tonic-gate 			if (freeable(cp))
207*7c478bd9Sstevel@tonic-gate 				xfree(cp->sval);
208*7c478bd9Sstevel@tonic-gate 			free(cp);
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 	free(tp->tab);
212*7c478bd9Sstevel@tonic-gate 	free(tp);
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate freeelem(ap, s)		/* free elem s from ap (i.e., ap["s"] */
216*7c478bd9Sstevel@tonic-gate 	Cell *ap;
217*7c478bd9Sstevel@tonic-gate 	uchar *s;
218*7c478bd9Sstevel@tonic-gate {
219*7c478bd9Sstevel@tonic-gate 	Array *tp;
220*7c478bd9Sstevel@tonic-gate 	Cell *p, *prev = NULL;
221*7c478bd9Sstevel@tonic-gate 	int h;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	tp = (Array *) ap->sval;
224*7c478bd9Sstevel@tonic-gate 	h = hash(s, tp->size);
225*7c478bd9Sstevel@tonic-gate 	for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
226*7c478bd9Sstevel@tonic-gate 		if (strcmp((char *) s, (char *) p->nval) == 0) {
227*7c478bd9Sstevel@tonic-gate 			if (prev == NULL)	/* 1st one */
228*7c478bd9Sstevel@tonic-gate 				tp->tab[h] = p->cnext;
229*7c478bd9Sstevel@tonic-gate 			else			/* middle somewhere */
230*7c478bd9Sstevel@tonic-gate 				prev->cnext = p->cnext;
231*7c478bd9Sstevel@tonic-gate 			if (freeable(p))
232*7c478bd9Sstevel@tonic-gate 				xfree(p->sval);
233*7c478bd9Sstevel@tonic-gate 			free(p->nval);
234*7c478bd9Sstevel@tonic-gate 			free(p);
235*7c478bd9Sstevel@tonic-gate 			tp->nelem--;
236*7c478bd9Sstevel@tonic-gate 			return;
237*7c478bd9Sstevel@tonic-gate 		}
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate Cell *setsymtab(n, s, f, t, tp)
241*7c478bd9Sstevel@tonic-gate 	uchar *n, *s;
242*7c478bd9Sstevel@tonic-gate 	Awkfloat f;
243*7c478bd9Sstevel@tonic-gate 	unsigned t;
244*7c478bd9Sstevel@tonic-gate 	Array *tp;
245*7c478bd9Sstevel@tonic-gate {
246*7c478bd9Sstevel@tonic-gate 	register int h;
247*7c478bd9Sstevel@tonic-gate 	register Cell *p;
248*7c478bd9Sstevel@tonic-gate 	Cell *lookup();
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	if (n != NULL && (p = lookup(n, tp)) != NULL) {
251*7c478bd9Sstevel@tonic-gate 		dprintf( ("setsymtab found %o: n=%s", p, p->nval) );
252*7c478bd9Sstevel@tonic-gate 		dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
253*7c478bd9Sstevel@tonic-gate 		return(p);
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 	p = (Cell *) malloc(sizeof(Cell));
256*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
257*7c478bd9Sstevel@tonic-gate 		ERROR "symbol table overflow at %s", n FATAL;
258*7c478bd9Sstevel@tonic-gate 	p->nval = tostring(n);
259*7c478bd9Sstevel@tonic-gate 	p->sval = s ? tostring(s) : tostring("");
260*7c478bd9Sstevel@tonic-gate 	p->fval = f;
261*7c478bd9Sstevel@tonic-gate 	p->tval = t;
262*7c478bd9Sstevel@tonic-gate 	p->csub = 0;
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	tp->nelem++;
265*7c478bd9Sstevel@tonic-gate 	if (tp->nelem > FULLTAB * tp->size)
266*7c478bd9Sstevel@tonic-gate 		rehash(tp);
267*7c478bd9Sstevel@tonic-gate 	h = hash(n, tp->size);
268*7c478bd9Sstevel@tonic-gate 	p->cnext = tp->tab[h];
269*7c478bd9Sstevel@tonic-gate 	tp->tab[h] = p;
270*7c478bd9Sstevel@tonic-gate 	dprintf( ("setsymtab set %o: n=%s", p, p->nval) );
271*7c478bd9Sstevel@tonic-gate 	dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
272*7c478bd9Sstevel@tonic-gate 	return(p);
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate hash(s, n)	/* form hash value for string s */
276*7c478bd9Sstevel@tonic-gate 	register uchar *s;
277*7c478bd9Sstevel@tonic-gate 	int n;
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	register unsigned hashval;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	for (hashval = 0; *s != '\0'; s++)
282*7c478bd9Sstevel@tonic-gate 		hashval = (*s + 31 * hashval);
283*7c478bd9Sstevel@tonic-gate 	return hashval % n;
284*7c478bd9Sstevel@tonic-gate }
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate rehash(tp)	/* rehash items in small table into big one */
287*7c478bd9Sstevel@tonic-gate 	Array *tp;
288*7c478bd9Sstevel@tonic-gate {
289*7c478bd9Sstevel@tonic-gate 	int i, nh, nsz;
290*7c478bd9Sstevel@tonic-gate 	Cell *cp, *op, **np;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	nsz = GROWTAB * tp->size;
293*7c478bd9Sstevel@tonic-gate 	np = (Cell **) calloc(nsz, sizeof(Cell *));
294*7c478bd9Sstevel@tonic-gate 	if (np == NULL)
295*7c478bd9Sstevel@tonic-gate 		ERROR "out of space in rehash" FATAL;
296*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < tp->size; i++) {
297*7c478bd9Sstevel@tonic-gate 		for (cp = tp->tab[i]; cp; cp = op) {
298*7c478bd9Sstevel@tonic-gate 			op = cp->cnext;
299*7c478bd9Sstevel@tonic-gate 			nh = hash(cp->nval, nsz);
300*7c478bd9Sstevel@tonic-gate 			cp->cnext = np[nh];
301*7c478bd9Sstevel@tonic-gate 			np[nh] = cp;
302*7c478bd9Sstevel@tonic-gate 		}
303*7c478bd9Sstevel@tonic-gate 	}
304*7c478bd9Sstevel@tonic-gate 	free(tp->tab);
305*7c478bd9Sstevel@tonic-gate 	tp->tab = np;
306*7c478bd9Sstevel@tonic-gate 	tp->size = nsz;
307*7c478bd9Sstevel@tonic-gate }
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate Cell *lookup(s, tp)	/* look for s in tp */
310*7c478bd9Sstevel@tonic-gate 	register uchar *s;
311*7c478bd9Sstevel@tonic-gate 	Array *tp;
312*7c478bd9Sstevel@tonic-gate {
313*7c478bd9Sstevel@tonic-gate 	register Cell *p, *prev = NULL;
314*7c478bd9Sstevel@tonic-gate 	int h;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	h = hash(s, tp->size);
317*7c478bd9Sstevel@tonic-gate 	for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
318*7c478bd9Sstevel@tonic-gate 		if (strcmp((char *) s, (char *) p->nval) == 0)
319*7c478bd9Sstevel@tonic-gate 			return(p);	/* found it */
320*7c478bd9Sstevel@tonic-gate 	return(NULL);			/* not found */
321*7c478bd9Sstevel@tonic-gate }
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate Awkfloat setfval(vp, f)
324*7c478bd9Sstevel@tonic-gate 	register Cell *vp;
325*7c478bd9Sstevel@tonic-gate 	Awkfloat f;
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & (NUM | STR)) == 0)
328*7c478bd9Sstevel@tonic-gate 		funnyvar(vp, "assign to");
329*7c478bd9Sstevel@tonic-gate 	if (vp->tval & FLD) {
330*7c478bd9Sstevel@tonic-gate 		donerec = 0;	/* mark $0 invalid */
331*7c478bd9Sstevel@tonic-gate 		if (vp-fldtab > *NF)
332*7c478bd9Sstevel@tonic-gate 			newfld(vp-fldtab);
333*7c478bd9Sstevel@tonic-gate 		dprintf( ("setting field %d to %g\n", vp-fldtab, f) );
334*7c478bd9Sstevel@tonic-gate 	} else if (vp->tval & REC) {
335*7c478bd9Sstevel@tonic-gate 		donefld = 0;	/* mark $1... invalid */
336*7c478bd9Sstevel@tonic-gate 		donerec = 1;
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate 	vp->tval &= ~STR;	/* mark string invalid */
339*7c478bd9Sstevel@tonic-gate 	vp->tval |= NUM;	/* mark number ok */
340*7c478bd9Sstevel@tonic-gate 	dprintf( ("setfval %p: %s = %g, t=%o\n", vp,
341*7c478bd9Sstevel@tonic-gate 		vp->nval ? vp->nval : (unsigned char *)"NULL",
342*7c478bd9Sstevel@tonic-gate 		f, vp->tval) );
343*7c478bd9Sstevel@tonic-gate 	return vp->fval = f;
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate funnyvar(vp, rw)
347*7c478bd9Sstevel@tonic-gate 	Cell *vp;
348*7c478bd9Sstevel@tonic-gate 	char *rw;
349*7c478bd9Sstevel@tonic-gate {
350*7c478bd9Sstevel@tonic-gate 	if (vp->tval & ARR)
351*7c478bd9Sstevel@tonic-gate 		ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL;
352*7c478bd9Sstevel@tonic-gate 	if (vp->tval & FCN)
353*7c478bd9Sstevel@tonic-gate 		ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL;
354*7c478bd9Sstevel@tonic-gate 	ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o",
355*7c478bd9Sstevel@tonic-gate 		vp, vp->nval, vp->sval, vp->fval, vp->tval);
356*7c478bd9Sstevel@tonic-gate }
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate uchar *setsval(vp, s)
359*7c478bd9Sstevel@tonic-gate register Cell *vp;
360*7c478bd9Sstevel@tonic-gate uchar *s;
361*7c478bd9Sstevel@tonic-gate {
362*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & (NUM | STR)) == 0)
363*7c478bd9Sstevel@tonic-gate 		funnyvar(vp, "assign to");
364*7c478bd9Sstevel@tonic-gate 	if (vp->tval & FLD) {
365*7c478bd9Sstevel@tonic-gate 		donerec = 0;	/* mark $0 invalid */
366*7c478bd9Sstevel@tonic-gate 		if (vp-fldtab > *NF)
367*7c478bd9Sstevel@tonic-gate 			newfld(vp-fldtab);
368*7c478bd9Sstevel@tonic-gate 		dprintf( ("setting field %d to %s\n", vp-fldtab, s) );
369*7c478bd9Sstevel@tonic-gate 	} else if (vp->tval & REC) {
370*7c478bd9Sstevel@tonic-gate 		donefld = 0;	/* mark $1... invalid */
371*7c478bd9Sstevel@tonic-gate 		donerec = 1;
372*7c478bd9Sstevel@tonic-gate 	}
373*7c478bd9Sstevel@tonic-gate 	vp->tval &= ~NUM;
374*7c478bd9Sstevel@tonic-gate 	vp->tval |= STR;
375*7c478bd9Sstevel@tonic-gate 	if (freeable(vp))
376*7c478bd9Sstevel@tonic-gate 		xfree(vp->sval);
377*7c478bd9Sstevel@tonic-gate 	vp->tval &= ~DONTFREE;
378*7c478bd9Sstevel@tonic-gate 	dprintf( ("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
379*7c478bd9Sstevel@tonic-gate 	return(vp->sval = tostring(s));
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate Awkfloat r_getfval(vp)
383*7c478bd9Sstevel@tonic-gate register Cell *vp;
384*7c478bd9Sstevel@tonic-gate {
385*7c478bd9Sstevel@tonic-gate 	/* if (vp->tval & ARR)
386*7c478bd9Sstevel@tonic-gate 		ERROR "illegal reference to array %s", vp->nval FATAL;
387*7c478bd9Sstevel@tonic-gate 		return 0.0; */
388*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & (NUM | STR)) == 0)
389*7c478bd9Sstevel@tonic-gate 		funnyvar(vp, "read value of");
390*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & FLD) && donefld == 0)
391*7c478bd9Sstevel@tonic-gate 		fldbld();
392*7c478bd9Sstevel@tonic-gate 	else if ((vp->tval & REC) && donerec == 0)
393*7c478bd9Sstevel@tonic-gate 		recbld();
394*7c478bd9Sstevel@tonic-gate 	if (!isnum(vp)) {	/* not a number */
395*7c478bd9Sstevel@tonic-gate 		vp->fval = atof(vp->sval);	/* best guess */
396*7c478bd9Sstevel@tonic-gate 		if (isnumber(vp->sval) && !(vp->tval&CON))
397*7c478bd9Sstevel@tonic-gate 			vp->tval |= NUM;	/* make NUM only sparingly */
398*7c478bd9Sstevel@tonic-gate 	}
399*7c478bd9Sstevel@tonic-gate 	dprintf( ("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
400*7c478bd9Sstevel@tonic-gate 	return(vp->fval);
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate uchar *r_getsval(vp)
404*7c478bd9Sstevel@tonic-gate register Cell *vp;
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate 	uchar s[100];
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	/* if (vp->tval & ARR)
409*7c478bd9Sstevel@tonic-gate 		ERROR "illegal reference to array %s", vp->nval FATAL;
410*7c478bd9Sstevel@tonic-gate 		return ""; */
411*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & (NUM | STR)) == 0)
412*7c478bd9Sstevel@tonic-gate 		funnyvar(vp, "read value of");
413*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & FLD) && donefld == 0)
414*7c478bd9Sstevel@tonic-gate 		fldbld();
415*7c478bd9Sstevel@tonic-gate 	else if ((vp->tval & REC) && donerec == 0)
416*7c478bd9Sstevel@tonic-gate 		recbld();
417*7c478bd9Sstevel@tonic-gate 	if ((vp->tval & STR) == 0) {
418*7c478bd9Sstevel@tonic-gate 		if (!(vp->tval&DONTFREE))
419*7c478bd9Sstevel@tonic-gate 			xfree(vp->sval);
420*7c478bd9Sstevel@tonic-gate 		if ((long long)vp->fval == vp->fval)
421*7c478bd9Sstevel@tonic-gate 			sprintf((char *)s, "%.20g", vp->fval);
422*7c478bd9Sstevel@tonic-gate 		else
423*7c478bd9Sstevel@tonic-gate 			sprintf((char *)s, (char *)*OFMT, vp->fval);
424*7c478bd9Sstevel@tonic-gate 		vp->sval = tostring(s);
425*7c478bd9Sstevel@tonic-gate 		vp->tval &= ~DONTFREE;
426*7c478bd9Sstevel@tonic-gate 		vp->tval |= STR;
427*7c478bd9Sstevel@tonic-gate 	}
428*7c478bd9Sstevel@tonic-gate 	dprintf( ("getsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval) );
429*7c478bd9Sstevel@tonic-gate 	return(vp->sval);
430*7c478bd9Sstevel@tonic-gate }
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate uchar *tostring(s)
433*7c478bd9Sstevel@tonic-gate register uchar *s;
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	register uchar *p;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	p = (uchar *) malloc(strlen((char *) s)+1);
438*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
439*7c478bd9Sstevel@tonic-gate 		ERROR "out of space in tostring on %s", s FATAL;
440*7c478bd9Sstevel@tonic-gate 	strcpy((char *) p, (char *) s);
441*7c478bd9Sstevel@tonic-gate 	return(p);
442*7c478bd9Sstevel@tonic-gate }
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate uchar *qstring(s, delim)	/* collect string up to delim */
445*7c478bd9Sstevel@tonic-gate 	uchar *s;
446*7c478bd9Sstevel@tonic-gate 	int delim;
447*7c478bd9Sstevel@tonic-gate {
448*7c478bd9Sstevel@tonic-gate 	uchar *q;
449*7c478bd9Sstevel@tonic-gate 	int c, n;
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	for (q = cbuf; (c = *s) != delim; s++) {
452*7c478bd9Sstevel@tonic-gate 		if (q >= cbuf + RECSIZE - 1)
453*7c478bd9Sstevel@tonic-gate 			ERROR "string %.10s... too long", cbuf SYNTAX;
454*7c478bd9Sstevel@tonic-gate 		else if (c == '\n')
455*7c478bd9Sstevel@tonic-gate 			ERROR "newline in string %.10s...", cbuf SYNTAX;
456*7c478bd9Sstevel@tonic-gate 		else if (c != '\\')
457*7c478bd9Sstevel@tonic-gate 			*q++ = c;
458*7c478bd9Sstevel@tonic-gate 		else	/* \something */
459*7c478bd9Sstevel@tonic-gate 			switch (c = *++s) {
460*7c478bd9Sstevel@tonic-gate 			case '\\':	*q++ = '\\'; break;
461*7c478bd9Sstevel@tonic-gate 			case 'n':	*q++ = '\n'; break;
462*7c478bd9Sstevel@tonic-gate 			case 't':	*q++ = '\t'; break;
463*7c478bd9Sstevel@tonic-gate 			case 'b':	*q++ = '\b'; break;
464*7c478bd9Sstevel@tonic-gate 			case 'f':	*q++ = '\f'; break;
465*7c478bd9Sstevel@tonic-gate 			case 'r':	*q++ = '\r'; break;
466*7c478bd9Sstevel@tonic-gate 			default:
467*7c478bd9Sstevel@tonic-gate 				if (!isdigit(c)) {
468*7c478bd9Sstevel@tonic-gate 					*q++ = c;
469*7c478bd9Sstevel@tonic-gate 					break;
470*7c478bd9Sstevel@tonic-gate 				}
471*7c478bd9Sstevel@tonic-gate 				n = c - '0';
472*7c478bd9Sstevel@tonic-gate 				if (isdigit(s[1])) {
473*7c478bd9Sstevel@tonic-gate 					n = 8 * n + *++s - '0';
474*7c478bd9Sstevel@tonic-gate 					if (isdigit(s[1]))
475*7c478bd9Sstevel@tonic-gate 						n = 8 * n + *++s - '0';
476*7c478bd9Sstevel@tonic-gate 				}
477*7c478bd9Sstevel@tonic-gate 				*q++ = n;
478*7c478bd9Sstevel@tonic-gate 				break;
479*7c478bd9Sstevel@tonic-gate 			}
480*7c478bd9Sstevel@tonic-gate 	}
481*7c478bd9Sstevel@tonic-gate 	*q = '\0';
482*7c478bd9Sstevel@tonic-gate 	return cbuf;
483*7c478bd9Sstevel@tonic-gate }
484