]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/line-map.c
fix changelog entry
[thirdparty/gcc.git] / gcc / line-map.c
CommitLineData
38692459 1/* Map logical line numbers to (source file, line number) pairs.
a8349c62 2 Copyright (C) 2001, 2003, 2004
38692459 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"
bd507c05 26#include "intl.h"
38692459 27
6d0a3bf2 28static void trace_include (const struct line_maps *, const struct line_map *);
438ac94c 29
38692459 30/* Initialize a line map set. */
31
32void
196ce2be 33linemap_init (struct line_maps *set)
38692459 34{
088db31b 35 set->maps = NULL;
38692459 36 set->allocated = 0;
37 set->used = 0;
bd507c05 38 set->last_listed = -1;
438ac94c 39 set->trace_includes = false;
4087823d 40 set->depth = 0;
088db31b 41 set->cache = 0;
38692459 42}
43
44/* Free a line map set. */
45
bd507c05 46void
196ce2be 47linemap_free (struct line_maps *set)
38692459 48{
49 if (set->maps)
bd507c05 50 {
bd507c05 51 struct line_map *map;
52
f85fcf2b 53 /* Depending upon whether we are handling preprocessed input or
54 not, this can be a user error or an ICE. */
bd507c05 55 for (map = CURRENT_LINE_MAP (set); ! MAIN_FILE_P (map);
56 map = INCLUDED_FROM (set, map))
57 fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
58 map->to_file);
f85fcf2b 59
bd507c05 60 free (set->maps);
61 }
38692459 62}
63
64/* Add a mapping of logical source line to physical source file and
748b50a3 65 line number.
66
67 The text pointed to by TO_FILE must have a lifetime
68 at least as long as the final call to lookup_line (). An empty
69 TO_FILE means standard input. If reason is LC_LEAVE, and
70 TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
71 natural values considering the file we are returning to.
38692459 72
73 FROM_LINE should be monotonic increasing across calls to this
748b50a3 74 function. A call to this function can relocate the previous set of
75 maps, so any stored line_map pointers should not be used. */
38692459 76
f85fcf2b 77const struct line_map *
196ce2be 78linemap_add (struct line_maps *set, enum lc_reason reason,
fd3638df 79 unsigned int sysp, source_location from_line,
196ce2be 80 const char *to_file, unsigned int to_line)
38692459 81{
82 struct line_map *map;
83
84 if (set->used && from_line < set->maps[set->used - 1].from_line)
85 abort ();
86
87 if (set->used == set->allocated)
88 {
89 set->allocated = 2 * set->allocated + 256;
f0af5a88 90 set->maps = xrealloc (set->maps, set->allocated * sizeof (struct line_map));
38692459 91 }
92
088db31b 93 map = &set->maps[set->used];
38692459 94
748b50a3 95 if (to_file && *to_file == '\0')
96 to_file = "<stdin>";
97
bd507c05 98 /* If we don't keep our line maps consistent, we can easily
99 segfault. Don't rely on the client to do it for us. */
4087823d 100 if (set->depth == 0)
bd507c05 101 reason = LC_ENTER;
102 else if (reason == LC_LEAVE)
103 {
f85fcf2b 104 struct line_map *from;
105 bool error;
106
107 if (MAIN_FILE_P (map - 1))
bd507c05 108 {
4d1574ae 109 if (to_file == NULL)
110 {
111 set->depth--;
4d1574ae 112 return NULL;
113 }
114 error = true;
115 reason = LC_RENAME;
116 from = map - 1;
f85fcf2b 117 }
118 else
119 {
120 from = INCLUDED_FROM (set, map - 1);
121 error = to_file && strcmp (from->to_file, to_file);
122 }
123
124 /* Depending upon whether we are handling preprocessed input or
125 not, this can be a user error or an ICE. */
126 if (error)
127 fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
128 to_file);
129
130 /* A TO_FILE of NULL is special - we use the natural values. */
131 if (error || to_file == NULL)
132 {
133 to_file = from->to_file;
134 to_line = LAST_SOURCE_LINE (from) + 1;
135 sysp = from->sysp;
bd507c05 136 }
137 }
138
f85fcf2b 139 map->reason = reason;
140 map->sysp = sysp;
141 map->from_line = from_line;
142 map->to_file = to_file;
143 map->to_line = to_line;
088db31b 144 set->cache = set->used++;
f85fcf2b 145
bd507c05 146 if (reason == LC_ENTER)
4087823d 147 {
e9f0d687 148 map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
4087823d 149 set->depth++;
4087823d 150 if (set->trace_includes)
151 trace_include (set, map);
152 }
38692459 153 else if (reason == LC_RENAME)
154 map->included_from = map[-1].included_from;
155 else if (reason == LC_LEAVE)
4087823d 156 {
157 set->depth--;
158 map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
159 }
438ac94c 160
38692459 161 return map;
162}
163
a98af3e0 164/* Given a logical line, returns the map from which the corresponding
165 (source file, line) pair can be deduced. Since the set is built
166 chronologically, the logical lines are monotonic increasing, and so
167 the list is sorted and we can use a binary search. */
38692459 168
f85fcf2b 169const struct line_map *
fd3638df 170linemap_lookup (struct line_maps *set, source_location line)
38692459 171{
088db31b 172 unsigned int md, mn, mx;
173 const struct line_map *cached;
174
175 mn = set->cache;
176 mx = set->used;
177
178 cached = &set->maps[mn];
179 /* We should get a segfault if no line_maps have been added yet. */
180 if (line >= cached->from_line)
181 {
182 if (mn + 1 == mx || line < cached[1].from_line)
183 return cached;
184 }
185 else
186 {
187 mx = mn;
188 mn = 0;
189 }
38692459 190
191 while (mx - mn > 1)
192 {
193 md = (mn + mx) / 2;
194 if (set->maps[md].from_line > line)
195 mx = md;
196 else
197 mn = md;
198 }
199
088db31b 200 set->cache = mn;
38692459 201 return &set->maps[mn];
202}
bd507c05 203
204/* Print the file names and line numbers of the #include commands
205 which led to the map MAP, if any, to stderr. Nothing is output if
206 the most recently listed stack is the same as the current one. */
207
208void
196ce2be 209linemap_print_containing_files (struct line_maps *set,
210 const struct line_map *map)
bd507c05 211{
212 if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
213 return;
214
215 set->last_listed = map->included_from;
216 map = INCLUDED_FROM (set, map);
217
218 fprintf (stderr, _("In file included from %s:%u"),
219 map->to_file, LAST_SOURCE_LINE (map));
220
221 while (! MAIN_FILE_P (map))
222 {
223 map = INCLUDED_FROM (set, map);
224 /* Translators note: this message is used in conjunction
225 with "In file included from %s:%ld" and some other
226 tricks. We want something like this:
227
228 | In file included from sys/select.h:123,
229 | from sys/types.h:234,
230 | from userfile.c:31:
231 | bits/select.h:45: <error message here>
232
233 with all the "from"s lined up.
234 The trailing comma is at the beginning of this message,
235 and the trailing colon is not translated. */
236 fprintf (stderr, _(",\n from %s:%u"),
237 map->to_file, LAST_SOURCE_LINE (map));
238 }
239
240 fputs (":\n", stderr);
241}
438ac94c 242
243/* Print an include trace, for e.g. the -H option of the preprocessor. */
244
245static void
6d0a3bf2 246trace_include (const struct line_maps *set, const struct line_map *map)
438ac94c 247{
4087823d 248 unsigned int i = set->depth;
438ac94c 249
4087823d 250 while (--i)
438ac94c 251 putc ('.', stderr);
252 fprintf (stderr, " %s\n", map->to_file);
253}