Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Ported palacios to Kbuild
[palacios.git] / scripts / basic / docproc.c
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
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           realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127         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                 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                                 /* 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  * Document spĂ„ecific function(s) in a file.
253  * 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         int i, idx = 0;
260         int startofsym = 1;
261         vec[idx++] = KERNELDOC;
262         vec[idx++] = DOCBOOK;
263
264         /* 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         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         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                                         /* filename */
315                                         while (*s && !isspace(*s)) s++;
316                                         *s++ = '\0';
317                                         /* function names */
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
334 int main(int argc, char *argv[])
335 {
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         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                 /* 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