| 1 | |
| 2 | |
| 3 | |
| 4 |
|
| 5 | use warnings;
|
| 6 | use strict;
|
| 7 |
|
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 |
|
| 19 | use Pod::Usage qw/pod2usage/;
|
| 20 |
|
| 21 | |
| 22 |
|
| 23 | kernel-doc - Print formatted kernel documentation to stdout
|
| 24 |
|
| 25 | =head1 SYNOPSIS
|
| 26 |
|
| 27 | kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-desc[ription]] [-Wcontents-before-sections]
|
| 28 | [ -man |
|
| 29 | -rst [-enable-lineno] |
|
| 30 | -none
|
| 31 | ]
|
| 32 | [
|
| 33 | -export |
|
| 34 | -internal |
|
| 35 | [-function NAME] ... |
|
| 36 | [-nosymbol NAME] ...
|
| 37 | ]
|
| 38 | [-no-doc-sections]
|
| 39 | [-export-file FILE] ...
|
| 40 | FILE ...
|
| 41 |
|
| 42 | Run `kernel-doc -h` for details.
|
| 43 |
|
| 44 | =head1 DESCRIPTION
|
| 45 |
|
| 46 | Read C language source or header FILEs, extract embedded documentation comments,
|
| 47 | and print formatted documentation to standard output.
|
| 48 |
|
| 49 | The documentation comments are identified by the "/**" opening comment mark.
|
| 50 |
|
| 51 | See Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
|
| 52 |
|
| 53 |
|
| 54 |
|
| 55 | |
| 56 |
|
| 57 | |
| 58 |
|
| 59 | my $errors = 0;
|
| 60 | my $warnings = 0;
|
| 61 | my $anon_struct_union = 0;
|
| 62 |
|
| 63 | |
| 64 | my $type_constant = '\b``([^\`]+)``\b';
|
| 65 | my $type_constant2 = '\%([-_*\w]+)';
|
| 66 | my $type_func = '(\w+)\(\)';
|
| 67 | my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
|
| 68 | my $type_param_ref = '([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
|
| 69 | my $type_fp_param = '\@(\w+)\(\)'; |
| 70 | my $type_fp_param2 = '\@(\w+->\S+)\(\)'; |
| 71 | my $type_env = '(\$\w+)';
|
| 72 | my $type_enum = '\&(enum\s*([_\w]+))';
|
| 73 | my $type_struct = '\&(struct\s*([_\w]+))';
|
| 74 | my $type_typedef = '\&(typedef\s*([_\w]+))';
|
| 75 | my $type_union = '\&(union\s*([_\w]+))';
|
| 76 | my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
|
| 77 | my $type_fallback = '\&([_\w]+)';
|
| 78 | my $type_member_func = $type_member . '\(\)';
|
| 79 |
|
| 80 | |
| 81 | |
| 82 |
|
| 83 | |
| 84 | my @highlights_man = (
|
| 85 | [$type_constant, "\$1"],
|
| 86 | [$type_constant2, "\$1"],
|
| 87 | [$type_func, "\\\\fB\$1\\\\fP"],
|
| 88 | [$type_enum, "\\\\fI\$1\\\\fP"],
|
| 89 | [$type_struct, "\\\\fI\$1\\\\fP"],
|
| 90 | [$type_typedef, "\\\\fI\$1\\\\fP"],
|
| 91 | [$type_union, "\\\\fI\$1\\\\fP"],
|
| 92 | [$type_param, "\\\\fI\$1\\\\fP"],
|
| 93 | [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
|
| 94 | [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
|
| 95 | [$type_fallback, "\\\\fI\$1\\\\fP"]
|
| 96 | );
|
| 97 | my $blankline_man = "";
|
| 98 |
|
| 99 | |
| 100 | my @highlights_rst = (
|
| 101 | [$type_constant, "``\$1``"],
|
| 102 | [$type_constant2, "``\$1``"],
|
| 103 |
|
| 104 | |
| 105 | [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
|
| 106 | [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
|
| 107 | [$type_fp_param, "**\$1\\\\(\\\\)**"],
|
| 108 | [$type_fp_param2, "**\$1\\\\(\\\\)**"],
|
| 109 | [$type_func, "\$1()"],
|
| 110 | [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
|
| 111 | [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
|
| 112 | [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
|
| 113 | [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
|
| 114 |
|
| 115 | |
| 116 | [$type_fallback, "\\:c\\:type\\:`\$1`"],
|
| 117 | [$type_param_ref, "**\$1\$2**"]
|
| 118 | );
|
| 119 | my $blankline_rst = "\n";
|
| 120 |
|
| 121 | |
| 122 | if ($#ARGV == -1) {
|
| 123 | pod2usage(
|
| 124 | -message => "No arguments!\n",
|
| 125 | -exitval => 1,
|
| 126 | -verbose => 99,
|
| 127 | -sections => 'SYNOPSIS',
|
| 128 | -output => \*STDERR,
|
| 129 | );
|
| 130 | }
|
| 131 |
|
| 132 | my $kernelversion;
|
| 133 |
|
| 134 | my $dohighlight = "";
|
| 135 |
|
| 136 | my $verbose = 0;
|
| 137 | my $Werror = 0;
|
| 138 | my $Wreturn = 0;
|
| 139 | my $Wshort_desc = 0;
|
| 140 | my $output_mode = "rst";
|
| 141 | my $output_preformatted = 0;
|
| 142 | my $no_doc_sections = 0;
|
| 143 | my $enable_lineno = 0;
|
| 144 | my @highlights = @highlights_rst;
|
| 145 | my $blankline = $blankline_rst;
|
| 146 | my $modulename = "Kernel API";
|
| 147 |
|
| 148 | use constant {
|
| 149 | OUTPUT_ALL => 0, |
| 150 | OUTPUT_INCLUDE => 1, |
| 151 | OUTPUT_EXPORTED => 2, |
| 152 | OUTPUT_INTERNAL => 3, |
| 153 | };
|
| 154 | my $output_selection = OUTPUT_ALL;
|
| 155 | my $show_not_found = 0; |
| 156 |
|
| 157 | my @export_file_list;
|
| 158 |
|
| 159 | my @build_time;
|
| 160 | if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
|
| 161 | (my $seconds = `date -d "${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
|
| 162 | @build_time = gmtime($seconds);
|
| 163 | } else {
|
| 164 | @build_time = localtime;
|
| 165 | }
|
| 166 |
|
| 167 | my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
|
| 168 | 'July', 'August', 'September', 'October',
|
| 169 | 'November', 'December')[$build_time[4]] .
|
| 170 | " " . ($build_time[5]+1900);
|
| 171 |
|
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | my ($function, %function_table, %parametertypes, $declaration_purpose);
|
| 177 | my %nosymbol_table = ();
|
| 178 | my $declaration_start_line;
|
| 179 | my ($type, $declaration_name, $return_type);
|
| 180 | my ($newsection, $newcontents, $prototype, $brcount);
|
| 181 |
|
| 182 | if (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') {
|
| 183 | $verbose = 1;
|
| 184 | }
|
| 185 |
|
| 186 | if (defined($ENV{'KCFLAGS'})) {
|
| 187 | my $kcflags = "$ENV{'KCFLAGS'}";
|
| 188 |
|
| 189 | if ($kcflags =~ /(\s|^)-Werror(\s|$)/) {
|
| 190 | $Werror = 1;
|
| 191 | }
|
| 192 | }
|
| 193 |
|
| 194 | |
| 195 | |
| 196 | |
| 197 | if (defined($ENV{'KDOC_WERROR'})) {
|
| 198 | $Werror = "$ENV{'KDOC_WERROR'}";
|
| 199 | }
|
| 200 | |
| 201 | |
| 202 |
|
| 203 | |
| 204 | |
| 205 | |
| 206 | |
| 207 | |
| 208 | |
| 209 | my $section_counter = 0;
|
| 210 |
|
| 211 | my $lineprefix="";
|
| 212 |
|
| 213 | |
| 214 | use constant {
|
| 215 | STATE_NORMAL => 0, |
| 216 | STATE_NAME => 1, |
| 217 | STATE_BODY_MAYBE => 2, |
| 218 | STATE_BODY => 3, |
| 219 | STATE_BODY_WITH_BLANK_LINE => 4, |
| 220 | STATE_PROTO => 5, |
| 221 | STATE_DOCBLOCK => 6, |
| 222 | STATE_INLINE => 7, |
| 223 | };
|
| 224 | my $state;
|
| 225 | my $leading_space;
|
| 226 |
|
| 227 | |
| 228 | use constant {
|
| 229 | STATE_INLINE_NA => 0, |
| 230 | STATE_INLINE_NAME => 1, |
| 231 | STATE_INLINE_TEXT => 2, |
| 232 | STATE_INLINE_END => 3, |
| 233 | STATE_INLINE_ERROR => 4, |
| 234 | |
| 235 | |
| 236 | };
|
| 237 | my $inline_doc_state;
|
| 238 |
|
| 239 | |
| 240 | |
| 241 | my $decl_type;
|
| 242 |
|
| 243 | |
| 244 | my $identifier;
|
| 245 |
|
| 246 | my $doc_start = '^/\*\*\s*$'; |
| 247 | my $doc_end = '\*/';
|
| 248 | my $doc_com = '\s*\*\s*';
|
| 249 | my $doc_com_body = '\s*\* ?';
|
| 250 | my $doc_decl = $doc_com . '(\w+)';
|
| 251 | |
| 252 | |
| 253 | |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | my $doc_sect = $doc_com .
|
| 259 | '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$';
|
| 260 | my $doc_content = $doc_com_body . '(.*)';
|
| 261 | my $doc_block = $doc_com . 'DOC:\s*(.*)?';
|
| 262 | my $doc_inline_start = '^\s*/\*\*\s*$';
|
| 263 | my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
|
| 264 | my $doc_inline_end = '^\s*\*/\s*$';
|
| 265 | my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
|
| 266 | my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
|
| 267 | my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"\S+"\)\s*;';
|
| 268 | my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)};
|
| 269 | my $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i;
|
| 270 |
|
| 271 | my %parameterdescs;
|
| 272 | my %parameterdesc_start_lines;
|
| 273 | my @parameterlist;
|
| 274 | my %sections;
|
| 275 | my @sectionlist;
|
| 276 | my %section_start_lines;
|
| 277 | my $sectcheck;
|
| 278 | my $struct_actual;
|
| 279 |
|
| 280 | my $contents = "";
|
| 281 | my $new_start_line = 0;
|
| 282 |
|
| 283 | |
| 284 | my $section_default = "Description"; |
| 285 | my $section_intro = "Introduction";
|
| 286 | my $section = $section_default;
|
| 287 | my $section_context = "Context";
|
| 288 | my $section_return = "Return";
|
| 289 |
|
| 290 | my $undescribed = "-- undescribed --";
|
| 291 |
|
| 292 | reset_state();
|
| 293 |
|
| 294 | while ($ARGV[0] =~ m/^--?(.*)/) {
|
| 295 | my $cmd = $1;
|
| 296 | shift @ARGV;
|
| 297 | if ($cmd eq "man") {
|
| 298 | $output_mode = "man";
|
| 299 | @highlights = @highlights_man;
|
| 300 | $blankline = $blankline_man;
|
| 301 | } elsif ($cmd eq "rst") {
|
| 302 | $output_mode = "rst";
|
| 303 | @highlights = @highlights_rst;
|
| 304 | $blankline = $blankline_rst;
|
| 305 | } elsif ($cmd eq "none") {
|
| 306 | $output_mode = "none";
|
| 307 | } elsif ($cmd eq "module") { |
| 308 | $modulename = shift @ARGV;
|
| 309 | } elsif ($cmd eq "function") { |
| 310 | $output_selection = OUTPUT_INCLUDE;
|
| 311 | $function = shift @ARGV;
|
| 312 | $function_table{$function} = 1;
|
| 313 | } elsif ($cmd eq "nosymbol") { |
| 314 | my $symbol = shift @ARGV;
|
| 315 | $nosymbol_table{$symbol} = 1;
|
| 316 | } elsif ($cmd eq "export") { |
| 317 | $output_selection = OUTPUT_EXPORTED;
|
| 318 | %function_table = ();
|
| 319 | } elsif ($cmd eq "internal") { |
| 320 | $output_selection = OUTPUT_INTERNAL;
|
| 321 | %function_table = ();
|
| 322 | } elsif ($cmd eq "export-file") {
|
| 323 | my $file = shift @ARGV;
|
| 324 | push(@export_file_list, $file);
|
| 325 | } elsif ($cmd eq "v") {
|
| 326 | $verbose = 1;
|
| 327 | } elsif ($cmd eq "Werror") {
|
| 328 | $Werror = 1;
|
| 329 | } elsif ($cmd eq "Wreturn") {
|
| 330 | $Wreturn = 1;
|
| 331 | } elsif ($cmd eq "Wshort-desc" or $cmd eq "Wshort-description") {
|
| 332 | $Wshort_desc = 1;
|
| 333 | } elsif ($cmd eq "Wall") {
|
| 334 | $Wreturn = 1;
|
| 335 | $Wshort_desc = 1;
|
| 336 | } elsif (($cmd eq "h") || ($cmd eq "help")) {
|
| 337 | pod2usage(-exitval => 0, -verbose => 2);
|
| 338 | } elsif ($cmd eq 'no-doc-sections') {
|
| 339 | $no_doc_sections = 1;
|
| 340 | } elsif ($cmd eq 'enable-lineno') {
|
| 341 | $enable_lineno = 1;
|
| 342 | } elsif ($cmd eq 'show-not-found') {
|
| 343 | $show_not_found = 1; |
| 344 | } else {
|
| 345 | |
| 346 | pod2usage(
|
| 347 | -message => "Argument unknown!\n",
|
| 348 | -exitval => 1,
|
| 349 | -verbose => 99,
|
| 350 | -sections => 'SYNOPSIS',
|
| 351 | -output => \*STDERR,
|
| 352 | );
|
| 353 | }
|
| 354 | if ($#ARGV < 0){
|
| 355 | pod2usage(
|
| 356 | -message => "FILE argument missing\n",
|
| 357 | -exitval => 1,
|
| 358 | -verbose => 99,
|
| 359 | -sections => 'SYNOPSIS',
|
| 360 | -output => \*STDERR,
|
| 361 | );
|
| 362 | }
|
| 363 | }
|
| 364 |
|
| 365 | |
| 366 |
|
| 367 | sub findprog($)
|
| 368 | {
|
| 369 | foreach(split(/:/, $ENV{PATH})) {
|
| 370 | return "$_/$_[0]" if(-x "$_/$_[0]");
|
| 371 | }
|
| 372 | }
|
| 373 |
|
| 374 | |
| 375 | sub get_kernel_version() {
|
| 376 | my $version = 'unknown kernel version';
|
| 377 |
|
| 378 | if (defined($ENV{'KERNELVERSION'})) {
|
| 379 | $version = $ENV{'KERNELVERSION'};
|
| 380 | }
|
| 381 | return $version;
|
| 382 | }
|
| 383 |
|
| 384 | |
| 385 | sub print_lineno {
|
| 386 | my $lineno = shift;
|
| 387 | if ($enable_lineno && defined($lineno)) {
|
| 388 | print ".. LINENO " . $lineno . "\n";
|
| 389 | }
|
| 390 | }
|
| 391 |
|
| 392 | sub emit_warning {
|
| 393 | my $location = shift;
|
| 394 | my $msg = shift;
|
| 395 | print STDERR "$location: warning: $msg";
|
| 396 | ++$warnings;
|
| 397 | }
|
| 398 | |
| 399 | |
| 400 | |
| 401 | sub dump_section {
|
| 402 | my $file = shift;
|
| 403 | my $name = shift;
|
| 404 | my $contents = join "\n", @_;
|
| 405 |
|
| 406 | if ($name =~ m/$type_param/) {
|
| 407 | $name = $1;
|
| 408 | $parameterdescs{$name} = $contents;
|
| 409 | $sectcheck = $sectcheck . $name . " ";
|
| 410 | $parameterdesc_start_lines{$name} = $new_start_line;
|
| 411 | $new_start_line = 0;
|
| 412 | } elsif ($name eq "@\.\.\.") {
|
| 413 | $name = "...";
|
| 414 | $parameterdescs{$name} = $contents;
|
| 415 | $sectcheck = $sectcheck . $name . " ";
|
| 416 | $parameterdesc_start_lines{$name} = $new_start_line;
|
| 417 | $new_start_line = 0;
|
| 418 | } else {
|
| 419 | if (defined($sections{$name}) && ($sections{$name} ne "")) {
|
| 420 | |
| 421 | if ($name ne $section_default) {
|
| 422 | emit_warning("${file}:$.", "duplicate section name '$name'\n");
|
| 423 | }
|
| 424 | $sections{$name} .= $contents;
|
| 425 | } else {
|
| 426 | $sections{$name} = $contents;
|
| 427 | push @sectionlist, $name;
|
| 428 | $section_start_lines{$name} = $new_start_line;
|
| 429 | $new_start_line = 0;
|
| 430 | }
|
| 431 | }
|
| 432 | }
|
| 433 |
|
| 434 | |
| 435 | |
| 436 | |
| 437 | sub dump_doc_section {
|
| 438 | my $file = shift;
|
| 439 | my $name = shift;
|
| 440 | my $contents = join "\n", @_;
|
| 441 |
|
| 442 | if ($no_doc_sections) {
|
| 443 | return;
|
| 444 | }
|
| 445 |
|
| 446 | return if (defined($nosymbol_table{$name}));
|
| 447 |
|
| 448 | if (($output_selection == OUTPUT_ALL) ||
|
| 449 | (($output_selection == OUTPUT_INCLUDE) &&
|
| 450 | defined($function_table{$name})))
|
| 451 | {
|
| 452 | dump_section($file, $name, $contents);
|
| 453 | output_blockhead({'sectionlist' => \@sectionlist,
|
| 454 | 'sections' => \%sections,
|
| 455 | 'module' => $modulename,
|
| 456 | 'content-only' => ($output_selection != OUTPUT_ALL), });
|
| 457 | }
|
| 458 | }
|
| 459 |
|
| 460 | |
| 461 | |
| 462 | |
| 463 | |
| 464 | |
| 465 | |
| 466 | |
| 467 | |
| 468 | |
| 469 | |
| 470 |
|
| 471 | sub output_highlight {
|
| 472 | my $contents = join "\n",@_;
|
| 473 | my $line;
|
| 474 |
|
| 475 | |
| 476 | |
| 477 | |
| 478 | |
| 479 | |
| 480 |
|
| 481 | |
| 482 | eval $dohighlight;
|
| 483 | die $@ if $@;
|
| 484 | |
| 485 |
|
| 486 | foreach $line (split "\n", $contents) {
|
| 487 | if (! $output_preformatted) {
|
| 488 | $line =~ s/^\s*//;
|
| 489 | }
|
| 490 | if ($line eq ""){
|
| 491 | if (! $output_preformatted) {
|
| 492 | print $lineprefix, $blankline;
|
| 493 | }
|
| 494 | } else {
|
| 495 | if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
|
| 496 | print "\\&$line";
|
| 497 | } else {
|
| 498 | print $lineprefix, $line;
|
| 499 | }
|
| 500 | }
|
| 501 | print "\n";
|
| 502 | }
|
| 503 | }
|
| 504 |
|
| 505 | |
| 506 | |
| 507 | sub output_function_man(%) {
|
| 508 | my %args = %{$_[0]};
|
| 509 | my ($parameter, $section);
|
| 510 | my $count;
|
| 511 | my $func_macro = $args{'func_macro'};
|
| 512 | my $paramcount = $#{$args{'parameterlist'}}; |
| 513 |
|
| 514 | print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
|
| 515 |
|
| 516 | print ".SH NAME\n";
|
| 517 | print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
|
| 518 |
|
| 519 | print ".SH SYNOPSIS\n";
|
| 520 | if ($args{'functiontype'} ne "") {
|
| 521 | print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
|
| 522 | } else {
|
| 523 | print ".B \"" . $args{'function'} . "\n";
|
| 524 | }
|
| 525 | $count = 0;
|
| 526 | my $parenth = "(";
|
| 527 | my $post = ",";
|
| 528 | foreach my $parameter (@{$args{'parameterlist'}}) {
|
| 529 | if ($count == $#{$args{'parameterlist'}}) {
|
| 530 | $post = ");";
|
| 531 | }
|
| 532 | $type = $args{'parametertypes'}{$parameter};
|
| 533 | if ($type =~ m/$function_pointer/) {
|
| 534 | |
| 535 | print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
|
| 536 | } else {
|
| 537 | $type =~ s/([^\*])$/$1 /;
|
| 538 | print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
|
| 539 | }
|
| 540 | $count++;
|
| 541 | $parenth = "";
|
| 542 | }
|
| 543 |
|
| 544 | $paramcount = $#{$args{'parameterlist'}}; |
| 545 | if ($paramcount >= 0) {
|
| 546 | print ".SH ARGUMENTS\n";
|
| 547 | }
|
| 548 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 549 | my $parameter_name = $parameter;
|
| 550 | $parameter_name =~ s/\[.*//;
|
| 551 |
|
| 552 | print ".IP \"" . $parameter . "\" 12\n";
|
| 553 | output_highlight($args{'parameterdescs'}{$parameter_name});
|
| 554 | }
|
| 555 | foreach $section (@{$args{'sectionlist'}}) {
|
| 556 | print ".SH \"", uc $section, "\"\n";
|
| 557 | output_highlight($args{'sections'}{$section});
|
| 558 | }
|
| 559 | }
|
| 560 |
|
| 561 | |
| 562 | |
| 563 | sub output_enum_man(%) {
|
| 564 | my %args = %{$_[0]};
|
| 565 | my ($parameter, $section);
|
| 566 | my $count;
|
| 567 |
|
| 568 | print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
|
| 569 |
|
| 570 | print ".SH NAME\n";
|
| 571 | print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
|
| 572 |
|
| 573 | print ".SH SYNOPSIS\n";
|
| 574 | print "enum " . $args{'enum'} . " {\n";
|
| 575 | $count = 0;
|
| 576 | foreach my $parameter (@{$args{'parameterlist'}}) {
|
| 577 | print ".br\n.BI \" $parameter\"\n";
|
| 578 | if ($count == $#{$args{'parameterlist'}}) {
|
| 579 | print "\n};\n";
|
| 580 | last;
|
| 581 | } else {
|
| 582 | print ", \n.br\n";
|
| 583 | }
|
| 584 | $count++;
|
| 585 | }
|
| 586 |
|
| 587 | print ".SH Constants\n";
|
| 588 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 589 | my $parameter_name = $parameter;
|
| 590 | $parameter_name =~ s/\[.*//;
|
| 591 |
|
| 592 | print ".IP \"" . $parameter . "\" 12\n";
|
| 593 | output_highlight($args{'parameterdescs'}{$parameter_name});
|
| 594 | }
|
| 595 | foreach $section (@{$args{'sectionlist'}}) {
|
| 596 | print ".SH \"$section\"\n";
|
| 597 | output_highlight($args{'sections'}{$section});
|
| 598 | }
|
| 599 | }
|
| 600 |
|
| 601 | |
| 602 | |
| 603 | sub output_struct_man(%) {
|
| 604 | my %args = %{$_[0]};
|
| 605 | my ($parameter, $section);
|
| 606 |
|
| 607 | print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
|
| 608 |
|
| 609 | print ".SH NAME\n";
|
| 610 | print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
|
| 611 |
|
| 612 | my $declaration = $args{'definition'};
|
| 613 | $declaration =~ s/\t/ /g;
|
| 614 | $declaration =~ s/\n/"\n.br\n.BI \"/g;
|
| 615 | print ".SH SYNOPSIS\n";
|
| 616 | print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
|
| 617 | print ".BI \"$declaration\n};\n.br\n\n";
|
| 618 |
|
| 619 | print ".SH Members\n";
|
| 620 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 621 | ($parameter =~ /^#/) && next;
|
| 622 |
|
| 623 | my $parameter_name = $parameter;
|
| 624 | $parameter_name =~ s/\[.*//;
|
| 625 |
|
| 626 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
|
| 627 | print ".IP \"" . $parameter . "\" 12\n";
|
| 628 | output_highlight($args{'parameterdescs'}{$parameter_name});
|
| 629 | }
|
| 630 | foreach $section (@{$args{'sectionlist'}}) {
|
| 631 | print ".SH \"$section\"\n";
|
| 632 | output_highlight($args{'sections'}{$section});
|
| 633 | }
|
| 634 | }
|
| 635 |
|
| 636 | |
| 637 | |
| 638 | sub output_typedef_man(%) {
|
| 639 | my %args = %{$_[0]};
|
| 640 | my ($parameter, $section);
|
| 641 |
|
| 642 | print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
|
| 643 |
|
| 644 | print ".SH NAME\n";
|
| 645 | print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
|
| 646 |
|
| 647 | foreach $section (@{$args{'sectionlist'}}) {
|
| 648 | print ".SH \"$section\"\n";
|
| 649 | output_highlight($args{'sections'}{$section});
|
| 650 | }
|
| 651 | }
|
| 652 |
|
| 653 | sub output_blockhead_man(%) {
|
| 654 | my %args = %{$_[0]};
|
| 655 | my ($parameter, $section);
|
| 656 | my $count;
|
| 657 |
|
| 658 | print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
|
| 659 |
|
| 660 | foreach $section (@{$args{'sectionlist'}}) {
|
| 661 | print ".SH \"$section\"\n";
|
| 662 | output_highlight($args{'sections'}{$section});
|
| 663 | }
|
| 664 | }
|
| 665 |
|
| 666 | |
| 667 | |
| 668 | |
| 669 |
|
| 670 | |
| 671 | |
| 672 | |
| 673 | |
| 674 | |
| 675 | sub output_blockhead_rst(%) {
|
| 676 | my %args = %{$_[0]};
|
| 677 | my ($parameter, $section);
|
| 678 |
|
| 679 | foreach $section (@{$args{'sectionlist'}}) {
|
| 680 | next if (defined($nosymbol_table{$section}));
|
| 681 |
|
| 682 | if ($output_selection != OUTPUT_INCLUDE) {
|
| 683 | print ".. _$section:\n\n";
|
| 684 | print "**$section**\n\n";
|
| 685 | }
|
| 686 | print_lineno($section_start_lines{$section});
|
| 687 | output_highlight_rst($args{'sections'}{$section});
|
| 688 | print "\n";
|
| 689 | }
|
| 690 | }
|
| 691 |
|
| 692 | |
| 693 | |
| 694 | |
| 695 | sub highlight_block($) {
|
| 696 | |
| 697 | my $contents = shift;
|
| 698 | eval $dohighlight;
|
| 699 | die $@ if $@;
|
| 700 | return $contents;
|
| 701 | }
|
| 702 |
|
| 703 | |
| 704 | |
| 705 | |
| 706 | my $sphinx_literal = '^[^.].*::$';
|
| 707 | my $sphinx_cblock = '^\.\.\ +code-block::';
|
| 708 |
|
| 709 | sub output_highlight_rst {
|
| 710 | my $input = join "\n",@_;
|
| 711 | my $output = "";
|
| 712 | my $line;
|
| 713 | my $in_literal = 0;
|
| 714 | my $litprefix;
|
| 715 | my $block = "";
|
| 716 |
|
| 717 | foreach $line (split "\n",$input) {
|
| 718 | |
| 719 | |
| 720 | |
| 721 | |
| 722 | if ($in_literal) {
|
| 723 | if (! ($line =~ /^\s*$/)) {
|
| 724 | |
| 725 | |
| 726 | |
| 727 | |
| 728 | if ($litprefix eq "") {
|
| 729 | $line =~ /^(\s*)/;
|
| 730 | $litprefix = '^' . $1;
|
| 731 | $output .= $line . "\n";
|
| 732 | } elsif (! ($line =~ /$litprefix/)) {
|
| 733 | $in_literal = 0;
|
| 734 | } else {
|
| 735 | $output .= $line . "\n";
|
| 736 | }
|
| 737 | } else {
|
| 738 | $output .= $line . "\n";
|
| 739 | }
|
| 740 | }
|
| 741 | |
| 742 | |
| 743 | |
| 744 | if (! $in_literal) {
|
| 745 | $block .= $line . "\n";
|
| 746 | if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
|
| 747 | $in_literal = 1;
|
| 748 | $litprefix = "";
|
| 749 | $output .= highlight_block($block);
|
| 750 | $block = ""
|
| 751 | }
|
| 752 | }
|
| 753 | }
|
| 754 |
|
| 755 | if ($block) {
|
| 756 | $output .= highlight_block($block);
|
| 757 | }
|
| 758 |
|
| 759 | $output =~ s/^\n+//g;
|
| 760 | $output =~ s/\n+$//g;
|
| 761 |
|
| 762 | foreach $line (split "\n", $output) {
|
| 763 | print $lineprefix . $line . "\n";
|
| 764 | }
|
| 765 | }
|
| 766 |
|
| 767 | sub output_function_rst(%) {
|
| 768 | my %args = %{$_[0]};
|
| 769 | my ($parameter, $section);
|
| 770 | my $oldprefix = $lineprefix;
|
| 771 |
|
| 772 | my $signature = "";
|
| 773 | my $func_macro = $args{'func_macro'};
|
| 774 | my $paramcount = $#{$args{'parameterlist'}}; |
| 775 |
|
| 776 | if ($func_macro) {
|
| 777 | $signature = $args{'function'};
|
| 778 | } else {
|
| 779 | if ($args{'functiontype'}) {
|
| 780 | $signature = $args{'functiontype'} . " ";
|
| 781 | }
|
| 782 | $signature .= $args{'function'} . " (";
|
| 783 | }
|
| 784 |
|
| 785 | my $count = 0;
|
| 786 | foreach my $parameter (@{$args{'parameterlist'}}) {
|
| 787 | if ($count ne 0) {
|
| 788 | $signature .= ", ";
|
| 789 | }
|
| 790 | $count++;
|
| 791 | $type = $args{'parametertypes'}{$parameter};
|
| 792 |
|
| 793 | if ($type =~ m/$function_pointer/) {
|
| 794 | |
| 795 | $signature .= $1 . $parameter . ") (" . $2 . ")";
|
| 796 | } else {
|
| 797 | $signature .= $type;
|
| 798 | }
|
| 799 | }
|
| 800 |
|
| 801 | if (!$func_macro) {
|
| 802 | $signature .= ")";
|
| 803 | }
|
| 804 |
|
| 805 | if ($args{'typedef'} || $args{'functiontype'} eq "") {
|
| 806 | print ".. c:macro:: ". $args{'function'} . "\n\n";
|
| 807 |
|
| 808 | if ($args{'typedef'}) {
|
| 809 | print_lineno($declaration_start_line);
|
| 810 | print " **Typedef**: ";
|
| 811 | $lineprefix = "";
|
| 812 | output_highlight_rst($args{'purpose'});
|
| 813 | print "\n\n**Syntax**\n\n";
|
| 814 | print " ``$signature``\n\n";
|
| 815 | } else {
|
| 816 | print "``$signature``\n\n";
|
| 817 | }
|
| 818 | } else {
|
| 819 | print ".. c:function:: $signature\n\n";
|
| 820 | }
|
| 821 |
|
| 822 | if (!$args{'typedef'}) {
|
| 823 | print_lineno($declaration_start_line);
|
| 824 | $lineprefix = " ";
|
| 825 | output_highlight_rst($args{'purpose'});
|
| 826 | print "\n";
|
| 827 | }
|
| 828 |
|
| 829 | |
| 830 | |
| 831 | |
| 832 | |
| 833 | $lineprefix = " ";
|
| 834 | if ($paramcount >= 0) {
|
| 835 | print ".. container:: kernelindent\n\n";
|
| 836 | print $lineprefix . "**Parameters**\n\n";
|
| 837 | }
|
| 838 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 839 | my $parameter_name = $parameter;
|
| 840 | $parameter_name =~ s/\[.*//;
|
| 841 | $type = $args{'parametertypes'}{$parameter};
|
| 842 |
|
| 843 | if ($type ne "") {
|
| 844 | print $lineprefix . "``$type``\n";
|
| 845 | } else {
|
| 846 | print $lineprefix . "``$parameter``\n";
|
| 847 | }
|
| 848 |
|
| 849 | print_lineno($parameterdesc_start_lines{$parameter_name});
|
| 850 |
|
| 851 | $lineprefix = " ";
|
| 852 | if (defined($args{'parameterdescs'}{$parameter_name}) &&
|
| 853 | $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
|
| 854 | output_highlight_rst($args{'parameterdescs'}{$parameter_name});
|
| 855 | } else {
|
| 856 | print $lineprefix . "*undescribed*\n";
|
| 857 | }
|
| 858 | $lineprefix = " ";
|
| 859 | print "\n";
|
| 860 | }
|
| 861 |
|
| 862 | output_section_rst(@_);
|
| 863 | $lineprefix = $oldprefix;
|
| 864 | }
|
| 865 |
|
| 866 | sub output_section_rst(%) {
|
| 867 | my %args = %{$_[0]};
|
| 868 | my $section;
|
| 869 | my $oldprefix = $lineprefix;
|
| 870 |
|
| 871 | foreach $section (@{$args{'sectionlist'}}) {
|
| 872 | print $lineprefix . "**$section**\n\n";
|
| 873 | print_lineno($section_start_lines{$section});
|
| 874 | output_highlight_rst($args{'sections'}{$section});
|
| 875 | print "\n";
|
| 876 | }
|
| 877 | print "\n";
|
| 878 | }
|
| 879 |
|
| 880 | sub output_enum_rst(%) {
|
| 881 | my %args = %{$_[0]};
|
| 882 | my ($parameter);
|
| 883 | my $oldprefix = $lineprefix;
|
| 884 | my $count;
|
| 885 | my $outer;
|
| 886 |
|
| 887 | my $name = $args{'enum'};
|
| 888 | print "\n\n.. c:enum:: " . $name . "\n\n";
|
| 889 |
|
| 890 | print_lineno($declaration_start_line);
|
| 891 | $lineprefix = " ";
|
| 892 | output_highlight_rst($args{'purpose'});
|
| 893 | print "\n";
|
| 894 |
|
| 895 | print ".. container:: kernelindent\n\n";
|
| 896 | $outer = $lineprefix . " ";
|
| 897 | $lineprefix = $outer . " ";
|
| 898 | print $outer . "**Constants**\n\n";
|
| 899 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 900 | print $outer . "``$parameter``\n";
|
| 901 |
|
| 902 | if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
|
| 903 | output_highlight_rst($args{'parameterdescs'}{$parameter});
|
| 904 | } else {
|
| 905 | print $lineprefix . "*undescribed*\n";
|
| 906 | }
|
| 907 | print "\n";
|
| 908 | }
|
| 909 | print "\n";
|
| 910 | $lineprefix = $oldprefix;
|
| 911 | output_section_rst(@_);
|
| 912 | }
|
| 913 |
|
| 914 | sub output_typedef_rst(%) {
|
| 915 | my %args = %{$_[0]};
|
| 916 | my ($parameter);
|
| 917 | my $oldprefix = $lineprefix;
|
| 918 | my $name;
|
| 919 |
|
| 920 | $name = $args{'typedef'};
|
| 921 |
|
| 922 | print "\n\n.. c:type:: " . $name . "\n\n";
|
| 923 | print_lineno($declaration_start_line);
|
| 924 | $lineprefix = " ";
|
| 925 | output_highlight_rst($args{'purpose'});
|
| 926 | print "\n";
|
| 927 |
|
| 928 | $lineprefix = $oldprefix;
|
| 929 | output_section_rst(@_);
|
| 930 | }
|
| 931 |
|
| 932 | sub output_struct_rst(%) {
|
| 933 | my %args = %{$_[0]};
|
| 934 | my ($parameter);
|
| 935 | my $oldprefix = $lineprefix;
|
| 936 |
|
| 937 | my $name = $args{'struct'};
|
| 938 | if ($args{'type'} eq 'union') {
|
| 939 | print "\n\n.. c:union:: " . $name . "\n\n";
|
| 940 | } else {
|
| 941 | print "\n\n.. c:struct:: " . $name . "\n\n";
|
| 942 | }
|
| 943 |
|
| 944 | print_lineno($declaration_start_line);
|
| 945 | $lineprefix = " ";
|
| 946 | output_highlight_rst($args{'purpose'});
|
| 947 | print "\n";
|
| 948 |
|
| 949 | print ".. container:: kernelindent\n\n";
|
| 950 | print $lineprefix . "**Definition**::\n\n";
|
| 951 | my $declaration = $args{'definition'};
|
| 952 | $lineprefix = $lineprefix . " ";
|
| 953 | $declaration =~ s/\t/$lineprefix/g;
|
| 954 | print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n";
|
| 955 |
|
| 956 | $lineprefix = " ";
|
| 957 | print $lineprefix . "**Members**\n\n";
|
| 958 | foreach $parameter (@{$args{'parameterlist'}}) {
|
| 959 | ($parameter =~ /^#/) && next;
|
| 960 |
|
| 961 | my $parameter_name = $parameter;
|
| 962 | $parameter_name =~ s/\[.*//;
|
| 963 |
|
| 964 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
|
| 965 | $type = $args{'parametertypes'}{$parameter};
|
| 966 | print_lineno($parameterdesc_start_lines{$parameter_name});
|
| 967 | print $lineprefix . "``" . $parameter . "``\n";
|
| 968 | $lineprefix = " ";
|
| 969 | output_highlight_rst($args{'parameterdescs'}{$parameter_name});
|
| 970 | $lineprefix = " ";
|
| 971 | print "\n";
|
| 972 | }
|
| 973 | print "\n";
|
| 974 |
|
| 975 | $lineprefix = $oldprefix;
|
| 976 | output_section_rst(@_);
|
| 977 | }
|
| 978 |
|
| 979 | |
| 980 |
|
| 981 | sub output_function_none(%) {
|
| 982 | }
|
| 983 |
|
| 984 | sub output_enum_none(%) {
|
| 985 | }
|
| 986 |
|
| 987 | sub output_typedef_none(%) {
|
| 988 | }
|
| 989 |
|
| 990 | sub output_struct_none(%) {
|
| 991 | }
|
| 992 |
|
| 993 | sub output_blockhead_none(%) {
|
| 994 | }
|
| 995 |
|
| 996 | |
| 997 | |
| 998 | |
| 999 | |
| 1000 | sub output_declaration {
|
| 1001 | no strict 'refs';
|
| 1002 | my $name = shift;
|
| 1003 | my $functype = shift;
|
| 1004 | my $func = "output_${functype}_$output_mode";
|
| 1005 |
|
| 1006 | return if (defined($nosymbol_table{$name}));
|
| 1007 |
|
| 1008 | if (($output_selection == OUTPUT_ALL) ||
|
| 1009 | (($output_selection == OUTPUT_INCLUDE ||
|
| 1010 | $output_selection == OUTPUT_EXPORTED) &&
|
| 1011 | defined($function_table{$name})) ||
|
| 1012 | ($output_selection == OUTPUT_INTERNAL &&
|
| 1013 | !($functype eq "function" && defined($function_table{$name}))))
|
| 1014 | {
|
| 1015 | &$func(@_);
|
| 1016 | $section_counter++;
|
| 1017 | }
|
| 1018 | }
|
| 1019 |
|
| 1020 | |
| 1021 | |
| 1022 | sub output_blockhead {
|
| 1023 | no strict 'refs';
|
| 1024 | my $func = "output_blockhead_" . $output_mode;
|
| 1025 | &$func(@_);
|
| 1026 | $section_counter++;
|
| 1027 | }
|
| 1028 |
|
| 1029 | |
| 1030 | |
| 1031 | |
| 1032 | sub dump_declaration($$) {
|
| 1033 | no strict 'refs';
|
| 1034 | my ($prototype, $file) = @_;
|
| 1035 | my $func = "dump_" . $decl_type;
|
| 1036 | &$func(@_);
|
| 1037 | }
|
| 1038 |
|
| 1039 | sub dump_union($$) {
|
| 1040 | dump_struct(@_);
|
| 1041 | }
|
| 1042 |
|
| 1043 | sub dump_struct($$) {
|
| 1044 | my $x = shift;
|
| 1045 | my $file = shift;
|
| 1046 | my $decl_type;
|
| 1047 | my $members;
|
| 1048 | my $type = qr{struct|union};
|
| 1049 | |
| 1050 | my $qualifiers = qr{$attribute|__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned};
|
| 1051 | my $definition_body = qr{\{(.*)\}\s*$qualifiers*};
|
| 1052 | my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};
|
| 1053 |
|
| 1054 | if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {
|
| 1055 | $decl_type = $1;
|
| 1056 | $declaration_name = $2;
|
| 1057 | $members = $3;
|
| 1058 | } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {
|
| 1059 | $decl_type = $1;
|
| 1060 | $declaration_name = $3;
|
| 1061 | $members = $2;
|
| 1062 | }
|
| 1063 |
|
| 1064 | if ($members) {
|
| 1065 | if ($identifier ne $declaration_name) {
|
| 1066 | emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
|
| 1067 | return;
|
| 1068 | }
|
| 1069 |
|
| 1070 | |
| 1071 | $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
|
| 1072 | $members =~ s/\/\*\s*private:.*//gosi;
|
| 1073 | |
| 1074 | $members =~ s/\/\*.*?\*\///gos;
|
| 1075 | |
| 1076 | $members =~ s/\s*$attribute/ /gi;
|
| 1077 | $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
|
| 1078 | $members =~ s/\s*__counted_by\s*\([^;]*\)/ /gos;
|
| 1079 | $members =~ s/\s*__counted_by_(le|be)\s*\([^;]*\)/ /gos;
|
| 1080 | $members =~ s/\s*__packed\s*/ /gos;
|
| 1081 | $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
|
| 1082 | $members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
|
| 1083 | $members =~ s/\s*____cacheline_aligned/ /gos;
|
| 1084 | |
| 1085 | |
| 1086 | |
| 1087 | $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
|
| 1088 | $members =~ s/\bstruct_group_attr\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
|
| 1089 | $members =~ s/\bstruct_group_tagged\s*\(([^,]*),([^,]*),/struct $1 $2; STRUCT_GROUP(/gos;
|
| 1090 | $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
|
| 1091 | $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
|
| 1092 |
|
| 1093 | my $args = qr{([^,)]+)};
|
| 1094 | |
| 1095 | $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
|
| 1096 | $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;
|
| 1097 | $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
|
| 1098 | |
| 1099 | $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
|
| 1100 | |
| 1101 | $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;
|
| 1102 | |
| 1103 | $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;
|
| 1104 | |
| 1105 | $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;
|
| 1106 | |
| 1107 | $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos;
|
| 1108 | |
| 1109 | $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos;
|
| 1110 | my $declaration = $members;
|
| 1111 |
|
| 1112 | |
| 1113 | while ($members =~ m/$struct_members/) {
|
| 1114 | my $newmember;
|
| 1115 | my $maintype = $1;
|
| 1116 | my $ids = $4;
|
| 1117 | my $content = $3;
|
| 1118 | foreach my $id(split /,/, $ids) {
|
| 1119 | $newmember .= "$maintype $id; ";
|
| 1120 |
|
| 1121 | $id =~ s/[:\[].*//;
|
| 1122 | $id =~ s/^\s*\**(\S+)\s*/$1/;
|
| 1123 | foreach my $arg (split /;/, $content) {
|
| 1124 | next if ($arg =~ m/^\s*$/);
|
| 1125 | if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
|
| 1126 | |
| 1127 | my $type = $1;
|
| 1128 | my $name = $2;
|
| 1129 | my $extra = $3;
|
| 1130 | next if (!$name);
|
| 1131 | if ($id =~ m/^\s*$/) {
|
| 1132 | |
| 1133 | $newmember .= "$type$name$extra; ";
|
| 1134 | } else {
|
| 1135 | $newmember .= "$type$id.$name$extra; ";
|
| 1136 | }
|
| 1137 | } else {
|
| 1138 | my $type;
|
| 1139 | my $names;
|
| 1140 | $arg =~ s/^\s+//;
|
| 1141 | $arg =~ s/\s+$//;
|
| 1142 | |
| 1143 | $arg =~ s/:\s*\d+\s*//g;
|
| 1144 | |
| 1145 | $arg =~ s/\[.*\]//g;
|
| 1146 | |
| 1147 | |
| 1148 | |
| 1149 | |
| 1150 | |
| 1151 | |
| 1152 | $arg =~ s/\s*,\s*/,/g;
|
| 1153 | if ($arg =~ m/(.*)\s+([\S+,]+)/) {
|
| 1154 | $type = $1;
|
| 1155 | $names = $2;
|
| 1156 | } else {
|
| 1157 | $newmember .= "$arg; ";
|
| 1158 | next;
|
| 1159 | }
|
| 1160 | foreach my $name (split /,/, $names) {
|
| 1161 | $name =~ s/^\s*\**(\S+)\s*/$1/;
|
| 1162 | next if (($name =~ m/^\s*$/));
|
| 1163 | if ($id =~ m/^\s*$/) {
|
| 1164 | |
| 1165 | $newmember .= "$type $name; ";
|
| 1166 | } else {
|
| 1167 | $newmember .= "$type $id.$name; ";
|
| 1168 | }
|
| 1169 | }
|
| 1170 | }
|
| 1171 | }
|
| 1172 | }
|
| 1173 | $members =~ s/$struct_members/$newmember/;
|
| 1174 | }
|
| 1175 |
|
| 1176 | |
| 1177 | $members =~ s/(\{[^\{\}]*\})//g;
|
| 1178 |
|
| 1179 | create_parameterlist($members, ';', $file, $declaration_name);
|
| 1180 | check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
|
| 1181 |
|
| 1182 | |
| 1183 | $declaration =~ s/([\{;])/$1\n/g;
|
| 1184 | $declaration =~ s/\}\s+;/};/g;
|
| 1185 | |
| 1186 | do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/);
|
| 1187 |
|
| 1188 | my @def_args = split /\n/, $declaration;
|
| 1189 | my $level = 1;
|
| 1190 | $declaration = "";
|
| 1191 | foreach my $clause (@def_args) {
|
| 1192 | $clause =~ s/^\s+//;
|
| 1193 | $clause =~ s/\s+$//;
|
| 1194 | $clause =~ s/\s+/ /;
|
| 1195 | next if (!$clause);
|
| 1196 | $level-- if ($clause =~ m/(\})/ && $level > 1);
|
| 1197 | if (!($clause =~ m/^\s*#/)) {
|
| 1198 | $declaration .= "\t" x $level;
|
| 1199 | }
|
| 1200 | $declaration .= "\t" . $clause . "\n";
|
| 1201 | $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));
|
| 1202 | }
|
| 1203 | output_declaration($declaration_name,
|
| 1204 | 'struct',
|
| 1205 | {'struct' => $declaration_name,
|
| 1206 | 'module' => $modulename,
|
| 1207 | 'definition' => $declaration,
|
| 1208 | 'parameterlist' => \@parameterlist,
|
| 1209 | 'parameterdescs' => \%parameterdescs,
|
| 1210 | 'parametertypes' => \%parametertypes,
|
| 1211 | 'sectionlist' => \@sectionlist,
|
| 1212 | 'sections' => \%sections,
|
| 1213 | 'purpose' => $declaration_purpose,
|
| 1214 | 'type' => $decl_type
|
| 1215 | });
|
| 1216 | } else {
|
| 1217 | print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
|
| 1218 | ++$errors;
|
| 1219 | }
|
| 1220 | }
|
| 1221 |
|
| 1222 |
|
| 1223 | sub show_warnings($$) {
|
| 1224 | my $functype = shift;
|
| 1225 | my $name = shift;
|
| 1226 |
|
| 1227 | return 0 if (defined($nosymbol_table{$name}));
|
| 1228 |
|
| 1229 | return 1 if ($output_selection == OUTPUT_ALL);
|
| 1230 |
|
| 1231 | if ($output_selection == OUTPUT_EXPORTED) {
|
| 1232 | if (defined($function_table{$name})) {
|
| 1233 | return 1;
|
| 1234 | } else {
|
| 1235 | return 0;
|
| 1236 | }
|
| 1237 | }
|
| 1238 | if ($output_selection == OUTPUT_INTERNAL) {
|
| 1239 | if (!($functype eq "function" && defined($function_table{$name}))) {
|
| 1240 | return 1;
|
| 1241 | } else {
|
| 1242 | return 0;
|
| 1243 | }
|
| 1244 | }
|
| 1245 | if ($output_selection == OUTPUT_INCLUDE) {
|
| 1246 | if (defined($function_table{$name})) {
|
| 1247 | return 1;
|
| 1248 | } else {
|
| 1249 | return 0;
|
| 1250 | }
|
| 1251 | }
|
| 1252 | die("Please add the new output type at show_warnings()");
|
| 1253 | }
|
| 1254 |
|
| 1255 | sub dump_enum($$) {
|
| 1256 | my $x = shift;
|
| 1257 | my $file = shift;
|
| 1258 | my $members;
|
| 1259 |
|
| 1260 | |
| 1261 | $x =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
|
| 1262 | $x =~ s/\/\*\s*private:.*}/}/gosi;
|
| 1263 |
|
| 1264 | $x =~ s@/\*.*?\*/@@gos; |
| 1265 | |
| 1266 | $x =~ s@#\s*((define|ifdef|if)\s+|endif)[^;]*;@@gos;
|
| 1267 |
|
| 1268 | if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
|
| 1269 | $declaration_name = $2;
|
| 1270 | $members = $1;
|
| 1271 | } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
|
| 1272 | $declaration_name = $1;
|
| 1273 | $members = $2;
|
| 1274 | }
|
| 1275 |
|
| 1276 | if ($members) {
|
| 1277 | if ($identifier ne $declaration_name) {
|
| 1278 | if ($identifier eq "") {
|
| 1279 | emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
|
| 1280 | } else {
|
| 1281 | emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
|
| 1282 | }
|
| 1283 | return;
|
| 1284 | }
|
| 1285 | $declaration_name = "(anonymous)" if ($declaration_name eq "");
|
| 1286 |
|
| 1287 | my %_members;
|
| 1288 |
|
| 1289 | $members =~ s/\s+$//;
|
| 1290 | $members =~ s/\([^;]*?[\)]//g;
|
| 1291 |
|
| 1292 | foreach my $arg (split ',', $members) {
|
| 1293 | $arg =~ s/^\s*(\w+).*/$1/;
|
| 1294 | push @parameterlist, $arg;
|
| 1295 | if (!$parameterdescs{$arg}) {
|
| 1296 | $parameterdescs{$arg} = $undescribed;
|
| 1297 | if (show_warnings("enum", $declaration_name)) {
|
| 1298 | emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
|
| 1299 | }
|
| 1300 | }
|
| 1301 | $_members{$arg} = 1;
|
| 1302 | }
|
| 1303 |
|
| 1304 | while (my ($k, $v) = each %parameterdescs) {
|
| 1305 | if (!exists($_members{$k})) {
|
| 1306 | if (show_warnings("enum", $declaration_name)) {
|
| 1307 | emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
|
| 1308 | }
|
| 1309 | }
|
| 1310 | }
|
| 1311 |
|
| 1312 | output_declaration($declaration_name,
|
| 1313 | 'enum',
|
| 1314 | {'enum' => $declaration_name,
|
| 1315 | 'module' => $modulename,
|
| 1316 | 'parameterlist' => \@parameterlist,
|
| 1317 | 'parameterdescs' => \%parameterdescs,
|
| 1318 | 'sectionlist' => \@sectionlist,
|
| 1319 | 'sections' => \%sections,
|
| 1320 | 'purpose' => $declaration_purpose
|
| 1321 | });
|
| 1322 | } else {
|
| 1323 | print STDERR "${file}:$.: error: Cannot parse enum!\n";
|
| 1324 | ++$errors;
|
| 1325 | }
|
| 1326 | }
|
| 1327 |
|
| 1328 | my $typedef_type = qr { ((?:\s+[\w\*]+\b){0,7}\s+(?:\w+\b|\*+))\s* }x;
|
| 1329 | my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
|
| 1330 | my $typedef_args = qr { \s*\((.*)\); }x;
|
| 1331 |
|
| 1332 | my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;
|
| 1333 | my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x;
|
| 1334 |
|
| 1335 | sub dump_typedef($$) {
|
| 1336 | my $x = shift;
|
| 1337 | my $file = shift;
|
| 1338 |
|
| 1339 | $x =~ s@/\*.*?\*/@@gos; |
| 1340 |
|
| 1341 | |
| 1342 | if ($x =~ $typedef1 || $x =~ $typedef2) {
|
| 1343 | $return_type = $1;
|
| 1344 | $declaration_name = $2;
|
| 1345 | my $args = $3;
|
| 1346 | $return_type =~ s/^\s+//;
|
| 1347 |
|
| 1348 | if ($identifier ne $declaration_name) {
|
| 1349 | emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
|
| 1350 | return;
|
| 1351 | }
|
| 1352 |
|
| 1353 | create_parameterlist($args, ',', $file, $declaration_name);
|
| 1354 |
|
| 1355 | output_declaration($declaration_name,
|
| 1356 | 'function',
|
| 1357 | {'function' => $declaration_name,
|
| 1358 | 'typedef' => 1,
|
| 1359 | 'module' => $modulename,
|
| 1360 | 'functiontype' => $return_type,
|
| 1361 | 'parameterlist' => \@parameterlist,
|
| 1362 | 'parameterdescs' => \%parameterdescs,
|
| 1363 | 'parametertypes' => \%parametertypes,
|
| 1364 | 'sectionlist' => \@sectionlist,
|
| 1365 | 'sections' => \%sections,
|
| 1366 | 'purpose' => $declaration_purpose
|
| 1367 | });
|
| 1368 | return;
|
| 1369 | }
|
| 1370 |
|
| 1371 | while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
|
| 1372 | $x =~ s/\(*.\)\s*;$/;/;
|
| 1373 | $x =~ s/\[*.\]\s*;$/;/;
|
| 1374 | }
|
| 1375 |
|
| 1376 | if ($x =~ /typedef.*\s+(\w+)\s*;/) {
|
| 1377 | $declaration_name = $1;
|
| 1378 |
|
| 1379 | if ($identifier ne $declaration_name) {
|
| 1380 | emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
|
| 1381 | return;
|
| 1382 | }
|
| 1383 |
|
| 1384 | output_declaration($declaration_name,
|
| 1385 | 'typedef',
|
| 1386 | {'typedef' => $declaration_name,
|
| 1387 | 'module' => $modulename,
|
| 1388 | 'sectionlist' => \@sectionlist,
|
| 1389 | 'sections' => \%sections,
|
| 1390 | 'purpose' => $declaration_purpose
|
| 1391 | });
|
| 1392 | } else {
|
| 1393 | print STDERR "${file}:$.: error: Cannot parse typedef!\n";
|
| 1394 | ++$errors;
|
| 1395 | }
|
| 1396 | }
|
| 1397 |
|
| 1398 | sub save_struct_actual($) {
|
| 1399 | my $actual = shift;
|
| 1400 |
|
| 1401 | |
| 1402 | $actual =~ s/\s*//g;
|
| 1403 | $struct_actual = $struct_actual . $actual . " ";
|
| 1404 | }
|
| 1405 |
|
| 1406 | sub create_parameterlist($$$$) {
|
| 1407 | my $args = shift;
|
| 1408 | my $splitter = shift;
|
| 1409 | my $file = shift;
|
| 1410 | my $declaration_name = shift;
|
| 1411 | my $type;
|
| 1412 | my $param;
|
| 1413 |
|
| 1414 | |
| 1415 | my $arg_expr = qr{\([^\),]+};
|
| 1416 | while ($args =~ /$arg_expr,/) {
|
| 1417 | $args =~ s/($arg_expr),/$1#/g;
|
| 1418 | }
|
| 1419 |
|
| 1420 | foreach my $arg (split($splitter, $args)) {
|
| 1421 | |
| 1422 | $arg =~ s/\/\*.*\*\///;
|
| 1423 | |
| 1424 | $arg =~ s/\sPOS0?\s/ /;
|
| 1425 | |
| 1426 | $arg =~ s/^\s*//;
|
| 1427 | $arg =~ s/\s*$//;
|
| 1428 | $arg =~ s/\s+/ /;
|
| 1429 |
|
| 1430 | if ($arg =~ /^#/) {
|
| 1431 | |
| 1432 | |
| 1433 | |
| 1434 | push_parameter($arg, "", "", $file);
|
| 1435 | } elsif ($arg =~ m/\(.+\)\s*\(/) {
|
| 1436 | |
| 1437 | $arg =~ tr/#/,/;
|
| 1438 | $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;
|
| 1439 | $param = $1;
|
| 1440 | $type = $arg;
|
| 1441 | $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
|
| 1442 | save_struct_actual($param);
|
| 1443 | push_parameter($param, $type, $arg, $file, $declaration_name);
|
| 1444 | } elsif ($arg =~ m/\(.+\)\s*\[/) {
|
| 1445 | |
| 1446 | $arg =~ tr/#/,/;
|
| 1447 | $arg =~ m/[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+\s*\]\s*)*\)/;
|
| 1448 | $param = $1;
|
| 1449 | $type = $arg;
|
| 1450 | $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
|
| 1451 | save_struct_actual($param);
|
| 1452 | push_parameter($param, $type, $arg, $file, $declaration_name);
|
| 1453 | } elsif ($arg) {
|
| 1454 | $arg =~ s/\s*:\s*/:/g;
|
| 1455 | $arg =~ s/\s*\[/\[/g;
|
| 1456 |
|
| 1457 | my @args = split('\s*,\s*', $arg);
|
| 1458 | if ($args[0] =~ m/\*/) {
|
| 1459 | $args[0] =~ s/(\*+)\s*/ $1/;
|
| 1460 | }
|
| 1461 |
|
| 1462 | my @first_arg;
|
| 1463 | if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
|
| 1464 | shift @args;
|
| 1465 | push(@first_arg, split('\s+', $1));
|
| 1466 | push(@first_arg, $2);
|
| 1467 | } else {
|
| 1468 | @first_arg = split('\s+', shift @args);
|
| 1469 | }
|
| 1470 |
|
| 1471 | unshift(@args, pop @first_arg);
|
| 1472 | $type = join " ", @first_arg;
|
| 1473 |
|
| 1474 | foreach $param (@args) {
|
| 1475 | if ($param =~ m/^(\*+)\s*(.*)/) {
|
| 1476 | save_struct_actual($2);
|
| 1477 |
|
| 1478 | push_parameter($2, "$type $1", $arg, $file, $declaration_name);
|
| 1479 | } elsif ($param =~ m/(.*?):(\w+)/) {
|
| 1480 | if ($type ne "") { |
| 1481 | save_struct_actual($1);
|
| 1482 | push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
|
| 1483 | }
|
| 1484 | } else {
|
| 1485 | save_struct_actual($param);
|
| 1486 | push_parameter($param, $type, $arg, $file, $declaration_name);
|
| 1487 | }
|
| 1488 | }
|
| 1489 | }
|
| 1490 | }
|
| 1491 | }
|
| 1492 |
|
| 1493 | sub push_parameter($$$$$) {
|
| 1494 | my $param = shift;
|
| 1495 | my $type = shift;
|
| 1496 | my $org_arg = shift;
|
| 1497 | my $file = shift;
|
| 1498 | my $declaration_name = shift;
|
| 1499 |
|
| 1500 | if (($anon_struct_union == 1) && ($type eq "") &&
|
| 1501 | ($param eq "}")) {
|
| 1502 | return; |
| 1503 | }
|
| 1504 |
|
| 1505 | $anon_struct_union = 0;
|
| 1506 | $param =~ s/[\[\)].*//;
|
| 1507 |
|
| 1508 | if ($type eq "" && $param =~ /\.\.\.$/)
|
| 1509 | {
|
| 1510 | if (!$param =~ /\w\.\.\.$/) {
|
| 1511 | |
| 1512 | $param = "...";
|
| 1513 | } elsif ($param =~ /\w\.\.\.$/) {
|
| 1514 | |
| 1515 | $param =~ s/\.\.\.$//;
|
| 1516 | }
|
| 1517 | if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
|
| 1518 | $parameterdescs{$param} = "variable arguments";
|
| 1519 | }
|
| 1520 | }
|
| 1521 | elsif ($type eq "" && ($param eq "" or $param eq "void"))
|
| 1522 | {
|
| 1523 | $param="void";
|
| 1524 | $parameterdescs{void} = "no arguments";
|
| 1525 | }
|
| 1526 | elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
|
| 1527 | |
| 1528 | {
|
| 1529 | $type = $param;
|
| 1530 | $param = "{unnamed_" . $param . "}";
|
| 1531 | $parameterdescs{$param} = "anonymous\n";
|
| 1532 | $anon_struct_union = 1;
|
| 1533 | }
|
| 1534 | elsif ($param =~ "__cacheline_group" )
|
| 1535 | |
| 1536 | {
|
| 1537 | return; |
| 1538 | }
|
| 1539 |
|
| 1540 | |
| 1541 | |
| 1542 | |
| 1543 | |
| 1544 | if (!defined $parameterdescs{$param} && $param !~ /^#/) {
|
| 1545 | $parameterdescs{$param} = $undescribed;
|
| 1546 |
|
| 1547 | if (show_warnings($type, $declaration_name) && $param !~ /\./) {
|
| 1548 | emit_warning("${file}:$.", "Function parameter or struct member '$param' not described in '$declaration_name'\n");
|
| 1549 | }
|
| 1550 | }
|
| 1551 |
|
| 1552 | |
| 1553 | |
| 1554 | |
| 1555 | |
| 1556 | |
| 1557 | |
| 1558 | |
| 1559 | |
| 1560 | |
| 1561 | push @parameterlist, $param;
|
| 1562 | $org_arg =~ s/\s\s+/ /g;
|
| 1563 | $parametertypes{$param} = $org_arg;
|
| 1564 | }
|
| 1565 |
|
| 1566 | sub check_sections($$$$$) {
|
| 1567 | my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
|
| 1568 | my @sects = split ' ', $sectcheck;
|
| 1569 | my @prms = split ' ', $prmscheck;
|
| 1570 | my $err;
|
| 1571 | my ($px, $sx);
|
| 1572 | my $prm_clean; |
| 1573 |
|
| 1574 | foreach $sx (0 .. $#sects) {
|
| 1575 | $err = 1;
|
| 1576 | foreach $px (0 .. $#prms) {
|
| 1577 | $prm_clean = $prms[$px];
|
| 1578 | $prm_clean =~ s/\[.*\]//;
|
| 1579 | $prm_clean =~ s/$attribute//i;
|
| 1580 | |
| 1581 | |
| 1582 | |
| 1583 | |
| 1584 | |
| 1585 | |
| 1586 | $prm_clean =~ s/\[.*//;
|
| 1587 |
|
| 1588 | |
| 1589 | if ($prm_clean eq $sects[$sx]) {
|
| 1590 | $err = 0;
|
| 1591 | last;
|
| 1592 | }
|
| 1593 | }
|
| 1594 | if ($err) {
|
| 1595 | if ($decl_type eq "function") {
|
| 1596 | emit_warning("${file}:$.",
|
| 1597 | "Excess function parameter " .
|
| 1598 | "'$sects[$sx]' " .
|
| 1599 | "description in '$decl_name'\n");
|
| 1600 | } elsif (($decl_type eq "struct") or
|
| 1601 | ($decl_type eq "union")) {
|
| 1602 | emit_warning("${file}:$.",
|
| 1603 | "Excess $decl_type member " .
|
| 1604 | "'$sects[$sx]' " .
|
| 1605 | "description in '$decl_name'\n");
|
| 1606 | }
|
| 1607 | }
|
| 1608 | }
|
| 1609 | }
|
| 1610 |
|
| 1611 | |
| 1612 | |
| 1613 | sub check_return_section {
|
| 1614 | my $file = shift;
|
| 1615 | my $declaration_name = shift;
|
| 1616 | my $return_type = shift;
|
| 1617 |
|
| 1618 | |
| 1619 | |
| 1620 | if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
|
| 1621 | return;
|
| 1622 | }
|
| 1623 |
|
| 1624 | if (!defined($sections{$section_return}) ||
|
| 1625 | $sections{$section_return} eq "")
|
| 1626 | {
|
| 1627 | emit_warning("${file}:$.",
|
| 1628 | "No description found for return value of " .
|
| 1629 | "'$declaration_name'\n");
|
| 1630 | }
|
| 1631 | }
|
| 1632 |
|
| 1633 | |
| 1634 | |
| 1635 | |
| 1636 | |
| 1637 | sub dump_function($$) {
|
| 1638 | my $prototype = shift;
|
| 1639 | my $file = shift;
|
| 1640 | my $func_macro = 0;
|
| 1641 |
|
| 1642 | print_lineno($new_start_line);
|
| 1643 |
|
| 1644 | $prototype =~ s/^static +//;
|
| 1645 | $prototype =~ s/^extern +//;
|
| 1646 | $prototype =~ s/^asmlinkage +//;
|
| 1647 | $prototype =~ s/^inline +//;
|
| 1648 | $prototype =~ s/^__inline__ +//;
|
| 1649 | $prototype =~ s/^__inline +//;
|
| 1650 | $prototype =~ s/^__always_inline +//;
|
| 1651 | $prototype =~ s/^noinline +//;
|
| 1652 | $prototype =~ s/^__FORTIFY_INLINE +//;
|
| 1653 | $prototype =~ s/__init +//;
|
| 1654 | $prototype =~ s/__init_or_module +//;
|
| 1655 | $prototype =~ s/__deprecated +//;
|
| 1656 | $prototype =~ s/__flatten +//;
|
| 1657 | $prototype =~ s/__meminit +//;
|
| 1658 | $prototype =~ s/__must_check +//;
|
| 1659 | $prototype =~ s/__weak +//;
|
| 1660 | $prototype =~ s/__sched +//;
|
| 1661 | $prototype =~ s/_noprof//;
|
| 1662 | $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
|
| 1663 | $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;
|
| 1664 | $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//;
|
| 1665 | $prototype =~ s/DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)/$1, $2/;
|
| 1666 | my $define = $prototype =~ s/^#\s*define\s+//; |
| 1667 | $prototype =~ s/__attribute_const__ +//;
|
| 1668 | $prototype =~ s/__attribute__\s*\(\(
|
| 1669 | (?:
|
| 1670 | [\w\s]++ # attribute name
|
| 1671 | (?:\([^)]*+\))? # attribute arguments
|
| 1672 | \s*+,? # optional comma at the end
|
| 1673 | )+
|
| 1674 | \)\)\s+//x;
|
| 1675 |
|
| 1676 | |
| 1677 | |
| 1678 | |
| 1679 | |
| 1680 | |
| 1681 | |
| 1682 | |
| 1683 | |
| 1684 | |
| 1685 | |
| 1686 | |
| 1687 | |
| 1688 | |
| 1689 | |
| 1690 | |
| 1691 | my $name = qr{[a-zA-Z0-9_~:]+};
|
| 1692 | my $prototype_end1 = qr{[^\(]*};
|
| 1693 | my $prototype_end2 = qr{[^\{]*};
|
| 1694 | my $prototype_end = qr{\(($prototype_end1|$prototype_end2)\)};
|
| 1695 | my $type1 = qr{[\w\s]+};
|
| 1696 | my $type2 = qr{$type1\*+};
|
| 1697 |
|
| 1698 | if ($define && $prototype =~ m/^()($name)\s+/) {
|
| 1699 | |
| 1700 | |
| 1701 | |
| 1702 | |
| 1703 | $return_type = $1;
|
| 1704 | $declaration_name = $2;
|
| 1705 | $func_macro = 1;
|
| 1706 | } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ ||
|
| 1707 | $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ ||
|
| 1708 | $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/) {
|
| 1709 | $return_type = $1;
|
| 1710 | $declaration_name = $2;
|
| 1711 | my $args = $3;
|
| 1712 |
|
| 1713 | create_parameterlist($args, ',', $file, $declaration_name);
|
| 1714 | } else {
|
| 1715 | emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
|
| 1716 | return;
|
| 1717 | }
|
| 1718 |
|
| 1719 | if ($identifier ne $declaration_name) {
|
| 1720 | emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
|
| 1721 | return;
|
| 1722 | }
|
| 1723 |
|
| 1724 | my $prms = join " ", @parameterlist;
|
| 1725 | check_sections($file, $declaration_name, "function", $sectcheck, $prms);
|
| 1726 |
|
| 1727 | |
| 1728 | |
| 1729 | |
| 1730 | |
| 1731 | |
| 1732 | if ($Wreturn && !$func_macro) {
|
| 1733 | check_return_section($file, $declaration_name, $return_type);
|
| 1734 | }
|
| 1735 |
|
| 1736 | |
| 1737 | |
| 1738 | if ($return_type =~ /typedef/) {
|
| 1739 | output_declaration($declaration_name,
|
| 1740 | 'function',
|
| 1741 | {'function' => $declaration_name,
|
| 1742 | 'typedef' => 1,
|
| 1743 | 'module' => $modulename,
|
| 1744 | 'functiontype' => $return_type,
|
| 1745 | 'parameterlist' => \@parameterlist,
|
| 1746 | 'parameterdescs' => \%parameterdescs,
|
| 1747 | 'parametertypes' => \%parametertypes,
|
| 1748 | 'sectionlist' => \@sectionlist,
|
| 1749 | 'sections' => \%sections,
|
| 1750 | 'purpose' => $declaration_purpose,
|
| 1751 | 'func_macro' => $func_macro
|
| 1752 | });
|
| 1753 | } else {
|
| 1754 | output_declaration($declaration_name,
|
| 1755 | 'function',
|
| 1756 | {'function' => $declaration_name,
|
| 1757 | 'module' => $modulename,
|
| 1758 | 'functiontype' => $return_type,
|
| 1759 | 'parameterlist' => \@parameterlist,
|
| 1760 | 'parameterdescs' => \%parameterdescs,
|
| 1761 | 'parametertypes' => \%parametertypes,
|
| 1762 | 'sectionlist' => \@sectionlist,
|
| 1763 | 'sections' => \%sections,
|
| 1764 | 'purpose' => $declaration_purpose,
|
| 1765 | 'func_macro' => $func_macro
|
| 1766 | });
|
| 1767 | }
|
| 1768 | }
|
| 1769 |
|
| 1770 | sub reset_state {
|
| 1771 | $function = "";
|
| 1772 | %parameterdescs = ();
|
| 1773 | %parametertypes = ();
|
| 1774 | @parameterlist = ();
|
| 1775 | %sections = ();
|
| 1776 | @sectionlist = ();
|
| 1777 | $sectcheck = "";
|
| 1778 | $struct_actual = "";
|
| 1779 | $prototype = "";
|
| 1780 |
|
| 1781 | $state = STATE_NORMAL;
|
| 1782 | $inline_doc_state = STATE_INLINE_NA;
|
| 1783 | }
|
| 1784 |
|
| 1785 | sub tracepoint_munge($) {
|
| 1786 | my $file = shift;
|
| 1787 | my $tracepointname = 0;
|
| 1788 | my $tracepointargs = 0;
|
| 1789 |
|
| 1790 | if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
|
| 1791 | $tracepointname = $1;
|
| 1792 | }
|
| 1793 | if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
|
| 1794 | $tracepointname = $1;
|
| 1795 | }
|
| 1796 | if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
|
| 1797 | $tracepointname = $2;
|
| 1798 | }
|
| 1799 | $tracepointname =~ s/^\s+//; |
| 1800 | if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
|
| 1801 | $tracepointargs = $1;
|
| 1802 | }
|
| 1803 | if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
|
| 1804 | emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
|
| 1805 | "$prototype\n");
|
| 1806 | } else {
|
| 1807 | $prototype = "static inline void trace_$tracepointname($tracepointargs)";
|
| 1808 | $identifier = "trace_$identifier";
|
| 1809 | }
|
| 1810 | }
|
| 1811 |
|
| 1812 | sub syscall_munge() {
|
| 1813 | my $void = 0;
|
| 1814 |
|
| 1815 | $prototype =~ s@[\r\n]+@ @gos; |
| 1816 | |
| 1817 | if ($prototype =~ m/SYSCALL_DEFINE0/) {
|
| 1818 | $void = 1;
|
| 1819 | |
| 1820 | }
|
| 1821 |
|
| 1822 | $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; |
| 1823 | if ($prototype =~ m/long (sys_.*?),/) {
|
| 1824 | $prototype =~ s/,/\(/;
|
| 1825 | } elsif ($void) {
|
| 1826 | $prototype =~ s/\)/\(void\)/;
|
| 1827 | }
|
| 1828 |
|
| 1829 | |
| 1830 | |
| 1831 | my $count = 0;
|
| 1832 | my $len = length($prototype);
|
| 1833 | if ($void) {
|
| 1834 | $len = 0; |
| 1835 | }
|
| 1836 | for (my $ix = 0; $ix < $len; $ix++) {
|
| 1837 | if (substr($prototype, $ix, 1) eq ',') {
|
| 1838 | $count++;
|
| 1839 | if ($count % 2 == 1) {
|
| 1840 | substr($prototype, $ix, 1) = ' ';
|
| 1841 | }
|
| 1842 | }
|
| 1843 | }
|
| 1844 | }
|
| 1845 |
|
| 1846 | sub process_proto_function($$) {
|
| 1847 | my $x = shift;
|
| 1848 | my $file = shift;
|
| 1849 |
|
| 1850 | $x =~ s@\/\/.*$@@gos; |
| 1851 |
|
| 1852 | if ($x =~ /^#/ && $x !~ /^#\s*define/) {
|
| 1853 | |
| 1854 | } elsif ($x =~ /([^\{]*)/) {
|
| 1855 | $prototype .= $1;
|
| 1856 | }
|
| 1857 |
|
| 1858 | if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
|
| 1859 | $prototype =~ s@/\*.*?\*/@@gos; |
| 1860 | $prototype =~ s@[\r\n]+@ @gos; |
| 1861 | $prototype =~ s@^\s+@@gos; |
| 1862 |
|
| 1863 | |
| 1864 | |
| 1865 | $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
|
| 1866 |
|
| 1867 | if ($prototype =~ /SYSCALL_DEFINE/) {
|
| 1868 | syscall_munge();
|
| 1869 | }
|
| 1870 | if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
|
| 1871 | $prototype =~ /DEFINE_SINGLE_EVENT/)
|
| 1872 | {
|
| 1873 | tracepoint_munge($file);
|
| 1874 | }
|
| 1875 | dump_function($prototype, $file);
|
| 1876 | reset_state();
|
| 1877 | }
|
| 1878 | }
|
| 1879 |
|
| 1880 | sub process_proto_type($$) {
|
| 1881 | my $x = shift;
|
| 1882 | my $file = shift;
|
| 1883 |
|
| 1884 | $x =~ s@[\r\n]+@ @gos; |
| 1885 | $x =~ s@^\s+@@gos; |
| 1886 | $x =~ s@\s+$@@gos; |
| 1887 | $x =~ s@\/\/.*$@@gos; |
| 1888 |
|
| 1889 | if ($x =~ /^#/) {
|
| 1890 | |
| 1891 | $x .= ";";
|
| 1892 | }
|
| 1893 |
|
| 1894 | while (1) {
|
| 1895 | if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) {
|
| 1896 | if( length $prototype ) {
|
| 1897 | $prototype .= " "
|
| 1898 | }
|
| 1899 | $prototype .= $1 . $2;
|
| 1900 | ($2 eq '{') && $brcount++;
|
| 1901 | ($2 eq '}') && $brcount--;
|
| 1902 | if (($2 eq ';') && ($brcount == 0)) {
|
| 1903 | dump_declaration($prototype, $file);
|
| 1904 | reset_state();
|
| 1905 | last;
|
| 1906 | }
|
| 1907 | $x = $3;
|
| 1908 | } else {
|
| 1909 | $prototype .= $x;
|
| 1910 | last;
|
| 1911 | }
|
| 1912 | }
|
| 1913 | }
|
| 1914 |
|
| 1915 |
|
| 1916 | sub map_filename($) {
|
| 1917 | my $file;
|
| 1918 | my ($orig_file) = @_;
|
| 1919 |
|
| 1920 | if (defined($ENV{'SRCTREE'})) {
|
| 1921 | $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
|
| 1922 | } else {
|
| 1923 | $file = $orig_file;
|
| 1924 | }
|
| 1925 |
|
| 1926 | return $file;
|
| 1927 | }
|
| 1928 |
|
| 1929 | sub process_export_file($) {
|
| 1930 | my ($orig_file) = @_;
|
| 1931 | my $file = map_filename($orig_file);
|
| 1932 |
|
| 1933 | if (!open(IN,"<$file")) {
|
| 1934 | print STDERR "Error: Cannot open file $file\n";
|
| 1935 | ++$errors;
|
| 1936 | return;
|
| 1937 | }
|
| 1938 |
|
| 1939 | while (<IN>) {
|
| 1940 | if (/$export_symbol/) {
|
| 1941 | next if (defined($nosymbol_table{$2}));
|
| 1942 | $function_table{$2} = 1;
|
| 1943 | }
|
| 1944 | if (/$export_symbol_ns/) {
|
| 1945 | next if (defined($nosymbol_table{$2}));
|
| 1946 | $function_table{$2} = 1;
|
| 1947 | }
|
| 1948 | }
|
| 1949 |
|
| 1950 | close(IN);
|
| 1951 | }
|
| 1952 |
|
| 1953 | |
| 1954 | |
| 1955 | |
| 1956 | |
| 1957 | |
| 1958 | sub process_normal() {
|
| 1959 | if (/$doc_start/o) {
|
| 1960 | $state = STATE_NAME; |
| 1961 | $declaration_start_line = $. + 1;
|
| 1962 | }
|
| 1963 | }
|
| 1964 |
|
| 1965 | |
| 1966 | |
| 1967 | |
| 1968 | sub process_name($$) {
|
| 1969 | my $file = shift;
|
| 1970 | my $descr;
|
| 1971 |
|
| 1972 | if (/$doc_block/o) {
|
| 1973 | $state = STATE_DOCBLOCK;
|
| 1974 | $contents = "";
|
| 1975 | $new_start_line = $.;
|
| 1976 |
|
| 1977 | if ( $1 eq "" ) {
|
| 1978 | $section = $section_intro;
|
| 1979 | } else {
|
| 1980 | $section = $1;
|
| 1981 | }
|
| 1982 | } elsif (/$doc_decl/o) {
|
| 1983 | $identifier = $1;
|
| 1984 | my $is_kernel_comment = 0;
|
| 1985 | my $decl_start = qr{$doc_com};
|
| 1986 | |
| 1987 | my $fn_type = qr{\w+\s*\*\s*};
|
| 1988 | my $parenthesis = qr{\(\w*\)};
|
| 1989 | my $decl_end = qr{[-:].*};
|
| 1990 | if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) {
|
| 1991 | $identifier = $1;
|
| 1992 | }
|
| 1993 | if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
|
| 1994 | $decl_type = $1;
|
| 1995 | $identifier = $2;
|
| 1996 | $is_kernel_comment = 1;
|
| 1997 | }
|
| 1998 | |
| 1999 | |
| 2000 | elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ ||
|
| 2001 | /^$decl_start$fn_type?(\w+[^-:]*)$parenthesis?\s*$decl_end$/) {
|
| 2002 | $identifier = $1;
|
| 2003 | $decl_type = 'function';
|
| 2004 | $identifier =~ s/^define\s+//;
|
| 2005 | $is_kernel_comment = 1;
|
| 2006 | }
|
| 2007 | $identifier =~ s/\s+$//;
|
| 2008 |
|
| 2009 | $state = STATE_BODY;
|
| 2010 | |
| 2011 | |
| 2012 | $contents = "";
|
| 2013 | $section = $section_default;
|
| 2014 | $new_start_line = $. + 1;
|
| 2015 | if (/[-:](.*)/) {
|
| 2016 | |
| 2017 | $descr= $1;
|
| 2018 | $descr =~ s/^\s*//;
|
| 2019 | $descr =~ s/\s*$//;
|
| 2020 | $descr =~ s/\s+/ /g;
|
| 2021 | $declaration_purpose = $descr;
|
| 2022 | $state = STATE_BODY_MAYBE;
|
| 2023 | } else {
|
| 2024 | $declaration_purpose = "";
|
| 2025 | }
|
| 2026 |
|
| 2027 | if (!$is_kernel_comment) {
|
| 2028 | emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
|
| 2029 | $state = STATE_NORMAL;
|
| 2030 | }
|
| 2031 |
|
| 2032 | if (($declaration_purpose eq "") && $Wshort_desc) {
|
| 2033 | emit_warning("${file}:$.", "missing initial short description on line:\n$_");
|
| 2034 | }
|
| 2035 |
|
| 2036 | if ($identifier eq "" && $decl_type ne "enum") {
|
| 2037 | emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
|
| 2038 | $state = STATE_NORMAL;
|
| 2039 | }
|
| 2040 |
|
| 2041 | if ($verbose) {
|
| 2042 | print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
|
| 2043 | }
|
| 2044 | } else {
|
| 2045 | emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
|
| 2046 | $state = STATE_NORMAL;
|
| 2047 | }
|
| 2048 | }
|
| 2049 |
|
| 2050 |
|
| 2051 | |
| 2052 | |
| 2053 | |
| 2054 | sub process_body($$) {
|
| 2055 | my $file = shift;
|
| 2056 |
|
| 2057 | if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
|
| 2058 | dump_section($file, $section, $contents);
|
| 2059 | $section = $section_default;
|
| 2060 | $new_start_line = $.;
|
| 2061 | $contents = "";
|
| 2062 | }
|
| 2063 |
|
| 2064 | if (/$doc_sect/i) { |
| 2065 | $newsection = $1;
|
| 2066 | $newcontents = $2;
|
| 2067 |
|
| 2068 | |
| 2069 | if ($newsection =~ m/^description$/i) {
|
| 2070 | $newsection = $section_default;
|
| 2071 | } elsif ($newsection =~ m/^context$/i) {
|
| 2072 | $newsection = $section_context;
|
| 2073 | } elsif ($newsection =~ m/^returns?$/i) {
|
| 2074 | $newsection = $section_return;
|
| 2075 | } elsif ($newsection =~ m/^\@return$/) {
|
| 2076 | |
| 2077 | $newsection = $section_return;
|
| 2078 | }
|
| 2079 |
|
| 2080 | if (($contents ne "") && ($contents ne "\n")) {
|
| 2081 | dump_section($file, $section, $contents);
|
| 2082 | $section = $section_default;
|
| 2083 | }
|
| 2084 |
|
| 2085 | $state = STATE_BODY;
|
| 2086 | $contents = $newcontents;
|
| 2087 | $new_start_line = $.;
|
| 2088 | while (substr($contents, 0, 1) eq " ") {
|
| 2089 | $contents = substr($contents, 1);
|
| 2090 | }
|
| 2091 | if ($contents ne "") {
|
| 2092 | $contents .= "\n";
|
| 2093 | }
|
| 2094 | $section = $newsection;
|
| 2095 | $leading_space = undef;
|
| 2096 | } elsif (/$doc_end/) {
|
| 2097 | if (($contents ne "") && ($contents ne "\n")) {
|
| 2098 | dump_section($file, $section, $contents);
|
| 2099 | $section = $section_default;
|
| 2100 | $contents = "";
|
| 2101 | }
|
| 2102 | |
| 2103 | if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
|
| 2104 | emit_warning("${file}:$.", "suspicious ending line: $_");
|
| 2105 | }
|
| 2106 |
|
| 2107 | $prototype = "";
|
| 2108 | $state = STATE_PROTO;
|
| 2109 | $brcount = 0;
|
| 2110 | $new_start_line = $. + 1;
|
| 2111 | } elsif (/$doc_content/) {
|
| 2112 | if ($1 eq "") {
|
| 2113 | if ($section eq $section_context) {
|
| 2114 | dump_section($file, $section, $contents);
|
| 2115 | $section = $section_default;
|
| 2116 | $contents = "";
|
| 2117 | $new_start_line = $.;
|
| 2118 | $state = STATE_BODY;
|
| 2119 | } else {
|
| 2120 | if ($section ne $section_default) {
|
| 2121 | $state = STATE_BODY_WITH_BLANK_LINE;
|
| 2122 | } else {
|
| 2123 | $state = STATE_BODY;
|
| 2124 | }
|
| 2125 | $contents .= "\n";
|
| 2126 | }
|
| 2127 | } elsif ($state == STATE_BODY_MAYBE) {
|
| 2128 | |
| 2129 | chomp($declaration_purpose);
|
| 2130 | $declaration_purpose .= " " . $1;
|
| 2131 | $declaration_purpose =~ s/\s+/ /g;
|
| 2132 | } else {
|
| 2133 | my $cont = $1;
|
| 2134 | if ($section =~ m/^@/ || $section eq $section_context) {
|
| 2135 | if (!defined $leading_space) {
|
| 2136 | if ($cont =~ m/^(\s+)/) {
|
| 2137 | $leading_space = $1;
|
| 2138 | } else {
|
| 2139 | $leading_space = "";
|
| 2140 | }
|
| 2141 | }
|
| 2142 | $cont =~ s/^$leading_space//;
|
| 2143 | }
|
| 2144 | $contents .= $cont . "\n";
|
| 2145 | }
|
| 2146 | } else {
|
| 2147 | |
| 2148 | emit_warning("${file}:$.", "bad line: $_");
|
| 2149 | }
|
| 2150 | }
|
| 2151 |
|
| 2152 |
|
| 2153 | |
| 2154 | |
| 2155 | |
| 2156 | sub process_proto($$) {
|
| 2157 | my $file = shift;
|
| 2158 |
|
| 2159 | if (/$doc_inline_oneline/) {
|
| 2160 | $section = $1;
|
| 2161 | $contents = $2;
|
| 2162 | if ($contents ne "") {
|
| 2163 | $contents .= "\n";
|
| 2164 | dump_section($file, $section, $contents);
|
| 2165 | $section = $section_default;
|
| 2166 | $contents = "";
|
| 2167 | }
|
| 2168 | } elsif (/$doc_inline_start/) {
|
| 2169 | $state = STATE_INLINE;
|
| 2170 | $inline_doc_state = STATE_INLINE_NAME;
|
| 2171 | } elsif ($decl_type eq 'function') {
|
| 2172 | process_proto_function($_, $file);
|
| 2173 | } else {
|
| 2174 | process_proto_type($_, $file);
|
| 2175 | }
|
| 2176 | }
|
| 2177 |
|
| 2178 | |
| 2179 | |
| 2180 | |
| 2181 | sub process_docblock($$) {
|
| 2182 | my $file = shift;
|
| 2183 |
|
| 2184 | if (/$doc_end/) {
|
| 2185 | dump_doc_section($file, $section, $contents);
|
| 2186 | $section = $section_default;
|
| 2187 | $contents = "";
|
| 2188 | $function = "";
|
| 2189 | %parameterdescs = ();
|
| 2190 | %parametertypes = ();
|
| 2191 | @parameterlist = ();
|
| 2192 | %sections = ();
|
| 2193 | @sectionlist = ();
|
| 2194 | $prototype = "";
|
| 2195 | $state = STATE_NORMAL;
|
| 2196 | } elsif (/$doc_content/) {
|
| 2197 | if ( $1 eq "" ) {
|
| 2198 | $contents .= $blankline;
|
| 2199 | } else {
|
| 2200 | $contents .= $1 . "\n";
|
| 2201 | }
|
| 2202 | }
|
| 2203 | }
|
| 2204 |
|
| 2205 | |
| 2206 | |
| 2207 | |
| 2208 | sub process_inline($$) {
|
| 2209 | my $file = shift;
|
| 2210 |
|
| 2211 | |
| 2212 | if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
|
| 2213 | $section = $1;
|
| 2214 | $contents = $2;
|
| 2215 | $new_start_line = $.;
|
| 2216 | if ($contents ne "") {
|
| 2217 | while (substr($contents, 0, 1) eq " ") {
|
| 2218 | $contents = substr($contents, 1);
|
| 2219 | }
|
| 2220 | $contents .= "\n";
|
| 2221 | }
|
| 2222 | $inline_doc_state = STATE_INLINE_TEXT;
|
| 2223 | |
| 2224 | } elsif (/$doc_inline_end/) {
|
| 2225 | if (($contents ne "") && ($contents ne "\n")) {
|
| 2226 | dump_section($file, $section, $contents);
|
| 2227 | $section = $section_default;
|
| 2228 | $contents = "";
|
| 2229 | }
|
| 2230 | $state = STATE_PROTO;
|
| 2231 | $inline_doc_state = STATE_INLINE_NA;
|
| 2232 | |
| 2233 | } elsif (/$doc_content/) {
|
| 2234 | if ($inline_doc_state == STATE_INLINE_TEXT) {
|
| 2235 | $contents .= $1 . "\n";
|
| 2236 | |
| 2237 | if ($contents =~ /^\s*$/) {
|
| 2238 | $contents = "";
|
| 2239 | }
|
| 2240 | } elsif ($inline_doc_state == STATE_INLINE_NAME) {
|
| 2241 | $inline_doc_state = STATE_INLINE_ERROR;
|
| 2242 | emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
|
| 2243 | }
|
| 2244 | }
|
| 2245 | }
|
| 2246 |
|
| 2247 |
|
| 2248 | sub process_file($) {
|
| 2249 | my $file;
|
| 2250 | my ($orig_file) = @_;
|
| 2251 |
|
| 2252 | $file = map_filename($orig_file);
|
| 2253 |
|
| 2254 | if (!open(IN_FILE,"<$file")) {
|
| 2255 | print STDERR "Error: Cannot open file $file\n";
|
| 2256 | ++$errors;
|
| 2257 | return;
|
| 2258 | }
|
| 2259 |
|
| 2260 | $. = 1;
|
| 2261 |
|
| 2262 | $section_counter = 0;
|
| 2263 | while (<IN_FILE>) {
|
| 2264 | while (!/^ \*/ && s/\\\s*$//) {
|
| 2265 | $_ .= <IN_FILE>;
|
| 2266 | }
|
| 2267 | |
| 2268 | while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
|
| 2269 | |
| 2270 | if ($state == STATE_NORMAL) {
|
| 2271 | process_normal();
|
| 2272 | } elsif ($state == STATE_NAME) {
|
| 2273 | process_name($file, $_);
|
| 2274 | } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
|
| 2275 | $state == STATE_BODY_WITH_BLANK_LINE) {
|
| 2276 | process_body($file, $_);
|
| 2277 | } elsif ($state == STATE_INLINE) { |
| 2278 | process_inline($file, $_);
|
| 2279 | } elsif ($state == STATE_PROTO) {
|
| 2280 | process_proto($file, $_);
|
| 2281 | } elsif ($state == STATE_DOCBLOCK) {
|
| 2282 | process_docblock($file, $_);
|
| 2283 | }
|
| 2284 | }
|
| 2285 |
|
| 2286 | |
| 2287 | if (!$section_counter && $output_mode ne "none") {
|
| 2288 | if ($output_selection == OUTPUT_INCLUDE) {
|
| 2289 | emit_warning("${file}:1", "'$_' not found\n")
|
| 2290 | for keys %function_table;
|
| 2291 | } else {
|
| 2292 | emit_warning("${file}:1", "no structured comments found\n");
|
| 2293 | }
|
| 2294 | }
|
| 2295 | close IN_FILE;
|
| 2296 | }
|
| 2297 |
|
| 2298 | $kernelversion = get_kernel_version();
|
| 2299 |
|
| 2300 | |
| 2301 | |
| 2302 | for (my $k = 0; $k < @highlights; $k++) {
|
| 2303 | my $pattern = $highlights[$k][0];
|
| 2304 | my $result = $highlights[$k][1];
|
| 2305 | |
| 2306 | $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n";
|
| 2307 | }
|
| 2308 |
|
| 2309 | if ($output_selection == OUTPUT_EXPORTED ||
|
| 2310 | $output_selection == OUTPUT_INTERNAL) {
|
| 2311 |
|
| 2312 | push(@export_file_list, @ARGV);
|
| 2313 |
|
| 2314 | foreach (@export_file_list) {
|
| 2315 | chomp;
|
| 2316 | process_export_file($_);
|
| 2317 | }
|
| 2318 | }
|
| 2319 |
|
| 2320 | foreach (@ARGV) {
|
| 2321 | chomp;
|
| 2322 | process_file($_);
|
| 2323 | }
|
| 2324 | if ($verbose && $errors) {
|
| 2325 | print STDERR "$errors errors\n";
|
| 2326 | }
|
| 2327 | if ($verbose && $warnings) {
|
| 2328 | print STDERR "$warnings warnings\n";
|
| 2329 | }
|
| 2330 |
|
| 2331 | if ($Werror && $warnings) {
|
| 2332 | print STDERR "$warnings warnings as Errors\n";
|
| 2333 | exit($warnings);
|
| 2334 | } else {
|
| 2335 | exit($output_mode eq "none" ? 0 : $errors)
|
| 2336 | }
|
| 2337 |
|
| 2338 | __END__
|
| 2339 |
|
| 2340 | |
| 2341 |
|
| 2342 | =head2 Output format selection (mutually exclusive):
|
| 2343 |
|
| 2344 | =over 8
|
| 2345 |
|
| 2346 | =item -man
|
| 2347 |
|
| 2348 | Output troff manual page format.
|
| 2349 |
|
| 2350 | =item -rst
|
| 2351 |
|
| 2352 | Output reStructuredText format. This is the default.
|
| 2353 |
|
| 2354 | =item -none
|
| 2355 |
|
| 2356 | Do not output documentation, only warnings.
|
| 2357 |
|
| 2358 | =back
|
| 2359 |
|
| 2360 | =head2 Output format modifiers
|
| 2361 |
|
| 2362 | =head3 reStructuredText only
|
| 2363 |
|
| 2364 | =head2 Output selection (mutually exclusive):
|
| 2365 |
|
| 2366 | =over 8
|
| 2367 |
|
| 2368 | =item -export
|
| 2369 |
|
| 2370 | Only output documentation for the symbols that have been exported using
|
| 2371 | EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
|
| 2372 |
|
| 2373 | =item -internal
|
| 2374 |
|
| 2375 | Only output documentation for the symbols that have NOT been exported using
|
| 2376 | EXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE.
|
| 2377 |
|
| 2378 | =item -function NAME
|
| 2379 |
|
| 2380 | Only output documentation for the given function or DOC: section title.
|
| 2381 | All other functions and DOC: sections are ignored.
|
| 2382 |
|
| 2383 | May be specified multiple times.
|
| 2384 |
|
| 2385 | =item -nosymbol NAME
|
| 2386 |
|
| 2387 | Exclude the specified symbol from the output documentation.
|
| 2388 |
|
| 2389 | May be specified multiple times.
|
| 2390 |
|
| 2391 | =back
|
| 2392 |
|
| 2393 | =head2 Output selection modifiers:
|
| 2394 |
|
| 2395 | =over 8
|
| 2396 |
|
| 2397 | =item -no-doc-sections
|
| 2398 |
|
| 2399 | Do not output DOC: sections.
|
| 2400 |
|
| 2401 | =item -export-file FILE
|
| 2402 |
|
| 2403 | Specify an additional FILE in which to look for EXPORT_SYMBOL information.
|
| 2404 |
|
| 2405 | To be used with -export or -internal.
|
| 2406 |
|
| 2407 | May be specified multiple times.
|
| 2408 |
|
| 2409 | =back
|
| 2410 |
|
| 2411 | =head3 reStructuredText only
|
| 2412 |
|
| 2413 | =over 8
|
| 2414 |
|
| 2415 | =item -enable-lineno
|
| 2416 |
|
| 2417 | Enable output of .. LINENO lines.
|
| 2418 |
|
| 2419 | =back
|
| 2420 |
|
| 2421 | =head2 Other parameters:
|
| 2422 |
|
| 2423 | =over 8
|
| 2424 |
|
| 2425 | =item -h, -help
|
| 2426 |
|
| 2427 | Print this help.
|
| 2428 |
|
| 2429 | =item -v
|
| 2430 |
|
| 2431 | Verbose output, more warnings and other information.
|
| 2432 |
|
| 2433 | =item -Werror
|
| 2434 |
|
| 2435 | Treat warnings as errors.
|
| 2436 |
|
| 2437 | =back
|
| 2438 |
|
| 2439 |
|