diff options
Diffstat (limited to 'asm/preproc.c')
-rw-r--r-- | asm/preproc.c | 143 |
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 = { |