mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-21 09:19:31 +08:00
preproc: mmacro argument fixes; listing option for mmacro args
Correctly handle empty mmacro arguments that still have preceding whitespace tokens. Default mmacro parameters are obtained by count_mmac_params() so they, too, need to be shifted over by one. Add an option to list mmacro calls with arguments. Name this -Lm; remove the old -Lm option to -Ls since it is related to single-line macros. Trivially optimize the case where an mmacro is called from within itself: if all possible mmacros are excluded by loop removal, there is no need to delve into the mmac processing code. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
parent
68075f8fa6
commit
41d91a9273
@ -2023,8 +2023,9 @@ static void help(FILE *out)
|
|||||||
" -Ld show byte and repeat counts in decimal, not hex\n"
|
" -Ld show byte and repeat counts in decimal, not hex\n"
|
||||||
" -Le show the preprocessed output\n"
|
" -Le show the preprocessed output\n"
|
||||||
" -Lf ignore .nolist (force output)\n"
|
" -Lf ignore .nolist (force output)\n"
|
||||||
" -Lm show all single-line macro definitions\n"
|
" -Lm show multi-line macro calls with expanded parmeters\n"
|
||||||
" -Lp output a list file every pass, in case of errors\n"
|
" -Lp output a list file every pass, in case of errors\n"
|
||||||
|
" -Ls show all single-line macro definitions\n"
|
||||||
" -L+ enable all listing options (very verbose!)\n"
|
" -L+ enable all listing options (very verbose!)\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -Oflags... optimize opcodes, immediates and branch offsets\n"
|
" -Oflags... optimize opcodes, immediates and branch offsets\n"
|
||||||
|
106
asm/preproc.c
106
asm/preproc.c
@ -527,7 +527,7 @@ static Token *delete_Token(Token * t);
|
|||||||
* Macros for safe checking of token pointers, avoid *(NULL)
|
* Macros for safe checking of token pointers, avoid *(NULL)
|
||||||
*/
|
*/
|
||||||
#define tok_type_(x,t) ((x) && (x)->type == (t))
|
#define tok_type_(x,t) ((x) && (x)->type == (t))
|
||||||
#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
|
#define skip_white_(x) ((x) = (tok_type_((x), TOK_WHITESPACE) ? (x)->next : (x)))
|
||||||
#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
|
#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
|
||||||
#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
|
#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
|
||||||
|
|
||||||
@ -1869,13 +1869,12 @@ static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
|
|||||||
params = nasm_malloc(paramsize * sizeof(*params));
|
params = nasm_malloc(paramsize * sizeof(*params));
|
||||||
params[0] = NULL;
|
params[0] = NULL;
|
||||||
|
|
||||||
while (t) {
|
while (skip_white_(t)) {
|
||||||
/* 2 slots for captured label and NULL */
|
/* 2 slots for captured label and NULL */
|
||||||
if (nparam+2 >= paramsize) {
|
if (nparam+2 >= paramsize) {
|
||||||
paramsize += PARAM_DELTA;
|
paramsize += PARAM_DELTA;
|
||||||
params = nasm_realloc(params, sizeof(*params) * paramsize);
|
params = nasm_realloc(params, sizeof(*params) * paramsize);
|
||||||
}
|
}
|
||||||
skip_white_(t);
|
|
||||||
brace = 0;
|
brace = 0;
|
||||||
if (tok_is_(t, "{"))
|
if (tok_is_(t, "{"))
|
||||||
brace++;
|
brace++;
|
||||||
@ -2508,7 +2507,7 @@ static SMacro *define_smacro(const char *mname, bool casesense,
|
|||||||
if (tmpl->expand)
|
if (tmpl->expand)
|
||||||
smac->expand = tmpl->expand;
|
smac->expand = tmpl->expand;
|
||||||
}
|
}
|
||||||
if (list_option('m')) {
|
if (list_option('s')) {
|
||||||
list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
|
list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
|
||||||
+ !casesense, ctx, smac);
|
+ !casesense, ctx, smac);
|
||||||
}
|
}
|
||||||
@ -2550,7 +2549,7 @@ static void undef_smacro(const char *mname, bool undefalias)
|
|||||||
s->in_progress = false;
|
s->in_progress = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (list_option('m'))
|
if (list_option('d'))
|
||||||
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
|
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
|
||||||
ctx, s);
|
ctx, s);
|
||||||
*sp = s->next;
|
*sp = s->next;
|
||||||
@ -5084,13 +5083,19 @@ static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Efficiency: first we see if any macro exists with the given
|
* Efficiency: first we see if any macro exists with the given
|
||||||
* name. If not, we can return NULL immediately. _Then_ we
|
* name which isn't already excluded by macro cycle removal.
|
||||||
|
* (The cycle removal test here helps optimize the case of wrapping
|
||||||
|
* instructions, and is cheap to do here.)
|
||||||
|
*
|
||||||
|
* If not, we can return NULL immediately. _Then_ we
|
||||||
* count the parameters, and then we look further along the
|
* count the parameters, and then we look further along the
|
||||||
* list if necessary to find the proper MMacro.
|
* list if necessary to find the proper MMacro.
|
||||||
*/
|
*/
|
||||||
list_for_each(m, head)
|
list_for_each(m, head) {
|
||||||
if (!mstrcmp(m->name, tline->text, m->casesense))
|
if (!mstrcmp(m->name, tline->text, m->casesense) &&
|
||||||
break;
|
(m->in_progress != 1 || m->max_depth > 0))
|
||||||
|
break; /* Found something that needs consideration */
|
||||||
|
}
|
||||||
if (!m)
|
if (!m)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -5124,13 +5129,12 @@ static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
|
|||||||
* parameters to the end of our list if necessary.
|
* parameters to the end of our list if necessary.
|
||||||
*/
|
*/
|
||||||
if (m->defaults && nparam < m->nparam_min + m->ndefs) {
|
if (m->defaults && nparam < m->nparam_min + m->ndefs) {
|
||||||
params =
|
int newnparam = m->nparam_min + m->ndefs;
|
||||||
nasm_realloc(params, sizeof(*params) *
|
params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
|
||||||
(m->nparam_min + m->ndefs + 2));
|
memcpy(¶ms[nparam+1], &m->defaults[nparam+1-m->nparam_min],
|
||||||
while (nparam < m->nparam_min + m->ndefs) {
|
(newnparam - nparam) * sizeof(*params));
|
||||||
nparam++;
|
nparam = newnparam;
|
||||||
params[nparam] = m->defaults[nparam - m->nparam_min];
|
params[nparam+1] = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we've gone over the maximum parameter count (and
|
* If we've gone over the maximum parameter count (and
|
||||||
@ -5218,6 +5222,57 @@ static void pop_mmacro(MMacro *m)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List an mmacro call with arguments (-La option)
|
||||||
|
*/
|
||||||
|
static void list_mmacro_call(const MMacro *m)
|
||||||
|
{
|
||||||
|
const char prefix[] = " ;;; [macro] ";
|
||||||
|
size_t namelen, size;
|
||||||
|
char *buf, *p;
|
||||||
|
unsigned int i;
|
||||||
|
const Token *t;
|
||||||
|
|
||||||
|
namelen = strlen(m->iname);
|
||||||
|
size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
|
||||||
|
|
||||||
|
for (i = 1; i <= m->nparam; i++) {
|
||||||
|
int j = 0;
|
||||||
|
size += 3; /* Braces and space/comma */
|
||||||
|
list_for_each(t, m->params[i]) {
|
||||||
|
if (j++ >= m->paramlen[i])
|
||||||
|
break;
|
||||||
|
size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = p = nasm_malloc(size);
|
||||||
|
p = mempcpy(p, prefix, sizeof(prefix) - 1);
|
||||||
|
p = mempcpy(p, m->iname, namelen);
|
||||||
|
*p++ = ' ';
|
||||||
|
|
||||||
|
for (i = 1; i <= m->nparam; i++) {
|
||||||
|
int j = 0;
|
||||||
|
*p++ = '{';
|
||||||
|
list_for_each(t, m->params[i]) {
|
||||||
|
if (j++ >= m->paramlen[i])
|
||||||
|
break;
|
||||||
|
if (!t->text) {
|
||||||
|
if (t->type == TOK_WHITESPACE)
|
||||||
|
*p++ = ' ';
|
||||||
|
} else {
|
||||||
|
p = mempcpy(p, t->text, t->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p++ = '}';
|
||||||
|
*p++ = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
*--p = '\0'; /* Replace last delimeter with null */
|
||||||
|
lfmt->line(LIST_MACRO, -1, buf);
|
||||||
|
nasm_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand the multi-line macro call made by the given line, if
|
* Expand the multi-line macro call made by the given line, if
|
||||||
* there is one to be expanded. If there is, push the expansion on
|
* there is one to be expanded. If there is, push the expansion on
|
||||||
@ -5287,20 +5342,24 @@ static int expand_mmacro(Token * tline)
|
|||||||
*/
|
*/
|
||||||
nasm_newn(paramlen, nparam+1);
|
nasm_newn(paramlen, nparam+1);
|
||||||
|
|
||||||
|
nasm_assert(params[nparam+1] == NULL);
|
||||||
|
|
||||||
for (i = 1; (t = params[i]); i++) {
|
for (i = 1; (t = params[i]); i++) {
|
||||||
int brace = 0;
|
int brace = 0;
|
||||||
int comma = !m->plus || i < nparam;
|
bool comma = !m->plus || i < nparam;
|
||||||
|
|
||||||
skip_white_(t);
|
skip_white_(t);
|
||||||
if (tok_is_(t, "{"))
|
if (tok_is_(t, "{"))
|
||||||
t = t->next, brace++, comma = false;
|
t = t->next, brace++, comma = false;
|
||||||
params[i] = t;
|
params[i] = t;
|
||||||
while (t) {
|
while (t) {
|
||||||
if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
|
if (comma) {
|
||||||
break; /* ... because we have hit a comma */
|
/* Check if we hit a comma that ends this argument */
|
||||||
if (comma && t->type == TOK_WHITESPACE
|
if (tok_is_(t, ","))
|
||||||
&& tok_is_(t->next, ","))
|
break;
|
||||||
break; /* ... or a space then a comma */
|
else if (t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (brace && t->type == TOK_OTHER) {
|
if (brace && t->type == TOK_OTHER) {
|
||||||
if (t->text[0] == '{')
|
if (t->text[0] == '{')
|
||||||
brace++; /* ... or a nested opening brace */
|
brace++; /* ... or a nested opening brace */
|
||||||
@ -5396,6 +5455,9 @@ static int expand_mmacro(Token * tline)
|
|||||||
|
|
||||||
lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
|
lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
|
||||||
|
|
||||||
|
if (list_option('m') && !m->nolist)
|
||||||
|
list_mmacro_call(m);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user