cleaned up error messages

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@372 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2024-03-25 00:51:11 +00:00
parent 15aa8b3a3c
commit 43759e6026
11 changed files with 113 additions and 95 deletions

View File

@ -192,7 +192,7 @@ Section: Errors during assembly
it, you can use the "--dialect" CLI switch to make ACME mimic an
older version.
"!pseudopc/!realpc" is obsolete; use "!pseudopc {}" instead.
"!pseudopc/!realpc" are obsolete; use "!pseudopc {}" instead.
This is given when one of the now obsolete !pseudopc/!realpc
pseudo opcodes is encountered.
If you want to assemble an old source code without first updating
@ -210,10 +210,6 @@ Section: Errors during assembly
This is given when the pseudo opcode "!error" is executed. The
actual message varies according to the pseudo opcode's arguments.
After ELSE, expected block or IF/IFDEF/IFNDEF.
There is something strange after ELSE: It must be "if", "ifdef",
"ifndef" or an opening brace.
Argument out of range.
You called arcsin/arccos with something not in the [-1, 1] range.
@ -241,13 +237,40 @@ CPU does not support this postfix for this mnemonic.
Division by zero.
Guess what - you attempted to divide by zero.
Expected ELSE or end-of-statement.
There is something after the closing brace of an IF block that is
not an ELSE.
Expected '{' or IF/IFDEF/IFNDEF keyword after ELSE keyword.
There is something strange after ELSE: It must be "if", "ifdef",
"ifndef" or an opening brace.
Expected ',' or IN keyword after loop variable.
You made a syntax error when using "!for": After the loop variable
there can either be a comma (for a simple counting loop) or the
"in" keyword (when iterating over string or list contents).
Anything else will give this error.
Expected end-of-statement after ELSE block.
There is something after the closing brace of an ELSE block.
Expected end-of-statement or ELSE keyword after '}'.
There is something after the closing brace of an IF block that is
not an ELSE.
Expected end-of-statement, found 'CHAR' instead.
There are still arguments when there should not be any more. The
given character is the one where end-of-line was expected.
Expected EOF, found '}' instead.
ACME encountered a '}' character when it expected the file to end
instead (because no blocks were open).
Expected WHILE or UNTIL keyword, or an empty loop condition.
When using "!do", loop conditions are optional before and after
the block, but if one is given, it has to start with "while" or
"until".
Expected index register after comma.
You used an addressing mode with a comma but did not supply a
valid index register (like 'x') after it.
Exponent is negative.
Using negative exponents only give sensible results when using
floating point maths.
@ -270,14 +293,6 @@ Force bits can only be given to numbers.
You tried to give a force bit to a symbol and then assign a string
or list to it.
Found '}' instead of end-of-file.
ACME encountered a '}' character when it expected the file to end
instead (because no blocks were open).
Garbage data at end of statement (unexpected 'CHAR').
There are still arguments when there should not be any more. The
given character is the one where end-of-line was expected.
Given object is not iterable.
You used "!for VAR in ITERABLE", but the iterable was neither a
string nor a list (likely a number).
@ -295,12 +310,6 @@ Index is undefined.
Index out of range.
The value for an indexing operation wasn't in the allowed range.
Loop var must be followed by either "in" keyword or comma.
You made a syntax error when using "!for": After the loop counter
symbol there can either be a comma (for a simple counting loop) or
the "in" keyword (when iterating over string or list contents).
Anything else will give this error.
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
@ -328,6 +337,7 @@ Negative value - cannot choose addressing mode.
No string given.
ACME expects a string but doesn't find it, or the string is empty.
This can also mean keywords or symbol names.
Number does not fit in N bits.
Number out of range.
@ -414,6 +424,9 @@ Unknown encoding.
Unknown function.
You used a mathematical function ACME does not know.
Unknown mnemonic.
You mistyped a mnemonic, or you forgot to select the correct cpu.
Unknown operator.
You used an arithmetic/logical operator ACME does not know.
@ -458,7 +471,12 @@ Section: Serious errors (stopping assembly)
This is given when the pseudo opcode "!serious" is executed. The
actual message varies according to the pseudo opcode's arguments.
Found end-of-file instead of '}'.
Expected '{' character.
ACME didn't find the expected '{' character. Remember that '{'
characters must be given on the same line as the keyword they
belong to.
Expected '}', found EOF instead.
The file ended when ACME expected the block to be closed instead
(because there was at least one block left open).
@ -467,11 +485,6 @@ Loop count is negative.
(getting this error is only possible when using the now deprecated
syntax).
Missing '{'.
ACME didn't find the expected '{' character. Remember that '{'
characters must be given on the same line as the keyword they
belong to.
Out of memory.
When ACME runs out of memory, it stops assembly, giving this
error. Free some memory and try again. It's highly unlikely anyone
@ -497,6 +510,9 @@ Too deeply nested. Recursive "!source"?
The default limit is 64, this can be changed using the
"--maxdepth" CLI switch.
Unexpected char when evaluating loop condition.
There was a syntax error while evaluating the loop condition.
Value not defined.
A value could not be worked out. Maybe you mistyped a symbol name.
Whether this is given as a "normal" or as a serious error depends

View File

@ -1160,12 +1160,12 @@ static void expect_dyadic_operator(struct expression *expression)
// Multi-character dyadic operators
case '!': // "!="
if (GetByte() == '=') {
GetByte(); // eat '!'
if (input_expect('=')) {
op = &ops_not_equal;
goto get_byte_and_push_dyadic;
goto push_dyadic_op;
}
Throw_error(exception_syntax);
alu_state = STATE_ERROR;
break;//goto end;
case '<': // "<", "<=", "<<" and "<>"

View File

@ -193,7 +193,7 @@ void flow_store_doloop_condition(struct condition *condition, char terminator)
} else if (strcmp(GlobalDynaBuf->buffer, "until") == 0) {
condition->invert = TRUE;
} else {
Throw_error(exception_syntax);
Throw_error("Expected WHILE or UNTIL keyword, or an empty loop condition.");
return;
}
// write given condition into buffer
@ -228,7 +228,7 @@ static boolean check_condition(struct condition *condition)
GetByte(); // proceed with next char
ALU_defined_int(&intresult);
if (GotByte)
Throw_serious_error(exception_syntax);
Throw_serious_error("Unexpected char when evaluating loop condition."); // FIXME - include that char in the error message!
return condition->invert ? !intresult.val.intval : !!intresult.val.intval;
}

View File

@ -35,9 +35,9 @@ char s_untitled[] = "<untitled>"; // FIXME - this is actually const
// Exception messages during assembly
const char exception_missing_string[] = "No string given.";
const char exception_negative_size[] = "Negative size argument.";
const char exception_no_left_brace[] = "Missing '{' character.";
const char exception_no_left_brace [] = "Expected '{' character.";
const char exception_no_memory_left[] = "Out of memory.";
const char exception_no_right_brace[] = "Found end-of-file instead of '}'.";
const char exception_no_right_brace [] = "Expected '}', found EOF instead.";
//const char exception_not_yet[] = "Sorry, feature not yet implemented.";
// TODO - show actual value in error message
const char exception_number_out_of_range[] = "Number out of range.";
@ -198,7 +198,7 @@ extern void parser_set_nowarn_prefix(void)
static int first_symbol_of_statement(void)
{
if (statement_flags & SF_FOUND_SYMBOL) {
Throw_error(exception_syntax);
Throw_error("Unknown mnemonic");
input_skip_remainder();
return FALSE;
}
@ -232,7 +232,7 @@ static void set_label(scope_t scope, bits force_bit, bits powers)
}
// call with symbol name in GlobalDynaBuf and GotByte == '='
// call with symbol name in GlobalDynaBuf and '=' already eaten.
// fn is exported so "!set" pseudo opcode can call it.
// "powers" is for "!set" pseudo opcode so changes are allowed (see symbol.h for powers)
void parse_assignment(scope_t scope, bits force_bit, bits powers)
@ -240,7 +240,6 @@ void parse_assignment(scope_t scope, bits force_bit, bits powers)
struct symbol *symbol;
struct object result;
GetByte(); // eat '='
symbol = symbol_find(scope);
ALU_any_result(&result);
// if wanted, mark as address reference
@ -267,6 +266,7 @@ static void parse_symbol_definition(scope_t scope)
force_bit = input_get_force_bit(); // skips spaces after (yes, force bit is allowed for label definitions)
if (GotByte == '=') {
// explicit symbol definition (symbol = <something>)
GetByte(); // eat '='
parse_assignment(scope, force_bit, POWER_NONE);
input_ensure_EOS();
} else {
@ -403,7 +403,7 @@ void parse_until_eob_or_eof(void)
if (BYTE_STARTS_KEYWORD(GotByte)) {
parse_mnemo_or_global_symbol_def();
} else {
Throw_error(exception_syntax);
Throw_error(exception_syntax); // FIXME - include char in error message!
input_skip_remainder();
}
}

View File

@ -179,7 +179,7 @@ extern void parser_set_addr_prefix(void);
// called by "!nowarn" pseudo op if used without block
extern void parser_set_nowarn_prefix(void);
// call with symbol name in GlobalDynaBuf and GotByte == '='
// call with symbol name in GlobalDynaBuf and '=' already eaten.
// "powers" is for "!set" pseudo opcode so changes are allowed (see symbol.h for powers)
extern void parse_assignment(scope_t scope, bits force_bit, bits powers);

View File

@ -72,7 +72,7 @@ void input_parse_and_close_platform_file(const char *eternal_plat_filename, FILE
// parse block and check end reason
parse_until_eob_or_eof();
if (GotByte != CHAR_EOF)
Throw_error("Found '}' instead of end-of-file.");
Throw_error("Expected EOF, found '}' instead." );
// close sublevel src
// (this looks like we could just use "fd" as arg, but maybe the file
// has been replaced with a different one in the meantime...)
@ -232,7 +232,7 @@ static char get_processed_from_file(void)
default:
// complain if byte is 0
Throw_error("Source file contains illegal character.");
Throw_error("Source file contains illegal character."); // FIXME - throw some dynamic "did not expect XYZ character" error instead!
return (char) from_file;
}
case INPUTSTATE_SKIPBLANKS:
@ -390,12 +390,13 @@ void input_ensure_EOS(void) // Now GotByte = first char to test
{
SKIPSPACE();
if (GotByte) {
// FIXME - move this to its own function!
char buf[80]; // actually needed are 51
char quote; // character before and after
// FIXME - change quoting: do not assume char is printable!
quote = (GotByte == '\'') ? '"' : '\''; // use single quotes, unless byte is a single quote (then use double quotes)
sprintf(buf, "Garbage data at end of statement (unexpected %c%c%c).", quote, GotByte, quote);
sprintf(buf, "Expected end-of-statement, found %c%c%c instead.", quote, GotByte, quote);
Throw_error(buf);
input_skip_remainder();
}
@ -734,6 +735,21 @@ int input_accept_comma(void)
return TRUE;
}
// Try to read given character.
// If found, eat character and return TRUE.
// If not found, throw syntax error and return FALSE.
int input_expect(int chr)
{
// one caller uses this to read the '=' part of "!=", so
// do not call SKIPSPACE() here!
if (GotByte == chr) {
GetByte(); // eat expected char
return TRUE;
}
Throw_error(exception_syntax); // FIXME - build "expected X, found Y" error msg!
return FALSE;
}
// read optional info about parameter length
// FIXME - move to different file!
bits input_get_force_bit(void)

View File

@ -154,6 +154,11 @@ extern int input_read_output_filename(void);
// found, otherwise FALSE.
extern int input_accept_comma(void);
// Try to read given character.
// If found, eat character and return TRUE.
// If not found, throw syntax error and return FALSE.
extern int input_expect(int chr);
// read optional info about parameter length
// FIXME - move to different file!
extern bits input_get_force_bit(void);

View File

@ -308,11 +308,8 @@ void macro_parse_call(void) // Now GotByte = first char of macro name
GotByte = local_gotbyte; // CAUTION - ugly kluge
// if needed, dump call stack
if (outer_msg_sum != pass.warning_count + pass.error_count) {
if (outer_msg_sum != pass.warning_count + pass.error_count)
Throw_warning("...called from here.");
// FIXME - use this instead:
//throw_message(DEBUGLEVEL_INFO, "...called from here.");
}
input_ensure_EOS();
}

View File

@ -571,7 +571,7 @@ static int get_index(void)
NEXTANDSKIPSPACE();
return INDEX_Z;
}
Throw_error(exception_syntax);
Throw_error("Expected index register after comma.");
return INDEX_NONE;
}
@ -605,20 +605,17 @@ static bits get_addr_mode(struct number *result)
address_mode_bits = AMB_IMPLIED;
break;
case '#':
GetByte(); // proceed with next char
GetByte(); // eat '#'
address_mode_bits = AMB_IMMEDIATE;
get_int_arg(result, FALSE);
typesystem_want_nonaddr(result); // FIXME - this is wrong for 65ce02's PHW#
break;
case '[':
GetByte(); // proceed with next char
GetByte(); // eat '['
get_int_arg(result, FALSE);
typesystem_want_addr(result);
if (GotByte == ']') {
GetByte();
if (input_expect(']')) {
address_mode_bits = AMB_LONGINDIRECT | AMB_INDEX(get_index());
} else {
Throw_error(exception_syntax);
}
break;
default:
@ -633,10 +630,8 @@ static bits get_addr_mode(struct number *result)
// in case there are still open parentheses,
// read internal index
address_mode_bits |= AMB_PREINDEX(get_index());
if (GotByte == ')') {
GetByte(); // go on with next char
} else {
Throw_error(exception_syntax);
if (input_expect(')')) {
// fn already does everything for us!
}
}
// check for external index (after closing parenthesis)
@ -1049,12 +1044,10 @@ static void group_bbr_bbs(int opcode)
get_int_arg(&zpmem, TRUE);
typesystem_want_addr(&zpmem);
if (input_accept_comma()) {
if (input_expect(',')) {
output_byte(opcode);
output_byte(zpmem.val.intval);
near_branch(3);
} else {
Throw_error(exception_syntax);
}
}
@ -1086,10 +1079,10 @@ static void group_mvn_mvp(int opcode)
get_int_arg(&source, TRUE);
typesystem_want_nonaddr(&source);
// get comma
if (!input_accept_comma()) {
Throw_error(exception_syntax);
if (!input_expect(',')) {
return;
}
SKIPSPACE();
// get second arg
if (GotByte == '#') {
GetByte(); // eat char
@ -1103,7 +1096,7 @@ static void group_mvn_mvp(int opcode)
output_8(source.val.intval);
// sanity check
if (unmatched_hash)
Throw_error(exception_syntax);
Throw_error(exception_syntax); // FIXME - maybe "Use ARG,ARG or #ARG,#ARG but do not mix and match"?
input_ensure_EOS();
}

View File

@ -32,7 +32,7 @@ enum eos {
};
// constants
static const char exception_missing_equals[] = "Missing '=' character.";
static const char exception_want_IN_or_comma[] = "Expected ',' or IN keyword after loop variable.";
// helper function, just for old, deprecated, obsolete, stupid "realpc":
@ -335,7 +335,7 @@ static enum eos po_hex(void) // now GotByte = illegal char
case CHAR_EOS:
return AT_EOS_ANYWAY; // normal exit
default:
Throw_error(exception_syntax); // all other characters are errors
Throw_error(exception_syntax); // FIXME - include character in error message!
return SKIP_REMAINDER; // error exit
}
}
@ -442,11 +442,9 @@ static enum eos po_convtab(void)
if (strcmp(GlobalDynaBuf->buffer, "file") == 0) {
SKIPSPACE();
if (GotByte != '=') {
Throw_error(exception_missing_equals);
if (!input_expect('=')) {
return SKIP_REMAINDER;
}
GetByte(); // eat '='
return use_encoding_from_file();
}
@ -524,11 +522,10 @@ static enum eos po_scrxor(void)
intval_t xor;
ALU_any_int(&xor);
if (input_accept_comma() == FALSE) {
Throw_error(exception_syntax);
return SKIP_REMAINDER;
if (input_expect(',')) {
return encode_string(&encoder_scr, xor);
}
return encode_string(&encoder_scr, xor);
return SKIP_REMAINDER;
}
// include binary file ("!binary" pseudo opcode)
@ -650,12 +647,12 @@ static enum eos po_align(void)
struct number pc;
// TODO:
// now: !align ANDVALUE, EQUALVALUE [,FILLVALUE]
// new: !align BLOCKSIZE
// ...where block size must be a power of two
// now: "!align ANDVALUE, EQUALVALUE [,FILLVALUE]"
// in future: "!align BLOCKSIZE" where block size must be a power of two
ALU_defined_int(&andresult); // FIXME - forbid addresses!
if (!input_accept_comma())
Throw_error(exception_syntax);
if (input_expect(',')) {
// fn already does everything for us
}
ALU_defined_int(&equalresult); // ...allow addresses (unlikely, but possible)
if (input_accept_comma())
ALU_any_int(&fill);
@ -680,11 +677,11 @@ static void old_offset_assembly(void)
{
if (config.dialect >= V0_94_8__DISABLED_OBSOLETE) {
// now it's obsolete
Throw_error("\"!pseudopc/!realpc\" is obsolete; use \"!pseudopc {}\" instead."); // FIXME - amend msg, tell user how to use old behaviour!
Throw_error("\"!pseudopc/!realpc\" are obsolete; use \"!pseudopc {}\" instead."); // FIXME - amend msg, tell user how to use old behaviour!
} else if (config.dialect >= V0_86__DEPRECATE_REALPC) {
// earlier it was deprecated
if (pass.number == 1)
Throw_warning("\"!pseudopc/!realpc\" is deprecated; use \"!pseudopc {}\" instead.");
Throw_warning("\"!pseudopc/!realpc\" are deprecated; use \"!pseudopc {}\" instead.");
} else {
// really old versions allowed it
}
@ -830,10 +827,8 @@ static enum eos po_set(void) // now GotByte = illegal char
return SKIP_REMAINDER; // zero length
force_bit = input_get_force_bit(); // skips spaces after
if (GotByte != '=') {
Throw_error(exception_missing_equals);
if (!input_expect('='))
return SKIP_REMAINDER;
}
// TODO: in versions before 0.97, force bit handling was broken in both
// "!set" and "!for":
@ -1001,7 +996,7 @@ static enum eos ifelse(enum ifmode mode)
// make sure it's "else"
if (strcmp(GlobalDynaBuf->buffer, "else")) {
Throw_error("Expected ELSE or end-of-statement.");
Throw_error("Expected end-of-statement or ELSE keyword after '}'.");
return SKIP_REMAINDER; // an error has been reported, so ignore rest of line
}
// anything more?
@ -1024,7 +1019,7 @@ static enum eos ifelse(enum ifmode mode)
} else if (strcmp(GlobalDynaBuf->buffer, "ifndef") == 0) {
mode = IFMODE_IFNDEF;
} else {
Throw_error("After ELSE, expected block or IF/IFDEF/IFNDEF.");
Throw_error("Expected '{' or IF/IFDEF/IFNDEF keyword after ELSE keyword.");
return SKIP_REMAINDER; // an error has been reported, so ignore rest of line
}
}
@ -1118,7 +1113,7 @@ static enum eos po_for(void) // now GotByte = illegal char
loop.algorithm = FORALGO_ITERATE;
// check for "in" keyword
if ((GotByte != 'i') && (GotByte != 'I')) {
Throw_error(exception_syntax);
Throw_error(exception_want_IN_or_comma);
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
}
/* checking for the first character explicitly here looks dumb, but actually
@ -1131,7 +1126,7 @@ knowing there is an "i" also makes sure that input_read_and_lower_keyword()
does not fail. */
input_read_and_lower_keyword();
if (strcmp(GlobalDynaBuf->buffer, "in") != 0) {
Throw_error("Loop var must be followed by either \"in\" keyword or comma.");
Throw_error(exception_want_IN_or_comma);
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
}
if (force_bit) {
@ -1380,10 +1375,9 @@ static enum eos po_debug(void)
struct number debuglevel;
ALU_defined_int(&debuglevel);
if (!input_accept_comma()) {
Throw_error("Expected comma after debug level.");
if (!input_expect(','))
return SKIP_REMAINDER;
}
// drop this one?
if (debuglevel.val.intval > config.debuglevel)
return SKIP_REMAINDER;
@ -1547,12 +1541,9 @@ void notreallypo_setpc(void) // GotByte is '*'
// next non-space must be '='
NEXTANDSKIPSPACE();
if (GotByte != '=') {
Throw_error(exception_missing_equals);
if (!input_expect('='))
goto fail;
}
GetByte();
ALU_defined_int(&intresult); // read new address
// check for modifiers
while (input_accept_comma()) {

View File

@ -9,7 +9,7 @@
#define RELEASE "0.97" // update before release FIXME
#define CODENAME "Zem" // update before release
#define CHANGE_DATE "14 Mar" // update before release FIXME
#define CHANGE_DATE "15 Mar" // 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