mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-02-19 09:31:42 +00:00
finished ELSE IF functionality. currently needs "--test", will be enabled in next release.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@156 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
16fb63deda
commit
dac11ba8c7
@ -839,25 +839,49 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
}
|
||||
|
||||
|
||||
/* TODO - new if/ifdef/ifndef/else function, to be able to do ELSE IF
|
||||
static boolean check_ifdef_condition(void)
|
||||
{
|
||||
scope_t scope;
|
||||
struct rwnode *node;
|
||||
struct symbol *symbol;
|
||||
|
||||
// read symbol name
|
||||
if (Input_read_scope_and_keyword(&scope) == 0) // skips spaces before
|
||||
return FALSE; // there was an error, it has been reported, so return value is more or less meaningless anway
|
||||
|
||||
// look for it
|
||||
Tree_hard_scan(&node, symbols_forest, scope, FALSE);
|
||||
if (!node)
|
||||
return FALSE; // not found -> no, not defined
|
||||
|
||||
symbol = (struct symbol *) node->body;
|
||||
// in first pass, count usage
|
||||
if (FIRST_PASS)
|
||||
symbol->usage++;
|
||||
return !!(symbol->result.flags & NUMBER_IS_DEFINED);
|
||||
}
|
||||
// new if/ifdef/ifndef/else function, to be able to do ELSE IF
|
||||
enum ifmode {
|
||||
IFMODE_IF, // parse expression, then block
|
||||
IFMODE_IFDEF, // check symbol, then parse block or line
|
||||
IFMODE_IFNDEF, // check symbol, then parse block or line
|
||||
IFMODE_ELSE, // unconditional block
|
||||
IFMODE_END // no more blocks
|
||||
IFMODE_ELSE // unconditional last block
|
||||
};
|
||||
// new function for if/ifdef/ifndef/else. has to be re-entrant.
|
||||
static enum eos ifelse(enum ifmode mode)
|
||||
{
|
||||
boolean nothing_done = TRUE; // once a block gets executed, this becomes FALSE, so all others will be skipped even if condition met
|
||||
boolean condition_met; // condition result for next block
|
||||
boolean nothing_done = TRUE; // once a block gets executed, this becomes FALSE, so all others will be skipped even if condition met
|
||||
boolean condition_met; // condition result for next block
|
||||
struct number ifresult;
|
||||
|
||||
do {
|
||||
for (;;) {
|
||||
// check condition according to mode
|
||||
switch (mode) {
|
||||
case IFMODE_IF:
|
||||
condition_met = check_if_condition();
|
||||
ALU_defined_int(&ifresult);
|
||||
condition_met = !!ifresult.val.intval;
|
||||
if (GotByte != CHAR_SOB)
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
break;
|
||||
case IFMODE_IFDEF:
|
||||
condition_met = check_ifdef_condition();
|
||||
@ -869,38 +893,84 @@ static enum eos ifelse(enum ifmode mode)
|
||||
condition_met = TRUE;
|
||||
break;
|
||||
default:
|
||||
Bug_found("Illegal ifmode");
|
||||
break;
|
||||
Bug_found("IllegalIfMode", mode); // FIXME - put in docs!
|
||||
condition_met = TRUE; // inhibit compiler warning ;)
|
||||
}
|
||||
SKIPSPACE();
|
||||
// execute this block?
|
||||
if (condition_met && nothing_done) {
|
||||
nothing_done = FALSE; // all further ones will be skipped
|
||||
if (check_for_left_brace()) {
|
||||
block_execute();
|
||||
nothing_done = FALSE; // all further ones will be skipped, even if conditions meet
|
||||
if (GotByte == CHAR_SOB) {
|
||||
Parse_until_eob_or_eof(); // parse block
|
||||
// if block isn't correctly terminated, complain and exit
|
||||
if (GotByte != CHAR_EOB)
|
||||
Throw_serious_error(exception_no_right_brace);
|
||||
} else {
|
||||
return PARSE_REMAINDER;
|
||||
return PARSE_REMAINDER; // parse line (only for ifdef/ifndef)
|
||||
}
|
||||
} else {
|
||||
if (check_for_left_brace()) {
|
||||
if (GotByte == CHAR_SOB) {
|
||||
Input_skip_or_store_block(FALSE); // skip block
|
||||
} else {
|
||||
return SKIP_REMAINDER;
|
||||
return SKIP_REMAINDER; // skip line (only for ifdef/ifndef)
|
||||
}
|
||||
}
|
||||
// any more?
|
||||
mode = check_for_else_and_next_keyword();
|
||||
} while (mode != IFMODE_END);
|
||||
return ENSURE_EOS;
|
||||
// now GotByte = '}'
|
||||
NEXTANDSKIPSPACE();
|
||||
// after ELSE {} it's all over. it must be.
|
||||
if (mode == IFMODE_ELSE) {
|
||||
// we could just return ENSURE_EOS, but checking here allows for better error message
|
||||
if (GotByte != CHAR_EOS)
|
||||
Throw_error("Expected end-of-statement after ELSE block"); // FIXME - put in docs!
|
||||
return SKIP_REMAINDER; // normal exit after ELSE {...}
|
||||
}
|
||||
|
||||
// anything more?
|
||||
if (GotByte == CHAR_EOS)
|
||||
return AT_EOS_ANYWAY; // normal exit if there is no ELSE {...} block
|
||||
|
||||
// read keyword (expected to be "else")
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER; // "missing string error" -> ignore rest of line
|
||||
|
||||
// make sure it's "else"
|
||||
if (strcmp(GlobalDynaBuf->buffer, "else")) {
|
||||
Throw_error("Expected ELSE or end-of-statement"); // FIXME - put in docs!
|
||||
return SKIP_REMAINDER; // an error has been reported, so ignore rest of line
|
||||
}
|
||||
// anything more?
|
||||
SKIPSPACE();
|
||||
if (GotByte == CHAR_SOB) {
|
||||
// ELSE {...} -> one last round
|
||||
mode = IFMODE_ELSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// read keyword (expected to be if/ifdef/ifndef)
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER; // "missing string error" -> ignore rest of line
|
||||
|
||||
// which one is it?
|
||||
if (strcmp(GlobalDynaBuf->buffer, "if") == 0) {
|
||||
mode = IFMODE_IF;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "ifdef") == 0) {
|
||||
mode = IFMODE_IFDEF;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "ifndef") == 0) {
|
||||
mode = IFMODE_IFNDEF;
|
||||
} else {
|
||||
Throw_error("After ELSE, expected block or IF/IFDEF/IFNDEF"); // FIXME - put in docs!
|
||||
return SKIP_REMAINDER; // an error has been reported, so ignore rest of line
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// conditional assembly ("!if"). has to be re-entrant.
|
||||
static enum eos po_if(void) // now GotByte = illegal char
|
||||
{
|
||||
struct number cond_result;
|
||||
|
||||
// if (config.test_new_features)
|
||||
// return ifelse(IFMODE_IF);
|
||||
if (config.test_new_features)
|
||||
return ifelse(IFMODE_IF);
|
||||
|
||||
ALU_defined_int(&cond_result);
|
||||
if (GotByte != CHAR_SOB)
|
||||
@ -946,8 +1016,8 @@ static enum eos ifdef_ifndef(boolean invert) // now GotByte = illegal char
|
||||
// conditional assembly ("!ifdef"). has to be re-entrant.
|
||||
static enum eos po_ifdef(void) // now GotByte = illegal char
|
||||
{
|
||||
// if (config.test_new_features)
|
||||
// return ifelse(IFMODE_IFDEF);
|
||||
if (config.test_new_features)
|
||||
return ifelse(IFMODE_IFDEF);
|
||||
|
||||
return ifdef_ifndef(FALSE);
|
||||
}
|
||||
@ -956,8 +1026,8 @@ static enum eos po_ifdef(void) // now GotByte = illegal char
|
||||
// conditional assembly ("!ifndef"). has to be re-entrant.
|
||||
static enum eos po_ifndef(void) // now GotByte = illegal char
|
||||
{
|
||||
// if (config.test_new_features)
|
||||
// return ifelse(IFMODE_IFNDEF);
|
||||
if (config.test_new_features)
|
||||
return ifelse(IFMODE_IFNDEF);
|
||||
|
||||
return ifdef_ifndef(TRUE);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ extern int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf
|
||||
// Search for a "RAM tree" item. Save pointer to found tree item in given
|
||||
// location. If no matching item is found, check the "create" flag: If set,
|
||||
// create new tree item, link to tree, fill with data and store its pointer.
|
||||
// If "create" is zero, store NULL. Returns whether item was created.
|
||||
// If "create" is FALSE, store NULL. Returns whether item was created.
|
||||
extern int Tree_hard_scan(struct rwnode **result, struct rwnode **forest, int id_number, boolean create);
|
||||
// Calls given function for each node of each tree of given forest.
|
||||
extern void Tree_dump_forest(struct rwnode **, int, void (*)(struct rwnode *, FILE *), FILE *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user