source: MondoRescue/branches/3.3/mindi-busybox/scripts/basic/docproc.c@ 3901

Last change on this file since 3901 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1/*
2 * docproc is a simple preprocessor for the template files
3 * used as placeholders for the kernel internal documentation.
4 * docproc is used for documentation-frontend and
5 * dependency-generator.
6 * The two usages have in common that they require
7 * some knowledge of the .tmpl syntax, therefore they
8 * are kept together.
9 *
10 * documentation-frontend
11 * Scans the template file and call kernel-doc for
12 * all occurrences of ![EIF]file
13 * Beforehand each referenced file are scanned for
14 * any exported sympols "EXPORT_SYMBOL()" statements.
15 * This is used to create proper -function and
16 * -nofunction arguments in calls to kernel-doc.
17 * Usage: docproc doc file.tmpl
18 *
19 * dependency-generator:
20 * Scans the template file and list all files
21 * referenced in a format recognized by make.
22 * Usage: docproc depend file.tmpl
23 * Writes dependency information to stdout
24 * in the following format:
25 * file.tmpl src.c src2.c
26 * The filenames are obtained from the following constructs:
27 * !Efilename
28 * !Ifilename
29 * !Dfilename
30 * !Ffilename
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//bbox disabled: #include <alloca.h>
43
44/* exitstatus is used to keep track of any failing calls to kernel-doc,
45 * but execution continues. */
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 * Execute kernel-doc with parameters givin in svec
78 */
79void exec_kernel_doc(char **svec)
80{
81 pid_t pid;
82 int ret;
83 char *real_filename;
84 int rflen;
85
86 /* Make sure output generated so far are flushed */
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/* Types used to create list of all exported symbols in a number of files */
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/* Add a filename to the list */
135struct symfile * add_new_file(char * filename)
136{
137 symfilelist[symfilecnt++].filename = strdup(filename);
138 return &symfilelist[symfilecnt - 1];
139}
140/* Check if file already are present in the list */
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 * List all files referenced within the template file.
152 * Files are separated by tabs.
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/* Echo the line without further action */
160void printline(char * line) { printf("%s", line); }
161
162/*
163 * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
164 * in filename.
165 * All symbols located are stored in symfilelist.
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 /* Skip EXPORT_SYMBOL{_GPL} */
190 while (isalnum(*p) || *p == '_')
191 p++;
192 /* Remove paranteses and additional ws */
193 while (isspace(*p))
194 p++;
195 if (*p != '(')
196 continue; /* Syntax error? */
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 * Document all external or internal functions in a file.
214 * Call kernel-doc with following parameters:
215 * kernel-doc -docbook -nofunction function_name1 filename
216 * function names are obtained from all the src files
217 * by find_export_symbols.
218 * intfunc uses -nofunction
219 * extfunc uses -function
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 * Document specific function(s) in a file.
256 * Call kernel-doc with the following parameters:
257 * kernel-doc -docbook -function function1 [-function function2]
258 */
259void singfunc(char * filename, char * line)
260{
261 char *vec[200]; /* Enough for specific functions */
262 int i, idx = 0;
263 int startofsym = 1;
264 vec[idx++] = KERNELDOC;
265 vec[idx++] = DOCBOOK;
266
267 /* Split line up in individual parameters preceded by FUNCTION */
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 * Parse file, calling action specific functions for:
287 * 1) Lines containing !E
288 * 2) Lines containing !I
289 * 3) Lines containing !D
290 * 4) Lines containing !F
291 * 5) Default lines - lines not matching the above
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 /* filename */
318 while (*s && !isspace(*s)) s++;
319 *s++ = '\0';
320 /* function names */
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 /* Open file, exit on error */
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 /* Need to do this in two passes.
355 * First pass is used to collect all symbols exported
356 * in the various files.
357 * Second pass generate the documentation.
358 * This is required because function are declared
359 * and exported in different files :-((
360 */
361 /* Collect symbols */
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 /* Rewind to start from beginning of file again */
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 /* Create first part of dependency chain
382 * file.tmpl */
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}
Note: See TracBrowser for help on using the repository browser.