xref: /openbmc/linux/scripts/kernel-doc (revision 12653414)
1#!/usr/bin/env perl
2
3use warnings;
4use 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
43sub usage {
44    my $message = <<"EOF";
45Usage: $0 [OPTION ...] FILE ...
46
47Read C language source or header FILEs, extract embedded documentation comments,
48and print formatted documentation to standard output.
49
50The documentation comments are identified by "/**" opening comment mark. See
51Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax.
52
53Output 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
62Output 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
76Output 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
84Other parameters:
85  -v			Verbose output, more warnings and other information.
86  -h			Print this help.
87
88EOF
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
210my $errors = 0;
211my $warnings = 0;
212my $anon_struct_union = 0;
213
214# match expressions used to find embedded type information
215my $type_constant = '\b``([^\`]+)``\b';
216my $type_constant2 = '\%([-_\w]+)';
217my $type_func = '(\w+)\(\)';
218my $type_param = '\@(\w+(\.\.\.)?)';
219my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
220my $type_env = '(\$\w+)';
221my $type_enum = '\&(enum\s*([_\w]+))';
222my $type_struct = '\&(struct\s*([_\w]+))';
223my $type_typedef = '\&(typedef\s*([_\w]+))';
224my $type_union = '\&(union\s*([_\w]+))';
225my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
226my $type_fallback = '\&([_\w]+)';
227my $type_enum_xml = '\&amp;(enum\s*([_\w]+))';
228my $type_struct_xml = '\&amp;(struct\s*([_\w]+))';
229my $type_typedef_xml = '\&amp;(typedef\s*([_\w]+))';
230my $type_union_xml = '\&amp;(union\s*([_\w]+))';
231my $type_member_xml = '\&amp;([_\w]+)(\.|-\&gt;)([_\w]+)';
232my $type_fallback_xml = '\&amp([_\w]+)';
233my $type_member_func = $type_member . '\(\)';
234
235# Output conversion substitutions.
236#  One for each output format
237
238# these work fairly well
239my @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                      );
252my $local_lt = "\\\\\\\\lt:";
253my $local_gt = "\\\\\\\\gt:";
254my $blankline_html = $local_lt . "p" . $local_gt;	# was "<p>"
255
256# html version 5
257my @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		       );
270my $blankline_html5 = $local_lt . "br /" . $local_gt;
271
272# XML, docbook format
273my @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		     );
287my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
288
289# gnome, docbook format
290my @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		       );
303my $blankline_gnome = "</para><para>\n";
304
305# these are pretty rough
306my @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		     );
318my $blankline_man = "";
319
320# text-mode
321my @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		      );
333my $blankline_text = "";
334
335# rst-mode
336my @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		      );
352my $blankline_rst = "\n";
353
354# list mode
355my @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		      );
367my $blankline_list = "";
368
369# read arguments
370if ($#ARGV == -1) {
371    usage();
372}
373
374my $kernelversion;
375my $dohighlight = "";
376
377my $verbose = 0;
378my $output_mode = "man";
379my $output_preformatted = 0;
380my $no_doc_sections = 0;
381my $enable_lineno = 0;
382my @highlights = @highlights_man;
383my $blankline = $blankline_man;
384my $modulename = "Kernel API";
385
386use 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};
393my $output_selection = OUTPUT_ALL;
394my $show_not_found = 0;
395
396my @export_file_list;
397
398my @build_time;
399if (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
406my $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.
415my ($function, %function_table, %parametertypes, $declaration_purpose);
416my $declaration_start_line;
417my ($type, $declaration_name, $return_type);
418my ($newsection, $newcontents, $prototype, $brcount, %source_map);
419
420if (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.
430my $section_counter = 0;
431
432my $lineprefix="";
433
434# Parser states
435use 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};
443my $state;
444my $in_doc_sect;
445
446# Inline documentation state
447use 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};
456my $inline_doc_state;
457
458#declaration types: can be
459# 'function', 'struct', 'union', 'enum', 'typedef'
460my $decl_type;
461
462my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
463my $doc_end = '\*/';
464my $doc_com = '\s*\*\s*';
465my $doc_com_body = '\s*\* ?';
466my $doc_decl = $doc_com . '(\w+)';
467# @params and a strictly limited set of supported section names
468my $doc_sect = $doc_com .
469    '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
470my $doc_content = $doc_com_body . '(.*)';
471my $doc_block = $doc_com . 'DOC:\s*(.*)?';
472my $doc_inline_start = '^\s*/\*\*\s*$';
473my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
474my $doc_inline_end = '^\s*\*/\s*$';
475my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
476my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
477
478my %parameterdescs;
479my %parameterdesc_start_lines;
480my @parameterlist;
481my %sections;
482my @sectionlist;
483my %section_start_lines;
484my $sectcheck;
485my $struct_actual;
486
487my $contents = "";
488my $new_start_line = 0;
489
490# the canonical section names. see also $doc_sect above.
491my $section_default = "Description";	# default section
492my $section_intro = "Introduction";
493my $section = $section_default;
494my $section_context = "Context";
495my $section_return = "Return";
496
497my $undescribed = "-- undescribed --";
498
499reset_state();
500
501while ($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
570sub 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#
580sub 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#
589sub 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#
626sub 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
660sub 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
707sub 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
720sub 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
751sub 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
763sub 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
810sub 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
852sub 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
867sub 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
882sub 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
926sub 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
948sub 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
1019sub 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
1081sub 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
1099sub 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
1125sub 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
1204sub 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
1298sub 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
1366sub 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
1403sub 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
1439sub 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
1519sub 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
1570sub 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
1611sub 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
1666sub 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
1681sub 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
1696sub 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
1741sub 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
1754sub 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
1783sub 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
1794sub 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
1838sub 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#
1858sub 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
1872sub 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
1887sub 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
1963sub 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
1979sub 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
2008sub 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
2024sub 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
2086sub output_function_list(%) {
2087    my %args = %{$_[0]};
2088
2089    print $args{'function'} . "\n";
2090}
2091
2092# output enum in list
2093sub output_enum_list(%) {
2094    my %args = %{$_[0]};
2095    print $args{'enum'} . "\n";
2096}
2097
2098# output typedef in list
2099sub output_typedef_list(%) {
2100    my %args = %{$_[0]};
2101    print $args{'typedef'} . "\n";
2102}
2103
2104# output struct as list
2105sub output_struct_list(%) {
2106    my %args = %{$_[0]};
2107
2108    print $args{'struct'} . "\n";
2109}
2110
2111sub 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
2124sub 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.
2144sub 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.
2154sub dump_declaration($$) {
2155    no strict 'refs';
2156    my ($prototype, $file) = @_;
2157    my $func = "dump_" . $decl_type;
2158    &$func(@_);
2159}
2160
2161sub dump_union($$) {
2162    dump_struct(@_);
2163}
2164
2165sub 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
2218sub 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
2258sub 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
2314sub 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
2322sub 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
2397sub 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
2470sub 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.
2520sub 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.
2544sub 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
2648sub 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
2663sub 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
2689sub 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
2723sub 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
2753sub 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())
2792sub 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
2804sub 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)
2817sub 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
2827sub 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
2844sub 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
2863sub 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.
3175for (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.
3184if (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
3195if ($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
3206foreach (@ARGV) {
3207    chomp;
3208    process_file($_);
3209}
3210if ($verbose && $errors) {
3211  print STDERR "$errors errors\n";
3212}
3213if ($verbose && $warnings) {
3214  print STDERR "$warnings warnings\n";
3215}
3216
3217exit($errors);
3218