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