From 5c459cad564f4f48c16d0ff48fd96a8d5162a8fe Mon Sep 17 00:00:00 2001 From: marcobaye Date: Tue, 5 May 2020 22:56:11 +0000 Subject: [PATCH] added "!while" pseudo opcode (will be enabled in next release) git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@136 4df02467-bbd4-4a76-a152-e7ce94205b78 --- src/flow.c | 45 +++++++++++++++++++++++++++++++-------------- src/flow.h | 25 +++++++++++++++---------- src/pseudoopcodes.c | 29 +++++++++++++++++++++++------ src/symbol.c | 1 + src/version.h | 2 +- 5 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/flow.c b/src/flow.c index df0796a..920896f 100644 --- a/src/flow.c +++ b/src/flow.c @@ -82,16 +82,26 @@ void flow_forloop(struct for_loop *loop) } -// try to read a condition into DynaBuf and store copy pointer in +// read condition, make copy, link to struct +static void copy_condition(struct condition *condition, char terminator) +{ + SKIPSPACE(); + DYNABUF_CLEAR(GlobalDynaBuf); + Input_until_terminator(terminator); + DynaBuf_append(GlobalDynaBuf, CHAR_EOS); // ensure terminator + condition->body = DynaBuf_get_copy(GlobalDynaBuf); +} + +// try to read a condition into DynaBuf and store pointer to copy in // given loop_condition structure. // if no condition given, NULL is written to structure. // call with GotByte = first interesting character -void flow_store_doloop_condition(struct loop_condition *condition, char terminator) +void flow_store_doloop_condition(struct condition *condition, char terminator) { // write line number condition->line = Input_now->line_number; // set defaults - condition->is_until = FALSE; + condition->invert = FALSE; condition->body = NULL; // check for empty condition if (GotByte == terminator) @@ -100,25 +110,32 @@ void flow_store_doloop_condition(struct loop_condition *condition, char terminat // seems as if there really *is* a condition, so check for until/while if (Input_read_and_lower_keyword()) { if (strcmp(GlobalDynaBuf->buffer, "while") == 0) { - //condition.is_until = FALSE; + //condition.invert = FALSE; } else if (strcmp(GlobalDynaBuf->buffer, "until") == 0) { - condition->is_until = TRUE; + condition->invert = TRUE; } else { Throw_error(exception_syntax); return; } // write given condition into buffer - SKIPSPACE(); - DYNABUF_CLEAR(GlobalDynaBuf); - Input_until_terminator(terminator); - DynaBuf_append(GlobalDynaBuf, CHAR_EOS); // ensure terminator - condition->body = DynaBuf_get_copy(GlobalDynaBuf); + copy_condition(condition, terminator); } } +// read a condition into DynaBuf and store pointer to copy in +// given loop_condition structure. +// call with GotByte = first interesting character +void flow_store_while_condition(struct condition *condition) +{ + condition->line = Input_now->line_number; + condition->invert = FALSE; + copy_condition(condition, CHAR_SOB); +} + + // check a condition expression -static int check_condition(struct loop_condition *condition) +static int check_condition(struct condition *condition) { struct number intresult; @@ -133,12 +150,12 @@ static int check_condition(struct loop_condition *condition) ALU_defined_int(&intresult); if (GotByte) Throw_serious_error(exception_syntax); - return condition->is_until ? !intresult.val.intval : !!intresult.val.intval; + return condition->invert ? !intresult.val.intval : !!intresult.val.intval; } -// back end function for "!do" pseudo opcode -void flow_doloop(struct do_loop *loop) +// back end function for "!do" and "!while" pseudo opcodes +void flow_do_while(struct do_while *loop) { struct input loop_input; struct input *outer_input; diff --git a/src/flow.h b/src/flow.h index 1fd21e7..fce3c20 100644 --- a/src/flow.h +++ b/src/flow.h @@ -29,32 +29,37 @@ struct for_loop { struct block block; }; -// structs to pass "!do" loop stuff from pseudoopcodes.c to flow.c -struct loop_condition { +// structs to pass "!do"/"!while" stuff from pseudoopcodes.c to flow.c +struct condition { int line; // original line number - boolean is_until; // so FALSE means WHILE, TRUE means UNTIL) + boolean invert; // only set for UNTIL conditions char *body; // pointer to actual expression }; -struct do_loop { - struct loop_condition head_cond; +struct do_while { + struct condition head_cond; struct block block; - struct loop_condition tail_cond; + struct condition tail_cond; }; // back end function for "!for" pseudo opcode extern void flow_forloop(struct for_loop *loop); -// try to read a condition into DynaBuf and store copy pointer in -// given loop_condition structure. +// try to read a condition into DynaBuf and store pointer to copy in +// given condition structure. // if no condition given, NULL is written to structure. // call with GotByte = first interesting character -extern void flow_store_doloop_condition(struct loop_condition *condition, char terminator); +extern void flow_store_doloop_condition(struct condition *condition, char terminator); +// read a condition into DynaBuf and store pointer to copy in +// given condition structure. +// call with GotByte = first interesting character +extern void flow_store_while_condition(struct condition *condition); // back end function for "!do" pseudo opcode -extern void flow_doloop(struct do_loop *loop); +extern void flow_do_while(struct do_while *loop); // parse a whole source code file extern void flow_parse_and_close_file(FILE *fd, const char *filename); // parse {block} [else {block}] extern void flow_parse_block_else_block(int parse_first); +// TODO - add an "else if" possibility #endif diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index b318db6..93efee9 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -937,7 +937,7 @@ static enum eos po_for(void) // now GotByte = illegal char // looping assembly ("!do"). has to be re-entrant. static enum eos po_do(void) // now GotByte = illegal char { - struct do_loop loop; + struct do_while loop; // read head condition to buffer SKIPSPACE(); @@ -954,7 +954,7 @@ static enum eos po_do(void) // now GotByte = illegal char // read tail condition to buffer flow_store_doloop_condition(&loop.tail_cond, CHAR_EOS); // must be freed! // now GotByte = CHAR_EOS - flow_doloop(&loop); + flow_do_while(&loop); // free memory free(loop.head_cond.body); free(loop.block.body); @@ -963,14 +963,31 @@ static enum eos po_do(void) // now GotByte = illegal char } -#if 0 -// looping assembly (alternative for people used to c-style loops) +// looping assembly ("!while", alternative for people used to c-style loops). has to be re-entrant. static enum eos po_while(void) // now GotByte = illegal char { -Throw_serious_error("Not yet"); // FIXME + struct do_while loop; + + // read condition to buffer + SKIPSPACE(); + flow_store_while_condition(&loop.head_cond); // must be freed! + if (GotByte != CHAR_SOB) + Throw_serious_error(exception_no_left_brace); + // remember line number of loop body, + // then read block and get copy + loop.block.start = Input_now->line_number; + // reading block changes line number! + loop.block.body = Input_skip_or_store_block(TRUE); // must be freed! + // clear tail condition + loop.tail_cond.body = NULL; + flow_do_while(&loop); + // free memory + free(loop.head_cond.body); + free(loop.block.body); + // GotByte of OuterInput would be '}' (if it would still exist) + GetByte(); // fetch next byte return ENSURE_EOS; } -#endif // macro definition ("!macro"). diff --git a/src/symbol.c b/src/symbol.c index fd3ca99..98a7689 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -180,6 +180,7 @@ void symbol_set_label(scope_t scope, int stat_flags, int force_bit, int change_a if ((stat_flags & SF_FOUND_BLANK) && config.warn_on_indented_labels) Throw_first_pass_warning("Label name not in leftmost column."); vcpu_read_pc(&pc); + // FIXME - if undefined, check pass.complain_about_undefined and maybe throw "value not defined"! result.flags = pc.flags & NUMBER_IS_DEFINED; result.val.intval = pc.val.intval; result.addr_refs = pc.addr_refs; diff --git a/src/version.h b/src/version.h index 7ee6eeb..19f12f5 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.96.5" // update before release FIXME #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "2 May" // update before release FIXME +#define CHANGE_DATE "6 May" // update before release FIXME #define CHANGE_YEAR "2020" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME