summaryrefslogtreecommitdiff
path: root/asm/preproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'asm/preproc.c')
-rw-r--r--asm/preproc.c143
1 files changed, 87 insertions, 56 deletions
diff --git a/asm/preproc.c b/asm/preproc.c
index aded0bec..5cb92879 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -231,6 +231,17 @@ struct SMacro {
};
/*
+ * "No listing" flags. Inside a loop (%rep..%endrep) we may have
+ * macro listing suppressed with .nolist, but we still need to
+ * update line numbers for error messages and debug information...
+ * unless we are nested inside an actual .nolist macro.
+ */
+enum nolist_flags {
+ NL_LIST = 1, /* Suppress list output */
+ NL_LINE = 2 /* Don't update line information */
+};
+
+/*
* Store the definition of a multi-line macro. This is also used to
* store the interiors of `%rep...%endrep' blocks, which are
* effectively self-re-invoking multi-line macros which simply
@@ -264,9 +275,9 @@ struct MMacro {
#endif
char *name;
int nparam_min, nparam_max;
+ enum nolist_flags nolist; /* is this macro listing-inhibited? */
bool casesense;
bool plus; /* is the last parameter greedy? */
- bool nolist; /* is this macro listing-inhibited? */
bool capture_label; /* macro definition has %00; capture label */
int32_t in_progress; /* is this macro currently being expanded? */
int32_t max_depth; /* maximum number of recursive expansions allowed */
@@ -447,16 +458,22 @@ struct Line {
/*
* To handle an arbitrary level of file inclusion, we maintain a
* stack (ie linked list) of these things.
+ *
+ * Note: when we issue a message for a continuation line, we want to
+ * issue it for the actual *start* of the continuation line. This means
+ * we need to remember how many lines to skip over for the next one.
*/
struct Include {
Include *next;
FILE *fp;
Cond *conds;
Line *expansion;
+ uint64_t nolist; /* Listing inhibit counter */
+ uint64_t noline; /* Line number update inhibit counter */
struct mstk mstk;
- struct src_location where; /* Filename and current line number */
+ struct src_location where; /* Filename and current line number */
int32_t lineinc; /* Increment given by %line */
- bool nolist;
+ int32_t lineskip; /* Accounting for passed continuation lines */
};
/*
@@ -1298,10 +1315,13 @@ static char *line_from_file(FILE *f)
unsigned int size, next;
const unsigned int delta = 512;
const unsigned int pad = 8;
- unsigned int nr_cont = 0;
bool cont = false;
char *buffer, *p;
+ istk->where.lineno += istk->lineskip + istk->lineinc;
+ src_set_linnum(istk->where.lineno);
+ istk->lineskip = 0;
+
size = delta;
p = buffer = nasm_malloc(size);
@@ -1345,7 +1365,7 @@ static char *line_from_file(FILE *f)
ungetc(next, f);
if (next == '\r' || next == '\n') {
cont = true;
- nr_cont++;
+ istk->lineskip += istk->lineinc;
continue;
}
break;
@@ -1360,9 +1380,6 @@ static char *line_from_file(FILE *f)
*p++ = c;
} while (c);
- istk->where.lineno += (nr_cont + 1) * istk->lineinc;
- src_set_linnum(istk->where.lineno);
-
return buffer;
}
@@ -1382,8 +1399,8 @@ static char *read_line(void)
if (!line)
return NULL;
- if (!istk->nolist)
- lfmt->line(LIST_READ, istk->where.lineno, line);
+ if (!istk->nolist)
+ lfmt->line(LIST_READ, istk->where.lineno, line);
return line;
}
@@ -3133,7 +3150,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
#endif
def->name = dup_text(tline);
def->plus = false;
- def->nolist = false;
+ def->nolist = 0;
def->nparam_min = 0;
def->nparam_max = 0;
@@ -3165,7 +3182,8 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
tline->next->len == 7 &&
!nasm_stricmp(tline->next->text.a, ".nolist")) {
tline = tline->next;
- def->nolist = !list_option('f') || istk->nolist;
+ if (!list_option('f'))
+ def->nolist |= NL_LIST|NL_LINE;
}
/*
@@ -3362,7 +3380,7 @@ static int do_directive(Token *tline, Token **output)
enum preproc_token op;
int j;
bool err;
- bool nolist;
+ enum nolist_flags nolist;
bool casesense;
int k, m;
int offset;
@@ -3798,10 +3816,12 @@ static int do_directive(Token *tline, Token **output)
/* -MG given but file not found */
nasm_free(inc);
} else {
- src_set(0, found_path ? found_path : p);
inc->where = src_where();
inc->lineinc = 1;
inc->nolist = istk->nolist;
+ inc->noline = istk->noline;
+ if (!inc->noline)
+ src_set(0, found_path ? found_path : p);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@@ -3827,8 +3847,10 @@ static int do_directive(Token *tline, Token **output)
stdmacpos = pkg->macros;
nasm_new(inc);
inc->next = istk;
- src_set(0, NULL);
- inc->nolist = !list_option('b') || istk->nolist;
+ inc->nolist = istk->nolist + !list_option('b');
+ inc->noline = istk->noline;
+ if (!inc->noline)
+ src_set(0, NULL);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@@ -4153,11 +4175,12 @@ issue_error:
{
MMacro *tmp_defining;
- nolist = false;
+ nolist = 0;
tline = skip_white(tline->next);
if (tok_type(tline, TOK_ID) && tline->len == 7 &&
!nasm_memicmp(tline->text.a, ".nolist", 7)) {
- nolist = !list_option('f') || istk->nolist;
+ if (!list_option('f'))
+ nolist |= NL_LIST; /* ... but update line numbers */
tline = skip_white(tline->next);
}
@@ -4234,7 +4257,11 @@ issue_error:
istk->mstk.mstk = defining;
- lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
+ /* A loop does not change istk->noline */
+ istk->nolist += !!(defining->nolist & NL_LIST);
+ if (!istk->nolist)
+ lfmt->uplevel(LIST_MACRO, 0);
+
defining = defining->dstk.mstk;
break;
@@ -6289,10 +6316,18 @@ static int expand_mmacro(Token * tline)
}
}
- lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
+ istk->nolist += !!(m->nolist & NL_LIST);
+ istk->noline += !!(m->nolist & NL_LINE);
- if (list_option('m') && !m->nolist)
- list_mmacro_call(m);
+ if (!istk->nolist) {
+ lfmt->uplevel(LIST_MACRO, 0);
+
+ if (list_option('m'))
+ list_mmacro_call(m);
+ }
+
+ if (!istk->noline)
+ src_macro_push(m, istk->where);
return 1;
}
@@ -6515,6 +6550,8 @@ static Token *pp_tokline(void)
while (l && l->finishes) {
MMacro *fm = l->finishes;
+ nasm_assert(fm == istk->mstk.mstk);
+
if (!fm->name && fm->in_progress > 1) {
/*
* This is a macro-end marker for a macro with no
@@ -6594,6 +6631,22 @@ static Token *pp_tokline(void)
}
}
+ if (fm->nolist & NL_LIST) {
+ istk->nolist--;
+ } else if (!istk->nolist) {
+ lfmt->downlevel(LIST_MACRO);
+ }
+
+ if (fm->nolist & NL_LINE) {
+ istk->noline--;
+ } else if (!istk->noline) {
+ if (fm == src_macro_current())
+ src_macro_pop();
+ src_update(l->where);
+ }
+
+ istk->where = l->where;
+
/*
* FIXME It is incorrect to always free_mmacro here.
* It leads to usage-after-free.
@@ -6605,10 +6658,9 @@ static Token *pp_tokline(void)
free_mmacro(m);
#endif
}
- istk->where = l->where;
istk->expansion = l->next;
nasm_free(l);
- lfmt->downlevel(LIST_MACRO);
+
return &tok_pop;
}
@@ -6623,6 +6675,9 @@ static Token *pp_tokline(void)
tline = l->first;
nasm_free(l);
+ if (!istk->noline)
+ src_update(istk->where);
+
if (!istk->nolist) {
line = detoken(tline, false);
lfmt->line(LIST_MACRO, istk->where.lineno, line);
@@ -6939,44 +6994,20 @@ static Token *make_tok_char(Token *next, char op)
}
/*
- * Descend the istk looking for macro definitions; we have to
- * recurse because we want to show the messages in top-down order.
+ * Descent the macro hierarchy and display the expansion after
+ * encountering an error message.
*/
-static void pp_list_macro_istk(Include *inc, errflags severity)
+static void pp_error_list_macros(errflags severity)
{
- MMacro *m;
- Include *inext;
-
- /* Find the next higher level true macro invocation if any */
- inext = inc->next;
- if (inext && inext->mstk.mmac) {
- while (inext) {
- if (inext->mstk.mstk->name) {
- pp_list_macro_istk(inext, severity);
- break;
- }
- inext = inext->next;
- }
- }
+ const MMacro *m;
- m = inc->mstk.mstk;
- if (m && m->name && !m->nolist) {
- src_update(inc->where);
+ severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
+
+ while ((m = src_error_down())) {
nasm_error(severity, "... from macro `%s' defined", m->name);
}
-}
-static void pp_error_list_macros(errflags severity)
-{
- struct src_location saved;
-
- if (!istk)
- return;
-
- severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
- saved = src_where();
- pp_list_macro_istk(istk, severity);
- src_update(saved);
+ src_error_reset();
}
const struct preproc_ops nasmpp = {