kernel-doc/rst: use *undescribed* instead of _undescribed_
[cascardo/linux.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-2012  Randy Dunlap                         ##
9 ## Copyright (C) 2012  Dan Luedtke                               ##
10 ##                                                               ##
11 ## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
12 ## Copyright (c) 2000 MontaVista Software, Inc.                  ##
13 ##                                                               ##
14 ## This software falls under the GNU General Public License.     ##
15 ## Please read the COPYING file for more information             ##
16
17 # 18/01/2001 -  Cleanups
18 #               Functions prototyped as foo(void) same as foo()
19 #               Stop eval'ing where we don't need to.
20 # -- huggie@earth.li
21
22 # 27/06/2001 -  Allowed whitespace after initial "/**" and
23 #               allowed comments before function declarations.
24 # -- Christian Kreibich <ck@whoop.org>
25
26 # Still to do:
27 #       - add perldoc documentation
28 #       - Look more closely at some of the scarier bits :)
29
30 # 26/05/2001 -  Support for separate source and object trees.
31 #               Return error code.
32 #               Keith Owens <kaos@ocs.com.au>
33
34 # 23/09/2001 - Added support for typedefs, structs, enums and unions
35 #              Support for Context section; can be terminated using empty line
36 #              Small fixes (like spaces vs. \s in regex)
37 # -- Tim Jansen <tim@tjansen.de>
38
39 # 25/07/2012 - Added support for HTML5
40 # -- Dan Luedtke <mail@danrl.de>
41
42 sub usage {
43     my $message = <<"EOF";
44 Usage: $0 [OPTION ...] FILE ...
45
46 Read C language source or header FILEs, extract embedded documentation comments,
47 and print formatted documentation to standard output.
48
49 The documentation comments are identified by "/**" opening comment mark. See
50 Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax.
51
52 Output format selection (mutually exclusive):
53   -docbook              Output DocBook format.
54   -html                 Output HTML format.
55   -html5                Output HTML5 format.
56   -list                 Output symbol list format. This is for use by docproc.
57   -man                  Output troff manual page format. This is the default.
58   -rst                  Output reStructuredText format.
59   -text                 Output plain text format.
60
61 Output selection (mutually exclusive):
62   -export               Only output documentation for symbols that have been
63                         exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
64                         in the same FILE.
65   -internal             Only output documentation for symbols that have NOT been
66                         exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
67                         in the same FILE.
68   -function NAME        Only output documentation for the given function(s)
69                         or DOC: section title(s). All other functions and DOC:
70                         sections are ignored. May be specified multiple times.
71   -nofunction NAME      Do NOT output documentation for the given function(s);
72                         only output documentation for the other functions and
73                         DOC: sections. May be specified multiple times.
74
75 Output selection modifiers:
76   -no-doc-sections      Do not output DOC: sections.
77
78 Other parameters:
79   -v                    Verbose output, more warnings and other information.
80   -h                    Print this help.
81
82 EOF
83     print $message;
84     exit 1;
85 }
86
87 #
88 # format of comments.
89 # In the following table, (...)? signifies optional structure.
90 #                         (...)* signifies 0 or more structure elements
91 # /**
92 #  * function_name(:)? (- short description)?
93 # (* @parameterx: (description of parameter x)?)*
94 # (* a blank line)?
95 #  * (Description:)? (Description of function)?
96 #  * (section header: (section description)? )*
97 #  (*)?*/
98 #
99 # So .. the trivial example would be:
100 #
101 # /**
102 #  * my_function
103 #  */
104 #
105 # If the Description: header tag is omitted, then there must be a blank line
106 # after the last parameter specification.
107 # e.g.
108 # /**
109 #  * my_function - does my stuff
110 #  * @my_arg: its mine damnit
111 #  *
112 #  * Does my stuff explained.
113 #  */
114 #
115 #  or, could also use:
116 # /**
117 #  * my_function - does my stuff
118 #  * @my_arg: its mine damnit
119 #  * Description: Does my stuff explained.
120 #  */
121 # etc.
122 #
123 # Besides functions you can also write documentation for structs, unions,
124 # enums and typedefs. Instead of the function name you must write the name
125 # of the declaration;  the struct/union/enum/typedef must always precede
126 # the name. Nesting of declarations is not supported.
127 # Use the argument mechanism to document members or constants.
128 # e.g.
129 # /**
130 #  * struct my_struct - short description
131 #  * @a: first member
132 #  * @b: second member
133 #  *
134 #  * Longer description
135 #  */
136 # struct my_struct {
137 #     int a;
138 #     int b;
139 # /* private: */
140 #     int c;
141 # };
142 #
143 # All descriptions can be multiline, except the short function description.
144 #
145 # For really longs structs, you can also describe arguments inside the
146 # body of the struct.
147 # eg.
148 # /**
149 #  * struct my_struct - short description
150 #  * @a: first member
151 #  * @b: second member
152 #  *
153 #  * Longer description
154 #  */
155 # struct my_struct {
156 #     int a;
157 #     int b;
158 #     /**
159 #      * @c: This is longer description of C
160 #      *
161 #      * You can use paragraphs to describe arguments
162 #      * using this method.
163 #      */
164 #     int c;
165 # };
166 #
167 # This should be use only for struct/enum members.
168 #
169 # You can also add additional sections. When documenting kernel functions you
170 # should document the "Context:" of the function, e.g. whether the functions
171 # can be called form interrupts. Unlike other sections you can end it with an
172 # empty line.
173 # A non-void function should have a "Return:" section describing the return
174 # value(s).
175 # Example-sections should contain the string EXAMPLE so that they are marked
176 # appropriately in DocBook.
177 #
178 # Example:
179 # /**
180 #  * user_function - function that can only be called in user context
181 #  * @a: some argument
182 #  * Context: !in_interrupt()
183 #  *
184 #  * Some description
185 #  * Example:
186 #  *    user_function(22);
187 #  */
188 # ...
189 #
190 #
191 # All descriptive text is further processed, scanning for the following special
192 # patterns, which are highlighted appropriately.
193 #
194 # 'funcname()' - function
195 # '$ENVVAR' - environmental variable
196 # '&struct_name' - name of a structure (up to two words including 'struct')
197 # '@parameter' - name of a parameter
198 # '%CONST' - name of a constant.
199
200 ## init lots of data
201
202 my $errors = 0;
203 my $warnings = 0;
204 my $anon_struct_union = 0;
205
206 # match expressions used to find embedded type information
207 my $type_constant = '\%([-_\w]+)';
208 my $type_func = '(\w+)\(\)';
209 my $type_param = '\@(\w+)';
210 my $type_struct = '\&((struct\s*)*[_\w]+)';
211 my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
212 my $type_env = '(\$\w+)';
213 my $type_enum_full = '\&(enum)\s*([_\w]+)';
214 my $type_struct_full = '\&(struct)\s*([_\w]+)';
215 my $type_typedef_full = '\&(typedef)\s*([_\w]+)';
216 my $type_union_full = '\&(union)\s*([_\w]+)';
217 my $type_member = '\&([_\w]+)((\.|->)[_\w]+)';
218 my $type_member_func = $type_member . '\(\)';
219
220 # Output conversion substitutions.
221 #  One for each output format
222
223 # these work fairly well
224 my @highlights_html = (
225                        [$type_constant, "<i>\$1</i>"],
226                        [$type_func, "<b>\$1</b>"],
227                        [$type_struct_xml, "<i>\$1</i>"],
228                        [$type_env, "<b><i>\$1</i></b>"],
229                        [$type_param, "<tt><b>\$1</b></tt>"]
230                       );
231 my $local_lt = "\\\\\\\\lt:";
232 my $local_gt = "\\\\\\\\gt:";
233 my $blankline_html = $local_lt . "p" . $local_gt;       # was "<p>"
234
235 # html version 5
236 my @highlights_html5 = (
237                         [$type_constant, "<span class=\"const\">\$1</span>"],
238                         [$type_func, "<span class=\"func\">\$1</span>"],
239                         [$type_struct_xml, "<span class=\"struct\">\$1</span>"],
240                         [$type_env, "<span class=\"env\">\$1</span>"],
241                         [$type_param, "<span class=\"param\">\$1</span>]"]
242                        );
243 my $blankline_html5 = $local_lt . "br /" . $local_gt;
244
245 # XML, docbook format
246 my @highlights_xml = (
247                       ["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"],
248                       [$type_constant, "<constant>\$1</constant>"],
249                       [$type_struct_xml, "<structname>\$1</structname>"],
250                       [$type_param, "<parameter>\$1</parameter>"],
251                       [$type_func, "<function>\$1</function>"],
252                       [$type_env, "<envar>\$1</envar>"]
253                      );
254 my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
255
256 # gnome, docbook format
257 my @highlights_gnome = (
258                         [$type_constant, "<replaceable class=\"option\">\$1</replaceable>"],
259                         [$type_func, "<function>\$1</function>"],
260                         [$type_struct, "<structname>\$1</structname>"],
261                         [$type_env, "<envar>\$1</envar>"],
262                         [$type_param, "<parameter>\$1</parameter>" ]
263                        );
264 my $blankline_gnome = "</para><para>\n";
265
266 # these are pretty rough
267 my @highlights_man = (
268                       [$type_constant, "\$1"],
269                       [$type_func, "\\\\fB\$1\\\\fP"],
270                       [$type_struct, "\\\\fI\$1\\\\fP"],
271                       [$type_param, "\\\\fI\$1\\\\fP"]
272                      );
273 my $blankline_man = "";
274
275 # text-mode
276 my @highlights_text = (
277                        [$type_constant, "\$1"],
278                        [$type_func, "\$1"],
279                        [$type_struct, "\$1"],
280                        [$type_param, "\$1"]
281                       );
282 my $blankline_text = "";
283
284 # rst-mode
285 my @highlights_rst = (
286                        [$type_constant, "``\$1``"],
287                        # Note: need to escape () to avoid func matching later
288                        [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"],
289                        [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"],
290                        [$type_func, "\\:c\\:func\\:`\$1()`"],
291                        [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
292                        [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
293                        [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
294                        [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
295                        # in rst this can refer to any type
296                        [$type_struct, "\\:c\\:type\\:`\$1`"],
297                        [$type_param, "**\$1**"]
298                       );
299 my $blankline_rst = "\n";
300
301 # list mode
302 my @highlights_list = (
303                        [$type_constant, "\$1"],
304                        [$type_func, "\$1"],
305                        [$type_struct, "\$1"],
306                        [$type_param, "\$1"]
307                       );
308 my $blankline_list = "";
309
310 # read arguments
311 if ($#ARGV == -1) {
312     usage();
313 }
314
315 my $kernelversion;
316 my $dohighlight = "";
317
318 my $verbose = 0;
319 my $output_mode = "man";
320 my $output_preformatted = 0;
321 my $no_doc_sections = 0;
322 my @highlights = @highlights_man;
323 my $blankline = $blankline_man;
324 my $modulename = "Kernel API";
325
326 use constant {
327     OUTPUT_ALL          => 0, # output all symbols and doc sections
328     OUTPUT_INCLUDE      => 1, # output only specified symbols
329     OUTPUT_EXCLUDE      => 2, # output everything except specified symbols
330     OUTPUT_EXPORTED     => 3, # output exported symbols
331     OUTPUT_INTERNAL     => 4, # output non-exported symbols
332 };
333 my $output_selection = OUTPUT_ALL;
334 my $show_not_found = 0;
335
336 my @build_time;
337 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
338     (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
339     @build_time = gmtime($seconds);
340 } else {
341     @build_time = localtime;
342 }
343
344 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
345                 'July', 'August', 'September', 'October',
346                 'November', 'December')[$build_time[4]] .
347   " " . ($build_time[5]+1900);
348
349 # Essentially these are globals.
350 # They probably want to be tidied up, made more localised or something.
351 # CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
352 # could cause "use of undefined value" or other bugs.
353 my ($function, %function_table, %parametertypes, $declaration_purpose);
354 my ($type, $declaration_name, $return_type);
355 my ($newsection, $newcontents, $prototype, $brcount, %source_map);
356
357 if (defined($ENV{'KBUILD_VERBOSE'})) {
358         $verbose = "$ENV{'KBUILD_VERBOSE'}";
359 }
360
361 # Generated docbook code is inserted in a template at a point where
362 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
363 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
364 # We keep track of number of generated entries and generate a dummy
365 # if needs be to ensure the expanded template can be postprocessed
366 # into html.
367 my $section_counter = 0;
368
369 my $lineprefix="";
370
371 # Parser states
372 use constant {
373     STATE_NORMAL        => 0, # normal code
374     STATE_NAME          => 1, # looking for function name
375     STATE_FIELD         => 2, # scanning field start
376     STATE_PROTO         => 3, # scanning prototype
377     STATE_DOCBLOCK      => 4, # documentation block
378     STATE_INLINE        => 5, # gathering documentation outside main block
379 };
380 my $state;
381 my $in_doc_sect;
382
383 # Inline documentation state
384 use constant {
385     STATE_INLINE_NA     => 0, # not applicable ($state != STATE_INLINE)
386     STATE_INLINE_NAME   => 1, # looking for member name (@foo:)
387     STATE_INLINE_TEXT   => 2, # looking for member documentation
388     STATE_INLINE_END    => 3, # done
389     STATE_INLINE_ERROR  => 4, # error - Comment without header was found.
390                               # Spit a warning as it's not
391                               # proper kernel-doc and ignore the rest.
392 };
393 my $inline_doc_state;
394
395 #declaration types: can be
396 # 'function', 'struct', 'union', 'enum', 'typedef'
397 my $decl_type;
398
399 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
400 my $doc_end = '\*/';
401 my $doc_com = '\s*\*\s*';
402 my $doc_com_body = '\s*\* ?';
403 my $doc_decl = $doc_com . '(\w+)';
404 my $doc_sect = $doc_com . '(\@?[\w\s]+):(.*)';
405 my $doc_content = $doc_com_body . '(.*)';
406 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
407 my $doc_inline_start = '^\s*/\*\*\s*$';
408 my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
409 my $doc_inline_end = '^\s*\*/\s*$';
410 my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
411
412 my %parameterdescs;
413 my @parameterlist;
414 my %sections;
415 my @sectionlist;
416 my $sectcheck;
417 my $struct_actual;
418
419 my $contents = "";
420 my $section_default = "Description";    # default section
421 my $section_intro = "Introduction";
422 my $section = $section_default;
423 my $section_context = "Context";
424 my $section_return = "Return";
425
426 my $undescribed = "-- undescribed --";
427
428 reset_state();
429
430 while ($ARGV[0] =~ m/^-(.*)/) {
431     my $cmd = shift @ARGV;
432     if ($cmd eq "-html") {
433         $output_mode = "html";
434         @highlights = @highlights_html;
435         $blankline = $blankline_html;
436     } elsif ($cmd eq "-html5") {
437         $output_mode = "html5";
438         @highlights = @highlights_html5;
439         $blankline = $blankline_html5;
440     } elsif ($cmd eq "-man") {
441         $output_mode = "man";
442         @highlights = @highlights_man;
443         $blankline = $blankline_man;
444     } elsif ($cmd eq "-text") {
445         $output_mode = "text";
446         @highlights = @highlights_text;
447         $blankline = $blankline_text;
448     } elsif ($cmd eq "-rst") {
449         $output_mode = "rst";
450         @highlights = @highlights_rst;
451         $blankline = $blankline_rst;
452     } elsif ($cmd eq "-docbook") {
453         $output_mode = "xml";
454         @highlights = @highlights_xml;
455         $blankline = $blankline_xml;
456     } elsif ($cmd eq "-list") {
457         $output_mode = "list";
458         @highlights = @highlights_list;
459         $blankline = $blankline_list;
460     } elsif ($cmd eq "-gnome") {
461         $output_mode = "gnome";
462         @highlights = @highlights_gnome;
463         $blankline = $blankline_gnome;
464     } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
465         $modulename = shift @ARGV;
466     } elsif ($cmd eq "-function") { # to only output specific functions
467         $output_selection = OUTPUT_INCLUDE;
468         $function = shift @ARGV;
469         $function_table{$function} = 1;
470     } elsif ($cmd eq "-nofunction") { # output all except specific functions
471         $output_selection = OUTPUT_EXCLUDE;
472         $function = shift @ARGV;
473         $function_table{$function} = 1;
474     } elsif ($cmd eq "-export") { # only exported symbols
475         $output_selection = OUTPUT_EXPORTED;
476         %function_table = ()
477     } elsif ($cmd eq "-internal") { # only non-exported symbols
478         $output_selection = OUTPUT_INTERNAL;
479         %function_table = ()
480     } elsif ($cmd eq "-v") {
481         $verbose = 1;
482     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
483         usage();
484     } elsif ($cmd eq '-no-doc-sections') {
485             $no_doc_sections = 1;
486     } elsif ($cmd eq '-show-not-found') {
487         $show_not_found = 1;
488     }
489 }
490
491 # continue execution near EOF;
492
493 # get kernel version from env
494 sub get_kernel_version() {
495     my $version = 'unknown kernel version';
496
497     if (defined($ENV{'KERNELVERSION'})) {
498         $version = $ENV{'KERNELVERSION'};
499     }
500     return $version;
501 }
502
503 ##
504 # dumps section contents to arrays/hashes intended for that purpose.
505 #
506 sub dump_section {
507     my $file = shift;
508     my $name = shift;
509     my $contents = join "\n", @_;
510
511     if ($name =~ m/$type_param/) {
512 #       print STDERR "parameter def '$1' = '$contents'\n";
513         $name = $1;
514         $parameterdescs{$name} = $contents;
515         $sectcheck = $sectcheck . $name . " ";
516     } elsif ($name eq "@\.\.\.") {
517 #       print STDERR "parameter def '...' = '$contents'\n";
518         $name = "...";
519         $parameterdescs{$name} = $contents;
520         $sectcheck = $sectcheck . $name . " ";
521     } else {
522 #       print STDERR "other section '$name' = '$contents'\n";
523         if (defined($sections{$name}) && ($sections{$name} ne "")) {
524                 print STDERR "${file}:$.: error: duplicate section name '$name'\n";
525                 ++$errors;
526         }
527         $sections{$name} = $contents;
528         push @sectionlist, $name;
529     }
530 }
531
532 ##
533 # dump DOC: section after checking that it should go out
534 #
535 sub dump_doc_section {
536     my $file = shift;
537     my $name = shift;
538     my $contents = join "\n", @_;
539
540     if ($no_doc_sections) {
541         return;
542     }
543
544     if (($output_selection == OUTPUT_ALL) ||
545         ($output_selection == OUTPUT_INCLUDE &&
546          defined($function_table{$name})) ||
547         ($output_selection == OUTPUT_EXCLUDE &&
548          !defined($function_table{$name})))
549     {
550         dump_section($file, $name, $contents);
551         output_blockhead({'sectionlist' => \@sectionlist,
552                           'sections' => \%sections,
553                           'module' => $modulename,
554                           'content-only' => ($output_selection != OUTPUT_ALL), });
555     }
556 }
557
558 ##
559 # output function
560 #
561 # parameterdescs, a hash.
562 #  function => "function name"
563 #  parameterlist => @list of parameters
564 #  parameterdescs => %parameter descriptions
565 #  sectionlist => @list of sections
566 #  sections => %section descriptions
567 #
568
569 sub output_highlight {
570     my $contents = join "\n",@_;
571     my $line;
572
573 #   DEBUG
574 #   if (!defined $contents) {
575 #       use Carp;
576 #       confess "output_highlight got called with no args?\n";
577 #   }
578
579     if ($output_mode eq "html" || $output_mode eq "html5" ||
580         $output_mode eq "xml") {
581         $contents = local_unescape($contents);
582         # convert data read & converted thru xml_escape() into &xyz; format:
583         $contents =~ s/\\\\\\/\&/g;
584     }
585 #   print STDERR "contents b4:$contents\n";
586     eval $dohighlight;
587     die $@ if $@;
588 #   print STDERR "contents af:$contents\n";
589
590 #   strip whitespaces when generating html5
591     if ($output_mode eq "html5") {
592         $contents =~ s/^\s+//;
593         $contents =~ s/\s+$//;
594     }
595     foreach $line (split "\n", $contents) {
596         if (! $output_preformatted) {
597             $line =~ s/^\s*//;
598         }
599         if ($line eq ""){
600             if (! $output_preformatted) {
601                 print $lineprefix, local_unescape($blankline);
602             }
603         } else {
604             $line =~ s/\\\\\\/\&/g;
605             if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
606                 print "\\&$line";
607             } else {
608                 print $lineprefix, $line;
609             }
610         }
611         print "\n";
612     }
613 }
614
615 # output sections in html
616 sub output_section_html(%) {
617     my %args = %{$_[0]};
618     my $section;
619
620     foreach $section (@{$args{'sectionlist'}}) {
621         print "<h3>$section</h3>\n";
622         print "<blockquote>\n";
623         output_highlight($args{'sections'}{$section});
624         print "</blockquote>\n";
625     }
626 }
627
628 # output enum in html
629 sub output_enum_html(%) {
630     my %args = %{$_[0]};
631     my ($parameter);
632     my $count;
633     print "<h2>enum " . $args{'enum'} . "</h2>\n";
634
635     print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
636     $count = 0;
637     foreach $parameter (@{$args{'parameterlist'}}) {
638         print " <b>" . $parameter . "</b>";
639         if ($count != $#{$args{'parameterlist'}}) {
640             $count++;
641             print ",\n";
642         }
643         print "<br>";
644     }
645     print "};<br>\n";
646
647     print "<h3>Constants</h3>\n";
648     print "<dl>\n";
649     foreach $parameter (@{$args{'parameterlist'}}) {
650         print "<dt><b>" . $parameter . "</b>\n";
651         print "<dd>";
652         output_highlight($args{'parameterdescs'}{$parameter});
653     }
654     print "</dl>\n";
655     output_section_html(@_);
656     print "<hr>\n";
657 }
658
659 # output typedef in html
660 sub output_typedef_html(%) {
661     my %args = %{$_[0]};
662     my ($parameter);
663     my $count;
664     print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
665
666     print "<b>typedef " . $args{'typedef'} . "</b>\n";
667     output_section_html(@_);
668     print "<hr>\n";
669 }
670
671 # output struct in html
672 sub output_struct_html(%) {
673     my %args = %{$_[0]};
674     my ($parameter);
675
676     print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
677     print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
678     foreach $parameter (@{$args{'parameterlist'}}) {
679         if ($parameter =~ /^#/) {
680                 print "$parameter<br>\n";
681                 next;
682         }
683         my $parameter_name = $parameter;
684         $parameter_name =~ s/\[.*//;
685
686         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
687         $type = $args{'parametertypes'}{$parameter};
688         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
689             # pointer-to-function
690             print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
691         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
692             # bitfield
693             print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
694         } else {
695             print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
696         }
697     }
698     print "};<br>\n";
699
700     print "<h3>Members</h3>\n";
701     print "<dl>\n";
702     foreach $parameter (@{$args{'parameterlist'}}) {
703         ($parameter =~ /^#/) && next;
704
705         my $parameter_name = $parameter;
706         $parameter_name =~ s/\[.*//;
707
708         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
709         print "<dt><b>" . $parameter . "</b>\n";
710         print "<dd>";
711         output_highlight($args{'parameterdescs'}{$parameter_name});
712     }
713     print "</dl>\n";
714     output_section_html(@_);
715     print "<hr>\n";
716 }
717
718 # output function in html
719 sub output_function_html(%) {
720     my %args = %{$_[0]};
721     my ($parameter, $section);
722     my $count;
723
724     print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
725     print "<i>" . $args{'functiontype'} . "</i>\n";
726     print "<b>" . $args{'function'} . "</b>\n";
727     print "(";
728     $count = 0;
729     foreach $parameter (@{$args{'parameterlist'}}) {
730         $type = $args{'parametertypes'}{$parameter};
731         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
732             # pointer-to-function
733             print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
734         } else {
735             print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
736         }
737         if ($count != $#{$args{'parameterlist'}}) {
738             $count++;
739             print ",\n";
740         }
741     }
742     print ")\n";
743
744     print "<h3>Arguments</h3>\n";
745     print "<dl>\n";
746     foreach $parameter (@{$args{'parameterlist'}}) {
747         my $parameter_name = $parameter;
748         $parameter_name =~ s/\[.*//;
749
750         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
751         print "<dt><b>" . $parameter . "</b>\n";
752         print "<dd>";
753         output_highlight($args{'parameterdescs'}{$parameter_name});
754     }
755     print "</dl>\n";
756     output_section_html(@_);
757     print "<hr>\n";
758 }
759
760 # output DOC: block header in html
761 sub output_blockhead_html(%) {
762     my %args = %{$_[0]};
763     my ($parameter, $section);
764     my $count;
765
766     foreach $section (@{$args{'sectionlist'}}) {
767         print "<h3>$section</h3>\n";
768         print "<ul>\n";
769         output_highlight($args{'sections'}{$section});
770         print "</ul>\n";
771     }
772     print "<hr>\n";
773 }
774
775 # output sections in html5
776 sub output_section_html5(%) {
777     my %args = %{$_[0]};
778     my $section;
779
780     foreach $section (@{$args{'sectionlist'}}) {
781         print "<section>\n";
782         print "<h1>$section</h1>\n";
783         print "<p>\n";
784         output_highlight($args{'sections'}{$section});
785         print "</p>\n";
786         print "</section>\n";
787     }
788 }
789
790 # output enum in html5
791 sub output_enum_html5(%) {
792     my %args = %{$_[0]};
793     my ($parameter);
794     my $count;
795     my $html5id;
796
797     $html5id = $args{'enum'};
798     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
799     print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
800     print "<h1>enum " . $args{'enum'} . "</h1>\n";
801     print "<ol class=\"code\">\n";
802     print "<li>";
803     print "<span class=\"keyword\">enum</span> ";
804     print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
805     print "</li>\n";
806     $count = 0;
807     foreach $parameter (@{$args{'parameterlist'}}) {
808         print "<li class=\"indent\">";
809         print "<span class=\"param\">" . $parameter . "</span>";
810         if ($count != $#{$args{'parameterlist'}}) {
811             $count++;
812             print ",";
813         }
814         print "</li>\n";
815     }
816     print "<li>};</li>\n";
817     print "</ol>\n";
818
819     print "<section>\n";
820     print "<h1>Constants</h1>\n";
821     print "<dl>\n";
822     foreach $parameter (@{$args{'parameterlist'}}) {
823         print "<dt>" . $parameter . "</dt>\n";
824         print "<dd>";
825         output_highlight($args{'parameterdescs'}{$parameter});
826         print "</dd>\n";
827     }
828     print "</dl>\n";
829     print "</section>\n";
830     output_section_html5(@_);
831     print "</article>\n";
832 }
833
834 # output typedef in html5
835 sub output_typedef_html5(%) {
836     my %args = %{$_[0]};
837     my ($parameter);
838     my $count;
839     my $html5id;
840
841     $html5id = $args{'typedef'};
842     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
843     print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
844     print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
845
846     print "<ol class=\"code\">\n";
847     print "<li>";
848     print "<span class=\"keyword\">typedef</span> ";
849     print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
850     print "</li>\n";
851     print "</ol>\n";
852     output_section_html5(@_);
853     print "</article>\n";
854 }
855
856 # output struct in html5
857 sub output_struct_html5(%) {
858     my %args = %{$_[0]};
859     my ($parameter);
860     my $html5id;
861
862     $html5id = $args{'struct'};
863     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
864     print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
865     print "<hgroup>\n";
866     print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
867     print "<h2>". $args{'purpose'} . "</h2>\n";
868     print "</hgroup>\n";
869     print "<ol class=\"code\">\n";
870     print "<li>";
871     print "<span class=\"type\">" . $args{'type'} . "</span> ";
872     print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
873     print "</li>\n";
874     foreach $parameter (@{$args{'parameterlist'}}) {
875         print "<li class=\"indent\">";
876         if ($parameter =~ /^#/) {
877                 print "<span class=\"param\">" . $parameter ."</span>\n";
878                 print "</li>\n";
879                 next;
880         }
881         my $parameter_name = $parameter;
882         $parameter_name =~ s/\[.*//;
883
884         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
885         $type = $args{'parametertypes'}{$parameter};
886         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
887             # pointer-to-function
888             print "<span class=\"type\">$1</span> ";
889             print "<span class=\"param\">$parameter</span>";
890             print "<span class=\"type\">)</span> ";
891             print "(<span class=\"args\">$2</span>);";
892         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
893             # bitfield
894             print "<span class=\"type\">$1</span> ";
895             print "<span class=\"param\">$parameter</span>";
896             print "<span class=\"bits\">$2</span>;";
897         } else {
898             print "<span class=\"type\">$type</span> ";
899             print "<span class=\"param\">$parameter</span>;";
900         }
901         print "</li>\n";
902     }
903     print "<li>};</li>\n";
904     print "</ol>\n";
905
906     print "<section>\n";
907     print "<h1>Members</h1>\n";
908     print "<dl>\n";
909     foreach $parameter (@{$args{'parameterlist'}}) {
910         ($parameter =~ /^#/) && next;
911
912         my $parameter_name = $parameter;
913         $parameter_name =~ s/\[.*//;
914
915         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
916         print "<dt>" . $parameter . "</dt>\n";
917         print "<dd>";
918         output_highlight($args{'parameterdescs'}{$parameter_name});
919         print "</dd>\n";
920     }
921     print "</dl>\n";
922     print "</section>\n";
923     output_section_html5(@_);
924     print "</article>\n";
925 }
926
927 # output function in html5
928 sub output_function_html5(%) {
929     my %args = %{$_[0]};
930     my ($parameter, $section);
931     my $count;
932     my $html5id;
933
934     $html5id = $args{'function'};
935     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
936     print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
937     print "<hgroup>\n";
938     print "<h1>" . $args{'function'} . "</h1>";
939     print "<h2>" . $args{'purpose'} . "</h2>\n";
940     print "</hgroup>\n";
941     print "<ol class=\"code\">\n";
942     print "<li>";
943     print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
944     print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
945     print "</li>";
946     $count = 0;
947     foreach $parameter (@{$args{'parameterlist'}}) {
948         print "<li class=\"indent\">";
949         $type = $args{'parametertypes'}{$parameter};
950         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
951             # pointer-to-function
952             print "<span class=\"type\">$1</span> ";
953             print "<span class=\"param\">$parameter</span>";
954             print "<span class=\"type\">)</span> ";
955             print "(<span class=\"args\">$2</span>)";
956         } else {
957             print "<span class=\"type\">$type</span> ";
958             print "<span class=\"param\">$parameter</span>";
959         }
960         if ($count != $#{$args{'parameterlist'}}) {
961             $count++;
962             print ",";
963         }
964         print "</li>\n";
965     }
966     print "<li>)</li>\n";
967     print "</ol>\n";
968
969     print "<section>\n";
970     print "<h1>Arguments</h1>\n";
971     print "<p>\n";
972     print "<dl>\n";
973     foreach $parameter (@{$args{'parameterlist'}}) {
974         my $parameter_name = $parameter;
975         $parameter_name =~ s/\[.*//;
976
977         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
978         print "<dt>" . $parameter . "</dt>\n";
979         print "<dd>";
980         output_highlight($args{'parameterdescs'}{$parameter_name});
981         print "</dd>\n";
982     }
983     print "</dl>\n";
984     print "</section>\n";
985     output_section_html5(@_);
986     print "</article>\n";
987 }
988
989 # output DOC: block header in html5
990 sub output_blockhead_html5(%) {
991     my %args = %{$_[0]};
992     my ($parameter, $section);
993     my $count;
994     my $html5id;
995
996     foreach $section (@{$args{'sectionlist'}}) {
997         $html5id = $section;
998         $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
999         print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
1000         print "<h1>$section</h1>\n";
1001         print "<p>\n";
1002         output_highlight($args{'sections'}{$section});
1003         print "</p>\n";
1004     }
1005     print "</article>\n";
1006 }
1007
1008 sub output_section_xml(%) {
1009     my %args = %{$_[0]};
1010     my $section;
1011     # print out each section
1012     $lineprefix="   ";
1013     foreach $section (@{$args{'sectionlist'}}) {
1014         print "<refsect1>\n";
1015         print "<title>$section</title>\n";
1016         if ($section =~ m/EXAMPLE/i) {
1017             print "<informalexample><programlisting>\n";
1018             $output_preformatted = 1;
1019         } else {
1020             print "<para>\n";
1021         }
1022         output_highlight($args{'sections'}{$section});
1023         $output_preformatted = 0;
1024         if ($section =~ m/EXAMPLE/i) {
1025             print "</programlisting></informalexample>\n";
1026         } else {
1027             print "</para>\n";
1028         }
1029         print "</refsect1>\n";
1030     }
1031 }
1032
1033 # output function in XML DocBook
1034 sub output_function_xml(%) {
1035     my %args = %{$_[0]};
1036     my ($parameter, $section);
1037     my $count;
1038     my $id;
1039
1040     $id = "API-" . $args{'function'};
1041     $id =~ s/[^A-Za-z0-9]/-/g;
1042
1043     print "<refentry id=\"$id\">\n";
1044     print "<refentryinfo>\n";
1045     print " <title>LINUX</title>\n";
1046     print " <productname>Kernel Hackers Manual</productname>\n";
1047     print " <date>$man_date</date>\n";
1048     print "</refentryinfo>\n";
1049     print "<refmeta>\n";
1050     print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
1051     print " <manvolnum>9</manvolnum>\n";
1052     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1053     print "</refmeta>\n";
1054     print "<refnamediv>\n";
1055     print " <refname>" . $args{'function'} . "</refname>\n";
1056     print " <refpurpose>\n";
1057     print "  ";
1058     output_highlight ($args{'purpose'});
1059     print " </refpurpose>\n";
1060     print "</refnamediv>\n";
1061
1062     print "<refsynopsisdiv>\n";
1063     print " <title>Synopsis</title>\n";
1064     print "  <funcsynopsis><funcprototype>\n";
1065     print "   <funcdef>" . $args{'functiontype'} . " ";
1066     print "<function>" . $args{'function'} . " </function></funcdef>\n";
1067
1068     $count = 0;
1069     if ($#{$args{'parameterlist'}} >= 0) {
1070         foreach $parameter (@{$args{'parameterlist'}}) {
1071             $type = $args{'parametertypes'}{$parameter};
1072             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1073                 # pointer-to-function
1074                 print "   <paramdef>$1<parameter>$parameter</parameter>)\n";
1075                 print "     <funcparams>$2</funcparams></paramdef>\n";
1076             } else {
1077                 print "   <paramdef>" . $type;
1078                 print " <parameter>$parameter</parameter></paramdef>\n";
1079             }
1080         }
1081     } else {
1082         print "  <void/>\n";
1083     }
1084     print "  </funcprototype></funcsynopsis>\n";
1085     print "</refsynopsisdiv>\n";
1086
1087     # print parameters
1088     print "<refsect1>\n <title>Arguments</title>\n";
1089     if ($#{$args{'parameterlist'}} >= 0) {
1090         print " <variablelist>\n";
1091         foreach $parameter (@{$args{'parameterlist'}}) {
1092             my $parameter_name = $parameter;
1093             $parameter_name =~ s/\[.*//;
1094
1095             print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
1096             print "   <listitem>\n    <para>\n";
1097             $lineprefix="     ";
1098             output_highlight($args{'parameterdescs'}{$parameter_name});
1099             print "    </para>\n   </listitem>\n  </varlistentry>\n";
1100         }
1101         print " </variablelist>\n";
1102     } else {
1103         print " <para>\n  None\n </para>\n";
1104     }
1105     print "</refsect1>\n";
1106
1107     output_section_xml(@_);
1108     print "</refentry>\n\n";
1109 }
1110
1111 # output struct in XML DocBook
1112 sub output_struct_xml(%) {
1113     my %args = %{$_[0]};
1114     my ($parameter, $section);
1115     my $id;
1116
1117     $id = "API-struct-" . $args{'struct'};
1118     $id =~ s/[^A-Za-z0-9]/-/g;
1119
1120     print "<refentry id=\"$id\">\n";
1121     print "<refentryinfo>\n";
1122     print " <title>LINUX</title>\n";
1123     print " <productname>Kernel Hackers Manual</productname>\n";
1124     print " <date>$man_date</date>\n";
1125     print "</refentryinfo>\n";
1126     print "<refmeta>\n";
1127     print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
1128     print " <manvolnum>9</manvolnum>\n";
1129     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1130     print "</refmeta>\n";
1131     print "<refnamediv>\n";
1132     print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
1133     print " <refpurpose>\n";
1134     print "  ";
1135     output_highlight ($args{'purpose'});
1136     print " </refpurpose>\n";
1137     print "</refnamediv>\n";
1138
1139     print "<refsynopsisdiv>\n";
1140     print " <title>Synopsis</title>\n";
1141     print "  <programlisting>\n";
1142     print $args{'type'} . " " . $args{'struct'} . " {\n";
1143     foreach $parameter (@{$args{'parameterlist'}}) {
1144         if ($parameter =~ /^#/) {
1145             my $prm = $parameter;
1146             # convert data read & converted thru xml_escape() into &xyz; format:
1147             # This allows us to have #define macros interspersed in a struct.
1148             $prm =~ s/\\\\\\/\&/g;
1149             print "$prm\n";
1150             next;
1151         }
1152
1153         my $parameter_name = $parameter;
1154         $parameter_name =~ s/\[.*//;
1155
1156         defined($args{'parameterdescs'}{$parameter_name}) || next;
1157         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1158         $type = $args{'parametertypes'}{$parameter};
1159         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1160             # pointer-to-function
1161             print "  $1 $parameter) ($2);\n";
1162         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1163             # bitfield
1164             print "  $1 $parameter$2;\n";
1165         } else {
1166             print "  " . $type . " " . $parameter . ";\n";
1167         }
1168     }
1169     print "};";
1170     print "  </programlisting>\n";
1171     print "</refsynopsisdiv>\n";
1172
1173     print " <refsect1>\n";
1174     print "  <title>Members</title>\n";
1175
1176     if ($#{$args{'parameterlist'}} >= 0) {
1177     print "  <variablelist>\n";
1178     foreach $parameter (@{$args{'parameterlist'}}) {
1179       ($parameter =~ /^#/) && next;
1180
1181       my $parameter_name = $parameter;
1182       $parameter_name =~ s/\[.*//;
1183
1184       defined($args{'parameterdescs'}{$parameter_name}) || next;
1185       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1186       print "    <varlistentry>";
1187       print "      <term>$parameter</term>\n";
1188       print "      <listitem><para>\n";
1189       output_highlight($args{'parameterdescs'}{$parameter_name});
1190       print "      </para></listitem>\n";
1191       print "    </varlistentry>\n";
1192     }
1193     print "  </variablelist>\n";
1194     } else {
1195         print " <para>\n  None\n </para>\n";
1196     }
1197     print " </refsect1>\n";
1198
1199     output_section_xml(@_);
1200
1201     print "</refentry>\n\n";
1202 }
1203
1204 # output enum in XML DocBook
1205 sub output_enum_xml(%) {
1206     my %args = %{$_[0]};
1207     my ($parameter, $section);
1208     my $count;
1209     my $id;
1210
1211     $id = "API-enum-" . $args{'enum'};
1212     $id =~ s/[^A-Za-z0-9]/-/g;
1213
1214     print "<refentry id=\"$id\">\n";
1215     print "<refentryinfo>\n";
1216     print " <title>LINUX</title>\n";
1217     print " <productname>Kernel Hackers Manual</productname>\n";
1218     print " <date>$man_date</date>\n";
1219     print "</refentryinfo>\n";
1220     print "<refmeta>\n";
1221     print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
1222     print " <manvolnum>9</manvolnum>\n";
1223     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1224     print "</refmeta>\n";
1225     print "<refnamediv>\n";
1226     print " <refname>enum " . $args{'enum'} . "</refname>\n";
1227     print " <refpurpose>\n";
1228     print "  ";
1229     output_highlight ($args{'purpose'});
1230     print " </refpurpose>\n";
1231     print "</refnamediv>\n";
1232
1233     print "<refsynopsisdiv>\n";
1234     print " <title>Synopsis</title>\n";
1235     print "  <programlisting>\n";
1236     print "enum " . $args{'enum'} . " {\n";
1237     $count = 0;
1238     foreach $parameter (@{$args{'parameterlist'}}) {
1239         print "  $parameter";
1240         if ($count != $#{$args{'parameterlist'}}) {
1241             $count++;
1242             print ",";
1243         }
1244         print "\n";
1245     }
1246     print "};";
1247     print "  </programlisting>\n";
1248     print "</refsynopsisdiv>\n";
1249
1250     print "<refsect1>\n";
1251     print " <title>Constants</title>\n";
1252     print "  <variablelist>\n";
1253     foreach $parameter (@{$args{'parameterlist'}}) {
1254       my $parameter_name = $parameter;
1255       $parameter_name =~ s/\[.*//;
1256
1257       print "    <varlistentry>";
1258       print "      <term>$parameter</term>\n";
1259       print "      <listitem><para>\n";
1260       output_highlight($args{'parameterdescs'}{$parameter_name});
1261       print "      </para></listitem>\n";
1262       print "    </varlistentry>\n";
1263     }
1264     print "  </variablelist>\n";
1265     print "</refsect1>\n";
1266
1267     output_section_xml(@_);
1268
1269     print "</refentry>\n\n";
1270 }
1271
1272 # output typedef in XML DocBook
1273 sub output_typedef_xml(%) {
1274     my %args = %{$_[0]};
1275     my ($parameter, $section);
1276     my $id;
1277
1278     $id = "API-typedef-" . $args{'typedef'};
1279     $id =~ s/[^A-Za-z0-9]/-/g;
1280
1281     print "<refentry id=\"$id\">\n";
1282     print "<refentryinfo>\n";
1283     print " <title>LINUX</title>\n";
1284     print " <productname>Kernel Hackers Manual</productname>\n";
1285     print " <date>$man_date</date>\n";
1286     print "</refentryinfo>\n";
1287     print "<refmeta>\n";
1288     print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
1289     print " <manvolnum>9</manvolnum>\n";
1290     print "</refmeta>\n";
1291     print "<refnamediv>\n";
1292     print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
1293     print " <refpurpose>\n";
1294     print "  ";
1295     output_highlight ($args{'purpose'});
1296     print " </refpurpose>\n";
1297     print "</refnamediv>\n";
1298
1299     print "<refsynopsisdiv>\n";
1300     print " <title>Synopsis</title>\n";
1301     print "  <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
1302     print "</refsynopsisdiv>\n";
1303
1304     output_section_xml(@_);
1305
1306     print "</refentry>\n\n";
1307 }
1308
1309 # output in XML DocBook
1310 sub output_blockhead_xml(%) {
1311     my %args = %{$_[0]};
1312     my ($parameter, $section);
1313     my $count;
1314
1315     my $id = $args{'module'};
1316     $id =~ s/[^A-Za-z0-9]/-/g;
1317
1318     # print out each section
1319     $lineprefix="   ";
1320     foreach $section (@{$args{'sectionlist'}}) {
1321         if (!$args{'content-only'}) {
1322                 print "<refsect1>\n <title>$section</title>\n";
1323         }
1324         if ($section =~ m/EXAMPLE/i) {
1325             print "<example><para>\n";
1326             $output_preformatted = 1;
1327         } else {
1328             print "<para>\n";
1329         }
1330         output_highlight($args{'sections'}{$section});
1331         $output_preformatted = 0;
1332         if ($section =~ m/EXAMPLE/i) {
1333             print "</para></example>\n";
1334         } else {
1335             print "</para>";
1336         }
1337         if (!$args{'content-only'}) {
1338                 print "\n</refsect1>\n";
1339         }
1340     }
1341
1342     print "\n\n";
1343 }
1344
1345 # output in XML DocBook
1346 sub output_function_gnome {
1347     my %args = %{$_[0]};
1348     my ($parameter, $section);
1349     my $count;
1350     my $id;
1351
1352     $id = $args{'module'} . "-" . $args{'function'};
1353     $id =~ s/[^A-Za-z0-9]/-/g;
1354
1355     print "<sect2>\n";
1356     print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
1357
1358     print "  <funcsynopsis>\n";
1359     print "   <funcdef>" . $args{'functiontype'} . " ";
1360     print "<function>" . $args{'function'} . " ";
1361     print "</function></funcdef>\n";
1362
1363     $count = 0;
1364     if ($#{$args{'parameterlist'}} >= 0) {
1365         foreach $parameter (@{$args{'parameterlist'}}) {
1366             $type = $args{'parametertypes'}{$parameter};
1367             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1368                 # pointer-to-function
1369                 print "   <paramdef>$1 <parameter>$parameter</parameter>)\n";
1370                 print "     <funcparams>$2</funcparams></paramdef>\n";
1371             } else {
1372                 print "   <paramdef>" . $type;
1373                 print " <parameter>$parameter</parameter></paramdef>\n";
1374             }
1375         }
1376     } else {
1377         print "  <void>\n";
1378     }
1379     print "  </funcsynopsis>\n";
1380     if ($#{$args{'parameterlist'}} >= 0) {
1381         print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
1382         print "<tgroup cols=\"2\">\n";
1383         print "<colspec colwidth=\"2*\">\n";
1384         print "<colspec colwidth=\"8*\">\n";
1385         print "<tbody>\n";
1386         foreach $parameter (@{$args{'parameterlist'}}) {
1387             my $parameter_name = $parameter;
1388             $parameter_name =~ s/\[.*//;
1389
1390             print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
1391             print "   <entry>\n";
1392             $lineprefix="     ";
1393             output_highlight($args{'parameterdescs'}{$parameter_name});
1394             print "    </entry></row>\n";
1395         }
1396         print " </tbody></tgroup></informaltable>\n";
1397     } else {
1398         print " <para>\n  None\n </para>\n";
1399     }
1400
1401     # print out each section
1402     $lineprefix="   ";
1403     foreach $section (@{$args{'sectionlist'}}) {
1404         print "<simplesect>\n <title>$section</title>\n";
1405         if ($section =~ m/EXAMPLE/i) {
1406             print "<example><programlisting>\n";
1407             $output_preformatted = 1;
1408         } else {
1409         }
1410         print "<para>\n";
1411         output_highlight($args{'sections'}{$section});
1412         $output_preformatted = 0;
1413         print "</para>\n";
1414         if ($section =~ m/EXAMPLE/i) {
1415             print "</programlisting></example>\n";
1416         } else {
1417         }
1418         print " </simplesect>\n";
1419     }
1420
1421     print "</sect2>\n\n";
1422 }
1423
1424 ##
1425 # output function in man
1426 sub output_function_man(%) {
1427     my %args = %{$_[0]};
1428     my ($parameter, $section);
1429     my $count;
1430
1431     print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
1432
1433     print ".SH NAME\n";
1434     print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
1435
1436     print ".SH SYNOPSIS\n";
1437     if ($args{'functiontype'} ne "") {
1438         print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
1439     } else {
1440         print ".B \"" . $args{'function'} . "\n";
1441     }
1442     $count = 0;
1443     my $parenth = "(";
1444     my $post = ",";
1445     foreach my $parameter (@{$args{'parameterlist'}}) {
1446         if ($count == $#{$args{'parameterlist'}}) {
1447             $post = ");";
1448         }
1449         $type = $args{'parametertypes'}{$parameter};
1450         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1451             # pointer-to-function
1452             print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
1453         } else {
1454             $type =~ s/([^\*])$/$1 /;
1455             print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
1456         }
1457         $count++;
1458         $parenth = "";
1459     }
1460
1461     print ".SH ARGUMENTS\n";
1462     foreach $parameter (@{$args{'parameterlist'}}) {
1463         my $parameter_name = $parameter;
1464         $parameter_name =~ s/\[.*//;
1465
1466         print ".IP \"" . $parameter . "\" 12\n";
1467         output_highlight($args{'parameterdescs'}{$parameter_name});
1468     }
1469     foreach $section (@{$args{'sectionlist'}}) {
1470         print ".SH \"", uc $section, "\"\n";
1471         output_highlight($args{'sections'}{$section});
1472     }
1473 }
1474
1475 ##
1476 # output enum in man
1477 sub output_enum_man(%) {
1478     my %args = %{$_[0]};
1479     my ($parameter, $section);
1480     my $count;
1481
1482     print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
1483
1484     print ".SH NAME\n";
1485     print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
1486
1487     print ".SH SYNOPSIS\n";
1488     print "enum " . $args{'enum'} . " {\n";
1489     $count = 0;
1490     foreach my $parameter (@{$args{'parameterlist'}}) {
1491         print ".br\n.BI \"    $parameter\"\n";
1492         if ($count == $#{$args{'parameterlist'}}) {
1493             print "\n};\n";
1494             last;
1495         }
1496         else {
1497             print ", \n.br\n";
1498         }
1499         $count++;
1500     }
1501
1502     print ".SH Constants\n";
1503     foreach $parameter (@{$args{'parameterlist'}}) {
1504         my $parameter_name = $parameter;
1505         $parameter_name =~ s/\[.*//;
1506
1507         print ".IP \"" . $parameter . "\" 12\n";
1508         output_highlight($args{'parameterdescs'}{$parameter_name});
1509     }
1510     foreach $section (@{$args{'sectionlist'}}) {
1511         print ".SH \"$section\"\n";
1512         output_highlight($args{'sections'}{$section});
1513     }
1514 }
1515
1516 ##
1517 # output struct in man
1518 sub output_struct_man(%) {
1519     my %args = %{$_[0]};
1520     my ($parameter, $section);
1521
1522     print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
1523
1524     print ".SH NAME\n";
1525     print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
1526
1527     print ".SH SYNOPSIS\n";
1528     print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
1529
1530     foreach my $parameter (@{$args{'parameterlist'}}) {
1531         if ($parameter =~ /^#/) {
1532             print ".BI \"$parameter\"\n.br\n";
1533             next;
1534         }
1535         my $parameter_name = $parameter;
1536         $parameter_name =~ s/\[.*//;
1537
1538         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1539         $type = $args{'parametertypes'}{$parameter};
1540         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1541             # pointer-to-function
1542             print ".BI \"    " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
1543         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1544             # bitfield
1545             print ".BI \"    " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
1546         } else {
1547             $type =~ s/([^\*])$/$1 /;
1548             print ".BI \"    " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
1549         }
1550         print "\n.br\n";
1551     }
1552     print "};\n.br\n";
1553
1554     print ".SH Members\n";
1555     foreach $parameter (@{$args{'parameterlist'}}) {
1556         ($parameter =~ /^#/) && next;
1557
1558         my $parameter_name = $parameter;
1559         $parameter_name =~ s/\[.*//;
1560
1561         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1562         print ".IP \"" . $parameter . "\" 12\n";
1563         output_highlight($args{'parameterdescs'}{$parameter_name});
1564     }
1565     foreach $section (@{$args{'sectionlist'}}) {
1566         print ".SH \"$section\"\n";
1567         output_highlight($args{'sections'}{$section});
1568     }
1569 }
1570
1571 ##
1572 # output typedef in man
1573 sub output_typedef_man(%) {
1574     my %args = %{$_[0]};
1575     my ($parameter, $section);
1576
1577     print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
1578
1579     print ".SH NAME\n";
1580     print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
1581
1582     foreach $section (@{$args{'sectionlist'}}) {
1583         print ".SH \"$section\"\n";
1584         output_highlight($args{'sections'}{$section});
1585     }
1586 }
1587
1588 sub output_blockhead_man(%) {
1589     my %args = %{$_[0]};
1590     my ($parameter, $section);
1591     my $count;
1592
1593     print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
1594
1595     foreach $section (@{$args{'sectionlist'}}) {
1596         print ".SH \"$section\"\n";
1597         output_highlight($args{'sections'}{$section});
1598     }
1599 }
1600
1601 ##
1602 # output in text
1603 sub output_function_text(%) {
1604     my %args = %{$_[0]};
1605     my ($parameter, $section);
1606     my $start;
1607
1608     print "Name:\n\n";
1609     print $args{'function'} . " - " . $args{'purpose'} . "\n";
1610
1611     print "\nSynopsis:\n\n";
1612     if ($args{'functiontype'} ne "") {
1613         $start = $args{'functiontype'} . " " . $args{'function'} . " (";
1614     } else {
1615         $start = $args{'function'} . " (";
1616     }
1617     print $start;
1618
1619     my $count = 0;
1620     foreach my $parameter (@{$args{'parameterlist'}}) {
1621         $type = $args{'parametertypes'}{$parameter};
1622         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1623             # pointer-to-function
1624             print $1 . $parameter . ") (" . $2;
1625         } else {
1626             print $type . " " . $parameter;
1627         }
1628         if ($count != $#{$args{'parameterlist'}}) {
1629             $count++;
1630             print ",\n";
1631             print " " x length($start);
1632         } else {
1633             print ");\n\n";
1634         }
1635     }
1636
1637     print "Arguments:\n\n";
1638     foreach $parameter (@{$args{'parameterlist'}}) {
1639         my $parameter_name = $parameter;
1640         $parameter_name =~ s/\[.*//;
1641
1642         print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
1643     }
1644     output_section_text(@_);
1645 }
1646
1647 #output sections in text
1648 sub output_section_text(%) {
1649     my %args = %{$_[0]};
1650     my $section;
1651
1652     print "\n";
1653     foreach $section (@{$args{'sectionlist'}}) {
1654         print "$section:\n\n";
1655         output_highlight($args{'sections'}{$section});
1656     }
1657     print "\n\n";
1658 }
1659
1660 # output enum in text
1661 sub output_enum_text(%) {
1662     my %args = %{$_[0]};
1663     my ($parameter);
1664     my $count;
1665     print "Enum:\n\n";
1666
1667     print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
1668     print "enum " . $args{'enum'} . " {\n";
1669     $count = 0;
1670     foreach $parameter (@{$args{'parameterlist'}}) {
1671         print "\t$parameter";
1672         if ($count != $#{$args{'parameterlist'}}) {
1673             $count++;
1674             print ",";
1675         }
1676         print "\n";
1677     }
1678     print "};\n\n";
1679
1680     print "Constants:\n\n";
1681     foreach $parameter (@{$args{'parameterlist'}}) {
1682         print "$parameter\n\t";
1683         print $args{'parameterdescs'}{$parameter} . "\n";
1684     }
1685
1686     output_section_text(@_);
1687 }
1688
1689 # output typedef in text
1690 sub output_typedef_text(%) {
1691     my %args = %{$_[0]};
1692     my ($parameter);
1693     my $count;
1694     print "Typedef:\n\n";
1695
1696     print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
1697     output_section_text(@_);
1698 }
1699
1700 # output struct as text
1701 sub output_struct_text(%) {
1702     my %args = %{$_[0]};
1703     my ($parameter);
1704
1705     print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
1706     print $args{'type'} . " " . $args{'struct'} . " {\n";
1707     foreach $parameter (@{$args{'parameterlist'}}) {
1708         if ($parameter =~ /^#/) {
1709             print "$parameter\n";
1710             next;
1711         }
1712
1713         my $parameter_name = $parameter;
1714         $parameter_name =~ s/\[.*//;
1715
1716         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1717         $type = $args{'parametertypes'}{$parameter};
1718         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1719             # pointer-to-function
1720             print "\t$1 $parameter) ($2);\n";
1721         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1722             # bitfield
1723             print "\t$1 $parameter$2;\n";
1724         } else {
1725             print "\t" . $type . " " . $parameter . ";\n";
1726         }
1727     }
1728     print "};\n\n";
1729
1730     print "Members:\n\n";
1731     foreach $parameter (@{$args{'parameterlist'}}) {
1732         ($parameter =~ /^#/) && next;
1733
1734         my $parameter_name = $parameter;
1735         $parameter_name =~ s/\[.*//;
1736
1737         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1738         print "$parameter\n\t";
1739         print $args{'parameterdescs'}{$parameter_name} . "\n";
1740     }
1741     print "\n";
1742     output_section_text(@_);
1743 }
1744
1745 sub output_blockhead_text(%) {
1746     my %args = %{$_[0]};
1747     my ($parameter, $section);
1748
1749     foreach $section (@{$args{'sectionlist'}}) {
1750         print " $section:\n";
1751         print "    -> ";
1752         output_highlight($args{'sections'}{$section});
1753     }
1754 }
1755
1756 ##
1757 # output in restructured text
1758 #
1759
1760 #
1761 # This could use some work; it's used to output the DOC: sections, and
1762 # starts by putting out the name of the doc section itself, but that tends
1763 # to duplicate a header already in the template file.
1764 #
1765 sub output_blockhead_rst(%) {
1766     my %args = %{$_[0]};
1767     my ($parameter, $section);
1768
1769     foreach $section (@{$args{'sectionlist'}}) {
1770         if ($output_selection != OUTPUT_INCLUDE) {
1771             print "**$section**\n\n";
1772         }
1773         output_highlight_rst($args{'sections'}{$section});
1774         print "\n";
1775     }
1776 }
1777
1778 sub output_highlight_rst {
1779     my $contents = join "\n",@_;
1780     my $line;
1781
1782     # undo the evil effects of xml_escape() earlier
1783     $contents = xml_unescape($contents);
1784
1785     eval $dohighlight;
1786     die $@ if $@;
1787
1788     foreach $line (split "\n", $contents) {
1789         print $lineprefix . $line . "\n";
1790     }
1791 }
1792
1793 sub output_function_rst(%) {
1794     my %args = %{$_[0]};
1795     my ($parameter, $section);
1796     my $oldprefix = $lineprefix;
1797     my $start;
1798
1799     print ".. c:function:: ";
1800     if ($args{'functiontype'} ne "") {
1801         $start = $args{'functiontype'} . " " . $args{'function'} . " (";
1802     } else {
1803         $start = $args{'function'} . " (";
1804     }
1805     print $start;
1806
1807     my $count = 0;
1808     foreach my $parameter (@{$args{'parameterlist'}}) {
1809         if ($count ne 0) {
1810             print ", ";
1811         }
1812         $count++;
1813         $type = $args{'parametertypes'}{$parameter};
1814         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1815             # pointer-to-function
1816             print $1 . $parameter . ") (" . $2;
1817         } else {
1818             print $type . " " . $parameter;
1819         }
1820     }
1821     print ")\n\n";
1822     $lineprefix = "   ";
1823     output_highlight_rst($args{'purpose'});
1824     print "\n";
1825
1826     print "**Parameters**\n\n";
1827     $lineprefix = "  ";
1828     foreach $parameter (@{$args{'parameterlist'}}) {
1829         my $parameter_name = $parameter;
1830         #$parameter_name =~ s/\[.*//;
1831         $type = $args{'parametertypes'}{$parameter};
1832
1833         if ($type ne "") {
1834             print "``$type $parameter``\n";
1835         } else {
1836             print "``$parameter``\n";
1837         }
1838         if (defined($args{'parameterdescs'}{$parameter_name}) &&
1839             $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
1840             output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1841         } else {
1842             print "  *undescribed*\n";
1843         }
1844         print "\n";
1845     }
1846
1847     $lineprefix = $oldprefix;
1848     output_section_rst(@_);
1849 }
1850
1851 sub output_section_rst(%) {
1852     my %args = %{$_[0]};
1853     my $section;
1854     my $oldprefix = $lineprefix;
1855     $lineprefix = "";
1856
1857     foreach $section (@{$args{'sectionlist'}}) {
1858         print "**$section**\n\n";
1859         output_highlight_rst($args{'sections'}{$section});
1860         print "\n";
1861     }
1862     print "\n";
1863     $lineprefix = $oldprefix;
1864 }
1865
1866 sub output_enum_rst(%) {
1867     my %args = %{$_[0]};
1868     my ($parameter);
1869     my $oldprefix = $lineprefix;
1870     my $count;
1871     my $name = "enum " . $args{'enum'};
1872
1873     print "\n\n.. c:type:: " . $name . "\n\n";
1874     $lineprefix = "   ";
1875     output_highlight_rst($args{'purpose'});
1876     print "\n";
1877
1878     print "**Constants**\n\n";
1879     $lineprefix = "  ";
1880     foreach $parameter (@{$args{'parameterlist'}}) {
1881         print "``$parameter``\n";
1882         if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
1883             output_highlight_rst($args{'parameterdescs'}{$parameter});
1884         } else {
1885             print "  *undescribed*\n";
1886         }
1887         print "\n";
1888     }
1889
1890     $lineprefix = $oldprefix;
1891     output_section_rst(@_);
1892 }
1893
1894 sub output_typedef_rst(%) {
1895     my %args = %{$_[0]};
1896     my ($parameter);
1897     my $oldprefix = $lineprefix;
1898     my $name = "typedef " . $args{'typedef'};
1899
1900     ### FIXME: should the name below contain "typedef" or not?
1901     print "\n\n.. c:type:: " . $name . "\n\n";
1902     $lineprefix = "   ";
1903     output_highlight_rst($args{'purpose'});
1904     print "\n";
1905
1906     $lineprefix = $oldprefix;
1907     output_section_rst(@_);
1908 }
1909
1910 sub output_struct_rst(%) {
1911     my %args = %{$_[0]};
1912     my ($parameter);
1913     my $oldprefix = $lineprefix;
1914     my $name = $args{'type'} . " " . $args{'struct'};
1915
1916     print "\n\n.. c:type:: " . $name . "\n\n";
1917     $lineprefix = "   ";
1918     output_highlight_rst($args{'purpose'});
1919     print "\n";
1920
1921     print "**Definition**\n\n";
1922     print "::\n\n";
1923     print "  " . $args{'type'} . " " . $args{'struct'} . " {\n";
1924     foreach $parameter (@{$args{'parameterlist'}}) {
1925         if ($parameter =~ /^#/) {
1926             print "  " . "$parameter\n";
1927             next;
1928         }
1929
1930         my $parameter_name = $parameter;
1931         $parameter_name =~ s/\[.*//;
1932
1933         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1934         $type = $args{'parametertypes'}{$parameter};
1935         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1936             # pointer-to-function
1937             print "    $1 $parameter) ($2);\n";
1938         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1939             # bitfield
1940             print "    $1 $parameter$2;\n";
1941         } else {
1942             print "    " . $type . " " . $parameter . ";\n";
1943         }
1944     }
1945     print "  };\n\n";
1946
1947     print "**Members**\n\n";
1948     $lineprefix = "  ";
1949     foreach $parameter (@{$args{'parameterlist'}}) {
1950         ($parameter =~ /^#/) && next;
1951
1952         my $parameter_name = $parameter;
1953         $parameter_name =~ s/\[.*//;
1954
1955         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1956         $type = $args{'parametertypes'}{$parameter};
1957         print "``$type $parameter``\n";
1958         output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1959         print "\n";
1960     }
1961     print "\n";
1962
1963     $lineprefix = $oldprefix;
1964     output_section_rst(@_);
1965 }
1966
1967
1968 ## list mode output functions
1969
1970 sub output_function_list(%) {
1971     my %args = %{$_[0]};
1972
1973     print $args{'function'} . "\n";
1974 }
1975
1976 # output enum in list
1977 sub output_enum_list(%) {
1978     my %args = %{$_[0]};
1979     print $args{'enum'} . "\n";
1980 }
1981
1982 # output typedef in list
1983 sub output_typedef_list(%) {
1984     my %args = %{$_[0]};
1985     print $args{'typedef'} . "\n";
1986 }
1987
1988 # output struct as list
1989 sub output_struct_list(%) {
1990     my %args = %{$_[0]};
1991
1992     print $args{'struct'} . "\n";
1993 }
1994
1995 sub output_blockhead_list(%) {
1996     my %args = %{$_[0]};
1997     my ($parameter, $section);
1998
1999     foreach $section (@{$args{'sectionlist'}}) {
2000         print "DOC: $section\n";
2001     }
2002 }
2003
2004 ##
2005 # generic output function for all types (function, struct/union, typedef, enum);
2006 # calls the generated, variable output_ function name based on
2007 # functype and output_mode
2008 sub output_declaration {
2009     no strict 'refs';
2010     my $name = shift;
2011     my $functype = shift;
2012     my $func = "output_${functype}_$output_mode";
2013     if (($output_selection == OUTPUT_ALL) ||
2014         (($output_selection == OUTPUT_INCLUDE ||
2015           $output_selection == OUTPUT_EXPORTED) &&
2016          defined($function_table{$name})) ||
2017         (($output_selection == OUTPUT_EXCLUDE ||
2018           $output_selection == OUTPUT_INTERNAL) &&
2019          !($functype eq "function" && defined($function_table{$name}))))
2020     {
2021         &$func(@_);
2022         $section_counter++;
2023     }
2024 }
2025
2026 ##
2027 # generic output function - calls the right one based on current output mode.
2028 sub output_blockhead {
2029     no strict 'refs';
2030     my $func = "output_blockhead_" . $output_mode;
2031     &$func(@_);
2032     $section_counter++;
2033 }
2034
2035 ##
2036 # takes a declaration (struct, union, enum, typedef) and
2037 # invokes the right handler. NOT called for functions.
2038 sub dump_declaration($$) {
2039     no strict 'refs';
2040     my ($prototype, $file) = @_;
2041     my $func = "dump_" . $decl_type;
2042     &$func(@_);
2043 }
2044
2045 sub dump_union($$) {
2046     dump_struct(@_);
2047 }
2048
2049 sub dump_struct($$) {
2050     my $x = shift;
2051     my $file = shift;
2052     my $nested;
2053
2054     if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
2055         #my $decl_type = $1;
2056         $declaration_name = $2;
2057         my $members = $3;
2058
2059         # ignore embedded structs or unions
2060         $members =~ s/({.*})//g;
2061         $nested = $1;
2062
2063         # ignore members marked private:
2064         $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
2065         $members =~ s/\/\*\s*private:.*//gosi;
2066         # strip comments:
2067         $members =~ s/\/\*.*?\*\///gos;
2068         $nested =~ s/\/\*.*?\*\///gos;
2069         # strip kmemcheck_bitfield_{begin,end}.*;
2070         $members =~ s/kmemcheck_bitfield_.*?;//gos;
2071         # strip attributes
2072         $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
2073         $members =~ s/__aligned\s*\([^;]*\)//gos;
2074         $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
2075         # replace DECLARE_BITMAP
2076         $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
2077
2078         create_parameterlist($members, ';', $file);
2079         check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
2080
2081         output_declaration($declaration_name,
2082                            'struct',
2083                            {'struct' => $declaration_name,
2084                             'module' => $modulename,
2085                             'parameterlist' => \@parameterlist,
2086                             'parameterdescs' => \%parameterdescs,
2087                             'parametertypes' => \%parametertypes,
2088                             'sectionlist' => \@sectionlist,
2089                             'sections' => \%sections,
2090                             'purpose' => $declaration_purpose,
2091                             'type' => $decl_type
2092                            });
2093     }
2094     else {
2095         print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
2096         ++$errors;
2097     }
2098 }
2099
2100 sub dump_enum($$) {
2101     my $x = shift;
2102     my $file = shift;
2103
2104     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
2105     # strip #define macros inside enums
2106     $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
2107
2108     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
2109         $declaration_name = $1;
2110         my $members = $2;
2111
2112         foreach my $arg (split ',', $members) {
2113             $arg =~ s/^\s*(\w+).*/$1/;
2114             push @parameterlist, $arg;
2115             if (!$parameterdescs{$arg}) {
2116                 $parameterdescs{$arg} = $undescribed;
2117                 print STDERR "${file}:$.: warning: Enum value '$arg' ".
2118                     "not described in enum '$declaration_name'\n";
2119             }
2120
2121         }
2122
2123         output_declaration($declaration_name,
2124                            'enum',
2125                            {'enum' => $declaration_name,
2126                             'module' => $modulename,
2127                             'parameterlist' => \@parameterlist,
2128                             'parameterdescs' => \%parameterdescs,
2129                             'sectionlist' => \@sectionlist,
2130                             'sections' => \%sections,
2131                             'purpose' => $declaration_purpose
2132                            });
2133     }
2134     else {
2135         print STDERR "${file}:$.: error: Cannot parse enum!\n";
2136         ++$errors;
2137     }
2138 }
2139
2140 sub dump_typedef($$) {
2141     my $x = shift;
2142     my $file = shift;
2143
2144     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
2145
2146     # Parse function prototypes
2147     if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/) {
2148         # Function typedefs
2149         $return_type = $1;
2150         $declaration_name = $2;
2151         my $args = $3;
2152
2153         create_parameterlist($args, ',', $file);
2154
2155         output_declaration($declaration_name,
2156                            'function',
2157                            {'function' => $declaration_name,
2158                             'module' => $modulename,
2159                             'functiontype' => $return_type,
2160                             'parameterlist' => \@parameterlist,
2161                             'parameterdescs' => \%parameterdescs,
2162                             'parametertypes' => \%parametertypes,
2163                             'sectionlist' => \@sectionlist,
2164                             'sections' => \%sections,
2165                             'purpose' => $declaration_purpose
2166                            });
2167         return;
2168     }
2169
2170     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
2171         $x =~ s/\(*.\)\s*;$/;/;
2172         $x =~ s/\[*.\]\s*;$/;/;
2173     }
2174
2175     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
2176         $declaration_name = $1;
2177
2178         output_declaration($declaration_name,
2179                            'typedef',
2180                            {'typedef' => $declaration_name,
2181                             'module' => $modulename,
2182                             'sectionlist' => \@sectionlist,
2183                             'sections' => \%sections,
2184                             'purpose' => $declaration_purpose
2185                            });
2186     }
2187     else {
2188         print STDERR "${file}:$.: error: Cannot parse typedef!\n";
2189         ++$errors;
2190     }
2191 }
2192
2193 sub save_struct_actual($) {
2194     my $actual = shift;
2195
2196     # strip all spaces from the actual param so that it looks like one string item
2197     $actual =~ s/\s*//g;
2198     $struct_actual = $struct_actual . $actual . " ";
2199 }
2200
2201 sub create_parameterlist($$$) {
2202     my $args = shift;
2203     my $splitter = shift;
2204     my $file = shift;
2205     my $type;
2206     my $param;
2207
2208     # temporarily replace commas inside function pointer definition
2209     while ($args =~ /(\([^\),]+),/) {
2210         $args =~ s/(\([^\),]+),/$1#/g;
2211     }
2212
2213     foreach my $arg (split($splitter, $args)) {
2214         # strip comments
2215         $arg =~ s/\/\*.*\*\///;
2216         # strip leading/trailing spaces
2217         $arg =~ s/^\s*//;
2218         $arg =~ s/\s*$//;
2219         $arg =~ s/\s+/ /;
2220
2221         if ($arg =~ /^#/) {
2222             # Treat preprocessor directive as a typeless variable just to fill
2223             # corresponding data structures "correctly". Catch it later in
2224             # output_* subs.
2225             push_parameter($arg, "", $file);
2226         } elsif ($arg =~ m/\(.+\)\s*\(/) {
2227             # pointer-to-function
2228             $arg =~ tr/#/,/;
2229             $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
2230             $param = $1;
2231             $type = $arg;
2232             $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
2233             save_struct_actual($param);
2234             push_parameter($param, $type, $file);
2235         } elsif ($arg) {
2236             $arg =~ s/\s*:\s*/:/g;
2237             $arg =~ s/\s*\[/\[/g;
2238
2239             my @args = split('\s*,\s*', $arg);
2240             if ($args[0] =~ m/\*/) {
2241                 $args[0] =~ s/(\*+)\s*/ $1/;
2242             }
2243
2244             my @first_arg;
2245             if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
2246                     shift @args;
2247                     push(@first_arg, split('\s+', $1));
2248                     push(@first_arg, $2);
2249             } else {
2250                     @first_arg = split('\s+', shift @args);
2251             }
2252
2253             unshift(@args, pop @first_arg);
2254             $type = join " ", @first_arg;
2255
2256             foreach $param (@args) {
2257                 if ($param =~ m/^(\*+)\s*(.*)/) {
2258                     save_struct_actual($2);
2259                     push_parameter($2, "$type $1", $file);
2260                 }
2261                 elsif ($param =~ m/(.*?):(\d+)/) {
2262                     if ($type ne "") { # skip unnamed bit-fields
2263                         save_struct_actual($1);
2264                         push_parameter($1, "$type:$2", $file)
2265                     }
2266                 }
2267                 else {
2268                     save_struct_actual($param);
2269                     push_parameter($param, $type, $file);
2270                 }
2271             }
2272         }
2273     }
2274 }
2275
2276 sub push_parameter($$$) {
2277         my $param = shift;
2278         my $type = shift;
2279         my $file = shift;
2280
2281         if (($anon_struct_union == 1) && ($type eq "") &&
2282             ($param eq "}")) {
2283                 return;         # ignore the ending }; from anon. struct/union
2284         }
2285
2286         $anon_struct_union = 0;
2287         my $param_name = $param;
2288         $param_name =~ s/\[.*//;
2289
2290         if ($type eq "" && $param =~ /\.\.\.$/)
2291         {
2292             if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
2293                 $parameterdescs{$param} = "variable arguments";
2294             }
2295         }
2296         elsif ($type eq "" && ($param eq "" or $param eq "void"))
2297         {
2298             $param="void";
2299             $parameterdescs{void} = "no arguments";
2300         }
2301         elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
2302         # handle unnamed (anonymous) union or struct:
2303         {
2304                 $type = $param;
2305                 $param = "{unnamed_" . $param . "}";
2306                 $parameterdescs{$param} = "anonymous\n";
2307                 $anon_struct_union = 1;
2308         }
2309
2310         # warn if parameter has no description
2311         # (but ignore ones starting with # as these are not parameters
2312         # but inline preprocessor statements);
2313         # also ignore unnamed structs/unions;
2314         if (!$anon_struct_union) {
2315         if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
2316
2317             $parameterdescs{$param_name} = $undescribed;
2318
2319             if (($type eq 'function') || ($type eq 'enum')) {
2320                 print STDERR "${file}:$.: warning: Function parameter ".
2321                     "or member '$param' not " .
2322                     "described in '$declaration_name'\n";
2323             }
2324             print STDERR "${file}:$.: warning:" .
2325                          " No description found for parameter '$param'\n";
2326             ++$warnings;
2327         }
2328         }
2329
2330         $param = xml_escape($param);
2331
2332         # strip spaces from $param so that it is one continuous string
2333         # on @parameterlist;
2334         # this fixes a problem where check_sections() cannot find
2335         # a parameter like "addr[6 + 2]" because it actually appears
2336         # as "addr[6", "+", "2]" on the parameter list;
2337         # but it's better to maintain the param string unchanged for output,
2338         # so just weaken the string compare in check_sections() to ignore
2339         # "[blah" in a parameter string;
2340         ###$param =~ s/\s*//g;
2341         push @parameterlist, $param;
2342         $parametertypes{$param} = $type;
2343 }
2344
2345 sub check_sections($$$$$$) {
2346         my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
2347         my @sects = split ' ', $sectcheck;
2348         my @prms = split ' ', $prmscheck;
2349         my $err;
2350         my ($px, $sx);
2351         my $prm_clean;          # strip trailing "[array size]" and/or beginning "*"
2352
2353         foreach $sx (0 .. $#sects) {
2354                 $err = 1;
2355                 foreach $px (0 .. $#prms) {
2356                         $prm_clean = $prms[$px];
2357                         $prm_clean =~ s/\[.*\]//;
2358                         $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
2359                         # ignore array size in a parameter string;
2360                         # however, the original param string may contain
2361                         # spaces, e.g.:  addr[6 + 2]
2362                         # and this appears in @prms as "addr[6" since the
2363                         # parameter list is split at spaces;
2364                         # hence just ignore "[..." for the sections check;
2365                         $prm_clean =~ s/\[.*//;
2366
2367                         ##$prm_clean =~ s/^\**//;
2368                         if ($prm_clean eq $sects[$sx]) {
2369                                 $err = 0;
2370                                 last;
2371                         }
2372                 }
2373                 if ($err) {
2374                         if ($decl_type eq "function") {
2375                                 print STDERR "${file}:$.: warning: " .
2376                                         "Excess function parameter " .
2377                                         "'$sects[$sx]' " .
2378                                         "description in '$decl_name'\n";
2379                                 ++$warnings;
2380                         } else {
2381                                 if ($nested !~ m/\Q$sects[$sx]\E/) {
2382                                     print STDERR "${file}:$.: warning: " .
2383                                         "Excess struct/union/enum/typedef member " .
2384                                         "'$sects[$sx]' " .
2385                                         "description in '$decl_name'\n";
2386                                     ++$warnings;
2387                                 }
2388                         }
2389                 }
2390         }
2391 }
2392
2393 ##
2394 # Checks the section describing the return value of a function.
2395 sub check_return_section {
2396         my $file = shift;
2397         my $declaration_name = shift;
2398         my $return_type = shift;
2399
2400         # Ignore an empty return type (It's a macro)
2401         # Ignore functions with a "void" return type. (But don't ignore "void *")
2402         if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
2403                 return;
2404         }
2405
2406         if (!defined($sections{$section_return}) ||
2407             $sections{$section_return} eq "") {
2408                 print STDERR "${file}:$.: warning: " .
2409                         "No description found for return value of " .
2410                         "'$declaration_name'\n";
2411                 ++$warnings;
2412         }
2413 }
2414
2415 ##
2416 # takes a function prototype and the name of the current file being
2417 # processed and spits out all the details stored in the global
2418 # arrays/hashes.
2419 sub dump_function($$) {
2420     my $prototype = shift;
2421     my $file = shift;
2422     my $noret = 0;
2423
2424     $prototype =~ s/^static +//;
2425     $prototype =~ s/^extern +//;
2426     $prototype =~ s/^asmlinkage +//;
2427     $prototype =~ s/^inline +//;
2428     $prototype =~ s/^__inline__ +//;
2429     $prototype =~ s/^__inline +//;
2430     $prototype =~ s/^__always_inline +//;
2431     $prototype =~ s/^noinline +//;
2432     $prototype =~ s/__init +//;
2433     $prototype =~ s/__init_or_module +//;
2434     $prototype =~ s/__meminit +//;
2435     $prototype =~ s/__must_check +//;
2436     $prototype =~ s/__weak +//;
2437     my $define = $prototype =~ s/^#\s*define\s+//; #ak added
2438     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
2439
2440     # Yes, this truly is vile.  We are looking for:
2441     # 1. Return type (may be nothing if we're looking at a macro)
2442     # 2. Function name
2443     # 3. Function parameters.
2444     #
2445     # All the while we have to watch out for function pointer parameters
2446     # (which IIRC is what the two sections are for), C types (these
2447     # regexps don't even start to express all the possibilities), and
2448     # so on.
2449     #
2450     # If you mess with these regexps, it's a good idea to check that
2451     # the following functions' documentation still comes out right:
2452     # - parport_register_device (function pointer parameters)
2453     # - atomic_set (macro)
2454     # - pci_match_device, __copy_to_user (long return type)
2455
2456     if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) {
2457         # This is an object-like macro, it has no return type and no parameter
2458         # list.
2459         # Function-like macros are not allowed to have spaces between
2460         # declaration_name and opening parenthesis (notice the \s+).
2461         $return_type = $1;
2462         $declaration_name = $2;
2463         $noret = 1;
2464     } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2465         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2466         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2467         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2468         $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2469         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2470         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2471         $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2472         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2473         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2474         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2475         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2476         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2477         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2478         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2479         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2480         $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
2481         $return_type = $1;
2482         $declaration_name = $2;
2483         my $args = $3;
2484
2485         create_parameterlist($args, ',', $file);
2486     } else {
2487         print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n";
2488         return;
2489     }
2490
2491         my $prms = join " ", @parameterlist;
2492         check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
2493
2494         # This check emits a lot of warnings at the moment, because many
2495         # functions don't have a 'Return' doc section. So until the number
2496         # of warnings goes sufficiently down, the check is only performed in
2497         # verbose mode.
2498         # TODO: always perform the check.
2499         if ($verbose && !$noret) {
2500                 check_return_section($file, $declaration_name, $return_type);
2501         }
2502
2503     output_declaration($declaration_name,
2504                        'function',
2505                        {'function' => $declaration_name,
2506                         'module' => $modulename,
2507                         'functiontype' => $return_type,
2508                         'parameterlist' => \@parameterlist,
2509                         'parameterdescs' => \%parameterdescs,
2510                         'parametertypes' => \%parametertypes,
2511                         'sectionlist' => \@sectionlist,
2512                         'sections' => \%sections,
2513                         'purpose' => $declaration_purpose
2514                        });
2515 }
2516
2517 sub reset_state {
2518     $function = "";
2519     %parameterdescs = ();
2520     %parametertypes = ();
2521     @parameterlist = ();
2522     %sections = ();
2523     @sectionlist = ();
2524     $sectcheck = "";
2525     $struct_actual = "";
2526     $prototype = "";
2527
2528     $state = STATE_NORMAL;
2529     $inline_doc_state = STATE_INLINE_NA;
2530 }
2531
2532 sub tracepoint_munge($) {
2533         my $file = shift;
2534         my $tracepointname = 0;
2535         my $tracepointargs = 0;
2536
2537         if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
2538                 $tracepointname = $1;
2539         }
2540         if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
2541                 $tracepointname = $1;
2542         }
2543         if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
2544                 $tracepointname = $2;
2545         }
2546         $tracepointname =~ s/^\s+//; #strip leading whitespace
2547         if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
2548                 $tracepointargs = $1;
2549         }
2550         if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
2551                 print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n".
2552                              "$prototype\n";
2553         } else {
2554                 $prototype = "static inline void trace_$tracepointname($tracepointargs)";
2555         }
2556 }
2557
2558 sub syscall_munge() {
2559         my $void = 0;
2560
2561         $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
2562 ##      if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
2563         if ($prototype =~ m/SYSCALL_DEFINE0/) {
2564                 $void = 1;
2565 ##              $prototype = "long sys_$1(void)";
2566         }
2567
2568         $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
2569         if ($prototype =~ m/long (sys_.*?),/) {
2570                 $prototype =~ s/,/\(/;
2571         } elsif ($void) {
2572                 $prototype =~ s/\)/\(void\)/;
2573         }
2574
2575         # now delete all of the odd-number commas in $prototype
2576         # so that arg types & arg names don't have a comma between them
2577         my $count = 0;
2578         my $len = length($prototype);
2579         if ($void) {
2580                 $len = 0;       # skip the for-loop
2581         }
2582         for (my $ix = 0; $ix < $len; $ix++) {
2583                 if (substr($prototype, $ix, 1) eq ',') {
2584                         $count++;
2585                         if ($count % 2 == 1) {
2586                                 substr($prototype, $ix, 1) = ' ';
2587                         }
2588                 }
2589         }
2590 }
2591
2592 sub process_state3_function($$) {
2593     my $x = shift;
2594     my $file = shift;
2595
2596     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2597
2598     if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
2599         # do nothing
2600     }
2601     elsif ($x =~ /([^\{]*)/) {
2602         $prototype .= $1;
2603     }
2604
2605     if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
2606         $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
2607         $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2608         $prototype =~ s@^\s+@@gos; # strip leading spaces
2609         if ($prototype =~ /SYSCALL_DEFINE/) {
2610                 syscall_munge();
2611         }
2612         if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
2613             $prototype =~ /DEFINE_SINGLE_EVENT/)
2614         {
2615                 tracepoint_munge($file);
2616         }
2617         dump_function($prototype, $file);
2618         reset_state();
2619     }
2620 }
2621
2622 sub process_state3_type($$) {
2623     my $x = shift;
2624     my $file = shift;
2625
2626     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2627     $x =~ s@^\s+@@gos; # strip leading spaces
2628     $x =~ s@\s+$@@gos; # strip trailing spaces
2629     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2630
2631     if ($x =~ /^#/) {
2632         # To distinguish preprocessor directive from regular declaration later.
2633         $x .= ";";
2634     }
2635
2636     while (1) {
2637         if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
2638             $prototype .= $1 . $2;
2639             ($2 eq '{') && $brcount++;
2640             ($2 eq '}') && $brcount--;
2641             if (($2 eq ';') && ($brcount == 0)) {
2642                 dump_declaration($prototype, $file);
2643                 reset_state();
2644                 last;
2645             }
2646             $x = $3;
2647         } else {
2648             $prototype .= $x;
2649             last;
2650         }
2651     }
2652 }
2653
2654 # xml_escape: replace <, >, and & in the text stream;
2655 #
2656 # however, formatting controls that are generated internally/locally in the
2657 # kernel-doc script are not escaped here; instead, they begin life like
2658 # $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
2659 # are converted to their mnemonic-expected output, without the 4 * '\' & ':',
2660 # just before actual output; (this is done by local_unescape())
2661 sub xml_escape($) {
2662         my $text = shift;
2663         if (($output_mode eq "text") || ($output_mode eq "man")) {
2664                 return $text;
2665         }
2666         $text =~ s/\&/\\\\\\amp;/g;
2667         $text =~ s/\</\\\\\\lt;/g;
2668         $text =~ s/\>/\\\\\\gt;/g;
2669         return $text;
2670 }
2671
2672 # xml_unescape: reverse the effects of xml_escape
2673 sub xml_unescape($) {
2674         my $text = shift;
2675         if (($output_mode eq "text") || ($output_mode eq "man")) {
2676                 return $text;
2677         }
2678         $text =~ s/\\\\\\amp;/\&/g;
2679         $text =~ s/\\\\\\lt;/</g;
2680         $text =~ s/\\\\\\gt;/>/g;
2681         return $text;
2682 }
2683
2684 # convert local escape strings to html
2685 # local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
2686 sub local_unescape($) {
2687         my $text = shift;
2688         if (($output_mode eq "text") || ($output_mode eq "man")) {
2689                 return $text;
2690         }
2691         $text =~ s/\\\\\\\\lt:/</g;
2692         $text =~ s/\\\\\\\\gt:/>/g;
2693         return $text;
2694 }
2695
2696 sub process_file($) {
2697     my $file;
2698     my $identifier;
2699     my $func;
2700     my $descr;
2701     my $in_purpose = 0;
2702     my $initial_section_counter = $section_counter;
2703     my ($orig_file) = @_;
2704     my $leading_space;
2705
2706     if (defined($ENV{'SRCTREE'})) {
2707         $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
2708     }
2709     else {
2710         $file = $orig_file;
2711     }
2712     if (defined($source_map{$file})) {
2713         $file = $source_map{$file};
2714     }
2715
2716     if (!open(IN,"<$file")) {
2717         print STDERR "Error: Cannot open file $file\n";
2718         ++$errors;
2719         return;
2720     }
2721
2722     # two passes for -export and -internal
2723     if ($output_selection == OUTPUT_EXPORTED ||
2724         $output_selection == OUTPUT_INTERNAL) {
2725         while (<IN>) {
2726             if (/$export_symbol/o) {
2727                 $function_table{$2} = 1;
2728             }
2729         }
2730         seek(IN, 0, 0);
2731     }
2732
2733     $. = 1;
2734
2735     $section_counter = 0;
2736     while (<IN>) {
2737         while (s/\\\s*$//) {
2738             $_ .= <IN>;
2739         }
2740         if ($state == STATE_NORMAL) {
2741             if (/$doc_start/o) {
2742                 $state = STATE_NAME;    # next line is always the function name
2743                 $in_doc_sect = 0;
2744             }
2745         } elsif ($state == STATE_NAME) {# this line is the function name (always)
2746             if (/$doc_block/o) {
2747                 $state = STATE_DOCBLOCK;
2748                 $contents = "";
2749                 if ( $1 eq "" ) {
2750                         $section = $section_intro;
2751                 } else {
2752                         $section = $1;
2753                 }
2754             }
2755             elsif (/$doc_decl/o) {
2756                 $identifier = $1;
2757                 if (/\s*([\w\s]+?)\s*-/) {
2758                     $identifier = $1;
2759                 }
2760
2761                 $state = STATE_FIELD;
2762                 if (/-(.*)/) {
2763                     # strip leading/trailing/multiple spaces
2764                     $descr= $1;
2765                     $descr =~ s/^\s*//;
2766                     $descr =~ s/\s*$//;
2767                     $descr =~ s/\s+/ /g;
2768                     $declaration_purpose = xml_escape($descr);
2769                     $in_purpose = 1;
2770                 } else {
2771                     $declaration_purpose = "";
2772                 }
2773
2774                 if (($declaration_purpose eq "") && $verbose) {
2775                         print STDERR "${file}:$.: warning: missing initial short description on line:\n";
2776                         print STDERR $_;
2777                         ++$warnings;
2778                 }
2779
2780                 if ($identifier =~ m/^struct/) {
2781                     $decl_type = 'struct';
2782                 } elsif ($identifier =~ m/^union/) {
2783                     $decl_type = 'union';
2784                 } elsif ($identifier =~ m/^enum/) {
2785                     $decl_type = 'enum';
2786                 } elsif ($identifier =~ m/^typedef/) {
2787                     $decl_type = 'typedef';
2788                 } else {
2789                     $decl_type = 'function';
2790                 }
2791
2792                 if ($verbose) {
2793                     print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
2794                 }
2795             } else {
2796                 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
2797                 " - I thought it was a doc line\n";
2798                 ++$warnings;
2799                 $state = STATE_NORMAL;
2800             }
2801         } elsif ($state == STATE_FIELD) {       # look for head: lines, and include content
2802             if (/$doc_sect/o) {
2803                 $newsection = $1;
2804                 $newcontents = $2;
2805
2806                 if (($contents ne "") && ($contents ne "\n")) {
2807                     if (!$in_doc_sect && $verbose) {
2808                         print STDERR "${file}:$.: warning: contents before sections\n";
2809                         ++$warnings;
2810                     }
2811                     dump_section($file, $section, xml_escape($contents));
2812                     $section = $section_default;
2813                 }
2814
2815                 $in_doc_sect = 1;
2816                 $in_purpose = 0;
2817                 $contents = $newcontents;
2818                 while ((substr($contents, 0, 1) eq " ") ||
2819                        substr($contents, 0, 1) eq "\t") {
2820                     $contents = substr($contents, 1);
2821                 }
2822                 if ($contents ne "") {
2823                     $contents .= "\n";
2824                 }
2825                 $section = $newsection;
2826                 $leading_space = undef;
2827             } elsif (/$doc_end/) {
2828                 if (($contents ne "") && ($contents ne "\n")) {
2829                     dump_section($file, $section, xml_escape($contents));
2830                     $section = $section_default;
2831                     $contents = "";
2832                 }
2833                 # look for doc_com + <text> + doc_end:
2834                 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
2835                     print STDERR "${file}:$.: warning: suspicious ending line: $_";
2836                     ++$warnings;
2837                 }
2838
2839                 $prototype = "";
2840                 $state = STATE_PROTO;
2841                 $brcount = 0;
2842 #               print STDERR "end of doc comment, looking for prototype\n";
2843             } elsif (/$doc_content/) {
2844                 # miguel-style comment kludge, look for blank lines after
2845                 # @parameter line to signify start of description
2846                 if ($1 eq "") {
2847                     if ($section =~ m/^@/ || $section eq $section_context) {
2848                         dump_section($file, $section, xml_escape($contents));
2849                         $section = $section_default;
2850                         $contents = "";
2851                     } else {
2852                         $contents .= "\n";
2853                     }
2854                     $in_purpose = 0;
2855                 } elsif ($in_purpose == 1) {
2856                     # Continued declaration purpose
2857                     chomp($declaration_purpose);
2858                     $declaration_purpose .= " " . xml_escape($1);
2859                     $declaration_purpose =~ s/\s+/ /g;
2860                 } else {
2861                     my $cont = $1;
2862                     if ($section =~ m/^@/ || $section eq $section_context) {
2863                         if (!defined $leading_space) {
2864                             if ($cont =~ m/^(\s+)/) {
2865                                 $leading_space = $1;
2866                             } else {
2867                                 $leading_space = "";
2868                             }
2869                         }
2870
2871                         $cont =~ s/^$leading_space//;
2872                     }
2873                     $contents .= $cont . "\n";
2874                 }
2875             } else {
2876                 # i dont know - bad line?  ignore.
2877                 print STDERR "${file}:$.: warning: bad line: $_";
2878                 ++$warnings;
2879             }
2880         } elsif ($state == STATE_INLINE) { # scanning for inline parameters
2881             # First line (state 1) needs to be a @parameter
2882             if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
2883                 $section = $1;
2884                 $contents = $2;
2885                 if ($contents ne "") {
2886                     while ((substr($contents, 0, 1) eq " ") ||
2887                            substr($contents, 0, 1) eq "\t") {
2888                         $contents = substr($contents, 1);
2889                     }
2890                     $contents .= "\n";
2891                 }
2892                 $inline_doc_state = STATE_INLINE_TEXT;
2893             # Documentation block end */
2894             } elsif (/$doc_inline_end/) {
2895                 if (($contents ne "") && ($contents ne "\n")) {
2896                     dump_section($file, $section, xml_escape($contents));
2897                     $section = $section_default;
2898                     $contents = "";
2899                 }
2900                 $state = STATE_PROTO;
2901                 $inline_doc_state = STATE_INLINE_NA;
2902             # Regular text
2903             } elsif (/$doc_content/) {
2904                 if ($inline_doc_state == STATE_INLINE_TEXT) {
2905                     $contents .= $1 . "\n";
2906                     # nuke leading blank lines
2907                     if ($contents =~ /^\s*$/) {
2908                         $contents = "";
2909                     }
2910                 } elsif ($inline_doc_state == STATE_INLINE_NAME) {
2911                     $inline_doc_state = STATE_INLINE_ERROR;
2912                     print STDERR "Warning(${file}:$.): ";
2913                     print STDERR "Incorrect use of kernel-doc format: $_";
2914                     ++$warnings;
2915                 }
2916             }
2917         } elsif ($state == STATE_PROTO) {       # scanning for function '{' (end of prototype)
2918             if (/$doc_inline_start/) {
2919                 $state = STATE_INLINE;
2920                 $inline_doc_state = STATE_INLINE_NAME;
2921             } elsif ($decl_type eq 'function') {
2922                 process_state3_function($_, $file);
2923             } else {
2924                 process_state3_type($_, $file);
2925             }
2926         } elsif ($state == STATE_DOCBLOCK) {
2927                 # Documentation block
2928                 if (/$doc_block/) {
2929                         dump_doc_section($file, $section, xml_escape($contents));
2930                         $contents = "";
2931                         $function = "";
2932                         %parameterdescs = ();
2933                         %parametertypes = ();
2934                         @parameterlist = ();
2935                         %sections = ();
2936                         @sectionlist = ();
2937                         $prototype = "";
2938                         if ( $1 eq "" ) {
2939                                 $section = $section_intro;
2940                         } else {
2941                                 $section = $1;
2942                         }
2943                 }
2944                 elsif (/$doc_end/)
2945                 {
2946                         dump_doc_section($file, $section, xml_escape($contents));
2947                         $contents = "";
2948                         $function = "";
2949                         %parameterdescs = ();
2950                         %parametertypes = ();
2951                         @parameterlist = ();
2952                         %sections = ();
2953                         @sectionlist = ();
2954                         $prototype = "";
2955                         $state = STATE_NORMAL;
2956                 }
2957                 elsif (/$doc_content/)
2958                 {
2959                         if ( $1 eq "" )
2960                         {
2961                                 $contents .= $blankline;
2962                         }
2963                         else
2964                         {
2965                                 $contents .= $1 . "\n";
2966                         }
2967                 }
2968         }
2969     }
2970     if ($initial_section_counter == $section_counter) {
2971         print STDERR "${file}:1: warning: no structured comments found\n";
2972         if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
2973             print STDERR "    Was looking for '$_'.\n" for keys %function_table;
2974         }
2975         if ($output_mode eq "xml") {
2976             # The template wants at least one RefEntry here; make one.
2977             print "<refentry>\n";
2978             print " <refnamediv>\n";
2979             print "  <refname>\n";
2980             print "   ${orig_file}\n";
2981             print "  </refname>\n";
2982             print "  <refpurpose>\n";
2983             print "   Document generation inconsistency\n";
2984             print "  </refpurpose>\n";
2985             print " </refnamediv>\n";
2986             print " <refsect1>\n";
2987             print "  <title>\n";
2988             print "   Oops\n";
2989             print "  </title>\n";
2990             print "  <warning>\n";
2991             print "   <para>\n";
2992             print "    The template for this document tried to insert\n";
2993             print "    the structured comment from the file\n";
2994             print "    <filename>${orig_file}</filename> at this point,\n";
2995             print "    but none was found.\n";
2996             print "    This dummy section is inserted to allow\n";
2997             print "    generation to continue.\n";
2998             print "   </para>\n";
2999             print "  </warning>\n";
3000             print " </refsect1>\n";
3001             print "</refentry>\n";
3002         }
3003     }
3004 }
3005
3006
3007 $kernelversion = get_kernel_version();
3008
3009 # generate a sequence of code that will splice in highlighting information
3010 # using the s// operator.
3011 for (my $k = 0; $k < @highlights; $k++) {
3012     my $pattern = $highlights[$k][0];
3013     my $result = $highlights[$k][1];
3014 #   print STDERR "scanning pattern:$pattern, highlight:($result)\n";
3015     $dohighlight .=  "\$contents =~ s:$pattern:$result:gs;\n";
3016 }
3017
3018 # Read the file that maps relative names to absolute names for
3019 # separate source and object directories and for shadow trees.
3020 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
3021         my ($relname, $absname);
3022         while(<SOURCE_MAP>) {
3023                 chop();
3024                 ($relname, $absname) = (split())[0..1];
3025                 $relname =~ s:^/+::;
3026                 $source_map{$relname} = $absname;
3027         }
3028         close(SOURCE_MAP);
3029 }
3030
3031 foreach (@ARGV) {
3032     chomp;
3033     process_file($_);
3034 }
3035 if ($verbose && $errors) {
3036   print STDERR "$errors errors\n";
3037 }
3038 if ($verbose && $warnings) {
3039   print STDERR "$warnings warnings\n";
3040 }
3041
3042 exit($errors);