typedef size_t (*decode_func)(input_t *input, utf32 *buffer, size_t buffer_size);
+typedef enum {
+ INPUT_FILE,
+ INPUT_STRING
+} input_kind_t;
+
struct input_t {
- FILE *file;
+ input_kind_t kind;
+ union {
+ FILE *file;
+ const char *string;
+ } in;
decode_func decode;
/* state for utf-8 decoder */
input_error = new_func;
}
-static size_t read_block(FILE *file, unsigned char *const read_buf,
+static size_t read_block(input_t *input, unsigned char *const read_buf,
size_t const n)
{
- size_t const s = fread(read_buf, 1, n, file);
- if (s == 0) {
- /* on OS/X ferror appears to return true on eof as well when running
- * the application in gdb... */
- if (!feof(file) && ferror(file))
- input_error(0, 0, "read from input failed");
- return 0;
+ if (input->kind == INPUT_FILE) {
+ FILE *file = input->in.file;
+ size_t const s = fread(read_buf, 1, n, file);
+ if (s == 0) {
+ /* on OS/X ferror appears to return true on eof as well when running
+ * the application in gdb... */
+ if (!feof(file) && ferror(file))
+ input_error(0, 0, "read from input failed");
+ return 0;
+ }
+ return s;
+ } else {
+ assert(input->kind == INPUT_STRING);
+ size_t len = strlen(input->in.string);
+ if (len > n)
+ len = n;
+ memcpy(read_buf, input->in.string, len);
+ input->in.string += len;
+ return len;
}
- return s;
}
static size_t decode_iso_8859_1(input_t *input, utf32 *buffer,
size_t buffer_size)
{
unsigned char read_buf[buffer_size];
- size_t const s = read_block(input->file, read_buf, sizeof(read_buf));
+ size_t const s = read_block(input, read_buf, sizeof(read_buf));
unsigned char const *src = read_buf;
unsigned char const *end = read_buf + s;
size_t buffer_size)
{
unsigned char read_buf[buffer_size];
- size_t const s = read_block(input->file, read_buf, sizeof(read_buf));
+ size_t const s = read_block(input, read_buf, sizeof(read_buf));
unsigned char const *src = read_buf;
unsigned char const *end = read_buf + s;
unsigned char read_buf[buffer_size];
while (true) {
- size_t const s = read_block(input->file, read_buf, sizeof(read_buf));
+ size_t const s = read_block(input, read_buf, sizeof(read_buf));
if (s == 0) {
if (input->utf8_part_decoded_rest_len > 0)
input_error(0, 0, "incomplete input char at end of input");
size_t buffer_size)
{
unsigned char read_buf[buffer_size];
- size_t const s = read_block(input->file, read_buf, sizeof(read_buf));
+ size_t const s = read_block(input, read_buf, sizeof(read_buf));
unsigned char const *src = read_buf;
unsigned char const *end = read_buf + s;
return (unsigned char)*s1 - (unsigned char)*s2;
}
-input_t *input_from_stream(FILE *file, const char *encoding)
+static void choose_decoder(input_t *result, const char *encoding)
{
- input_t *result = XMALLOCZ(input_t);
- result->file = file;
-
if (encoding == NULL) {
result->decode = decode_utf8;
} else {
result->decode = decode_utf8;
}
}
+}
+
+input_t *input_from_stream(FILE *file, const char *encoding)
+{
+ input_t *result = XMALLOCZ(input_t);
+ result->kind = INPUT_FILE;
+ result->in.file = file;
+
+ choose_decoder(result, encoding);
+
+ return result;
+}
+
+input_t *input_from_string(const char *string, const char *encoding)
+{
+ input_t *result = XMALLOCZ(input_t);
+ result->kind = INPUT_STRING;
+ result->in.string = string;
+
+ choose_decoder(result, encoding);
return result;
}
token_t lexer_token;
static symbol_t *symbol_L;
static strset_t stringset;
-static char *encoding;
bool allow_dollar_in_symbol = true;
/**
errorf(&lexer_pos, "%s", message);
}
-void select_input_encoding(char const* new_encoding)
+void lexer_switch_input(input_t *new_input, const char *input_name)
{
- if (encoding != NULL)
- xfree(encoding);
- encoding = xstrdup(new_encoding);
-}
-
-void lexer_open_stream(FILE *stream, const char *input_name)
-{
- if (input != NULL) {
- input_free(input);
- input = NULL;
- }
-
lexer_pos.lineno = 0;
lexer_pos.colno = 0;
lexer_pos.input_name = input_name;
set_input_error_callback(input_error);
- input = input_from_stream(stream, encoding);
+ input = new_input;
bufpos = NULL;
bufend = NULL;
void exit_lexer(void)
{
- if (input != NULL) {
- input_free(input);
- input = NULL;
- }
strset_destroy(&stringset);
}
static char dep_target[1024];
static const char *outname;
static bool define_intmax_types;
+static const char *input_encoding;
typedef enum lang_standard_t {
STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
{
start_parsing();
- lexer_open_stream(in, input_name);
+ input_t *input = input_from_stream(in, input_encoding);
+ lexer_switch_input(input, input_name);
parse();
-
translation_unit_t *unit = finish_parsing();
+ input_free(input);
+
return unit;
}
static void lextest(FILE *in, const char *fname)
{
- lexer_open_stream(in, fname);
+ input_t *input = input_from_stream(in, input_encoding);
+ lexer_switch_input(input, fname);
do {
lexer_next_preprocessing_token();
print_token(stdout, &lexer_token);
putchar('\n');
} while (lexer_token.kind != T_EOF);
+ input_free(input);
}
static void add_flag(struct obstack *obst, const char *format, ...)
if (strstart(orig_opt, "input-charset=")) {
char const* const encoding = strchr(orig_opt, '=') + 1;
- select_input_encoding(encoding);
+ input_encoding = encoding;
} else if (strstart(orig_opt, "align-loops=") ||
strstart(orig_opt, "align-jumps=") ||
strstart(orig_opt, "align-functions=")) {