xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gprof/source.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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