summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2020-06-30 11:51:41 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2020-06-30 11:51:41 -0700
commite99a946390e561804bf624a1e67f25ae34b13dfd (patch)
tree79b64c9f824147a7371bb6c3336035a00e01399f
parent5c85b7f87b71134d95dbb01c69406cc08a7f9503 (diff)
downloadnasm-e99a946390e561804bf624a1e67f25ae34b13dfd.tar.gz
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>
-rw-r--r--asm/preproc.c87
-rw-r--r--[l---------]test/emptyarg.asm140
2 files changed, 164 insertions, 63 deletions
diff --git a/asm/preproc.c b/asm/preproc.c
index 14ca17d3..2165fa12 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -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;
-
- pos = strchr(tok_text(tline), ':');
- nasm_assert(pos);
+ Token *t;
+ const char *arg = tok_text(tline) + 1;
+ int fst, lst, incr, n;
+ int parsed;
- 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;
- 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;
- }
- }
+ 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;
}
- *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;
}
diff --git a/test/emptyarg.asm b/test/emptyarg.asm
index 0627dfae..f164fe41 120000..100644
--- a/test/emptyarg.asm
+++ b/test/emptyarg.asm
@@ -1 +1,139 @@
-../../nasm-2.14.xx/test/emptyarg.asm \ No newline at end of file
+%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