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.
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
first definition and a serious error (stopping assembly) for the
second definition.
will help you find the definitions by giving a warning for the new
definition and then an error for the earlier definition.
Macro not defined (or wrong signature).
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
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 '{'.
ACME didn't find the expected '{' character. Remember that '{'
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
will ever see this error, though. ;)
Produced too much code.
Reached memory limit.
The program counter reached address $10000, leaving the output
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;
++pass.number;
if (config.process_verbosity > 1)
printf("Pass %d:\n", pass.number);
cputype_passinit(); // set default cpu type
output_passinit(); // set initial pc or start with undefined pc
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_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.number = -1; // pre-init, will be incremented by perform_pass()
perform_pass(); // first pass
// pretend there has been a previous pass, with one more undefined result
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!)
while (pass.undefined_count && (pass.undefined_count < undefs_before)) {
undefs_before = pass.undefined_count;
if (config.process_verbosity > 1)
puts("Further pass.");
perform_pass();
if (--sanity.passes_left < 0) {
// FIXME - exit with error
@ -384,7 +381,7 @@ static boolean do_actual_work(void)
// There are still errors (unsolvable by doing further passes),
// so perform additional pass to find and show them.
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
perform_pass(); // perform pass, but now show "value undefined"
return FALSE;
@ -708,6 +705,8 @@ int main(int argc, const char *argv[])
if (argc == 1)
show_help_and_exit();
cliargs_init(argc, argv);
// init var that may be needed for -DSYMBOL=VALUE
pass.number = PASS_NUMBER_EARLY;
// init platform-specific stuff.
// this may read the library path from an environment variable.
PLATFORM_INIT;

View File

@ -1,5 +1,5 @@
// 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
//
// Configuration
@ -20,6 +20,15 @@ typedef unsigned int bits;
typedef unsigned int scope_t;
typedef signed long intval_t; // at least 32 bits
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 {
NUMTYPE_UNDEFINED,
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
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)
{
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);
}
@ -576,7 +589,7 @@ void output_8(intval_t value)
void output_be16(intval_t value)
{
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);
}
@ -586,7 +599,7 @@ void output_be16(intval_t value)
void output_le16(intval_t value)
{
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 >> 8);
}
@ -596,7 +609,7 @@ void output_le16(intval_t value)
void output_be24(intval_t value)
{
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 >> 8);
output_byte(value);
@ -607,7 +620,7 @@ void output_be24(intval_t value)
void output_le24(intval_t value)
{
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 >> 8);
output_byte(value >> 16);
@ -624,7 +637,7 @@ void output_le24(intval_t value)
void output_be32(intval_t value)
{
// 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 >> 16);
output_byte(value >> 8);
@ -636,7 +649,7 @@ void output_be32(intval_t value)
void output_le32(intval_t value)
{
// 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 >> 8);
output_byte(value >> 16);

View File

@ -117,7 +117,8 @@ struct pass {
boolean complain_about_undefined; // will be FALSE until error pass is needed
};
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 {
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.
#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).
#define Throw_serious_error(msg) throw_message(DEBUGLEVEL_SERIOUS, msg)

View File

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

View File

@ -28,9 +28,8 @@ static const char exception_macro_twice[] = "Macro already defined.";
// macro struct type definition
struct macro {
int def_line_number; // line number of definition for error msgs
char *def_filename, // file name of definition for error msgs
*original_name, // user-supplied name for error msgs
struct location definition; // for "macro twice" error
char *original_name, // as section title in error msgs
*parameter_list, // parameters (whole line)
*body; // RAM block containing macro body
};
@ -98,6 +97,8 @@ static int pipe_comma(void)
}
// 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)
{
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.
// 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
// the maximum error limit inbetween.
static void report_redefinition(struct rwnode *macro_node)
{
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
Throw_warning(exception_macro_twice); // FIXME - throw as info?
// CAUTION, ugly kluge: fiddle with input_now and section_now
// data to generate helpful error messages
input_now->original_filename = original_macro->def_filename;
input_now->line_number = original_macro->def_line_number;
section_now->type = "original";
// FIXME - move this to a function so "symbol twice" error can also use it
// buffer old data
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";
// show serious error with location of original definition
Throw_serious_error(exception_macro_twice);
// show error with location of earlier definition
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
@ -194,11 +211,11 @@ void macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
// Search for macro. Create if not found.
// But if found, complain (macro twice).
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.
new_macro = safe_malloc(sizeof(*new_macro));
new_macro->def_line_number = input_now->line_number;
new_macro->def_filename = get_string_copy(input_now->original_filename);
new_macro->definition.line_number = input_now->line_number;
new_macro->definition.filename = get_string_copy(input_now->original_filename);
new_macro->original_name = get_string_copy(user_macro_name->buffer);
new_macro->parameter_list = formal_parameters;
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
// set up new input
new_input.original_filename = actual_macro->def_filename;
new_input.line_number = actual_macro->def_line_number;
new_input.original_filename = actual_macro->definition.filename;
new_input.line_number = actual_macro->definition.line_number;
new_input.source = INPUTSRC_RAM;
new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others!
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
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;
parse_until_eob_or_eof();
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
// if value is negative, size cannot be chosen. Complain!
if (argument->val.intval < 0) {
Throw_error("Negative value - cannot choose addressing mode.");
throw_symbol_error("Negative value - cannot choose addressing mode.");
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
Throw_error(exception_number_out_of_range);
throw_symbol_error(exception_number_out_of_range);
return 0;
}
@ -793,7 +793,7 @@ static void not_in_bank(intval_t target)
char buffer[60]; // 640K should be enough for anybody
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)
@ -819,7 +819,7 @@ static void near_branch(int preoffset)
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));
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)
{
// 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)
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
if (FIRST_PASS) {
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 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 HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME