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