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