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