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