[nasm:nasm-2.15.xx] Make debug info and error messages correctly reflect macros and reps

nasm-bot for H. Peter Anvin (Intel) hpa at zytor.com
Sun Jul 5 02:21:06 PDT 2020


Commit-ID:  5b7369d7e0e256684bc92ab2ec8a822d9eb32e32
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=5b7369d7e0e256684bc92ab2ec8a822d9eb32e32
Author:     H. Peter Anvin (Intel) <hpa at zytor.com>
AuthorDate: Sun, 5 Jul 2020 02:16:13 -0700
Committer:  H. Peter Anvin (Intel) <hpa at zytor.com>
CommitDate: Sun, 5 Jul 2020 02:16:13 -0700

Make debug info and error messages correctly reflect macros and reps

1. Error messages would issue with the line number of %endrep.
2. Debug line information would ignore both macros and reps.
   This is doubly wrong; macros are semantically equivalent to
   inline functions, and it is expected that debuggers trace
   into these functions.

These changes finishes the last parts of moving all responsibility for
the listing enable/disable into the preprocessor, so remove the
way over-complicated macro inhibit facility from the listing module
entirely.

Signed-off-by: H. Peter Anvin (Intel) <hpa at zytor.com>


---
 asm/listing.c    |  50 +------------------
 asm/nasm.c       |  82 ++++++++++++++++---------------
 asm/preproc.c    | 143 +++++++++++++++++++++++++++++++++----------------------
 asm/srcfile.c    |  41 ++++++++++++++--
 asm/srcfile.h    |  77 +++++++++++++++++++++++++-----
 include/nasm.h   |   1 -
 test/exitrep.asm |  30 ++++++++++--
 7 files changed, 260 insertions(+), 164 deletions(-)

diff --git a/asm/listing.c b/asm/listing.c
index 6d6f3606..f6ef6d1b 100644
--- a/asm/listing.c
+++ b/asm/listing.c
@@ -49,14 +49,6 @@
 #define LIST_INDENT  40
 #define LIST_HEXBIT  18
 
-typedef struct MacroInhibit MacroInhibit;
-
-static struct MacroInhibit {
-    MacroInhibit *next;
-    int level;
-    int inhibiting;
-} *mistack;
-
 static const char xdigit[] = "0123456789ABCDEF";
 
 #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
@@ -135,12 +127,6 @@ static void list_cleanup(void)
     if (!listfp)
         return;
 
-    while (mistack) {
-        MacroInhibit *temp = mistack;
-        mistack = temp->next;
-        nasm_free(temp);
-    }
-
     list_emit();
     fclose(listfp);
     listfp = NULL;
@@ -172,10 +158,6 @@ static void list_init(const char *fname)
     list_errors = NULL;
     listlevel = 0;
     suppress = 0;
-    nasm_new(mistack);
-    mistack->next = NULL;
-    mistack->level = 0;
-    mistack->inhibiting = true;
 }
 
 static void list_out(int64_t offset, char *str)
@@ -292,21 +274,14 @@ static void list_output(const struct out_data *data)
 
 static void list_line(int type, int32_t lineno, const char *line)
 {
+    (void)type;
+
     if (!listfp)
         return;
 
     if (user_nolist)
       return;
 
-    if (mistack && mistack->inhibiting) {
-        if (type == LIST_MACRO)
-            return;
-        else {                  /* pop the m i stack */
-            MacroInhibit *temp = mistack;
-            mistack = temp->next;
-            nasm_free(temp);
-        }
-    }
     list_emit();
     if (lineno >= 0)
         listlineno = lineno;
@@ -316,15 +291,6 @@ static void list_line(int type, int32_t lineno, const char *line)
     listlevel_e = listlevel;
 }
 
-static void mistack_push(bool inhibiting)
-{
-    MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
-    temp->next = mistack;
-    temp->level = listlevel;
-    temp->inhibiting = inhibiting;
-    mistack = temp;
-}
-
 static void list_uplevel(int type, int64_t size)
 {
     if (!listfp)
@@ -343,13 +309,6 @@ static void list_uplevel(int type, int64_t size)
 
     case LIST_INCLUDE:
         listlevel++;
-        if (mistack && mistack->inhibiting)
-            mistack_push(false);
-        break;
-
-    case LIST_MACRO_NOLIST:
-        listlevel++;
-        mistack_push(true);
         break;
 
     default:
@@ -374,11 +333,6 @@ static void list_downlevel(int type)
 
     default:
         listlevel--;
-        while (mistack && mistack->level > listlevel) {
-            MacroInhibit *temp = mistack;
-            mistack = temp->next;
-            nasm_free(temp);
-        }
         break;
     }
 }
