Commit | Line | Data |
---|---|---|
b803c326 | 1 | #ifndef lint |
e58105eb | 2 | static char sccsid[] = "@(#)tran.c 4.4 %G%"; |
b803c326 | 3 | #endif |
b455c1c4 KM |
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; | |
c48090b0 SL |
36 | FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval; |
37 | nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab); | |
b455c1c4 | 38 | NF = &nfloc->fval; |
c48090b0 | 39 | nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab); |
b455c1c4 KM |
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) { | |
c48090b0 SL |
67 | strfree(cp->nval); |
68 | strfree(cp->sval); | |
b455c1c4 KM |
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) { | |
c48090b0 | 86 | if (s != EMPTY ) xfree(s); /* careful here */ |
b455c1c4 KM |
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 */ | |
e58105eb | 139 | if ((vp->tval & FLD) && isnull(vp->nval)) |
b455c1c4 KM |
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; | |
e58105eb | 154 | if ((vp->tval & FLD) && isnull(vp->nval)) |
b455c1c4 KM |
155 | donerec = 0; |
156 | if (!(vp->tval&FLD)) | |
c48090b0 | 157 | strfree(vp->sval); |
b455c1c4 KM |
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)) | |
c48090b0 | 198 | strfree(vp->sval); |
b455c1c4 KM |
199 | if ((long)vp->fval==vp->fval) |
200 | sprintf(s, "%.20g", vp->fval); | |
201 | else | |
202 | 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 | ||
c48090b0 SL |
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 | } | |
b455c1c4 KM |
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 |