]> granicus.if.org Git - yasm/commitdiff
Change from current file/line dual storage to a monotonically-increasing line
authorPeter Johnson <peter@tortall.net>
Mon, 7 Jan 2002 07:42:27 +0000 (07:42 -0000)
committerPeter Johnson <peter@tortall.net>
Mon, 7 Jan 2002 07:42:27 +0000 (07:42 -0000)
"index".  This fixes some problems with assumptions made by various parts of
the code that are invalidated when the line number doesn't always increase (eg.
when the NASM %line directive is used).
Speed fixes are needed to the implementation of the line_* functions in
globals.c before this is finished.

svn path=/trunk/yasm/; revision=424

28 files changed:
frontends/yasm/yasm.c
libyasm/bc-int.h
libyasm/bytecode.c
libyasm/errwarn.c
libyasm/errwarn.h
libyasm/expr-int.h
libyasm/expr.c
libyasm/linemgr.c
libyasm/linemgr.h
libyasm/symrec.c
modules/arch/x86/x86expr.c
modules/parsers/nasm/bison.y.in
modules/parsers/nasm/nasm-bison.y
src/arch/x86/x86expr.c
src/bc-int.h
src/bytecode.c
src/errwarn.c
src/errwarn.h
src/expr-int.h
src/expr.c
src/globals.c
src/globals.h
src/linemgr.c
src/linemgr.h
src/main.c
src/parsers/nasm/bison.y.in
src/parsers/nasm/nasm-bison.y
src/symrec.c

index e8c245385c392e459da59535085cc5465402d4d2..ca2413587b6b8f54d1af3f4555d55b5e68b51a9a 100644 (file)
@@ -46,7 +46,7 @@
 #endif
 
 static int files_open = 0;
-/*@null@*/ /*@only@*/ static char *obj_filename = NULL;
+/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
 /*@null@*/ static FILE *in = NULL, *obj = NULL;
 
 /* Forward declarations: cmd line parser handlers */
@@ -119,11 +119,14 @@ main(int argc, char *argv[])
     /* if no files were specified, fallback to reading stdin */
     if (!in) {
        in = stdin;
-       switch_filename("<STDIN>");
+       in_filename = xstrdup("<STDIN>");
        if (!obj)
            obj = stdout;
     }
 
+    /* Initialize line info */
+    line_set(in_filename, 1, 1);
+
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
@@ -173,7 +176,8 @@ main(int argc, char *argv[])
     if (OutputAllErrorWarning() > 0) {
        sections_delete(sections);
        symrec_delete_all();
-       filename_delete_all();
+       line_shutdown();
+       floatnum_shutdown();
        BitVector_Shutdown();
        return EXIT_FAILURE;
     }
@@ -208,7 +212,7 @@ main(int argc, char *argv[])
 
     sections_delete(sections);
     symrec_delete_all();
-    filename_delete_all();
+    line_shutdown();
 
     floatnum_shutdown();
 
@@ -227,6 +231,8 @@ not_an_option_handler(char *param)
        WarningNow("can open only one input file, only latest file will be processed");
        if(fclose(in))
            ErrorNow("could not close old input file");
+       if (in_filename)
+           xfree(in_filename);
     }
 
     in = fopen(param, "rt");
@@ -234,7 +240,7 @@ not_an_option_handler(char *param)
        ErrorNow(_("could not open file `%s'"), param);
        return 1;
     }
-    switch_filename(param);
+    in_filename = xstrdup(param);
 
     files_open++;
     return 0;
index 0b8b20b4c6e0fc5fe213d87c8b1bcdf1f8d8ab54..97ab493d0d2093f2558652b86c8575cdd8bcc1cf 100644 (file)
@@ -59,8 +59,7 @@ struct bytecode {
                                   multiple copies), 0 if unknown */
 
     /* where it came from */
-    /*@dependent@*/ /*@null@*/ const char *filename;
-    unsigned int lineno;
+    unsigned int line;
 
     /* other assembler state info */
     unsigned long offset;      /* 0 if unknown */
index 149f71d4887a18a0600a069d975c0d648302c504..c35a71d61103ae69a7b5353f2bddca73ba455ec4 100644 (file)
@@ -148,8 +148,7 @@ bc_new_common(bytecode_type type, size_t datasize)
     bc->multiple = (expr *)NULL;
     bc->len = 0;
 
-    bc->filename = in_filename;
-    bc->lineno = line_number;
+    bc->line = line_index;
 
     bc->offset = 0;
 
@@ -246,6 +245,8 @@ bc_print(FILE *f, const bytecode *bc)
     const bytecode_data *data;
     const bytecode_reserve *reserve;
     const bytecode_incbin *incbin;
+    const char *filename;
+    unsigned long line;
 
     switch (bc->type) {
        case BC_EMPTY:
@@ -300,8 +301,9 @@ bc_print(FILE *f, const bytecode *bc)
     else
        expr_print(f, bc->multiple);
     fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
-    fprintf(f, "%*sFilename=\"%s\" Line Number=%u\n", indent_level, "",
-           bc->filename ? bc->filename : "<UNKNOWN>", bc->lineno);
+    line_lookup(bc->line, &filename, &line);
+    fprintf(f, "%*sFilename=\"%s\" Line Number=%lu\n", indent_level, "",
+           filename, line);
     fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
 }
 
index daf412cfd44f0953a223ddf1cbacecdf74d16b83..a80889b6387f27585c0954edcabda013155dac78 100644 (file)
@@ -65,7 +65,6 @@ typedef struct errwarn_s {
 
     enum { WE_ERROR, WE_WARNING } type;
 
-    /*@dependent@*/ const char *filename;
     unsigned long line;
     /* FIXME: This should not be a fixed size.  But we don't have vasprintf()
      * right now. */
@@ -151,7 +150,7 @@ Error(const char *fmt, ...)
     va_list ap;
     errwarn *we;
 
-    if ((previous_error_line == line_number) && !previous_error_parser)
+    if ((previous_error_line == line_index) && !previous_error_parser)
        return;
 
     if (!errwarns) {
@@ -166,8 +165,7 @@ Error(const char *fmt, ...)
        we = xmalloc(sizeof(errwarn));
 
        we->type = WE_ERROR;
-       we->filename = in_filename;
-       we->line = line_number;
+       we->line = line_index;
     }
 
     assert(we != NULL);
@@ -181,7 +179,7 @@ Error(const char *fmt, ...)
        STAILQ_INSERT_TAIL(errwarns, we, link);
     /*@=branchstate@*/
 
-    previous_error_line = line_number;
+    previous_error_line = line_index;
     previous_error_parser = 0;
 
     error_count++;
@@ -196,16 +194,15 @@ Warning(const char *fmt, ...)
     va_list ap;
     errwarn *we;
 
-    if (previous_warning_line == line_number)
+    if (previous_warning_line == line_index)
        return;
 
-    previous_warning_line = line_number;
+    previous_warning_line = line_index;
 
     we = xmalloc(sizeof(errwarn));
 
     we->type = WE_WARNING;
-    we->filename = in_filename;
-    we->line = line_number;
+    we->line = line_index;
     va_start(ap, fmt);
     vsprintf(we->msg, fmt, ap);
     va_end(ap);
@@ -242,11 +239,14 @@ WarningNow(const char *fmt, ...)
 }
 
 void