diff --git a/asm/nasm.c b/asm/nasm.c
index 557484c1..69a3db55 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -1932,6 +1932,32 @@ static fatal_func die_hard(errflags true_type, errflags severity)
     exit(true_type - ERR_FATAL + 1);
 }
 
+/*
+ * Returns the struct src_location appropriate for use, after some
+ * potential filename mangling.
+ */
+static struct src_location error_where(errflags severity)
+{
+    struct src_location where;
+
+    if (severity & ERR_NOFILE) {
+        where.filename = NULL;
+        where.lineno = 0;
+    } else {
+        where = src_where_error();
+
+        if (!where.filename) {
+            where.filename =
+            inname && inname[0] ? inname :
+                outname && outname[0] ? outname :
+                NULL;
+            where.lineno = 0;
+        }
+    }
+
+    return where;
+}
+
 /*
  * error reporting for critical and panic errors: minimize
  * the amount of system dependencies for getting a message out,
@@ -1939,8 +1965,7 @@ static fatal_func die_hard(errflags true_type, errflags severity)
  */
 fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args)
 {
-    const char *currentfile = no_file_name;
-    int32_t lineno = 0;
+    struct src_location where;
     errflags true_type = severity & ERR_MASK;
     static bool been_here = false;
 
@@ -1949,22 +1974,15 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
 
     been_here = true;
 
-    if (!(severity & ERR_NOFILE)) {
-        src_get(&lineno, &currentfile);
-        if (!currentfile) {
-            currentfile =
-                inname && inname[0] ? inname :
-                outname && outname[0] ? outname :
-                no_file_name;
-                lineno = 0;
-        }
-    }
+    where = error_where(severity);
+    if (!where.filename)
+        where.filename = no_file_name;
 
     fputs(error_pfx_table[severity], error_file);
-    fputs(currentfile, error_file);
-    if (lineno) {
+    fputs(where.filename, error_file);
+    if (where.lineno) {
         fprintf(error_file, "%s%"PRId32"%s",
-                errfmt->beforeline, lineno, errfmt->afterline);
+                errfmt->beforeline, where.lineno, errfmt->afterline);
     }
     fputs(errfmt->beforemsg, error_file);
     vfprintf(error_file, fmt, args);
@@ -1978,11 +1996,10 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
  */
 struct nasm_errtext {
     struct nasm_errtext *next;
-    const char *currentfile;    /* Owned by the filename system */
     char *msg;                  /* Owned by this structure */
+    struct src_location where;  /* Owned by the srcfile system */
     errflags severity;
     errflags true_type;
-    int32_t lineno;
 };
 struct nasm_errhold {
     struct nasm_errhold *up;
@@ -2067,17 +2084,7 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
     et->severity = severity;
     et->true_type = true_type;
     et->msg = nasm_vasprintf(fmt, args);
-    if (!(severity & ERR_NOFILE)) {
-        src_get(&et->lineno, &et->currentfile);
-
-        if (!et->currentfile) {
-            et->currentfile =
-                inname && inname[0] ? inname :
-                outname && outname[0] ? outname :
-                NULL;
-            et->lineno = 0;
-        }
-    }
+    et->where = error_where(severity);
 
     if (errhold_stack && true_type <= ERR_NONFATAL) {
         /* It is a tentative error */
@@ -2109,8 +2116,7 @@ static void nasm_issue_error(struct nasm_errtext *et)
     char linestr[64];           /* Formatted line number if applicable */
     const errflags severity  = et->severity;
     const errflags true_type = et->true_type;
-    const char * const currentfile = et->currentfile;
-    const uint32_t lineno = et->lineno;
+    const struct src_location where = et->where;
 
     if (severity & ERR_NO_SEVERITY)
         pfx = "";
@@ -2129,17 +2135,17 @@ static void nasm_issue_error(struct nasm_errtext *et)
     }
 
     *linestr = 0;
-    if (lineno) {
+    if (where.lineno) {
         snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
-                 errfmt->beforeline, lineno, errfmt->afterline);
+                 errfmt->beforeline, where.lineno, errfmt->afterline);
     }
 
     if (!skip_this_pass(severity)) {
-        const char *file = currentfile ? currentfile : no_file_name;
+        const char *file = where.filename ? where.filename : no_file_name;
         const char *here = "";
 
         if (severity & ERR_HERE) {
-            here = currentfile ? " here" : " in an unknown location";
+            here = where.filename ? " here" : " in an unknown location";
         }
 
         if (warn_list && true_type < ERR_NONFATAL &&
@@ -2176,12 +2182,12 @@ static void nasm_issue_error(struct nasm_errtext *et)
      * pass1 or preprocessor warnings in the list file
      */
     if (severity & ERR_HERE) {
-        if (lineno)
+        if (where.lineno)
             lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
-                        pfx, et->msg, currentfile, lineno, warnsuf);
-        else if (currentfile)
+                        pfx, et->msg, where.filename, where.lineno, warnsuf);
+        else if (where.filename)
             lfmt->error(severity, "%s%s in file %s%s",
-                        pfx, et->msg, currentfile, warnsuf);
+                        pfx, et->msg, where.filename, warnsuf);
         else
             lfmt->error(severity, "%s%s in an unknown location%s",
                         pfx, et->msg, warnsuf);
diff --git a/asm/preproc.c b/asm/preproc.c
index aded0bec..5cb92879 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -230,6 +230,17 @@ struct SMacro {
     bool alias;                 /* This is an alias macro */
 };
 
+/*
+ * "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
@@ -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 = {
diff --git a/asm/srcfile.c b/asm/srcfile.c
index a27fffac..b44c021c 100644
--- a/asm/srcfile.c
+++ b/asm/srcfile.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2020 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -32,7 +32,14 @@
  * ----------------------------------------------------------------------- */
 
 /*
- * srcfile.c - keep track of the current position in the input stream
+ * srcfile.c - keep track of the current position in the input stream.
+ *
+ * This is used for error messages, listing, and debug information. In
+ * both cases we also want to understand where inside a non-nolist
+ * macro we may be.
+ *
+ * This hierarchy is a stack that is kept as a doubly-linked list, as
+ * we want to traverse it in either top-down order or bottom-up.
  */
 
 #include "compiler.h"
@@ -42,7 +49,9 @@
 #include "hashtbl.h"
 #include "srcfile.h"
 
-struct src_location _src_here;
+struct src_location_stack _src_top;
+struct src_location_stack *_src_bottom = &_src_top;
+struct src_location_stack *_src_error = &_src_top;
 
 static struct hash_table filename_hash;
 
@@ -75,8 +84,8 @@ const char *src_set_fname(const char *newname)
         }
     }
 
