[nasm:nasm-2.16.xx] preproc: add the ability for %map() to have fixed arguments
nasm-bot for H. Peter Anvin
hpa at zytor.com
Mon Oct 16 03:00:05 PDT 2023
Commit-ID: cb96db9b70e49ca0257298c9d373f796aac59901
Gitweb: http://repo.or.cz/w/nasm.git?a=commitdiff;h=cb96db9b70e49ca0257298c9d373f796aac59901
Author: H. Peter Anvin <hpa at zytor.com>
AuthorDate: Mon, 16 Oct 2023 02:56:13 -0700
Committer: H. Peter Anvin <hpa at zytor.com>
CommitDate: Mon, 16 Oct 2023 02:56:13 -0700
preproc: add the ability for %map() to have fixed arguments
Add the ability to have fixed arguments in %map. This is extremely
useful for parameterizing the invoked macro using arguments to a
surrounding macro.
Signed-off-by: H. Peter Anvin <hpa at zytor.com>
---
asm/preproc.c | 95 +++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 73 insertions(+), 22 deletions(-)
diff --git a/asm/preproc.c b/asm/preproc.c
index 52a24ce5..e8070ea2 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -5863,9 +5863,10 @@ expand_smacro_with_params(SMacro *m, Token *mstart, Token **params,
/*
* Count the arguments to an smacro call. Returns 0 if the token following
- * is not a left paren.
+ * is not a left paren. *tp is set to point to the final ) if non-NULL;
+ * it is left unchanged for the zero-argument case.
*/
-static int count_smacro_args(Token *t)
+static int count_smacro_args(Token *t, Token **tp)
{
int nparam;
int paren, brackets;
@@ -5917,6 +5918,8 @@ static int count_smacro_args(Token *t)
}
}
+ if (tp)
+ *tp = t;
return nparam;
}
@@ -5949,6 +5952,7 @@ static Token **parse_smacro_args(Token **tp, int *nparamp, const SMacro *m)
/* Is it a macro or a preprocessor function? Used for diagnostics. */
const char * const mtype = m->name[0] == '%' ? "function" : "macro";
+ t = skip_white(t);
nasm_assert(tok_is(t, '('));
if (nparam > m->nparam) {
@@ -6135,10 +6139,8 @@ static SMacro *expand_one_smacro(Token ***tpp)
* substitute for the parameters when we expand. What a
* pain.
*/
-
- tline = tline->next;
- tline = skip_white(tline);
- nparam = count_smacro_args(tline);
+ tline = skip_white(tline->next);
+ nparam = count_smacro_args(tline, NULL);
if (!nparam)
goto not_a_macro;
@@ -6175,7 +6177,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
if (m->in_progress && !m->recursive)
goto not_a_macro;
- if (nparam) {
+ if (nparam) {
params = parse_smacro_args(&tline, &nparam, m);
}
@@ -7435,8 +7437,14 @@ stdmac_map(const SMacro *s, Token **params, int nparam)
SMacro *smac;
Context *ctx;
Token *t, *tline, *mstart;
- int mparams;
- int greedify;
+ int i;
+ Token *fixargs;
+ int fixparams; /* Number of fixed parameters */
+ int mparams; /* Number of variable parameters */
+ int tparams; /* Total number of parameters */
+ int greedify; /* Number of parameters that must be joined */
+ Token **fparam; /* Fixed parameters */
+ Token **cparam; /* Final list of macro call parameters */
t = params[0];
mname = get_id_noskip(&t, "%map");
@@ -7444,8 +7452,16 @@ stdmac_map(const SMacro *s, Token **params, int nparam)
return NULL;
mstart = t;
- t = t->next;
+ fixargs = NULL;
+ fixparams = 0;
+ t = skip_white(t->next);
+ if (tok_is(t, ':')) {
+ fixargs = t->next;
+ fixparams = count_smacro_args(fixargs, &t);
+ if (fixparams)
+ t = skip_white(t->next);
+ }
mparams = 1;
if (tok_is(t, ':')) {
struct ppscan pps;
@@ -7484,57 +7500,92 @@ stdmac_map(const SMacro *s, Token **params, int nparam)
s->name, mparams, nparam);
}
+ tparams = fixparams + mparams;
+
ctx = get_ctx(mname, &ctxname);
- if (!smacro_defined(ctx, ctxname, mparams, &smac, true, false) ||
- smac->nparam == 0 || (smac->in_progress && !smac->recursive)) {
- nasm_nonfatal("macro `%s' taking %d parameters not found in function %s",
- mname, mparams, s->name);
+ if (!smacro_defined(ctx, ctxname, tparams, &smac, true, false)
+ || smac->nparam == 0 || (smac->in_progress && !smac->recursive)) {
+ nasm_nonfatal("macro `%s' taking %d parameter%s not found in function %s",
+ mname, tparams, tparams == 1 ? "" : "s", s->name);
return NULL;
}
if (nparam < mparams)
return NULL; /* Empty expansion */
+ fparam = NULL;
+ if (fixparams) {
+ int nfp = fixparams;
+ fparam = parse_smacro_args(&fixargs, &nfp, smac);
+ if (nfp < fixparams) {
+ fixparams = nfp;
+ tparams = fixparams + mparams;
+ }
+ }
+
greedify = 0;
- if (unlikely(mparams > smac->nparam)) {
+ if (unlikely(tparams > smac->nparam)) {
if (smac->params[smac->nparam-1].flags & SPARM_GREEDY)
greedify = smac->nparam;
}
+ nasm_newn(cparam, tparams);
+
tline = NULL;
while (1) {
- int xparams = mparams;
+ int xparams;
+
+ for (i = 0; i < fixparams; i++) {
+ /* expand_smacro_with_params() is allowed to clobber the
+ * parameter array, so we need to give it its own copy.
+ */
+ cparam[i] = dup_tlist(fparam[i], NULL);
+ }
+
+ for (i = fixparams; i < tparams; i++) {
+ cparam[i] = *params;
+ *params = NULL; /* Taking over ownership */
+ params++;
+ }
+
if (unlikely(greedify)) {
/* Need to re-concatenate some number of arguments as
comma-separated lists... */
int i;
- Token **tp = ¶ms[greedify-1];
+ Token **tp = &cparam[greedify-1];
while (*tp)
tp = &(*tp)->next;
- for (i = greedify; i < mparams; i++) {
+ for (i = greedify; i < tparams; i++) {
*tp = make_tok_char(NULL, ',');
- tp = steal_tlist(params[i], &(*tp)->next);
- params[i] = NULL;
+ tp = steal_tlist(cparam[i], &(*tp)->next);
+ cparam[i] = NULL;
}
xparams = greedify;
+ } else {
+ xparams = tparams;
}
- t = expand_smacro_with_params(smac, mstart, params, xparams, NULL);
+ t = expand_smacro_with_params(smac, mstart, cparam, xparams, NULL);
if (t) {
Token *rt = reverse_tokens(t);
t->next = tline;
tline = rt;
}
+ for (i = 0; i < xparams; i++)
+ free_tlist(cparam[i]);
+
nparam -= mparams;
if (nparam < mparams)
break;
- params += mparams;
tline = make_tok_char(tline, ',');
}
+ nasm_free(fparam);
+ nasm_free(cparam);
+
return tline;
}
More information about the Nasm-commits
mailing list