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