diff --git a/src/acme.c b/src/acme.c index 46de09e..04cb0a7 100644 --- a/src/acme.c +++ b/src/acme.c @@ -399,9 +399,9 @@ static void perform_pass(bits passflags) } // now increment pass number // this must be done _after_ the pass because assignments done via - // "-DSYMBOL=VALUE" cli args must be handled as if they were done at the - // start of pass 1, so we cannot change that variable at the start of - // the pass. + // "-D SYMBOL=VALUE" cli args must be handled as if they were done at + // the start of pass 1, so we cannot change that variable at the start + // of the pass. ++pass.number; } @@ -788,7 +788,7 @@ int main(int argc, const char *argv[]) if (argc == 1) show_help_and_exit(); cliargs_init(argc, argv); - // init pass number because any assignments done via "-DSYMBOL=VALUE" + // init pass number because any assignments done via "-D SYMBOL=VALUE" // cli args must be handled as if they happened at the start of pass 1: pass.number = 1; // init platform-specific stuff. diff --git a/src/alu.c b/src/alu.c index 820cac6..aa061d4 100644 --- a/src/alu.c +++ b/src/alu.c @@ -1405,7 +1405,7 @@ static boolean string_differs(const struct object *self, const struct object *ot // int/float: // assign new value -static void number_assign(struct object *self, const struct object *new_value, boolean accept_change) +static boolean number_assign(struct object *self, const struct object *new_value, boolean accept_change) { bits own_flags = self->u.number.flags, other_flags = new_value->u.number.flags; @@ -1427,10 +1427,9 @@ static void number_assign(struct object *self, const struct object *new_value, b } else { // symbol is already defined, so compare new and old values // if values differ, complain and return - if (number_differs(self, new_value)) { - throw_error(exception_symbol_defined); - return; - } + if (number_differs(self, new_value)) + return TRUE; // -> throw "symbol already defined" error + // values are the same, so only fiddle with flags } @@ -1448,29 +1447,30 @@ static void number_assign(struct object *self, const struct object *new_value, b own_flags |= other_flags & (NUMBER_FITS_BYTE | NUMBER_EVER_UNDEFINED); self->u.number.flags = own_flags; + return FALSE; } // list: // assign new value -static void list_assign(struct object *self, const struct object *new_value, boolean accept_change) +static boolean list_assign(struct object *self, const struct object *new_value, boolean accept_change) { - if ((!accept_change) && list_differs(self, new_value)) { - throw_error(exception_symbol_defined); - return; - } + if ((!accept_change) && list_differs(self, new_value)) + return TRUE; // -> throw "symbol already defined" error + *self = *new_value; + return FALSE; } // string: // assign new value -static void string_assign(struct object *self, const struct object *new_value, boolean accept_change) +static boolean string_assign(struct object *self, const struct object *new_value, boolean accept_change) { - if ((!accept_change) && string_differs(self, new_value)) { - throw_error(exception_symbol_defined); - return; - } + if ((!accept_change) && string_differs(self, new_value)) + return TRUE; // -> throw "symbol already defined" error + *self = *new_value; + return FALSE; } diff --git a/src/alu.h b/src/alu.h index 0f861aa..9d95fa9 100644 --- a/src/alu.h +++ b/src/alu.h @@ -16,7 +16,7 @@ struct type { const char *name; boolean (*is_defined)(const struct object *self); boolean (*differs)(const struct object *self, const struct object *other); - void (*assign)(struct object *self, const struct object *new_value, boolean accept_change); + boolean (*assign)(struct object *self, const struct object *new_value, boolean accept_change); void (*monadic_op)(struct object *self, const struct op *op); void (*dyadic_op)(struct object *self, const struct op *op, struct object *other); void (*fix_result)(struct object *self); diff --git a/src/config.h b/src/config.h index 85628c8..24649f4 100644 --- a/src/config.h +++ b/src/config.h @@ -22,7 +22,7 @@ typedef signed int intval_t; // at least 32 bits typedef unsigned int uintval_t; // at least 32 bits (only used for logical shift right) #define OUTBUF_MAXSIZE 0x1000000 // 16 MiB ought to be enough for anybody -// struct to remember where macros were defined (FIXME - use for symbols as well!) +// struct to remember where macros/symbols were defined struct location { const char *plat_filename; // filename in platform style int line_number; diff --git a/src/global.c b/src/global.c index 3b23495..4c7a291 100644 --- a/src/global.c +++ b/src/global.c @@ -627,12 +627,19 @@ void throw_redef_error(const char error_msg[], struct location *old_def, const c // show error with current location throw_error(error_msg); + // symbol structs do not necessarily have valid location data: + if (old_def->plat_filename == NULL) + return; + // CAUTION, ugly kluge: fiddle with section_now data to generate // "earlier definition" section. // buffer old section buffered_section_type = section_now->type; buffered_section_title = section_now->title; // set new (fake) section + // FIXME - maybe store section in definition, just as location is stored? + // then we could use real data here instead of faking it, but it would + // take a bit more memory... section_now->type = "earlier"; section_now->title = "section"; // show info message with location of earlier definition diff --git a/src/symbol.c b/src/symbol.c index 78f7b3a..91950d4 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -123,6 +123,10 @@ struct symbol *symbol_find(scope_t scope) symbol->has_been_read = FALSE; symbol->has_been_reported = FALSE; symbol->pseudopc = NULL; + // we must set "definition" fields to dummy data, because the object + // has been created, but not necessarily set to a defined value: + symbol->definition.plat_filename = NULL; + symbol->definition.line_number = 0; } else { symbol = node->body; } @@ -142,6 +146,8 @@ struct symbol *symbol_find(scope_t scope) // CAUTION: actual incrementing of counter is then done directly without calls here! void symbol_set_object(struct symbol *symbol, struct object *new_value, bits powers) { + boolean complain; + if (symbol->object.type == NULL) { // symbol has no object assigned to it yet symbol->object = *new_value; // copy whole struct including type @@ -154,22 +160,27 @@ void symbol_set_object(struct symbol *symbol, struct object *new_value, bits pow // if too different, needs power (or complains) if (symbol->object.type != new_value->type) { if (!(powers & POWER_CHANGE_OBJTYPE)) - throw_error(exception_symbol_defined); - // CAUTION: if above line throws error, we still go ahead and change type! + complain = TRUE; + // CAUTION: if line above triggers, we still go ahead and change type! // this is to keep "!for" working, where the counter var is accessed. symbol->object = *new_value; // copy whole struct including type // clear flag so caller can adjust force bits: symbol->has_been_read = FALSE; // it's basically a new symbol now } else { // symbol and new value have compatible types, so call handler: - symbol->object.type->assign(&symbol->object, new_value, !!(powers & POWER_CHANGE_VALUE)); + complain = symbol->object.type->assign(&symbol->object, new_value, !!(powers & POWER_CHANGE_VALUE)); } + // if needed, throw "already defined" error with location of previous definition + if (complain) + throw_redef_error(exception_symbol_defined, &symbol->definition, "Previous definition."); } // if symbol is an address, give it a pseudopc context: if ((symbol->object.type == &type_number) && (symbol->object.u.number.addr_refs == 1)) { symbol->pseudopc = pseudopc_get_context(); } + // remember current location for "symbol twice" errors in future: + input_get_location(&symbol->definition); } @@ -212,6 +223,8 @@ void symbol_define(intval_t value) result.u.number.val.intval = value; symbol = symbol_find(SCOPE_GLOBAL); symbol->object = result; + symbol->definition.plat_filename = "\"-D SYMBOL=VALUE\""; + symbol->definition.line_number = 1; } diff --git a/src/symbol.h b/src/symbol.h index a5ec826..0829e4c 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -17,7 +17,7 @@ struct symbol { boolean has_been_read; // to find out if actually used boolean has_been_reported; // indicates "has been reported as undefined" struct pseudopc *pseudopc; // for "unpseudopc"-Operator '&', may be NULL -//TODO struct location definition; // for "label twice" error + struct location definition; // for "label twice" error }; diff --git a/src/version.h b/src/version.h index 7f06a18..83a44ef 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 "8 Aug" // update before release FIXME +#define CHANGE_DATE "9 Aug" // 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 diff --git a/testing/errors/Makefile b/testing/errors/Makefile index e957db9..9951226 100644 --- a/testing/errors/Makefile +++ b/testing/errors/Makefile @@ -1,4 +1,4 @@ -ACMEFLAGS = -v0 +ACMEFLAGS = -v0 --color FILES := $(wildcard *.a) TESTS = $(subst .a,.test,$(FILES)) diff --git a/testing/warnings/Makefile b/testing/warnings/Makefile index 6696a06..c245de1 100644 --- a/testing/warnings/Makefile +++ b/testing/warnings/Makefile @@ -1,4 +1,4 @@ -ACMEFLAGS = -v0 +ACMEFLAGS = -v0 --color FILES := $(wildcard *.a) FAILTESTS = $(subst .a,.fail,$(FILES)) SUCCTESTS = $(subst .a,.succ,$(FILES))