mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-08-10 02:24:56 +00:00
a bit of refactoring concerning "unpseudopc"
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@413 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
47
src/alu.c
47
src/alu.c
@@ -349,7 +349,8 @@ 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, boolean check_pass_number)
|
||||
// returns pointer to symbol because the "unpseudopc" caller needs it
|
||||
static struct symbol *get_symbol_value(scope_t scope, size_t name_length, boolean check_pass_number)
|
||||
{
|
||||
struct symbol *symbol;
|
||||
struct object *arg;
|
||||
@@ -377,26 +378,20 @@ static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unp
|
||||
// first push on arg stack, so we have a local copy we can "unpseudo"
|
||||
arg = &arg_stack[arg_sp++];
|
||||
*arg = symbol->object;
|
||||
if (unpseudo_count) {
|
||||
if (arg->type == &type_number) {
|
||||
pseudopc_unpseudo(&arg->u.number, symbol->pseudopc, unpseudo_count);
|
||||
} else {
|
||||
throw_error("Un-pseudopc operator '&' can only be applied to number symbols.");
|
||||
}
|
||||
}
|
||||
|
||||
// if needed, output "value not defined" error
|
||||
// FIXME - in case of unpseudo, error message should include the correct number of '&' characters
|
||||
// if (!(arg->type->is_defined(arg)))
|
||||
// FIXME - now that lists with undefined items are "undefined", this fails in
|
||||
// case of "!if len(some_list) {", so check for undefined _numbers_ explicitly:
|
||||
if ((arg->type == &type_number) && (arg->u.number.ntype == NUMTYPE_UNDEFINED))
|
||||
is_not_defined(symbol, GLOBALDYNABUF_CURRENT, name_length);
|
||||
// FIXME - if arg is list, increment ref count!
|
||||
return symbol; // only needed by "unpseudopc" caller
|
||||
}
|
||||
|
||||
|
||||
// parse program counter ('*')
|
||||
static void parse_program_counter(unsigned int unpseudo_count) // now GotByte = "*"
|
||||
static void parse_program_counter(void) // now GotByte = "*"
|
||||
{
|
||||
struct number pc;
|
||||
struct object *arg;
|
||||
@@ -406,8 +401,6 @@ static void parse_program_counter(unsigned int unpseudo_count) // now GotByte =
|
||||
// if needed, output "value not defined" error
|
||||
if (pc.ntype == NUMTYPE_UNDEFINED)
|
||||
is_not_defined(NULL, "*", 1);
|
||||
if (unpseudo_count)
|
||||
pseudopc_unpseudo(&pc, pseudopc_get_context(), unpseudo_count);
|
||||
// push to arg stack
|
||||
arg = &arg_stack[arg_sp++];
|
||||
arg->type = &type_number;
|
||||
@@ -715,11 +708,13 @@ static void list_append_list(struct listitem *selfhead, struct listitem *otherhe
|
||||
|
||||
|
||||
// helper function for "monadic &" (either octal value or "unpseudo" operator)
|
||||
// returns nonzero on error
|
||||
// returns nonzero on (syntax) error
|
||||
static int parse_octal_or_unpseudo(void) // now GotByte = '&'
|
||||
{
|
||||
unsigned int unpseudo_count = 1;
|
||||
scope_t scope; // for "unpseudo symbol"
|
||||
struct pseudopc *context;
|
||||
struct symbol *symbol;
|
||||
scope_t scope;
|
||||
|
||||
// first count ampersand characters so we know how many layers to "unpseudo":
|
||||
while (GetByte() == '&')
|
||||
@@ -734,13 +729,19 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&'
|
||||
// it's not an octal number, so it must be something to "unpseudo":
|
||||
if (GotByte == '*') {
|
||||
// program counter
|
||||
parse_program_counter(unpseudo_count);
|
||||
parse_program_counter();
|
||||
context = pseudopc_get_context();
|
||||
} else if (BYTE_STARTS_KEYWORD(GotByte) || (GotByte == LOCAL_PREFIX) || (GotByte == CHEAP_PREFIX)) {
|
||||
// symbol
|
||||
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, FALSE); // -1 to not count terminator, no pass number check
|
||||
symbol = get_symbol_value(scope, GlobalDynaBuf->size - 1, FALSE); // -1 to not count terminator, no pass number check
|
||||
if (symbol->object.type != &type_number) {
|
||||
throw_error("Un-pseudopc operator '&' can only be applied to number symbols.");
|
||||
return 0; // "ok" (because the error above does not inhibit parsing)
|
||||
}
|
||||
context = symbol->pseudopc;
|
||||
// } else if (...) {
|
||||
// // anonymous symbol
|
||||
// "unpseudo"-ing anonymous symbols is not supported
|
||||
@@ -748,6 +749,8 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&'
|
||||
throw_error(exception_missing_string); // FIXME - create some "expected octal value or symbol name" error instead!
|
||||
return 1; // error
|
||||
}
|
||||
// now process argument on arg stack (sp has been incremented)
|
||||
pseudopc_unpseudo(&arg_stack[arg_sp - 1].u.number, context, unpseudo_count);
|
||||
return 0; // ok
|
||||
}
|
||||
|
||||
@@ -916,7 +919,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, FALSE); // no prefix, no unpseudo, no pass number check
|
||||
get_symbol_value(section_now->local_scope, ugly_length_kluge, FALSE); // no prefix, no pass number check
|
||||
goto now_expect_dyadic_op;
|
||||
|
||||
case '-': // NEGATION operator or anonymous backward label
|
||||
@@ -930,7 +933,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, TRUE); // no prefix, -1 to not count terminator, no unpseudo, check pass number
|
||||
get_symbol_value(section_now->local_scope, GlobalDynaBuf->size - 1, TRUE); // no prefix, -1 to not count terminator, check pass number
|
||||
goto now_expect_dyadic_op;
|
||||
}
|
||||
|
||||
@@ -1001,7 +1004,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
|
||||
goto now_expect_dyadic_op;
|
||||
|
||||
case '*': // Program counter
|
||||
parse_program_counter(0);
|
||||
parse_program_counter();
|
||||
// Now GotByte = char after closing quote
|
||||
goto now_expect_dyadic_op;
|
||||
|
||||
@@ -1016,7 +1019,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, FALSE); // -1 to not count terminator, no unpseudo, no pass number check
|
||||
get_symbol_value(scope, GlobalDynaBuf->size - 1, FALSE); // -1 to not count terminator, no pass number check
|
||||
goto now_expect_dyadic_op; // ok
|
||||
}
|
||||
|
||||
@@ -1026,7 +1029,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, FALSE); // -1 to not count terminator, no unpseudo, no pass number check
|
||||
get_symbol_value(scope, GlobalDynaBuf->size - 1, FALSE); // -1 to not count terminator, no pass number check
|
||||
goto now_expect_dyadic_op; // ok
|
||||
}
|
||||
|
||||
@@ -1066,7 +1069,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, FALSE); // no prefix, -1 to not count terminator, no unpseudo, no pass number check
|
||||
get_symbol_value(SCOPE_GLOBAL, GlobalDynaBuf->size - 1, FALSE); // no prefix, -1 to not count terminator, no pass number check
|
||||
goto now_expect_dyadic_op;
|
||||
}
|
||||
}
|
||||
|
32
src/output.c
32
src/output.c
@@ -553,26 +553,34 @@ void pseudopc_end(void)
|
||||
if (pseudopc_current_context == NULL)
|
||||
BUG("PseudoPCContext", 0);
|
||||
}
|
||||
// un-pseudopc a label value by given number of levels
|
||||
// returns nonzero on error (if level too high)
|
||||
int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels)
|
||||
// un-pseudopc a value by given number of levels
|
||||
void pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels)
|
||||
{
|
||||
switch (target->ntype) {
|
||||
case NUMTYPE_UNDEFINED:
|
||||
return; // this might be an unresolved forward ref,
|
||||
// which would have no context ptr.
|
||||
// so we do nothing now and let later passes handle it.
|
||||
case NUMTYPE_INT:
|
||||
break; // this is what we expect
|
||||
case NUMTYPE_FLOAT:
|
||||
throw_error("Un-pseudopc operator '&' does not work on floats.");
|
||||
return;
|
||||
default:
|
||||
BUG("IllegalNumberType8", target->ntype);
|
||||
}
|
||||
if (context == NULL) {
|
||||
throw_error("Un-pseudopc operator '&' only works on addresses.");
|
||||
return;
|
||||
}
|
||||
while (levels--) {
|
||||
if (target->ntype == NUMTYPE_UNDEFINED)
|
||||
return 0; // ok (no sense in trying to unpseudo this, and it might be an unresolved forward ref anyway)
|
||||
|
||||
if (context == NULL) {
|
||||
throw_error("Un-pseudopc operator '&' only works on addresses.");
|
||||
return 1; // error
|
||||
}
|
||||
if (context == &outermost_pseudopc_context) {
|
||||
throw_error("Un-pseudopc operator '&' has no !pseudopc context.");
|
||||
return 1; // error
|
||||
return;
|
||||
}
|
||||
target->val.intval = target->val.intval - context->offset; // remove offset
|
||||
context = context->outer;
|
||||
}
|
||||
return 0; // ok
|
||||
}
|
||||
// return pointer to current "pseudopc" struct
|
||||
// this gets called when parsing label definitions
|
||||
|
@@ -72,9 +72,8 @@ extern void pseudopc_start(struct number *new_pc);
|
||||
// end offset assembly
|
||||
extern void pseudopc_end(void);
|
||||
|
||||
// un-pseudopc a label value by given number of levels
|
||||
// returns nonzero on error (if level too high)
|
||||
extern int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels);
|
||||
// un-pseudopc a value by given number of levels
|
||||
extern void pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels);
|
||||
|
||||
// return pointer to current "pseudopc" struct
|
||||
// this gets called when parsing label definitions
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "15 Aug" // update before release FIXME
|
||||
#define CHANGE_DATE "16 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
|
||||
|
Reference in New Issue
Block a user