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:
@@ -44,6 +44,7 @@
|
|||||||
*
|
*
|
||||||
*ctx
|
*ctx
|
||||||
*def
|
*def
|
||||||
|
*defalias
|
||||||
*empty
|
*empty
|
||||||
*env
|
*env
|
||||||
*id
|
*id
|
||||||
|
@@ -638,6 +638,8 @@ static Token *delete_Token(Token *t);
|
|||||||
static Token *steal_Token(Token *dst, Token *src);
|
static Token *steal_Token(Token *dst, Token *src);
|
||||||
static const struct use_package *
|
static const struct use_package *
|
||||||
get_use_pkg(Token *t, const char *dname, const char **name);
|
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 */
|
/* Safe test for token type, false on x == NULL */
|
||||||
static inline bool tok_type(const Token *x, enum pp_token_type t)
|
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
|
* Note that this is also called with nparam zero to resolve
|
||||||
* `ifdef'.
|
* `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
|
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)
|
bool nocase, bool find_alias)
|
||||||
{
|
{
|
||||||
struct hash_table *smtbl;
|
struct hash_table *smtbl;
|
||||||
SMacro *m;
|
SMacro *m;
|
||||||
|
|
||||||
if (ctx) {
|
smtbl = ctx ? &ctx->localmac : &smacros;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
m = (SMacro *) hash_findix(smtbl, name);
|
m = (SMacro *) hash_findix(smtbl, name);
|
||||||
@@ -2442,6 +2429,13 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PP_IFDEF:
|
case PP_IFDEF:
|
||||||
|
case PP_IFDEFALIAS:
|
||||||
|
{
|
||||||
|
bool alias = cond == PP_IFDEFALIAS;
|
||||||
|
SMacro *smac;
|
||||||
|
Context *ctx;
|
||||||
|
const char *mname;
|
||||||
|
|
||||||
j = false; /* have we matched yet? */
|
j = false; /* have we matched yet? */
|
||||||
while (tline) {
|
while (tline) {
|
||||||
tline = skip_white(tline);
|
tline = skip_white(tline);
|
||||||
@@ -2451,11 +2445,18 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
|
|||||||
dname);
|
dname);
|
||||||
goto fail;
|
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;
|
j = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
tline = tline->next;
|
tline = tline->next;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PP_IFENV:
|
case PP_IFENV:
|
||||||
tline = expand_smacro(tline);
|
tline = expand_smacro(tline);
|
||||||
@@ -2932,6 +2933,8 @@ static SMacro *define_smacro(const char *mname, bool casesense,
|
|||||||
if (tmpl) {
|
if (tmpl) {
|
||||||
defining_alias = tmpl->alias;
|
defining_alias = tmpl->alias;
|
||||||
nparam = tmpl->nparam;
|
nparam = tmpl->nparam;
|
||||||
|
if (nparam && !defining_alias)
|
||||||
|
mark_smac_params(expansion, tmpl, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -3022,8 +3025,7 @@ static void undef_smacro(const char *mname, bool undefalias)
|
|||||||
while ((s = *sp) != NULL) {
|
while ((s = *sp) != NULL) {
|
||||||
if (!mstrcmp(s->name, mname, s->casesense)) {
|
if (!mstrcmp(s->name, mname, s->casesense)) {
|
||||||
if (s->alias && !undefalias) {
|
if (s->alias && !undefalias) {
|
||||||
if (!do_aliases)
|
if (do_aliases) {
|
||||||
continue;
|
|
||||||
if (s->in_progress) {
|
if (s->in_progress) {
|
||||||
nasm_nonfatal("macro alias loop");
|
nasm_nonfatal("macro alias loop");
|
||||||
} else {
|
} else {
|
||||||
@@ -3031,18 +3033,19 @@ static void undef_smacro(const char *mname, bool undefalias)
|
|||||||
undef_smacro(tok_text(s->expansion), false);
|
undef_smacro(tok_text(s->expansion), false);
|
||||||
s->in_progress = false;
|
s->in_progress = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (list_option('d'))
|
if (list_option('d'))
|
||||||
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
|
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
|
||||||
ctx, s);
|
ctx, s);
|
||||||
*sp = s->next;
|
*sp = s->next;
|
||||||
free_smacro(s);
|
free_smacro(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
sp = &s->next;
|
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;
|
* is 0, create smac param tokens, otherwise use the type specified;
|
||||||
* normally this is used for TOK_XDEF_PARAM, which is used to protect
|
* normally this is used for TOK_XDEF_PARAM, which is used to protect
|
||||||
* parameter tokens during expansion during %xdefine.
|
* parameter tokens during expansion during %xdefine.
|
||||||
|
*
|
||||||
|
* tmpl may not be NULL here.
|
||||||
*/
|
*/
|
||||||
static void mark_smac_params(Token *tline, const SMacro *tmpl,
|
static void mark_smac_params(Token *tline, const SMacro *tmpl,
|
||||||
enum pp_token_type type)
|
enum pp_token_type type)
|
||||||
@@ -3222,9 +3227,6 @@ static void mark_smac_params(Token *tline, const SMacro *tmpl,
|
|||||||
Token *t;
|
Token *t;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!nparam)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list_for_each(t, tline) {
|
list_for_each(t, tline) {
|
||||||
if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
|
if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
|
||||||
continue;
|
continue;
|
||||||
@@ -4052,13 +4054,14 @@ issue_error:
|
|||||||
{
|
{
|
||||||
SMacro tmpl;
|
SMacro tmpl;
|
||||||
Token **lastp;
|
Token **lastp;
|
||||||
|
int nparam;
|
||||||
|
|
||||||
if (!(mname = get_id(&tline, dname)))
|
if (!(mname = get_id(&tline, dname)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
nasm_zero(tmpl);
|
nasm_zero(tmpl);
|
||||||
lastp = &tline->next;
|
lastp = &tline->next;
|
||||||
parse_smacro_template(&lastp, &tmpl);
|
nparam = parse_smacro_template(&lastp, &tmpl);
|
||||||
tline = *lastp;
|
tline = *lastp;
|
||||||
*lastp = NULL;
|
*lastp = NULL;
|
||||||
|
|
||||||
@@ -4082,11 +4085,10 @@ issue_error:
|
|||||||
} else {
|
} else {
|
||||||
if (op == PP_XDEFINE) {
|
if (op == PP_XDEFINE) {
|
||||||
/* Protect macro parameter tokens */
|
/* Protect macro parameter tokens */
|
||||||
|
if (nparam)
|
||||||
mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
|
mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
|
||||||
tline = expand_smacro(tline);
|
tline = expand_smacro(tline);
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_smac_params(tline, &tmpl, 0);
|
|
||||||
/* NB: Does this still make sense? */
|
/* NB: Does this still make sense? */
|
||||||
macro_start = reverse_tokens(tline);
|
macro_start = reverse_tokens(tline);
|
||||||
}
|
}
|
||||||
|
52
test/defalias.asm
Normal file
52
test/defalias.asm
Normal 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
|
Reference in New Issue
Block a user