From 3f2186c1bf2af9a11eb32feafafaa62559f501ba Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 7 Jan 2002 07:42:27 +0000 Subject: [PATCH] Change from current file/line dual storage to a monotonically-increasing line "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 --- frontends/yasm/yasm.c | 16 ++++-- libyasm/bc-int.h | 3 +- libyasm/bytecode.c | 10 ++-- libyasm/errwarn.c | 34 +++++++----- libyasm/errwarn.h | 6 +-- libyasm/expr-int.h | 1 - libyasm/expr.c | 6 +-- libyasm/linemgr.c | 90 +++++++++++++++++++++++++++---- libyasm/linemgr.h | 19 ++++--- libyasm/symrec.c | 24 ++++----- modules/arch/x86/x86expr.c | 20 +++---- modules/parsers/nasm/bison.y.in | 11 ++-- modules/parsers/nasm/nasm-bison.y | 11 ++-- src/arch/x86/x86expr.c | 20 +++---- src/bc-int.h | 3 +- src/bytecode.c | 10 ++-- src/errwarn.c | 34 +++++++----- src/errwarn.h | 6 +-- src/expr-int.h | 1 - src/expr.c | 6 +-- src/globals.c | 90 +++++++++++++++++++++++++++---- src/globals.h | 19 ++++--- src/linemgr.c | 90 +++++++++++++++++++++++++++---- src/linemgr.h | 19 ++++--- src/main.c | 16 ++++-- src/parsers/nasm/bison.y.in | 11 ++-- src/parsers/nasm/nasm-bison.y | 11 ++-- src/symrec.c | 24 ++++----- 28 files changed, 412 insertions(+), 199 deletions(-) diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index e8c24538..ca241358 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -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(""); + in_filename = xstrdup(""); 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; diff --git a/libyasm/bc-int.h b/libyasm/bc-int.h index 0b8b20b4..97ab493d 100644 --- a/libyasm/bc-int.h +++ b/libyasm/bc-int.h @@ -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 */ diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 149f71d4..c35a71d6 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -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 : "", 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); } diff --git a/libyasm/errwarn.c b/libyasm/errwarn.c index daf412cf..a80889b6 100644 --- a/libyasm/errwarn.c +++ b/libyasm/errwarn.c @@ -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. */ diff --git a/libyasm/errwarn.h b/libyasm/errwarn.h index 59713c27..b50fa08b 100644 --- a/libyasm/errwarn.h +++ b/libyasm/errwarn.h @@ -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 diff --git a/libyasm/expr-int.h b/libyasm/expr-int.h index c47c977b..6c37fa20 100644 --- a/libyasm/expr-int.h +++ b/libyasm/expr-int.h @@ -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 */ diff --git a/libyasm/expr.c b/libyasm/expr.c index 211dceab..be0ab2e4 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -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; inumterms; i++) { diff --git a/libyasm/linemgr.c b/libyasm/linemgr.c index bcdd65e3..b57dc2da 100644 --- a/libyasm/linemgr.c +++ b/libyasm/linemgr.c @@ -33,15 +33,37 @@ /* 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); +} diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index be2fcf43..690b8d65 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -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 diff --git a/libyasm/symrec.c b/libyasm/symrec.c index e88d5e7b..3dba92fc 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -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); } diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c index 09b21767..49ab69ba 100644 --- a/modules/arch/x86/x86expr.c +++ b/modules/arch/x86/x86expr.c @@ -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; } diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index d16775b9..e0f0b66a 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -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); diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index d16775b9..e0f0b66a 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -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); diff --git a/src/arch/x86/x86expr.c b/src/arch/x86/x86expr.c index 09b21767..49ab69ba 100644 --- a/src/arch/x86/x86expr.c +++ b/src/arch/x86/x86expr.c @@ -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; } diff --git a/src/bc-int.h b/src/bc-int.h index 0b8b20b4..97ab493d 100644 --- a/src/bc-int.h +++ b/src/bc-int.h @@ -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 */ diff --git a/src/bytecode.c b/src/bytecode.c index 149f71d4..c35a71d6 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -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 : "", 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); } diff --git a/src/errwarn.c b/src/errwarn.c index daf412cf..a80889b6 100644 --- a/src/errwarn.c +++ b/src/errwarn.c @@ -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. */ diff --git a/src/errwarn.h b/src/errwarn.h index 59713c27..b50fa08b 100644 --- a/src/errwarn.h +++ b/src/errwarn.h @@ -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 diff --git a/src/expr-int.h b/src/expr-int.h index c47c977b..6c37fa20 100644 --- a/src/expr-int.h +++ b/src/expr-int.h @@ -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 */ diff --git a/src/expr.c b/src/expr.c index 211dceab..be0ab2e4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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; inumterms; i++) { diff --git a/src/globals.c b/src/globals.c index bcdd65e3..b57dc2da 100644 --- a/src/globals.c +++ b/src/globals.c @@ -33,15 +33,37 @@ /* 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); +} diff --git a/src/globals.h b/src/globals.h index be2fcf43..690b8d65 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 diff --git a/src/linemgr.c b/src/linemgr.c index bcdd65e3..b57dc2da 100644 --- a/src/linemgr.c +++ b/src/linemgr.c @@ -33,15 +33,37 @@ /* 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); +} diff --git a/src/linemgr.h b/src/linemgr.h index be2fcf43..690b8d65 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -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 diff --git a/src/main.c b/src/main.c index e8c24538..ca241358 100644 --- a/src/main.c +++ b/src/main.c @@ -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(""); + in_filename = xstrdup(""); 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; diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index d16775b9..e0f0b66a 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -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); diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index d16775b9..e0f0b66a 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -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); diff --git a/src/symrec.c b/src/symrec.c index e88d5e7b..3dba92fc 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -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); }