-ErrorAt(const char *filename, unsigned long line, const char *fmt, ...)
+ErrorAt(unsigned long index, const char *fmt, ...)
 {
     /* XXX: Should insert into list instead of printing immediately */
     va_list ap;
+    const char *filename;
+    unsigned long line;
 
+    line_lookup(index, &filename, &line);
     fprintf(stderr, "%s:%lu: ", filename?filename:"(NULL)", line);
     va_start(ap, fmt);
     vfprintf(stderr, fmt, ap);
@@ -255,11 +255,14 @@ ErrorAt(const char *filename, unsigned long line, const char *fmt, ...)
 }
 
 void
-WarningAt(const char *filename, unsigned long line, const char *fmt, ...)
+WarningAt(unsigned long index, const char *fmt, ...)
 {
     /* XXX: Should insert into list instead of printing immediately */
     va_list ap;
+    const char *filename;
+    unsigned long line;
 
+    line_lookup(index, &filename, &line);
     fprintf(stderr, "%s:%lu: %s ", filename?filename:"NULL", line,
            _("warning:"));
     va_start(ap, fmt);
@@ -273,6 +276,8 @@ unsigned int
 OutputAllErrorWarning(void)
 {
     errwarn *we, *we2;
+    const char *filename;
+    unsigned long line;
 
     /* If errwarns hasn't been initialized, there are no messages. */
     if (!errwarns)
@@ -280,11 +285,12 @@ OutputAllErrorWarning(void)
 
     /* Output error and warning messages. */
     STAILQ_FOREACH(we, errwarns, link) {
+       line_lookup(we->line, &filename, &line);
        if (we->type == WE_ERROR)
-           fprintf(stderr, "%s:%lu: %s\n", we->filename, we->line, we->msg);
+           fprintf(stderr, "%s:%lu: %s\n", filename, line, we->msg);
        else
-           fprintf(stderr, "%s:%lu: %s %s\n", we->filename, we->line,
-                   _("warning:"), we->msg);
+           fprintf(stderr, "%s:%lu: %s %s\n", filename, line, _("warning:"),
+                   we->msg);
     }
 
     /* Delete messages. */
index 59713c276706c1446f5e1980daa4945fdfa178cd..b50fa08b3c42af353d563297fd05b8a0e8fc1848 100644 (file)
@@ -46,10 +46,8 @@ void Warning(const char *, ...) /*@printflike@*/;
  * called in line order from a parser.  The *At() functions are much slower,
  * at least in the current implementation.
  */
-void ErrorAt(/*@null@*/ const char *filename, unsigned long line, const char *,
-            ...) /*@printflike@*/;
-void WarningAt(/*@null@*/ const char *filename, unsigned long line,
-              const char *, ...) /*@printflike@*/;
+void ErrorAt(unsigned long index, const char *, ...) /*@printflike@*/;
+void WarningAt(unsigned long index, const char *, ...) /*@printflike@*/;
 
 /* These two functions immediately output the error or warning, with no file
  * or line information.  They should be used for errors and warnings outside
index c47c977b1258dd4ddca05df44c9b377c2fb1ca5f..6c37fa20b5f39b38983c914ca1855bd34e9e968d 100644 (file)
@@ -52,7 +52,6 @@ struct ExprItem {
  */
 struct expr {
     ExprOp op;
-    /*@dependent@*/ /*@null@*/ const char *filename;
     unsigned long line;
     int numterms;
     ExprItem terms[2];         /* structure may be extended to include more */
index 211dceab30c1629093b1d6826d5ff901c3a6f5e8..be0ab2e4df2083ed71e0426490a95aa9c8ec23f2 100644 (file)
@@ -89,8 +89,7 @@ expr_new(ExprOp op, ExprItem *left, ExprItem *right)
        }
     }
 
-    ptr->filename = in_filename;
-    ptr->line = line_number;
+    ptr->line = line_index;
 
     return ptr;
 }
@@ -151,7 +150,6 @@ expr_xform_neg_item(expr *e, ExprItem *ei)
 
     /* Build -1*ei subexpression */
     sube->op = EXPR_MUL;
-    sube->filename = e->filename;
     sube->line = e->line;
     sube->numterms = 2;
     sube->terms[0].type = EXPR_INT;
@@ -212,7 +210,6 @@ expr_xform_neg_helper(/*@returned@*/ /*@only@*/ expr *e)
             */
            ne = xmalloc(sizeof(expr));
            ne->op = EXPR_MUL;
-           ne->filename = e->filename;
            ne->line = e->line;
            ne->numterms = 2;
            ne->terms[0].type = EXPR_INT;
@@ -634,7 +631,6 @@ expr_copy_except(const expr *e, int except)
     n = xmalloc(sizeof(expr)+sizeof(ExprItem)*(e->numterms<2?0:e->numterms-2));
 
     n->op = e->op;
