Commit 146ce6474d0355a45fbd289981ecc8d2d15ff993

Authored by Heinrich Schuchardt
Committed by Tom Rini
1 parent b7ab098207

scripts/kernel-doc: fix parsing of function pointers

kernel-doc fails to parse function definitions like the one below

efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
			      void (EFIAPI *notify_function) (
					struct efi_event *event,
					void *context),
			      void *notify_context, efi_guid_t *group,
			      struct efi_event **event)
{

due to the "EFIAPI" attribute preceding the function name.

cf. https://lkml.org/lkml/2018/9/3/1185

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

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 3
4 use warnings; 4 use warnings;
5 use strict; 5 use strict;
6 6
7 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ## 7 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
8 ## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## 8 ## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
9 ## Copyright (C) 2001 Simon Huggins ## 9 ## Copyright (C) 2001 Simon Huggins ##
10 ## Copyright (C) 2005-2012 Randy Dunlap ## 10 ## Copyright (C) 2005-2012 Randy Dunlap ##
11 ## Copyright (C) 2012 Dan Luedtke ## 11 ## Copyright (C) 2012 Dan Luedtke ##
12 ## ## 12 ## ##
13 ## #define enhancements by Armin Kuster <akuster@mvista.com> ## 13 ## #define enhancements by Armin Kuster <akuster@mvista.com> ##
14 ## Copyright (c) 2000 MontaVista Software, Inc. ## 14 ## Copyright (c) 2000 MontaVista Software, Inc. ##
15 ## ## 15 ## ##
16 ## This software falls under the GNU General Public License. ## 16 ## This software falls under the GNU General Public License. ##
17 ## Please read the COPYING file for more information ## 17 ## Please read the COPYING file for more information ##
18 18
19 # 18/01/2001 - Cleanups 19 # 18/01/2001 - Cleanups
20 # Functions prototyped as foo(void) same as foo() 20 # Functions prototyped as foo(void) same as foo()
21 # Stop eval'ing where we don't need to. 21 # Stop eval'ing where we don't need to.
22 # -- huggie@earth.li 22 # -- huggie@earth.li
23 23
24 # 27/06/2001 - Allowed whitespace after initial "/**" and 24 # 27/06/2001 - Allowed whitespace after initial "/**" and
25 # allowed comments before function declarations. 25 # allowed comments before function declarations.
26 # -- Christian Kreibich <ck@whoop.org> 26 # -- Christian Kreibich <ck@whoop.org>
27 27
28 # Still to do: 28 # Still to do:
29 # - add perldoc documentation 29 # - add perldoc documentation
30 # - Look more closely at some of the scarier bits :) 30 # - Look more closely at some of the scarier bits :)
31 31
32 # 26/05/2001 - Support for separate source and object trees. 32 # 26/05/2001 - Support for separate source and object trees.
33 # Return error code. 33 # Return error code.
34 # Keith Owens <kaos@ocs.com.au> 34 # Keith Owens <kaos@ocs.com.au>
35 35
36 # 23/09/2001 - Added support for typedefs, structs, enums and unions 36 # 23/09/2001 - Added support for typedefs, structs, enums and unions
37 # Support for Context section; can be terminated using empty line 37 # Support for Context section; can be terminated using empty line
38 # Small fixes (like spaces vs. \s in regex) 38 # Small fixes (like spaces vs. \s in regex)
39 # -- Tim Jansen <tim@tjansen.de> 39 # -- Tim Jansen <tim@tjansen.de>
40 40
41 # 25/07/2012 - Added support for HTML5 41 # 25/07/2012 - Added support for HTML5
42 # -- Dan Luedtke <mail@danrl.de> 42 # -- Dan Luedtke <mail@danrl.de>
43 43
44 sub usage { 44 sub usage {
45 my $message = <<"EOF"; 45 my $message = <<"EOF";
46 Usage: $0 [OPTION ...] FILE ... 46 Usage: $0 [OPTION ...] FILE ...
47 47
48 Read C language source or header FILEs, extract embedded documentation comments, 48 Read C language source or header FILEs, extract embedded documentation comments,
49 and print formatted documentation to standard output. 49 and print formatted documentation to standard output.
50 50
51 The documentation comments are identified by "/**" opening comment mark. See 51 The documentation comments are identified by "/**" opening comment mark. See
52 Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax. 52 Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
53 53
54 Output format selection (mutually exclusive): 54 Output format selection (mutually exclusive):
55 -man Output troff manual page format. This is the default. 55 -man Output troff manual page format. This is the default.
56 -rst Output reStructuredText format. 56 -rst Output reStructuredText format.
57 -none Do not output documentation, only warnings. 57 -none Do not output documentation, only warnings.
58 58
59 Output selection (mutually exclusive): 59 Output selection (mutually exclusive):
60 -export Only output documentation for symbols that have been 60 -export Only output documentation for symbols that have been
61 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() 61 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
62 in any input FILE or -export-file FILE. 62 in any input FILE or -export-file FILE.
63 -internal Only output documentation for symbols that have NOT been 63 -internal Only output documentation for symbols that have NOT been
64 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() 64 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
65 in any input FILE or -export-file FILE. 65 in any input FILE or -export-file FILE.
66 -function NAME Only output documentation for the given function(s) 66 -function NAME Only output documentation for the given function(s)
67 or DOC: section title(s). All other functions and DOC: 67 or DOC: section title(s). All other functions and DOC:
68 sections are ignored. May be specified multiple times. 68 sections are ignored. May be specified multiple times.
69 -nofunction NAME Do NOT output documentation for the given function(s); 69 -nofunction NAME Do NOT output documentation for the given function(s);
70 only output documentation for the other functions and 70 only output documentation for the other functions and
71 DOC: sections. May be specified multiple times. 71 DOC: sections. May be specified multiple times.
72 72
73 Output selection modifiers: 73 Output selection modifiers:
74 -no-doc-sections Do not output DOC: sections. 74 -no-doc-sections Do not output DOC: sections.
75 -enable-lineno Enable output of #define LINENO lines. Only works with 75 -enable-lineno Enable output of #define LINENO lines. Only works with
76 reStructuredText format. 76 reStructuredText format.
77 -export-file FILE Specify an additional FILE in which to look for 77 -export-file FILE Specify an additional FILE in which to look for
78 EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with 78 EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with
79 -export or -internal. May be specified multiple times. 79 -export or -internal. May be specified multiple times.
80 80
81 Other parameters: 81 Other parameters:
82 -v Verbose output, more warnings and other information. 82 -v Verbose output, more warnings and other information.
83 -h Print this help. 83 -h Print this help.
84 84
85 EOF 85 EOF
86 print $message; 86 print $message;
87 exit 1; 87 exit 1;
88 } 88 }
89 89
90 # 90 #
91 # format of comments. 91 # format of comments.
92 # In the following table, (...)? signifies optional structure. 92 # In the following table, (...)? signifies optional structure.
93 # (...)* signifies 0 or more structure elements 93 # (...)* signifies 0 or more structure elements
94 # /** 94 # /**
95 # * function_name(:)? (- short description)? 95 # * function_name(:)? (- short description)?
96 # (* @parameterx: (description of parameter x)?)* 96 # (* @parameterx: (description of parameter x)?)*
97 # (* a blank line)? 97 # (* a blank line)?
98 # * (Description:)? (Description of function)? 98 # * (Description:)? (Description of function)?
99 # * (section header: (section description)? )* 99 # * (section header: (section description)? )*
100 # (*)?*/ 100 # (*)?*/
101 # 101 #
102 # So .. the trivial example would be: 102 # So .. the trivial example would be:
103 # 103 #
104 # /** 104 # /**
105 # * my_function 105 # * my_function
106 # */ 106 # */
107 # 107 #
108 # If the Description: header tag is omitted, then there must be a blank line 108 # If the Description: header tag is omitted, then there must be a blank line
109 # after the last parameter specification. 109 # after the last parameter specification.
110 # e.g. 110 # e.g.
111 # /** 111 # /**
112 # * my_function - does my stuff 112 # * my_function - does my stuff
113 # * @my_arg: its mine damnit 113 # * @my_arg: its mine damnit
114 # * 114 # *
115 # * Does my stuff explained. 115 # * Does my stuff explained.
116 # */ 116 # */
117 # 117 #
118 # or, could also use: 118 # or, could also use:
119 # /** 119 # /**
120 # * my_function - does my stuff 120 # * my_function - does my stuff
121 # * @my_arg: its mine damnit 121 # * @my_arg: its mine damnit
122 # * Description: Does my stuff explained. 122 # * Description: Does my stuff explained.
123 # */ 123 # */
124 # etc. 124 # etc.
125 # 125 #
126 # Besides functions you can also write documentation for structs, unions, 126 # Besides functions you can also write documentation for structs, unions,
127 # enums and typedefs. Instead of the function name you must write the name 127 # enums and typedefs. Instead of the function name you must write the name
128 # of the declaration; the struct/union/enum/typedef must always precede 128 # of the declaration; the struct/union/enum/typedef must always precede
129 # the name. Nesting of declarations is not supported. 129 # the name. Nesting of declarations is not supported.
130 # Use the argument mechanism to document members or constants. 130 # Use the argument mechanism to document members or constants.
131 # e.g. 131 # e.g.
132 # /** 132 # /**
133 # * struct my_struct - short description 133 # * struct my_struct - short description
134 # * @a: first member 134 # * @a: first member
135 # * @b: second member 135 # * @b: second member
136 # * 136 # *
137 # * Longer description 137 # * Longer description
138 # */ 138 # */
139 # struct my_struct { 139 # struct my_struct {
140 # int a; 140 # int a;
141 # int b; 141 # int b;
142 # /* private: */ 142 # /* private: */
143 # int c; 143 # int c;
144 # }; 144 # };
145 # 145 #
146 # All descriptions can be multiline, except the short function description. 146 # All descriptions can be multiline, except the short function description.
147 # 147 #
148 # For really longs structs, you can also describe arguments inside the 148 # For really longs structs, you can also describe arguments inside the
149 # body of the struct. 149 # body of the struct.
150 # eg. 150 # eg.
151 # /** 151 # /**
152 # * struct my_struct - short description 152 # * struct my_struct - short description
153 # * @a: first member 153 # * @a: first member
154 # * @b: second member 154 # * @b: second member
155 # * 155 # *
156 # * Longer description 156 # * Longer description
157 # */ 157 # */
158 # struct my_struct { 158 # struct my_struct {
159 # int a; 159 # int a;
160 # int b; 160 # int b;
161 # /** 161 # /**
162 # * @c: This is longer description of C 162 # * @c: This is longer description of C
163 # * 163 # *
164 # * You can use paragraphs to describe arguments 164 # * You can use paragraphs to describe arguments
165 # * using this method. 165 # * using this method.
166 # */ 166 # */
167 # int c; 167 # int c;
168 # }; 168 # };
169 # 169 #
170 # This should be use only for struct/enum members. 170 # This should be use only for struct/enum members.
171 # 171 #
172 # You can also add additional sections. When documenting kernel functions you 172 # You can also add additional sections. When documenting kernel functions you
173 # should document the "Context:" of the function, e.g. whether the functions 173 # should document the "Context:" of the function, e.g. whether the functions
174 # can be called form interrupts. Unlike other sections you can end it with an 174 # can be called form interrupts. Unlike other sections you can end it with an
175 # empty line. 175 # empty line.
176 # A non-void function should have a "Return:" section describing the return 176 # A non-void function should have a "Return:" section describing the return
177 # value(s). 177 # value(s).
178 # Example-sections should contain the string EXAMPLE so that they are marked 178 # Example-sections should contain the string EXAMPLE so that they are marked
179 # appropriately in DocBook. 179 # appropriately in DocBook.
180 # 180 #
181 # Example: 181 # Example:
182 # /** 182 # /**
183 # * user_function - function that can only be called in user context 183 # * user_function - function that can only be called in user context
184 # * @a: some argument 184 # * @a: some argument
185 # * Context: !in_interrupt() 185 # * Context: !in_interrupt()
186 # * 186 # *
187 # * Some description 187 # * Some description
188 # * Example: 188 # * Example:
189 # * user_function(22); 189 # * user_function(22);
190 # */ 190 # */
191 # ... 191 # ...
192 # 192 #
193 # 193 #
194 # All descriptive text is further processed, scanning for the following special 194 # All descriptive text is further processed, scanning for the following special
195 # patterns, which are highlighted appropriately. 195 # patterns, which are highlighted appropriately.
196 # 196 #
197 # 'funcname()' - function 197 # 'funcname()' - function
198 # '$ENVVAR' - environmental variable 198 # '$ENVVAR' - environmental variable
199 # '&struct_name' - name of a structure (up to two words including 'struct') 199 # '&struct_name' - name of a structure (up to two words including 'struct')
200 # '&struct_name.member' - name of a structure member 200 # '&struct_name.member' - name of a structure member
201 # '@parameter' - name of a parameter 201 # '@parameter' - name of a parameter
202 # '%CONST' - name of a constant. 202 # '%CONST' - name of a constant.
203 # '``LITERAL``' - literal string without any spaces on it. 203 # '``LITERAL``' - literal string without any spaces on it.
204 204
205 ## init lots of data 205 ## init lots of data
206 206
207 my $errors = 0; 207 my $errors = 0;
208 my $warnings = 0; 208 my $warnings = 0;
209 my $anon_struct_union = 0; 209 my $anon_struct_union = 0;
210 210
211 # match expressions used to find embedded type information 211 # match expressions used to find embedded type information
212 my $type_constant = '\b``([^\`]+)``\b'; 212 my $type_constant = '\b``([^\`]+)``\b';
213 my $type_constant2 = '\%([-_\w]+)'; 213 my $type_constant2 = '\%([-_\w]+)';
214 my $type_func = '(\w+)\(\)'; 214 my $type_func = '(\w+)\(\)';
215 my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; 215 my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
216 my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params 216 my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
217 my $type_env = '(\$\w+)'; 217 my $type_env = '(\$\w+)';
218 my $type_enum = '\&(enum\s*([_\w]+))'; 218 my $type_enum = '\&(enum\s*([_\w]+))';
219 my $type_struct = '\&(struct\s*([_\w]+))'; 219 my $type_struct = '\&(struct\s*([_\w]+))';
220 my $type_typedef = '\&(typedef\s*([_\w]+))'; 220 my $type_typedef = '\&(typedef\s*([_\w]+))';
221 my $type_union = '\&(union\s*([_\w]+))'; 221 my $type_union = '\&(union\s*([_\w]+))';
222 my $type_member = '\&([_\w]+)(\.|->)([_\w]+)'; 222 my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
223 my $type_fallback = '\&([_\w]+)'; 223 my $type_fallback = '\&([_\w]+)';
224 my $type_member_func = $type_member . '\(\)'; 224 my $type_member_func = $type_member . '\(\)';
225 225
226 # Output conversion substitutions. 226 # Output conversion substitutions.
227 # One for each output format 227 # One for each output format
228 228
229 # these are pretty rough 229 # these are pretty rough
230 my @highlights_man = ( 230 my @highlights_man = (
231 [$type_constant, "\$1"], 231 [$type_constant, "\$1"],
232 [$type_constant2, "\$1"], 232 [$type_constant2, "\$1"],
233 [$type_func, "\\\\fB\$1\\\\fP"], 233 [$type_func, "\\\\fB\$1\\\\fP"],
234 [$type_enum, "\\\\fI\$1\\\\fP"], 234 [$type_enum, "\\\\fI\$1\\\\fP"],
235 [$type_struct, "\\\\fI\$1\\\\fP"], 235 [$type_struct, "\\\\fI\$1\\\\fP"],
236 [$type_typedef, "\\\\fI\$1\\\\fP"], 236 [$type_typedef, "\\\\fI\$1\\\\fP"],
237 [$type_union, "\\\\fI\$1\\\\fP"], 237 [$type_union, "\\\\fI\$1\\\\fP"],
238 [$type_param, "\\\\fI\$1\\\\fP"], 238 [$type_param, "\\\\fI\$1\\\\fP"],
239 [$type_member, "\\\\fI\$1\$2\$3\\\\fP"], 239 [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
240 [$type_fallback, "\\\\fI\$1\\\\fP"] 240 [$type_fallback, "\\\\fI\$1\\\\fP"]
241 ); 241 );
242 my $blankline_man = ""; 242 my $blankline_man = "";
243 243
244 # rst-mode 244 # rst-mode
245 my @highlights_rst = ( 245 my @highlights_rst = (
246 [$type_constant, "``\$1``"], 246 [$type_constant, "``\$1``"],
247 [$type_constant2, "``\$1``"], 247 [$type_constant2, "``\$1``"],
248 # Note: need to escape () to avoid func matching later 248 # Note: need to escape () to avoid func matching later
249 [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"], 249 [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
250 [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"], 250 [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
251 [$type_fp_param, "**\$1\\\\(\\\\)**"], 251 [$type_fp_param, "**\$1\\\\(\\\\)**"],
252 [$type_func, "\\:c\\:func\\:`\$1()`"], 252 [$type_func, "\\:c\\:func\\:`\$1()`"],
253 [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"], 253 [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
254 [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"], 254 [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
255 [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"], 255 [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
256 [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"], 256 [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
257 # in rst this can refer to any type 257 # in rst this can refer to any type
258 [$type_fallback, "\\:c\\:type\\:`\$1`"], 258 [$type_fallback, "\\:c\\:type\\:`\$1`"],
259 [$type_param, "**\$1**"] 259 [$type_param, "**\$1**"]
260 ); 260 );
261 my $blankline_rst = "\n"; 261 my $blankline_rst = "\n";
262 262
263 # read arguments 263 # read arguments
264 if ($#ARGV == -1) { 264 if ($#ARGV == -1) {
265 usage(); 265 usage();
266 } 266 }
267 267
268 my $kernelversion; 268 my $kernelversion;
269 my $dohighlight = ""; 269 my $dohighlight = "";
270 270
271 my $verbose = 0; 271 my $verbose = 0;
272 my $output_mode = "rst"; 272 my $output_mode = "rst";
273 my $output_preformatted = 0; 273 my $output_preformatted = 0;
274 my $no_doc_sections = 0; 274 my $no_doc_sections = 0;
275 my $enable_lineno = 0; 275 my $enable_lineno = 0;
276 my @highlights = @highlights_rst; 276 my @highlights = @highlights_rst;
277 my $blankline = $blankline_rst; 277 my $blankline = $blankline_rst;
278 my $modulename = "Kernel API"; 278 my $modulename = "Kernel API";
279 279
280 use constant { 280 use constant {
281 OUTPUT_ALL => 0, # output all symbols and doc sections 281 OUTPUT_ALL => 0, # output all symbols and doc sections
282 OUTPUT_INCLUDE => 1, # output only specified symbols 282 OUTPUT_INCLUDE => 1, # output only specified symbols
283 OUTPUT_EXCLUDE => 2, # output everything except specified symbols 283 OUTPUT_EXCLUDE => 2, # output everything except specified symbols
284 OUTPUT_EXPORTED => 3, # output exported symbols 284 OUTPUT_EXPORTED => 3, # output exported symbols
285 OUTPUT_INTERNAL => 4, # output non-exported symbols 285 OUTPUT_INTERNAL => 4, # output non-exported symbols
286 }; 286 };
287 my $output_selection = OUTPUT_ALL; 287 my $output_selection = OUTPUT_ALL;
288 my $show_not_found = 0; 288 my $show_not_found = 0;
289 289
290 my @export_file_list; 290 my @export_file_list;
291 291
292 my @build_time; 292 my @build_time;
293 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && 293 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
294 (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') { 294 (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
295 @build_time = gmtime($seconds); 295 @build_time = gmtime($seconds);
296 } else { 296 } else {
297 @build_time = localtime; 297 @build_time = localtime;
298 } 298 }
299 299
300 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 300 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
301 'July', 'August', 'September', 'October', 301 'July', 'August', 'September', 'October',
302 'November', 'December')[$build_time[4]] . 302 'November', 'December')[$build_time[4]] .
303 " " . ($build_time[5]+1900); 303 " " . ($build_time[5]+1900);
304 304
305 # Essentially these are globals. 305 # Essentially these are globals.
306 # They probably want to be tidied up, made more localised or something. 306 # They probably want to be tidied up, made more localised or something.
307 # CAVEAT EMPTOR! Some of the others I localised may not want to be, which 307 # CAVEAT EMPTOR! Some of the others I localised may not want to be, which
308 # could cause "use of undefined value" or other bugs. 308 # could cause "use of undefined value" or other bugs.
309 my ($function, %function_table, %parametertypes, $declaration_purpose); 309 my ($function, %function_table, %parametertypes, $declaration_purpose);
310 my $declaration_start_line; 310 my $declaration_start_line;
311 my ($type, $declaration_name, $return_type); 311 my ($type, $declaration_name, $return_type);
312 my ($newsection, $newcontents, $prototype, $brcount, %source_map); 312 my ($newsection, $newcontents, $prototype, $brcount, %source_map);
313 313
314 if (defined($ENV{'KBUILD_VERBOSE'})) { 314 if (defined($ENV{'KBUILD_VERBOSE'})) {
315 $verbose = "$ENV{'KBUILD_VERBOSE'}"; 315 $verbose = "$ENV{'KBUILD_VERBOSE'}";
316 } 316 }
317 317
318 # Generated docbook code is inserted in a template at a point where 318 # Generated docbook code is inserted in a template at a point where
319 # docbook v3.1 requires a non-zero sequence of RefEntry's; see: 319 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
320 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html 320 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
321 # We keep track of number of generated entries and generate a dummy 321 # We keep track of number of generated entries and generate a dummy
322 # if needs be to ensure the expanded template can be postprocessed 322 # if needs be to ensure the expanded template can be postprocessed
323 # into html. 323 # into html.
324 my $section_counter = 0; 324 my $section_counter = 0;
325 325
326 my $lineprefix=""; 326 my $lineprefix="";
327 327
328 # Parser states 328 # Parser states
329 use constant { 329 use constant {
330 STATE_NORMAL => 0, # normal code 330 STATE_NORMAL => 0, # normal code
331 STATE_NAME => 1, # looking for function name 331 STATE_NAME => 1, # looking for function name
332 STATE_BODY_MAYBE => 2, # body - or maybe more description 332 STATE_BODY_MAYBE => 2, # body - or maybe more description
333 STATE_BODY => 3, # the body of the comment 333 STATE_BODY => 3, # the body of the comment
334 STATE_PROTO => 4, # scanning prototype 334 STATE_PROTO => 4, # scanning prototype
335 STATE_DOCBLOCK => 5, # documentation block 335 STATE_DOCBLOCK => 5, # documentation block
336 STATE_INLINE => 6, # gathering documentation outside main block 336 STATE_INLINE => 6, # gathering documentation outside main block
337 }; 337 };
338 my $state; 338 my $state;
339 my $in_doc_sect; 339 my $in_doc_sect;
340 my $leading_space; 340 my $leading_space;
341 341
342 # Inline documentation state 342 # Inline documentation state
343 use constant { 343 use constant {
344 STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE) 344 STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE)
345 STATE_INLINE_NAME => 1, # looking for member name (@foo:) 345 STATE_INLINE_NAME => 1, # looking for member name (@foo:)
346 STATE_INLINE_TEXT => 2, # looking for member documentation 346 STATE_INLINE_TEXT => 2, # looking for member documentation
347 STATE_INLINE_END => 3, # done 347 STATE_INLINE_END => 3, # done
348 STATE_INLINE_ERROR => 4, # error - Comment without header was found. 348 STATE_INLINE_ERROR => 4, # error - Comment without header was found.
349 # Spit a warning as it's not 349 # Spit a warning as it's not
350 # proper kernel-doc and ignore the rest. 350 # proper kernel-doc and ignore the rest.
351 }; 351 };
352 my $inline_doc_state; 352 my $inline_doc_state;
353 353
354 #declaration types: can be 354 #declaration types: can be
355 # 'function', 'struct', 'union', 'enum', 'typedef' 355 # 'function', 'struct', 'union', 'enum', 'typedef'
356 my $decl_type; 356 my $decl_type;
357 357
358 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 358 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
359 my $doc_end = '\*/'; 359 my $doc_end = '\*/';
360 my $doc_com = '\s*\*\s*'; 360 my $doc_com = '\s*\*\s*';
361 my $doc_com_body = '\s*\* ?'; 361 my $doc_com_body = '\s*\* ?';
362 my $doc_decl = $doc_com . '(\w+)'; 362 my $doc_decl = $doc_com . '(\w+)';
363 # @params and a strictly limited set of supported section names 363 # @params and a strictly limited set of supported section names
364 my $doc_sect = $doc_com . 364 my $doc_sect = $doc_com .
365 '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)'; 365 '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
366 my $doc_content = $doc_com_body . '(.*)'; 366 my $doc_content = $doc_com_body . '(.*)';
367 my $doc_block = $doc_com . 'DOC:\s*(.*)?'; 367 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
368 my $doc_inline_start = '^\s*/\*\*\s*$'; 368 my $doc_inline_start = '^\s*/\*\*\s*$';
369 my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)'; 369 my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
370 my $doc_inline_end = '^\s*\*/\s*$'; 370 my $doc_inline_end = '^\s*\*/\s*$';
371 my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$'; 371 my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
372 my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; 372 my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
373 373
374 my %parameterdescs; 374 my %parameterdescs;
375 my %parameterdesc_start_lines; 375 my %parameterdesc_start_lines;
376 my @parameterlist; 376 my @parameterlist;
377 my %sections; 377 my %sections;
378 my @sectionlist; 378 my @sectionlist;
379 my %section_start_lines; 379 my %section_start_lines;
380 my $sectcheck; 380 my $sectcheck;
381 my $struct_actual; 381 my $struct_actual;
382 382
383 my $contents = ""; 383 my $contents = "";
384 my $new_start_line = 0; 384 my $new_start_line = 0;
385 385
386 # the canonical section names. see also $doc_sect above. 386 # the canonical section names. see also $doc_sect above.
387 my $section_default = "Description"; # default section 387 my $section_default = "Description"; # default section
388 my $section_intro = "Introduction"; 388 my $section_intro = "Introduction";
389 my $section = $section_default; 389 my $section = $section_default;
390 my $section_context = "Context"; 390 my $section_context = "Context";
391 my $section_return = "Return"; 391 my $section_return = "Return";
392 392
393 my $undescribed = "-- undescribed --"; 393 my $undescribed = "-- undescribed --";
394 394
395 reset_state(); 395 reset_state();
396 396
397 while ($ARGV[0] =~ m/^--?(.*)/) { 397 while ($ARGV[0] =~ m/^--?(.*)/) {
398 my $cmd = $1; 398 my $cmd = $1;
399 shift @ARGV; 399 shift @ARGV;
400 if ($cmd eq "man") { 400 if ($cmd eq "man") {
401 $output_mode = "man"; 401 $output_mode = "man";
402 @highlights = @highlights_man; 402 @highlights = @highlights_man;
403 $blankline = $blankline_man; 403 $blankline = $blankline_man;
404 } elsif ($cmd eq "rst") { 404 } elsif ($cmd eq "rst") {
405 $output_mode = "rst"; 405 $output_mode = "rst";
406 @highlights = @highlights_rst; 406 @highlights = @highlights_rst;
407 $blankline = $blankline_rst; 407 $blankline = $blankline_rst;
408 } elsif ($cmd eq "none") { 408 } elsif ($cmd eq "none") {
409 $output_mode = "none"; 409 $output_mode = "none";
410 } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document 410 } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
411 $modulename = shift @ARGV; 411 $modulename = shift @ARGV;
412 } elsif ($cmd eq "function") { # to only output specific functions 412 } elsif ($cmd eq "function") { # to only output specific functions
413 $output_selection = OUTPUT_INCLUDE; 413 $output_selection = OUTPUT_INCLUDE;
414 $function = shift @ARGV; 414 $function = shift @ARGV;
415 $function_table{$function} = 1; 415 $function_table{$function} = 1;
416 } elsif ($cmd eq "nofunction") { # output all except specific functions 416 } elsif ($cmd eq "nofunction") { # output all except specific functions
417 $output_selection = OUTPUT_EXCLUDE; 417 $output_selection = OUTPUT_EXCLUDE;
418 $function = shift @ARGV; 418 $function = shift @ARGV;
419 $function_table{$function} = 1; 419 $function_table{$function} = 1;
420 } elsif ($cmd eq "export") { # only exported symbols 420 } elsif ($cmd eq "export") { # only exported symbols
421 $output_selection = OUTPUT_EXPORTED; 421 $output_selection = OUTPUT_EXPORTED;
422 %function_table = (); 422 %function_table = ();
423 } elsif ($cmd eq "internal") { # only non-exported symbols 423 } elsif ($cmd eq "internal") { # only non-exported symbols
424 $output_selection = OUTPUT_INTERNAL; 424 $output_selection = OUTPUT_INTERNAL;
425 %function_table = (); 425 %function_table = ();
426 } elsif ($cmd eq "export-file") { 426 } elsif ($cmd eq "export-file") {
427 my $file = shift @ARGV; 427 my $file = shift @ARGV;
428 push(@export_file_list, $file); 428 push(@export_file_list, $file);
429 } elsif ($cmd eq "v") { 429 } elsif ($cmd eq "v") {
430 $verbose = 1; 430 $verbose = 1;
431 } elsif (($cmd eq "h") || ($cmd eq "help")) { 431 } elsif (($cmd eq "h") || ($cmd eq "help")) {
432 usage(); 432 usage();
433 } elsif ($cmd eq 'no-doc-sections') { 433 } elsif ($cmd eq 'no-doc-sections') {
434 $no_doc_sections = 1; 434 $no_doc_sections = 1;
435 } elsif ($cmd eq 'enable-lineno') { 435 } elsif ($cmd eq 'enable-lineno') {
436 $enable_lineno = 1; 436 $enable_lineno = 1;
437 } elsif ($cmd eq 'show-not-found') { 437 } elsif ($cmd eq 'show-not-found') {
438 $show_not_found = 1; 438 $show_not_found = 1;
439 } else { 439 } else {
440 # Unknown argument 440 # Unknown argument
441 usage(); 441 usage();
442 } 442 }
443 } 443 }
444 444
445 # continue execution near EOF; 445 # continue execution near EOF;
446 446
447 # get kernel version from env 447 # get kernel version from env
448 sub get_kernel_version() { 448 sub get_kernel_version() {
449 my $version = 'unknown kernel version'; 449 my $version = 'unknown kernel version';
450 450
451 if (defined($ENV{'KERNELVERSION'})) { 451 if (defined($ENV{'KERNELVERSION'})) {
452 $version = $ENV{'KERNELVERSION'}; 452 $version = $ENV{'KERNELVERSION'};
453 } 453 }
454 return $version; 454 return $version;
455 } 455 }
456 456
457 # 457 #
458 sub print_lineno { 458 sub print_lineno {
459 my $lineno = shift; 459 my $lineno = shift;
460 if ($enable_lineno && defined($lineno)) { 460 if ($enable_lineno && defined($lineno)) {
461 print "#define LINENO " . $lineno . "\n"; 461 print "#define LINENO " . $lineno . "\n";
462 } 462 }
463 } 463 }
464 ## 464 ##
465 # dumps section contents to arrays/hashes intended for that purpose. 465 # dumps section contents to arrays/hashes intended for that purpose.
466 # 466 #
467 sub dump_section { 467 sub dump_section {
468 my $file = shift; 468 my $file = shift;
469 my $name = shift; 469 my $name = shift;
470 my $contents = join "\n", @_; 470 my $contents = join "\n", @_;
471 471
472 if ($name =~ m/$type_param/) { 472 if ($name =~ m/$type_param/) {
473 $name = $1; 473 $name = $1;
474 $parameterdescs{$name} = $contents; 474 $parameterdescs{$name} = $contents;
475 $sectcheck = $sectcheck . $name . " "; 475 $sectcheck = $sectcheck . $name . " ";
476 $parameterdesc_start_lines{$name} = $new_start_line; 476 $parameterdesc_start_lines{$name} = $new_start_line;
477 $new_start_line = 0; 477 $new_start_line = 0;
478 } elsif ($name eq "@\.\.\.") { 478 } elsif ($name eq "@\.\.\.") {
479 $name = "..."; 479 $name = "...";
480 $parameterdescs{$name} = $contents; 480 $parameterdescs{$name} = $contents;
481 $sectcheck = $sectcheck . $name . " "; 481 $sectcheck = $sectcheck . $name . " ";
482 $parameterdesc_start_lines{$name} = $new_start_line; 482 $parameterdesc_start_lines{$name} = $new_start_line;
483 $new_start_line = 0; 483 $new_start_line = 0;
484 } else { 484 } else {
485 if (defined($sections{$name}) && ($sections{$name} ne "")) { 485 if (defined($sections{$name}) && ($sections{$name} ne "")) {
486 # Only warn on user specified duplicate section names. 486 # Only warn on user specified duplicate section names.
487 if ($name ne $section_default) { 487 if ($name ne $section_default) {
488 print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; 488 print STDERR "${file}:$.: warning: duplicate section name '$name'\n";
489 ++$warnings; 489 ++$warnings;
490 } 490 }
491 $sections{$name} .= $contents; 491 $sections{$name} .= $contents;
492 } else { 492 } else {
493 $sections{$name} = $contents; 493 $sections{$name} = $contents;
494 push @sectionlist, $name; 494 push @sectionlist, $name;
495 $section_start_lines{$name} = $new_start_line; 495 $section_start_lines{$name} = $new_start_line;
496 $new_start_line = 0; 496 $new_start_line = 0;
497 } 497 }
498 } 498 }
499 } 499 }
500 500
501 ## 501 ##
502 # dump DOC: section after checking that it should go out 502 # dump DOC: section after checking that it should go out
503 # 503 #
504 sub dump_doc_section { 504 sub dump_doc_section {
505 my $file = shift; 505 my $file = shift;
506 my $name = shift; 506 my $name = shift;
507 my $contents = join "\n", @_; 507 my $contents = join "\n", @_;
508 508
509 if ($no_doc_sections) { 509 if ($no_doc_sections) {
510 return; 510 return;
511 } 511 }
512 512
513 if (($output_selection == OUTPUT_ALL) || 513 if (($output_selection == OUTPUT_ALL) ||
514 ($output_selection == OUTPUT_INCLUDE && 514 ($output_selection == OUTPUT_INCLUDE &&
515 defined($function_table{$name})) || 515 defined($function_table{$name})) ||
516 ($output_selection == OUTPUT_EXCLUDE && 516 ($output_selection == OUTPUT_EXCLUDE &&
517 !defined($function_table{$name}))) 517 !defined($function_table{$name})))
518 { 518 {
519 dump_section($file, $name, $contents); 519 dump_section($file, $name, $contents);
520 output_blockhead({'sectionlist' => \@sectionlist, 520 output_blockhead({'sectionlist' => \@sectionlist,
521 'sections' => \%sections, 521 'sections' => \%sections,
522 'module' => $modulename, 522 'module' => $modulename,
523 'content-only' => ($output_selection != OUTPUT_ALL), }); 523 'content-only' => ($output_selection != OUTPUT_ALL), });
524 } 524 }
525 } 525 }
526 526
527 ## 527 ##
528 # output function 528 # output function
529 # 529 #
530 # parameterdescs, a hash. 530 # parameterdescs, a hash.
531 # function => "function name" 531 # function => "function name"
532 # parameterlist => @list of parameters 532 # parameterlist => @list of parameters
533 # parameterdescs => %parameter descriptions 533 # parameterdescs => %parameter descriptions
534 # sectionlist => @list of sections 534 # sectionlist => @list of sections
535 # sections => %section descriptions 535 # sections => %section descriptions
536 # 536 #
537 537
538 sub output_highlight { 538 sub output_highlight {
539 my $contents = join "\n",@_; 539 my $contents = join "\n",@_;
540 my $line; 540 my $line;
541 541
542 # DEBUG 542 # DEBUG
543 # if (!defined $contents) { 543 # if (!defined $contents) {
544 # use Carp; 544 # use Carp;
545 # confess "output_highlight got called with no args?\n"; 545 # confess "output_highlight got called with no args?\n";
546 # } 546 # }
547 547
548 # print STDERR "contents b4:$contents\n"; 548 # print STDERR "contents b4:$contents\n";
549 eval $dohighlight; 549 eval $dohighlight;
550 die $@ if $@; 550 die $@ if $@;
551 # print STDERR "contents af:$contents\n"; 551 # print STDERR "contents af:$contents\n";
552 552
553 foreach $line (split "\n", $contents) { 553 foreach $line (split "\n", $contents) {
554 if (! $output_preformatted) { 554 if (! $output_preformatted) {
555 $line =~ s/^\s*//; 555 $line =~ s/^\s*//;
556 } 556 }
557 if ($line eq ""){ 557 if ($line eq ""){
558 if (! $output_preformatted) { 558 if (! $output_preformatted) {
559 print $lineprefix, $blankline; 559 print $lineprefix, $blankline;
560 } 560 }
561 } else { 561 } else {
562 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { 562 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
563 print "\\&$line"; 563 print "\\&$line";
564 } else { 564 } else {
565 print $lineprefix, $line; 565 print $lineprefix, $line;
566 } 566 }
567 } 567 }
568 print "\n"; 568 print "\n";
569 } 569 }
570 } 570 }
571 571
572 ## 572 ##
573 # output function in man 573 # output function in man
574 sub output_function_man(%) { 574 sub output_function_man(%) {
575 my %args = %{$_[0]}; 575 my %args = %{$_[0]};
576 my ($parameter, $section); 576 my ($parameter, $section);
577 my $count; 577 my $count;
578 578
579 print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; 579 print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
580 580
581 print ".SH NAME\n"; 581 print ".SH NAME\n";
582 print $args{'function'} . " \\- " . $args{'purpose'} . "\n"; 582 print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
583 583
584 print ".SH SYNOPSIS\n"; 584 print ".SH SYNOPSIS\n";
585 if ($args{'functiontype'} ne "") { 585 if ($args{'functiontype'} ne "") {
586 print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n"; 586 print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
587 } else { 587 } else {
588 print ".B \"" . $args{'function'} . "\n"; 588 print ".B \"" . $args{'function'} . "\n";
589 } 589 }
590 $count = 0; 590 $count = 0;
591 my $parenth = "("; 591 my $parenth = "(";
592 my $post = ","; 592 my $post = ",";
593 foreach my $parameter (@{$args{'parameterlist'}}) { 593 foreach my $parameter (@{$args{'parameterlist'}}) {
594 if ($count == $#{$args{'parameterlist'}}) { 594 if ($count == $#{$args{'parameterlist'}}) {
595 $post = ");"; 595 $post = ");";
596 } 596 }
597 $type = $args{'parametertypes'}{$parameter}; 597 $type = $args{'parametertypes'}{$parameter};
598 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 598 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
599 # pointer-to-function 599 # pointer-to-function
600 print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n"; 600 print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
601 } else { 601 } else {
602 $type =~ s/([^\*])$/$1 /; 602 $type =~ s/([^\*])$/$1 /;
603 print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n"; 603 print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
604 } 604 }
605 $count++; 605 $count++;
606 $parenth = ""; 606 $parenth = "";
607 } 607 }
608 608
609 print ".SH ARGUMENTS\n"; 609 print ".SH ARGUMENTS\n";
610 foreach $parameter (@{$args{'parameterlist'}}) { 610 foreach $parameter (@{$args{'parameterlist'}}) {
611 my $parameter_name = $parameter; 611 my $parameter_name = $parameter;
612 $parameter_name =~ s/\[.*//; 612 $parameter_name =~ s/\[.*//;
613 613
614 print ".IP \"" . $parameter . "\" 12\n"; 614 print ".IP \"" . $parameter . "\" 12\n";
615 output_highlight($args{'parameterdescs'}{$parameter_name}); 615 output_highlight($args{'parameterdescs'}{$parameter_name});
616 } 616 }
617 foreach $section (@{$args{'sectionlist'}}) { 617 foreach $section (@{$args{'sectionlist'}}) {
618 print ".SH \"", uc $section, "\"\n"; 618 print ".SH \"", uc $section, "\"\n";
619 output_highlight($args{'sections'}{$section}); 619 output_highlight($args{'sections'}{$section});
620 } 620 }
621 } 621 }
622 622
623 ## 623 ##
624 # output enum in man 624 # output enum in man
625 sub output_enum_man(%) { 625 sub output_enum_man(%) {
626 my %args = %{$_[0]}; 626 my %args = %{$_[0]};
627 my ($parameter, $section); 627 my ($parameter, $section);
628 my $count; 628 my $count;
629 629
630 print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; 630 print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
631 631
632 print ".SH NAME\n"; 632 print ".SH NAME\n";
633 print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n"; 633 print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
634 634
635 print ".SH SYNOPSIS\n"; 635 print ".SH SYNOPSIS\n";
636 print "enum " . $args{'enum'} . " {\n"; 636 print "enum " . $args{'enum'} . " {\n";
637 $count = 0; 637 $count = 0;
638 foreach my $parameter (@{$args{'parameterlist'}}) { 638 foreach my $parameter (@{$args{'parameterlist'}}) {
639 print ".br\n.BI \" $parameter\"\n"; 639 print ".br\n.BI \" $parameter\"\n";
640 if ($count == $#{$args{'parameterlist'}}) { 640 if ($count == $#{$args{'parameterlist'}}) {
641 print "\n};\n"; 641 print "\n};\n";
642 last; 642 last;
643 } 643 }
644 else { 644 else {
645 print ", \n.br\n"; 645 print ", \n.br\n";
646 } 646 }
647 $count++; 647 $count++;
648 } 648 }
649 649
650 print ".SH Constants\n"; 650 print ".SH Constants\n";
651 foreach $parameter (@{$args{'parameterlist'}}) { 651 foreach $parameter (@{$args{'parameterlist'}}) {
652 my $parameter_name = $parameter; 652 my $parameter_name = $parameter;
653 $parameter_name =~ s/\[.*//; 653 $parameter_name =~ s/\[.*//;
654 654
655 print ".IP \"" . $parameter . "\" 12\n"; 655 print ".IP \"" . $parameter . "\" 12\n";
656 output_highlight($args{'parameterdescs'}{$parameter_name}); 656 output_highlight($args{'parameterdescs'}{$parameter_name});
657 } 657 }
658 foreach $section (@{$args{'sectionlist'}}) { 658 foreach $section (@{$args{'sectionlist'}}) {
659 print ".SH \"$section\"\n"; 659 print ".SH \"$section\"\n";
660 output_highlight($args{'sections'}{$section}); 660 output_highlight($args{'sections'}{$section});
661 } 661 }
662 } 662 }
663 663
664 ## 664 ##
665 # output struct in man 665 # output struct in man
666 sub output_struct_man(%) { 666 sub output_struct_man(%) {
667 my %args = %{$_[0]}; 667 my %args = %{$_[0]};
668 my ($parameter, $section); 668 my ($parameter, $section);
669 669
670 print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n"; 670 print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
671 671
672 print ".SH NAME\n"; 672 print ".SH NAME\n";
673 print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n"; 673 print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
674 674
675 my $declaration = $args{'definition'}; 675 my $declaration = $args{'definition'};
676 $declaration =~ s/\t/ /g; 676 $declaration =~ s/\t/ /g;
677 $declaration =~ s/\n/"\n.br\n.BI \"/g; 677 $declaration =~ s/\n/"\n.br\n.BI \"/g;
678 print ".SH SYNOPSIS\n"; 678 print ".SH SYNOPSIS\n";
679 print $args{'type'} . " " . $args{'struct'} . " {\n.br\n"; 679 print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
680 print ".BI \"$declaration\n};\n.br\n\n"; 680 print ".BI \"$declaration\n};\n.br\n\n";
681 681
682 print ".SH Members\n"; 682 print ".SH Members\n";
683 foreach $parameter (@{$args{'parameterlist'}}) { 683 foreach $parameter (@{$args{'parameterlist'}}) {
684 ($parameter =~ /^#/) && next; 684 ($parameter =~ /^#/) && next;
685 685
686 my $parameter_name = $parameter; 686 my $parameter_name = $parameter;
687 $parameter_name =~ s/\[.*//; 687 $parameter_name =~ s/\[.*//;
688 688
689 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 689 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
690 print ".IP \"" . $parameter . "\" 12\n"; 690 print ".IP \"" . $parameter . "\" 12\n";
691 output_highlight($args{'parameterdescs'}{$parameter_name}); 691 output_highlight($args{'parameterdescs'}{$parameter_name});
692 } 692 }
693 foreach $section (@{$args{'sectionlist'}}) { 693 foreach $section (@{$args{'sectionlist'}}) {
694 print ".SH \"$section\"\n"; 694 print ".SH \"$section\"\n";
695 output_highlight($args{'sections'}{$section}); 695 output_highlight($args{'sections'}{$section});
696 } 696 }
697 } 697 }
698 698
699 ## 699 ##
700 # output typedef in man 700 # output typedef in man
701 sub output_typedef_man(%) { 701 sub output_typedef_man(%) {
702 my %args = %{$_[0]}; 702 my %args = %{$_[0]};
703 my ($parameter, $section); 703 my ($parameter, $section);
704 704
705 print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; 705 print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
706 706
707 print ".SH NAME\n"; 707 print ".SH NAME\n";
708 print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n"; 708 print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
709 709
710 foreach $section (@{$args{'sectionlist'}}) { 710 foreach $section (@{$args{'sectionlist'}}) {
711 print ".SH \"$section\"\n"; 711 print ".SH \"$section\"\n";
712 output_highlight($args{'sections'}{$section}); 712 output_highlight($args{'sections'}{$section});
713 } 713 }
714 } 714 }
715 715
716 sub output_blockhead_man(%) { 716 sub output_blockhead_man(%) {
717 my %args = %{$_[0]}; 717 my %args = %{$_[0]};
718 my ($parameter, $section); 718 my ($parameter, $section);
719 my $count; 719 my $count;
720 720
721 print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; 721 print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
722 722
723 foreach $section (@{$args{'sectionlist'}}) { 723 foreach $section (@{$args{'sectionlist'}}) {
724 print ".SH \"$section\"\n"; 724 print ".SH \"$section\"\n";
725 output_highlight($args{'sections'}{$section}); 725 output_highlight($args{'sections'}{$section});
726 } 726 }
727 } 727 }
728 728
729 ## 729 ##
730 # output in restructured text 730 # output in restructured text
731 # 731 #
732 732
733 # 733 #
734 # This could use some work; it's used to output the DOC: sections, and 734 # This could use some work; it's used to output the DOC: sections, and
735 # starts by putting out the name of the doc section itself, but that tends 735 # starts by putting out the name of the doc section itself, but that tends
736 # to duplicate a header already in the template file. 736 # to duplicate a header already in the template file.
737 # 737 #
738 sub output_blockhead_rst(%) { 738 sub output_blockhead_rst(%) {
739 my %args = %{$_[0]}; 739 my %args = %{$_[0]};
740 my ($parameter, $section); 740 my ($parameter, $section);
741 741
742 foreach $section (@{$args{'sectionlist'}}) { 742 foreach $section (@{$args{'sectionlist'}}) {
743 if ($output_selection != OUTPUT_INCLUDE) { 743 if ($output_selection != OUTPUT_INCLUDE) {
744 print "**$section**\n\n"; 744 print "**$section**\n\n";
745 } 745 }
746 print_lineno($section_start_lines{$section}); 746 print_lineno($section_start_lines{$section});
747 output_highlight_rst($args{'sections'}{$section}); 747 output_highlight_rst($args{'sections'}{$section});
748 print "\n"; 748 print "\n";
749 } 749 }
750 } 750 }
751 751
752 # 752 #
753 # Apply the RST highlights to a sub-block of text. 753 # Apply the RST highlights to a sub-block of text.
754 # 754 #
755 sub highlight_block($) { 755 sub highlight_block($) {
756 # The dohighlight kludge requires the text be called $contents 756 # The dohighlight kludge requires the text be called $contents
757 my $contents = shift; 757 my $contents = shift;
758 eval $dohighlight; 758 eval $dohighlight;
759 die $@ if $@; 759 die $@ if $@;
760 return $contents; 760 return $contents;
761 } 761 }
762 762
763 # 763 #
764 # Regexes used only here. 764 # Regexes used only here.
765 # 765 #
766 my $sphinx_literal = '^[^.].*::$'; 766 my $sphinx_literal = '^[^.].*::$';
767 my $sphinx_cblock = '^\.\.\ +code-block::'; 767 my $sphinx_cblock = '^\.\.\ +code-block::';
768 768
769 sub output_highlight_rst { 769 sub output_highlight_rst {
770 my $input = join "\n",@_; 770 my $input = join "\n",@_;
771 my $output = ""; 771 my $output = "";
772 my $line; 772 my $line;
773 my $in_literal = 0; 773 my $in_literal = 0;
774 my $litprefix; 774 my $litprefix;
775 my $block = ""; 775 my $block = "";
776 776
777 foreach $line (split "\n",$input) { 777 foreach $line (split "\n",$input) {
778 # 778 #
779 # If we're in a literal block, see if we should drop out 779 # If we're in a literal block, see if we should drop out
780 # of it. Otherwise pass the line straight through unmunged. 780 # of it. Otherwise pass the line straight through unmunged.
781 # 781 #
782 if ($in_literal) { 782 if ($in_literal) {
783 if (! ($line =~ /^\s*$/)) { 783 if (! ($line =~ /^\s*$/)) {
784 # 784 #
785 # If this is the first non-blank line in a literal 785 # If this is the first non-blank line in a literal
786 # block we need to figure out what the proper indent is. 786 # block we need to figure out what the proper indent is.
787 # 787 #
788 if ($litprefix eq "") { 788 if ($litprefix eq "") {
789 $line =~ /^(\s*)/; 789 $line =~ /^(\s*)/;
790 $litprefix = '^' . $1; 790 $litprefix = '^' . $1;
791 $output .= $line . "\n"; 791 $output .= $line . "\n";
792 } elsif (! ($line =~ /$litprefix/)) { 792 } elsif (! ($line =~ /$litprefix/)) {
793 $in_literal = 0; 793 $in_literal = 0;
794 } else { 794 } else {
795 $output .= $line . "\n"; 795 $output .= $line . "\n";
796 } 796 }
797 } else { 797 } else {
798 $output .= $line . "\n"; 798 $output .= $line . "\n";
799 } 799 }
800 } 800 }
801 # 801 #
802 # Not in a literal block (or just dropped out) 802 # Not in a literal block (or just dropped out)
803 # 803 #
804 if (! $in_literal) { 804 if (! $in_literal) {
805 $block .= $line . "\n"; 805 $block .= $line . "\n";
806 if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) { 806 if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
807 $in_literal = 1; 807 $in_literal = 1;
808 $litprefix = ""; 808 $litprefix = "";
809 $output .= highlight_block($block); 809 $output .= highlight_block($block);
810 $block = "" 810 $block = ""
811 } 811 }
812 } 812 }
813 } 813 }
814 814
815 if ($block) { 815 if ($block) {
816 $output .= highlight_block($block); 816 $output .= highlight_block($block);
817 } 817 }
818 foreach $line (split "\n", $output) { 818 foreach $line (split "\n", $output) {
819 print $lineprefix . $line . "\n"; 819 print $lineprefix . $line . "\n";
820 } 820 }
821 } 821 }
822 822
823 sub output_function_rst(%) { 823 sub output_function_rst(%) {
824 my %args = %{$_[0]}; 824 my %args = %{$_[0]};
825 my ($parameter, $section); 825 my ($parameter, $section);
826 my $oldprefix = $lineprefix; 826 my $oldprefix = $lineprefix;
827 my $start = ""; 827 my $start = "";
828 828
829 if ($args{'typedef'}) { 829 if ($args{'typedef'}) {
830 print ".. c:type:: ". $args{'function'} . "\n\n"; 830 print ".. c:type:: ". $args{'function'} . "\n\n";
831 print_lineno($declaration_start_line); 831 print_lineno($declaration_start_line);
832 print " **Typedef**: "; 832 print " **Typedef**: ";
833 $lineprefix = ""; 833 $lineprefix = "";
834 output_highlight_rst($args{'purpose'}); 834 output_highlight_rst($args{'purpose'});
835 $start = "\n\n**Syntax**\n\n ``"; 835 $start = "\n\n**Syntax**\n\n ``";
836 } else { 836 } else {
837 print ".. c:function:: "; 837 print ".. c:function:: ";
838 } 838 }
839 if ($args{'functiontype'} ne "") { 839 if ($args{'functiontype'} ne "") {
840 $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; 840 $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
841 } else { 841 } else {
842 $start .= $args{'function'} . " ("; 842 $start .= $args{'function'} . " (";
843 } 843 }
844 print $start; 844 print $start;
845 845
846 my $count = 0; 846 my $count = 0;
847 foreach my $parameter (@{$args{'parameterlist'}}) { 847 foreach my $parameter (@{$args{'parameterlist'}}) {
848 if ($count ne 0) { 848 if ($count ne 0) {
849 print ", "; 849 print ", ";
850 } 850 }
851 $count++; 851 $count++;
852 $type = $args{'parametertypes'}{$parameter}; 852 $type = $args{'parametertypes'}{$parameter};
853 853
854 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 854 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
855 # pointer-to-function 855 # pointer-to-function
856 print $1 . $parameter . ") (" . $2; 856 print $1 . $parameter . ") (" . $2;
857 } else { 857 } else {
858 print $type . " " . $parameter; 858 print $type . " " . $parameter;
859 } 859 }
860 } 860 }
861 if ($args{'typedef'}) { 861 if ($args{'typedef'}) {
862 print ");``\n\n"; 862 print ");``\n\n";
863 } else { 863 } else {
864 print ")\n\n"; 864 print ")\n\n";
865 print_lineno($declaration_start_line); 865 print_lineno($declaration_start_line);
866 $lineprefix = " "; 866 $lineprefix = " ";
867 output_highlight_rst($args{'purpose'}); 867 output_highlight_rst($args{'purpose'});
868 print "\n"; 868 print "\n";
869 } 869 }
870 870
871 print "**Parameters**\n\n"; 871 print "**Parameters**\n\n";
872 $lineprefix = " "; 872 $lineprefix = " ";
873 foreach $parameter (@{$args{'parameterlist'}}) { 873 foreach $parameter (@{$args{'parameterlist'}}) {
874 my $parameter_name = $parameter; 874 my $parameter_name = $parameter;
875 $parameter_name =~ s/\[.*//; 875 $parameter_name =~ s/\[.*//;
876 $type = $args{'parametertypes'}{$parameter}; 876 $type = $args{'parametertypes'}{$parameter};
877 877
878 if ($type ne "") { 878 if ($type ne "") {
879 print "``$type $parameter``\n"; 879 print "``$type $parameter``\n";
880 } else { 880 } else {
881 print "``$parameter``\n"; 881 print "``$parameter``\n";
882 } 882 }
883 883
884 print_lineno($parameterdesc_start_lines{$parameter_name}); 884 print_lineno($parameterdesc_start_lines{$parameter_name});
885 885
886 if (defined($args{'parameterdescs'}{$parameter_name}) && 886 if (defined($args{'parameterdescs'}{$parameter_name}) &&
887 $args{'parameterdescs'}{$parameter_name} ne $undescribed) { 887 $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
888 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 888 output_highlight_rst($args{'parameterdescs'}{$parameter_name});
889 } else { 889 } else {
890 print " *undescribed*\n"; 890 print " *undescribed*\n";
891 } 891 }
892 print "\n"; 892 print "\n";
893 } 893 }
894 894
895 $lineprefix = $oldprefix; 895 $lineprefix = $oldprefix;
896 output_section_rst(@_); 896 output_section_rst(@_);
897 } 897 }
898 898
899 sub output_section_rst(%) { 899 sub output_section_rst(%) {
900 my %args = %{$_[0]}; 900 my %args = %{$_[0]};
901 my $section; 901 my $section;
902 my $oldprefix = $lineprefix; 902 my $oldprefix = $lineprefix;
903 $lineprefix = ""; 903 $lineprefix = "";
904 904
905 foreach $section (@{$args{'sectionlist'}}) { 905 foreach $section (@{$args{'sectionlist'}}) {
906 print "**$section**\n\n"; 906 print "**$section**\n\n";
907 print_lineno($section_start_lines{$section}); 907 print_lineno($section_start_lines{$section});
908 output_highlight_rst($args{'sections'}{$section}); 908 output_highlight_rst($args{'sections'}{$section});
909 print "\n"; 909 print "\n";
910 } 910 }
911 print "\n"; 911 print "\n";
912 $lineprefix = $oldprefix; 912 $lineprefix = $oldprefix;
913 } 913 }
914 914
915 sub output_enum_rst(%) { 915 sub output_enum_rst(%) {
916 my %args = %{$_[0]}; 916 my %args = %{$_[0]};
917 my ($parameter); 917 my ($parameter);
918 my $oldprefix = $lineprefix; 918 my $oldprefix = $lineprefix;
919 my $count; 919 my $count;
920 my $name = "enum " . $args{'enum'}; 920 my $name = "enum " . $args{'enum'};
921 921
922 print "\n\n.. c:type:: " . $name . "\n\n"; 922 print "\n\n.. c:type:: " . $name . "\n\n";
923 print_lineno($declaration_start_line); 923 print_lineno($declaration_start_line);
924 $lineprefix = " "; 924 $lineprefix = " ";
925 output_highlight_rst($args{'purpose'}); 925 output_highlight_rst($args{'purpose'});
926 print "\n"; 926 print "\n";
927 927
928 print "**Constants**\n\n"; 928 print "**Constants**\n\n";
929 $lineprefix = " "; 929 $lineprefix = " ";
930 foreach $parameter (@{$args{'parameterlist'}}) { 930 foreach $parameter (@{$args{'parameterlist'}}) {
931 print "``$parameter``\n"; 931 print "``$parameter``\n";
932 if ($args{'parameterdescs'}{$parameter} ne $undescribed) { 932 if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
933 output_highlight_rst($args{'parameterdescs'}{$parameter}); 933 output_highlight_rst($args{'parameterdescs'}{$parameter});
934 } else { 934 } else {
935 print " *undescribed*\n"; 935 print " *undescribed*\n";
936 } 936 }
937 print "\n"; 937 print "\n";
938 } 938 }
939 939
940 $lineprefix = $oldprefix; 940 $lineprefix = $oldprefix;
941 output_section_rst(@_); 941 output_section_rst(@_);
942 } 942 }
943 943
944 sub output_typedef_rst(%) { 944 sub output_typedef_rst(%) {
945 my %args = %{$_[0]}; 945 my %args = %{$_[0]};
946 my ($parameter); 946 my ($parameter);
947 my $oldprefix = $lineprefix; 947 my $oldprefix = $lineprefix;
948 my $name = "typedef " . $args{'typedef'}; 948 my $name = "typedef " . $args{'typedef'};
949 949
950 print "\n\n.. c:type:: " . $name . "\n\n"; 950 print "\n\n.. c:type:: " . $name . "\n\n";
951 print_lineno($declaration_start_line); 951 print_lineno($declaration_start_line);
952 $lineprefix = " "; 952 $lineprefix = " ";
953 output_highlight_rst($args{'purpose'}); 953 output_highlight_rst($args{'purpose'});
954 print "\n"; 954 print "\n";
955 955
956 $lineprefix = $oldprefix; 956 $lineprefix = $oldprefix;
957 output_section_rst(@_); 957 output_section_rst(@_);
958 } 958 }
959 959
960 sub output_struct_rst(%) { 960 sub output_struct_rst(%) {
961 my %args = %{$_[0]}; 961 my %args = %{$_[0]};
962 my ($parameter); 962 my ($parameter);
963 my $oldprefix = $lineprefix; 963 my $oldprefix = $lineprefix;
964 my $name = $args{'type'} . " " . $args{'struct'}; 964 my $name = $args{'type'} . " " . $args{'struct'};
965 965
966 print "\n\n.. c:type:: " . $name . "\n\n"; 966 print "\n\n.. c:type:: " . $name . "\n\n";
967 print_lineno($declaration_start_line); 967 print_lineno($declaration_start_line);
968 $lineprefix = " "; 968 $lineprefix = " ";
969 output_highlight_rst($args{'purpose'}); 969 output_highlight_rst($args{'purpose'});
970 print "\n"; 970 print "\n";
971 971
972 print "**Definition**\n\n"; 972 print "**Definition**\n\n";
973 print "::\n\n"; 973 print "::\n\n";
974 my $declaration = $args{'definition'}; 974 my $declaration = $args{'definition'};
975 $declaration =~ s/\t/ /g; 975 $declaration =~ s/\t/ /g;
976 print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n"; 976 print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n";
977 977
978 print "**Members**\n\n"; 978 print "**Members**\n\n";
979 $lineprefix = " "; 979 $lineprefix = " ";
980 foreach $parameter (@{$args{'parameterlist'}}) { 980 foreach $parameter (@{$args{'parameterlist'}}) {
981 ($parameter =~ /^#/) && next; 981 ($parameter =~ /^#/) && next;
982 982
983 my $parameter_name = $parameter; 983 my $parameter_name = $parameter;
984 $parameter_name =~ s/\[.*//; 984 $parameter_name =~ s/\[.*//;
985 985
986 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 986 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
987 $type = $args{'parametertypes'}{$parameter}; 987 $type = $args{'parametertypes'}{$parameter};
988 print_lineno($parameterdesc_start_lines{$parameter_name}); 988 print_lineno($parameterdesc_start_lines{$parameter_name});
989 print "``" . $parameter . "``\n"; 989 print "``" . $parameter . "``\n";
990 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 990 output_highlight_rst($args{'parameterdescs'}{$parameter_name});
991 print "\n"; 991 print "\n";
992 } 992 }
993 print "\n"; 993 print "\n";
994 994
995 $lineprefix = $oldprefix; 995 $lineprefix = $oldprefix;
996 output_section_rst(@_); 996 output_section_rst(@_);
997 } 997 }
998 998
999 ## none mode output functions 999 ## none mode output functions
1000 1000
1001 sub output_function_none(%) { 1001 sub output_function_none(%) {
1002 } 1002 }
1003 1003
1004 sub output_enum_none(%) { 1004 sub output_enum_none(%) {
1005 } 1005 }
1006 1006
1007 sub output_typedef_none(%) { 1007 sub output_typedef_none(%) {
1008 } 1008 }
1009 1009
1010 sub output_struct_none(%) { 1010 sub output_struct_none(%) {
1011 } 1011 }
1012 1012
1013 sub output_blockhead_none(%) { 1013 sub output_blockhead_none(%) {
1014 } 1014 }
1015 1015
1016 ## 1016 ##
1017 # generic output function for all types (function, struct/union, typedef, enum); 1017 # generic output function for all types (function, struct/union, typedef, enum);
1018 # calls the generated, variable output_ function name based on 1018 # calls the generated, variable output_ function name based on
1019 # functype and output_mode 1019 # functype and output_mode
1020 sub output_declaration { 1020 sub output_declaration {
1021 no strict 'refs'; 1021 no strict 'refs';
1022 my $name = shift; 1022 my $name = shift;
1023 my $functype = shift; 1023 my $functype = shift;
1024 my $func = "output_${functype}_$output_mode"; 1024 my $func = "output_${functype}_$output_mode";
1025 if (($output_selection == OUTPUT_ALL) || 1025 if (($output_selection == OUTPUT_ALL) ||
1026 (($output_selection == OUTPUT_INCLUDE || 1026 (($output_selection == OUTPUT_INCLUDE ||
1027 $output_selection == OUTPUT_EXPORTED) && 1027 $output_selection == OUTPUT_EXPORTED) &&
1028 defined($function_table{$name})) || 1028 defined($function_table{$name})) ||
1029 (($output_selection == OUTPUT_EXCLUDE || 1029 (($output_selection == OUTPUT_EXCLUDE ||
1030 $output_selection == OUTPUT_INTERNAL) && 1030 $output_selection == OUTPUT_INTERNAL) &&
1031 !($functype eq "function" && defined($function_table{$name})))) 1031 !($functype eq "function" && defined($function_table{$name}))))
1032 { 1032 {
1033 &$func(@_); 1033 &$func(@_);
1034 $section_counter++; 1034 $section_counter++;
1035 } 1035 }
1036 } 1036 }
1037 1037
1038 ## 1038 ##
1039 # generic output function - calls the right one based on current output mode. 1039 # generic output function - calls the right one based on current output mode.
1040 sub output_blockhead { 1040 sub output_blockhead {
1041 no strict 'refs'; 1041 no strict 'refs';
1042 my $func = "output_blockhead_" . $output_mode; 1042 my $func = "output_blockhead_" . $output_mode;
1043 &$func(@_); 1043 &$func(@_);
1044 $section_counter++; 1044 $section_counter++;
1045 } 1045 }
1046 1046
1047 ## 1047 ##
1048 # takes a declaration (struct, union, enum, typedef) and 1048 # takes a declaration (struct, union, enum, typedef) and
1049 # invokes the right handler. NOT called for functions. 1049 # invokes the right handler. NOT called for functions.
1050 sub dump_declaration($$) { 1050 sub dump_declaration($$) {
1051 no strict 'refs'; 1051 no strict 'refs';
1052 my ($prototype, $file) = @_; 1052 my ($prototype, $file) = @_;
1053 my $func = "dump_" . $decl_type; 1053 my $func = "dump_" . $decl_type;
1054 &$func(@_); 1054 &$func(@_);
1055 } 1055 }
1056 1056
1057 sub dump_union($$) { 1057 sub dump_union($$) {
1058 dump_struct(@_); 1058 dump_struct(@_);
1059 } 1059 }
1060 1060
1061 sub dump_struct($$) { 1061 sub dump_struct($$) {
1062 my $x = shift; 1062 my $x = shift;
1063 my $file = shift; 1063 my $file = shift;
1064 1064
1065 if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { 1065 if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) {
1066 my $decl_type = $1; 1066 my $decl_type = $1;
1067 $declaration_name = $2; 1067 $declaration_name = $2;
1068 my $members = $3; 1068 my $members = $3;
1069 1069
1070 # ignore members marked private: 1070 # ignore members marked private:
1071 $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; 1071 $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
1072 $members =~ s/\/\*\s*private:.*//gosi; 1072 $members =~ s/\/\*\s*private:.*//gosi;
1073 # strip comments: 1073 # strip comments:
1074 $members =~ s/\/\*.*?\*\///gos; 1074 $members =~ s/\/\*.*?\*\///gos;
1075 # strip attributes 1075 # strip attributes
1076 $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi; 1076 $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi;
1077 $members =~ s/\s*__aligned\s*\([^;]*\)//gos; 1077 $members =~ s/\s*__aligned\s*\([^;]*\)//gos;
1078 $members =~ s/\s*__packed\s*//gos; 1078 $members =~ s/\s*__packed\s*//gos;
1079 $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; 1079 $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
1080 # replace DECLARE_BITMAP 1080 # replace DECLARE_BITMAP
1081 $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; 1081 $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
1082 # replace DECLARE_HASHTABLE 1082 # replace DECLARE_HASHTABLE
1083 $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos; 1083 $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
1084 # replace DECLARE_KFIFO 1084 # replace DECLARE_KFIFO
1085 $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; 1085 $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
1086 # replace DECLARE_KFIFO_PTR 1086 # replace DECLARE_KFIFO_PTR
1087 $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; 1087 $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
1088 1088
1089 my $declaration = $members; 1089 my $declaration = $members;
1090 1090
1091 # Split nested struct/union elements as newer ones 1091 # Split nested struct/union elements as newer ones
1092 while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) { 1092 while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) {
1093 my $newmember; 1093 my $newmember;
1094 my $maintype = $1; 1094 my $maintype = $1;
1095 my $ids = $4; 1095 my $ids = $4;
1096 my $content = $3; 1096 my $content = $3;
1097 foreach my $id(split /,/, $ids) { 1097 foreach my $id(split /,/, $ids) {
1098 $newmember .= "$maintype $id; "; 1098 $newmember .= "$maintype $id; ";
1099 1099
1100 $id =~ s/[:\[].*//; 1100 $id =~ s/[:\[].*//;
1101 $id =~ s/^\s*\**(\S+)\s*/$1/; 1101 $id =~ s/^\s*\**(\S+)\s*/$1/;
1102 foreach my $arg (split /;/, $content) { 1102 foreach my $arg (split /;/, $content) {
1103 next if ($arg =~ m/^\s*$/); 1103 next if ($arg =~ m/^\s*$/);
1104 if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) { 1104 if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
1105 # pointer-to-function 1105 # pointer-to-function
1106 my $type = $1; 1106 my $type = $1;
1107 my $name = $2; 1107 my $name = $2;
1108 my $extra = $3; 1108 my $extra = $3;
1109 next if (!$name); 1109 next if (!$name);
1110 if ($id =~ m/^\s*$/) { 1110 if ($id =~ m/^\s*$/) {
1111 # anonymous struct/union 1111 # anonymous struct/union
1112 $newmember .= "$type$name$extra; "; 1112 $newmember .= "$type$name$extra; ";
1113 } else { 1113 } else {
1114 $newmember .= "$type$id.$name$extra; "; 1114 $newmember .= "$type$id.$name$extra; ";
1115 } 1115 }
1116 } else { 1116 } else {
1117 my $type; 1117 my $type;
1118 my $names; 1118 my $names;
1119 $arg =~ s/^\s+//; 1119 $arg =~ s/^\s+//;
1120 $arg =~ s/\s+$//; 1120 $arg =~ s/\s+$//;
1121 # Handle bitmaps 1121 # Handle bitmaps
1122 $arg =~ s/:\s*\d+\s*//g; 1122 $arg =~ s/:\s*\d+\s*//g;
1123 # Handle arrays 1123 # Handle arrays
1124 $arg =~ s/\[.*\]//g; 1124 $arg =~ s/\[.*\]//g;
1125 # The type may have multiple words, 1125 # The type may have multiple words,
1126 # and multiple IDs can be defined, like: 1126 # and multiple IDs can be defined, like:
1127 # const struct foo, *bar, foobar 1127 # const struct foo, *bar, foobar
1128 # So, we remove spaces when parsing the 1128 # So, we remove spaces when parsing the
1129 # names, in order to match just names 1129 # names, in order to match just names
1130 # and commas for the names 1130 # and commas for the names
1131 $arg =~ s/\s*,\s*/,/g; 1131 $arg =~ s/\s*,\s*/,/g;
1132 if ($arg =~ m/(.*)\s+([\S+,]+)/) { 1132 if ($arg =~ m/(.*)\s+([\S+,]+)/) {
1133 $type = $1; 1133 $type = $1;
1134 $names = $2; 1134 $names = $2;
1135 } else { 1135 } else {
1136 $newmember .= "$arg; "; 1136 $newmember .= "$arg; ";
1137 next; 1137 next;
1138 } 1138 }
1139 foreach my $name (split /,/, $names) { 1139 foreach my $name (split /,/, $names) {
1140 $name =~ s/^\s*\**(\S+)\s*/$1/; 1140 $name =~ s/^\s*\**(\S+)\s*/$1/;
1141 next if (($name =~ m/^\s*$/)); 1141 next if (($name =~ m/^\s*$/));
1142 if ($id =~ m/^\s*$/) { 1142 if ($id =~ m/^\s*$/) {
1143 # anonymous struct/union 1143 # anonymous struct/union
1144 $newmember .= "$type $name; "; 1144 $newmember .= "$type $name; ";
1145 } else { 1145 } else {
1146 $newmember .= "$type $id.$name; "; 1146 $newmember .= "$type $id.$name; ";
1147 } 1147 }
1148 } 1148 }
1149 } 1149 }
1150 } 1150 }
1151 } 1151 }
1152 $members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/$newmember/; 1152 $members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/$newmember/;
1153 } 1153 }
1154 1154
1155 # Ignore other nested elements, like enums 1155 # Ignore other nested elements, like enums
1156 $members =~ s/(\{[^\{\}]*\})//g; 1156 $members =~ s/(\{[^\{\}]*\})//g;
1157 1157
1158 create_parameterlist($members, ';', $file, $declaration_name); 1158 create_parameterlist($members, ';', $file, $declaration_name);
1159 check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual); 1159 check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
1160 1160
1161 # Adjust declaration for better display 1161 # Adjust declaration for better display
1162 $declaration =~ s/([\{;])/$1\n/g; 1162 $declaration =~ s/([\{;])/$1\n/g;
1163 $declaration =~ s/\}\s+;/};/g; 1163 $declaration =~ s/\}\s+;/};/g;
1164 # Better handle inlined enums 1164 # Better handle inlined enums
1165 do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/); 1165 do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
1166 1166
1167 my @def_args = split /\n/, $declaration; 1167 my @def_args = split /\n/, $declaration;
1168 my $level = 1; 1168 my $level = 1;
1169 $declaration = ""; 1169 $declaration = "";
1170 foreach my $clause (@def_args) { 1170 foreach my $clause (@def_args) {
1171 $clause =~ s/^\s+//; 1171 $clause =~ s/^\s+//;
1172 $clause =~ s/\s+$//; 1172 $clause =~ s/\s+$//;
1173 $clause =~ s/\s+/ /; 1173 $clause =~ s/\s+/ /;
1174 next if (!$clause); 1174 next if (!$clause);
1175 $level-- if ($clause =~ m/(\})/ && $level > 1); 1175 $level-- if ($clause =~ m/(\})/ && $level > 1);
1176 if (!($clause =~ m/^\s*#/)) { 1176 if (!($clause =~ m/^\s*#/)) {
1177 $declaration .= "\t" x $level; 1177 $declaration .= "\t" x $level;
1178 } 1178 }
1179 $declaration .= "\t" . $clause . "\n"; 1179 $declaration .= "\t" . $clause . "\n";
1180 $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/)); 1180 $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
1181 } 1181 }
1182 output_declaration($declaration_name, 1182 output_declaration($declaration_name,
1183 'struct', 1183 'struct',
1184 {'struct' => $declaration_name, 1184 {'struct' => $declaration_name,
1185 'module' => $modulename, 1185 'module' => $modulename,
1186 'definition' => $declaration, 1186 'definition' => $declaration,
1187 'parameterlist' => \@parameterlist, 1187 'parameterlist' => \@parameterlist,
1188 'parameterdescs' => \%parameterdescs, 1188 'parameterdescs' => \%parameterdescs,
1189 'parametertypes' => \%parametertypes, 1189 'parametertypes' => \%parametertypes,
1190 'sectionlist' => \@sectionlist, 1190 'sectionlist' => \@sectionlist,
1191 'sections' => \%sections, 1191 'sections' => \%sections,
1192 'purpose' => $declaration_purpose, 1192 'purpose' => $declaration_purpose,
1193 'type' => $decl_type 1193 'type' => $decl_type
1194 }); 1194 });
1195 } 1195 }
1196 else { 1196 else {
1197 print STDERR "${file}:$.: error: Cannot parse struct or union!\n"; 1197 print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
1198 ++$errors; 1198 ++$errors;
1199 } 1199 }
1200 } 1200 }
1201 1201
1202 1202
1203 sub show_warnings($$) { 1203 sub show_warnings($$) {
1204 my $functype = shift; 1204 my $functype = shift;
1205 my $name = shift; 1205 my $name = shift;
1206 1206
1207 return 1 if ($output_selection == OUTPUT_ALL); 1207 return 1 if ($output_selection == OUTPUT_ALL);
1208 1208
1209 if ($output_selection == OUTPUT_EXPORTED) { 1209 if ($output_selection == OUTPUT_EXPORTED) {
1210 if (defined($function_table{$name})) { 1210 if (defined($function_table{$name})) {
1211 return 1; 1211 return 1;
1212 } else { 1212 } else {
1213 return 0; 1213 return 0;
1214 } 1214 }
1215 } 1215 }
1216 if ($output_selection == OUTPUT_INTERNAL) { 1216 if ($output_selection == OUTPUT_INTERNAL) {
1217 if (!($functype eq "function" && defined($function_table{$name}))) { 1217 if (!($functype eq "function" && defined($function_table{$name}))) {
1218 return 1; 1218 return 1;
1219 } else { 1219 } else {
1220 return 0; 1220 return 0;
1221 } 1221 }
1222 } 1222 }
1223 if ($output_selection == OUTPUT_INCLUDE) { 1223 if ($output_selection == OUTPUT_INCLUDE) {
1224 if (defined($function_table{$name})) { 1224 if (defined($function_table{$name})) {
1225 return 1; 1225 return 1;
1226 } else { 1226 } else {
1227 return 0; 1227 return 0;
1228 } 1228 }
1229 } 1229 }
1230 if ($output_selection == OUTPUT_EXCLUDE) { 1230 if ($output_selection == OUTPUT_EXCLUDE) {
1231 if (!defined($function_table{$name})) { 1231 if (!defined($function_table{$name})) {
1232 return 1; 1232 return 1;
1233 } else { 1233 } else {
1234 return 0; 1234 return 0;
1235 } 1235 }
1236 } 1236 }
1237 die("Please add the new output type at show_warnings()"); 1237 die("Please add the new output type at show_warnings()");
1238 } 1238 }
1239 1239
1240 sub dump_enum($$) { 1240 sub dump_enum($$) {
1241 my $x = shift; 1241 my $x = shift;
1242 my $file = shift; 1242 my $file = shift;
1243 1243
1244 $x =~ s@/\*.*?\*/@@gos; # strip comments. 1244 $x =~ s@/\*.*?\*/@@gos; # strip comments.
1245 # strip #define macros inside enums 1245 # strip #define macros inside enums
1246 $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; 1246 $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
1247 1247
1248 if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) { 1248 if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) {
1249 $declaration_name = $1; 1249 $declaration_name = $1;
1250 my $members = $2; 1250 my $members = $2;
1251 my %_members; 1251 my %_members;
1252 1252
1253 $members =~ s/\s+$//; 1253 $members =~ s/\s+$//;
1254 1254
1255 foreach my $arg (split ',', $members) { 1255 foreach my $arg (split ',', $members) {
1256 $arg =~ s/^\s*(\w+).*/$1/; 1256 $arg =~ s/^\s*(\w+).*/$1/;
1257 push @parameterlist, $arg; 1257 push @parameterlist, $arg;
1258 if (!$parameterdescs{$arg}) { 1258 if (!$parameterdescs{$arg}) {
1259 $parameterdescs{$arg} = $undescribed; 1259 $parameterdescs{$arg} = $undescribed;
1260 if (show_warnings("enum", $declaration_name)) { 1260 if (show_warnings("enum", $declaration_name)) {
1261 print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n"; 1261 print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n";
1262 } 1262 }
1263 } 1263 }
1264 $_members{$arg} = 1; 1264 $_members{$arg} = 1;
1265 } 1265 }
1266 1266
1267 while (my ($k, $v) = each %parameterdescs) { 1267 while (my ($k, $v) = each %parameterdescs) {
1268 if (!exists($_members{$k})) { 1268 if (!exists($_members{$k})) {
1269 if (show_warnings("enum", $declaration_name)) { 1269 if (show_warnings("enum", $declaration_name)) {
1270 print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n"; 1270 print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n";
1271 } 1271 }
1272 } 1272 }
1273 } 1273 }
1274 1274
1275 output_declaration($declaration_name, 1275 output_declaration($declaration_name,
1276 'enum', 1276 'enum',
1277 {'enum' => $declaration_name, 1277 {'enum' => $declaration_name,
1278 'module' => $modulename, 1278 'module' => $modulename,
1279 'parameterlist' => \@parameterlist, 1279 'parameterlist' => \@parameterlist,
1280 'parameterdescs' => \%parameterdescs, 1280 'parameterdescs' => \%parameterdescs,
1281 'sectionlist' => \@sectionlist, 1281 'sectionlist' => \@sectionlist,
1282 'sections' => \%sections, 1282 'sections' => \%sections,
1283 'purpose' => $declaration_purpose 1283 'purpose' => $declaration_purpose
1284 }); 1284 });
1285 } 1285 }
1286 else { 1286 else {
1287 print STDERR "${file}:$.: error: Cannot parse enum!\n"; 1287 print STDERR "${file}:$.: error: Cannot parse enum!\n";
1288 ++$errors; 1288 ++$errors;
1289 } 1289 }
1290 } 1290 }
1291 1291
1292 sub dump_typedef($$) { 1292 sub dump_typedef($$) {
1293 my $x = shift; 1293 my $x = shift;
1294 my $file = shift; 1294 my $file = shift;
1295 1295
1296 $x =~ s@/\*.*?\*/@@gos; # strip comments. 1296 $x =~ s@/\*.*?\*/@@gos; # strip comments.
1297 1297
1298 # Parse function prototypes 1298 # Parse function prototypes
1299 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || 1299 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
1300 $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { 1300 $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
1301 1301
1302 # Function typedefs 1302 # Function typedefs
1303 $return_type = $1; 1303 $return_type = $1;
1304 $declaration_name = $2; 1304 $declaration_name = $2;
1305 my $args = $3; 1305 my $args = $3;
1306 1306
1307 create_parameterlist($args, ',', $file, $declaration_name); 1307 create_parameterlist($args, ',', $file, $declaration_name);
1308 1308
1309 output_declaration($declaration_name, 1309 output_declaration($declaration_name,
1310 'function', 1310 'function',
1311 {'function' => $declaration_name, 1311 {'function' => $declaration_name,
1312 'typedef' => 1, 1312 'typedef' => 1,
1313 'module' => $modulename, 1313 'module' => $modulename,
1314 'functiontype' => $return_type, 1314 'functiontype' => $return_type,
1315 'parameterlist' => \@parameterlist, 1315 'parameterlist' => \@parameterlist,
1316 'parameterdescs' => \%parameterdescs, 1316 'parameterdescs' => \%parameterdescs,
1317 'parametertypes' => \%parametertypes, 1317 'parametertypes' => \%parametertypes,
1318 'sectionlist' => \@sectionlist, 1318 'sectionlist' => \@sectionlist,
1319 'sections' => \%sections, 1319 'sections' => \%sections,
1320 'purpose' => $declaration_purpose 1320 'purpose' => $declaration_purpose
1321 }); 1321 });
1322 return; 1322 return;
1323 } 1323 }
1324 1324
1325 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 1325 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
1326 $x =~ s/\(*.\)\s*;$/;/; 1326 $x =~ s/\(*.\)\s*;$/;/;
1327 $x =~ s/\[*.\]\s*;$/;/; 1327 $x =~ s/\[*.\]\s*;$/;/;
1328 } 1328 }
1329 1329
1330 if ($x =~ /typedef.*\s+(\w+)\s*;/) { 1330 if ($x =~ /typedef.*\s+(\w+)\s*;/) {
1331 $declaration_name = $1; 1331 $declaration_name = $1;
1332 1332
1333 output_declaration($declaration_name, 1333 output_declaration($declaration_name,
1334 'typedef', 1334 'typedef',
1335 {'typedef' => $declaration_name, 1335 {'typedef' => $declaration_name,
1336 'module' => $modulename, 1336 'module' => $modulename,
1337 'sectionlist' => \@sectionlist, 1337 'sectionlist' => \@sectionlist,
1338 'sections' => \%sections, 1338 'sections' => \%sections,
1339 'purpose' => $declaration_purpose 1339 'purpose' => $declaration_purpose
1340 }); 1340 });
1341 } 1341 }
1342 else { 1342 else {
1343 print STDERR "${file}:$.: error: Cannot parse typedef!\n"; 1343 print STDERR "${file}:$.: error: Cannot parse typedef!\n";
1344 ++$errors; 1344 ++$errors;
1345 } 1345 }
1346 } 1346 }
1347 1347
1348 sub save_struct_actual($) { 1348 sub save_struct_actual($) {
1349 my $actual = shift; 1349 my $actual = shift;
1350 1350
1351 # strip all spaces from the actual param so that it looks like one string item 1351 # strip all spaces from the actual param so that it looks like one string item
1352 $actual =~ s/\s*//g; 1352 $actual =~ s/\s*//g;
1353 $struct_actual = $struct_actual . $actual . " "; 1353 $struct_actual = $struct_actual . $actual . " ";
1354 } 1354 }
1355 1355
1356 sub create_parameterlist($$$$) { 1356 sub create_parameterlist($$$$) {
1357 my $args = shift; 1357 my $args = shift;
1358 my $splitter = shift; 1358 my $splitter = shift;
1359 my $file = shift; 1359 my $file = shift;
1360 my $declaration_name = shift; 1360 my $declaration_name = shift;
1361 my $type; 1361 my $type;
1362 my $param; 1362 my $param;
1363 1363
1364 # temporarily replace commas inside function pointer definition 1364 # temporarily replace commas inside function pointer definition
1365 while ($args =~ /(\([^\),]+),/) { 1365 while ($args =~ /(\([^\),]+),/) {
1366 $args =~ s/(\([^\),]+),/$1#/g; 1366 $args =~ s/(\([^\),]+),/$1#/g;
1367 } 1367 }
1368 1368
1369 foreach my $arg (split($splitter, $args)) { 1369 foreach my $arg (split($splitter, $args)) {
1370 # strip comments 1370 # strip comments
1371 $arg =~ s/\/\*.*\*\///; 1371 $arg =~ s/\/\*.*\*\///;
1372 # strip leading/trailing spaces 1372 # strip leading/trailing spaces
1373 $arg =~ s/^\s*//; 1373 $arg =~ s/^\s*//;
1374 $arg =~ s/\s*$//; 1374 $arg =~ s/\s*$//;
1375 $arg =~ s/\s+/ /; 1375 $arg =~ s/\s+/ /;
1376 1376
1377 if ($arg =~ /^#/) { 1377 if ($arg =~ /^#/) {
1378 # Treat preprocessor directive as a typeless variable just to fill 1378 # Treat preprocessor directive as a typeless variable just to fill
1379 # corresponding data structures "correctly". Catch it later in 1379 # corresponding data structures "correctly". Catch it later in
1380 # output_* subs. 1380 # output_* subs.
1381 push_parameter($arg, "", $file); 1381 push_parameter($arg, "", $file);
1382 } elsif ($arg =~ m/\(.+\)\s*\(/) { 1382 } elsif ($arg =~ m/\(.+\)\s*\(/) {
1383 # pointer-to-function 1383 # pointer-to-function
1384 $arg =~ tr/#/,/; 1384 $arg =~ tr/#/,/;
1385 $arg =~ m/[^\(]+\(\*?\s*([\w\.]*)\s*\)/; 1385 $arg =~ m/[^\(]+\([\w\s]*\*?\s*([\w\.]*)\s*\)/;
1386 $param = $1; 1386 $param = $1;
1387 $type = $arg; 1387 $type = $arg;
1388 $type =~ s/([^\(]+\(\*?)\s*$param/$1/; 1388 $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
1389 save_struct_actual($param); 1389 save_struct_actual($param);
1390 push_parameter($param, $type, $file, $declaration_name); 1390 push_parameter($param, $type, $file, $declaration_name);
1391 } elsif ($arg) { 1391 } elsif ($arg) {
1392 $arg =~ s/\s*:\s*/:/g; 1392 $arg =~ s/\s*:\s*/:/g;
1393 $arg =~ s/\s*\[/\[/g; 1393 $arg =~ s/\s*\[/\[/g;
1394 1394
1395 my @args = split('\s*,\s*', $arg); 1395 my @args = split('\s*,\s*', $arg);
1396 if ($args[0] =~ m/\*/) { 1396 if ($args[0] =~ m/\*/) {
1397 $args[0] =~ s/(\*+)\s*/ $1/; 1397 $args[0] =~ s/(\*+)\s*/ $1/;
1398 } 1398 }
1399 1399
1400 my @first_arg; 1400 my @first_arg;
1401 if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { 1401 if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
1402 shift @args; 1402 shift @args;
1403 push(@first_arg, split('\s+', $1)); 1403 push(@first_arg, split('\s+', $1));
1404 push(@first_arg, $2); 1404 push(@first_arg, $2);
1405 } else { 1405 } else {
1406 @first_arg = split('\s+', shift @args); 1406 @first_arg = split('\s+', shift @args);
1407 } 1407 }
1408 1408
1409 unshift(@args, pop @first_arg); 1409 unshift(@args, pop @first_arg);
1410 $type = join " ", @first_arg; 1410 $type = join " ", @first_arg;
1411 1411
1412 foreach $param (@args) { 1412 foreach $param (@args) {
1413 if ($param =~ m/^(\*+)\s*(.*)/) { 1413 if ($param =~ m/^(\*+)\s*(.*)/) {
1414 save_struct_actual($2); 1414 save_struct_actual($2);
1415 push_parameter($2, "$type $1", $file, $declaration_name); 1415 push_parameter($2, "$type $1", $file, $declaration_name);
1416 } 1416 }
1417 elsif ($param =~ m/(.*?):(\d+)/) { 1417 elsif ($param =~ m/(.*?):(\d+)/) {
1418 if ($type ne "") { # skip unnamed bit-fields 1418 if ($type ne "") { # skip unnamed bit-fields
1419 save_struct_actual($1); 1419 save_struct_actual($1);
1420 push_parameter($1, "$type:$2", $file, $declaration_name) 1420 push_parameter($1, "$type:$2", $file, $declaration_name)
1421 } 1421 }
1422 } 1422 }
1423 else { 1423 else {
1424 save_struct_actual($param); 1424 save_struct_actual($param);
1425 push_parameter($param, $type, $file, $declaration_name); 1425 push_parameter($param, $type, $file, $declaration_name);
1426 } 1426 }
1427 } 1427 }
1428 } 1428 }
1429 } 1429 }
1430 } 1430 }
1431 1431
1432 sub push_parameter($$$$) { 1432 sub push_parameter($$$$) {
1433 my $param = shift; 1433 my $param = shift;
1434 my $type = shift; 1434 my $type = shift;
1435 my $file = shift; 1435 my $file = shift;
1436 my $declaration_name = shift; 1436 my $declaration_name = shift;
1437 1437
1438 if (($anon_struct_union == 1) && ($type eq "") && 1438 if (($anon_struct_union == 1) && ($type eq "") &&
1439 ($param eq "}")) { 1439 ($param eq "}")) {
1440 return; # ignore the ending }; from anon. struct/union 1440 return; # ignore the ending }; from anon. struct/union
1441 } 1441 }
1442 1442
1443 $anon_struct_union = 0; 1443 $anon_struct_union = 0;
1444 $param =~ s/[\[\)].*//; 1444 $param =~ s/[\[\)].*//;
1445 1445
1446 if ($type eq "" && $param =~ /\.\.\.$/) 1446 if ($type eq "" && $param =~ /\.\.\.$/)
1447 { 1447 {
1448 if (!$param =~ /\w\.\.\.$/) { 1448 if (!$param =~ /\w\.\.\.$/) {
1449 # handles unnamed variable parameters 1449 # handles unnamed variable parameters
1450 $param = "..."; 1450 $param = "...";
1451 } 1451 }
1452 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { 1452 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
1453 $parameterdescs{$param} = "variable arguments"; 1453 $parameterdescs{$param} = "variable arguments";
1454 } 1454 }
1455 } 1455 }
1456 elsif ($type eq "" && ($param eq "" or $param eq "void")) 1456 elsif ($type eq "" && ($param eq "" or $param eq "void"))
1457 { 1457 {
1458 $param="void"; 1458 $param="void";
1459 $parameterdescs{void} = "no arguments"; 1459 $parameterdescs{void} = "no arguments";
1460 } 1460 }
1461 elsif ($type eq "" && ($param eq "struct" or $param eq "union")) 1461 elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
1462 # handle unnamed (anonymous) union or struct: 1462 # handle unnamed (anonymous) union or struct:
1463 { 1463 {
1464 $type = $param; 1464 $type = $param;
1465 $param = "{unnamed_" . $param . "}"; 1465 $param = "{unnamed_" . $param . "}";
1466 $parameterdescs{$param} = "anonymous\n"; 1466 $parameterdescs{$param} = "anonymous\n";
1467 $anon_struct_union = 1; 1467 $anon_struct_union = 1;
1468 } 1468 }
1469 1469
1470 # warn if parameter has no description 1470 # warn if parameter has no description
1471 # (but ignore ones starting with # as these are not parameters 1471 # (but ignore ones starting with # as these are not parameters
1472 # but inline preprocessor statements); 1472 # but inline preprocessor statements);
1473 # Note: It will also ignore void params and unnamed structs/unions 1473 # Note: It will also ignore void params and unnamed structs/unions
1474 if (!defined $parameterdescs{$param} && $param !~ /^#/) { 1474 if (!defined $parameterdescs{$param} && $param !~ /^#/) {
1475 $parameterdescs{$param} = $undescribed; 1475 $parameterdescs{$param} = $undescribed;
1476 1476
1477 if (show_warnings($type, $declaration_name) && $param !~ /\./) { 1477 if (show_warnings($type, $declaration_name) && $param !~ /\./) {
1478 print STDERR 1478 print STDERR
1479 "${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n"; 1479 "${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n";
1480 ++$warnings; 1480 ++$warnings;
1481 } 1481 }
1482 } 1482 }
1483 1483
1484 # strip spaces from $param so that it is one continuous string 1484 # strip spaces from $param so that it is one continuous string
1485 # on @parameterlist; 1485 # on @parameterlist;
1486 # this fixes a problem where check_sections() cannot find 1486 # this fixes a problem where check_sections() cannot find
1487 # a parameter like "addr[6 + 2]" because it actually appears 1487 # a parameter like "addr[6 + 2]" because it actually appears
1488 # as "addr[6", "+", "2]" on the parameter list; 1488 # as "addr[6", "+", "2]" on the parameter list;
1489 # but it's better to maintain the param string unchanged for output, 1489 # but it's better to maintain the param string unchanged for output,
1490 # so just weaken the string compare in check_sections() to ignore 1490 # so just weaken the string compare in check_sections() to ignore
1491 # "[blah" in a parameter string; 1491 # "[blah" in a parameter string;
1492 ###$param =~ s/\s*//g; 1492 ###$param =~ s/\s*//g;
1493 push @parameterlist, $param; 1493 push @parameterlist, $param;
1494 $type =~ s/\s\s+/ /g; 1494 $type =~ s/\s\s+/ /g;
1495 $parametertypes{$param} = $type; 1495 $parametertypes{$param} = $type;
1496 } 1496 }
1497 1497
1498 sub check_sections($$$$$) { 1498 sub check_sections($$$$$) {
1499 my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_; 1499 my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
1500 my @sects = split ' ', $sectcheck; 1500 my @sects = split ' ', $sectcheck;
1501 my @prms = split ' ', $prmscheck; 1501 my @prms = split ' ', $prmscheck;
1502 my $err; 1502 my $err;
1503 my ($px, $sx); 1503 my ($px, $sx);
1504 my $prm_clean; # strip trailing "[array size]" and/or beginning "*" 1504 my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
1505 1505
1506 foreach $sx (0 .. $#sects) { 1506 foreach $sx (0 .. $#sects) {
1507 $err = 1; 1507 $err = 1;
1508 foreach $px (0 .. $#prms) { 1508 foreach $px (0 .. $#prms) {
1509 $prm_clean = $prms[$px]; 1509 $prm_clean = $prms[$px];
1510 $prm_clean =~ s/\[.*\]//; 1510 $prm_clean =~ s/\[.*\]//;
1511 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; 1511 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
1512 # ignore array size in a parameter string; 1512 # ignore array size in a parameter string;
1513 # however, the original param string may contain 1513 # however, the original param string may contain
1514 # spaces, e.g.: addr[6 + 2] 1514 # spaces, e.g.: addr[6 + 2]
1515 # and this appears in @prms as "addr[6" since the 1515 # and this appears in @prms as "addr[6" since the
1516 # parameter list is split at spaces; 1516 # parameter list is split at spaces;
1517 # hence just ignore "[..." for the sections check; 1517 # hence just ignore "[..." for the sections check;
1518 $prm_clean =~ s/\[.*//; 1518 $prm_clean =~ s/\[.*//;
1519 1519
1520 ##$prm_clean =~ s/^\**//; 1520 ##$prm_clean =~ s/^\**//;
1521 if ($prm_clean eq $sects[$sx]) { 1521 if ($prm_clean eq $sects[$sx]) {
1522 $err = 0; 1522 $err = 0;
1523 last; 1523 last;
1524 } 1524 }
1525 } 1525 }
1526 if ($err) { 1526 if ($err) {
1527 if ($decl_type eq "function") { 1527 if ($decl_type eq "function") {
1528 print STDERR "${file}:$.: warning: " . 1528 print STDERR "${file}:$.: warning: " .
1529 "Excess function parameter " . 1529 "Excess function parameter " .
1530 "'$sects[$sx]' " . 1530 "'$sects[$sx]' " .
1531 "description in '$decl_name'\n"; 1531 "description in '$decl_name'\n";
1532 ++$warnings; 1532 ++$warnings;
1533 } 1533 }
1534 } 1534 }
1535 } 1535 }
1536 } 1536 }
1537 1537
1538 ## 1538 ##
1539 # Checks the section describing the return value of a function. 1539 # Checks the section describing the return value of a function.
1540 sub check_return_section { 1540 sub check_return_section {
1541 my $file = shift; 1541 my $file = shift;
1542 my $declaration_name = shift; 1542 my $declaration_name = shift;
1543 my $return_type = shift; 1543 my $return_type = shift;
1544 1544
1545 # Ignore an empty return type (It's a macro) 1545 # Ignore an empty return type (It's a macro)
1546 # Ignore functions with a "void" return type. (But don't ignore "void *") 1546 # Ignore functions with a "void" return type. (But don't ignore "void *")
1547 if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) { 1547 if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
1548 return; 1548 return;
1549 } 1549 }
1550 1550
1551 if (!defined($sections{$section_return}) || 1551 if (!defined($sections{$section_return}) ||
1552 $sections{$section_return} eq "") { 1552 $sections{$section_return} eq "") {
1553 print STDERR "${file}:$.: warning: " . 1553 print STDERR "${file}:$.: warning: " .
1554 "No description found for return value of " . 1554 "No description found for return value of " .
1555 "'$declaration_name'\n"; 1555 "'$declaration_name'\n";
1556 ++$warnings; 1556 ++$warnings;
1557 } 1557 }
1558 } 1558 }
1559 1559
1560 ## 1560 ##
1561 # takes a function prototype and the name of the current file being 1561 # takes a function prototype and the name of the current file being
1562 # processed and spits out all the details stored in the global 1562 # processed and spits out all the details stored in the global
1563 # arrays/hashes. 1563 # arrays/hashes.
1564 sub dump_function($$) { 1564 sub dump_function($$) {
1565 my $prototype = shift; 1565 my $prototype = shift;
1566 my $file = shift; 1566 my $file = shift;
1567 my $noret = 0; 1567 my $noret = 0;
1568 1568
1569 $prototype =~ s/^static +//; 1569 $prototype =~ s/^static +//;
1570 $prototype =~ s/^extern +//; 1570 $prototype =~ s/^extern +//;
1571 $prototype =~ s/^asmlinkage +//; 1571 $prototype =~ s/^asmlinkage +//;
1572 $prototype =~ s/^inline +//; 1572 $prototype =~ s/^inline +//;
1573 $prototype =~ s/^__inline__ +//; 1573 $prototype =~ s/^__inline__ +//;
1574 $prototype =~ s/^__inline +//; 1574 $prototype =~ s/^__inline +//;
1575 $prototype =~ s/^__always_inline +//; 1575 $prototype =~ s/^__always_inline +//;
1576 $prototype =~ s/^noinline +//; 1576 $prototype =~ s/^noinline +//;
1577 $prototype =~ s/__init +//; 1577 $prototype =~ s/__init +//;
1578 $prototype =~ s/__init_or_module +//; 1578 $prototype =~ s/__init_or_module +//;
1579 $prototype =~ s/__meminit +//; 1579 $prototype =~ s/__meminit +//;
1580 $prototype =~ s/__must_check +//; 1580 $prototype =~ s/__must_check +//;
1581 $prototype =~ s/__weak +//; 1581 $prototype =~ s/__weak +//;
1582 $prototype =~ s/__sched +//; 1582 $prototype =~ s/__sched +//;
1583 my $define = $prototype =~ s/^#\s*define\s+//; #ak added 1583 my $define = $prototype =~ s/^#\s*define\s+//; #ak added
1584 $prototype =~ s/__attribute__\s*\(\( 1584 $prototype =~ s/__attribute__\s*\(\(
1585 (?: 1585 (?:
1586 [\w\s]++ # attribute name 1586 [\w\s]++ # attribute name
1587 (?:\([^)]*+\))? # attribute arguments 1587 (?:\([^)]*+\))? # attribute arguments
1588 \s*+,? # optional comma at the end 1588 \s*+,? # optional comma at the end
1589 )+ 1589 )+
1590 \)\)\s+//x; 1590 \)\)\s+//x;
1591 1591
1592 # Yes, this truly is vile. We are looking for: 1592 # Yes, this truly is vile. We are looking for:
1593 # 1. Return type (may be nothing if we're looking at a macro) 1593 # 1. Return type (may be nothing if we're looking at a macro)
1594 # 2. Function name 1594 # 2. Function name
1595 # 3. Function parameters. 1595 # 3. Function parameters.
1596 # 1596 #
1597 # All the while we have to watch out for function pointer parameters 1597 # All the while we have to watch out for function pointer parameters
1598 # (which IIRC is what the two sections are for), C types (these 1598 # (which IIRC is what the two sections are for), C types (these
1599 # regexps don't even start to express all the possibilities), and 1599 # regexps don't even start to express all the possibilities), and
1600 # so on. 1600 # so on.
1601 # 1601 #
1602 # If you mess with these regexps, it's a good idea to check that 1602 # If you mess with these regexps, it's a good idea to check that
1603 # the following functions' documentation still comes out right: 1603 # the following functions' documentation still comes out right:
1604 # - parport_register_device (function pointer parameters) 1604 # - parport_register_device (function pointer parameters)
1605 # - atomic_set (macro) 1605 # - atomic_set (macro)
1606 # - pci_match_device, __copy_to_user (long return type) 1606 # - pci_match_device, __copy_to_user (long return type)
1607 1607
1608 if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) { 1608 if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) {
1609 # This is an object-like macro, it has no return type and no parameter 1609 # This is an object-like macro, it has no return type and no parameter
1610 # list. 1610 # list.
1611 # Function-like macros are not allowed to have spaces between 1611 # Function-like macros are not allowed to have spaces between
1612 # declaration_name and opening parenthesis (notice the \s+). 1612 # declaration_name and opening parenthesis (notice the \s+).
1613 $return_type = $1; 1613 $return_type = $1;
1614 $declaration_name = $2; 1614 $declaration_name = $2;
1615 $noret = 1; 1615 $noret = 1;
1616 } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1616 } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1617 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1617 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1618 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1618 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1619 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1619 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1620 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1620 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1621 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1621 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1622 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1622 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1623 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1623 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1624 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1624 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1625 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1625 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1626 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1626 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1627 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1627 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1628 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1628 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1629 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1629 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1630 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1630 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1631 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1631 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1632 $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { 1632 $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
1633 $return_type = $1; 1633 $return_type = $1;
1634 $declaration_name = $2; 1634 $declaration_name = $2;
1635 my $args = $3; 1635 my $args = $3;
1636 1636
1637 create_parameterlist($args, ',', $file, $declaration_name); 1637 create_parameterlist($args, ',', $file, $declaration_name);
1638 } else { 1638 } else {
1639 print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n"; 1639 print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n";
1640 return; 1640 return;
1641 } 1641 }
1642 1642
1643 my $prms = join " ", @parameterlist; 1643 my $prms = join " ", @parameterlist;
1644 check_sections($file, $declaration_name, "function", $sectcheck, $prms); 1644 check_sections($file, $declaration_name, "function", $sectcheck, $prms);
1645 1645
1646 # This check emits a lot of warnings at the moment, because many 1646 # This check emits a lot of warnings at the moment, because many
1647 # functions don't have a 'Return' doc section. So until the number 1647 # functions don't have a 'Return' doc section. So until the number
1648 # of warnings goes sufficiently down, the check is only performed in 1648 # of warnings goes sufficiently down, the check is only performed in
1649 # verbose mode. 1649 # verbose mode.
1650 # TODO: always perform the check. 1650 # TODO: always perform the check.
1651 if ($verbose && !$noret) { 1651 if ($verbose && !$noret) {
1652 check_return_section($file, $declaration_name, $return_type); 1652 check_return_section($file, $declaration_name, $return_type);
1653 } 1653 }
1654 1654
1655 output_declaration($declaration_name, 1655 output_declaration($declaration_name,
1656 'function', 1656 'function',
1657 {'function' => $declaration_name, 1657 {'function' => $declaration_name,
1658 'module' => $modulename, 1658 'module' => $modulename,
1659 'functiontype' => $return_type, 1659 'functiontype' => $return_type,
1660 'parameterlist' => \@parameterlist, 1660 'parameterlist' => \@parameterlist,
1661 'parameterdescs' => \%parameterdescs, 1661 'parameterdescs' => \%parameterdescs,
1662 'parametertypes' => \%parametertypes, 1662 'parametertypes' => \%parametertypes,
1663 'sectionlist' => \@sectionlist, 1663 'sectionlist' => \@sectionlist,
1664 'sections' => \%sections, 1664 'sections' => \%sections,
1665 'purpose' => $declaration_purpose 1665 'purpose' => $declaration_purpose
1666 }); 1666 });
1667 } 1667 }
1668 1668
1669 sub reset_state { 1669 sub reset_state {
1670 $function = ""; 1670 $function = "";
1671 %parameterdescs = (); 1671 %parameterdescs = ();
1672 %parametertypes = (); 1672 %parametertypes = ();
1673 @parameterlist = (); 1673 @parameterlist = ();
1674 %sections = (); 1674 %sections = ();
1675 @sectionlist = (); 1675 @sectionlist = ();
1676 $sectcheck = ""; 1676 $sectcheck = "";
1677 $struct_actual = ""; 1677 $struct_actual = "";
1678 $prototype = ""; 1678 $prototype = "";
1679 1679
1680 $state = STATE_NORMAL; 1680 $state = STATE_NORMAL;
1681 $inline_doc_state = STATE_INLINE_NA; 1681 $inline_doc_state = STATE_INLINE_NA;
1682 } 1682 }
1683 1683
1684 sub tracepoint_munge($) { 1684 sub tracepoint_munge($) {
1685 my $file = shift; 1685 my $file = shift;
1686 my $tracepointname = 0; 1686 my $tracepointname = 0;
1687 my $tracepointargs = 0; 1687 my $tracepointargs = 0;
1688 1688
1689 if ($prototype =~ m/TRACE_EVENT\((.*?),/) { 1689 if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
1690 $tracepointname = $1; 1690 $tracepointname = $1;
1691 } 1691 }
1692 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) { 1692 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
1693 $tracepointname = $1; 1693 $tracepointname = $1;
1694 } 1694 }
1695 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) { 1695 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
1696 $tracepointname = $2; 1696 $tracepointname = $2;
1697 } 1697 }
1698 $tracepointname =~ s/^\s+//; #strip leading whitespace 1698 $tracepointname =~ s/^\s+//; #strip leading whitespace
1699 if ($prototype =~ m/TP_PROTO\((.*?)\)/) { 1699 if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
1700 $tracepointargs = $1; 1700 $tracepointargs = $1;
1701 } 1701 }
1702 if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 1702 if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
1703 print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". 1703 print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n".
1704 "$prototype\n"; 1704 "$prototype\n";
1705 } else { 1705 } else {
1706 $prototype = "static inline void trace_$tracepointname($tracepointargs)"; 1706 $prototype = "static inline void trace_$tracepointname($tracepointargs)";
1707 } 1707 }
1708 } 1708 }
1709 1709
1710 sub syscall_munge() { 1710 sub syscall_munge() {
1711 my $void = 0; 1711 my $void = 0;
1712 1712
1713 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's 1713 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
1714 ## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) { 1714 ## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
1715 if ($prototype =~ m/SYSCALL_DEFINE0/) { 1715 if ($prototype =~ m/SYSCALL_DEFINE0/) {
1716 $void = 1; 1716 $void = 1;
1717 ## $prototype = "long sys_$1(void)"; 1717 ## $prototype = "long sys_$1(void)";
1718 } 1718 }
1719 1719
1720 $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name 1720 $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
1721 if ($prototype =~ m/long (sys_.*?),/) { 1721 if ($prototype =~ m/long (sys_.*?),/) {
1722 $prototype =~ s/,/\(/; 1722 $prototype =~ s/,/\(/;
1723 } elsif ($void) { 1723 } elsif ($void) {
1724 $prototype =~ s/\)/\(void\)/; 1724 $prototype =~ s/\)/\(void\)/;
1725 } 1725 }
1726 1726
1727 # now delete all of the odd-number commas in $prototype 1727 # now delete all of the odd-number commas in $prototype
1728 # so that arg types & arg names don't have a comma between them 1728 # so that arg types & arg names don't have a comma between them
1729 my $count = 0; 1729 my $count = 0;
1730 my $len = length($prototype); 1730 my $len = length($prototype);
1731 if ($void) { 1731 if ($void) {
1732 $len = 0; # skip the for-loop 1732 $len = 0; # skip the for-loop
1733 } 1733 }
1734 for (my $ix = 0; $ix < $len; $ix++) { 1734 for (my $ix = 0; $ix < $len; $ix++) {
1735 if (substr($prototype, $ix, 1) eq ',') { 1735 if (substr($prototype, $ix, 1) eq ',') {
1736 $count++; 1736 $count++;
1737 if ($count % 2 == 1) { 1737 if ($count % 2 == 1) {
1738 substr($prototype, $ix, 1) = ' '; 1738 substr($prototype, $ix, 1) = ' ';
1739 } 1739 }
1740 } 1740 }
1741 } 1741 }
1742 } 1742 }
1743 1743
1744 sub process_proto_function($$) { 1744 sub process_proto_function($$) {
1745 my $x = shift; 1745 my $x = shift;
1746 my $file = shift; 1746 my $file = shift;
1747 1747
1748 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 1748 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1749 1749
1750 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { 1750 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
1751 # do nothing 1751 # do nothing
1752 } 1752 }
1753 elsif ($x =~ /([^\{]*)/) { 1753 elsif ($x =~ /([^\{]*)/) {
1754 $prototype .= $1; 1754 $prototype .= $1;
1755 } 1755 }
1756 1756
1757 if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) { 1757 if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
1758 $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 1758 $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
1759 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1759 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1760 $prototype =~ s@^\s+@@gos; # strip leading spaces 1760 $prototype =~ s@^\s+@@gos; # strip leading spaces
1761 if ($prototype =~ /SYSCALL_DEFINE/) { 1761 if ($prototype =~ /SYSCALL_DEFINE/) {
1762 syscall_munge(); 1762 syscall_munge();
1763 } 1763 }
1764 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ || 1764 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
1765 $prototype =~ /DEFINE_SINGLE_EVENT/) 1765 $prototype =~ /DEFINE_SINGLE_EVENT/)
1766 { 1766 {
1767 tracepoint_munge($file); 1767 tracepoint_munge($file);
1768 } 1768 }
1769 dump_function($prototype, $file); 1769 dump_function($prototype, $file);
1770 reset_state(); 1770 reset_state();
1771 } 1771 }
1772 } 1772 }
1773 1773
1774 sub process_proto_type($$) { 1774 sub process_proto_type($$) {
1775 my $x = shift; 1775 my $x = shift;
1776 my $file = shift; 1776 my $file = shift;
1777 1777
1778 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1778 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1779 $x =~ s@^\s+@@gos; # strip leading spaces 1779 $x =~ s@^\s+@@gos; # strip leading spaces
1780 $x =~ s@\s+$@@gos; # strip trailing spaces 1780 $x =~ s@\s+$@@gos; # strip trailing spaces
1781 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 1781 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1782 1782
1783 if ($x =~ /^#/) { 1783 if ($x =~ /^#/) {
1784 # To distinguish preprocessor directive from regular declaration later. 1784 # To distinguish preprocessor directive from regular declaration later.
1785 $x .= ";"; 1785 $x .= ";";
1786 } 1786 }
1787 1787
1788 while (1) { 1788 while (1) {
1789 if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) { 1789 if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
1790 if( length $prototype ) { 1790 if( length $prototype ) {
1791 $prototype .= " " 1791 $prototype .= " "
1792 } 1792 }
1793 $prototype .= $1 . $2; 1793 $prototype .= $1 . $2;
1794 ($2 eq '{') && $brcount++; 1794 ($2 eq '{') && $brcount++;
1795 ($2 eq '}') && $brcount--; 1795 ($2 eq '}') && $brcount--;
1796 if (($2 eq ';') && ($brcount == 0)) { 1796 if (($2 eq ';') && ($brcount == 0)) {
1797 dump_declaration($prototype, $file); 1797 dump_declaration($prototype, $file);
1798 reset_state(); 1798 reset_state();
1799 last; 1799 last;
1800 } 1800 }
1801 $x = $3; 1801 $x = $3;
1802 } else { 1802 } else {
1803 $prototype .= $x; 1803 $prototype .= $x;
1804 last; 1804 last;
1805 } 1805 }
1806 } 1806 }
1807 } 1807 }
1808 1808
1809 1809
1810 sub map_filename($) { 1810 sub map_filename($) {
1811 my $file; 1811 my $file;
1812 my ($orig_file) = @_; 1812 my ($orig_file) = @_;
1813 1813
1814 if (defined($ENV{'SRCTREE'})) { 1814 if (defined($ENV{'SRCTREE'})) {
1815 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; 1815 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
1816 } else { 1816 } else {
1817 $file = $orig_file; 1817 $file = $orig_file;
1818 } 1818 }
1819 1819
1820 if (defined($source_map{$file})) { 1820 if (defined($source_map{$file})) {
1821 $file = $source_map{$file}; 1821 $file = $source_map{$file};
1822 } 1822 }
1823 1823
1824 return $file; 1824 return $file;
1825 } 1825 }
1826 1826
1827 sub process_export_file($) { 1827 sub process_export_file($) {
1828 my ($orig_file) = @_; 1828 my ($orig_file) = @_;
1829 my $file = map_filename($orig_file); 1829 my $file = map_filename($orig_file);
1830 1830
1831 if (!open(IN,"<$file")) { 1831 if (!open(IN,"<$file")) {
1832 print STDERR "Error: Cannot open file $file\n"; 1832 print STDERR "Error: Cannot open file $file\n";
1833 ++$errors; 1833 ++$errors;
1834 return; 1834 return;
1835 } 1835 }
1836 1836
1837 while (<IN>) { 1837 while (<IN>) {
1838 if (/$export_symbol/) { 1838 if (/$export_symbol/) {
1839 $function_table{$2} = 1; 1839 $function_table{$2} = 1;
1840 } 1840 }
1841 } 1841 }
1842 1842
1843 close(IN); 1843 close(IN);
1844 } 1844 }
1845 1845
1846 # 1846 #
1847 # Parsers for the various processing states. 1847 # Parsers for the various processing states.
1848 # 1848 #
1849 # STATE_NORMAL: looking for the /** to begin everything. 1849 # STATE_NORMAL: looking for the /** to begin everything.
1850 # 1850 #
1851 sub process_normal() { 1851 sub process_normal() {
1852 if (/$doc_start/o) { 1852 if (/$doc_start/o) {
1853 $state = STATE_NAME; # next line is always the function name 1853 $state = STATE_NAME; # next line is always the function name
1854 $in_doc_sect = 0; 1854 $in_doc_sect = 0;
1855 $declaration_start_line = $. + 1; 1855 $declaration_start_line = $. + 1;
1856 } 1856 }
1857 } 1857 }
1858 1858
1859 # 1859 #
1860 # STATE_NAME: Looking for the "name - description" line 1860 # STATE_NAME: Looking for the "name - description" line
1861 # 1861 #
1862 sub process_name($$) { 1862 sub process_name($$) {
1863 my $file = shift; 1863 my $file = shift;
1864 my $identifier; 1864 my $identifier;
1865 my $descr; 1865 my $descr;
1866 1866
1867 if (/$doc_block/o) { 1867 if (/$doc_block/o) {
1868 $state = STATE_DOCBLOCK; 1868 $state = STATE_DOCBLOCK;
1869 $contents = ""; 1869 $contents = "";
1870 $new_start_line = $. + 1; 1870 $new_start_line = $. + 1;
1871 1871
1872 if ( $1 eq "" ) { 1872 if ( $1 eq "" ) {
1873 $section = $section_intro; 1873 $section = $section_intro;
1874 } else { 1874 } else {
1875 $section = $1; 1875 $section = $1;
1876 } 1876 }
1877 } 1877 }
1878 elsif (/$doc_decl/o) { 1878 elsif (/$doc_decl/o) {
1879 $identifier = $1; 1879 $identifier = $1;
1880 if (/\s*([\w\s]+?)(\(\))?\s*-/) { 1880 if (/\s*([\w\s]+?)(\(\))?\s*-/) {
1881 $identifier = $1; 1881 $identifier = $1;
1882 } 1882 }
1883 1883
1884 $state = STATE_BODY; 1884 $state = STATE_BODY;
1885 # if there's no @param blocks need to set up default section 1885 # if there's no @param blocks need to set up default section
1886 # here 1886 # here
1887 $contents = ""; 1887 $contents = "";
1888 $section = $section_default; 1888 $section = $section_default;
1889 $new_start_line = $. + 1; 1889 $new_start_line = $. + 1;
1890 if (/-(.*)/) { 1890 if (/-(.*)/) {
1891 # strip leading/trailing/multiple spaces 1891 # strip leading/trailing/multiple spaces
1892 $descr= $1; 1892 $descr= $1;
1893 $descr =~ s/^\s*//; 1893 $descr =~ s/^\s*//;
1894 $descr =~ s/\s*$//; 1894 $descr =~ s/\s*$//;
1895 $descr =~ s/\s+/ /g; 1895 $descr =~ s/\s+/ /g;
1896 $declaration_purpose = $descr; 1896 $declaration_purpose = $descr;
1897 $state = STATE_BODY_MAYBE; 1897 $state = STATE_BODY_MAYBE;
1898 } else { 1898 } else {
1899 $declaration_purpose = ""; 1899 $declaration_purpose = "";
1900 } 1900 }
1901 1901
1902 if (($declaration_purpose eq "") && $verbose) { 1902 if (($declaration_purpose eq "") && $verbose) {
1903 print STDERR "${file}:$.: warning: missing initial short description on line:\n"; 1903 print STDERR "${file}:$.: warning: missing initial short description on line:\n";
1904 print STDERR $_; 1904 print STDERR $_;
1905 ++$warnings; 1905 ++$warnings;
1906 } 1906 }
1907 1907
1908 if ($identifier =~ m/^struct\b/) { 1908 if ($identifier =~ m/^struct\b/) {
1909 $decl_type = 'struct'; 1909 $decl_type = 'struct';
1910 } elsif ($identifier =~ m/^union\b/) { 1910 } elsif ($identifier =~ m/^union\b/) {
1911 $decl_type = 'union'; 1911 $decl_type = 'union';
1912 } elsif ($identifier =~ m/^enum\b/) { 1912 } elsif ($identifier =~ m/^enum\b/) {
1913 $decl_type = 'enum'; 1913 $decl_type = 'enum';
1914 } elsif ($identifier =~ m/^typedef\b/) { 1914 } elsif ($identifier =~ m/^typedef\b/) {
1915 $decl_type = 'typedef'; 1915 $decl_type = 'typedef';
1916 } else { 1916 } else {
1917 $decl_type = 'function'; 1917 $decl_type = 'function';
1918 } 1918 }
1919 1919
1920 if ($verbose) { 1920 if ($verbose) {
1921 print STDERR "${file}:$.: info: Scanning doc for $identifier\n"; 1921 print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
1922 } 1922 }
1923 } else { 1923 } else {
1924 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", 1924 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
1925 " - I thought it was a doc line\n"; 1925 " - I thought it was a doc line\n";
1926 ++$warnings; 1926 ++$warnings;
1927 $state = STATE_NORMAL; 1927 $state = STATE_NORMAL;
1928 } 1928 }
1929 } 1929 }
1930 1930
1931 1931
1932 # 1932 #
1933 # STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment. 1933 # STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment.
1934 # 1934 #
1935 sub process_body($$) { 1935 sub process_body($$) {
1936 my $file = shift; 1936 my $file = shift;
1937 1937
1938 if (/$doc_sect/i) { # case insensitive for supported section names 1938 if (/$doc_sect/i) { # case insensitive for supported section names
1939 $newsection = $1; 1939 $newsection = $1;
1940 $newcontents = $2; 1940 $newcontents = $2;
1941 1941
1942 # map the supported section names to the canonical names 1942 # map the supported section names to the canonical names
1943 if ($newsection =~ m/^description$/i) { 1943 if ($newsection =~ m/^description$/i) {
1944 $newsection = $section_default; 1944 $newsection = $section_default;
1945 } elsif ($newsection =~ m/^context$/i) { 1945 } elsif ($newsection =~ m/^context$/i) {
1946 $newsection = $section_context; 1946 $newsection = $section_context;
1947 } elsif ($newsection =~ m/^returns?$/i) { 1947 } elsif ($newsection =~ m/^returns?$/i) {
1948 $newsection = $section_return; 1948 $newsection = $section_return;
1949 } elsif ($newsection =~ m/^\@return$/) { 1949 } elsif ($newsection =~ m/^\@return$/) {
1950 # special: @return is a section, not a param description 1950 # special: @return is a section, not a param description
1951 $newsection = $section_return; 1951 $newsection = $section_return;
1952 } 1952 }
1953 1953
1954 if (($contents ne "") && ($contents ne "\n")) { 1954 if (($contents ne "") && ($contents ne "\n")) {
1955 if (!$in_doc_sect && $verbose) { 1955 if (!$in_doc_sect && $verbose) {
1956 print STDERR "${file}:$.: warning: contents before sections\n"; 1956 print STDERR "${file}:$.: warning: contents before sections\n";
1957 ++$warnings; 1957 ++$warnings;
1958 } 1958 }
1959 dump_section($file, $section, $contents); 1959 dump_section($file, $section, $contents);
1960 $section = $section_default; 1960 $section = $section_default;
1961 } 1961 }
1962 1962
1963 $in_doc_sect = 1; 1963 $in_doc_sect = 1;
1964 $state = STATE_BODY; 1964 $state = STATE_BODY;
1965 $contents = $newcontents; 1965 $contents = $newcontents;
1966 $new_start_line = $.; 1966 $new_start_line = $.;
1967 while (substr($contents, 0, 1) eq " ") { 1967 while (substr($contents, 0, 1) eq " ") {
1968 $contents = substr($contents, 1); 1968 $contents = substr($contents, 1);
1969 } 1969 }
1970 if ($contents ne "") { 1970 if ($contents ne "") {
1971 $contents .= "\n"; 1971 $contents .= "\n";
1972 } 1972 }
1973 $section = $newsection; 1973 $section = $newsection;
1974 $leading_space = undef; 1974 $leading_space = undef;
1975 } elsif (/$doc_end/) { 1975 } elsif (/$doc_end/) {
1976 if (($contents ne "") && ($contents ne "\n")) { 1976 if (($contents ne "") && ($contents ne "\n")) {
1977 dump_section($file, $section, $contents); 1977 dump_section($file, $section, $contents);
1978 $section = $section_default; 1978 $section = $section_default;
1979 $contents = ""; 1979 $contents = "";
1980 } 1980 }
1981 # look for doc_com + <text> + doc_end: 1981 # look for doc_com + <text> + doc_end:
1982 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { 1982 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
1983 print STDERR "${file}:$.: warning: suspicious ending line: $_"; 1983 print STDERR "${file}:$.: warning: suspicious ending line: $_";
1984 ++$warnings; 1984 ++$warnings;
1985 } 1985 }
1986 1986
1987 $prototype = ""; 1987 $prototype = "";
1988 $state = STATE_PROTO; 1988 $state = STATE_PROTO;
1989 $brcount = 0; 1989 $brcount = 0;
1990 } elsif (/$doc_content/) { 1990 } elsif (/$doc_content/) {
1991 # miguel-style comment kludge, look for blank lines after 1991 # miguel-style comment kludge, look for blank lines after
1992 # @parameter line to signify start of description 1992 # @parameter line to signify start of description
1993 if ($1 eq "") { 1993 if ($1 eq "") {
1994 if ($section =~ m/^@/ || $section eq $section_context) { 1994 if ($section =~ m/^@/ || $section eq $section_context) {
1995 dump_section($file, $section, $contents); 1995 dump_section($file, $section, $contents);
1996 $section = $section_default; 1996 $section = $section_default;
1997 $contents = ""; 1997 $contents = "";
1998 $new_start_line = $.; 1998 $new_start_line = $.;
1999 } else { 1999 } else {
2000 $contents .= "\n"; 2000 $contents .= "\n";
2001 } 2001 }
2002 $state = STATE_BODY; 2002 $state = STATE_BODY;
2003 } elsif ($state == STATE_BODY_MAYBE) { 2003 } elsif ($state == STATE_BODY_MAYBE) {
2004 # Continued declaration purpose 2004 # Continued declaration purpose
2005 chomp($declaration_purpose); 2005 chomp($declaration_purpose);
2006 $declaration_purpose .= " " . $1; 2006 $declaration_purpose .= " " . $1;
2007 $declaration_purpose =~ s/\s+/ /g; 2007 $declaration_purpose =~ s/\s+/ /g;
2008 } else { 2008 } else {
2009 my $cont = $1; 2009 my $cont = $1;
2010 if ($section =~ m/^@/ || $section eq $section_context) { 2010 if ($section =~ m/^@/ || $section eq $section_context) {
2011 if (!defined $leading_space) { 2011 if (!defined $leading_space) {
2012 if ($cont =~ m/^(\s+)/) { 2012 if ($cont =~ m/^(\s+)/) {
2013 $leading_space = $1; 2013 $leading_space = $1;
2014 } else { 2014 } else {
2015 $leading_space = ""; 2015 $leading_space = "";
2016 } 2016 }
2017 } 2017 }
2018 $cont =~ s/^$leading_space//; 2018 $cont =~ s/^$leading_space//;
2019 } 2019 }
2020 $contents .= $cont . "\n"; 2020 $contents .= $cont . "\n";
2021 } 2021 }
2022 } else { 2022 } else {
2023 # i dont know - bad line? ignore. 2023 # i dont know - bad line? ignore.
2024 print STDERR "${file}:$.: warning: bad line: $_"; 2024 print STDERR "${file}:$.: warning: bad line: $_";
2025 ++$warnings; 2025 ++$warnings;
2026 } 2026 }
2027 } 2027 }
2028 2028
2029 2029
2030 # 2030 #
2031 # STATE_PROTO: reading a function/whatever prototype. 2031 # STATE_PROTO: reading a function/whatever prototype.
2032 # 2032 #
2033 sub process_proto($$) { 2033 sub process_proto($$) {
2034 my $file = shift; 2034 my $file = shift;
2035 2035
2036 if (/$doc_inline_oneline/) { 2036 if (/$doc_inline_oneline/) {
2037 $section = $1; 2037 $section = $1;
2038 $contents = $2; 2038 $contents = $2;
2039 if ($contents ne "") { 2039 if ($contents ne "") {
2040 $contents .= "\n"; 2040 $contents .= "\n";
2041 dump_section($file, $section, $contents); 2041 dump_section($file, $section, $contents);
2042 $section = $section_default; 2042 $section = $section_default;
2043 $contents = ""; 2043 $contents = "";
2044 } 2044 }
2045 } elsif (/$doc_inline_start/) { 2045 } elsif (/$doc_inline_start/) {
2046 $state = STATE_INLINE; 2046 $state = STATE_INLINE;
2047 $inline_doc_state = STATE_INLINE_NAME; 2047 $inline_doc_state = STATE_INLINE_NAME;
2048 } elsif ($decl_type eq 'function') { 2048 } elsif ($decl_type eq 'function') {
2049 process_proto_function($_, $file); 2049 process_proto_function($_, $file);
2050 } else { 2050 } else {
2051 process_proto_type($_, $file); 2051 process_proto_type($_, $file);
2052 } 2052 }
2053 } 2053 }
2054 2054
2055 # 2055 #
2056 # STATE_DOCBLOCK: within a DOC: block. 2056 # STATE_DOCBLOCK: within a DOC: block.
2057 # 2057 #
2058 sub process_docblock($$) { 2058 sub process_docblock($$) {
2059 my $file = shift; 2059 my $file = shift;
2060 2060
2061 if (/$doc_end/) { 2061 if (/$doc_end/) {
2062 dump_doc_section($file, $section, $contents); 2062 dump_doc_section($file, $section, $contents);
2063 $section = $section_default; 2063 $section = $section_default;
2064 $contents = ""; 2064 $contents = "";
2065 $function = ""; 2065 $function = "";
2066 %parameterdescs = (); 2066 %parameterdescs = ();
2067 %parametertypes = (); 2067 %parametertypes = ();
2068 @parameterlist = (); 2068 @parameterlist = ();
2069 %sections = (); 2069 %sections = ();
2070 @sectionlist = (); 2070 @sectionlist = ();
2071 $prototype = ""; 2071 $prototype = "";
2072 $state = STATE_NORMAL; 2072 $state = STATE_NORMAL;
2073 } elsif (/$doc_content/) { 2073 } elsif (/$doc_content/) {
2074 if ( $1 eq "" ) { 2074 if ( $1 eq "" ) {
2075 $contents .= $blankline; 2075 $contents .= $blankline;
2076 } else { 2076 } else {
2077 $contents .= $1 . "\n"; 2077 $contents .= $1 . "\n";
2078 } 2078 }
2079 } 2079 }
2080 } 2080 }
2081 2081
2082 # 2082 #
2083 # STATE_INLINE: docbook comments within a prototype. 2083 # STATE_INLINE: docbook comments within a prototype.
2084 # 2084 #
2085 sub process_inline($$) { 2085 sub process_inline($$) {
2086 my $file = shift; 2086 my $file = shift;
2087 2087
2088 # First line (state 1) needs to be a @parameter 2088 # First line (state 1) needs to be a @parameter
2089 if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { 2089 if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
2090 $section = $1; 2090 $section = $1;
2091 $contents = $2; 2091 $contents = $2;
2092 $new_start_line = $.; 2092 $new_start_line = $.;
2093 if ($contents ne "") { 2093 if ($contents ne "") {
2094 while (substr($contents, 0, 1) eq " ") { 2094 while (substr($contents, 0, 1) eq " ") {
2095 $contents = substr($contents, 1); 2095 $contents = substr($contents, 1);
2096 } 2096 }
2097 $contents .= "\n"; 2097 $contents .= "\n";
2098 } 2098 }
2099 $inline_doc_state = STATE_INLINE_TEXT; 2099 $inline_doc_state = STATE_INLINE_TEXT;
2100 # Documentation block end */ 2100 # Documentation block end */
2101 } elsif (/$doc_inline_end/) { 2101 } elsif (/$doc_inline_end/) {
2102 if (($contents ne "") && ($contents ne "\n")) { 2102 if (($contents ne "") && ($contents ne "\n")) {
2103 dump_section($file, $section, $contents); 2103 dump_section($file, $section, $contents);
2104 $section = $section_default; 2104 $section = $section_default;
2105 $contents = ""; 2105 $contents = "";
2106 } 2106 }
2107 $state = STATE_PROTO; 2107 $state = STATE_PROTO;
2108 $inline_doc_state = STATE_INLINE_NA; 2108 $inline_doc_state = STATE_INLINE_NA;
2109 # Regular text 2109 # Regular text
2110 } elsif (/$doc_content/) { 2110 } elsif (/$doc_content/) {
2111 if ($inline_doc_state == STATE_INLINE_TEXT) { 2111 if ($inline_doc_state == STATE_INLINE_TEXT) {
2112 $contents .= $1 . "\n"; 2112 $contents .= $1 . "\n";
2113 # nuke leading blank lines 2113 # nuke leading blank lines
2114 if ($contents =~ /^\s*$/) { 2114 if ($contents =~ /^\s*$/) {
2115 $contents = ""; 2115 $contents = "";
2116 } 2116 }
2117 } elsif ($inline_doc_state == STATE_INLINE_NAME) { 2117 } elsif ($inline_doc_state == STATE_INLINE_NAME) {
2118 $inline_doc_state = STATE_INLINE_ERROR; 2118 $inline_doc_state = STATE_INLINE_ERROR;
2119 print STDERR "${file}:$.: warning: "; 2119 print STDERR "${file}:$.: warning: ";
2120 print STDERR "Incorrect use of kernel-doc format: $_"; 2120 print STDERR "Incorrect use of kernel-doc format: $_";
2121 ++$warnings; 2121 ++$warnings;
2122 } 2122 }
2123 } 2123 }
2124 } 2124 }
2125 2125
2126 2126
2127 sub process_file($) { 2127 sub process_file($) {
2128 my $file; 2128 my $file;
2129 my $initial_section_counter = $section_counter; 2129 my $initial_section_counter = $section_counter;
2130 my ($orig_file) = @_; 2130 my ($orig_file) = @_;
2131 2131
2132 $file = map_filename($orig_file); 2132 $file = map_filename($orig_file);
2133 2133
2134 if (!open(IN,"<$file")) { 2134 if (!open(IN,"<$file")) {
2135 print STDERR "Error: Cannot open file $file\n"; 2135 print STDERR "Error: Cannot open file $file\n";
2136 ++$errors; 2136 ++$errors;
2137 return; 2137 return;
2138 } 2138 }
2139 2139
2140 $. = 1; 2140 $. = 1;
2141 2141
2142 $section_counter = 0; 2142 $section_counter = 0;
2143 while (<IN>) { 2143 while (<IN>) {
2144 while (s/\\\s*$//) { 2144 while (s/\\\s*$//) {
2145 $_ .= <IN>; 2145 $_ .= <IN>;
2146 } 2146 }
2147 # Replace tabs by spaces 2147 # Replace tabs by spaces
2148 while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; 2148 while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
2149 # Hand this line to the appropriate state handler 2149 # Hand this line to the appropriate state handler
2150 if ($state == STATE_NORMAL) { 2150 if ($state == STATE_NORMAL) {
2151 process_normal(); 2151 process_normal();
2152 } elsif ($state == STATE_NAME) { 2152 } elsif ($state == STATE_NAME) {
2153 process_name($file, $_); 2153 process_name($file, $_);
2154 } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) { 2154 } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) {
2155 process_body($file, $_); 2155 process_body($file, $_);
2156 } elsif ($state == STATE_INLINE) { # scanning for inline parameters 2156 } elsif ($state == STATE_INLINE) { # scanning for inline parameters
2157 process_inline($file, $_); 2157 process_inline($file, $_);
2158 } elsif ($state == STATE_PROTO) { 2158 } elsif ($state == STATE_PROTO) {
2159 process_proto($file, $_); 2159 process_proto($file, $_);
2160 } elsif ($state == STATE_DOCBLOCK) { 2160 } elsif ($state == STATE_DOCBLOCK) {
2161 process_docblock($file, $_); 2161 process_docblock($file, $_);
2162 } 2162 }
2163 } 2163 }
2164 2164
2165 # Make sure we got something interesting. 2165 # Make sure we got something interesting.
2166 if ($initial_section_counter == $section_counter) { 2166 if ($initial_section_counter == $section_counter) {
2167 if ($output_mode ne "none") { 2167 if ($output_mode ne "none") {
2168 print STDERR "${file}:1: warning: no structured comments found\n"; 2168 print STDERR "${file}:1: warning: no structured comments found\n";
2169 } 2169 }
2170 if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) { 2170 if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
2171 print STDERR " Was looking for '$_'.\n" for keys %function_table; 2171 print STDERR " Was looking for '$_'.\n" for keys %function_table;
2172 } 2172 }
2173 } 2173 }
2174 } 2174 }
2175 2175
2176 2176
2177 $kernelversion = get_kernel_version(); 2177 $kernelversion = get_kernel_version();
2178 2178
2179 # generate a sequence of code that will splice in highlighting information 2179 # generate a sequence of code that will splice in highlighting information
2180 # using the s// operator. 2180 # using the s// operator.
2181 for (my $k = 0; $k < @highlights; $k++) { 2181 for (my $k = 0; $k < @highlights; $k++) {
2182 my $pattern = $highlights[$k][0]; 2182 my $pattern = $highlights[$k][0];
2183 my $result = $highlights[$k][1]; 2183 my $result = $highlights[$k][1];
2184 # print STDERR "scanning pattern:$pattern, highlight:($result)\n"; 2184 # print STDERR "scanning pattern:$pattern, highlight:($result)\n";
2185 $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n"; 2185 $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n";
2186 } 2186 }
2187 2187
2188 # Read the file that maps relative names to absolute names for 2188 # Read the file that maps relative names to absolute names for
2189 # separate source and object directories and for shadow trees. 2189 # separate source and object directories and for shadow trees.
2190 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 2190 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
2191 my ($relname, $absname); 2191 my ($relname, $absname);
2192 while(<SOURCE_MAP>) { 2192 while(<SOURCE_MAP>) {
2193 chop(); 2193 chop();
2194 ($relname, $absname) = (split())[0..1]; 2194 ($relname, $absname) = (split())[0..1];
2195 $relname =~ s:^/+::; 2195 $relname =~ s:^/+::;
2196 $source_map{$relname} = $absname; 2196 $source_map{$relname} = $absname;
2197 } 2197 }
2198 close(SOURCE_MAP); 2198 close(SOURCE_MAP);
2199 } 2199 }
2200 2200
2201 if ($output_selection == OUTPUT_EXPORTED || 2201 if ($output_selection == OUTPUT_EXPORTED ||
2202 $output_selection == OUTPUT_INTERNAL) { 2202 $output_selection == OUTPUT_INTERNAL) {
2203 2203
2204 push(@export_file_list, @ARGV); 2204 push(@export_file_list, @ARGV);
2205 2205
2206 foreach (@export_file_list) { 2206 foreach (@export_file_list) {
2207 chomp; 2207 chomp;
2208 process_export_file($_); 2208 process_export_file($_);
2209 } 2209 }
2210 } 2210 }
2211 2211
2212 foreach (@ARGV) { 2212 foreach (@ARGV) {
2213 chomp; 2213 chomp;
2214 process_file($_); 2214 process_file($_);
2215 } 2215 }
2216 if ($verbose && $errors) { 2216 if ($verbose && $errors) {
2217 print STDERR "$errors errors\n"; 2217 print STDERR "$errors errors\n";
2218 } 2218 }
2219 if ($verbose && $warnings) { 2219 if ($verbose && $warnings) {
2220 print STDERR "$warnings warnings\n"; 2220 print STDERR "$warnings warnings\n";
2221 } 2221 }
2222 2222
2223 exit($output_mode eq "none" ? 0 : $errors); 2223 exit($output_mode eq "none" ? 0 : $errors);
2224 2224