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