[nasm:nasm-2.16.xx] preproc, %map(): require second colon, update documentation
nasm-bot for H. Peter Anvin
hpa at zytor.com
Mon Oct 16 13:44:05 PDT 2023
Commit-ID: 9f83c383e42d65c03c463b55d2ab4faba2bfdeff
Gitweb: http://repo.or.cz/w/nasm.git?a=commitdiff;h=9f83c383e42d65c03c463b55d2ab4faba2bfdeff
Author: H. Peter Anvin <hpa at zytor.com>
AuthorDate: Mon, 16 Oct 2023 13:42:16 -0700
Committer: H. Peter Anvin <hpa at zytor.com>
CommitDate: Mon, 16 Oct 2023 13:42:16 -0700
preproc, %map(): require second colon, update documentation
Require the second colon before the grouped parameter count; otherwise
the syntax is ambiguous since an expression can start with (.
Update/complete the documentation and the examples.
Signed-off-by: H. Peter Anvin <hpa at zytor.com>
---
asm/preproc.c | 58 ++++++++++++++++++++++++++++-----------------------------
doc/nasmdoc.src | 58 +++++++++++++++++++++++++++++++++++++++++++++++----------
test/map.asm | 14 +++++++++++---
3 files changed, 88 insertions(+), 42 deletions(-)
diff --git a/asm/preproc.c b/asm/preproc.c
index e8070ea2..cf495bcd 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -7455,41 +7455,41 @@ stdmac_map(const SMacro *s, Token **params, int nparam)
fixargs = NULL;
fixparams = 0;
+ mparams = 1;
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;
- struct tokenval tokval;
- expr *evalresult;
- Token *ep;
+ t = skip_white(t->next);
- pps.tptr = ep = zap_white(expand_smacro_noreset(t->next));
- t->next = NULL;
- pps.ntokens = -1;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
- free_tlist(ep);
+ if (tok_is(t, ':')) {
+ struct ppscan pps;
+ struct tokenval tokval;
+ expr *evalresult;
+ Token *ep;
+
+ pps.tptr = ep = zap_white(expand_smacro_noreset(t->next));
+ t->next = NULL;
+ pps.ntokens = -1;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
+ free_tlist(ep);
- if (!evalresult || tokval.t_type) {
- nasm_nonfatal("invalid expression in parameter count for `%s' in function %s",
- mname, s->name);
- return NULL;
- } else if (!is_simple(evalresult)) {
- nasm_nonfatal("non-constant expression in parameter count for `%s' in function %s",
- mname, s->name);
- return NULL;
- }
- mparams = reloc_value(evalresult);
- if (mparams < 1) {
- nasm_nonfatal("invalid parameter count for `%s' in function %s",
- mname, s->name);
- return NULL;
+ if (!evalresult || tokval.t_type) {
+ nasm_nonfatal("invalid expression in parameter count for `%s' in function %s",
+ mname, s->name);
+ return NULL;
+ } else if (!is_simple(evalresult)) {
+ nasm_nonfatal("non-constant expression in parameter count for `%s' in function %s",
+ mname, s->name);
+ return NULL;
+ }
+ mparams = reloc_value(evalresult);
+ if (mparams < 1) {
+ nasm_nonfatal("invalid parameter count for `%s' in function %s",
+ mname, s->name);
+ return NULL;
+ }
}
}
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 42bee347..3aabd6c8 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -2901,7 +2901,7 @@ the macro. Note that just as for single-line macros, \c{%count()}
treats an empty argument list as a single empty argument.
\c %xdefine empty %count() ; %define empty 1
-\c %xdefine one %count(1) ; %define one 1
+\c %xdefine one %count(1) ; %define one 1
\c %xdefine two %count(5,q) ; %define two 2
\c %define list a,b,46
\c %xdefine lc1 %count(list) ; %define lc 1 (just one argument)
@@ -2959,22 +2959,60 @@ argument to the conditional using \c{\{\}}:
\S{f_map} \i\c{%map()} Function
The \c{%map()} function takes as its first parameter the name of a
-single-line macro, optionally followed by a colon and an integer
-expression (default 1), specifying the number of parameter to the
-macro, \e{n}.
+single-line macro, followed by up to two optional colon-separated
+subparameters:
-The following parameters are then passed as parameters to the given
-macro for expansion, in groups of \e{n}, and the results turned into a
-comma-separated list.
+\b The first subparameter, if present, should be a list of macro
+parameters enclosed in parentheses. Note that \c{()} represents a
+one-argument list containing an empty parameter; omit the parentheses
+to specify no parameters.
+
+\b The second subparameter, if present, represent the number of
+group size for additional parameters to the macro (default 1).
+
+Further parameters, if any, are then passed as additional parameters to the
+given macro for expansion, in sets given by the specified group size,
+and the results turned into a comma-separated list. If no additional
+parameters are given, \c{%map()} expands to nothing.
For example:
-\c %define alpha(&x,y) y dup (x)
-\c db %map(alpha:2,foo,bar,baz,quux)
+\c %define alpha(&x) x
+\c %define alpha(&x,y) y dup (x)
+\c %define alpha(s,&x,y) y dup (x,s)
+\c ; 0 fixed + 1 grouped parameters per call, calls alpha(&x)
+\c db %map(alpha,foo,bar,baz,quux)
+\c ; 0 fixed + 2 grouped parameters per call, calls alpha(&x,y)
+\c db %map(alpha::2,foo,bar,baz,quux)
+\c ; 1 fixed + 2 grouped parameters per call, calls alpha(s,&x,y)
+\c db %map(alpha:("!"):2,foo,bar,baz,quux)
+
+... expands to:
+
+\c db 'foo','bar','baz','quux'
+\c db bar dup ('foo'),quux dup ('baz')
+\c db bar dup ('foo',"!"),quux dup ('baz',"!")
+
+As a more complex example, a macro that joins quoted strings together
+with a user-specified delimiter string:
+
+\c %define join(sep) '' ; handle the case of zero strings
+\c %define _join(sep,str) sep,str ; helper macro
+\c %define join(sep,s1,sn+) %strcat(s1, %map(_join:(sep) %, sn))
+\c
+\c db join(':')
+\c db join(':','a')
+\c db join(':','a','b')
+\c db join(':','a','b','c')
+\c db join(':','a','b','c','d')
... expands to:
-\c db bar dup ("foo"),quux dup ("baz")
+\c db ''
+\c db 'a'
+\c db 'a:b'
+\c db 'a:b:c'
+\c db 'a:b:c:d'
\S{f_num} \i\c{%num()} Function
diff --git a/test/map.asm b/test/map.asm
index 48f4739d..2538b7d5 100644
--- a/test/map.asm
+++ b/test/map.asm
@@ -1,7 +1,15 @@
%define foo(x) (x+1)
%define bar(=x,y) (x*y)
%define baz(x+) %(x)
-
dw %map(foo,1,2,3,4)
- dw %map(bar:2,1+2,3+4,5+6,7+8)
- dw %map(baz:2,1+2,3+4,5+6,7+8)
+ dw %map(bar::2,1+2,3+4,5+6,7+8)
+ dw %map(baz::2,1+2,3+4,5+6,7+8)
+
+bar equ 8
+quux equ 4
+%define alpha(&x) x
+%define alpha(&x,y) y dup (x)
+%define alpha(s,&x,y) y dup (x,s)
+ db %map(alpha,foo,bar,baz,quux)
+ db %map(alpha::2,foo,bar,baz,quux)
+ db %map(alpha:("!"):2,foo,bar,baz,quux)
More information about the Nasm-commits
mailing list