mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Implement order-independent purge (#1173)
Each symbol passed to purge is collected in a list before mass removal. Fixes the issue described in gbdev/rgbds issue #1152. --------- Co-authored-by: Rangi42 <remy.oukaour+rangi42@gmail.com>
This commit is contained in:
@@ -97,4 +97,11 @@ struct DsArgList {
|
|||||||
struct Expression *args;
|
struct Expression *args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define INITIAL_PURGE_ARG_SIZE 2
|
||||||
|
struct PurgeArgList {
|
||||||
|
size_t nbArgs;
|
||||||
|
size_t capacity;
|
||||||
|
char **args;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // RGBDS_ASM_LEXER_H
|
#endif // RGBDS_ASM_LEXER_H
|
||||||
|
|||||||
@@ -398,6 +398,35 @@ static void freeDsArgList(struct DsArgList *args)
|
|||||||
free(args->args);
|
free(args->args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initPurgeArgList(struct PurgeArgList *args)
|
||||||
|
{
|
||||||
|
args->nbArgs = 0;
|
||||||
|
args->capacity = INITIAL_PURGE_ARG_SIZE;
|
||||||
|
args->args = malloc(args->capacity * sizeof(*args->args));
|
||||||
|
if (!args->args)
|
||||||
|
fatalerror("Failed to allocate memory for purge arg list: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void appendPurgeArgList(struct PurgeArgList *args, char *arg)
|
||||||
|
{
|
||||||
|
if (args->nbArgs == args->capacity) {
|
||||||
|
args->capacity = (args->capacity + 1) * 2;
|
||||||
|
args->args = realloc(args->args, args->capacity * sizeof(*args->args));
|
||||||
|
if (!args->args)
|
||||||
|
fatalerror("realloc error while resizing purge arg list: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
args->args[args->nbArgs++] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freePurgeArgList(struct PurgeArgList *args)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < args->nbArgs; i++)
|
||||||
|
free(args->args[i]);
|
||||||
|
free(args->args);
|
||||||
|
}
|
||||||
|
|
||||||
static void failAssert(enum AssertionType type)
|
static void failAssert(enum AssertionType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -481,6 +510,7 @@ enum {
|
|||||||
struct MacroArgs *macroArg;
|
struct MacroArgs *macroArg;
|
||||||
enum AssertionType assertType;
|
enum AssertionType assertType;
|
||||||
struct DsArgList dsArgs;
|
struct DsArgList dsArgs;
|
||||||
|
struct PurgeArgList purgeArgs;
|
||||||
struct {
|
struct {
|
||||||
int32_t start;
|
int32_t start;
|
||||||
int32_t stop;
|
int32_t stop;
|
||||||
@@ -636,6 +666,8 @@ enum {
|
|||||||
|
|
||||||
%type <dsArgs> ds_args
|
%type <dsArgs> ds_args
|
||||||
|
|
||||||
|
%type <purgeArgs> purge_args
|
||||||
|
|
||||||
%type <forArgs> for_args
|
%type <forArgs> for_args
|
||||||
|
|
||||||
%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
|
%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
|
||||||
@@ -1199,16 +1231,22 @@ redef_equs : redef_id T_POP_EQUS string { sym_RedefString($1, $3); }
|
|||||||
|
|
||||||
purge : T_POP_PURGE {
|
purge : T_POP_PURGE {
|
||||||
lexer_ToggleStringExpansion(false);
|
lexer_ToggleStringExpansion(false);
|
||||||
} purge_list trailing_comma {
|
} purge_args trailing_comma {
|
||||||
|
for (uint32_t i = 0; i < $3.nbArgs; i++)
|
||||||
|
sym_Purge($3.args[i]);
|
||||||
|
freePurgeArgList(&$3);
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
purge_list : purge_list_entry
|
purge_args : scoped_id {
|
||||||
| purge_list T_COMMA purge_list_entry
|
initPurgeArgList(&$$);
|
||||||
;
|
appendPurgeArgList(&$$, strdup($1));
|
||||||
|
}
|
||||||
purge_list_entry : scoped_id { sym_Purge($1); }
|
| purge_args T_COMMA scoped_id {
|
||||||
|
appendPurgeArgList(&$1, strdup($3));
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
export : T_POP_EXPORT export_list trailing_comma
|
export : T_POP_EXPORT export_list trailing_comma
|
||||||
|
|||||||
11
test/asm/purge-deferred.asm
Normal file
11
test/asm/purge-deferred.asm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
DEF prefix EQUS "cool"
|
||||||
|
DEF {prefix}banana EQU 1
|
||||||
|
|
||||||
|
ASSERT DEF(prefix)
|
||||||
|
ASSERT DEF(coolbanana)
|
||||||
|
|
||||||
|
; purging `prefix` should not prevent expanding it to purge `coolbanana`
|
||||||
|
PURGE prefix, {prefix}banana
|
||||||
|
|
||||||
|
ASSERT !DEF(prefix)
|
||||||
|
ASSERT !DEF(coolbanana)
|
||||||
0
test/asm/purge-deferred.err
Normal file
0
test/asm/purge-deferred.err
Normal file
0
test/asm/purge-deferred.out
Normal file
0
test/asm/purge-deferred.out
Normal file
Reference in New Issue
Block a user