diff --git a/src/alu.c b/src/alu.c index 2467134..4efc8eb 100644 --- a/src/alu.c +++ b/src/alu.c @@ -158,7 +158,7 @@ static int operator_sp; // operator stack pointer static struct result *operand_stack = NULL; // flags and value static int operand_stk_size = HALF_INITIAL_STACK_SIZE; static int operand_sp; // value stack pointer -static int indirect_flag; // Flag for indirect addressing +static int indirect_flag; // Flag for indirect addressing TODO - get rid of extra var // (indicated by useless parentheses) // Contains either 0 or MVALUE_INDIRECT enum alu_state { @@ -1423,17 +1423,19 @@ RNTLObutDontTouchIndirectFlag: } -// The core of it. Returns number of parentheses left open. +// The core of it. // FIXME - make state machine using function pointers? or too slow? -static int parse_expression(struct result *result) +static void parse_expression(struct expression *expression) { - int open_parentheses = 0; + struct result *result = &expression->number; + + expression->open_parentheses = 0; operator_sp = 0; // operator stack pointer operand_sp = 0; // value stack pointer // begin by reading value (or monadic operator) alu_state = STATE_EXPECT_OPERAND_OR_MONADIC_OPERATOR; - indirect_flag = 0; // Contains either 0 or MVALUE_INDIRECT + indirect_flag = 0; // Contains either 0 or MVALUE_INDIRECT // FIXME PUSH_OPERATOR(&ops_exprstart); do { // check stack sizes. enlarge if needed @@ -1450,7 +1452,7 @@ static int parse_expression(struct result *result) break; // no fallthrough; state might // have been changed to END or ERROR case STATE_TRY_TO_REDUCE_STACKS: - try_to_reduce_stacks(&open_parentheses); + try_to_reduce_stacks(&expression->open_parentheses); break; case STATE_MAX_GO_ON: // suppress case STATE_ERROR: // compiler @@ -1467,7 +1469,7 @@ static int parse_expression(struct result *result) Bug_found("OperatorStackNotEmpty", operator_sp); // copy result *result = operand_stack[0]; - result->flags |= indirect_flag; // OR indirect flag + expression->number.flags |= indirect_flag; // OR indirect flag FIXME - get rid of "indirect" // only allow *one* force bit if (result->flags & MVALUE_FORCE24) result->flags &= ~(MVALUE_FORCE16 | MVALUE_FORCE08); @@ -1475,7 +1477,7 @@ static int parse_expression(struct result *result) result->flags &= ~MVALUE_FORCE08; // if there was nothing to parse, mark as undefined // (so ALU_defined_int() can react) - if ((result->flags & MVALUE_EXISTS) == 0) + if ((expression->number.flags & MVALUE_EXISTS) == 0) result->flags &= ~MVALUE_DEFINED; // do some checks depending on int/float if (result->flags & MVALUE_IS_FP) { @@ -1509,8 +1511,6 @@ static int parse_expression(struct result *result) // callers must decide for themselves what to do when expression parser returns error // (currently LDA'' results in both "no string given" AND "illegal combination of command and addressing mode"!) } - // return number of open (unmatched) parentheses - return open_parentheses; // FIXME - move this into "expression struct flags", together with indirect flag and EXISTS flag } @@ -1525,22 +1525,23 @@ static int parse_expression(struct result *result) // FLOAT: convert to int int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY { - struct result result; + struct expression expression; - if (parse_expression(&result)) + parse_expression(&expression); + if (expression.open_parentheses) Throw_error(exception_paren_open); // do not combine the next two checks, they were separated because EXISTS should move from result flags to expression flags... - if ((result.flags & MVALUE_EXISTS) - && ((result.flags & MVALUE_DEFINED) == 0)) + if ((expression.number.flags & MVALUE_EXISTS) + && ((expression.number.flags & MVALUE_DEFINED) == 0)) Throw_serious_error(value_not_defined()); - if ((result.flags & MVALUE_EXISTS) == 0) + if ((expression.number.flags & MVALUE_EXISTS) == 0) return 0; // something was given, so store - if (result.flags & MVALUE_IS_FP) - *target = result.val.fpval; + if (expression.number.flags & MVALUE_IS_FP) + *target = expression.number.val.fpval; else - *target = result.val.intval; + *target = expression.number.val.intval; return 1; } @@ -1555,14 +1556,18 @@ int ALU_optional_defined_int(intval_t *target) // ACCEPT_EMPTY // FLOAT: convert to int void ALU_int_result(struct result *intresult) // ACCEPT_UNDEFINED { - if (parse_expression(intresult)) + struct expression expression; + + parse_expression(&expression); + *intresult = expression.number; + if (expression.open_parentheses) Throw_error(exception_paren_open); // make sure result is not float if (intresult->flags & MVALUE_IS_FP) { intresult->val.intval = intresult->val.fpval; intresult->flags &= ~MVALUE_IS_FP; } - if ((intresult->flags & MVALUE_EXISTS) == 0) + if ((expression.number.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); else if ((intresult->flags & MVALUE_DEFINED) == 0) result_is_undefined(); @@ -1580,18 +1585,19 @@ void ALU_int_result(struct result *intresult) // ACCEPT_UNDEFINED intval_t ALU_any_int(void) // ACCEPT_UNDEFINED { // FIXME - replace this fn with a call to ALU_int_result() above! - struct result result; + struct expression expression; - if (parse_expression(&result)) + parse_expression(&expression); + if (expression.open_parentheses) Throw_error(exception_paren_open); - if ((result.flags & MVALUE_EXISTS) == 0) + if ((expression.number.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); - else if ((result.flags & MVALUE_DEFINED) == 0) + else if ((expression.number.flags & MVALUE_DEFINED) == 0) result_is_undefined(); - if (result.flags & MVALUE_IS_FP) - return result.val.fpval; + if (expression.number.flags & MVALUE_IS_FP) + return expression.number.val.fpval; else - return result.val.intval; + return expression.number.val.intval; } @@ -1601,9 +1607,13 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED // EMPTY: treat as UNDEFINED <= this is a problem - maybe use a wrapper fn for this use case? // UNDEFINED: complain _seriously_ // FLOAT: convert to int -extern void ALU_defined_int(struct result *intresult) // no ACCEPT constants? +void ALU_defined_int(struct result *intresult) // no ACCEPT constants? { - if (parse_expression(intresult)) + struct expression expression; + + parse_expression(&expression); + *intresult = expression.number; + if (expression.open_parentheses) Throw_error(exception_paren_open); if ((intresult->flags & MVALUE_DEFINED) == 0) Throw_serious_error(value_not_defined()); @@ -1616,34 +1626,32 @@ extern void ALU_defined_int(struct result *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. Returns number -// of parentheses still open (either 0 or 1). +// addressing modes where internal indices have to be possible. // If the result's "exists" flag is clear (=empty expression), it throws an // error. // OPEN_PARENTHESIS: allow // UNDEFINED: allow // EMPTY: complain // FLOAT: convert to int -int ALU_liberal_int(struct result *intresult) // ACCEPT_UNDEFINED | ACCEPT_OPENPARENTHESIS +void ALU_liberal_int(struct expression *expression) // ACCEPT_UNDEFINED | ACCEPT_OPENPARENTHESIS { - int parentheses_still_open; + struct result *intresult = &expression->number; - parentheses_still_open = parse_expression(intresult); + parse_expression(expression); // make sure result is not float if (intresult->flags & MVALUE_IS_FP) { intresult->val.intval = intresult->val.fpval; intresult->flags &= ~MVALUE_IS_FP; } - if (parentheses_still_open > 1) { - parentheses_still_open = 0; + if (expression->open_parentheses > 1) { + expression->open_parentheses = 0; Throw_error(exception_paren_open); } - if ((intresult->flags & MVALUE_EXISTS) == 0) + if ((expression->number.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); - if ((intresult->flags & MVALUE_EXISTS) + if ((expression->number.flags & MVALUE_EXISTS) && ((intresult->flags & MVALUE_DEFINED) == 0)) result_is_undefined(); - return parentheses_still_open; } @@ -1657,9 +1665,13 @@ int ALU_liberal_int(struct result *intresult) // ACCEPT_UNDEFINED | ACCEPT_OPENP // FLOAT: keep void ALU_any_result(struct result *result) // ACCEPT_UNDEFINED | ACCEPT_FLOAT { - if (parse_expression(result)) + struct expression expression; + + parse_expression(&expression); + *result = expression.number; + if (expression.open_parentheses) Throw_error(exception_paren_open); - if ((result->flags & MVALUE_EXISTS) == 0) + if ((expression.number.flags & MVALUE_EXISTS) == 0) Throw_error(exception_no_value); else if ((result->flags & MVALUE_DEFINED) == 0) result_is_undefined(); diff --git a/src/alu.h b/src/alu.h index a046803..6c4c4d5 100644 --- a/src/alu.h +++ b/src/alu.h @@ -10,6 +10,24 @@ #include "config.h" +// types +/* +enum expression_type { + EXTY_EMPTY, // next char after space was comma or end-of-statement + EXTY_NUMBER, // int or float (what is returned by the current functions) + EXTY_STRING, // TODO + EXTY_REGISTER, // reserved cpu constant (register names), TODO + EXTY_LIST // TODO +}; +*/ +struct expression { + //enum expression_type type; + struct result number; + //int flags; // TODO: move EXISTS and INDIRECT here + int open_parentheses; // number of parentheses still open +}; + + // constants // TODO - move EXISTS and INDIRECT to a new "expression flags" struct! make "nothing" its own result type? @@ -38,15 +56,7 @@ extern void (*ALU_optional_notdef_handler)(const char *); // FIXME - replace all the functions below with a single one using a "flags" arg! -/* its return value would then be: -enum expression_result { - EXRE_ERROR, // error (has been reported, so skip remainder of statement) - EXRE_NOTHING, // next char after space was comma or end-of-statement - EXRE_NUMBER, // int or float (what is returned by the current functions) - EXRE_STRING, // TODO - EXRE_RESERVED, // reserved cpu constant (register names), TODO - EXRE_LIST // TODO -}; +/* its return value would then be "error"/"ok". // input flags: #define ACCEPT_EMPTY (1u << 0) // if not given, throws error #define ACCEPT_UNDEFINED (1u << 1) // if not given, undefined throws serious error @@ -67,8 +77,7 @@ extern void ALU_int_result(struct result *intresult); // if result was undefined, serious error is thrown extern void ALU_defined_int(struct result *intresult); // stores int value and flags, allowing for one '(' too many (x-indirect addr). -// returns number of additional '(' (1 or 0). -extern int ALU_liberal_int(struct result *intresult); +extern void ALU_liberal_int(struct expression *expression); // stores value and flags (result may be either int or float) extern void ALU_any_result(struct result *result); diff --git a/src/config.h b/src/config.h index 535f15e..8cfc050 100644 --- a/src/config.h +++ b/src/config.h @@ -1,5 +1,5 @@ // ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. -// Copyright (C) 1998-2016 Marco Baye +// Copyright (C) 1998-2020 Marco Baye // Have a look at "acme.c" for further info // // Configuration @@ -12,9 +12,8 @@ typedef unsigned int scope_t; typedef signed long intval_t; // at least 32 bits typedef unsigned long uintval_t; // just for logical shift right // result structure type definition with support for floating point -// future result types: EMPTY, UNDEFINED, INT, FLOAT (, STRING) -struct result { // either int or float - int flags; // expression flags +struct result { // either int or float (TODO - rename to "number"?) + int flags; // result flags (see alu.h, one if these tells ints and floats apart) union { intval_t intval; // integer value double fpval; // floating point value diff --git a/src/mnemo.c b/src/mnemo.c index 1a1853e..cf5927c 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -523,8 +523,8 @@ static int get_index(int next) // structure (using the valueparser). The addressing mode is returned. static int get_argument(struct result *result) { - int open_paren, - address_mode_bits = 0; + struct expression expression; + int address_mode_bits = 0; SKIPSPACE(); switch (GotByte) { @@ -548,13 +548,14 @@ static int get_argument(struct result *result) break; default: // liberal, to allow for "(...," - open_paren = ALU_liberal_int(result); + ALU_liberal_int(&expression); + *result = expression.number; typesystem_want_addr(result); // check for indirect addressing - if (result->flags & MVALUE_INDIRECT) + if (expression.number.flags & MVALUE_INDIRECT) address_mode_bits |= AMB_INDIRECT; // check for internal index (before closing parenthesis) - if (open_paren) { + if (expression.open_parentheses) { // in case there are still open parentheses, // read internal index address_mode_bits |= AMB_PREINDEX(get_index(FALSE));