mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-04-12 01:36:59 +00:00
another one of those "great rename" cleanup commits, no change in functionality
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@331 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
e90cfc90b2
commit
2092961bb8
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Platform specific stuff (in this case, for RISC OS)
|
||||
@ -90,14 +90,14 @@ void RISCOS_throwback(const char *message, int type)
|
||||
regs.r[0] = 0;
|
||||
regs.r[1] = 0;
|
||||
// regs.r[2] = (int) toplevel_source;
|
||||
regs.r[2] = (int) Input_now->original_filename;
|
||||
regs.r[2] = (int) input_now->original_filename;
|
||||
_kernel_swi(XDDEUTILS_THROWBACKSEND, ®s, ®s);
|
||||
}
|
||||
// send throwback message
|
||||
regs.r[0] = 1;
|
||||
regs.r[1] = 0;
|
||||
regs.r[2] = (int) Input_now->original_filename;
|
||||
regs.r[3] = Input_now->line_number;
|
||||
regs.r[2] = (int) input_now->original_filename;
|
||||
regs.r[3] = input_now->line_number;
|
||||
regs.r[4] = type;
|
||||
regs.r[5] = (int) message;
|
||||
_kernel_swi(XDDEUTILS_THROWBACKSEND, ®s, ®s);
|
||||
|
@ -236,7 +236,7 @@ static void save_output_file(void)
|
||||
output_filename);
|
||||
return;
|
||||
}
|
||||
Output_save_file(fd);
|
||||
output_save_file(fd);
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ static void perform_pass(void)
|
||||
|
||||
++pass.number;
|
||||
// call modules' "pass init" functions
|
||||
Output_passinit(); // disable output, PC undefined
|
||||
output_passinit(); // disable output, PC undefined
|
||||
cputype_passinit(default_cpu); // set default cpu type
|
||||
// if start address was given on command line, use it:
|
||||
if (start_address != ILLEGAL_START_ADDRESS)
|
||||
@ -271,7 +271,7 @@ static void perform_pass(void)
|
||||
++pass.error_count;
|
||||
}
|
||||
}
|
||||
Output_end_segment();
|
||||
output_end_segment();
|
||||
/* TODO:
|
||||
if --save-start is given, parse arg string
|
||||
if --save-limit is given, parse arg string
|
||||
@ -648,7 +648,7 @@ int main(int argc, const char *argv[])
|
||||
// generate list of files to process
|
||||
cliargs_get_rest(&toplevel_src_count, &toplevel_sources, "No top level sources given");
|
||||
// init output buffer
|
||||
Output_init(fill_value, config.test_new_features);
|
||||
output_createbuffer(fill_value, /* use_large_buf= */ config.test_new_features);
|
||||
if (do_actual_work())
|
||||
save_output_file();
|
||||
return ACME_finalize(EXIT_SUCCESS); // dump labels, if wanted
|
||||
|
68
src/alu.c
68
src/alu.c
@ -326,7 +326,7 @@ static void is_not_defined(struct symbol *optional_symbol, char *name, size_t le
|
||||
|
||||
dynabuf_add_string(errormsg_dyna_buf, name);
|
||||
if (errormsg_dyna_buf->size < length) {
|
||||
Bug_found("IllegalSymbolNameLength", errormsg_dyna_buf->size - length);
|
||||
BUG("IllegalSymbolNameLength", errormsg_dyna_buf->size - length);
|
||||
} else {
|
||||
errormsg_dyna_buf->size = length;
|
||||
}
|
||||
@ -357,7 +357,7 @@ static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unp
|
||||
symbol->object.u.number.flags = NUMBER_EVER_UNDEFINED; // reading undefined taints it
|
||||
symbol->object.u.number.addr_refs = 0;
|
||||
} else {
|
||||
// FIXME - add sanity check for UNDEFINED where EVER_UNDEFINED is false -> Bug_found()!
|
||||
// FIXME - add sanity check for UNDEFINED where EVER_UNDEFINED is false -> BUG()!
|
||||
// (because the only way to have UNDEFINED is the block above, and EVER_UNDEFINED taints everything it touches)
|
||||
}
|
||||
// first push on arg stack, so we have a local copy we can "unpseudo"
|
||||
@ -413,13 +413,13 @@ static void parse_quoted(char closing_quote)
|
||||
intval_t value;
|
||||
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
if (Input_quoted_to_dynabuf(closing_quote))
|
||||
if (input_quoted_to_dynabuf(closing_quote))
|
||||
goto fail; // unterminated or escaping error
|
||||
|
||||
// eat closing quote
|
||||
GetByte();
|
||||
// now convert to unescaped version
|
||||
if (Input_unescape_dynabuf(0))
|
||||
if (input_unescape_dynabuf(0))
|
||||
goto fail; // escaping error
|
||||
|
||||
// without backslash escaping, both ' and " are used for single
|
||||
@ -647,7 +647,7 @@ static void parse_function_call(void)
|
||||
// make lower case version of name in local dynamic buffer
|
||||
dynabuf_to_lower(function_dyna_buf, GlobalDynaBuf);
|
||||
// search for tree item
|
||||
if (Tree_easy_scan(function_tree, &node_body, function_dyna_buf)) {
|
||||
if (tree_easy_scan(function_tree, &node_body, function_dyna_buf)) {
|
||||
PUSH_OP((struct op *) node_body);
|
||||
} else {
|
||||
Throw_error("Unknown function.");
|
||||
@ -685,7 +685,7 @@ static void list_append_list(struct listitem *selfhead, struct listitem *otherhe
|
||||
struct listitem *item;
|
||||
|
||||
if (selfhead == otherhead)
|
||||
Bug_found("ExtendingListWithItself", 0);
|
||||
BUG("ExtendingListWithItself", 0);
|
||||
item = otherhead->next;
|
||||
while (item != otherhead) {
|
||||
list_append_object(selfhead, &item->u.payload);
|
||||
@ -717,7 +717,7 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&'
|
||||
parse_program_counter(unpseudo_count);
|
||||
} else if (BYTE_STARTS_KEYWORD(GotByte) || (GotByte == LOCAL_PREFIX) || (GotByte == CHEAP_PREFIX)) {
|
||||
// symbol
|
||||
if (Input_read_scope_and_symbol_name(&scope)) // now GotByte = illegal char
|
||||
if (input_read_scope_and_symbol_name(&scope)) // now GotByte = illegal char
|
||||
return 1; // error (no string given)
|
||||
|
||||
if ((GotByte == '?') && symbol_fix_dynamic_name())
|
||||
@ -802,7 +802,7 @@ static void handle_special_operator(struct expression *expression, enum op_id pr
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalOperatorId", previous);
|
||||
BUG("IllegalOperatorId", previous);
|
||||
}
|
||||
}
|
||||
// put dyadic operator on stack and try to reduce stacks by performing
|
||||
@ -835,7 +835,7 @@ static void push_dyadic_and_check(struct expression *expression, struct op *op)
|
||||
case OPGROUP_MONADIC:
|
||||
// stacks: ... ... previous op(monadic) newest arg newest op(dyadic)
|
||||
if (arg_sp < 1)
|
||||
Bug_found("ArgStackEmpty", arg_sp);
|
||||
BUG("ArgStackEmpty", arg_sp);
|
||||
NEWEST_ARGUMENT.type->monadic_op(&NEWEST_ARGUMENT, PREVIOUS_OPERATOR);
|
||||
expression->is_parenthesized = FALSE; // operation was something other than parentheses
|
||||
// now remove previous operator by overwriting with newest one...
|
||||
@ -845,7 +845,7 @@ static void push_dyadic_and_check(struct expression *expression, struct op *op)
|
||||
case OPGROUP_DYADIC:
|
||||
// stacks: previous arg previous op(dyadic) newest arg newest op(dyadic)
|
||||
if (arg_sp < 2)
|
||||
Bug_found("NotEnoughArgs", arg_sp);
|
||||
BUG("NotEnoughArgs", arg_sp);
|
||||
PREVIOUS_ARGUMENT.type->dyadic_op(&PREVIOUS_ARGUMENT, PREVIOUS_OPERATOR, &NEWEST_ARGUMENT);
|
||||
expression->is_parenthesized = FALSE; // operation was something other than parentheses
|
||||
// now remove previous operator by overwriting with newest one...
|
||||
@ -856,12 +856,12 @@ static void push_dyadic_and_check(struct expression *expression, struct op *op)
|
||||
case OPGROUP_SPECIAL:
|
||||
// stacks: ... ... previous op(special) newest arg newest op(dyadic)
|
||||
if (NEWEST_OPERATOR->id != OPID_TERMINATOR)
|
||||
Bug_found("StrangeOperator", NEWEST_OPERATOR->id);
|
||||
BUG("StrangeOperator", NEWEST_OPERATOR->id);
|
||||
handle_special_operator(expression, PREVIOUS_OPERATOR->id);
|
||||
// the function above fixes both stacks and "is_parenthesized"!
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalOperatorGroup", PREVIOUS_OPERATOR->group);
|
||||
BUG("IllegalOperatorGroup", PREVIOUS_OPERATOR->group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -986,7 +986,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
|
||||
}
|
||||
|
||||
// here we need to put '.' into GlobalDynaBuf even though we have already skipped it:
|
||||
if (Input_read_scope_and_symbol_name_KLUGED(&scope) == 0) { // now GotByte = illegal char
|
||||
if (input_read_scope_and_symbol_name_KLUGED(&scope) == 0) { // now GotByte = illegal char
|
||||
if ((GotByte == '?') && symbol_fix_dynamic_name()) {
|
||||
alu_state = STATE_ERROR;
|
||||
break;//goto done;
|
||||
@ -1000,7 +1000,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
|
||||
break;//goto done;
|
||||
case CHEAP_PREFIX: // cheap local symbol
|
||||
//printf("looking in cheap scope %d\n", section_now->cheap_scope);
|
||||
if (Input_read_scope_and_symbol_name(&scope) == 0) { // now GotByte = illegal char
|
||||
if (input_read_scope_and_symbol_name(&scope) == 0) { // now GotByte = illegal char
|
||||
if ((GotByte == '?') && symbol_fix_dynamic_name()) {
|
||||
alu_state = STATE_ERROR;
|
||||
break;//goto done;
|
||||
@ -1024,7 +1024,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
|
||||
register int length;
|
||||
|
||||
// Read global label (or "NOT")
|
||||
length = Input_read_keyword();
|
||||
length = input_read_keyword();
|
||||
// Now GotByte = illegal char
|
||||
// Check for NOT. Okay, it's hardcoded,
|
||||
// but so what? Sue me...
|
||||
@ -1209,10 +1209,10 @@ static void expect_dyadic_operator(struct expression *expression)
|
||||
default:
|
||||
// check string versions of operators
|
||||
if (BYTE_STARTS_KEYWORD(GotByte)) {
|
||||
Input_read_and_lower_keyword();
|
||||
input_read_and_lower_keyword();
|
||||
// Now GotByte = illegal char
|
||||
// search for tree item
|
||||
if (Tree_easy_scan(op_tree, &node_body, GlobalDynaBuf)) {
|
||||
if (tree_easy_scan(op_tree, &node_body, GlobalDynaBuf)) {
|
||||
op = node_body;
|
||||
goto push_dyadic_op;
|
||||
}
|
||||
@ -1227,7 +1227,7 @@ static void expect_dyadic_operator(struct expression *expression)
|
||||
}
|
||||
}
|
||||
//end:
|
||||
return; // TODO - change the two points that go here and add a Bug_found() instead
|
||||
return; // TODO - change the two points that go here and add a BUG() instead
|
||||
|
||||
// shared endings
|
||||
get_byte_and_push_dyadic:
|
||||
@ -1242,10 +1242,10 @@ static void unsupported_operation(const struct object *optional, const struct op
|
||||
{
|
||||
if (optional) {
|
||||
if (op->group != OPGROUP_DYADIC)
|
||||
Bug_found("OperatorIsNotDyadic", op->id);
|
||||
BUG("OperatorIsNotDyadic", op->id);
|
||||
} else {
|
||||
if (op->group != OPGROUP_MONADIC)
|
||||
Bug_found("OperatorIsNotMonadic", op->id);
|
||||
BUG("OperatorIsNotMonadic", op->id);
|
||||
}
|
||||
dynabuf_clear(errormsg_dyna_buf);
|
||||
dynabuf_add_string(errormsg_dyna_buf, "Operation not supported: Cannot apply \"");
|
||||
@ -1387,7 +1387,7 @@ static boolean list_differs(const struct object *self, const struct object *othe
|
||||
ford = other->u.listhead->next;
|
||||
while (arthur != self->u.listhead) {
|
||||
if (ford == other->u.listhead)
|
||||
Bug_found("ListLengthError", 0);
|
||||
BUG("ListLengthError", 0);
|
||||
if (arthur->u.payload.type != ford->u.payload.type)
|
||||
return TRUE; // item types differ
|
||||
|
||||
@ -1398,7 +1398,7 @@ static boolean list_differs(const struct object *self, const struct object *othe
|
||||
ford = ford->next;
|
||||
}
|
||||
if (ford != other->u.listhead)
|
||||
Bug_found("ListLengthError", 1);
|
||||
BUG("ListLengthError", 1);
|
||||
return FALSE; // no difference found
|
||||
}
|
||||
// string:
|
||||
@ -1685,7 +1685,7 @@ static void number_handle_monadic_operator(struct object *self, const struct op
|
||||
float_handle_monadic_operator(self, op);
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalNumberType1", self->u.number.ntype);
|
||||
BUG("IllegalNumberType1", self->u.number.ntype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1888,7 +1888,7 @@ static void int_handle_dyadic_operator(struct object *self, const struct op *op,
|
||||
// maybe put this into an extra "int_dyadic_int" function?
|
||||
// sanity check, now "other" must be an int
|
||||
if (other->u.number.ntype != NUMTYPE_INT)
|
||||
Bug_found("SecondArgIsNotAnInt", op->id);
|
||||
BUG("SecondArgIsNotAnInt", op->id);
|
||||
|
||||
// part 2: now we got rid of non-ints, perform actual operation:
|
||||
switch (op->id) {
|
||||
@ -2150,7 +2150,7 @@ static void number_handle_dyadic_operator(struct object *self, const struct op *
|
||||
else if (self->u.number.ntype == NUMTYPE_FLOAT)
|
||||
float_handle_dyadic_operator(self, op, other);
|
||||
else
|
||||
Bug_found("IllegalNumberType2", self->u.number.ntype);
|
||||
BUG("IllegalNumberType2", self->u.number.ntype);
|
||||
}
|
||||
|
||||
|
||||
@ -2171,7 +2171,7 @@ static int get_valid_index(int *target, int length, const struct object *self, c
|
||||
if (other->u.number.ntype == NUMTYPE_FLOAT)
|
||||
float_to_int(other);
|
||||
if (other->u.number.ntype != NUMTYPE_INT)
|
||||
Bug_found("IllegalNumberType3", other->u.number.ntype);
|
||||
BUG("IllegalNumberType3", other->u.number.ntype);
|
||||
|
||||
index = other->u.number.val.intval;
|
||||
// negative indices access from the end
|
||||
@ -2337,7 +2337,7 @@ static void number_print(const struct object *self, struct dynabuf *db)
|
||||
sprintf(buffer, "%.30g", self->u.number.val.fpval);
|
||||
dynabuf_add_string(db, buffer);
|
||||
} else {
|
||||
Bug_found("IllegalNumberType5", self->u.number.ntype);
|
||||
BUG("IllegalNumberType5", self->u.number.ntype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2395,7 +2395,7 @@ static int string_get_length(const struct object *self)
|
||||
// cannot be indexed
|
||||
static void cannot_be_indexed(const struct object *self, struct object *target, int index)
|
||||
{
|
||||
Bug_found("TriedToIndexNumber", index);
|
||||
BUG("TriedToIndexNumber", index);
|
||||
}
|
||||
|
||||
// list:
|
||||
@ -2499,9 +2499,9 @@ static int parse_expression(struct expression *expression)
|
||||
if (alu_state == STATE_END) {
|
||||
// check for bugs
|
||||
if (arg_sp != 1)
|
||||
Bug_found("ArgStackNotEmpty", arg_sp);
|
||||
BUG("ArgStackNotEmpty", arg_sp);
|
||||
if (op_sp != 1)
|
||||
Bug_found("OperatorStackNotEmpty", op_sp);
|
||||
BUG("OperatorStackNotEmpty", op_sp);
|
||||
// copy result
|
||||
*result = arg_stack[0];
|
||||
// if there was nothing to parse, mark as undefined FIXME - change this! make "nothing" its own result type; only numbers may be undefined
|
||||
@ -2531,10 +2531,10 @@ static int parse_expression(struct expression *expression)
|
||||
//result->u.number.val.intval = 0;
|
||||
result->u.number.addr_refs = 0;
|
||||
// make sure no additional (spurious) errors are reported:
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
// FIXME - remove this when new function interface gets used:
|
||||
// callers must decide for themselves what to do when expression
|
||||
// parser returns error (and may decide to call Input_skip_remainder)
|
||||
// parser returns error (and may decide to call input_skip_remainder)
|
||||
return 1; // error
|
||||
}
|
||||
}
|
||||
@ -2563,7 +2563,7 @@ void ALU_any_int(intval_t *target) // ACCEPT_UNDEFINED
|
||||
else if (expression.result.u.number.ntype == NUMTYPE_FLOAT)
|
||||
*target = expression.result.u.number.val.fpval;
|
||||
else
|
||||
Bug_found("IllegalNumberType6", expression.result.u.number.ntype);
|
||||
BUG("IllegalNumberType6", expression.result.u.number.ntype);
|
||||
} else if (expression.result.type == &type_string) {
|
||||
// accept single-char strings, to be more
|
||||
// compatible with versions before 0.97:
|
||||
@ -2618,7 +2618,7 @@ throws errors even though the result is defined!
|
||||
} else if (expression.result.u.number.ntype == NUMTYPE_FLOAT) {
|
||||
float_to_int(&expression.result);
|
||||
} else {
|
||||
Bug_found("IllegalNumberType7", expression.result.u.number.ntype);
|
||||
BUG("IllegalNumberType7", expression.result.u.number.ntype);
|
||||
}
|
||||
} else if (expression.result.type == &type_string) {
|
||||
// accept single-char strings, to be more
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// CPU type stuff
|
||||
@ -96,7 +96,7 @@ const struct cpu_type *cputype_find(void)
|
||||
void *node_body;
|
||||
|
||||
// perform lookup
|
||||
if (!Tree_easy_scan(cputype_tree, &node_body, GlobalDynaBuf))
|
||||
if (!tree_easy_scan(cputype_tree, &node_body, GlobalDynaBuf))
|
||||
return NULL;
|
||||
|
||||
return node_body;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Character encoding stuff
|
||||
@ -121,7 +121,7 @@ const struct encoder *encoding_find(void)
|
||||
void *node_body;
|
||||
|
||||
// perform lookup
|
||||
if (!Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) {
|
||||
if (!tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) {
|
||||
Throw_error("Unknown encoding.");
|
||||
return NULL;
|
||||
}
|
||||
|
54
src/flow.c
54
src/flow.c
@ -35,18 +35,18 @@ boolean check_ifdef_condition(void)
|
||||
struct symbol *symbol;
|
||||
|
||||
// read symbol name
|
||||
if (Input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
if (input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
return FALSE; // there was an error, it has been reported, so return value is more or less meaningless anway
|
||||
|
||||
// look for it
|
||||
Tree_hard_scan(&node, symbols_forest, scope, FALSE);
|
||||
tree_hard_scan(&node, symbols_forest, scope, FALSE);
|
||||
if (!node)
|
||||
return FALSE; // not found -> no, not defined
|
||||
|
||||
symbol = (struct symbol *) node->body;
|
||||
symbol->has_been_read = TRUE; // we did not really read the symbol's value, but checking for its existence still counts as "used it"
|
||||
if (symbol->object.type == NULL)
|
||||
Bug_found("ObjectHasNullType", 0);
|
||||
BUG("ObjectHasNullType", 0);
|
||||
return symbol->object.type->is_defined(&symbol->object);
|
||||
}
|
||||
|
||||
@ -54,12 +54,12 @@ boolean check_ifdef_condition(void)
|
||||
// parse a loop body (TODO - also use for macro body?)
|
||||
static void parse_ram_block(struct block *block)
|
||||
{
|
||||
Input_now->line_number = block->start; // set line number to loop start
|
||||
Input_now->src.ram_ptr = block->body; // set RAM read pointer to loop
|
||||
input_now->line_number = block->start; // set line number to loop start
|
||||
input_now->src.ram_ptr = block->body; // set RAM read pointer to loop
|
||||
// parse block
|
||||
Parse_until_eob_or_eof();
|
||||
parse_until_eob_or_eof();
|
||||
if (GotByte != CHAR_EOB)
|
||||
Bug_found("IllegalBlockTerminator", GotByte);
|
||||
BUG("IllegalBlockTerminator", GotByte);
|
||||
}
|
||||
|
||||
|
||||
@ -124,15 +124,15 @@ void flow_forloop(struct for_loop *loop)
|
||||
|
||||
// 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 = *input_now; // copy current input structure into new
|
||||
loop_input.source = INPUTSRC_RAM; // set new byte source
|
||||
// remember old input
|
||||
outer_input = Input_now;
|
||||
outer_input = input_now;
|
||||
// activate new input
|
||||
// (not yet useable; pointer and line number are still missing)
|
||||
Input_now = &loop_input;
|
||||
input_now = &loop_input;
|
||||
// fix line number (not for block, but in case symbol handling throws errors)
|
||||
Input_now->line_number = loop->block.start;
|
||||
input_now->line_number = loop->block.start;
|
||||
switch (loop->algorithm) {
|
||||
case FORALGO_OLDCOUNT:
|
||||
case FORALGO_NEWCOUNT:
|
||||
@ -142,10 +142,10 @@ void flow_forloop(struct for_loop *loop)
|
||||
iterating_for(loop);
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalLoopAlgo", loop->algorithm);
|
||||
BUG("IllegalLoopAlgo", loop->algorithm);
|
||||
}
|
||||
// restore previous input:
|
||||
Input_now = outer_input;
|
||||
input_now = outer_input;
|
||||
}
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ static void copy_condition(struct condition *condition, char terminator)
|
||||
// append to GlobalDynaBuf and check for quotes
|
||||
DYNABUF_APPEND(GlobalDynaBuf, GotByte);
|
||||
if ((GotByte == '"') || (GotByte == '\'')) {
|
||||
err = Input_quoted_to_dynabuf(GotByte);
|
||||
err = input_quoted_to_dynabuf(GotByte);
|
||||
// here GotByte changes, it might become CHAR_EOS
|
||||
DYNABUF_APPEND(GlobalDynaBuf, GotByte); // add closing quotes (or CHAR_EOS) as well
|
||||
if (err)
|
||||
@ -179,7 +179,7 @@ static void copy_condition(struct condition *condition, char terminator)
|
||||
void flow_store_doloop_condition(struct condition *condition, char terminator)
|
||||
{
|
||||
// write line number
|
||||
condition->line = Input_now->line_number;
|
||||
condition->line = input_now->line_number;
|
||||
// set defaults
|
||||
condition->invert = FALSE;
|
||||
condition->body = NULL;
|
||||
@ -188,7 +188,7 @@ void flow_store_doloop_condition(struct condition *condition, char terminator)
|
||||
return;
|
||||
|
||||
// seems as if there really *is* a condition, so check for until/while
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
if (input_read_and_lower_keyword()) {
|
||||
if (strcmp(GlobalDynaBuf->buffer, "while") == 0) {
|
||||
//condition.invert = FALSE;
|
||||
} else if (strcmp(GlobalDynaBuf->buffer, "until") == 0) {
|
||||
@ -208,7 +208,7 @@ void flow_store_doloop_condition(struct condition *condition, char terminator)
|
||||
// call with GotByte = first interesting character
|
||||
void flow_store_while_condition(struct condition *condition)
|
||||
{
|
||||
condition->line = Input_now->line_number;
|
||||
condition->line = input_now->line_number;
|
||||
condition->invert = FALSE;
|
||||
copy_condition(condition, CHAR_SOB);
|
||||
}
|
||||
@ -224,8 +224,8 @@ static boolean check_condition(struct condition *condition)
|
||||
return TRUE; // non-existing conditions are always true
|
||||
|
||||
// set up input for expression evaluation
|
||||
Input_now->line_number = condition->line;
|
||||
Input_now->src.ram_ptr = condition->body;
|
||||
input_now->line_number = condition->line;
|
||||
input_now->src.ram_ptr = condition->body;
|
||||
GetByte(); // proceed with next char
|
||||
ALU_defined_int(&intresult);
|
||||
if (GotByte)
|
||||
@ -241,13 +241,13 @@ void flow_do_while(struct do_while *loop)
|
||||
struct input *outer_input;
|
||||
|
||||
// set up new input
|
||||
loop_input = *Input_now; // copy current input structure into new
|
||||
loop_input = *input_now; // copy current input structure into new
|
||||
loop_input.source = INPUTSRC_RAM; // set new byte source
|
||||
// remember old input
|
||||
outer_input = Input_now;
|
||||
outer_input = input_now;
|
||||
// activate new input (not useable yet, as pointer and
|
||||
// line number are not yet set up)
|
||||
Input_now = &loop_input;
|
||||
input_now = &loop_input;
|
||||
for (;;) {
|
||||
// check head condition
|
||||
if (!check_condition(&loop->head_cond))
|
||||
@ -258,7 +258,7 @@ void flow_do_while(struct do_while *loop)
|
||||
break;
|
||||
}
|
||||
// restore previous input:
|
||||
Input_now = outer_input;
|
||||
input_now = outer_input;
|
||||
GotByte = CHAR_EOS; // CAUTION! Very ugly kluge.
|
||||
// But by switching input, we lost the outer input's GotByte. We know
|
||||
// it was CHAR_EOS. We could just call GetByte() to get real input, but
|
||||
@ -274,11 +274,11 @@ void flow_parse_and_close_file(FILE *fd, const char *filename)
|
||||
if (config.process_verbosity > 2)
|
||||
printf("Parsing source file '%s'\n", filename);
|
||||
// set up new input
|
||||
Input_new_file(filename, fd);
|
||||
// Parse block and check end reason
|
||||
Parse_until_eob_or_eof();
|
||||
input_new_file(filename, fd);
|
||||
// parse block and check end reason
|
||||
parse_until_eob_or_eof();
|
||||
if (GotByte != CHAR_EOF)
|
||||
Throw_error("Found '}' instead of end-of-file.");
|
||||
// close sublevel src
|
||||
fclose(Input_now->src.fd);
|
||||
fclose(input_now->src.fd);
|
||||
}
|
||||
|
68
src/global.c
68
src/global.c
@ -143,7 +143,7 @@ static int first_label_of_statement(bits *statement_flags)
|
||||
{
|
||||
if ((*statement_flags) & SF_IMPLIED_LABEL) {
|
||||
Throw_error(exception_syntax);
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
return FALSE;
|
||||
}
|
||||
(*statement_flags) |= SF_IMPLIED_LABEL; // now there has been one
|
||||
@ -211,11 +211,11 @@ static void parse_symbol_definition(scope_t scope, bits stat_flags)
|
||||
if (GotByte == '?')
|
||||
symbol_fix_dynamic_name();
|
||||
|
||||
force_bit = Input_get_force_bit(); // skips spaces after (yes, force bit is allowed for label definitions)
|
||||
force_bit = input_get_force_bit(); // skips spaces after (yes, force bit is allowed for label definitions)
|
||||
if (GotByte == '=') {
|
||||
// explicit symbol definition (symbol = <something>)
|
||||
parse_assignment(scope, force_bit, POWER_NONE);
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
} else {
|
||||
// implicit symbol definition (label)
|
||||
set_label(scope, stat_flags, force_bit, POWER_NONE);
|
||||
@ -228,7 +228,7 @@ static void parse_mnemo_or_global_symbol_def(bits *statement_flags)
|
||||
{
|
||||
boolean is_mnemonic;
|
||||
|
||||
is_mnemonic = CPU_state.type->keyword_is_mnemonic(Input_read_keyword());
|
||||
is_mnemonic = CPU_state.type->keyword_is_mnemonic(input_read_keyword());
|
||||
// It is only a label if it isn't a mnemonic
|
||||
if ((!is_mnemonic)
|
||||
&& first_label_of_statement(statement_flags)) {
|
||||
@ -251,7 +251,7 @@ static void parse_local_symbol_def(bits *statement_flags)
|
||||
if (!first_label_of_statement(statement_flags))
|
||||
return;
|
||||
|
||||
if (Input_read_scope_and_symbol_name(&scope) == 0)
|
||||
if (input_read_scope_and_symbol_name(&scope) == 0)
|
||||
parse_symbol_definition(scope, *statement_flags);
|
||||
}
|
||||
|
||||
@ -294,7 +294,7 @@ static void parse_forward_anon_def(bits *statement_flags)
|
||||
// Parse block, beginning with next byte.
|
||||
// End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards
|
||||
// Has to be re-entrant.
|
||||
void Parse_until_eob_or_eof(void)
|
||||
void parse_until_eob_or_eof(void)
|
||||
{
|
||||
bits statement_flags;
|
||||
|
||||
@ -335,7 +335,7 @@ void Parse_until_eob_or_eof(void)
|
||||
if ((GotByte == LOCAL_PREFIX)
|
||||
|| (GotByte == CHEAP_PREFIX)
|
||||
|| (BYTE_CONTINUES_KEYWORD(GotByte)))
|
||||
Macro_parse_call();
|
||||
macro_parse_call();
|
||||
else
|
||||
parse_forward_anon_def(&statement_flags);
|
||||
break;
|
||||
@ -351,7 +351,7 @@ void Parse_until_eob_or_eof(void)
|
||||
parse_mnemo_or_global_symbol_def(&statement_flags);
|
||||
} else {
|
||||
Throw_error(exception_syntax);
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -366,12 +366,12 @@ void Parse_until_eob_or_eof(void)
|
||||
// Skip space. If GotByte is CHAR_SOB ('{'), parse block and return TRUE.
|
||||
// Otherwise (if there is no block), return FALSE.
|
||||
// Don't forget to call EnsureEOL() afterwards.
|
||||
int Parse_optional_block(void)
|
||||
int parse_optional_block(void)
|
||||
{
|
||||
SKIPSPACE();
|
||||
if (GotByte != CHAR_SOB)
|
||||
return FALSE;
|
||||
Parse_until_eob_or_eof();
|
||||
parse_until_eob_or_eof();
|
||||
if (GotByte != CHAR_EOB)
|
||||
Throw_serious_error(exception_no_right_brace);
|
||||
GetByte();
|
||||
@ -397,11 +397,11 @@ static void throw_message(const char *message, const char *type)
|
||||
++throw_counter;
|
||||
if (config.format_msvc)
|
||||
fprintf(config.msg_stream, "%s(%d) : %s (%s %s): %s\n",
|
||||
Input_now->original_filename, Input_now->line_number,
|
||||
input_now->original_filename, input_now->line_number,
|
||||
type, section_now->type, section_now->title, message);
|
||||
else
|
||||
fprintf(config.msg_stream, "%s - File %s, line %d (%s %s): %s\n",
|
||||
type, Input_now->original_filename, Input_now->line_number,
|
||||
type, input_now->original_filename, input_now->line_number,
|
||||
section_now->type, section_now->title, message);
|
||||
}
|
||||
|
||||
@ -461,7 +461,7 @@ void Throw_serious_error(const char *message)
|
||||
|
||||
|
||||
// Handle bugs
|
||||
void Bug_found(const char *message, int code)
|
||||
void BUG(const char *message, int code)
|
||||
{
|
||||
Throw_warning("Bug in ACME, code follows");
|
||||
fprintf(stderr, "(0x%x:)", code);
|
||||
@ -484,7 +484,7 @@ void output_object(struct object *object, struct iter_context *iter)
|
||||
else if (object->u.number.ntype == NUMTYPE_FLOAT)
|
||||
iter->fn(object->u.number.val.fpval);
|
||||
else
|
||||
Bug_found("IllegalNumberType0", object->u.number.ntype);
|
||||
BUG("IllegalNumberType0", object->u.number.ntype);
|
||||
} else if (object->type == &type_list) {
|
||||
// iterate over list
|
||||
item = object->u.listhead->next;
|
||||
@ -505,7 +505,7 @@ void output_object(struct object *object, struct iter_context *iter)
|
||||
Throw_error("There's more than one character."); // see alu.c for the original of this error
|
||||
}
|
||||
} else {
|
||||
Bug_found("IllegalObjectType", 0);
|
||||
BUG("IllegalObjectType", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,7 +515,7 @@ void output_8(intval_t value)
|
||||
{
|
||||
if ((value < -0x80) || (value > 0xff))
|
||||
Throw_error(exception_number_out_of_8b_range);
|
||||
Output_byte(value);
|
||||
output_byte(value);
|
||||
}
|
||||
|
||||
|
||||
@ -524,8 +524,8 @@ void output_be16(intval_t value)
|
||||
{
|
||||
if ((value < -0x8000) || (value > 0xffff))
|
||||
Throw_error(exception_number_out_of_16b_range);
|
||||
Output_byte(value >> 8);
|
||||
Output_byte(value);
|
||||
output_byte(value >> 8);
|
||||
output_byte(value);
|
||||
}
|
||||
|
||||
|
||||
@ -534,8 +534,8 @@ void output_le16(intval_t value)
|
||||
{
|
||||
if ((value < -0x8000) || (value > 0xffff))
|
||||
Throw_error(exception_number_out_of_16b_range);
|
||||
Output_byte(value);
|
||||
Output_byte(value >> 8);
|
||||
output_byte(value);
|
||||
output_byte(value >> 8);
|
||||
}
|
||||
|
||||
|
||||
@ -544,9 +544,9 @@ void output_be24(intval_t value)
|
||||
{
|
||||
if ((value < -0x800000) || (value > 0xffffff))
|
||||
Throw_error(exception_number_out_of_24b_range);
|
||||
Output_byte(value >> 16);
|
||||
Output_byte(value >> 8);
|
||||
Output_byte(value);
|
||||
output_byte(value >> 16);
|
||||
output_byte(value >> 8);
|
||||
output_byte(value);
|
||||
}
|
||||
|
||||
|
||||
@ -555,9 +555,9 @@ void output_le24(intval_t value)
|
||||
{
|
||||
if ((value < -0x800000) || (value > 0xffffff))
|
||||
Throw_error(exception_number_out_of_24b_range);
|
||||
Output_byte(value);
|
||||
Output_byte(value >> 8);
|
||||
Output_byte(value >> 16);
|
||||
output_byte(value);
|
||||
output_byte(value >> 8);
|
||||
output_byte(value >> 16);
|
||||
}
|
||||
|
||||
|
||||
@ -572,10 +572,10 @@ void output_be32(intval_t value)
|
||||
{
|
||||
// if ((value < -0x80000000) || (value > 0xffffffff))
|
||||
// Throw_error(exception_number_out_of_32b_range);
|
||||
Output_byte(value >> 24);
|
||||
Output_byte(value >> 16);
|
||||
Output_byte(value >> 8);
|
||||
Output_byte(value);
|
||||
output_byte(value >> 24);
|
||||
output_byte(value >> 16);
|
||||
output_byte(value >> 8);
|
||||
output_byte(value);
|
||||
}
|
||||
|
||||
|
||||
@ -584,8 +584,8 @@ void output_le32(intval_t value)
|
||||
{
|
||||
// if ((value < -0x80000000) || (value > 0xffffffff))
|
||||
// Throw_error(exception_number_out_of_32b_range);
|
||||
Output_byte(value);
|
||||
Output_byte(value >> 8);
|
||||
Output_byte(value >> 16);
|
||||
Output_byte(value >> 24);
|
||||
output_byte(value);
|
||||
output_byte(value >> 8);
|
||||
output_byte(value >> 16);
|
||||
output_byte(value >> 24);
|
||||
}
|
||||
|
27
src/global.h
27
src/global.h
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Global stuff - things that are needed by several modules
|
||||
@ -121,41 +121,52 @@ do { \
|
||||
|
||||
// set configuration to default values
|
||||
extern void config_default(struct config *conf);
|
||||
|
||||
// allocate memory and die if not available
|
||||
extern void *safe_malloc(size_t amount);
|
||||
|
||||
// call with symbol name in GlobalDynaBuf and GotByte == '='
|
||||
// "powers" is for "!set" pseudo opcode so changes are allowed (see symbol.h for powers)
|
||||
extern void parse_assignment(scope_t scope, bits force_bit, bits powers);
|
||||
|
||||
// Parse block, beginning with next byte.
|
||||
// End reason (either CHAR_EOB or CHAR_EOF) can be found in GotByte afterwards
|
||||
// Has to be re-entrant.
|
||||
extern void Parse_until_eob_or_eof(void);
|
||||
extern void parse_until_eob_or_eof(void);
|
||||
|
||||
// Skip space. If GotByte is CHAR_SOB ('{'), parse block and return TRUE.
|
||||
// Otherwise (if there is no block), return FALSE.
|
||||
// Don't forget to call EnsureEOL() afterwards.
|
||||
extern int Parse_optional_block(void);
|
||||
extern int parse_optional_block(void);
|
||||
|
||||
// error/warning counter so macro calls can find out whether to show a call stack
|
||||
extern int Throw_get_counter(void);
|
||||
|
||||
// Output a warning.
|
||||
// This means the produced code looks as expected. But there has been a
|
||||
// situation that should be reported to the user, for example ACME may have
|
||||
// assembled a 16-bit parameter with an 8-bit value.
|
||||
extern void Throw_warning(const char *msg);
|
||||
|
||||
// Output a warning if in first pass. See above.
|
||||
extern void Throw_first_pass_warning(const char *msg);
|
||||
|
||||
// Output an error.
|
||||
// This means something went wrong in a way that implies that the output
|
||||
// almost for sure won't look like expected, for example when there was a
|
||||
// syntax error. The assembler will try to go on with the assembly though, so
|
||||
// the user gets to know about more than one of his typos at a time.
|
||||
extern void Throw_error(const char *msg);
|
||||
|
||||
// Output a serious error, stopping assembly.
|
||||
// Serious errors are those that make it impossible to go on with the
|
||||
// assembly. Example: "!fill" without a parameter - the program counter cannot
|
||||
// be set correctly in this case, so proceeding would be of no use at all.
|
||||
extern void Throw_serious_error(const char *msg);
|
||||
|
||||
// handle bugs
|
||||
extern void Bug_found(const char *msg, int code);
|
||||
extern void BUG(const char *msg, int code);
|
||||
|
||||
// insert object (in case of list, will iterate/recurse until done)
|
||||
struct iter_context {
|
||||
void (*fn)(intval_t); // output function
|
||||
@ -163,21 +174,27 @@ struct iter_context {
|
||||
unsigned char stringxor; // for !scrxor, 0 otherwise
|
||||
};
|
||||
extern void output_object(struct object *object, struct iter_context *iter);
|
||||
|
||||
// output 8-bit value with range check
|
||||
extern void output_8(intval_t value);
|
||||
|
||||
// output 16-bit value with range check big-endian
|
||||
extern void output_be16(intval_t value);
|
||||
|
||||
// output 16-bit value with range check little-endian
|
||||
extern void output_le16(intval_t value);
|
||||
|
||||
// output 24-bit value with range check big-endian
|
||||
extern void output_be24(intval_t value);
|
||||
|
||||
// output 24-bit value with range check little-endian
|
||||
extern void output_le24(intval_t value);
|
||||
|
||||
// output 32-bit value (without range check) big-endian
|
||||
extern void output_be32(intval_t value);
|
||||
|
||||
// output 32-bit value (without range check) little-endian
|
||||
extern void output_le32(intval_t value);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
142
src/input.c
142
src/input.c
@ -37,19 +37,19 @@ static struct input outermost = {
|
||||
|
||||
|
||||
// variables
|
||||
struct input *Input_now = &outermost; // current input structure
|
||||
struct input *input_now = &outermost; // current input structure
|
||||
|
||||
|
||||
// functions
|
||||
|
||||
// let current input point to start of file
|
||||
void Input_new_file(const char *filename, FILE *fd)
|
||||
void input_new_file(const char *filename, FILE *fd)
|
||||
{
|
||||
Input_now->original_filename = filename;
|
||||
Input_now->line_number = 1;
|
||||
Input_now->source = INPUTSRC_FILE;
|
||||
Input_now->state = INPUTSTATE_SOF;
|
||||
Input_now->src.fd = fd;
|
||||
input_now->original_filename = filename;
|
||||
input_now->line_number = 1;
|
||||
input_now->source = INPUTSRC_FILE;
|
||||
input_now->state = INPUTSTATE_SOF;
|
||||
input_now->src.fd = fd;
|
||||
}
|
||||
|
||||
|
||||
@ -64,9 +64,9 @@ static void report_srcchar(char new_char)
|
||||
char hexdump[2 * REPORT_BINBUFSIZE + 2]; // +2 for '.' and terminator
|
||||
|
||||
// if input has changed, insert explanation
|
||||
if (Input_now != report->last_input) {
|
||||
fprintf(report->fd, "\n; ******** Source: %s\n", Input_now->original_filename);
|
||||
report->last_input = Input_now;
|
||||
if (input_now != report->last_input) {
|
||||
fprintf(report->fd, "\n; ******** Source: %s\n", input_now->original_filename);
|
||||
report->last_input = input_now;
|
||||
report->asc_used = 0; // clear buffer
|
||||
prev_char = '\0';
|
||||
}
|
||||
@ -74,7 +74,7 @@ static void report_srcchar(char new_char)
|
||||
// line start after line break detected and EOS processed,
|
||||
// build report line:
|
||||
// show line number...
|
||||
fprintf(report->fd, "%6d ", Input_now->line_number - 1);
|
||||
fprintf(report->fd, "%6d ", input_now->line_number - 1);
|
||||
// prepare outbytes' start address
|
||||
if (report->bin_used) {
|
||||
#if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
|
||||
@ -117,23 +117,23 @@ static char get_processed_from_file(void)
|
||||
static int from_file = 0;
|
||||
|
||||
for (;;) {
|
||||
switch (Input_now->state) {
|
||||
switch (input_now->state) {
|
||||
case INPUTSTATE_SOF:
|
||||
// fetch first byte from the current source file
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
//TODO - check for bogus/malformed BOM (0xef 0xbb 0xbf as UTF-8-encoded 0xfeff) and ignore?
|
||||
// check for hashbang line and ignore
|
||||
if (from_file == '#') {
|
||||
// remember to skip remainder of line
|
||||
Input_now->state = INPUTSTATE_COMMENT;
|
||||
input_now->state = INPUTSTATE_COMMENT;
|
||||
return CHAR_EOS; // end of statement
|
||||
}
|
||||
Input_now->state = INPUTSTATE_AGAIN;
|
||||
input_now->state = INPUTSTATE_AGAIN;
|
||||
break;
|
||||
case INPUTSTATE_NORMAL:
|
||||
// fetch a fresh byte from the current source file
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
// now process it
|
||||
/*FALLTHROUGH*/
|
||||
@ -144,12 +144,12 @@ static char get_processed_from_file(void)
|
||||
// If the source is changed so there is a possibility
|
||||
// to enter INPUTSTATE_AGAIN mode without first having
|
||||
// defined "from_file", trouble may arise...
|
||||
Input_now->state = INPUTSTATE_NORMAL;
|
||||
input_now->state = INPUTSTATE_NORMAL;
|
||||
// EOF must be checked first because it cannot be used
|
||||
// as an index into global_byte_flags[]
|
||||
if (from_file == EOF) {
|
||||
// remember to send an end-of-file
|
||||
Input_now->state = INPUTSTATE_EOF;
|
||||
input_now->state = INPUTSTATE_EOF;
|
||||
return CHAR_EOS; // end of statement
|
||||
}
|
||||
|
||||
@ -163,38 +163,38 @@ static char get_processed_from_file(void)
|
||||
case '\t':
|
||||
case ' ':
|
||||
// remember to skip all following blanks
|
||||
Input_now->state = INPUTSTATE_SKIPBLANKS;
|
||||
input_now->state = INPUTSTATE_SKIPBLANKS;
|
||||
return ' ';
|
||||
|
||||
case CHAR_LF: // LF character
|
||||
// remember to send a start-of-line
|
||||
Input_now->state = INPUTSTATE_LF;
|
||||
input_now->state = INPUTSTATE_LF;
|
||||
return CHAR_EOS; // end of statement
|
||||
|
||||
case CHAR_CR: // CR character
|
||||
// remember to check CRLF + send start-of-line
|
||||
Input_now->state = INPUTSTATE_CR;
|
||||
input_now->state = INPUTSTATE_CR;
|
||||
return CHAR_EOS; // end of statement
|
||||
|
||||
case CHAR_EOB:
|
||||
// remember to send an end-of-block
|
||||
Input_now->state = INPUTSTATE_EOB;
|
||||
input_now->state = INPUTSTATE_EOB;
|
||||
return CHAR_EOS; // end of statement
|
||||
|
||||
case '/':
|
||||
// to check for "//", get another byte:
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
if (from_file != '/') {
|
||||
// not "//", so:
|
||||
Input_now->state = INPUTSTATE_AGAIN; // second byte must be parsed normally later on
|
||||
input_now->state = INPUTSTATE_AGAIN; // second byte must be parsed normally later on
|
||||
return '/'; // first byte is returned normally right now
|
||||
}
|
||||
// it's really "//", so act as if ';'
|
||||
/*FALLTHROUGH*/
|
||||
case ';':
|
||||
// remember to skip remainder of line
|
||||
Input_now->state = INPUTSTATE_COMMENT;
|
||||
input_now->state = INPUTSTATE_COMMENT;
|
||||
return CHAR_EOS; // end of statement
|
||||
|
||||
case ':': // statement delimiter
|
||||
@ -209,60 +209,60 @@ static char get_processed_from_file(void)
|
||||
case INPUTSTATE_SKIPBLANKS:
|
||||
// read until non-blank, then deliver that
|
||||
do {
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
} while ((from_file == '\t') || (from_file == ' '));
|
||||
// re-process last byte
|
||||
Input_now->state = INPUTSTATE_AGAIN;
|
||||
input_now->state = INPUTSTATE_AGAIN;
|
||||
break;
|
||||
case INPUTSTATE_LF:
|
||||
// return start-of-line, then continue in normal mode
|
||||
Input_now->state = INPUTSTATE_NORMAL;
|
||||
input_now->state = INPUTSTATE_NORMAL;
|
||||
return CHAR_SOL; // new line
|
||||
|
||||
case INPUTSTATE_CR:
|
||||
// return start-of-line, remember to check for LF
|
||||
Input_now->state = INPUTSTATE_SKIPLF;
|
||||
input_now->state = INPUTSTATE_SKIPLF;
|
||||
return CHAR_SOL; // new line
|
||||
|
||||
case INPUTSTATE_SKIPLF:
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
// if LF, ignore it and fetch another byte
|
||||
// otherwise, process current byte
|
||||
if (from_file == CHAR_LF)
|
||||
Input_now->state = INPUTSTATE_NORMAL;
|
||||
input_now->state = INPUTSTATE_NORMAL;
|
||||
else
|
||||
Input_now->state = INPUTSTATE_AGAIN;
|
||||
input_now->state = INPUTSTATE_AGAIN;
|
||||
break;
|
||||
case INPUTSTATE_COMMENT:
|
||||
// read until end-of-line or end-of-file
|
||||
do {
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
} while ((from_file != EOF) && (from_file != CHAR_CR) && (from_file != CHAR_LF));
|
||||
// re-process last byte
|
||||
Input_now->state = INPUTSTATE_AGAIN;
|
||||
input_now->state = INPUTSTATE_AGAIN;
|
||||
break;
|
||||
case INPUTSTATE_EOB:
|
||||
// deliver EOB
|
||||
Input_now->state = INPUTSTATE_NORMAL;
|
||||
input_now->state = INPUTSTATE_NORMAL;
|
||||
return CHAR_EOB; // end of block
|
||||
|
||||
case INPUTSTATE_EOF:
|
||||
// deliver EOF
|
||||
Input_now->state = INPUTSTATE_NORMAL;
|
||||
input_now->state = INPUTSTATE_NORMAL;
|
||||
return CHAR_EOF; // end of file
|
||||
|
||||
default:
|
||||
Bug_found("StrangeInputMode", Input_now->state);
|
||||
BUG("StrangeInputMode", input_now->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function delivers the next byte from the currently active byte source
|
||||
// in shortened high-level format. FIXME - use fn ptr?
|
||||
// When inside quotes, use Input_quoted_to_dynabuf() instead!
|
||||
// When inside quotes, use input_quoted_to_dynabuf() instead!
|
||||
char GetByte(void)
|
||||
{
|
||||
// for (;;) {
|
||||
@ -271,23 +271,23 @@ char GetByte(void)
|
||||
// high-level format
|
||||
// Otherwise, the source is a file. This means we will call
|
||||
// get_processed_from_file() which will do a shit load of conversions.
|
||||
switch (Input_now->source) {
|
||||
switch (input_now->source) {
|
||||
case INPUTSRC_RAM:
|
||||
GotByte = *(Input_now->src.ram_ptr++);
|
||||
GotByte = *(input_now->src.ram_ptr++);
|
||||
break;
|
||||
case INPUTSRC_FILE:
|
||||
GotByte = get_processed_from_file();
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalInputSrc", Input_now->source);
|
||||
BUG("IllegalInputSrc", input_now->source);
|
||||
}
|
||||
// // if start-of-line was read, increment line counter and repeat
|
||||
// if (GotByte != CHAR_SOL)
|
||||
// return GotByte;
|
||||
// Input_now->line_number++;
|
||||
// input_now->line_number++;
|
||||
// }
|
||||
if (GotByte == CHAR_SOL)
|
||||
Input_now->line_number++;
|
||||
input_now->line_number++;
|
||||
return GotByte;
|
||||
}
|
||||
|
||||
@ -299,30 +299,30 @@ static char GetQuotedByte(void)
|
||||
{
|
||||
int from_file; // must be an int to catch EOF
|
||||
|
||||
switch (Input_now->source) {
|
||||
switch (input_now->source) {
|
||||
case INPUTSRC_RAM:
|
||||
// if byte source is RAM, then no conversion is necessary,
|
||||
// because in RAM the source already has high-level format
|
||||
GotByte = *(Input_now->src.ram_ptr++);
|
||||
GotByte = *(input_now->src.ram_ptr++);
|
||||
break;
|
||||
case INPUTSRC_FILE:
|
||||
// fetch a fresh byte from the current source file
|
||||
from_file = getc(Input_now->src.fd);
|
||||
from_file = getc(input_now->src.fd);
|
||||
IF_WANTED_REPORT_SRCCHAR(from_file);
|
||||
switch (from_file) {
|
||||
case EOF:
|
||||
// remember to send an end-of-file
|
||||
Input_now->state = INPUTSTATE_EOF;
|
||||
input_now->state = INPUTSTATE_EOF;
|
||||
GotByte = CHAR_EOS; // end of statement
|
||||
break;
|
||||
case CHAR_LF: // LF character
|
||||
// remember to send a start-of-line
|
||||
Input_now->state = INPUTSTATE_LF;
|
||||
input_now->state = INPUTSTATE_LF;
|
||||
GotByte = CHAR_EOS; // end of statement
|
||||
break;
|
||||
case CHAR_CR: // CR character
|
||||
// remember to check for CRLF + send a start-of-line
|
||||
Input_now->state = INPUTSTATE_CR;
|
||||
input_now->state = INPUTSTATE_CR;
|
||||
GotByte = CHAR_EOS; // end of statement
|
||||
break;
|
||||
default:
|
||||
@ -330,7 +330,7 @@ static char GetQuotedByte(void)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalInputSrc", Input_now->source);
|
||||
BUG("IllegalInputSrc", input_now->source);
|
||||
}
|
||||
// now check for end of statement
|
||||
if (GotByte == CHAR_EOS)
|
||||
@ -340,7 +340,7 @@ static char GetQuotedByte(void)
|
||||
|
||||
// Skip remainder of statement, for example on error
|
||||
// FIXME - check for quotes, otherwise this might treat a quoted colon like EOS!
|
||||
void Input_skip_remainder(void)
|
||||
void input_skip_remainder(void)
|
||||
{
|
||||
while (GotByte)
|
||||
GetByte(); // Read characters until end-of-statement
|
||||
@ -348,7 +348,7 @@ void Input_skip_remainder(void)
|
||||
|
||||
// Ensure that the remainder of the current statement is empty, for example
|
||||
// after mnemonics using implied addressing.
|
||||
void Input_ensure_EOS(void) // Now GotByte = first char to test
|
||||
void input_ensure_EOS(void) // Now GotByte = first char to test
|
||||
{
|
||||
SKIPSPACE();
|
||||
if (GotByte) {
|
||||
@ -359,13 +359,13 @@ void Input_ensure_EOS(void) // Now GotByte = first char to test
|
||||
quote = (GotByte == '\'') ? '"' : '\''; // use single quotes, unless byte is a single quote (then use double quotes)
|
||||
sprintf(buf, "Garbage data at end of statement (unexpected %c%c%c).", quote, GotByte, quote);
|
||||
Throw_error(buf);
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
}
|
||||
}
|
||||
|
||||
// read string to dynabuf until closing quote is found
|
||||
// returns 1 on errors (unterminated, escaping error)
|
||||
int Input_quoted_to_dynabuf(char closing_quote)
|
||||
int input_quoted_to_dynabuf(char closing_quote)
|
||||
{
|
||||
boolean escaped = FALSE;
|
||||
|
||||
@ -378,7 +378,7 @@ int Input_quoted_to_dynabuf(char closing_quote)
|
||||
if (escaped) {
|
||||
// previous byte was backslash, so do not check for terminator nor backslash
|
||||
escaped = FALSE;
|
||||
// do not actually _convert_ escape sequences to their target byte, that is done by Input_unescape_dynabuf() below!
|
||||
// do not actually _convert_ escape sequences to their target byte, that is done by input_unescape_dynabuf() below!
|
||||
// TODO - but maybe check for illegal escape sequences?
|
||||
// at the moment checking is only done when the string
|
||||
// gets used for something...
|
||||
@ -396,8 +396,8 @@ int Input_quoted_to_dynabuf(char closing_quote)
|
||||
|
||||
// process backslash escapes in GlobalDynaBuf (so size might shrink)
|
||||
// returns 1 on errors (escaping errors)
|
||||
// TODO - check: if this is only ever called directly after Input_quoted_to_dynabuf, integrate that call here?
|
||||
int Input_unescape_dynabuf(int read_index)
|
||||
// TODO - check: if this is only ever called directly after input_quoted_to_dynabuf, integrate that call here?
|
||||
int input_unescape_dynabuf(int read_index)
|
||||
{
|
||||
int write_index;
|
||||
char byte;
|
||||
@ -444,7 +444,7 @@ int Input_unescape_dynabuf(int read_index)
|
||||
}
|
||||
}
|
||||
if (escaped)
|
||||
Bug_found("PartialEscapeSequence", 0);
|
||||
BUG("PartialEscapeSequence", 0);
|
||||
GlobalDynaBuf->size = write_index;
|
||||
return 0; // ok
|
||||
}
|
||||
@ -457,7 +457,7 @@ int Input_unescape_dynabuf(int read_index)
|
||||
// After calling this function, GotByte holds '}'. Unless EOF was found first,
|
||||
// but then a serious error would have been thrown.
|
||||
// FIXME - use a struct block *ptr argument!
|
||||
char *Input_skip_or_store_block(boolean store)
|
||||
char *input_skip_or_store_block(boolean store)
|
||||
{
|
||||
char byte;
|
||||
int depth = 1; // to find matching block end
|
||||
@ -475,7 +475,7 @@ char *Input_skip_or_store_block(boolean store)
|
||||
|
||||
case '"': // Quotes? Okay, read quoted stuff.
|
||||
case '\'':
|
||||
Input_quoted_to_dynabuf(byte);
|
||||
input_quoted_to_dynabuf(byte);
|
||||
DYNABUF_APPEND(GlobalDynaBuf, GotByte); // add closing quote
|
||||
break;
|
||||
case CHAR_SOB:
|
||||
@ -520,7 +520,7 @@ static int append_keyword_to_global_dynabuf(void)
|
||||
// appending while characters are legal for keywords.
|
||||
// throw "missing string" error if none.
|
||||
// return whether there was an error.
|
||||
int Input_append_symbol_name_to_global_dynabuf(void)
|
||||
int input_append_symbol_name_to_global_dynabuf(void)
|
||||
{
|
||||
if ((GotByte == LOCAL_PREFIX)
|
||||
|| (GotByte == CHEAP_PREFIX)) {
|
||||
@ -536,7 +536,7 @@ int Input_append_symbol_name_to_global_dynabuf(void)
|
||||
|
||||
// read symbol name into GlobalDynaBuf, set scope,
|
||||
// return whether there was an error (namely, "no string given").
|
||||
int Input_readscopeandsymbolname(scope_t *scope, boolean dotkluge)
|
||||
int input_readscopeandsymbolname(scope_t *scope, boolean dotkluge)
|
||||
{
|
||||
int err;
|
||||
|
||||
@ -550,7 +550,7 @@ int Input_readscopeandsymbolname(scope_t *scope, boolean dotkluge)
|
||||
dynabuf_append(GlobalDynaBuf, '.');
|
||||
err = append_keyword_to_global_dynabuf() == 0; // zero length -> error!
|
||||
} else {
|
||||
err = Input_append_symbol_name_to_global_dynabuf();
|
||||
err = input_append_symbol_name_to_global_dynabuf();
|
||||
}
|
||||
// add terminator to buffer (increments buffer's length counter)
|
||||
dynabuf_append(GlobalDynaBuf, '\0');
|
||||
@ -572,7 +572,7 @@ int Input_readscopeandsymbolname(scope_t *scope, boolean dotkluge)
|
||||
// character is read. Zero-terminate the string. Return its length (without
|
||||
// terminator).
|
||||
// Zero lengths will produce a "missing string" error.
|
||||
int Input_read_keyword(void)
|
||||
int input_read_keyword(void)
|
||||
{
|
||||
int length;
|
||||
|
||||
@ -587,7 +587,7 @@ int Input_read_keyword(void)
|
||||
// character is read. Zero-terminate the string, then convert to lower case.
|
||||
// Return its length (without terminator).
|
||||
// Zero lengths will produce a "missing string" error.
|
||||
int Input_read_and_lower_keyword(void)
|
||||
int input_read_and_lower_keyword(void)
|
||||
{
|
||||
int length;
|
||||
|
||||
@ -607,8 +607,8 @@ int Input_read_and_lower_keyword(void)
|
||||
// UNIX style to platform style.
|
||||
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
||||
// Errors are handled and reported, but caller should call
|
||||
// Input_skip_remainder() then.
|
||||
int Input_read_filename(boolean allow_library, boolean *uses_lib)
|
||||
// input_skip_remainder() then.
|
||||
int input_read_filename(boolean allow_library, boolean *uses_lib)
|
||||
{
|
||||
int start_of_string;
|
||||
char *lib_prefix,
|
||||
@ -651,7 +651,7 @@ int Input_read_filename(boolean allow_library, boolean *uses_lib)
|
||||
// remember border between optional library prefix and string from assembler source file
|
||||
start_of_string = GlobalDynaBuf->size;
|
||||
// read file name string
|
||||
if (Input_quoted_to_dynabuf(terminator))
|
||||
if (input_quoted_to_dynabuf(terminator))
|
||||
return 1; // unterminated or escaping error
|
||||
|
||||
GetByte(); // eat terminator
|
||||
@ -662,7 +662,7 @@ int Input_read_filename(boolean allow_library, boolean *uses_lib)
|
||||
}
|
||||
|
||||
// resolve backslash escapes
|
||||
if (Input_unescape_dynabuf(start_of_string))
|
||||
if (input_unescape_dynabuf(start_of_string))
|
||||
return 1; // escaping error
|
||||
|
||||
// terminate string
|
||||
@ -676,7 +676,7 @@ int Input_read_filename(boolean allow_library, boolean *uses_lib)
|
||||
|
||||
// Try to read a comma, skipping spaces before and after. Return TRUE if comma
|
||||
// found, otherwise FALSE.
|
||||
int Input_accept_comma(void)
|
||||
int input_accept_comma(void)
|
||||
{
|
||||
SKIPSPACE();
|
||||
if (GotByte != ',')
|
||||
@ -688,7 +688,7 @@ int Input_accept_comma(void)
|
||||
|
||||
// read optional info about parameter length
|
||||
// FIXME - move to different file!
|
||||
bits Input_get_force_bit(void)
|
||||
bits input_get_force_bit(void)
|
||||
{
|
||||
char byte;
|
||||
bits force_bit = 0;
|
||||
|
44
src/input.h
44
src/input.h
@ -55,29 +55,32 @@ extern const char FILE_READBINARY[];
|
||||
|
||||
|
||||
// Variables
|
||||
extern struct input *Input_now; // current input structure
|
||||
extern struct input *input_now; // current input structure
|
||||
|
||||
|
||||
// Prototypes
|
||||
|
||||
// let current input point to start of file
|
||||
extern void Input_new_file(const char *filename, FILE *fd);
|
||||
extern void input_new_file(const char *filename, FILE *fd);
|
||||
|
||||
// get next byte from currently active byte source in shortened high-level
|
||||
// format. When inside quotes, use Input_quoted_to_dynabuf() instead!
|
||||
// format. When inside quotes, use input_quoted_to_dynabuf() instead!
|
||||
extern char GetByte(void);
|
||||
|
||||
// Skip remainder of statement, for example on error
|
||||
extern void Input_skip_remainder(void);
|
||||
extern void input_skip_remainder(void);
|
||||
|
||||
// Ensure that the remainder of the current statement is empty, for example
|
||||
// after mnemonics using implied addressing.
|
||||
extern void Input_ensure_EOS(void);
|
||||
extern void input_ensure_EOS(void);
|
||||
|
||||
// read string to dynabuf until closing quote is found
|
||||
// returns 1 on errors (unterminated, escaping error)
|
||||
extern int Input_quoted_to_dynabuf(char closing_quote);
|
||||
extern int input_quoted_to_dynabuf(char closing_quote);
|
||||
|
||||
// process backslash escapes in GlobalDynaBuf (so size might shrink)
|
||||
// returns 1 on errors (escaping errors)
|
||||
extern int Input_unescape_dynabuf(int start_index);
|
||||
extern int input_unescape_dynabuf(int start_index);
|
||||
|
||||
// Skip or store block (starting with next byte, so call directly after
|
||||
// reading opening brace).
|
||||
@ -86,32 +89,33 @@ extern int Input_unescape_dynabuf(int start_index);
|
||||
// If "Store" is FALSE, NULL is returned.
|
||||
// After calling this function, GotByte holds '}'. Unless EOF was found first,
|
||||
// but then a serious error would have been thrown.
|
||||
extern char *Input_skip_or_store_block(boolean store);
|
||||
extern char *input_skip_or_store_block(boolean store);
|
||||
|
||||
// append optional '.'/'@' prefix to GlobalDynaBuf, then keep
|
||||
// appending while characters are legal for keywords.
|
||||
// throw "missing string" error if none.
|
||||
// return whether there was an error.
|
||||
extern int Input_append_symbol_name_to_global_dynabuf(void);
|
||||
extern int input_append_symbol_name_to_global_dynabuf(void);
|
||||
|
||||
// FIXME - move these to "symbol.h" and remove dependency on "scope":
|
||||
// read symbol name into GlobalDynaBuf, set scope,
|
||||
// return whether there was an error (namely, "no string given").
|
||||
extern int Input_readscopeandsymbolname(scope_t *scope, boolean dotkluge);
|
||||
#define Input_read_scope_and_symbol_name(scope) Input_readscopeandsymbolname(scope, FALSE)
|
||||
#define Input_read_scope_and_symbol_name_KLUGED(scope) Input_readscopeandsymbolname(scope, TRUE)
|
||||
extern int input_readscopeandsymbolname(scope_t *scope, boolean dotkluge);
|
||||
#define input_read_scope_and_symbol_name(scope) input_readscopeandsymbolname(scope, FALSE)
|
||||
#define input_read_scope_and_symbol_name_KLUGED(scope) input_readscopeandsymbolname(scope, TRUE)
|
||||
|
||||
// Clear dynamic buffer, then append to it until an illegal (for a keyword)
|
||||
// character is read. Zero-terminate the string. Return its length (without
|
||||
// terminator).
|
||||
// Zero lengths will produce a "missing string" error.
|
||||
extern int Input_read_keyword(void);
|
||||
extern int input_read_keyword(void);
|
||||
|
||||
// Clear dynamic buffer, then append to it until an illegal (for a keyword)
|
||||
// character is read. Zero-terminate the string, then convert to lower case.
|
||||
// Return its length (without terminator).
|
||||
// Zero lengths will produce a "missing string" error.
|
||||
extern int Input_read_and_lower_keyword(void);
|
||||
extern int input_read_and_lower_keyword(void);
|
||||
|
||||
// Try to read a file name.
|
||||
// If "allow_library" is TRUE, library access by using <...> quoting
|
||||
// is possible as well. If "uses_lib" is non-NULL, info about library
|
||||
@ -120,19 +124,23 @@ extern int Input_read_and_lower_keyword(void);
|
||||
// UNIX style to platform style.
|
||||
// Returns nonzero on error. Filename in GlobalDynaBuf.
|
||||
// Errors are handled and reported, but caller should call
|
||||
// Input_skip_remainder() then.
|
||||
extern int Input_read_filename(boolean library_allowed, boolean *uses_lib);
|
||||
// input_skip_remainder() then.
|
||||
extern int input_read_filename(boolean library_allowed, boolean *uses_lib);
|
||||
|
||||
// Try to read a comma, skipping spaces before and after. Return TRUE if comma
|
||||
// found, otherwise FALSE.
|
||||
extern int Input_accept_comma(void);
|
||||
extern int input_accept_comma(void);
|
||||
|
||||
// read optional info about parameter length
|
||||
extern bits Input_get_force_bit(void);
|
||||
// FIXME - move to different file!
|
||||
extern bits input_get_force_bit(void);
|
||||
|
||||
|
||||
// include path stuff - should be moved to its own file:
|
||||
|
||||
// add entry
|
||||
extern void includepaths_add(const char *path);
|
||||
|
||||
// open file for reading (trying list entries as prefixes)
|
||||
// "uses_lib" tells whether to access library or to make use of include paths
|
||||
// file name is expected in GlobalDynaBuf
|
||||
|
56
src/macro.c
56
src/macro.c
@ -74,7 +74,7 @@ static scope_t get_scope_and_title(void)
|
||||
{
|
||||
scope_t macro_scope;
|
||||
|
||||
Input_read_scope_and_symbol_name(¯o_scope); // skips spaces before
|
||||
input_read_scope_and_symbol_name(¯o_scope); // skips spaces before
|
||||
// now GotByte = illegal character after title
|
||||
// copy macro title to private dynabuf and add separator character
|
||||
dynabuf_clear(user_macro_name);
|
||||
@ -92,7 +92,7 @@ static int pipe_comma(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = Input_accept_comma();
|
||||
result = input_accept_comma();
|
||||
if (result)
|
||||
DYNABUF_APPEND(GlobalDynaBuf, ',');
|
||||
return result;
|
||||
@ -112,7 +112,7 @@ static char *get_string_copy(const char *original)
|
||||
|
||||
// This function is called from both macro definition and macro call.
|
||||
// Terminate macro name and copy from internal_name to GlobalDynaBuf
|
||||
// (because that's where Tree_hard_scan() looks for the search string).
|
||||
// (because that's where tree_hard_scan() looks for the search string).
|
||||
// Then try to find macro and return whether it was created.
|
||||
static int search_for_macro(struct rwnode **result, scope_t scope, int create)
|
||||
{
|
||||
@ -121,7 +121,7 @@ static int search_for_macro(struct rwnode **result, scope_t scope, int create)
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
dynabuf_add_string(GlobalDynaBuf, internal_name->buffer);
|
||||
dynabuf_append(GlobalDynaBuf, '\0');
|
||||
return Tree_hard_scan(result, macro_forest, scope, create);
|
||||
return tree_hard_scan(result, macro_forest, scope, create);
|
||||
}
|
||||
|
||||
// This function is called when an already existing macro is re-defined.
|
||||
@ -134,10 +134,10 @@ static void report_redefinition(struct rwnode *macro_node)
|
||||
|
||||
// show warning with location of current definition
|
||||
Throw_warning(exception_macro_twice);
|
||||
// CAUTION, ugly kluge: fiddle with Input_now and section_now
|
||||
// CAUTION, ugly kluge: fiddle with input_now and section_now
|
||||
// data to generate helpful error messages
|
||||
Input_now->original_filename = original_macro->def_filename;
|
||||
Input_now->line_number = original_macro->def_line_number;
|
||||
input_now->original_filename = original_macro->def_filename;
|
||||
input_now->line_number = original_macro->def_line_number;
|
||||
section_now->type = "original";
|
||||
section_now->title = "definition";
|
||||
// show serious error with location of original definition
|
||||
@ -147,7 +147,7 @@ static void report_redefinition(struct rwnode *macro_node)
|
||||
// This function is only called during the first pass, so there's no need to
|
||||
// check whether to skip the definition or not.
|
||||
// Return with GotByte = '}'
|
||||
void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
void macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
{
|
||||
char *formal_parameters;
|
||||
struct rwnode *macro_node;
|
||||
@ -179,7 +179,7 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
GetByte();
|
||||
}
|
||||
// handle symbol name (including '.'/'@' prefix)
|
||||
Input_append_symbol_name_to_global_dynabuf();
|
||||
input_append_symbol_name_to_global_dynabuf();
|
||||
} while (pipe_comma());
|
||||
// ensure CHAR_SOB ('{')
|
||||
if (GotByte != CHAR_SOB)
|
||||
@ -198,17 +198,17 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
report_redefinition(macro_node); // quits with serious error
|
||||
// Create new macro struct and set it up. Finally we'll read the body.
|
||||
new_macro = safe_malloc(sizeof(*new_macro));
|
||||
new_macro->def_line_number = Input_now->line_number;
|
||||
new_macro->def_filename = get_string_copy(Input_now->original_filename);
|
||||
new_macro->def_line_number = input_now->line_number;
|
||||
new_macro->def_filename = get_string_copy(input_now->original_filename);
|
||||
new_macro->original_name = get_string_copy(user_macro_name->buffer);
|
||||
new_macro->parameter_list = formal_parameters;
|
||||
new_macro->body = Input_skip_or_store_block(TRUE); // changes LineNumber
|
||||
new_macro->body = input_skip_or_store_block(TRUE); // changes LineNumber
|
||||
macro_node->body = new_macro; // link macro struct to tree node
|
||||
// and that about sums it up
|
||||
}
|
||||
|
||||
// Parse macro call ("+MACROTITLE"). Has to be re-entrant.
|
||||
void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
void macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
{
|
||||
char local_gotbyte;
|
||||
struct symbol *symbol;
|
||||
@ -251,7 +251,7 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
// read call-by-reference arg
|
||||
dynabuf_append(internal_name, ARGTYPE_REF);
|
||||
GetByte(); // eat '~'
|
||||
Input_read_scope_and_symbol_name(&symbol_scope);
|
||||
input_read_scope_and_symbol_name(&symbol_scope);
|
||||
// GotByte = illegal char
|
||||
arg_table[arg_count].symbol = symbol_find(symbol_scope); // CAUTION, object type may be NULL!
|
||||
} else {
|
||||
@ -260,7 +260,7 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
ALU_any_result(&(arg_table[arg_count].result));
|
||||
}
|
||||
++arg_count;
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
}
|
||||
// now arg_table contains the arguments
|
||||
// now GlobalDynaBuf = unused
|
||||
@ -269,7 +269,7 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
search_for_macro(¯o_node, macro_scope, FALSE);
|
||||
if (macro_node == NULL) {
|
||||
Throw_error("Macro not defined (or wrong signature).");
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
} else {
|
||||
// make macro_node point to the macro struct
|
||||
actual_macro = macro_node->body;
|
||||
@ -282,9 +282,9 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others!
|
||||
new_input.src.ram_ptr = actual_macro->parameter_list;
|
||||
// remember old input
|
||||
outer_input = Input_now;
|
||||
outer_input = input_now;
|
||||
// activate new input
|
||||
Input_now = &new_input;
|
||||
input_now = &new_input;
|
||||
|
||||
outer_err_count = Throw_get_counter(); // remember error count (for call stack decision)
|
||||
|
||||
@ -305,15 +305,15 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
if (GotByte == REFERENCE_CHAR) {
|
||||
// assign call-by-reference arg
|
||||
GetByte(); // eat '~'
|
||||
Input_read_scope_and_symbol_name(&symbol_scope);
|
||||
input_read_scope_and_symbol_name(&symbol_scope);
|
||||
// create new tree node and link existing symbol struct from arg list to it
|
||||
if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_scope, TRUE) == FALSE)
|
||||
if ((tree_hard_scan(&symbol_node, symbols_forest, symbol_scope, TRUE) == FALSE)
|
||||
&& (FIRST_PASS))
|
||||
Throw_error("Macro parameter twice.");
|
||||
symbol_node->body = arg_table[arg_count].symbol; // CAUTION, object type may be NULL
|
||||
} else {
|
||||
// assign call-by-value arg
|
||||
Input_read_scope_and_symbol_name(&symbol_scope);
|
||||
input_read_scope_and_symbol_name(&symbol_scope);
|
||||
symbol = symbol_find(symbol_scope);
|
||||
// FIXME - find out if symbol was just created.
|
||||
// Then check for the same error message here as above ("Macro parameter twice.").
|
||||
@ -321,21 +321,21 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
symbol->object = arg_table[arg_count].result; // FIXME - this assignment redefines globals/whatever without throwing errors!
|
||||
}
|
||||
++arg_count;
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
}
|
||||
// and now, finally, parse the actual macro body
|
||||
Input_now->state = INPUTSTATE_NORMAL; // FIXME - fix others!
|
||||
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();
|
||||
input_now->src.ram_ptr = actual_macro->body;
|
||||
parse_until_eob_or_eof();
|
||||
if (GotByte != CHAR_EOB)
|
||||
Bug_found("IllegalBlockTerminator", GotByte);
|
||||
BUG("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;
|
||||
input_now = outer_input;
|
||||
// restore old Gotbyte context
|
||||
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
||||
|
||||
@ -343,7 +343,7 @@ void Macro_parse_call(void) // Now GotByte = first char of macro name
|
||||
if (Throw_get_counter() != outer_err_count)
|
||||
Throw_warning("...called from here.");
|
||||
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
}
|
||||
++macro_recursions_left; // leave this nesting level
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2016 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Macro stuff
|
||||
@ -13,9 +13,10 @@
|
||||
// Prototypes
|
||||
|
||||
// only call once (during first pass)
|
||||
extern void Macro_parse_definition(void);
|
||||
extern void macro_parse_definition(void);
|
||||
|
||||
// Parse macro call ("+MACROTITLE"). Has to be re-entrant.
|
||||
extern void Macro_parse_call(void);
|
||||
extern void macro_parse_call(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
78
src/mnemo.c
78
src/mnemo.c
@ -536,7 +536,7 @@ static struct ronode mnemo_m65_tree[] = {
|
||||
// TODO: add pointer arg for result, use return value to indicate parse error!
|
||||
static int get_index(void)
|
||||
{
|
||||
if (!Input_accept_comma())
|
||||
if (!input_accept_comma())
|
||||
return INDEX_NONE;
|
||||
|
||||
// there was a comma, so check next character (spaces will have been skipped):
|
||||
@ -636,7 +636,7 @@ static bits get_addr_mode(struct number *result)
|
||||
address_mode_bits |= AMB_INDEX(get_index());
|
||||
}
|
||||
// ensure end of line
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
//printf("AM: %x\n", address_mode_bits);
|
||||
return address_mode_bits;
|
||||
}
|
||||
@ -772,13 +772,13 @@ static bits calc_arg_size(bits force_bit, struct number *argument, bits addressi
|
||||
// Mnemonics using only implied addressing.
|
||||
static void group_only_implied_addressing(int opcode)
|
||||
{
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
// TODO - accept argument and complain about it? error message should tell more than "garbage data at end of line"!
|
||||
// for 65ce02 and 4502, warn about buggy decimal mode
|
||||
if ((opcode == 0xf8) && (CPU_state.type->flags & CPUFLAG_DECIMALSUBTRACTBUGGY))
|
||||
Throw_first_pass_warning("Found SED instruction for CPU with known decimal SBC bug.");
|
||||
Output_byte(opcode);
|
||||
Input_ensure_EOS();
|
||||
output_byte(opcode);
|
||||
input_ensure_EOS();
|
||||
}
|
||||
|
||||
// helper function to output "Target not in bank" message
|
||||
@ -819,10 +819,10 @@ static void near_branch(int preoffset)
|
||||
}
|
||||
// this fn has its own range check (see above).
|
||||
// No reason to irritate the user with another error message,
|
||||
// so use Output_byte() instead of output_8()
|
||||
// so use output_byte() instead of output_8()
|
||||
//output_8(offset);
|
||||
Output_byte(offset);
|
||||
Input_ensure_EOS();
|
||||
output_byte(offset);
|
||||
input_ensure_EOS();
|
||||
}
|
||||
|
||||
// helper function for relative addressing with 16-bit offset
|
||||
@ -844,7 +844,7 @@ static void far_branch(int preoffset)
|
||||
}
|
||||
}
|
||||
output_le16(offset);
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
}
|
||||
|
||||
// set addressing mode bits depending on which opcodes exist, then calculate
|
||||
@ -861,15 +861,15 @@ static void make_instruction(bits force_bit, struct number *result, unsigned lon
|
||||
addressing_modes |= MAYBE_____3;
|
||||
switch (calc_arg_size(force_bit, result, addressing_modes)) {
|
||||
case NUMBER_FORCES_8:
|
||||
Output_byte(opcodes & 255);
|
||||
output_byte(opcodes & 255);
|
||||
output_8(result->val.intval);
|
||||
break;
|
||||
case NUMBER_FORCES_16:
|
||||
Output_byte((opcodes >> 8) & 255);
|
||||
output_byte((opcodes >> 8) & 255);
|
||||
output_le16(result->val.intval);
|
||||
break;
|
||||
case NUMBER_FORCES_24:
|
||||
Output_byte((opcodes >> 16) & 255);
|
||||
output_byte((opcodes >> 16) & 255);
|
||||
output_le24(result->val.intval);
|
||||
}
|
||||
}
|
||||
@ -895,7 +895,7 @@ static unsigned int imm_ops(bits *force_bit, unsigned char opcode, bits immediat
|
||||
long_register = CPU_state.xy_are_long;
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalImmediateMode", immediate_mode);
|
||||
BUG("IllegalImmediateMode", immediate_mode);
|
||||
}
|
||||
// if the CPU does not support long registers...
|
||||
if ((CPU_state.type->flags & CPUFLAG_SUPPORTSLONGREGS) == 0)
|
||||
@ -923,7 +923,7 @@ static void group_main(int index, bits flags)
|
||||
{
|
||||
unsigned long immediate_opcodes;
|
||||
struct number result;
|
||||
bits force_bit = Input_get_force_bit(); // skips spaces after
|
||||
bits force_bit = input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_addr_mode(&result)) {
|
||||
case IMMEDIATE_ADDRESSING: // #$ff or #$ffff (depending on accu length)
|
||||
@ -962,7 +962,7 @@ static void group_main(int index, bits flags)
|
||||
case LONG_INDIRECT_ADDRESSING: // [$ff] for 65816 and m65
|
||||
// if in quad mode, m65 encodes this as NOP + ($ff),z
|
||||
if (flags & LI_PREFIX_NOP)
|
||||
Output_byte(0xea);
|
||||
output_byte(0xea);
|
||||
make_instruction(force_bit, &result, accu_lind8[index]);
|
||||
break;
|
||||
case LONG_INDIRECT_Y_INDEXED_ADDRESSING: // [$ff],y only for 65816
|
||||
@ -974,7 +974,7 @@ static void group_main(int index, bits flags)
|
||||
case LONG_INDIRECT_Z_INDEXED_ADDRESSING: // [$ff],z only for m65
|
||||
// if not in quad mode, m65 encodes this as NOP + ($ff),z
|
||||
if (flags & LI_PREFIX_NOP)
|
||||
Output_byte(0xea);
|
||||
output_byte(0xea);
|
||||
make_instruction(force_bit, &result, accu_lindz8[index]);
|
||||
break;
|
||||
default: // other combinations are illegal
|
||||
@ -987,12 +987,12 @@ static void group_misc(int index, bits immediate_mode)
|
||||
{
|
||||
unsigned long immediate_opcodes;
|
||||
struct number result;
|
||||
bits force_bit = Input_get_force_bit(); // skips spaces after
|
||||
bits force_bit = input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_addr_mode(&result)) {
|
||||
case IMPLIED_ADDRESSING: // implied addressing
|
||||
if (misc_impl[index])
|
||||
Output_byte(misc_impl[index]);
|
||||
output_byte(misc_impl[index]);
|
||||
else
|
||||
Throw_error(exception_illegal_combination);
|
||||
break;
|
||||
@ -1028,8 +1028,8 @@ static void group_misc(int index, bits immediate_mode)
|
||||
// mnemonics using only 8bit relative addressing (short branch instructions).
|
||||
static void group_std_branches(int opcode)
|
||||
{
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
Output_byte(opcode);
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
output_byte(opcode);
|
||||
near_branch(2);
|
||||
}
|
||||
|
||||
@ -1037,13 +1037,13 @@ static void group_std_branches(int opcode)
|
||||
static void group_bbr_bbs(int opcode)
|
||||
{
|
||||
struct number zpmem;
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
|
||||
get_int_arg(&zpmem, TRUE);
|
||||
typesystem_want_addr(&zpmem);
|
||||
if (Input_accept_comma()) {
|
||||
Output_byte(opcode);
|
||||
Output_byte(zpmem.val.intval);
|
||||
if (input_accept_comma()) {
|
||||
output_byte(opcode);
|
||||
output_byte(zpmem.val.intval);
|
||||
near_branch(3);
|
||||
} else {
|
||||
Throw_error(exception_syntax);
|
||||
@ -1053,8 +1053,8 @@ static void group_bbr_bbs(int opcode)
|
||||
// mnemonics using only 16bit relative addressing (BRL and PER of 65816, and the long branches of 65ce02)
|
||||
static void group_relative16(int opcode, int preoffset)
|
||||
{
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
Output_byte(opcode);
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
output_byte(opcode);
|
||||
far_branch(preoffset);
|
||||
}
|
||||
|
||||
@ -1065,7 +1065,7 @@ static void group_mvn_mvp(int opcode)
|
||||
boolean unmatched_hash = FALSE;
|
||||
struct number source,
|
||||
target;
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
|
||||
// assembler syntax: "mnemonic source, target" or "mnemonic #source, #target"
|
||||
// machine language order: "opcode target source"
|
||||
@ -1078,7 +1078,7 @@ static void group_mvn_mvp(int opcode)
|
||||
get_int_arg(&source, TRUE);
|
||||
typesystem_want_nonaddr(&source);
|
||||
// get comma
|
||||
if (!Input_accept_comma()) {
|
||||
if (!input_accept_comma()) {
|
||||
Throw_error(exception_syntax);
|
||||
return;
|
||||
}
|
||||
@ -1090,32 +1090,32 @@ static void group_mvn_mvp(int opcode)
|
||||
get_int_arg(&target, TRUE);
|
||||
typesystem_want_nonaddr(&target);
|
||||
// output
|
||||
Output_byte(opcode);
|
||||
output_byte(opcode);
|
||||
output_8(target.val.intval);
|
||||
output_8(source.val.intval);
|
||||
// sanity check
|
||||
if (unmatched_hash)
|
||||
Throw_error(exception_syntax);
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
}
|
||||
|
||||
// "rmb0..7" and "smb0..7"
|
||||
static void group_only_zp(int opcode)
|
||||
{
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
struct number target;
|
||||
|
||||
get_int_arg(&target, TRUE);
|
||||
typesystem_want_addr(&target);
|
||||
Output_byte(opcode);
|
||||
output_byte(opcode);
|
||||
output_8(target.val.intval);
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
}
|
||||
|
||||
// NOP on m65 cpu (FIXME - "!align" outputs NOPs, what about that? what if user writes NEG:NEG?)
|
||||
static void group_prefix(int opcode)
|
||||
{
|
||||
//bits force_bit = Input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
//bits force_bit = input_get_force_bit(); // skips spaces after // TODO - accept postfix and complain about it?
|
||||
char buffer[100]; // 640K should be enough for anybody
|
||||
|
||||
sprintf(buffer, "The chosen CPU uses opcode 0x%02x as a prefix code, do not use this mnemonic!", opcode);
|
||||
@ -1126,7 +1126,7 @@ static void group_prefix(int opcode)
|
||||
static void group_jump(int index)
|
||||
{
|
||||
struct number result;
|
||||
bits force_bit = Input_get_force_bit(); // skips spaces after
|
||||
bits force_bit = input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_addr_mode(&result)) {
|
||||
case ABSOLUTE_ADDRESSING: // absolute16 or absolute24
|
||||
@ -1159,14 +1159,14 @@ static boolean check_mnemo_tree(struct ronode *tree, struct dynabuf *dyna_buf)
|
||||
bits flags;
|
||||
|
||||
// search for tree item
|
||||
if (!Tree_easy_scan(tree, &node_body, dyna_buf))
|
||||
if (!tree_easy_scan(tree, &node_body, dyna_buf))
|
||||
return FALSE;
|
||||
|
||||
code = ((int) node_body) & CODEMASK; // get opcode or table index
|
||||
flags = ((int) node_body) & FLAGSMASK; // get immediate mode flags and prefix flags
|
||||
if (flags & PREFIX_NEGNEG) {
|
||||
Output_byte(0x42);
|
||||
Output_byte(0x42);
|
||||
output_byte(0x42);
|
||||
output_byte(0x42);
|
||||
}
|
||||
switch (GROUP((long) node_body)) {
|
||||
case GROUP_ACCU: // main accumulator stuff
|
||||
@ -1203,7 +1203,7 @@ static boolean check_mnemo_tree(struct ronode *tree, struct dynabuf *dyna_buf)
|
||||
group_prefix(code);
|
||||
break;
|
||||
default: // others indicate bugs
|
||||
Bug_found("IllegalGroupIndex", code);
|
||||
BUG("IllegalGroupIndex", code);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
11
src/mnemo.h
11
src/mnemo.h
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// mnemonic definitions
|
||||
@ -12,22 +12,31 @@
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by standard 6502 cpu.
|
||||
extern boolean keyword_is_6502_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by NMOS 6502 cpu (includes undocumented opcodes).
|
||||
extern boolean keyword_is_nmos6502_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by C64DTV2 cpu.
|
||||
extern boolean keyword_is_c64dtv2_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by 65C02 cpu.
|
||||
extern boolean keyword_is_65c02_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65C02 cpu.
|
||||
extern boolean keyword_is_r65c02_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by WDC 65C02 cpu.
|
||||
extern boolean keyword_is_w65c02_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu.
|
||||
extern boolean keyword_is_65816_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by CSG 65CE02 cpu.
|
||||
extern boolean keyword_is_65ce02_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by CSG 4502 cpu.
|
||||
extern boolean keyword_is_4502_mnemo(int length);
|
||||
|
||||
// check whether mnemonic in GlobalDynaBuf is supported by MEGA65 cpu.
|
||||
extern boolean keyword_is_m65_mnemo(int length);
|
||||
|
||||
|
37
src/output.c
37
src/output.c
@ -135,7 +135,7 @@ static void border_crossed(int current_offset)
|
||||
|
||||
|
||||
// function ptr to write byte into output buffer (might point to real fn or error trigger)
|
||||
void (*Output_byte)(intval_t byte);
|
||||
void (*output_byte)(intval_t byte);
|
||||
|
||||
|
||||
// send low byte to output buffer, automatically increasing program counter
|
||||
@ -165,14 +165,14 @@ static void no_output(intval_t byte)
|
||||
{
|
||||
Throw_error(exception_pc_undefined);
|
||||
// now change fn ptr to not complain again.
|
||||
Output_byte = real_output;
|
||||
Output_byte(byte); // try again
|
||||
output_byte = real_output;
|
||||
output_byte(byte); // try again
|
||||
}
|
||||
|
||||
|
||||
// skip over some bytes in output buffer without starting a new segment
|
||||
// (used by "!skip", and also called by "!binary" if really calling
|
||||
// Output_byte would be a waste of time)
|
||||
// output_byte would be a waste of time)
|
||||
void output_skip(int size)
|
||||
{
|
||||
if (size < 1) {
|
||||
@ -182,8 +182,8 @@ void output_skip(int size)
|
||||
}
|
||||
|
||||
// check whether ptr undefined
|
||||
if (Output_byte == no_output) {
|
||||
Output_byte(0); // trigger error with a dummy byte
|
||||
if (output_byte == no_output) {
|
||||
output_byte(0); // trigger error with a dummy byte
|
||||
--size; // fix amount to cater for dummy byte
|
||||
}
|
||||
// CAUTION - there are two copies of these checks!
|
||||
@ -212,7 +212,7 @@ static void fill_completely(char value)
|
||||
|
||||
// define default value for empty memory ("!initmem" pseudo opcode)
|
||||
// returns zero if ok, nonzero if already set
|
||||
int output_initmem(char content)
|
||||
int output_setdefault(char content)
|
||||
{
|
||||
// if MemInit flag is already set, complain
|
||||
if (out->initvalue_set) {
|
||||
@ -241,7 +241,7 @@ int outputfile_set_format(void)
|
||||
void *node_body;
|
||||
|
||||
// perform lookup
|
||||
if (!Tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf))
|
||||
if (!tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf))
|
||||
return 1;
|
||||
|
||||
output_format = (enum output_format) node_body;
|
||||
@ -276,7 +276,7 @@ int outputfile_set_filename(void)
|
||||
|
||||
|
||||
// init output struct (done later)
|
||||
void Output_init(signed long fill_value, boolean use_large_buf)
|
||||
void output_createbuffer(signed long fill_value, boolean use_large_buf)
|
||||
{
|
||||
out->bufsize = use_large_buf ? 0x1000000 : 0x10000;
|
||||
out->buffer = safe_malloc(out->bufsize);
|
||||
@ -295,7 +295,7 @@ void Output_init(signed long fill_value, boolean use_large_buf)
|
||||
|
||||
|
||||
// dump used portion of output buffer into output file
|
||||
void Output_save_file(FILE *fd)
|
||||
void output_save_file(FILE *fd)
|
||||
{
|
||||
intval_t start,
|
||||
amount;
|
||||
@ -388,7 +388,7 @@ static void check_segment(intval_t new_pc)
|
||||
|
||||
|
||||
// clear segment list and disable output
|
||||
void Output_passinit(void)
|
||||
void output_passinit(void)
|
||||
{
|
||||
// struct segment *temp;
|
||||
|
||||
@ -405,7 +405,7 @@ void Output_passinit(void)
|
||||
out->lowest_written = out->bufsize - 1;
|
||||
out->highest_written = 0;
|
||||
// deactivate output - any byte written will trigger error:
|
||||
Output_byte = no_output;
|
||||
output_byte = no_output;
|
||||
out->write_idx = 0; // same as pc on pass init!
|
||||
out->segment.start = NO_SEGMENT_START; // TODO - "no active segment" could be made a segment flag!
|
||||
out->segment.max = out->bufsize - 1; // TODO - use end of bank?
|
||||
@ -427,7 +427,7 @@ void Output_passinit(void)
|
||||
|
||||
// show start and end of current segment
|
||||
// called whenever a new segment begins, and at end of pass.
|
||||
void Output_end_segment(void)
|
||||
void output_end_segment(void)
|
||||
{
|
||||
intval_t amount;
|
||||
|
||||
@ -461,17 +461,17 @@ void Output_end_segment(void)
|
||||
|
||||
// change output pointer and enable output
|
||||
// TODO - this only gets called from vcpu_set_pc so could be made static!
|
||||
void Output_start_segment(intval_t address_change, bits segment_flags)
|
||||
void output_start_segment(intval_t address_change, bits segment_flags)
|
||||
{
|
||||
// properly finalize previous segment (link to list, announce)
|
||||
Output_end_segment();
|
||||
output_end_segment();
|
||||
|
||||
// calculate start of new segment
|
||||
out->write_idx = (out->write_idx + address_change) & (out->bufsize - 1);
|
||||
out->segment.start = out->write_idx;
|
||||
out->segment.flags = segment_flags;
|
||||
// allow writing to output buffer
|
||||
Output_byte = real_output;
|
||||
output_byte = real_output;
|
||||
// in first pass, check for other segments and maybe issue warning
|
||||
// TODO - remove FIRST_PASS condition
|
||||
if (FIRST_PASS) {
|
||||
@ -486,6 +486,7 @@ char output_get_xor(void)
|
||||
{
|
||||
return out->xor;
|
||||
}
|
||||
|
||||
void output_set_xor(char xor)
|
||||
{
|
||||
out->xor = xor;
|
||||
@ -518,7 +519,7 @@ void vcpu_set_pc(intval_t new_pc, bits segment_flags)
|
||||
CPU_state.pc.ntype = NUMTYPE_INT; // FIXME - remove when allowing undefined!
|
||||
CPU_state.pc.addr_refs = 1; // yes, PC counts as address
|
||||
// now tell output buffer to start a new segment
|
||||
Output_start_segment(pc_change, segment_flags);
|
||||
output_start_segment(pc_change, segment_flags);
|
||||
}
|
||||
/*
|
||||
TODO - overhaul program counter and memory pointer stuff:
|
||||
@ -604,7 +605,7 @@ void pseudopc_end(void)
|
||||
// encountering "*=".
|
||||
// so if wanted version is new enough, choke on bug!
|
||||
if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF)
|
||||
Bug_found("ClosingUnopenedPseudopcBlock", 0);
|
||||
BUG("ClosingUnopenedPseudopcBlock", 0);
|
||||
} else {
|
||||
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - pseudopc_current_context->offset) & (out->bufsize - 1); // pc might have wrapped around
|
||||
CPU_state.pc.ntype = pseudopc_current_context->ntype;
|
||||
|
40
src/output.h
40
src/output.h
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Output stuff (FIXME - split into outbuf, outfile/format and vcpu parts)
|
||||
@ -37,61 +37,83 @@ extern struct vcpu CPU_state; // current CPU state FIXME - restrict visibility t
|
||||
|
||||
// clear segment list and disable output
|
||||
//TODO - does this belong to outbuf stuff?
|
||||
extern void Output_passinit(void);
|
||||
extern void output_passinit(void);
|
||||
|
||||
|
||||
// outbuf stuff:
|
||||
|
||||
// alloc and init mem buffer (done later)
|
||||
extern void Output_init(signed long fill_value, boolean use_large_buf);
|
||||
extern void output_createbuffer(signed long fill_value, boolean use_large_buf);
|
||||
|
||||
// skip over some bytes in output buffer without starting a new segment
|
||||
// (used by "!skip", and also called by "!binary" if really calling
|
||||
// Output_byte would be a waste of time)
|
||||
// output_byte would be a waste of time)
|
||||
extern void output_skip(int size);
|
||||
|
||||
// Send low byte of arg to output buffer and advance pointer
|
||||
// FIXME - replace by output_sequence(char *src, size_t size)
|
||||
extern void (*Output_byte)(intval_t);
|
||||
extern void (*output_byte)(intval_t);
|
||||
|
||||
// define default value for empty memory ("!initmem" pseudo opcode)
|
||||
// returns zero if ok, nonzero if already set
|
||||
extern int output_initmem(char content);
|
||||
extern int output_setdefault(char content);
|
||||
|
||||
|
||||
// outfile stuff:
|
||||
|
||||
// try to set output format held in DynaBuf. Returns zero on success.
|
||||
extern int outputfile_set_format(void);
|
||||
extern const char outputfile_formats[]; // string to show if outputfile_set_format() returns nonzero
|
||||
|
||||
// if file format was already chosen, returns zero.
|
||||
// if file format isn't set, chooses CBM and returns 1.
|
||||
extern int outputfile_prefer_cbm_format(void);
|
||||
|
||||
// try to set output file name held in DynaBuf. Returns zero on success.
|
||||
extern int outputfile_set_filename(void);
|
||||
|
||||
// write smallest-possible part of memory buffer to file
|
||||
extern void Output_save_file(FILE *fd);
|
||||
extern void output_save_file(FILE *fd);
|
||||
|
||||
// change output pointer and enable output
|
||||
extern void Output_start_segment(intval_t address_change, bits segment_flags);
|
||||
extern void output_start_segment(intval_t address_change, bits segment_flags);
|
||||
|
||||
// Show start and end of current segment
|
||||
extern void Output_end_segment(void);
|
||||
extern void output_end_segment(void);
|
||||
|
||||
extern char output_get_xor(void);
|
||||
|
||||
extern void output_set_xor(char xor);
|
||||
|
||||
// set program counter to defined value (TODO - allow undefined!)
|
||||
extern void vcpu_set_pc(intval_t new_pc, bits flags);
|
||||
|
||||
// get program counter
|
||||
extern void vcpu_read_pc(struct number *target);
|
||||
|
||||
// get size of current statement (until now) - needed for "!bin" verbose output
|
||||
extern int vcpu_get_statement_size(void);
|
||||
|
||||
// adjust program counter (called at end of each statement)
|
||||
extern void vcpu_end_statement(void);
|
||||
|
||||
|
||||
// pseudopc stuff:
|
||||
struct pseudopc;
|
||||
|
||||
// start offset assembly
|
||||
extern void pseudopc_start(struct number *new_pc);
|
||||
|
||||
// end offset assembly
|
||||
extern void pseudopc_end(void);
|
||||
|
||||
// this is only for old, deprecated, obsolete, stupid "realpc":
|
||||
extern void pseudopc_end_all(void);
|
||||
|
||||
// un-pseudopc a label value by given number of levels
|
||||
// returns nonzero on error (if level too high)
|
||||
extern int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels);
|
||||
|
||||
// return pointer to current "pseudopc" struct (may be NULL!)
|
||||
// this gets called when parsing label definitions
|
||||
extern struct pseudopc *pseudopc_get_context(void);
|
||||
|
@ -52,9 +52,9 @@ void notreallypo_setpc(void) // GotByte is '*'
|
||||
GetByte();
|
||||
ALU_defined_int(&intresult); // read new address
|
||||
// check for modifiers
|
||||
while (Input_accept_comma()) {
|
||||
while (input_accept_comma()) {
|
||||
// parse modifier. if no keyword given, give up
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
goto fail;
|
||||
|
||||
if (strcmp(GlobalDynaBuf->buffer, "overlay") == 0) {
|
||||
@ -78,11 +78,11 @@ void notreallypo_setpc(void) // GotByte is '*'
|
||||
}
|
||||
vcpu_set_pc(intresult.val.intval, segment_flags);
|
||||
// TODO - allow block syntax, so it is possible to put data "somewhere else" and then return to old position?
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
return;
|
||||
|
||||
fail:
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
}
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ static enum eos po_initmem(void)
|
||||
ALU_defined_int(&intresult);
|
||||
if ((intresult.val.intval > 255) || (intresult.val.intval < -128))
|
||||
Throw_error(exception_number_out_of_8b_range);
|
||||
if (output_initmem(intresult.val.intval & 0xff))
|
||||
if (output_setdefault(intresult.val.intval & 0xff))
|
||||
return SKIP_REMAINDER;
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
@ -120,7 +120,7 @@ static enum eos po_xor(void)
|
||||
}
|
||||
output_set_xor(old_value ^ change);
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (Parse_optional_block())
|
||||
if (parse_optional_block())
|
||||
output_set_xor(old_value);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
@ -136,7 +136,7 @@ static enum eos po_to(void)
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (Input_read_filename(FALSE, NULL))
|
||||
if (input_read_filename(FALSE, NULL))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// only act upon this pseudo opcode in first pass
|
||||
@ -148,7 +148,7 @@ static enum eos po_to(void)
|
||||
|
||||
// select output format
|
||||
// if no comma found, use default file format
|
||||
if (Input_accept_comma() == FALSE) {
|
||||
if (input_accept_comma() == FALSE) {
|
||||
if (outputfile_prefer_cbm_format()) {
|
||||
// output deprecation warning (unless user requests really old behaviour)
|
||||
if (config.wanted_version >= VER_DEPRECATE_REALPC)
|
||||
@ -159,7 +159,7 @@ static enum eos po_to(void)
|
||||
|
||||
// parse output format name
|
||||
// if no keyword given, give up
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
if (outputfile_set_format()) {
|
||||
@ -183,7 +183,7 @@ static enum eos iterate(void (*fn)(intval_t))
|
||||
do {
|
||||
ALU_any_result(&object);
|
||||
output_object(&object, &iter);
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ static enum eos po_hex(void) // now GotByte = illegal char
|
||||
|
||||
for (;;) {
|
||||
if (digits == 2) {
|
||||
Output_byte(byte);
|
||||
output_byte(byte);
|
||||
digits = 0;
|
||||
byte = 0;
|
||||
}
|
||||
@ -324,7 +324,7 @@ static enum eos user_defined_encoding(FILE *stream)
|
||||
encoder_current = &encoder_file; // activate new encoding
|
||||
encoding_loaded_table = local_table; // activate local table
|
||||
// if there's a block, parse that and then restore old values
|
||||
if (Parse_optional_block()) {
|
||||
if (parse_optional_block()) {
|
||||
encoder_current = buffered_encoder;
|
||||
} else {
|
||||
// if there's *no* block, the table must be used from now on.
|
||||
@ -344,7 +344,7 @@ static enum eos predefined_encoding(void)
|
||||
*buffered_table = encoding_loaded_table;
|
||||
const struct encoder *buffered_encoder = encoder_current;
|
||||
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
if (input_read_and_lower_keyword()) {
|
||||
const struct encoder *new_encoder = encoding_find();
|
||||
|
||||
if (new_encoder)
|
||||
@ -352,7 +352,7 @@ static enum eos predefined_encoding(void)
|
||||
}
|
||||
encoding_loaded_table = local_table; // activate local table
|
||||
// if there's a block, parse that and then restore old values
|
||||
if (Parse_optional_block())
|
||||
if (parse_optional_block())
|
||||
encoder_current = buffered_encoder;
|
||||
// re-activate "outer" table
|
||||
encoding_loaded_table = buffered_table;
|
||||
@ -367,7 +367,7 @@ static enum eos po_convtab(void)
|
||||
|
||||
if ((GotByte == '<') || (GotByte == '"')) {
|
||||
// encoding table from file
|
||||
if (Input_read_filename(TRUE, &uses_lib))
|
||||
if (input_read_filename(TRUE, &uses_lib))
|
||||
return SKIP_REMAINDER; // missing or unterminated file name
|
||||
|
||||
stream = includepaths_open_ro(uses_lib);
|
||||
@ -397,13 +397,13 @@ static enum eos encode_string(const struct encoder *inner_encoder, unsigned char
|
||||
int offset;
|
||||
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
if (Input_quoted_to_dynabuf('"'))
|
||||
if (input_quoted_to_dynabuf('"'))
|
||||
return SKIP_REMAINDER; // unterminated or escaping error
|
||||
|
||||
// eat closing quote
|
||||
GetByte();
|
||||
// now convert to unescaped version
|
||||
if (Input_unescape_dynabuf(0))
|
||||
if (input_unescape_dynabuf(0))
|
||||
return SKIP_REMAINDER; // escaping error
|
||||
|
||||
// send characters
|
||||
@ -416,7 +416,7 @@ static enum eos encode_string(const struct encoder *inner_encoder, unsigned char
|
||||
ALU_any_result(&object);
|
||||
output_object(&object, &iter);
|
||||
}
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
encoder_current = outer_encoder; // reactivate buffered encoder
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
@ -446,7 +446,7 @@ static enum eos po_scrxor(void)
|
||||
intval_t xor;
|
||||
|
||||
ALU_any_int(&xor);
|
||||
if (Input_accept_comma() == FALSE) {
|
||||
if (input_accept_comma() == FALSE) {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
@ -467,7 +467,7 @@ static enum eos po_binary(void)
|
||||
skip.val.intval = 0;
|
||||
|
||||
// if file name is missing, don't bother continuing
|
||||
if (Input_read_filename(TRUE, &uses_lib))
|
||||
if (input_read_filename(TRUE, &uses_lib))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// try to open file
|
||||
@ -476,7 +476,7 @@ static enum eos po_binary(void)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// read optional arguments
|
||||
if (Input_accept_comma()) {
|
||||
if (input_accept_comma()) {
|
||||
// any size given?
|
||||
if ((GotByte != ',') && (GotByte != CHAR_EOS)) {
|
||||
// then parse it
|
||||
@ -485,7 +485,7 @@ static enum eos po_binary(void)
|
||||
Throw_serious_error(exception_negative_size);
|
||||
}
|
||||
// more?
|
||||
if (Input_accept_comma()) {
|
||||
if (input_accept_comma()) {
|
||||
// any skip given?
|
||||
if (GotByte != CHAR_EOS) {
|
||||
// then parse it
|
||||
@ -508,15 +508,15 @@ static enum eos po_binary(void)
|
||||
byte = getc(stream);
|
||||
if (byte == EOF)
|
||||
break;
|
||||
Output_byte(byte);
|
||||
output_byte(byte);
|
||||
--size.val.intval;
|
||||
}
|
||||
// if more should have been read, warn and add padding
|
||||
if (size.val.intval > 0) {
|
||||
Throw_warning("Padding with zeroes.");
|
||||
do
|
||||
Output_byte(0);
|
||||
while (--size.val.intval);
|
||||
do {
|
||||
output_byte(0);
|
||||
} while (--size.val.intval);
|
||||
}
|
||||
}
|
||||
fclose(stream);
|
||||
@ -538,7 +538,7 @@ static enum eos po_fill(void)
|
||||
intval_t fill = FILLVALUE_FILL;
|
||||
|
||||
ALU_defined_int(&sizeresult); // FIXME - forbid addresses!
|
||||
if (Input_accept_comma())
|
||||
if (input_accept_comma())
|
||||
ALU_any_int(&fill); // FIXME - forbid addresses!
|
||||
while (sizeresult.val.intval--)
|
||||
output_8(fill);
|
||||
@ -575,10 +575,10 @@ static enum eos po_align(void)
|
||||
// new: !align BLOCKSIZE
|
||||
// ...where block size must be a power of two
|
||||
ALU_defined_int(&andresult); // FIXME - forbid addresses!
|
||||
if (!Input_accept_comma())
|
||||
if (!input_accept_comma())
|
||||
Throw_error(exception_syntax);
|
||||
ALU_defined_int(&equalresult); // ...allow addresses (unlikely, but possible)
|
||||
if (Input_accept_comma())
|
||||
if (input_accept_comma())
|
||||
ALU_any_int(&fill);
|
||||
else
|
||||
fill = CPU_state.type->default_align_value;
|
||||
@ -624,9 +624,9 @@ static enum eos po_pseudopc(void)
|
||||
ALU_defined_int(&new_pc); // FIXME - allow for undefined! (complaining about non-addresses would be logical, but annoying)
|
||||
/* TODO - add this. check if code can be shared with "*="!
|
||||
// check for modifiers
|
||||
while (Input_accept_comma()) {
|
||||
while (input_accept_comma()) {
|
||||
// parse modifier. if no keyword given, give up
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
if (strcmp(GlobalDynaBuf->buffer, "limit") == 0) {
|
||||
@ -643,7 +643,7 @@ static enum eos po_pseudopc(void)
|
||||
*/
|
||||
pseudopc_start(&new_pc);
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (Parse_optional_block()) {
|
||||
if (parse_optional_block()) {
|
||||
pseudopc_end(); // restore old state
|
||||
} else {
|
||||
old_offset_assembly();
|
||||
@ -668,7 +668,7 @@ static enum eos po_cpu(void)
|
||||
const struct cpu_type *cpu_buffer = CPU_state.type; // remember current cpu
|
||||
const struct cpu_type *new_cpu_type;
|
||||
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
if (input_read_and_lower_keyword()) {
|
||||
new_cpu_type = cputype_find();
|
||||
if (new_cpu_type)
|
||||
CPU_state.type = new_cpu_type; // activate new cpu type
|
||||
@ -676,7 +676,7 @@ static enum eos po_cpu(void)
|
||||
Throw_error("Unknown processor.");
|
||||
}
|
||||
// if there's a block, parse that and then restore old value
|
||||
if (Parse_optional_block())
|
||||
if (parse_optional_block())
|
||||
CPU_state.type = cpu_buffer;
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
@ -691,7 +691,7 @@ static enum eos set_register_length(boolean *var, boolean make_long)
|
||||
// set new register length (or complain - whichever is more fitting)
|
||||
vcpu_check_and_set_reg_length(var, make_long);
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (Parse_optional_block())
|
||||
if (parse_optional_block())
|
||||
vcpu_check_and_set_reg_length(var, old_size); // restore old length
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
@ -750,10 +750,10 @@ static enum eos po_set(void) // now GotByte = illegal char
|
||||
scope_t scope;
|
||||
int force_bit;
|
||||
|
||||
if (Input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
if (input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
return SKIP_REMAINDER; // zero length
|
||||
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
force_bit = input_get_force_bit(); // skips spaces after
|
||||
if (GotByte != '=') {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
@ -780,7 +780,7 @@ static enum eos po_symbollist(void)
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (Input_read_filename(FALSE, NULL))
|
||||
if (input_read_filename(FALSE, NULL))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// only process this pseudo opcode in first pass
|
||||
@ -818,14 +818,14 @@ static enum eos po_zone(void)
|
||||
if (BYTE_CONTINUES_KEYWORD(GotByte)) {
|
||||
// because we know of one character for sure,
|
||||
// there's no need to check the return value.
|
||||
Input_read_keyword();
|
||||
input_read_keyword();
|
||||
new_title = dynabuf_get_copy(GlobalDynaBuf);
|
||||
allocated = TRUE;
|
||||
}
|
||||
// setup new section
|
||||
// section type is "subzone", just in case a block follows
|
||||
section_new(section_now, "Subzone", new_title, allocated);
|
||||
if (Parse_optional_block()) {
|
||||
if (parse_optional_block()) {
|
||||
// block has been parsed, so it was a SUBzone.
|
||||
section_finalize(section_now); // end inner zone
|
||||
*section_now = entry_values; // restore entry values
|
||||
@ -862,7 +862,7 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
if (--source_recursions_left < 0)
|
||||
Throw_serious_error("Too deeply nested. Recursive \"!source\"?");
|
||||
// read file name. quit function on error
|
||||
if (Input_read_filename(TRUE, &uses_lib))
|
||||
if (input_read_filename(TRUE, &uses_lib))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// if file could be opened, parse it. otherwise, complain
|
||||
@ -876,11 +876,11 @@ static enum eos po_source(void) // now GotByte = illegal char
|
||||
#endif
|
||||
|
||||
strcpy(filename, GLOBALDYNABUF_CURRENT);
|
||||
outer_input = Input_now; // remember old input
|
||||
outer_input = input_now; // remember old input
|
||||
local_gotbyte = GotByte; // CAUTION - ugly kluge
|
||||
Input_now = &new_input; // activate new input
|
||||
input_now = &new_input; // activate new input
|
||||
flow_parse_and_close_file(stream, filename);
|
||||
Input_now = outer_input; // restore previous input
|
||||
input_now = outer_input; // restore previous input
|
||||
GotByte = local_gotbyte; // CAUTION - ugly kluge
|
||||
#ifndef __GNUC__
|
||||
free(filename); // GCC auto-frees
|
||||
@ -924,7 +924,7 @@ static enum eos ifelse(enum ifmode mode)
|
||||
condition_met = TRUE;
|
||||
break;
|
||||
default:
|
||||
Bug_found("IllegalIfMode", mode);
|
||||
BUG("IllegalIfMode", mode);
|
||||
condition_met = TRUE; // inhibit compiler warning ;)
|
||||
}
|
||||
SKIPSPACE();
|
||||
@ -932,7 +932,7 @@ static enum eos ifelse(enum ifmode mode)
|
||||
if (condition_met && nothing_done) {
|
||||
nothing_done = FALSE; // all further ones will be skipped, even if conditions meet
|
||||
if (GotByte == CHAR_SOB) {
|
||||
Parse_until_eob_or_eof(); // parse block
|
||||
parse_until_eob_or_eof(); // parse block
|
||||
// if block isn't correctly terminated, complain and exit
|
||||
if (GotByte != CHAR_EOB)
|
||||
Throw_serious_error(exception_no_right_brace);
|
||||
@ -941,7 +941,7 @@ static enum eos ifelse(enum ifmode mode)
|
||||
}
|
||||
} else {
|
||||
if (GotByte == CHAR_SOB) {
|
||||
Input_skip_or_store_block(FALSE); // skip block
|
||||
input_skip_or_store_block(FALSE); // skip block
|
||||
} else {
|
||||
return SKIP_REMAINDER; // skip line (only for ifdef/ifndef)
|
||||
}
|
||||
@ -961,7 +961,7 @@ static enum eos ifelse(enum ifmode mode)
|
||||
return AT_EOS_ANYWAY; // normal exit if there is no ELSE {...} block
|
||||
|
||||
// read keyword (expected to be "else")
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER; // "missing string error" -> ignore rest of line
|
||||
|
||||
// make sure it's "else"
|
||||
@ -978,7 +978,7 @@ static enum eos ifelse(enum ifmode mode)
|
||||
}
|
||||
|
||||
// read keyword (expected to be if/ifdef/ifndef)
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER; // "missing string error" -> ignore rest of line
|
||||
|
||||
// which one is it?
|
||||
@ -1027,18 +1027,18 @@ static enum eos po_for(void) // now GotByte = illegal char
|
||||
struct for_loop loop;
|
||||
struct number intresult;
|
||||
|
||||
if (Input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
if (input_read_scope_and_symbol_name(&scope)) // skips spaces before
|
||||
return SKIP_REMAINDER; // zero length
|
||||
|
||||
// now GotByte = illegal char
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
force_bit = input_get_force_bit(); // skips spaces after
|
||||
loop.symbol = symbol_find(scope); // if not number, error will be reported on first assignment
|
||||
if (Input_accept_comma()) {
|
||||
if (input_accept_comma()) {
|
||||
// counter syntax (old or new)
|
||||
loop.u.counter.force_bit = force_bit;
|
||||
ALU_defined_int(&intresult); // read first argument
|
||||
loop.u.counter.addr_refs = intresult.addr_refs;
|
||||
if (Input_accept_comma()) {
|
||||
if (input_accept_comma()) {
|
||||
// new counter syntax
|
||||
loop.algorithm = FORALGO_NEWCOUNT;
|
||||
if (config.wanted_version < VER_NEWFORSYNTAX)
|
||||
@ -1086,9 +1086,9 @@ was just a typo. if the current byte is '.' or '-' or whatever, then trying to
|
||||
read a keyword will result in "No string given" - which is confusing for the
|
||||
user if they did not even want to put a string there.
|
||||
so if the current byte is not the start of "in" we just throw a syntax error.
|
||||
knowing there is an "i" also makes sure that Input_read_and_lower_keyword()
|
||||
knowing there is an "i" also makes sure that input_read_and_lower_keyword()
|
||||
does not fail. */
|
||||
Input_read_and_lower_keyword();
|
||||
input_read_and_lower_keyword();
|
||||
if (strcmp(GlobalDynaBuf->buffer, "in") != 0) {
|
||||
Throw_error("Loop var must be followed by either \"in\" keyword or comma.");
|
||||
return SKIP_REMAINDER; // FIXME - this ignores '{' and will then complain about '}'
|
||||
@ -1109,9 +1109,9 @@ does not fail. */
|
||||
Throw_serious_error(exception_no_left_brace);
|
||||
|
||||
// remember line number of loop pseudo opcode
|
||||
loop.block.start = Input_now->line_number;
|
||||
loop.block.start = input_now->line_number;
|
||||
// read loop body into DynaBuf and get copy
|
||||
loop.block.body = Input_skip_or_store_block(TRUE); // changes line number!
|
||||
loop.block.body = input_skip_or_store_block(TRUE); // changes line number!
|
||||
|
||||
flow_forloop(&loop);
|
||||
// free memory
|
||||
@ -1135,9 +1135,9 @@ static enum eos po_do(void) // now GotByte = illegal char
|
||||
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;
|
||||
loop.block.start = input_now->line_number;
|
||||
// reading block changes line number!
|
||||
loop.block.body = Input_skip_or_store_block(TRUE); // must be freed!
|
||||
loop.block.body = input_skip_or_store_block(TRUE); // must be freed!
|
||||
// now GotByte = '}'
|
||||
NEXTANDSKIPSPACE(); // now GotByte = first non-blank char after block
|
||||
// read tail condition to buffer
|
||||
@ -1164,9 +1164,9 @@ static enum eos po_while(void) // now GotByte = illegal char
|
||||
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;
|
||||
loop.block.start = input_now->line_number;
|
||||
// reading block changes line number!
|
||||
loop.block.body = Input_skip_or_store_block(TRUE); // must be freed!
|
||||
loop.block.body = input_skip_or_store_block(TRUE); // must be freed!
|
||||
// clear tail condition
|
||||
loop.tail_cond.body = NULL;
|
||||
flow_do_while(&loop);
|
||||
@ -1184,7 +1184,7 @@ static enum eos po_macro(void) // now GotByte = illegal char
|
||||
{
|
||||
// in first pass, parse. In all other passes, skip.
|
||||
if (FIRST_PASS) {
|
||||
Macro_parse_definition(); // now GotByte = '}'
|
||||
macro_parse_definition(); // now GotByte = '}'
|
||||
} else {
|
||||
// skip until CHAR_SOB ('{') is found.
|
||||
// no need to check for end-of-statement, because such an
|
||||
@ -1192,7 +1192,7 @@ static enum eos po_macro(void) // now GotByte = illegal char
|
||||
// for the same reason, there is no need to check for quotes.
|
||||
while (GotByte != CHAR_SOB)
|
||||
GetByte();
|
||||
Input_skip_or_store_block(FALSE); // now GotByte = '}'
|
||||
input_skip_or_store_block(FALSE); // now GotByte = '}'
|
||||
}
|
||||
GetByte(); // Proceed with next character
|
||||
return ENSURE_EOS;
|
||||
@ -1216,7 +1216,7 @@ static enum eos tracewatch(boolean enter_monitor)
|
||||
if (GotByte != CHAR_EOS) {
|
||||
do {
|
||||
// parse flag. if no keyword given, give up
|
||||
if (Input_read_and_lower_keyword() == 0)
|
||||
if (input_read_and_lower_keyword() == 0)
|
||||
return SKIP_REMAINDER; // fail (error has been reported)
|
||||
|
||||
if (strcmp(GlobalDynaBuf->buffer, "load") == 0) {
|
||||
@ -1229,7 +1229,7 @@ static enum eos tracewatch(boolean enter_monitor)
|
||||
Throw_error("Unknown flag (known are: load, store, exec)."); // FIXME - add to docs!
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
}
|
||||
// shortcut: no flags at all -> set all flags!
|
||||
if (!flags)
|
||||
@ -1260,7 +1260,7 @@ static enum eos po_nowarn(void)
|
||||
|
||||
global_inhibit_warnings = TRUE;
|
||||
// if there's a block, parse it and then restore old value
|
||||
if (Parse_optional_block()) {
|
||||
if (parse_optional_block()) {
|
||||
global_inhibit_warnings = flag_buf;
|
||||
return ENSURE_EOS;
|
||||
} else {
|
||||
@ -1289,13 +1289,13 @@ static enum eos throw_string(const char prefix[], void (*fn)(const char *))
|
||||
do {
|
||||
if ((GotByte == '"') && (config.wanted_version < VER_BACKSLASHESCAPING)) {
|
||||
dynabuf_clear(GlobalDynaBuf);
|
||||
if (Input_quoted_to_dynabuf('"'))
|
||||
if (input_quoted_to_dynabuf('"'))
|
||||
return SKIP_REMAINDER; // unterminated or escaping error
|
||||
|
||||
// eat closing quote
|
||||
GetByte();
|
||||
// now convert to unescaped version
|
||||
if (Input_unescape_dynabuf(0))
|
||||
if (input_unescape_dynabuf(0))
|
||||
return SKIP_REMAINDER; // escaping error
|
||||
|
||||
dynabuf_append(GlobalDynaBuf, '\0'); // terminate string
|
||||
@ -1305,7 +1305,7 @@ static enum eos throw_string(const char prefix[], void (*fn)(const char *))
|
||||
ALU_any_result(&object);
|
||||
object.type->print(&object, user_message);
|
||||
}
|
||||
} while (Input_accept_comma());
|
||||
} while (input_accept_comma());
|
||||
dynabuf_append(user_message, '\0');
|
||||
fn(user_message->buffer);
|
||||
return ENSURE_EOS;
|
||||
@ -1353,8 +1353,8 @@ static enum eos po_serious(void)
|
||||
static enum eos po_endoffile(void)
|
||||
{
|
||||
// well, it doesn't end right here and now, but at end-of-line! :-)
|
||||
Input_ensure_EOS();
|
||||
Input_now->state = INPUTSTATE_EOF;
|
||||
input_ensure_EOS();
|
||||
input_now->state = INPUTSTATE_EOF;
|
||||
return AT_EOS_ANYWAY;
|
||||
}
|
||||
|
||||
@ -1447,9 +1447,9 @@ void pseudoopcode_parse(void) // now GotByte = "!"
|
||||
|
||||
GetByte(); // read next byte
|
||||
// on missing keyword, return (complaining will have been done)
|
||||
if (Input_read_and_lower_keyword()) {
|
||||
if (input_read_and_lower_keyword()) {
|
||||
// search for tree item
|
||||
if ((Tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf))
|
||||
if ((tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf))
|
||||
&& node_body) {
|
||||
fn = (enum eos (*)(void)) node_body;
|
||||
SKIPSPACE();
|
||||
@ -1460,9 +1460,9 @@ void pseudoopcode_parse(void) // now GotByte = "!"
|
||||
}
|
||||
}
|
||||
if (then == SKIP_REMAINDER)
|
||||
Input_skip_remainder();
|
||||
input_skip_remainder();
|
||||
else if (then == ENSURE_EOS)
|
||||
Input_ensure_EOS();
|
||||
input_ensure_EOS();
|
||||
// the other two possibilities (PARSE_REMAINDER and AT_EOS_ANYWAY)
|
||||
// will lead to the remainder of the line being parsed by the mainloop.
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// pseudo opcode stuff
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
// call when "*= EXPRESSION" is parsed
|
||||
extern void notreallypo_setpc(void);
|
||||
|
||||
// parse pseudo opcode. has to be re-entrant.
|
||||
extern void pseudoopcode_parse(void);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// section stuff
|
||||
@ -26,10 +26,13 @@ extern struct section *section_now;
|
||||
|
||||
// write given info into given structure and activate it
|
||||
extern void section_new(struct section *section, const char *type, char *title, boolean allocated);
|
||||
|
||||
// change scope of cheap locals in given section
|
||||
extern void section_new_cheap_scope(struct section *section);
|
||||
|
||||
// setup outermost section
|
||||
extern void section_passinit(void);
|
||||
|
||||
// tidy up: if necessary, release section title.
|
||||
extern void section_finalize(struct section *section);
|
||||
|
||||
|
22
src/symbol.c
22
src/symbol.c
@ -60,7 +60,7 @@ static void dump_one_symbol(struct rwnode *node, FILE *fd)
|
||||
else if (symbol->object.u.number.ntype == NUMTYPE_FLOAT)
|
||||
fprintf(fd, "%.30f", symbol->object.u.number.val.fpval); //FIXME %g
|
||||
else
|
||||
Bug_found("IllegalNumberType4", symbol->object.u.number.ntype);
|
||||
BUG("IllegalNumberType4", symbol->object.u.number.ntype);
|
||||
if (symbol->object.u.number.flags & NUMBER_EVER_UNDEFINED)
|
||||
fprintf(fd, "\t; ?"); // TODO - write "forward" instead?
|
||||
if (!symbol->has_been_read)
|
||||
@ -112,7 +112,7 @@ struct symbol *symbol_find(scope_t scope)
|
||||
struct symbol *symbol;
|
||||
boolean node_created;
|
||||
|
||||
node_created = Tree_hard_scan(&node, symbols_forest, scope, TRUE);
|
||||
node_created = tree_hard_scan(&node, symbols_forest, scope, TRUE);
|
||||
// if node has just been created, create symbol as well
|
||||
if (node_created) {
|
||||
// create new symbol structure
|
||||
@ -175,9 +175,9 @@ void symbol_set_object(struct symbol *symbol, struct object *new_value, bits pow
|
||||
void symbol_set_force_bit(struct symbol *symbol, bits force_bit)
|
||||
{
|
||||
if (!force_bit)
|
||||
Bug_found("ForceBitZero", 0);
|
||||
BUG("ForceBitZero", 0);
|
||||
if (symbol->object.type == NULL)
|
||||
Bug_found("NullTypeObject", 0);
|
||||
BUG("NullTypeObject", 0);
|
||||
|
||||
if (symbol->object.type != &type_number) {
|
||||
Throw_error("Force bits can only be given to numbers.");
|
||||
@ -216,7 +216,7 @@ void symbol_define(intval_t value)
|
||||
// dump global symbols to file
|
||||
void symbols_list(FILE *fd)
|
||||
{
|
||||
Tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_one_symbol, fd);
|
||||
tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_one_symbol, fd);
|
||||
}
|
||||
|
||||
|
||||
@ -225,13 +225,13 @@ void symbols_vicelabels(FILE *fd)
|
||||
// FIXME - if type checking is enabled, maybe only output addresses?
|
||||
// the order of dumped labels is important because VICE will prefer later defined labels
|
||||
// dump unused labels
|
||||
Tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_unusednonaddress, fd);
|
||||
tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_unusednonaddress, fd);
|
||||
fputc('\n', fd);
|
||||
// dump other used labels
|
||||
Tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_usednonaddress, fd);
|
||||
tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_usednonaddress, fd);
|
||||
fputc('\n', fd);
|
||||
// dump address symbols
|
||||
Tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_address, fd);
|
||||
tree_dump_forest(symbols_forest, SCOPE_GLOBAL, dump_vice_address, fd);
|
||||
// TODO - add trace points and watch points with load/store/exec args!
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ void symbol_fix_forward_anon_name(boolean increment)
|
||||
counter_symbol->object.u.number.val.intval = 0;
|
||||
} else if (counter_symbol->object.type != &type_number) {
|
||||
// sanity check: it must be a number!
|
||||
Bug_found("ForwardAnonCounterNotInt", 0);
|
||||
BUG("ForwardAnonCounterNotInt", 0);
|
||||
}
|
||||
// make sure it gets reset to zero in each new pass
|
||||
if (counter_symbol->pass != pass.number) {
|
||||
@ -300,7 +300,7 @@ int symbol_fix_dynamic_name(void)
|
||||
boolean parenthesized;
|
||||
|
||||
if (GotByte != '?')
|
||||
Bug_found("NotQuestionMark", GotByte);
|
||||
BUG("NotQuestionMark", GotByte);
|
||||
|
||||
// start with base name
|
||||
// (reading the inner parts will clobber GlobalDynaBuf, so copy it now)
|
||||
@ -318,7 +318,7 @@ int symbol_fix_dynamic_name(void)
|
||||
}
|
||||
|
||||
// read inner part
|
||||
if (Input_read_scope_and_symbol_name(&tmp_scope))
|
||||
if (input_read_scope_and_symbol_name(&tmp_scope))
|
||||
return 1;
|
||||
|
||||
tmp_symbol = symbol_find(tmp_scope);
|
||||
|
@ -65,7 +65,7 @@ static void tree_from_list(struct ronode **tree, struct ronode *table_to_add)
|
||||
// tree item that matches the given data (HashValue and DynaBuf-String).
|
||||
// Store "body" component in node_body and return TRUE.
|
||||
// Return FALSE if no matching item found.
|
||||
int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf)
|
||||
int tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf)
|
||||
{
|
||||
struct ronode wanted; // temporary storage
|
||||
const char *p1,
|
||||
@ -121,7 +121,7 @@ int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_b
|
||||
// a new tree item, link to tree, fill with data and store its pointer. If the
|
||||
// "create" flag is zero, store NULL as result.
|
||||
// Returns whether item was created.
|
||||
int Tree_hard_scan(struct rwnode **result, struct rwnode **forest, int id_number, boolean create)
|
||||
int tree_hard_scan(struct rwnode **result, struct rwnode **forest, int id_number, boolean create)
|
||||
{
|
||||
struct ronode wanted; // temporary storage
|
||||
struct rwnode **current_node;
|
||||
@ -200,8 +200,8 @@ static void dump_tree(struct rwnode *node, int id_number, void (*fn)(struct rwno
|
||||
dump_tree(node->less_than_or_equal, id_number, fn, env);
|
||||
}
|
||||
|
||||
// Call Tree_dump_tree for each non-zero entry of the given tree table.
|
||||
void Tree_dump_forest(struct rwnode **forest, int id_number, void (*fn)(struct rwnode *, FILE *), FILE *env)
|
||||
// call dump_tree for each non-zero entry of the given tree table.
|
||||
void tree_dump_forest(struct rwnode **forest, int id_number, void (*fn)(struct rwnode *, FILE *), FILE *env)
|
||||
{
|
||||
int ii;
|
||||
|
||||
|
@ -45,16 +45,16 @@ struct rwnode {
|
||||
// Search for a given ID string in a given tree. Store "body" component in
|
||||
// node_body and return TRUE. Return FALSE if no matching item found.
|
||||
struct dynabuf;
|
||||
extern int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf);
|
||||
extern int tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf);
|
||||
|
||||
// Search for a "RAM tree" item. Save pointer to found tree item in given
|
||||
// location. If no matching item is found, check the "create" flag: If set,
|
||||
// create new tree item, link to tree, fill with data and store its pointer.
|
||||
// If "create" is FALSE, store NULL. Returns whether item was created.
|
||||
extern int Tree_hard_scan(struct rwnode **result, struct rwnode **forest, int id_number, boolean create);
|
||||
extern int tree_hard_scan(struct rwnode **result, struct rwnode **forest, int id_number, boolean create);
|
||||
|
||||
// Call given function for each node of each tree of given forest.
|
||||
extern void Tree_dump_forest(struct rwnode **, int id_number, void (*)(struct rwnode *, FILE *), FILE *);
|
||||
extern void tree_dump_forest(struct rwnode **, int id_number, void (*)(struct rwnode *, FILE *), FILE *);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// type system stuff
|
||||
@ -26,7 +26,7 @@ void typesystem_force_address_block(void)
|
||||
boolean buffer = in_address_block;
|
||||
|
||||
in_address_block = TRUE;
|
||||
Parse_optional_block();
|
||||
parse_optional_block();
|
||||
in_address_block = buffer;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
||||
// Copyright (C) 1998-2020 Marco Baye
|
||||
// Copyright (C) 1998-2024 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Type system stuff
|
||||
@ -12,12 +12,16 @@
|
||||
|
||||
// return whether explicit symbol definitions should force "address" mode
|
||||
extern boolean typesystem_says_address(void);
|
||||
|
||||
// parse a block while forcing address mode
|
||||
extern void typesystem_force_address_block(void);
|
||||
|
||||
// force address mode on or off for the next statement
|
||||
extern void typesystem_force_address_statement(boolean value);
|
||||
|
||||
// warn if result is not integer
|
||||
extern void typesystem_want_nonaddr(struct number *result);
|
||||
|
||||
// warn if result is not address
|
||||
extern void typesystem_want_addr(struct number *result);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#define RELEASE "0.97" // update before release FIXME
|
||||
#define CODENAME "Zem" // update before release
|
||||
#define CHANGE_DATE "6 Feb" // update before release FIXME
|
||||
#define CHANGE_DATE "8 Feb" // update before release FIXME
|
||||
#define CHANGE_YEAR "2024" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
|
Loading…
x
Reference in New Issue
Block a user