#include "config.h"
#include "system.h"
#include "line-map.h"
#include "intl.h"
static
void
trace_include
PARAMS ((
const
struct
line_maps *,
const
struct
line_map *));
void
init_line_maps (set)
struct
line_maps *set;
{
set->maps = 0;
set->allocated = 0;
set->used = 0;
set->last_listed = -1;
set->trace_includes =
false
;
set->depth = 0;
}
void
free_line_maps (set)
struct
line_maps *set;
{
if
(set->maps)
{
struct
line_map *map;
for
(map = CURRENT_LINE_MAP (set); ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
fprintf
(stderr,
"line-map.c: file \"%s\" entered but not left\n"
,
map->to_file);
free
(set->maps);
}
}
const
struct
line_map *
add_line_map (set, reason, sysp, from_line, to_file, to_line)
struct
line_maps *set;
enum
lc_reason reason;
unsigned
int
sysp;
unsigned
int
from_line;
const
char
*to_file;
unsigned
int
to_line;
{
struct
line_map *map;
if
(set->used && from_line < set->maps[set->used - 1].from_line)
abort
();
if
(set->used == set->allocated)
{
set->allocated = 2 * set->allocated + 256;
set->maps = (
struct
line_map *)
xrealloc (set->maps, set->allocated *
sizeof
(
struct
line_map));
}
map = &set->maps[set->used++];
if
(set->depth == 0)
reason = LC_ENTER;
else
if
(reason == LC_LEAVE)
{
struct
line_map *from;
bool
error;
if
(MAIN_FILE_P (map - 1))
{
error =
true
;
reason = LC_RENAME;
from = map - 1;
}
else
{
from = INCLUDED_FROM (set, map - 1);
error = to_file &&
strcmp
(from->to_file, to_file);
}
if
(error)
fprintf
(stderr,
"line-map.c: file \"%s\" left but not entered\n"
,
to_file);
if
(error || to_file == NULL)
{
to_file = from->to_file;
to_line = LAST_SOURCE_LINE (from) + 1;
sysp = from->sysp;
}
}
map->reason = reason;
map->sysp = sysp;
map->from_line = from_line;
map->to_file = to_file;
map->to_line = to_line;
if
(reason == LC_ENTER)
{
set->depth++;
map->included_from = set->used - 2;
if
(set->trace_includes)
trace_include (set, map);
}
else
if
(reason == LC_RENAME)
map->included_from = map[-1].included_from;
else
if
(reason == LC_LEAVE)
{
set->depth--;
map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
}
return
map;
}
const
struct
line_map *
lookup_line (set, line)
struct
line_maps *set;
unsigned
int
line;
{
unsigned
int
md, mn = 0, mx = set->used;
if
(mx == 0)
abort
();
while
(mx - mn > 1)
{
md = (mn + mx) / 2;
if
(set->maps[md].from_line > line)
mx = md;
else
mn = md;
}
return
&set->maps[mn];
}
void
print_containing_files (set, map)
struct
line_maps *set;
const
struct
line_map *map;
{
if
(MAIN_FILE_P (map) || set->last_listed == map->included_from)
return
;
set->last_listed = map->included_from;
map = INCLUDED_FROM (set, map);
fprintf
(stderr,
"In file included from %s:%u"
,
map->to_file, LAST_SOURCE_LINE (map));
while
(! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (set, map);
fprintf
(stderr,
",\n from %s:%u"
,
map->to_file, LAST_SOURCE_LINE (map));
}
fputs
(
":\n"
, stderr);
}
static
void
trace_include (set, map)
const
struct
line_maps *set;
const
struct
line_map *map;
{
unsigned
int
i = set->depth;
while
(--i)
putc
(
'.'
, stderr);
fprintf
(stderr,
" %s\n"
, map->to_file);
}