more cleanup and preparations for new features

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@349 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2024-02-26 23:54:10 +00:00
parent 3deb9700dc
commit 5910081651
10 changed files with 89 additions and 48 deletions

View File

@ -303,9 +303,8 @@ Loop var must be followed by either "in" keyword or comma.
Macro already defined. Macro already defined.
Macros can only be defined once. If you define a macro twice, ACME Macros can only be defined once. If you define a macro twice, ACME
will help you find the definitions by giving a warning for the will help you find the definitions by giving a warning for the new
first definition and a serious error (stopping assembly) for the definition and then an error for the earlier definition.
second definition.
Macro not defined (or wrong signature). Macro not defined (or wrong signature).
You tried to call a macro that either wasn't defined yet (always You tried to call a macro that either wasn't defined yet (always
@ -462,12 +461,6 @@ Loop count is negative.
(getting this error is only possible when using the now deprecated (getting this error is only possible when using the now deprecated
syntax). syntax).
Macro already defined.
Macros can only be defined once. If you define a macro twice, ACME
will help you find both definitions by giving a warning for the
first definition and a serious error (stopping assembly) for the
second definition.
Missing '{'. Missing '{'.
ACME didn't find the expected '{' character. Remember that '{' ACME didn't find the expected '{' character. Remember that '{'
characters must be given on the same line as the keyword they characters must be given on the same line as the keyword they
@ -478,7 +471,7 @@ Out of memory.
error. Free some memory and try again. It's highly unlikely anyone error. Free some memory and try again. It's highly unlikely anyone
will ever see this error, though. ;) will ever see this error, though. ;)
Produced too much code. Reached memory limit.
The program counter reached address $10000, leaving the output The program counter reached address $10000, leaving the output
buffer. At the moment, ACME can only produce a maximum of 64 KB. buffer. At the moment, ACME can only produce a maximum of 64 KB.

View File

@ -310,6 +310,8 @@ static void perform_pass(void)
int ii; int ii;
++pass.number; ++pass.number;
if (config.process_verbosity > 1)
printf("Pass %d:\n", pass.number);
cputype_passinit(); // set default cpu type cputype_passinit(); // set default cpu type
output_passinit(); // set initial pc or start with undefined pc output_passinit(); // set initial pc or start with undefined pc
encoding_passinit(); // set default encoding encoding_passinit(); // set default encoding
@ -347,10 +349,7 @@ static boolean do_actual_work(void)
report = &global_report; // let global pointer point to something report = &global_report; // let global pointer point to something
report_init(report); // we must init struct before doing passes report_init(report); // we must init struct before doing passes
if (config.process_verbosity > 1)
puts("First pass.");
pass.complain_about_undefined = FALSE; // disable until error pass needed pass.complain_about_undefined = FALSE; // disable until error pass needed
pass.number = -1; // pre-init, will be incremented by perform_pass()
perform_pass(); // first pass perform_pass(); // first pass
// pretend there has been a previous pass, with one more undefined result // pretend there has been a previous pass, with one more undefined result
undefs_before = pass.undefined_count + 1; undefs_before = pass.undefined_count + 1;
@ -358,8 +357,6 @@ static boolean do_actual_work(void)
// stop on zero (FIXME - zero-check pass.needvalue_count instead!) // stop on zero (FIXME - zero-check pass.needvalue_count instead!)
while (pass.undefined_count && (pass.undefined_count < undefs_before)) { while (pass.undefined_count && (pass.undefined_count < undefs_before)) {
undefs_before = pass.undefined_count; undefs_before = pass.undefined_count;
if (config.process_verbosity > 1)
puts("Further pass.");
perform_pass(); perform_pass();
if (--sanity.passes_left < 0) { if (--sanity.passes_left < 0) {
// FIXME - exit with error // FIXME - exit with error
@ -384,7 +381,7 @@ static boolean do_actual_work(void)
// There are still errors (unsolvable by doing further passes), // There are still errors (unsolvable by doing further passes),
// so perform additional pass to find and show them. // so perform additional pass to find and show them.
if (config.process_verbosity > 1) if (config.process_verbosity > 1)
puts("Extra pass needed to find error."); puts("Extra pass to display errors.");
pass.complain_about_undefined = TRUE; // activate error output pass.complain_about_undefined = TRUE; // activate error output
perform_pass(); // perform pass, but now show "value undefined" perform_pass(); // perform pass, but now show "value undefined"
return FALSE; return FALSE;
@ -708,6 +705,8 @@ 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 var that may be needed for -DSYMBOL=VALUE
pass.number = PASS_NUMBER_EARLY;
// init platform-specific stuff. // init platform-specific stuff.
// this may read the library path from an environment variable. // this may read the library path from an environment variable.
PLATFORM_INIT; PLATFORM_INIT;

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2020 Marco Baye // Copyright (C) 1998-2024 Marco Baye
// Have a look at "acme.c" for further info // Have a look at "acme.c" for further info
// //
// Configuration // Configuration
@ -20,6 +20,15 @@ typedef unsigned int bits;
typedef unsigned int scope_t; typedef unsigned int scope_t;
typedef signed long intval_t; // at least 32 bits typedef signed long intval_t; // at least 32 bits
typedef unsigned long uintval_t; // just for logical shift right typedef unsigned long uintval_t; // just for logical shift right
// struct to remember where macros were defined (FIXME - use for symbols as well!)
struct location {
const char *filename;
int line_number;
};
// stuff for results from expression parser:
enum numtype { enum numtype {
NUMTYPE_UNDEFINED, NUMTYPE_UNDEFINED,
NUMTYPE_INT, NUMTYPE_INT,

View File

@ -513,6 +513,19 @@ void Throw_first_pass_warning(const char *message)
} }
// 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.
void throw_symbol_error(const char *msg)
{
// atm we just mimic the old behaviour. in future, do something like this:
//if (pass.is_error_pass)
Throw_error(msg);
//else
//pass.has_symbol_errors = TRUE;
}
// handle bugs // handle bugs
void BUG(const char *message, int code) void BUG(const char *message, int code)
{ {
@ -567,7 +580,7 @@ void output_object(struct object *object, struct iter_context *iter)
void output_8(intval_t value) void output_8(intval_t value)
{ {
if ((value < -0x80) || (value > 0xff)) if ((value < -0x80) || (value > 0xff))
Throw_error(exception_number_out_of_8b_range); throw_symbol_error(exception_number_out_of_8b_range);
output_byte(value); output_byte(value);
} }
@ -576,7 +589,7 @@ void output_8(intval_t value)
void output_be16(intval_t value) void output_be16(intval_t value)
{ {
if ((value < -0x8000) || (value > 0xffff)) if ((value < -0x8000) || (value > 0xffff))
Throw_error(exception_number_out_of_16b_range); throw_symbol_error(exception_number_out_of_16b_range);
output_byte(value >> 8); output_byte(value >> 8);
output_byte(value); output_byte(value);
} }
@ -586,7 +599,7 @@ void output_be16(intval_t value)
void output_le16(intval_t value) void output_le16(intval_t value)
{ {
if ((value < -0x8000) || (value > 0xffff)) if ((value < -0x8000) || (value > 0xffff))
Throw_error(exception_number_out_of_16b_range); throw_symbol_error(exception_number_out_of_16b_range);
output_byte(value); output_byte(value);
output_byte(value >> 8); output_byte(value >> 8);
} }
@ -596,7 +609,7 @@ void output_le16(intval_t value)
void output_be24(intval_t value) void output_be24(intval_t value)
{ {
if ((value < -0x800000) || (value > 0xffffff)) if ((value < -0x800000) || (value > 0xffffff))
Throw_error(exception_number_out_of_24b_range); throw_symbol_error(exception_number_out_of_24b_range);
output_byte(value >> 16); output_byte(value >> 16);
output_byte(value >> 8); output_byte(value >> 8);
output_byte(value); output_byte(value);
@ -607,7 +620,7 @@ void output_be24(intval_t value)
void output_le24(intval_t value) void output_le24(intval_t value)
{ {
if ((value < -0x800000) || (value > 0xffffff)) if ((value < -0x800000) || (value > 0xffffff))
Throw_error(exception_number_out_of_24b_range); throw_symbol_error(exception_number_out_of_24b_range);
output_byte(value); output_byte(value);
output_byte(value >> 8); output_byte(value >> 8);
output_byte(value >> 16); output_byte(value >> 16);
@ -624,7 +637,7 @@ void output_le24(intval_t value)
void output_be32(intval_t value) void output_be32(intval_t value)
{ {
// if ((value < -0x80000000) || (value > 0xffffffff)) // if ((value < -0x80000000) || (value > 0xffffffff))
// Throw_error(exception_number_out_of_32b_range); // throw_symbol_error(exception_number_out_of_32b_range);
output_byte(value >> 24); output_byte(value >> 24);
output_byte(value >> 16); output_byte(value >> 16);
output_byte(value >> 8); output_byte(value >> 8);
@ -636,7 +649,7 @@ void output_be32(intval_t value)
void output_le32(intval_t value) void output_le32(intval_t value)
{ {
// if ((value < -0x80000000) || (value > 0xffffffff)) // if ((value < -0x80000000) || (value > 0xffffffff))
// Throw_error(exception_number_out_of_32b_range); // throw_symbol_error(exception_number_out_of_32b_range);
output_byte(value); output_byte(value);
output_byte(value >> 8); output_byte(value >> 8);
output_byte(value >> 16); output_byte(value >> 16);

View File

@ -117,7 +117,8 @@ struct pass {
boolean complain_about_undefined; // will be FALSE until error pass is needed boolean complain_about_undefined; // will be FALSE until error pass is needed
}; };
extern struct pass pass; extern struct pass pass;
#define FIRST_PASS (pass.number == 0) #define PASS_NUMBER_EARLY 0 // for symbol definitions on command line
#define FIRST_PASS (pass.number == 1)
struct sanity { struct sanity {
int macro_recursions_left; // for macro calls int macro_recursions_left; // for macro calls
@ -205,6 +206,11 @@ extern void Throw_first_pass_warning(const char *msg);
// about more than one of his typos at a time. // about more than one of his typos at a time.
#define Throw_error(msg) throw_message(DEBUGLEVEL_ERROR, msg) #define Throw_error(msg) throw_message(DEBUGLEVEL_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.
extern void throw_symbol_error(const char *msg);
// output a serious error (assembly stops, for example if outbuffer overruns). // output a serious error (assembly stops, for example if outbuffer overruns).
#define Throw_serious_error(msg) throw_message(DEBUGLEVEL_SERIOUS, msg) #define Throw_serious_error(msg) throw_message(DEBUGLEVEL_SERIOUS, msg)

View File

@ -31,6 +31,7 @@ enum inputsrc {
INPUTSRC_RAM INPUTSRC_RAM
}; };
struct input { struct input {
// FIXME - use struct location for first two elements:
const char *original_filename; // during RAM reads, too const char *original_filename; // during RAM reads, too
int line_number; // in file (on RAM reads, too) int line_number; // in file (on RAM reads, too)
enum inputsrc source; enum inputsrc source;

View File

@ -28,9 +28,8 @@ static const char exception_macro_twice[] = "Macro already defined.";
// macro struct type definition // macro struct type definition
struct macro { struct macro {
int def_line_number; // line number of definition for error msgs struct location definition; // for "macro twice" error
char *def_filename, // file name of definition for error msgs char *original_name, // as section title in error msgs
*original_name, // user-supplied name for error msgs
*parameter_list, // parameters (whole line) *parameter_list, // parameters (whole line)
*body; // RAM block containing macro body *body; // RAM block containing macro body
}; };
@ -98,6 +97,8 @@ static int pipe_comma(void)
} }
// Return malloc'd copy of string // Return malloc'd copy of string
// (yes, we could also use strdup() from <string.h>, but then we still would
// need to check for NULL etc.)
static char *get_string_copy(const char *original) static char *get_string_copy(const char *original)
{ {
size_t size; size_t size;
@ -124,23 +125,39 @@ static int search_for_macro(struct rwnode **result, scope_t scope, int create)
} }
// This function is called when an already existing macro is re-defined. // This function is called when an already existing macro is re-defined.
// It first outputs a warning and then a serious error, stopping assembly. // It first outputs a warning and then an error.
// Showing the first message as a warning guarantees that ACME does not reach // Showing the first message as a warning guarantees that ACME does not reach
// the maximum error limit inbetween. // the maximum error limit inbetween.
static void report_redefinition(struct rwnode *macro_node) static void report_redefinition(struct rwnode *macro_node)
{ {
struct macro *original_macro = macro_node->body; struct macro *original_macro = macro_node->body;
const char *buffered_filename;
int buffered_linenum;
const char *buffered_section_type;
char *buffered_section_title;
// show warning with location of current definition // show warning with location of current definition
Throw_warning(exception_macro_twice); // FIXME - throw as info? Throw_warning(exception_macro_twice); // FIXME - throw as info?
// CAUTION, ugly kluge: fiddle with input_now and section_now // CAUTION, ugly kluge: fiddle with input_now and section_now
// data to generate helpful error messages // data to generate helpful error messages
input_now->original_filename = original_macro->def_filename; // FIXME - move this to a function so "symbol twice" error can also use it
input_now->line_number = original_macro->def_line_number; // buffer old data
section_now->type = "original"; buffered_filename = input_now->original_filename;
buffered_linenum = input_now->line_number;
buffered_section_type = section_now->type;
buffered_section_title = section_now->title;
// set new (fake) data
input_now->original_filename = original_macro->definition.filename;
input_now->line_number = original_macro->definition.line_number;
section_now->type = "earlier";
section_now->title = "definition"; section_now->title = "definition";
// show serious error with location of original definition // show error with location of earlier definition
Throw_serious_error(exception_macro_twice); Throw_error(exception_macro_twice);
// restore old data
input_now->original_filename = buffered_filename;
input_now->line_number = buffered_linenum;
section_now->type = buffered_section_type;
section_now->title = buffered_section_title;
} }
// This function is only called during the first pass, so there's no need to // This function is only called during the first pass, so there's no need to
@ -194,11 +211,11 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
// Search for macro. Create if not found. // Search for macro. Create if not found.
// But if found, complain (macro twice). // But if found, complain (macro twice).
if (search_for_macro(&macro_node, macro_scope, TRUE) == FALSE) if (search_for_macro(&macro_node, macro_scope, TRUE) == FALSE)
report_redefinition(macro_node); // quits with serious error report_redefinition(macro_node);
// Create new macro struct and set it up. Finally we'll read the body. // Create new macro struct and set it up. Finally we'll read the body.
new_macro = safe_malloc(sizeof(*new_macro)); new_macro = safe_malloc(sizeof(*new_macro));
new_macro->def_line_number = input_now->line_number; new_macro->definition.line_number = input_now->line_number;
new_macro->def_filename = get_string_copy(input_now->original_filename); new_macro->definition.filename = get_string_copy(input_now->original_filename);
new_macro->original_name = get_string_copy(user_macro_name->buffer); new_macro->original_name = get_string_copy(user_macro_name->buffer);
new_macro->parameter_list = formal_parameters; new_macro->parameter_list = formal_parameters;
new_macro->body = input_skip_or_store_block(TRUE); // changes LineNumber new_macro->body = input_skip_or_store_block(TRUE); // changes LineNumber
@ -275,8 +292,8 @@ void macro_parse_call(void) // Now GotByte = first char of macro name
local_gotbyte = GotByte; // CAUTION - ugly kluge local_gotbyte = GotByte; // CAUTION - ugly kluge
// set up new input // set up new input
new_input.original_filename = actual_macro->def_filename; new_input.original_filename = actual_macro->definition.filename;
new_input.line_number = actual_macro->def_line_number; new_input.line_number = actual_macro->definition.line_number;
new_input.source = INPUTSRC_RAM; new_input.source = INPUTSRC_RAM;
new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others! new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others!
new_input.src.ram_ptr = actual_macro->parameter_list; new_input.src.ram_ptr = actual_macro->parameter_list;
@ -324,7 +341,7 @@ void macro_parse_call(void) // Now GotByte = first char of macro name
} }
// and now, finally, parse the actual macro body // and now, finally, parse the actual macro body
input_now->state = INPUTSTATE_NORMAL; // FIXME - fix others! input_now->state = INPUTSTATE_NORMAL; // FIXME - fix others!
// maybe call parse_ram_block(actual_macro->def_line_number, actual_macro->body) // maybe call parse_ram_block(actual_macro->definition.line_number, actual_macro->body)
input_now->src.ram_ptr = actual_macro->body; input_now->src.ram_ptr = actual_macro->body;
parse_until_eob_or_eof(); parse_until_eob_or_eof();
if (GotByte != CHAR_EOB) if (GotByte != CHAR_EOB)

View File

@ -749,7 +749,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi
// Value is sure, so use its own size // Value is sure, so use its own size
// if value is negative, size cannot be chosen. Complain! // if value is negative, size cannot be chosen. Complain!
if (argument->val.intval < 0) { if (argument->val.intval < 0) {
Throw_error("Negative value - cannot choose addressing mode."); throw_symbol_error("Negative value - cannot choose addressing mode.");
return 0; return 0;
} }
@ -771,7 +771,7 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi
} }
// Value is too big for all possible addressing modes // Value is too big for all possible addressing modes
Throw_error(exception_number_out_of_range); throw_symbol_error(exception_number_out_of_range);
return 0; return 0;
} }
@ -793,7 +793,7 @@ static void not_in_bank(intval_t target)
char buffer[60]; // 640K should be enough for anybody char buffer[60]; // 640K should be enough for anybody
sprintf(buffer, "Target not in bank (0x%lx).", (long) target); sprintf(buffer, "Target not in bank (0x%lx).", (long) target);
Throw_error(buffer); throw_symbol_error(buffer);
} }
// helper function for branches with 8-bit offset (including bbr0..7/bbs0..7) // helper function for branches with 8-bit offset (including bbr0..7/bbs0..7)
@ -819,7 +819,7 @@ static void near_branch(int preoffset)
char buffer[60]; // 640K should be enough for anybody char buffer[60]; // 640K should be enough for anybody
sprintf(buffer, "Target out of range (%ld; %ld too far).", (long) offset, (long) (offset < -128 ? -128 - offset : offset - 127)); sprintf(buffer, "Target out of range (%ld; %ld too far).", (long) offset, (long) (offset < -128 ? -128 - offset : offset - 127));
Throw_error(buffer); throw_symbol_error(buffer);
} }
} }
} }

View File

@ -87,8 +87,11 @@ static void find_segment_max(intval_t new_pc)
// //
static void border_crossed(int current_offset) static void border_crossed(int current_offset)
{ {
// FIXME - find a way to make this a normal error instead of a serious one,
// so it can be suppressed until we are sure the program won't shrink any
// further:
if (current_offset >= config.outbuf_size) if (current_offset >= config.outbuf_size)
Throw_serious_error("Produced too much code."); Throw_serious_error("Reached memory limit.");
// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want // TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want
if (FIRST_PASS) { if (FIRST_PASS) {
throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it."); throw_message(config.debuglevel_segmentprobs, "Segment reached another one, overwriting it.");

View File

@ -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 "21 Feb" // update before release FIXME #define CHANGE_DATE "22 Feb" // 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