Commit | Line | Data |
---|---|---|
ef368dac NC |
1 | /* source.c - Keep track of source files. |
2 | ||
651dbc76 | 3 | Copyright 2000, 2001, 2002, 2004, 2007 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. */ |
b34976b6 | 31 | bfd_boolean 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 | { |
b34976b6 | 96 | static bfd_boolean first_file = TRUE; |
252b5132 | 97 | int i, line_num, nread; |
b34976b6 | 98 | bfd_boolean new_line; |
252b5132 RH |
99 | char buf[8192]; |
100 | char fname[PATH_MAX]; | |
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. */ | |
252b5132 | 107 | strcpy (fname, 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; |
b34976b6 | 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 RH |
118 | ifp = fopen (fname, FOPEN_RB); |
119 | if (ifp) | |
ef368dac NC |
120 | break; |
121 | ||
252b5132 RH |
122 | if (!sle && !name_only) |
123 | { | |
124 | name_only = strrchr (sf->name, '/'); | |
5af11cab AM |
125 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
126 | { | |
127 | char *bslash = strrchr (sf->name, '\\'); | |
2ab47eed | 128 | if (name_only == NULL || (bslash != NULL && bslash > name_only)) |
5af11cab AM |
129 | name_only = bslash; |
130 | if (name_only == NULL && sf->name[0] != '\0' && sf->name[1] == ':') | |
131 | name_only = (char *)sf->name + 1; | |
132 | } | |
133 | #endif | |
252b5132 RH |
134 | if (name_only) |
135 | { | |
ef368dac | 136 | /* Try search-list again, but this time with name only. */ |
252b5132 RH |
137 | ++name_only; |
138 | sle = src_search_list.head; | |
139 | } | |
140 | } | |
0eee5820 | 141 | |
252b5132 RH |
142 | if (sle) |
143 | { | |
144 | strcpy (fname, sle->path); | |
5af11cab AM |
145 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
146 | /* d:foo is not the same thing as d:/foo! */ | |
147 | if (fname[strlen (fname) - 1] == ':') | |
148 | strcat (fname, "."); | |
149 | #endif | |
252b5132 | 150 | strcat (fname, "/"); |
0eee5820 | 151 | |
252b5132 | 152 | if (name_only) |
ef368dac | 153 | strcat (fname, name_only); |
252b5132 | 154 | else |
ef368dac NC |
155 | strcat (fname, sf->name); |
156 | ||
252b5132 RH |
157 | sle = sle->next; |
158 | } | |
159 | else | |
160 | { | |
161 | if (errno == ENOENT) | |
ef368dac NC |
162 | fprintf (stderr, _("%s: could not locate `%s'\n"), |
163 | whoami, sf->name); | |
252b5132 | 164 | else |
ef368dac NC |
165 | perror (sf->name); |
166 | ||
252b5132 RH |
167 | return 0; |
168 | } | |
169 | } | |
170 | ||
171 | ofp = stdout; | |
0eee5820 | 172 | |
252b5132 RH |
173 | if (create_annotation_files) |
174 | { | |
ef368dac | 175 | /* Try to create annotated source file. */ |
252b5132 RH |
176 | const char *filename; |
177 | ||
ef368dac | 178 | /* Create annotation files in the current working directory. */ |
252b5132 | 179 | filename = strrchr (sf->name, '/'); |
5af11cab AM |
180 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM |
181 | { | |
182 | char *bslash = strrchr (sf->name, '\\'); | |
2ab47eed | 183 | if (filename == NULL || (bslash != NULL && bslash > filename)) |
5af11cab AM |
184 | filename = bslash; |
185 | if (filename == NULL && sf->name[0] != '\0' && sf->name[1] == ':') | |
186 | filename = sf->name + 1; | |
187 | } | |
188 | #endif | |
252b5132 | 189 | if (filename) |
ef368dac | 190 | ++filename; |
252b5132 | 191 | else |
ef368dac | 192 | filename = sf->name; |
252b5132 RH |
193 | |
194 | strcpy (fname, filename); | |
195 | strcat (fname, EXT_ANNO); | |
5af11cab AM |
196 | #ifdef __MSDOS__ |
197 | { | |
198 | /* foo.cpp-ann can overwrite foo.cpp due to silent truncation of | |
199 | file names on 8+3 filesystems. Their `stat' better be good... */ | |
200 | struct stat buf1, buf2; | |
201 | ||
202 | if (stat (filename, &buf1) == 0 | |
203 | && stat (fname, &buf2) == 0 | |
204 | && buf1.st_ino == buf2.st_ino) | |
205 | { | |
206 | char *dot = strrchr (fname, '.'); | |
207 | ||
208 | if (dot) | |
209 | *dot = '\0'; | |
210 | strcat (fname, ".ann"); | |
211 | } | |
212 | } | |
213 | #endif | |
252b5132 | 214 | ofp = fopen (fname, "w"); |
0eee5820 | 215 | |
252b5132 RH |
216 | if (!ofp) |
217 | { | |
218 | perror (fname); | |
219 | return 0; | |
220 | } | |
221 | } | |
222 | ||
ef368dac NC |
223 | /* Print file names if output goes to stdout |
224 | and there are more than one source file. */ | |
252b5132 RH |
225 | if (ofp == stdout) |
226 | { | |
227 | if (first_file) | |
b34976b6 | 228 | first_file = FALSE; |
252b5132 | 229 | else |
ef368dac NC |
230 | fputc ('\n', ofp); |
231 | ||
252b5132 | 232 | if (first_output) |
b34976b6 | 233 | first_output = FALSE; |
252b5132 | 234 | else |
ef368dac NC |
235 | fprintf (ofp, "\f\n"); |
236 | ||
252b5132 RH |
237 | fprintf (ofp, _("*** File %s:\n"), sf->name); |
238 | } | |
239 | ||
1e9cc1c2 | 240 | annotation = (char *) xmalloc (max_width + 1); |
252b5132 | 241 | line_num = 1; |
b34976b6 | 242 | new_line = TRUE; |
0eee5820 | 243 | |
252b5132 RH |
244 | while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0) |
245 | { | |
246 | for (i = 0; i < nread; ++i) | |
247 | { | |
248 | if (new_line) | |
249 | { | |
250 | (*annote) (annotation, max_width, line_num, arg); | |
251 | fputs (annotation, ofp); | |
252 | ++line_num; | |
b34976b6 | 253 | new_line = FALSE; |
252b5132 | 254 | } |
0eee5820 | 255 | |
252b5132 RH |
256 | new_line = (buf[i] == '\n'); |
257 | fputc (buf[i], ofp); | |
258 | } | |
259 | } | |
0eee5820 | 260 | |
252b5132 RH |
261 | free (annotation); |
262 | return ofp; | |
263 | } |