-    n->filename = e->filename;
     n->line = e->line;
     n->numterms = e->numterms;
     for (i=0; i<e->numterms; i++) {
index bcdd65e32c1ba3706e14245d0673be7c579596de..b57dc2da0ad6d0f90dd7cc75af03e5ace74a58f4 100644 (file)
 /* Current (selected) object format) */
 /*@null@*/ objfmt *cur_objfmt = NULL;
 
-/*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
-unsigned int line_number = 1;
-unsigned int line_number_inc = 1;
-unsigned int asm_options = 0;
+/* Source lines tracking */
+/* FIXME: Need better data structure for this than a linked list. */
+typedef /*@reldef@*/ STAILQ_HEAD(line_index_mapping_head, line_index_mapping)
+    line_index_mapping_head;
+typedef struct line_index_mapping {
+    /*@reldef@*/ STAILQ_ENTRY(line_index_mapping) link;
 
-int indent_level = 0;
+    /* monotonically increasing line index */
+    unsigned long index;
 
+    /* related info */
+    /* "original" source filename */
+    /*@null@*/ /*@dependent@*/ const char *filename;
+    /* "original" source base line number */
+    unsigned long line;
+    /* "original" source line number increment (for following lines) */
+    unsigned int line_inc;
+} line_index_mapping;
+/* Shared storage for filenames */
 static /*@only@*/ /*@null@*/ HAMT *filename_table = NULL;
 
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+unsigned long line_index = 1;
+static line_index_mapping_head *line_index_map = NULL;
+
+/* Global assembler options. */
+unsigned int asm_options = 0;
+
+/* Indentation level for assembler *_print() routines */
+int indent_level = 0;
+
 static void
 filename_delete_one(/*@only@*/ void *d)
 {
@@ -49,24 +71,70 @@ filename_delete_one(/*@only@*/ void *d)
 }
 
 void
-switch_filename(const char *filename)
+line_set(const char *filename, unsigned long line, unsigned long line_inc)
 {
-    char *copy = xstrdup(filename);
+    char *copy;
     int replace = 0;
+    line_index_mapping *mapping;
+
+    /* Build a mapping */
+    mapping = xmalloc(sizeof(line_index_mapping));
+
+    /* Copy the filename (via shared storage) */
+    copy = xstrdup(filename);
     if (!filename_table)
        filename_table = HAMT_new();
     /*@-aliasunique@*/
-    in_filename = HAMT_insert(filename_table, copy, copy, &replace,
-                             filename_delete_one);
+    mapping->filename = HAMT_insert(filename_table, copy, copy, &replace,
+                                   filename_delete_one);
     /*@=aliasunique@*/
+
+    mapping->index = line_index;
+    mapping->line = line;
+    mapping->line_inc = line_inc;
+
+    /* Add the mapping to the map */
+    if (!line_index_map) {
+       line_index_map = xmalloc(sizeof(line_index_mapping_head));
+       STAILQ_INIT(line_index_map);
+    }
+    STAILQ_INSERT_TAIL(line_index_map, mapping, link);
 }
 
 void
-filename_delete_all(void)
+line_shutdown(void)
 {
-    in_filename = NULL;
+    line_index_mapping *mapping, *mapping2;
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       xfree(mapping);
+       mapping = mapping2;
+    }
+    xfree(line_index_map);
+
     if (filename_table) {
        HAMT_delete(filename_table, filename_delete_one);
        filename_table = NULL;
     }
 }
+
+void
+line_lookup(unsigned long index, const char **filename, unsigned long *line)
+{
+    line_index_mapping *mapping, *mapping2;
+
+    assert(index <= line_index);
+
+    /* Linearly search through map to find highest line_index <= index */
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       if (!mapping2 || mapping2->index > index)
+           break;
+       mapping = mapping2;
+    }
+
+    *filename = mapping->filename;
+    *line = mapping->line+mapping->line_inc*(index-mapping->index);
+}
index be2fcf4359549b32f8788d8e34cf7777266c709b..690b8d65bcb5f8c63bcd0e6a72c152d856b4c525 100644 (file)
@@ -28,20 +28,19 @@ extern /*@null@*/ parser *cur_parser;
 /* Current (selected) object format */
 extern /*@null@*/ objfmt *cur_objfmt;
 
-/*@null@*/ /*@dependent@*/ extern const char *in_filename;
-extern unsigned int line_number;
-
-/* Amount to increase line_number by after each line.  Should be 0 or 1, set by
- * %line (in NASM syntax).  Initialized to 1 at startup.
- * (0 is for 1-line macros that expand to multiple lines).
- */
-extern unsigned int line_number_inc;
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+extern unsigned long line_index;
 
+/* Global assembler options. */
 extern unsigned int asm_options;
 
+/* Indentation level for assembler *_print() routines */
 extern int indent_level;
 
-void switch_filename(const char *filename);
-void filename_delete_all(void);
+void line_set(const char *filename, unsigned long line,
+             unsigned long line_inc);
+void line_shutdown(void);
+void line_lookup(unsigned long index, const char **filename,
+                unsigned long *line);
 
 #endif
index e88d5e7b3ced07d1299424ffd26a389a35c9b6f7..3dba92fc805aa884fb0e5f77a235432e028535be 100644 (file)
@@ -59,7 +59,6 @@ struct symrec {
     SymType type;
     SymStatus status;
     SymVisibility visibility;
-    /*@dependent@*/ /*@null@*/ const char *filename;   /* file and line */
     unsigned long line;                /*  symbol was first declared or used on */
     union {
        expr *expn;             /* equ value */
@@ -113,8 +112,7 @@ symrec_get_or_new(const char *name, int in_table)
     rec = xmalloc(sizeof(symrec));
     rec->name = symname;
     rec->type = SYM_UNKNOWN;
-    rec->filename = in_filename;
-    rec->line = line_number;
+    rec->line = line_index;
     rec->visibility = SYM_LOCAL;
     rec->of_data_vis_ce = NULL;
     rec->of_data_vis_g = NULL;
@@ -163,7 +161,7 @@ symrec_define(const char *name, SymType type, int in_table)
        Error(_("duplicate definition of `%s'; first defined on line %d"),
              name, rec->line);
     } else {
-       rec->line = line_number;        /* set line number of definition */
+       rec->line = line_index; /* set line number of definition */
        rec->type = type;
        rec->status |= SYM_DEFINED;
     }
@@ -206,7 +204,7 @@ symrec_declare(const char *name, SymVisibility vis, void *of_data)
        if (of_data)
            cur_objfmt->declare_data_delete(vis, of_data);
     } else {
-       rec->line = line_number;        /* set line number of declaration */
+       rec->line = line_index; /* set line number of declaration */
        rec->visibility |= vis;
 
        /* If declared as COMMON or EXTERN, set as DEFINED. */
@@ -299,18 +297,14 @@ symrec_set_opt_flags(symrec *sym, unsigned long opt_flags)
 }
 
 static unsigned long firstundef_line;
-static /*@dependent@*/ /*@null@*/ const char *firstundef_filename;
 static int
 symrec_parser_finalize_checksym(symrec *sym, /*@unused@*/ /*@null@*/ void *d)
 {
     /* error if a symbol is used but never defined */
     if ((sym->status & SYM_USED) && !(sym->status & SYM_DEFINED)) {
-       ErrorAt(sym->filename, sym->line,
-               _("undefined symbol `%s' (first use)"), sym->name);
-       if (sym->line < firstundef_line) {
+       ErrorAt(sym->line, _("undefined symbol `%s' (first use)"), sym->name);
+       if (sym->line < firstundef_line)
            firstundef_line = sym->line;
-           firstundef_filename = sym->filename;
-       }
     }
 
     return 1;
@@ -322,7 +316,7 @@ symrec_parser_finalize(void)
     firstundef_line = ULONG_MAX;
     symrec_traverse(NULL, symrec_parser_finalize_checksym);
     if (firstundef_line < ULONG_MAX)
-       ErrorAt(firstundef_filename, firstundef_line,
+       ErrorAt(firstundef_line,
                _(" (Each undefined symbol is reported only once.)"));
 }
 
@@ -368,6 +362,9 @@ symrec_print_all(FILE *f)
 void
 symrec_print(FILE *f, const symrec *sym)
 {
+    const char *filename;
+    unsigned long line;
+
     switch (sym->type) {
        case SYM_UNKNOWN:
            fprintf(f, "%*s-Unknown (Common/Extern)-\n", indent_level, "");
@@ -439,6 +436,7 @@ symrec_print(FILE *f, const symrec *sym)
        indent_level--;
     }
 
+    line_lookup(sym->line, &filename, &line);
     fprintf(f, "%*sFilename=\"%s\" Line Number=%lu\n", indent_level, "",
-          sym->filename?sym->filename:"(NULL)", sym->line);
+          filename, line);
 }
