// Looping assembly ("!for"). Has to be re-entrant. static enum eos_t PO_for(void) {// Now GotByte = illegal char input_t loop_input, *outer_input; result_t loop_counter; intval_t maximum; char* loop_body;// pointer to loop's body block label_t* label; zone_t zone; int force_bit, loop_start;// line number of "!for" pseudo opcode if(Input_read_zone_and_keyword(&zone) == 0) // skips spaces before return(SKIP_REMAINDER); // Now GotByte = illegal char force_bit = Input_get_force_bit(); // skips spaces after label = Label_find(zone, force_bit); if(Input_accept_comma() == FALSE) { Throw_error(exception_syntax); return(SKIP_REMAINDER); } maximum = ALU_defined_int(); if(maximum < 0) Throw_serious_error("Loop count is negative."); if(GotByte != CHAR_SOB) Throw_serious_error(exception_no_left_brace); // remember line number of loop pseudo opcode loop_start = Input_now->line_number; // read loop body into DynaBuf and get copy loop_body = Input_skip_or_store_block(TRUE); // changes line number! // switching input makes us lose GotByte. But we know it's '}' anyway! // set up new input loop_input = *Input_now;// copy current input structure into new loop_input.source_is_ram = TRUE; // set new byte source // remember old input outer_input = Input_now; // activate new input // (not yet useable; pointer and line number are still missing) Input_now = &loop_input; // init counter loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS; loop_counter.val.intval = 0; // if count == 0, skip loop if(maximum) { do { loop_counter.val.intval++;// increment counter Label_set_value(label, &loop_counter, TRUE); parse_ram_block(loop_start, loop_body); } while(loop_counter.val.intval < maximum); } else Label_set_value(label, &loop_counter, TRUE); // Free memory free(loop_body); // restore previous input: Input_now = outer_input; // GotByte of OuterInput would be '}' (if it would still exist) GetByte(); // fetch next byte return(ENSURE_EOS); }
// (Re)set label static enum eos_t PO_set(void) // Now GotByte = illegal char { struct result_t result; int force_bit; struct label_t *label; zone_t zone; if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before // Now GotByte = illegal char return SKIP_REMAINDER; force_bit = Input_get_force_bit(); // skips spaces after label = Label_find(zone, force_bit); if (GotByte != '=') { Throw_error(exception_syntax); return SKIP_REMAINDER; } // label = parsed value GetByte(); // proceed with next char ALU_any_result(&result); // clear label's force bits and set new ones label->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE); if (force_bit) { label->result.flags |= force_bit; result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE); } Label_set_value(label, &result, TRUE); return ENSURE_EOS; }
// set global label to value, no questions asked (for "-D" switch) // Name must be held in GlobalDynaBuf. void Label_define(intval_t value) { struct result_t result; struct label_t *label; result.flags = MVALUE_GIVEN; result.val.intval = value; label = Label_find(ZONE_GLOBAL, 0); Label_set_value(label, &result, TRUE); }
// Parse implicit label definition (can be either global or local). // GlobalDynaBuf holds the label name. void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change) { struct result_t result; struct label_t *label; label = Label_find(zone, force_bit); // implicit label definition (label) if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels) Throw_first_pass_warning("Implicit label definition not in leftmost column."); result.flags = CPU_pc.flags & MVALUE_DEFINED; result.val.intval = CPU_pc.intval; Label_set_value(label, &result, change); }
// parse label definition (can be either global or local). // GlobalDynaBuf holds the label name. void Label_parse_definition(zone_t zone, int stat_flags) { struct result_t result; struct label_t *label; int force_bit = Input_get_force_bit(); // skips spaces after // FIXME - force bit is allowed for implicit label defs?! if (GotByte == '=') { // explicit label definition (label = <something>) label = Label_find(zone, force_bit); // label = parsed value GetByte(); // skip '=' ALU_any_result(&result); Label_set_value(label, &result, FALSE); Input_ensure_EOS(); } else { Label_implicit_definition(zone, stat_flags, force_bit, FALSE); } }