xref: /original-bsd/old/awk/tran.c (revision 2301fdfb)
1 #ifndef lint
2 static char sccsid[] = "@(#)tran.c	4.5 10/22/87";
3 #endif
4 
5 #include "stdio.h"
6 #include "awk.def"
7 #include "awk.h"
8 
9 cell *symtab[MAXSYM];	/* symbol table pointers */
10 
11 char	**FS;	/* initial field sep */
12 char	**RS;	/* initial record sep */
13 char	**OFS;	/* output field sep */
14 char	**ORS;	/* output record sep */
15 char	**OFMT;	/*output format for numbers*/
16 awkfloat *NF;	/* number of fields in current record */
17 awkfloat *NR;	/* number of current record */
18 char	**FILENAME;	/* current filename argument */
19 
20 cell	*recloc;	/* location of record */
21 cell	*nrloc;		/* NR */
22 cell	*nfloc;		/* NF */
23 
24 syminit()
25 {
26 	setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab);
27 	/* this one is used for if(x)... tests: */
28 	setsymtab("$zero&null", tostring(""), 0.0, NUM|STR|CON|FLD, symtab);
29 	recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab);
30 	dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab, 0), NULL);
31 	FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval;
32 	RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval;
33 	OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval;
34 	ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval;
35 	OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval;
36 	FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval;
37 	nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab);
38 	NF = &nfloc->fval;
39 	nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab);
40 	NR = &nrloc->fval;
41 }
42 
43 cell **makesymtab()
44 {
45 	int i;
46 	cell **cp;
47 
48 	cp = (cell **) malloc(MAXSYM * sizeof(cell *));
49 	if (cp == NULL)
50 		error(FATAL, "out of space in makesymtab");
51 	for (i = 0; i < MAXSYM; i++)
52 		cp[i] = 0;
53 	return(cp);
54 }
55 
56 freesymtab(ap)	/* free symbol table */
57 cell *ap;
58 {
59 	cell *cp, **tp;
60 	int i;
61 
62 	if (!(ap->tval & ARR))
63 		return;
64 	tp = (cell **) ap->sval;
65 	for (i = 0; i < MAXSYM; i++) {
66 		for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
67 			strfree(cp->nval);
68 			strfree(cp->sval);
69 			free(cp);
70 		}
71 	}
72 	xfree(tp);
73 }
74 
75 cell *setsymtab(n, s, f, t, tab)
76 char *n, *s;
77 awkfloat f;
78 unsigned t;
79 cell **tab;
80 {
81 	register h;
82 	register cell *p;
83 	cell *lookup();
84 
85 	if (n != NULL && (p = lookup(n, tab, 0)) != NULL) {
86 		if (s != EMPTY ) xfree(s); /* careful here */
87 		dprintf("setsymtab found %o: %s", p, p->nval, NULL);
88 		dprintf(" %s %g %o\n", p->sval, p->fval, p->tval);
89 		return(p);
90 	}
91 	p = (cell *) malloc(sizeof(cell));
92 	if (p == NULL)
93 		error(FATAL, "symbol table overflow at %s", n);
94 	p->nval = tostring(n);
95 	p->sval = s;
96 	p->fval = f;
97 	p->tval = t;
98 	h = hash(n);
99 	p->nextval = tab[h];
100 	tab[h] = p;
101 	dprintf("setsymtab set %o: %s", p, p->nval, NULL);
102 	dprintf(" %s %g %o\n", p->sval, p->fval, p->tval);
103 	return(p);
104 }
105 
106 hash(s)	/* form hash value for string s */
107 register unsigned char *s;
108 {
109 	register int hashval;
110 
111 	for (hashval = 0; *s != '\0'; )
112 		hashval += *s++;
113 	return(hashval % MAXSYM);
114 }
115 
116 cell *lookup(s, tab, flag)	/* look for s in tab, flag must match*/
117 register char *s;
118 cell **tab;
119 {
120 	register cell *p;
121 
122 	for (p = tab[hash(s)]; p != NULL; p = p->nextval)
123 		if (strcmp(s, p->nval) == 0 &&
124 			(flag == 0 || flag == p->tval))
125 			return(p);	/* found it */
126 	return(NULL);	/* not found */
127 }
128 
129 awkfloat setfval(vp, f)
130 register cell *vp;
131 awkfloat f;
132 {
133 	dprintf("setfval: %o %g\n", vp, f, NULL);
134 	checkval(vp);
135 	if (vp == recloc)
136 		error(FATAL, "can't set $0");
137 	vp->tval &= ~STR;	/* mark string invalid */
138 	vp->tval |= NUM;	/* mark number ok */
139 	if ((vp->tval & FLD) && isnull(vp->nval))
140 		donerec = 0;
141 	return(vp->fval = f);
142 }
143 
144 char *setsval(vp, s)
145 register cell *vp;
146 char *s;
147 {
148 	dprintf("setsval: %o %s\n", vp, s, NULL);
149 	checkval(vp);
150 	if (vp == recloc)
151 		error(FATAL, "can't set $0");
152 	vp->tval &= ~NUM;
153 	vp->tval |= STR;
154 	if ((vp->tval & FLD) && isnull(vp->nval))
155 		donerec = 0;
156 	if (!(vp->tval&FLD))
157 		strfree(vp->sval);
158 	vp->tval &= ~FLD;
159 	return(vp->sval = tostring(s));
160 }
161 
162 awkfloat getfval(vp)
163 register cell *vp;
164 {
165 
166 	if (vp->sval == record && donerec == 0)
167 		recbld();
168 	dprintf("getfval: %o", vp, NULL, NULL);
169 	checkval(vp);
170 	if ((vp->tval & NUM) == 0) {
171 		/* the problem is to make non-numeric things */
172 		/* have unlikely numeric variables, so that */
173 		/* $1 == $2 comparisons sort of make sense when */
174 		/* one or the other is numeric */
175 		if (isnumber(vp->sval)) {
176 			vp->fval = atof(vp->sval);
177 			if (!(vp->tval & CON))	/* don't change type of a constant */
178 				vp->tval |= NUM;
179 		}
180 		else
181 			vp->fval = 0.0;	/* not a very good idea */
182 	}
183 	dprintf("  %g\n", vp->fval, NULL, NULL);
184 	return(vp->fval);
185 }
186 
187 char *getsval(vp)
188 register cell *vp;
189 {
190 	char s[100];
191 
192 	if (vp->sval == record && donerec == 0)
193 		recbld();
194 	dprintf("getsval: %o", vp, NULL, NULL);
195 	checkval(vp);
196 	if ((vp->tval & STR) == 0) {
197 		if (!(vp->tval&FLD))
198 			strfree(vp->sval);
199 		if ((long)vp->fval==vp->fval)
200 			(void)sprintf(s, "%.20g", vp->fval);
201 		else
202 			(void)sprintf(s, *OFMT, vp->fval);
203 		vp->sval = tostring(s);
204 		vp->tval &= ~FLD;
205 		vp->tval |= STR;
206 	}
207 	dprintf("  %s\n", vp->sval, NULL, NULL);
208 	return(vp->sval);
209 }
210 
211 checkval(vp)
212 register cell *vp;
213 {
214 	if (vp->tval & ARR)
215 		error(FATAL, "illegal reference to array %s", vp->nval);
216 	if ((vp->tval & (NUM | STR)) == 0)
217 		error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval,
218 			vp->sval, vp->fval, vp->tval);
219 }
220 
221 char *tostring(s)
222 register char *s;
223 {
224 	register char *p;
225 
226 	if (s==NULL){
227 		p = malloc(1);
228 		if (p == NULL)
229 			error(FATAL, "out of space in tostring on %s", s);
230 		*p = '\0';
231 	} else {
232 		p = malloc(strlen(s)+1);
233 		if (p == NULL)
234 			error(FATAL, "out of space in tostring on %s", s);
235 		strcpy(p, s);
236 	}
237 	return(p);
238 }
239 #ifndef yfree
240 yfree(a) char *a;
241 {
242 	printf("%o\n", a);
243 	free(a);
244 }
245 #endif
246 #ifdef malloc
247 #undef malloc
248 char *ymalloc(u) unsigned u;
249 {	char *p;
250 	p = malloc(u);
251 	printf("%o %o\n", u, p);
252 	return(p);
253 }
254 #endif
255