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