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