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