0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-09-22 10:43:39 -04:00

preproc: fix %undef of macro aliases, and add %ifdefalias

Macro aliases can legitimately point to nonexistent
macros. Furthermore, %undef should remove the pointed-at macro, not
the alias. This led to an infinite loop in the existing code; fix
that.

Add an %ifdefalias directive to test for the existence of an alias.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel)
2019-10-23 12:59:06 -07:00
parent 0741eb6004
commit e91f5cc132
3 changed files with 90 additions and 35 deletions

View File

@@ -44,6 +44,7 @@
*
*ctx
*def
*defalias
*empty
*env
*id

View File

@@ -638,6 +638,8 @@ static Token *delete_Token(Token *t);
static Token *steal_Token(Token *dst, Token *src);
static const struct use_package *
get_use_pkg(Token *t, const char *dname, const char **name);
static void mark_smac_params(Token *tline, const SMacro *tmpl,
enum pp_token_type type);
/* Safe test for token type, false on x == NULL */
static inline bool tok_type(const Token *x, enum pp_token_type t)
@@ -2278,30 +2280,15 @@ FILE *pp_input_fopen(const char *filename, enum file_flags mode)
*
* Note that this is also called with nparam zero to resolve
* `ifdef'.
*
* If you already know which context macro belongs to, you can pass
* the context pointer as first parameter; if you won't but name begins
* with %$ the context will be automatically computed. If all_contexts
* is true, macro will be searched in outer contexts as well.
*/
static bool
smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
bool nocase, bool find_alias)
{
struct hash_table *smtbl;
SMacro *m;
if (ctx) {
smtbl = &ctx->localmac;
} else if (name[0] == '%' && name[1] == '$') {
if (cstk)
ctx = get_ctx(name, &name);
if (!ctx)
return false; /* got to return _something_ */
smtbl = &ctx->localmac;
} else {
smtbl = &smacros;
}
smtbl = ctx ? &ctx->localmac : &smacros;
restart:
m = (SMacro *) hash_findix(smtbl, name);
@@ -2442,6 +2429,13 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
break;
case PP_IFDEF:
case PP_IFDEFALIAS:
{
bool alias = cond == PP_IFDEFALIAS;
SMacro *smac;
Context *ctx;
const char *mname;
j = false; /* have we matched yet? */
while (tline) {
tline = skip_white(tline);
@@ -2451,11 +2445,18 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
dname);
goto fail;
}
if (smacro_defined(NULL, tok_text(tline), 0, NULL, true, false))
mname = tok_text(tline);
ctx = get_ctx(mname, &mname);
if (smacro_defined(ctx, mname, 0, &smac, true, alias)
&& smac->alias == alias) {
j = true;
break;
}
tline = tline->next;
}
break;
}
case PP_IFENV:
tline = expand_smacro(tline);
@@ -2932,6 +2933,8 @@ static SMacro *define_smacro(const char *mname, bool casesense,
if (tmpl) {
defining_alias = tmpl->alias;
nparam = tmpl->nparam;
if (nparam && !defining_alias)
mark_smac_params(expansion, tmpl, 0);
}
while (1) {
@@ -3022,8 +3025,7 @@ static void undef_smacro(const char *mname, bool undefalias)
while ((s = *sp) != NULL) {
if (!mstrcmp(s->name, mname, s->casesense)) {
if (s->alias && !undefalias) {
if (!do_aliases)
continue;
if (do_aliases) {
if (s->in_progress) {
nasm_nonfatal("macro alias loop");
} else {
@@ -3031,18 +3033,19 @@ static void undef_smacro(const char *mname, bool undefalias)
undef_smacro(tok_text(s->expansion), false);
s->in_progress = false;
}
}
} else {
if (list_option('d'))
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
ctx, s);
*sp = s->next;
free_smacro(s);
continue;
}
}
} else {
sp = &s->next;
}
}
}
}
/*
@@ -3213,6 +3216,8 @@ get_use_pkg(Token *t, const char *dname, const char **name)
* is 0, create smac param tokens, otherwise use the type specified;
* normally this is used for TOK_XDEF_PARAM, which is used to protect
* parameter tokens during expansion during %xdefine.
*
* tmpl may not be NULL here.
*/
static void mark_smac_params(Token *tline, const SMacro *tmpl,
enum pp_token_type type)
@@ -3222,9 +3227,6 @@ static void mark_smac_params(Token *tline, const SMacro *tmpl,
Token *t;
int i;
if (!nparam)
return;
list_for_each(t, tline) {
if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
continue;
@@ -4052,13 +4054,14 @@ issue_error:
{
SMacro tmpl;
Token **lastp;
int nparam;
if (!(mname = get_id(&tline, dname)))
goto done;
nasm_zero(tmpl);
lastp = &tline->next;
parse_smacro_template(&lastp, &tmpl);
nparam = parse_smacro_template(&lastp, &tmpl);
tline = *lastp;
*lastp = NULL;
@@ -4082,11 +4085,10 @@ issue_error:
} else {
if (op == PP_XDEFINE) {
/* Protect macro parameter tokens */
if (nparam)
mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
tline = expand_smacro(tline);
}
mark_smac_params(tline, &tmpl, 0);
/* NB: Does this still make sense? */
macro_start = reverse_tokens(tline);
}

52
test/defalias.asm Normal file
View File

@@ -0,0 +1,52 @@
%defalias foo bar
%ifdef foo
%error "foo should not be defined here!"
%endif
%define foo 33
%ifndef foo
%error "foo should be defined here!"
%endif
%ifndef bar
%error "bar should be defined here!"
%endif
%if bar != 33
%error "bar should have the value 33 here"
%endif
%define bar 34
%if foo != 34
%error "foo should have the value 34 here"
%endif
%undef foo
%ifdef foo
%error "foo should not be defined here!"
%endif
%ifdef bar
%error "bar should not be defined here!"
%endif
%ifndefalias foo
%error "foo was removed as an alias!"
%endif
%define bar 35
%if foo != 35
%error "foo should have the value 35 here"
%endif
%define foo 36
%if bar != 36
%error "bar should have the value 36 here"
%endif
%undefalias foo
%ifdef foo
%error "foo is still defined after %undefalias"
%elifdefalias foo
%error "foo is undefined, but still an alias"
%endif
%ifndef bar
%error "bar disappeared after %undefalias foo"
%endif