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