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