mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-02-05 16:51:27 +08:00
preproc: Add new %[...] indirection construct
Add a new %[...] construct to support indirect macro expansion. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
8b5e68079a
commit
992fe7591d
95
preproc.c
95
preproc.c
@ -159,6 +159,7 @@ enum pp_token_type {
|
||||
TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
|
||||
TOK_INTERNAL_STRING,
|
||||
TOK_PREPROC_Q, TOK_PREPROC_QQ,
|
||||
TOK_INDIRECT, /* %[...] */
|
||||
TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
|
||||
TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
|
||||
};
|
||||
@ -396,6 +397,7 @@ static Blocks blocks = { NULL, NULL };
|
||||
static Token *expand_mmac_params(Token * tline);
|
||||
static Token *expand_smacro(Token * tline);
|
||||
static Token *expand_id(Token * tline);
|
||||
static Token *expand_indirect(Token * tline, int level);
|
||||
static Context *get_ctx(const char *name, bool all_contexts);
|
||||
static void make_tok_num(Token * tok, int64_t val);
|
||||
static void error(int severity, const char *fmt, ...);
|
||||
@ -804,6 +806,22 @@ static Token *tokenize(char *line)
|
||||
if (*p)
|
||||
p++;
|
||||
type = TOK_PREPROC_ID;
|
||||
} else if (*p == '[') {
|
||||
int lvl = 1;
|
||||
line += 2; /* Skip the leading %[ */
|
||||
p++;
|
||||
while (*p) {
|
||||
if (*p == ']') {
|
||||
if (!--lvl)
|
||||
break;
|
||||
} else if (*p == '%' && p[1] == '[') {
|
||||
lvl++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
type = TOK_INDIRECT;
|
||||
} else if (*p == '?') {
|
||||
type = TOK_PREPROC_Q; /* %? */
|
||||
p++;
|
||||
@ -2446,10 +2464,13 @@ static int do_directive(Token * tline)
|
||||
* called expand_mmac_params(); however, if we're
|
||||
* processing an %elif we must have been in a
|
||||
* non-emitting mode, which would have inhibited
|
||||
* the normal invocation of expand_mmac_params(). Therefore,
|
||||
* we have to do it explicitly here.
|
||||
* the normal invocation of expand_indirect() and
|
||||
* expand_mmac_params(). Therefore, we have to do it
|
||||
* explicitly here.
|
||||
*/
|
||||
j = if_condition(expand_mmac_params(tline->next), i);
|
||||
t = expand_indirect(tline->next,0);
|
||||
t = expand_mmac_params(t);
|
||||
j = if_condition(expand_mmac_params(t), i);
|
||||
tline->next = NULL; /* it got freed */
|
||||
istk->conds->state =
|
||||
j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
|
||||
@ -3442,15 +3463,8 @@ static Token *expand_mmac_params(Token * tline)
|
||||
}
|
||||
break;
|
||||
case TOK_ID:
|
||||
if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
|
||||
char *tmp = nasm_strcat(t->text, tt->text);
|
||||
nasm_free(t->text);
|
||||
t->text = tmp;
|
||||
t->next = delete_Token(tt);
|
||||
}
|
||||
break;
|
||||
case TOK_NUMBER:
|
||||
if (tt->type == TOK_NUMBER) {
|
||||
if (tt->type == t->type || tt->type == TOK_NUMBER) {
|
||||
char *tmp = nasm_strcat(t->text, tt->text);
|
||||
nasm_free(t->text);
|
||||
t->text = tmp;
|
||||
@ -3886,6 +3900,61 @@ static Token *expand_id(Token * tline)
|
||||
return tline;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand indirect tokens, %[...].
|
||||
*/
|
||||
static Token *expand_indirect(Token * tline, int level)
|
||||
{
|
||||
const int max_indirect_level = 1000;
|
||||
Token *t, *thead, **tp;
|
||||
Token *it;
|
||||
bool skip;
|
||||
|
||||
if (level >= max_indirect_level) {
|
||||
error(ERR_NONFATAL, "interminable indirect expansion");
|
||||
} else {
|
||||
thead = NULL;
|
||||
for (tp = &tline; (t = *tp); thead = t, tp = &t->next) {
|
||||
if (t->type != TOK_INDIRECT)
|
||||
continue;
|
||||
it = tokenize(t->text);
|
||||
it = expand_indirect(it, level+1);
|
||||
it = expand_smacro(it);
|
||||
while (it) {
|
||||
skip = false;
|
||||
switch (thead ? thead->type : TOK_NONE) {
|
||||
case TOK_WHITESPACE:
|
||||
skip = (it->type == TOK_WHITESPACE);
|
||||
break;
|
||||
|
||||
case TOK_ID:
|
||||
case TOK_NUMBER:
|
||||
if (it->type == thead->type || it->type == TOK_NUMBER) {
|
||||
char *tmp = nasm_strcat(thead->text, it->text);
|
||||
thead->text = tmp;
|
||||
skip = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
it = delete_Token(it);
|
||||
} else {
|
||||
*tp = thead = it;
|
||||
tp = &it->next;
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
*tp = t->next;
|
||||
delete_Token(t);
|
||||
}
|
||||
}
|
||||
return tline;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether the given line constitutes a multi-line macro
|
||||
* call, and return the MMacro structure called if so. Doesn't have
|
||||
@ -4428,8 +4497,10 @@ static char *pp_getline(void)
|
||||
* anything.
|
||||
*/
|
||||
if (!defining && !(istk->conds && !emitting(istk->conds->state))
|
||||
&& !(istk->mstk && !istk->mstk->in_progress))
|
||||
&& !(istk->mstk && !istk->mstk->in_progress)) {
|
||||
tline = expand_indirect(tline,0);
|
||||
tline = expand_mmac_params(tline);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the line to see if it's a preprocessor directive.
|
||||
|
Loading…
Reference in New Issue
Block a user