-    oldname = _src_here.filename;
-    _src_here.filename = newname;
+    oldname = _src_bottom->l.filename;
+    _src_bottom->l.filename = newname;
     return oldname;
 }
 
@@ -85,3 +94,25 @@ void src_set(int32_t line, const char *fname)
     src_set_fname(fname);
     src_set_linnum(line);
 }
+
+void src_macro_push(const void *macro, struct src_location where)
+{
+    struct src_location_stack *sl;
+
+    nasm_new(sl);
+    sl->l = where;
+    sl->macro = macro;
+    sl->up = _src_bottom;
+    _src_bottom->down = sl;
+    _src_bottom = sl;
+}
+
+void src_macro_pop(void)
+{
+    struct src_location_stack *sl = _src_bottom;
+
+    _src_bottom = sl->up;
+    _src_bottom->down = NULL;
+
+    nasm_free(sl);
+}
diff --git a/asm/srcfile.h b/asm/srcfile.h
index 759ceabf..a26e1e4f 100644
--- a/asm/srcfile.h
+++ b/asm/srcfile.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2020 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -43,24 +43,31 @@ struct src_location {
     const char *filename;
     int32_t lineno;
 };
-extern struct src_location _src_here;
+struct src_location_stack {
+    struct src_location l;
+    struct src_location_stack *up, *down;
+    const void *macro;
+};
+extern struct src_location_stack _src_top;
+extern struct src_location_stack *_src_bottom;
+extern struct src_location_stack *_src_error;
 
 void src_init(void);
 void src_free(void);
 const char *src_set_fname(const char *newname);
 static inline const char *src_get_fname(void)
 {
-    return _src_here.filename;
+    return _src_bottom->l.filename;
 }
 static inline int32_t src_set_linnum(int32_t newline)
 {
-    int32_t oldline = _src_here.lineno;
-    _src_here.lineno = newline;
+    int32_t oldline = _src_bottom->l.lineno;
+    _src_bottom->l.lineno = newline;
     return oldline;
 }
 static inline int32_t src_get_linnum(void)
 {
-    return _src_here.lineno;
+    return _src_bottom->l.lineno;
 }
 
 /* Can be used when there is no need for the old information */
