diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-19 15:45:05 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-19 15:45:05 -0700 |
commit | 992fe7591dca84b0ec5c779dad2f17b46b8ddd84 (patch) | |
tree | dbd07452909e640698f7673bacc299230d5dafd7 /preproc.c | |
parent | 8b5e68079a52d5c68a05be825ef10e5ce2f3d36b (diff) | |
download | nasm-992fe7591dca84b0ec5c779dad2f17b46b8ddd84.tar.gz nasm-992fe7591dca84b0ec5c779dad2f17b46b8ddd84.tar.bz2 nasm-992fe7591dca84b0ec5c779dad2f17b46b8ddd84.zip |
preproc: Add new %[...] indirection construct
Add a new %[...] construct to support indirect macro expansion.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'preproc.c')
-rw-r--r-- | preproc.c | 95 |
1 files changed, 83 insertions, 12 deletions
@@ -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; @@ -3887,6 +3901,61 @@ static Token *expand_id(Token * 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 * to check for an initial label - that's taken care of in @@ -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. |