]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/line-map.c
gcc_release (announce_snapshot): Use changedir instead of plain cd.
[thirdparty/gcc.git] / gcc / line-map.c
CommitLineData
d82fc108 1/* Map logical line numbers to (source file, line number) pairs.
d9221e01 2 Copyright (C) 2001, 2003, 2004
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
17Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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"
fde84349 26#include "intl.h"
d82fc108 27
e2b9853b 28static void trace_include (const struct line_maps *, const struct line_map *);
5993019d 29
d82fc108
NB
30/* Initialize a line map set. */
31
32void
a2f7be91 33linemap_init (struct line_maps *set)
d82fc108 34{
9132fbb7 35 set->maps = NULL;
d82fc108
NB
36 set->allocated = 0;
37 set->used = 0;
fde84349 38 set->last_listed = -1;
5993019d 39 set->trace_includes = false;
d8693c6f 40 set->depth = 0;
9132fbb7 41 set->cache = 0;
12f9df4e
PB
42 set->highest_location = 0;
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 83 function. A call to this function can relocate the previous set of
12f9df4e 84 A call to this function can relocate the previous set of
9074464c 85 maps, so any stored line_map pointers should not be used. */
d82fc108 86
47d89cf3 87const struct line_map *
a2f7be91 88linemap_add (struct line_maps *set, enum lc_reason reason,
12f9df4e 89 unsigned int sysp, const char *to_file, unsigned int to_line)
d82fc108
NB
90{
91 struct line_map *map;
12f9df4e 92 source_location start_location = set->highest_location + 1;
d82fc108 93
12f9df4e 94 if (set->used && start_location < set->maps[set->used - 1].start_location)
d82fc108
NB
95 abort ();
96
97 if (set->used == set->allocated)
98 {
99 set->allocated = 2 * set->allocated + 256;
703ad42b 100 set->maps = xrealloc (set->maps, set->allocated * sizeof (struct line_map));
d82fc108
NB
101 }
102
9132fbb7 103 map = &set->maps[set->used];
d82fc108 104
9074464c
GK
105 if (to_file && *to_file == '\0')
106 to_file = "<stdin>";
107
fde84349
NB
108 /* If we don't keep our line maps consistent, we can easily
109 segfault. Don't rely on the client to do it for us. */
d8693c6f 110 if (set->depth == 0)
fde84349
NB
111 reason = LC_ENTER;
112 else if (reason == LC_LEAVE)
113 {
47d89cf3
NB
114 struct line_map *from;
115 bool error;
116
117 if (MAIN_FILE_P (map - 1))
fde84349 118 {
b3147029
PB
119 if (to_file == NULL)
120 {
121 set->depth--;
b3147029
PB
122 return NULL;
123 }
124 error = true;
125 reason = LC_RENAME;
126 from = map - 1;
47d89cf3
NB
127 }
128 else
129 {
130 from = INCLUDED_FROM (set, map - 1);
131 error = to_file && strcmp (from->to_file, to_file);
132 }
133
134 /* Depending upon whether we are handling preprocessed input or
135 not, this can be a user error or an ICE. */
136 if (error)
137 fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
138 to_file);
139
140 /* A TO_FILE of NULL is special - we use the natural values. */
141 if (error || to_file == NULL)
142 {
143 to_file = from->to_file;
12f9df4e 144 to_line = SOURCE_LINE (from, from[1].start_location);
47d89cf3 145 sysp = from->sysp;
fde84349
NB
146 }
147 }
148
47d89cf3
NB
149 map->reason = reason;
150 map->sysp = sysp;
12f9df4e 151 map->start_location = start_location;
47d89cf3
NB
152 map->to_file = to_file;
153 map->to_line = to_line;
9132fbb7 154 set->cache = set->used++;
12f9df4e
PB
155 map->column_bits = 0;
156 set->highest_location = start_location;
157 set->max_column_hint = 0;
47d89cf3 158
fde84349 159 if (reason == LC_ENTER)
d8693c6f 160 {
8826ff0f 161 map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
d8693c6f 162 set->depth++;
d8693c6f
NB
163 if (set->trace_includes)
164 trace_include (set, map);
165 }
d82fc108
NB
166 else if (reason == LC_RENAME)
167 map->included_from = map[-1].included_from;
168 else if (reason == LC_LEAVE)
d8693c6f
NB
169 {
170 set->depth--;
171 map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
172 }
5993019d 173
d82fc108
NB
174 return map;
175}
176
12f9df4e
PB
177source_location
178linemap_line_start (struct line_maps *set, unsigned int to_line,
179 unsigned int max_column_hint)
180{
181 struct line_map *map = &set->maps[set->used - 1];
182 source_location highest = set->highest_location;
183 source_location r;
184 unsigned int last_line = SOURCE_LINE (map, highest);
185 int line_delta = to_line - last_line;
186 bool add_map = false;
187 if (line_delta < 0
188 || (line_delta > 10 && line_delta * map->column_bits > 1000)
189 || (max_column_hint >= (1U << map->column_bits))
190 || (max_column_hint <= 80 && map->column_bits >= 10))
191 {
192 add_map = true;
193 }
194 else
195 max_column_hint = set->max_column_hint;
196 if (add_map)
197 {
198 int column_bits;
199 if (max_column_hint > 1000000 || highest > 0xC0000000)
200 {
201 max_column_hint = 0;
202 if (highest >0xF0000000)
203 return 0;
204 column_bits = 0;
205 }
206 else
207 {
208 column_bits = 7;
209 while (max_column_hint >= (1U << column_bits))
210 column_bits++;
211 max_column_hint = 1U << column_bits;
212 }
213 if (line_delta < 0
214 || last_line != map->to_line
215 || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
216 map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
217 map->to_file, to_line);
218 map->column_bits = column_bits;
219 r = map->start_location;
220 }
221 else
222 r = highest - SOURCE_COLUMN (map, highest)
223 + (line_delta << map->column_bits);
224 if (r > set->highest_location)
225 set->highest_location = r;
226 set->max_column_hint = max_column_hint;
227 return r;
228}
229
6604e6f3
NB
230/* Given a logical line, returns the map from which the corresponding
231 (source file, line) pair can be deduced. Since the set is built
232 chronologically, the logical lines are monotonic increasing, and so
233 the list is sorted and we can use a binary search. */
d82fc108 234
47d89cf3 235const struct line_map *
7d40b45f 236linemap_lookup (struct line_maps *set, source_location line)
d82fc108 237{
9132fbb7
PB
238 unsigned int md, mn, mx;
239 const struct line_map *cached;
240
241 mn = set->cache;
242 mx = set->used;
243
244 cached = &set->maps[mn];
9ac97460 245 /* We should get a segfault if no line_maps have been added yet. */
12f9df4e 246 if (line >= cached->start_location)
9132fbb7 247 {
12f9df4e 248 if (mn + 1 == mx || line < cached[1].start_location)
9132fbb7
PB
249 return cached;
250 }
251 else
252 {
253 mx = mn;
254 mn = 0;
255 }
d82fc108
NB
256
257 while (mx - mn > 1)
258 {
259 md = (mn + mx) / 2;
12f9df4e 260 if (set->maps[md].start_location > line)
d82fc108
NB
261 mx = md;
262 else
263 mn = md;
264 }
265
9132fbb7 266 set->cache = mn;
d82fc108
NB
267 return &set->maps[mn];
268}
fde84349
NB
269
270/* Print the file names and line numbers of the #include commands
271 which led to the map MAP, if any, to stderr. Nothing is output if
272 the most recently listed stack is the same as the current one. */
273
274void
a2f7be91
ZW
275linemap_print_containing_files (struct line_maps *set,
276 const struct line_map *map)
fde84349
NB
277{
278 if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
279 return;
280
281 set->last_listed = map->included_from;
282 map = INCLUDED_FROM (set, map);
283
284 fprintf (stderr, _("In file included from %s:%u"),
285 map->to_file, LAST_SOURCE_LINE (map));
286
287 while (! MAIN_FILE_P (map))
288 {
289 map = INCLUDED_FROM (set, map);
290 /* Translators note: this message is used in conjunction
291 with "In file included from %s:%ld" and some other
292 tricks. We want something like this:
293
294 | In file included from sys/select.h:123,
295 | from sys/types.h:234,
296 | from userfile.c:31:
297 | bits/select.h:45: <error message here>
298
299 with all the "from"s lined up.
300 The trailing comma is at the beginning of this message,
301 and the trailing colon is not translated. */
302 fprintf (stderr, _(",\n from %s:%u"),
303 map->to_file, LAST_SOURCE_LINE (map));
304 }
305
306 fputs (":\n", stderr);
307}
5993019d
NB
308
309/* Print an include trace, for e.g. the -H option of the preprocessor. */
310
311static void
e2b9853b 312trace_include (const struct line_maps *set, const struct line_map *map)
5993019d 313{
d8693c6f 314 unsigned int i = set->depth;
5993019d 315
d8693c6f 316 while (--i)
5993019d
NB
317 putc ('.', stderr);
318 fprintf (stderr, " %s\n", map->to_file);
319}