summaryrefslogtreecommitdiffhomepage
path: root/mixlib
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
commit39f5ef6c753eba6c6e7eb8da6063c4f26514487e (patch)
tree42b4bbd2fc15a3c14f556d8b2711e657703b2cfb /mixlib
parente4ea0f415121795b552134254dccf76999f70d40 (diff)
downloadmdk-39f5ef6c753eba6c6e7eb8da6063c4f26514487e.tar.gz
mdk-39f5ef6c753eba6c6e7eb8da6063c4f26514487e.tar.bz2
properly treat undefined forward references, inserting new addresses at the program's end.
Diffstat (limited to 'mixlib')
-rw-r--r--mixlib/mix_parser.c67
-rw-r--r--mixlib/mix_parser.h26
2 files changed, 55 insertions, 38 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));
diff --git a/mixlib/mix_parser.h b/mixlib/mix_parser.h
index a18442c..8bc0dd6 100644
--- a/mixlib/mix_parser.h
+++ b/mixlib/mix_parser.h
@@ -2,7 +2,7 @@
* Declarations for mix_parser_t, which compiles a source file into
* a mix code file.
* ------------------------------------------------------------------
- * Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 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
@@ -32,17 +32,17 @@ typedef struct mix_parser_t mix_parser_t;
/* Create/destroy a mix_parser */
extern mix_parser_t *
-mix_parser_new(const gchar *in_file);
+mix_parser_new (const gchar *in_file);
extern void
-mix_parser_delete(mix_parser_t *parser);
+mix_parser_delete (mix_parser_t *parser);
/* Access source file name */
extern const gchar *
-mix_parser_src_file_base_name(const mix_parser_t *parser);
+mix_parser_src_file_base_name (const mix_parser_t *parser);
extern const gchar *
-mix_parser_src_file_extension(const mix_parser_t *parser);
+mix_parser_src_file_extension (const mix_parser_t *parser);
/* Compile a mix source file */
/* compilation errors */
@@ -75,16 +75,16 @@ typedef enum {
} mix_parser_err_t;
extern const gchar *
-mix_parser_err_string(mix_parser_err_t error);
+mix_parser_err_string (mix_parser_err_t error);
extern mix_parser_err_t
-mix_parser_compile(mix_parser_t *parser);
+mix_parser_compile (mix_parser_t *parser);
extern guint
-mix_parser_warning_count(const mix_parser_t *parser);
+mix_parser_warning_count (const mix_parser_t *parser);
extern guint
-mix_parser_err_count(const mix_parser_t *parser);
+mix_parser_err_count (const mix_parser_t *parser);
/* Write the compilation result to a code file with the given name.
code_file is completed, if required, with the requisite extension;
@@ -92,19 +92,19 @@ mix_parser_err_count(const mix_parser_t *parser);
If debug == TRUE, debug information is written.
*/
extern mix_parser_err_t
-mix_parser_write_code(mix_parser_t *parser, const gchar *code_file,
- gboolean debug);
+mix_parser_write_code (mix_parser_t *parser, const gchar *code_file,
+ gboolean debug);
/* Write a "canonical" listing of a compiled source, i.e. a source
file with all symbols substituted by their actual values after
compilation.
*/
extern mix_parser_err_t
-mix_parser_write_listing(mix_parser_t *parser, const gchar *list_file);
+mix_parser_write_listing (mix_parser_t *parser, const gchar *list_file);
/* load a virtual machine's memory with the contents of a compiled file */
extern mix_parser_err_t
-mix_parser_load_vm(const mix_parser_t *parser, mix_vm_t *vm);
+mix_parser_load_vm (const mix_parser_t *parser, mix_vm_t *vm);
#endif /* MIX_PARSER_H */