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 2230 foreach my $arg (split ',', $members) { 2231 $arg =~ s/^\s*(\w+).*/$1/; 2232 push @parameterlist, $arg; 2233 if (!$parameterdescs{$arg}) { 2234 $parameterdescs{$arg} = $undescribed; 2235 print STDERR "${file}:$.: warning: Enum value '$arg' ". 2236 "not described in enum '$declaration_name'\n"; 2237 } 2238 2239 } 2240 2241 output_declaration($declaration_name, 2242 'enum', 2243 {'enum' => $declaration_name, 2244 'module' => $modulename, 2245 'parameterlist' => \@parameterlist, 2246 'parameterdescs' => \%parameterdescs, 2247 'sectionlist' => \@sectionlist, 2248 'sections' => \%sections, 2249 'purpose' => $declaration_purpose 2250 }); 2251 } 2252 else { 2253 print STDERR "${file}:$.: error: Cannot parse enum!\n"; 2254 ++$errors; 2255 } 2256} 2257 2258sub dump_typedef($$) { 2259 my $x = shift; 2260 my $file = shift; 2261 2262 $x =~ s@/\*.*?\*/@@gos; # strip comments. 2263 2264 # Parse function prototypes 2265 if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || 2266 $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { 2267 2268 # Function typedefs 2269 $return_type = $1; 2270 $declaration_name = $2; 2271 my $args = $3; 2272 2273 create_parameterlist($args, ',', $file); 2274 2275 output_declaration($declaration_name, 2276 'function', 2277 {'function' => $declaration_name, 2278 'typedef' => 1, 2279 'module' => $modulename, 2280 'functiontype' => $return_type, 2281 'parameterlist' => \@parameterlist, 2282 'parameterdescs' => \%parameterdescs, 2283 'parametertypes' => \%parametertypes, 2284 'sectionlist' => \@sectionlist, 2285 'sections' => \%sections, 2286 'purpose' => $declaration_purpose 2287 }); 2288 return; 2289 } 2290 2291 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 2292 $x =~ s/\(*.\)\s*;$/;/; 2293 $x =~ s/\[*.\]\s*;$/;/; 2294 } 2295 2296 if ($x =~ /typedef.*\s+(\w+)\s*;/) { 2297 $declaration_name = $1; 2298 2299 output_declaration($declaration_name, 2300 'typedef', 2301 {'typedef' => $declaration_name, 2302 'module' => $modulename, 2303 'sectionlist' => \@sectionlist, 2304 'sections' => \%sections, 2305 'purpose' => $declaration_purpose 2306 }); 2307 } 2308 else { 2309 print STDERR "${file}:$.: error: Cannot parse typedef!\n"; 2310 ++$errors; 2311 } 2312} 2313 2314sub save_struct_actual($) { 2315 my $actual = shift; 2316 2317 # strip all spaces from the actual param so that it looks like one string item 2318 $actual =~ s/\s*//g; 2319 $struct_actual = $struct_actual . $actual . " "; 2320} 2321 2322sub create_parameterlist($$$) { 2323 my $args = shift; 2324 my $splitter = shift; 2325 my $file = shift; 2326 my $type; 2327 my $param; 2328 2329 # temporarily replace commas inside function pointer definition 2330 while ($args =~ /(\([^\),]+),/) { 2331 $args =~ s/(\([^\),]+),/$1#/g; 2332 } 2333 2334 foreach my $arg (split($splitter, $args)) { 2335 # strip comments 2336 $arg =~ s/\/\*.*\*\///; 2337 # strip leading/trailing spaces 2338 $arg =~ s/^\s*//; 2339 $arg =~ s/\s*$//; 2340 $arg =~ s/\s+/ /; 2341 2342 if ($arg =~ /^#/) { 2343 # Treat preprocessor directive as a typeless variable just to fill 2344 # corresponding data structures "correctly". Catch it later in 2345 # output_* subs. 2346 push_parameter($arg, "", $file); 2347 } elsif ($arg =~ m/\(.+\)\s*\(/) { 2348 # pointer-to-function 2349 $arg =~ tr/#/,/; 2350 $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/; 2351 $param = $1; 2352 $type = $arg; 2353 $type =~ s/([^\(]+\(\*?)\s*$param/$1/; 2354 save_struct_actual($param); 2355 push_parameter($param, $type, $file); 2356 } elsif ($arg) { 2357 $arg =~ s/\s*:\s*/:/g; 2358 $arg =~ s/\s*\[/\[/g; 2359 2360 my @args = split('\s*,\s*', $arg); 2361 if ($args[0] =~ m/\*/) { 2362 $args[0] =~ s/(\*+)\s*/ $1/; 2363 } 2364 2365 my @first_arg; 2366 if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { 2367 shift @args; 2368 push(@first_arg, split('\s+', $1)); 2369 push(@first_arg, $2); 2370 } else { 2371 @first_arg = split('\s+', shift @args); 2372 } 2373 2374 unshift(@args, pop @first_arg); 2375 $type = join " ", @first_arg; 2376 2377 foreach $param (@args) { 2378 if ($param =~ m/^(\*+)\s*(.*)/) { 2379 save_struct_actual($2); 2380 push_parameter($2, "$type $1", $file); 2381 } 2382 elsif ($param =~ m/(.*?):(\d+)/) { 2383 if ($type ne "") { # skip unnamed bit-fields 2384 save_struct_actual($1); 2385 push_parameter($1, "$type:$2", $file) 2386 } 2387 } 2388 else { 2389 save_struct_actual($param); 2390 push_parameter($param, $type, $file); 2391 } 2392 } 2393 } 2394 } 2395} 2396 2397sub push_parameter($$$) { 2398 my $param = shift; 2399 my $type = shift; 2400 my $file = shift; 2401 2402 if (($anon_struct_union == 1) && ($type eq "") && 2403 ($param eq "}")) { 2404 return; # ignore the ending }; from anon. struct/union 2405 } 2406 2407 $anon_struct_union = 0; 2408 $param =~ s/[\[\)].*//; 2409 2410 if ($type eq "" && $param =~ /\.\.\.$/) 2411 { 2412 if (!$param =~ /\w\.\.\.$/) { 2413 # handles unnamed variable parameters 2414 $param = "..."; 2415 } 2416 if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { 2417 $parameterdescs{$param} = "variable arguments"; 2418 } 2419 } 2420 elsif ($type eq "" && ($param eq "" or $param eq "void")) 2421 { 2422 $param="void"; 2423 $parameterdescs{void} = "no arguments"; 2424 } 2425 elsif ($type eq "" && ($param eq "struct" or $param eq "union")) 2426 # handle unnamed (anonymous) union or struct: 2427 { 2428 $type = $param; 2429 $param = "{unnamed_" . $param . "}"; 2430 $parameterdescs{$param} = "anonymous\n"; 2431 $anon_struct_union = 1; 2432 } 2433 2434 # warn if parameter has no description 2435 # (but ignore ones starting with # as these are not parameters 2436 # but inline preprocessor statements); 2437 # also ignore unnamed structs/unions; 2438 if (!$anon_struct_union) { 2439 if (!defined $parameterdescs{$param} && $param !~ /^#/) { 2440 2441 $parameterdescs{$param} = $undescribed; 2442 2443 if (($type eq 'function') || ($type eq 'enum')) { 2444 print STDERR "${file}:$.: warning: Function parameter ". 2445 "or member '$param' not " . 2446 "described in '$declaration_name'\n"; 2447 } 2448 print STDERR "${file}:$.: warning:" . 2449 " No description found for parameter '$param'\n"; 2450 ++$warnings; 2451 } 2452 } 2453 2454 $param = xml_escape($param); 2455 2456 # strip spaces from $param so that it is one continuous string 2457 # on @parameterlist; 2458 # this fixes a problem where check_sections() cannot find 2459 # a parameter like "addr[6 + 2]" because it actually appears 2460 # as "addr[6", "+", "2]" on the parameter list; 2461 # but it's better to maintain the param string unchanged for output, 2462 # so just weaken the string compare in check_sections() to ignore 2463 # "[blah" in a parameter string; 2464 ###$param =~ s/\s*//g; 2465 push @parameterlist, $param; 2466 $type =~ s/\s\s+/ /g; 2467 $parametertypes{$param} = $type; 2468} 2469 2470sub check_sections($$$$$$) { 2471 my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_; 2472 my @sects = split ' ', $sectcheck; 2473 my @prms = split ' ', $prmscheck; 2474 my $err; 2475 my ($px, $sx); 2476 my $prm_clean; # strip trailing "[array size]" and/or beginning "*" 2477 2478 foreach $sx (0 .. $#sects) { 2479 $err = 1; 2480 foreach $px (0 .. $#prms) { 2481 $prm_clean = $prms[$px]; 2482 $prm_clean =~ s/\[.*\]//; 2483 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; 2484 # ignore array size in a parameter string; 2485 # however, the original param string may contain 2486 # spaces, e.g.: addr[6 + 2] 2487 # and this appears in @prms as "addr[6" since the 2488 # parameter list is split at spaces; 2489 # hence just ignore "[..." for the sections check; 2490 $prm_clean =~ s/\[.*//; 2491 2492 ##$prm_clean =~ s/^\**//; 2493 if ($prm_clean eq $sects[$sx]) { 2494 $err = 0; 2495 last; 2496 } 2497 } 2498 if ($err) { 2499 if ($decl_type eq "function") { 2500 print STDERR "${file}:$.: warning: " . 2501 "Excess function parameter " . 2502 "'$sects[$sx]' " . 2503 "description in '$decl_name'\n"; 2504 ++$warnings; 2505 } else { 2506 if ($nested !~ m/\Q$sects[$sx]\E/) { 2507 print STDERR "${file}:$.: warning: " . 2508 "Excess struct/union/enum/typedef member " . 2509 "'$sects[$sx]' " . 2510 "description in '$decl_name'\n"; 2511 ++$warnings; 2512 } 2513 } 2514 } 2515 } 2516} 2517 2518## 2519# Checks the section describing the return value of a function. 2520sub check_return_section { 2521 my $file = shift; 2522 my $declaration_name = shift; 2523 my $return_type = shift; 2524 2525 # Ignore an empty return type (It's a macro) 2526 # Ignore functions with a "void" return type. (But don't ignore "void *") 2527 if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) { 2528 return; 2529 } 2530 2531 if (!defined($sections{$section_return}) || 2532 $sections{$section_return} eq "") { 2533 print STDERR "${file}:$.: warning: " . 2534 "No description found for return value of " . 2535 "'$declaration_name'\n"; 2536 ++$warnings; 2537 } 2538} 2539 2540## 2541# takes a function prototype and the name of the current file being 2542# processed and spits out all the details stored in the global 2543# arrays/hashes. 2544sub dump_function($$) { 2545 my $prototype = shift; 2546 my $file = shift; 2547 my $noret = 0; 2548 2549 $prototype =~ s/^static +//; 2550 $prototype =~ s/^extern +//; 2551 $prototype =~ s/^asmlinkage +//; 2552 $prototype =~ s/^inline +//; 2553 $prototype =~ s/^__inline__ +//; 2554 $prototype =~ s/^__inline +//; 2555 $prototype =~ s/^__always_inline +//; 2556 $prototype =~ s/^noinline +//; 2557 $prototype =~ s/__init +//; 2558 $prototype =~ s/__init_or_module +//; 2559 $prototype =~ s/__meminit +//; 2560 $prototype =~ s/__must_check +//; 2561 $prototype =~ s/__weak +//; 2562 my $define = $prototype =~ s/^#\s*define\s+//; #ak added 2563 $prototype =~ s/__attribute__\s*\(\( 2564 (?: 2565 [\w\s]++ # attribute name 2566 (?:\([^)]*+\))? # attribute arguments 2567 \s*+,? # optional comma at the end 2568 )+ 2569 \)\)\s+//x; 2570 2571 # Yes, this truly is vile. We are looking for: 2572 # 1. Return type (may be nothing if we're looking at a macro) 2573 # 2. Function name 2574 # 3. Function parameters. 2575 # 2576 # All the while we have to watch out for function pointer parameters 2577 # (which IIRC is what the two sections are for), C types (these 2578 # regexps don't even start to express all the possibilities), and 2579 # so on. 2580 # 2581 # If you mess with these regexps, it's a good idea to check that 2582 # the following functions' documentation still comes out right: 2583 # - parport_register_device (function pointer parameters) 2584 # - atomic_set (macro) 2585 # - pci_match_device, __copy_to_user (long return type) 2586 2587 if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) { 2588 # This is an object-like macro, it has no return type and no parameter 2589 # list. 2590 # Function-like macros are not allowed to have spaces between 2591 # declaration_name and opening parenthesis (notice the \s+). 2592 $return_type = $1; 2593 $declaration_name = $2; 2594 $noret = 1; 2595 } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2596 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2597 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2598 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2599 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2600 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2601 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 2602 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2603 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2604 $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2605 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2606 $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2607 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2608 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2609 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2610 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 2611 $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { 2612 $return_type = $1; 2613 $declaration_name = $2; 2614 my $args = $3; 2615 2616 create_parameterlist($args, ',', $file); 2617 } else { 2618 print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n"; 2619 return; 2620 } 2621 2622 my $prms = join " ", @parameterlist; 2623 check_sections($file, $declaration_name, "function", $sectcheck, $prms, ""); 2624 2625 # This check emits a lot of warnings at the moment, because many 2626 # functions don't have a 'Return' doc section. So until the number 2627 # of warnings goes sufficiently down, the check is only performed in 2628 # verbose mode. 2629 # TODO: always perform the check. 2630 if ($verbose && !$noret) { 2631 check_return_section($file, $declaration_name, $return_type); 2632 } 2633 2634 output_declaration($declaration_name, 2635 'function', 2636 {'function' => $declaration_name, 2637 'module' => $modulename, 2638 'functiontype' => $return_type, 2639 'parameterlist' => \@parameterlist, 2640 'parameterdescs' => \%parameterdescs, 2641 'parametertypes' => \%parametertypes, 2642 'sectionlist' => \@sectionlist, 2643 'sections' => \%sections, 2644 'purpose' => $declaration_purpose 2645 }); 2646} 2647 2648sub reset_state { 2649 $function = ""; 2650 %parameterdescs = (); 2651 %parametertypes = (); 2652 @parameterlist = (); 2653 %sections = (); 2654 @sectionlist = (); 2655 $sectcheck = ""; 2656 $struct_actual = ""; 2657 $prototype = ""; 2658 2659 $state = STATE_NORMAL; 2660 $inline_doc_state = STATE_INLINE_NA; 2661} 2662 2663sub tracepoint_munge($) { 2664 my $file = shift; 2665 my $tracepointname = 0; 2666 my $tracepointargs = 0; 2667 2668 if ($prototype =~ m/TRACE_EVENT\((.*?),/) { 2669 $tracepointname = $1; 2670 } 2671 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) { 2672 $tracepointname = $1; 2673 } 2674 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) { 2675 $tracepointname = $2; 2676 } 2677 $tracepointname =~ s/^\s+//; #strip leading whitespace 2678 if ($prototype =~ m/TP_PROTO\((.*?)\)/) { 2679 $tracepointargs = $1; 2680 } 2681 if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 2682 print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". 2683 "$prototype\n"; 2684 } else { 2685 $prototype = "static inline void trace_$tracepointname($tracepointargs)"; 2686 } 2687} 2688 2689sub syscall_munge() { 2690 my $void = 0; 2691 2692 $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs 2693## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) { 2694 if ($prototype =~ m/SYSCALL_DEFINE0/) { 2695 $void = 1; 2696## $prototype = "long sys_$1(void)"; 2697 } 2698 2699 $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name 2700 if ($prototype =~ m/long (sys_.*?),/) { 2701 $prototype =~ s/,/\(/; 2702 } elsif ($void) { 2703 $prototype =~ s/\)/\(void\)/; 2704 } 2705 2706 # now delete all of the odd-number commas in $prototype 2707 # so that arg types & arg names don't have a comma between them 2708 my $count = 0; 2709 my $len = length($prototype); 2710 if ($void) { 2711 $len = 0; # skip the for-loop 2712 } 2713 for (my $ix = 0; $ix < $len; $ix++) { 2714 if (substr($prototype, $ix, 1) eq ',') { 2715 $count++; 2716 if ($count % 2 == 1) { 2717 substr($prototype, $ix, 1) = ' '; 2718 } 2719 } 2720 } 2721} 2722 2723sub process_proto_function($$) { 2724 my $x = shift; 2725 my $file = shift; 2726 2727 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 2728 2729 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { 2730 # do nothing 2731 } 2732 elsif ($x =~ /([^\{]*)/) { 2733 $prototype .= $1; 2734 } 2735 2736 if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) { 2737 $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 2738 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 2739 $prototype =~ s@^\s+@@gos; # strip leading spaces 2740 if ($prototype =~ /SYSCALL_DEFINE/) { 2741 syscall_munge(); 2742 } 2743 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ || 2744 $prototype =~ /DEFINE_SINGLE_EVENT/) 2745 { 2746 tracepoint_munge($file); 2747 } 2748 dump_function($prototype, $file); 2749 reset_state(); 2750 } 2751} 2752 2753sub process_proto_type($$) { 2754 my $x = shift; 2755 my $file = shift; 2756 2757 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 2758 $x =~ s@^\s+@@gos; # strip leading spaces 2759 $x =~ s@\s+$@@gos; # strip trailing spaces 2760 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 2761 2762 if ($x =~ /^#/) { 2763 # To distinguish preprocessor directive from regular declaration later. 2764 $x .= ";"; 2765 } 2766 2767 while (1) { 2768 if ( $x =~ /([^{};]*)([{};])(.*)/ ) { 2769 $prototype .= $1 . $2; 2770 ($2 eq '{') && $brcount++; 2771 ($2 eq '}') && $brcount--; 2772 if (($2 eq ';') && ($brcount == 0)) { 2773 dump_declaration($prototype, $file); 2774 reset_state(); 2775 last; 2776 } 2777 $x = $3; 2778 } else { 2779 $prototype .= $x; 2780 last; 2781 } 2782 } 2783} 2784 2785# xml_escape: replace <, >, and & in the text stream; 2786# 2787# however, formatting controls that are generated internally/locally in the 2788# kernel-doc script are not escaped here; instead, they begin life like 2789# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings 2790# are converted to their mnemonic-expected output, without the 4 * '\' & ':', 2791# just before actual output; (this is done by local_unescape()) 2792sub xml_escape($) { 2793 my $text = shift; 2794 if (($output_mode eq "text") || ($output_mode eq "man")) { 2795 return $text; 2796 } 2797 $text =~ s/\&/\\\\\\amp;/g; 2798 $text =~ s/\</\\\\\\lt;/g; 2799 $text =~ s/\>/\\\\\\gt;/g; 2800 return $text; 2801} 2802 2803# xml_unescape: reverse the effects of xml_escape 2804sub xml_unescape($) { 2805 my $text = shift; 2806 if (($output_mode eq "text") || ($output_mode eq "man")) { 2807 return $text; 2808 } 2809 $text =~ s/\\\\\\amp;/\&/g; 2810 $text =~ s/\\\\\\lt;/</g; 2811 $text =~ s/\\\\\\gt;/>/g; 2812 return $text; 2813} 2814 2815# convert local escape strings to html 2816# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes) 2817sub local_unescape($) { 2818 my $text = shift; 2819 if (($output_mode eq "text") || ($output_mode eq "man")) { 2820 return $text; 2821 } 2822 $text =~ s/\\\\\\\\lt:/</g; 2823 $text =~ s/\\\\\\\\gt:/>/g; 2824 return $text; 2825} 2826 2827sub map_filename($) { 2828 my $file; 2829 my ($orig_file) = @_; 2830 2831 if (defined($ENV{'SRCTREE'})) { 2832 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; 2833 } else { 2834 $file = $orig_file; 2835 } 2836 2837 if (defined($source_map{$file})) { 2838 $file = $source_map{$file}; 2839 } 2840 2841 return $file; 2842} 2843 2844sub process_export_file($) { 2845 my ($orig_file) = @_; 2846 my $file = map_filename($orig_file); 2847 2848 if (!open(IN,"<$file")) { 2849 print STDERR "Error: Cannot open file $file\n"; 2850 ++$errors; 2851 return; 2852 } 2853 2854 while (<IN>) { 2855 if (/$export_symbol/) { 2856 $function_table{$2} = 1; 2857 } 2858 } 2859 2860 close(IN); 2861} 2862 2863sub process_file($) { 2864 my $file; 2865 my $identifier; 2866 my $func; 2867 my $descr; 2868 my $in_purpose = 0; 2869 my $initial_section_counter = $section_counter; 2870 my ($orig_file) = @_; 2871 my $leading_space; 2872 2873 $file = map_filename($orig_file); 2874 2875 if (!open(IN,"<$file")) { 2876 print STDERR "Error: Cannot open file $file\n"; 2877 ++$errors; 2878 return; 2879 } 2880 2881 $. = 1; 2882 2883 $section_counter = 0; 2884 while (<IN>) { 2885 while (s/\\\s*$//) { 2886 $_ .= <IN>; 2887 } 2888 if ($state == STATE_NORMAL) { 2889 if (/$doc_start/o) { 2890 $state = STATE_NAME; # next line is always the function name 2891 $in_doc_sect = 0; 2892 $declaration_start_line = $. + 1; 2893 } 2894 } elsif ($state == STATE_NAME) {# this line is the function name (always) 2895 if (/$doc_block/o) { 2896 $state = STATE_DOCBLOCK; 2897 $contents = ""; 2898 $new_start_line = $. + 1; 2899 2900 if ( $1 eq "" ) { 2901 $section = $section_intro; 2902 } else { 2903 $section = $1; 2904 } 2905 } 2906 elsif (/$doc_decl/o) { 2907 $identifier = $1; 2908 if (/\s*([\w\s]+?)\s*-/) { 2909 $identifier = $1; 2910 } 2911 2912 $state = STATE_FIELD; 2913 # if there's no @param blocks need to set up default section 2914 # here 2915 $contents = ""; 2916 $section = $section_default; 2917 $new_start_line = $. + 1; 2918 if (/-(.*)/) { 2919 # strip leading/trailing/multiple spaces 2920 $descr= $1; 2921 $descr =~ s/^\s*//; 2922 $descr =~ s/\s*$//; 2923 $descr =~ s/\s+/ /g; 2924 $declaration_purpose = xml_escape($descr); 2925 $in_purpose = 1; 2926 } else { 2927 $declaration_purpose = ""; 2928 } 2929 2930 if (($declaration_purpose eq "") && $verbose) { 2931 print STDERR "${file}:$.: warning: missing initial short description on line:\n"; 2932 print STDERR $_; 2933 ++$warnings; 2934 } 2935 2936 if ($identifier =~ m/^struct/) { 2937 $decl_type = 'struct'; 2938 } elsif ($identifier =~ m/^union/) { 2939 $decl_type = 'union'; 2940 } elsif ($identifier =~ m/^enum/) { 2941 $decl_type = 'enum'; 2942 } elsif ($identifier =~ m/^typedef/) { 2943 $decl_type = 'typedef'; 2944 } else { 2945 $decl_type = 'function'; 2946 } 2947 2948 if ($verbose) { 2949 print STDERR "${file}:$.: info: Scanning doc for $identifier\n"; 2950 } 2951 } else { 2952 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", 2953 " - I thought it was a doc line\n"; 2954 ++$warnings; 2955 $state = STATE_NORMAL; 2956 } 2957 } elsif ($state == STATE_FIELD) { # look for head: lines, and include content 2958 if (/$doc_sect/i) { # case insensitive for supported section names 2959 $newsection = $1; 2960 $newcontents = $2; 2961 2962 # map the supported section names to the canonical names 2963 if ($newsection =~ m/^description$/i) { 2964 $newsection = $section_default; 2965 } elsif ($newsection =~ m/^context$/i) { 2966 $newsection = $section_context; 2967 } elsif ($newsection =~ m/^returns?$/i) { 2968 $newsection = $section_return; 2969 } elsif ($newsection =~ m/^\@return$/) { 2970 # special: @return is a section, not a param description 2971 $newsection = $section_return; 2972 } 2973 2974 if (($contents ne "") && ($contents ne "\n")) { 2975 if (!$in_doc_sect && $verbose) { 2976 print STDERR "${file}:$.: warning: contents before sections\n"; 2977 ++$warnings; 2978 } 2979 dump_section($file, $section, xml_escape($contents)); 2980 $section = $section_default; 2981 } 2982 2983 $in_doc_sect = 1; 2984 $in_purpose = 0; 2985 $contents = $newcontents; 2986 $new_start_line = $.; 2987 while ((substr($contents, 0, 1) eq " ") || 2988 substr($contents, 0, 1) eq "\t") { 2989 $contents = substr($contents, 1); 2990 } 2991 if ($contents ne "") { 2992 $contents .= "\n"; 2993 } 2994 $section = $newsection; 2995 $leading_space = undef; 2996 } elsif (/$doc_end/) { 2997 if (($contents ne "") && ($contents ne "\n")) { 2998 dump_section($file, $section, xml_escape($contents)); 2999 $section = $section_default; 3000 $contents = ""; 3001 } 3002 # look for doc_com + <text> + doc_end: 3003 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { 3004 print STDERR "${file}:$.: warning: suspicious ending line: $_"; 3005 ++$warnings; 3006 } 3007 3008 $prototype = ""; 3009 $state = STATE_PROTO; 3010 $brcount = 0; 3011# print STDERR "end of doc comment, looking for prototype\n"; 3012 } elsif (/$doc_content/) { 3013 # miguel-style comment kludge, look for blank lines after 3014 # @parameter line to signify start of description 3015 if ($1 eq "") { 3016 if ($section =~ m/^@/ || $section eq $section_context) { 3017 dump_section($file, $section, xml_escape($contents)); 3018 $section = $section_default; 3019 $contents = ""; 3020 $new_start_line = $.; 3021 } else { 3022 $contents .= "\n"; 3023 } 3024 $in_purpose = 0; 3025 } elsif ($in_purpose == 1) { 3026 # Continued declaration purpose 3027 chomp($declaration_purpose); 3028 $declaration_purpose .= " " . xml_escape($1); 3029 $declaration_purpose =~ s/\s+/ /g; 3030 } else { 3031 my $cont = $1; 3032 if ($section =~ m/^@/ || $section eq $section_context) { 3033 if (!defined $leading_space) { 3034 if ($cont =~ m/^(\s+)/) { 3035 $leading_space = $1; 3036 } else { 3037 $leading_space = ""; 3038 } 3039 } 3040 3041 $cont =~ s/^$leading_space//; 3042 } 3043 $contents .= $cont . "\n"; 3044 } 3045 } else { 3046 # i dont know - bad line? ignore. 3047 print STDERR "${file}:$.: warning: bad line: $_"; 3048 ++$warnings; 3049 } 3050 } elsif ($state == STATE_INLINE) { # scanning for inline parameters 3051 # First line (state 1) needs to be a @parameter 3052 if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { 3053 $section = $1; 3054 $contents = $2; 3055 $new_start_line = $.; 3056 if ($contents ne "") { 3057 while ((substr($contents, 0, 1) eq " ") || 3058 substr($contents, 0, 1) eq "\t") { 3059 $contents = substr($contents, 1); 3060 } 3061 $contents .= "\n"; 3062 } 3063 $inline_doc_state = STATE_INLINE_TEXT; 3064 # Documentation block end */ 3065 } elsif (/$doc_inline_end/) { 3066 if (($contents ne "") && ($contents ne "\n")) { 3067 dump_section($file, $section, xml_escape($contents)); 3068 $section = $section_default; 3069 $contents = ""; 3070 } 3071 $state = STATE_PROTO; 3072 $inline_doc_state = STATE_INLINE_NA; 3073 # Regular text 3074 } elsif (/$doc_content/) { 3075 if ($inline_doc_state == STATE_INLINE_TEXT) { 3076 $contents .= $1 . "\n"; 3077 # nuke leading blank lines 3078 if ($contents =~ /^\s*$/) { 3079 $contents = ""; 3080 } 3081 } elsif ($inline_doc_state == STATE_INLINE_NAME) { 3082 $inline_doc_state = STATE_INLINE_ERROR; 3083 print STDERR "${file}:$.: warning: "; 3084 print STDERR "Incorrect use of kernel-doc format: $_"; 3085 ++$warnings; 3086 } 3087 } 3088 } elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype) 3089 if (/$doc_inline_oneline/) { 3090 $section = $1; 3091 $contents = $2; 3092 if ($contents ne "") { 3093 $contents .= "\n"; 3094 dump_section($file, $section, xml_escape($contents)); 3095 $section = $section_default; 3096 $contents = ""; 3097 } 3098 } elsif (/$doc_inline_start/) { 3099 $state = STATE_INLINE; 3100 $inline_doc_state = STATE_INLINE_NAME; 3101 } elsif ($decl_type eq 'function') { 3102 process_proto_function($_, $file); 3103 } else { 3104 process_proto_type($_, $file); 3105 } 3106 } elsif ($state == STATE_DOCBLOCK) { 3107 if (/$doc_end/) 3108 { 3109 dump_doc_section($file, $section, xml_escape($contents)); 3110 $section = $section_default; 3111 $contents = ""; 3112 $function = ""; 3113 %parameterdescs = (); 3114 %parametertypes = (); 3115 @parameterlist = (); 3116 %sections = (); 3117 @sectionlist = (); 3118 $prototype = ""; 3119 $state = STATE_NORMAL; 3120 } 3121 elsif (/$doc_content/) 3122 { 3123 if ( $1 eq "" ) 3124 { 3125 $contents .= $blankline; 3126 } 3127 else 3128 { 3129 $contents .= $1 . "\n"; 3130 } 3131 } 3132 } 3133 } 3134 if ($initial_section_counter == $section_counter) { 3135 print STDERR "${file}:1: warning: no structured comments found\n"; 3136 if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) { 3137 print STDERR " Was looking for '$_'.\n" for keys %function_table; 3138 } 3139 if ($output_mode eq "xml") { 3140 # The template wants at least one RefEntry here; make one. 3141 print "<refentry>\n"; 3142 print " <refnamediv>\n"; 3143 print " <refname>\n"; 3144 print " ${orig_file}\n"; 3145 print " </refname>\n"; 3146 print " <refpurpose>\n"; 3147 print " Document generation inconsistency\n"; 3148 print " </refpurpose>\n"; 3149 print " </refnamediv>\n"; 3150 print " <refsect1>\n"; 3151 print " <title>\n"; 3152 print " Oops\n"; 3153 print " </title>\n"; 3154 print " <warning>\n"; 3155 print " <para>\n"; 3156 print " The template for this document tried to insert\n"; 3157 print " the structured comment from the file\n"; 3158 print " <filename>${orig_file}</filename> at this point,\n"; 3159 print " but none was found.\n"; 3160 print " This dummy section is inserted to allow\n"; 3161 print " generation to continue.\n"; 3162 print " </para>\n"; 3163 print " </warning>\n"; 3164 print " </refsect1>\n"; 3165 print "</refentry>\n"; 3166 } 3167 } 3168} 3169 3170 3171$kernelversion = get_kernel_version(); 3172 3173# generate a sequence of code that will splice in highlighting information 3174# using the s// operator. 3175for (my $k = 0; $k < @highlights; $k++) { 3176 my $pattern = $highlights[$k][0]; 3177 my $result = $highlights[$k][1]; 3178# print STDERR "scanning pattern:$pattern, highlight:($result)\n"; 3179 $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n"; 3180} 3181 3182# Read the file that maps relative names to absolute names for 3183# separate source and object directories and for shadow trees. 3184if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 3185 my ($relname, $absname); 3186 while(<SOURCE_MAP>) { 3187 chop(); 3188 ($relname, $absname) = (split())[0..1]; 3189 $relname =~ s:^/+::; 3190 $source_map{$relname} = $absname; 3191 } 3192 close(SOURCE_MAP); 3193} 3194 3195if ($output_selection == OUTPUT_EXPORTED || 3196 $output_selection == OUTPUT_INTERNAL) { 3197 3198 push(@export_file_list, @ARGV); 3199 3200 foreach (@export_file_list) { 3201 chomp; 3202 process_export_file($_); 3203 } 3204} 3205 3206foreach (@ARGV) { 3207 chomp; 3208 process_file($_); 3209} 3210if ($verbose && $errors) { 3211 print STDERR "$errors errors\n"; 3212} 3213if ($verbose && $warnings) { 3214 print STDERR "$warnings warnings\n"; 3215} 3216 3217exit($errors); 3218