1 /* 2 * Keeps track of source files. 3 */ 4 #include "gprof.h" 5 #include "libiberty.h" 6 #include "search_list.h" 7 #include "source.h" 8 9 #define EXT_ANNO "-ann" /* postfix of annotated files */ 10 11 /* 12 * Default option values: 13 */ 14 bool create_annotation_files = FALSE; 15 16 Search_List src_search_list = 17 {0, 0}; 18 Source_File *first_src_file = 0; 19 20 21 Source_File * 22 DEFUN (source_file_lookup_path, (path), const char *path) 23 { 24 Source_File *sf; 25 26 for (sf = first_src_file; sf; sf = sf->next) 27 { 28 if (strcmp (path, sf->name) == 0) 29 { 30 break; 31 } 32 } 33 if (!sf) 34 { 35 /* create a new source file descriptor: */ 36 37 sf = (Source_File *) xmalloc (sizeof (*sf)); 38 memset (sf, 0, sizeof (*sf)); 39 sf->name = xstrdup (path); 40 sf->next = first_src_file; 41 first_src_file = sf; 42 } 43 return sf; 44 } 45 46 47 Source_File * 48 DEFUN (source_file_lookup_name, (filename), const char *filename) 49 { 50 const char *fname; 51 Source_File *sf; 52 /* 53 * The user cannot know exactly how a filename will be stored in 54 * the debugging info (e.g., ../include/foo.h 55 * vs. /usr/include/foo.h). So we simply compare the filename 56 * component of a path only: 57 */ 58 for (sf = first_src_file; sf; sf = sf->next) 59 { 60 fname = strrchr (sf->name, '/'); 61 if (fname) 62 { 63 ++fname; 64 } 65 else 66 { 67 fname = sf->name; 68 } 69 if (strcmp (filename, fname) == 0) 70 { 71 break; 72 } 73 } 74 return sf; 75 } 76 77 78 FILE * 79 DEFUN (annotate_source, (sf, max_width, annote, arg), 80 Source_File * sf AND int max_width 81 AND void (*annote) PARAMS ((char *buf, int w, int l, void *arg)) 82 AND void *arg) 83 { 84 static bool first_file = TRUE; 85 int i, line_num, nread; 86 bool new_line; 87 char buf[8192]; 88 char fname[PATH_MAX]; 89 char *annotation, *name_only; 90 FILE *ifp, *ofp; 91 Search_List_Elem *sle = src_search_list.head; 92 93 /* 94 * Open input file. If open fails, walk along search-list until 95 * open succeeds or reaching end of list: 96 */ 97 strcpy (fname, sf->name); 98 if (sf->name[0] == '/') 99 { 100 sle = 0; /* don't use search list for absolute paths */ 101 } 102 name_only = 0; 103 while (TRUE) 104 { 105 DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n", 106 sf->name, fname)); 107 ifp = fopen (fname, FOPEN_RB); 108 if (ifp) 109 { 110 break; 111 } 112 if (!sle && !name_only) 113 { 114 name_only = strrchr (sf->name, '/'); 115 if (name_only) 116 { 117 /* try search-list again, but this time with name only: */ 118 ++name_only; 119 sle = src_search_list.head; 120 } 121 } 122 if (sle) 123 { 124 strcpy (fname, sle->path); 125 strcat (fname, "/"); 126 if (name_only) 127 { 128 strcat (fname, name_only); 129 } 130 else 131 { 132 strcat (fname, sf->name); 133 } 134 sle = sle->next; 135 } 136 else 137 { 138 if (errno == ENOENT) 139 { 140 fprintf (stderr, "%s: could not locate `%s'\n", 141 whoami, sf->name); 142 } 143 else 144 { 145 perror (sf->name); 146 } 147 return 0; 148 } 149 } 150 151 ofp = stdout; 152 if (create_annotation_files) 153 { 154 /* try to create annotated source file: */ 155 const char *filename; 156 157 /* create annotation files in the current working directory: */ 158 filename = strrchr (sf->name, '/'); 159 if (filename) 160 { 161 ++filename; 162 } 163 else 164 { 165 filename = sf->name; 166 } 167 168 strcpy (fname, filename); 169 strcat (fname, EXT_ANNO); 170 ofp = fopen (fname, "w"); 171 if (!ofp) 172 { 173 perror (fname); 174 return 0; 175 } 176 } 177 178 /* 179 * Print file names if output goes to stdout and there are 180 * more than one source file: 181 */ 182 if (ofp == stdout) 183 { 184 if (first_file) 185 { 186 first_file = FALSE; 187 } 188 else 189 { 190 fputc ('\n', ofp); 191 } 192 if (first_output) 193 { 194 first_output = FALSE; 195 } 196 else 197 { 198 fprintf (ofp, "\f\n"); 199 } 200 fprintf (ofp, "*** File %s:\n", sf->name); 201 } 202 203 annotation = 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 new_line = FALSE; 216 } 217 new_line = (buf[i] == '\n'); 218 fputc (buf[i], ofp); 219 } 220 } 221 free (annotation); 222 return ofp; 223 } 224