1
0
mirror of https://github.com/uffejakobsen/acme.git synced 2025-04-08 20:37:20 +00:00

a bit of internal cleanup before adding new features...

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@326 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2024-01-28 19:38:20 +00:00
parent 4f0f108494
commit 4d33e5db14
11 changed files with 139 additions and 105 deletions

@ -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
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -452,7 +452,8 @@ static void define_symbol(const char definition[])
DynaBuf_append(GlobalDynaBuf, *walk++);
if ((*walk == '\0') || (walk[1] == '\0'))
could_not_parse(definition);
value = string_to_number(walk + 1);
// TODO - if first char is double quote, maybe interpret as string instead of number?
value = string_to_number(walk + 1);
DynaBuf_append(GlobalDynaBuf, '\0');
symbol_define(value);
}

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2021 Marco Baye
// Copyright (C) 1998-2024 Marco Baye
// Have a look at "acme.c" for further info
//
// Arithmetic/logic unit
@ -307,7 +307,7 @@ static intval_t my_asr(intval_t left, intval_t right)
// if wanted, throw "Value not defined" error
// This function is not allowed to change DynaBuf because the symbol's name
// might be stored there!
static void is_not_defined(struct symbol *optional_symbol, char optional_prefix_char, char *name, size_t length)
static void is_not_defined(struct symbol *optional_symbol, char *name, size_t length)
{
if (!pass.complain_about_undefined)
return;
@ -324,10 +324,6 @@ static void is_not_defined(struct symbol *optional_symbol, char optional_prefix_
DynaBuf_add_string(errormsg_dyna_buf, "Value not defined (");
length += errormsg_dyna_buf->size;
if (optional_prefix_char) {
DynaBuf_append(errormsg_dyna_buf, optional_prefix_char);
++length;
}
DynaBuf_add_string(errormsg_dyna_buf, name);
if (errormsg_dyna_buf->size < length) {
Bug_found("IllegalSymbolNameLength", errormsg_dyna_buf->size - length);
@ -344,9 +340,10 @@ static void is_not_defined(struct symbol *optional_symbol, char optional_prefix_
// DynaBuf holds the symbol's name and "scope" its scope.
// The name length must be given explicitly because of anonymous forward labels;
// their internal name is different (longer) than their displayed name.
// FIXME - just split this up into two different buffers, "user name" and "internal name", that way the scope can be changed to a prefix as well!
// This function is not allowed to change DynaBuf because that's where the
// symbol name is stored!
static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t name_length, unsigned int unpseudo_count)
static void get_symbol_value(scope_t scope, size_t name_length, unsigned int unpseudo_count)
{
struct symbol *symbol;
struct object *arg;
@ -363,7 +360,7 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na
// FIXME - add sanity check for UNDEFINED where EVER_UNDEFINED is false -> Bug_found()!
// (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 "unpseudopc"
// first push on arg stack, so we have a local copy we can "unpseudo"
arg = &arg_stack[arg_sp++];
*arg = symbol->object;
if (unpseudo_count) {
@ -374,12 +371,12 @@ static void get_symbol_value(scope_t scope, char optional_prefix_char, size_t na
}
}
// if needed, output "value not defined" error
// FIXME - in case of unpseudopc, error message should include the correct number of '&' characters
// FIXME - in case of unpseudo, error message should include the correct number of '&' characters
// if (!(arg->type->is_defined(arg)))
// FIXME - now that lists with undefined items are "undefined", this fails in
// case of "!if len(some_list) {", so check for undefined _numbers_ explicitly:
if ((arg->type == &type_number) && (arg->u.number.ntype == NUMTYPE_UNDEFINED))
is_not_defined(symbol, optional_prefix_char, GLOBALDYNABUF_CURRENT, name_length);
is_not_defined(symbol, GLOBALDYNABUF_CURRENT, name_length);
// FIXME - if arg is list, increment ref count!
}
@ -393,7 +390,7 @@ static void parse_program_counter(unsigned int unpseudo_count) // Now GotByte =
vcpu_read_pc(&pc);
// if needed, output "value not defined" error
if (pc.ntype == NUMTYPE_UNDEFINED)
is_not_defined(NULL, 0, "*", 1);
is_not_defined(NULL, "*", 1);
if (unpseudo_count)
pseudopc_unpseudo(&pc, pseudopc_get_context(), unpseudo_count);
PUSH_INT_ARG(pc.val.intval, pc.flags, pc.addr_refs); // FIXME - when undefined pc is allowed, this must be changed for numtype!
@ -702,32 +699,31 @@ static void list_append_list(struct listitem *selfhead, struct listitem *otherhe
static int parse_octal_or_unpseudo(void) // now GotByte = '&'
{
unsigned int unpseudo_count = 1;
scope_t scope; // for "unpseudo symbol"
// first count ampersand characters so we know how many layers to "unpseudo":
while (GetByte() == '&')
++unpseudo_count;
// check for octal number:
if ((unpseudo_count == 1) && (GotByte >= '0') & (GotByte <= '7')) {
parse_octal_literal(); // now GotByte = non-octal char
return 0; // ok
}
// TODO - support anonymous labels as well?
// it's not an octal number, so it must be something to "unpseudo":
if (GotByte == '*') {
// program counter
parse_program_counter(unpseudo_count);
} else if (GotByte == '.') {
GetByte();
if (Input_read_keyword() == 0) // now GotByte = illegal char
} 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
return 1; // error (no string given)
get_symbol_value(section_now->local_scope, LOCAL_PREFIX, GlobalDynaBuf->size - 1, unpseudo_count); // -1 to not count terminator
} else if (GotByte == CHEAP_PREFIX) {
GetByte();
if (Input_read_keyword() == 0) // now GotByte = illegal char
return 1; // error (no string given)
get_symbol_value(section_now->cheap_scope, CHEAP_PREFIX, GlobalDynaBuf->size - 1, unpseudo_count); // -1 to not count terminator
} else if (BYTE_STARTS_KEYWORD(GotByte)) {
Input_read_keyword(); // now GotByte = illegal char
get_symbol_value(SCOPE_GLOBAL, '\0', GlobalDynaBuf->size - 1, unpseudo_count); // no prefix, -1 to not count terminator
get_symbol_value(scope, GlobalDynaBuf->size - 1, unpseudo_count); // -1 to not count terminator
// } else if (...) {
// // anonymous symbol
// "unpseudo"-ing anonymous symbols is not supported
} else {
Throw_error(exception_missing_string); // FIXME - create some "expected octal value or symbol name" error instead!
return 1; // error
@ -876,6 +872,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
struct op *op;
int ugly_length_kluge;
boolean perform_negation;
scope_t scope; // for parsing symbols
SKIPSPACE();
switch (GotByte) {
@ -887,7 +884,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
while (GetByte() == '+');
ugly_length_kluge = GlobalDynaBuf->size; // FIXME - get rid of this!
symbol_fix_forward_anon_name(FALSE); // FALSE: do not increment counter
get_symbol_value(section_now->local_scope, '\0', ugly_length_kluge, 0); // no prefix, no unpseudo
get_symbol_value(section_now->local_scope, ugly_length_kluge, 0); // no prefix, no unpseudo
goto now_expect_dyadic_op;
case '-': // NEGATION operator or anonymous backward label
@ -901,7 +898,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
SKIPSPACE();
if (BYTE_FOLLOWS_ANON(GotByte)) {
DynaBuf_append(GlobalDynaBuf, '\0');
get_symbol_value(section_now->local_scope, '\0', GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo
get_symbol_value(section_now->local_scope, GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo
goto now_expect_dyadic_op;
}
@ -985,23 +982,23 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
goto now_expect_dyadic_op;
}
if (Input_read_keyword()) { // now GotByte = illegal char
get_symbol_value(section_now->local_scope, LOCAL_PREFIX, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo
// FIXME - here we have a problem, 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
get_symbol_value(scope, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo
goto now_expect_dyadic_op; // ok
}
// if we're here, Input_read_keyword() will have thrown an error (like "no string given"):
// if we're here, an error has been thrown because there was no string after the '.'.
alu_state = STATE_ERROR;
break;//goto done;
case CHEAP_PREFIX: // cheap local symbol
//printf("looking in cheap scope %d\n", section_now->cheap_scope);
GetByte(); // start after '@'
if (Input_read_keyword()) { // now GotByte = illegal char
get_symbol_value(section_now->cheap_scope, CHEAP_PREFIX, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo
if (Input_read_scope_and_symbol_name(&scope) == 0) { // now GotByte = illegal char
get_symbol_value(scope, GlobalDynaBuf->size - 1, 0); // -1 to not count terminator, no unpseudo
goto now_expect_dyadic_op; // ok
}
// if we're here, Input_read_keyword() will have thrown an error (like "no string given"):
// if we're here, an error has been thrown because there was no string after the '@'.
alu_state = STATE_ERROR;
break;//goto done;
// decimal values and global symbols
@ -1037,7 +1034,7 @@ static boolean expect_argument_or_monadic_operator(struct expression *expression
// however, apart from that check above, function calls have nothing to do with
// parentheses: "sin(x+y)" gets parsed just like "not(x+y)".
} else {
get_symbol_value(SCOPE_GLOBAL, '\0', GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo
get_symbol_value(SCOPE_GLOBAL, GlobalDynaBuf->size - 1, 0); // no prefix, -1 to not count terminator, no unpseudo
goto now_expect_dyadic_op;
}
}

@ -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
//
// Flow control stuff (loops, conditional assembly etc.)
@ -35,7 +35,7 @@ boolean check_ifdef_condition(void)
struct symbol *symbol;
// read symbol name
if (Input_read_scope_and_keyword(&scope) == 0) // 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

@ -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
@ -241,13 +241,14 @@ static void parse_mnemo_or_global_symbol_def(bits *statement_flags)
// parse (cheap) local symbol definition
static void parse_local_symbol_def(bits *statement_flags, scope_t scope)
static void parse_local_symbol_def(bits *statement_flags)
{
scope_t scope;
if (!first_label_of_statement(statement_flags))
return;
GetByte(); // start after '.'/'@'
if (Input_read_keyword())
if (Input_read_scope_and_symbol_name(&scope) == 0)
parse_symbol_definition(scope, *statement_flags);
}
@ -328,7 +329,8 @@ void Parse_until_eob_or_eof(void)
break;
case '+':
GetByte();
if ((GotByte == LOCAL_PREFIX) // TODO - allow "cheap macros"?!
if ((GotByte == LOCAL_PREFIX)
|| (GotByte == CHEAP_PREFIX)
|| (BYTE_CONTINUES_KEYWORD(GotByte)))
Macro_parse_call();
else
@ -338,10 +340,8 @@ void Parse_until_eob_or_eof(void)
notreallypo_setpc(); // define program counter (fn is in pseudoopcodes.c)
break;
case LOCAL_PREFIX:
parse_local_symbol_def(&statement_flags, section_now->local_scope);
break;
case CHEAP_PREFIX:
parse_local_symbol_def(&statement_flags, section_now->cheap_scope);
parse_local_symbol_def(&statement_flags);
break;
default:
if (BYTE_STARTS_KEYWORD(GotByte)) {

@ -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
//
// Input stuff
@ -122,7 +122,7 @@ static char get_processed_from_file(void)
// fetch first byte from the current source file
from_file = getc(Input_now->src.fd);
IF_WANTED_REPORT_SRCCHAR(from_file);
//TODO - check for bogus/malformed BOM and ignore?
//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
@ -355,6 +355,7 @@ void Input_ensure_EOS(void) // Now GotByte = first char to test
char buf[80]; // actually needed are 51
char quote; // character before and after
// FIXME - change quoting: do not assume char is printable!
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);
@ -500,7 +501,7 @@ char *Input_skip_or_store_block(boolean store)
// Append to GlobalDynaBuf while characters are legal for keywords.
// Throws "missing string" error if none.
// Returns number of characters added.
int Input_append_keyword_to_global_dynabuf(void)
static int append_keyword_to_global_dynabuf(void)
{
int length = 0;
@ -515,24 +516,56 @@ int Input_append_keyword_to_global_dynabuf(void)
return length;
}
// Check GotByte.
// If LOCAL_PREFIX ('.'), store current local scope value and read next byte.
// If CHEAP_PREFIX ('@'), store current cheap scope value and read next byte.
// Otherwise, store global scope value.
// Then jump to Input_read_keyword(), which returns length of keyword.
int Input_read_scope_and_keyword(scope_t *scope)
// 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.
int Input_append_symbol_name_to_global_dynabuf(void)
{
if ((GotByte == LOCAL_PREFIX)
|| (GotByte == CHEAP_PREFIX)) {
DynaBuf_append(GlobalDynaBuf, GotByte);
GetByte();
} else if (!BYTE_STARTS_KEYWORD(GotByte)) {
// FIXME - show invalid char in error message!
Throw_error(exception_missing_string);
return 1; // error
}
return append_keyword_to_global_dynabuf() == 0; // zero length -> error!
}
// 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 err;
SKIPSPACE();
if (GotByte == LOCAL_PREFIX) {
GetByte();
DYNABUF_CLEAR(GlobalDynaBuf);
if (dotkluge) {
// this happens after the expression parser has eaten the '.'
// and did not find a decimal digit. -> not a float value ->
// must be a local symbol -> we must restore the '.' in front!
DynaBuf_append(GlobalDynaBuf, '.');
err = append_keyword_to_global_dynabuf() == 0; // zero length -> error!
} else {
err = Input_append_symbol_name_to_global_dynabuf();
}
// add terminator to buffer (increments buffer's length counter)
DynaBuf_append(GlobalDynaBuf, '\0');
if (err) {
*scope = SCOPE_GLOBAL; // bogus, but at least not un-initialized
return 1; // error
}
if (GLOBALDYNABUF_CURRENT[0] == LOCAL_PREFIX) {
*scope = section_now->local_scope;
} else if (GotByte == CHEAP_PREFIX) {
GetByte();
} else if (GLOBALDYNABUF_CURRENT[0] == CHEAP_PREFIX) {
*scope = section_now->cheap_scope;
} else {
*scope = SCOPE_GLOBAL;
}
return Input_read_keyword();
return 0; // no error
}
// Clear dynamic buffer, then append to it until an illegal (for a keyword)
@ -544,7 +577,7 @@ int Input_read_keyword(void)
int length;
DYNABUF_CLEAR(GlobalDynaBuf);
length = Input_append_keyword_to_global_dynabuf();
length = append_keyword_to_global_dynabuf();
// add terminator to buffer (increments buffer's length counter)
DynaBuf_append(GlobalDynaBuf, '\0');
return length;
@ -559,7 +592,7 @@ int Input_read_and_lower_keyword(void)
int length;
DYNABUF_CLEAR(GlobalDynaBuf);
length = Input_append_keyword_to_global_dynabuf();
length = append_keyword_to_global_dynabuf();
// add terminator to buffer (increments buffer's length counter)
DynaBuf_append(GlobalDynaBuf, '\0');
DynaBuf_to_lower(GlobalDynaBuf, GlobalDynaBuf); // convert to lower case

@ -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
//
// Input stuff
@ -88,20 +88,25 @@ extern int Input_unescape_dynabuf(int start_index);
// but then a serious error would have been thrown.
extern char *Input_skip_or_store_block(boolean store);
// Append to GlobalDynaBuf while characters are legal for keywords.
// Throws "missing string" error if none. Returns number of characters added.
extern int Input_append_keyword_to_global_dynabuf(void);
// Check GotByte.
// If LOCAL_PREFIX ('.'), store current local scope value and read next byte.
// If CHEAP_PREFIX ('@'), store current cheap scope value and read next byte.
// Otherwise, store global scope value.
// Then jump to Input_read_keyword(), which returns length of keyword.
extern int Input_read_scope_and_keyword(scope_t *scope);
// 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);
// 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)
// 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);
// 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).

@ -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
//
// Macro stuff
@ -68,24 +68,20 @@ static void enlarge_arg_table(void)
// Read macro scope and title. Title is read to GlobalDynaBuf and then copied
// over to internal_name DynaBuf, where ARG_SEPARATOR is added.
// In user_macro_name DynaBuf, the original name is reconstructed (even with
// LOCAL_PREFIX) so a copy can be linked to the resulting macro struct.
// In user_macro_name DynaBuf, the original name is kept so a copy can be
// linked to the resulting macro struct.
static scope_t get_scope_and_title(void)
{
scope_t macro_scope;
Input_read_scope_and_keyword(&macro_scope); // skips spaces before
Input_read_scope_and_symbol_name(&macro_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);
DYNABUF_CLEAR(internal_name);
if (macro_scope != SCOPE_GLOBAL) {
// TODO - allow "cheap macros"?!
DynaBuf_append(user_macro_name, LOCAL_PREFIX);
}
DynaBuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT);
DynaBuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
DynaBuf_append(user_macro_name, '\0');
DYNABUF_CLEAR(internal_name);
DynaBuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
DynaBuf_append(internal_name, ARG_SEPARATOR);
SKIPSPACE(); // done here once so it's not necessary at two callers
return macro_scope;
@ -161,7 +157,7 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
// now GotByte = first non-space after title
DYNABUF_CLEAR(GlobalDynaBuf); // prepare to hold formal parameters
// GlobalDynaBuf = "" (will hold formal parameter list)
// user_macro_name = [LOCAL_PREFIX] MacroTitle NUL
// user_macro_name = MacroTitle NUL
// internal_name = MacroTitle ARG_SEPARATOR (grows to signature)
// Accept n>=0 comma-separated formal parameters before CHAR_SOB ('{').
// Valid argument formats are:
@ -182,14 +178,8 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
DynaBuf_append(GlobalDynaBuf, REFERENCE_CHAR);
GetByte();
}
// handle prefix for (cheap) local symbols ('.'/'@')
if ((GotByte == LOCAL_PREFIX)
|| (GotByte == CHEAP_PREFIX)) {
DynaBuf_append(GlobalDynaBuf, GotByte);
GetByte();
}
// handle symbol name
Input_append_keyword_to_global_dynabuf();
// handle symbol name (including '.'/'@' prefix)
Input_append_symbol_name_to_global_dynabuf();
} while (pipe_comma());
// ensure CHAR_SOB ('{')
if (GotByte != CHAR_SOB)
@ -218,7 +208,7 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
}
// Parse macro call ("+MACROTITLE"). Has to be re-entrant.
void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
void Macro_parse_call(void) // Now GotByte = first char of macro name
{
char local_gotbyte;
struct symbol *symbol;
@ -261,7 +251,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
// read call-by-reference arg
DynaBuf_append(internal_name, ARGTYPE_REF);
GetByte(); // eat '~'
Input_read_scope_and_keyword(&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 {
@ -315,7 +305,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
if (GotByte == REFERENCE_CHAR) {
// assign call-by-reference arg
GetByte(); // eat '~'
Input_read_scope_and_keyword(&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)
&& (FIRST_PASS))
@ -323,7 +313,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
symbol_node->body = arg_table[arg_count].symbol; // CAUTION, object type may be NULL
} else {
// assign call-by-value arg
Input_read_scope_and_keyword(&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.").

@ -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
@ -743,7 +743,7 @@ static enum eos po_set(void) // now GotByte = illegal char
scope_t scope;
int force_bit;
if (Input_read_scope_and_keyword(&scope) == 0) // 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
@ -1019,7 +1019,7 @@ static enum eos po_for(void) // now GotByte = illegal char
struct for_loop loop;
struct number intresult;
if (Input_read_scope_and_keyword(&scope) == 0) // skips spaces before
if (Input_read_scope_and_symbol_name(&scope)) // skips spaces before
return SKIP_REMAINDER; // zero length
// now GotByte = illegal char

@ -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
//
// symbol stuff
@ -32,6 +32,7 @@ extern struct rwnode *symbols_forest[]; // trees (because of 8-bit hash)
// search for symbol. if it does not exist, create with NULL type object (CAUTION!).
// the symbol name must be held in GlobalDynaBuf.
extern struct symbol *symbol_find(scope_t scope);
// assign object to symbol. function acts upon the symbol's flag bits and
// produces an error if needed.
// using "power" bits, caller can state which changes are ok.
@ -39,15 +40,20 @@ extern struct symbol *symbol_find(scope_t scope);
#define POWER_CHANGE_VALUE (1u << 0) // e.g. change 3 to 5 or 2.71
#define POWER_CHANGE_OBJTYPE (1u << 1) // e.g. change 3 to "somestring"
extern void symbol_set_object(struct symbol *symbol, struct object *new_obj, bits powers);
// set force bit of symbol. trying to change to a different one will raise error.
extern void symbol_set_force_bit(struct symbol *symbol, bits force_bit);
// set global symbol to value, no questions asked (for "-D" switch)
// name must be held in GlobalDynaBuf.
extern void symbol_define(intval_t value);
// dump global symbols to file
extern void symbols_list(FILE *fd);
// dump global labels to file in VICE format
extern void symbols_vicelabels(FILE *fd);
// fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!)
// so it references the *next* anonymous forward label definition.
extern void symbol_fix_forward_anon_name(boolean increment);

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2021 Marco Baye
// Copyright (C) 1998-2024 Marco Baye
// Have a look at "acme.c" for further info
//
// tree stuff
@ -36,7 +36,7 @@ struct rwnode {
hash_t hash_value;
char *id_string; // name, zero-terminated
void *body; // macro/symbol body
int id_number; // scope number
int id_number; // scope number (FIXME - get rid of this, use name prefixes instead!)
};
@ -46,11 +46,13 @@ struct rwnode {
// 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);
// 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);
// 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 *);

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
// Copyright (C) 1998-2021 Marco Baye
// Copyright (C) 1998-2024 Marco Baye
// Have a look at "acme.c" for further info
//
// version info
@ -9,8 +9,8 @@
#define RELEASE "0.97" // update before release FIXME
#define CODENAME "Zem" // update before release
#define CHANGE_DATE "31 Jan" // update before release FIXME
#define CHANGE_YEAR "2021" // update before release
#define CHANGE_DATE "28 Jan" // 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