mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-25 07:31:52 +00:00
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:
parent
3deb9700dc
commit
5910081651
@ -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.
|
||||
|
||||
|
11
src/acme.c
11
src/acme.c
@ -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;
|
||||
|
11
src/config.h
11
src/config.h
@ -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,
|
||||
|
27
src/global.c
27
src/global.c
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
51
src/macro.c
51
src/macro.c
@ -28,11 +28,10 @@ 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
|
||||
*parameter_list, // parameters (whole line)
|
||||
*body; // RAM block containing macro body
|
||||
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
|
||||
};
|
||||
// there's no need to make this a struct and add a type component:
|
||||
// when the macro has been found, accessing its parameter_list component
|
||||
@ -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(¯o_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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user