1b55d4692Sfgsch /* source.c - Keep track of source files.
2b55d4692Sfgsch
3*c074d1c9Sdrahn Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
4b55d4692Sfgsch
5b55d4692Sfgsch This file is part of GNU Binutils.
6b55d4692Sfgsch
7b55d4692Sfgsch This program is free software; you can redistribute it and/or modify
8b55d4692Sfgsch it under the terms of the GNU General Public License as published by
9b55d4692Sfgsch the Free Software Foundation; either version 2 of the License, or
10b55d4692Sfgsch (at your option) any later version.
11b55d4692Sfgsch
12b55d4692Sfgsch This program is distributed in the hope that it will be useful,
13b55d4692Sfgsch but WITHOUT ANY WARRANTY; without even the implied warranty of
14b55d4692Sfgsch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15b55d4692Sfgsch GNU General Public License for more details.
16b55d4692Sfgsch
17b55d4692Sfgsch You should have received a copy of the GNU General Public License
18b55d4692Sfgsch along with this program; if not, write to the Free Software
19b55d4692Sfgsch Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20b55d4692Sfgsch 02111-1307, USA. */
21b55d4692Sfgsch
222159047fSniklas #include "gprof.h"
232159047fSniklas #include "libiberty.h"
24b305b0f1Sespie #include "filenames.h"
252159047fSniklas #include "search_list.h"
262159047fSniklas #include "source.h"
272159047fSniklas
28b55d4692Sfgsch #define EXT_ANNO "-ann" /* Postfix of annotated files. */
292159047fSniklas
30b55d4692Sfgsch /* Default option values. */
31*c074d1c9Sdrahn bfd_boolean create_annotation_files = FALSE;
322159047fSniklas
33b55d4692Sfgsch Search_List src_search_list = {0, 0};
342159047fSniklas Source_File *first_src_file = 0;
352159047fSniklas
362159047fSniklas
372159047fSniklas Source_File *
source_file_lookup_path(path)38*c074d1c9Sdrahn source_file_lookup_path (path)
39*c074d1c9Sdrahn const char *path;
402159047fSniklas {
412159047fSniklas Source_File *sf;
422159047fSniklas
432159047fSniklas for (sf = first_src_file; sf; sf = sf->next)
442159047fSniklas {
45b305b0f1Sespie if (FILENAME_CMP (path, sf->name) == 0)
462159047fSniklas break;
472159047fSniklas }
48b55d4692Sfgsch
492159047fSniklas if (!sf)
502159047fSniklas {
51b55d4692Sfgsch /* Create a new source file descriptor. */
522159047fSniklas sf = (Source_File *) xmalloc (sizeof (*sf));
53b55d4692Sfgsch
542159047fSniklas memset (sf, 0, sizeof (*sf));
55b55d4692Sfgsch
564361b62eSniklas sf->name = xstrdup (path);
572159047fSniklas sf->next = first_src_file;
582159047fSniklas first_src_file = sf;
592159047fSniklas }
60b55d4692Sfgsch
612159047fSniklas return sf;
622159047fSniklas }
632159047fSniklas
642159047fSniklas
652159047fSniklas Source_File *
source_file_lookup_name(filename)66*c074d1c9Sdrahn source_file_lookup_name (filename)
67*c074d1c9Sdrahn const char *filename;
682159047fSniklas {
692159047fSniklas const char *fname;
702159047fSniklas Source_File *sf;
71b55d4692Sfgsch
72b55d4692Sfgsch /* The user cannot know exactly how a filename will be stored in
73b55d4692Sfgsch the debugging info (e.g., ../include/foo.h
74b55d4692Sfgsch vs. /usr/include/foo.h). So we simply compare the filename
75b55d4692Sfgsch component of a path only. */
762159047fSniklas for (sf = first_src_file; sf; sf = sf->next)
772159047fSniklas {
782159047fSniklas fname = strrchr (sf->name, '/');
79b55d4692Sfgsch
802159047fSniklas if (fname)
812159047fSniklas ++fname;
822159047fSniklas else
832159047fSniklas fname = sf->name;
84b55d4692Sfgsch
85b305b0f1Sespie if (FILENAME_CMP (filename, fname) == 0)
862159047fSniklas break;
872159047fSniklas }
88b55d4692Sfgsch
892159047fSniklas return sf;
902159047fSniklas }
912159047fSniklas
922159047fSniklas
932159047fSniklas FILE *
annotate_source(sf,max_width,annote,arg)94*c074d1c9Sdrahn annotate_source (sf, max_width, annote, arg)
95*c074d1c9Sdrahn Source_File *sf;
96*c074d1c9Sdrahn unsigned int max_width;
97*c074d1c9Sdrahn void (*annote) PARAMS ((char *, unsigned int, int, void *));
98*c074d1c9Sdrahn void *arg;
992159047fSniklas {
100*c074d1c9Sdrahn static bfd_boolean first_file = TRUE;
1012159047fSniklas int i, line_num, nread;
102*c074d1c9Sdrahn bfd_boolean new_line;
1032159047fSniklas char buf[8192];
1042159047fSniklas char fname[PATH_MAX];
1052159047fSniklas char *annotation, *name_only;
1062159047fSniklas FILE *ifp, *ofp;
1072159047fSniklas Search_List_Elem *sle = src_search_list.head;
1082159047fSniklas
109b55d4692Sfgsch /* Open input file. If open fails, walk along search-list until
110b55d4692Sfgsch open succeeds or reaching end of list. */
1112159047fSniklas strcpy (fname, sf->name);
112b55d4692Sfgsch
113b305b0f1Sespie if (IS_ABSOLUTE_PATH (sf->name))
114b55d4692Sfgsch sle = 0; /* Don't use search list for absolute paths. */
115b55d4692Sfgsch
1162159047fSniklas name_only = 0;
1172159047fSniklas while (TRUE)
1182159047fSniklas {
1192159047fSniklas DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
1202159047fSniklas sf->name, fname));
121b55d4692Sfgsch
1222159047fSniklas ifp = fopen (fname, FOPEN_RB);
1232159047fSniklas if (ifp)
1242159047fSniklas break;
125b55d4692Sfgsch
1262159047fSniklas if (!sle && !name_only)
1272159047fSniklas {
1282159047fSniklas name_only = strrchr (sf->name, '/');
129b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
130b305b0f1Sespie {
131b305b0f1Sespie char *bslash = strrchr (sf->name, '\\');
132b55d4692Sfgsch if (name_only == NULL || (bslash != NULL && bslash > name_only))
133b305b0f1Sespie name_only = bslash;
134b305b0f1Sespie if (name_only == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
135b305b0f1Sespie name_only = (char *)sf->name + 1;
136b305b0f1Sespie }
137b305b0f1Sespie #endif
1382159047fSniklas if (name_only)
1392159047fSniklas {
140b55d4692Sfgsch /* Try search-list again, but this time with name only. */
1412159047fSniklas ++name_only;
1422159047fSniklas sle = src_search_list.head;
1432159047fSniklas }
1442159047fSniklas }
145b55d4692Sfgsch
1462159047fSniklas if (sle)
1472159047fSniklas {
1482159047fSniklas strcpy (fname, sle->path);
149b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
150b305b0f1Sespie /* d:foo is not the same thing as d:/foo! */
151b305b0f1Sespie if (fname[strlen (fname) - 1] == ':')
152b305b0f1Sespie strcat (fname, ".");
153b305b0f1Sespie #endif
1542159047fSniklas strcat (fname, "/");
155b55d4692Sfgsch
1562159047fSniklas if (name_only)
1572159047fSniklas strcat (fname, name_only);
1582159047fSniklas else
1592159047fSniklas strcat (fname, sf->name);
160b55d4692Sfgsch
1612159047fSniklas sle = sle->next;
1622159047fSniklas }
1632159047fSniklas else
1642159047fSniklas {
1652159047fSniklas if (errno == ENOENT)
166b305b0f1Sespie fprintf (stderr, _("%s: could not locate `%s'\n"),
1672159047fSniklas whoami, sf->name);
1682159047fSniklas else
1692159047fSniklas perror (sf->name);
170b55d4692Sfgsch
1712159047fSniklas return 0;
1722159047fSniklas }
1732159047fSniklas }
1742159047fSniklas
1752159047fSniklas ofp = stdout;
176b55d4692Sfgsch
1772159047fSniklas if (create_annotation_files)
1782159047fSniklas {
179b55d4692Sfgsch /* Try to create annotated source file. */
1802159047fSniklas const char *filename;
1812159047fSniklas
182b55d4692Sfgsch /* Create annotation files in the current working directory. */
1832159047fSniklas filename = strrchr (sf->name, '/');
184b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
185b305b0f1Sespie {
186b305b0f1Sespie char *bslash = strrchr (sf->name, '\\');
187b55d4692Sfgsch if (filename == NULL || (bslash != NULL && bslash > filename))
188b305b0f1Sespie filename = bslash;
189b305b0f1Sespie if (filename == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
190b305b0f1Sespie filename = sf->name + 1;
191b305b0f1Sespie }
192b305b0f1Sespie #endif
1932159047fSniklas if (filename)
1942159047fSniklas ++filename;
1952159047fSniklas else
1962159047fSniklas filename = sf->name;
1972159047fSniklas
1982159047fSniklas strcpy (fname, filename);
1992159047fSniklas strcat (fname, EXT_ANNO);
200b305b0f1Sespie #ifdef __MSDOS__
201b305b0f1Sespie {
202b305b0f1Sespie /* foo.cpp-ann can overwrite foo.cpp due to silent truncation of
203b305b0f1Sespie file names on 8+3 filesystems. Their `stat' better be good... */
204b305b0f1Sespie struct stat buf1, buf2;
205b305b0f1Sespie
206b305b0f1Sespie if (stat (filename, &buf1) == 0
207b305b0f1Sespie && stat (fname, &buf2) == 0
208b305b0f1Sespie && buf1.st_ino == buf2.st_ino)
209b305b0f1Sespie {
210b305b0f1Sespie char *dot = strrchr (fname, '.');
211b305b0f1Sespie
212b305b0f1Sespie if (dot)
213b305b0f1Sespie *dot = '\0';
214b305b0f1Sespie strcat (fname, ".ann");
215b305b0f1Sespie }
216b305b0f1Sespie }
217b305b0f1Sespie #endif
2182159047fSniklas ofp = fopen (fname, "w");
219b55d4692Sfgsch
2202159047fSniklas if (!ofp)
2212159047fSniklas {
2222159047fSniklas perror (fname);
2232159047fSniklas return 0;
2242159047fSniklas }
2252159047fSniklas }
2262159047fSniklas
227b55d4692Sfgsch /* Print file names if output goes to stdout
228b55d4692Sfgsch and there are more than one source file. */
2292159047fSniklas if (ofp == stdout)
2302159047fSniklas {
2312159047fSniklas if (first_file)
2322159047fSniklas first_file = FALSE;
2332159047fSniklas else
2342159047fSniklas fputc ('\n', ofp);
235b55d4692Sfgsch
2362159047fSniklas if (first_output)
2372159047fSniklas first_output = FALSE;
2382159047fSniklas else
2392159047fSniklas fprintf (ofp, "\f\n");
240b55d4692Sfgsch
241b305b0f1Sespie fprintf (ofp, _("*** File %s:\n"), sf->name);
2422159047fSniklas }
2432159047fSniklas
2442159047fSniklas annotation = xmalloc (max_width + 1);
2452159047fSniklas line_num = 1;
2462159047fSniklas new_line = TRUE;
247b55d4692Sfgsch
2482159047fSniklas while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
2492159047fSniklas {
2502159047fSniklas for (i = 0; i < nread; ++i)
2512159047fSniklas {
2522159047fSniklas if (new_line)
2532159047fSniklas {
2542159047fSniklas (*annote) (annotation, max_width, line_num, arg);
2552159047fSniklas fputs (annotation, ofp);
2562159047fSniklas ++line_num;
2572159047fSniklas new_line = FALSE;
2582159047fSniklas }
259b55d4692Sfgsch
2602159047fSniklas new_line = (buf[i] == '\n');
2612159047fSniklas fputc (buf[i], ofp);
2622159047fSniklas }
2632159047fSniklas }
264b55d4692Sfgsch
2652159047fSniklas free (annotation);
2662159047fSniklas return ofp;
2672159047fSniklas }
268