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:
parent
cb96db9b70
commit
9f83c383e4
@ -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;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 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
|
||||
|
14
test/map.asm
14
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user