0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-07-24 10:25:42 -04:00

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@zytor.com>
This commit is contained in:
H. Peter Anvin 2023-10-16 13:42:16 -07:00
parent cb96db9b70
commit 9f83c383e4
3 changed files with 88 additions and 42 deletions

View File

@ -7455,14 +7455,13 @@ 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;
@ -7492,6 +7491,7 @@ stdmac_map(const SMacro *s, Token **params, int nparam)
return NULL;
}
}
}
nparam--;
params++;

View File

@ -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) x
\c %define alpha(&x,y) y dup (x)
\c db %map(alpha:2,foo,bar,baz,quux)
\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 bar dup ("foo"),quux dup ("baz")
\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 ''
\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

View File

@ -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)