|
|
1.1 root 1: /*
2: * AWK - part 2
3: * Initialisation, and
4: * other compiler support.
5: * Symbol table maintenance
6: * and lookup.
7: */
8:
9: #include "awk.h"
10: #include "y.tab.h"
11:
12: void keyenter();
13: void funcenter();
14:
15: typedef struct FUNC {
16: int (*f_funcp)();
17: CHAR *f_name;
18: CHAR f_minarg; /* Minimum number of arguments */
19: CHAR f_maxarg; /* Maximum # args (-1 = variable) */
20: } FUNC;
21:
22: FUNC functions[] = {
23: f_length, "length", 0, 1,
24: f_sqrt, "sqrt", 1, 1,
25: f_log, "log", 1, 1,
26: f_exp, "exp", 1, 1,
27: f_int, "int", 1, 1,
28: f_substr, "substr", 2, 3,
29: f_index, "index", 2, 2,
30: f_sprintf, "sprintf", 1, -1,
31: f_split, "split", 2, 3,
32: f_abs, "abs", 1, 1,
33: };
34:
35: typedef struct KEYW {
36: int k_lval;
37: CHAR *k_name;
38: } KEYW;
39:
40: KEYW keywords[] = {
41: BEGIN_, "BEGIN",
42: END_, "END",
43: PRINT_, "print",
44: PRINTF_, "printf",
45: IF_, "if",
46: ELSE_, "else",
47: WHILE_, "while",
48: FOR_, "for",
49: IN_, "in",
50: BREAK_, "break",
51: CONTINUE_, "continue",
52: NEXT_, "next",
53: EXIT_, "exit",
54: };
55:
56: /*
57: * Initialisation --
58: * Turn on buffering for output.
59: * Initialse static constant values,
60: * install keywords,
61: * and install built-in functions.
62: */
63: awkinit()
64: {
65: setbuf(stdin, inbuf);
66: setbuf(stdout, outbuf);
67: setbuf(stderr, NULL);
68: /*
69: * Initialise keywords into
70: * the symbol table.
71: */
72: {
73: register KEYW *kp;
74:
75: for (kp = keywords; kp < endof(keywords); kp++)
76: keyenter(kp->k_name, kp->k_lval);
77: }
78: /*
79: * Install functions into symbol
80: * table.
81: */
82: {
83: register FUNC *fp;
84:
85: for (fp = functions; fp < endof(functions); fp++)
86: funcenter(fp->f_name, fp->f_funcp, fp->f_minarg,
87: fp->f_maxarg);
88: }
89: xzero.t_INT = 0;
90: xone.t_INT = 1;
91: xone.t_op = xzero.t_op = ATERM;
92: xone.t_flag = xzero.t_flag = T_INT|T_NUM;
93: xfield0.n_op = AFIELD;
94: xfield0.n_O1 = &xzero;
95: /*
96: * Set up the built-in variables.
97: */
98: NRp = install("NR", (INT)0);
99: NFp = install("NF", (INT)0);
100: FILENAMEp = lookup("FILENAME");
101: sassign(FSp = install("FS", (INT)0), " \t");
102: sassign(RSp = install("RS", (INT)0), "\n");
103: sassign(OFSp = install("OFS", (INT)0), " ");
104: sassign(ORSp = install("ORS", (INT)0), "\n");
105: sassign(OFMTp = install("OFMT", (INT)0), "%ld");
106: }
107:
108: /*
109: * Lookup an identifier - `id' and
110: * if it is not found, initialise it
111: * with the NULL string.
112: * The hash value is the sum of all
113: * the characters in the name +
114: * the length of the name.
115: */
116: NODE *
117: lookup(id)
118: CHAR *id;
119: {
120: register CHAR *ip;
121: register TERM *tp;
122: register unsigned hash;
123: register unsigned nb;
124:
125: hash = 0;
126: nb = sizeof (CHAR);
127: for (ip = id; *ip != '\0'; hash++, nb++)
128: hash += *ip++;
129: for (tp = symtab[hash%NHASH]; tp != NULL; tp = tp->t_next)
130: if (hash==tp->t_hval && tp->t_flag&T_VAR
131: && streq(tp->t_name, id))
132: return (tp);
133: tp = (TERM *)xalloc(sizeof(NODE) + nb);
134: strcpy(tp->t_name, id);
135: tp->t_STRING = xalloc(sizeof(CHAR));
136: tp->t_STRING[0] = '\0';
137: tp->t_op = ATERM;
138: tp->t_flag = T_VAR|T_ALLOC;
139: tp->t_hval = hash;
140: tp->t_ahval = -1;
141: tp->t_next = symtab[hash %= NHASH];
142: symtab[hash] = tp;
143: return ((NODE *)tp);
144: }
145:
146: /*
147: * Lookup for an array.
148: * Arguments are `array' and `index'
149: * (both strings). Hashing is an
150: * extension of that in lookup().
151: * New array elements are given value the
152: * NULL string.
153: */
154: NODE *
155: alookup(array, index)
156: CHAR *array;
157: CHAR *index;
158: {
159: register CHAR *ip;
160: register TERM *tp;
161: register unsigned hash;
162: register unsigned nba, nbi;
163: register unsigned hash2;
164:
165: hash = 0;
166: nba = nbi = sizeof (CHAR);
167: for (ip = array; *ip != '\0'; hash++, nba++)
168: hash += *ip++;
169: hash2 = hash;
170: for (ip = index; *ip != '\0'; hash++, nbi++)
171: hash += *ip++;
172: for (tp = symtab[hash % NHASH]; tp != NULL; tp = tp->t_next)
173: if (hash==tp->t_hval && tp->t_flag&T_ARRAY
174: && streq(tp->t_name, array) && streq(tp->t_name+nba, index))
175: return (tp);
176: tp = (TERM *)xalloc(sizeof(NODE) + nba + nbi);
177: strcpy(tp->t_name, array);
178: strcpy(tp->t_name+nba, index);
179: tp->t_STRING = xalloc(sizeof(CHAR));
180: tp->t_STRING[0] = '\0';
181: tp->t_op = ATERM;
182: tp->t_flag = T_ARRAY|T_ALLOC;
183: tp->t_hval = hash;
184: tp->t_ahval = hash2;
185: tp->t_next = symtab[hash %= NHASH];
186: symtab[hash] = tp;
187: return ((NODE *)tp);
188: }
189:
190: /*
191: * Install a built-in integer
192: * name with value `val'.
193: */
194: NODE *
195: install(id, val)
196: CHAR *id;
197: INT val;
198: {
199: register NODE *np;
200:
201: np = lookup(id);
202: np->t_flag |= T_NUM|T_INT;
203: free(np->t_STRING);
204: np->t_INT = val;
205: return (np);
206: }
207:
208: /*
209: * Enter a keyword in the symbol table.
210: * `lval' is the lexical value of the keyword
211: * and the TERM type is `AKEYW'.
212: */
213: void
214: keyenter(word, lval)
215: CHAR *word;
216: int lval;
217: {
218: register CHAR *ip;
219: register unsigned hash;
220: register TERM *tp;
221: register int nb;
222:
223: hash = 0;
224: nb = sizeof (CHAR);
225: for (ip = word; *ip != '\0'; hash++, nb++)
226: hash += *ip++;
227: tp = (TERM *)xalloc(nb + sizeof(TERM));
228: tp->t_hval = hash;
229: tp->t_op = AKEYW;
230: tp->t_flag = T_ALLOC|T_VAR;
231: strcpy(tp->t_name, word);
232: tp->t_INT = lval;
233: tp->t_next = symtab[hash %= NHASH];
234: symtab[hash] = tp;
235: }
236:
237: /*
238: * Enter a function name into the
239: * symbol table.
240: * `min' and `max' are the minimum and
241: * maximum number of arguments, respectively.
242: */
243: void
244: funcenter(name, fun, min, max)
245: CHAR *name;
246: int (*fun)();
247: int min, max;
248: {
249: register CHAR *np;
250: register unsigned hash;
251: register TERM *tp;
252: register unsigned nb;
253:
254: hash = 0;
255: nb = sizeof (CHAR);
256: for (np = name; *np != '\0'; hash++, nb++)
257: hash += *np++;
258: tp = (TERM *)xalloc(nb + sizeof(TERM));
259: tp->t_hval = hash;
260: tp->t_op = AFUNC;
261: tp->t_flag = T_ALLOC|T_VAR;
262: strcpy(tp->t_name, name);
263: tp->t_FUNC = fun;
264: tp->t_MINARG = min;
265: tp->t_MAXARG = max;
266: tp->t_next = symtab[hash %= NHASH];
267: symtab[hash] = tp;
268: }
269:
270: /*
271: * Assign a new value to a string.
272: * It produces a static string.
273: */
274: sassign(np, s)
275: register NODE *np;
276: STRING s;
277: {
278: if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC)
279: free(np->t_STRING);
280: np->t_flag &= ~(T_ALLOC|T_NUM);
281: np->t_STRING = s;
282: }
283:
284: /*
285: * Assign an INT to a node.
286: */
287: iassign(np, i)
288: register NODE *np;
289: INT i;
290: {
291: if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC)
292: free(np->t_STRING);
293: np->t_flag &= ~T_ALLOC;
294: np->t_flag |= T_INT|T_NUM;
295: np->t_INT = i;
296: }
297:
298: /*
299: * Initialise (or reset) the mapping
300: * table for field extraction. It is
301: * set to non-zero for every character
302: * that can end a field + '\0'
303: * Note that FSMAP is defined over `wordbuf'
304: * which is only used lexically and by `sprintf'
305: * Therefore this routine must be called if this
306: * buffer is disturbed.
307: */
308: fsmapinit(fsp)
309: register CHAR *fsp;
310: {
311: register CHAR *cp;
312:
313: whitesw = !strcmp(fsp, " \t");
314: for (cp = FSMAP; cp < &FSMAP[NCSET]; )
315: *cp++ = 0;
316: while (*fsp != '\0')
317: FSMAP[*fsp++] = 1;
318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.