diff options
author | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2004-06-06 22:56:20 +0000 |
---|---|---|
committer | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2004-06-06 22:56:20 +0000 |
commit | b41b09e33d48ec4374284015ca25ca0135f9a934 (patch) | |
tree | 3bf216f58883ef8c5dccd4e93fd88667b7a959d3 /mixlib/mix_parser.c | |
parent | c39f8e909b0fde21c586c09f2cb7c6538da1d492 (diff) | |
download | mdk-b41b09e33d48ec4374284015ca25ca0135f9a934.tar.gz mdk-b41b09e33d48ec4374284015ca25ca0135f9a934.tar.bz2 |
properly treat undefined forward references, inserting new addresses at the program's end.
Diffstat (limited to 'mixlib/mix_parser.c')
-rw-r--r-- | mixlib/mix_parser.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/mixlib/mix_parser.c b/mixlib/mix_parser.c index e2c7e3f..012345b 100644 --- a/mixlib/mix_parser.c +++ b/mixlib/mix_parser.c @@ -2,7 +2,7 @@ * Implementation of the functions declared in mix_parser.h and * xmix_parser.h * ------------------------------------------------------------------ - * Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -177,20 +177,9 @@ mix_parser_delete (mix_parser_t *parser) } /* Compile a mix source file */ -static gboolean -undef_warning_ (gpointer symbol, gpointer value, gpointer data) -{ - mix_parser_log_error ((mix_parser_t *)data, MIX_PERR_UNDEF_SYM, 1, - (const gchar *)symbol, TRUE); - /* move the symbol to the symbol table */ - mix_symbol_table_insert_static (((mix_parser_t *)data)->symbol_table, - symbol, MIX_WORD_ZERO); - return TRUE; -} - static void update_future_refs_value_ (mix_parser_t *parser, const gchar *name, - mix_short_t value) + mix_short_t value, gboolean remove) { GSList *list = NULL; gpointer key; @@ -204,7 +193,7 @@ update_future_refs_value_ (mix_parser_t *parser, const gchar *name, while ( tmp != NULL ) { node = - (ins_node_ *)g_tree_lookup (parser->ins_table,tmp->data); + (ins_node_ *)g_tree_lookup (parser->ins_table, tmp->data); g_assert (node); if (mix_get_ins_address (node->ins) == 1) { value = mix_short_negative (value); @@ -216,14 +205,16 @@ update_future_refs_value_ (mix_parser_t *parser, const gchar *name, g_tree_insert (parser->ins_table, tmp->data, (gpointer)node); tmp = g_slist_next (tmp); } - g_hash_table_remove (parser->future_refs, name); - g_free (key); + if (remove) { + g_hash_table_remove (parser->future_refs, name); + g_free (key); + } g_slist_free (list); } } -#define update_future_refs_(parser,name) \ - update_future_refs_value_(parser, name, (parser)->loc_count); +#define update_future_refs_(parser,name,rem) \ + update_future_refs_value_(parser, name, (parser)->loc_count, rem) static void update_ls_ (gpointer symbol, gpointer value, gpointer parser) @@ -234,10 +225,30 @@ update_ls_ (gpointer symbol, gpointer value, gpointer parser) mix_word_to_ins_uncheck (w, ins); mix_parser_add_ins (par, &ins, 0); - update_future_refs_ (par, (const gchar *)symbol); + update_future_refs_ (par, (const gchar *)symbol, TRUE); par->loc_count++; } +static gboolean +undef_warning_ (gpointer symbol, gpointer value, gpointer data) +{ + mix_parser_t *parser = (mix_parser_t *)data; + const gchar *name = (const gchar *)symbol; + mix_ins_t ins; + + mix_word_to_ins_uncheck (MIX_WORD_ZERO, ins); + mix_parser_add_ins (parser, &ins, 0); + mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, 0, name, TRUE); + + /* move the symbol to the symbol table */ + update_future_refs_ (parser, name, FALSE); + mix_symbol_table_insert (parser->symbol_table, name, + mix_short_to_word_fast (parser->loc_count)); + + parser->loc_count++; + return TRUE; +} + mix_parser_err_t mix_parser_compile (mix_parser_t *parser) { @@ -248,12 +259,18 @@ mix_parser_compile (mix_parser_t *parser) g_return_val_if_fail (parser->ins_table != NULL, MIX_PERR_INTERNAL); parser->status = mix_flex_scan (parser); + if ( parser->status == MIX_PERR_OK ) { - mix_symbol_table_foreach (parser->ls_table, update_ls_, - (gpointer)parser); - g_hash_table_foreach_remove (parser->future_refs, - undef_warning_, (gpointer)parser); + mix_symbol_table_foreach (parser->ls_table, update_ls_, (gpointer)parser); + if ( g_hash_table_size (parser->future_refs) > 0) + { + parser->loc_count = parser->end + parser->cur_ls; + g_hash_table_foreach_remove (parser->future_refs, + undef_warning_, (gpointer)parser); + + parser->end = parser->loc_count; + } } return parser->status; @@ -417,7 +434,7 @@ mix_parser_define_symbol_value (mix_parser_t *parser, const gchar *name, { case MIX_SYM_OK: if ( parser->status == MIX_PERR_NOCOMP ) - update_future_refs_value_ (parser, name, value); + update_future_refs_value_ (parser, name, value, TRUE); return MIX_PERR_OK; case MIX_SYM_LONG: return MIX_PERR_LONG_SYMBOL; case MIX_SYM_DUP: return MIX_PERR_DUP_SYMBOL; @@ -463,7 +480,7 @@ mix_parser_manage_local_symbol (mix_parser_t *parser, const gchar *name, ref[0] = name[0]; ref[1] = 'F'; if ( parser->status == MIX_PERR_NOCOMP ) - update_future_refs_value_ (parser, ref, value); + update_future_refs_value_ (parser, ref, value, TRUE); ref[1] = 'B'; mix_symbol_table_insert (parser->symbol_table, ref, mix_short_to_word_fast (value)); |