Commit | Line | Data |
---|---|---|
ef368dac NC |
1 | /* source.c - Keep track of source files. |
2 | ||
250d07de | 3 | Copyright (C) 2000-2021 Free Software Foundation, Inc. |
ef368dac NC |
4 | |
5 | This file is part of GNU Binutils. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
651dbc76 | 9 | the Free Software Foundation; either version 3 of the License, or |
ef368dac NC |
10 | (at your option) any later version. |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
44eb1801 NC |
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
20 | 02110-1301, USA. */ | |
ef368dac | 21 | \f |
252b5132 RH |
22 | #include "gprof.h" |
23 | #include "libiberty.h" | |
5af11cab | 24 | #include "filenames.h" |
252b5132 RH |
25 | #include "search_list.h" |
26 | #include "source.h" | |
27 | ||
ef368dac | 28 | #define EXT_ANNO "-ann" /* Postfix of annotated files. */ |
252b5132 | 29 | |
ef368dac | 30 | /* Default option values. */ |
faa7a260 | 31 | bool create_annotation_files = false; |
252b5132 | 32 | |
ef368dac | 33 | Search_List src_search_list = {0, 0}; |
252b5132 RH |
34 | Source_File *first_src_file = 0; |
35 | ||
36 | ||
37 | Source_File * | |
3e8f6abf | 38 | source_file_lookup_path (const char *path) |
252b5132 RH |
39 | { |
40 | Source_File *sf; | |
41 | ||
42 | for (sf = first_src_file; sf; sf = sf->next) | |
43 | { | |
5af11cab | 44 | if (FILENAME_CMP (path, sf->name) == 0) |
ef368dac | 45 | break; |
252b5132 | 46 | } |
0eee5820 | 47 | |
252b5132 RH |
48 | if (!sf) |
49 | { | |
ef368dac | 50 | /* Create a new source file descriptor. */ |
252b5132 | 51 | sf = (Source_File *) xmalloc (sizeof (*sf)); |
0eee5820 | 52 | |
252b5132 | 53 | memset (sf, 0, sizeof (*sf)); |
0eee5820 | 54 | |
252b5132 RH |
55 | sf->name = xstrdup (path); |
56 | sf->next = first_src_file; | |
57 | first_src_file = sf; | |
58 | } | |
0eee5820 | 59 | |
252b5132 RH |
60 | return sf; |
61 | } | |
62 | ||
63 | ||
64 | Source_File * | |
3e8f6abf | 65 | source_file_lookup_name (const char *filename) |
252b5132 RH |
66 | { |
67 | const char *fname; | |
68 | Source_File *sf; | |
0eee5820 | 69 | |
ef368dac NC |
70 | /* The user cannot know exactly how a filename will be stored in |
71 | the debugging info (e.g., ../include/foo.h | |
72 | vs. /usr/include/foo.h). So we simply compare the filename | |
73 | component of a path only. */ | |
252b5132 RH |
74 | for (sf = first_src_file; sf; sf = sf->next) |
75 | { | |
76 | fname = strrchr (sf->name, '/'); | |
0eee5820 | 77 | |
252b5132 | 78 | if (fname) |
ef368dac | 79 | ++fname; |
252b5132 | 80 | else |
ef368dac NC |
81 | fname = sf->name; |
82 | ||
5af11cab | 83 | if (FILENAME_CMP (filename, fname) == 0) |
ef368dac | 84 | break; |
252b5132 | 85 | } |
0eee5820 | 86 | |
252b5132 RH |
87 | return sf; |
88 | } | |
89 | ||
90 | ||
91 | FILE * | |
3e8f6abf BE |
92 | annotate_source (Source_File *sf, unsigned int max_width, |
93 | void (*annote) (char *, unsigned int, int, void *), | |
94 | void *arg) | |
252b5132 | 95 | { |
faa7a260 | 96 | static bool first_file = true; |
252b5132 | 97 | int i, line_num, nread; |
faa7a260 | 98 | bool new_line; |
252b5132 | 99 | char buf[8192]; |
13acb58d | 100 | char *fname; |
252b5132 RH |
101 | char *annotation, *name_only; |
102 | FILE *ifp, *ofp; | |
103 | Search_List_Elem *sle = src_search_list.head; | |
104 | ||
ef368dac NC |
105 | /* Open input file. If open fails, walk along search-list until |
106 | open succeeds or reaching end of list. */ | |
13acb58d | 107 | fname = (char *) sf->name; |
0eee5820 | 108 | |
5af11cab | 109 | if (IS_ABSOLUTE_PATH (sf->name)) |
ef368dac NC |
110 | sle = 0; /* Don't use search list for absolute paths. */ |
111 | ||
252b5132 | 112 | name_only = 0; |
faa7a260 | 113 | while (true) |
252b5132 RH |
114 | { |
115 | DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n", | |
116 | sf->name, fname)); | |
0eee5820 | 117 | |
252b5132 | 118 | ifp = fopen (fname, FOPEN_RB); |
13acb58d AM |
119 | if (fname != sf->name) |
120 | free (fname); | |
252b5132 | 121 | if (ifp) |
ef368dac NC |
122 | break; |
123 | ||
252b5132 RH |
124 | if (!sle && !name_only) |
125 | { | |
126 | name_only = strrchr (sf->name, '/'); | |
5af11cab AM |
127 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
128 | { | |
129 | char *bslash = strrchr (sf->name, '\\'); | |
2ab47eed | 130 | if (name_only == NULL || (bslash != NULL && bslash > name_only)) |
5af11cab AM |
131 | name_only = bslash; |
132 | if (name_only == NULL && sf->name[0] != '\0' && sf->name[1] == ':') | |
133 | name_only = (char *)sf->name + 1; | |
134 | } | |
135 | #endif | |
252b5132 RH |
136 | if (name_only) |
137 | { | |
ef368dac | 138 | /* Try search-list again, but this time with name only. */ |
252b5132 RH |
139 | ++name_only; |
140 | sle = src_search_list.head; | |
141 | } | |
142 | } | |
0eee5820 | 143 | |
252b5132 RH |
144 | if (sle) |
145 | { | |
13acb58d AM |
146 | fname = xmalloc (strlen (sle->path) + 3 |
147 | + strlen (name_only ? name_only : sf->name)); | |
252b5132 | 148 | strcpy (fname, sle->path); |
5af11cab AM |
149 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
150 | /* d:foo is not the same thing as d:/foo! */ | |
151 | if (fname[strlen (fname) - 1] == ':') | |
152 | strcat (fname, "."); | |
153 | #endif | |
252b5132 | 154 | strcat (fname, "/"); |
0eee5820 | 155 | |
252b5132 | 156 | if (name_only) |
ef368dac | 157 | strcat (fname, name_only); |
252b5132 | 158 | else |
ef368dac NC |
159 | strcat (fname, sf->name); |
160 | ||
252b5132 RH |
161 | sle = sle->next; |
162 | } | |
163 | else | |
164 | { | |
165 | if (errno == ENOENT) | |
ef368dac NC |
166 | fprintf (stderr, _("%s: could not locate `%s'\n"), |
167 | whoami, sf->name); | |
252b5132 | 168 | else |
ef368dac NC |
169 | perror (sf->name); |
170 | ||
252b5132 RH |
171 | return 0; |
172 | } | |
173 | } | |
174 | ||
175 | ofp = stdout; | |
0eee5820 | 176 | |
252b5132 RH |
177 | if (create_annotation_files) |
178 | { | |
ef368dac | 179 | /* Try to create annotated source file. */ |
252b5132 RH |
180 | const char *filename; |
181 | ||
ef368dac | 182 | /* Create annotation files in the current working directory. */ |
252b5132 | 183 | filename = strrchr (sf->name, '/'); |
5af11cab AM |
184 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
185 | { | |
186 | char *bslash = strrchr (sf->name, '\\'); | |
2ab47eed | 187 | if (filename == NULL || (bslash != NULL && bslash > filename)) |
5af11cab AM |
188 | filename = bslash; |
189 | if (filename == NULL && sf->name[0] != '\0' && sf->name[1] == ':') | |
190 | filename = sf->name + 1; | |
191 | } | |
192 | #endif | |
252b5132 | 193 | if (filename) |
ef368dac | 194 | ++filename; |
252b5132 | 195 | else |
ef368dac | 196 | filename = sf->name; |
252b5132 | 197 | |
13acb58d | 198 | fname = xmalloc (strlen (filename) + strlen (EXT_ANNO) + 1); |
252b5132 RH |
199 | strcpy (fname, filename); |
200 | strcat (fname, EXT_ANNO); | |
5af11cab AM |
201 | #ifdef __MSDOS__ |
202 | { | |
203 | /* foo.cpp-ann can overwrite foo.cpp due to silent truncation of | |
204 | file names on 8+3 filesystems. Their `stat' better be good... */ | |
205 | struct stat buf1, buf2; | |
206 | ||
207 | if (stat (filename, &buf1) == 0 | |
208 | && stat (fname, &buf2) == 0 | |
209 | && buf1.st_ino == buf2.st_ino) | |
210 | { | |
211 | char *dot = strrchr (fname, '.'); | |
212 | ||
13acb58d AM |
213 | if (!dot) |
214 | dot = fname + strlen (filename); | |
215 | strcpy (dot, ".ann"); | |
5af11cab AM |
216 | } |
217 | } | |
218 | #endif | |
252b5132 | 219 | ofp = fopen (fname, "w"); |
0eee5820 | 220 | |
252b5132 RH |
221 | if (!ofp) |
222 | { | |
223 | perror (fname); | |
13acb58d | 224 | free (fname); |
252b5132 RH |
225 | return 0; |
226 | } | |
13acb58d | 227 | free (fname); |
252b5132 RH |
228 | } |
229 | ||
ef368dac NC |
230 | /* Print file names if output goes to stdout |
231 | and there are more than one source file. */ | |
252b5132 RH |
232 | if (ofp == stdout) |
233 | { | |
234 | if (first_file) | |
faa7a260 | 235 | first_file = false; |
252b5132 | 236 | else |
ef368dac NC |
237 | fputc ('\n', ofp); |
238 | ||
252b5132 | 239 | if (first_output) |
faa7a260 | 240 | first_output = false; |
252b5132 | 241 | else |
ef368dac NC |
242 | fprintf (ofp, "\f\n"); |
243 | ||
252b5132 RH |
244 | fprintf (ofp, _("*** File %s:\n"), sf->name); |
245 | } | |
246 | ||
1e9cc1c2 | 247 | annotation = (char *) xmalloc (max_width + 1); |
252b5132 | 248 | line_num = 1; |
faa7a260 | 249 | new_line = true; |
0eee5820 | 250 | |
252b5132 RH |
251 | while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0) |
252 | { | |
253 | for (i = 0; i < nread; ++i) | |
254 | { | |
255 | if (new_line) | |
256 | { | |
257 | (*annote) (annotation, max_width, line_num, arg); | |
258 | fputs (annotation, ofp); | |
259 | ++line_num; | |
252b5132 | 260 | } |
0eee5820 | 261 | |
252b5132 RH |
262 | new_line = (buf[i] == '\n'); |
263 | fputc (buf[i], ofp); | |
264 | } | |
265 | } | |
0eee5820 | 266 | |
252b5132 | 267 | free (annotation); |
5af84f93 | 268 | fclose (ifp); |
252b5132 RH |
269 | return ofp; |
270 | } |