index 09b217672199a9ce5b5123def75f08ab2e3941b5..49ab69ba93dff249be7d3b31d1d43f013d77b5f4 100644 (file)
@@ -373,7 +373,7 @@ x86_checkea_calc_displen(expr **ep, unsigned int wordsize, int noreg,
             */
            if (!intnum_check_size(intn, (size_t)wordsize, 0) &&
                !intnum_check_size(intn, 1, 1)) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
 
@@ -431,7 +431,7 @@ x86_checkea_calc_displen(expr **ep, unsigned int wordsize, int noreg,
        case 2:
        case 4:
            if (wordsize != *displen) {
-               ErrorAt(e->filename, e->line,
+               ErrorAt(e->line,
                        _("invalid effective address (displacement size)"));
                return 0;
            }
@@ -522,7 +522,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
                                             x86_expr_checkea_get_reg32)) {
            case 0:
                e = *ep;
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            case 1:
                return 1;
@@ -544,7 +544,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
         */
        for (i=0; i<8; i++) {
            if (reg32mult[i] < 0) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
            if (i != indexreg && reg32mult[i] == 1)
@@ -585,7 +585,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
         */
        for (i=0; i<8; i++)
            if (i != basereg && i != indexreg && reg32mult[i] != 0) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
 
@@ -593,7 +593,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
        if (indexreg != REG32_NONE && reg32mult[indexreg] != 1 &&
            reg32mult[indexreg] != 2 && reg32mult[indexreg] != 4 &&
            reg32mult[indexreg] != 8) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
@@ -603,7 +603,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
             * legal.
             */
            if (reg32mult[REG32_ESP] > 1 || basereg == REG32_ESP) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
            /* If mult==1 and basereg is not ESP, swap indexreg w/basereg. */
@@ -705,7 +705,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
                                             x86_expr_checkea_get_reg16)) {
            case 0:
                e = *ep;
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            case 1:
                return 1;
@@ -717,7 +717,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
        /* reg multipliers not 0 or 1 are illegal. */
        if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 ||
            reg16mult.bp & ~1) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
@@ -733,7 +733,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
 
        /* Check the modrm value for invalid combinations. */
        if (modrm16[havereg] & 0070) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
index d16775b9a3e9ceec60f97ccab9494a7c8adadb3a..e0f0b66a8be6a20100a135d086e2785f280d0024 100644 (file)
@@ -146,17 +146,18 @@ input: /* empty */
                                               $2);
        if (nasm_parser_temp_bc)
            nasm_parser_prev_bc = nasm_parser_temp_bc;
-       line_number += line_number_inc;
+       line_index++;
     }
 ;
 
 line: '\n'             { $$ = (bytecode *)NULL; }
     | lineexp '\n'
     | LINE INTNUM '+' INTNUM FILENAME '\n' {
-       line_number = (unsigned int)intnum_get_uint($2);
-       line_number_inc = (unsigned int)intnum_get_uint($4);
-       line_number -= line_number_inc; /* as we'll add it back in */
-       switch_filename($5);
+       /* %line indicates the line number of the *next* line, so subtract out
+        * the increment when setting the line number.
+        */
+       line_set($5, intnum_get_uint($2)-intnum_get_uint($4),
+                intnum_get_uint($4));
        intnum_delete($2);
        intnum_delete($4);
        xfree($5);
index d16775b9a3e9ceec60f97ccab9494a7c8adadb3a..e0f0b66a8be6a20100a135d086e2785f280d0024 100644 (file)
@@ -146,17 +146,18 @@ input: /* empty */
                                               $2);
        if (nasm_parser_temp_bc)
            nasm_parser_prev_bc = nasm_parser_temp_bc;
