2000-06-07 Philippe De Muyter <phdm@macqel.be>
[deliverable/binutils-gdb.git] / gprof / source.c
1 /*
2 * Keeps track of source files.
3 */
4 #include "gprof.h"
5 #include "libiberty.h"
6 #include "filenames.h"
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 {
29 if (FILENAME_CMP (path, sf->name) == 0)
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 }
70 if (FILENAME_CMP (filename, fname) == 0)
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);
99 if (IS_ABSOLUTE_PATH (sf->name))
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, '/');
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
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);
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
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, '/');
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
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);
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
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 }
This page took 0.053849 seconds and 5 git commands to generate.