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