summaryrefslogtreecommitdiff
path: root/preproc.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-19 15:45:05 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-19 15:45:05 -0700
commit992fe7591dca84b0ec5c779dad2f17b46b8ddd84 (patch)
treedbd07452909e640698f7673bacc299230d5dafd7 /preproc.c
parent8b5e68079a52d5c68a05be825ef10e5ce2f3d36b (diff)
downloadnasm-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.c95
1 files changed, 83 insertions, 12 deletions
diff --git a/preproc.c b/preproc.c
index e5b5ab3..447f235 100644
--- a/preproc.c
+++ b/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;
@@ -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.