summaryrefslogtreecommitdiffhomepage
path: root/mixlib/mix_parser.c
diff options
context:
space:
mode:
authorJose Antonio Ortega Ruiz <jao@gnu.org>2004-06-06 22:56:20 +0000
committerJose Antonio Ortega Ruiz <jao@gnu.org>2004-06-06 22:56:20 +0000
commitb41b09e33d48ec4374284015ca25ca0135f9a934 (patch)
tree3bf216f58883ef8c5dccd4e93fd88667b7a959d3 /mixlib/mix_parser.c
parentc39f8e909b0fde21c586c09f2cb7c6538da1d492 (diff)
downloadmdk-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.c67
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));