12a6b7db3Sskrll /* source.c - Keep track of source files.
22a6b7db3Sskrll
3*cb63e24eSchristos Copyright (C) 2000-2024 Free Software Foundation, Inc.
42a6b7db3Sskrll
52a6b7db3Sskrll This file is part of GNU Binutils.
62a6b7db3Sskrll
72a6b7db3Sskrll This program is free software; you can redistribute it and/or modify
82a6b7db3Sskrll it under the terms of the GNU General Public License as published by
92a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or
102a6b7db3Sskrll (at your option) any later version.
112a6b7db3Sskrll
122a6b7db3Sskrll This program is distributed in the hope that it will be useful,
132a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
142a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152a6b7db3Sskrll GNU General Public License for more details.
162a6b7db3Sskrll
172a6b7db3Sskrll You should have received a copy of the GNU General Public License
182a6b7db3Sskrll along with this program; if not, write to the Free Software
192a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
202a6b7db3Sskrll 02110-1301, USA. */
212a6b7db3Sskrll
222a6b7db3Sskrll #include "gprof.h"
232a6b7db3Sskrll #include "libiberty.h"
242a6b7db3Sskrll #include "filenames.h"
252a6b7db3Sskrll #include "search_list.h"
262a6b7db3Sskrll #include "source.h"
272a6b7db3Sskrll
282a6b7db3Sskrll #define EXT_ANNO "-ann" /* Postfix of annotated files. */
292a6b7db3Sskrll
302a6b7db3Sskrll /* Default option values. */
314f645668Schristos bool create_annotation_files = false;
322a6b7db3Sskrll
332a6b7db3Sskrll Search_List src_search_list = {0, 0};
342a6b7db3Sskrll Source_File *first_src_file = 0;
352a6b7db3Sskrll
362a6b7db3Sskrll
372a6b7db3Sskrll Source_File *
source_file_lookup_path(const char * path)382a6b7db3Sskrll source_file_lookup_path (const char *path)
392a6b7db3Sskrll {
402a6b7db3Sskrll Source_File *sf;
412a6b7db3Sskrll
422a6b7db3Sskrll for (sf = first_src_file; sf; sf = sf->next)
432a6b7db3Sskrll {
442a6b7db3Sskrll if (FILENAME_CMP (path, sf->name) == 0)
452a6b7db3Sskrll break;
462a6b7db3Sskrll }
472a6b7db3Sskrll
482a6b7db3Sskrll if (!sf)
492a6b7db3Sskrll {
502a6b7db3Sskrll /* Create a new source file descriptor. */
512a6b7db3Sskrll sf = (Source_File *) xmalloc (sizeof (*sf));
522a6b7db3Sskrll
532a6b7db3Sskrll memset (sf, 0, sizeof (*sf));
542a6b7db3Sskrll
552a6b7db3Sskrll sf->name = xstrdup (path);
562a6b7db3Sskrll sf->next = first_src_file;
572a6b7db3Sskrll first_src_file = sf;
582a6b7db3Sskrll }
592a6b7db3Sskrll
602a6b7db3Sskrll return sf;
612a6b7db3Sskrll }
622a6b7db3Sskrll
632a6b7db3Sskrll
642a6b7db3Sskrll Source_File *
source_file_lookup_name(const char * filename)652a6b7db3Sskrll source_file_lookup_name (const char *filename)
662a6b7db3Sskrll {
672a6b7db3Sskrll const char *fname;
682a6b7db3Sskrll Source_File *sf;
692a6b7db3Sskrll
702a6b7db3Sskrll /* The user cannot know exactly how a filename will be stored in
712a6b7db3Sskrll the debugging info (e.g., ../include/foo.h
722a6b7db3Sskrll vs. /usr/include/foo.h). So we simply compare the filename
732a6b7db3Sskrll component of a path only. */
742a6b7db3Sskrll for (sf = first_src_file; sf; sf = sf->next)
752a6b7db3Sskrll {
762a6b7db3Sskrll fname = strrchr (sf->name, '/');
772a6b7db3Sskrll
782a6b7db3Sskrll if (fname)
792a6b7db3Sskrll ++fname;
802a6b7db3Sskrll else
812a6b7db3Sskrll fname = sf->name;
822a6b7db3Sskrll
832a6b7db3Sskrll if (FILENAME_CMP (filename, fname) == 0)
842a6b7db3Sskrll break;
852a6b7db3Sskrll }
862a6b7db3Sskrll
872a6b7db3Sskrll return sf;
882a6b7db3Sskrll }
892a6b7db3Sskrll
902a6b7db3Sskrll
912a6b7db3Sskrll FILE *
annotate_source(Source_File * sf,unsigned int max_width,void (* annote)(char *,unsigned int,int,void *),void * arg)922a6b7db3Sskrll annotate_source (Source_File *sf, unsigned int max_width,
932a6b7db3Sskrll void (*annote) (char *, unsigned int, int, void *),
942a6b7db3Sskrll void *arg)
952a6b7db3Sskrll {
964f645668Schristos static bool first_file = true;
972a6b7db3Sskrll int i, line_num, nread;
984f645668Schristos bool new_line;
992a6b7db3Sskrll char buf[8192];
1004f645668Schristos char *fname;
1012a6b7db3Sskrll char *annotation, *name_only;
1022a6b7db3Sskrll FILE *ifp, *ofp;
1032a6b7db3Sskrll Search_List_Elem *sle = src_search_list.head;
1042a6b7db3Sskrll
1052a6b7db3Sskrll /* Open input file. If open fails, walk along search-list until
1062a6b7db3Sskrll open succeeds or reaching end of list. */
1074f645668Schristos fname = (char *) sf->name;
1082a6b7db3Sskrll
1092a6b7db3Sskrll if (IS_ABSOLUTE_PATH (sf->name))
1102a6b7db3Sskrll sle = 0; /* Don't use search list for absolute paths. */
1112a6b7db3Sskrll
1122a6b7db3Sskrll name_only = 0;
1134f645668Schristos while (true)
1142a6b7db3Sskrll {
1152a6b7db3Sskrll DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
1162a6b7db3Sskrll sf->name, fname));
1172a6b7db3Sskrll
1182a6b7db3Sskrll ifp = fopen (fname, FOPEN_RB);
1194f645668Schristos if (fname != sf->name)
1204f645668Schristos free (fname);
1212a6b7db3Sskrll if (ifp)
1222a6b7db3Sskrll break;
1232a6b7db3Sskrll
1242a6b7db3Sskrll if (!sle && !name_only)
1252a6b7db3Sskrll {
1262a6b7db3Sskrll name_only = strrchr (sf->name, '/');
1272a6b7db3Sskrll #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1282a6b7db3Sskrll {
1292a6b7db3Sskrll char *bslash = strrchr (sf->name, '\\');
1302a6b7db3Sskrll if (name_only == NULL || (bslash != NULL && bslash > name_only))
1312a6b7db3Sskrll name_only = bslash;
1322a6b7db3Sskrll if (name_only == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
1332a6b7db3Sskrll name_only = (char *)sf->name + 1;
1342a6b7db3Sskrll }
1352a6b7db3Sskrll #endif
1362a6b7db3Sskrll if (name_only)
1372a6b7db3Sskrll {
1382a6b7db3Sskrll /* Try search-list again, but this time with name only. */
1392a6b7db3Sskrll ++name_only;
1402a6b7db3Sskrll sle = src_search_list.head;
1412a6b7db3Sskrll }
1422a6b7db3Sskrll }
1432a6b7db3Sskrll
1442a6b7db3Sskrll if (sle)
1452a6b7db3Sskrll {
1464f645668Schristos fname = xmalloc (strlen (sle->path) + 3
1474f645668Schristos + strlen (name_only ? name_only : sf->name));
1482a6b7db3Sskrll strcpy (fname, sle->path);
1492a6b7db3Sskrll #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1502a6b7db3Sskrll /* d:foo is not the same thing as d:/foo! */
1512a6b7db3Sskrll if (fname[strlen (fname) - 1] == ':')
1522a6b7db3Sskrll strcat (fname, ".");
1532a6b7db3Sskrll #endif
1542a6b7db3Sskrll strcat (fname, "/");
1552a6b7db3Sskrll
1562a6b7db3Sskrll if (name_only)
1572a6b7db3Sskrll strcat (fname, name_only);
1582a6b7db3Sskrll else
1592a6b7db3Sskrll strcat (fname, sf->name);
1602a6b7db3Sskrll
1612a6b7db3Sskrll sle = sle->next;
1622a6b7db3Sskrll }
1632a6b7db3Sskrll else
1642a6b7db3Sskrll {
1652a6b7db3Sskrll if (errno == ENOENT)
1662a6b7db3Sskrll fprintf (stderr, _("%s: could not locate `%s'\n"),
1672a6b7db3Sskrll whoami, sf->name);
1682a6b7db3Sskrll else
1692a6b7db3Sskrll perror (sf->name);
1702a6b7db3Sskrll
1712a6b7db3Sskrll return 0;
1722a6b7db3Sskrll }
1732a6b7db3Sskrll }
1742a6b7db3Sskrll
1752a6b7db3Sskrll ofp = stdout;
1762a6b7db3Sskrll
1772a6b7db3Sskrll if (create_annotation_files)
1782a6b7db3Sskrll {
1792a6b7db3Sskrll /* Try to create annotated source file. */
1802a6b7db3Sskrll const char *filename;
1812a6b7db3Sskrll
1822a6b7db3Sskrll /* Create annotation files in the current working directory. */
1832a6b7db3Sskrll filename = strrchr (sf->name, '/');
1842a6b7db3Sskrll #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1852a6b7db3Sskrll {
1862a6b7db3Sskrll char *bslash = strrchr (sf->name, '\\');
1872a6b7db3Sskrll if (filename == NULL || (bslash != NULL && bslash > filename))
1882a6b7db3Sskrll filename = bslash;
1892a6b7db3Sskrll if (filename == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
1902a6b7db3Sskrll filename = sf->name + 1;
1912a6b7db3Sskrll }
1922a6b7db3Sskrll #endif
1932a6b7db3Sskrll if (filename)
1942a6b7db3Sskrll ++filename;
1952a6b7db3Sskrll else
1962a6b7db3Sskrll filename = sf->name;
1972a6b7db3Sskrll
1984f645668Schristos fname = xmalloc (strlen (filename) + strlen (EXT_ANNO) + 1);
1992a6b7db3Sskrll strcpy (fname, filename);
2002a6b7db3Sskrll strcat (fname, EXT_ANNO);
2012a6b7db3Sskrll #ifdef __MSDOS__
2022a6b7db3Sskrll {
2032a6b7db3Sskrll /* foo.cpp-ann can overwrite foo.cpp due to silent truncation of
2042a6b7db3Sskrll file names on 8+3 filesystems. Their `stat' better be good... */
2052a6b7db3Sskrll struct stat buf1, buf2;
2062a6b7db3Sskrll
2072a6b7db3Sskrll if (stat (filename, &buf1) == 0
2082a6b7db3Sskrll && stat (fname, &buf2) == 0
2092a6b7db3Sskrll && buf1.st_ino == buf2.st_ino)
2102a6b7db3Sskrll {
2112a6b7db3Sskrll char *dot = strrchr (fname, '.');
2122a6b7db3Sskrll
2134f645668Schristos if (!dot)
2144f645668Schristos dot = fname + strlen (filename);
2154f645668Schristos strcpy (dot, ".ann");
2162a6b7db3Sskrll }
2172a6b7db3Sskrll }
2182a6b7db3Sskrll #endif
2192a6b7db3Sskrll ofp = fopen (fname, "w");
2202a6b7db3Sskrll
2212a6b7db3Sskrll if (!ofp)
2222a6b7db3Sskrll {
2232a6b7db3Sskrll perror (fname);
2244f645668Schristos free (fname);
2252a6b7db3Sskrll return 0;
2262a6b7db3Sskrll }
2274f645668Schristos free (fname);
2282a6b7db3Sskrll }
2292a6b7db3Sskrll
2302a6b7db3Sskrll /* Print file names if output goes to stdout
2312a6b7db3Sskrll and there are more than one source file. */
2322a6b7db3Sskrll if (ofp == stdout)
2332a6b7db3Sskrll {
2342a6b7db3Sskrll if (first_file)
2354f645668Schristos first_file = false;
2362a6b7db3Sskrll else
2372a6b7db3Sskrll fputc ('\n', ofp);
2382a6b7db3Sskrll
2392a6b7db3Sskrll if (first_output)
2404f645668Schristos first_output = false;
2412a6b7db3Sskrll else
2422a6b7db3Sskrll fprintf (ofp, "\f\n");
2432a6b7db3Sskrll
2442a6b7db3Sskrll fprintf (ofp, _("*** File %s:\n"), sf->name);
2452a6b7db3Sskrll }
2462a6b7db3Sskrll
247be12b8bcSchristos annotation = (char *) xmalloc (max_width + 1);
2482a6b7db3Sskrll line_num = 1;
2494f645668Schristos new_line = true;
2502a6b7db3Sskrll
2512a6b7db3Sskrll while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
2522a6b7db3Sskrll {
2532a6b7db3Sskrll for (i = 0; i < nread; ++i)
2542a6b7db3Sskrll {
2552a6b7db3Sskrll if (new_line)
2562a6b7db3Sskrll {
2572a6b7db3Sskrll (*annote) (annotation, max_width, line_num, arg);
2582a6b7db3Sskrll fputs (annotation, ofp);
2592a6b7db3Sskrll ++line_num;
2602a6b7db3Sskrll }
2612a6b7db3Sskrll
2622a6b7db3Sskrll new_line = (buf[i] == '\n');
2632a6b7db3Sskrll fputc (buf[i], ofp);
2642a6b7db3Sskrll }
2652a6b7db3Sskrll }
2662a6b7db3Sskrll
2672a6b7db3Sskrll free (annotation);
2689573673dSchristos fclose (ifp);
2692a6b7db3Sskrll return ofp;
2702a6b7db3Sskrll }
271