diff --git a/src/acme.c b/src/acme.c index bbb8d6c..69429cc 100644 --- a/src/acme.c +++ b/src/acme.c @@ -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); } diff --git a/src/alu.c b/src/alu.c index bf9a0f2..1dc9186 100644 --- a/src/alu.c +++ b/src/alu.c @@ -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; } } diff --git a/src/flow.c b/src/flow.c index dcdfe93..6a19956 100644 --- a/src/flow.c +++ b/src/flow.c @@ -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 diff --git a/src/global.c b/src/global.c index 6583ac6..589b706 100644 --- a/src/global.c +++ b/src/global.c @@ -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)) { diff --git a/src/input.c b/src/input.c index 4858d8c..7c7f057 100644 --- a/src/input.c +++ b/src/input.c @@ -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 diff --git a/src/input.h b/src/input.h index 8248e0e..1931e8a 100644 --- a/src/input.h +++ b/src/input.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 // // 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). diff --git a/src/macro.c b/src/macro.c index 1b26edb..0beb0af 100644 --- a/src/macro.c +++ b/src/macro.c @@ -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(¯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); - 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."). diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index 4647d8b..2ff72eb 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -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 diff --git a/src/symbol.h b/src/symbol.h index bce6c70..2feeb4e 100644 --- a/src/symbol.h +++ b/src/symbol.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 // // 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); diff --git a/src/tree.h b/src/tree.h index 5ee9adb..1f09590 100644 --- a/src/tree.h +++ b/src/tree.h @@ -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 *); diff --git a/src/version.h b/src/version.h index 20052c3..bcce7f9 100644 --- a/src/version.h +++ b/src/version.h @@ -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