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:
parent
4f0f108494
commit
4d33e5db14
@ -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);
|
||||
}
|
||||
|
67
src/alu.c
67
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
16
src/global.c
16
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)) {
|
||||
|
65
src/input.c
65
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
|
||||
|
25
src/input.h
25
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).
|
||||
|
36
src/macro.c
36
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.").
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user