diff --git a/src/global.c b/src/global.c index 3ec9658..4d16b6c 100644 --- a/src/global.c +++ b/src/global.c @@ -513,6 +513,36 @@ void Throw_first_pass_warning(const char *message) } +// throw "macro twice" error (FIXME - also use for "symbol twice"!) +// first output a warning, then an error, this guarantees that ACME does not +// reach the maximum error limit inbetween. +void throw_redef_error(struct location *old_def, const char msg[]) +{ + struct location buffered_location; + const char *buffered_section_type; + char *buffered_section_title; + + // CAUTION, ugly kluge: fiddle with input_now and section_now + // data so error message is actually helpful + // buffer old data + buffered_location = input_now->location; + buffered_section_type = section_now->type; + buffered_section_title = section_now->title; + // set new (fake) data + input_now->location = *old_def; + section_now->type = "earlier"; + section_now->title = "definition"; + // show warning with location of earlier definition + Throw_warning(msg); // FIXME - throw as info? + // restore old data + input_now->location = buffered_location; + section_now->type = buffered_section_type; + section_now->title = buffered_section_title; + // show error with location of current definition + Throw_error(msg); +} + + // process error that might vanish if symbols change: // if current pass is an "error output" pass, actually throw error. // otherwise just set a flag to let mainloop know this pass wasn't successful. diff --git a/src/global.h b/src/global.h index 1020b39..bc1c024 100644 --- a/src/global.h +++ b/src/global.h @@ -206,6 +206,11 @@ extern void Throw_first_pass_warning(const char *msg); // about more than one of his typos at a time. #define Throw_error(msg) throw_message(DEBUGLEVEL_ERROR, msg) +// throw "macro twice" error (FIXME - also use for "symbol twice"!) +// first output a warning, then an error, this guarantees that ACME does not +// reach the maximum error limit inbetween. +extern void throw_redef_error(struct location *old_def, const char msg[]); + // process error that might vanish if symbols change: // if current pass is an "error output" pass, actually throw error. // otherwise just set a flag to let mainloop know this pass wasn't successful. diff --git a/src/macro.c b/src/macro.c index 15b1391..5806844 100644 --- a/src/macro.c +++ b/src/macro.c @@ -23,7 +23,6 @@ #define ARGTYPE_REF 'r' #define REFERENCE_CHAR '~' // prefix for call-by-reference #define HALF_INITIAL_ARG_TABLE_SIZE 4 -static const char exception_macro_twice[] = "Macro already defined."; // macro struct type definition @@ -110,39 +109,6 @@ static int search_for_macro(struct rwnode **result, scope_t scope, int create) return tree_hard_scan(result, macro_forest, scope, create); } -// This function is called when an already existing macro is re-defined. -// It first outputs a warning and then an error. -// Showing the first message as a warning guarantees that ACME does not reach -// the maximum error limit inbetween. -static void report_redefinition(struct rwnode *macro_node) -{ - struct macro *original_macro = macro_node->body; - struct location buffered_location; - const char *buffered_section_type; - char *buffered_section_title; - - // CAUTION, ugly kluge: fiddle with input_now and section_now - // data to generate helpful error messages - // FIXME - move this to a function so "symbol twice" error can also use it - // buffer old data - buffered_location = input_now->location; - buffered_section_type = section_now->type; - buffered_section_title = section_now->title; - // set new (fake) data - input_now->location = original_macro->definition; - section_now->type = "earlier"; - section_now->title = "definition"; - // show warning with location of earlier definition - Throw_warning(exception_macro_twice); // FIXME - throw as info? - // restore old data - input_now->location = buffered_location; - section_now->type = buffered_section_type; - section_now->title = buffered_section_title; - - // show error with location of current definition - Throw_error(exception_macro_twice); -} - // This function is only called during the first pass, so there's no need to // check whether to skip the definition or not. // Return with GotByte = '}' @@ -150,6 +116,7 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro" { char *formal_parameters; struct rwnode *macro_node; + struct macro *original_macro; // for "macro twice" error struct macro *new_macro; scope_t macro_scope = get_scope_and_title(); @@ -193,8 +160,10 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro" // error messages, we're checking for "macro twice" *now*. // Search for macro. Create if not found. // But if found, complain (macro twice). - if (search_for_macro(¯o_node, macro_scope, TRUE) == FALSE) - report_redefinition(macro_node); + if (search_for_macro(¯o_node, macro_scope, TRUE) == FALSE) { + original_macro = macro_node->body; + throw_redef_error(&(original_macro->definition), "Macro already defined."); + } // Create new macro struct and set it up. Finally we'll read the body. new_macro = safe_malloc(sizeof(*new_macro)); new_macro->definition = input_now->location; diff --git a/src/version.h b/src/version.h index abc656f..aee394d 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.97" // update before release FIXME #define CODENAME "Zem" // update before release -#define CHANGE_DATE "28 Feb" // update before release FIXME +#define CHANGE_DATE "29 Feb" // update before release FIXME #define CHANGE_YEAR "2024" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME