|
|
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.