~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kernel-doc

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/kernel-doc (Architecture mips) and /scripts/kernel-doc (Architecture i386)


  1 #!/usr/bin/env perl                                 1 #!/usr/bin/env perl
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3 # vim: softtabstop=4                                3 # vim: softtabstop=4
  4                                                     4 
  5 use warnings;                                       5 use warnings;
  6 use strict;                                         6 use strict;
  7                                                     7 
  8 ## Copyright (c) 1998 Michael Zucchi, All Righ      8 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
  9 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@red      9 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
 10 ## Copyright (C) 2001  Simon Huggins               10 ## Copyright (C) 2001  Simon Huggins                             ##
 11 ## Copyright (C) 2005-2012  Randy Dunlap           11 ## Copyright (C) 2005-2012  Randy Dunlap                         ##
 12 ## Copyright (C) 2012  Dan Luedtke                 12 ## Copyright (C) 2012  Dan Luedtke                               ##
 13 ##                                                 13 ##                                                               ##
 14 ## #define enhancements by Armin Kuster <akuste     14 ## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
 15 ## Copyright (c) 2000 MontaVista Software, Inc     15 ## Copyright (c) 2000 MontaVista Software, Inc.                  ##
 16 #                                                  16 #
 17 # Copyright (C) 2022 Tomasz Warniełło (POD)      17 # Copyright (C) 2022 Tomasz Warniełło (POD)
 18                                                    18 
 19 use Pod::Usage qw/pod2usage/;                      19 use Pod::Usage qw/pod2usage/;
 20                                                    20 
 21 =head1 NAME                                        21 =head1 NAME
 22                                                    22 
 23 kernel-doc - Print formatted kernel documentat     23 kernel-doc - Print formatted kernel documentation to stdout
 24                                                    24 
 25 =head1 SYNOPSIS                                    25 =head1 SYNOPSIS
 26                                                    26 
 27  kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wret     27  kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-desc[ription]] [-Wcontents-before-sections]
 28    [ -man |                                        28    [ -man |
 29      -rst [-sphinx-version VERSION] [-enable-l     29      -rst [-sphinx-version VERSION] [-enable-lineno] |
 30      -none                                         30      -none
 31    ]                                               31    ]
 32    [                                               32    [
 33      -export |                                     33      -export |
 34      -internal |                                   34      -internal |
 35      [-function NAME] ... |                        35      [-function NAME] ... |
 36      [-nosymbol NAME] ...                          36      [-nosymbol NAME] ...
 37    ]                                               37    ]
 38    [-no-doc-sections]                              38    [-no-doc-sections]
 39    [-export-file FILE] ...                         39    [-export-file FILE] ...
 40    FILE ...                                        40    FILE ...
 41                                                    41 
 42 Run `kernel-doc -h` for details.                   42 Run `kernel-doc -h` for details.
 43                                                    43 
 44 =head1 DESCRIPTION                                 44 =head1 DESCRIPTION
 45                                                    45 
 46 Read C language source or header FILEs, extrac     46 Read C language source or header FILEs, extract embedded documentation comments,
 47 and print formatted documentation to standard      47 and print formatted documentation to standard output.
 48                                                    48 
 49 The documentation comments are identified by t     49 The documentation comments are identified by the "/**" opening comment mark.
 50                                                    50 
 51 See Documentation/doc-guide/kernel-doc.rst for     51 See Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
 52                                                    52 
 53 =cut                                               53 =cut
 54                                                    54 
 55 # more perldoc at the end of the file              55 # more perldoc at the end of the file
 56                                                    56 
 57 ## init lots of data                               57 ## init lots of data
 58                                                    58 
 59 my $errors = 0;                                    59 my $errors = 0;
 60 my $warnings = 0;                                  60 my $warnings = 0;
 61 my $anon_struct_union = 0;                         61 my $anon_struct_union = 0;
 62                                                    62 
 63 # match expressions used to find embedded type     63 # match expressions used to find embedded type information
 64 my $type_constant = '\b``([^\`]+)``\b';            64 my $type_constant = '\b``([^\`]+)``\b';
 65 my $type_constant2 = '\%([-_*\w]+)';               65 my $type_constant2 = '\%([-_*\w]+)';
 66 my $type_func = '(\w+)\(\)';                       66 my $type_func = '(\w+)\(\)';
 67 my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\     67 my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
 68 my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)     68 my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
 69 my $type_fp_param = '\@(\w+)\(\)';  # Special      69 my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
 70 my $type_fp_param2 = '\@(\w+->\S+)\(\)';  # Sp     70 my $type_fp_param2 = '\@(\w+->\S+)\(\)';  # Special RST handling for structs with func ptr params
 71 my $type_env = '(\$\w+)';                          71 my $type_env = '(\$\w+)';
 72 my $type_enum = '\&(enum\s*([_\w]+))';             72 my $type_enum = '\&(enum\s*([_\w]+))';
 73 my $type_struct = '\&(struct\s*([_\w]+))';         73 my $type_struct = '\&(struct\s*([_\w]+))';
 74 my $type_typedef = '\&(typedef\s*([_\w]+))';       74 my $type_typedef = '\&(typedef\s*([_\w]+))';
 75 my $type_union = '\&(union\s*([_\w]+))';           75 my $type_union = '\&(union\s*([_\w]+))';
 76 my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';     76 my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
 77 my $type_fallback = '\&([_\w]+)';                  77 my $type_fallback = '\&([_\w]+)';
 78 my $type_member_func = $type_member . '\(\)';      78 my $type_member_func = $type_member . '\(\)';
 79                                                    79 
 80 # Output conversion substitutions.                 80 # Output conversion substitutions.
 81 #  One for each output format                      81 #  One for each output format
 82                                                    82 
 83 # these are pretty rough                           83 # these are pretty rough
 84 my @highlights_man = (                             84 my @highlights_man = (
 85     [$type_constant, "\$1"],                       85     [$type_constant, "\$1"],
 86     [$type_constant2, "\$1"],                      86     [$type_constant2, "\$1"],
 87     [$type_func, "\\\\fB\$1\\\\fP"],               87     [$type_func, "\\\\fB\$1\\\\fP"],
 88     [$type_enum, "\\\\fI\$1\\\\fP"],               88     [$type_enum, "\\\\fI\$1\\\\fP"],
 89     [$type_struct, "\\\\fI\$1\\\\fP"],             89     [$type_struct, "\\\\fI\$1\\\\fP"],
 90     [$type_typedef, "\\\\fI\$1\\\\fP"],            90     [$type_typedef, "\\\\fI\$1\\\\fP"],
 91     [$type_union, "\\\\fI\$1\\\\fP"],              91     [$type_union, "\\\\fI\$1\\\\fP"],
 92     [$type_param, "\\\\fI\$1\\\\fP"],              92     [$type_param, "\\\\fI\$1\\\\fP"],
 93     [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],       93     [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
 94     [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],       94     [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 95     [$type_fallback, "\\\\fI\$1\\\\fP"]            95     [$type_fallback, "\\\\fI\$1\\\\fP"]
 96   );                                               96   );
 97 my $blankline_man = "";                            97 my $blankline_man = "";
 98                                                    98 
 99 # rst-mode                                         99 # rst-mode
100 my @highlights_rst = (                            100 my @highlights_rst = (
101     [$type_constant, "``\$1``"],                  101     [$type_constant, "``\$1``"],
102     [$type_constant2, "``\$1``"],                 102     [$type_constant2, "``\$1``"],
103                                                   103 
104     # Note: need to escape () to avoid func ma    104     # Note: need to escape () to avoid func matching later
105     [$type_member_func, "\\:c\\:type\\:`\$1\$2    105     [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
106     [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <    106     [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
107     [$type_fp_param, "**\$1\\\\(\\\\)**"],        107     [$type_fp_param, "**\$1\\\\(\\\\)**"],
108     [$type_fp_param2, "**\$1\\\\(\\\\)**"],       108     [$type_fp_param2, "**\$1\\\\(\\\\)**"],
109     [$type_func, "\$1()"],                        109     [$type_func, "\$1()"],
110     [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],    110     [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
111     [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"    111     [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
112     [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`    112     [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
113     [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"]    113     [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
114                                                   114 
115     # in rst this can refer to any type           115     # in rst this can refer to any type
116     [$type_fallback, "\\:c\\:type\\:`\$1`"],      116     [$type_fallback, "\\:c\\:type\\:`\$1`"],
117     [$type_param_ref, "**\$1\$2**"]               117     [$type_param_ref, "**\$1\$2**"]
118   );                                              118   );
119 my $blankline_rst = "\n";                         119 my $blankline_rst = "\n";
120                                                   120 
121 # read arguments                                  121 # read arguments
122 if ($#ARGV == -1) {                               122 if ($#ARGV == -1) {
123     pod2usage(                                    123     pod2usage(
124         -message => "No arguments!\n",            124         -message => "No arguments!\n",
125         -exitval => 1,                            125         -exitval => 1,
126         -verbose => 99,                           126         -verbose => 99,
127         -sections => 'SYNOPSIS',                  127         -sections => 'SYNOPSIS',
128         -output => \*STDERR,                      128         -output => \*STDERR,
129       );                                          129       );
130 }                                                 130 }
131                                                   131 
132 my $kernelversion;                                132 my $kernelversion;
133 my ($sphinx_major, $sphinx_minor, $sphinx_patc    133 my ($sphinx_major, $sphinx_minor, $sphinx_patch);
134                                                   134 
135 my $dohighlight = "";                             135 my $dohighlight = "";
136                                                   136 
137 my $verbose = 0;                                  137 my $verbose = 0;
138 my $Werror = 0;                                   138 my $Werror = 0;
139 my $Wreturn = 0;                                  139 my $Wreturn = 0;
140 my $Wshort_desc = 0;                              140 my $Wshort_desc = 0;
141 my $Wcontents_before_sections = 0;                141 my $Wcontents_before_sections = 0;
142 my $output_mode = "rst";                          142 my $output_mode = "rst";
143 my $output_preformatted = 0;                      143 my $output_preformatted = 0;
144 my $no_doc_sections = 0;                          144 my $no_doc_sections = 0;
145 my $enable_lineno = 0;                            145 my $enable_lineno = 0;
146 my @highlights = @highlights_rst;                 146 my @highlights = @highlights_rst;
147 my $blankline = $blankline_rst;                   147 my $blankline = $blankline_rst;
148 my $modulename = "Kernel API";                    148 my $modulename = "Kernel API";
149                                                   149 
150 use constant {                                    150 use constant {
151     OUTPUT_ALL          => 0, # output all sym    151     OUTPUT_ALL          => 0, # output all symbols and doc sections
152     OUTPUT_INCLUDE      => 1, # output only sp    152     OUTPUT_INCLUDE      => 1, # output only specified symbols
153     OUTPUT_EXPORTED     => 2, # output exporte    153     OUTPUT_EXPORTED     => 2, # output exported symbols
154     OUTPUT_INTERNAL     => 3, # output non-exp    154     OUTPUT_INTERNAL     => 3, # output non-exported symbols
155 };                                                155 };
156 my $output_selection = OUTPUT_ALL;                156 my $output_selection = OUTPUT_ALL;
157 my $show_not_found = 0; # No longer used          157 my $show_not_found = 0; # No longer used
158                                                   158 
159 my @export_file_list;                             159 my @export_file_list;
160                                                   160 
161 my @build_time;                                   161 my @build_time;
162 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&    162 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
163     (my $seconds = `date -d"${ENV{'KBUILD_BUIL    163     (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
164     @build_time = gmtime($seconds);               164     @build_time = gmtime($seconds);
165 } else {                                          165 } else {
166     @build_time = localtime;                      166     @build_time = localtime;
167 }                                                 167 }
168                                                   168 
169 my $man_date = ('January', 'February', 'March'    169 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
170                 'July', 'August', 'September',    170                 'July', 'August', 'September', 'October',
171                 'November', 'December')[$build    171                 'November', 'December')[$build_time[4]] .
172     " " . ($build_time[5]+1900);                  172     " " . ($build_time[5]+1900);
173                                                   173 
174 # Essentially these are globals.                  174 # Essentially these are globals.
175 # They probably want to be tidied up, made mor    175 # They probably want to be tidied up, made more localised or something.
176 # CAVEAT EMPTOR!  Some of the others I localis    176 # CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
177 # could cause "use of undefined value" or othe    177 # could cause "use of undefined value" or other bugs.
178 my ($function, %function_table, %parametertype    178 my ($function, %function_table, %parametertypes, $declaration_purpose);
179 my %nosymbol_table = ();                          179 my %nosymbol_table = ();
180 my $declaration_start_line;                       180 my $declaration_start_line;
181 my ($type, $declaration_name, $return_type);      181 my ($type, $declaration_name, $return_type);
182 my ($newsection, $newcontents, $prototype, $br    182 my ($newsection, $newcontents, $prototype, $brcount, %source_map);
183                                                   183 
184 if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'K    184 if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') {
185     $verbose = 1;                                 185     $verbose = 1;
186 }                                                 186 }
187                                                   187 
188 if (defined($ENV{'KCFLAGS'})) {                   188 if (defined($ENV{'KCFLAGS'})) {
189     my $kcflags = "$ENV{'KCFLAGS'}";              189     my $kcflags = "$ENV{'KCFLAGS'}";
190                                                   190 
191     if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {      191     if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
192         $Werror = 1;                              192         $Werror = 1;
193     }                                             193     }
194 }                                                 194 }
195                                                   195 
196 # reading this variable is for backwards compa    196 # reading this variable is for backwards compat just in case
197 # someone was calling it with the variable fro    197 # someone was calling it with the variable from outside the
198 # kernel's build system                           198 # kernel's build system
199 if (defined($ENV{'KDOC_WERROR'})) {               199 if (defined($ENV{'KDOC_WERROR'})) {
200     $Werror = "$ENV{'KDOC_WERROR'}";              200     $Werror = "$ENV{'KDOC_WERROR'}";
201 }                                                 201 }
202 # other environment variables are converted to    202 # other environment variables are converted to command-line
203 # arguments in cmd_checkdoc in the build syste    203 # arguments in cmd_checkdoc in the build system
204                                                   204 
205 # Generated docbook code is inserted in a temp    205 # Generated docbook code is inserted in a template at a point where
206 # docbook v3.1 requires a non-zero sequence of    206 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
207 # https://www.oasis-open.org/docbook/documenta    207 # https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
208 # We keep track of number of generated entries    208 # We keep track of number of generated entries and generate a dummy
209 # if needs be to ensure the expanded template     209 # if needs be to ensure the expanded template can be postprocessed
210 # into html.                                      210 # into html.
211 my $section_counter = 0;                          211 my $section_counter = 0;
212                                                   212 
213 my $lineprefix="";                                213 my $lineprefix="";
214                                                   214 
215 # Parser states                                   215 # Parser states
216 use constant {                                    216 use constant {
217     STATE_NORMAL        => 0,        # normal     217     STATE_NORMAL        => 0,        # normal code
218     STATE_NAME          => 1,        # looking    218     STATE_NAME          => 1,        # looking for function name
219     STATE_BODY_MAYBE    => 2,        # body -     219     STATE_BODY_MAYBE    => 2,        # body - or maybe more description
220     STATE_BODY          => 3,        # the bod    220     STATE_BODY          => 3,        # the body of the comment
221     STATE_BODY_WITH_BLANK_LINE => 4, # the bod    221     STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line
222     STATE_PROTO         => 5,        # scannin    222     STATE_PROTO         => 5,        # scanning prototype
223     STATE_DOCBLOCK      => 6,        # documen    223     STATE_DOCBLOCK      => 6,        # documentation block
224     STATE_INLINE        => 7,        # gatheri    224     STATE_INLINE        => 7,        # gathering doc outside main block
225 };                                                225 };
226 my $state;                                        226 my $state;
227 my $in_doc_sect;                                  227 my $in_doc_sect;
228 my $leading_space;                                228 my $leading_space;
229                                                   229 
230 # Inline documentation state                      230 # Inline documentation state
231 use constant {                                    231 use constant {
232     STATE_INLINE_NA     => 0, # not applicable    232     STATE_INLINE_NA     => 0, # not applicable ($state != STATE_INLINE)
233     STATE_INLINE_NAME   => 1, # looking for me    233     STATE_INLINE_NAME   => 1, # looking for member name (@foo:)
234     STATE_INLINE_TEXT   => 2, # looking for me    234     STATE_INLINE_TEXT   => 2, # looking for member documentation
235     STATE_INLINE_END    => 3, # done              235     STATE_INLINE_END    => 3, # done
236     STATE_INLINE_ERROR  => 4, # error - Commen    236     STATE_INLINE_ERROR  => 4, # error - Comment without header was found.
237                               # Spit a warning    237                               # Spit a warning as it's not
238                               # proper kernel-    238                               # proper kernel-doc and ignore the rest.
239 };                                                239 };
240 my $inline_doc_state;                             240 my $inline_doc_state;
241                                                   241 
242 #declaration types: can be                        242 #declaration types: can be
243 # 'function', 'struct', 'union', 'enum', 'type    243 # 'function', 'struct', 'union', 'enum', 'typedef'
244 my $decl_type;                                    244 my $decl_type;
245                                                   245 
246 # Name of the kernel-doc identifier for non-DO    246 # Name of the kernel-doc identifier for non-DOC markups
247 my $identifier;                                   247 my $identifier;
248                                                   248 
249 my $doc_start = '^/\*\*\s*$'; # Allow whitespa    249 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
250 my $doc_end = '\*/';                              250 my $doc_end = '\*/';
251 my $doc_com = '\s*\*\s*';                         251 my $doc_com = '\s*\*\s*';
252 my $doc_com_body = '\s*\* ?';                     252 my $doc_com_body = '\s*\* ?';
253 my $doc_decl = $doc_com . '(\w+)';                253 my $doc_decl = $doc_com . '(\w+)';
254 # @params and a strictly limited set of suppor    254 # @params and a strictly limited set of supported section names
255 # Specifically:                                   255 # Specifically:
256 #   Match @word:                                  256 #   Match @word:
257 #         @...:                                   257 #         @...:
258 #         @{section-name}:                        258 #         @{section-name}:
259 # while trying to not match literal block star    259 # while trying to not match literal block starts like "example::"
260 #                                                 260 #
261 my $doc_sect = $doc_com .                         261 my $doc_sect = $doc_com .
262     '\s*(\@[.\w]+|\@\.\.\.|description|context    262     '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$';
263 my $doc_content = $doc_com_body . '(.*)';         263 my $doc_content = $doc_com_body . '(.*)';
264 my $doc_block = $doc_com . 'DOC:\s*(.*)?';        264 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
265 my $doc_inline_start = '^\s*/\*\*\s*$';           265 my $doc_inline_start = '^\s*/\*\*\s*$';
266 my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]    266 my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
267 my $doc_inline_end = '^\s*\*/\s*$';               267 my $doc_inline_end = '^\s*\*/\s*$';
268 my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]    268 my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
269 my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\    269 my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
270 my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_    270 my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*\w+\)\s*;';
271 my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*    271 my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)};
272 my $attribute = qr{__attribute__\s*\(\([a-z0-9    272 my $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i;
273                                                   273 
274 my %parameterdescs;                               274 my %parameterdescs;
275 my %parameterdesc_start_lines;                    275 my %parameterdesc_start_lines;
276 my @parameterlist;                                276 my @parameterlist;
277 my %sections;                                     277 my %sections;
278 my @sectionlist;                                  278 my @sectionlist;
279 my %section_start_lines;                          279 my %section_start_lines;
280 my $sectcheck;                                    280 my $sectcheck;
281 my $struct_actual;                                281 my $struct_actual;
282                                                   282 
283 my $contents = "";                                283 my $contents = "";
284 my $new_start_line = 0;                           284 my $new_start_line = 0;
285                                                   285 
286 # the canonical section names. see also $doc_s    286 # the canonical section names. see also $doc_sect above.
287 my $section_default = "Description";    # defa    287 my $section_default = "Description";    # default section
288 my $section_intro = "Introduction";               288 my $section_intro = "Introduction";
289 my $section = $section_default;                   289 my $section = $section_default;
290 my $section_context = "Context";                  290 my $section_context = "Context";
291 my $section_return = "Return";                    291 my $section_return = "Return";
292                                                   292 
293 my $undescribed = "-- undescribed --";            293 my $undescribed = "-- undescribed --";
294                                                   294 
295 reset_state();                                    295 reset_state();
296                                                   296 
297 while ($ARGV[0] =~ m/^--?(.*)/) {                 297 while ($ARGV[0] =~ m/^--?(.*)/) {
298     my $cmd = $1;                                 298     my $cmd = $1;
299     shift @ARGV;                                  299     shift @ARGV;
300     if ($cmd eq "man") {                          300     if ($cmd eq "man") {
301         $output_mode = "man";                     301         $output_mode = "man";
302         @highlights = @highlights_man;            302         @highlights = @highlights_man;
303         $blankline = $blankline_man;              303         $blankline = $blankline_man;
304     } elsif ($cmd eq "rst") {                     304     } elsif ($cmd eq "rst") {
305         $output_mode = "rst";                     305         $output_mode = "rst";
306         @highlights = @highlights_rst;            306         @highlights = @highlights_rst;
307         $blankline = $blankline_rst;              307         $blankline = $blankline_rst;
308     } elsif ($cmd eq "none") {                    308     } elsif ($cmd eq "none") {
309         $output_mode = "none";                    309         $output_mode = "none";
310     } elsif ($cmd eq "module") { # not needed     310     } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
311         $modulename = shift @ARGV;                311         $modulename = shift @ARGV;
312     } elsif ($cmd eq "function") { # to only o    312     } elsif ($cmd eq "function") { # to only output specific functions
313         $output_selection = OUTPUT_INCLUDE;       313         $output_selection = OUTPUT_INCLUDE;
314         $function = shift @ARGV;                  314         $function = shift @ARGV;
315         $function_table{$function} = 1;           315         $function_table{$function} = 1;
316     } elsif ($cmd eq "nosymbol") { # Exclude s    316     } elsif ($cmd eq "nosymbol") { # Exclude specific symbols
317         my $symbol = shift @ARGV;                 317         my $symbol = shift @ARGV;
318         $nosymbol_table{$symbol} = 1;             318         $nosymbol_table{$symbol} = 1;
319     } elsif ($cmd eq "export") { # only export    319     } elsif ($cmd eq "export") { # only exported symbols
320         $output_selection = OUTPUT_EXPORTED;      320         $output_selection = OUTPUT_EXPORTED;
321         %function_table = ();                     321         %function_table = ();
322     } elsif ($cmd eq "internal") { # only non-    322     } elsif ($cmd eq "internal") { # only non-exported symbols
323         $output_selection = OUTPUT_INTERNAL;      323         $output_selection = OUTPUT_INTERNAL;
324         %function_table = ();                     324         %function_table = ();
325     } elsif ($cmd eq "export-file") {             325     } elsif ($cmd eq "export-file") {
326         my $file = shift @ARGV;                   326         my $file = shift @ARGV;
327         push(@export_file_list, $file);           327         push(@export_file_list, $file);
328     } elsif ($cmd eq "v") {                       328     } elsif ($cmd eq "v") {
329         $verbose = 1;                             329         $verbose = 1;
330     } elsif ($cmd eq "Werror") {                  330     } elsif ($cmd eq "Werror") {
331         $Werror = 1;                              331         $Werror = 1;
332     } elsif ($cmd eq "Wreturn") {                 332     } elsif ($cmd eq "Wreturn") {
333         $Wreturn = 1;                             333         $Wreturn = 1;
334     } elsif ($cmd eq "Wshort-desc" or $cmd eq     334     } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") {
335         $Wshort_desc = 1;                         335         $Wshort_desc = 1;
336     } elsif ($cmd eq "Wcontents-before-section    336     } elsif ($cmd eq "Wcontents-before-sections") {
337         $Wcontents_before_sections = 1;           337         $Wcontents_before_sections = 1;
338     } elsif ($cmd eq "Wall") {                    338     } elsif ($cmd eq "Wall") {
339         $Wreturn = 1;                             339         $Wreturn = 1;
340         $Wshort_desc = 1;                         340         $Wshort_desc = 1;
341         $Wcontents_before_sections = 1;           341         $Wcontents_before_sections = 1;
342     } elsif (($cmd eq "h") || ($cmd eq "help")    342     } elsif (($cmd eq "h") || ($cmd eq "help")) {
343         pod2usage(-exitval => 0, -verbose => 2    343         pod2usage(-exitval => 0, -verbose => 2);
344     } elsif ($cmd eq 'no-doc-sections') {         344     } elsif ($cmd eq 'no-doc-sections') {
345         $no_doc_sections = 1;                     345         $no_doc_sections = 1;
346     } elsif ($cmd eq 'enable-lineno') {           346     } elsif ($cmd eq 'enable-lineno') {
347         $enable_lineno = 1;                       347         $enable_lineno = 1;
348     } elsif ($cmd eq 'show-not-found') {          348     } elsif ($cmd eq 'show-not-found') {
349         $show_not_found = 1;  # A no-op but do    349         $show_not_found = 1;  # A no-op but don't fail
350     } elsif ($cmd eq "sphinx-version") {          350     } elsif ($cmd eq "sphinx-version") {
351         my $ver_string = shift @ARGV;             351         my $ver_string = shift @ARGV;
352         if ($ver_string =~ m/^(\d+)(\.\d+)?(\.    352         if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
353             $sphinx_major = $1;                   353             $sphinx_major = $1;
354             if (defined($2)) {                    354             if (defined($2)) {
355                 $sphinx_minor = substr($2,1);     355                 $sphinx_minor = substr($2,1);
356             } else {                              356             } else {
357                 $sphinx_minor = 0;                357                 $sphinx_minor = 0;
358             }                                     358             }
359             if (defined($3)) {                    359             if (defined($3)) {
360                 $sphinx_patch = substr($3,1)      360                 $sphinx_patch = substr($3,1)
361             } else {                              361             } else {
362                 $sphinx_patch = 0;                362                 $sphinx_patch = 0;
363             }                                     363             }
364         } else {                                  364         } else {
365             die "Sphinx version should either     365             die "Sphinx version should either major.minor or major.minor.patch format\n";
366         }                                         366         }
367     } else {                                      367     } else {
368         # Unknown argument                        368         # Unknown argument
369         pod2usage(                                369         pod2usage(
370             -message => "Argument unknown!\n",    370             -message => "Argument unknown!\n",
371             -exitval => 1,                        371             -exitval => 1,
372             -verbose => 99,                       372             -verbose => 99,
373             -sections => 'SYNOPSIS',              373             -sections => 'SYNOPSIS',
374             -output => \*STDERR,                  374             -output => \*STDERR,
375             );                                    375             );
376     }                                             376     }
377     if ($#ARGV < 0){                              377     if ($#ARGV < 0){
378         pod2usage(                                378         pod2usage(
379             -message => "FILE argument missing    379             -message => "FILE argument missing\n",
380             -exitval => 1,                        380             -exitval => 1,
381             -verbose => 99,                       381             -verbose => 99,
382             -sections => 'SYNOPSIS',              382             -sections => 'SYNOPSIS',
383             -output => \*STDERR,                  383             -output => \*STDERR,
384             );                                    384             );
385     }                                             385     }
386 }                                                 386 }
387                                                   387 
388 # continue execution near EOF;                    388 # continue execution near EOF;
389                                                   389 
390 # The C domain dialect changed on Sphinx 3. So    390 # The C domain dialect changed on Sphinx 3. So, we need to check the
391 # version in order to produce the right tags.     391 # version in order to produce the right tags.
392 sub findprog($)                                   392 sub findprog($)
393 {                                                 393 {
394     foreach(split(/:/, $ENV{PATH})) {             394     foreach(split(/:/, $ENV{PATH})) {
395         return "$_/$_[0]" if(-x "$_/$_[0]");      395         return "$_/$_[0]" if(-x "$_/$_[0]");
396     }                                             396     }
397 }                                                 397 }
398                                                   398 
399 sub get_sphinx_version()                          399 sub get_sphinx_version()
400 {                                                 400 {
401     my $ver;                                      401     my $ver;
402                                                   402 
403     my $cmd = "sphinx-build";                     403     my $cmd = "sphinx-build";
404     if (!findprog($cmd)) {                        404     if (!findprog($cmd)) {
405         my $cmd = "sphinx-build3";                405         my $cmd = "sphinx-build3";
406         if (!findprog($cmd)) {                    406         if (!findprog($cmd)) {
407             $sphinx_major = 1;                    407             $sphinx_major = 1;
408             $sphinx_minor = 2;                    408             $sphinx_minor = 2;
409             $sphinx_patch = 0;                    409             $sphinx_patch = 0;
410             printf STDERR "Warning: Sphinx ver    410             printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n",
411                    $sphinx_major, $sphinx_mino    411                    $sphinx_major, $sphinx_minor, $sphinx_patch;
412             return;                               412             return;
413         }                                         413         }
414     }                                             414     }
415                                                   415 
416     open IN, "$cmd --version 2>&1 |";             416     open IN, "$cmd --version 2>&1 |";
417     while (<IN>) {                                417     while (<IN>) {
418         if (m/^\s*sphinx-build\s+([\d]+)\.([\d    418         if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
419             $sphinx_major = $1;                   419             $sphinx_major = $1;
420             $sphinx_minor = $2;                   420             $sphinx_minor = $2;
421             $sphinx_patch = $3;                   421             $sphinx_patch = $3;
422             last;                                 422             last;
423         }                                         423         }
424         # Sphinx 1.2.x uses a different format    424         # Sphinx 1.2.x uses a different format
425         if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+    425         if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
426             $sphinx_major = $1;                   426             $sphinx_major = $1;
427             $sphinx_minor = $2;                   427             $sphinx_minor = $2;
428             $sphinx_patch = $3;                   428             $sphinx_patch = $3;
429             last;                                 429             last;
430         }                                         430         }
431     }                                             431     }
432     close IN;                                     432     close IN;
433 }                                                 433 }
434                                                   434 
435 # get kernel version from env                     435 # get kernel version from env
436 sub get_kernel_version() {                        436 sub get_kernel_version() {
437     my $version = 'unknown kernel version';       437     my $version = 'unknown kernel version';
438                                                   438 
439     if (defined($ENV{'KERNELVERSION'})) {         439     if (defined($ENV{'KERNELVERSION'})) {
440         $version = $ENV{'KERNELVERSION'};         440         $version = $ENV{'KERNELVERSION'};
441     }                                             441     }
442     return $version;                              442     return $version;
443 }                                                 443 }
444                                                   444 
445 #                                                 445 #
446 sub print_lineno {                                446 sub print_lineno {
447     my $lineno = shift;                           447     my $lineno = shift;
448     if ($enable_lineno && defined($lineno)) {     448     if ($enable_lineno && defined($lineno)) {
449         print ".. LINENO " . $lineno . "\n";      449         print ".. LINENO " . $lineno . "\n";
450     }                                             450     }
451 }                                                 451 }
452                                                   452 
453 sub emit_warning {                                453 sub emit_warning {
454     my $location = shift;                         454     my $location = shift;
455     my $msg = shift;                              455     my $msg = shift;
456     print STDERR "$location: warning: $msg";      456     print STDERR "$location: warning: $msg";
457     ++$warnings;                                  457     ++$warnings;
458 }                                                 458 }
459 ##                                                459 ##
460 # dumps section contents to arrays/hashes inte    460 # dumps section contents to arrays/hashes intended for that purpose.
461 #                                                 461 #
462 sub dump_section {                                462 sub dump_section {
463     my $file = shift;                             463     my $file = shift;
464     my $name = shift;                             464     my $name = shift;
465     my $contents = join "\n", @_;                 465     my $contents = join "\n", @_;
466                                                   466 
467     if ($name =~ m/$type_param/) {                467     if ($name =~ m/$type_param/) {
468         $name = $1;                               468         $name = $1;
469         $parameterdescs{$name} = $contents;       469         $parameterdescs{$name} = $contents;
470         $sectcheck = $sectcheck . $name . " ";    470         $sectcheck = $sectcheck . $name . " ";
471         $parameterdesc_start_lines{$name} = $n    471         $parameterdesc_start_lines{$name} = $new_start_line;
472         $new_start_line = 0;                      472         $new_start_line = 0;
473     } elsif ($name eq "@\.\.\.") {                473     } elsif ($name eq "@\.\.\.") {
474         $name = "...";                            474         $name = "...";
475         $parameterdescs{$name} = $contents;       475         $parameterdescs{$name} = $contents;
476         $sectcheck = $sectcheck . $name . " ";    476         $sectcheck = $sectcheck . $name . " ";
477         $parameterdesc_start_lines{$name} = $n    477         $parameterdesc_start_lines{$name} = $new_start_line;
478         $new_start_line = 0;                      478         $new_start_line = 0;
479     } else {                                      479     } else {
480         if (defined($sections{$name}) && ($sec    480         if (defined($sections{$name}) && ($sections{$name} ne "")) {
481             # Only warn on user specified dupl    481             # Only warn on user specified duplicate section names.
482             if ($name ne $section_default) {      482             if ($name ne $section_default) {
483                 emit_warning("${file}:$.", "du    483                 emit_warning("${file}:$.", "duplicate section name '$name'\n");
484             }                                     484             }
485             $sections{$name} .= $contents;        485             $sections{$name} .= $contents;
486         } else {                                  486         } else {
487             $sections{$name} = $contents;         487             $sections{$name} = $contents;
488             push @sectionlist, $name;             488             push @sectionlist, $name;
489             $section_start_lines{$name} = $new    489             $section_start_lines{$name} = $new_start_line;
490             $new_start_line = 0;                  490             $new_start_line = 0;
491         }                                         491         }
492     }                                             492     }
493 }                                                 493 }
494                                                   494 
495 ##                                                495 ##
496 # dump DOC: section after checking that it sho    496 # dump DOC: section after checking that it should go out
497 #                                                 497 #
498 sub dump_doc_section {                            498 sub dump_doc_section {
499     my $file = shift;                             499     my $file = shift;
500     my $name = shift;                             500     my $name = shift;
501     my $contents = join "\n", @_;                 501     my $contents = join "\n", @_;
502                                                   502 
503     if ($no_doc_sections) {                       503     if ($no_doc_sections) {
504         return;                                   504         return;
505     }                                             505     }
506                                                   506 
507     return if (defined($nosymbol_table{$name})    507     return if (defined($nosymbol_table{$name}));
508                                                   508 
509     if (($output_selection == OUTPUT_ALL) ||      509     if (($output_selection == OUTPUT_ALL) ||
510         (($output_selection == OUTPUT_INCLUDE)    510         (($output_selection == OUTPUT_INCLUDE) &&
511          defined($function_table{$name})))        511          defined($function_table{$name})))
512     {                                             512     {
513         dump_section($file, $name, $contents);    513         dump_section($file, $name, $contents);
514         output_blockhead({'sectionlist' => \@s    514         output_blockhead({'sectionlist' => \@sectionlist,
515                           'sections' => \%sect    515                           'sections' => \%sections,
516                           'module' => $modulen    516                           'module' => $modulename,
517                           'content-only' => ($    517                           'content-only' => ($output_selection != OUTPUT_ALL), });
518     }                                             518     }
519 }                                                 519 }
520                                                   520 
521 ##                                                521 ##
522 # output function                                 522 # output function
523 #                                                 523 #
524 # parameterdescs, a hash.                         524 # parameterdescs, a hash.
525 #  function => "function name"                    525 #  function => "function name"
526 #  parameterlist => @list of parameters           526 #  parameterlist => @list of parameters
527 #  parameterdescs => %parameter descriptions      527 #  parameterdescs => %parameter descriptions
528 #  sectionlist => @list of sections               528 #  sectionlist => @list of sections
529 #  sections => %section descriptions              529 #  sections => %section descriptions
530 #                                                 530 #
531                                                   531 
532 sub output_highlight {                            532 sub output_highlight {
533     my $contents = join "\n",@_;                  533     my $contents = join "\n",@_;
534     my $line;                                     534     my $line;
535                                                   535 
536 #   DEBUG                                         536 #   DEBUG
537 #   if (!defined $contents) {                     537 #   if (!defined $contents) {
538 #       use Carp;                                 538 #       use Carp;
539 #       confess "output_highlight got called w    539 #       confess "output_highlight got called with no args?\n";
540 #   }                                             540 #   }
541                                                   541 
542 #   print STDERR "contents b4:$contents\n";       542 #   print STDERR "contents b4:$contents\n";
543     eval $dohighlight;                            543     eval $dohighlight;
544     die $@ if $@;                                 544     die $@ if $@;
545 #   print STDERR "contents af:$contents\n";       545 #   print STDERR "contents af:$contents\n";
546                                                   546 
547     foreach $line (split "\n", $contents) {       547     foreach $line (split "\n", $contents) {
548         if (! $output_preformatted) {             548         if (! $output_preformatted) {
549             $line =~ s/^\s*//;                    549             $line =~ s/^\s*//;
550         }                                         550         }
551         if ($line eq ""){                         551         if ($line eq ""){
552             if (! $output_preformatted) {         552             if (! $output_preformatted) {
553                 print $lineprefix, $blankline;    553                 print $lineprefix, $blankline;
554             }                                     554             }
555         } else {                                  555         } else {
556             if ($output_mode eq "man" && subst    556             if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
557                 print "\\&$line";                 557                 print "\\&$line";
558             } else {                              558             } else {
559                 print $lineprefix, $line;         559                 print $lineprefix, $line;
560             }                                     560             }
561         }                                         561         }
562         print "\n";                               562         print "\n";
563     }                                             563     }
564 }                                                 564 }
565                                                   565 
566 ##                                                566 ##
567 # output function in man                          567 # output function in man
568 sub output_function_man(%) {                      568 sub output_function_man(%) {
569     my %args = %{$_[0]};                          569     my %args = %{$_[0]};
570     my ($parameter, $section);                    570     my ($parameter, $section);
571     my $count;                                    571     my $count;
572                                                   572 
573     print ".TH \"$args{'function'}\" 9 \"$args    573     print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
574                                                   574 
575     print ".SH NAME\n";                           575     print ".SH NAME\n";
576     print $args{'function'} . " \\- " . $args{    576     print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
577                                                   577 
578     print ".SH SYNOPSIS\n";                       578     print ".SH SYNOPSIS\n";
579     if ($args{'functiontype'} ne "") {            579     if ($args{'functiontype'} ne "") {
580         print ".B \"" . $args{'functiontype'}     580         print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
581     } else {                                      581     } else {
582         print ".B \"" . $args{'function'} . "\    582         print ".B \"" . $args{'function'} . "\n";
583     }                                             583     }
584     $count = 0;                                   584     $count = 0;
585     my $parenth = "(";                            585     my $parenth = "(";
586     my $post = ",";                               586     my $post = ",";
587     foreach my $parameter (@{$args{'parameterl    587     foreach my $parameter (@{$args{'parameterlist'}}) {
588         if ($count == $#{$args{'parameterlist'    588         if ($count == $#{$args{'parameterlist'}}) {
589             $post = ");";                         589             $post = ");";
590         }                                         590         }
591         $type = $args{'parametertypes'}{$param    591         $type = $args{'parametertypes'}{$parameter};
592         if ($type =~ m/$function_pointer/) {      592         if ($type =~ m/$function_pointer/) {
593             # pointer-to-function                 593             # pointer-to-function
594             print ".BI \"" . $parenth . $1 . "    594             print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
595         } else {                                  595         } else {
596             $type =~ s/([^\*])$/$1 /;             596             $type =~ s/([^\*])$/$1 /;
597             print ".BI \"" . $parenth . $type     597             print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
598         }                                         598         }
599         $count++;                                 599         $count++;
600         $parenth = "";                            600         $parenth = "";
601     }                                             601     }
602                                                   602 
603     print ".SH ARGUMENTS\n";                      603     print ".SH ARGUMENTS\n";
604     foreach $parameter (@{$args{'parameterlist    604     foreach $parameter (@{$args{'parameterlist'}}) {
605         my $parameter_name = $parameter;          605         my $parameter_name = $parameter;
606         $parameter_name =~ s/\[.*//;              606         $parameter_name =~ s/\[.*//;
607                                                   607 
608         print ".IP \"" . $parameter . "\" 12\n    608         print ".IP \"" . $parameter . "\" 12\n";
609         output_highlight($args{'parameterdescs    609         output_highlight($args{'parameterdescs'}{$parameter_name});
610     }                                             610     }
611     foreach $section (@{$args{'sectionlist'}})    611     foreach $section (@{$args{'sectionlist'}}) {
612         print ".SH \"", uc $section, "\"\n";      612         print ".SH \"", uc $section, "\"\n";
613         output_highlight($args{'sections'}{$se    613         output_highlight($args{'sections'}{$section});
614     }                                             614     }
615 }                                                 615 }
616                                                   616 
617 ##                                                617 ##
618 # output enum in man                              618 # output enum in man
619 sub output_enum_man(%) {                          619 sub output_enum_man(%) {
620     my %args = %{$_[0]};                          620     my %args = %{$_[0]};
621     my ($parameter, $section);                    621     my ($parameter, $section);
622     my $count;                                    622     my $count;
623                                                   623 
624     print ".TH \"$args{'module'}\" 9 \"enum $a    624     print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
625                                                   625 
626     print ".SH NAME\n";                           626     print ".SH NAME\n";
627     print "enum " . $args{'enum'} . " \\- " .     627     print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
628                                                   628 
629     print ".SH SYNOPSIS\n";                       629     print ".SH SYNOPSIS\n";
630     print "enum " . $args{'enum'} . " {\n";       630     print "enum " . $args{'enum'} . " {\n";
631     $count = 0;                                   631     $count = 0;
632     foreach my $parameter (@{$args{'parameterl    632     foreach my $parameter (@{$args{'parameterlist'}}) {
633         print ".br\n.BI \"    $parameter\"\n";    633         print ".br\n.BI \"    $parameter\"\n";
634         if ($count == $#{$args{'parameterlist'    634         if ($count == $#{$args{'parameterlist'}}) {
635             print "\n};\n";                       635             print "\n};\n";
636             last;                                 636             last;
637         } else {                                  637         } else {
638             print ", \n.br\n";                    638             print ", \n.br\n";
639         }                                         639         }
640         $count++;                                 640         $count++;
641     }                                             641     }
642                                                   642 
643     print ".SH Constants\n";                      643     print ".SH Constants\n";
644     foreach $parameter (@{$args{'parameterlist    644     foreach $parameter (@{$args{'parameterlist'}}) {
645         my $parameter_name = $parameter;          645         my $parameter_name = $parameter;
646         $parameter_name =~ s/\[.*//;              646         $parameter_name =~ s/\[.*//;
647                                                   647 
648         print ".IP \"" . $parameter . "\" 12\n    648         print ".IP \"" . $parameter . "\" 12\n";
649         output_highlight($args{'parameterdescs    649         output_highlight($args{'parameterdescs'}{$parameter_name});
650     }                                             650     }
651     foreach $section (@{$args{'sectionlist'}})    651     foreach $section (@{$args{'sectionlist'}}) {
652         print ".SH \"$section\"\n";               652         print ".SH \"$section\"\n";
653         output_highlight($args{'sections'}{$se    653         output_highlight($args{'sections'}{$section});
654     }                                             654     }
655 }                                                 655 }
656                                                   656 
657 ##                                                657 ##
658 # output struct in man                            658 # output struct in man
659 sub output_struct_man(%) {                        659 sub output_struct_man(%) {
660     my %args = %{$_[0]};                          660     my %args = %{$_[0]};
661     my ($parameter, $section);                    661     my ($parameter, $section);
662                                                   662 
663     print ".TH \"$args{'module'}\" 9 \"" . $ar    663     print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
664                                                   664 
665     print ".SH NAME\n";                           665     print ".SH NAME\n";
666     print $args{'type'} . " " . $args{'struct'    666     print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
667                                                   667 
668     my $declaration = $args{'definition'};        668     my $declaration = $args{'definition'};
669     $declaration =~ s/\t/  /g;                    669     $declaration =~ s/\t/  /g;
670     $declaration =~ s/\n/"\n.br\n.BI \"/g;        670     $declaration =~ s/\n/"\n.br\n.BI \"/g;
671     print ".SH SYNOPSIS\n";                       671     print ".SH SYNOPSIS\n";
672     print $args{'type'} . " " . $args{'struct'    672     print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
673     print ".BI \"$declaration\n};\n.br\n\n";      673     print ".BI \"$declaration\n};\n.br\n\n";
674                                                   674 
675     print ".SH Members\n";                        675     print ".SH Members\n";
676     foreach $parameter (@{$args{'parameterlist    676     foreach $parameter (@{$args{'parameterlist'}}) {
677         ($parameter =~ /^#/) && next;             677         ($parameter =~ /^#/) && next;
678                                                   678 
679         my $parameter_name = $parameter;          679         my $parameter_name = $parameter;
680         $parameter_name =~ s/\[.*//;              680         $parameter_name =~ s/\[.*//;
681                                                   681 
682         ($args{'parameterdescs'}{$parameter_na    682         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
683         print ".IP \"" . $parameter . "\" 12\n    683         print ".IP \"" . $parameter . "\" 12\n";
684         output_highlight($args{'parameterdescs    684         output_highlight($args{'parameterdescs'}{$parameter_name});
685     }                                             685     }
686     foreach $section (@{$args{'sectionlist'}})    686     foreach $section (@{$args{'sectionlist'}}) {
687         print ".SH \"$section\"\n";               687         print ".SH \"$section\"\n";
688         output_highlight($args{'sections'}{$se    688         output_highlight($args{'sections'}{$section});
689     }                                             689     }
690 }                                                 690 }
691                                                   691 
692 ##                                                692 ##
693 # output typedef in man                           693 # output typedef in man
694 sub output_typedef_man(%) {                       694 sub output_typedef_man(%) {
695     my %args = %{$_[0]};                          695     my %args = %{$_[0]};
696     my ($parameter, $section);                    696     my ($parameter, $section);
697                                                   697 
698     print ".TH \"$args{'module'}\" 9 \"$args{'    698     print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
699                                                   699 
700     print ".SH NAME\n";                           700     print ".SH NAME\n";
701     print "typedef " . $args{'typedef'} . " \\    701     print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
702                                                   702 
703     foreach $section (@{$args{'sectionlist'}})    703     foreach $section (@{$args{'sectionlist'}}) {
704         print ".SH \"$section\"\n";               704         print ".SH \"$section\"\n";
705         output_highlight($args{'sections'}{$se    705         output_highlight($args{'sections'}{$section});
706     }                                             706     }
707 }                                                 707 }
708                                                   708 
709 sub output_blockhead_man(%) {                     709 sub output_blockhead_man(%) {
710     my %args = %{$_[0]};                          710     my %args = %{$_[0]};
711     my ($parameter, $section);                    711     my ($parameter, $section);
712     my $count;                                    712     my $count;
713                                                   713 
714     print ".TH \"$args{'module'}\" 9 \"$args{'    714     print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
715                                                   715 
716     foreach $section (@{$args{'sectionlist'}})    716     foreach $section (@{$args{'sectionlist'}}) {
717         print ".SH \"$section\"\n";               717         print ".SH \"$section\"\n";
718         output_highlight($args{'sections'}{$se    718         output_highlight($args{'sections'}{$section});
719     }                                             719     }
720 }                                                 720 }
721                                                   721 
722 ##                                                722 ##
723 # output in restructured text                     723 # output in restructured text
724 #                                                 724 #
725                                                   725 
726 #                                                 726 #
727 # This could use some work; it's used to outpu    727 # This could use some work; it's used to output the DOC: sections, and
728 # starts by putting out the name of the doc se    728 # starts by putting out the name of the doc section itself, but that tends
729 # to duplicate a header already in the templat    729 # to duplicate a header already in the template file.
730 #                                                 730 #
731 sub output_blockhead_rst(%) {                     731 sub output_blockhead_rst(%) {
732     my %args = %{$_[0]};                          732     my %args = %{$_[0]};
733     my ($parameter, $section);                    733     my ($parameter, $section);
734                                                   734 
735     foreach $section (@{$args{'sectionlist'}})    735     foreach $section (@{$args{'sectionlist'}}) {
736         next if (defined($nosymbol_table{$sect    736         next if (defined($nosymbol_table{$section}));
737                                                   737 
738         if ($output_selection != OUTPUT_INCLUD    738         if ($output_selection != OUTPUT_INCLUDE) {
739             print ".. _$section:\n\n";            739             print ".. _$section:\n\n";
740             print "**$section**\n\n";             740             print "**$section**\n\n";
741         }                                         741         }
742         print_lineno($section_start_lines{$sec    742         print_lineno($section_start_lines{$section});
743         output_highlight_rst($args{'sections'}    743         output_highlight_rst($args{'sections'}{$section});
744         print "\n";                               744         print "\n";
745     }                                             745     }
746 }                                                 746 }
747                                                   747 
748 #                                                 748 #
749 # Apply the RST highlights to a sub-block of t    749 # Apply the RST highlights to a sub-block of text.
750 #                                                 750 #
751 sub highlight_block($) {                          751 sub highlight_block($) {
752     # The dohighlight kludge requires the text    752     # The dohighlight kludge requires the text be called $contents
753     my $contents = shift;                         753     my $contents = shift;
754     eval $dohighlight;                            754     eval $dohighlight;
755     die $@ if $@;                                 755     die $@ if $@;
756     return $contents;                             756     return $contents;
757 }                                                 757 }
758                                                   758 
759 #                                                 759 #
760 # Regexes used only here.                         760 # Regexes used only here.
761 #                                                 761 #
762 my $sphinx_literal = '^[^.].*::$';                762 my $sphinx_literal = '^[^.].*::$';
763 my $sphinx_cblock = '^\.\.\ +code-block::';       763 my $sphinx_cblock = '^\.\.\ +code-block::';
764                                                   764 
765 sub output_highlight_rst {                        765 sub output_highlight_rst {
766     my $input = join "\n",@_;                     766     my $input = join "\n",@_;
767     my $output = "";                              767     my $output = "";
768     my $line;                                     768     my $line;
769     my $in_literal = 0;                           769     my $in_literal = 0;
770     my $litprefix;                                770     my $litprefix;
771     my $block = "";                               771     my $block = "";
772                                                   772 
773     foreach $line (split "\n",$input) {           773     foreach $line (split "\n",$input) {
774         #                                         774         #
775         # If we're in a literal block, see if     775         # If we're in a literal block, see if we should drop out
776         # of it.  Otherwise pass the line stra    776         # of it.  Otherwise pass the line straight through unmunged.
777         #                                         777         #
778         if ($in_literal) {                        778         if ($in_literal) {
779             if (! ($line =~ /^\s*$/)) {           779             if (! ($line =~ /^\s*$/)) {
780                 #                                 780                 #
781                 # If this is the first non-bla    781                 # If this is the first non-blank line in a literal
782                 # block we need to figure out     782                 # block we need to figure out what the proper indent is.
783                 #                                 783                 #
784                 if ($litprefix eq "") {           784                 if ($litprefix eq "") {
785                     $line =~ /^(\s*)/;            785                     $line =~ /^(\s*)/;
786                     $litprefix = '^' . $1;        786                     $litprefix = '^' . $1;
787                     $output .= $line . "\n";      787                     $output .= $line . "\n";
788                 } elsif (! ($line =~ /$litpref    788                 } elsif (! ($line =~ /$litprefix/)) {
789                     $in_literal = 0;              789                     $in_literal = 0;
790                 } else {                          790                 } else {
791                     $output .= $line . "\n";      791                     $output .= $line . "\n";
792                 }                                 792                 }
793             } else {                              793             } else {
794                 $output .= $line . "\n";          794                 $output .= $line . "\n";
795             }                                     795             }
796         }                                         796         }
797         #                                         797         #
798         # Not in a literal block (or just drop    798         # Not in a literal block (or just dropped out)
799         #                                         799         #
800         if (! $in_literal) {                      800         if (! $in_literal) {
801             $block .= $line . "\n";               801             $block .= $line . "\n";
802             if (($line =~ /$sphinx_literal/) |    802             if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
803                 $in_literal = 1;                  803                 $in_literal = 1;
804                 $litprefix = "";                  804                 $litprefix = "";
805                 $output .= highlight_block($bl    805                 $output .= highlight_block($block);
806                 $block = ""                       806                 $block = ""
807             }                                     807             }
808         }                                         808         }
809     }                                             809     }
810                                                   810 
811     if ($block) {                                 811     if ($block) {
812         $output .= highlight_block($block);       812         $output .= highlight_block($block);
813     }                                             813     }
814     foreach $line (split "\n", $output) {         814     foreach $line (split "\n", $output) {
815         print $lineprefix . $line . "\n";         815         print $lineprefix . $line . "\n";
816     }                                             816     }
817 }                                                 817 }
818                                                   818 
819 sub output_function_rst(%) {                      819 sub output_function_rst(%) {
820     my %args = %{$_[0]};                          820     my %args = %{$_[0]};
821     my ($parameter, $section);                    821     my ($parameter, $section);
822     my $oldprefix = $lineprefix;                  822     my $oldprefix = $lineprefix;
823                                                   823 
824     my $signature = "";                           824     my $signature = "";
825     if ($args{'functiontype'} ne "") {            825     if ($args{'functiontype'} ne "") {
826         $signature = $args{'functiontype'} . "    826         $signature = $args{'functiontype'} . " " . $args{'function'} . " (";
827     } else {                                      827     } else {
828         $signature = $args{'function'} . " (";    828         $signature = $args{'function'} . " (";
829     }                                             829     }
830                                                   830 
831     my $count = 0;                                831     my $count = 0;
832     foreach my $parameter (@{$args{'parameterl    832     foreach my $parameter (@{$args{'parameterlist'}}) {
833         if ($count ne 0) {                        833         if ($count ne 0) {
834             $signature .= ", ";                   834             $signature .= ", ";
835         }                                         835         }
836         $count++;                                 836         $count++;
837         $type = $args{'parametertypes'}{$param    837         $type = $args{'parametertypes'}{$parameter};
838                                                   838 
839         if ($type =~ m/$function_pointer/) {      839         if ($type =~ m/$function_pointer/) {
840             # pointer-to-function                 840             # pointer-to-function
841             $signature .= $1 . $parameter . ")    841             $signature .= $1 . $parameter . ") (" . $2 . ")";
842         } else {                                  842         } else {
843             $signature .= $type;                  843             $signature .= $type;
844         }                                         844         }
845     }                                             845     }
846                                                   846 
847     $signature .= ")";                            847     $signature .= ")";
848                                                   848 
849     if ($sphinx_major < 3) {                      849     if ($sphinx_major < 3) {
850         if ($args{'typedef'}) {                   850         if ($args{'typedef'}) {
851             print ".. c:type:: ". $args{'funct    851             print ".. c:type:: ". $args{'function'} . "\n\n";
852             print_lineno($declaration_start_li    852             print_lineno($declaration_start_line);
853             print "   **Typedef**: ";             853             print "   **Typedef**: ";
854             $lineprefix = "";                     854             $lineprefix = "";
855             output_highlight_rst($args{'purpos    855             output_highlight_rst($args{'purpose'});
856             print "\n\n**Syntax**\n\n";           856             print "\n\n**Syntax**\n\n";
857             print "  ``$signature``\n\n";         857             print "  ``$signature``\n\n";
858         } else {                                  858         } else {
859             print ".. c:function:: $signature\    859             print ".. c:function:: $signature\n\n";
860         }                                         860         }
861     } else {                                      861     } else {
862         if ($args{'typedef'} || $args{'functio    862         if ($args{'typedef'} || $args{'functiontype'} eq "") {
863             print ".. c:macro:: ". $args{'func    863             print ".. c:macro:: ". $args{'function'} . "\n\n";
864                                                   864 
865             if ($args{'typedef'}) {               865             if ($args{'typedef'}) {
866                 print_lineno($declaration_star    866                 print_lineno($declaration_start_line);
867                 print "   **Typedef**: ";         867                 print "   **Typedef**: ";
868                 $lineprefix = "";                 868                 $lineprefix = "";
869                 output_highlight_rst($args{'pu    869                 output_highlight_rst($args{'purpose'});
870                 print "\n\n**Syntax**\n\n";       870                 print "\n\n**Syntax**\n\n";
871                 print "  ``$signature``\n\n";     871                 print "  ``$signature``\n\n";
872             } else {                              872             } else {
873                 print "``$signature``\n\n";       873                 print "``$signature``\n\n";
874             }                                     874             }
875         } else {                                  875         } else {
876             print ".. c:function:: $signature\    876             print ".. c:function:: $signature\n\n";
877         }                                         877         }
878     }                                             878     }
879                                                   879 
880     if (!$args{'typedef'}) {                      880     if (!$args{'typedef'}) {
881         print_lineno($declaration_start_line);    881         print_lineno($declaration_start_line);
882         $lineprefix = "   ";                      882         $lineprefix = "   ";
883         output_highlight_rst($args{'purpose'})    883         output_highlight_rst($args{'purpose'});
884         print "\n";                               884         print "\n";
885     }                                             885     }
886                                                   886 
887     #                                             887     #
888     # Put our descriptive text into a containe    888     # Put our descriptive text into a container (thus an HTML <div>) to help
889     # set the function prototypes apart.          889     # set the function prototypes apart.
890     #                                             890     #
891     print ".. container:: kernelindent\n\n";      891     print ".. container:: kernelindent\n\n";
892     $lineprefix = "  ";                           892     $lineprefix = "  ";
893     print $lineprefix . "**Parameters**\n\n";     893     print $lineprefix . "**Parameters**\n\n";
894     foreach $parameter (@{$args{'parameterlist    894     foreach $parameter (@{$args{'parameterlist'}}) {
895         my $parameter_name = $parameter;          895         my $parameter_name = $parameter;
896         $parameter_name =~ s/\[.*//;              896         $parameter_name =~ s/\[.*//;
897         $type = $args{'parametertypes'}{$param    897         $type = $args{'parametertypes'}{$parameter};
898                                                   898 
899         if ($type ne "") {                        899         if ($type ne "") {
900             print $lineprefix . "``$type``\n";    900             print $lineprefix . "``$type``\n";
901         } else {                                  901         } else {
902             print $lineprefix . "``$parameter`    902             print $lineprefix . "``$parameter``\n";
903         }                                         903         }
904                                                   904 
905         print_lineno($parameterdesc_start_line    905         print_lineno($parameterdesc_start_lines{$parameter_name});
906                                                   906 
907         $lineprefix = "    ";                     907         $lineprefix = "    ";
908         if (defined($args{'parameterdescs'}{$p    908         if (defined($args{'parameterdescs'}{$parameter_name}) &&
909             $args{'parameterdescs'}{$parameter    909             $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
910             output_highlight_rst($args{'parame    910             output_highlight_rst($args{'parameterdescs'}{$parameter_name});
911         } else {                                  911         } else {
912             print $lineprefix . "*undescribed*    912             print $lineprefix . "*undescribed*\n";
913         }                                         913         }
914         $lineprefix = "  ";                       914         $lineprefix = "  ";
915         print "\n";                               915         print "\n";
916     }                                             916     }
917                                                   917 
918     output_section_rst(@_);                       918     output_section_rst(@_);
919     $lineprefix = $oldprefix;                     919     $lineprefix = $oldprefix;
920 }                                                 920 }
921                                                   921 
922 sub output_section_rst(%) {                       922 sub output_section_rst(%) {
923     my %args = %{$_[0]};                          923     my %args = %{$_[0]};
924     my $section;                                  924     my $section;
925     my $oldprefix = $lineprefix;                  925     my $oldprefix = $lineprefix;
926                                                   926 
927     foreach $section (@{$args{'sectionlist'}})    927     foreach $section (@{$args{'sectionlist'}}) {
928         print $lineprefix . "**$section**\n\n"    928         print $lineprefix . "**$section**\n\n";
929         print_lineno($section_start_lines{$sec    929         print_lineno($section_start_lines{$section});
930         output_highlight_rst($args{'sections'}    930         output_highlight_rst($args{'sections'}{$section});
931         print "\n";                               931         print "\n";
932     }                                             932     }
933     print "\n";                                   933     print "\n";
934 }                                                 934 }
935                                                   935 
936 sub output_enum_rst(%) {                          936 sub output_enum_rst(%) {
937     my %args = %{$_[0]};                          937     my %args = %{$_[0]};
938     my ($parameter);                              938     my ($parameter);
939     my $oldprefix = $lineprefix;                  939     my $oldprefix = $lineprefix;
940     my $count;                                    940     my $count;
941     my $outer;                                    941     my $outer;
942                                                   942 
943     if ($sphinx_major < 3) {                      943     if ($sphinx_major < 3) {
944         my $name = "enum " . $args{'enum'};       944         my $name = "enum " . $args{'enum'};
945         print "\n\n.. c:type:: " . $name . "\n    945         print "\n\n.. c:type:: " . $name . "\n\n";
946     } else {                                      946     } else {
947         my $name = $args{'enum'};                 947         my $name = $args{'enum'};
948         print "\n\n.. c:enum:: " . $name . "\n    948         print "\n\n.. c:enum:: " . $name . "\n\n";
949     }                                             949     }
950     print_lineno($declaration_start_line);        950     print_lineno($declaration_start_line);
951     $lineprefix = "  ";                           951     $lineprefix = "  ";
952     output_highlight_rst($args{'purpose'});       952     output_highlight_rst($args{'purpose'});
953     print "\n";                                   953     print "\n";
954                                                   954 
955     print ".. container:: kernelindent\n\n";      955     print ".. container:: kernelindent\n\n";
956     $outer = $lineprefix . "  ";                  956     $outer = $lineprefix . "  ";
957     $lineprefix = $outer . "  ";                  957     $lineprefix = $outer . "  ";
958     print $outer . "**Constants**\n\n";           958     print $outer . "**Constants**\n\n";
959     foreach $parameter (@{$args{'parameterlist    959     foreach $parameter (@{$args{'parameterlist'}}) {
960         print $outer . "``$parameter``\n";        960         print $outer . "``$parameter``\n";
961                                                   961 
962         if ($args{'parameterdescs'}{$parameter    962         if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
963             output_highlight_rst($args{'parame    963             output_highlight_rst($args{'parameterdescs'}{$parameter});
964         } else {                                  964         } else {
965             print $lineprefix . "*undescribed*    965             print $lineprefix . "*undescribed*\n";
966         }                                         966         }
967         print "\n";                               967         print "\n";
968     }                                             968     }
969     print "\n";                                   969     print "\n";
970     $lineprefix = $oldprefix;                     970     $lineprefix = $oldprefix;
971     output_section_rst(@_);                       971     output_section_rst(@_);
972 }                                                 972 }
973                                                   973 
974 sub output_typedef_rst(%) {                       974 sub output_typedef_rst(%) {
975     my %args = %{$_[0]};                          975     my %args = %{$_[0]};
976     my ($parameter);                              976     my ($parameter);
977     my $oldprefix = $lineprefix;                  977     my $oldprefix = $lineprefix;
978     my $name;                                     978     my $name;
979                                                   979 
980     if ($sphinx_major < 3) {                      980     if ($sphinx_major < 3) {
981         $name = "typedef " . $args{'typedef'};    981         $name = "typedef " . $args{'typedef'};
982     } else {                                      982     } else {
983         $name = $args{'typedef'};                 983         $name = $args{'typedef'};
984     }                                             984     }
985     print "\n\n.. c:type:: " . $name . "\n\n";    985     print "\n\n.. c:type:: " . $name . "\n\n";
986     print_lineno($declaration_start_line);        986     print_lineno($declaration_start_line);
987     $lineprefix = "   ";                          987     $lineprefix = "   ";
988     output_highlight_rst($args{'purpose'});       988     output_highlight_rst($args{'purpose'});
989     print "\n";                                   989     print "\n";
990                                                   990 
991     $lineprefix = $oldprefix;                     991     $lineprefix = $oldprefix;
992     output_section_rst(@_);                       992     output_section_rst(@_);
993 }                                                 993 }
994                                                   994 
995 sub output_struct_rst(%) {                        995 sub output_struct_rst(%) {
996     my %args = %{$_[0]};                          996     my %args = %{$_[0]};
997     my ($parameter);                              997     my ($parameter);
998     my $oldprefix = $lineprefix;                  998     my $oldprefix = $lineprefix;
999                                                   999 
1000     if ($sphinx_major < 3) {                     1000     if ($sphinx_major < 3) {
1001         my $name = $args{'type'} . " " . $arg    1001         my $name = $args{'type'} . " " . $args{'struct'};
1002         print "\n\n.. c:type:: " . $name . "\    1002         print "\n\n.. c:type:: " . $name . "\n\n";
1003     } else {                                     1003     } else {
1004         my $name = $args{'struct'};              1004         my $name = $args{'struct'};
1005         if ($args{'type'} eq 'union') {          1005         if ($args{'type'} eq 'union') {
1006             print "\n\n.. c:union:: " . $name    1006             print "\n\n.. c:union:: " . $name . "\n\n";
1007         } else {                                 1007         } else {
1008             print "\n\n.. c:struct:: " . $nam    1008             print "\n\n.. c:struct:: " . $name . "\n\n";
1009         }                                        1009         }
1010     }                                            1010     }
1011     print_lineno($declaration_start_line);       1011     print_lineno($declaration_start_line);
1012     $lineprefix = "  ";                          1012     $lineprefix = "  ";
1013     output_highlight_rst($args{'purpose'});      1013     output_highlight_rst($args{'purpose'});
1014     print "\n";                                  1014     print "\n";
1015                                                  1015 
1016     print ".. container:: kernelindent\n\n";     1016     print ".. container:: kernelindent\n\n";
1017     print $lineprefix . "**Definition**::\n\n    1017     print $lineprefix . "**Definition**::\n\n";
1018     my $declaration = $args{'definition'};       1018     my $declaration = $args{'definition'};
1019     $lineprefix = $lineprefix . "  ";            1019     $lineprefix = $lineprefix . "  ";
1020     $declaration =~ s/\t/$lineprefix/g;          1020     $declaration =~ s/\t/$lineprefix/g;
1021     print $lineprefix . $args{'type'} . " " .    1021     print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n";
1022                                                  1022 
1023     $lineprefix = "  ";                          1023     $lineprefix = "  ";
1024     print $lineprefix . "**Members**\n\n";       1024     print $lineprefix . "**Members**\n\n";
1025     foreach $parameter (@{$args{'parameterlis    1025     foreach $parameter (@{$args{'parameterlist'}}) {
1026         ($parameter =~ /^#/) && next;            1026         ($parameter =~ /^#/) && next;
1027                                                  1027 
1028         my $parameter_name = $parameter;         1028         my $parameter_name = $parameter;
1029         $parameter_name =~ s/\[.*//;             1029         $parameter_name =~ s/\[.*//;
1030                                                  1030 
1031         ($args{'parameterdescs'}{$parameter_n    1031         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1032         $type = $args{'parametertypes'}{$para    1032         $type = $args{'parametertypes'}{$parameter};
1033         print_lineno($parameterdesc_start_lin    1033         print_lineno($parameterdesc_start_lines{$parameter_name});
1034         print $lineprefix . "``" . $parameter    1034         print $lineprefix . "``" . $parameter . "``\n";
1035         $lineprefix = "    ";                    1035         $lineprefix = "    ";
1036         output_highlight_rst($args{'parameter    1036         output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1037         $lineprefix = "  ";                      1037         $lineprefix = "  ";
1038         print "\n";                              1038         print "\n";
1039     }                                            1039     }
1040     print "\n";                                  1040     print "\n";
1041                                                  1041 
1042     $lineprefix = $oldprefix;                    1042     $lineprefix = $oldprefix;
1043     output_section_rst(@_);                      1043     output_section_rst(@_);
1044 }                                                1044 }
1045                                                  1045 
1046 ## none mode output functions                    1046 ## none mode output functions
1047                                                  1047 
1048 sub output_function_none(%) {                    1048 sub output_function_none(%) {
1049 }                                                1049 }
1050                                                  1050 
1051 sub output_enum_none(%) {                        1051 sub output_enum_none(%) {
1052 }                                                1052 }
1053                                                  1053 
1054 sub output_typedef_none(%) {                     1054 sub output_typedef_none(%) {
1055 }                                                1055 }
1056                                                  1056 
1057 sub output_struct_none(%) {                      1057 sub output_struct_none(%) {
1058 }                                                1058 }
1059                                                  1059 
1060 sub output_blockhead_none(%) {                   1060 sub output_blockhead_none(%) {
1061 }                                                1061 }
1062                                                  1062 
1063 ##                                               1063 ##
1064 # generic output function for all types (func    1064 # generic output function for all types (function, struct/union, typedef, enum);
1065 # calls the generated, variable output_ funct    1065 # calls the generated, variable output_ function name based on
1066 # functype and output_mode                       1066 # functype and output_mode
1067 sub output_declaration {                         1067 sub output_declaration {
1068     no strict 'refs';                            1068     no strict 'refs';
1069     my $name = shift;                            1069     my $name = shift;
1070     my $functype = shift;                        1070     my $functype = shift;
1071     my $func = "output_${functype}_$output_mo    1071     my $func = "output_${functype}_$output_mode";
1072                                                  1072 
1073     return if (defined($nosymbol_table{$name}    1073     return if (defined($nosymbol_table{$name}));
1074                                                  1074 
1075     if (($output_selection == OUTPUT_ALL) ||     1075     if (($output_selection == OUTPUT_ALL) ||
1076         (($output_selection == OUTPUT_INCLUDE    1076         (($output_selection == OUTPUT_INCLUDE ||
1077           $output_selection == OUTPUT_EXPORTE    1077           $output_selection == OUTPUT_EXPORTED) &&
1078          defined($function_table{$name})) ||     1078          defined($function_table{$name})) ||
1079         ($output_selection == OUTPUT_INTERNAL    1079         ($output_selection == OUTPUT_INTERNAL &&
1080          !($functype eq "function" && defined    1080          !($functype eq "function" && defined($function_table{$name}))))
1081     {                                            1081     {
1082         &$func(@_);                              1082         &$func(@_);
1083         $section_counter++;                      1083         $section_counter++;
1084     }                                            1084     }
1085 }                                                1085 }
1086                                                  1086 
1087 ##                                               1087 ##
1088 # generic output function - calls the right o    1088 # generic output function - calls the right one based on current output mode.
1089 sub output_blockhead {                           1089 sub output_blockhead {
1090     no strict 'refs';                            1090     no strict 'refs';
1091     my $func = "output_blockhead_" . $output_    1091     my $func = "output_blockhead_" . $output_mode;
1092     &$func(@_);                                  1092     &$func(@_);
1093     $section_counter++;                          1093     $section_counter++;
1094 }                                                1094 }
1095                                                  1095 
1096 ##                                               1096 ##
1097 # takes a declaration (struct, union, enum, t    1097 # takes a declaration (struct, union, enum, typedef) and
1098 # invokes the right handler. NOT called for f    1098 # invokes the right handler. NOT called for functions.
1099 sub dump_declaration($$) {                       1099 sub dump_declaration($$) {
1100     no strict 'refs';                            1100     no strict 'refs';
1101     my ($prototype, $file) = @_;                 1101     my ($prototype, $file) = @_;
1102     my $func = "dump_" . $decl_type;             1102     my $func = "dump_" . $decl_type;
1103     &$func(@_);                                  1103     &$func(@_);
1104 }                                                1104 }
1105                                                  1105 
1106 sub dump_union($$) {                             1106 sub dump_union($$) {
1107     dump_struct(@_);                             1107     dump_struct(@_);
1108 }                                                1108 }
1109                                                  1109 
1110 sub dump_struct($$) {                            1110 sub dump_struct($$) {
1111     my $x = shift;                               1111     my $x = shift;
1112     my $file = shift;                            1112     my $file = shift;
1113     my $decl_type;                               1113     my $decl_type;
1114     my $members;                                 1114     my $members;
1115     my $type = qr{struct|union};                 1115     my $type = qr{struct|union};
1116     # For capturing struct/union definition b    1116     # For capturing struct/union definition body, i.e. "{members*}qualifiers*"
1117     my $qualifiers = qr{$attribute|__packed|_    1117     my $qualifiers = qr{$attribute|__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned};
1118     my $definition_body = qr{\{(.*)\}\s*$qual    1118     my $definition_body = qr{\{(.*)\}\s*$qualifiers*};
1119     my $struct_members = qr{($type)([^\{\};]+    1119     my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};
1120                                                  1120 
1121     if ($x =~ /($type)\s+(\w+)\s*$definition_    1121     if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {
1122         $decl_type = $1;                         1122         $decl_type = $1;
1123         $declaration_name = $2;                  1123         $declaration_name = $2;
1124         $members = $3;                           1124         $members = $3;
1125     } elsif ($x =~ /typedef\s+($type)\s*$defi    1125     } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {
1126         $decl_type = $1;                         1126         $decl_type = $1;
1127         $declaration_name = $3;                  1127         $declaration_name = $3;
1128         $members = $2;                           1128         $members = $2;
1129     }                                            1129     }
1130                                                  1130 
1131     if ($members) {                              1131     if ($members) {
1132         if ($identifier ne $declaration_name)    1132         if ($identifier ne $declaration_name) {
1133             emit_warning("${file}:$.", "expec    1133             emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
1134             return;                              1134             return;
1135         }                                        1135         }
1136                                                  1136 
1137         # ignore members marked private:         1137         # ignore members marked private:
1138         $members =~ s/\/\*\s*private:.*?\/\*\    1138         $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
1139         $members =~ s/\/\*\s*private:.*//gosi    1139         $members =~ s/\/\*\s*private:.*//gosi;
1140         # strip comments:                        1140         # strip comments:
1141         $members =~ s/\/\*.*?\*\///gos;          1141         $members =~ s/\/\*.*?\*\///gos;
1142         # strip attributes                       1142         # strip attributes
1143         $members =~ s/\s*$attribute/ /gi;        1143         $members =~ s/\s*$attribute/ /gi;
1144         $members =~ s/\s*__aligned\s*\([^;]*\    1144         $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
1145         $members =~ s/\s*__counted_by\s*\([^;    1145         $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
1146         $members =~ s/\s*__counted_by_(le|be)    1146         $members =~ s/\s*__counted_by_(le|be)\s*\([^;]*\)/ /gos;
1147         $members =~ s/\s*__packed\s*/ /gos;      1147         $members =~ s/\s*__packed\s*/ /gos;
1148         $members =~ s/\s*CRYPTO_MINALIGN_ATTR    1148         $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
1149         $members =~ s/\s*____cacheline_aligne    1149         $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
1150         $members =~ s/\s*____cacheline_aligne    1150         $members =~ s/\s*____cacheline_aligned/ /gos;
1151         # unwrap struct_group():                 1151         # unwrap struct_group():
1152         # - first eat non-declaration paramet    1152         # - first eat non-declaration parameters and rewrite for final match
1153         # - then remove macro, outer parens,     1153         # - then remove macro, outer parens, and trailing semicolon
1154         $members =~ s/\bstruct_group\s*\(([^,    1154         $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
1155         $members =~ s/\bstruct_group_attr\s*\    1155         $members =~ s/\bstruct_group_attr\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
1156         $members =~ s/\bstruct_group_tagged\s    1156         $members =~ s/\bstruct_group_tagged\s*\(([^,]*),([^,]*),/struct $1 $2; STRUCT_GROUP(/gos;
1157         $members =~ s/\b__struct_group\s*\(([    1157         $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
1158         $members =~ s/\bSTRUCT_GROUP(\(((?:(?    1158         $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
1159                                                  1159 
1160         my $args = qr{([^,)]+)};                 1160         my $args = qr{([^,)]+)};
1161         # replace DECLARE_BITMAP                 1161         # replace DECLARE_BITMAP
1162         $members =~ s/__ETHTOOL_DECLARE_LINK_    1162         $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
1163         $members =~ s/DECLARE_PHY_INTERFACE_M    1163         $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
1164         $members =~ s/DECLARE_BITMAP\s*\($arg    1164         $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
1165         # replace DECLARE_HASHTABLE              1165         # replace DECLARE_HASHTABLE
1166         $members =~ s/DECLARE_HASHTABLE\s*\($    1166         $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
1167         # replace DECLARE_KFIFO                  1167         # replace DECLARE_KFIFO
1168         $members =~ s/DECLARE_KFIFO\s*\($args    1168         $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
1169         # replace DECLARE_KFIFO_PTR              1169         # replace DECLARE_KFIFO_PTR
1170         $members =~ s/DECLARE_KFIFO_PTR\s*\($    1170         $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
1171         # replace DECLARE_FLEX_ARRAY             1171         # replace DECLARE_FLEX_ARRAY
1172         $members =~ s/(?:__)?DECLARE_FLEX_ARR    1172         $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
1173         #replace DEFINE_DMA_UNMAP_ADDR           1173         #replace DEFINE_DMA_UNMAP_ADDR
1174         $members =~ s/DEFINE_DMA_UNMAP_ADDR\s    1174         $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
1175         #replace DEFINE_DMA_UNMAP_LEN            1175         #replace DEFINE_DMA_UNMAP_LEN
1176         $members =~ s/DEFINE_DMA_UNMAP_LEN\s*    1176         $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
1177         my $declaration = $members;              1177         my $declaration = $members;
1178                                                  1178 
1179         # Split nested struct/union elements     1179         # Split nested struct/union elements as newer ones
1180         while ($members =~ m/$struct_members/    1180         while ($members =~ m/$struct_members/) {
1181             my $newmember;                       1181             my $newmember;
1182             my $maintype = $1;                   1182             my $maintype = $1;
1183             my $ids = $4;                        1183             my $ids = $4;
1184             my $content = $3;                    1184             my $content = $3;
1185             foreach my $id(split /,/, $ids) {    1185             foreach my $id(split /,/, $ids) {
1186                 $newmember .= "$maintype $id;    1186                 $newmember .= "$maintype $id; ";
1187                                                  1187 
1188                 $id =~ s/[:\[].*//;              1188                 $id =~ s/[:\[].*//;
1189                 $id =~ s/^\s*\**(\S+)\s*/$1/;    1189                 $id =~ s/^\s*\**(\S+)\s*/$1/;
1190                 foreach my $arg (split /;/, $    1190                 foreach my $arg (split /;/, $content) {
1191                     next if ($arg =~ m/^\s*$/    1191                     next if ($arg =~ m/^\s*$/);
1192                     if ($arg =~ m/^([^\(]+\(\    1192                     if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
1193                         # pointer-to-function    1193                         # pointer-to-function
1194                         my $type = $1;           1194                         my $type = $1;
1195                         my $name = $2;           1195                         my $name = $2;
1196                         my $extra = $3;          1196                         my $extra = $3;
1197                         next if (!$name);        1197                         next if (!$name);
1198                         if ($id =~ m/^\s*$/)     1198                         if ($id =~ m/^\s*$/) {
1199                             # anonymous struc    1199                             # anonymous struct/union
1200                             $newmember .= "$t    1200                             $newmember .= "$type$name$extra; ";
1201                         } else {                 1201                         } else {
1202                             $newmember .= "$t    1202                             $newmember .= "$type$id.$name$extra; ";
1203                         }                        1203                         }
1204                     } else {                     1204                     } else {
1205                         my $type;                1205                         my $type;
1206                         my $names;               1206                         my $names;
1207                         $arg =~ s/^\s+//;        1207                         $arg =~ s/^\s+//;
1208                         $arg =~ s/\s+$//;        1208                         $arg =~ s/\s+$//;
1209                         # Handle bitmaps         1209                         # Handle bitmaps
1210                         $arg =~ s/:\s*\d+\s*/    1210                         $arg =~ s/:\s*\d+\s*//g;
1211                         # Handle arrays          1211                         # Handle arrays
1212                         $arg =~ s/\[.*\]//g;     1212                         $arg =~ s/\[.*\]//g;
1213                         # The type may have m    1213                         # The type may have multiple words,
1214                         # and multiple IDs ca    1214                         # and multiple IDs can be defined, like:
1215                         #    const struct foo    1215                         #    const struct foo, *bar, foobar
1216                         # So, we remove space    1216                         # So, we remove spaces when parsing the
1217                         # names, in order to     1217                         # names, in order to match just names
1218                         # and commas for the     1218                         # and commas for the names
1219                         $arg =~ s/\s*,\s*/,/g    1219                         $arg =~ s/\s*,\s*/,/g;
1220                         if ($arg =~ m/(.*)\s+    1220                         if ($arg =~ m/(.*)\s+([\S+,]+)/) {
1221                             $type = $1;          1221                             $type = $1;
1222                             $names = $2;         1222                             $names = $2;
1223                         } else {                 1223                         } else {
1224                             $newmember .= "$a    1224                             $newmember .= "$arg; ";
1225                             next;                1225                             next;
1226                         }                        1226                         }
1227                         foreach my $name (spl    1227                         foreach my $name (split /,/, $names) {
1228                             $name =~ s/^\s*\*    1228                             $name =~ s/^\s*\**(\S+)\s*/$1/;
1229                             next if (($name =    1229                             next if (($name =~ m/^\s*$/));
1230                             if ($id =~ m/^\s*    1230                             if ($id =~ m/^\s*$/) {
1231                                 # anonymous s    1231                                 # anonymous struct/union
1232                                 $newmember .=    1232                                 $newmember .= "$type $name; ";
1233                             } else {             1233                             } else {
1234                                 $newmember .=    1234                                 $newmember .= "$type $id.$name; ";
1235                             }                    1235                             }
1236                         }                        1236                         }
1237                     }                            1237                     }
1238                 }                                1238                 }
1239             }                                    1239             }
1240             $members =~ s/$struct_members/$ne    1240             $members =~ s/$struct_members/$newmember/;
1241         }                                        1241         }
1242                                                  1242 
1243         # Ignore other nested elements, like     1243         # Ignore other nested elements, like enums
1244         $members =~ s/(\{[^\{\}]*\})//g;         1244         $members =~ s/(\{[^\{\}]*\})//g;
1245                                                  1245 
1246         create_parameterlist($members, ';', $    1246         create_parameterlist($members, ';', $file, $declaration_name);
1247         check_sections($file, $declaration_na    1247         check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
1248                                                  1248 
1249         # Adjust declaration for better displ    1249         # Adjust declaration for better display
1250         $declaration =~ s/([\{;])/$1\n/g;        1250         $declaration =~ s/([\{;])/$1\n/g;
1251         $declaration =~ s/\}\s+;/};/g;           1251         $declaration =~ s/\}\s+;/};/g;
1252         # Better handle inlined enums            1252         # Better handle inlined enums
1253         do {} while ($declaration =~ s/(enum\    1253         do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
1254                                                  1254 
1255         my @def_args = split /\n/, $declarati    1255         my @def_args = split /\n/, $declaration;
1256         my $level = 1;                           1256         my $level = 1;
1257         $declaration = "";                       1257         $declaration = "";
1258         foreach my $clause (@def_args) {         1258         foreach my $clause (@def_args) {
1259             $clause =~ s/^\s+//;                 1259             $clause =~ s/^\s+//;
1260             $clause =~ s/\s+$//;                 1260             $clause =~ s/\s+$//;
1261             $clause =~ s/\s+/ /;                 1261             $clause =~ s/\s+/ /;
1262             next if (!$clause);                  1262             next if (!$clause);
1263             $level-- if ($clause =~ m/(\})/ &    1263             $level-- if ($clause =~ m/(\})/ && $level > 1);
1264             if (!($clause =~ m/^\s*#/)) {        1264             if (!($clause =~ m/^\s*#/)) {
1265                 $declaration .= "\t" x $level    1265                 $declaration .= "\t" x $level;
1266             }                                    1266             }
1267             $declaration .= "\t" . $clause .     1267             $declaration .= "\t" . $clause . "\n";
1268             $level++ if ($clause =~ m/(\{)/ &    1268             $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
1269         }                                        1269         }
1270         output_declaration($declaration_name,    1270         output_declaration($declaration_name,
1271                    'struct',                     1271                    'struct',
1272                    {'struct' => $declaration_    1272                    {'struct' => $declaration_name,
1273                     'module' => $modulename,     1273                     'module' => $modulename,
1274                     'definition' => $declarat    1274                     'definition' => $declaration,
1275                     'parameterlist' => \@para    1275                     'parameterlist' => \@parameterlist,
1276                     'parameterdescs' => \%par    1276                     'parameterdescs' => \%parameterdescs,
1277                     'parametertypes' => \%par    1277                     'parametertypes' => \%parametertypes,
1278                     'sectionlist' => \@sectio    1278                     'sectionlist' => \@sectionlist,
1279                     'sections' => \%sections,    1279                     'sections' => \%sections,
1280                     'purpose' => $declaration    1280                     'purpose' => $declaration_purpose,
1281                     'type' => $decl_type         1281                     'type' => $decl_type
1282                    });                           1282                    });
1283     } else {                                     1283     } else {
1284         print STDERR "${file}:$.: error: Cann    1284         print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
1285         ++$errors;                               1285         ++$errors;
1286     }                                            1286     }
1287 }                                                1287 }
1288                                                  1288 
1289                                                  1289 
1290 sub show_warnings($$) {                          1290 sub show_warnings($$) {
1291     my $functype = shift;                        1291     my $functype = shift;
1292     my $name = shift;                            1292     my $name = shift;
1293                                                  1293 
1294     return 0 if (defined($nosymbol_table{$nam    1294     return 0 if (defined($nosymbol_table{$name}));
1295                                                  1295 
1296     return 1 if ($output_selection == OUTPUT_    1296     return 1 if ($output_selection == OUTPUT_ALL);
1297                                                  1297 
1298     if ($output_selection == OUTPUT_EXPORTED)    1298     if ($output_selection == OUTPUT_EXPORTED) {
1299         if (defined($function_table{$name}))     1299         if (defined($function_table{$name})) {
1300             return 1;                            1300             return 1;
1301         } else {                                 1301         } else {
1302             return 0;                            1302             return 0;
1303         }                                        1303         }
1304     }                                            1304     }
1305     if ($output_selection == OUTPUT_INTERNAL)    1305     if ($output_selection == OUTPUT_INTERNAL) {
1306         if (!($functype eq "function" && defi    1306         if (!($functype eq "function" && defined($function_table{$name}))) {
1307             return 1;                            1307             return 1;
1308         } else {                                 1308         } else {
1309             return 0;                            1309             return 0;
1310         }                                        1310         }
1311     }                                            1311     }
1312     if ($output_selection == OUTPUT_INCLUDE)     1312     if ($output_selection == OUTPUT_INCLUDE) {
1313         if (defined($function_table{$name}))     1313         if (defined($function_table{$name})) {
1314             return 1;                            1314             return 1;
1315         } else {                                 1315         } else {
1316             return 0;                            1316             return 0;
1317         }                                        1317         }
1318     }                                            1318     }
1319     die("Please add the new output type at sh    1319     die("Please add the new output type at show_warnings()");
1320 }                                                1320 }
1321                                                  1321 
1322 sub dump_enum($$) {                              1322 sub dump_enum($$) {
1323     my $x = shift;                               1323     my $x = shift;
1324     my $file = shift;                            1324     my $file = shift;
1325     my $members;                                 1325     my $members;
1326                                                  1326 
1327     # ignore members marked private:             1327     # ignore members marked private:
1328     $x =~ s/\/\*\s*private:.*?\/\*\s*public:.    1328     $x =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
1329     $x =~ s/\/\*\s*private:.*}/}/gosi;           1329     $x =~ s/\/\*\s*private:.*}/}/gosi;
1330                                                  1330 
1331     $x =~ s@/\*.*?\*/@@gos;     # strip comme    1331     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1332     # strip #define macros inside enums          1332     # strip #define macros inside enums
1333     $x =~ s@#\s*((define|ifdef|if)\s+|endif)[    1333     $x =~ s@#\s*((define|ifdef|if)\s+|endif)[^;]*;@@gos;
1334                                                  1334 
1335     if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\    1335     if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
1336         $declaration_name = $2;                  1336         $declaration_name = $2;
1337         $members = $1;                           1337         $members = $1;
1338     } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/)    1338     } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
1339         $declaration_name = $1;                  1339         $declaration_name = $1;
1340         $members = $2;                           1340         $members = $2;
1341     }                                            1341     }
1342                                                  1342 
1343     if ($members) {                              1343     if ($members) {
1344         if ($identifier ne $declaration_name)    1344         if ($identifier ne $declaration_name) {
1345             if ($identifier eq "") {             1345             if ($identifier eq "") {
1346                 emit_warning("${file}:$.", "w    1346                 emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
1347             } else {                             1347             } else {
1348                 emit_warning("${file}:$.", "e    1348                 emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
1349             }                                    1349             }
1350             return;                              1350             return;
1351         }                                        1351         }
1352         $declaration_name = "(anonymous)" if     1352         $declaration_name = "(anonymous)" if ($declaration_name eq "");
1353                                                  1353 
1354         my %_members;                            1354         my %_members;
1355                                                  1355 
1356         $members =~ s/\s+$//;                    1356         $members =~ s/\s+$//;
1357         $members =~ s/\([^;]*?[\)]//g;           1357         $members =~ s/\([^;]*?[\)]//g;
1358                                                  1358 
1359         foreach my $arg (split ',', $members)    1359         foreach my $arg (split ',', $members) {
1360             $arg =~ s/^\s*(\w+).*/$1/;           1360             $arg =~ s/^\s*(\w+).*/$1/;
1361             push @parameterlist, $arg;           1361             push @parameterlist, $arg;
1362             if (!$parameterdescs{$arg}) {        1362             if (!$parameterdescs{$arg}) {
1363                 $parameterdescs{$arg} = $unde    1363                 $parameterdescs{$arg} = $undescribed;
1364                 if (show_warnings("enum", $de    1364                 if (show_warnings("enum", $declaration_name)) {
1365                     emit_warning("${file}:$."    1365                     emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
1366                 }                                1366                 }
1367             }                                    1367             }
1368             $_members{$arg} = 1;                 1368             $_members{$arg} = 1;
1369         }                                        1369         }
1370                                                  1370 
1371         while (my ($k, $v) = each %parameterd    1371         while (my ($k, $v) = each %parameterdescs) {
1372             if (!exists($_members{$k})) {        1372             if (!exists($_members{$k})) {
1373                 if (show_warnings("enum", $de    1373                 if (show_warnings("enum", $declaration_name)) {
1374                     emit_warning("${file}:$."    1374                     emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
1375                 }                                1375                 }
1376             }                                    1376             }
1377         }                                        1377         }
1378                                                  1378 
1379         output_declaration($declaration_name,    1379         output_declaration($declaration_name,
1380                            'enum',               1380                            'enum',
1381                            {'enum' => $declar    1381                            {'enum' => $declaration_name,
1382                             'module' => $modu    1382                             'module' => $modulename,
1383                             'parameterlist' =    1383                             'parameterlist' => \@parameterlist,
1384                             'parameterdescs'     1384                             'parameterdescs' => \%parameterdescs,
1385                             'sectionlist' =>     1385                             'sectionlist' => \@sectionlist,
1386                             'sections' => \%s    1386                             'sections' => \%sections,
1387                             'purpose' => $dec    1387                             'purpose' => $declaration_purpose
1388                            });                   1388                            });
1389     } else {                                     1389     } else {
1390         print STDERR "${file}:$.: error: Cann    1390         print STDERR "${file}:$.: error: Cannot parse enum!\n";
1391         ++$errors;                               1391         ++$errors;
1392     }                                            1392     }
1393 }                                                1393 }
1394                                                  1394 
1395 my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8    1395 my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x;
1396 my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;    1396 my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
1397 my $typedef_args = qr { \s*\((.*)\); }x;         1397 my $typedef_args = qr { \s*\((.*)\); }x;
1398                                                  1398 
1399 my $typedef1 = qr { typedef$typedef_type\($ty    1399 my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;
1400 my $typedef2 = qr { typedef$typedef_type$type    1400 my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x;
1401                                                  1401 
1402 sub dump_typedef($$) {                           1402 sub dump_typedef($$) {
1403     my $x = shift;                               1403     my $x = shift;
1404     my $file = shift;                            1404     my $file = shift;
1405                                                  1405 
1406     $x =~ s@/\*.*?\*/@@gos;     # strip comme    1406     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1407                                                  1407 
1408     # Parse function typedef prototypes          1408     # Parse function typedef prototypes
1409     if ($x =~ $typedef1 || $x =~ $typedef2) {    1409     if ($x =~ $typedef1 || $x =~ $typedef2) {
1410         $return_type = $1;                       1410         $return_type = $1;
1411         $declaration_name = $2;                  1411         $declaration_name = $2;
1412         my $args = $3;                           1412         my $args = $3;
1413         $return_type =~ s/^\s+//;                1413         $return_type =~ s/^\s+//;
1414                                                  1414 
1415         if ($identifier ne $declaration_name)    1415         if ($identifier ne $declaration_name) {
1416             emit_warning("${file}:$.", "expec    1416             emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
1417             return;                              1417             return;
1418         }                                        1418         }
1419                                                  1419 
1420         create_parameterlist($args, ',', $fil    1420         create_parameterlist($args, ',', $file, $declaration_name);
1421                                                  1421 
1422         output_declaration($declaration_name,    1422         output_declaration($declaration_name,
1423                            'function',           1423                            'function',
1424                            {'function' => $de    1424                            {'function' => $declaration_name,
1425                             'typedef' => 1,      1425                             'typedef' => 1,
1426                             'module' => $modu    1426                             'module' => $modulename,
1427                             'functiontype' =>    1427                             'functiontype' => $return_type,
1428                             'parameterlist' =    1428                             'parameterlist' => \@parameterlist,
1429                             'parameterdescs'     1429                             'parameterdescs' => \%parameterdescs,
1430                             'parametertypes'     1430                             'parametertypes' => \%parametertypes,
1431                             'sectionlist' =>     1431                             'sectionlist' => \@sectionlist,
1432                             'sections' => \%s    1432                             'sections' => \%sections,
1433                             'purpose' => $dec    1433                             'purpose' => $declaration_purpose
1434                            });                   1434                            });
1435         return;                                  1435         return;
1436     }                                            1436     }
1437                                                  1437 
1438     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\    1438     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
1439         $x =~ s/\(*.\)\s*;$/;/;                  1439         $x =~ s/\(*.\)\s*;$/;/;
1440         $x =~ s/\[*.\]\s*;$/;/;                  1440         $x =~ s/\[*.\]\s*;$/;/;
1441     }                                            1441     }
1442                                                  1442 
1443     if ($x =~ /typedef.*\s+(\w+)\s*;/) {         1443     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
1444         $declaration_name = $1;                  1444         $declaration_name = $1;
1445                                                  1445 
1446         if ($identifier ne $declaration_name)    1446         if ($identifier ne $declaration_name) {
1447             emit_warning("${file}:$.", "expec    1447             emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
1448             return;                              1448             return;
1449         }                                        1449         }
1450                                                  1450 
1451         output_declaration($declaration_name,    1451         output_declaration($declaration_name,
1452                            'typedef',            1452                            'typedef',
1453                            {'typedef' => $dec    1453                            {'typedef' => $declaration_name,
1454                             'module' => $modu    1454                             'module' => $modulename,
1455                             'sectionlist' =>     1455                             'sectionlist' => \@sectionlist,
1456                             'sections' => \%s    1456                             'sections' => \%sections,
1457                             'purpose' => $dec    1457                             'purpose' => $declaration_purpose
1458                            });                   1458                            });
1459     } else {                                     1459     } else {
1460         print STDERR "${file}:$.: error: Cann    1460         print STDERR "${file}:$.: error: Cannot parse typedef!\n";
1461         ++$errors;                               1461         ++$errors;
1462     }                                            1462     }
1463 }                                                1463 }
1464                                                  1464 
1465 sub save_struct_actual($) {                      1465 sub save_struct_actual($) {
1466     my $actual = shift;                          1466     my $actual = shift;
1467                                                  1467 
1468     # strip all spaces from the actual param     1468     # strip all spaces from the actual param so that it looks like one string item
1469     $actual =~ s/\s*//g;                         1469     $actual =~ s/\s*//g;
1470     $struct_actual = $struct_actual . $actual    1470     $struct_actual = $struct_actual . $actual . " ";
1471 }                                                1471 }
1472                                                  1472 
1473 sub create_parameterlist($$$$) {                 1473 sub create_parameterlist($$$$) {
1474     my $args = shift;                            1474     my $args = shift;
1475     my $splitter = shift;                        1475     my $splitter = shift;
1476     my $file = shift;                            1476     my $file = shift;
1477     my $declaration_name = shift;                1477     my $declaration_name = shift;
1478     my $type;                                    1478     my $type;
1479     my $param;                                   1479     my $param;
1480                                                  1480 
1481     # temporarily replace commas inside funct    1481     # temporarily replace commas inside function pointer definition
1482     my $arg_expr = qr{\([^\),]+};                1482     my $arg_expr = qr{\([^\),]+};
1483     while ($args =~ /$arg_expr,/) {              1483     while ($args =~ /$arg_expr,/) {
1484         $args =~ s/($arg_expr),/$1#/g;           1484         $args =~ s/($arg_expr),/$1#/g;
1485     }                                            1485     }
1486                                                  1486 
1487     foreach my $arg (split($splitter, $args))    1487     foreach my $arg (split($splitter, $args)) {
1488         # strip comments                         1488         # strip comments
1489         $arg =~ s/\/\*.*\*\///;                  1489         $arg =~ s/\/\*.*\*\///;
1490         # ignore argument attributes             1490         # ignore argument attributes
1491         $arg =~ s/\sPOS0?\s/ /;                  1491         $arg =~ s/\sPOS0?\s/ /;
1492         # strip leading/trailing spaces          1492         # strip leading/trailing spaces
1493         $arg =~ s/^\s*//;                        1493         $arg =~ s/^\s*//;
1494         $arg =~ s/\s*$//;                        1494         $arg =~ s/\s*$//;
1495         $arg =~ s/\s+/ /;                        1495         $arg =~ s/\s+/ /;
1496                                                  1496 
1497         if ($arg =~ /^#/) {                      1497         if ($arg =~ /^#/) {
1498             # Treat preprocessor directive as    1498             # Treat preprocessor directive as a typeless variable just to fill
1499             # corresponding data structures "    1499             # corresponding data structures "correctly". Catch it later in
1500             # output_* subs.                     1500             # output_* subs.
1501             push_parameter($arg, "", "", $fil    1501             push_parameter($arg, "", "", $file);
1502         } elsif ($arg =~ m/\(.+\)\s*\(/) {       1502         } elsif ($arg =~ m/\(.+\)\s*\(/) {
1503             # pointer-to-function                1503             # pointer-to-function
1504             $arg =~ tr/#/,/;                     1504             $arg =~ tr/#/,/;
1505             $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\    1505             $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
1506             $param = $1;                         1506             $param = $1;
1507             $type = $arg;                        1507             $type = $arg;
1508             $type =~ s/([^\(]+\(\*?)\s*$param    1508             $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
1509             save_struct_actual($param);          1509             save_struct_actual($param);
1510             push_parameter($param, $type, $ar    1510             push_parameter($param, $type, $arg, $file, $declaration_name);
1511         } elsif ($arg =~ m/\(.+\)\s*\[/) {       1511         } elsif ($arg =~ m/\(.+\)\s*\[/) {
1512             # array-of-pointers                  1512             # array-of-pointers
1513             $arg =~ tr/#/,/;                     1513             $arg =~ tr/#/,/;
1514             $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\    1514             $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)/;
1515             $param = $1;                         1515             $param = $1;
1516             $type = $arg;                        1516             $type = $arg;
1517             $type =~ s/([^\(]+\(\*?)\s*$param    1517             $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
1518             save_struct_actual($param);          1518             save_struct_actual($param);
1519             push_parameter($param, $type, $ar    1519             push_parameter($param, $type, $arg, $file, $declaration_name);
1520         } elsif ($arg) {                         1520         } elsif ($arg) {
1521             $arg =~ s/\s*:\s*/:/g;               1521             $arg =~ s/\s*:\s*/:/g;
1522             $arg =~ s/\s*\[/\[/g;                1522             $arg =~ s/\s*\[/\[/g;
1523                                                  1523 
1524             my @args = split('\s*,\s*', $arg)    1524             my @args = split('\s*,\s*', $arg);
1525             if ($args[0] =~ m/\*/) {             1525             if ($args[0] =~ m/\*/) {
1526                 $args[0] =~ s/(\*+)\s*/ $1/;     1526                 $args[0] =~ s/(\*+)\s*/ $1/;
1527             }                                    1527             }
1528                                                  1528 
1529             my @first_arg;                       1529             my @first_arg;
1530             if ($args[0] =~ /^(.*\s+)(.*?\[.*    1530             if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
1531                 shift @args;                     1531                 shift @args;
1532                 push(@first_arg, split('\s+',    1532                 push(@first_arg, split('\s+', $1));
1533                 push(@first_arg, $2);            1533                 push(@first_arg, $2);
1534             } else {                             1534             } else {
1535                 @first_arg = split('\s+', shi    1535                 @first_arg = split('\s+', shift @args);
1536             }                                    1536             }
1537                                                  1537 
1538             unshift(@args, pop @first_arg);      1538             unshift(@args, pop @first_arg);
1539             $type = join " ", @first_arg;        1539             $type = join " ", @first_arg;
1540                                                  1540 
1541             foreach $param (@args) {             1541             foreach $param (@args) {
1542                 if ($param =~ m/^(\*+)\s*(.*)    1542                 if ($param =~ m/^(\*+)\s*(.*)/) {
1543                     save_struct_actual($2);      1543                     save_struct_actual($2);
1544                                                  1544 
1545                     push_parameter($2, "$type    1545                     push_parameter($2, "$type $1", $arg, $file, $declaration_name);
1546                 } elsif ($param =~ m/(.*?):(\    1546                 } elsif ($param =~ m/(.*?):(\w+)/) {
1547                     if ($type ne "") { # skip    1547                     if ($type ne "") { # skip unnamed bit-fields
1548                         save_struct_actual($1    1548                         save_struct_actual($1);
1549                         push_parameter($1, "$    1549                         push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
1550                     }                            1550                     }
1551                 } else {                         1551                 } else {
1552                     save_struct_actual($param    1552                     save_struct_actual($param);
1553                     push_parameter($param, $t    1553                     push_parameter($param, $type, $arg, $file, $declaration_name);
1554                 }                                1554                 }
1555             }                                    1555             }
1556         }                                        1556         }
1557     }                                            1557     }
1558 }                                                1558 }
1559                                                  1559 
1560 sub push_parameter($$$$$) {                      1560 sub push_parameter($$$$$) {
1561     my $param = shift;                           1561     my $param = shift;
1562     my $type = shift;                            1562     my $type = shift;
1563     my $org_arg = shift;                         1563     my $org_arg = shift;
1564     my $file = shift;                            1564     my $file = shift;
1565     my $declaration_name = shift;                1565     my $declaration_name = shift;
1566                                                  1566 
1567     if (($anon_struct_union == 1) && ($type e    1567     if (($anon_struct_union == 1) && ($type eq "") &&
1568         ($param eq "}")) {                       1568         ($param eq "}")) {
1569         return;        # ignore the ending };    1569         return;        # ignore the ending }; from anon. struct/union
1570     }                                            1570     }
1571                                                  1571 
1572     $anon_struct_union = 0;                      1572     $anon_struct_union = 0;
1573     $param =~ s/[\[\)].*//;                      1573     $param =~ s/[\[\)].*//;
1574                                                  1574 
1575     if ($type eq "" && $param =~ /\.\.\.$/)      1575     if ($type eq "" && $param =~ /\.\.\.$/)
1576     {                                            1576     {
1577         if (!$param =~ /\w\.\.\.$/) {            1577         if (!$param =~ /\w\.\.\.$/) {
1578             # handles unnamed variable parame    1578             # handles unnamed variable parameters
1579             $param = "...";                      1579             $param = "...";
1580         } elsif ($param =~ /\w\.\.\.$/) {        1580         } elsif ($param =~ /\w\.\.\.$/) {
1581             # for named variable parameters o    1581             # for named variable parameters of the form `x...`, remove the dots
1582             $param =~ s/\.\.\.$//;               1582             $param =~ s/\.\.\.$//;
1583         }                                        1583         }
1584         if (!defined $parameterdescs{$param}     1584         if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
1585             $parameterdescs{$param} = "variab    1585             $parameterdescs{$param} = "variable arguments";
1586         }                                        1586         }
1587     }                                            1587     }
1588     elsif ($type eq "" && ($param eq "" or $p    1588     elsif ($type eq "" && ($param eq "" or $param eq "void"))
1589     {                                            1589     {
1590         $param="void";                           1590         $param="void";
1591         $parameterdescs{void} = "no arguments    1591         $parameterdescs{void} = "no arguments";
1592     }                                            1592     }
1593     elsif ($type eq "" && ($param eq "struct"    1593     elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
1594     # handle unnamed (anonymous) union or str    1594     # handle unnamed (anonymous) union or struct:
1595     {                                            1595     {
1596         $type = $param;                          1596         $type = $param;
1597         $param = "{unnamed_" . $param . "}";     1597         $param = "{unnamed_" . $param . "}";
1598         $parameterdescs{$param} = "anonymous\    1598         $parameterdescs{$param} = "anonymous\n";
1599         $anon_struct_union = 1;                  1599         $anon_struct_union = 1;
1600     }                                            1600     }
1601     elsif ($param =~ "__cacheline_group" )       1601     elsif ($param =~ "__cacheline_group" )
1602     # handle cache group enforcing variables:    1602     # handle cache group enforcing variables: they do not need be described in header files
1603     {                                            1603     {
1604         return; # ignore __cacheline_group_be    1604         return; # ignore __cacheline_group_begin and __cacheline_group_end
1605     }                                            1605     }
1606                                                  1606 
1607     # warn if parameter has no description       1607     # warn if parameter has no description
1608     # (but ignore ones starting with # as the    1608     # (but ignore ones starting with # as these are not parameters
1609     # but inline preprocessor statements);       1609     # but inline preprocessor statements);
1610     # Note: It will also ignore void params a    1610     # Note: It will also ignore void params and unnamed structs/unions
1611     if (!defined $parameterdescs{$param} && $    1611     if (!defined $parameterdescs{$param} && $param !~ /^#/) {
1612         $parameterdescs{$param} = $undescribe    1612         $parameterdescs{$param} = $undescribed;
1613                                                  1613 
1614         if (show_warnings($type, $declaration    1614         if (show_warnings($type, $declaration_name) && $param !~ /\./) {
1615             emit_warning("${file}:$.", "Funct    1615             emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
1616         }                                        1616         }
1617     }                                            1617     }
1618                                                  1618 
1619     # strip spaces from $param so that it is     1619     # strip spaces from $param so that it is one continuous string
1620     # on @parameterlist;                         1620     # on @parameterlist;
1621     # this fixes a problem where check_sectio    1621     # this fixes a problem where check_sections() cannot find
1622     # a parameter like "addr[6 + 2]" because     1622     # a parameter like "addr[6 + 2]" because it actually appears
1623     # as "addr[6", "+", "2]" on the parameter    1623     # as "addr[6", "+", "2]" on the parameter list;
1624     # but it's better to maintain the param s    1624     # but it's better to maintain the param string unchanged for output,
1625     # so just weaken the string compare in ch    1625     # so just weaken the string compare in check_sections() to ignore
1626     # "[blah" in a parameter string;             1626     # "[blah" in a parameter string;
1627     ###$param =~ s/\s*//g;                       1627     ###$param =~ s/\s*//g;
1628     push @parameterlist, $param;                 1628     push @parameterlist, $param;
1629     $org_arg =~ s/\s\s+/ /g;                     1629     $org_arg =~ s/\s\s+/ /g;
1630     $parametertypes{$param} = $org_arg;          1630     $parametertypes{$param} = $org_arg;
1631 }                                                1631 }
1632                                                  1632 
1633 sub check_sections($$$$$) {                      1633 sub check_sections($$$$$) {
1634     my ($file, $decl_name, $decl_type, $sectc    1634     my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
1635     my @sects = split ' ', $sectcheck;           1635     my @sects = split ' ', $sectcheck;
1636     my @prms = split ' ', $prmscheck;            1636     my @prms = split ' ', $prmscheck;
1637     my $err;                                     1637     my $err;
1638     my ($px, $sx);                               1638     my ($px, $sx);
1639     my $prm_clean;        # strip trailing "[    1639     my $prm_clean;        # strip trailing "[array size]" and/or beginning "*"
1640                                                  1640 
1641     foreach $sx (0 .. $#sects) {                 1641     foreach $sx (0 .. $#sects) {
1642         $err = 1;                                1642         $err = 1;
1643         foreach $px (0 .. $#prms) {              1643         foreach $px (0 .. $#prms) {
1644             $prm_clean = $prms[$px];             1644             $prm_clean = $prms[$px];
1645             $prm_clean =~ s/\[.*\]//;            1645             $prm_clean =~ s/\[.*\]//;
1646             $prm_clean =~ s/$attribute//i;       1646             $prm_clean =~ s/$attribute//i;
1647             # ignore array size in a paramete    1647             # ignore array size in a parameter string;
1648             # however, the original param str    1648             # however, the original param string may contain
1649             # spaces, e.g.:  addr[6 + 2]         1649             # spaces, e.g.:  addr[6 + 2]
1650             # and this appears in @prms as "a    1650             # and this appears in @prms as "addr[6" since the
1651             # parameter list is split at spac    1651             # parameter list is split at spaces;
1652             # hence just ignore "[..." for th    1652             # hence just ignore "[..." for the sections check;
1653             $prm_clean =~ s/\[.*//;              1653             $prm_clean =~ s/\[.*//;
1654                                                  1654 
1655             ##$prm_clean =~ s/^\**//;            1655             ##$prm_clean =~ s/^\**//;
1656             if ($prm_clean eq $sects[$sx]) {     1656             if ($prm_clean eq $sects[$sx]) {
1657                 $err = 0;                        1657                 $err = 0;
1658                 last;                            1658                 last;
1659             }                                    1659             }
1660         }                                        1660         }
1661         if ($err) {                              1661         if ($err) {
1662             if ($decl_type eq "function") {      1662             if ($decl_type eq "function") {
1663                 emit_warning("${file}:$.",       1663                 emit_warning("${file}:$.",
1664                     "Excess function paramete    1664                     "Excess function parameter " .
1665                     "'$sects[$sx]' " .           1665                     "'$sects[$sx]' " .
1666                     "description in '$decl_na    1666                     "description in '$decl_name'\n");
1667             } elsif (($decl_type eq "struct")    1667             } elsif (($decl_type eq "struct") or
1668                           ($decl_type eq "uni    1668                           ($decl_type eq "union")) {
1669                 emit_warning("${file}:$.",       1669                 emit_warning("${file}:$.",
1670                     "Excess $decl_type member    1670                     "Excess $decl_type member " .
1671                     "'$sects[$sx]' " .           1671                     "'$sects[$sx]' " .
1672                     "description in '$decl_na    1672                     "description in '$decl_name'\n");
1673             }                                    1673             }
1674         }                                        1674         }
1675     }                                            1675     }
1676 }                                                1676 }
1677                                                  1677 
1678 ##                                               1678 ##
1679 # Checks the section describing the return va    1679 # Checks the section describing the return value of a function.
1680 sub check_return_section {                       1680 sub check_return_section {
1681     my $file = shift;                            1681     my $file = shift;
1682     my $declaration_name = shift;                1682     my $declaration_name = shift;
1683     my $return_type = shift;                     1683     my $return_type = shift;
1684                                                  1684 
1685     # Ignore an empty return type (It's a mac    1685     # Ignore an empty return type (It's a macro)
1686     # Ignore functions with a "void" return t    1686     # Ignore functions with a "void" return type. (But don't ignore "void *")
1687     if (($return_type eq "") || ($return_type    1687     if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
1688         return;                                  1688         return;
1689     }                                            1689     }
1690                                                  1690 
1691     if (!defined($sections{$section_return})     1691     if (!defined($sections{$section_return}) ||
1692         $sections{$section_return} eq "")        1692         $sections{$section_return} eq "")
1693     {                                            1693     {
1694         emit_warning("${file}:$.",               1694         emit_warning("${file}:$.",
1695                      "No description found fo    1695                      "No description found for return value of " .
1696                      "'$declaration_name'\n")    1696                      "'$declaration_name'\n");
1697     }                                            1697     }
1698 }                                                1698 }
1699                                                  1699 
1700 ##                                               1700 ##
1701 # takes a function prototype and the name of     1701 # takes a function prototype and the name of the current file being
1702 # processed and spits out all the details sto    1702 # processed and spits out all the details stored in the global
1703 # arrays/hashes.                                 1703 # arrays/hashes.
1704 sub dump_function($$) {                          1704 sub dump_function($$) {
1705     my $prototype = shift;                       1705     my $prototype = shift;
1706     my $file = shift;                            1706     my $file = shift;
1707     my $noret = 0;                               1707     my $noret = 0;
1708                                                  1708 
1709     print_lineno($new_start_line);               1709     print_lineno($new_start_line);
1710                                                  1710 
1711     $prototype =~ s/^static +//;                 1711     $prototype =~ s/^static +//;
1712     $prototype =~ s/^extern +//;                 1712     $prototype =~ s/^extern +//;
1713     $prototype =~ s/^asmlinkage +//;             1713     $prototype =~ s/^asmlinkage +//;
1714     $prototype =~ s/^inline +//;                 1714     $prototype =~ s/^inline +//;
1715     $prototype =~ s/^__inline__ +//;             1715     $prototype =~ s/^__inline__ +//;
1716     $prototype =~ s/^__inline +//;               1716     $prototype =~ s/^__inline +//;
1717     $prototype =~ s/^__always_inline +//;        1717     $prototype =~ s/^__always_inline +//;
1718     $prototype =~ s/^noinline +//;               1718     $prototype =~ s/^noinline +//;
1719     $prototype =~ s/^__FORTIFY_INLINE +//;       1719     $prototype =~ s/^__FORTIFY_INLINE +//;
1720     $prototype =~ s/__init +//;                  1720     $prototype =~ s/__init +//;
1721     $prototype =~ s/__init_or_module +//;        1721     $prototype =~ s/__init_or_module +//;
1722     $prototype =~ s/__deprecated +//;            1722     $prototype =~ s/__deprecated +//;
1723     $prototype =~ s/__flatten +//;               1723     $prototype =~ s/__flatten +//;
1724     $prototype =~ s/__meminit +//;               1724     $prototype =~ s/__meminit +//;
1725     $prototype =~ s/__must_check +//;            1725     $prototype =~ s/__must_check +//;
1726     $prototype =~ s/__weak +//;                  1726     $prototype =~ s/__weak +//;
1727     $prototype =~ s/__sched +//;                 1727     $prototype =~ s/__sched +//;
1728     $prototype =~ s/_noprof//;                   1728     $prototype =~ s/_noprof//;
1729     $prototype =~ s/__printf\s*\(\s*\d*\s*,\s    1729     $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
1730     $prototype =~ s/__(?:re)?alloc_size\s*\(\    1730     $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;
1731     $prototype =~ s/__diagnose_as\s*\(\s*\S+\    1731     $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//;
1732     $prototype =~ s/DECL_BUCKET_PARAMS\s*\(\s    1732     $prototype =~ s/DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)/$1, $2/;
1733     my $define = $prototype =~ s/^#\s*define\    1733     my $define = $prototype =~ s/^#\s*define\s+//; #ak added
1734     $prototype =~ s/__attribute_const__ +//;     1734     $prototype =~ s/__attribute_const__ +//;
1735     $prototype =~ s/__attribute__\s*\(\(         1735     $prototype =~ s/__attribute__\s*\(\(
1736             (?:                                  1736             (?:
1737                  [\w\s]++          # attribut    1737                  [\w\s]++          # attribute name
1738                  (?:\([^)]*+\))?   # attribut    1738                  (?:\([^)]*+\))?   # attribute arguments
1739                  \s*+,?            # optional    1739                  \s*+,?            # optional comma at the end
1740             )+                                   1740             )+
1741           \)\)\s+//x;                            1741           \)\)\s+//x;
1742                                                  1742 
1743     # Yes, this truly is vile.  We are lookin    1743     # Yes, this truly is vile.  We are looking for:
1744     # 1. Return type (may be nothing if we're    1744     # 1. Return type (may be nothing if we're looking at a macro)
1745     # 2. Function name                           1745     # 2. Function name
1746     # 3. Function parameters.                    1746     # 3. Function parameters.
1747     #                                            1747     #
1748     # All the while we have to watch out for     1748     # All the while we have to watch out for function pointer parameters
1749     # (which IIRC is what the two sections ar    1749     # (which IIRC is what the two sections are for), C types (these
1750     # regexps don't even start to express all    1750     # regexps don't even start to express all the possibilities), and
1751     # so on.                                     1751     # so on.
1752     #                                            1752     #
1753     # If you mess with these regexps, it's a     1753     # If you mess with these regexps, it's a good idea to check that
1754     # the following functions' documentation     1754     # the following functions' documentation still comes out right:
1755     # - parport_register_device (function poi    1755     # - parport_register_device (function pointer parameters)
1756     # - atomic_set (macro)                       1756     # - atomic_set (macro)
1757     # - pci_match_device, __copy_to_user (lon    1757     # - pci_match_device, __copy_to_user (long return type)
1758     my $name = qr{[a-zA-Z0-9_~:]+};              1758     my $name = qr{[a-zA-Z0-9_~:]+};
1759     my $prototype_end1 = qr{[^\(]*};             1759     my $prototype_end1 = qr{[^\(]*};
1760     my $prototype_end2 = qr{[^\{]*};             1760     my $prototype_end2 = qr{[^\{]*};
1761     my $prototype_end = qr{\(($prototype_end1    1761     my $prototype_end = qr{\(($prototype_end1|$prototype_end2)\)};
1762     my $type1 = qr{[\w\s]+};                     1762     my $type1 = qr{[\w\s]+};
1763     my $type2 = qr{$type1\*+};                   1763     my $type2 = qr{$type1\*+};
1764                                                  1764 
1765     if ($define && $prototype =~ m/^()($name)    1765     if ($define && $prototype =~ m/^()($name)\s+/) {
1766         # This is an object-like macro, it ha    1766         # This is an object-like macro, it has no return type and no parameter
1767         # list.                                  1767         # list.
1768         # Function-like macros are not allowe    1768         # Function-like macros are not allowed to have spaces between
1769         # declaration_name and opening parent    1769         # declaration_name and opening parenthesis (notice the \s+).
1770         $return_type = $1;                       1770         $return_type = $1;
1771         $declaration_name = $2;                  1771         $declaration_name = $2;
1772         $noret = 1;                              1772         $noret = 1;
1773     } elsif ($prototype =~ m/^()($name)\s*$pr    1773     } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ ||
1774         $prototype =~ m/^($type1)\s+($name)\s    1774         $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
1775         $prototype =~ m/^($type2+)\s*($name)\    1775         $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/)  {
1776         $return_type = $1;                       1776         $return_type = $1;
1777         $declaration_name = $2;                  1777         $declaration_name = $2;
1778         my $args = $3;                           1778         my $args = $3;
1779                                                  1779 
1780         create_parameterlist($args, ',', $fil    1780         create_parameterlist($args, ',', $file, $declaration_name);
1781     } else {                                     1781     } else {
1782         emit_warning("${file}:$.", "cannot un    1782         emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
1783         return;                                  1783         return;
1784     }                                            1784     }
1785                                                  1785 
1786     if ($identifier ne $declaration_name) {      1786     if ($identifier ne $declaration_name) {
1787         emit_warning("${file}:$.", "expecting    1787         emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
1788         return;                                  1788         return;
1789     }                                            1789     }
1790                                                  1790 
1791     my $prms = join " ", @parameterlist;         1791     my $prms = join " ", @parameterlist;
1792     check_sections($file, $declaration_name,     1792     check_sections($file, $declaration_name, "function", $sectcheck, $prms);
1793                                                  1793 
1794     # This check emits a lot of warnings at t    1794     # This check emits a lot of warnings at the moment, because many
1795     # functions don't have a 'Return' doc sec    1795     # functions don't have a 'Return' doc section. So until the number
1796     # of warnings goes sufficiently down, the    1796     # of warnings goes sufficiently down, the check is only performed in
1797     # -Wreturn mode.                             1797     # -Wreturn mode.
1798     # TODO: always perform the check.            1798     # TODO: always perform the check.
1799     if ($Wreturn && !$noret) {                   1799     if ($Wreturn && !$noret) {
1800         check_return_section($file, $declarat    1800         check_return_section($file, $declaration_name, $return_type);
1801     }                                            1801     }
1802                                                  1802 
1803     # The function parser can be called with     1803     # The function parser can be called with a typedef parameter.
1804     # Handle it.                                 1804     # Handle it.
1805     if ($return_type =~ /typedef/) {             1805     if ($return_type =~ /typedef/) {
1806         output_declaration($declaration_name,    1806         output_declaration($declaration_name,
1807                            'function',           1807                            'function',
1808                            {'function' => $de    1808                            {'function' => $declaration_name,
1809                             'typedef' => 1,      1809                             'typedef' => 1,
1810                             'module' => $modu    1810                             'module' => $modulename,
1811                             'functiontype' =>    1811                             'functiontype' => $return_type,
1812                             'parameterlist' =    1812                             'parameterlist' => \@parameterlist,
1813                             'parameterdescs'     1813                             'parameterdescs' => \%parameterdescs,
1814                             'parametertypes'     1814                             'parametertypes' => \%parametertypes,
1815                             'sectionlist' =>     1815                             'sectionlist' => \@sectionlist,
1816                             'sections' => \%s    1816                             'sections' => \%sections,
1817                             'purpose' => $dec    1817                             'purpose' => $declaration_purpose
1818                            });                   1818                            });
1819     } else {                                     1819     } else {
1820         output_declaration($declaration_name,    1820         output_declaration($declaration_name,
1821                            'function',           1821                            'function',
1822                            {'function' => $de    1822                            {'function' => $declaration_name,
1823                             'module' => $modu    1823                             'module' => $modulename,
1824                             'functiontype' =>    1824                             'functiontype' => $return_type,
1825                             'parameterlist' =    1825                             'parameterlist' => \@parameterlist,
1826                             'parameterdescs'     1826                             'parameterdescs' => \%parameterdescs,
1827                             'parametertypes'     1827                             'parametertypes' => \%parametertypes,
1828                             'sectionlist' =>     1828                             'sectionlist' => \@sectionlist,
1829                             'sections' => \%s    1829                             'sections' => \%sections,
1830                             'purpose' => $dec    1830                             'purpose' => $declaration_purpose
1831                            });                   1831                            });
1832     }                                            1832     }
1833 }                                                1833 }
1834                                                  1834 
1835 sub reset_state {                                1835 sub reset_state {
1836     $function = "";                              1836     $function = "";
1837     %parameterdescs = ();                        1837     %parameterdescs = ();
1838     %parametertypes = ();                        1838     %parametertypes = ();
1839     @parameterlist = ();                         1839     @parameterlist = ();
1840     %sections = ();                              1840     %sections = ();
1841     @sectionlist = ();                           1841     @sectionlist = ();
1842     $sectcheck = "";                             1842     $sectcheck = "";
1843     $struct_actual = "";                         1843     $struct_actual = "";
1844     $prototype = "";                             1844     $prototype = "";
1845                                                  1845 
1846     $state = STATE_NORMAL;                       1846     $state = STATE_NORMAL;
1847     $inline_doc_state = STATE_INLINE_NA;         1847     $inline_doc_state = STATE_INLINE_NA;
1848 }                                                1848 }
1849                                                  1849 
1850 sub tracepoint_munge($) {                        1850 sub tracepoint_munge($) {
1851     my $file = shift;                            1851     my $file = shift;
1852     my $tracepointname = 0;                      1852     my $tracepointname = 0;
1853     my $tracepointargs = 0;                      1853     my $tracepointargs = 0;
1854                                                  1854 
1855     if ($prototype =~ m/TRACE_EVENT\((.*?),/)    1855     if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
1856         $tracepointname = $1;                    1856         $tracepointname = $1;
1857     }                                            1857     }
1858     if ($prototype =~ m/DEFINE_SINGLE_EVENT\(    1858     if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
1859         $tracepointname = $1;                    1859         $tracepointname = $1;
1860     }                                            1860     }
1861     if ($prototype =~ m/DEFINE_EVENT\((.*?),(    1861     if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
1862         $tracepointname = $2;                    1862         $tracepointname = $2;
1863     }                                            1863     }
1864     $tracepointname =~ s/^\s+//; #strip leadi    1864     $tracepointname =~ s/^\s+//; #strip leading whitespace
1865     if ($prototype =~ m/TP_PROTO\((.*?)\)/) {    1865     if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
1866         $tracepointargs = $1;                    1866         $tracepointargs = $1;
1867     }                                            1867     }
1868     if (($tracepointname eq 0) || ($tracepoin    1868     if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
1869         emit_warning("${file}:$.", "Unrecogni    1869         emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
1870                  "$prototype\n");                1870                  "$prototype\n");
1871     } else {                                     1871     } else {
1872         $prototype = "static inline void trac    1872         $prototype = "static inline void trace_$tracepointname($tracepointargs)";
1873         $identifier = "trace_$identifier";       1873         $identifier = "trace_$identifier";
1874     }                                            1874     }
1875 }                                                1875 }
1876                                                  1876 
1877 sub syscall_munge() {                            1877 sub syscall_munge() {
1878     my $void = 0;                                1878     my $void = 0;
1879                                                  1879 
1880     $prototype =~ s@[\r\n]+@ @gos; # strip ne    1880     $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
1881 ##    if ($prototype =~ m/SYSCALL_DEFINE0\s*\    1881 ##    if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
1882     if ($prototype =~ m/SYSCALL_DEFINE0/) {      1882     if ($prototype =~ m/SYSCALL_DEFINE0/) {
1883         $void = 1;                               1883         $void = 1;
1884 ##        $prototype = "long sys_$1(void)";      1884 ##        $prototype = "long sys_$1(void)";
1885     }                                            1885     }
1886                                                  1886 
1887     $prototype =~ s/SYSCALL_DEFINE.*\(/long s    1887     $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
1888     if ($prototype =~ m/long (sys_.*?),/) {      1888     if ($prototype =~ m/long (sys_.*?),/) {
1889         $prototype =~ s/,/\(/;                   1889         $prototype =~ s/,/\(/;
1890     } elsif ($void) {                            1890     } elsif ($void) {
1891         $prototype =~ s/\)/\(void\)/;            1891         $prototype =~ s/\)/\(void\)/;
1892     }                                            1892     }
1893                                                  1893 
1894     # now delete all of the odd-number commas    1894     # now delete all of the odd-number commas in $prototype
1895     # so that arg types & arg names don't hav    1895     # so that arg types & arg names don't have a comma between them
1896     my $count = 0;                               1896     my $count = 0;
1897     my $len = length($prototype);                1897     my $len = length($prototype);
1898     if ($void) {                                 1898     if ($void) {
1899         $len = 0;    # skip the for-loop         1899         $len = 0;    # skip the for-loop
1900     }                                            1900     }
1901     for (my $ix = 0; $ix < $len; $ix++) {        1901     for (my $ix = 0; $ix < $len; $ix++) {
1902         if (substr($prototype, $ix, 1) eq ','    1902         if (substr($prototype, $ix, 1) eq ',') {
1903             $count++;                            1903             $count++;
1904             if ($count % 2 == 1) {               1904             if ($count % 2 == 1) {
1905                 substr($prototype, $ix, 1) =     1905                 substr($prototype, $ix, 1) = ' ';
1906             }                                    1906             }
1907         }                                        1907         }
1908     }                                            1908     }
1909 }                                                1909 }
1910                                                  1910 
1911 sub process_proto_function($$) {                 1911 sub process_proto_function($$) {
1912     my $x = shift;                               1912     my $x = shift;
1913     my $file = shift;                            1913     my $file = shift;
1914                                                  1914 
1915     $x =~ s@\/\/.*$@@gos; # strip C99-style c    1915     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1916                                                  1916 
1917     if ($x =~ /^#/ && $x !~ /^#\s*define/) {     1917     if ($x =~ /^#/ && $x !~ /^#\s*define/) {
1918         # do nothing                             1918         # do nothing
1919     } elsif ($x =~ /([^\{]*)/) {                 1919     } elsif ($x =~ /([^\{]*)/) {
1920         $prototype .= $1;                        1920         $prototype .= $1;
1921     }                                            1921     }
1922                                                  1922 
1923     if (($x =~ /\{/) || ($x =~ /\#\s*define/)    1923     if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
1924         $prototype =~ s@/\*.*?\*/@@gos;          1924         $prototype =~ s@/\*.*?\*/@@gos;        # strip comments.
1925         $prototype =~ s@[\r\n]+@ @gos; # stri    1925         $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1926         $prototype =~ s@^\s+@@gos; # strip le    1926         $prototype =~ s@^\s+@@gos; # strip leading spaces
1927                                                  1927 
1928         # Handle prototypes for function poin    1928         # Handle prototypes for function pointers like:
1929         # int (*pcs_config)(struct foo)          1929         # int (*pcs_config)(struct foo)
1930         $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)    1930         $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
1931                                                  1931 
1932         if ($prototype =~ /SYSCALL_DEFINE/) {    1932         if ($prototype =~ /SYSCALL_DEFINE/) {
1933             syscall_munge();                     1933             syscall_munge();
1934         }                                        1934         }
1935         if ($prototype =~ /TRACE_EVENT/ || $p    1935         if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
1936             $prototype =~ /DEFINE_SINGLE_EVEN    1936             $prototype =~ /DEFINE_SINGLE_EVENT/)
1937         {                                        1937         {
1938             tracepoint_munge($file);             1938             tracepoint_munge($file);
1939         }                                        1939         }
1940         dump_function($prototype, $file);        1940         dump_function($prototype, $file);
1941         reset_state();                           1941         reset_state();
1942     }                                            1942     }
1943 }                                                1943 }
1944                                                  1944 
1945 sub process_proto_type($$) {                     1945 sub process_proto_type($$) {
1946     my $x = shift;                               1946     my $x = shift;
1947     my $file = shift;                            1947     my $file = shift;
1948                                                  1948 
1949     $x =~ s@[\r\n]+@ @gos; # strip newlines/c    1949     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1950     $x =~ s@^\s+@@gos; # strip leading spaces    1950     $x =~ s@^\s+@@gos; # strip leading spaces
1951     $x =~ s@\s+$@@gos; # strip trailing space    1951     $x =~ s@\s+$@@gos; # strip trailing spaces
1952     $x =~ s@\/\/.*$@@gos; # strip C99-style c    1952     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1953                                                  1953 
1954     if ($x =~ /^#/) {                            1954     if ($x =~ /^#/) {
1955         # To distinguish preprocessor directi    1955         # To distinguish preprocessor directive from regular declaration later.
1956         $x .= ";";                               1956         $x .= ";";
1957     }                                            1957     }
1958                                                  1958 
1959     while (1) {                                  1959     while (1) {
1960         if ( $x =~ /([^\{\};]*)([\{\};])(.*)/    1960         if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
1961             if( length $prototype ) {            1961             if( length $prototype ) {
1962                 $prototype .= " "                1962                 $prototype .= " "
1963             }                                    1963             }
1964             $prototype .= $1 . $2;               1964             $prototype .= $1 . $2;
1965             ($2 eq '{') && $brcount++;           1965             ($2 eq '{') && $brcount++;
1966             ($2 eq '}') && $brcount--;           1966             ($2 eq '}') && $brcount--;
1967             if (($2 eq ';') && ($brcount == 0    1967             if (($2 eq ';') && ($brcount == 0)) {
1968                 dump_declaration($prototype,     1968                 dump_declaration($prototype, $file);
1969                 reset_state();                   1969                 reset_state();
1970                 last;                            1970                 last;
1971             }                                    1971             }
1972             $x = $3;                             1972             $x = $3;
1973         } else {                                 1973         } else {
1974             $prototype .= $x;                    1974             $prototype .= $x;
1975             last;                                1975             last;
1976         }                                        1976         }
1977     }                                            1977     }
1978 }                                                1978 }
1979                                                  1979 
1980                                                  1980 
1981 sub map_filename($) {                            1981 sub map_filename($) {
1982     my $file;                                    1982     my $file;
1983     my ($orig_file) = @_;                        1983     my ($orig_file) = @_;
1984                                                  1984 
1985     if (defined($ENV{'SRCTREE'})) {              1985     if (defined($ENV{'SRCTREE'})) {
1986         $file = "$ENV{'SRCTREE'}" . "/" . $or    1986         $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
1987     } else {                                     1987     } else {
1988         $file = $orig_file;                      1988         $file = $orig_file;
1989     }                                            1989     }
1990                                                  1990 
1991     if (defined($source_map{$file})) {           1991     if (defined($source_map{$file})) {
1992         $file = $source_map{$file};              1992         $file = $source_map{$file};
1993     }                                            1993     }
1994                                                  1994 
1995     return $file;                                1995     return $file;
1996 }                                                1996 }
1997                                                  1997 
1998 sub process_export_file($) {                     1998 sub process_export_file($) {
1999     my ($orig_file) = @_;                        1999     my ($orig_file) = @_;
2000     my $file = map_filename($orig_file);         2000     my $file = map_filename($orig_file);
2001                                                  2001 
2002     if (!open(IN,"<$file")) {                    2002     if (!open(IN,"<$file")) {
2003         print STDERR "Error: Cannot open file    2003         print STDERR "Error: Cannot open file $file\n";
2004         ++$errors;                               2004         ++$errors;
2005         return;                                  2005         return;
2006     }                                            2006     }
2007                                                  2007 
2008     while (<IN>) {                               2008     while (<IN>) {
2009         if (/$export_symbol/) {                  2009         if (/$export_symbol/) {
2010             next if (defined($nosymbol_table{    2010             next if (defined($nosymbol_table{$2}));
2011             $function_table{$2} = 1;             2011             $function_table{$2} = 1;
2012         }                                        2012         }
2013         if (/$export_symbol_ns/) {               2013         if (/$export_symbol_ns/) {
2014             next if (defined($nosymbol_table{    2014             next if (defined($nosymbol_table{$2}));
2015             $function_table{$2} = 1;             2015             $function_table{$2} = 1;
2016         }                                        2016         }
2017     }                                            2017     }
2018                                                  2018 
2019     close(IN);                                   2019     close(IN);
2020 }                                                2020 }
2021                                                  2021 
2022 #                                                2022 #
2023 # Parsers for the various processing states.     2023 # Parsers for the various processing states.
2024 #                                                2024 #
2025 # STATE_NORMAL: looking for the /** to begin     2025 # STATE_NORMAL: looking for the /** to begin everything.
2026 #                                                2026 #
2027 sub process_normal() {                           2027 sub process_normal() {
2028     if (/$doc_start/o) {                         2028     if (/$doc_start/o) {
2029         $state = STATE_NAME;        # next li    2029         $state = STATE_NAME;        # next line is always the function name
2030         $in_doc_sect = 0;                        2030         $in_doc_sect = 0;
2031         $declaration_start_line = $. + 1;        2031         $declaration_start_line = $. + 1;
2032     }                                            2032     }
2033 }                                                2033 }
2034                                                  2034 
2035 #                                                2035 #
2036 # STATE_NAME: Looking for the "name - descrip    2036 # STATE_NAME: Looking for the "name - description" line
2037 #                                                2037 #
2038 sub process_name($$) {                           2038 sub process_name($$) {
2039     my $file = shift;                            2039     my $file = shift;
2040     my $descr;                                   2040     my $descr;
2041                                                  2041 
2042     if (/$doc_block/o) {                         2042     if (/$doc_block/o) {
2043         $state = STATE_DOCBLOCK;                 2043         $state = STATE_DOCBLOCK;
2044         $contents = "";                          2044         $contents = "";
2045         $new_start_line = $.;                    2045         $new_start_line = $.;
2046                                                  2046 
2047         if ( $1 eq "" ) {                        2047         if ( $1 eq "" ) {
2048             $section = $section_intro;           2048             $section = $section_intro;
2049         } else {                                 2049         } else {
2050             $section = $1;                       2050             $section = $1;
2051         }                                        2051         }
2052     } elsif (/$doc_decl/o) {                     2052     } elsif (/$doc_decl/o) {
2053         $identifier = $1;                        2053         $identifier = $1;
2054         my $is_kernel_comment = 0;               2054         my $is_kernel_comment = 0;
2055         my $decl_start = qr{$doc_com};           2055         my $decl_start = qr{$doc_com};
2056         # test for pointer declaration type,     2056         # test for pointer declaration type, foo * bar() - desc
2057         my $fn_type = qr{\w+\s*\*\s*};           2057         my $fn_type = qr{\w+\s*\*\s*};
2058         my $parenthesis = qr{\(\w*\)};           2058         my $parenthesis = qr{\(\w*\)};
2059         my $decl_end = qr{[-:].*};               2059         my $decl_end = qr{[-:].*};
2060         if (/^$decl_start([\w\s]+?)$parenthes    2060         if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
2061             $identifier = $1;                    2061             $identifier = $1;
2062         }                                        2062         }
2063         if ($identifier =~ m/^(struct|union|e    2063         if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
2064             $decl_type = $1;                     2064             $decl_type = $1;
2065             $identifier = $2;                    2065             $identifier = $2;
2066             $is_kernel_comment = 1;              2066             $is_kernel_comment = 1;
2067         }                                        2067         }
2068         # Look for foo() or static void foo()    2068         # Look for foo() or static void foo() - description; or misspelt
2069         # identifier                             2069         # identifier
2070         elsif (/^$decl_start$fn_type?(\w+)\s*    2070         elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
2071             /^$decl_start$fn_type?(\w+.*)$par    2071             /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) {
2072             $identifier = $1;                    2072             $identifier = $1;
2073             $decl_type = 'function';             2073             $decl_type = 'function';
2074             $identifier =~ s/^define\s+//;       2074             $identifier =~ s/^define\s+//;
2075             $is_kernel_comment = 1;              2075             $is_kernel_comment = 1;
2076         }                                        2076         }
2077         $identifier =~ s/\s+$//;                 2077         $identifier =~ s/\s+$//;
2078                                                  2078 
2079         $state = STATE_BODY;                     2079         $state = STATE_BODY;
2080         # if there's no @param blocks need to    2080         # if there's no @param blocks need to set up default section
2081         # here                                   2081         # here
2082         $contents = "";                          2082         $contents = "";
2083         $section = $section_default;             2083         $section = $section_default;
2084         $new_start_line = $. + 1;                2084         $new_start_line = $. + 1;
2085         if (/[-:](.*)/) {                        2085         if (/[-:](.*)/) {
2086             # strip leading/trailing/multiple    2086             # strip leading/trailing/multiple spaces
2087             $descr= $1;                          2087             $descr= $1;
2088             $descr =~ s/^\s*//;                  2088             $descr =~ s/^\s*//;
2089             $descr =~ s/\s*$//;                  2089             $descr =~ s/\s*$//;
2090             $descr =~ s/\s+/ /g;                 2090             $descr =~ s/\s+/ /g;
2091             $declaration_purpose = $descr;       2091             $declaration_purpose = $descr;
2092             $state = STATE_BODY_MAYBE;           2092             $state = STATE_BODY_MAYBE;
2093         } else {                                 2093         } else {
2094             $declaration_purpose = "";           2094             $declaration_purpose = "";
2095         }                                        2095         }
2096                                                  2096 
2097         if (!$is_kernel_comment) {               2097         if (!$is_kernel_comment) {
2098             emit_warning("${file}:$.", "This     2098             emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
2099             $state = STATE_NORMAL;               2099             $state = STATE_NORMAL;
2100         }                                        2100         }
2101                                                  2101 
2102         if (($declaration_purpose eq "") && $    2102         if (($declaration_purpose eq "") && $Wshort_desc) {
2103             emit_warning("${file}:$.", "missi    2103             emit_warning("${file}:$.", "missing initial short description on line:\n$_");
2104         }                                        2104         }
2105                                                  2105 
2106         if ($identifier eq "" && $decl_type n    2106         if ($identifier eq "" && $decl_type ne "enum") {
2107             emit_warning("${file}:$.", "wrong    2107             emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
2108             $state = STATE_NORMAL;               2108             $state = STATE_NORMAL;
2109         }                                        2109         }
2110                                                  2110 
2111         if ($verbose) {                          2111         if ($verbose) {
2112             print STDERR "${file}:$.: info: S    2112             print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
2113         }                                        2113         }
2114     } else {                                     2114     } else {
2115         emit_warning("${file}:$.", "Cannot un    2115         emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
2116         $state = STATE_NORMAL;                   2116         $state = STATE_NORMAL;
2117     }                                            2117     }
2118 }                                                2118 }
2119                                                  2119 
2120                                                  2120 
2121 #                                                2121 #
2122 # STATE_BODY and STATE_BODY_MAYBE: the bulk o    2122 # STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment.
2123 #                                                2123 #
2124 sub process_body($$) {                           2124 sub process_body($$) {
2125     my $file = shift;                            2125     my $file = shift;
2126                                                  2126 
2127     if ($state == STATE_BODY_WITH_BLANK_LINE     2127     if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
2128         dump_section($file, $section, $conten    2128         dump_section($file, $section, $contents);
2129         $section = $section_default;             2129         $section = $section_default;
2130         $new_start_line = $.;                    2130         $new_start_line = $.;
2131         $contents = "";                          2131         $contents = "";
2132     }                                            2132     }
2133                                                  2133 
2134     if (/$doc_sect/i) { # case insensitive fo    2134     if (/$doc_sect/i) { # case insensitive for supported section names
2135         $in_doc_sect = 1;                        2135         $in_doc_sect = 1;
2136         $newsection = $1;                        2136         $newsection = $1;
2137         $newcontents = $2;                       2137         $newcontents = $2;
2138                                                  2138 
2139         # map the supported section names to     2139         # map the supported section names to the canonical names
2140         if ($newsection =~ m/^description$/i)    2140         if ($newsection =~ m/^description$/i) {
2141             $newsection = $section_default;      2141             $newsection = $section_default;
2142         } elsif ($newsection =~ m/^context$/i    2142         } elsif ($newsection =~ m/^context$/i) {
2143             $newsection = $section_context;      2143             $newsection = $section_context;
2144         } elsif ($newsection =~ m/^returns?$/    2144         } elsif ($newsection =~ m/^returns?$/i) {
2145             $newsection = $section_return;       2145             $newsection = $section_return;
2146         } elsif ($newsection =~ m/^\@return$/    2146         } elsif ($newsection =~ m/^\@return$/) {
2147             # special: @return is a section,     2147             # special: @return is a section, not a param description
2148             $newsection = $section_return;       2148             $newsection = $section_return;
2149         }                                        2149         }
2150                                                  2150 
2151         if (($contents ne "") && ($contents n    2151         if (($contents ne "") && ($contents ne "\n")) {
2152             if (!$in_doc_sect && $Wcontents_b    2152             if (!$in_doc_sect && $Wcontents_before_sections) {
2153                 emit_warning("${file}:$.", "c    2153                 emit_warning("${file}:$.", "contents before sections\n");
2154             }                                    2154             }
2155             dump_section($file, $section, $co    2155             dump_section($file, $section, $contents);
2156             $section = $section_default;         2156             $section = $section_default;
2157         }                                        2157         }
2158                                                  2158 
2159         $in_doc_sect = 1;                        2159         $in_doc_sect = 1;
2160         $state = STATE_BODY;                     2160         $state = STATE_BODY;
2161         $contents = $newcontents;                2161         $contents = $newcontents;
2162         $new_start_line = $.;                    2162         $new_start_line = $.;
2163         while (substr($contents, 0, 1) eq " "    2163         while (substr($contents, 0, 1) eq " ") {
2164             $contents = substr($contents, 1);    2164             $contents = substr($contents, 1);
2165         }                                        2165         }
2166         if ($contents ne "") {                   2166         if ($contents ne "") {
2167             $contents .= "\n";                   2167             $contents .= "\n";
2168         }                                        2168         }
2169         $section = $newsection;                  2169         $section = $newsection;
2170         $leading_space = undef;                  2170         $leading_space = undef;
2171     } elsif (/$doc_end/) {                       2171     } elsif (/$doc_end/) {
2172         if (($contents ne "") && ($contents n    2172         if (($contents ne "") && ($contents ne "\n")) {
2173             dump_section($file, $section, $co    2173             dump_section($file, $section, $contents);
2174             $section = $section_default;         2174             $section = $section_default;
2175             $contents = "";                      2175             $contents = "";
2176         }                                        2176         }
2177         # look for doc_com + <text> + doc_end    2177         # look for doc_com + <text> + doc_end:
2178         if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\    2178         if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
2179             emit_warning("${file}:$.", "suspi    2179             emit_warning("${file}:$.", "suspicious ending line: $_");
2180         }                                        2180         }
2181                                                  2181 
2182         $prototype = "";                         2182         $prototype = "";
2183         $state = STATE_PROTO;                    2183         $state = STATE_PROTO;
2184         $brcount = 0;                            2184         $brcount = 0;
2185         $new_start_line = $. + 1;                2185         $new_start_line = $. + 1;
2186     } elsif (/$doc_content/) {                   2186     } elsif (/$doc_content/) {
2187         if ($1 eq "") {                          2187         if ($1 eq "") {
2188             if ($section eq $section_context)    2188             if ($section eq $section_context) {
2189                 dump_section($file, $section,    2189                 dump_section($file, $section, $contents);
2190                 $section = $section_default;     2190                 $section = $section_default;
2191                 $contents = "";                  2191                 $contents = "";
2192                 $new_start_line = $.;            2192                 $new_start_line = $.;
2193                 $state = STATE_BODY;             2193                 $state = STATE_BODY;
2194             } else {                             2194             } else {
2195                 if ($section ne $section_defa    2195                 if ($section ne $section_default) {
2196                     $state = STATE_BODY_WITH_    2196                     $state = STATE_BODY_WITH_BLANK_LINE;
2197                 } else {                         2197                 } else {
2198                     $state = STATE_BODY;         2198                     $state = STATE_BODY;
2199                 }                                2199                 }
2200                 $contents .= "\n";               2200                 $contents .= "\n";
2201             }                                    2201             }
2202         } elsif ($state == STATE_BODY_MAYBE)     2202         } elsif ($state == STATE_BODY_MAYBE) {
2203             # Continued declaration purpose      2203             # Continued declaration purpose
2204             chomp($declaration_purpose);         2204             chomp($declaration_purpose);
2205             $declaration_purpose .= " " . $1;    2205             $declaration_purpose .= " " . $1;
2206             $declaration_purpose =~ s/\s+/ /g    2206             $declaration_purpose =~ s/\s+/ /g;
2207         } else {                                 2207         } else {
2208             my $cont = $1;                       2208             my $cont = $1;
2209             if ($section =~ m/^@/ || $section    2209             if ($section =~ m/^@/ || $section eq $section_context) {
2210                 if (!defined $leading_space)     2210                 if (!defined $leading_space) {
2211                     if ($cont =~ m/^(\s+)/) {    2211                     if ($cont =~ m/^(\s+)/) {
2212                         $leading_space = $1;     2212                         $leading_space = $1;
2213                     } else {                     2213                     } else {
2214                         $leading_space = "";     2214                         $leading_space = "";
2215                     }                            2215                     }
2216                 }                                2216                 }
2217                 $cont =~ s/^$leading_space//;    2217                 $cont =~ s/^$leading_space//;
2218             }                                    2218             }
2219             $contents .= $cont . "\n";           2219             $contents .= $cont . "\n";
2220         }                                        2220         }
2221     } else {                                     2221     } else {
2222         # i dont know - bad line?  ignore.       2222         # i dont know - bad line?  ignore.
2223         emit_warning("${file}:$.", "bad line:    2223         emit_warning("${file}:$.", "bad line: $_");
2224     }                                            2224     }
2225 }                                                2225 }
2226                                                  2226 
2227                                                  2227 
2228 #                                                2228 #
2229 # STATE_PROTO: reading a function/whatever pr    2229 # STATE_PROTO: reading a function/whatever prototype.
2230 #                                                2230 #
2231 sub process_proto($$) {                          2231 sub process_proto($$) {
2232     my $file = shift;                            2232     my $file = shift;
2233                                                  2233 
2234     if (/$doc_inline_oneline/) {                 2234     if (/$doc_inline_oneline/) {
2235         $section = $1;                           2235         $section = $1;
2236         $contents = $2;                          2236         $contents = $2;
2237         if ($contents ne "") {                   2237         if ($contents ne "") {
2238             $contents .= "\n";                   2238             $contents .= "\n";
2239             dump_section($file, $section, $co    2239             dump_section($file, $section, $contents);
2240             $section = $section_default;         2240             $section = $section_default;
2241             $contents = "";                      2241             $contents = "";
2242         }                                        2242         }
2243     } elsif (/$doc_inline_start/) {              2243     } elsif (/$doc_inline_start/) {
2244         $state = STATE_INLINE;                   2244         $state = STATE_INLINE;
2245         $inline_doc_state = STATE_INLINE_NAME    2245         $inline_doc_state = STATE_INLINE_NAME;
2246     } elsif ($decl_type eq 'function') {         2246     } elsif ($decl_type eq 'function') {
2247         process_proto_function($_, $file);       2247         process_proto_function($_, $file);
2248     } else {                                     2248     } else {
2249         process_proto_type($_, $file);           2249         process_proto_type($_, $file);
2250     }                                            2250     }
2251 }                                                2251 }
2252                                                  2252 
2253 #                                                2253 #
2254 # STATE_DOCBLOCK: within a DOC: block.           2254 # STATE_DOCBLOCK: within a DOC: block.
2255 #                                                2255 #
2256 sub process_docblock($$) {                       2256 sub process_docblock($$) {
2257     my $file = shift;                            2257     my $file = shift;
2258                                                  2258 
2259     if (/$doc_end/) {                            2259     if (/$doc_end/) {
2260         dump_doc_section($file, $section, $co    2260         dump_doc_section($file, $section, $contents);
2261         $section = $section_default;             2261         $section = $section_default;
2262         $contents = "";                          2262         $contents = "";
2263         $function = "";                          2263         $function = "";
2264         %parameterdescs = ();                    2264         %parameterdescs = ();
2265         %parametertypes = ();                    2265         %parametertypes = ();
2266         @parameterlist = ();                     2266         @parameterlist = ();
2267         %sections = ();                          2267         %sections = ();
2268         @sectionlist = ();                       2268         @sectionlist = ();
2269         $prototype = "";                         2269         $prototype = "";
2270         $state = STATE_NORMAL;                   2270         $state = STATE_NORMAL;
2271     } elsif (/$doc_content/) {                   2271     } elsif (/$doc_content/) {
2272         if ( $1 eq "" )        {                 2272         if ( $1 eq "" )        {
2273             $contents .= $blankline;             2273             $contents .= $blankline;
2274         } else {                                 2274         } else {
2275             $contents .= $1 . "\n";              2275             $contents .= $1 . "\n";
2276         }                                        2276         }
2277     }                                            2277     }
2278 }                                                2278 }
2279                                                  2279 
2280 #                                                2280 #
2281 # STATE_INLINE: docbook comments within a pro    2281 # STATE_INLINE: docbook comments within a prototype.
2282 #                                                2282 #
2283 sub process_inline($$) {                         2283 sub process_inline($$) {
2284     my $file = shift;                            2284     my $file = shift;
2285                                                  2285 
2286     # First line (state 1) needs to be a @par    2286     # First line (state 1) needs to be a @parameter
2287     if ($inline_doc_state == STATE_INLINE_NAM    2287     if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
2288         $section = $1;                           2288         $section = $1;
2289         $contents = $2;                          2289         $contents = $2;
2290         $new_start_line = $.;                    2290         $new_start_line = $.;
2291         if ($contents ne "") {                   2291         if ($contents ne "") {
2292             while (substr($contents, 0, 1) eq    2292             while (substr($contents, 0, 1) eq " ") {
2293                 $contents = substr($contents,    2293                 $contents = substr($contents, 1);
2294             }                                    2294             }
2295             $contents .= "\n";                   2295             $contents .= "\n";
2296         }                                        2296         }
2297         $inline_doc_state = STATE_INLINE_TEXT    2297         $inline_doc_state = STATE_INLINE_TEXT;
2298         # Documentation block end */             2298         # Documentation block end */
2299     } elsif (/$doc_inline_end/) {                2299     } elsif (/$doc_inline_end/) {
2300         if (($contents ne "") && ($contents n    2300         if (($contents ne "") && ($contents ne "\n")) {
2301             dump_section($file, $section, $co    2301             dump_section($file, $section, $contents);
2302             $section = $section_default;         2302             $section = $section_default;
2303             $contents = "";                      2303             $contents = "";
2304         }                                        2304         }
2305         $state = STATE_PROTO;                    2305         $state = STATE_PROTO;
2306         $inline_doc_state = STATE_INLINE_NA;     2306         $inline_doc_state = STATE_INLINE_NA;
2307         # Regular text                           2307         # Regular text
2308     } elsif (/$doc_content/) {                   2308     } elsif (/$doc_content/) {
2309         if ($inline_doc_state == STATE_INLINE    2309         if ($inline_doc_state == STATE_INLINE_TEXT) {
2310             $contents .= $1 . "\n";              2310             $contents .= $1 . "\n";
2311             # nuke leading blank lines           2311             # nuke leading blank lines
2312             if ($contents =~ /^\s*$/) {          2312             if ($contents =~ /^\s*$/) {
2313                 $contents = "";                  2313                 $contents = "";
2314             }                                    2314             }
2315         } elsif ($inline_doc_state == STATE_I    2315         } elsif ($inline_doc_state == STATE_INLINE_NAME) {
2316             $inline_doc_state = STATE_INLINE_    2316             $inline_doc_state = STATE_INLINE_ERROR;
2317             emit_warning("${file}:$.", "Incor    2317             emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
2318         }                                        2318         }
2319     }                                            2319     }
2320 }                                                2320 }
2321                                                  2321 
2322                                                  2322 
2323 sub process_file($) {                            2323 sub process_file($) {
2324     my $file;                                    2324     my $file;
2325     my $initial_section_counter = $section_co    2325     my $initial_section_counter = $section_counter;
2326     my ($orig_file) = @_;                        2326     my ($orig_file) = @_;
2327                                                  2327 
2328     $file = map_filename($orig_file);            2328     $file = map_filename($orig_file);
2329                                                  2329 
2330     if (!open(IN_FILE,"<$file")) {               2330     if (!open(IN_FILE,"<$file")) {
2331         print STDERR "Error: Cannot open file    2331         print STDERR "Error: Cannot open file $file\n";
2332         ++$errors;                               2332         ++$errors;
2333         return;                                  2333         return;
2334     }                                            2334     }
2335                                                  2335 
2336     $. = 1;                                      2336     $. = 1;
2337                                                  2337 
2338     $section_counter = 0;                        2338     $section_counter = 0;
2339     while (<IN_FILE>) {                          2339     while (<IN_FILE>) {
2340         while (!/^ \*/ && s/\\\s*$//) {          2340         while (!/^ \*/ && s/\\\s*$//) {
2341             $_ .= <IN_FILE>;                     2341             $_ .= <IN_FILE>;
2342         }                                        2342         }
2343         # Replace tabs by spaces                 2343         # Replace tabs by spaces
2344         while ($_ =~ s/\t+/' ' x (length($&)     2344         while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
2345         # Hand this line to the appropriate s    2345         # Hand this line to the appropriate state handler
2346         if ($state == STATE_NORMAL) {            2346         if ($state == STATE_NORMAL) {
2347             process_normal();                    2347             process_normal();
2348         } elsif ($state == STATE_NAME) {         2348         } elsif ($state == STATE_NAME) {
2349             process_name($file, $_);             2349             process_name($file, $_);
2350         } elsif ($state == STATE_BODY || $sta    2350         } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
2351                  $state == STATE_BODY_WITH_BL    2351                  $state == STATE_BODY_WITH_BLANK_LINE) {
2352             process_body($file, $_);             2352             process_body($file, $_);
2353         } elsif ($state == STATE_INLINE) { #     2353         } elsif ($state == STATE_INLINE) { # scanning for inline parameters
2354             process_inline($file, $_);           2354             process_inline($file, $_);
2355         } elsif ($state == STATE_PROTO) {        2355         } elsif ($state == STATE_PROTO) {
2356             process_proto($file, $_);            2356             process_proto($file, $_);
2357         } elsif ($state == STATE_DOCBLOCK) {     2357         } elsif ($state == STATE_DOCBLOCK) {
2358             process_docblock($file, $_);         2358             process_docblock($file, $_);
2359         }                                        2359         }
2360     }                                            2360     }
2361                                                  2361 
2362     # Make sure we got something interesting.    2362     # Make sure we got something interesting.
2363     if ($initial_section_counter == $section_    2363     if ($initial_section_counter == $section_counter && $
2364         output_mode ne "none") {                 2364         output_mode ne "none") {
2365         if ($output_selection == OUTPUT_INCLU    2365         if ($output_selection == OUTPUT_INCLUDE) {
2366             emit_warning("${file}:1", "'$_' n    2366             emit_warning("${file}:1", "'$_' not found\n")
2367                 for keys %function_table;        2367                 for keys %function_table;
2368         } else {                                 2368         } else {
2369             emit_warning("${file}:1", "no str    2369             emit_warning("${file}:1", "no structured comments found\n");
2370         }                                        2370         }
2371     }                                            2371     }
2372     close IN_FILE;                               2372     close IN_FILE;
2373 }                                                2373 }
2374                                                  2374 
2375                                                  2375 
2376 if ($output_mode eq "rst") {                     2376 if ($output_mode eq "rst") {
2377     get_sphinx_version() if (!$sphinx_major);    2377     get_sphinx_version() if (!$sphinx_major);
2378 }                                                2378 }
2379                                                  2379 
2380 $kernelversion = get_kernel_version();           2380 $kernelversion = get_kernel_version();
2381                                                  2381 
2382 # generate a sequence of code that will splic    2382 # generate a sequence of code that will splice in highlighting information
2383 # using the s// operator.                        2383 # using the s// operator.
2384 for (my $k = 0; $k < @highlights; $k++) {        2384 for (my $k = 0; $k < @highlights; $k++) {
2385     my $pattern = $highlights[$k][0];            2385     my $pattern = $highlights[$k][0];
2386     my $result = $highlights[$k][1];             2386     my $result = $highlights[$k][1];
2387 #   print STDERR "scanning pattern:$pattern,     2387 #   print STDERR "scanning pattern:$pattern, highlight:($result)\n";
2388     $dohighlight .=  "\$contents =~ s:$patter    2388     $dohighlight .=  "\$contents =~ s:$pattern:$result:gs;\n";
2389 }                                                2389 }
2390                                                  2390 
2391 # Read the file that maps relative names to a    2391 # Read the file that maps relative names to absolute names for
2392 # separate source and object directories and     2392 # separate source and object directories and for shadow trees.
2393 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {    2393 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
2394     my ($relname, $absname);                     2394     my ($relname, $absname);
2395     while(<SOURCE_MAP>) {                        2395     while(<SOURCE_MAP>) {
2396         chop();                                  2396         chop();
2397         ($relname, $absname) = (split())[0..1    2397         ($relname, $absname) = (split())[0..1];
2398         $relname =~ s:^/+::;                     2398         $relname =~ s:^/+::;
2399         $source_map{$relname} = $absname;        2399         $source_map{$relname} = $absname;
2400     }                                            2400     }
2401     close(SOURCE_MAP);                           2401     close(SOURCE_MAP);
2402 }                                                2402 }
2403                                                  2403 
2404 if ($output_selection == OUTPUT_EXPORTED ||      2404 if ($output_selection == OUTPUT_EXPORTED ||
2405     $output_selection == OUTPUT_INTERNAL) {      2405     $output_selection == OUTPUT_INTERNAL) {
2406                                                  2406 
2407     push(@export_file_list, @ARGV);              2407     push(@export_file_list, @ARGV);
2408                                                  2408 
2409     foreach (@export_file_list) {                2409     foreach (@export_file_list) {
2410         chomp;                                   2410         chomp;
2411         process_export_file($_);                 2411         process_export_file($_);
2412     }                                            2412     }
2413 }                                                2413 }
2414                                                  2414 
2415 foreach (@ARGV) {                                2415 foreach (@ARGV) {
2416     chomp;                                       2416     chomp;
2417     process_file($_);                            2417     process_file($_);
2418 }                                                2418 }
2419 if ($verbose && $errors) {                       2419 if ($verbose && $errors) {
2420     print STDERR "$errors errors\n";             2420     print STDERR "$errors errors\n";
2421 }                                                2421 }
2422 if ($verbose && $warnings) {                     2422 if ($verbose && $warnings) {
2423     print STDERR "$warnings warnings\n";         2423     print STDERR "$warnings warnings\n";
2424 }                                                2424 }
2425                                                  2425 
2426 if ($Werror && $warnings) {                      2426 if ($Werror && $warnings) {
2427     print STDERR "$warnings warnings as Error    2427     print STDERR "$warnings warnings as Errors\n";
2428     exit($warnings);                             2428     exit($warnings);
2429 } else {                                         2429 } else {
2430     exit($output_mode eq "none" ? 0 : $errors    2430     exit($output_mode eq "none" ? 0 : $errors)
2431 }                                                2431 }
2432                                                  2432 
2433 __END__                                          2433 __END__
2434                                                  2434 
2435 =head1 OPTIONS                                   2435 =head1 OPTIONS
2436                                                  2436 
2437 =head2 Output format selection (mutually excl    2437 =head2 Output format selection (mutually exclusive):
2438                                                  2438 
2439 =over 8                                          2439 =over 8
2440                                                  2440 
2441 =item -man                                       2441 =item -man
2442                                                  2442 
2443 Output troff manual page format.                 2443 Output troff manual page format.
2444                                                  2444 
2445 =item -rst                                       2445 =item -rst
2446                                                  2446 
2447 Output reStructuredText format. This is the d    2447 Output reStructuredText format. This is the default.
2448                                                  2448 
2449 =item -none                                      2449 =item -none
2450                                                  2450 
2451 Do not output documentation, only warnings.      2451 Do not output documentation, only warnings.
2452                                                  2452 
2453 =back                                            2453 =back
2454                                                  2454 
2455 =head2 Output format modifiers                   2455 =head2 Output format modifiers
2456                                                  2456 
2457 =head3 reStructuredText only                     2457 =head3 reStructuredText only
2458                                                  2458 
2459 =over 8                                          2459 =over 8
2460                                                  2460 
2461 =item -sphinx-version VERSION                    2461 =item -sphinx-version VERSION
2462                                                  2462 
2463 Use the ReST C domain dialect compatible with    2463 Use the ReST C domain dialect compatible with a specific Sphinx Version.
2464                                                  2464 
2465 If not specified, kernel-doc will auto-detect    2465 If not specified, kernel-doc will auto-detect using the sphinx-build version
2466 found on PATH.                                   2466 found on PATH.
2467                                                  2467 
2468 =back                                            2468 =back
2469                                                  2469 
2470 =head2 Output selection (mutually exclusive):    2470 =head2 Output selection (mutually exclusive):
2471                                                  2471 
2472 =over 8                                          2472 =over 8
2473                                                  2473 
2474 =item -export                                    2474 =item -export
2475                                                  2475 
2476 Only output documentation for the symbols tha    2476 Only output documentation for the symbols that have been exported using
2477 EXPORT_SYMBOL() and related macros in any inp    2477 EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
2478                                                  2478 
2479 =item -internal                                  2479 =item -internal
2480                                                  2480 
2481 Only output documentation for the symbols tha    2481 Only output documentation for the symbols that have NOT been exported using
2482 EXPORT_SYMBOL() and related macros in any inp    2482 EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
2483                                                  2483 
2484 =item -function NAME                             2484 =item -function NAME
2485                                                  2485 
2486 Only output documentation for the given funct    2486 Only output documentation for the given function or DOC: section title.
2487 All other functions and DOC: sections are ign    2487 All other functions and DOC: sections are ignored.
2488                                                  2488 
2489 May be specified multiple times.                 2489 May be specified multiple times.
2490                                                  2490 
2491 =item -nosymbol NAME                             2491 =item -nosymbol NAME
2492                                                  2492 
2493 Exclude the specified symbol from the output     2493 Exclude the specified symbol from the output documentation.
2494                                                  2494 
2495 May be specified multiple times.                 2495 May be specified multiple times.
2496                                                  2496 
2497 =back                                            2497 =back
2498                                                  2498 
2499 =head2 Output selection modifiers:               2499 =head2 Output selection modifiers:
2500                                                  2500 
2501 =over 8                                          2501 =over 8
2502                                                  2502 
2503 =item -no-doc-sections                           2503 =item -no-doc-sections
2504                                                  2504 
2505 Do not output DOC: sections.                     2505 Do not output DOC: sections.
2506                                                  2506 
2507 =item -export-file FILE                          2507 =item -export-file FILE
2508                                                  2508 
2509 Specify an additional FILE in which to look f    2509 Specify an additional FILE in which to look for EXPORT_SYMBOL information.
2510                                                  2510 
2511 To be used with -export or -internal.            2511 To be used with -export or -internal.
2512                                                  2512 
2513 May be specified multiple times.                 2513 May be specified multiple times.
2514                                                  2514 
2515 =back                                            2515 =back
2516                                                  2516 
2517 =head3 reStructuredText only                     2517 =head3 reStructuredText only
2518                                                  2518 
2519 =over 8                                          2519 =over 8
2520                                                  2520 
2521 =item -enable-lineno                             2521 =item -enable-lineno
2522                                                  2522 
2523 Enable output of .. LINENO lines.                2523 Enable output of .. LINENO lines.
2524                                                  2524 
2525 =back                                            2525 =back
2526                                                  2526 
2527 =head2 Other parameters:                         2527 =head2 Other parameters:
2528                                                  2528 
2529 =over 8                                          2529 =over 8
2530                                                  2530 
2531 =item -h, -help                                  2531 =item -h, -help
2532                                                  2532 
2533 Print this help.                                 2533 Print this help.
2534                                                  2534 
2535 =item -v                                         2535 =item -v
2536                                                  2536 
2537 Verbose output, more warnings and other infor    2537 Verbose output, more warnings and other information.
2538                                                  2538 
2539 =item -Werror                                    2539 =item -Werror
2540                                                  2540 
2541 Treat warnings as errors.                        2541 Treat warnings as errors.
2542                                                  2542 
2543 =back                                            2543 =back
2544                                                  2544 
2545 =cut                                             2545 =cut
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php