mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-09-22 10:43:39 -04:00
preproc: unify token-pasting code
Unify the token-pasting code between the macro expansion and the preprocessor parameter case. Parameterize whether or not to handle %+ tokens during expansion (%+ tokens have late binding semantics.) Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
210
preproc.c
210
preproc.c
@@ -159,6 +159,7 @@ enum pp_token_type {
|
|||||||
TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
|
TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
|
||||||
TOK_INTERNAL_STRING,
|
TOK_INTERNAL_STRING,
|
||||||
TOK_PREPROC_Q, TOK_PREPROC_QQ,
|
TOK_PREPROC_Q, TOK_PREPROC_QQ,
|
||||||
|
TOK_PASTE, /* %+ */
|
||||||
TOK_INDIRECT, /* %[...] */
|
TOK_INDIRECT, /* %[...] */
|
||||||
TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
|
TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
|
||||||
TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
|
TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
|
||||||
@@ -788,9 +789,11 @@ static Token *tokenize(char *line)
|
|||||||
p = line;
|
p = line;
|
||||||
if (*p == '%') {
|
if (*p == '%') {
|
||||||
p++;
|
p++;
|
||||||
if (nasm_isdigit(*p) ||
|
if (*p == '+' && !nasm_isdigit(p[1])) {
|
||||||
((*p == '-' || *p == '+') && nasm_isdigit(p[1])) ||
|
p++;
|
||||||
((*p == '+') && (nasm_isspace(p[1]) || !p[1]))) {
|
type = TOK_PASTE;
|
||||||
|
} else if (nasm_isdigit(*p) ||
|
||||||
|
((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
|
||||||
do {
|
do {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@@ -942,7 +945,7 @@ static Token *tokenize(char *line)
|
|||||||
/* 1e13 is floating-point, but 1e13h is not */
|
/* 1e13 is floating-point, but 1e13h is not */
|
||||||
is_float = true;
|
is_float = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = is_float ? TOK_FLOAT : TOK_NUMBER;
|
type = is_float ? TOK_FLOAT : TOK_NUMBER;
|
||||||
}
|
}
|
||||||
} else if (nasm_isspace(*p)) {
|
} else if (nasm_isspace(*p)) {
|
||||||
@@ -3326,6 +3329,109 @@ static int find_cc(Token * t)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool paste_tokens(Token **head, bool handle_paste_tokens)
|
||||||
|
{
|
||||||
|
Token **tail, *t, *tt;
|
||||||
|
Token **paste_head;
|
||||||
|
bool did_paste = false;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
/* Now handle token pasting... */
|
||||||
|
paste_head = NULL;
|
||||||
|
tail = head;
|
||||||
|
while ((t = *tail) && (tt = t->next)) {
|
||||||
|
switch (t->type) {
|
||||||
|
case TOK_WHITESPACE:
|
||||||
|
if (tt->type == TOK_WHITESPACE) {
|
||||||
|
/* Zap adjacent whitespace tokens */
|
||||||
|
t->next = delete_Token(tt);
|
||||||
|
} else {
|
||||||
|
/* Do not advance paste_head here */
|
||||||
|
tail = &t->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOK_ID:
|
||||||
|
case TOK_PREPROC_ID:
|
||||||
|
case TOK_NUMBER:
|
||||||
|
case TOK_FLOAT:
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
char *tmp, *p;
|
||||||
|
|
||||||
|
while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
|
||||||
|
tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
|
||||||
|
tt->type == TOK_OTHER)) {
|
||||||
|
len += strlen(tt->text);
|
||||||
|
tt = tt->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now tt points to the first token after the potential
|
||||||
|
paste area... */
|
||||||
|
if (tt != t->next) {
|
||||||
|
/* We have at least two tokens... */
|
||||||
|
len += strlen(t->text);
|
||||||
|
p = tmp = nasm_malloc(len+1);
|
||||||
|
|
||||||
|
while (t != tt) {
|
||||||
|
strcpy(p, t->text);
|
||||||
|
p = strchr(p, '\0');
|
||||||
|
t = delete_Token(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
t = *tail = tokenize(tmp);
|
||||||
|
nasm_free(tmp);
|
||||||
|
|
||||||
|
while (t->next) {
|
||||||
|
tail = &t->next;
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
|
t->next = tt; /* Attach the remaining token chain */
|
||||||
|
|
||||||
|
did_paste = true;
|
||||||
|
}
|
||||||
|
paste_head = tail;
|
||||||
|
tail = &t->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOK_PASTE: /* %+ */
|
||||||
|
if (handle_paste_tokens) {
|
||||||
|
/* Zap %+ and whitespace tokens to the right */
|
||||||
|
while (t && (t->type == TOK_WHITESPACE ||
|
||||||
|
t->type == TOK_PASTE))
|
||||||
|
t = *tail = delete_Token(t);
|
||||||
|
if (!paste_head || !t)
|
||||||
|
break; /* Nothing to paste with */
|
||||||
|
tail = paste_head;
|
||||||
|
t = *tail;
|
||||||
|
tt = t->next;
|
||||||
|
while (tok_type_(tt, TOK_WHITESPACE))
|
||||||
|
tt = t->next = delete_Token(tt);
|
||||||
|
|
||||||
|
if (tt) {
|
||||||
|
tmp = nasm_strcat(t->text, tt->text);
|
||||||
|
delete_Token(t);
|
||||||
|
tt = delete_Token(tt);
|
||||||
|
t = *tail = tokenize(tmp);
|
||||||
|
nasm_free(tmp);
|
||||||
|
while (t->next) {
|
||||||
|
tail = &t->next;
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
|
t->next = tt; /* Attach the remaining token chain */
|
||||||
|
did_paste = true;
|
||||||
|
}
|
||||||
|
paste_head = tail;
|
||||||
|
tail = &t->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* else fall through */
|
||||||
|
default:
|
||||||
|
tail = paste_head = &t->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return did_paste;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Expand MMacro-local things: parameter references (%0, %n, %+n,
|
* Expand MMacro-local things: parameter references (%0, %n, %+n,
|
||||||
* %-n) and MMacro-local identifiers (%%foo) as well as
|
* %-n) and MMacro-local identifiers (%%foo) as well as
|
||||||
@@ -3476,63 +3582,9 @@ static Token *expand_mmac_params(Token * tline)
|
|||||||
}
|
}
|
||||||
*tail = NULL;
|
*tail = NULL;
|
||||||
|
|
||||||
if (!changed)
|
if (changed)
|
||||||
return thead;
|
paste_tokens(&thead, false);
|
||||||
|
|
||||||
/* Now handle token pasting... */
|
|
||||||
tail = &thead;
|
|
||||||
while ((t = *tail) && (tt = t->next)) {
|
|
||||||
switch (t->type) {
|
|
||||||
case TOK_WHITESPACE:
|
|
||||||
if (tt->type == TOK_WHITESPACE) {
|
|
||||||
t->next = delete_Token(tt);
|
|
||||||
} else {
|
|
||||||
tail = &t->next;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TOK_ID:
|
|
||||||
case TOK_NUMBER:
|
|
||||||
case TOK_FLOAT:
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
char *tmp, *p;
|
|
||||||
|
|
||||||
while (tt &&
|
|
||||||
(tt->type == TOK_ID || tt->type == TOK_NUMBER ||
|
|
||||||
tt->type == TOK_FLOAT || tt->type == TOK_OTHER)) {
|
|
||||||
len += strlen(tt->text);
|
|
||||||
tt = tt->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now tt points to the first token after the potential
|
|
||||||
paste area... */
|
|
||||||
if (tt != t->next) {
|
|
||||||
/* We have at least two tokens... */
|
|
||||||
len += strlen(t->text);
|
|
||||||
p = tmp = nasm_malloc(len+1);
|
|
||||||
|
|
||||||
while (t != tt) {
|
|
||||||
strcpy(p, t->text);
|
|
||||||
p = strchr(p, '\0');
|
|
||||||
t = delete_Token(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
t = *tail = tokenize(tmp);
|
|
||||||
nasm_free(tmp);
|
|
||||||
|
|
||||||
while (t->next)
|
|
||||||
t = t->next;
|
|
||||||
|
|
||||||
t->next = tt; /* Attach the remaining token chain */
|
|
||||||
}
|
|
||||||
tail = &t->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
tail = &t->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return thead;
|
return thead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3553,11 +3605,12 @@ static Token *expand_smacro(Token * tline)
|
|||||||
Token **params;
|
Token **params;
|
||||||
int *paramsize;
|
int *paramsize;
|
||||||
unsigned int nparam, sparam;
|
unsigned int nparam, sparam;
|
||||||
int brackets, rescan;
|
int brackets;
|
||||||
Token *org_tline = tline;
|
Token *org_tline = tline;
|
||||||
Context *ctx;
|
Context *ctx;
|
||||||
const char *mname;
|
const char *mname;
|
||||||
int deadman = DEADMAN_LIMIT;
|
int deadman = DEADMAN_LIMIT;
|
||||||
|
bool expanded;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trick: we should avoid changing the start token pointer since it can
|
* Trick: we should avoid changing the start token pointer since it can
|
||||||
@@ -3577,6 +3630,7 @@ static Token *expand_smacro(Token * tline)
|
|||||||
again:
|
again:
|
||||||
tail = &thead;
|
tail = &thead;
|
||||||
thead = NULL;
|
thead = NULL;
|
||||||
|
expanded = false;
|
||||||
|
|
||||||
while (tline) { /* main token loop */
|
while (tline) { /* main token loop */
|
||||||
if (!--deadman) {
|
if (!--deadman) {
|
||||||
@@ -3821,6 +3875,7 @@ again:
|
|||||||
nasm_free(params);
|
nasm_free(params);
|
||||||
nasm_free(paramsize);
|
nasm_free(paramsize);
|
||||||
free_tlist(mstart);
|
free_tlist(mstart);
|
||||||
|
expanded = true;
|
||||||
continue; /* main token loop */
|
continue; /* main token loop */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3845,37 +3900,8 @@ again:
|
|||||||
* Also we look for %+ tokens and concatenate the tokens before and after
|
* Also we look for %+ tokens and concatenate the tokens before and after
|
||||||
* them (without white spaces in between).
|
* them (without white spaces in between).
|
||||||
*/
|
*/
|
||||||
t = thead;
|
if (expanded && paste_tokens(&thead, true)) {
|
||||||
rescan = 0;
|
/* If we concatenated something, re-scan the line for macros */
|
||||||
while (t) {
|
|
||||||
while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
|
|
||||||
t = t->next;
|
|
||||||
if (!t || !t->next)
|
|
||||||
break;
|
|
||||||
if (t->next->type == TOK_ID ||
|
|
||||||
t->next->type == TOK_PREPROC_ID ||
|
|
||||||
t->next->type == TOK_NUMBER) {
|
|
||||||
char *p = nasm_strcat(t->text, t->next->text);
|
|
||||||
nasm_free(t->text);
|
|
||||||
t->next = delete_Token(t->next);
|
|
||||||
t->text = p;
|
|
||||||
rescan = 1;
|
|
||||||
} else if (t->next->type == TOK_WHITESPACE && t->next->next &&
|
|
||||||
t->next->next->type == TOK_PREPROC_ID &&
|
|
||||||
strcmp(t->next->next->text, "%+") == 0) {
|
|
||||||
/* free the next whitespace, the %+ token and next whitespace */
|
|
||||||
int i;
|
|
||||||
for (i = 1; i <= 3; i++) {
|
|
||||||
if (!t->next
|
|
||||||
|| (i != 2 && t->next->type != TOK_WHITESPACE))
|
|
||||||
break;
|
|
||||||
t->next = delete_Token(t->next);
|
|
||||||
} /* endfor */
|
|
||||||
} else
|
|
||||||
t = t->next;
|
|
||||||
}
|
|
||||||
/* If we concatenaded something, re-scan the line for macros */
|
|
||||||
if (rescan) {
|
|
||||||
tline = thead;
|
tline = thead;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
@@ -23,3 +23,7 @@
|
|||||||
df 33, 20
|
df 33, 20
|
||||||
df 0, 2
|
df 0, 2
|
||||||
df 1.2, 5
|
df 1.2, 5
|
||||||
|
|
||||||
|
|
||||||
|
%define N 1e%++%+ 5
|
||||||
|
dd N, 1e+5
|
||||||
|
Reference in New Issue
Block a user