1#!/usr/bin/perl -w 2 3use strict; 4 5## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ## 6## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## 7## Copyright (C) 2001 Simon Huggins ## 8## Copyright (C) 2005-2012 Randy Dunlap ## 9## Copyright (C) 2012 Dan Luedtke ## 10## ## 11## #define enhancements by Armin Kuster <akuster@mvista.com> ## 12## Copyright (c) 2000 MontaVista Software, Inc. ## 13## ## 14## This software falls under the GNU General Public License. ## 15## Please read the COPYING file for more information ## 16 17# 18/01/2001 - Cleanups 18# Functions prototyped as foo(void) same as foo() 19# Stop eval'ing where we don't need to. 20# -- huggie@earth.li 21 22# 27/06/2001 - Allowed whitespace after initial "/**" and 23# allowed comments before function declarations. 24# -- Christian Kreibich <ck@whoop.org> 25 26# Still to do: 27# - add perldoc documentation 28# - Look more closely at some of the scarier bits :) 29 30# 26/05/2001 - Support for separate source and object trees. 31# Return error code. 32# Keith Owens <kaos@ocs.com.au> 33 34# 23/09/2001 - Added support for typedefs, structs, enums and unions 35# Support for Context section; can be terminated using empty line 36# Small fixes (like spaces vs. \s in regex) 37# -- Tim Jansen <tim@tjansen.de> 38 39# 25/07/2012 - Added support for HTML5 40# -- Dan Luedtke <mail@danrl.de> 41 42sub usage { 43 my $message = <<"EOF"; 44Usage: $0 [OPTION ...] FILE ... 45 46Read C language source or header FILEs, extract embedded documentation comments, 47and print formatted documentation to standard output. 48 49The documentation comments are identified by "/**" opening comment mark. See 50Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax. 51 52Output format selection (mutually exclusive): 53 -docbook Output DocBook format. 54 -html Output HTML format. 55 -html5 Output HTML5 format. 56 -list Output symbol list format. This is for use by docproc. 57 -man Output troff manual page format. This is the default. 58 -rst Output reStructuredText format. 59 -text Output plain text format. 60 61Output selection (mutually exclusive): 62 -export Only output documentation for symbols that have been 63 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() 64 in the same FILE. 65 -internal Only output documentation for symbols that have NOT been 66 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() 67 in the same FILE. 68 -function NAME Only output documentation for the given function(s) 69 or DOC: section title(s). All other functions and DOC: 70 sections are ignored. May be specified multiple times. 71 -nofunction NAME Do NOT output documentation for the given function(s); 72 only output documentation for the other functions and 73 DOC: sections. May be specified multiple times. 74 75Output selection modifiers: 76 -no-doc-sections Do not output DOC: sections. 77 78Other parameters: 79 -v Verbose output, more warnings and other information. 80 -h Print this help. 81 82EOF 83 print $message; 84 exit 1; 85} 86 87# 88# format of comments. 89# In the following table, (...)? signifies optional structure. 90# (...)* signifies 0 or more structure elements 91# /** 92# * function_name(:)? (- short description)? 93# (* @parameterx: (description of parameter x)?)* 94# (* a blank line)? 95# * (Description:)? (Description of function)? 96# * (section header: (section description)? )* 97# (*)?*/ 98# 99# So .. the trivial example would be: 100# 101# /** 102# * my_function 103# */ 104# 105# If the Description: header tag is omitted, then there must be a blank line 106# after the last parameter specification. 107# e.g. 108# /** 109# * my_function - does my stuff 110# * @my_arg: its mine damnit 111# * 112# * Does my stuff explained. 113# */ 114# 115# or, could also use: 116# /** 117# * my_function - does my stuff 118# * @my_arg: its mine damnit 119# * Description: Does my stuff explained. 120# */ 121# etc. 122# 123# Besides functions you can also write documentation for structs, unions, 124# enums and typedefs. Instead of the function name you must write the name 125# of the declaration; the struct/union/enum/typedef must always precede 126# the name. Nesting of declarations is not supported. 127# Use the argument mechanism to document members or constants. 128# e.g. 129# /** 130# * struct my_struct - short description 131# * @a: first member 132# * @b: second member 133# * 134# * Longer description 135# */ 136# struct my_struct { 137# int a; 138# int b; 139# /* private: */ 140# int c; 141# }; 142# 143# All descriptions can be multiline, except the short function description. 144# 145# For really longs structs, you can also describe arguments inside the 146# body of the struct. 147# eg. 148# /** 149# * struct my_struct - short description 150# * @a: first member 151# * @b: second member 152# * 153# * Longer description 154# */ 155# struct my_struct { 156# int a; 157# int b; 158# /** 159# * @c: This is longer description of C 160# * 161# * You can use paragraphs to describe arguments 162# * using this method. 163# */ 164# int c; 165# }; 166# 167# This should be use only for struct/enum members. 168# 169# You can also add additional sections. When documenting kernel functions you 170# should document the "Context:" of the function, e.g. whether the functions 171# can be called form interrupts. Unlike other sections you can end it with an 172# empty line. 173# A non-void function should have a "Return:" section describing the return 174# value(s). 175# Example-sections should contain the string EXAMPLE so that they are marked 176# appropriately in DocBook. 177# 178# Example: 179# /** 180# * user_function - function that can only be called in user context 181# * @a: some argument 182# * Context: !in_interrupt() 183# * 184# * Some description 185# * Example: 186# * user_function(22); 187# */ 188# ... 189# 190# 191# All descriptive text is further processed, scanning for the following special 192# patterns, which are highlighted appropriately. 193# 194# 'funcname()' - function 195# '$ENVVAR' - environmental variable 196# '&struct_name' - name of a structure (up to two words including 'struct') 197# '@parameter' - name of a parameter 198# '%CONST' - name of a constant. 199 200## init lots of data 201 202my $errors = 0; 203my $warnings = 0; 204my $anon_struct_union = 0; 205 206# match expressions used to find embedded type information 207my $type_constant = '\%([-_\w]+)'; 208my $type_func = '(\w+)\(\)'; 209my $type_param = '\@(\w+)'; 210my $type_struct = '\&((struct\s*)*[_\w]+)'; 211my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; 212my $type_env = '(\$\w+)'; 213my $type_enum_full = '\&(enum)\s*([_\w]+)'; 214my $type_struct_full = '\&(struct)\s*([_\w]+)'; 215my $type_typedef_full = '\&(typedef)\s*([_\w]+)'; 216my $type_union_full = '\&(union)\s*([_\w]+)'; 217 218# Output conversion substitutions. 219# One for each output format 220 221# these work fairly well 222my @highlights_html = ( 223 [$type_constant, "<i>\$1</i>"], 224 [$type_func, "<b>\$1</b>"], 225 [$type_struct_xml, "<i>\$1</i>"], 226 [$type_env, "<b><i>\$1</i></b>"], 227 [$type_param, "<tt><b>\$1</b></tt>"] 228 ); 229my $local_lt = "\\\\\\\\lt:"; 230my $local_gt = "\\\\\\\\gt:"; 231my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" 232 233# html version 5 234my @highlights_html5 = ( 235 [$type_constant, "<span class=\"const\">\$1</span>"], 236 [$type_func, "<span class=\"func\">\$1</span>"], 237 [$type_struct_xml, "<span class=\"struct\">\$1</span>"], 238 [$type_env, "<span class=\"env\">\$1</span>"], 239 [$type_param, "<span class=\"param\">\$1</span>]"] 240 ); 241my $blankline_html5 = $local_lt . "br /" . $local_gt; 242 243# XML, docbook format 244my @highlights_xml = ( 245 ["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"], 246 [$type_constant, "<constant>\$1</constant>"], 247 [$type_struct_xml, "<structname>\$1</structname>"], 248 [$type_param, "<parameter>\$1</parameter>"], 249 [$type_func, "<function>\$1</function>"], 250 [$type_env, "<envar>\$1</envar>"] 251 ); 252my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n"; 253 254# gnome, docbook format 255my @highlights_gnome = ( 256 [$type_constant, "<replaceable class=\"option\">\$1</replaceable>"], 257 [$type_func, "<function>\$1</function>"], 258 [$type_struct, "<structname>\$1</structname>"], 259 [$type_env, "<envar>\$1</envar>"], 260 [$type_param, "<parameter>\$1</parameter>" ] 261 ); 262my $blankline_gnome = "</para><para>\n"; 263 264# these are pretty rough 265my @highlights_man = ( 266 [$type_constant, "\$1"], 267 [$type_func, "\\\\fB\$1\\\\fP"], 268 [$type_struct, "\\\\fI\$1\\\\fP"], 269 [$type_param, "\\\\fI\$1\\\\fP"] 270 ); 271my $blankline_man = ""; 272 273# text-mode 274my @highlights_text = ( 275 [$type_constant, "\$1"], 276 [$type_func, "\$1"], 277 [$type_struct, "\$1"], 278 [$type_param, "\$1"] 279 ); 280my $blankline_text = ""; 281 282# rst-mode 283my @highlights_rst = ( 284 [$type_constant, "``\$1``"], 285 [$type_func, "\\:c\\:func\\:`\$1()`"], 286 [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 287 [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 288 [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 289 [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 290 # in rst this can refer to any type 291 [$type_struct, "\\:c\\:type\\:`\$1`"], 292 [$type_param, "**\$1**"] 293 ); 294my $blankline_rst = "\n"; 295 296# list mode 297my @highlights_list = ( 298 [$type_constant, "\$1"], 299 [$type_func, "\$1"], 300 [$type_struct, "\$1"], 301 [$type_param, "\$1"] 302 ); 303my $blankline_list = ""; 304 305# read arguments 306if ($#ARGV == -1) { 307 usage(); 308} 309 310my $kernelversion; 311my $dohighlight = ""; 312 313my $verbose = 0; 314my $output_mode = "man"; 315my $output_preformatted = 0; 316my $no_doc_sections = 0; 317my @highlights = @highlights_man; 318my $blankline = $blankline_man; 319my $modulename = "Kernel API"; 320 321use constant { 322 OUTPUT_ALL => 0, # output all symbols and doc sections 323 OUTPUT_INCLUDE => 1, # output only specified symbols 324 OUTPUT_EXCLUDE => 2, # output everything except specified symbols 325 OUTPUT_EXPORTED => 3, # output exported symbols 326 OUTPUT_INTERNAL => 4, # output non-exported symbols 327}; 328my $output_selection = OUTPUT_ALL; 329my $show_not_found = 0; 330 331my @build_time; 332if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && 333 (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') { 334 @build_time = gmtime($seconds); 335} else { 336 @build_time = localtime; 337} 338 339my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 340 'July', 'August', 'September', 'October', 341 'November', 'December')[$build_time[4]] . 342 " " . ($build_time[5]+1900); 343 344# Essentially these are globals. 345# They probably want to be tidied up, made more localised or something. 346# CAVEAT EMPTOR! Some of the others I localised may not want to be, which 347# could cause "use of undefined value" or other bugs. 348my ($function, %function_table, %parametertypes, $declaration_purpose); 349my ($type, $declaration_name, $return_type); 350my ($newsection, $newcontents, $prototype, $brcount, %source_map); 351 352if (defined($ENV{'KBUILD_VERBOSE'})) { 353 $verbose = "$ENV{'KBUILD_VERBOSE'}"; 354} 355 356# Generated docbook code is inserted in a template at a point where 357# docbook v3.1 requires a non-zero sequence of RefEntry's; see: 358# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html 359# We keep track of number of generated entries and generate a dummy 360# if needs be to ensure the expanded template can be postprocessed 361# into html. 362my $section_counter = 0; 363 364my $lineprefix=""; 365 366# Parser states 367use constant { 368 STATE_NORMAL => 0, # normal code 369 STATE_NAME => 1, # looking for function name 370 STATE_FIELD => 2, # scanning field start 371 STATE_PROTO => 3, # scanning prototype 372 STATE_DOCBLOCK => 4, # documentation block 373 STATE_INLINE => 5, # gathering documentation outside main block 374}; 375my $state; 376my $in_doc_sect; 377 378# Inline documentation state 379use constant { 380 STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE) 381 STATE_INLINE_NAME => 1, # looking for member name (@foo:) 382 STATE_INLINE_TEXT => 2, # looking for member documentation 383 STATE_INLINE_END => 3, # done 384 STATE_INLINE_ERROR => 4, # error - Comment without header was found. 385 # Spit a warning as it's not 386 # proper kernel-doc and ignore the rest. 387}; 388my $inline_doc_state; 389 390#declaration types: can be 391# 'function', 'struct', 'union', 'enum', 'typedef' 392my $decl_type; 393 394my $doc_special = "\@\%\$\&"; 395 396my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 397my $doc_end = '\*/'; 398my $doc_com = '\s*\*\s*'; 399my $doc_com_body = '\s*\* ?'; 400my $doc_decl = $doc_com . '(\w+)'; 401my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; 402my $doc_content = $doc_com_body . '(.*)'; 403my $doc_block = $doc_com . 'DOC:\s*(.*)?'; 404my $doc_inline_start = '^\s*/\*\*\s*$'; 405my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)'; 406my $doc_inline_end = '^\s*\*/\s*$'; 407my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; 408 409my %constants; 410my %parameterdescs; 411my @parameterlist; 412my %sections; 413my @sectionlist; 414my $sectcheck; 415my $struct_actual; 416 417my $contents = ""; 418my $section_default = "Description"; # default section 419my $section_intro = "Introduction"; 420my $section = $section_default; 421my $section_context = "Context"; 422my $section_return = "Return"; 423 424my $undescribed = "-- undescribed --"; 425 426reset_state(); 427 428while ($ARGV[0] =~ m/^-(.*)/) { 429 my $cmd = shift @ARGV; 430 if ($cmd eq "-html") { 431 $output_mode = "html"; 432 @highlights = @highlights_html; 433 $blankline = $blankline_html; 434 } elsif ($cmd eq "-html5") { 435 $output_mode = "html5"; 436 @highlights = @highlights_html5; 437 $blankline = $blankline_html5; 438 } elsif ($cmd eq "-man") { 439 $output_mode = "man"; 440 @highlights = @highlights_man; 441 $blankline = $blankline_man; 442 } elsif ($cmd eq "-text") { 443 $output_mode = "text"; 444 @highlights = @highlights_text; 445 $blankline = $blankline_text; 446 } elsif ($cmd eq "-rst") { 447 $output_mode = "rst"; 448 @highlights = @highlights_rst; 449 $blankline = $blankline_rst; 450 } elsif ($cmd eq "-docbook") { 451 $output_mode = "xml"; 452 @highlights = @highlights_xml; 453 $blankline = $blankline_xml; 454 } elsif ($cmd eq "-list") { 455 $output_mode = "list"; 456 @highlights = @highlights_list; 457 $blankline = $blankline_list; 458 } elsif ($cmd eq "-gnome") { 459 $output_mode = "gnome"; 460 @highlights = @highlights_gnome; 461 $blankline = $blankline_gnome; 462 } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document 463 $modulename = shift @ARGV; 464 } elsif ($cmd eq "-function") { # to only output specific functions 465 $output_selection = OUTPUT_INCLUDE; 466 $function = shift @ARGV; 467 $function_table{$function} = 1; 468 } elsif ($cmd eq "-nofunction") { # output all except specific functions 469 $output_selection = OUTPUT_EXCLUDE; 470 $function = shift @ARGV; 471 $function_table{$function} = 1; 472 } elsif ($cmd eq "-export") { # only exported symbols 473 $output_selection = OUTPUT_EXPORTED; 474 %function_table = () 475 } elsif ($cmd eq "-internal") { # only non-exported symbols 476 $output_selection = OUTPUT_INTERNAL; 477 %function_table = () 478 } elsif ($cmd eq "-v") { 479 $verbose = 1; 480 } elsif (($cmd eq "-h") || ($cmd eq "--help")) { 481 usage(); 482 } elsif ($cmd eq '-no-doc-sections') { 483 $no_doc_sections = 1; 484 } elsif ($cmd eq '-show-not-found') { 485 $show_not_found = 1; 486 } 487} 488 489# continue execution near EOF; 490 491# get kernel version from env 492sub get_kernel_version() { 493 my $version = 'unknown kernel version'; 494 495 if (defined($ENV{'KERNELVERSION'})) { 496 $version = $ENV{'KERNELVERSION'}; 497 } 498 return $version; 499} 500 501## 502# dumps section contents to arrays/hashes intended for that purpose. 503# 504sub dump_section { 505 my $file = shift; 506 my $name = shift; 507 my $contents = join "\n", @_; 508 509 if ($name =~ m/$type_constant/) { 510 $name = $1; 511# print STDERR "constant section '$1' = '$contents'\n"; 512 $constants{$name} = $contents; 513 } elsif ($name =~ m/$type_param/) { 514# print STDERR "parameter def '$1' = '$contents'\n"; 515 $name = $1; 516 $parameterdescs{$name} = $contents; 517 $sectcheck = $sectcheck . $name . " "; 518 } elsif ($name eq "@\.\.\.") { 519# print STDERR "parameter def '...' = '$contents'\n"; 520 $name = "..."; 521 $parameterdescs{$name} = $contents; 522 $sectcheck = $sectcheck . $name . " "; 523 } else { 524# print STDERR "other section '$name' = '$contents'\n"; 525 if (defined($sections{$name}) && ($sections{$name} ne "")) { 526 print STDERR "${file}:$.: error: duplicate section name '$name'\n"; 527 ++$errors; 528 } 529 $sections{$name} = $contents; 530 push @sectionlist, $name; 531 } 532} 533 534## 535# dump DOC: section after checking that it should go out 536# 537sub dump_doc_section { 538 my $file = shift; 539 my $name = shift; 540 my $contents = join "\n", @_; 541 542 if ($no_doc_sections) { 543 return; 544 } 545 546 if (($output_selection == OUTPUT_ALL) || 547 ($output_selection == OUTPUT_INCLUDE && 548 defined($function_table{$name})) || 549 ($output_selection == OUTPUT_EXCLUDE && 550 !defined($function_table{$name}))) 551 { 552 dump_section($file, $name, $contents); 553 output_blockhead({'sectionlist' => \@sectionlist, 554 'sections' => \%sections, 555 'module' => $modulename, 556 'content-only' => ($output_selection != OUTPUT_ALL), }); 557 } 558} 559 560## 561# output function 562# 563# parameterdescs, a hash. 564# function => "function name" 565# parameterlist => @list of parameters 566# parameterdescs => %parameter descriptions 567# sectionlist => @list of sections 568# sections => %section descriptions 569# 570 571sub output_highlight { 572 my $contents = join "\n",@_; 573 my $line; 574 575# DEBUG 576# if (!defined $contents) { 577# use Carp; 578# confess "output_highlight got called with no args?\n"; 579# } 580 581 if ($output_mode eq "html" || $output_mode eq "html5" || 582 $output_mode eq "xml") { 583 $contents = local_unescape($contents); 584 # convert data read & converted thru xml_escape() into &xyz; format: 585 $contents =~ s/\\\\\\/\&/g; 586 } 587# print STDERR "contents b4:$contents\n"; 588 eval $dohighlight; 589 die $@ if $@; 590# print STDERR "contents af:$contents\n"; 591 592# strip whitespaces when generating html5 593 if ($output_mode eq "html5") { 594 $contents =~ s/^\s+//; 595 $contents =~ s/\s+$//; 596 } 597 foreach $line (split "\n", $contents) { 598 if (! $output_preformatted) { 599 $line =~ s/^\s*//; 600 } 601 if ($line eq ""){ 602 if (! $output_preformatted) { 603 print $lineprefix, local_unescape($blankline); 604 } 605 } else { 606 $line =~ s/\\\\\\/\&/g; 607 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { 608 print "\\&$line"; 609 } else { 610 print $lineprefix, $line; 611 } 612 } 613 print "\n"; 614 } 615} 616 617# output sections in html 618sub output_section_html(%) { 619 my %args = %{$_[0]}; 620 my $section; 621 622 foreach $section (@{$args{'sectionlist'}}) { 623 print "<h3>$section</h3>\n"; 624 print "<blockquote>\n"; 625 output_highlight($args{'sections'}{$section}); 626 print "</blockquote>\n"; 627 } 628} 629 630# output enum in html 631sub output_enum_html(%) { 632 my %args = %{$_[0]}; 633 my ($parameter); 634 my $count; 635 print "<h2>enum " . $args{'enum'} . "</h2>\n"; 636 637 print "<b>enum " . $args{'enum'} . "</b> {<br>\n"; 638 $count = 0; 639 foreach $parameter (@{$args{'parameterlist'}}) { 640 print " <b>" . $parameter . "</b>"; 641 if ($count != $#{$args{'parameterlist'}}) { 642 $count++; 643 print ",\n"; 644 } 645 print "<br>"; 646 } 647 print "};<br>\n"; 648 649 print "<h3>Constants</h3>\n"; 650 print "<dl>\n"; 651 foreach $parameter (@{$args{'parameterlist'}}) { 652 print "<dt><b>" . $parameter . "</b>\n"; 653 print "<dd>"; 654 output_highlight($args{'parameterdescs'}{$parameter}); 655 } 656 print "</dl>\n"; 657 output_section_html(@_); 658 print "<hr>\n"; 659} 660 661# output typedef in html 662sub output_typedef_html(%) { 663 my %args = %{$_[0]}; 664 my ($parameter); 665 my $count; 666 print "<h2>typedef " . $args{'typedef'} . "</h2>\n"; 667 668 print "<b>typedef " . $args{'typedef'} . "</b>\n"; 669 output_section_html(@_); 670 print "<hr>\n"; 671} 672 673# output struct in html 674sub output_struct_html(%) { 675 my %args = %{$_[0]}; 676 my ($parameter); 677 678 print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n"; 679 print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n"; 680 foreach $parameter (@{$args{'parameterlist'}}) { 681 if ($parameter =~ /^#/) { 682 print "$parameter<br>\n"; 683 next; 684 } 685 my $parameter_name = $parameter; 686 $parameter_name =~ s/\[.*//; 687 688 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 689 $type = $args{'parametertypes'}{$parameter}; 690 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 691 # pointer-to-function 692 print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n"; 693 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 694 # bitfield 695 print " <i>$1</i> <b>$parameter</b>$2;<br>\n"; 696 } else { 697 print " <i>$type</i> <b>$parameter</b>;<br>\n"; 698 } 699 } 700 print "};<br>\n"; 701 702 print "<h3>Members</h3>\n"; 703 print "<dl>\n"; 704 foreach $parameter (@{$args{'parameterlist'}}) { 705 ($parameter =~ /^#/) && next; 706 707 my $parameter_name = $parameter; 708 $parameter_name =~ s/\[.*//; 709 710 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 711 print "<dt><b>" . $parameter . "</b>\n"; 712 print "<dd>"; 713 output_highlight($args{'parameterdescs'}{$parameter_name}); 714 } 715 print "</dl>\n"; 716 output_section_html(@_); 717 print "<hr>\n"; 718} 719 720# output function in html 721sub output_function_html(%) { 722 my %args = %{$_[0]}; 723 my ($parameter, $section); 724 my $count; 725 726 print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n"; 727 print "<i>" . $args{'functiontype'} . "</i>\n"; 728 print "<b>" . $args{'function'} . "</b>\n"; 729 print "("; 730 $count = 0; 731 foreach $parameter (@{$args{'parameterlist'}}) { 732 $type = $args{'parametertypes'}{$parameter}; 733 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 734 # pointer-to-function 735 print "<i>$1</i><b>$parameter</b>) <i>($2)</i>"; 736 } else { 737 print "<i>" . $type . "</i> <b>" . $parameter . "</b>"; 738 } 739 if ($count != $#{$args{'parameterlist'}}) { 740 $count++; 741 print ",\n"; 742 } 743 } 744 print ")\n"; 745 746 print "<h3>Arguments</h3>\n"; 747 print "<dl>\n"; 748 foreach $parameter (@{$args{'parameterlist'}}) { 749 my $parameter_name = $parameter; 750 $parameter_name =~ s/\[.*//; 751 752 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 753 print "<dt><b>" . $parameter . "</b>\n"; 754 print "<dd>"; 755 output_highlight($args{'parameterdescs'}{$parameter_name}); 756 } 757 print "</dl>\n"; 758 output_section_html(@_); 759 print "<hr>\n"; 760} 761 762# output DOC: block header in html 763sub output_blockhead_html(%) { 764 my %args = %{$_[0]}; 765 my ($parameter, $section); 766 my $count; 767 768 foreach $section (@{$args{'sectionlist'}}) { 769 print "<h3>$section</h3>\n"; 770 print "<ul>\n"; 771 output_highlight($args{'sections'}{$section}); 772 print "</ul>\n"; 773 } 774 print "<hr>\n"; 775} 776 777# output sections in html5 778sub output_section_html5(%) { 779 my %args = %{$_[0]}; 780 my $section; 781 782 foreach $section (@{$args{'sectionlist'}}) { 783 print "<section>\n"; 784 print "<h1>$section</h1>\n"; 785 print "<p>\n"; 786 output_highlight($args{'sections'}{$section}); 787 print "</p>\n"; 788 print "</section>\n"; 789 } 790} 791 792# output enum in html5 793sub output_enum_html5(%) { 794 my %args = %{$_[0]}; 795 my ($parameter); 796 my $count; 797 my $html5id; 798 799 $html5id = $args{'enum'}; 800 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; 801 print "<article class=\"enum\" id=\"enum:". $html5id . "\">"; 802 print "<h1>enum " . $args{'enum'} . "</h1>\n"; 803 print "<ol class=\"code\">\n"; 804 print "<li>"; 805 print "<span class=\"keyword\">enum</span> "; 806 print "<span class=\"identifier\">" . $args{'enum'} . "</span> {"; 807 print "</li>\n"; 808 $count = 0; 809 foreach $parameter (@{$args{'parameterlist'}}) { 810 print "<li class=\"indent\">"; 811 print "<span class=\"param\">" . $parameter . "</span>"; 812 if ($count != $#{$args{'parameterlist'}}) { 813 $count++; 814 print ","; 815 } 816 print "</li>\n"; 817 } 818 print "<li>};</li>\n"; 819 print "</ol>\n"; 820 821 print "<section>\n"; 822 print "<h1>Constants</h1>\n"; 823 print "<dl>\n"; 824 foreach $parameter (@{$args{'parameterlist'}}) { 825 print "<dt>" . $parameter . "</dt>\n"; 826 print "<dd>"; 827 output_highlight($args{'parameterdescs'}{$parameter}); 828 print "</dd>\n"; 829 } 830 print "</dl>\n"; 831 print "</section>\n"; 832 output_section_html5(@_); 833 print "</article>\n"; 834} 835 836# output typedef in html5 837sub output_typedef_html5(%) { 838 my %args = %{$_[0]}; 839 my ($parameter); 840 my $count; 841 my $html5id; 842 843 $html5id = $args{'typedef'}; 844 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; 845 print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n"; 846 print "<h1>typedef " . $args{'typedef'} . "</h1>\n"; 847 848 print "<ol class=\"code\">\n"; 849 print "<li>"; 850 print "<span class=\"keyword\">typedef</span> "; 851 print "<span class=\"identifier\">" . $args{'typedef'} . "</span>"; 852 print "</li>\n"; 853 print "</ol>\n"; 854 output_section_html5(@_); 855 print "</article>\n"; 856} 857 858# output struct in html5 859sub output_struct_html5(%) { 860 my %args = %{$_[0]}; 861 my ($parameter); 862 my $html5id; 863 864 $html5id = $args{'struct'}; 865 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; 866 print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n"; 867 print "<hgroup>\n"; 868 print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>"; 869 print "<h2>". $args{'purpose'} . "</h2>\n"; 870 print "</hgroup>\n"; 871 print "<ol class=\"code\">\n"; 872 print "<li>"; 873 print "<span class=\"type\">" . $args{'type'} . "</span> "; 874 print "<span class=\"identifier\">" . $args{'struct'} . "</span> {"; 875 print "</li>\n"; 876 foreach $parameter (@{$args{'parameterlist'}}) { 877 print "<li class=\"indent\">"; 878 if ($parameter =~ /^#/) { 879 print "<span class=\"param\">" . $parameter ."</span>\n"; 880 print "</li>\n"; 881 next; 882 } 883 my $parameter_name = $parameter; 884 $parameter_name =~ s/\[.*//; 885 886 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 887 $type = $args{'parametertypes'}{$parameter}; 888 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 889 # pointer-to-function 890 print "<span class=\"type\">$1</span> "; 891 print "<span class=\"param\">$parameter</span>"; 892 print "<span class=\"type\">)</span> "; 893 print "(<span class=\"args\">$2</span>);"; 894 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 895 # bitfield 896 print "<span class=\"type\">$1</span> "; 897 print "<span class=\"param\">$parameter</span>"; 898 print "<span class=\"bits\">$2</span>;"; 899 } else { 900 print "<span class=\"type\">$type</span> "; 901 print "<span class=\"param\">$parameter</span>;"; 902 } 903 print "</li>\n"; 904 } 905 print "<li>};</li>\n"; 906 print "</ol>\n"; 907 908 print "<section>\n"; 909 print "<h1>Members</h1>\n"; 910 print "<dl>\n"; 911 foreach $parameter (@{$args{'parameterlist'}}) { 912 ($parameter =~ /^#/) && next; 913 914 my $parameter_name = $parameter; 915 $parameter_name =~ s/\[.*//; 916 917 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 918 print "<dt>" . $parameter . "</dt>\n"; 919 print "<dd>"; 920 output_highlight($args{'parameterdescs'}{$parameter_name}); 921 print "</dd>\n"; 922 } 923 print "</dl>\n"; 924 print "</section>\n"; 925 output_section_html5(@_); 926 print "</article>\n"; 927} 928 929# output function in html5 930sub output_function_html5(%) { 931 my %args = %{$_[0]}; 932 my ($parameter, $section); 933 my $count; 934 my $html5id; 935 936 $html5id = $args{'function'}; 937 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; 938 print "<article class=\"function\" id=\"func:". $html5id . "\">\n"; 939 print "<hgroup>\n"; 940 print "<h1>" . $args{'function'} . "</h1>"; 941 print "<h2>" . $args{'purpose'} . "</h2>\n"; 942 print "</hgroup>\n"; 943 print "<ol class=\"code\">\n"; 944 print "<li>"; 945 print "<span class=\"type\">" . $args{'functiontype'} . "</span> "; 946 print "<span class=\"identifier\">" . $args{'function'} . "</span> ("; 947 print "</li>"; 948 $count = 0; 949 foreach $parameter (@{$args{'parameterlist'}}) { 950 print "<li class=\"indent\">"; 951 $type = $args{'parametertypes'}{$parameter}; 952 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 953 # pointer-to-function 954 print "<span class=\"type\">$1</span> "; 955 print "<span class=\"param\">$parameter</span>"; 956 print "<span class=\"type\">)</span> "; 957 print "(<span class=\"args\">$2</span>)"; 958 } else { 959 print "<span class=\"type\">$type</span> "; 960 print "<span class=\"param\">$parameter</span>"; 961 } 962 if ($count != $#{$args{'parameterlist'}}) { 963 $count++; 964 print ","; 965 } 966 print "</li>\n"; 967 } 968 print "<li>)</li>\n"; 969 print "</ol>\n"; 970 971 print "<section>\n"; 972 print "<h1>Arguments</h1>\n"; 973 print "<p>\n"; 974 print "<dl>\n"; 975 foreach $parameter (@{$args{'parameterlist'}}) { 976 my $parameter_name = $parameter; 977 $parameter_name =~ s/\[.*//; 978 979 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 980 print "<dt>" . $parameter . "</dt>\n"; 981 print "<dd>"; 982 output_highlight($args{'parameterdescs'}{$parameter_name}); 983 print "</dd>\n"; 984 } 985 print "</dl>\n"; 986 print "</section>\n"; 987 output_section_html5(@_); 988 print "</article>\n"; 989} 990 991# output DOC: block header in html5 992sub output_blockhead_html5(%) { 993 my %args = %{$_[0]}; 994 my ($parameter, $section); 995 my $count; 996 my $html5id; 997 998 foreach $section (@{$args{'sectionlist'}}) { 999 $html5id = $section; 1000 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; 1001 print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n"; 1002 print "<h1>$section</h1>\n"; 1003 print "<p>\n"; 1004 output_highlight($args{'sections'}{$section}); 1005 print "</p>\n"; 1006 } 1007 print "</article>\n"; 1008} 1009 1010sub output_section_xml(%) { 1011 my %args = %{$_[0]}; 1012 my $section; 1013 # print out each section 1014 $lineprefix=" "; 1015 foreach $section (@{$args{'sectionlist'}}) { 1016 print "<refsect1>\n"; 1017 print "<title>$section</title>\n"; 1018 if ($section =~ m/EXAMPLE/i) { 1019 print "<informalexample><programlisting>\n"; 1020 $output_preformatted = 1; 1021 } else { 1022 print "<para>\n"; 1023 } 1024 output_highlight($args{'sections'}{$section}); 1025 $output_preformatted = 0; 1026 if ($section =~ m/EXAMPLE/i) { 1027 print "</programlisting></informalexample>\n"; 1028 } else { 1029 print "</para>\n"; 1030 } 1031 print "</refsect1>\n"; 1032 } 1033} 1034 1035# output function in XML DocBook 1036sub output_function_xml(%) { 1037 my %args = %{$_[0]}; 1038 my ($parameter, $section); 1039 my $count; 1040 my $id; 1041 1042 $id = "API-" . $args{'function'}; 1043 $id =~ s/[^A-Za-z0-9]/-/g; 1044 1045 print "<refentry id=\"$id\">\n"; 1046 print "<refentryinfo>\n"; 1047 print " <title>LINUX</title>\n"; 1048 print " <productname>Kernel Hackers Manual</productname>\n"; 1049 print " <date>$man_date</date>\n"; 1050 print "</refentryinfo>\n"; 1051 print "<refmeta>\n"; 1052 print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n"; 1053 print " <manvolnum>9</manvolnum>\n"; 1054 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 1055 print "</refmeta>\n"; 1056 print "<refnamediv>\n"; 1057 print " <refname>" . $args{'function'} . "</refname>\n"; 1058 print " <refpurpose>\n"; 1059 print " "; 1060 output_highlight ($args{'purpose'}); 1061 print " </refpurpose>\n"; 1062 print "</refnamediv>\n"; 1063 1064 print "<refsynopsisdiv>\n"; 1065 print " <title>Synopsis</title>\n"; 1066 print " <funcsynopsis><funcprototype>\n"; 1067 print " <funcdef>" . $args{'functiontype'} . " "; 1068 print "<function>" . $args{'function'} . " </function></funcdef>\n"; 1069 1070 $count = 0; 1071 if ($#{$args{'parameterlist'}} >= 0) { 1072 foreach $parameter (@{$args{'parameterlist'}}) { 1073 $type = $args{'parametertypes'}{$parameter}; 1074 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1075 # pointer-to-function 1076 print " <paramdef>$1<parameter>$parameter</parameter>)\n"; 1077 print " <funcparams>$2</funcparams></paramdef>\n"; 1078 } else { 1079 print " <paramdef>" . $type; 1080 print " <parameter>$parameter</parameter></paramdef>\n"; 1081 } 1082 } 1083 } else { 1084 print " <void/>\n"; 1085 } 1086 print " </funcprototype></funcsynopsis>\n"; 1087 print "</refsynopsisdiv>\n"; 1088 1089 # print parameters 1090 print "<refsect1>\n <title>Arguments</title>\n"; 1091 if ($#{$args{'parameterlist'}} >= 0) { 1092 print " <variablelist>\n"; 1093 foreach $parameter (@{$args{'parameterlist'}}) { 1094 my $parameter_name = $parameter; 1095 $parameter_name =~ s/\[.*//; 1096 1097 print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n"; 1098 print " <listitem>\n <para>\n"; 1099 $lineprefix=" "; 1100 output_highlight($args{'parameterdescs'}{$parameter_name}); 1101 print " </para>\n </listitem>\n </varlistentry>\n"; 1102 } 1103 print " </variablelist>\n"; 1104 } else { 1105 print " <para>\n None\n </para>\n"; 1106 } 1107 print "</refsect1>\n"; 1108 1109 output_section_xml(@_); 1110 print "</refentry>\n\n"; 1111} 1112 1113# output struct in XML DocBook 1114sub output_struct_xml(%) { 1115 my %args = %{$_[0]}; 1116 my ($parameter, $section); 1117 my $id; 1118 1119 $id = "API-struct-" . $args{'struct'}; 1120 $id =~ s/[^A-Za-z0-9]/-/g; 1121 1122 print "<refentry id=\"$id\">\n"; 1123 print "<refentryinfo>\n"; 1124 print " <title>LINUX</title>\n"; 1125 print " <productname>Kernel Hackers Manual</productname>\n"; 1126 print " <date>$man_date</date>\n"; 1127 print "</refentryinfo>\n"; 1128 print "<refmeta>\n"; 1129 print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n"; 1130 print " <manvolnum>9</manvolnum>\n"; 1131 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 1132 print "</refmeta>\n"; 1133 print "<refnamediv>\n"; 1134 print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n"; 1135 print " <refpurpose>\n"; 1136 print " "; 1137 output_highlight ($args{'purpose'}); 1138 print " </refpurpose>\n"; 1139 print "</refnamediv>\n"; 1140 1141 print "<refsynopsisdiv>\n"; 1142 print " <title>Synopsis</title>\n"; 1143 print " <programlisting>\n"; 1144 print $args{'type'} . " " . $args{'struct'} . " {\n"; 1145 foreach $parameter (@{$args{'parameterlist'}}) { 1146 if ($parameter =~ /^#/) { 1147 my $prm = $parameter; 1148 # convert data read & converted thru xml_escape() into &xyz; format: 1149 # This allows us to have #define macros interspersed in a struct. 1150 $prm =~ s/\\\\\\/\&/g; 1151 print "$prm\n"; 1152 next; 1153 } 1154 1155 my $parameter_name = $parameter; 1156 $parameter_name =~ s/\[.*//; 1157 1158 defined($args{'parameterdescs'}{$parameter_name}) || next; 1159 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1160 $type = $args{'parametertypes'}{$parameter}; 1161 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1162 # pointer-to-function 1163 print " $1 $parameter) ($2);\n"; 1164 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1165 # bitfield 1166 print " $1 $parameter$2;\n"; 1167 } else { 1168 print " " . $type . " " . $parameter . ";\n"; 1169 } 1170 } 1171 print "};"; 1172 print " </programlisting>\n"; 1173 print "</refsynopsisdiv>\n"; 1174 1175 print " <refsect1>\n"; 1176 print " <title>Members</title>\n"; 1177 1178 if ($#{$args{'parameterlist'}} >= 0) { 1179 print " <variablelist>\n"; 1180 foreach $parameter (@{$args{'parameterlist'}}) { 1181 ($parameter =~ /^#/) && next; 1182 1183 my $parameter_name = $parameter; 1184 $parameter_name =~ s/\[.*//; 1185 1186 defined($args{'parameterdescs'}{$parameter_name}) || next; 1187 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1188 print " <varlistentry>"; 1189 print " <term>$parameter</term>\n"; 1190 print " <listitem><para>\n"; 1191 output_highlight($args{'parameterdescs'}{$parameter_name}); 1192 print " </para></listitem>\n"; 1193 print " </varlistentry>\n"; 1194 } 1195 print " </variablelist>\n"; 1196 } else { 1197 print " <para>\n None\n </para>\n"; 1198 } 1199 print " </refsect1>\n"; 1200 1201 output_section_xml(@_); 1202 1203 print "</refentry>\n\n"; 1204} 1205 1206# output enum in XML DocBook 1207sub output_enum_xml(%) { 1208 my %args = %{$_[0]}; 1209 my ($parameter, $section); 1210 my $count; 1211 my $id; 1212 1213 $id = "API-enum-" . $args{'enum'}; 1214 $id =~ s/[^A-Za-z0-9]/-/g; 1215 1216 print "<refentry id=\"$id\">\n"; 1217 print "<refentryinfo>\n"; 1218 print " <title>LINUX</title>\n"; 1219 print " <productname>Kernel Hackers Manual</productname>\n"; 1220 print " <date>$man_date</date>\n"; 1221 print "</refentryinfo>\n"; 1222 print "<refmeta>\n"; 1223 print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n"; 1224 print " <manvolnum>9</manvolnum>\n"; 1225 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 1226 print "</refmeta>\n"; 1227 print "<refnamediv>\n"; 1228 print " <refname>enum " . $args{'enum'} . "</refname>\n"; 1229 print " <refpurpose>\n"; 1230 print " "; 1231 output_highlight ($args{'purpose'}); 1232 print " </refpurpose>\n"; 1233 print "</refnamediv>\n"; 1234 1235 print "<refsynopsisdiv>\n"; 1236 print " <title>Synopsis</title>\n"; 1237 print " <programlisting>\n"; 1238 print "enum " . $args{'enum'} . " {\n"; 1239 $count = 0; 1240 foreach $parameter (@{$args{'parameterlist'}}) { 1241 print " $parameter"; 1242 if ($count != $#{$args{'parameterlist'}}) { 1243 $count++; 1244 print ","; 1245 } 1246 print "\n"; 1247 } 1248 print "};"; 1249 print " </programlisting>\n"; 1250 print "</refsynopsisdiv>\n"; 1251 1252 print "<refsect1>\n"; 1253 print " <title>Constants</title>\n"; 1254 print " <variablelist>\n"; 1255 foreach $parameter (@{$args{'parameterlist'}}) { 1256 my $parameter_name = $parameter; 1257 $parameter_name =~ s/\[.*//; 1258 1259 print " <varlistentry>"; 1260 print " <term>$parameter</term>\n"; 1261 print " <listitem><para>\n"; 1262 output_highlight($args{'parameterdescs'}{$parameter_name}); 1263 print " </para></listitem>\n"; 1264 print " </varlistentry>\n"; 1265 } 1266 print " </variablelist>\n"; 1267 print "</refsect1>\n"; 1268 1269 output_section_xml(@_); 1270 1271 print "</refentry>\n\n"; 1272} 1273 1274# output typedef in XML DocBook 1275sub output_typedef_xml(%) { 1276 my %args = %{$_[0]}; 1277 my ($parameter, $section); 1278 my $id; 1279 1280 $id = "API-typedef-" . $args{'typedef'}; 1281 $id =~ s/[^A-Za-z0-9]/-/g; 1282 1283 print "<refentry id=\"$id\">\n"; 1284 print "<refentryinfo>\n"; 1285 print " <title>LINUX</title>\n"; 1286 print " <productname>Kernel Hackers Manual</productname>\n"; 1287 print " <date>$man_date</date>\n"; 1288 print "</refentryinfo>\n"; 1289 print "<refmeta>\n"; 1290 print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n"; 1291 print " <manvolnum>9</manvolnum>\n"; 1292 print "</refmeta>\n"; 1293 print "<refnamediv>\n"; 1294 print " <refname>typedef " . $args{'typedef'} . "</refname>\n"; 1295 print " <refpurpose>\n"; 1296 print " "; 1297 output_highlight ($args{'purpose'}); 1298 print " </refpurpose>\n"; 1299 print "</refnamediv>\n"; 1300 1301 print "<refsynopsisdiv>\n"; 1302 print " <title>Synopsis</title>\n"; 1303 print " <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n"; 1304 print "</refsynopsisdiv>\n"; 1305 1306 output_section_xml(@_); 1307 1308 print "</refentry>\n\n"; 1309} 1310 1311# output in XML DocBook 1312sub output_blockhead_xml(%) { 1313 my %args = %{$_[0]}; 1314 my ($parameter, $section); 1315 my $count; 1316 1317 my $id = $args{'module'}; 1318 $id =~ s/[^A-Za-z0-9]/-/g; 1319 1320 # print out each section 1321 $lineprefix=" "; 1322 foreach $section (@{$args{'sectionlist'}}) { 1323 if (!$args{'content-only'}) { 1324 print "<refsect1>\n <title>$section</title>\n"; 1325 } 1326 if ($section =~ m/EXAMPLE/i) { 1327 print "<example><para>\n"; 1328 $output_preformatted = 1; 1329 } else { 1330 print "<para>\n"; 1331 } 1332 output_highlight($args{'sections'}{$section}); 1333 $output_preformatted = 0; 1334 if ($section =~ m/EXAMPLE/i) { 1335 print "</para></example>\n"; 1336 } else { 1337 print "</para>"; 1338 } 1339 if (!$args{'content-only'}) { 1340 print "\n</refsect1>\n"; 1341 } 1342 } 1343 1344 print "\n\n"; 1345} 1346 1347# output in XML DocBook 1348sub output_function_gnome { 1349 my %args = %{$_[0]}; 1350 my ($parameter, $section); 1351 my $count; 1352 my $id; 1353 1354 $id = $args{'module'} . "-" . $args{'function'}; 1355 $id =~ s/[^A-Za-z0-9]/-/g; 1356 1357 print "<sect2>\n"; 1358 print " <title id=\"$id\">" . $args{'function'} . "</title>\n"; 1359 1360 print " <funcsynopsis>\n"; 1361 print " <funcdef>" . $args{'functiontype'} . " "; 1362 print "<function>" . $args{'function'} . " "; 1363 print "</function></funcdef>\n"; 1364 1365 $count = 0; 1366 if ($#{$args{'parameterlist'}} >= 0) { 1367 foreach $parameter (@{$args{'parameterlist'}}) { 1368 $type = $args{'parametertypes'}{$parameter}; 1369 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1370 # pointer-to-function 1371 print " <paramdef>$1 <parameter>$parameter</parameter>)\n"; 1372 print " <funcparams>$2</funcparams></paramdef>\n"; 1373 } else { 1374 print " <paramdef>" . $type; 1375 print " <parameter>$parameter</parameter></paramdef>\n"; 1376 } 1377 } 1378 } else { 1379 print " <void>\n"; 1380 } 1381 print " </funcsynopsis>\n"; 1382 if ($#{$args{'parameterlist'}} >= 0) { 1383 print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n"; 1384 print "<tgroup cols=\"2\">\n"; 1385 print "<colspec colwidth=\"2*\">\n"; 1386 print "<colspec colwidth=\"8*\">\n"; 1387 print "<tbody>\n"; 1388 foreach $parameter (@{$args{'parameterlist'}}) { 1389 my $parameter_name = $parameter; 1390 $parameter_name =~ s/\[.*//; 1391 1392 print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n"; 1393 print " <entry>\n"; 1394 $lineprefix=" "; 1395 output_highlight($args{'parameterdescs'}{$parameter_name}); 1396 print " </entry></row>\n"; 1397 } 1398 print " </tbody></tgroup></informaltable>\n"; 1399 } else { 1400 print " <para>\n None\n </para>\n"; 1401 } 1402 1403 # print out each section 1404 $lineprefix=" "; 1405 foreach $section (@{$args{'sectionlist'}}) { 1406 print "<simplesect>\n <title>$section</title>\n"; 1407 if ($section =~ m/EXAMPLE/i) { 1408 print "<example><programlisting>\n"; 1409 $output_preformatted = 1; 1410 } else { 1411 } 1412 print "<para>\n"; 1413 output_highlight($args{'sections'}{$section}); 1414 $output_preformatted = 0; 1415 print "</para>\n"; 1416 if ($section =~ m/EXAMPLE/i) { 1417 print "</programlisting></example>\n"; 1418 } else { 1419 } 1420 print " </simplesect>\n"; 1421 } 1422 1423 print "</sect2>\n\n"; 1424} 1425 1426## 1427# output function in man 1428sub output_function_man(%) { 1429 my %args = %{$_[0]}; 1430 my ($parameter, $section); 1431 my $count; 1432 1433 print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; 1434 1435 print ".SH NAME\n"; 1436 print $args{'function'} . " \\- " . $args{'purpose'} . "\n"; 1437 1438 print ".SH SYNOPSIS\n"; 1439 if ($args{'functiontype'} ne "") { 1440 print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n"; 1441 } else { 1442 print ".B \"" . $args{'function'} . "\n"; 1443 } 1444 $count = 0; 1445 my $parenth = "("; 1446 my $post = ","; 1447 foreach my $parameter (@{$args{'parameterlist'}}) { 1448 if ($count == $#{$args{'parameterlist'}}) { 1449 $post = ");"; 1450 } 1451 $type = $args{'parametertypes'}{$parameter}; 1452 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1453 # pointer-to-function 1454 print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n"; 1455 } else { 1456 $type =~ s/([^\*])$/$1 /; 1457 print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n"; 1458 } 1459 $count++; 1460 $parenth = ""; 1461 } 1462 1463 print ".SH ARGUMENTS\n"; 1464 foreach $parameter (@{$args{'parameterlist'}}) { 1465 my $parameter_name = $parameter; 1466 $parameter_name =~ s/\[.*//; 1467 1468 print ".IP \"" . $parameter . "\" 12\n"; 1469 output_highlight($args{'parameterdescs'}{$parameter_name}); 1470 } 1471 foreach $section (@{$args{'sectionlist'}}) { 1472 print ".SH \"", uc $section, "\"\n"; 1473 output_highlight($args{'sections'}{$section}); 1474 } 1475} 1476 1477## 1478# output enum in man 1479sub output_enum_man(%) { 1480 my %args = %{$_[0]}; 1481 my ($parameter, $section); 1482 my $count; 1483 1484 print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1485 1486 print ".SH NAME\n"; 1487 print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n"; 1488 1489 print ".SH SYNOPSIS\n"; 1490 print "enum " . $args{'enum'} . " {\n"; 1491 $count = 0; 1492 foreach my $parameter (@{$args{'parameterlist'}}) { 1493 print ".br\n.BI \" $parameter\"\n"; 1494 if ($count == $#{$args{'parameterlist'}}) { 1495 print "\n};\n"; 1496 last; 1497 } 1498 else { 1499 print ", \n.br\n"; 1500 } 1501 $count++; 1502 } 1503 1504 print ".SH Constants\n"; 1505 foreach $parameter (@{$args{'parameterlist'}}) { 1506 my $parameter_name = $parameter; 1507 $parameter_name =~ s/\[.*//; 1508 1509 print ".IP \"" . $parameter . "\" 12\n"; 1510 output_highlight($args{'parameterdescs'}{$parameter_name}); 1511 } 1512 foreach $section (@{$args{'sectionlist'}}) { 1513 print ".SH \"$section\"\n"; 1514 output_highlight($args{'sections'}{$section}); 1515 } 1516} 1517 1518## 1519# output struct in man 1520sub output_struct_man(%) { 1521 my %args = %{$_[0]}; 1522 my ($parameter, $section); 1523 1524 print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n"; 1525 1526 print ".SH NAME\n"; 1527 print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n"; 1528 1529 print ".SH SYNOPSIS\n"; 1530 print $args{'type'} . " " . $args{'struct'} . " {\n.br\n"; 1531 1532 foreach my $parameter (@{$args{'parameterlist'}}) { 1533 if ($parameter =~ /^#/) { 1534 print ".BI \"$parameter\"\n.br\n"; 1535 next; 1536 } 1537 my $parameter_name = $parameter; 1538 $parameter_name =~ s/\[.*//; 1539 1540 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1541 $type = $args{'parametertypes'}{$parameter}; 1542 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1543 # pointer-to-function 1544 print ".BI \" " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n"; 1545 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1546 # bitfield 1547 print ".BI \" " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n"; 1548 } else { 1549 $type =~ s/([^\*])$/$1 /; 1550 print ".BI \" " . $type . "\" " . $parameter . " \"" . "\"\n;\n"; 1551 } 1552 print "\n.br\n"; 1553 } 1554 print "};\n.br\n"; 1555 1556 print ".SH Members\n"; 1557 foreach $parameter (@{$args{'parameterlist'}}) { 1558 ($parameter =~ /^#/) && next; 1559 1560 my $parameter_name = $parameter; 1561 $parameter_name =~ s/\[.*//; 1562 1563 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1564 print ".IP \"" . $parameter . "\" 12\n"; 1565 output_highlight($args{'parameterdescs'}{$parameter_name}); 1566 } 1567 foreach $section (@{$args{'sectionlist'}}) { 1568 print ".SH \"$section\"\n"; 1569 output_highlight($args{'sections'}{$section}); 1570 } 1571} 1572 1573## 1574# output typedef in man 1575sub output_typedef_man(%) { 1576 my %args = %{$_[0]}; 1577 my ($parameter, $section); 1578 1579 print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1580 1581 print ".SH NAME\n"; 1582 print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n"; 1583 1584 foreach $section (@{$args{'sectionlist'}}) { 1585 print ".SH \"$section\"\n"; 1586 output_highlight($args{'sections'}{$section}); 1587 } 1588} 1589 1590sub output_blockhead_man(%) { 1591 my %args = %{$_[0]}; 1592 my ($parameter, $section); 1593 my $count; 1594 1595 print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1596 1597 foreach $section (@{$args{'sectionlist'}}) { 1598 print ".SH \"$section\"\n"; 1599 output_highlight($args{'sections'}{$section}); 1600 } 1601} 1602 1603## 1604# output in text 1605sub output_function_text(%) { 1606 my %args = %{$_[0]}; 1607 my ($parameter, $section); 1608 my $start; 1609 1610 print "Name:\n\n"; 1611 print $args{'function'} . " - " . $args{'purpose'} . "\n"; 1612 1613 print "\nSynopsis:\n\n"; 1614 if ($args{'functiontype'} ne "") { 1615 $start = $args{'functiontype'} . " " . $args{'function'} . " ("; 1616 } else { 1617 $start = $args{'function'} . " ("; 1618 } 1619 print $start; 1620 1621 my $count = 0; 1622 foreach my $parameter (@{$args{'parameterlist'}}) { 1623 $type = $args{'parametertypes'}{$parameter}; 1624 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1625 # pointer-to-function 1626 print $1 . $parameter . ") (" . $2; 1627 } else { 1628 print $type . " " . $parameter; 1629 } 1630 if ($count != $#{$args{'parameterlist'}}) { 1631 $count++; 1632 print ",\n"; 1633 print " " x length($start); 1634 } else { 1635 print ");\n\n"; 1636 } 1637 } 1638 1639 print "Arguments:\n\n"; 1640 foreach $parameter (@{$args{'parameterlist'}}) { 1641 my $parameter_name = $parameter; 1642 $parameter_name =~ s/\[.*//; 1643 1644 print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n"; 1645 } 1646 output_section_text(@_); 1647} 1648 1649#output sections in text 1650sub output_section_text(%) { 1651 my %args = %{$_[0]}; 1652 my $section; 1653 1654 print "\n"; 1655 foreach $section (@{$args{'sectionlist'}}) { 1656 print "$section:\n\n"; 1657 output_highlight($args{'sections'}{$section}); 1658 } 1659 print "\n\n"; 1660} 1661 1662# output enum in text 1663sub output_enum_text(%) { 1664 my %args = %{$_[0]}; 1665 my ($parameter); 1666 my $count; 1667 print "Enum:\n\n"; 1668 1669 print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n"; 1670 print "enum " . $args{'enum'} . " {\n"; 1671 $count = 0; 1672 foreach $parameter (@{$args{'parameterlist'}}) { 1673 print "\t$parameter"; 1674 if ($count != $#{$args{'parameterlist'}}) { 1675 $count++; 1676 print ","; 1677 } 1678 print "\n"; 1679 } 1680 print "};\n\n"; 1681 1682 print "Constants:\n\n"; 1683 foreach $parameter (@{$args{'parameterlist'}}) { 1684 print "$parameter\n\t"; 1685 print $args{'parameterdescs'}{$parameter} . "\n"; 1686 } 1687 1688 output_section_text(@_); 1689} 1690 1691# output typedef in text 1692sub output_typedef_text(%) { 1693 my %args = %{$_[0]}; 1694 my ($parameter); 1695 my $count; 1696 print "Typedef:\n\n"; 1697 1698 print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n"; 1699 output_section_text(@_); 1700} 1701 1702# output struct as text 1703sub output_struct_text(%) { 1704 my %args = %{$_[0]}; 1705 my ($parameter); 1706 1707 print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n"; 1708 print $args{'type'} . " " . $args{'struct'} . " {\n"; 1709 foreach $parameter (@{$args{'parameterlist'}}) { 1710 if ($parameter =~ /^#/) { 1711 print "$parameter\n"; 1712 next; 1713 } 1714 1715 my $parameter_name = $parameter; 1716 $parameter_name =~ s/\[.*//; 1717 1718 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1719 $type = $args{'parametertypes'}{$parameter}; 1720 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1721 # pointer-to-function 1722 print "\t$1 $parameter) ($2);\n"; 1723 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1724 # bitfield 1725 print "\t$1 $parameter$2;\n"; 1726 } else { 1727 print "\t" . $type . " " . $parameter . ";\n"; 1728 } 1729 } 1730 print "};\n\n"; 1731 1732 print "Members:\n\n"; 1733 foreach $parameter (@{$args{'parameterlist'}}) { 1734 ($parameter =~ /^#/) && next; 1735 1736 my $parameter_name = $parameter; 1737 $parameter_name =~ s/\[.*//; 1738 1739 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1740 print "$parameter\n\t"; 1741 print $args{'parameterdescs'}{$parameter_name} . "\n"; 1742 } 1743 print "\n"; 1744 output_section_text(@_); 1745} 1746 1747sub output_blockhead_text(%) { 1748 my %args = %{$_[0]}; 1749 my ($parameter, $section); 1750 1751 foreach $section (@{$args{'sectionlist'}}) { 1752 print " $section:\n"; 1753 print " -> "; 1754 output_highlight($args{'sections'}{$section}); 1755 } 1756} 1757 1758## 1759# output in restructured text 1760# 1761 1762# 1763# This could use some work; it's used to output the DOC: sections, and 1764# starts by putting out the name of the doc section itself, but that tends 1765# to duplicate a header already in the template file. 1766# 1767sub output_blockhead_rst(%) { 1768 my %args = %{$_[0]}; 1769 my ($parameter, $section); 1770 1771 foreach $section (@{$args{'sectionlist'}}) { 1772 if ($output_selection != OUTPUT_INCLUDE) { 1773 print "**$section**\n\n"; 1774 } 1775 output_highlight_rst($args{'sections'}{$section}); 1776 print "\n"; 1777 } 1778} 1779 1780sub output_highlight_rst { 1781 my $contents = join "\n",@_; 1782 my $line; 1783 1784 # undo the evil effects of xml_escape() earlier 1785 $contents = xml_unescape($contents); 1786 1787 eval $dohighlight; 1788 die $@ if $@; 1789 1790 foreach $line (split "\n", $contents) { 1791 if ($line eq "") { 1792 print $lineprefix, $blankline; 1793 } else { 1794 $line =~ s/\\\\\\/\&/g; 1795 print $lineprefix, $line; 1796 } 1797 print "\n"; 1798 } 1799} 1800 1801sub output_function_rst(%) { 1802 my %args = %{$_[0]}; 1803 my ($parameter, $section); 1804 my $start; 1805 1806 print ".. c:function:: "; 1807 if ($args{'functiontype'} ne "") { 1808 $start = $args{'functiontype'} . " " . $args{'function'} . " ("; 1809 } else { 1810 $start = $args{'function'} . " ("; 1811 } 1812 print $start; 1813 1814 my $count = 0; 1815 foreach my $parameter (@{$args{'parameterlist'}}) { 1816 if ($count ne 0) { 1817 print ", "; 1818 } 1819 $count++; 1820 $type = $args{'parametertypes'}{$parameter}; 1821 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1822 # pointer-to-function 1823 print $1 . $parameter . ") (" . $2; 1824 } else { 1825 print $type . " " . $parameter; 1826 } 1827 } 1828 print ")\n\n " . $args{'purpose'} . "\n\n"; 1829 1830 print ":Parameters:\n\n"; 1831 foreach $parameter (@{$args{'parameterlist'}}) { 1832 my $parameter_name = $parameter; 1833 #$parameter_name =~ s/\[.*//; 1834 $type = $args{'parametertypes'}{$parameter}; 1835 1836 if ($type ne "") { 1837 print " ``$type $parameter``\n"; 1838 } else { 1839 print " ``$parameter``\n"; 1840 } 1841 if (defined($args{'parameterdescs'}{$parameter_name}) && 1842 $args{'parameterdescs'}{$parameter_name} ne $undescribed) { 1843 my $oldprefix = $lineprefix; 1844 $lineprefix = " "; 1845 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 1846 $lineprefix = $oldprefix; 1847 } else { 1848 print "\n _undescribed_\n"; 1849 } 1850 print "\n"; 1851 } 1852 output_section_rst(@_); 1853} 1854 1855sub output_section_rst(%) { 1856 my %args = %{$_[0]}; 1857 my $section; 1858 my $oldprefix = $lineprefix; 1859 $lineprefix = " "; 1860 1861 foreach $section (@{$args{'sectionlist'}}) { 1862 print ":$section:\n\n"; 1863 output_highlight_rst($args{'sections'}{$section}); 1864 print "\n"; 1865 } 1866 print "\n"; 1867 $lineprefix = $oldprefix; 1868} 1869 1870sub output_enum_rst(%) { 1871 my %args = %{$_[0]}; 1872 my ($parameter); 1873 my $count; 1874 my $name = "enum " . $args{'enum'}; 1875 1876 print "\n\n.. c:type:: " . $name . "\n\n"; 1877 print " " . $args{'purpose'} . "\n\n"; 1878 1879 print "..\n\n:Constants:\n\n"; 1880 my $oldprefix = $lineprefix; 1881 $lineprefix = " "; 1882 foreach $parameter (@{$args{'parameterlist'}}) { 1883 print " `$parameter`\n"; 1884 if ($args{'parameterdescs'}{$parameter} ne $undescribed) { 1885 output_highlight_rst($args{'parameterdescs'}{$parameter}); 1886 } else { 1887 print " undescribed\n"; 1888 } 1889 print "\n"; 1890 } 1891 $lineprefix = $oldprefix; 1892 output_section_rst(@_); 1893} 1894 1895sub output_typedef_rst(%) { 1896 my %args = %{$_[0]}; 1897 my ($parameter); 1898 my $count; 1899 my $name = "typedef " . $args{'typedef'}; 1900 1901 ### FIXME: should the name below contain "typedef" or not? 1902 print "\n\n.. c:type:: " . $name . "\n\n"; 1903 print " " . $args{'purpose'} . "\n\n"; 1904 1905 output_section_rst(@_); 1906} 1907 1908sub output_struct_rst(%) { 1909 my %args = %{$_[0]}; 1910 my ($parameter); 1911 my $name = $args{'type'} . " " . $args{'struct'}; 1912 1913 print "\n\n.. c:type:: " . $name . "\n\n"; 1914 print " " . $args{'purpose'} . "\n\n"; 1915 1916 print ":Definition:\n\n"; 1917 print " ::\n\n"; 1918 print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; 1919 foreach $parameter (@{$args{'parameterlist'}}) { 1920 if ($parameter =~ /^#/) { 1921 print " " . "$parameter\n"; 1922 next; 1923 } 1924 1925 my $parameter_name = $parameter; 1926 $parameter_name =~ s/\[.*//; 1927 1928 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1929 $type = $args{'parametertypes'}{$parameter}; 1930 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1931 # pointer-to-function 1932 print " $1 $parameter) ($2);\n"; 1933 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1934 # bitfield 1935 print " $1 $parameter$2;\n"; 1936 } else { 1937 print " " . $type . " " . $parameter . ";\n"; 1938 } 1939 } 1940 print " };\n\n"; 1941 1942 print ":Members:\n\n"; 1943 foreach $parameter (@{$args{'parameterlist'}}) { 1944 ($parameter =~ /^#/) && next; 1945 1946 my $parameter_name = $parameter; 1947 $parameter_name =~ s/\[.*//; 1948 1949 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1950 $type = $args{'parametertypes'}{$parameter}; 1951 print " `$type $parameter`" . "\n"; 1952 my $oldprefix = $lineprefix; 1953 $lineprefix = " "; 1954 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 1955 $lineprefix = $oldprefix; 1956 print "\n"; 1957 } 1958 print "\n"; 1959 output_section_rst(@_); 1960} 1961 1962 1963## list mode output functions 1964 1965sub output_function_list(%) { 1966 my %args = %{$_[0]}; 1967 1968 print $args{'function'} . "\n"; 1969} 1970 1971# output enum in list 1972sub output_enum_list(%) { 1973 my %args = %{$_[0]}; 1974 print $args{'enum'} . "\n"; 1975} 1976 1977# output typedef in list 1978sub output_typedef_list(%) { 1979 my %args = %{$_[0]}; 1980 print $args{'typedef'} . "\n"; 1981} 1982 1983# output struct as list 1984sub output_struct_list(%) { 1985 my %args = %{$_[0]}; 1986 1987 print $args{'struct'} . "\n"; 1988} 1989 1990sub output_blockhead_list(%) { 1991 my %args = %{$_[0]}; 1992 my ($parameter, $section); 1993 1994 foreach $section (@{$args{'sectionlist'}}) { 1995 print "DOC: $section\n"; 1996 } 1997} 1998 1999## 2000# generic output function for all types (function, struct/union, typedef, enum); 2001# calls the generated, variable output_ function name based on 2002# functype and output_mode 2003sub output_declaration { 2004 no strict 'refs'; 2005 my $name = shift; 2006 my $functype = shift; 2007 my $func = "output_${functype}_$output_mode"; 2008 if (($output_selection == OUTPUT_ALL) || 2009 (($output_selection == OUTPUT_INCLUDE || 2010 $output_selection == OUTPUT_EXPORTED) && 2011 defined($function_table{$name})) || 2012 (($output_selection == OUTPUT_EXCLUDE || 2013 $output_selection == OUTPUT_INTERNAL) && 2014 !($functype eq "function" && defined($function_table{$name})))) 2015 { 2016 &$func(@_); 2017 $section_counter++; 2018 } 2019} 2020 2021## 2022# generic output function - calls the right one based on current output mode. 2023sub output_blockhead { 2024 no strict 'refs'; 2025 my $func = "output_blockhead_" . $output_mode; 2026 &$func(@_); 2027 $section_counter++; 2028} 2029 2030## 2031# takes a declaration (struct, union, enum, typedef) and 2032# invokes the right handler. NOT called for functions. 2033sub dump_declaration($$) { 2034 no strict 'refs'; 2035 my ($prototype, $file) = @_; 2036 my $func = "dump_" . $decl_type; 2037 &$func(@_); 2038} 2039 2040sub dump_union($$) { 2041 dump_struct(@_); 2042} 2043 2044sub dump_struct($$) { 2045 my $x = shift; 2046 my $file = shift; 2047 my $nested; 2048 2049 if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) { 2050 #my $decl_type = $1; 2051 $declaration_name = $2; 2052 my $members = $3; 2053 2054 # ignore embedded structs or unions 2055 $members =~ s/({.*})//g; 2056 $nested = $1; 2057 2058 # ignore members marked private: 2059 $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; 2060 $members =~ s/\/\*\s*private:.*//gosi; 2061 # strip comments: 2062 $members =~ s/\/\*.*?\*\///gos; 2063 $nested =~ s/\/\*.*?\*\///gos; 2064 # strip kmemcheck_bitfield_{begin,end}.*; 2065 $members =~ s/kmemcheck_bitfield_.*?;//gos; 2066 # strip attributes 2067 $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; 2068 $members =~ s/__aligned\s*\([^;]*\)//gos; 2069 $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; 2070 # replace DECLARE_BITMAP 2071 $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; 2072 2073 create_parameterlist($members, ';', $file); 2074 check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); 2075 2076 output_declaration($declaration_name, 2077 'struct', 2078 {'struct' => $declaration_name, 2079 'module' => $modulename, 2080 'parameterlist' => \@parameterlist, 2081 'parameterdescs' => \%parameterdescs, 2082 'parametertypes' => \%parametertypes, 2083 'sectionlist' => \@sectionlist, 2084 'sections' => \%sections, 2085 'purpose' => $declaration_purpose, 2086 'type' => $decl_type 2087 }); 2088 } 2089 else { 2090 print STDERR "${file}:$.: error: Cannot parse struct or union!\n"; 2091 ++$errors; 2092 } 2093} 2094 2095sub dump_enum($$) { 2096 my $x = shift; 2097 my $file = shift; 2098 2099 $x =~ s@/\*.*?\*/@@gos; # strip comments. 2100 # strip #define macros inside enums 2101 $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; 2102 2103 if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { 2104 $declaration_name = $1; 2105 my $members = $2; 2106 2107 foreach my $arg (split ',', $members) { 2108 $arg =~ s/^\s*(\w+).*/$1/; 2109 push @parameterlist, $arg; 2110 if (!$parameterdescs{$arg}) { 2111 $parameterdescs{$arg} = $undescribed; 2112 print STDERR "${file}:$.: warning: Enum value '$arg' ". 2113 "not described in enum '$declaration_name'\n"; 2114 } 2115 2116 } 2117 2118 output_declaration($declaration_name, 2119 'enum', 2120 {'enum' => $declaration_name, 2121 'module' => $modulename, 2122 'parameterlist' => \@parameterlist, 2123 'parameterdescs' => \%parameterdescs, 2124 'sectionlist' => \@sectionlist, 2125 'sections' => \%sections, 2126 'purpose' => $declaration_purpose 2127 }); 2128 } 2129 else { 2130 print STDERR "${file}:$.: error: Cannot parse enum!\n"; 2131 ++$errors; 2132 } 2133} 2134 2135sub dump_typedef($$) { 2136 my $x = shift; 2137 my $file = shift; 2138 2139 $x =~ s@/\*.*?\*/@@gos; # strip comments. 2140 2141 # Parse function prototypes 2142 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/) { 2143 # Function typedefs 2144 $return_type = $1; 2145 $declaration_name = $2; 2146 my $args = $3; 2147 2148 create_parameterlist($args, ',', $file); 2149 2150 output_declaration($declaration_name, 2151 'function', 2152 {'function' => $declaration_name, 2153 'module' => $modulename, 2154 'functiontype' => $return_type, 2155 'parameterlist' => \@parameterlist, 2156 'parameterdescs' => \%parameterdescs, 2157 'parametertypes' => \%parametertypes, 2158 'sectionlist' => \@sectionlist, 2159 'sections' => \%sections, 2160 'purpose' => $declaration_purpose 2161 }); 2162 return; 2163 } 2164 2165 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 2166 $x =~ s/\(*.\)\s*;$/;/; 2167 $x =~ s/\[*.\]\s*;$/;/; 2168 } 2169 2170 if ($x =~ /typedef.*\s+(\w+)\s*;/) { 2171 $declaration_name = $1; 2172 2173 output_declaration($declaration_name, 2174 'typedef', 2175 {'typedef' => $declaration_name, 2176 'module' => $modulename, 2177 'sectionlist' => \@sectionlist, 2178 'sections' => \%sections, 2179 'purpose' => $declaration_purpose 2180 }); 2181 } 2182 else { 2183 print STDERR "${file}:$.: error: Cannot parse typedef!\n"; 2184 ++$errors; 2185 } 2186} 2187 2188sub save_struct_actual($) { 2189 my $actual = shift; 2190 2191 # strip all spaces from the actual param so that it looks like one string item 2192 $actual =~ s/\s*//g; 2193 $struct_actual = $struct_actual . $actual . " "; 2194} 2195 2196sub create_parameterlist($$$) { 2197 my $args = shift; 2198 my $splitter = shift; 2199 my $file = shift; 2200 my $type; 2201 my $param; 2202 2203 # temporarily replace commas inside function pointer definition 2204 while ($args =~ /(\([^\),]+),/) { 2205 $args =~ s/(\([^\),]+),/$1#/g; 2206 } 2207 2208 foreach my $arg (split($splitter, $args)) { 2209 # strip comments 2210 $arg =~ s/\/\*.*\*\///; 2211 # strip leading/trailing spaces 2212 $arg =~ s/^\s*//; 2213 $arg =~ s/\s*$//; 2214 $arg =~ s/\s+/ /; 2215 2216 if ($arg =~ /^#/) { 2217 # Treat preprocessor directive as a typeless variable just to fill 2218 # corresponding data structures "correctly". Catch it later in 2219 # output_* subs. 2220 push_parameter($arg, "", $file); 2221 } elsif ($arg =~ m/\(.+\)\s*\(/) { 2222 # pointer-to-function 2223 $arg =~ tr/#/,/; 2224 $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/; 2225 $param = $1; 2226 $type = $arg; 2227 $type =~ s/([^\(]+\(\*?)\s*$param/$1/; 2228 save_struct_actual($param); 2229 push_parameter($param, $type, $file); 2230 } elsif ($arg) { 2231 $arg =~ s/\s*:\s*/:/g; 2232 $arg =~ s/\s*\[/\[/g; 2233 2234 my @args = split('\s*,\s*', $arg); 2235 if ($args[0] =~ m/\*/) { 2236 $args[0] =~ s/(\*+)\s*/ $1/; 2237 } 2238 2239 my @first_arg; 2240 if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { 2241 shift @args; 2242 push(@first_arg, split('\s+', $1)); 2243 push(@first_arg, $2); 2244 } else { 2245 @first_arg = split('\s+', shift @args); 2246 } 2247 2248 unshift(@args, pop @first_arg); 2249 $type = join " ", @first_arg; 2250 2251 foreach $param (@args) { 2252 if ($param =~ m/^(\*+)\s*(.*)/) { 2253 save_struct_actual($2); 2254 push_parameter($2, "$type $1", $file); 2255 } 2256 elsif ($param =~ m/(.*?):(\d+)/) { 2257 if ($type ne "") { # skip unnamed bit-fields 2258 save_struct_actual($1); 2259 push_parameter($1, "$type:$2", $file) 2260 } 2261 } 2262 else { 2263 save_struct_actual($param); 2264 push_parameter($param, $type, $file); 2265 } 2266 } 2267 } 2268 } 2269} 2270 2271sub push_parameter($$$) { 2272 my $param = shift; 2273 my $type = shift; 2274 my $file = shift; 2275 2276 if (($anon_struct_union == 1) && ($type eq "") && 2277 ($param eq "}")) { 2278 return; # ignore the ending }; from anon. struct/union 2279 } 2280 2281 $anon_struct_union = 0; 2282 my $param_name = $param; 2283 $param_name =~ s/\[.*//; 2284 2285 if ($type eq "" && $param =~ /\.\.\.$/) 2286 { 2287 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { 2288 $parameterdescs{$param} = "variable arguments"; 2289 } 2290 } 2291 elsif ($type eq "" && ($param eq "" or $param eq "void")) 2292 { 2293 $param="void"; 2294 $parameterdescs{void} = "no arguments"; 2295 } 2296 elsif ($type eq "" && ($param eq "struct" or $param eq "union")) 2297 # handle unnamed (anonymous) union or struct: 2298 { 2299 $type = $param; 2300 $param = "{unnamed_" . $param . "}"; 2301 $parameterdescs{$param} = "anonymous\n"; 2302 $anon_struct_union = 1; 2303 } 2304 2305 # warn if parameter has no description 2306 # (but ignore ones starting with # as these are not parameters 2307 # but inline preprocessor statements); 2308 # also ignore unnamed structs/unions; 2309 if (!$anon_struct_union) { 2310 if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) { 2311 2312 $parameterdescs{$param_name} = $undescribed; 2313 2314 if (($type eq 'function') || ($type eq 'enum')) { 2315 print STDERR "${file}:$.: warning: Function parameter ". 2316 "or member '$param' not " . 2317 "described in '$declaration_name'\n"; 2318 } 2319 print STDERR "${file}:$.: warning:" . 2320 " No description found for parameter '$param'\n"; 2321 ++$warnings; 2322 } 2323 } 2324 2325 $param = xml_escape($param); 2326 2327 # strip spaces from $param so that it is one continuous string 2328 # on @parameterlist; 2329 # this fixes a problem where check_sections() cannot find 2330 # a parameter like "addr[6 + 2]" because it actually appears 2331 # as "addr[6", "+", "2]" on the parameter list; 2332 # but it's better to maintain the param string unchanged for output, 2333 # so just weaken the string compare in check_sections() to ignore 2334 # "[blah" in a parameter string; 2335 ###$param =~ s/\s*//g; 2336 push @parameterlist, $param; 2337 $parametertypes{$param} = $type; 2338} 2339 2340sub check_sections($$$$$$) { 2341 my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_; 2342 my @sects = split ' ', $sectcheck; 2343 my @prms = split ' ', $prmscheck; 2344 my $err; 2345 my ($px, $sx); 2346 my $prm_clean; # strip trailing "[array size]" and/or beginning "*" 2347 2348 foreach $sx (0 .. $#sects) { 2349 $err = 1; 2350 foreach $px (0 .. $#prms) { 2351 $prm_clean = $prms[$px]; 2352 $prm_clean =~ s/\[.*\]//; 2353 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; 2354 # ignore array size in a parameter string; 2355 # however, the original param string may contain 2356 # spaces, e.g.: addr[6 + 2] 2357 # and this appears in @prms as "addr[6" since the 2358 # parameter list is split at spaces; 2359 # hence just ignore "[..." for the sections check; 2360 $prm_clean =~ s/\[.*//; 2361 2362 ##$prm_clean =~ s/^\**//; 2363 if ($prm_clean eq $sects[$sx]) { 2364 $err = 0; 2365 last; 2366 } 2367 } 2368 if ($err) { 2369 if ($decl_type eq "function") { 2370 print STDERR "${file}:$.: warning: " . 2371 "Excess function parameter " . 2372 "'$sects[$sx]' " . 2373 "description in '$decl_name'\n"; 2374 ++$warnings; 2375 } else { 2376 if ($nested !~ m/\Q$sects[$sx]\E/) { 2377 print STDERR "${file}:$.: warning: " . 2378 "Excess struct/union/enum/typedef member " . 2379 "'$sects[$sx]' " . 2380 "description in '$decl_name'\n"; 2381 ++$warnings; 2382 } 2383 } 2384 } 2385 } 2386} 2387 2388## 2389# Checks the section describing the return value of a function. 2390sub check_return_section { 2391 my $file = shift; 2392 my $declaration_name = shift; 2393 my $return_type = shift; 2394 2395 # Ignore an empty return type (It's a macro) 2396 # Ignore functions with a "void" return type. (But don't ignore "void *") 2397 if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) { 2398 return; 2399 } 2400 2401 if (!defined($sections{$section_return}) || 2402 $sections{$section_return} eq "") { 2403 print STDERR "${file}:$.: warning: " . 2404 "No description found for return value of " . 2405 "'$declaration_name'\n"; 2406 ++$warnings; 2407 } 2408} 2409 2410## 2411# takes a function prototype and the name of the current file being 2412# processed and spits out all the details stored in the global 2413# arrays/hashes. 2414sub dump_function($$) { 2415 my $prototype = shift; 2416 my $file = shift; 2417 my $noret = 0; 2418 2419 $prototype =~ s/^static +//; 2420 $prototype =~ s/^extern +//; 2421 $prototype =~ s/^asmlinkage +//; 2422 $prototype =~ s/^inline +//; 2423 $prototype =~ s/^__inline__ +//; 2424 $prototype =~ s/^__inline +//; 2425 $prototype =~ s/^__always_inline +//; 2426 $prototype =~ s/^noinline +//; 2427 $prototype =~ s/__init +//; 2428 $prototype =~ s/__init_or_module +//; 2429 $prototype =~ s/__meminit +//; 2430 $prototype =~ s/__must_check +//; 2431 $prototype =~ s/__weak +//; 2432 my $define = $prototype =~ s/^#\s*define\s+//; #ak added 2433 $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; 2434 2435 # Yes, this truly is vile. We are looking for: 2436 # 1. Return type (may be nothing if we're looking at a macro) 2437 # 2. Function name 2438 # 3. Function parameters. 2439 # 2440 # All the while we have to watch out for function pointer parameters 2441 # (which IIRC is what the two sections are for), C types (these 2442 # regexps don't even start to express all the possibilities), and 2443 # so on. 2444 # 2445 # If you mess with these regexps, it's a good idea to check that 2446 # the following functions' documentation still comes out right: 2447 # - parport_register_device (function pointer parameters) 2448 # - atomic_set (macro) 2449 # - pci_match_device, __copy_to_user (long return type) 2450 2451 if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) { 2452 # This is an object-like macro, it has no return type and no parameter 2453 # list. 2454 # Function-like macros are not allowed to have spaces between 2455 # declaration_name and opening parenthesis (notice the \s+). 2456 $return_type = $1; 2457 $declaration_name = $2; 2458 $noret = 1; 2459 } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2460 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2461 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2462 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2463 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2464 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2465 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2466 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2467 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2468 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2469 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2470 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2471 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2472 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2473 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2474 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2475 $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { 2476 $return_type = $1; 2477 $declaration_name = $2; 2478 my $args = $3; 2479 2480 create_parameterlist($args, ',', $file); 2481 } else { 2482 print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n"; 2483 return; 2484 } 2485 2486 my $prms = join " ", @parameterlist; 2487 check_sections($file, $declaration_name, "function", $sectcheck, $prms, ""); 2488 2489 # This check emits a lot of warnings at the moment, because many 2490 # functions don't have a 'Return' doc section. So until the number 2491 # of warnings goes sufficiently down, the check is only performed in 2492 # verbose mode. 2493 # TODO: always perform the check. 2494 if ($verbose && !$noret) { 2495 check_return_section($file, $declaration_name, $return_type); 2496 } 2497 2498 output_declaration($declaration_name, 2499 'function', 2500 {'function' => $declaration_name, 2501 'module' => $modulename, 2502 'functiontype' => $return_type, 2503 'parameterlist' => \@parameterlist, 2504 'parameterdescs' => \%parameterdescs, 2505 'parametertypes' => \%parametertypes, 2506 'sectionlist' => \@sectionlist, 2507 'sections' => \%sections, 2508 'purpose' => $declaration_purpose 2509 }); 2510} 2511 2512sub reset_state { 2513 $function = ""; 2514 %constants = (); 2515 %parameterdescs = (); 2516 %parametertypes = (); 2517 @parameterlist = (); 2518 %sections = (); 2519 @sectionlist = (); 2520 $sectcheck = ""; 2521 $struct_actual = ""; 2522 $prototype = ""; 2523 2524 $state = STATE_NORMAL; 2525 $inline_doc_state = STATE_INLINE_NA; 2526} 2527 2528sub tracepoint_munge($) { 2529 my $file = shift; 2530 my $tracepointname = 0; 2531 my $tracepointargs = 0; 2532 2533 if ($prototype =~ m/TRACE_EVENT\((.*?),/) { 2534 $tracepointname = $1; 2535 } 2536 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) { 2537 $tracepointname = $1; 2538 } 2539 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) { 2540 $tracepointname = $2; 2541 } 2542 $tracepointname =~ s/^\s+//; #strip leading whitespace 2543 if ($prototype =~ m/TP_PROTO\((.*?)\)/) { 2544 $tracepointargs = $1; 2545 } 2546 if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 2547 print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". 2548 "$prototype\n"; 2549 } else { 2550 $prototype = "static inline void trace_$tracepointname($tracepointargs)"; 2551 } 2552} 2553 2554sub syscall_munge() { 2555 my $void = 0; 2556 2557 $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs 2558## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) { 2559 if ($prototype =~ m/SYSCALL_DEFINE0/) { 2560 $void = 1; 2561## $prototype = "long sys_$1(void)"; 2562 } 2563 2564 $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name 2565 if ($prototype =~ m/long (sys_.*?),/) { 2566 $prototype =~ s/,/\(/; 2567 } elsif ($void) { 2568 $prototype =~ s/\)/\(void\)/; 2569 } 2570 2571 # now delete all of the odd-number commas in $prototype 2572 # so that arg types & arg names don't have a comma between them 2573 my $count = 0; 2574 my $len = length($prototype); 2575 if ($void) { 2576 $len = 0; # skip the for-loop 2577 } 2578 for (my $ix = 0; $ix < $len; $ix++) { 2579 if (substr($prototype, $ix, 1) eq ',') { 2580 $count++; 2581 if ($count % 2 == 1) { 2582 substr($prototype, $ix, 1) = ' '; 2583 } 2584 } 2585 } 2586} 2587 2588sub process_state3_function($$) { 2589 my $x = shift; 2590 my $file = shift; 2591 2592 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 2593 2594 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { 2595 # do nothing 2596 } 2597 elsif ($x =~ /([^\{]*)/) { 2598 $prototype .= $1; 2599 } 2600 2601 if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) { 2602 $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 2603 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 2604 $prototype =~ s@^\s+@@gos; # strip leading spaces 2605 if ($prototype =~ /SYSCALL_DEFINE/) { 2606 syscall_munge(); 2607 } 2608 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ || 2609 $prototype =~ /DEFINE_SINGLE_EVENT/) 2610 { 2611 tracepoint_munge($file); 2612 } 2613 dump_function($prototype, $file); 2614 reset_state(); 2615 } 2616} 2617 2618sub process_state3_type($$) { 2619 my $x = shift; 2620 my $file = shift; 2621 2622 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 2623 $x =~ s@^\s+@@gos; # strip leading spaces 2624 $x =~ s@\s+$@@gos; # strip trailing spaces 2625 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 2626 2627 if ($x =~ /^#/) { 2628 # To distinguish preprocessor directive from regular declaration later. 2629 $x .= ";"; 2630 } 2631 2632 while (1) { 2633 if ( $x =~ /([^{};]*)([{};])(.*)/ ) { 2634 $prototype .= $1 . $2; 2635 ($2 eq '{') && $brcount++; 2636 ($2 eq '}') && $brcount--; 2637 if (($2 eq ';') && ($brcount == 0)) { 2638 dump_declaration($prototype, $file); 2639 reset_state(); 2640 last; 2641 } 2642 $x = $3; 2643 } else { 2644 $prototype .= $x; 2645 last; 2646 } 2647 } 2648} 2649 2650# xml_escape: replace <, >, and & in the text stream; 2651# 2652# however, formatting controls that are generated internally/locally in the 2653# kernel-doc script are not escaped here; instead, they begin life like 2654# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings 2655# are converted to their mnemonic-expected output, without the 4 * '\' & ':', 2656# just before actual output; (this is done by local_unescape()) 2657sub xml_escape($) { 2658 my $text = shift; 2659 if (($output_mode eq "text") || ($output_mode eq "man")) { 2660 return $text; 2661 } 2662 $text =~ s/\&/\\\\\\amp;/g; 2663 $text =~ s/\</\\\\\\lt;/g; 2664 $text =~ s/\>/\\\\\\gt;/g; 2665 return $text; 2666} 2667 2668# xml_unescape: reverse the effects of xml_escape 2669sub xml_unescape($) { 2670 my $text = shift; 2671 if (($output_mode eq "text") || ($output_mode eq "man")) { 2672 return $text; 2673 } 2674 $text =~ s/\\\\\\amp;/\&/g; 2675 $text =~ s/\\\\\\lt;/</g; 2676 $text =~ s/\\\\\\gt;/>/g; 2677 return $text; 2678} 2679 2680# convert local escape strings to html 2681# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes) 2682sub local_unescape($) { 2683 my $text = shift; 2684 if (($output_mode eq "text") || ($output_mode eq "man")) { 2685 return $text; 2686 } 2687 $text =~ s/\\\\\\\\lt:/</g; 2688 $text =~ s/\\\\\\\\gt:/>/g; 2689 return $text; 2690} 2691 2692sub process_file($) { 2693 my $file; 2694 my $identifier; 2695 my $func; 2696 my $descr; 2697 my $in_purpose = 0; 2698 my $initial_section_counter = $section_counter; 2699 my ($orig_file) = @_; 2700 2701 if (defined($ENV{'SRCTREE'})) { 2702 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; 2703 } 2704 else { 2705 $file = $orig_file; 2706 } 2707 if (defined($source_map{$file})) { 2708 $file = $source_map{$file}; 2709 } 2710 2711 if (!open(IN,"<$file")) { 2712 print STDERR "Error: Cannot open file $file\n"; 2713 ++$errors; 2714 return; 2715 } 2716 2717 # two passes for -export and -internal 2718 if ($output_selection == OUTPUT_EXPORTED || 2719 $output_selection == OUTPUT_INTERNAL) { 2720 while (<IN>) { 2721 if (/$export_symbol/o) { 2722 $function_table{$2} = 1; 2723 } 2724 } 2725 seek(IN, 0, 0); 2726 } 2727 2728 $. = 1; 2729 2730 $section_counter = 0; 2731 while (<IN>) { 2732 while (s/\\\s*$//) { 2733 $_ .= <IN>; 2734 } 2735 if ($state == STATE_NORMAL) { 2736 if (/$doc_start/o) { 2737 $state = STATE_NAME; # next line is always the function name 2738 $in_doc_sect = 0; 2739 } 2740 } elsif ($state == STATE_NAME) {# this line is the function name (always) 2741 if (/$doc_block/o) { 2742 $state = STATE_DOCBLOCK; 2743 $contents = ""; 2744 if ( $1 eq "" ) { 2745 $section = $section_intro; 2746 } else { 2747 $section = $1; 2748 } 2749 } 2750 elsif (/$doc_decl/o) { 2751 $identifier = $1; 2752 if (/\s*([\w\s]+?)\s*-/) { 2753 $identifier = $1; 2754 } 2755 2756 $state = STATE_FIELD; 2757 if (/-(.*)/) { 2758 # strip leading/trailing/multiple spaces 2759 $descr= $1; 2760 $descr =~ s/^\s*//; 2761 $descr =~ s/\s*$//; 2762 $descr =~ s/\s+/ /g; 2763 $declaration_purpose = xml_escape($descr); 2764 $in_purpose = 1; 2765 } else { 2766 $declaration_purpose = ""; 2767 } 2768 2769 if (($declaration_purpose eq "") && $verbose) { 2770 print STDERR "${file}:$.: warning: missing initial short description on line:\n"; 2771 print STDERR $_; 2772 ++$warnings; 2773 } 2774 2775 if ($identifier =~ m/^struct/) { 2776 $decl_type = 'struct'; 2777 } elsif ($identifier =~ m/^union/) { 2778 $decl_type = 'union'; 2779 } elsif ($identifier =~ m/^enum/) { 2780 $decl_type = 'enum'; 2781 } elsif ($identifier =~ m/^typedef/) { 2782 $decl_type = 'typedef'; 2783 } else { 2784 $decl_type = 'function'; 2785 } 2786 2787 if ($verbose) { 2788 print STDERR "${file}:$.: info: Scanning doc for $identifier\n"; 2789 } 2790 } else { 2791 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", 2792 " - I thought it was a doc line\n"; 2793 ++$warnings; 2794 $state = STATE_NORMAL; 2795 } 2796 } elsif ($state == STATE_FIELD) { # look for head: lines, and include content 2797 if (/$doc_sect/o) { 2798 $newsection = $1; 2799 $newcontents = $2; 2800 2801 if (($contents ne "") && ($contents ne "\n")) { 2802 if (!$in_doc_sect && $verbose) { 2803 print STDERR "${file}:$.: warning: contents before sections\n"; 2804 ++$warnings; 2805 } 2806 dump_section($file, $section, xml_escape($contents)); 2807 $section = $section_default; 2808 } 2809 2810 $in_doc_sect = 1; 2811 $in_purpose = 0; 2812 $contents = $newcontents; 2813 if ($contents ne "") { 2814 while ((substr($contents, 0, 1) eq " ") || 2815 substr($contents, 0, 1) eq "\t") { 2816 $contents = substr($contents, 1); 2817 } 2818 $contents .= "\n"; 2819 } 2820 $section = $newsection; 2821 } elsif (/$doc_end/) { 2822 if (($contents ne "") && ($contents ne "\n")) { 2823 dump_section($file, $section, xml_escape($contents)); 2824 $section = $section_default; 2825 $contents = ""; 2826 } 2827 # look for doc_com + <text> + doc_end: 2828 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { 2829 print STDERR "${file}:$.: warning: suspicious ending line: $_"; 2830 ++$warnings; 2831 } 2832 2833 $prototype = ""; 2834 $state = STATE_PROTO; 2835 $brcount = 0; 2836# print STDERR "end of doc comment, looking for prototype\n"; 2837 } elsif (/$doc_content/) { 2838 # miguel-style comment kludge, look for blank lines after 2839 # @parameter line to signify start of description 2840 if ($1 eq "") { 2841 if ($section =~ m/^@/ || $section eq $section_context) { 2842 dump_section($file, $section, xml_escape($contents)); 2843 $section = $section_default; 2844 $contents = ""; 2845 } else { 2846 $contents .= "\n"; 2847 } 2848 $in_purpose = 0; 2849 } elsif ($in_purpose == 1) { 2850 # Continued declaration purpose 2851 chomp($declaration_purpose); 2852 $declaration_purpose .= " " . xml_escape($1); 2853 $declaration_purpose =~ s/\s+/ /g; 2854 } else { 2855 $contents .= $1 . "\n"; 2856 } 2857 } else { 2858 # i dont know - bad line? ignore. 2859 print STDERR "${file}:$.: warning: bad line: $_"; 2860 ++$warnings; 2861 } 2862 } elsif ($state == STATE_INLINE) { # scanning for inline parameters 2863 # First line (state 1) needs to be a @parameter 2864 if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { 2865 $section = $1; 2866 $contents = $2; 2867 if ($contents ne "") { 2868 while ((substr($contents, 0, 1) eq " ") || 2869 substr($contents, 0, 1) eq "\t") { 2870 $contents = substr($contents, 1); 2871 } 2872 $contents .= "\n"; 2873 } 2874 $inline_doc_state = STATE_INLINE_TEXT; 2875 # Documentation block end */ 2876 } elsif (/$doc_inline_end/) { 2877 if (($contents ne "") && ($contents ne "\n")) { 2878 dump_section($file, $section, xml_escape($contents)); 2879 $section = $section_default; 2880 $contents = ""; 2881 } 2882 $state = STATE_PROTO; 2883 $inline_doc_state = STATE_INLINE_NA; 2884 # Regular text 2885 } elsif (/$doc_content/) { 2886 if ($inline_doc_state == STATE_INLINE_TEXT) { 2887 $contents .= $1 . "\n"; 2888 } elsif ($inline_doc_state == STATE_INLINE_NAME) { 2889 $inline_doc_state = STATE_INLINE_ERROR; 2890 print STDERR "Warning(${file}:$.): "; 2891 print STDERR "Incorrect use of kernel-doc format: $_"; 2892 ++$warnings; 2893 } 2894 } 2895 } elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype) 2896 if (/$doc_inline_start/) { 2897 $state = STATE_INLINE; 2898 $inline_doc_state = STATE_INLINE_NAME; 2899 } elsif ($decl_type eq 'function') { 2900 process_state3_function($_, $file); 2901 } else { 2902 process_state3_type($_, $file); 2903 } 2904 } elsif ($state == STATE_DOCBLOCK) { 2905 # Documentation block 2906 if (/$doc_block/) { 2907 dump_doc_section($file, $section, xml_escape($contents)); 2908 $contents = ""; 2909 $function = ""; 2910 %constants = (); 2911 %parameterdescs = (); 2912 %parametertypes = (); 2913 @parameterlist = (); 2914 %sections = (); 2915 @sectionlist = (); 2916 $prototype = ""; 2917 if ( $1 eq "" ) { 2918 $section = $section_intro; 2919 } else { 2920 $section = $1; 2921 } 2922 } 2923 elsif (/$doc_end/) 2924 { 2925 dump_doc_section($file, $section, xml_escape($contents)); 2926 $contents = ""; 2927 $function = ""; 2928 %constants = (); 2929 %parameterdescs = (); 2930 %parametertypes = (); 2931 @parameterlist = (); 2932 %sections = (); 2933 @sectionlist = (); 2934 $prototype = ""; 2935 $state = STATE_NORMAL; 2936 } 2937 elsif (/$doc_content/) 2938 { 2939 if ( $1 eq "" ) 2940 { 2941 $contents .= $blankline; 2942 } 2943 else 2944 { 2945 $contents .= $1 . "\n"; 2946 } 2947 } 2948 } 2949 } 2950 if ($initial_section_counter == $section_counter) { 2951 print STDERR "${file}:1: warning: no structured comments found\n"; 2952 if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) { 2953 print STDERR " Was looking for '$_'.\n" for keys %function_table; 2954 } 2955 if ($output_mode eq "xml") { 2956 # The template wants at least one RefEntry here; make one. 2957 print "<refentry>\n"; 2958 print " <refnamediv>\n"; 2959 print " <refname>\n"; 2960 print " ${orig_file}\n"; 2961 print " </refname>\n"; 2962 print " <refpurpose>\n"; 2963 print " Document generation inconsistency\n"; 2964 print " </refpurpose>\n"; 2965 print " </refnamediv>\n"; 2966 print " <refsect1>\n"; 2967 print " <title>\n"; 2968 print " Oops\n"; 2969 print " </title>\n"; 2970 print " <warning>\n"; 2971 print " <para>\n"; 2972 print " The template for this document tried to insert\n"; 2973 print " the structured comment from the file\n"; 2974 print " <filename>${orig_file}</filename> at this point,\n"; 2975 print " but none was found.\n"; 2976 print " This dummy section is inserted to allow\n"; 2977 print " generation to continue.\n"; 2978 print " </para>\n"; 2979 print " </warning>\n"; 2980 print " </refsect1>\n"; 2981 print "</refentry>\n"; 2982 } 2983 } 2984} 2985 2986 2987$kernelversion = get_kernel_version(); 2988 2989# generate a sequence of code that will splice in highlighting information 2990# using the s// operator. 2991for (my $k = 0; $k < @highlights; $k++) { 2992 my $pattern = $highlights[$k][0]; 2993 my $result = $highlights[$k][1]; 2994# print STDERR "scanning pattern:$pattern, highlight:($result)\n"; 2995 $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n"; 2996} 2997 2998# Read the file that maps relative names to absolute names for 2999# separate source and object directories and for shadow trees. 3000if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 3001 my ($relname, $absname); 3002 while(<SOURCE_MAP>) { 3003 chop(); 3004 ($relname, $absname) = (split())[0..1]; 3005 $relname =~ s:^/+::; 3006 $source_map{$relname} = $absname; 3007 } 3008 close(SOURCE_MAP); 3009} 3010 3011foreach (@ARGV) { 3012 chomp; 3013 process_file($_); 3014} 3015if ($verbose && $errors) { 3016 print STDERR "$errors errors\n"; 3017} 3018if ($verbose && $warnings) { 3019 print STDERR "$warnings warnings\n"; 3020} 3021 3022exit($errors); 3023