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