-       line_number += line_number_inc;
+       line_index++;
     }
 ;
 
 line: '\n'             { $$ = (bytecode *)NULL; }
     | lineexp '\n'
     | LINE INTNUM '+' INTNUM FILENAME '\n' {
-       line_number = (unsigned int)intnum_get_uint($2);
-       line_number_inc = (unsigned int)intnum_get_uint($4);
-       line_number -= line_number_inc; /* as we'll add it back in */
-       switch_filename($5);
+       /* %line indicates the line number of the *next* line, so subtract out
+        * the increment when setting the line number.
+        */
+       line_set($5, intnum_get_uint($2)-intnum_get_uint($4),
+                intnum_get_uint($4));
        intnum_delete($2);
        intnum_delete($4);
        xfree($5);
index 09b217672199a9ce5b5123def75f08ab2e3941b5..49ab69ba93dff249be7d3b31d1d43f013d77b5f4 100644 (file)
@@ -373,7 +373,7 @@ x86_checkea_calc_displen(expr **ep, unsigned int wordsize, int noreg,
             */
            if (!intnum_check_size(intn, (size_t)wordsize, 0) &&
                !intnum_check_size(intn, 1, 1)) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
 
@@ -431,7 +431,7 @@ x86_checkea_calc_displen(expr **ep, unsigned int wordsize, int noreg,
        case 2:
        case 4:
            if (wordsize != *displen) {
-               ErrorAt(e->filename, e->line,
+               ErrorAt(e->line,
                        _("invalid effective address (displacement size)"));
                return 0;
            }
@@ -522,7 +522,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
                                             x86_expr_checkea_get_reg32)) {
            case 0:
                e = *ep;
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            case 1:
                return 1;
@@ -544,7 +544,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
         */
        for (i=0; i<8; i++) {
            if (reg32mult[i] < 0) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
            if (i != indexreg && reg32mult[i] == 1)
@@ -585,7 +585,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
         */
        for (i=0; i<8; i++)
            if (i != basereg && i != indexreg && reg32mult[i] != 0) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
 
@@ -593,7 +593,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
        if (indexreg != REG32_NONE && reg32mult[indexreg] != 1 &&
            reg32mult[indexreg] != 2 && reg32mult[indexreg] != 4 &&
            reg32mult[indexreg] != 8) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
@@ -603,7 +603,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
             * legal.
             */
            if (reg32mult[REG32_ESP] > 1 || basereg == REG32_ESP) {
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            }
            /* If mult==1 and basereg is not ESP, swap indexreg w/basereg. */
@@ -705,7 +705,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
                                             x86_expr_checkea_get_reg16)) {
            case 0:
                e = *ep;
-               ErrorAt(e->filename, e->line, _("invalid effective address"));
+               ErrorAt(e->line, _("invalid effective address"));
                return 0;
            case 1:
                return 1;
@@ -717,7 +717,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
        /* reg multipliers not 0 or 1 are illegal. */
        if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 ||
            reg16mult.bp & ~1) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
@@ -733,7 +733,7 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
 
        /* Check the modrm value for invalid combinations. */
        if (modrm16[havereg] & 0070) {
-           ErrorAt(e->filename, e->line, _("invalid effective address"));
+           ErrorAt(e->line, _("invalid effective address"));
            return 0;
        }
 
index 0b8b20b4c6e0fc5fe213d87c8b1bcdf1f8d8ab54..97ab493d0d2093f2558652b86c8575cdd8bcc1cf 100644 (file)
@@ -59,8 +59,7 @@ struct bytecode {
                                   multiple copies), 0 if unknown */
 
     /* where it came from */
-    /*@dependent@*/ /*@null@*/ const char *filename;
-    unsigned int lineno;
+    unsigned int line;
 
     /* other assembler state info */
     unsigned long offset;      /* 0 if unknown */
index 149f71d4887a18a0600a069d975c0d648302c504..c35a71d61103ae69a7b5353f2bddca73ba455ec4 100644 (file)
@@ -148,8 +148,7 @@ bc_new_common(bytecode_type type, size_t datasize)
     bc->multiple = (expr *)NULL;
     bc->len = 0;
 
-    bc->filename = in_filename;
-    bc->lineno = line_number;
+    bc->line = line_index;
 
     bc->offset = 0;
 
@@ -246,6 +245,8 @@ bc_print(FILE *f, const bytecode *bc)
     const bytecode_data *data;
     const bytecode_reserve *reserve;
     const bytecode_incbin *incbin;
+    const char *filename;
+    unsigned long line;
 
     switch (bc->type) {
        case BC_EMPTY:
@@ -300,8 +301,9 @@ bc_print(FILE *f, const bytecode *bc)
     else
        expr_print(f, bc->multiple);
     fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
-    fprintf(f, "%*sFilename=\"%s\" Line Number=%u\n", indent_level, "",
-           bc->filename ? bc->filename : "<UNKNOWN>", bc->lineno);
+    line_lookup(bc->line, &filename, &line);
+    fprintf(f, "%*sFilename=\"%s\" Line Number=%lu\n", indent_level, "",
+           filename, line);
     fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
 }
 
index daf412cfd44f0953a223ddf1cbacecdf74d16b83..a80889b6387f27585c0954edcabda013155dac78 100644 (file)
@@ -65,7 +65,6 @@ typedef struct errwarn_s {
 
     enum { WE_ERROR, WE_WARNING } type;
 
-    /*@dependent@*/ const char *filename;
     unsigned long line;
     /* FIXME: This should not be a fixed size.  But we don't have vasprintf()
      * right now. */
@@ -151,7 +150,7 @@ Error(const char *fmt, ...)
     va_list ap;
     errwarn *we;
 
-    if ((previous_error_line == line_number) && !previous_error_parser)
+    if ((previous_error_line == line_index) && !previous_error_parser)
        return;
 
     if (!errwarns) {
@@ -166,8 +165,7 @@ Error(const char *fmt, ...)
        we = xmalloc(sizeof(errwarn));
 
        we->type = WE_ERROR;
-       we->filename = in_filename;
-       we->line = line_number;
+       we->line = line_index;
     }
 
     assert(we != NULL);
@@ -181,7 +179,7 @@ Error(const char *fmt, ...)
        STAILQ_INSERT_TAIL(errwarns, we, link);
     /*@=branchstate@*/
 
-    previous_error_line = line_number;
+    previous_error_line = line_index;
     previous_error_parser = 0;
 
     error_count++;
@@ -196,16 +194,15 @@ Warning(const char *fmt, ...)
     va_list ap;
     errwarn *we;
 
-    if (previous_warning_line == line_number)
+    if (previous_warning_line == line_index)
        return;
 
-    previous_warning_line = line_number;
+    previous_warning_line = line_index;
 
     we = xmalloc(sizeof(errwarn));
 
     we->type = WE_WARNING;
-    we->filename = in_filename;
-    we->line = line_number;
+    we->line = line_index;
     va_start(ap, fmt);
     vsprintf(we->msg, fmt, ap);
     va_end(ap);
@@ -242,11 +239,14 @@ WarningNow(const char *fmt, ...)
 }
 
 void
-ErrorAt(const char *filename, unsigned long line, const char *fmt, ...)
+ErrorAt(unsigned long index, const char *fmt, ...)
 {
     /* XXX: Should insert into list instead of printing immediately */
     va_list ap;
+    const char *filename;
+    unsigned long line;
 
+    line_lookup(index, &filename, &line);
     fprintf(stderr, "%s:%lu: ", filename?filename:"(NULL)", line);
     va_start(ap, fmt);
     vfprintf(stderr, fmt, ap);
@@ -255,11 +255,14 @@ ErrorAt(const char *filename, unsigned long line, const char *fmt, ...)
 }
 
 void
-WarningAt(const char *filename, unsigned long line, const char *fmt, ...)
+WarningAt(unsigned long index, const char *fmt, ...)
 {
     /* XXX: Should insert into list instead of printing immediately */
     va_list ap;
+    const char *filename;
+    unsigned long line;
 
+    line_lookup(index, &filename, &line);
     fprintf(stderr, "%s:%lu: %s ", filename?filename:"NULL", line,
            _("warning:"));
     va_start(ap, fmt);
@@ -273,6 +276,8 @@ unsigned int
 OutputAllErrorWarning(void)
 {
     errwarn *we, *we2;
+    const char *filename;
+    unsigned long line;
 
     /* If errwarns hasn't been initialized, there are no messages. */
     if (!errwarns)
@@ -280,11 +285,12 @@ OutputAllErrorWarning(void)
 
     /* Output error and warning messages. */
     STAILQ_FOREACH(we, errwarns, link) {
+       line_lookup(we->line, &filename, &line);
        if (we->type == WE_ERROR)
-           fprintf(stderr, "%s:%lu: %s\n", we->filename, we->line, we->msg);
+           fprintf(stderr, "%s:%lu: %s\n", filename, line, we->msg);
        else
-           fprintf(stderr, "%s:%lu: %s %s\n", we->filename, we->line,
-                   _("warning:"), we->msg);
+           fprintf(stderr, "%s:%lu: %s %s\n", filename, line, _("warning:"),
+                   we->msg);
     }
 
     /* Delete messages. */
index 59713c276706c1446f5e1980daa4945fdfa178cd..b50fa08b3c42af353d563297fd05b8a0e8fc1848 100644 (file)
@@ -46,10 +46,8 @@ void Warning(const char *, ...) /*@printflike@*/;
  * called in line order from a parser.  The *At() functions are much slower,
  * at least in the current implementation.
  */
-void ErrorAt(/*@null@*/ const char *filename, unsigned long line, const char *,
-            ...) /*@printflike@*/;
-void WarningAt(/*@null@*/ const char *filename, unsigned long line,
-              const char *, ...) /*@printflike@*/;
+void ErrorAt(unsigned long index, const char *, ...) /*@printflike@*/;
+void WarningAt(unsigned long index, const char *, ...) /*@printflike@*/;
 
 /* These two functions immediately output the error or warning, with no file
  * or line information.  They should be used for errors and warnings outside
index c47c977b1258dd4ddca05df44c9b377c2fb1ca5f..6c37fa20b5f39b38983c914ca1855bd34e9e968d 100644 (file)
@@ -52,7 +52,6 @@ struct ExprItem {
  */
 struct expr {
     ExprOp op;
-    /*@dependent@*/ /*@null@*/ const char *filename;
     unsigned long line;
     int numterms;
     ExprItem terms[2];         /* structure may be extended to include more */
index 211dceab30c1629093b1d6826d5ff901c3a6f5e8..be0ab2e4df2083ed71e0426490a95aa9c8ec23f2 100644 (file)
@@ -89,8 +89,7 @@ expr_new(ExprOp op, ExprItem *left, ExprItem *right)
        }
     }
 
-    ptr->filename = in_filename;
-    ptr->line = line_number;
+    ptr->line = line_index;
 
     return ptr;
 }
@@ -151,7 +150,6 @@ expr_xform_neg_item(expr *e, ExprItem *ei)
 
     /* Build -1*ei subexpression */
     sube->op = EXPR_MUL;
-    sube->filename = e->filename;
     sube->line = e->line;
     sube->numterms = 2;
     sube->terms[0].type = EXPR_INT;
@@ -212,7 +210,6 @@ expr_xform_neg_helper(/*@returned@*/ /*@only@*/ expr *e)
             */
            ne = xmalloc(sizeof(expr));
            ne->op = EXPR_MUL;
-           ne->filename = e->filename;
            ne->line = e->line;
            ne->numterms = 2;
            ne->terms[0].type = EXPR_INT;
@@ -634,7 +631,6 @@ expr_copy_except(const expr *e, int except)
     n = xmalloc(sizeof(expr)+sizeof(ExprItem)*(e->numterms<2?0:e->numterms-2));
 
     n->op = e->op;
-    n->filename = e->filename;
     n->line = e->line;
     n->numterms = e->numterms;
     for (i=0; i<e->numterms; i++) {
index bcdd65e32c1ba3706e14245d0673be7c579596de..b57dc2da0ad6d0f90dd7cc75af03e5ace74a58f4 100644 (file)
 /* Current (selected) object format) */
 /*@null@*/ objfmt *cur_objfmt = NULL;
 
-/*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
-unsigned int line_number = 1;
-unsigned int line_number_inc = 1;
-unsigned int asm_options = 0;
+/* Source lines tracking */
+/* FIXME: Need better data structure for this than a linked list. */
+typedef /*@reldef@*/ STAILQ_HEAD(line_index_mapping_head, line_index_mapping)
+    line_index_mapping_head;
+typedef struct line_index_mapping {
+    /*@reldef@*/ STAILQ_ENTRY(line_index_mapping) link;
 
-int indent_level = 0;
+    /* monotonically increasing line index */
+    unsigned long index;
 
+    /* related info */
+    /* "original" source filename */
+    /*@null@*/ /*@dependent@*/ const char *filename;
+    /* "original" source base line number */
+    unsigned long line;
+    /* "original" source line number increment (for following lines) */
+    unsigned int line_inc;
+} line_index_mapping;
+/* Shared storage for filenames */
 static /*@only@*/ /*@null@*/ HAMT *filename_table = NULL;
 
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+unsigned long line_index = 1;
+static line_index_mapping_head *line_index_map = NULL;
+
+/* Global assembler options. */
+unsigned int asm_options = 0;
+
+/* Indentation level for assembler *_print() routines */
+int indent_level = 0;
+
 static void
 filename_delete_one(/*@only@*/ void *d)
 {
@@ -49,24 +71,70 @@ filename_delete_one(/*@only@*/ void *d)
 }
 
 void
-switch_filename(const char *filename)
+line_set(const char *filename, unsigned long line, unsigned long line_inc)
 {
-    char *copy = xstrdup(filename);
+    char *copy;
     int replace = 0;
+    line_index_mapping *mapping;
+
+    /* Build a mapping */
+    mapping = xmalloc(sizeof(line_index_mapping));
+
+    /* Copy the filename (via shared storage) */
+    copy = xstrdup(filename);
     if (!filename_table)
        filename_table = HAMT_new();
     /*@-aliasunique@*/
-    in_filename = HAMT_insert(filename_table, copy, copy, &replace,
-                             filename_delete_one);
+    mapping->filename = HAMT_insert(filename_table, copy, copy, &replace,
+                                   filename_delete_one);
     /*@=aliasunique@*/
+
+    mapping->index = line_index;
+    mapping->line = line;
+    mapping->line_inc = line_inc;
+
+    /* Add the mapping to the map */
+    if (!line_index_map) {
+       line_index_map = xmalloc(sizeof(line_index_mapping_head));
+       STAILQ_INIT(line_index_map);
+    }
+    STAILQ_INSERT_TAIL(line_index_map, mapping, link);
 }
 
 void
-filename_delete_all(void)
+line_shutdown(void)
 {
-    in_filename = NULL;
+    line_index_mapping *mapping, *mapping2;
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       xfree(mapping);
+       mapping = mapping2;
+    }
+    xfree(line_index_map);
+
     if (filename_table) {
        HAMT_delete(filename_table, filename_delete_one);
        filename_table = NULL;
     }
 }
+
+void
+line_lookup(unsigned long index, const char **filename, unsigned long *line)
+{
+    line_index_mapping *mapping, *mapping2;
+
+    assert(index <= line_index);
+
+    /* Linearly search through map to find highest line_index <= index */
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       if (!mapping2 || mapping2->index > index)
+           break;
+       mapping = mapping2;
+    }
+
+    *filename = mapping->filename;
+    *line = mapping->line+mapping->line_inc*(index-mapping->index);
+}
index be2fcf4359549b32f8788d8e34cf7777266c709b..690b8d65bcb5f8c63bcd0e6a72c152d856b4c525 100644 (file)
@@ -28,20 +28,19 @@ extern /*@null@*/ parser *cur_parser;
 /* Current (selected) object format */
 extern /*@null@*/ objfmt *cur_objfmt;
 
-/*@null@*/ /*@dependent@*/ extern const char *in_filename;
-extern unsigned int line_number;
-
-/* Amount to increase line_number by after each line.  Should be 0 or 1, set by
- * %line (in NASM syntax).  Initialized to 1 at startup.
- * (0 is for 1-line macros that expand to multiple lines).
- */
-extern unsigned int line_number_inc;
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+extern unsigned long line_index;
 
+/* Global assembler options. */
 extern unsigned int asm_options;
 
+/* Indentation level for assembler *_print() routines */
 extern int indent_level;
 
-void switch_filename(const char *filename);
-void filename_delete_all(void);
+void line_set(const char *filename, unsigned long line,
+             unsigned long line_inc);
+void line_shutdown(void);
+void line_lookup(unsigned long index, const char **filename,
+                unsigned long *line);
 
 #endif
index bcdd65e32c1ba3706e14245d0673be7c579596de..b57dc2da0ad6d0f90dd7cc75af03e5ace74a58f4 100644 (file)
 /* Current (selected) object format) */
 /*@null@*/ objfmt *cur_objfmt = NULL;
 
-/*@null@*/ /*@dependent@*/ const char *in_filename = (const char *)NULL;
-unsigned int line_number = 1;
-unsigned int line_number_inc = 1;
-unsigned int asm_options = 0;
+/* Source lines tracking */
+/* FIXME: Need better data structure for this than a linked list. */
+typedef /*@reldef@*/ STAILQ_HEAD(line_index_mapping_head, line_index_mapping)
+    line_index_mapping_head;
+typedef struct line_index_mapping {
+    /*@reldef@*/ STAILQ_ENTRY(line_index_mapping) link;
 
-int indent_level = 0;
+    /* monotonically increasing line index */
+    unsigned long index;
 
+    /* related info */
+    /* "original" source filename */
+    /*@null@*/ /*@dependent@*/ const char *filename;
+    /* "original" source base line number */
+    unsigned long line;
+    /* "original" source line number increment (for following lines) */
+    unsigned int line_inc;
+} line_index_mapping;
+/* Shared storage for filenames */
 static /*@only@*/ /*@null@*/ HAMT *filename_table = NULL;
 
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+unsigned long line_index = 1;
+static line_index_mapping_head *line_index_map = NULL;
+
+/* Global assembler options. */
+unsigned int asm_options = 0;
+
+/* Indentation level for assembler *_print() routines */
+int indent_level = 0;
+
 static void
 filename_delete_one(/*@only@*/ void *d)
 {
@@ -49,24 +71,70 @@ filename_delete_one(/*@only@*/ void *d)
 }
 
 void
-switch_filename(const char *filename)
+line_set(const char *filename, unsigned long line, unsigned long line_inc)
 {
-    char *copy = xstrdup(filename);
+    char *copy;
     int replace = 0;
+    line_index_mapping *mapping;
+
+    /* Build a mapping */
+    mapping = xmalloc(sizeof(line_index_mapping));
+
+    /* Copy the filename (via shared storage) */
+    copy = xstrdup(filename);
     if (!filename_table)
        filename_table = HAMT_new();
     /*@-aliasunique@*/
-    in_filename = HAMT_insert(filename_table, copy, copy, &replace,
-                             filename_delete_one);
+    mapping->filename = HAMT_insert(filename_table, copy, copy, &replace,
+                                   filename_delete_one);
     /*@=aliasunique@*/
+
+    mapping->index = line_index;
+    mapping->line = line;
+    mapping->line_inc = line_inc;
+
+    /* Add the mapping to the map */
+    if (!line_index_map) {
+       line_index_map = xmalloc(sizeof(line_index_mapping_head));
+       STAILQ_INIT(line_index_map);
+    }
+    STAILQ_INSERT_TAIL(line_index_map, mapping, link);
 }
 
 void
-filename_delete_all(void)
+line_shutdown(void)
 {
-    in_filename = NULL;
+    line_index_mapping *mapping, *mapping2;
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       xfree(mapping);
+       mapping = mapping2;
+    }
+    xfree(line_index_map);
+
     if (filename_table) {
        HAMT_delete(filename_table, filename_delete_one);
        filename_table = NULL;
     }
 }
