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