|
|
1.1 root 1: #define DEBUG
2: #include <stdio.h>
3: #include <ctype.h>
4: #include "awk.h"
5: #include "y.tab.h"
6:
7: #define FULLTAB 2 /* rehash when table gets this x full */
8: #define GROWTAB 4 /* grow table by this factor */
9:
10: Array *symtab; /* main symbol table */
11:
12: uchar **FS; /* initial field sep */
13: uchar **RS; /* initial record sep */
14: uchar **OFS; /* output field sep */
15: uchar **ORS; /* output record sep */
16: uchar **OFMT; /* output format for numbers*/
17: Awkfloat *NF; /* number of fields in current record */
18: Awkfloat *NR; /* number of current record */
19: Awkfloat *FNR; /* number of current record in current file */
20: uchar **FILENAME; /* current filename argument */
21: Awkfloat *ARGC; /* number of arguments from command line */
22: uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
23: Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
24: Awkfloat *RLENGTH; /* length of same */
25:
26: Cell *recloc; /* location of record */
27: Cell *nrloc; /* NR */
28: Cell *nfloc; /* NF */
29: Cell *fnrloc; /* FNR */
30: Array *ARGVtab; /* symbol table containing ARGV[...] */
31: Cell *rstartloc; /* RSTART */
32: Cell *rlengthloc; /* RLENGTH */
33: Cell *symtabloc; /* SYMTAB */
34:
35: Cell *nullloc;
36: Node *nullnode; /* zero&null, converted into a node for comparisons */
37:
38: syminit()
39: {
40: extern Node *valtonode();
41: extern Cell fldtab[];
42:
43: symtab = makesymtab(NSYMTAB);
44: setsymtab("0", "0", 0.0, NUM|STR|CON, symtab);
45: /* this is used for if(x)... tests: */
46: nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON, symtab);
47: nullnode = valtonode(nullloc, CCON);
48: /* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */
49: recloc = &fldtab[0];
50: FS = &setsymtab("FS", " ", 0.0, STR, symtab)->sval;
51: RS = &setsymtab("RS", "\n", 0.0, STR, symtab)->sval;
52: OFS = &setsymtab("OFS", " ", 0.0, STR, symtab)->sval;
53: ORS = &setsymtab("ORS", "\n", 0.0, STR, symtab)->sval;
54: OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR, symtab)->sval;
55: FILENAME = &setsymtab("FILENAME", "", 0.0, STR, symtab)->sval;
56: nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
57: NF = &nfloc->fval;
58: nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
59: NR = &nrloc->fval;
60: fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
61: FNR = &fnrloc->fval;
62: SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR, symtab)->sval;
63: rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
64: RSTART = &rstartloc->fval;
65: rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
66: RLENGTH = &rlengthloc->fval;
67: symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
68: symtabloc->sval = (uchar *) symtab;
69: }
70:
71: arginit(ac, av)
72: int ac;
73: uchar *av[];
74: {
75: Cell *cp;
76: Array *makesymtab();
77: int i;
78: uchar temp[5];
79:
80: ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
81: cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
82: ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
83: cp->sval = (uchar *) ARGVtab;
84: for (i = 0; i < ac; i++) {
85: sprintf(temp, "%d", i);
86: if (isnumber(*av))
87: setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
88: else
89: setsymtab(temp, *av, 0.0, STR, ARGVtab);
90: av++;
91: }
92: }
93:
94: Array *makesymtab(n)
95: int n;
96: {
97: Array *ap;
98: Cell **tp;
99:
100: ap = (Array *) Malloc(sizeof(Array));
101: tp = (Cell **) Calloc(n, sizeof(Cell *));
102: if (ap == NULL || tp == NULL)
103: error(FATAL, "out of space in makesymtab");
104: ap->nelem = 0;
105: ap->size = n;
106: ap->tab = tp;
107: return(ap);
108: }
109:
110: freesymtab(ap) /* free symbol table */
111: Cell *ap;
112: {
113: Cell *cp;
114: Array *tp;
115: int i;
116:
117: if (!isarr(ap))
118: return;
119: tp = (Array *) ap->sval;
120: if (tp == NULL)
121: return;
122: for (i = 0; i < tp->size; i++) {
123: for (cp = tp->tab[i]; cp != NULL; cp = cp->cnext) {
124: xfree(cp->nval);
125: xfree(cp->sval);
126: Free(cp);
127: }
128: }
129: Free(tp->tab);
130: Free(tp);
131: }
132:
133: freeelem(ap, s) /* free elem s from ap (i.e., ap["s"] */
134: Cell *ap;
135: uchar *s;
136: {
137: Array *tp;
138: Cell *p, *prev = NULL;
139: int h;
140:
141: tp = (Array *) ap->sval;
142: h = hash(s, tp->size);
143: for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
144: if (strcmp(s, p->nval) == 0) {
145: if (prev == NULL) /* 1st one */
146: tp->tab[h] = p->cnext;
147: else /* middle somewhere */
148: prev->cnext = p->cnext;
149: if (freeable(p))
150: xfree(p->sval);
151: Free(p->nval);
152: Free(p);
153: tp->nelem--;
154: return;
155: }
156: }
157:
158: Cell *setsymtab(n, s, f, t, tp)
159: uchar *n, *s;
160: Awkfloat f;
161: unsigned t;
162: Array *tp;
163: {
164: register h;
165: register Cell *p;
166: Cell *lookup();
167:
168: if (n != NULL && (p = lookup(n, tp)) != NULL) {
169: dprintf("setsymtab found %o: n=%s", p, p->nval, NULL);
170: dprintf(" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval);
171: return(p);
172: }
173: p = (Cell *) Malloc(sizeof(Cell));
174: if (p == NULL)
175: error(FATAL, "symbol table overflow at %s", n);
176: p->nval = tostring(n);
177: p->sval = s ? tostring(s) : tostring("");
178: p->fval = f;
179: p->tval = t;
180: tp->nelem++;
181: if (tp->nelem > FULLTAB * tp->size)
182: rehash(tp);
183: h = hash(n, tp->size);
184: p->cnext = tp->tab[h];
185: tp->tab[h] = p;
186: dprintf("setsymtab set %o: n=%s", p, p->nval, NULL);
187: dprintf(" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval);
188: return(p);
189: }
190:
191: hash(s, n) /* form hash value for string s */
192: register uchar *s;
193: int n;
194: {
195: register unsigned hashval;
196:
197: for (hashval = 0; *s != '\0'; s++)
198: hashval = (*s + 31 * hashval);
199: return hashval % n;
200: }
201:
202: rehash(tp) /* rehash items in small table into big one */
203: Array *tp;
204: {
205: int i, nh, nsz;
206: Cell *cp, *op, **np;
207:
208: nsz = GROWTAB * tp->size;
209: np = (Cell **) Calloc(nsz, sizeof(Cell *));
210: if (np == NULL)
211: error(FATAL, "out of space in rehash");
212: for (i = 0; i < tp->size; i++) {
213: for (cp = tp->tab[i]; cp; cp = op) {
214: op = cp->cnext;
215: nh = hash(cp->nval, nsz);
216: cp->cnext = np[nh];
217: np[nh] = cp;
218: }
219: }
220: free(tp->tab);
221: tp->tab = np;
222: tp->size = nsz;
223: }
224:
225: Cell *lookup(s, tp) /* look for s in tp */
226: register uchar *s;
227: Array *tp;
228: {
229: register Cell *p, *prev = NULL;
230: int h;
231:
232: h = hash(s, tp->size);
233: for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
234: if (strcmp(s, p->nval) == 0)
235: return(p); /* found it */
236: return(NULL); /* not found */
237: }
238:
239: Awkfloat setfval(vp, f)
240: register Cell *vp;
241: Awkfloat f;
242: {
243: extern Cell fldtab[];
244:
245: if ((vp->tval & (NUM | STR)) == 0)
246: funnyvar(vp, "assign to");
247: if (vp->tval & FLD) {
248: donerec = 0; /* mark $0 invalid */
249: if (vp-fldtab > *NF)
250: newfld(vp-fldtab);
251: dprintf("setting field %d to %g\n", vp-fldtab, f);
252: } else if (vp->tval & REC) {
253: donefld = 0; /* mark $1... invalid */
254: donerec = 1;
255: }
256: vp->tval &= ~STR; /* mark string invalid */
257: vp->tval |= NUM; /* mark number ok */
258: dprintf("setfval %o: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval);
259: return vp->fval = f;
260: }
261:
262: funnyvar(vp, rw)
263: Cell *vp;
264: char *rw;
265: {
266: if (vp->tval & ARR)
267: error(FATAL, "can't %s %s; it's an array name.", rw, vp->nval);
268: if (vp->tval & FCN)
269: error(FATAL, "can't %s %s; it's a function.", rw, vp->nval);
270: error(FATAL, "funny variable %o: n=%s s=\"%s\" f=%g t=%o",
271: vp, vp->nval, vp->sval, vp->fval, vp->tval);
272: }
273:
274: uchar *setsval(vp, s)
275: register Cell *vp;
276: uchar *s;
277: {
278: if ((vp->tval & (NUM | STR)) == 0)
279: funnyvar(vp, "assign to");
280: if (vp->tval & FLD) {
281: donerec = 0; /* mark $0 invalid */
282: if (vp-fldtab > *NF)
283: newfld(vp-fldtab);
284: dprintf("setting field %d to %s\n", vp-fldtab, s);
285: } else if (vp->tval & REC) {
286: donefld = 0; /* mark $1... invalid */
287: donerec = 1;
288: }
289: vp->tval &= ~NUM;
290: vp->tval |= STR;
291: if (!(vp->tval&DONTFREE))
292: xfree(vp->sval);
293: vp->tval &= ~DONTFREE;
294: dprintf("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval);
295: return(vp->sval = tostring(s));
296: }
297:
298: Awkfloat r_getfval(vp)
299: register Cell *vp;
300: {
301: /* if (vp->tval & ARR)
302: error(FATAL, "illegal reference to array %s", vp->nval);
303: return 0.0; */
304: if ((vp->tval & (NUM | STR)) == 0)
305: funnyvar(vp, "read value of");
306: if ((vp->tval & FLD) && donefld == 0)
307: fldbld();
308: else if ((vp->tval & REC) && donerec == 0)
309: recbld();
310: if (!isnum(vp)) { /* not a number */
311: vp->fval = atof(vp->sval); /* best guess */
312: if (isnumber(vp->sval) && !(vp->tval&CON))
313: vp->tval |= NUM; /* make NUM only sparingly */
314: }
315: dprintf("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval);
316: return(vp->fval);
317: }
318:
319: uchar *r_getsval(vp)
320: register Cell *vp;
321: {
322: uchar s[100];
323:
324: /* if (vp->tval & ARR)
325: error(FATAL, "illegal reference to array %s", vp->nval);
326: return ""; */
327: if ((vp->tval & (NUM | STR)) == 0)
328: funnyvar(vp, "read value of");
329: if ((vp->tval & FLD) && donefld == 0)
330: fldbld();
331: else if ((vp->tval & REC) && donerec == 0)
332: recbld();
333: if ((vp->tval & STR) == 0) {
334: if (!(vp->tval&DONTFREE))
335: xfree(vp->sval);
336: if ((long)vp->fval == vp->fval)
337: sprintf(s, "%.20g", vp->fval);
338: else
339: sprintf(s, *OFMT, vp->fval);
340: vp->sval = tostring(s);
341: vp->tval &= ~DONTFREE;
342: vp->tval |= STR;
343: }
344: dprintf("getsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval);
345: return(vp->sval);
346: }
347:
348: uchar *tostring(s)
349: register uchar *s;
350: {
351: register uchar *p;
352:
353: p = Malloc(strlen(s)+1);
354: if (p == NULL)
355: error(FATAL, "out of space in tostring on %s", s);
356: strcpy(p, s);
357: return(p);
358: }
359:
360: uchar *qstring(s, delim) /* collect string up to delim */
361: uchar *s;
362: int delim;
363: {
364: uchar *q;
365: int c, n;
366:
367: for (q = cbuf; (c = *s) != delim; s++) {
368: if (q >= cbuf + CBUFLEN - 1)
369: yyerror("string %.10s... too long", cbuf);
370: else if (c == '\n')
371: yyerror("newline in string %.10s...", cbuf);
372: else if (c != '\\')
373: *q++ = c;
374: else /* \something */
375: switch (c = *++s) {
376: case '\\': *q++ = '\\'; break;
377: case 'n': *q++ = '\n'; break;
378: case 't': *q++ = '\t'; break;
379: case 'b': *q++ = '\b'; break;
380: case 'f': *q++ = '\f'; break;
381: case 'r': *q++ = '\r'; break;
382: default:
383: if (!isdigit(c)) {
384: *q++ = c;
385: break;
386: }
387: n = c - '0';
388: if (isdigit(s[1])) {
389: n = 8 * n + *++s - '0';
390: if (isdigit(s[1]))
391: n = 8 * n + *++s - '0';
392: }
393: *q++ = n;
394: break;
395: }
396: }
397: *q = '\0';
398: return cbuf;
399: }
400:
401: #ifdef MYALLOC
402:
403: long stamp;
404:
405: uchar *Malloc(n)
406: int n;
407: {
408: uchar *p;
409:
410: p = (uchar *) malloc(n);
411: fprintf(stderr, "%6d a %d %d\n", ++stamp, p, n);
412: return p;
413: }
414:
415: uchar *Calloc(n, sz)
416: int n, sz;
417: {
418: uchar *p;
419:
420: p = (uchar *) calloc(n, sz);
421: fprintf(stderr, "%6d a %d %d (%d %d)\n", ++stamp, p, n*sz, n, sz);
422: return p;
423: }
424:
425: Free(p)
426: uchar *p;
427: {
428: fprintf(stderr, "%6d f %d\n", ++stamp, p);
429: free(p);
430: }
431:
432: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.