mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-15 09:09:58 +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"
|
||||
" -Le show the preprocessed 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"
|
||||
" -Ls show all single-line macro definitions\n"
|
||||
" -L+ enable all listing options (very verbose!)\n"
|
||||
"\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)
|
||||
*/
|
||||
#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_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[0] = NULL;
|
||||
|
||||
while (t) {
|
||||
while (skip_white_(t)) {
|
||||
/* 2 slots for captured label and NULL */
|
||||
if (nparam+2 >= paramsize) {
|
||||
paramsize += PARAM_DELTA;
|
||||
params = nasm_realloc(params, sizeof(*params) * paramsize);
|
||||
}
|
||||
skip_white_(t);
|
||||
brace = 0;
|
||||
if (tok_is_(t, "{"))
|
||||
brace++;
|
||||
@ -2508,7 +2507,7 @@ static SMacro *define_smacro(const char *mname, bool casesense,
|
||||
if (tmpl->expand)
|
||||
smac->expand = tmpl->expand;
|
||||
}
|
||||
if (list_option('m')) {
|
||||
if (list_option('s')) {
|
||||
list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
|
||||
+ !casesense, ctx, smac);
|
||||
}
|
||||
@ -2550,7 +2549,7 @@ static void undef_smacro(const char *mname, bool undefalias)
|
||||
s->in_progress = false;
|
||||
}
|
||||
} else {
|
||||
if (list_option('m'))
|
||||
if (list_option('d'))
|
||||
list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
|
||||
ctx, s);
|
||||
*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
|
||||
* 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
|
||||
* list if necessary to find the proper MMacro.
|
||||
*/
|
||||
list_for_each(m, head)
|
||||
if (!mstrcmp(m->name, tline->text, m->casesense))
|
||||
break;
|
||||
list_for_each(m, head) {
|
||||
if (!mstrcmp(m->name, tline->text, m->casesense) &&
|
||||
(m->in_progress != 1 || m->max_depth > 0))
|
||||
break; /* Found something that needs consideration */
|
||||
}
|
||||
if (!m)
|
||||
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.
|
||||
*/
|
||||
if (m->defaults && nparam < m->nparam_min + m->ndefs) {
|
||||
params =
|
||||
nasm_realloc(params, sizeof(*params) *
|
||||
(m->nparam_min + m->ndefs + 2));
|
||||
while (nparam < m->nparam_min + m->ndefs) {
|
||||
nparam++;
|
||||
params[nparam] = m->defaults[nparam - m->nparam_min];
|
||||
}
|
||||
int newnparam = m->nparam_min + m->ndefs;
|
||||
params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
|
||||
memcpy(¶ms[nparam+1], &m->defaults[nparam+1-m->nparam_min],
|
||||
(newnparam - nparam) * sizeof(*params));
|
||||
nparam = newnparam;
|
||||
params[nparam+1] = NULL;
|
||||
}
|
||||
/*
|
||||
* If we've gone over the maximum parameter count (and
|
||||
@ -5218,6 +5222,57 @@ static void pop_mmacro(MMacro *m)
|
||||
|
||||
#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
|
||||
* 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_assert(params[nparam+1] == NULL);
|
||||
|
||||
for (i = 1; (t = params[i]); i++) {
|
||||
int brace = 0;
|
||||
int comma = !m->plus || i < nparam;
|
||||
bool comma = !m->plus || i < nparam;
|
||||
|
||||
skip_white_(t);
|
||||
if (tok_is_(t, "{"))
|
||||
t = t->next, brace++, comma = false;
|
||||
params[i] = t;
|
||||
while (t) {
|
||||
if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
|
||||
break; /* ... because we have hit a comma */
|
||||
if (comma && t->type == TOK_WHITESPACE
|
||||
&& tok_is_(t->next, ","))
|
||||
break; /* ... or a space then a comma */
|
||||
if (comma) {
|
||||
/* Check if we hit a comma that ends this argument */
|
||||
if (tok_is_(t, ","))
|
||||
break;
|
||||
else if (t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
|
||||
break;
|
||||
}
|
||||
if (brace && t->type == TOK_OTHER) {
|
||||
if (t->text[0] == '{')
|
||||
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);
|
||||
|
||||
if (list_option('m') && !m->nolist)
|
||||
list_mmacro_call(m);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user