slightly improved experimental feature to dynamically create symbol names

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@329 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2024-02-06 21:56:52 +00:00
parent aec6f8e99d
commit c6739be77d
5 changed files with 143 additions and 46 deletions

View File

@ -70,7 +70,7 @@ void dynabuf_clear(struct dynabuf *db)
db->size = 0; // clear buffer
}
// Enlarge buffer
// this gets called by "APPEND" macro whenever buffer is too small
void dynabuf_enlarge(struct dynabuf *db)
{
resize(db, MAKE_LARGER_THAN(db->reserved));
@ -94,15 +94,18 @@ void dynabuf_append(struct dynabuf *db, char byte)
DYNABUF_APPEND(db, byte);
}
// Append string to buffer (without terminator)
// add string to buffer (terminator is added, but not included in "size"!)
void dynabuf_add_string(struct dynabuf *db, const char *string)
{
char byte;
while ((byte = *string++))
do {
byte = *string++;
DYNABUF_APPEND(db, byte);
} while (byte);
db->size--; // do not consider terminator to be part of content
}
/*
// make sure DynaBuf is large enough to take "size" more bytes
// return pointer to end of current contents
static char *ensure_free_space(struct dynabuf *db, int size)
@ -110,9 +113,35 @@ static char *ensure_free_space(struct dynabuf *db, int size)
while ((db->reserved - db->size) < size)
resize(db, MAKE_LARGER_THAN(db->reserved));
return db->buffer + db->size;
}*/
}
// Convert buffer contents to lower case (target and source may be identical)
// append byte sequence to buffer
void dynabuf_add_bytes(struct dynabuf *db, const char *src, size_t size)
{
char *target;
target = ensure_free_space(db, size);
memcpy(target, src, size);
db->size += size;
}
// add long integer as decimal number to buffer
#define NUMBUFSIZE 30 // 21 would be large enough(tm) even for 64bit systems
void dynabuf_add_signed_long(struct dynabuf *db, signed long number)
{
char *target;
int added;
target = ensure_free_space(db, NUMBUFSIZE);
#if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
added = snprintf(target, NUMBUFSIZE, "%ld", number);
#else
added = sprintf(target, "%ld", number);
#endif
db->size += added;
}
// convert buffer contents to lower case (target and source may be identical)
void dynabuf_to_lower(struct dynabuf *target, struct dynabuf *source)
{
char *read,

View File

@ -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
//
// Dynamic buffer stuff
@ -47,19 +47,25 @@ extern struct dynabuf GlobalDynaBuf[1]; // global dynamic buffer
// (ensure buffer is ready to use, then) clear dynamic buffer
extern void dynabuf_clear(struct dynabuf *db);
// call whenever buffer is too small
// this gets called by "APPEND" macro whenever buffer is too small
extern void dynabuf_enlarge(struct dynabuf *db);
// return malloc'd copy of buffer contents
extern char *dynabuf_get_copy(struct dynabuf *db);
// copy string to buffer (without terminator)
extern void dynabuf_add_string(struct dynabuf *db, const char *);
// add string to buffer (terminator is added, but not included in "size"!)
extern void dynabuf_add_string(struct dynabuf *db, const char *str);
// converts buffer contents to lower case
// add byte sequence to buffer
extern void dynabuf_add_bytes(struct dynabuf *db, const char *src, size_t size);
// add long integer as decimal number to buffer
extern void dynabuf_add_signed_long(struct dynabuf *db, signed long number);
// convert buffer contents to lower case
extern void dynabuf_to_lower(struct dynabuf *target, struct dynabuf *source);
// add char to buffer
// append char to buffer
extern void dynabuf_append(struct dynabuf *db, char);

View File

@ -106,6 +106,7 @@ static enum eos po_initmem(void)
// change output "encryption" ("!xor" pseudo opcode)
// (allows for block, so must be reentrant)
static enum eos po_xor(void)
{
char old_value;
@ -309,6 +310,7 @@ static enum eos po_cbm(void)
}
// read encoding table from file
// (allows for block, so must be reentrant)
static enum eos user_defined_encoding(FILE *stream)
{
unsigned char local_table[256],
@ -335,6 +337,7 @@ static enum eos user_defined_encoding(FILE *stream)
}
// use one of the pre-defined encodings (raw, pet, scr)
// (allows for block, so must be reentrant)
static enum eos predefined_encoding(void)
{
unsigned char local_table[256],
@ -356,6 +359,7 @@ static enum eos predefined_encoding(void)
return ENSURE_EOS;
}
// set current encoding ("!convtab" pseudo opcode)
// (allows for block, so must be reentrant)
static enum eos po_convtab(void)
{
boolean uses_lib;
@ -610,6 +614,7 @@ static void old_offset_assembly(void)
}
// start offset assembly
// (allows for block, so must be reentrant)
// TODO - maybe add a label argument to assign the block size afterwards (for assemble-to-end-address) (or add another pseudo opcode)
static enum eos po_pseudopc(void)
{
@ -657,6 +662,7 @@ static enum eos po_realpc(void)
// select CPU ("!cpu" pseudo opcode)
// (allows for block, so must be reentrant)
static enum eos po_cpu(void)
{
const struct cpu_type *cpu_buffer = CPU_state.type; // remember current cpu
@ -677,6 +683,7 @@ static enum eos po_cpu(void)
// set register length, block-wise if needed.
// (allows for block, so must be reentrant)
static enum eos set_register_length(boolean *var, boolean make_long)
{
int old_size = *var;
@ -794,6 +801,7 @@ static enum eos po_symbollist(void)
// switch to new zone ("!zone" or "!zn"). has to be re-entrant.
// (allows for block, so must be reentrant)
static enum eos po_zone(void)
{
struct section entry_values; // buffer for outer zone
@ -1245,6 +1253,24 @@ static enum eos po_watch(void)
}
*/
/* // disable warnings for a statement or block of code
static enum eos po_nowarn(void)
{
boolean flag_buf = global_inhibit_warnings;
global_inhibit_warnings = TRUE;
// if there's a block, parse it and then restore old value
if (Parse_optional_block()) {
global_inhibit_warnings = flag_buf;
return ENSURE_EOS;
} else {
return PARSE_REMAINDER;
TODO: restore previous state after the current statement,
do it like "!address" does it!
}
}
*/
// constants
#define USERMSG_INITIALSIZE 80
@ -1291,6 +1317,7 @@ static enum eos throw_string(const char prefix[], void (*fn)(const char *))
static enum eos po_debug(void)
{
// FIXME - make debug output depend on some cli switch
// FIXME - add a number arg to this po so user can decide how much to display?
return throw_string("!debug: ", throw_message);
}
// show info given in source code
@ -1305,7 +1332,6 @@ static enum eos po_info(void)
static enum eos po_warn(void)
{
return throw_string("!warn: ", Throw_warning);
}
@ -1398,11 +1424,14 @@ static struct ronode pseudo_opcode_tree[] = {
PREDEFNODE("macro", po_macro),
/* PREDEFNODE("trace", po_trace),
PREDEFNODE("watch", po_watch), */
// PREDEFNODE("nowarn", po_nowarn),
// PREDEFNODE("debug", po_debug),
// PREDEFNODE("info", po_info),
PREDEFNODE("warn", po_warn),
PREDEFNODE("error", po_error),
PREDEFNODE("serious", po_serious),
// PREDEFNODE("filestart", po_),
// PREDEFNODE("filestop", po_),
PREDEFNODE("eof", po_endoffile),
PREDEF_END("endoffile", po_endoffile),
// ^^^^ this marks the last element

View File

@ -283,51 +283,84 @@ void symbol_fix_forward_anon_name(boolean increment)
}
// temporary buffer for base name while handling second part
STRUCT_DYNABUF_REF(basename_db, 64);
STRUCT_DYNABUF_REF(dyn_sym_name, 40);
// replace dynamic symbol name with its final version.
// ("basename?indexsymbol" -> "basename4711")
// replace dynamic symbol name with its final version, for example:
// if "somesymbol" is 42 and "endsymbol" is 47,
// basename?(somesymbol)middle?endsymbol
// becomes
// basename42middle47
// on entry: GlobalDynaBuf holds base name, GotByte holds '?'
// on exit: GlobalDynaBuf holds fixed name
// return whether there was an error.
#define NUMBUFSIZE 64 // large enough(tm) even for 64bit systems
int symbol_fix_dynamic_name(void)
{
scope_t second_scope;
struct symbol *second_symbol;
char numbuf[NUMBUFSIZE];
scope_t tmp_scope;
struct symbol *tmp_symbol;
boolean parenthesized;
if (GotByte != '?')
Bug_found("NotQuestionMark", GotByte);
GetByte(); // eat '?' character
// remember base name
dynabuf_clear(basename_db);
dynabuf_add_string(basename_db, GLOBALDYNABUF_CURRENT);
dynabuf_append(basename_db, '\0'); // terminate
// read second part (CAUTION, this will overwrite GlobalDynaBuf!)
if (Input_read_scope_and_symbol_name(&second_scope))
return 1;
second_symbol = symbol_find(second_scope);
if (second_symbol->object.type != &type_number) {
Throw_error("Second part of dynamic symbol name is not a number.");
return 1;
// start with base name
// (reading the inner parts will clobber GlobalDynaBuf, so copy it now)
dynabuf_clear(dyn_sym_name);
dynabuf_add_string(dyn_sym_name, GLOBALDYNABUF_CURRENT);
while (GotByte == '?') {
GetByte(); // eat '?' character
if (GotByte == '(') {
GetByte(); // eat '(' character
parenthesized = TRUE;
} else {
parenthesized = FALSE;
}
// read inner part
if (Input_read_scope_and_symbol_name(&tmp_scope))
return 1;
tmp_symbol = symbol_find(tmp_scope);
tmp_symbol->has_been_read = TRUE;
if (tmp_symbol->object.type == &type_number) {
if (tmp_symbol->object.u.number.ntype != NUMTYPE_INT) {
Throw_error("Inner part of dynamic symbol name is undefined or not integer.");
return 1;
}
dynabuf_add_signed_long(dyn_sym_name, (long) tmp_symbol->object.u.number.val.intval);
} else if (tmp_symbol->object.type == &type_string) {
dynabuf_add_bytes(dyn_sym_name, tmp_symbol->object.u.string->payload, tmp_symbol->object.u.string->length);
} else {
Throw_error("Inner part of dynamic symbol name is neither number nor string.");
return 1;
}
// check for closing parenthesis
if (parenthesized) {
SKIPSPACE();
if (GotByte == ')') {
GetByte(); // eat ')'
} else {
Throw_error("Inner part of dynamic symbol name does not end with ')' character.");
return 1;
}
}
// any more characters?
while (BYTE_CONTINUES_KEYWORD(GotByte)) {
DYNABUF_APPEND(dyn_sym_name, GotByte);
GetByte();
}
}
if (second_symbol->object.u.number.ntype != NUMTYPE_INT) {
Throw_error("Second part of dynamic symbol name is undefined or not integer.");
return 1;
}
second_symbol->has_been_read = TRUE;
#if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
snprintf(numbuf, NUMBUFSIZE, "%ld", (long) second_symbol->object.u.number.val.intval);
#else
sprintf(numbuf, "%ld", (long) second_symbol->object.u.number.val.intval);
#endif
dynabuf_append(dyn_sym_name, '\0');
// FIXME: now the dynamically created symbol name should be checked for
// its validity, because a string subst could have put anything in there!
// return basename and number in GlobalDynaBuf:
dynabuf_clear(GlobalDynaBuf);
dynabuf_add_string(GlobalDynaBuf, basename_db->buffer);
dynabuf_add_string(GlobalDynaBuf, numbuf);
dynabuf_add_string(GlobalDynaBuf, dyn_sym_name->buffer);
dynabuf_append(GlobalDynaBuf, '\0');
//printf("skipping '?' for <%s>\n", GLOBALDYNABUF_CURRENT);
//printf("created dynamic symbol name <%s>\n", GLOBALDYNABUF_CURRENT);
return 0;
}

View File

@ -9,7 +9,7 @@
#define RELEASE "0.97" // update before release FIXME
#define CODENAME "Zem" // update before release
#define CHANGE_DATE "29 Jan" // update before release FIXME
#define CHANGE_DATE "6 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