示例#1
0
// (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;
}
示例#2
0
// Conditional assembly ("!ifdef"). Has to be re-entrant.
static enum eos_t PO_ifdef(void) {// Now GotByte = illegal char
	node_ra_t*	node;
	label_t*	label;
	zone_t		zone;
	bool		defined	= FALSE;

	if(Input_read_zone_and_keyword(&zone) == 0)	// skips spaces before
		return(SKIP_REMAINDER);
	Tree_hard_scan(&node, Label_forest, zone, FALSE);
	if(node) {
		label = (label_t*) node->body;
		// in first pass, count usage
		if(pass_count == 0)
			label->usage++;
		if(label->result.flags & MVALUE_DEFINED)
			defined = TRUE;
	}
	SKIPSPACE();
	if(GotByte == CHAR_SOB)
		parse_block_else_block(defined);
	else {
		if(defined)
			return(PARSE_REMAINDER);
		return(SKIP_REMAINDER);
	}
	return(ENSURE_EOS);
}
示例#3
0
// 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);
}
示例#4
0
文件: macro.c 项目: lhz/acme
// Read macro zone and title. Title is read to GlobalDynaBuf and then copied
// over to internal_name DynaBuf, where ARG_SEPARATOR is added.
// In user_macro_name DynaBuf, the original name is reconstructed (even with
// LOCAL_PREFIX) so a copy can be linked to the resulting macro struct.
static zone_t get_zone_and_title(void)
{
    zone_t	macro_zone;

    Input_read_zone_and_keyword(&macro_zone);	// skips spaces before
    // now GotByte = illegal character after title
    // copy macro title to private dynabuf and add separator character
    DYNABUF_CLEAR(user_macro_name);
    DYNABUF_CLEAR(internal_name);
    if (macro_zone != ZONE_GLOBAL)
        DynaBuf_append(user_macro_name, LOCAL_PREFIX);
    DynaBuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT);
    DynaBuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
    DynaBuf_append(user_macro_name, '\0');
    DynaBuf_append(internal_name, ARG_SEPARATOR);
    SKIPSPACE();	// done here once so it's not necessary at two callers
    return macro_zone;
}
示例#5
0
文件: macro.c 项目: lhz/acme
// Parse macro call ("+MACROTITLE"). Has to be re-entrant.
void Macro_parse_call(void)	// Now GotByte = dot or first char of macro name
{
    char		local_gotbyte;
    struct symbol	*symbol;
    struct section	new_section,
                *outer_section;
    struct input	new_input,
                  *outer_input;
    struct macro	*actual_macro;
    struct rwnode	*macro_node,
                 *symbol_node;
    zone_t		macro_zone,
                symbol_zone;
    int		arg_count	= 0;

    // Enter deeper nesting level
    // Quit program if recursion too deep.
    if (--macro_recursions_left < 0)
        Throw_serious_error("Too deeply nested. Recursive macro calls?");
    macro_zone = get_zone_and_title();
    // now GotByte = first non-space after title
    // internal_name = MacroTitle ARG_SEPARATOR (grows to signature)
    // Accept n>=0 comma-separated arguments before CHAR_EOS.
    // Valid argument formats are:
    // EXPRESSION (everything that does NOT start with '~'
    // ~.LOCAL_LABEL_BY_REFERENCE
    // ~GLOBAL_LABEL_BY_REFERENCE
    // now GotByte = non-space
    if (GotByte != CHAR_EOS) {	// any at all?
        do {
            // if arg table cannot take another element, enlarge
            if (argtable_size <= arg_count)
                enlarge_arg_table();
            // Decide whether call-by-reference or call-by-value
            // In both cases, GlobalDynaBuf may be used.
            if (GotByte == REFERENCE_CHAR) {
                // read call-by-reference arg
                DynaBuf_append(internal_name, ARGTYPE_NUM_REF);
                GetByte();	// skip '~' character
                Input_read_zone_and_keyword(&symbol_zone);
                // GotByte = illegal char
                arg_table[arg_count].symbol = symbol_find(symbol_zone, 0);
            } else {
                // read call-by-value arg
                DynaBuf_append(internal_name, ARGTYPE_NUM_VAL);
                ALU_any_result(&(arg_table[arg_count].result));
            }
            ++arg_count;
        } while (Input_accept_comma());
    }
    // now arg_table contains the arguments
    // now GlobalDynaBuf = unused
    // check for "unknown macro"
    // Search for macro. Do not create if not found.
    search_for_macro(&macro_node, macro_zone, FALSE);
    if (macro_node == NULL) {
        Throw_error("Macro not defined (or wrong signature).");
        Input_skip_remainder();
    } else {
        // make macro_node point to the macro struct
        actual_macro = macro_node->body;
        local_gotbyte = GotByte;	// CAUTION - ugly kluge
        // set up new input
        new_input.original_filename = actual_macro->def_filename;
        new_input.line_number = actual_macro->def_line_number;
        new_input.source_is_ram = TRUE;
        new_input.state = INPUTSTATE_NORMAL;	// FIXME - fix others!
        new_input.src.ram_ptr = actual_macro->parameter_list;
        // remember old input
        outer_input = Input_now;
        // activate new input
        Input_now = &new_input;
        // remember old section
        outer_section = Section_now;
        // start new section (with new zone)
        // FALSE = title mustn't be freed
        Section_new_zone(&new_section, "Macro", actual_macro->original_name, FALSE);
        GetByte();	// fetch first byte of parameter list
        // assign arguments
        if (GotByte != CHAR_EOS) {	// any at all?
            arg_count = 0;
            do {
                // Decide whether call-by-reference
                // or call-by-value
                // In both cases, GlobalDynaBuf may be used.
                if (GotByte == REFERENCE_CHAR) {
                    // assign call-by-reference arg
                    GetByte();	// skip '~' character
                    Input_read_zone_and_keyword(&symbol_zone);
                    if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_zone, TRUE) == FALSE)
                            && (pass_count == 0))
                        Throw_error("Macro parameter twice.");
                    symbol_node->body = arg_table[arg_count].symbol;
                } else {
                    // assign call-by-value arg
                    Input_read_zone_and_keyword(&symbol_zone);
                    symbol = symbol_find(symbol_zone, 0);
// FIXME - add a possibility to symbol_find to make it possible to find out
// whether symbol was just created. Then check for the same error message here
// as above ("Macro parameter twice.").
                    symbol->result = arg_table[arg_count].result;
                }
                ++arg_count;
            } while (Input_accept_comma());
        }
        // and now, finally, parse the actual macro body
        Input_now->state = INPUTSTATE_NORMAL;	// FIXME - fix others!
// maybe call parse_ram_block(actual_macro->def_line_number, actual_macro->body)
        Input_now->src.ram_ptr = actual_macro->body;
        Parse_until_eob_or_eof();
        if (GotByte != CHAR_EOB)
            Bug_found("IllegalBlockTerminator", GotByte);
        // end section (free title memory, if needed)
        Section_finalize(&new_section);
        // restore previous section
        Section_now = outer_section;
        // restore previous input:
        Input_now = outer_input;
        // restore old Gotbyte context
        GotByte = local_gotbyte;	// CAUTION - ugly kluge
        Input_ensure_EOS();
    }
    ++macro_recursions_left;	// leave this nesting level
}