|
|
1.1 root 1: /*
2: *-IMPORTS:
3: * <sys/compat.h>
4: * USE_PROTO
5: * LOCAL
6: * <stdio.h>
7: * NULL
8: * FILE
9: * fopen ()
10: * fclose ()
11: * <stdlib.h>
12: * malloc ()
13: * <string.h>
14: * strerror ()
15: * memcmp ()
16: * <errno.h>
17: * errno
18: * "buildobj.h"
19: * BUILD_OK
20: * build_t
21: * builder_alloc ()
22: * build_begin ()
23: * build_error ()
24: * "ehand.h"
25: * ehand_t
26: * CHAIN_ERROR ()
27: * POP_HANDLER ()
28: * PUSH_HANDLER ()
29: * throw_error ()
30: * "mkinput.h"
31: * input_t
32: * make_file_input ()
33: * "read.h"
34: * READ_EOF
35: * token_t
36: * read_token ()
37: * token_copy ()
38: * token_discard ()
39: * token_end ()
40: * "lex.h"
41: * WHITESPACE
42: * lex_t
43: */
44:
45: #include <sys/compat.h>
46: #include <stdio.h>
47: #include <stdlib.h>
48: #include <string.h>
49: #include <errno.h>
50:
51: #include "buildobj.h"
52: #include "ehand.h"
53: #include "mkinput.h"
54: #include "read.h"
55: #include "lex.h"
56:
57: #include "symbol.h"
58:
59:
60: /*
61: * Symbols in the symbol table are all built here. The symbols are kept in
62: * buckets sorted by size so it's easy to detect duplicates when adding more.
63: */
64:
65: LOCAL build_t * data_heap;
66: LOCAL symbol_t * symbols [10];
67: LOCAL symbol_t * bigsyms;
68:
69:
70: /*
71: * Initialise the symbol data memory (also used as temporary space by various
72: * reader routines below). Returns 0 on success, 1 on error.
73: */
74:
75: #if USE_PROTO
76: int (symbol_init) (void)
77: #else
78: int
79: symbol_init ARGS (())
80: #endif
81: {
82: return (data_heap = builder_alloc (256, 0)) == NULL;
83: }
84:
85:
86: /*
87: * Try and find a match for a symbol.
88: */
89:
90: #if USE_PROTO
91: symbol_t * (sym_find) (CONST unsigned char * data, size_t len)
92: #else
93: symbol_t *
94: sym_find ARGS ((data, len))
95: CONST unsigned char
96: * data;
97: size_t len;
98: #endif
99: {
100: symbol_t * scan;
101:
102: if (len <= (sizeof (symbols) / sizeof (* symbols)))
103: scan = symbols [len - 1];
104: else
105: scan = bigsyms;
106:
107: /*
108: * Because we might be scanning the "bigsyms" bucket, remember that we
109: * have to check the lengths for equality.
110: */
111:
112: while (scan != NULL) {
113:
114: if (len == scan->s_size &&
115: memcmp (scan->s_data, data, len) == 0)
116: return scan;
117:
118: scan = scan->s_next;
119: }
120:
121: return NULL;
122: }
123:
124:
125: /*
126: * Common constructor code from string_to_symbol () and sym_intern ().
127: */
128:
129: #if USE_PROTO
130: LOCAL symbol_t * (make_sym) (CONST unsigned char * str, size_t len)
131: #else
132: LOCAL symbol_t *
133: make_sym ARGS ((str, len))
134: CONST unsigned char
135: * str;
136: size_t len;
137: #endif
138: {
139: symbol_t * scan;
140:
141: if ((scan = (symbol_t *) malloc (sizeof (* scan))) == NULL)
142: throw_error ("Unable to allocate symbol record");
143:
144: scan->s_size = len;
145: scan->s_data = str;
146:
147: if (len <= (sizeof (symbols) / sizeof (* symbols))) {
148:
149: scan->s_next = symbols [len - 1];
150: symbols [len - 1] = scan;
151: } else {
152:
153: scan->s_next = bigsyms;
154: bigsyms = scan;
155: }
156:
157: return scan;
158: }
159:
160:
161: /*
162: * Turn a string constant into a symbol.
163: */
164:
165: #if USE_PROTO
166: symbol_t * (string_to_symbol) (CONST unsigned char * str, size_t len)
167: #else
168: symbol_t *
169: string_to_symbol ARGS ((str, len))
170: CONST unsigned char
171: * str;
172: size_t len;
173: #endif
174: {
175: symbol_t * scan;
176:
177: return (scan = sym_find (str, len)) != NULL ?
178: scan : make_sym (str, len);
179: }
180:
181:
182: /*
183: * Turn a newly-read token into an interned symbol.
184: */
185:
186: #if USE_PROTO
187: symbol_t * (sym_intern) (token_t * tok)
188: #else
189: symbol_t *
190: sym_intern ARGS ((tok))
191: token_t * tok;
192: #endif
193: {
194: symbol_t * scan;
195:
196: if ((scan = sym_find (tok->tok_data, tok->tok_len)) != NULL) {
197: /*
198: * If the token data was copied to the heap, discard
199: * it.
200: */
201:
202: token_discard (tok);
203: return scan;
204: }
205:
206:
207: /*
208: * Add a new symbol to this symbol bucket. If the token data wasn't
209: * copied to the heap, then do that now.
210: */
211:
212: token_copy (tok, data_heap);
213: return make_sym (tok->tok_data, tok->tok_len);
214: }
215:
216:
217: /*
218: * Read and intern a symbol.
219: */
220:
221: #if USE_PROTO
222: int (read_symbol) (input_t * input, lex_t * lexp, symbol_t ** sym)
223: #else
224: int
225: read_symbol ARGS ((input, lexp, sym))
226: input_t * input;
227: lex_t * lexp;
228: symbol_t ** sym;
229: #endif
230: {
231: token_t temp;
232: int ch;
233:
234: if ((ch = build_begin (data_heap, 0, 0)) != 0)
235: throw_error ("Problem beginning symbol construction, %s",
236: build_error (ch));
237:
238: ch = read_token (input, lexp, data_heap, & temp);
239:
240: token_end (& temp);
241:
242: * sym = temp.tok_len > 0 ? sym_intern (& temp) : NULL;
243:
244: return ch == READ_EOF ? SYM_EOF : ch;
245: }
246:
247:
248: /*
249: * Suck in an entire configuration file.
250: */
251:
252: #if __COHERENT__
253: # define TEXT_MODE
254: #else
255: # define TEXT_MODE "t"
256: #endif
257:
258:
259: #if USE_PROTO
260: void (read_dev_file) (CONST char * inname, CONST char * outname,
261: dev_func_p devfuncp, VOID * extra)
262: #else
263: void
264: read_dev_file ARGS ((inname, outname, devfuncp, extra))
265: CONST char * inname;
266: CONST char * outname;
267: dev_func_p devfuncp;
268: VOID * extra;
269: #endif
270: {
271: FILE * infile;
272: FILE * outfile;
273: input_t * input;
274: ehand_t err;
275:
276: if ((infile = fopen (inname, "r" TEXT_MODE)) == NULL)
277: throw_error ("cannot open file '%s', OS error %d \"%s\"",
278: inname, errno, strerror (errno));
279:
280: outfile = NULL;
281:
282: if (outname != NULL &&
283: (outfile = fopen (outname, "w" TEXT_MODE)) == NULL) {
284: throw_error ("cannot open file '%s', OS error %d \"%s\"",
285: outname, errno, strerror (errno));
286: }
287:
288:
289: if ((input = make_filter (infile, inname, 1, '#',
290: outfile, 1)) == NULL) {
291:
292: (void) fclose (infile);
293: if (outfile != NULL)
294: (void) fclose (outfile);
295: throw_error ("could not create input stream in read_dev_file ()");
296: }
297:
298: if (PUSH_HANDLER (err) == 0) {
299:
300: while ((* devfuncp) (input, WHITESPACE, extra) == '\n')
301: ;
302: } else {
303:
304: read_error (input);
305: read_close (input);
306: CHAIN_ERROR (err);
307: }
308:
309: read_close (input);
310: POP_HANDLER (err);
311: }
312:
313: /*
314: * Suck in a single configuration file entry from a string.
315: */
316:
317: #if USE_PROTO
318: void (read_dev_string) (CONST char * string, dev_func_p devfuncp,
319: VOID * extra)
320: #else
321: void
322: read_dev_string ARGS ((string, devfuncp, extra))
323: CONST char * string;
324: dev_func_p devfuncp;
325: VOID * extra;
326: #endif
327: {
328: input_t * input;
329: ehand_t err;
330:
331: if ((input = make_string_input (string, 0)) == NULL)
332: throw_error ("could not create input stream in read_dev_string ()");
333:
334: if (PUSH_HANDLER (err) == 0)
335: (* devfuncp) (input, WHITESPACE, extra);
336: else {
337: read_error (input);
338: read_close (input);
339: CHAIN_ERROR (err);
340: }
341:
342: read_close (input);
343: POP_HANDLER (err);
344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.