source.c 6.1 KB

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