kernel-doc: fix doc blocks and html
[linux-2.6.git] / scripts / kernel-doc
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
6 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
7 ## Copyright (C) 2001  Simon Huggins                             ##
8 ## Copyright (C) 2005-2007  Randy Dunlap                         ##
9 ##                                                               ##
10 ## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
11 ## Copyright (c) 2000 MontaVista Software, Inc.                  ##
12 ##                                                               ##
13 ## This software falls under the GNU General Public License.     ##
14 ## Please read the COPYING file for more information             ##
15
16 # w.o. 03-11-2000: added the '-filelist' option.
17
18 # 18/01/2001 -  Cleanups
19 #               Functions prototyped as foo(void) same as foo()
20 #               Stop eval'ing where we don't need to.
21 # -- huggie@earth.li
22
23 # 27/06/2001 -  Allowed whitespace after initial "/**" and
24 #               allowed comments before function declarations.
25 # -- Christian Kreibich <ck@whoop.org>
26
27 # Still to do:
28 #       - add perldoc documentation
29 #       - Look more closely at some of the scarier bits :)
30
31 # 26/05/2001 -  Support for separate source and object trees.
32 #               Return error code.
33 #               Keith Owens <kaos@ocs.com.au>
34
35 # 23/09/2001 - Added support for typedefs, structs, enums and unions
36 #              Support for Context section; can be terminated using empty line
37 #              Small fixes (like spaces vs. \s in regex)
38 # -- Tim Jansen <tim@tjansen.de>
39
40
41 #
42 # This will read a 'c' file and scan for embedded comments in the
43 # style of gnome comments (+minor extensions - see below).
44 #
45
46 # Note: This only supports 'c'.
47
48 # usage:
49 # kernel-doc [ -docbook | -html | -text | -man ]
50 #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
51 # or
52 #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
53 #
54 #  Set output format using one of -docbook -html -text or -man.  Default is man.
55 #
56 #  -function funcname
57 #       If set, then only generate documentation for the given function(s).  All
58 #       other functions are ignored.
59 #
60 #  -nofunction funcname
61 #       If set, then only generate documentation for the other function(s).
62 #       Cannot be used together with -function
63 #       (yes, that's a bug -- perl hackers can fix it 8))
64 #
65 #  c files - list of 'c' files to process
66 #
67 #  All output goes to stdout, with errors to stderr.
68
69 #
70 # format of comments.
71 # In the following table, (...)? signifies optional structure.
72 #                         (...)* signifies 0 or more structure elements
73 # /**
74 #  * function_name(:)? (- short description)?
75 # (* @parameterx: (description of parameter x)?)*
76 # (* a blank line)?
77 #  * (Description:)? (Description of function)?
78 #  * (section header: (section description)? )*
79 #  (*)?*/
80 #
81 # So .. the trivial example would be:
82 #
83 # /**
84 #  * my_function
85 #  **/
86 #
87 # If the Description: header tag is omitted, then there must be a blank line
88 # after the last parameter specification.
89 # e.g.
90 # /**
91 #  * my_function - does my stuff
92 #  * @my_arg: its mine damnit
93 #  *
94 #  * Does my stuff explained.
95 #  */
96 #
97 #  or, could also use:
98 # /**
99 #  * my_function - does my stuff
100 #  * @my_arg: its mine damnit
101 #  * Description: Does my stuff explained.
102 #  */
103 # etc.
104 #
105 # Beside functions you can also write documentation for structs, unions,
106 # enums and typedefs. Instead of the function name you must write the name
107 # of the declaration;  the struct/union/enum/typedef must always precede
108 # the name. Nesting of declarations is not supported.
109 # Use the argument mechanism to document members or constants.
110 # e.g.
111 # /**
112 #  * struct my_struct - short description
113 #  * @a: first member
114 #  * @b: second member
115 #  *
116 #  * Longer description
117 #  */
118 # struct my_struct {
119 #     int a;
120 #     int b;
121 # /* private: */
122 #     int c;
123 # };
124 #
125 # All descriptions can be multiline, except the short function description.
126 #
127 # You can also add additional sections. When documenting kernel functions you
128 # should document the "Context:" of the function, e.g. whether the functions
129 # can be called form interrupts. Unlike other sections you can end it with an
130 # empty line.
131 # Example-sections should contain the string EXAMPLE so that they are marked
132 # appropriately in DocBook.
133 #
134 # Example:
135 # /**
136 #  * user_function - function that can only be called in user context
137 #  * @a: some argument
138 #  * Context: !in_interrupt()
139 #  *
140 #  * Some description
141 #  * Example:
142 #  *    user_function(22);
143 #  */
144 # ...
145 #
146 #
147 # All descriptive text is further processed, scanning for the following special
148 # patterns, which are highlighted appropriately.
149 #
150 # 'funcname()' - function
151 # '$ENVVAR' - environmental variable
152 # '&struct_name' - name of a structure (up to two words including 'struct')
153 # '@parameter' - name of a parameter
154 # '%CONST' - name of a constant.
155
156 my $errors = 0;
157 my $warnings = 0;
158 my $anon_struct_union = 0;
159
160 # match expressions used to find embedded type information
161 my $type_constant = '\%([-_\w]+)';
162 my $type_func = '(\w+)\(\)';
163 my $type_param = '\@(\w+)';
164 my $type_struct = '\&((struct\s*)*[_\w]+)';
165 my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
166 my $type_env = '(\$\w+)';
167
168 # Output conversion substitutions.
169 #  One for each output format
170
171 # these work fairly well
172 my %highlights_html = ( $type_constant, "<i>\$1</i>",
173                         $type_func, "<b>\$1</b>",
174                         $type_struct_xml, "<i>\$1</i>",
175                         $type_env, "<b><i>\$1</i></b>",
176                         $type_param, "<tt><b>\$1</b></tt>" );
177 my $local_lt = "\\\\\\\\lt:";
178 my $local_gt = "\\\\\\\\gt:";
179 my $blankline_html = $local_lt . "p" . $local_gt;       # was "<p>"
180
181 # XML, docbook format
182 my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
183                         $type_constant, "<constant>\$1</constant>",
184                         $type_func, "<function>\$1</function>",
185                         $type_struct, "<structname>\$1</structname>",
186                         $type_env, "<envar>\$1</envar>",
187                         $type_param, "<parameter>\$1</parameter>" );
188 my $blankline_xml = "</para><para>\n";
189
190 # gnome, docbook format
191 my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
192                          $type_func, "<function>\$1</function>",
193                          $type_struct, "<structname>\$1</structname>",
194                          $type_env, "<envar>\$1</envar>",
195                          $type_param, "<parameter>\$1</parameter>" );
196 my $blankline_gnome = "</para><para>\n";
197
198 # these are pretty rough
199 my %highlights_man = ( $type_constant, "\$1",
200                        $type_func, "\\\\fB\$1\\\\fP",
201                        $type_struct, "\\\\fI\$1\\\\fP",
202                        $type_param, "\\\\fI\$1\\\\fP" );
203 my $blankline_man = "";
204
205 # text-mode
206 my %highlights_text = ( $type_constant, "\$1",
207                         $type_func, "\$1",
208                         $type_struct, "\$1",
209                         $type_param, "\$1" );
210 my $blankline_text = "";
211
212
213 sub usage {
214     print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
215     print "         [ -function funcname [ -function funcname ...] ]\n";
216     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
217     print "         c source file(s) > outputfile\n";
218     exit 1;
219 }
220
221 # read arguments
222 if ($#ARGV==-1) {
223     usage();
224 }
225
226 my $verbose = 0;
227 my $output_mode = "man";
228 my %highlights = %highlights_man;
229 my $blankline = $blankline_man;
230 my $modulename = "Kernel API";
231 my $function_only = 0;
232 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
233                 'July', 'August', 'September', 'October',
234                 'November', 'December')[(localtime)[4]] .
235   " " . ((localtime)[5]+1900);
236
237 # Essentially these are globals
238 # They probably want to be tidied up made more localised or summat.
239 # CAVEAT EMPTOR!  Some of the others I localised may not want to be which
240 # could cause "use of undefined value" or other bugs.
241 my ($function, %function_table,%parametertypes,$declaration_purpose);
242 my ($type,$declaration_name,$return_type);
243 my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
244
245 # Generated docbook code is inserted in a template at a point where
246 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
247 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
248 # We keep track of number of generated entries and generate a dummy
249 # if needs be to ensure the expanded template can be postprocessed
250 # into html.
251 my $section_counter = 0;
252
253 my $lineprefix="";
254
255 # states
256 # 0 - normal code
257 # 1 - looking for function name
258 # 2 - scanning field start.
259 # 3 - scanning prototype.
260 # 4 - documentation block
261 my $state;
262 my $in_doc_sect;
263
264 #declaration types: can be
265 # 'function', 'struct', 'union', 'enum', 'typedef'
266 my $decl_type;
267
268 my $doc_special = "\@\%\$\&";
269
270 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
271 my $doc_end = '\*/';
272 my $doc_com = '\s*\*\s*';
273 my $doc_decl = $doc_com.'(\w+)';
274 my $doc_sect = $doc_com.'(['.$doc_special.']?[\w\s]+):(.*)';
275 my $doc_content = $doc_com.'(.*)';
276 my $doc_block = $doc_com.'DOC:\s*(.*)?';
277
278 my %constants;
279 my %parameterdescs;
280 my @parameterlist;
281 my %sections;
282 my @sectionlist;
283
284 my $contents = "";
285 my $section_default = "Description";    # default section
286 my $section_intro = "Introduction";
287 my $section = $section_default;
288 my $section_context = "Context";
289
290 my $undescribed = "-- undescribed --";
291
292 reset_state();
293
294 while ($ARGV[0] =~ m/^-(.*)/) {
295     my $cmd = shift @ARGV;
296     if ($cmd eq "-html") {
297         $output_mode = "html";
298         %highlights = %highlights_html;
299         $blankline = $blankline_html;
300     } elsif ($cmd eq "-man") {
301         $output_mode = "man";
302         %highlights = %highlights_man;
303         $blankline = $blankline_man;
304     } elsif ($cmd eq "-text") {
305         $output_mode = "text";
306         %highlights = %highlights_text;
307         $blankline = $blankline_text;
308     } elsif ($cmd eq "-docbook") {
309         $output_mode = "xml";
310         %highlights = %highlights_xml;
311         $blankline = $blankline_xml;
312     } elsif ($cmd eq "-gnome") {
313         $output_mode = "gnome";
314         %highlights = %highlights_gnome;
315         $blankline = $blankline_gnome;
316     } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
317         $modulename = shift @ARGV;
318     } elsif ($cmd eq "-function") { # to only output specific functions
319         $function_only = 1;
320         $function = shift @ARGV;
321         $function_table{$function} = 1;
322     } elsif ($cmd eq "-nofunction") { # to only output specific functions
323         $function_only = 2;
324         $function = shift @ARGV;
325         $function_table{$function} = 1;
326     } elsif ($cmd eq "-v") {
327         $verbose = 1;
328     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
329         usage();
330     } elsif ($cmd eq '-filelist') {
331             $filelist = shift @ARGV;
332     }
333 }
334
335 # get kernel version from env
336 sub get_kernel_version() {
337     my $version;
338
339     if (defined($ENV{'KERNELVERSION'})) {
340         $version = $ENV{'KERNELVERSION'};
341     }
342     return $version;
343 }
344 my $kernelversion = get_kernel_version();
345
346 # generate a sequence of code that will splice in highlighting information
347 # using the s// operator.
348 my $dohighlight = "";
349 foreach my $pattern (keys %highlights) {
350 #   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
351     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
352 }
353
354 ##
355 # dumps section contents to arrays/hashes intended for that purpose.
356 #
357 sub dump_section {
358     my $name = shift;
359     my $contents = join "\n", @_;
360
361     if ($name =~ m/$type_constant/) {
362         $name = $1;
363 #       print STDERR "constant section '$1' = '$contents'\n";
364         $constants{$name} = $contents;
365     } elsif ($name =~ m/$type_param/) {
366 #       print STDERR "parameter def '$1' = '$contents'\n";
367         $name = $1;
368         $parameterdescs{$name} = $contents;
369     } else {
370 #       print STDERR "other section '$name' = '$contents'\n";
371         $sections{$name} = $contents;
372         push @sectionlist, $name;
373     }
374 }
375
376 ##
377 # output function
378 #
379 # parameterdescs, a hash.
380 #  function => "function name"
381 #  parameterlist => @list of parameters
382 #  parameterdescs => %parameter descriptions
383 #  sectionlist => @list of sections
384 #  sections => %section descriptions
385 #
386
387 sub output_highlight {
388     my $contents = join "\n",@_;
389     my $line;
390
391 #   DEBUG
392 #   if (!defined $contents) {
393 #       use Carp;
394 #       confess "output_highlight got called with no args?\n";
395 #   }
396
397     if ($output_mode eq "html") {
398         $contents = local_unescape($contents);
399         # convert data read & converted thru xml_escape() into &xyz; format:
400         $contents =~ s/\\\\\\/&/g;
401     }
402 #   print STDERR "contents b4:$contents\n";
403     eval $dohighlight;
404     die $@ if $@;
405 #   print STDERR "contents af:$contents\n";
406
407     foreach $line (split "\n", $contents) {
408         if ($line eq ""){
409             print $lineprefix, local_unescape($blankline);
410         } else {
411             $line =~ s/\\\\\\/\&/g;
412             if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
413                 print "\\&$line";
414             } else {
415                 print $lineprefix, $line;
416             }
417         }
418         print "\n";
419     }
420 }
421
422 #output sections in html
423 sub output_section_html(%) {
424     my %args = %{$_[0]};
425     my $section;
426
427     foreach $section (@{$args{'sectionlist'}}) {
428         print "<h3>$section</h3>\n";
429         print "<blockquote>\n";
430         output_highlight($args{'sections'}{$section});
431         print "</blockquote>\n";
432     }
433 }
434
435 # output enum in html
436 sub output_enum_html(%) {
437     my %args = %{$_[0]};
438     my ($parameter);
439     my $count;
440     print "<h2>enum ".$args{'enum'}."</h2>\n";
441
442     print "<b>enum ".$args{'enum'}."</b> {<br>\n";
443     $count = 0;
444     foreach $parameter (@{$args{'parameterlist'}}) {
445         print " <b>".$parameter."</b>";
446         if ($count != $#{$args{'parameterlist'}}) {
447             $count++;
448             print ",\n";
449         }
450         print "<br>";
451     }
452     print "};<br>\n";
453
454     print "<h3>Constants</h3>\n";
455     print "<dl>\n";
456     foreach $parameter (@{$args{'parameterlist'}}) {
457         print "<dt><b>".$parameter."</b>\n";
458         print "<dd>";
459         output_highlight($args{'parameterdescs'}{$parameter});
460     }
461     print "</dl>\n";
462     output_section_html(@_);
463     print "<hr>\n";
464 }
465
466 # output typedef in html
467 sub output_typedef_html(%) {
468     my %args = %{$_[0]};
469     my ($parameter);
470     my $count;
471     print "<h2>typedef ".$args{'typedef'}."</h2>\n";
472
473     print "<b>typedef ".$args{'typedef'}."</b>\n";
474     output_section_html(@_);
475     print "<hr>\n";
476 }
477
478 # output struct in html
479 sub output_struct_html(%) {
480     my %args = %{$_[0]};
481     my ($parameter);
482
483     print "<h2>".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."</h2>\n";
484     print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
485     foreach $parameter (@{$args{'parameterlist'}}) {
486         if ($parameter =~ /^#/) {
487                 print "$parameter<br>\n";
488                 next;
489         }
490         my $parameter_name = $parameter;
491         $parameter_name =~ s/\[.*//;
492
493         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
494         $type = $args{'parametertypes'}{$parameter};
495         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
496             # pointer-to-function
497             print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
498         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
499             # bitfield
500             print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
501         } else {
502             print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
503         }
504     }
505     print "};<br>\n";
506
507     print "<h3>Members</h3>\n";
508     print "<dl>\n";
509     foreach $parameter (@{$args{'parameterlist'}}) {
510         ($parameter =~ /^#/) && next;
511
512         my $parameter_name = $parameter;
513         $parameter_name =~ s/\[.*//;
514
515         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
516         print "<dt><b>".$parameter."</b>\n";
517         print "<dd>";
518         output_highlight($args{'parameterdescs'}{$parameter_name});
519     }
520     print "</dl>\n";
521     output_section_html(@_);
522     print "<hr>\n";
523 }
524
525 # output function in html
526 sub output_function_html(%) {
527     my %args = %{$_[0]};
528     my ($parameter, $section);
529     my $count;
530
531     print "<h2>" .$args{'function'}." - ".$args{'purpose'}."</h2>\n";
532     print "<i>".$args{'functiontype'}."</i>\n";
533     print "<b>".$args{'function'}."</b>\n";
534     print "(";
535     $count = 0;
536     foreach $parameter (@{$args{'parameterlist'}}) {
537         $type = $args{'parametertypes'}{$parameter};
538         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
539             # pointer-to-function
540             print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
541         } else {
542             print "<i>".$type."</i> <b>".$parameter."</b>";
543         }
544         if ($count != $#{$args{'parameterlist'}}) {
545             $count++;
546             print ",\n";
547         }
548     }
549     print ")\n";
550
551     print "<h3>Arguments</h3>\n";
552     print "<dl>\n";
553     foreach $parameter (@{$args{'parameterlist'}}) {
554         my $parameter_name = $parameter;
555         $parameter_name =~ s/\[.*//;
556
557         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
558         print "<dt><b>".$parameter."</b>\n";
559         print "<dd>";
560         output_highlight($args{'parameterdescs'}{$parameter_name});
561     }
562     print "</dl>\n";
563     output_section_html(@_);
564     print "<hr>\n";
565 }
566
567 # output intro in html
568 sub output_intro_html(%) {
569     my %args = %{$_[0]};
570     my ($parameter, $section);
571     my $count;
572
573     foreach $section (@{$args{'sectionlist'}}) {
574         print "<h3>$section</h3>\n";
575         print "<ul>\n";
576         output_highlight($args{'sections'}{$section});
577         print "</ul>\n";
578     }
579     print "<hr>\n";
580 }
581
582 sub output_section_xml(%) {
583     my %args = %{$_[0]};
584     my $section;
585     # print out each section
586     $lineprefix="   ";
587     foreach $section (@{$args{'sectionlist'}}) {
588         print "<refsect1>\n";
589         print "<title>$section</title>\n";
590         if ($section =~ m/EXAMPLE/i) {
591             print "<informalexample><programlisting>\n";
592         } else {
593             print "<para>\n";
594         }
595         output_highlight($args{'sections'}{$section});
596         if ($section =~ m/EXAMPLE/i) {
597             print "</programlisting></informalexample>\n";
598         } else {
599             print "</para>\n";
600         }
601         print "</refsect1>\n";
602     }
603 }
604
605 # output function in XML DocBook
606 sub output_function_xml(%) {
607     my %args = %{$_[0]};
608     my ($parameter, $section);
609     my $count;
610     my $id;
611
612     $id = "API-".$args{'function'};
613     $id =~ s/[^A-Za-z0-9]/-/g;
614
615     print "<refentry id=\"$id\">\n";
616     print "<refentryinfo>\n";
617     print " <title>LINUX</title>\n";
618     print " <productname>Kernel Hackers Manual</productname>\n";
619     print " <date>$man_date</date>\n";
620     print "</refentryinfo>\n";
621     print "<refmeta>\n";
622     print " <refentrytitle><phrase>".$args{'function'}."</phrase></refentrytitle>\n";
623     print " <manvolnum>9</manvolnum>\n";
624     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
625     print "</refmeta>\n";
626     print "<refnamediv>\n";
627     print " <refname>".$args{'function'}."</refname>\n";
628     print " <refpurpose>\n";
629     print "  ";
630     output_highlight ($args{'purpose'});
631     print " </refpurpose>\n";
632     print "</refnamediv>\n";
633
634     print "<refsynopsisdiv>\n";
635     print " <title>Synopsis</title>\n";
636     print "  <funcsynopsis><funcprototype>\n";
637     print "   <funcdef>".$args{'functiontype'}." ";
638     print "<function>".$args{'function'}." </function></funcdef>\n";
639
640     $count = 0;
641     if ($#{$args{'parameterlist'}} >= 0) {
642         foreach $parameter (@{$args{'parameterlist'}}) {
643             $type = $args{'parametertypes'}{$parameter};
644             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
645                 # pointer-to-function
646                 print "   <paramdef>$1<parameter>$parameter</parameter>)\n";
647                 print "     <funcparams>$2</funcparams></paramdef>\n";
648             } else {
649                 print "   <paramdef>".$type;
650                 print " <parameter>$parameter</parameter></paramdef>\n";
651             }
652         }
653     } else {
654         print "  <void/>\n";
655     }
656     print "  </funcprototype></funcsynopsis>\n";
657     print "</refsynopsisdiv>\n";
658
659     # print parameters
660     print "<refsect1>\n <title>Arguments</title>\n";
661     if ($#{$args{'parameterlist'}} >= 0) {
662         print " <variablelist>\n";
663         foreach $parameter (@{$args{'parameterlist'}}) {
664             my $parameter_name = $parameter;
665             $parameter_name =~ s/\[.*//;
666
667             print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
668             print "   <listitem>\n    <para>\n";
669             $lineprefix="     ";
670             output_highlight($args{'parameterdescs'}{$parameter_name});
671             print "    </para>\n   </listitem>\n  </varlistentry>\n";
672         }
673         print " </variablelist>\n";
674     } else {
675         print " <para>\n  None\n </para>\n";
676     }
677     print "</refsect1>\n";
678
679     output_section_xml(@_);
680     print "</refentry>\n\n";
681 }
682
683 # output struct in XML DocBook
684 sub output_struct_xml(%) {
685     my %args = %{$_[0]};
686     my ($parameter, $section);
687     my $id;
688
689     $id = "API-struct-".$args{'struct'};
690     $id =~ s/[^A-Za-z0-9]/-/g;
691
692     print "<refentry id=\"$id\">\n";
693     print "<refentryinfo>\n";
694     print " <title>LINUX</title>\n";
695     print " <productname>Kernel Hackers Manual</productname>\n";
696     print " <date>$man_date</date>\n";
697     print "</refentryinfo>\n";
698     print "<refmeta>\n";
699     print " <refentrytitle><phrase>".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
700     print " <manvolnum>9</manvolnum>\n";
701     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
702     print "</refmeta>\n";
703     print "<refnamediv>\n";
704     print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
705     print " <refpurpose>\n";
706     print "  ";
707     output_highlight ($args{'purpose'});
708     print " </refpurpose>\n";
709     print "</refnamediv>\n";
710
711     print "<refsynopsisdiv>\n";
712     print " <title>Synopsis</title>\n";
713     print "  <programlisting>\n";
714     print $args{'type'}." ".$args{'struct'}." {\n";
715     foreach $parameter (@{$args{'parameterlist'}}) {
716         if ($parameter =~ /^#/) {
717             print "$parameter\n";
718             next;
719         }
720
721         my $parameter_name = $parameter;
722         $parameter_name =~ s/\[.*//;
723
724         defined($args{'parameterdescs'}{$parameter_name}) || next;
725         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
726         $type = $args{'parametertypes'}{$parameter};
727         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
728             # pointer-to-function
729             print "  $1 $parameter) ($2);\n";
730         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
731             # bitfield
732             print "  $1 $parameter$2;\n";
733         } else {
734             print "  ".$type." ".$parameter.";\n";
735         }
736     }
737     print "};";
738     print "  </programlisting>\n";
739     print "</refsynopsisdiv>\n";
740
741     print " <refsect1>\n";
742     print "  <title>Members</title>\n";
743
744     print "  <variablelist>\n";
745     foreach $parameter (@{$args{'parameterlist'}}) {
746       ($parameter =~ /^#/) && next;
747
748       my $parameter_name = $parameter;
749       $parameter_name =~ s/\[.*//;
750
751       defined($args{'parameterdescs'}{$parameter_name}) || next;
752       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
753       print "    <varlistentry>";
754       print "      <term>$parameter</term>\n";
755       print "      <listitem><para>\n";
756       output_highlight($args{'parameterdescs'}{$parameter_name});
757       print "      </para></listitem>\n";
758       print "    </varlistentry>\n";
759     }
760     print "  </variablelist>\n";
761     print " </refsect1>\n";
762
763     output_section_xml(@_);
764
765     print "</refentry>\n\n";
766 }
767
768 # output enum in XML DocBook
769 sub output_enum_xml(%) {
770     my %args = %{$_[0]};
771     my ($parameter, $section);
772     my $count;
773     my $id;
774
775     $id = "API-enum-".$args{'enum'};
776     $id =~ s/[^A-Za-z0-9]/-/g;
777
778     print "<refentry id=\"$id\">\n";
779     print "<refentryinfo>\n";
780     print " <title>LINUX</title>\n";
781     print " <productname>Kernel Hackers Manual</productname>\n";
782     print " <date>$man_date</date>\n";
783     print "</refentryinfo>\n";
784     print "<refmeta>\n";
785     print " <refentrytitle><phrase>enum ".$args{'enum'}."</phrase></refentrytitle>\n";
786     print " <manvolnum>9</manvolnum>\n";
787     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
788     print "</refmeta>\n";
789     print "<refnamediv>\n";
790     print " <refname>enum ".$args{'enum'}."</refname>\n";
791     print " <refpurpose>\n";
792     print "  ";
793     output_highlight ($args{'purpose'});
794     print " </refpurpose>\n";
795     print "</refnamediv>\n";
796
797     print "<refsynopsisdiv>\n";
798     print " <title>Synopsis</title>\n";
799     print "  <programlisting>\n";
800     print "enum ".$args{'enum'}." {\n";
801     $count = 0;
802     foreach $parameter (@{$args{'parameterlist'}}) {
803         print "  $parameter";
804         if ($count != $#{$args{'parameterlist'}}) {
805             $count++;
806             print ",";
807         }
808         print "\n";
809     }
810     print "};";
811     print "  </programlisting>\n";
812     print "</refsynopsisdiv>\n";
813
814     print "<refsect1>\n";
815     print " <title>Constants</title>\n";
816     print "  <variablelist>\n";
817     foreach $parameter (@{$args{'parameterlist'}}) {
818       my $parameter_name = $parameter;
819       $parameter_name =~ s/\[.*//;
820
821       print "    <varlistentry>";
822       print "      <term>$parameter</term>\n";
823       print "      <listitem><para>\n";
824       output_highlight($args{'parameterdescs'}{$parameter_name});
825       print "      </para></listitem>\n";
826       print "    </varlistentry>\n";
827     }
828     print "  </variablelist>\n";
829     print "</refsect1>\n";
830
831     output_section_xml(@_);
832
833     print "</refentry>\n\n";
834 }
835
836 # output typedef in XML DocBook
837 sub output_typedef_xml(%) {
838     my %args = %{$_[0]};
839     my ($parameter, $section);
840     my $id;
841
842     $id = "API-typedef-".$args{'typedef'};
843     $id =~ s/[^A-Za-z0-9]/-/g;
844
845     print "<refentry id=\"$id\">\n";
846     print "<refentryinfo>\n";
847     print " <title>LINUX</title>\n";
848     print " <productname>Kernel Hackers Manual</productname>\n";
849     print " <date>$man_date</date>\n";
850     print "</refentryinfo>\n";
851     print "<refmeta>\n";
852     print " <refentrytitle><phrase>typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
853     print " <manvolnum>9</manvolnum>\n";
854     print "</refmeta>\n";
855     print "<refnamediv>\n";
856     print " <refname>typedef ".$args{'typedef'}."</refname>\n";
857     print " <refpurpose>\n";
858     print "  ";
859     output_highlight ($args{'purpose'});
860     print " </refpurpose>\n";
861     print "</refnamediv>\n";
862
863     print "<refsynopsisdiv>\n";
864     print " <title>Synopsis</title>\n";
865     print "  <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
866     print "</refsynopsisdiv>\n";
867
868     output_section_xml(@_);
869
870     print "</refentry>\n\n";
871 }
872
873 # output in XML DocBook
874 sub output_intro_xml(%) {
875     my %args = %{$_[0]};
876     my ($parameter, $section);
877     my $count;
878
879     my $id = $args{'module'};
880     $id =~ s/[^A-Za-z0-9]/-/g;
881
882     # print out each section
883     $lineprefix="   ";
884     foreach $section (@{$args{'sectionlist'}}) {
885         print "<refsect1>\n <title>$section</title>\n <para>\n";
886         if ($section =~ m/EXAMPLE/i) {
887             print "<example><para>\n";
888         }
889         output_highlight($args{'sections'}{$section});
890         if ($section =~ m/EXAMPLE/i) {
891             print "</para></example>\n";
892         }
893         print " </para>\n</refsect1>\n";
894     }
895
896     print "\n\n";
897 }
898
899 # output in XML DocBook
900 sub output_function_gnome {
901     my %args = %{$_[0]};
902     my ($parameter, $section);
903     my $count;
904     my $id;
905
906     $id = $args{'module'}."-".$args{'function'};
907     $id =~ s/[^A-Za-z0-9]/-/g;
908
909     print "<sect2>\n";
910     print " <title id=\"$id\">".$args{'function'}."</title>\n";
911
912     print "  <funcsynopsis>\n";
913     print "   <funcdef>".$args{'functiontype'}." ";
914     print "<function>".$args{'function'}." ";
915     print "</function></funcdef>\n";
916
917     $count = 0;
918     if ($#{$args{'parameterlist'}} >= 0) {
919         foreach $parameter (@{$args{'parameterlist'}}) {
920             $type = $args{'parametertypes'}{$parameter};
921             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
922                 # pointer-to-function
923                 print "   <paramdef>$1 <parameter>$parameter</parameter>)\n";
924                 print "     <funcparams>$2</funcparams></paramdef>\n";
925             } else {
926                 print "   <paramdef>".$type;
927                 print " <parameter>$parameter</parameter></paramdef>\n";
928             }
929         }
930     } else {
931         print "  <void>\n";
932     }
933     print "  </funcsynopsis>\n";
934     if ($#{$args{'parameterlist'}} >= 0) {
935         print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
936         print "<tgroup cols=\"2\">\n";
937         print "<colspec colwidth=\"2*\">\n";
938         print "<colspec colwidth=\"8*\">\n";
939         print "<tbody>\n";
940         foreach $parameter (@{$args{'parameterlist'}}) {
941             my $parameter_name = $parameter;
942             $parameter_name =~ s/\[.*//;
943
944             print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
945             print "   <entry>\n";
946             $lineprefix="     ";
947             output_highlight($args{'parameterdescs'}{$parameter_name});
948             print "    </entry></row>\n";
949         }
950         print " </tbody></tgroup></informaltable>\n";
951     } else {
952         print " <para>\n  None\n </para>\n";
953     }
954
955     # print out each section
956     $lineprefix="   ";
957     foreach $section (@{$args{'sectionlist'}}) {
958         print "<simplesect>\n <title>$section</title>\n";
959         if ($section =~ m/EXAMPLE/i) {
960             print "<example><programlisting>\n";
961         } else {
962         }
963         print "<para>\n";
964         output_highlight($args{'sections'}{$section});
965         print "</para>\n";
966         if ($section =~ m/EXAMPLE/i) {
967             print "</programlisting></example>\n";
968         } else {
969         }
970         print " </simplesect>\n";
971     }
972
973     print "</sect2>\n\n";
974 }
975
976 ##
977 # output function in man
978 sub output_function_man(%) {
979     my %args = %{$_[0]};
980     my ($parameter, $section);
981     my $count;
982
983     print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
984
985     print ".SH NAME\n";
986     print $args{'function'}." \\- ".$args{'purpose'}."\n";
987
988     print ".SH SYNOPSIS\n";
989     if ($args{'functiontype'} ne "") {
990         print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
991     } else {
992         print ".B \"".$args{'function'}."\n";
993     }
994     $count = 0;
995     my $parenth = "(";
996     my $post = ",";
997     foreach my $parameter (@{$args{'parameterlist'}}) {
998         if ($count == $#{$args{'parameterlist'}}) {
999             $post = ");";
1000         }
1001         $type = $args{'parametertypes'}{$parameter};
1002         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1003             # pointer-to-function
1004             print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
1005         } else {
1006             $type =~ s/([^\*])$/$1 /;
1007             print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
1008         }
1009         $count++;
1010         $parenth = "";
1011     }
1012
1013     print ".SH ARGUMENTS\n";
1014     foreach $parameter (@{$args{'parameterlist'}}) {
1015         my $parameter_name = $parameter;
1016         $parameter_name =~ s/\[.*//;
1017
1018         print ".IP \"".$parameter."\" 12\n";
1019         output_highlight($args{'parameterdescs'}{$parameter_name});
1020     }
1021     foreach $section (@{$args{'sectionlist'}}) {
1022         print ".SH \"", uc $section, "\"\n";
1023         output_highlight($args{'sections'}{$section});
1024     }
1025 }
1026
1027 ##
1028 # output enum in man
1029 sub output_enum_man(%) {
1030     my %args = %{$_[0]};
1031     my ($parameter, $section);
1032     my $count;
1033
1034     print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
1035
1036     print ".SH NAME\n";
1037     print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n";
1038
1039     print ".SH SYNOPSIS\n";
1040     print "enum ".$args{'enum'}." {\n";
1041     $count = 0;
1042     foreach my $parameter (@{$args{'parameterlist'}}) {
1043         print ".br\n.BI \"    $parameter\"\n";
1044         if ($count == $#{$args{'parameterlist'}}) {
1045             print "\n};\n";
1046             last;
1047         }
1048         else {
1049             print ", \n.br\n";
1050         }
1051         $count++;
1052     }
1053
1054     print ".SH Constants\n";
1055     foreach $parameter (@{$args{'parameterlist'}}) {
1056         my $parameter_name = $parameter;
1057         $parameter_name =~ s/\[.*//;
1058
1059         print ".IP \"".$parameter."\" 12\n";
1060         output_highlight($args{'parameterdescs'}{$parameter_name});
1061     }
1062     foreach $section (@{$args{'sectionlist'}}) {
1063         print ".SH \"$section\"\n";
1064         output_highlight($args{'sections'}{$section});
1065     }
1066 }
1067
1068 ##
1069 # output struct in man
1070 sub output_struct_man(%) {
1071     my %args = %{$_[0]};
1072     my ($parameter, $section);
1073
1074     print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n";
1075
1076     print ".SH NAME\n";
1077     print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
1078
1079     print ".SH SYNOPSIS\n";
1080     print $args{'type'}." ".$args{'struct'}." {\n.br\n";
1081
1082     foreach my $parameter (@{$args{'parameterlist'}}) {
1083         if ($parameter =~ /^#/) {
1084             print ".BI \"$parameter\"\n.br\n";
1085             next;
1086         }
1087         my $parameter_name = $parameter;
1088         $parameter_name =~ s/\[.*//;
1089
1090         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1091         $type = $args{'parametertypes'}{$parameter};
1092         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1093             # pointer-to-function
1094             print ".BI \"    ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
1095         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1096             # bitfield
1097             print ".BI \"    ".$1."\ \" ".$parameter.$2." \""."\"\n;\n";
1098         } else {
1099             $type =~ s/([^\*])$/$1 /;
1100             print ".BI \"    ".$type."\" ".$parameter." \""."\"\n;\n";
1101         }
1102         print "\n.br\n";
1103     }
1104     print "};\n.br\n";
1105
1106     print ".SH Members\n";
1107     foreach $parameter (@{$args{'parameterlist'}}) {
1108         ($parameter =~ /^#/) && next;
1109
1110         my $parameter_name = $parameter;
1111         $parameter_name =~ s/\[.*//;
1112
1113         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1114         print ".IP \"".$parameter."\" 12\n";
1115         output_highlight($args{'parameterdescs'}{$parameter_name});
1116     }
1117     foreach $section (@{$args{'sectionlist'}}) {
1118         print ".SH \"$section\"\n";
1119         output_highlight($args{'sections'}{$section});
1120     }
1121 }
1122
1123 ##
1124 # output typedef in man
1125 sub output_typedef_man(%) {
1126     my %args = %{$_[0]};
1127     my ($parameter, $section);
1128
1129     print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
1130
1131     print ".SH NAME\n";
1132     print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n";
1133
1134     foreach $section (@{$args{'sectionlist'}}) {
1135         print ".SH \"$section\"\n";
1136         output_highlight($args{'sections'}{$section});
1137     }
1138 }
1139
1140 sub output_intro_man(%) {
1141     my %args = %{$_[0]};
1142     my ($parameter, $section);
1143     my $count;
1144
1145     print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
1146
1147     foreach $section (@{$args{'sectionlist'}}) {
1148         print ".SH \"$section\"\n";
1149         output_highlight($args{'sections'}{$section});
1150     }
1151 }
1152
1153 ##
1154 # output in text
1155 sub output_function_text(%) {
1156     my %args = %{$_[0]};
1157     my ($parameter, $section);
1158     my $start;
1159
1160     print "Name:\n\n";
1161     print $args{'function'}." - ".$args{'purpose'}."\n";
1162
1163     print "\nSynopsis:\n\n";
1164     if ($args{'functiontype'} ne "") {
1165         $start = $args{'functiontype'}." ".$args{'function'}." (";
1166     } else {
1167         $start = $args{'function'}." (";
1168     }
1169     print $start;
1170
1171     my $count = 0;
1172     foreach my $parameter (@{$args{'parameterlist'}}) {
1173         $type = $args{'parametertypes'}{$parameter};
1174         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1175             # pointer-to-function
1176             print $1.$parameter.") (".$2;
1177         } else {
1178             print $type." ".$parameter;
1179         }
1180         if ($count != $#{$args{'parameterlist'}}) {
1181             $count++;
1182             print ",\n";
1183             print " " x length($start);
1184         } else {
1185             print ");\n\n";
1186         }
1187     }
1188
1189     print "Arguments:\n\n";
1190     foreach $parameter (@{$args{'parameterlist'}}) {
1191         my $parameter_name = $parameter;
1192         $parameter_name =~ s/\[.*//;
1193
1194         print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n";
1195     }
1196     output_section_text(@_);
1197 }
1198
1199 #output sections in text
1200 sub output_section_text(%) {
1201     my %args = %{$_[0]};
1202     my $section;
1203
1204     print "\n";
1205     foreach $section (@{$args{'sectionlist'}}) {
1206         print "$section:\n\n";
1207         output_highlight($args{'sections'}{$section});
1208     }
1209     print "\n\n";
1210 }
1211
1212 # output enum in text
1213 sub output_enum_text(%) {
1214     my %args = %{$_[0]};
1215     my ($parameter);
1216     my $count;
1217     print "Enum:\n\n";
1218
1219     print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n";
1220     print "enum ".$args{'enum'}." {\n";
1221     $count = 0;
1222     foreach $parameter (@{$args{'parameterlist'}}) {
1223         print "\t$parameter";
1224         if ($count != $#{$args{'parameterlist'}}) {
1225             $count++;
1226             print ",";
1227         }
1228         print "\n";
1229     }
1230     print "};\n\n";
1231
1232     print "Constants:\n\n";
1233     foreach $parameter (@{$args{'parameterlist'}}) {
1234         print "$parameter\n\t";
1235         print $args{'parameterdescs'}{$parameter}."\n";
1236     }
1237
1238     output_section_text(@_);
1239 }
1240
1241 # output typedef in text
1242 sub output_typedef_text(%) {
1243     my %args = %{$_[0]};
1244     my ($parameter);
1245     my $count;
1246     print "Typedef:\n\n";
1247
1248     print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n";
1249     output_section_text(@_);
1250 }
1251
1252 # output struct as text
1253 sub output_struct_text(%) {
1254     my %args = %{$_[0]};
1255     my ($parameter);
1256
1257     print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n";
1258     print $args{'type'}." ".$args{'struct'}." {\n";
1259     foreach $parameter (@{$args{'parameterlist'}}) {
1260         if ($parameter =~ /^#/) {
1261             print "$parameter\n";
1262             next;
1263         }
1264
1265         my $parameter_name = $parameter;
1266         $parameter_name =~ s/\[.*//;
1267
1268         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1269         $type = $args{'parametertypes'}{$parameter};
1270         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1271             # pointer-to-function
1272             print "\t$1 $parameter) ($2);\n";
1273         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1274             # bitfield
1275             print "\t$1 $parameter$2;\n";
1276         } else {
1277             print "\t".$type." ".$parameter.";\n";
1278         }
1279     }
1280     print "};\n\n";
1281
1282     print "Members:\n\n";
1283     foreach $parameter (@{$args{'parameterlist'}}) {
1284         ($parameter =~ /^#/) && next;
1285
1286         my $parameter_name = $parameter;
1287         $parameter_name =~ s/\[.*//;
1288
1289         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1290         print "$parameter\n\t";
1291         print $args{'parameterdescs'}{$parameter_name}."\n";
1292     }
1293     print "\n";
1294     output_section_text(@_);
1295 }
1296
1297 sub output_intro_text(%) {
1298     my %args = %{$_[0]};
1299     my ($parameter, $section);
1300
1301     foreach $section (@{$args{'sectionlist'}}) {
1302         print " $section:\n";
1303         print "    -> ";
1304         output_highlight($args{'sections'}{$section});
1305     }
1306 }
1307
1308 ##
1309 # generic output function for all types (function, struct/union, typedef, enum);
1310 # calls the generated, variable output_ function name based on
1311 # functype and output_mode
1312 sub output_declaration {
1313     no strict 'refs';
1314     my $name = shift;
1315     my $functype = shift;
1316     my $func = "output_${functype}_$output_mode";
1317     if (($function_only==0) ||
1318         ( $function_only == 1 && defined($function_table{$name})) ||
1319         ( $function_only == 2 && !defined($function_table{$name})))
1320     {
1321         &$func(@_);
1322         $section_counter++;
1323     }
1324 }
1325
1326 ##
1327 # generic output function - calls the right one based on current output mode.
1328 sub output_intro {
1329     no strict 'refs';
1330     my $func = "output_intro_".$output_mode;
1331     &$func(@_);
1332     $section_counter++;
1333 }
1334
1335 ##
1336 # takes a declaration (struct, union, enum, typedef) and
1337 # invokes the right handler. NOT called for functions.
1338 sub dump_declaration($$) {
1339     no strict 'refs';
1340     my ($prototype, $file) = @_;
1341     my $func = "dump_".$decl_type;
1342     &$func(@_);
1343 }
1344
1345 sub dump_union($$) {
1346     dump_struct(@_);
1347 }
1348
1349 sub dump_struct($$) {
1350     my $x = shift;
1351     my $file = shift;
1352
1353     if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
1354         $declaration_name = $2;
1355         my $members = $3;
1356
1357         # ignore embedded structs or unions
1358         $members =~ s/{.*?}//g;
1359
1360         # ignore members marked private:
1361         $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
1362         $members =~ s/\/\*.*?private:.*//gos;
1363         # strip comments:
1364         $members =~ s/\/\*.*?\*\///gos;
1365
1366         create_parameterlist($members, ';', $file);
1367
1368         output_declaration($declaration_name,
1369                            'struct',
1370                            {'struct' => $declaration_name,
1371                             'module' => $modulename,
1372                             'parameterlist' => \@parameterlist,
1373                             'parameterdescs' => \%parameterdescs,
1374                             'parametertypes' => \%parametertypes,
1375                             'sectionlist' => \@sectionlist,
1376                             'sections' => \%sections,
1377                             'purpose' => $declaration_purpose,
1378                             'type' => $decl_type
1379                            });
1380     }
1381     else {
1382         print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
1383         ++$errors;
1384     }
1385 }
1386
1387 sub dump_enum($$) {
1388     my $x = shift;
1389     my $file = shift;
1390
1391     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1392     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
1393         $declaration_name = $1;
1394         my $members = $2;
1395
1396         foreach my $arg (split ',', $members) {
1397             $arg =~ s/^\s*(\w+).*/$1/;
1398             push @parameterlist, $arg;
1399             if (!$parameterdescs{$arg}) {
1400                 $parameterdescs{$arg} = $undescribed;
1401                 print STDERR "Warning(${file}:$.): Enum value '$arg' ".
1402                     "not described in enum '$declaration_name'\n";
1403             }
1404
1405         }
1406
1407         output_declaration($declaration_name,
1408                            'enum',
1409                            {'enum' => $declaration_name,
1410                             'module' => $modulename,
1411                             'parameterlist' => \@parameterlist,
1412                             'parameterdescs' => \%parameterdescs,
1413                             'sectionlist' => \@sectionlist,
1414                             'sections' => \%sections,
1415                             'purpose' => $declaration_purpose
1416                            });
1417     }
1418     else {
1419         print STDERR "Error(${file}:$.): Cannot parse enum!\n";
1420         ++$errors;
1421     }
1422 }
1423
1424 sub dump_typedef($$) {
1425     my $x = shift;
1426     my $file = shift;
1427
1428     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1429     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
1430         $x =~ s/\(*.\)\s*;$/;/;
1431         $x =~ s/\[*.\]\s*;$/;/;
1432     }
1433
1434     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
1435         $declaration_name = $1;
1436
1437         output_declaration($declaration_name,
1438                            'typedef',
1439                            {'typedef' => $declaration_name,
1440                             'module' => $modulename,
1441                             'sectionlist' => \@sectionlist,
1442                             'sections' => \%sections,
1443                             'purpose' => $declaration_purpose
1444                            });
1445     }
1446     else {
1447         print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
1448         ++$errors;
1449     }
1450 }
1451
1452 sub create_parameterlist($$$) {
1453     my $args = shift;
1454     my $splitter = shift;
1455     my $file = shift;
1456     my $type;
1457     my $param;
1458
1459     # temporarily replace commas inside function pointer definition
1460     while ($args =~ /(\([^\),]+),/) {
1461         $args =~ s/(\([^\),]+),/$1#/g;
1462     }
1463
1464     foreach my $arg (split($splitter, $args)) {
1465         # strip comments
1466         $arg =~ s/\/\*.*\*\///;
1467         # strip leading/trailing spaces
1468         $arg =~ s/^\s*//;
1469         $arg =~ s/\s*$//;
1470         $arg =~ s/\s+/ /;
1471
1472         if ($arg =~ /^#/) {
1473             # Treat preprocessor directive as a typeless variable just to fill
1474             # corresponding data structures "correctly". Catch it later in
1475             # output_* subs.
1476             push_parameter($arg, "", $file);
1477         } elsif ($arg =~ m/\(.*\*/) {
1478             # pointer-to-function
1479             $arg =~ tr/#/,/;
1480             $arg =~ m/[^\(]+\(\*\s*([^\)]+)\)/;
1481             $param = $1;
1482             $type = $arg;
1483             $type =~ s/([^\(]+\(\*)$param/$1/;
1484             push_parameter($param, $type, $file);
1485         } elsif ($arg) {
1486             $arg =~ s/\s*:\s*/:/g;
1487             $arg =~ s/\s*\[/\[/g;
1488
1489             my @args = split('\s*,\s*', $arg);
1490             if ($args[0] =~ m/\*/) {
1491                 $args[0] =~ s/(\*+)\s*/ $1/;
1492             }
1493
1494             my @first_arg;
1495             if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
1496                     shift @args;
1497                     push(@first_arg, split('\s+', $1));
1498                     push(@first_arg, $2);
1499             } else {
1500                     @first_arg = split('\s+', shift @args);
1501             }
1502
1503             unshift(@args, pop @first_arg);
1504             $type = join " ", @first_arg;
1505
1506             foreach $param (@args) {
1507                 if ($param =~ m/^(\*+)\s*(.*)/) {
1508                     push_parameter($2, "$type $1", $file);
1509                 }
1510                 elsif ($param =~ m/(.*?):(\d+)/) {
1511                     push_parameter($1, "$type:$2", $file)
1512                 }
1513                 else {
1514                     push_parameter($param, $type, $file);
1515                 }
1516             }
1517         }
1518     }
1519 }
1520
1521 sub push_parameter($$$) {
1522         my $param = shift;
1523         my $type = shift;
1524         my $file = shift;
1525
1526         if (($anon_struct_union == 1) && ($type eq "") &&
1527             ($param eq "}")) {
1528                 return;         # ignore the ending }; from anon. struct/union
1529         }
1530
1531         $anon_struct_union = 0;
1532         my $param_name = $param;
1533         $param_name =~ s/\[.*//;
1534
1535         if ($type eq "" && $param =~ /\.\.\.$/)
1536         {
1537             $type="";
1538             $parameterdescs{$param} = "variable arguments";
1539         }
1540         elsif ($type eq "" && ($param eq "" or $param eq "void"))
1541         {
1542             $type="";
1543             $param="void";
1544             $parameterdescs{void} = "no arguments";
1545         }
1546         elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
1547         # handle unnamed (anonymous) union or struct:
1548         {
1549                 $type = $param;
1550                 $param = "{unnamed_" . $param . "}";
1551                 $parameterdescs{$param} = "anonymous\n";
1552                 $anon_struct_union = 1;
1553         }
1554
1555         # warn if parameter has no description
1556         # (but ignore ones starting with # as these are not parameters
1557         # but inline preprocessor statements);
1558         # also ignore unnamed structs/unions;
1559         if (!$anon_struct_union) {
1560         if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
1561
1562             $parameterdescs{$param_name} = $undescribed;
1563
1564             if (($type eq 'function') || ($type eq 'enum')) {
1565                 print STDERR "Warning(${file}:$.): Function parameter ".
1566                     "or member '$param' not " .
1567                     "described in '$declaration_name'\n";
1568             }
1569             print STDERR "Warning(${file}:$.):".
1570                          " No description found for parameter '$param'\n";
1571             ++$warnings;
1572         }
1573         }
1574
1575         push @parameterlist, $param;
1576         $parametertypes{$param} = $type;
1577 }
1578
1579 ##
1580 # takes a function prototype and the name of the current file being
1581 # processed and spits out all the details stored in the global
1582 # arrays/hashes.
1583 sub dump_function($$) {
1584     my $prototype = shift;
1585     my $file = shift;
1586
1587     $prototype =~ s/^static +//;
1588     $prototype =~ s/^extern +//;
1589     $prototype =~ s/^fastcall +//;
1590     $prototype =~ s/^asmlinkage +//;
1591     $prototype =~ s/^inline +//;
1592     $prototype =~ s/^__inline__ +//;
1593     $prototype =~ s/^__inline +//;
1594     $prototype =~ s/^__always_inline +//;
1595     $prototype =~ s/^noinline +//;
1596     $prototype =~ s/__devinit +//;
1597     $prototype =~ s/^#define\s+//; #ak added
1598     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
1599
1600     # Yes, this truly is vile.  We are looking for:
1601     # 1. Return type (may be nothing if we're looking at a macro)
1602     # 2. Function name
1603     # 3. Function parameters.
1604     #
1605     # All the while we have to watch out for function pointer parameters
1606     # (which IIRC is what the two sections are for), C types (these
1607     # regexps don't even start to express all the possibilities), and
1608     # so on.
1609     #
1610     # If you mess with these regexps, it's a good idea to check that
1611     # the following functions' documentation still comes out right:
1612     # - parport_register_device (function pointer parameters)
1613     # - atomic_set (macro)
1614     # - pci_match_device, __copy_to_user (long return type)
1615
1616     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1617         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1618         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1619         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1620         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1621         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1622         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1623         $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1624         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1625         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1626         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1627         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1628         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1629         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1630         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1631         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1632         $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
1633         $return_type = $1;
1634         $declaration_name = $2;
1635         my $args = $3;
1636
1637         create_parameterlist($args, ',', $file);
1638     } else {
1639         print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
1640         ++$errors;
1641         return;
1642     }
1643
1644     output_declaration($declaration_name,
1645                        'function',
1646                        {'function' => $declaration_name,
1647                         'module' => $modulename,
1648                         'functiontype' => $return_type,
1649                         'parameterlist' => \@parameterlist,
1650                         'parameterdescs' => \%parameterdescs,
1651                         'parametertypes' => \%parametertypes,
1652                         'sectionlist' => \@sectionlist,
1653                         'sections' => \%sections,
1654                         'purpose' => $declaration_purpose
1655                        });
1656 }
1657
1658 sub process_file($);
1659
1660 # Read the file that maps relative names to absolute names for
1661 # separate source and object directories and for shadow trees.
1662 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
1663         my ($relname, $absname);
1664         while(<SOURCE_MAP>) {
1665                 chop();
1666                 ($relname, $absname) = (split())[0..1];
1667                 $relname =~ s:^/+::;
1668                 $source_map{$relname} = $absname;
1669         }
1670         close(SOURCE_MAP);
1671 }
1672
1673 if ($filelist) {
1674         open(FLIST,"<$filelist") or die "Can't open file list $filelist";
1675         while(<FLIST>) {
1676                 chop;
1677                 process_file($_);
1678         }
1679 }
1680
1681 foreach (@ARGV) {
1682     chomp;
1683     process_file($_);
1684 }
1685 if ($verbose && $errors) {
1686   print STDERR "$errors errors\n";
1687 }
1688 if ($verbose && $warnings) {
1689   print STDERR "$warnings warnings\n";
1690 }
1691
1692 exit($errors);
1693
1694 sub reset_state {
1695     $function = "";
1696     %constants = ();
1697     %parameterdescs = ();
1698     %parametertypes = ();
1699     @parameterlist = ();
1700     %sections = ();
1701     @sectionlist = ();
1702     $prototype = "";
1703
1704     $state = 0;
1705 }
1706
1707 sub process_state3_function($$) {
1708     my $x = shift;
1709     my $file = shift;
1710
1711     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1712
1713     if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) {
1714         # do nothing
1715     }
1716     elsif ($x =~ /([^\{]*)/) {
1717         $prototype .= $1;
1718     }
1719     if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {
1720         $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
1721         $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1722         $prototype =~ s@^\s+@@gos; # strip leading spaces
1723         dump_function($prototype,$file);
1724         reset_state();
1725     }
1726 }
1727
1728 sub process_state3_type($$) {
1729     my $x = shift;
1730     my $file = shift;
1731
1732     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1733     $x =~ s@^\s+@@gos; # strip leading spaces
1734     $x =~ s@\s+$@@gos; # strip trailing spaces
1735     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1736
1737     if ($x =~ /^#/) {
1738         # To distinguish preprocessor directive from regular declaration later.
1739         $x .= ";";
1740     }
1741
1742     while (1) {
1743         if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
1744             $prototype .= $1 . $2;
1745             ($2 eq '{') && $brcount++;
1746             ($2 eq '}') && $brcount--;
1747             if (($2 eq ';') && ($brcount == 0)) {
1748                 dump_declaration($prototype,$file);
1749                 reset_state();
1750                 last;
1751             }
1752             $x = $3;
1753         } else {
1754             $prototype .= $x;
1755             last;
1756         }
1757     }
1758 }
1759
1760 # xml_escape: replace <, >, and & in the text stream;
1761 #
1762 # however, formatting controls that are generated internally/locally in the
1763 # kernel-doc script are not escaped here; instead, they begin life like
1764 # $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
1765 # are converted to their mnemonic-expected output, without the 4 * '\' & ':',
1766 # just before actual output; (this is done by local_unescape())
1767 sub xml_escape($) {
1768         my $text = shift;
1769         if (($output_mode eq "text") || ($output_mode eq "man")) {
1770                 return $text;
1771         }
1772         $text =~ s/\&/\\\\\\amp;/g;
1773         $text =~ s/\</\\\\\\lt;/g;
1774         $text =~ s/\>/\\\\\\gt;/g;
1775         return $text;
1776 }
1777
1778 # convert local escape strings to html
1779 # local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
1780 sub local_unescape($) {
1781         my $text = shift;
1782         if (($output_mode eq "text") || ($output_mode eq "man")) {
1783                 return $text;
1784         }
1785         $text =~ s/\\\\\\\\lt:/</g;
1786         $text =~ s/\\\\\\\\gt:/>/g;
1787         return $text;
1788 }
1789
1790 sub process_file($) {
1791     my $file;
1792     my $identifier;
1793     my $func;
1794     my $descr;
1795     my $initial_section_counter = $section_counter;
1796
1797     if (defined($ENV{'SRCTREE'})) {
1798         $file = "$ENV{'SRCTREE'}" . "/" . "@_";
1799     }
1800     else {
1801         $file = "@_";
1802     }
1803     if (defined($source_map{$file})) {
1804         $file = $source_map{$file};
1805     }
1806
1807     if (!open(IN,"<$file")) {
1808         print STDERR "Error: Cannot open file $file\n";
1809         ++$errors;
1810         return;
1811     }
1812
1813     $section_counter = 0;
1814     while (<IN>) {
1815         if ($state == 0) {
1816             if (/$doc_start/o) {
1817                 $state = 1;             # next line is always the function name
1818                 $in_doc_sect = 0;
1819             }
1820         } elsif ($state == 1) { # this line is the function name (always)
1821             if (/$doc_block/o) {
1822                 $state = 4;
1823                 $contents = "";
1824                 if ( $1 eq "" ) {
1825                         $section = $section_intro;
1826                 } else {
1827                         $section = $1;
1828                 }
1829             }
1830             elsif (/$doc_decl/o) {
1831                 $identifier = $1;
1832                 if (/\s*([\w\s]+?)\s*-/) {
1833                     $identifier = $1;
1834                 }
1835
1836                 $state = 2;
1837                 if (/-(.*)/) {
1838                     # strip leading/trailing/multiple spaces
1839                     $descr= $1;
1840                     $descr =~ s/^\s*//;
1841                     $descr =~ s/\s*$//;
1842                     $descr =~ s/\s+/ /;
1843                     $declaration_purpose = xml_escape($descr);
1844                 } else {
1845                     $declaration_purpose = "";
1846                 }
1847                 if ($identifier =~ m/^struct/) {
1848                     $decl_type = 'struct';
1849                 } elsif ($identifier =~ m/^union/) {
1850                     $decl_type = 'union';
1851                 } elsif ($identifier =~ m/^enum/) {
1852                     $decl_type = 'enum';
1853                 } elsif ($identifier =~ m/^typedef/) {
1854                     $decl_type = 'typedef';
1855                 } else {
1856                     $decl_type = 'function';
1857                 }
1858
1859                 if ($verbose) {
1860                     print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
1861                 }
1862             } else {
1863                 print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
1864                 " - I thought it was a doc line\n";
1865                 ++$warnings;
1866                 $state = 0;
1867             }
1868         } elsif ($state == 2) { # look for head: lines, and include content
1869             if (/$doc_sect/o) {
1870                 $newsection = $1;
1871                 $newcontents = $2;
1872
1873                 if ($contents ne "") {
1874                     if (!$in_doc_sect && $verbose) {
1875                         print STDERR "Warning(${file}:$.): contents before sections\n";
1876                         ++$warnings;
1877                     }
1878                     dump_section($section, xml_escape($contents));
1879                     $section = $section_default;
1880                 }
1881
1882                 $in_doc_sect = 1;
1883                 $contents = $newcontents;
1884                 if ($contents ne "") {
1885                     while ((substr($contents, 0, 1) eq " ") ||
1886                         substr($contents, 0, 1) eq "\t") {
1887                             $contents = substr($contents, 1);
1888                     }
1889                     $contents .= "\n";
1890                 }
1891                 $section = $newsection;
1892             } elsif (/$doc_end/) {
1893
1894                 if ($contents ne "") {
1895                     dump_section($section, xml_escape($contents));
1896                     $section = $section_default;
1897                     $contents = "";
1898                 }
1899
1900                 $prototype = "";
1901                 $state = 3;
1902                 $brcount = 0;
1903 #               print STDERR "end of doc comment, looking for prototype\n";
1904             } elsif (/$doc_content/) {
1905                 # miguel-style comment kludge, look for blank lines after
1906                 # @parameter line to signify start of description
1907                 if ($1 eq "" &&
1908                         ($section =~ m/^@/ || $section eq $section_context)) {
1909                     dump_section($section, xml_escape($contents));
1910                     $section = $section_default;
1911                     $contents = "";
1912                 } else {
1913                     $contents .= $1."\n";
1914                 }
1915             } else {
1916                 # i dont know - bad line?  ignore.
1917                 print STDERR "Warning(${file}:$.): bad line: $_";
1918                 ++$warnings;
1919             }
1920         } elsif ($state == 3) { # scanning for function '{' (end of prototype)
1921             if ($decl_type eq 'function') {
1922                 process_state3_function($_, $file);
1923             } else {
1924                 process_state3_type($_, $file);
1925             }
1926         } elsif ($state == 4) {
1927                 # Documentation block
1928                 if (/$doc_block/) {
1929                         dump_section($section, xml_escape($contents));
1930                         output_intro({'sectionlist' => \@sectionlist,
1931                                       'sections' => \%sections });
1932                         $contents = "";
1933                         $function = "";
1934                         %constants = ();
1935                         %parameterdescs = ();
1936                         %parametertypes = ();
1937                         @parameterlist = ();
1938                         %sections = ();
1939                         @sectionlist = ();
1940                         $prototype = "";
1941                         if ( $1 eq "" ) {
1942                                 $section = $section_intro;
1943                         } else {
1944                                 $section = $1;
1945                         }
1946                 }
1947                 elsif (/$doc_end/)
1948                 {
1949                         dump_section($section, xml_escape($contents));
1950                         output_intro({'sectionlist' => \@sectionlist,
1951                                       'sections' => \%sections });
1952                         $contents = "";
1953                         $function = "";
1954                         %constants = ();
1955                         %parameterdescs = ();
1956                         %parametertypes = ();
1957                         @parameterlist = ();
1958                         %sections = ();
1959                         @sectionlist = ();
1960                         $prototype = "";
1961                         $state = 0;
1962                 }
1963                 elsif (/$doc_content/)
1964                 {
1965                         if ( $1 eq "" )
1966                         {
1967                                 $contents .= $blankline;
1968                         }
1969                         else
1970                         {
1971                                 $contents .= $1 . "\n";
1972                         }
1973                 }
1974         }
1975     }
1976     if ($initial_section_counter == $section_counter) {
1977         print STDERR "Warning(${file}): no structured comments found\n";
1978         if ($output_mode eq "xml") {
1979             # The template wants at least one RefEntry here; make one.
1980             print "<refentry>\n";
1981             print " <refnamediv>\n";
1982             print "  <refname>\n";
1983             print "   ${file}\n";
1984             print "  </refname>\n";
1985             print "  <refpurpose>\n";
1986             print "   Document generation inconsistency\n";
1987             print "  </refpurpose>\n";
1988             print " </refnamediv>\n";
1989             print " <refsect1>\n";
1990             print "  <title>\n";
1991             print "   Oops\n";
1992             print "  </title>\n";
1993             print "  <warning>\n";
1994             print "   <para>\n";
1995             print "    The template for this document tried to insert\n";
1996             print "    the structured comment from the file\n";
1997             print "    <filename>${file}</filename> at this point,\n";
1998             print "    but none was found.\n";
1999             print "    This dummy section is inserted to allow\n";
2000             print "    generation to continue.\n";
2001             print "   </para>\n";
2002             print "  </warning>\n";
2003             print " </refsect1>\n";
2004             print "</refentry>\n";
2005         }
2006     }
2007 }