mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-08-08 20:25:02 +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:
@@ -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 {
|
enum ifmode {
|
||||||
IFMODE_IF, // parse expression, then block
|
IFMODE_IF, // parse expression, then block
|
||||||
IFMODE_IFDEF, // check symbol, then parse block or line
|
IFMODE_IFDEF, // check symbol, then parse block or line
|
||||||
IFMODE_IFNDEF, // check symbol, then parse block or line
|
IFMODE_IFNDEF, // check symbol, then parse block or line
|
||||||
IFMODE_ELSE, // unconditional block
|
IFMODE_ELSE // unconditional last block
|
||||||
IFMODE_END // no more blocks
|
|
||||||
};
|
};
|
||||||
// new function for if/ifdef/ifndef/else. has to be re-entrant.
|
// new function for if/ifdef/ifndef/else. has to be re-entrant.
|
||||||
static enum eos ifelse(enum ifmode mode)
|
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 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 condition_met; // condition result for next block
|
||||||
|
struct number ifresult;
|
||||||
|
|
||||||
do {
|
for (;;) {
|
||||||
// check condition according to mode
|
// check condition according to mode
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case IFMODE_IF:
|
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;
|
break;
|
||||||
case IFMODE_IFDEF:
|
case IFMODE_IFDEF:
|
||||||
condition_met = check_ifdef_condition();
|
condition_met = check_ifdef_condition();
|
||||||
@@ -869,38 +893,84 @@ static enum eos ifelse(enum ifmode mode)
|
|||||||
condition_met = TRUE;
|
condition_met = TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Bug_found("Illegal ifmode");
|
Bug_found("IllegalIfMode", mode); // FIXME - put in docs!
|
||||||
break;
|
condition_met = TRUE; // inhibit compiler warning ;)
|
||||||
}
|
}
|
||||||
|
SKIPSPACE();
|
||||||
// execute this block?
|
// execute this block?
|
||||||
if (condition_met && nothing_done) {
|
if (condition_met && nothing_done) {
|
||||||
nothing_done = FALSE; // all further ones will be skipped
|
nothing_done = FALSE; // all further ones will be skipped, even if conditions meet
|
||||||
if (check_for_left_brace()) {
|
if (GotByte == CHAR_SOB) {
|
||||||
block_execute();
|
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 {
|
} else {
|
||||||
return PARSE_REMAINDER;
|
return PARSE_REMAINDER; // parse line (only for ifdef/ifndef)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (check_for_left_brace()) {
|
if (GotByte == CHAR_SOB) {
|
||||||
Input_skip_or_store_block(FALSE); // skip block
|
Input_skip_or_store_block(FALSE); // skip block
|
||||||
} else {
|
} else {
|
||||||
return SKIP_REMAINDER;
|
return SKIP_REMAINDER; // skip line (only for ifdef/ifndef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// any more?
|
// now GotByte = '}'
|
||||||
mode = check_for_else_and_next_keyword();
|
NEXTANDSKIPSPACE();
|
||||||
} while (mode != IFMODE_END);
|
// after ELSE {} it's all over. it must be.
|
||||||
return ENSURE_EOS;
|
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.
|
// conditional assembly ("!if"). has to be re-entrant.
|
||||||
static enum eos po_if(void) // now GotByte = illegal char
|
static enum eos po_if(void) // now GotByte = illegal char
|
||||||
{
|
{
|
||||||
struct number cond_result;
|
struct number cond_result;
|
||||||
|
|
||||||
// if (config.test_new_features)
|
if (config.test_new_features)
|
||||||
// return ifelse(IFMODE_IF);
|
return ifelse(IFMODE_IF);
|
||||||
|
|
||||||
ALU_defined_int(&cond_result);
|
ALU_defined_int(&cond_result);
|
||||||
if (GotByte != CHAR_SOB)
|
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.
|
// conditional assembly ("!ifdef"). has to be re-entrant.
|
||||||
static enum eos po_ifdef(void) // now GotByte = illegal char
|
static enum eos po_ifdef(void) // now GotByte = illegal char
|
||||||
{
|
{
|
||||||
// if (config.test_new_features)
|
if (config.test_new_features)
|
||||||
// return ifelse(IFMODE_IFDEF);
|
return ifelse(IFMODE_IFDEF);
|
||||||
|
|
||||||
return ifdef_ifndef(FALSE);
|
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.
|
// conditional assembly ("!ifndef"). has to be re-entrant.
|
||||||
static enum eos po_ifndef(void) // now GotByte = illegal char
|
static enum eos po_ifndef(void) // now GotByte = illegal char
|
||||||
{
|
{
|
||||||
// if (config.test_new_features)
|
if (config.test_new_features)
|
||||||
// return ifelse(IFMODE_IFNDEF);
|
return ifelse(IFMODE_IFNDEF);
|
||||||
|
|
||||||
return ifdef_ifndef(TRUE);
|
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
|
// 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,
|
// 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.
|
// 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);
|
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.
|
// 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 *);
|
extern void Tree_dump_forest(struct rwnode **, int, void (*)(struct rwnode *, FILE *), FILE *);
|
||||||
|
Reference in New Issue
Block a user