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)); | 
