diff --git a/docs/Errors.txt b/docs/Errors.txt index 56499b1..f0f0bbc 100644 --- a/docs/Errors.txt +++ b/docs/Errors.txt @@ -350,9 +350,14 @@ Operation not supported: Cannot apply "OP" to "TYPE" and "TYPE". You tried to use an operator on the wrong type(s) of argument(s), like indexing a float or negating a string. -Program counter is unset. - You didn't set the program counter, so ACME didn't know where to - start. +Program counter cannot be negative. + You used "--setpc VALUE", "* = VALUE" or "!pseudopc VALUE" with a + negative number. + +Program counter undefined. + You tried to generate data before setting the program counter. Use + either "--setpc VALUE" on the command line or "* = VALUE" at the + start of your source code file. Quotes still open at end of line. You forgot the closing quotes. @@ -511,6 +516,14 @@ Too deeply nested. Recursive "!source"? The default limit is 64, this can be changed using the "--maxdepth" CLI switch. +Tried to write to negative address. + This means that a new segment inside a !pseudopc block would be + placed before the start of the output buffer. Example: + * = $1000 ; ok (we begin at $1000) + !pseudopc $8000 { ; ok (we pretend to be at $8000) + * = $5000 ; error (we need to go back by $3000, + } ; which would mean going to -$2000!) + Unexpected char when evaluating loop condition. There was a syntax error while evaluating the loop condition. diff --git a/src/alu.c b/src/alu.c index 74c4a0f..10c28ec 100644 --- a/src/alu.c +++ b/src/alu.c @@ -349,7 +349,7 @@ static void is_not_defined(struct symbol *optional_symbol, char *name, size_t le // FIXME - just split this up into two different buffers, "user name" and "internal name", that way the scope can be changed to a prefix as well! // This function is not allowed to change DynaBuf because that's where the // symbol name is stored! -static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unpseudo_count) +static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unpseudo_count, boolean check_pass_number) { struct symbol *symbol; struct object *arg; @@ -365,6 +365,14 @@ static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unp } else { // FIXME - add sanity check for UNDEFINED where EVER_UNDEFINED is false -> BUG()! // (because the only way to have UNDEFINED is the block above, and EVER_UNDEFINED taints everything it touches) + + // special kluge for anonymous backward labels: + // if they are referenced before they are defined, the last + // value of the previous pass would be used! so we check the + // pass number and if the value is from the previous pass, we + // delete it: + if (check_pass_number && (symbol->pass_number != pass.number)) + symbol->object.u.number.ntype = NUMTYPE_UNDEFINED; } // first push on arg stack, so we have a local copy we can "unpseudo" arg = &arg_stack[arg_sp++]; @@ -732,7 +740,7 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&' if (input_read_scope_and_symbol_name(&scope)) // now GotByte = illegal char return 1; // error (no string given) - get_symbol_value(scope, GlobalDynaBuf->size - 1, unpseudo_count); // -1 to not count terminator + get_symbol_value(scope, GlobalDynaBuf->size - 1, unpseudo_count, FALSE); // -1 to not count terminator, no pass number check // } else if (...) { // // anonymous symbol // "unpseudo"-ing anonymous symbols is not supported @@ -908,7 +916,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression } while (GetByte() == '+'); ugly_length_kluge = GlobalDynaBuf->size; // FIXME - get rid of this! symbol_fix_forward_anon_name(FALSE); // FALSE: do not increment counter - get_symbol_value(section_now->local_scope, ugly_length_kluge, 0); // no prefix, no unpseudo + get_symbol_value(section_now->local_scope, ugly_length_kluge, 0, FALSE); // no prefix, no unpseudo, no pass number check goto now_expect_dyadic_op; case '-': // NEGATION operator or anonymous backward label @@ -922,7 +930,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression SKIPSPACE(); if (BYTE_FOLLOWS_ANON(GotByte)) { dynabuf_append(GlobalDynaBuf, '\0'); - get_symbol_value(section_now->local_scope, GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo + get_symbol_value(section_now->local_scope, GlobalDynaBuf->size - 1, 0, TRUE); // no prefix, -1 to not count terminator, no unpseudo, check pass number goto now_expect_dyadic_op; } @@ -1008,7 +1016,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression // here we need to put '.' into GlobalDynaBuf even though we have already skipped it: if (input_read_scope_and_symbol_name_KLUGED(&scope) == 0) { // now GotByte = illegal char - get_symbol_value(scope, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo + get_symbol_value(scope, GlobalDynaBuf->size - 1, 0, FALSE); // -1 to not count terminator, no unpseudo, no pass number check goto now_expect_dyadic_op; // ok } @@ -1018,7 +1026,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression case CHEAP_PREFIX: // cheap local symbol //printf("looking in cheap scope %d\n", section_now->cheap_scope); if (input_read_scope_and_symbol_name(&scope) == 0) { // now GotByte = illegal char - get_symbol_value(scope, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo + get_symbol_value(scope, GlobalDynaBuf->size - 1, 0, FALSE); // -1 to not count terminator, no unpseudo, no pass number check goto now_expect_dyadic_op; // ok } @@ -1058,7 +1066,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression // however, apart from that check above, function calls have nothing to do with // parentheses: "sin(x+y)" gets parsed just like "not(x+y)". } else { - get_symbol_value(SCOPE_GLOBAL, GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo + get_symbol_value(SCOPE_GLOBAL, GlobalDynaBuf->size - 1, 0, FALSE); // no prefix, -1 to not count terminator, no unpseudo, no pass number check goto now_expect_dyadic_op; } } diff --git a/src/output.c b/src/output.c index d2df681..664c54d 100644 --- a/src/output.c +++ b/src/output.c @@ -411,7 +411,7 @@ static void start_segment(intval_t address_change, bits segment_flags) // calculate start of new segment out->write_idx = out->write_idx + address_change; if (out->write_idx < 0) { - throw_serious_error("Tried to write to negative addresses."); + throw_serious_error("Tried to write to negative address."); } else if (out->write_idx >= OUTBUF_MAXSIZE) { throw_serious_error("Reached memory limit."); } diff --git a/src/version.h b/src/version.h index 4d5ed85..bbfb165 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.97" // update before release FIXME #define CODENAME "Zem" // update before release -#define CHANGE_DATE "14 Aug" // update before release FIXME +#define CHANGE_DATE "15 Aug" // 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 diff --git a/testing/errors/negativeaddress.a b/testing/errors/negativeaddress.a new file mode 100644 index 0000000..cdc8555 --- /dev/null +++ b/testing/errors/negativeaddress.a @@ -0,0 +1,5 @@ + *=$1000 + !pseudopc $8000 { + * = $6000 ; -> "Tried to write to negative address." + rts + } diff --git a/testing/errors/valuenotdefined6.a b/testing/errors/valuenotdefined6.a new file mode 100644 index 0000000..b36dfe9 --- /dev/null +++ b/testing/errors/valuenotdefined6.a @@ -0,0 +1,4 @@ + *=$1000 + jmp -- ; -> "Symbol not defined." +-- ; older versions had a bug where the last value set in a pass survived to the next pass + jmp --