summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-19 16:24:53 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-19 16:24:53 -0700
commitc0ab1cd15a8008d820ebbeedb04c53bc84afd995 (patch)
tree9d4a6d48f52ff49e8b2912801ebe4114d7238445
parent992fe7591dca84b0ec5c779dad2f17b46b8ddd84 (diff)
downloadnasm-c0ab1cd15a8008d820ebbeedb04c53bc84afd995.tar.gz
preproc: fix list iteration in the case of expand_indirect()
Linked lists where an element may be deleted or substituted during processing can be subtle to deal with. Fix the iteration conditions in this particular case. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--preproc.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/preproc.c b/preproc.c
index 447f2357..e83abbe9 100644
--- a/preproc.c
+++ b/preproc.c
@@ -3901,7 +3901,8 @@ static Token *expand_id(Token * tline)
}
/*
- * Expand indirect tokens, %[...].
+ * Expand indirect tokens, %[...]. Just like expand_smacro(),
+ * the input is considered destroyed.
*/
static Token *expand_indirect(Token * tline, int level)
{
@@ -3914,42 +3915,44 @@ static Token *expand_indirect(Token * tline, int level)
error(ERR_NONFATAL, "interminable indirect expansion");
} else {
thead = NULL;
- for (tp = &tline; (t = *tp); thead = t, tp = &t->next) {
- if (t->type != TOK_INDIRECT)
- continue;
- it = tokenize(t->text);
- it = expand_indirect(it, level+1);
- it = expand_smacro(it);
- while (it) {
- skip = false;
- switch (thead ? thead->type : TOK_NONE) {
- case TOK_WHITESPACE:
- skip = (it->type == TOK_WHITESPACE);
- break;
-
- case TOK_ID:
- case TOK_NUMBER:
- if (it->type == thead->type || it->type == TOK_NUMBER) {
- char *tmp = nasm_strcat(thead->text, it->text);
- thead->text = tmp;
- skip = true;
+ tp = &tline;
+ while ((t = *tp)) {
+ if (t->type != TOK_INDIRECT) {
+ thead = t;
+ tp = &t->next;
+ } else {
+ it = tokenize(t->text);
+ it = expand_indirect(it, level+1);
+ it = expand_smacro(it);
+ while (it) {
+ skip = false;
+ switch (thead ? thead->type : TOK_NONE) {
+ case TOK_WHITESPACE:
+ skip = (it->type == TOK_WHITESPACE);
+ break;
+ case TOK_ID:
+ case TOK_NUMBER:
+ if (it->type == thead->type || it->type == TOK_NUMBER) {
+ char *tmp = nasm_strcat(thead->text, it->text);
+ nasm_free(thead->text);
+ thead->text = tmp;
+ skip = true;
+ }
+ break;
+ default:
+ break;
+ }
+ if (skip) {
+ it = delete_Token(it);
+ } else {
+ *tp = thead = it;
+ tp = &it->next;
+ it = it->next;
}
- break;
-
- default:
- break;
- }
-
- if (skip) {
- it = delete_Token(it);
- } else {
- *tp = thead = it;
- tp = &it->next;
- it = it->next;
}
+ *tp = thead = t->next;
+ t = delete_Token(t);
}
- *tp = t->next;
- delete_Token(t);
}
}
return tline;