+
+void
+line_lookup(unsigned long index, const char **filename, unsigned long *line)
+{
+    line_index_mapping *mapping, *mapping2;
+
+    assert(index <= line_index);
+
+    /* Linearly search through map to find highest line_index <= index */
+    mapping = STAILQ_FIRST(line_index_map);
+    while (mapping) {
+       mapping2 = STAILQ_NEXT(mapping, link);
+       if (!mapping2 || mapping2->index > index)
+           break;
+       mapping = mapping2;
+    }
+
+    *filename = mapping->filename;
+    *line = mapping->line+mapping->line_inc*(index-mapping->index);
+}
index be2fcf4359549b32f8788d8e34cf7777266c709b..690b8d65bcb5f8c63bcd0e6a72c152d856b4c525 100644 (file)
@@ -28,20 +28,19 @@ extern /*@null@*/ parser *cur_parser;
 /* Current (selected) object format */
 extern /*@null@*/ objfmt *cur_objfmt;
 
-/*@null@*/ /*@dependent@*/ extern const char *in_filename;
-extern unsigned int line_number;
-
-/* Amount to increase line_number by after each line.  Should be 0 or 1, set by
- * %line (in NASM syntax).  Initialized to 1 at startup.
- * (0 is for 1-line macros that expand to multiple lines).
- */
-extern unsigned int line_number_inc;
+/* Virtual line number.  Uniquely specifies every line read by the parser. */
+extern unsigned long line_index;
 
