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>
This commit is contained in:
H. Peter Anvin 2008-10-19 16:24:53 -07:00
parent 992fe7591d
commit c0ab1cd15a

View File

@ -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) 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"); error(ERR_NONFATAL, "interminable indirect expansion");
} else { } else {
thead = NULL; thead = NULL;
for (tp = &tline; (t = *tp); thead = t, tp = &t->next) { tp = &tline;
if (t->type != TOK_INDIRECT) while ((t = *tp)) {
continue; if (t->type != TOK_INDIRECT) {
it = tokenize(t->text); thead = t;
it = expand_indirect(it, level+1); tp = &t->next;
it = expand_smacro(it); } else {
while (it) { it = tokenize(t->text);
skip = false; it = expand_indirect(it, level+1);
switch (thead ? thead->type : TOK_NONE) { it = expand_smacro(it);
case TOK_WHITESPACE: while (it) {
skip = (it->type == TOK_WHITESPACE); skip = false;
break; switch (thead ? thead->type : TOK_NONE) {
case TOK_WHITESPACE:
case TOK_ID: skip = (it->type == TOK_WHITESPACE);
case TOK_NUMBER: break;
if (it->type == thead->type || it->type == TOK_NUMBER) { case TOK_ID:
char *tmp = nasm_strcat(thead->text, it->text); case TOK_NUMBER:
thead->text = tmp; if (it->type == thead->type || it->type == TOK_NUMBER) {
skip = true; 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; return tline;