Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/scripts/basic/docproc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 9779 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /*
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    
43     /* exitstatus is used to keep track of any failing calls to kernel-doc,
44     * but execution continues. */
45     int exitstatus = 0;
46    
47     typedef void DFL(char *);
48     DFL *defaultline;
49    
50     typedef void FILEONLY(char * file);
51     FILEONLY *internalfunctions;
52     FILEONLY *externalfunctions;
53     FILEONLY *symbolsonly;
54    
55     typedef void FILELINE(char * file, char * line);
56     FILELINE * singlefunctions;
57     FILELINE * 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    
67     void 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     * Execute kernel-doc with parameters givin in svec
77     */
78     void exec_kernel_doc(char **svec)
79     {
80     pid_t pid;
81     int ret;
82     char real_filename[PATH_MAX + 1];
83     /* Make sure output generated so far are flushed */
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     /* Types used to create list of all exported symbols in a number of files */
108     struct symbols
109     {
110     char *name;
111     };
112    
113     struct symfile
114     {
115     char *filename;
116     struct symbols *symbollist;
117     int symbolcnt;
118     };
119    
120     struct symfile symfilelist[MAXFILES];
121     int symfilecnt = 0;
122    
123     void add_new_symbol(struct symfile *sym, char * symname)
124     {
125     sym->symbollist =
126 niro 816 realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127 niro 532 sym->symbollist[sym->symbolcnt++].name = strdup(symname);
128     }
129    
130     /* Add a filename to the list */
131     struct symfile * add_new_file(char * filename)
132     {
133     symfilelist[symfilecnt++].filename = strdup(filename);
134     return &symfilelist[symfilecnt - 1];
135     }
136     /* Check if file already are present in the list */
137     struct 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     * List all files referenced within the template file.
148     * Files are separated by tabs.
149     */
150     void adddep(char * file) { printf("\t%s", file); }
151     void adddep2(char * file, char * line) { line = line; adddep(file); }
152     void noaction(char * line) { line = line; }
153     void noaction2(char * file, char * line) { file = file; line = line; }
154    
155     /* Echo the line without further action */
156     void printline(char * line) { printf("%s", line); }
157    
158     /*
159     * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
160     * in filename.
161     * All symbols located are stored in symfilelist.
162     */
163     void 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 niro 816 while (fgets(line, MAXLINESZ, fp)) {
182 niro 532 char *p;
183     char *e;
184     if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
185 niro 816 ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
186 niro 532 /* Skip EXPORT_SYMBOL{_GPL} */
187     while (isalnum(*p) || *p == '_')
188     p++;
189     /* Remove paranteses and additional ws */
190     while (isspace(*p))
191     p++;
192     if (*p != '(')
193     continue; /* Syntax error? */
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     * Document all external or internal functions in a file.
211     * Call kernel-doc with following parameters:
212     * kernel-doc -docbook -nofunction function_name1 filename
213     * function names are obtained from all the the src files
214     * by find_export_symbols.
215     * intfunc uses -nofunction
216     * extfunc uses -function
217     */
218     void 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     }
248     void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
249     void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
250    
251     /*
252 niro 984 * Document specific function(s) in a file.
253 niro 532 * Call kernel-doc with the following parameters:
254     * kernel-doc -docbook -function function1 [-function function2]
255     */
256     void singfunc(char * filename, char * line)
257     {
258     char *vec[200]; /* Enough for specific functions */
259 niro 816 int i, idx = 0;
260     int startofsym = 1;
261 niro 532 vec[idx++] = KERNELDOC;
262     vec[idx++] = DOCBOOK;
263    
264 niro 816 /* Split line up in individual parameters preceeded by FUNCTION */
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 niro 532 vec[idx++] = filename;
278     vec[idx] = NULL;
279     exec_kernel_doc(vec);
280     }
281    
282     /*
283     * Parse file, calling action specific functions for:
284     * 1) Lines containing !E
285     * 2) Lines containing !I
286     * 3) Lines containing !D
287     * 4) Lines containing !F
288     * 5) Default lines - lines not matching the above
289     */
290     void parse_file(FILE *infile)
291     {
292     char line[MAXLINESZ];
293     char * s;
294 niro 816 while (fgets(line, MAXLINESZ, infile)) {
295 niro 532 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 niro 816 *s = '\0';
311     symbolsonly(line+2);
312     break;
313 niro 532 case 'F':
314     /* filename */
315     while (*s && !isspace(*s)) s++;
316     *s++ = '\0';
317 niro 816 /* function names */
318 niro 532 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    
334 niro 816 int main(int argc, char **argv)
335 niro 532 {
336     FILE * infile;
337     if (argc != 3) {
338     usage();
339     exit(1);
340     }
341     /* Open file, exit on error */
342     infile = fopen(argv[2], "r");
343 niro 816 if (infile == NULL) {
344     fprintf(stderr, "docproc: ");
345     perror(argv[2]);
346     exit(2);
347     }
348 niro 532
349     if (strcmp("doc", argv[1]) == 0)
350     {
351     /* Need to do this in two passes.
352     * First pass is used to collect all symbols exported
353     * in the various files.
354     * Second pass generate the documentation.
355     * This is required because function are declared
356     * and exported in different files :-((
357     */
358     /* Collect symbols */
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     /* Rewind to start from beginning of file again */
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     /* Create first part of dependency chain
379     * file.tmpl */
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