more cleanup

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@131 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-05-02 10:40:10 +00:00
parent 7286e00855
commit e3e68af762
9 changed files with 86 additions and 85 deletions

View File

@ -237,12 +237,13 @@ static void save_output_file(void)
}
// perform a single pass. Returns number of "NeedValue" type errors.
static int perform_pass(void)
// increment pass number and perform a single pass
static void perform_pass(void)
{
FILE *fd;
int ii;
++pass.number;
// call modules' "pass init" functions
Output_passinit(); // disable output, PC undefined
cputype_passinit(default_cpu); // set default cpu type
@ -252,8 +253,9 @@ static int perform_pass(void)
encoding_passinit(); // set default encoding
section_passinit(); // set initial zone (untitled)
// init variables
pass_undefined_count = 0; // no "NeedValue" errors yet
pass_real_errors = 0; // no real errors yet
pass.undefined_count = 0;
//pass.needvalue_count = 0; FIXME - use
pass.error_count = 0;
// Process toplevel files
for (ii = 0; ii < toplevel_src_count; ++ii) {
if ((fd = fopen(toplevel_sources[ii], FILE_READBINARY))) {
@ -262,7 +264,7 @@ static int perform_pass(void)
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[ii]);
if (toplevel_sources[ii][0] == '-')
fprintf(stderr, "Options (starting with '-') must be given _before_ source files!\n");
++pass_real_errors;
++pass.error_count;
}
}
Output_end_segment();
@ -270,50 +272,46 @@ static int perform_pass(void)
if --save-start is given, parse arg string
if --save-limit is given, parse arg string
*/
if (pass_real_errors)
if (pass.error_count)
exit(ACME_finalize(EXIT_FAILURE));
return pass_undefined_count;
}
static struct report global_report;
// do passes until done (or errors occurred). Return whether output is ready.
static int do_actual_work(void)
static boolean do_actual_work(void)
{
int undefined_prev, // "NeedValue" errors of previous pass
undefined_curr; // "NeedValue" errors of current pass
int undefs_before; // number of undefined results in previous pass
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_count = 0;
undefined_curr = perform_pass(); // First pass
// now pretend there has been a pass before the first one
undefined_prev = undefined_curr + 1;
// As long as the number of "NeedValue" errors is decreasing but
// non-zero, keep doing passes.
while (undefined_curr && (undefined_curr < undefined_prev)) {
++pass_count;
undefined_prev = undefined_curr;
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;
// keep doing passes as long as the number of undefined results keeps decreasing.
// 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.");
undefined_curr = perform_pass();
perform_pass();
}
// any errors left?
if (undefined_curr == 0) {
if (pass.undefined_count == 0) { // FIXME - use pass.needvalue_count instead!
// if listing report is wanted and there were no errors,
// do another pass to generate listing report
if (report_filename) {
if (config.process_verbosity > 1)
puts("Extra pass to generate listing report.");
if (report_open(report, report_filename) == 0) {
++pass_count;
perform_pass();
report_close(report);
}
}
return 1;
return TRUE;
}
// There are still errors (unsolvable by doing further passes),
// so perform additional pass to find and show them.
@ -322,9 +320,8 @@ static int do_actual_work(void)
// activate error output
ALU_optional_notdef_handler = Throw_error;
++pass_count;
perform_pass(); // perform pass, but now show "value undefined"
return 0;
return FALSE;
}

View File

@ -241,7 +241,7 @@ void (*ALU_optional_notdef_handler)(const char *) = NULL;
// maybe split this into "_result_ is undefined" (in that case, count) and "symbol is undefined" (in that case, call handler)
static void result_is_undefined(void)
{
++pass_undefined_count;
++pass.undefined_count;
if (ALU_optional_notdef_handler)
ALU_optional_notdef_handler(value_not_defined());
}
@ -320,7 +320,7 @@ static intval_t my_asr(intval_t left, intval_t right)
// if undefined, remember name for error output
static void check_for_def(int flags, char optional_prefix_char, char *name, size_t length)
{
if ((flags & NUMBER_IS_DEFINED) == 0) {
if (!(flags & NUMBER_IS_DEFINED)) {
DYNABUF_CLEAR(undefsym_dyna_buf);
if (optional_prefix_char) {
DynaBuf_append(undefsym_dyna_buf, optional_prefix_char);
@ -351,7 +351,7 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na
// if needed, remember name for "undefined" error output
check_for_def(symbol->result.flags, optional_prefix_char, GLOBALDYNABUF_CURRENT, name_length);
// in first pass, count usage
if (pass_count == 0)
if (FIRST_PASS)
symbol->usage++;
// push operand, regardless of whether int or float
operand_stack[operand_sp++] = symbol->result;
@ -573,6 +573,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
// Parse program counter ('*')
// FIXME - this function is similar to symbol lookup, so move it there
static void parse_program_counter(void) // Now GotByte = "*"
{
struct number pc;
@ -1472,7 +1473,7 @@ static void parse_expression(struct expression *expression)
result->flags &= ~(NUMBER_FORCES_16 | NUMBER_FORCES_8);
else if (result->flags & NUMBER_FORCES_16)
result->flags &= ~NUMBER_FORCES_8;
// if there was nothing to parse, mark as undefined
// if there was nothing to parse, mark as undefined FIXME - change this! make "nothing" its own result type; only numbers may be undefined
// (so ALU_defined_int() can react)
if (expression->is_empty)
result->flags &= ~NUMBER_IS_DEFINED;
@ -1499,6 +1500,7 @@ static void parse_expression(struct expression *expression)
} else {
// State is STATE_ERROR. Errors have already been reported,
// but we must make sure not to pass bogus data to caller.
// FIXME - just use the return value to indicate "there were errors, do not use result!"
result->flags = 0; // maybe set DEFINED flag to suppress follow-up errors?
result->val.intval = 0;
result->addr_refs = 0;
@ -1514,8 +1516,7 @@ static void parse_expression(struct expression *expression)
// Store int value if given. Returns whether stored. Throws error if undefined.
// This function needs either a defined value or no expression at all. So
// empty expressions are accepted, but undefined ones are not.
// If the result's "defined" flag is clear and the "exists" flag is set, it
// throws a serious error and therefore stops assembly.
// If the result is non-empty but undefined, a serious error is thrown, stopping assembly.
// OPEN_PARENTHESIS: complain
// EMPTY: allow
// UNDEFINED: complain _seriously_
@ -1527,8 +1528,8 @@ int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY
parse_expression(&expression);
if (expression.open_parentheses)
Throw_error(exception_paren_open);
if ((expression.is_empty == FALSE)
&& ((expression.number.flags & NUMBER_IS_DEFINED) == 0))
if ((!expression.is_empty)
&& (!(expression.number.flags & NUMBER_IS_DEFINED)))
Throw_serious_error(value_not_defined());
if (expression.is_empty)
return 0;
@ -1543,9 +1544,8 @@ int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY
// Store int value and flags (floats are transformed to int)
// It the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
// For empty expressions, an error is thrown.
// For undefined results, result_is_undefined() is called.
// OPEN_PARENTHESIS: complain
// EMPTY: complain
// UNDEFINED: allow
@ -1565,15 +1565,14 @@ void ALU_int_result(struct number *intresult) // ACCEPT_UNDEFINED
}
if (expression.is_empty)
Throw_error(exception_no_value);
else if ((intresult->flags & NUMBER_IS_DEFINED) == 0)
else if (!(intresult->flags & NUMBER_IS_DEFINED))
result_is_undefined();
}
// return int value (if result is undefined, returns zero)
// If the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
// return int value (if undefined, return zero)
// For empty expressions, an error is thrown.
// For undefined results, result_is_undefined() is called.
// OPEN_PARENTHESIS: complain
// EMPTY: complain
// UNDEFINED: allow
@ -1588,7 +1587,7 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED
Throw_error(exception_paren_open);
if (expression.is_empty)
Throw_error(exception_no_value);
else if ((expression.number.flags & NUMBER_IS_DEFINED) == 0)
else if (!(expression.number.flags & NUMBER_IS_DEFINED))
result_is_undefined();
if (expression.number.flags & NUMBER_IS_FLOAT)
return expression.number.val.fpval;
@ -1598,9 +1597,9 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED
// stores int value and flags (floats are transformed to int)
// if result was undefined, serious error is thrown
// if result is empty or undefined, serious error is thrown
// OPEN_PARENTHESIS: complain
// EMPTY: treat as UNDEFINED <= this is a problem - maybe use a wrapper fn for this use case?
// EMPTY: complain _seriously_
// UNDEFINED: complain _seriously_
// FLOAT: convert to int
void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
@ -1611,7 +1610,9 @@ void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
*intresult = expression.number;
if (expression.open_parentheses)
Throw_error(exception_paren_open);
if ((intresult->flags & NUMBER_IS_DEFINED) == 0)
if (expression.is_empty)
Throw_serious_error(exception_no_value);
if (!(intresult->flags & NUMBER_IS_DEFINED))
Throw_serious_error(value_not_defined());
if (intresult->flags & NUMBER_IS_FLOAT) {
intresult->val.intval = intresult->val.fpval;
@ -1623,8 +1624,7 @@ void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
// Store int value and flags.
// This function allows for one '(' too many. Needed when parsing indirect
// addressing modes where internal indices have to be possible.
// If the result's "exists" flag is clear (=empty expression), it throws an
// error.
// For empty expressions, an error is thrown.
// OPEN_PARENTHESIS: allow
// UNDEFINED: allow
// EMPTY: complain
@ -1645,15 +1645,13 @@ void ALU_liberal_int(struct expression *expression) // ACCEPT_UNDEFINED | ACCEPT
}
if (expression->is_empty)
Throw_error(exception_no_value);
if ((expression->is_empty == FALSE)
&& ((intresult->flags & NUMBER_IS_DEFINED) == 0))
else if (!(intresult->flags & NUMBER_IS_DEFINED))
result_is_undefined();
}
// Store value and flags (result may be either int or float)
// It the result's "exists" flag is clear (=empty expression), it throws an
// error.
// For empty expressions, an error is thrown.
// If the result's "defined" flag is clear, result_is_undefined() is called.
// OPEN_PARENTHESIS: complain
// EMPTY: complain
@ -1669,10 +1667,12 @@ void ALU_any_result(struct number *result) // ACCEPT_UNDEFINED | ACCEPT_FLOAT
Throw_error(exception_paren_open);
if (expression.is_empty)
Throw_error(exception_no_value);
else if ((result->flags & NUMBER_IS_DEFINED) == 0)
else if (!(result->flags & NUMBER_IS_DEFINED))
result_is_undefined();
}
// FIXME - find out where pass.needvalue_count must be incremented and do that!
/* TODO
// stores int value and flags, allowing for one '(' too many (x-indirect addr).
@ -1694,12 +1694,12 @@ void ALU_int_result(struct number *intresult)
// stores value and flags (result may be either int or float)
void ALU_any_result(struct number *result)
macro.c
macro call, when parsing call-by-value arg
macro call, when parsing call-by-value arg (FIXME: undefined does not mean needvalue!)
pseudoopcodes.c
!set
when throwing user-specified errors
!set (FIXME: undefined does not mean needvalue!)
when throwing user-specified errors (FIXME: undefined does not mean needvalue!)
symbol.c
explicit symbol definition
explicit symbol definition (FIXME: undefined does not mean needvalue!)
// stores int value and flags (floats are transformed to int)
// if result was undefined, serious error is thrown

View File

@ -109,15 +109,10 @@ const char global_byte_flags[256] = {
// variables
int pass_count; // number of current pass (starts 0)
char GotByte; // Last byte read (processed)
// global counters
int pass_undefined_count; // "NeedValue" type errors
int pass_real_errors; // Errors yet
struct report *report = NULL;
// configuration
struct config config;
struct pass pass;
// set configuration to default values
void config_default(struct config *conf)
@ -371,7 +366,7 @@ void Throw_warning(const char *message)
// Output a warning if in first pass. See above.
void Throw_first_pass_warning(const char *message)
{
if (pass_count == 0)
if (FIRST_PASS)
Throw_warning(message);
}
@ -388,8 +383,8 @@ void Throw_error(const char *message)
throw_message(message, "\033[31mError\033[0m");
else
throw_message(message, "Error");
++pass_real_errors;
if (pass_real_errors >= config.max_errors)
++pass.error_count;
if (pass.error_count >= config.max_errors)
exit(ACME_finalize(EXIT_FAILURE));
}

View File

@ -59,10 +59,7 @@ extern const char global_byte_flags[];
// bits 2, 1 and 0 are currently unused
// TODO - put in runtime struct:
extern int pass_count;
extern char GotByte; // Last byte read (processed)
extern int pass_undefined_count; // "NeedValue" type errors in current pass
extern int pass_real_errors; // Errors yet
// configuration
struct config {
char pseudoop_prefix; // '!' or '.'
@ -80,6 +77,15 @@ struct config {
};
extern struct config config;
struct pass {
int number; // counts up from zero
int undefined_count; // counts undefined expression results (if this stops decreasing, next pass must list them as errors)
//int needvalue_count; // counts undefined expression results actually needed for output (when this hits zero, we're done) FIXME - use
int error_count;
};
extern struct pass pass;
#define FIRST_PASS (pass.number == 0)
// report stuff
#define REPORT_ASCBUFSIZE 1024
#define REPORT_BINBUFSIZE 9 // eight are shown, then "..."

View File

@ -323,7 +323,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
GetByte(); // skip '~' character
Input_read_scope_and_keyword(&symbol_scope);
if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_scope, TRUE) == FALSE)
&& (pass_count == 0))
&& (FIRST_PASS))
Throw_error("Macro parameter twice.");
symbol_node->body = arg_table[arg_count].symbol;
} else {

View File

@ -118,7 +118,7 @@ static void border_crossed(int current_offset)
{
if (current_offset >= OUTBUFFERSIZE)
Throw_serious_error("Produced too much code.");
if (pass_count == 0) {
if (FIRST_PASS) {
// TODO: make warn/err an arg for a general "Throw" function
if (config.segment_warning_is_error)
Throw_error("Segment reached another one, overwriting it.");
@ -303,8 +303,10 @@ int output_initmem(char content)
// init memory
fill_completely(content);
// enforce another pass
if (pass_undefined_count == 0)
pass_undefined_count = 1;
if (pass.undefined_count == 0)
pass.undefined_count = 1;
//if (pass.needvalue_count == 0) FIXME - use? instead or additionally?
// pass.needvalue_count = 1;
// FIXME - enforcing another pass is not needed if there hasn't been any
// output yet. But that's tricky to detect without too much overhead.
// The old solution was to add &&(out->lowest_written < out->highest_written+1) to "if" above
@ -506,7 +508,7 @@ void Output_end_segment(void)
intval_t amount;
// in later passes, ignore completely
if (pass_count)
if (!FIRST_PASS)
return;
// if there is no segment, there is nothing to do
@ -546,7 +548,7 @@ void Output_start_segment(intval_t address_change, int segment_flags)
// allow writing to output buffer
Output_byte = real_output;
// in first pass, check for other segments and maybe issue warning
if (pass_count == 0) {
if (FIRST_PASS) {
if (!(segment_flags & SEGMENT_FLAG_OVERLAY))
check_segment(out->segment.start);
find_segment_max(out->segment.start);

View File

@ -82,7 +82,7 @@ static enum eos po_initmem(void)
struct number intresult;
// ignore in all passes but in first
if (pass_count)
if (!FIRST_PASS)
return SKIP_REMAINDER;
// get value
@ -129,7 +129,7 @@ static enum eos po_to(void)
return SKIP_REMAINDER;
// only act upon this pseudo opcode in first pass
if (pass_count)
if (!FIRST_PASS)
return SKIP_REMAINDER;
if (outputfile_set_filename())
@ -442,7 +442,8 @@ static enum eos po_binary(void)
// check whether including is a waste of time
// FIXME - future changes ("several-projects-at-once")
// may be incompatible with this!
if ((size >= 0) && (pass_undefined_count || pass_real_errors)) {
if ((size >= 0) && (pass.undefined_count || pass.error_count)) {
//if ((size >= 0) && (pass.needvalue_count || pass.error_count)) { FIXME - use!
output_skip(size); // really including is useless anyway
} else {
// really insert file
@ -466,7 +467,7 @@ static enum eos po_binary(void)
}
fclose(stream);
// if verbose, produce some output
if ((pass_count == 0) && (config.process_verbosity > 1)) {
if (FIRST_PASS && (config.process_verbosity > 1)) {
int amount = vcpu_get_statement_size();
printf("Loaded %d (0x%04x) bytes from file offset %ld (0x%04lx).\n",
@ -707,7 +708,7 @@ static enum eos po_symbollist(void)
return SKIP_REMAINDER;
// only process this pseudo opcode in first pass
if (pass_count)
if (!FIRST_PASS)
return SKIP_REMAINDER;
// if symbol list file name already set, complain and exit
@ -838,7 +839,7 @@ static enum eos ifdef_ifndef(int is_ifndef) // now GotByte = illegal char
if (node) {
symbol = (struct symbol *) node->body;
// in first pass, count usage
if (pass_count == 0)
if (FIRST_PASS)
symbol->usage++;
if (symbol->result.flags & NUMBER_IS_DEFINED)
defined = TRUE;
@ -976,7 +977,7 @@ Throw_serious_error("Not yet"); // FIXME
static enum eos po_macro(void) // now GotByte = illegal char
{
// in first pass, parse. In all other passes, skip.
if (pass_count == 0) {
if (FIRST_PASS) {
Macro_parse_definition(); // now GotByte = '}'
} else {
// skip until CHAR_SOB ('{') is found.

View File

@ -120,7 +120,7 @@ struct symbol *symbol_find(scope_t scope, int flags)
else
symbol->result.val.intval = 0;
symbol->usage = 0; // usage count
symbol->pass = pass_count;
symbol->pass = pass.number;
node->body = symbol;
} else {
symbol = node->body;
@ -264,8 +264,8 @@ void symbol_fix_forward_anon_name(int increment)
DynaBuf_append(GlobalDynaBuf, '\0');
counter_symbol = symbol_find(section_now->local_scope, 0);
// make sure it gets reset to zero in each new pass
if (counter_symbol->pass != pass_count) {
counter_symbol->pass = pass_count;
if (counter_symbol->pass != pass.number) {
counter_symbol->pass = pass.number;
counter_symbol->result.val.intval = 0;
}
number = (unsigned long) counter_symbol->result.val.intval;

View File

@ -9,7 +9,7 @@
#define RELEASE "0.96.5" // update before release FIXME
#define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "1 May" // update before release FIXME
#define CHANGE_DATE "2 May" // update before release FIXME
#define CHANGE_YEAR "2020" // update before release
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME