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