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
0.3
Peter Johnson 23 years ago
parent 587a05e3eb
commit 3f2186c1bf
  1. 16
      frontends/yasm/yasm.c
  2. 3
      libyasm/bc-int.h
  3. 10
      libyasm/bytecode.c
  4. 34
      libyasm/errwarn.c
  5. 6
      libyasm/errwarn.h
  6. 1
      libyasm/expr-int.h
  7. 6
      libyasm/expr.c
  8. 90
      libyasm/linemgr.c
  9. 19
      libyasm/linemgr.h
  10. 24
      libyasm/symrec.c
  11. 20
      modules/arch/x86/x86expr.c
  12. 11
      modules/parsers/nasm/bison.y.in
  13. 11
      modules/parsers/nasm/nasm-bison.y
  14. 20
      src/arch/x86/x86expr.c
  15. 3
      src/bc-int.h
  16. 10
      src/bytecode.c
  17. 34
      src/errwarn.c
  18. 6
      src/errwarn.h
  19. 1
      src/expr-int.h
  20. 6
      src/expr.c
  21. 90
      src/globals.c
  22. 19
      src/globals.h
  23. 90
      src/linemgr.c
  24. 19
      src/linemgr.h
  25. 16
      src/main.c
  26. 11
      src/parsers/nasm/bison.y.in
  27. 11
      src/parsers/nasm/nasm-bison.y
  28. 24
      src/symrec.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("<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;

@ -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 */

@ -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);
}

@ -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. */

@ -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

@ -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 */

@ -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++) {

@ -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);
}

@ -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

@ -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);
}

@ -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;
}

@ -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);

@ -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);

@ -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;
}

@ -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 */

@ -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);
}

@ -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. */

@ -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

@ -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 */

@ -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++) {

@ -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);
}

@ -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

@ -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);
}

@ -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

@ -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;

@ -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);

@ -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);

@ -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);
}

Loading…
Cancel
Save