1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <limits.h>
40#include <sys/types.h>
41#include <sys/wait.h>
42
43
44
45int exitstatus = 0;
46
47typedef void DFL(char *);
48DFL *defaultline;
49
50typedef void FILEONLY(char * file);
51FILEONLY *internalfunctions;
52FILEONLY *externalfunctions;
53FILEONLY *symbolsonly;
54
55typedef void FILELINE(char * file, char * line);
56FILELINE * singlefunctions;
57FILELINE * entity_system;
58
59#define MAXLINESZ 2048
60#define MAXFILES 250
61#define KERNELDOCPATH "scripts/"
62#define KERNELDOC "kernel-doc"
63#define DOCBOOK "-docbook"
64#define FUNCTION "-function"
65#define NOFUNCTION "-nofunction"
66
67void usage (void)
68{
69 fprintf(stderr, "Usage: docproc {doc|depend} file\n");
70 fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
71 fprintf(stderr, "doc: frontend when generating kernel documentation\n");
72 fprintf(stderr, "depend: generate list of files referenced within file\n");
73}
74
75
76
77
78void exec_kernel_doc(char **svec)
79{
80 pid_t pid;
81 int ret;
82 char real_filename[PATH_MAX + 1];
83
84 fflush(stdout);
85 switch(pid=fork()) {
86 case -1:
87 perror("fork");
88 exit(1);
89 case 0:
90 memset(real_filename, 0, sizeof(real_filename));
91 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
92 strncat(real_filename, KERNELDOCPATH KERNELDOC,
93 PATH_MAX - strlen(real_filename));
94 execvp(real_filename, svec);
95 fprintf(stderr, "exec ");
96 perror(real_filename);
97 exit(1);
98 default:
99 waitpid(pid, &ret ,0);
100 }
101 if (WIFEXITED(ret))
102 exitstatus |= WEXITSTATUS(ret);
103 else
104 exitstatus = 0xff;
105}
106
107
108struct symbols
109{
110 char *name;
111};
112
113struct symfile
114{
115 char *filename;
116 struct symbols *symbollist;
117 int symbolcnt;
118};
119
120struct symfile symfilelist[MAXFILES];
121int symfilecnt = 0;
122
123void add_new_symbol(struct symfile *sym, char * symname)
124{
125 sym->symbollist =
126 realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127 sym->symbollist[sym->symbolcnt++].name = strdup(symname);
128}
129
130
131struct symfile * add_new_file(char * filename)
132{
133 symfilelist[symfilecnt++].filename = strdup(filename);
134 return &symfilelist[symfilecnt - 1];
135}
136
137struct symfile * filename_exist(char * filename)
138{
139 int i;
140 for (i=0; i < symfilecnt; i++)
141 if (strcmp(symfilelist[i].filename, filename) == 0)
142 return &symfilelist[i];
143 return NULL;
144}
145
146
147
148
149
150void adddep(char * file) { printf("\t%s", file); }
151void adddep2(char * file, char * line) { line = line; adddep(file); }
152void noaction(char * line) { line = line; }
153void noaction2(char * file, char * line) { file = file; line = line; }
154
155
156void printline(char * line) { printf("%s", line); }
157
158
159
160
161
162
163void find_export_symbols(char * filename)
164{
165 FILE * fp;
166 struct symfile *sym;
167 char line[MAXLINESZ];
168 if (filename_exist(filename) == NULL) {
169 char real_filename[PATH_MAX + 1];
170 memset(real_filename, 0, sizeof(real_filename));
171 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
172 strncat(real_filename, filename,
173 PATH_MAX - strlen(real_filename));
174 sym = add_new_file(filename);
175 fp = fopen(real_filename, "r");
176 if (fp == NULL)
177 {
178 fprintf(stderr, "docproc: ");
179 perror(real_filename);
180 }
181 while (fgets(line, MAXLINESZ, fp)) {
182 char *p;
183 char *e;
184 if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
185 ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
186
187 while (isalnum(*p) || *p == '_')
188 p++;
189
190 while (isspace(*p))
191 p++;
192 if (*p != '(')
193 continue;
194 else
195 p++;
196 while (isspace(*p))
197 p++;
198 e = p;
199 while (isalnum(*e) || *e == '_')
200 e++;
201 *e = '\0';
202 add_new_symbol(sym, p);
203 }
204 }
205 fclose(fp);
206 }
207}
208
209
210
211
212
213
214
215
216
217
218void docfunctions(char * filename, char * type)
219{
220 int i,j;
221 int symcnt = 0;
222 int idx = 0;
223 char **vec;
224
225 for (i=0; i <= symfilecnt; i++)
226 symcnt += symfilelist[i].symbolcnt;
227 vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
228 if (vec == NULL) {
229 perror("docproc: ");
230 exit(1);
231 }
232 vec[idx++] = KERNELDOC;
233 vec[idx++] = DOCBOOK;
234 for (i=0; i < symfilecnt; i++) {
235 struct symfile * sym = &symfilelist[i];
236 for (j=0; j < sym->symbolcnt; j++) {
237 vec[idx++] = type;
238 vec[idx++] = sym->symbollist[j].name;
239 }
240 }
241 vec[idx++] = filename;
242 vec[idx] = NULL;
243 printf("<!-- %s -->\n", filename);
244 exec_kernel_doc(vec);
245 fflush(stdout);
246 free(vec);
247}
248void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
249void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
250
251
252
253
254
255
256void singfunc(char * filename, char * line)
257{
258 char *vec[200];
259 int i, idx = 0;
260 int startofsym = 1;
261 vec[idx++] = KERNELDOC;
262 vec[idx++] = DOCBOOK;
263
264
265 for (i=0; line[i]; i++) {
266 if (isspace(line[i])) {
267 line[i] = '\0';
268 startofsym = 1;
269 continue;
270 }
271 if (startofsym) {
272 startofsym = 0;
273 vec[idx++] = FUNCTION;
274 vec[idx++] = &line[i];
275 }
276 }
277 vec[idx++] = filename;
278 vec[idx] = NULL;
279 exec_kernel_doc(vec);
280}
281
282
283
284
285
286
287
288
289
290void parse_file(FILE *infile)
291{
292 char line[MAXLINESZ];
293 char * s;
294 while (fgets(line, MAXLINESZ, infile)) {
295 if (line[0] == '!') {
296 s = line + 2;
297 switch (line[1]) {
298 case 'E':
299 while (*s && !isspace(*s)) s++;
300 *s = '\0';
301 externalfunctions(line+2);
302 break;
303 case 'I':
304 while (*s && !isspace(*s)) s++;
305 *s = '\0';
306 internalfunctions(line+2);
307 break;
308 case 'D':
309 while (*s && !isspace(*s)) s++;
310 *s = '\0';
311 symbolsonly(line+2);
312 break;
313 case 'F':
314
315 while (*s && !isspace(*s)) s++;
316 *s++ = '\0';
317
318 while (isspace(*s))
319 s++;
320 singlefunctions(line +2, s);
321 break;
322 default:
323 defaultline(line);
324 }
325 }
326 else {
327 defaultline(line);
328 }
329 }
330 fflush(stdout);
331}
332
333
334int main(int argc, char **argv)
335{
336 FILE * infile;
337 if (argc != 3) {
338 usage();
339 exit(1);
340 }
341
342 infile = fopen(argv[2], "r");
343 if (infile == NULL) {
344 fprintf(stderr, "docproc: ");
345 perror(argv[2]);
346 exit(2);
347 }
348
349 if (strcmp("doc", argv[1]) == 0)
350 {
351
352
353
354
355
356
357
358
359 defaultline = noaction;
360 internalfunctions = find_export_symbols;
361 externalfunctions = find_export_symbols;
362 symbolsonly = find_export_symbols;
363 singlefunctions = noaction2;
364 parse_file(infile);
365
366
367 fseek(infile, 0, SEEK_SET);
368 defaultline = printline;
369 internalfunctions = intfunc;
370 externalfunctions = extfunc;
371 symbolsonly = printline;
372 singlefunctions = singfunc;
373
374 parse_file(infile);
375 }
376 else if (strcmp("depend", argv[1]) == 0)
377 {
378
379
380 printf("%s\t", argv[2]);
381 defaultline = noaction;
382 internalfunctions = adddep;
383 externalfunctions = adddep;
384 symbolsonly = adddep;
385 singlefunctions = adddep2;
386 parse_file(infile);
387 printf("\n");
388 }
389 else
390 {
391 fprintf(stderr, "Unknown option: %s\n", argv[1]);
392 exit(1);
393 }
394 fclose(infile);
395 fflush(stdout);
396 return exitstatus;
397}
398
399