+/* Global assembler options. */
 extern unsigned int asm_options;
 
+/* Indentation level for assembler *_print() routines */
 extern int indent_level;
 
-void switch_filename(const char *filename);
-void filename_delete_all(void);
+void line_set(const char *filename, unsigned long line,
+             unsigned long line_inc);
+void line_shutdown(void);
+void line_lookup(unsigned long index, const char **filename,
+                unsigned long *line);
 
 #endif
index e8c245385c392e459da59535085cc5465402d4d2..ca2413587b6b8f54d1af3f4555d55b5e68b51a9a 100644 (file)
@@ -46,7 +46,7 @@
 #endif
 
 static int files_open = 0;
-/*@null@*/ /*@only@*/ static char *obj_filename = NULL;
+/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
 /*@null@*/ static FILE *in = NULL, *obj = NULL;
 
 /* Forward declarations: cmd line parser handlers */
@@ -119,11 +119,14 @@ main(int argc, char *argv[])
     /* if no files were specified, fallback to reading stdin */
     if (!in) {
        in = stdin;
-       switch_filename("<STDIN>");
+       in_filename = xstrdup("<STDIN>");
        if (!obj)
            obj = stdout;
     }
 
+    /* Initialize line info */
+    line_set(in_filename, 1, 1);
+
     /* Set x86 as the architecture */
     cur_arch = &x86_arch;
 
@@ -173,7 +176,8 @@ main(int argc, char *argv[])
     if (OutputAllErrorWarning() > 0) {
        sections_delete(sections);
        symrec_delete_all();
-       filename_delete_all();
+       line_shutdown();
+       floatnum_shutdown();
        BitVector_Shutdown();
        return EXIT_FAILURE;
     }