@@ -80,15 +87,16 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
 {
     const char *xn = *xname;
     int32_t xl = *xline;
+    int32_t line = _src_bottom->l.lineno;
 
-    *xline = _src_here.lineno;
-    *xname = _src_here.filename;
+    *xline = line;
+    *xname = _src_bottom->l.filename;
 
     /* The return value is expected to be optimized out almost everywhere */
-    if (!xn || xn != _src_here.filename)
+    if (!xn || xn != _src_bottom->l.filename)
         return -2;
     else
-        return _src_here.lineno - xl;
+        return line - xl;
 }
 
 /*
@@ -96,7 +104,39 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
  */
 static inline struct src_location src_where(void)
 {
-    return _src_here;
+    return _src_bottom->l;
+}
+
+/*
+ * Returns the top-level information as a structure. Use this for panic
+ * errors, since descent is not possible there.
+ */
+static inline struct src_location src_where_top(void)
+{
+    return _src_top.l;
+}
+
+/*
+ * Returns the appropriate level of the location stack to use for error
+ * messages. This is the same as the top level except during the descent
+ * through the macro hierarchy for elucidation;
+ */
+static inline struct src_location src_where_error(void)
+{
+    return _src_error->l;
+}
+static inline const void *src_error_down(void)
+{
+    if (_src_error->down) {
+        _src_error = _src_error->down;
+        return _src_error->macro;
+    } else {
+        return NULL;
+    }
+}
+static inline void src_error_reset(void)
+{
+    _src_error = &_src_top;
 }
 
 /*
@@ -106,9 +146,20 @@ static inline struct src_location src_where(void)
  */
 static inline struct src_location src_update(struct src_location whence)
 {
-    struct src_location old = _src_here;
-    _src_here = whence;
+    struct src_location old = _src_bottom->l;
+    _src_bottom->l = whence;
     return old;
 }
 
+/*
+ * Push/pop macro expansion level. "macroname" must remain constant at
+ * least until the same macro expansion level is popped.
+ */
+void src_macro_push(const void *macroname, struct src_location where);
+static inline const void *src_macro_current(void)
+{
+    return _src_bottom->macro;
+}
+void src_macro_pop(void);
+
 #endif /* ASM_SRCFILE_H */
diff --git a/include/nasm.h b/include/nasm.h
index 91dc9e6f..616ffb37 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -428,7 +428,6 @@ static inline char *nasm_skip_identifier(const char *str)
 enum {
     LIST_READ,
     LIST_MACRO,
-    LIST_MACRO_NOLIST,
     LIST_INCLUDE,
     LIST_INCBIN,
     LIST_TIMES
diff --git a/test/exitrep.asm b/test/exitrep.asm
index 4e1b6e3c..755f05d5 100644
--- a/test/exitrep.asm
+++ b/test/exitrep.asm
@@ -1,16 +1,40 @@
-%macro testrep 0.nolist
+%macro testrep 0-1
   %assign i 1
-  %rep 4
+  %rep %1 4
     mov eax,i
     %if i==3
       %exitrep
     %endif
     mov ebx,i
+    %warning in %?%1 iteration i
     %if i >= 3
 	%error iteration i should not be seen
     %endif
     %assign i i+1
   %endrep
+  ret
 %endmacro
 
-testrep
+%macro testrep_nl 0-1.nolist
+  %assign i 1
+  %rep %1 4
+    mov eax,i
+    %if i==3
+      %exitrep
+    %endif
+    %warning in %?%1 iteration i
+    mov ebx,i
+    %if i >= 3
+	%error iteration i should not be seen
+    %endif
+    %assign i i+1
+  %endrep
+  ret
+%endmacro
+
+
+	testrep
+	testrep .nolist
+
+	testrep_nl
+	testrep_nl .nolist


More information about the Nasm-commits mailing list