|
|
coherent
/*
*-IMPORTS:
* <sys/compat.h>
* USE_PROTO
* LOCAL
* <stdio.h>
* NULL
* FILE
* fopen ()
* fclose ()
* <stdlib.h>
* malloc ()
* <string.h>
* strerror ()
* memcmp ()
* <errno.h>
* errno
* "buildobj.h"
* BUILD_OK
* build_t
* builder_alloc ()
* build_begin ()
* build_error ()
* "ehand.h"
* ehand_t
* CHAIN_ERROR ()
* POP_HANDLER ()
* PUSH_HANDLER ()
* throw_error ()
* "mkinput.h"
* input_t
* make_file_input ()
* "read.h"
* READ_EOF
* token_t
* read_token ()
* token_copy ()
* token_discard ()
* token_end ()
* "lex.h"
* WHITESPACE
* lex_t
*/
#include <sys/compat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "buildobj.h"
#include "ehand.h"
#include "mkinput.h"
#include "read.h"
#include "lex.h"
#include "symbol.h"
/*
* Symbols in the symbol table are all built here. The symbols are kept in
* buckets sorted by size so it's easy to detect duplicates when adding more.
*/
LOCAL build_t * data_heap;
LOCAL symbol_t * symbols [10];
LOCAL symbol_t * bigsyms;
/*
* Initialise the symbol data memory (also used as temporary space by various
* reader routines below). Returns 0 on success, 1 on error.
*/
#if USE_PROTO
int (symbol_init) (void)
#else
int
symbol_init ARGS (())
#endif
{
return (data_heap = builder_alloc (256, 0)) == NULL;
}
/*
* Try and find a match for a symbol.
*/
#if USE_PROTO
symbol_t * (sym_find) (CONST unsigned char * data, size_t len)
#else
symbol_t *
sym_find ARGS ((data, len))
CONST unsigned char
* data;
size_t len;
#endif
{
symbol_t * scan;
if (len <= (sizeof (symbols) / sizeof (* symbols)))
scan = symbols [len - 1];
else
scan = bigsyms;
/*
* Because we might be scanning the "bigsyms" bucket, remember that we
* have to check the lengths for equality.
*/
while (scan != NULL) {
if (len == scan->s_size &&
memcmp (scan->s_data, data, len) == 0)
return scan;
scan = scan->s_next;
}
return NULL;
}
/*
* Common constructor code from string_to_symbol () and sym_intern ().
*/
#if USE_PROTO
LOCAL symbol_t * (make_sym) (CONST unsigned char * str, size_t len)
#else
LOCAL symbol_t *
make_sym ARGS ((str, len))
CONST unsigned char
* str;
size_t len;
#endif
{
symbol_t * scan;
if ((scan = (symbol_t *) malloc (sizeof (* scan))) == NULL)
throw_error ("Unable to allocate symbol record");
scan->s_size = len;
scan->s_data = str;
if (len <= (sizeof (symbols) / sizeof (* symbols))) {
scan->s_next = symbols [len - 1];
symbols [len - 1] = scan;
} else {
scan->s_next = bigsyms;
bigsyms = scan;
}
return scan;
}
/*
* Turn a string constant into a symbol.
*/
#if USE_PROTO
symbol_t * (string_to_symbol) (CONST unsigned char * str, size_t len)
#else
symbol_t *
string_to_symbol ARGS ((str, len))
CONST unsigned char
* str;
size_t len;
#endif
{
symbol_t * scan;
return (scan = sym_find (str, len)) != NULL ?
scan : make_sym (str, len);
}
/*
* Turn a newly-read token into an interned symbol.
*/
#if USE_PROTO
symbol_t * (sym_intern) (token_t * tok)
#else
symbol_t *
sym_intern ARGS ((tok))
token_t * tok;
#endif
{
symbol_t * scan;
if ((scan = sym_find (tok->tok_data, tok->tok_len)) != NULL) {
/*
* If the token data was copied to the heap, discard
* it.
*/
token_discard (tok);
return scan;
}
/*
* Add a new symbol to this symbol bucket. If the token data wasn't
* copied to the heap, then do that now.
*/
token_copy (tok, data_heap);
return make_sym (tok->tok_data, tok->tok_len);
}
/*
* Read and intern a symbol.
*/
#if USE_PROTO
int (read_symbol) (input_t * input, lex_t * lexp, symbol_t ** sym)
#else
int
read_symbol ARGS ((input, lexp, sym))
input_t * input;
lex_t * lexp;
symbol_t ** sym;
#endif
{
token_t temp;
int ch;
if ((ch = build_begin (data_heap, 0, 0)) != 0)
throw_error ("Problem beginning symbol construction, %s",
build_error (ch));
ch = read_token (input, lexp, data_heap, & temp);
token_end (& temp);
* sym = temp.tok_len > 0 ? sym_intern (& temp) : NULL;
return ch == READ_EOF ? SYM_EOF : ch;
}
/*
* Suck in an entire configuration file.
*/
#if __COHERENT__
# define TEXT_MODE
#else
# define TEXT_MODE "t"
#endif
#if USE_PROTO
void (read_dev_file) (CONST char * inname, CONST char * outname,
dev_func_p devfuncp, VOID * extra)
#else
void
read_dev_file ARGS ((inname, outname, devfuncp, extra))
CONST char * inname;
CONST char * outname;
dev_func_p devfuncp;
VOID * extra;
#endif
{
FILE * infile;
FILE * outfile;
input_t * input;
ehand_t err;
if ((infile = fopen (inname, "r" TEXT_MODE)) == NULL)
throw_error ("cannot open file '%s', OS error %d \"%s\"",
inname, errno, strerror (errno));
outfile = NULL;
if (outname != NULL &&
(outfile = fopen (outname, "w" TEXT_MODE)) == NULL) {
throw_error ("cannot open file '%s', OS error %d \"%s\"",
outname, errno, strerror (errno));
}
if ((input = make_filter (infile, inname, 1, '#',
outfile, 1)) == NULL) {
(void) fclose (infile);
if (outfile != NULL)
(void) fclose (outfile);
throw_error ("could not create input stream in read_dev_file ()");
}
if (PUSH_HANDLER (err) == 0) {
while ((* devfuncp) (input, WHITESPACE, extra) == '\n')
;
} else {
read_error (input);
read_close (input);
CHAIN_ERROR (err);
}
read_close (input);
POP_HANDLER (err);
}
/*
* Suck in a single configuration file entry from a string.
*/
#if USE_PROTO
void (read_dev_string) (CONST char * string, dev_func_p devfuncp,
VOID * extra)
#else
void
read_dev_string ARGS ((string, devfuncp, extra))
CONST char * string;
dev_func_p devfuncp;
VOID * extra;
#endif
{
input_t * input;
ehand_t err;
if ((input = make_string_input (string, 0)) == NULL)
throw_error ("could not create input stream in read_dev_string ()");
if (PUSH_HANDLER (err) == 0)
(* devfuncp) (input, WHITESPACE, extra);
else {
read_error (input);
read_close (input);
CHAIN_ERROR (err);
}
read_close (input);
POP_HANDLER (err);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.