]> git.ipfire.org Git - thirdparty/gcc.git/blame - libcpp/line-map.c
* de.po: Update.
[thirdparty/gcc.git] / libcpp / line-map.c
CommitLineData
d82fc108 1/* Map logical line numbers to (source file, line number) pairs.
2bf41bf0 2 Copyright (C) 2001, 2003, 2004, 2007, 2008
d82fc108
NB
3 Free Software Foundation, Inc.
4
5This program is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option) any
8later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
200031d1 17Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
d82fc108
NB
18
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding! */
22
23#include "config.h"
24#include "system.h"
25#include "line-map.h"
26
e2b9853b 27static void trace_include (const struct line_maps *, const struct line_map *);
5993019d 28
d82fc108
NB
29/* Initialize a line map set. */
30
31void
a2f7be91 32linemap_init (struct line_maps *set)
d82fc108 33{
9132fbb7 34 set->maps = NULL;
d82fc108
NB
35 set->allocated = 0;
36 set->used = 0;
fde84349 37 set->last_listed = -1;
5993019d 38 set->trace_includes = false;
d8693c6f 39 set->depth = 0;
9132fbb7 40 set->cache = 0;
12f9df4e 41 set->highest_location = 0;
500bee0a 42 set->highest_line = 0;
12f9df4e 43 set->max_column_hint = 0;
d82fc108
NB
44}
45
9ac97460 46/* Check for and warn about line_maps entered but not exited. */
12f9df4e
PB
47
48void
49linemap_check_files_exited (struct line_maps *set)
50{
51 struct line_map *map;
52 /* Depending upon whether we are handling preprocessed input or
53 not, this can be a user error or an ICE. */
54 for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
55 map = INCLUDED_FROM (set, map))
56 fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
57 map->to_file);
58}
59
d82fc108
NB
60/* Free a line map set. */
61
fde84349 62void
a2f7be91 63linemap_free (struct line_maps *set)
d82fc108
NB
64{
65 if (set->maps)
fde84349 66 {
12f9df4e 67 linemap_check_files_exited (set);
47d89cf3 68
fde84349
NB
69 free (set->maps);
70 }
d82fc108
NB
71}
72
73/* Add a mapping of logical source line to physical source file and
9074464c
GK
74 line number.
75
76 The text pointed to by TO_FILE must have a lifetime
77 at least as long as the final call to lookup_line (). An empty
78 TO_FILE means standard input. If reason is LC_LEAVE, and
79 TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
80 natural values considering the file we are returning to.
d82fc108
NB
81
82 FROM_LINE should be monotonic increasing across calls to this
9074464c
GK
83 function. A call to this function can relocate the previous set of
84 maps, so any stored line_map pointers should not be used. */
d82fc108 85
47d89cf3 86const struct line_map *
a2f7be91 87linemap_add (struct line_maps *set, enum lc_reason reason,
12f9df4e 88 unsigned int sysp, const char *to_file, unsigned int to_line)
d82fc108
NB
89{
90 struct line_map *map;
12f9df4e 91 source_location start_location = set->highest_location + 1;
d82fc108 92
12f9df4e 93 if (set->used && start_location < set->maps[set->used - 1].start_location)
d82fc108
NB
94 abort ();
95
96 if (set->used == set->allocated)
97 {
5ffeb913
TT
98 line_map_realloc reallocator
99 = set->reallocator ? set->reallocator : xrealloc;
d82fc108 100 set->allocated = 2 * set->allocated + 256;
5ffeb913
TT
101 set->maps
102 = (struct line_map *) (*reallocator) (set->maps,
103 set->allocated
104 * sizeof (struct line_map));
105 memset (&set->maps[set->used], 0, ((set->allocated - set->used)
106 * sizeof (struct line_map)));
d82fc108
NB
107 }
108
9132fbb7 109 map = &set->maps[set->used];
d82fc108 110
9074464c
GK
111 if (to_file && *to_file == '\0')
112 to_file = "<stdin>";
113
fde84349
NB
114 /* If we don't keep our line maps consistent, we can easily
115 segfault. Don't rely on the client to do it for us. */
d8693c6f 116 if (set->depth == 0)
fde84349
NB
117 reason = LC_ENTER;
118 else if (reason == LC_LEAVE)
119 {
47d89cf3
NB
120 struct line_map *from;
121 bool error;
122
123 if (MAIN_FILE_P (map - 1))
fde84349 124 {
b3147029
PB
125 if (to_file == NULL)
126 {
127 set->depth--;
b3147029
PB
128 return NULL;
129 }
130 error = true;
131 reason = LC_RENAME;
132 from = map - 1;
47d89cf3
NB
133 }
134 else
135 {
136 from = INCLUDED_FROM (set, map - 1);
137 error = to_file && strcmp (from->to_file, to_file);
138 }
139
140 /* Depending upon whether we are handling preprocessed input or
141 not, this can be a user error or an ICE. */
142 if (error)
143 fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
144 to_file);
145
146 /* A TO_FILE of NULL is special - we use the natural values. */
147 if (error || to_file == NULL)
148 {
149 to_file = from->to_file;
12f9df4e 150 to_line = SOURCE_LINE (from, from[1].start_location);
47d89cf3 151 sysp = from->sysp;
fde84349
NB
152 }
153 }
154
47d89cf3
NB
155 map->reason = reason;
156 map->sysp = sysp;
12f9df4e 157 map->start_location = start_location;
47d89cf3
NB
158 map->to_file = to_file;
159 map->to_line = to_line;
9132fbb7 160 set->cache = set->used++;
12f9df4e
PB
161 map->column_bits = 0;
162 set->highest_location = start_location;
500bee0a 163 set->highest_line = start_location;
12f9df4e 164 set->max_column_hint = 0;
47d89cf3 165
fde84349 166 if (reason == LC_ENTER)
d8693c6f 167 {
8826ff0f 168 map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
d8693c6f 169 set->depth++;
d8693c6f
NB
170 if (set->trace_includes)
171 trace_include (set, map);
172 }
d82fc108
NB
173 else if (reason == LC_RENAME)
174 map->included_from = map[-1].included_from;
175 else if (reason == LC_LEAVE)
d8693c6f
NB
176 {
177 set->depth--;
178 map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
179 }
5993019d 180
d82fc108
NB
181 return map;
182}
183
12f9df4e
PB
184source_location
185linemap_line_start (struct line_maps *set, unsigned int to_line,
186 unsigned int max_column_hint)
187{
188 struct line_map *map = &set->maps[set->used - 1];
189 source_location highest = set->highest_location;
190 source_location r;
500bee0a 191 unsigned int last_line = SOURCE_LINE (map, set->highest_line);
12f9df4e
PB
192 int line_delta = to_line - last_line;
193 bool add_map = false;
194 if (line_delta < 0
195 || (line_delta > 10 && line_delta * map->column_bits > 1000)
196 || (max_column_hint >= (1U << map->column_bits))
197 || (max_column_hint <= 80 && map->column_bits >= 10))
198 {
199 add_map = true;
200 }
201 else
202 max_column_hint = set->max_column_hint;
203 if (add_map)
204 {
205 int column_bits;
500bee0a 206 if (max_column_hint > 100000 || highest > 0xC0000000)
12f9df4e 207 {
c1fc5047
PB
208 /* If the column number is ridiculous or we've allocated a huge
209 number of source_locations, give up on column numbers. */
12f9df4e
PB
210 max_column_hint = 0;
211 if (highest >0xF0000000)
212 return 0;
213 column_bits = 0;
214 }
215 else
216 {
217 column_bits = 7;
218 while (max_column_hint >= (1U << column_bits))
219 column_bits++;
220 max_column_hint = 1U << column_bits;
221 }
c1fc5047
PB
222 /* Allocate the new line_map. However, if the current map only has a
223 single line we can sometimes just increase its column_bits instead. */
12f9df4e
PB
224 if (line_delta < 0
225 || last_line != map->to_line
226 || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
2bf41bf0
TT
227 map = (struct line_map *) linemap_add (set, LC_RENAME, map->sysp,
228 map->to_file, to_line);
12f9df4e 229 map->column_bits = column_bits;
c1fc5047 230 r = map->start_location + ((to_line - map->to_line) << column_bits);
12f9df4e
PB
231 }
232 else
233 r = highest - SOURCE_COLUMN (map, highest)
234 + (line_delta << map->column_bits);
500bee0a 235 set->highest_line = r;
12f9df4e
PB
236 if (r > set->highest_location)
237 set->highest_location = r;
238 set->max_column_hint = max_column_hint;
239 return r;
240}
241
500bee0a
PB
242source_location
243linemap_position_for_column (struct line_maps *set, unsigned int to_column)
244{
245 source_location r = set->highest_line;
246 if (to_column >= set->max_column_hint)
247 {
248 if (r >= 0xC000000 || to_column > 100000)
249 {
250 /* Running low on source_locations - disable column numbers. */
251 return r;
252 }
253 else
254 {
255 struct line_map *map = &set->maps[set->used - 1];
256 r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
257 }
258 }
259 r = r + to_column;
260 if (r >= set->highest_location)
261 set->highest_location = r;
262 return r;
263}
264
6604e6f3
NB
265/* Given a logical line, returns the map from which the corresponding
266 (source file, line) pair can be deduced. Since the set is built
267 chronologically, the logical lines are monotonic increasing, and so
268 the list is sorted and we can use a binary search. */
d82fc108 269
47d89cf3 270const struct line_map *
7d40b45f 271linemap_lookup (struct line_maps *set, source_location line)
d82fc108 272{
9132fbb7
PB
273 unsigned int md, mn, mx;
274 const struct line_map *cached;
275
276 mn = set->cache;
277 mx = set->used;
278
279 cached = &set->maps[mn];
9ac97460 280 /* We should get a segfault if no line_maps have been added yet. */
12f9df4e 281 if (line >= cached->start_location)
9132fbb7 282 {
12f9df4e 283 if (mn + 1 == mx || line < cached[1].start_location)
9132fbb7
PB
284 return cached;
285 }
286 else
287 {
288 mx = mn;
289 mn = 0;
290 }
d82fc108
NB
291
292 while (mx - mn > 1)
293 {
294 md = (mn + mx) / 2;
12f9df4e 295 if (set->maps[md].start_location > line)
d82fc108
NB
296 mx = md;
297 else
298 mn = md;
299 }
300
9132fbb7 301 set->cache = mn;
d82fc108
NB
302 return &set->maps[mn];
303}
fde84349
NB
304
305/* Print the file names and line numbers of the #include commands
306 which led to the map MAP, if any, to stderr. Nothing is output if
307 the most recently listed stack is the same as the current one. */
308
309void
a2f7be91
ZW
310linemap_print_containing_files (struct line_maps *set,
311 const struct line_map *map)
fde84349
NB
312{
313 if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
314 return;
315
316 set->last_listed = map->included_from;
317 map = INCLUDED_FROM (set, map);
318
319 fprintf (stderr, _("In file included from %s:%u"),
320 map->to_file, LAST_SOURCE_LINE (map));
321
322 while (! MAIN_FILE_P (map))
323 {
324 map = INCLUDED_FROM (set, map);
325 /* Translators note: this message is used in conjunction
326 with "In file included from %s:%ld" and some other
327 tricks. We want something like this:
328
329 | In file included from sys/select.h:123,
330 | from sys/types.h:234,
331 | from userfile.c:31:
332 | bits/select.h:45: <error message here>
333
334 with all the "from"s lined up.
335 The trailing comma is at the beginning of this message,
336 and the trailing colon is not translated. */
337 fprintf (stderr, _(",\n from %s:%u"),
338 map->to_file, LAST_SOURCE_LINE (map));
339 }
340
341 fputs (":\n", stderr);
342}
5993019d
NB
343
344/* Print an include trace, for e.g. the -H option of the preprocessor. */
345
346static void
e2b9853b 347trace_include (const struct line_maps *set, const struct line_map *map)
5993019d 348{
d8693c6f 349 unsigned int i = set->depth;
5993019d 350
d8693c6f 351 while (--i)
5993019d
NB
352 putc ('.', stderr);
353 fprintf (stderr, " %s\n", map->to_file);
354}