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