1169695Skan/* Map logical line numbers to (source file, line number) pairs.
2169695Skan   Copyright (C) 2001, 2003, 2004
3169695Skan   Free Software Foundation, Inc.
4169695Skan
5169695SkanThis program is free software; you can redistribute it and/or modify it
6169695Skanunder the terms of the GNU General Public License as published by the
7169695SkanFree Software Foundation; either version 2, or (at your option) any
8169695Skanlater version.
9169695Skan
10169695SkanThis program is distributed in the hope that it will be useful,
11169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
12169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13169695SkanGNU General Public License for more details.
14169695Skan
15169695SkanYou should have received a copy of the GNU General Public License
16169695Skanalong with this program; if not, write to the Free Software
17169695SkanFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18169695Skan
19169695Skan In other words, you are welcome to use, share and improve this program.
20169695Skan You are forbidden to forbid anyone else to use, share and improve
21169695Skan what you give them.   Help stamp out software-hoarding!  */
22169695Skan
23169695Skan#include "config.h"
24169695Skan#include "system.h"
25169695Skan#include "line-map.h"
26169695Skan
27169695Skanstatic void trace_include (const struct line_maps *, const struct line_map *);
28169695Skan
29169695Skan/* Initialize a line map set.  */
30169695Skan
31169695Skanvoid
32169695Skanlinemap_init (struct line_maps *set)
33169695Skan{
34169695Skan  set->maps = NULL;
35169695Skan  set->allocated = 0;
36169695Skan  set->used = 0;
37169695Skan  set->last_listed = -1;
38169695Skan  set->trace_includes = false;
39169695Skan  set->depth = 0;
40169695Skan  set->cache = 0;
41169695Skan  set->highest_location = 0;
42169695Skan  set->highest_line = 0;
43169695Skan  set->max_column_hint = 0;
44169695Skan}
45169695Skan
46169695Skan/* Check for and warn about line_maps entered but not exited.  */
47169695Skan
48169695Skanvoid
49169695Skanlinemap_check_files_exited (struct line_maps *set)
50169695Skan{
51169695Skan  struct line_map *map;
52169695Skan  /* Depending upon whether we are handling preprocessed input or
53169695Skan     not, this can be a user error or an ICE.  */
54169695Skan  for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
55169695Skan       map = INCLUDED_FROM (set, map))
56169695Skan    fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
57169695Skan	     map->to_file);
58169695Skan}
59169695Skan
60169695Skan/* Free a line map set.  */
61169695Skan
62169695Skanvoid
63169695Skanlinemap_free (struct line_maps *set)
64169695Skan{
65169695Skan  if (set->maps)
66169695Skan    {
67169695Skan      linemap_check_files_exited (set);
68169695Skan
69169695Skan      free (set->maps);
70169695Skan    }
71169695Skan}
72169695Skan
73169695Skan/* Add a mapping of logical source line to physical source file and
74169695Skan   line number.
75169695Skan
76169695Skan   The text pointed to by TO_FILE must have a lifetime
77169695Skan   at least as long as the final call to lookup_line ().  An empty
78169695Skan   TO_FILE means standard input.  If reason is LC_LEAVE, and
79169695Skan   TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
80169695Skan   natural values considering the file we are returning to.
81169695Skan
82169695Skan   FROM_LINE should be monotonic increasing across calls to this
83169695Skan   function.  A call to this function can relocate the previous set of
84169695Skan   A call to this function can relocate the previous set of
85169695Skan   maps, so any stored line_map pointers should not be used.  */
86169695Skan
87169695Skanconst struct line_map *
88169695Skanlinemap_add (struct line_maps *set, enum lc_reason reason,
89169695Skan	     unsigned int sysp, const char *to_file, unsigned int to_line)
90169695Skan{
91169695Skan  struct line_map *map;
92169695Skan  source_location start_location = set->highest_location + 1;
93169695Skan
94169695Skan  if (set->used && start_location < set->maps[set->used - 1].start_location)
95169695Skan    abort ();
96169695Skan
97169695Skan  if (set->used == set->allocated)
98169695Skan    {
99169695Skan      set->allocated = 2 * set->allocated + 256;
100169695Skan      set->maps = XRESIZEVEC (struct line_map, set->maps, set->allocated);
101169695Skan    }
102169695Skan
103169695Skan  map = &set->maps[set->used];
104169695Skan
105169695Skan  if (to_file && *to_file == '\0')
106169695Skan    to_file = "<stdin>";
107169695Skan
108169695Skan  /* If we don't keep our line maps consistent, we can easily
109169695Skan     segfault.  Don't rely on the client to do it for us.  */
110169695Skan  if (set->depth == 0)
111169695Skan    reason = LC_ENTER;
112169695Skan  else if (reason == LC_LEAVE)
113169695Skan    {
114169695Skan      struct line_map *from;
115169695Skan      bool error;
116169695Skan
117169695Skan      if (MAIN_FILE_P (map - 1))
118169695Skan	{
119169695Skan	  if (to_file == NULL)
120169695Skan	    {
121169695Skan	      set->depth--;
122169695Skan	      return NULL;
123169695Skan	    }
124169695Skan	  error = true;
125169695Skan          reason = LC_RENAME;
126169695Skan          from = map - 1;
127169695Skan	}
128169695Skan      else
129169695Skan	{
130169695Skan	  from = INCLUDED_FROM (set, map - 1);
131169695Skan	  error = to_file && strcmp (from->to_file, to_file);
132169695Skan	}
133169695Skan
134169695Skan      /* Depending upon whether we are handling preprocessed input or
135169695Skan	 not, this can be a user error or an ICE.  */
136169695Skan      if (error)
137169695Skan	fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
138169695Skan		 to_file);
139169695Skan
140169695Skan      /* A TO_FILE of NULL is special - we use the natural values.  */
141169695Skan      if (error || to_file == NULL)
142169695Skan	{
143169695Skan	  to_file = from->to_file;
144169695Skan	  to_line = SOURCE_LINE (from, from[1].start_location);
145169695Skan	  sysp = from->sysp;
146169695Skan	}
147169695Skan    }
148169695Skan
149169695Skan  map->reason = reason;
150169695Skan  map->sysp = sysp;
151169695Skan  map->start_location = start_location;
152169695Skan  map->to_file = to_file;
153169695Skan  map->to_line = to_line;
154169695Skan  set->cache = set->used++;
155169695Skan  map->column_bits = 0;
156169695Skan  set->highest_location = start_location;
157169695Skan  set->highest_line = start_location;
158169695Skan  set->max_column_hint = 0;
159169695Skan
160169695Skan  if (reason == LC_ENTER)
161169695Skan    {
162169695Skan      map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
163169695Skan      set->depth++;
164169695Skan      if (set->trace_includes)
165169695Skan	trace_include (set, map);
166169695Skan    }
167169695Skan  else if (reason == LC_RENAME)
168169695Skan    map->included_from = map[-1].included_from;
169169695Skan  else if (reason == LC_LEAVE)
170169695Skan    {
171169695Skan      set->depth--;
172169695Skan      map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
173169695Skan    }
174169695Skan
175169695Skan  return map;
176169695Skan}
177169695Skan
178169695Skansource_location
179169695Skanlinemap_line_start (struct line_maps *set, unsigned int to_line,
180169695Skan		    unsigned int max_column_hint)
181169695Skan{
182169695Skan  struct line_map *map = &set->maps[set->used - 1];
183169695Skan  source_location highest = set->highest_location;
184169695Skan  source_location r;
185169695Skan  unsigned int last_line = SOURCE_LINE (map, set->highest_line);
186169695Skan  int line_delta = to_line - last_line;
187169695Skan  bool add_map = false;
188169695Skan  if (line_delta < 0
189169695Skan      || (line_delta > 10 && line_delta * map->column_bits > 1000)
190169695Skan      || (max_column_hint >= (1U << map->column_bits))
191169695Skan      || (max_column_hint <= 80 && map->column_bits >= 10))
192169695Skan    {
193169695Skan      add_map = true;
194169695Skan    }
195169695Skan  else
196169695Skan    max_column_hint = set->max_column_hint;
197169695Skan  if (add_map)
198169695Skan    {
199169695Skan      int column_bits;
200169695Skan      if (max_column_hint > 100000 || highest > 0xC0000000)
201169695Skan	{
202169695Skan	  /* If the column number is ridiculous or we've allocated a huge
203169695Skan	     number of source_locations, give up on column numbers. */
204169695Skan	  max_column_hint = 0;
205169695Skan	  if (highest >0xF0000000)
206169695Skan	    return 0;
207169695Skan	  column_bits = 0;
208169695Skan	}
209169695Skan      else
210169695Skan	{
211169695Skan	  column_bits = 7;
212169695Skan	  while (max_column_hint >= (1U << column_bits))
213169695Skan	    column_bits++;
214169695Skan	  max_column_hint = 1U << column_bits;
215169695Skan	}
216169695Skan      /* Allocate the new line_map.  However, if the current map only has a
217169695Skan	 single line we can sometimes just increase its column_bits instead. */
218169695Skan      if (line_delta < 0
219169695Skan	  || last_line != map->to_line
220169695Skan	  || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
221169695Skan	map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
222169695Skan				      map->to_file, to_line);
223169695Skan      map->column_bits = column_bits;
224169695Skan      r = map->start_location + ((to_line - map->to_line) << column_bits);
225169695Skan    }
226169695Skan  else
227169695Skan    r = highest - SOURCE_COLUMN (map, highest)
228169695Skan      + (line_delta << map->column_bits);
229169695Skan  set->highest_line = r;
230169695Skan  if (r > set->highest_location)
231169695Skan    set->highest_location = r;
232169695Skan  set->max_column_hint = max_column_hint;
233169695Skan  return r;
234169695Skan}
235169695Skan
236169695Skansource_location
237169695Skanlinemap_position_for_column (struct line_maps *set, unsigned int to_column)
238169695Skan{
239169695Skan  source_location r = set->highest_line;
240169695Skan  if (to_column >= set->max_column_hint)
241169695Skan    {
242169695Skan      if (r >= 0xC000000 || to_column > 100000)
243169695Skan	{
244169695Skan	  /* Running low on source_locations - disable column numbers.  */
245169695Skan	  return r;
246169695Skan	}
247169695Skan      else
248169695Skan	{
249169695Skan	  struct line_map *map = &set->maps[set->used - 1];
250169695Skan	  r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
251169695Skan	}
252169695Skan    }
253169695Skan  r = r + to_column;
254169695Skan  if (r >= set->highest_location)
255169695Skan    set->highest_location = r;
256169695Skan  return r;
257169695Skan}
258169695Skan
259169695Skan/* Given a logical line, returns the map from which the corresponding
260169695Skan   (source file, line) pair can be deduced.  Since the set is built
261169695Skan   chronologically, the logical lines are monotonic increasing, and so
262169695Skan   the list is sorted and we can use a binary search.  */
263169695Skan
264169695Skanconst struct line_map *
265169695Skanlinemap_lookup (struct line_maps *set, source_location line)
266169695Skan{
267169695Skan  unsigned int md, mn, mx;
268169695Skan  const struct line_map *cached;
269169695Skan
270169695Skan  mn = set->cache;
271169695Skan  mx = set->used;
272169695Skan
273169695Skan  cached = &set->maps[mn];
274169695Skan  /* We should get a segfault if no line_maps have been added yet.  */
275169695Skan  if (line >= cached->start_location)
276169695Skan    {
277169695Skan      if (mn + 1 == mx || line < cached[1].start_location)
278169695Skan	return cached;
279169695Skan    }
280169695Skan  else
281169695Skan    {
282169695Skan      mx = mn;
283169695Skan      mn = 0;
284169695Skan    }
285169695Skan
286169695Skan  while (mx - mn > 1)
287169695Skan    {
288169695Skan      md = (mn + mx) / 2;
289169695Skan      if (set->maps[md].start_location > line)
290169695Skan	mx = md;
291169695Skan      else
292169695Skan	mn = md;
293169695Skan    }
294169695Skan
295169695Skan  set->cache = mn;
296169695Skan  return &set->maps[mn];
297169695Skan}
298169695Skan
299169695Skan/* Print the file names and line numbers of the #include commands
300169695Skan   which led to the map MAP, if any, to stderr.  Nothing is output if
301169695Skan   the most recently listed stack is the same as the current one.  */
302169695Skan
303169695Skanvoid
304169695Skanlinemap_print_containing_files (struct line_maps *set,
305169695Skan				const struct line_map *map)
306169695Skan{
307169695Skan  if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
308169695Skan    return;
309169695Skan
310169695Skan  set->last_listed = map->included_from;
311169695Skan  map = INCLUDED_FROM (set, map);
312169695Skan
313169695Skan  fprintf (stderr,  _("In file included from %s:%u"),
314169695Skan	   map->to_file, LAST_SOURCE_LINE (map));
315169695Skan
316169695Skan  while (! MAIN_FILE_P (map))
317169695Skan    {
318169695Skan      map = INCLUDED_FROM (set, map);
319169695Skan      /* Translators note: this message is used in conjunction
320169695Skan	 with "In file included from %s:%ld" and some other
321169695Skan	 tricks.  We want something like this:
322169695Skan
323169695Skan	 | In file included from sys/select.h:123,
324169695Skan	 |                  from sys/types.h:234,
325169695Skan	 |                  from userfile.c:31:
326169695Skan	 | bits/select.h:45: <error message here>
327169695Skan
328169695Skan	 with all the "from"s lined up.
329169695Skan	 The trailing comma is at the beginning of this message,
330169695Skan	 and the trailing colon is not translated.  */
331169695Skan      fprintf (stderr, _(",\n                 from %s:%u"),
332169695Skan	       map->to_file, LAST_SOURCE_LINE (map));
333169695Skan    }
334169695Skan
335169695Skan  fputs (":\n", stderr);
336169695Skan}
337169695Skan
338169695Skan/* Print an include trace, for e.g. the -H option of the preprocessor.  */
339169695Skan
340169695Skanstatic void
341169695Skantrace_include (const struct line_maps *set, const struct line_map *map)
342169695Skan{
343169695Skan  unsigned int i = set->depth;
344169695Skan
345169695Skan  while (--i)
346169695Skan    putc ('.', stderr);
347169695Skan  fprintf (stderr, " %s\n", map->to_file);
348169695Skan}
349