@@ -208,7 +212,7 @@ main(int argc, char *argv[])
 
     sections_delete(sections);
     symrec_delete_all();
-    filename_delete_all();
+    line_shutdown();
 
     floatnum_shutdown();
 
@@ -227,6 +231,8 @@ not_an_option_handler(char *param)
        WarningNow("can open only one input file, only latest file will be processed");
        if(fclose(in))
            ErrorNow("could not close old input file");
+       if (in_filename)
+           xfree(in_filename);
     }
 
     in = fopen(param, "rt");
@@ -234,7 +240,7 @@ not_an_option_handler(char *param)
        ErrorNow(_("could not open file `%s'"), param);
        return 1;
     }
-    switch_filename(param);
+    in_filename = xstrdup(param);
 
     files_open++;
     return 0;
index d16775b9a3e9ceec60f97ccab9494a7c8adadb3a..e0f0b66a8be6a20100a135d086e2785f280d0024 100644 (file)
@@ -146,17 +146,18 @@ input: /* empty */
                                               $2);
        if (nasm_parser_temp_bc)
            nasm_parser_prev_bc = nasm_parser_temp_bc;
-       line_number += line_number_inc;
+       line_index++;
     }
 ;
 
 line: '\n'             { $$ = (bytecode *)NULL; }
     | lineexp '\n'
     | LINE INTNUM '+' INTNUM FILENAME '\n' {
-       line_number = (unsigned int)intnum_get_uint($2);
-       line_number_inc = (unsigned int)intnum_get_uint($4);
-       line_number -= line_number_inc; /* as we'll add it back in */
-       switch_filename($5);
+       /* %line indicates the line number of the *next* line, so subtract out
+        * the increment when setting the line number.
+        */
+       line_set($5, intnum_get_uint($2)-intnum_get_uint($4),
+                intnum_get_uint($4));
        intnum_delete($2);
        intnum_delete($4);
        xfree($5);
index d16775b9a3e9ceec60f97ccab9494a7c8adadb3a..e0f0b66a8be6a20100a135d086e2785f280d0024 100644 (file)
@@ -146,17 +146,18 @@ input: /* empty */
                                               $2);
        if (nasm_parser_temp_bc)
            nasm_parser_prev_bc = nasm_parser_temp_bc;
-       line_number += line_number_inc;
+       line_index++;
     }
 ;
 
 line: '\n'             { $$ = (bytecode *)NULL; }
     | lineexp '\n'
     | LINE INTNUM '+' INTNUM FILENAME '\n' {
-       line_number = (unsigned int)intnum_get_uint($2);
-       line_number_inc = (unsigned int)intnum_get_uint($4);
-       line_number -= line_number_inc; /* as we'll add it back in */
-       switch_filename($5);
+       /* %line indicates the line number of the *next* line, so subtract out
+        * the increment when setting the line number.
+        */
+       line_set($5, intnum_get_uint($2)-intnum_get_uint($4),
+                intnum_get_uint($4));
        intnum_delete($2);
        intnum_delete($4);
        xfree($5);
index e88d5e7b3ced07d1299424ffd26a389a35c9b6f7..3dba92fc805aa884fb0e5f77a235432e028535be 100644 (file)
@@ -59,7 +59,6 @@ struct symrec {
     SymType type;
     SymStatus status;
     SymVisibility visibility;
-    /*@dependent@*/ /*@null@*/ const char *filename;   /* file and line */
     unsigned long line;                /*  symbol was first declared or used on */
     union {
        expr *expn;             /* equ value */
@@ -113,8 +112,7 @@ symrec_get_or_new(const char *name, int in_table)
     rec = xmalloc(sizeof(symrec));
     rec->name = symname;
     rec->type = SYM_UNKNOWN;
-    rec->filename = in_filename;
-    rec->line = line_number;
+    rec->line = line_index;
     rec->visibility = SYM_LOCAL;
     rec->of_data_vis_ce = NULL;
     rec->of_data_vis_g = NULL;
@@ -163,7 +161,7 @@ symrec_define(const char *name, SymType type, int in_table)
        Error(_("duplicate definition of `%s'; first defined on line %d"),
              name, rec->line);
     } else {
-       rec->line = line_number;        /* set line number of definition */
+       rec->line = line_index; /* set line number of definition */
        rec->type = type;
        rec->status |= SYM_DEFINED;
     }
@@ -206,7 +204,7 @@ symrec_declare(const char *name, SymVisibility vis, void *of_data)
        if (of_data)
            cur_objfmt->declare_data_delete(vis, of_data);
     } else {
-       rec->line = line_number;        /* set line number of declaration */
+       rec->line = line_index; /* set line number of declaration */
        rec->visibility |= vis;
 
        /* If declared as COMMON or EXTERN, set as DEFINED. */
@@ -299,18 +297,14 @@ symrec_set_opt_flags(symrec *sym, unsigned long opt_flags)
 }
 
 static unsigned long firstundef_line;
-static /*@dependent@*/ /*@null@*/ const char *firstundef_filename;
 static int
 symrec_parser_finalize_checksym(symrec *sym, /*@unused@*/ /*@null@*/ void *d)
 {
     /* error if a symbol is used but never defined */
     if ((sym->status & SYM_USED) && !(sym->status & SYM_DEFINED)) {
-       ErrorAt(sym->filename, sym->line,
-               _("undefined symbol `%s' (first use)"), sym->name);
-       if (sym->line < firstundef_line) {
+       ErrorAt(sym->line, _("undefined symbol `%s' (first use)"), sym->name);
+       if (sym->line < firstundef_line)
            firstundef_line = sym->line;
-           firstundef_filename = sym->filename;
-       }
     }
 
     return 1;
@@ -322,7 +316,7 @@ symrec_parser_finalize(void)
     firstundef_line = ULONG_MAX;
     symrec_traverse(NULL, symrec_parser_finalize_checksym);
     if (firstundef_line < ULONG_MAX)
-       ErrorAt(firstundef_filename, firstundef_line,
+       ErrorAt(firstundef_line,
                _(" (Each undefined symbol is reported only once.)"));
 }
 
@@ -368,6 +362,9 @@ symrec_print_all(FILE *f)
 void
 symrec_print(FILE *f, const symrec *sym)
 {
+    const char *filename;
+    unsigned long line;
+
     switch (sym->type) {
        case SYM_UNKNOWN:
            fprintf(f, "%*s-Unknown (Common/Extern)-\n", indent_level, "");
@@ -439,6 +436,7 @@ symrec_print(FILE *f, const symrec *sym)
        indent_level--;
     }
 
+    line_lookup(sym->line, &filename, &line);
     fprintf(f, "%*sFilename=\"%s\" Line Number=%lu\n", indent_level, "",
-          sym->filename?sym->filename:"(NULL)", sym->line);
+          filename, line);
 }