preproc: fix %{:} macro operand ranges

Fix the handling of %{:} macro operands. Use the same code for
expanding the subarguments as for normal arguments.

This (hopefully) resolves the following bug reports:
  BR 3392611, BR 3392686, BR 3392688

Reported-by: <coconutfaistoslimeregistry@gmail.com>
Reported-by: Jasper Lievisse Adriaanse <r+nasm@jasper.la>
Reported-by: Jason Hood <jadoxa@yahoo.com.au>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2020-06-30 11:51:41 -07:00
parent 5c85b7f87b
commit e99a946390
2 changed files with 165 additions and 64 deletions

View file

@ -4835,17 +4835,15 @@ static int mmac_rotate(const MMacro *mac, unsigned int n)
/*
* expands to a list of tokens from %{x:y}
*/
static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
void expand_mmac_params_range(MMacro *mac, Token *tline, Token ***tail)
{
Token *t = tline, **tt, *tm, *head;
char *pos;
int fst, lst, j, i;
Token *t;
const char *arg = tok_text(tline) + 1;
int fst, lst, incr, n;
int parsed;
pos = strchr(tok_text(tline), ':');
nasm_assert(pos);
lst = atoi(pos + 1);
fst = atoi(tok_text(tline) + 1);
parsed = sscanf(arg, "%d:%d", &fst, &lst);
nasm_assert(parsed == 2);
/*
* only macros params are accounted so
@ -4863,56 +4861,28 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
/* count from zero */
fst--, lst--;
/*
* It will be at least one token. Note we
* need to scan params until separator, otherwise
* only first token will be passed.
* It will be at least one parameter, as we can loop
* in either direction.
*/
j = (fst + mac->rotate) % mac->nparam;
tm = mac->params[j+1];
if (!tm)
goto err;
head = dup_Token(NULL, tm);
tt = &head->next, tm = tm->next;
while (tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
incr = (fst < lst) ? 1 : -1;
while (true) {
n = mmac_rotate(mac, fst);
dup_tlistn(mac->params[n], mac->paramlen[n], tail);
if (fst == lst)
break;
t = make_tok_char(NULL, ',');
**tail = t;
*tail = &t->next;
fst += incr;
}
if (fst < lst) {
for (i = fst + 1; i <= lst; i++) {
t = make_tok_char(NULL, ',');
*tt = t, tt = &t->next;
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j+1];
while (tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
}
} else {
for (i = fst - 1; i >= lst; i--) {
t = make_tok_char(NULL, ',');
*tt = t, tt = &t->next;
j = (i + mac->rotate) % mac->nparam;
tm = mac->params[j+1];
while (!tok_isnt(tm, ',')) {
t = dup_Token(NULL, tm);
*tt = t, tt = &t->next, tm = tm->next;
}
}
}
*last = tt;
return head;
return;
err:
nasm_nonfatal("`%%{%s}': macro parameters out of range",
tok_text(tline) + 1);
return NULL;
nasm_nonfatal("`%%{%s}': macro parameters out of range", arg);
return;
}
/*
@ -4963,16 +4933,9 @@ static Token *expand_mmac_params(Token * tline)
}
if (strchr(text, ':')) {
/*
* seems we have a parameters range here
*/
Token *head, **last;
head = expand_mmac_params_range(mac, t, &last);
if (head) {
*tail = head;
*last = tline;
text = NULL;
}
/* It is a range */
expand_mmac_params_range(mac, t, &tail);
text = NULL;
break;
}

View file

@ -1 +0,0 @@
../../nasm-2.14.xx/test/emptyarg.asm

139
test/emptyarg.asm Normal file
View file

@ -0,0 +1,139 @@
%define EMPTY
%macro bar 1
db "bar", __LINE__, %0, %1
%endmacro
%macro baz 2
db "baz", __LINE__, %0, %1, %2
%endmacro
%macro nothing 0
db "nothing", __LINE__, %0
%endmacro
%macro xyzzy 1-2
db "xyzzy", __LINE__, %0, %1, %2, %3
%endmacro
%macro vararg 0-*
db "vararg", __LINE__, %0
%assign %%i 1
%rep %0
db "vararg arg ", %%i, %1
%rotate 1
%assign %%i %%i + 1
%endrep
%endmacro
%macro defargs 1-5 def2, def3, def4, def5
db "defargs", __LINE__, %0, %1, %2, %3, %4, %5
%endmacro
%macro ivar 1
vararg %1
%endmacro
%macro foo 1-2
db "foo", __LINE__, %0, %1, %2
bar %2
bar {%2}
bar %2,
bar {%2},
baz %1,%2
baz {%1},{%2}
nothing %1
nothing %2
xyzzy "meep",%1,%2,
xyzzy "meep","meep",%1,%2
xyzzy "alpha","bravo",
xyzzy "with","empty",EMPTY
%endmacro
%macro prange1 2-3
db %{1:2}, 0%3
%endmacro
%macro prange2 1-3 'two', 'three'
db %{1:3}
%endmacro
db 4,
nothing
nothing 1
nothing ; foo
nothing EMPTY
flup: foo 1,2
foo 3
bar
bar EMPTY
foo 6,
foo 6, ; With space/comment
foo 6,EMPTY
baz 8,EMPTY
foo 6,{}
foo ,5
xyzzy 13,14,15,
xyzzy 13,14,15,EMPTY
xyzzy 20,21
xyzzy 22,23,
xyzzy 24,25,EMPTY
xyzzy 26,27,,
xyzzy 28,29,EMPTY,EMPTY
vararg
vararg EMPTY
vararg ,
vararg 10
vararg 11,
vararg 12,EMPTY
vararg 13,14,15,
vararg 13,14,15,EMPTY
vararg 20,21
vararg 22,23,
vararg 24,25,EMPTY
vararg 26,27,,
vararg 28,29,EMPTY,EMPTY
ivar {}
ivar {EMPTY}
ivar EMPTY
ivar ,
ivar {,}
ivar {60}
ivar {61,}
ivar {62,EMPTY}
ivar {63,64,65,}
ivar {63,64,65,EMPTY}
ivar {70,71}
ivar {72,73,}
ivar {74,75,EMPTY}
ivar {76,77,,}
ivar {78,79,EMPTY,EMPTY}
defargs EMPTY
defargs 91
defargs 91,92
defargs 91,92,93
defargs 91,92,93,94
defargs 91,92,93,94,95
defargs ,
defargs 91,
defargs 91,92,
defargs 91,92,93,
defargs 91,92,93,94,
defargs 91,92,93,94,95,
prange1 101
prange1 101, 102
prange1 101, 102, 103
prange2 121
prange2 121, 122
prange2 121, 122, 123
prange2 {121}
prange2 {121,121}
prange2 {121},{122}
prange2 {121},122,{123}
prange2 121,{122,122},123