2000-07-24 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
[deliverable/binutils-gdb.git] / gprof / source.c
CommitLineData
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 */
15bool create_annotation_files = FALSE;
16
17Search_List src_search_list =
18{0, 0};
19Source_File *first_src_file = 0;
20
21
22Source_File *
23DEFUN (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
48Source_File *
49DEFUN (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
79FILE *
80DEFUN (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, '\\');
2ab47eed 119 if (name_only == NULL || (bslash != NULL && bslash > name_only))
5af11cab
AM
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, '\\');
2ab47eed 177 if (filename == NULL || (bslash != NULL && bslash > filename))
5af11cab
AM
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}
This page took 0.056432 seconds and 4 git commands to generate.