Esempio n. 1
0
// insert byte until PC fits condition
static enum eos_t PO_align(void) {
	intval_t	and,
			equal,
			fill,
			test	= CPU_pc.intval;

	// make sure PC is defined.
	if ((CPU_pc.flags & MVALUE_DEFINED) == 0) {
		Throw_error(exception_pc_undefined);
		CPU_pc.flags |= MVALUE_DEFINED;	// do not complain again
		return SKIP_REMAINDER;
	}

	and = ALU_defined_int();
	if (!Input_accept_comma())
		Throw_error(exception_syntax);
	equal = ALU_defined_int();
	if (Input_accept_comma())
		fill = ALU_any_int();
	else
		fill = CPU_now->default_align_value;
	while ((test++ & and) != equal)
		Output_8b(fill);
	return ENSURE_EOS;
}
Esempio n. 2
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);
}
Esempio n. 3
0
File: macro.c Progetto: lhz/acme
// Check for comma. If there, append to GlobalDynaBuf.
static int pipe_comma(void)
{
    int	result;

    result = Input_accept_comma();
    if (result)
        DYNABUF_APPEND(GlobalDynaBuf, ',');
    return result;
}
Esempio n. 4
0
// Reserve space by sending bytes of given value ("!fi" / "!fill" pseudo opcode)
static enum eos_t PO_fill(void) {
	intval_t	fill	= FILLVALUE_FILL,
			size	= ALU_defined_int();

	if(Input_accept_comma())
		fill = ALU_any_int();
	while(size--)
		Output_8b(fill);
	return(ENSURE_EOS);
}
Esempio n. 5
0
// show user-defined message
static enum eos_t throw_string(const char prefix[], void (*fn)(const char*)) {
	result_t	result;

	DYNABUF_CLEAR(user_message);
	DynaBuf_add_string(user_message, prefix);
	do {
		if(GotByte == '"') {
			// parse string
			GetQuotedByte();	// read initial character
			// send characters until closing quote is reached
			while(GotByte && (GotByte != '"')) {
				DYNABUF_APPEND(user_message, GotByte);
				GetQuotedByte();
			}
			if(GotByte == CHAR_EOS)
				return(AT_EOS_ANYWAY);
			// after closing quote, proceed with next char
			GetByte();
		} else {
			// parse value
			ALU_any_result(&result);
			if(result.flags & MVALUE_IS_FP) {
				// floating point
				if(result.flags & MVALUE_DEFINED)
					DynaBuf_add_double(
						user_message,
						result.val.fpval);
				else
					DynaBuf_add_string(
						user_message,
						"<UNDEFINED FLOAT>");
			} else {
				// integer
				if(result.flags & MVALUE_DEFINED)
					DynaBuf_add_signed_long(
						user_message,
						result.val.intval);
				else
					DynaBuf_add_string(
						user_message,
						"<UNDEFINED INT>");
			}
		}
	} while(Input_accept_comma());
	DynaBuf_append(user_message, '\0');
	fn(user_message->buffer);
	return(ENSURE_EOS);
}
Esempio n. 6
0
// Include binary file
static enum eos_t PO_binary(void) {
	FILE*		fd;
	int		byte;
	intval_t	size	= -1,	// means "not given" => "until EOF"
			skip	= 0,
			interleave = 1;
	int skipByte;

	// if file name is missing, don't bother continuing
	if(Input_read_filename(TRUE))
		return(SKIP_REMAINDER);
	// try to open file
	fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY);
	if(fd == NULL) {
		Throw_error(exception_cannot_open_input_file);
		return(SKIP_REMAINDER);
	}
	// read optional arguments
	if(Input_accept_comma()) {
		if(ALU_optional_defined_int(&size)
		&& (size <0))
			Throw_serious_error("Negative size argument.");
		if(Input_accept_comma())
		{
			ALU_optional_defined_int(&skip);// read skip

			if(Input_accept_comma())
			{
				ALU_optional_defined_int(&interleave);// read interleave
				if (interleave <= 1)
				{
					Throw_serious_error("Negative size argument.");
				}
			}
		}
	}
	skipByte = interleave;
	// check whether including is a waste of time
	if((size >= 0) && (pass_undefined_count || pass_real_errors))
		Output_fake(size);	// really including is useless anyway
	else {
		// really insert file
		fseek(fd, skip, SEEK_SET);	// set read pointer
		// if "size" non-negative, read "size" bytes.
		// otherwise, read until EOF.
		while(size != 0) {
			byte = getc(fd);
			if(byte == EOF)
				break;
			skipByte++;
			if (skipByte >= interleave)
			{
				Output_byte(byte);
				size--;
				skipByte = 0;
			}
		}
		// if more should have been read, warn and add padding
		if(size > 0) {
			Throw_warning("Padding with zeroes.");
			do
				Output_byte(0);
			while(--size);
		}
	}
	fclose(fd);
	// if verbose, produce some output
	if((pass_count == 0) && (Process_verbosity > 1))
		printf("Loaded %d ($%x) bytes from file offset %ld ($%lx).\n",
		CPU_2add, CPU_2add, skip, skip);
	return(ENSURE_EOS);
}
Esempio n. 7
0
// Helper function for !8, !16, !24 and !32 pseudo opcodes
static enum eos_t output_objects(void (*fn)(intval_t)) {
	do
		fn(ALU_any_int());
	while(Input_accept_comma());
	return(ENSURE_EOS);
}
Esempio n. 8
0
File: macro.c Progetto: 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
}