Commit | Line | Data |
---|---|---|
5489fcc3 KR |
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 ***/ |