#include "config.h"
#include "system.h"
#include "line-map.h"
#include "intl.h"
extern int flag_cpp_precomp;
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 && !flag_cpp_precomp)
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);
}