// (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; }
// 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); }
// 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); }
Token *Label_expression(Function *func, Token *tk) { Label *label = Label_find(func, tk); if(!label) { // forward label expression, create but not realized label = Label_create_and_add(func, tk, 0); } else { if(label->realized) { // backward label expression tk->value = (unsigned long)label->ref; } else { // forward label expression that's being used again // do nothing with it, Call_operation will handle the gore } } return tk; }
// 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); } }
// fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it // references the *next* anonymous forward label definition. The tricky bit is, // each name length would need its own counter. But hey, ACME's real quick in // finding labels, so I'll just abuse the label system to store those counters. struct label_t *Label_fix_forward_name(void) { struct label_t *counter_label; unsigned long number; // terminate name, find "counter" label and read value DynaBuf_append(GlobalDynaBuf, '\0'); counter_label = Label_find(Section_now->zone, 0); // make sure it gets reset to zero in each new pass if (counter_label->pass != pass_count) { counter_label->pass = pass_count; counter_label->result.val.intval = 0; } number = (unsigned long) counter_label->result.val.intval; // now append to the name to make it unique GlobalDynaBuf->size--; // forget terminator, we want to append do { DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15)); number >>= 4; } while (number); DynaBuf_append(GlobalDynaBuf, '\0'); return counter_label; }