mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-02-10 11:31:49 +00:00
"symbol twice" error now outputs location of previous definition,
just as "macro twice" does. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@406 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
45ce8164e9
commit
158379ce9a
@ -399,9 +399,9 @@ static void perform_pass(bits passflags)
|
|||||||
}
|
}
|
||||||
// now increment pass number
|
// now increment pass number
|
||||||
// this must be done _after_ the pass because assignments done via
|
// 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
|
// "-D SYMBOL=VALUE" cli args must be handled as if they were done at
|
||||||
// start of pass 1, so we cannot change that variable at the start of
|
// the start of pass 1, so we cannot change that variable at the start
|
||||||
// the pass.
|
// of the pass.
|
||||||
++pass.number;
|
++pass.number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,7 +788,7 @@ int main(int argc, const char *argv[])
|
|||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
show_help_and_exit();
|
show_help_and_exit();
|
||||||
cliargs_init(argc, argv);
|
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:
|
// cli args must be handled as if they happened at the start of pass 1:
|
||||||
pass.number = 1;
|
pass.number = 1;
|
||||||
// init platform-specific stuff.
|
// init platform-specific stuff.
|
||||||
|
30
src/alu.c
30
src/alu.c
@ -1405,7 +1405,7 @@ static boolean string_differs(const struct object *self, const struct object *ot
|
|||||||
|
|
||||||
// int/float:
|
// int/float:
|
||||||
// assign new value
|
// 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,
|
bits own_flags = self->u.number.flags,
|
||||||
other_flags = new_value->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 {
|
} else {
|
||||||
// symbol is already defined, so compare new and old values
|
// symbol is already defined, so compare new and old values
|
||||||
// if values differ, complain and return
|
// if values differ, complain and return
|
||||||
if (number_differs(self, new_value)) {
|
if (number_differs(self, new_value))
|
||||||
throw_error(exception_symbol_defined);
|
return TRUE; // -> throw "symbol already defined" error
|
||||||
return;
|
|
||||||
}
|
|
||||||
// values are the same, so only fiddle with flags
|
// 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);
|
own_flags |= other_flags & (NUMBER_FITS_BYTE | NUMBER_EVER_UNDEFINED);
|
||||||
|
|
||||||
self->u.number.flags = own_flags;
|
self->u.number.flags = own_flags;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// list:
|
// list:
|
||||||
// assign new value
|
// 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)) {
|
if ((!accept_change) && list_differs(self, new_value))
|
||||||
throw_error(exception_symbol_defined);
|
return TRUE; // -> throw "symbol already defined" error
|
||||||
return;
|
|
||||||
}
|
|
||||||
*self = *new_value;
|
*self = *new_value;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// string:
|
// string:
|
||||||
// assign new value
|
// 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)) {
|
if ((!accept_change) && string_differs(self, new_value))
|
||||||
throw_error(exception_symbol_defined);
|
return TRUE; // -> throw "symbol already defined" error
|
||||||
return;
|
|
||||||
}
|
|
||||||
*self = *new_value;
|
*self = *new_value;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ struct type {
|
|||||||
const char *name;
|
const char *name;
|
||||||
boolean (*is_defined)(const struct object *self);
|
boolean (*is_defined)(const struct object *self);
|
||||||
boolean (*differs)(const struct object *self, const struct object *other);
|
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 (*monadic_op)(struct object *self, const struct op *op);
|
||||||
void (*dyadic_op)(struct object *self, const struct op *op, struct object *other);
|
void (*dyadic_op)(struct object *self, const struct op *op, struct object *other);
|
||||||
void (*fix_result)(struct object *self);
|
void (*fix_result)(struct object *self);
|
||||||
|
@ -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)
|
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
|
#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 {
|
struct location {
|
||||||
const char *plat_filename; // filename in platform style
|
const char *plat_filename; // filename in platform style
|
||||||
int line_number;
|
int line_number;
|
||||||
|
@ -627,12 +627,19 @@ void throw_redef_error(const char error_msg[], struct location *old_def, const c
|
|||||||
// show error with current location
|
// show error with current location
|
||||||
throw_error(error_msg);
|
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
|
// CAUTION, ugly kluge: fiddle with section_now data to generate
|
||||||
// "earlier definition" section.
|
// "earlier definition" section.
|
||||||
// buffer old section
|
// buffer old section
|
||||||
buffered_section_type = section_now->type;
|
buffered_section_type = section_now->type;
|
||||||
buffered_section_title = section_now->title;
|
buffered_section_title = section_now->title;
|
||||||
// set new (fake) section
|
// 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->type = "earlier";
|
||||||
section_now->title = "section";
|
section_now->title = "section";
|
||||||
// show info message with location of earlier definition
|
// show info message with location of earlier definition
|
||||||
|
19
src/symbol.c
19
src/symbol.c
@ -123,6 +123,10 @@ struct symbol *symbol_find(scope_t scope)
|
|||||||
symbol->has_been_read = FALSE;
|
symbol->has_been_read = FALSE;
|
||||||
symbol->has_been_reported = FALSE;
|
symbol->has_been_reported = FALSE;
|
||||||
symbol->pseudopc = NULL;
|
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 {
|
} else {
|
||||||
symbol = node->body;
|
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!
|
// 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)
|
void symbol_set_object(struct symbol *symbol, struct object *new_value, bits powers)
|
||||||
{
|
{
|
||||||
|
boolean complain;
|
||||||
|
|
||||||
if (symbol->object.type == NULL) {
|
if (symbol->object.type == NULL) {
|
||||||
// symbol has no object assigned to it yet
|
// symbol has no object assigned to it yet
|
||||||
symbol->object = *new_value; // copy whole struct including type
|
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 too different, needs power (or complains)
|
||||||
if (symbol->object.type != new_value->type) {
|
if (symbol->object.type != new_value->type) {
|
||||||
if (!(powers & POWER_CHANGE_OBJTYPE))
|
if (!(powers & POWER_CHANGE_OBJTYPE))
|
||||||
throw_error(exception_symbol_defined);
|
complain = TRUE;
|
||||||
// CAUTION: if above line throws error, we still go ahead and change type!
|
// CAUTION: if line above triggers, we still go ahead and change type!
|
||||||
// this is to keep "!for" working, where the counter var is accessed.
|
// this is to keep "!for" working, where the counter var is accessed.
|
||||||
symbol->object = *new_value; // copy whole struct including type
|
symbol->object = *new_value; // copy whole struct including type
|
||||||
// clear flag so caller can adjust force bits:
|
// clear flag so caller can adjust force bits:
|
||||||
symbol->has_been_read = FALSE; // it's basically a new symbol now
|
symbol->has_been_read = FALSE; // it's basically a new symbol now
|
||||||
} else {
|
} else {
|
||||||
// symbol and new value have compatible types, so call handler:
|
// 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 is an address, give it a pseudopc context:
|
||||||
if ((symbol->object.type == &type_number)
|
if ((symbol->object.type == &type_number)
|
||||||
&& (symbol->object.u.number.addr_refs == 1)) {
|
&& (symbol->object.u.number.addr_refs == 1)) {
|
||||||
symbol->pseudopc = pseudopc_get_context();
|
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;
|
result.u.number.val.intval = value;
|
||||||
symbol = symbol_find(SCOPE_GLOBAL);
|
symbol = symbol_find(SCOPE_GLOBAL);
|
||||||
symbol->object = result;
|
symbol->object = result;
|
||||||
|
symbol->definition.plat_filename = "\"-D SYMBOL=VALUE\"";
|
||||||
|
symbol->definition.line_number = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ struct symbol {
|
|||||||
boolean has_been_read; // to find out if actually used
|
boolean has_been_read; // to find out if actually used
|
||||||
boolean has_been_reported; // indicates "has been reported as undefined"
|
boolean has_been_reported; // indicates "has been reported as undefined"
|
||||||
struct pseudopc *pseudopc; // for "unpseudopc"-Operator '&', may be NULL
|
struct pseudopc *pseudopc; // for "unpseudopc"-Operator '&', may be NULL
|
||||||
//TODO struct location definition; // for "label twice" error
|
struct location definition; // for "label twice" error
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#define RELEASE "0.97" // update before release FIXME
|
#define RELEASE "0.97" // update before release FIXME
|
||||||
#define CODENAME "Zem" // update before release
|
#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 CHANGE_YEAR "2024" // update before release
|
||||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
ACMEFLAGS = -v0
|
ACMEFLAGS = -v0 --color
|
||||||
FILES := $(wildcard *.a)
|
FILES := $(wildcard *.a)
|
||||||
TESTS = $(subst .a,.test,$(FILES))
|
TESTS = $(subst .a,.test,$(FILES))
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
ACMEFLAGS = -v0
|
ACMEFLAGS = -v0 --color
|
||||||
FILES := $(wildcard *.a)
|
FILES := $(wildcard *.a)
|
||||||
FAILTESTS = $(subst .a,.fail,$(FILES))
|
FAILTESTS = $(subst .a,.fail,$(FILES))
|
||||||
SUCCTESTS = $(subst .a,.succ,$(FILES))
|
SUCCTESTS = $(subst .a,.succ,$(FILES))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user