mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
@@ -140,6 +140,7 @@ struct Symbol const *sym_GetPC(void);
|
||||
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
|
||||
struct Symbol *sym_Ref(char const *symName);
|
||||
struct Symbol *sym_AddString(char const *symName, char const *value);
|
||||
struct Symbol *sym_RedefString(char const *symName, char const *value);
|
||||
void sym_Purge(char const *symName);
|
||||
void sym_Init(time_t now);
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ static struct KeywordMapping {
|
||||
{"RW", T_POP_RW},
|
||||
{"EQU", T_POP_EQU},
|
||||
{"EQUS", T_POP_EQUS},
|
||||
{"REDEF", T_POP_REDEF},
|
||||
|
||||
/* Handled before in list of CPU instructions */
|
||||
/* {"SET", T_POP_SET}, */
|
||||
@@ -490,7 +491,7 @@ struct KeywordDictNode {
|
||||
uint16_t children[0x60 - ' '];
|
||||
struct KeywordMapping const *keyword;
|
||||
/* Since the keyword structure is invariant, the min number of nodes is known at compile time */
|
||||
} keywordDict[352] = {0}; /* Make sure to keep this correct when adding keywords! */
|
||||
} keywordDict[356] = {0}; /* Make sure to keep this correct when adding keywords! */
|
||||
|
||||
/* Convert a char into its index into the dict */
|
||||
static inline uint8_t dictIndex(char c)
|
||||
|
||||
@@ -425,6 +425,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
|
||||
%token T_POP_FATAL
|
||||
%token T_POP_ASSERT T_POP_STATIC_ASSERT
|
||||
%token T_POP_PURGE
|
||||
%token T_POP_REDEF
|
||||
%token T_POP_POPS
|
||||
%token T_POP_PUSHS
|
||||
%token T_POP_POPO
|
||||
@@ -645,6 +646,7 @@ simple_pseudoop : include
|
||||
| warn
|
||||
| assert
|
||||
| purge
|
||||
| redef
|
||||
| pops
|
||||
| pushs
|
||||
| popo
|
||||
@@ -877,6 +879,15 @@ purge : T_POP_PURGE {
|
||||
}
|
||||
;
|
||||
|
||||
redef : T_POP_REDEF {
|
||||
lexer_ToggleStringExpansion(false);
|
||||
} scoped_id {
|
||||
lexer_ToggleStringExpansion(true);
|
||||
} T_POP_EQUS string {
|
||||
sym_RedefString($3, $6);
|
||||
}
|
||||
;
|
||||
|
||||
purge_list : purge_list_entry
|
||||
| purge_list T_COMMA purge_list_entry
|
||||
;
|
||||
|
||||
@@ -929,7 +929,7 @@ or its synonym
|
||||
.Ic = ,
|
||||
defines constant symbols like
|
||||
.Ic EQU ,
|
||||
but those constants can be re-defined.
|
||||
but those constants can be redefined.
|
||||
This is useful for variables in macros, for counters, etc.
|
||||
.Bd -literal -offset indent
|
||||
ARRAY_SIZE EQU 4
|
||||
@@ -1008,8 +1008,23 @@ pusha EQUS "push af\[rs]npush bc\[rs]npush de\[rs]npush hl\[rs]n"
|
||||
Note that colons
|
||||
.Ql \&:
|
||||
following the name are not allowed.
|
||||
.Pp
|
||||
String equates can't be exported or imported.
|
||||
.Pp
|
||||
String equates, like
|
||||
.Ic EQU
|
||||
constants, cannot be redefined.
|
||||
However, the
|
||||
.Ic REDEF
|
||||
keyword will define or redefine a string symbol.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
s EQUS "Hello, "
|
||||
REDEF s EQUS "{s}world!"
|
||||
; prints "Hello, world!"
|
||||
PRINTT "{s}\n"
|
||||
.Ed
|
||||
.Pp
|
||||
.Sy Important note :
|
||||
An
|
||||
.Ic EQUS
|
||||
|
||||
@@ -222,6 +222,19 @@ static void fullSymbolName(char *output, size_t outputSize,
|
||||
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
||||
}
|
||||
|
||||
static void assignStringSymbol(struct Symbol *sym, char const *value)
|
||||
{
|
||||
char *string = strdup(value);
|
||||
|
||||
if (string == NULL)
|
||||
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
||||
|
||||
sym->type = SYM_EQUS;
|
||||
/* TODO: use other fields */
|
||||
sym->macro = string;
|
||||
sym->macroSize = strlen(string);
|
||||
}
|
||||
|
||||
struct Symbol *sym_FindExactSymbol(char const *name)
|
||||
{
|
||||
return hash_GetElement(symbols, name);
|
||||
@@ -283,6 +296,11 @@ void sym_Purge(char const *symName)
|
||||
if (symbol->name == labelScope)
|
||||
labelScope = NULL;
|
||||
|
||||
/*
|
||||
* FIXME: this leaks symbol->macro for SYM_EQUS and SYM_MACRO, but this can't
|
||||
* free(symbol->macro) because the expansion may be purging itself.
|
||||
*/
|
||||
|
||||
hash_RemoveElement(symbols, symbol->name);
|
||||
/* TODO: ideally, also unref the file stack nodes */
|
||||
free(symbol);
|
||||
@@ -390,17 +408,30 @@ struct Symbol *sym_AddEqu(char const *symName, int32_t value)
|
||||
struct Symbol *sym_AddString(char const *symName, char const *value)
|
||||
{
|
||||
struct Symbol *sym = createNonrelocSymbol(symName);
|
||||
size_t len = strlen(value);
|
||||
char *string = malloc(len + 1);
|
||||
|
||||
if (string == NULL)
|
||||
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
||||
strcpy(string, value);
|
||||
assignStringSymbol(sym, value);
|
||||
|
||||
sym->type = SYM_EQUS;
|
||||
/* TODO: use other fields */
|
||||
sym->macroSize = len;
|
||||
sym->macro = string;
|
||||
return sym;
|
||||
}
|
||||
|
||||
struct Symbol *sym_RedefString(char const *symName, char const *value)
|
||||
{
|
||||
struct Symbol *sym = sym_FindExactSymbol(symName);
|
||||
|
||||
if (!sym) {
|
||||
sym = createsymbol(symName);
|
||||
} else if (sym->type != SYM_EQUS) {
|
||||
error("'%s' already defined as non-EQUS at ", symName);
|
||||
dumpFilename(sym);
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: this leaks the previous sym->macro value, but this can't
|
||||
* free(sym->macro) because the expansion may be redefining itself.
|
||||
*/
|
||||
|
||||
assignStringSymbol(sym, value);
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
23
test/asm/redef-equs.asm
Normal file
23
test/asm/redef-equs.asm
Normal file
@@ -0,0 +1,23 @@
|
||||
s EQUS "Hello, "
|
||||
REDEF s EQUS "{s}world!"
|
||||
; prints "Hello, world!"
|
||||
PRINTT "{s}\n"
|
||||
|
||||
list: MACRO
|
||||
LIST_NAME EQUS "\1"
|
||||
REDEF {LIST_NAME} EQUS "["
|
||||
REPT _NARG - 1
|
||||
REDEF {LIST_NAME} EQUS "{{LIST_NAME}}\2;"
|
||||
SHIFT
|
||||
ENDR
|
||||
REDEF {LIST_NAME} EQUS "{{LIST_NAME}}]"
|
||||
PURGE LIST_NAME
|
||||
ENDM
|
||||
|
||||
list FOO
|
||||
PRINTT "{FOO}\n"
|
||||
list FOO, 1, A, 2, B
|
||||
PRINTT "{FOO}\n"
|
||||
|
||||
N EQU 42
|
||||
REDEF N EQUS "X"
|
||||
3
test/asm/redef-equs.err
Normal file
3
test/asm/redef-equs.err
Normal file
@@ -0,0 +1,3 @@
|
||||
ERROR: redef-equs.asm(23):
|
||||
'N' already defined as non-EQUS at redef-equs.asm(22)
|
||||
error: Assembly aborted (1 errors)!
|
||||
3
test/asm/redef-equs.out
Normal file
3
test/asm/redef-equs.out
Normal file
@@ -0,0 +1,3 @@
|
||||
Hello, world!
|
||||
[]
|
||||
[1;A;2;B;]
|
||||
Reference in New Issue
Block a user