From 4565070849eef95ba3025a99f7d3c25cbfe88640 Mon Sep 17 00:00:00 2001 From: marcobaye Date: Sat, 2 May 2020 21:59:20 +0000 Subject: [PATCH] improved "Value not defined" output: Now all undefined symbols of expression are reported, but never more than once. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@135 4df02467-bbd4-4a76-a152-e7ce94205b78 --- src/alu.c | 87 +++++++++++++++++++++++++++++----------------------- src/global.c | 1 + src/global.h | 1 + src/symbol.c | 1 + src/symbol.h | 2 +- 5 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/alu.c b/src/alu.c index 4d30234..c802cad 100644 --- a/src/alu.c +++ b/src/alu.c @@ -31,7 +31,6 @@ #define ERRORMSG_DYNABUF_INITIALSIZE 256 // ad hoc #define FUNCTION_DYNABUF_INITIALSIZE 8 // enough for "arctan" -#define UNDEFSYM_DYNABUF_INITIALSIZE 256 // ad hoc #define HALF_INITIAL_STACK_SIZE 8 static const char exception_div_by_zero[] = "Division by zero."; static const char exception_no_value[] = "No value given."; @@ -151,7 +150,6 @@ static struct operator ops_arctan = {OPHANDLE_ARCTAN, 32}; // function // variables static struct dynabuf *errormsg_dyna_buf; // dynamic buffer for "value not defined" error static struct dynabuf *function_dyna_buf; // dynamic buffer for fn names -static struct dynabuf *undefsym_dyna_buf; // dynamic buffer for name of undefined symbol TODO - get rid of this intermediate kluge and report errors immediately static struct operator **operator_stack = NULL; static int operator_stk_size = HALF_INITIAL_STACK_SIZE; static int operator_sp; // operator stack pointer @@ -222,18 +220,6 @@ do { \ } while (0) -// generate "Value not defined" error message with added symbol name -static char *value_not_defined(void) -{ - DYNABUF_CLEAR(errormsg_dyna_buf); - DynaBuf_add_string(errormsg_dyna_buf, "Value not defined ("); - DynaBuf_add_string(errormsg_dyna_buf, undefsym_dyna_buf->buffer); - DynaBuf_add_string(errormsg_dyna_buf, ")."); - DynaBuf_append(errormsg_dyna_buf, '\0'); - return errormsg_dyna_buf->buffer; -} - - // enlarge operator stack static void enlarge_operator_stack(void) { @@ -259,7 +245,6 @@ void ALU_init(void) { errormsg_dyna_buf = DynaBuf_create(ERRORMSG_DYNABUF_INITIALSIZE); function_dyna_buf = DynaBuf_create(FUNCTION_DYNABUF_INITIALSIZE); - undefsym_dyna_buf = DynaBuf_create(UNDEFSYM_DYNABUF_INITIALSIZE); Tree_add_table(&operator_tree, operator_list); Tree_add_table(&function_tree, function_list); enlarge_operator_stack(); @@ -304,25 +289,46 @@ static intval_t my_asr(intval_t left, intval_t right) return ~((~left) >> 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 needed, throw "Value not defined" error +// This function is not allowed to change DynaBuf because the symbol's name +// might be stored there! +static void check_for_def(struct symbol *optional_symbol, int flags, char optional_prefix_char, char *name, size_t length) { - if (!(flags & NUMBER_IS_DEFINED)) { - DYNABUF_CLEAR(undefsym_dyna_buf); - if (optional_prefix_char) { - DynaBuf_append(undefsym_dyna_buf, optional_prefix_char); - length++; - } - DynaBuf_add_string(undefsym_dyna_buf, name); - if (length > undefsym_dyna_buf->size) { - Bug_found("Illegal symbol name length", undefsym_dyna_buf->size - length); - } else { - undefsym_dyna_buf->size = length; - } - DynaBuf_append(undefsym_dyna_buf, '\0'); + if (flags & NUMBER_IS_DEFINED) + return; + + if (!pass.complain_about_undefined) + return; + + // only complain once per symbol + if (optional_symbol) { + if (optional_symbol->has_been_reported) + return; + + optional_symbol->has_been_reported = TRUE; } + + DYNABUF_CLEAR(errormsg_dyna_buf); + DynaBuf_add_string(errormsg_dyna_buf, "Value not defined ("); + length += errormsg_dyna_buf->size; + + if (optional_prefix_char) { + DynaBuf_append(errormsg_dyna_buf, optional_prefix_char); + ++length; + } + DynaBuf_add_string(errormsg_dyna_buf, name); + if (errormsg_dyna_buf->size < length) { + Bug_found("Illegal symbol name length", errormsg_dyna_buf->size - length); + } else { + errormsg_dyna_buf->size = length; + } + DynaBuf_add_string(errormsg_dyna_buf, ")."); + DynaBuf_append(errormsg_dyna_buf, '\0'); + Throw_error(errormsg_dyna_buf->buffer); } + // Lookup (and create, if necessary) symbol tree item and return its value. // DynaBuf holds the symbol's name and "scope" its scope. // The name length must be given explicitly because of anonymous forward labels; @@ -335,8 +341,8 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na // if the symbol gets created now, mark it as unsure symbol = symbol_find(scope, NUMBER_EVER_UNDEFINED); - // if needed, remember name for "undefined" error output - check_for_def(symbol->result.flags, optional_prefix_char, GLOBALDYNABUF_CURRENT, name_length); + // if needed, output "value not defined" error + check_for_def(symbol, symbol->result.flags, optional_prefix_char, GLOBALDYNABUF_CURRENT, name_length); // in first pass, count usage if (FIRST_PASS) symbol->usage++; @@ -352,8 +358,8 @@ static void parse_program_counter(void) // Now GotByte = "*" GetByte(); vcpu_read_pc(&pc); - // if needed, remember name for "undefined" error output - check_for_def(pc.flags, 0, "*", 1); + // if needed, output "value not defined" error + check_for_def(NULL, pc.flags, 0, "*", 1); PUSH_INTOPERAND(pc.val.intval, pc.flags, pc.addr_refs); } @@ -1468,9 +1474,6 @@ static void parse_expression(struct expression *expression) if (!(expression->number.flags & NUMBER_IS_DEFINED)) { // then count (in all passes) ++pass.undefined_count; - // and throw error (in error pass) - if (pass.complain_about_undefined) - Throw_error(value_not_defined()); } } // do some checks depending on int/float @@ -1520,13 +1523,16 @@ static void parse_expression(struct expression *expression) boolean ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY { struct expression expression; + boolean buf = pass.complain_about_undefined; + pass.complain_about_undefined = TRUE; parse_expression(&expression); + pass.complain_about_undefined = buf; if (expression.open_parentheses) Throw_error(exception_paren_open); if ((!expression.is_empty) && (!(expression.number.flags & NUMBER_IS_DEFINED))) - Throw_serious_error(value_not_defined()); + Throw_serious_error(exception_value_not_defined); if (expression.is_empty) return FALSE; @@ -1595,15 +1601,18 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED void ALU_defined_int(struct number *intresult) // no ACCEPT constants? { struct expression expression; + boolean buf = pass.complain_about_undefined; + pass.complain_about_undefined = TRUE; parse_expression(&expression); + pass.complain_about_undefined = buf; *intresult = expression.number; if (expression.open_parentheses) Throw_error(exception_paren_open); if (expression.is_empty) Throw_serious_error(exception_no_value); if (!(intresult->flags & NUMBER_IS_DEFINED)) - Throw_serious_error(value_not_defined()); + Throw_serious_error(exception_value_not_defined); if (intresult->flags & NUMBER_IS_FLOAT) { intresult->val.intval = intresult->val.fpval; intresult->flags &= ~NUMBER_IS_FLOAT; diff --git a/src/global.c b/src/global.c index 5c1953e..4622922 100644 --- a/src/global.c +++ b/src/global.c @@ -57,6 +57,7 @@ const char exception_no_right_brace[] = "Found end-of-file instead of '}'."; const char exception_number_out_of_range[] = "Number out of range."; const char exception_pc_undefined[] = "Program counter undefined."; const char exception_syntax[] = "Syntax error."; +const char exception_value_not_defined[] = "Value not defined."; // default value for number of errors before exiting #define MAXERRORS 10 diff --git a/src/global.h b/src/global.h index 948262f..1097593 100644 --- a/src/global.h +++ b/src/global.h @@ -49,6 +49,7 @@ extern const char exception_no_right_brace[]; extern const char exception_number_out_of_range[]; extern const char exception_pc_undefined[]; extern const char exception_syntax[]; +extern const char exception_value_not_defined[]; // byte flags table extern const char global_byte_flags[]; #define BYTE_STARTS_KEYWORD(b) (global_byte_flags[(unsigned char) b] & (1u << 7)) // byte is allowed at start of keyword (a-z, A-Z, _, everything>127) diff --git a/src/symbol.c b/src/symbol.c index da7a44e..fd3ca99 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -121,6 +121,7 @@ struct symbol *symbol_find(scope_t scope, int flags) symbol->result.val.intval = 0; symbol->usage = 0; // usage count symbol->pass = pass.number; + symbol->has_been_reported = FALSE; node->body = symbol; } else { symbol = node->body; diff --git a/src/symbol.h b/src/symbol.h index c8b0e91..2249d9c 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -15,7 +15,7 @@ struct symbol { struct number result; // flags, value, address refs int usage; // usage count int pass; // pass of creation (for anon counters) - // add flag to indicate "has already been reported as undefined" + boolean has_been_reported; // indicates "has been reported as undefined" // add file ref + line num of last definition };