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