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