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