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-2007 Randy Dunlap ## 9## ## 10## #define enhancements by Armin Kuster <akuster@mvista.com> ## 11## Copyright (c) 2000 MontaVista Software, Inc. ## 12## ## 13## This software falls under the GNU General Public License. ## 14## Please read the COPYING file for more information ## 15 16# w.o. 03-11-2000: added the '-filelist' option. 17 18# 18/01/2001 - Cleanups 19# Functions prototyped as foo(void) same as foo() 20# Stop eval'ing where we don't need to. 21# -- huggie@earth.li 22 23# 27/06/2001 - Allowed whitespace after initial "/**" and 24# allowed comments before function declarations. 25# -- Christian Kreibich <ck@whoop.org> 26 27# Still to do: 28# - add perldoc documentation 29# - Look more closely at some of the scarier bits :) 30 31# 26/05/2001 - Support for separate source and object trees. 32# Return error code. 33# Keith Owens <kaos@ocs.com.au> 34 35# 23/09/2001 - Added support for typedefs, structs, enums and unions 36# Support for Context section; can be terminated using empty line 37# Small fixes (like spaces vs. \s in regex) 38# -- Tim Jansen <tim@tjansen.de> 39 40 41# 42# This will read a 'c' file and scan for embedded comments in the 43# style of gnome comments (+minor extensions - see below). 44# 45 46# Note: This only supports 'c'. 47 48# usage: 49# kernel-doc [ -docbook | -html | -text | -man ] 50# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile 51# or 52# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile 53# 54# Set output format using one of -docbook -html -text or -man. Default is man. 55# 56# -function funcname 57# If set, then only generate documentation for the given function(s). All 58# other functions are ignored. 59# 60# -nofunction funcname 61# If set, then only generate documentation for the other function(s). 62# Cannot be used together with -function 63# (yes, that's a bug -- perl hackers can fix it 8)) 64# 65# c files - list of 'c' files to process 66# 67# All output goes to stdout, with errors to stderr. 68 69# 70# format of comments. 71# In the following table, (...)? signifies optional structure. 72# (...)* signifies 0 or more structure elements 73# /** 74# * function_name(:)? (- short description)? 75# (* @parameterx: (description of parameter x)?)* 76# (* a blank line)? 77# * (Description:)? (Description of function)? 78# * (section header: (section description)? )* 79# (*)?*/ 80# 81# So .. the trivial example would be: 82# 83# /** 84# * my_function 85# **/ 86# 87# If the Description: header tag is omitted, then there must be a blank line 88# after the last parameter specification. 89# e.g. 90# /** 91# * my_function - does my stuff 92# * @my_arg: its mine damnit 93# * 94# * Does my stuff explained. 95# */ 96# 97# or, could also use: 98# /** 99# * my_function - does my stuff 100# * @my_arg: its mine damnit 101# * Description: Does my stuff explained. 102# */ 103# etc. 104# 105# Beside functions you can also write documentation for structs, unions, 106# enums and typedefs. Instead of the function name you must write the name 107# of the declaration; the struct/union/enum/typedef must always precede 108# the name. Nesting of declarations is not supported. 109# Use the argument mechanism to document members or constants. 110# e.g. 111# /** 112# * struct my_struct - short description 113# * @a: first member 114# * @b: second member 115# * 116# * Longer description 117# */ 118# struct my_struct { 119# int a; 120# int b; 121# /* private: */ 122# int c; 123# }; 124# 125# All descriptions can be multiline, except the short function description. 126# 127# You can also add additional sections. When documenting kernel functions you 128# should document the "Context:" of the function, e.g. whether the functions 129# can be called form interrupts. Unlike other sections you can end it with an 130# empty line. 131# Example-sections should contain the string EXAMPLE so that they are marked 132# appropriately in DocBook. 133# 134# Example: 135# /** 136# * user_function - function that can only be called in user context 137# * @a: some argument 138# * Context: !in_interrupt() 139# * 140# * Some description 141# * Example: 142# * user_function(22); 143# */ 144# ... 145# 146# 147# All descriptive text is further processed, scanning for the following special 148# patterns, which are highlighted appropriately. 149# 150# 'funcname()' - function 151# '$ENVVAR' - environmental variable 152# '&struct_name' - name of a structure (up to two words including 'struct') 153# '@parameter' - name of a parameter 154# '%CONST' - name of a constant. 155 156my $errors = 0; 157my $warnings = 0; 158my $anon_struct_union = 0; 159 160# match expressions used to find embedded type information 161my $type_constant = '\%([-_\w]+)'; 162my $type_func = '(\w+)\(\)'; 163my $type_param = '\@(\w+)'; 164my $type_struct = '\&((struct\s*)*[_\w]+)'; 165my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; 166my $type_env = '(\$\w+)'; 167 168# Output conversion substitutions. 169# One for each output format 170 171# these work fairly well 172my %highlights_html = ( $type_constant, "<i>\$1</i>", 173 $type_func, "<b>\$1</b>", 174 $type_struct_xml, "<i>\$1</i>", 175 $type_env, "<b><i>\$1</i></b>", 176 $type_param, "<tt><b>\$1</b></tt>" ); 177my $local_lt = "\\\\\\\\lt:"; 178my $local_gt = "\\\\\\\\gt:"; 179my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" 180 181# XML, docbook format 182my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", 183 $type_constant, "<constant>\$1</constant>", 184 $type_func, "<function>\$1</function>", 185 $type_struct_xml, "<structname>\$1</structname>", 186 $type_env, "<envar>\$1</envar>", 187 $type_param, "<parameter>\$1</parameter>" ); 188my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n"; 189 190# gnome, docbook format 191my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>", 192 $type_func, "<function>\$1</function>", 193 $type_struct, "<structname>\$1</structname>", 194 $type_env, "<envar>\$1</envar>", 195 $type_param, "<parameter>\$1</parameter>" ); 196my $blankline_gnome = "</para><para>\n"; 197 198# these are pretty rough 199my %highlights_man = ( $type_constant, "\$1", 200 $type_func, "\\\\fB\$1\\\\fP", 201 $type_struct, "\\\\fI\$1\\\\fP", 202 $type_param, "\\\\fI\$1\\\\fP" ); 203my $blankline_man = ""; 204 205# text-mode 206my %highlights_text = ( $type_constant, "\$1", 207 $type_func, "\$1", 208 $type_struct, "\$1", 209 $type_param, "\$1" ); 210my $blankline_text = ""; 211 212 213sub usage { 214 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n"; 215 print " [ -function funcname [ -function funcname ...] ]\n"; 216 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; 217 print " c source file(s) > outputfile\n"; 218 exit 1; 219} 220 221# read arguments 222if ($#ARGV==-1) { 223 usage(); 224} 225 226my $verbose = 0; 227my $output_mode = "man"; 228my %highlights = %highlights_man; 229my $blankline = $blankline_man; 230my $modulename = "Kernel API"; 231my $function_only = 0; 232my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 233 'July', 'August', 'September', 'October', 234 'November', 'December')[(localtime)[4]] . 235 " " . ((localtime)[5]+1900); 236 237# Essentially these are globals 238# They probably want to be tidied up made more localised or summat. 239# CAVEAT EMPTOR! Some of the others I localised may not want to be which 240# could cause "use of undefined value" or other bugs. 241my ($function, %function_table,%parametertypes,$declaration_purpose); 242my ($type,$declaration_name,$return_type); 243my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map); 244 245# Generated docbook code is inserted in a template at a point where 246# docbook v3.1 requires a non-zero sequence of RefEntry's; see: 247# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html 248# We keep track of number of generated entries and generate a dummy 249# if needs be to ensure the expanded template can be postprocessed 250# into html. 251my $section_counter = 0; 252 253my $lineprefix=""; 254 255# states 256# 0 - normal code 257# 1 - looking for function name 258# 2 - scanning field start. 259# 3 - scanning prototype. 260# 4 - documentation block 261my $state; 262my $in_doc_sect; 263 264#declaration types: can be 265# 'function', 'struct', 'union', 'enum', 'typedef' 266my $decl_type; 267 268my $doc_special = "\@\%\$\&"; 269 270my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 271my $doc_end = '\*/'; 272my $doc_com = '\s*\*\s*'; 273my $doc_decl = $doc_com.'(\w+)'; 274my $doc_sect = $doc_com.'(['.$doc_special.']?[\w\s]+):(.*)'; 275my $doc_content = $doc_com.'(.*)'; 276my $doc_block = $doc_com.'DOC:\s*(.*)?'; 277 278my %constants; 279my %parameterdescs; 280my @parameterlist; 281my %sections; 282my @sectionlist; 283 284my $contents = ""; 285my $section_default = "Description"; # default section 286my $section_intro = "Introduction"; 287my $section = $section_default; 288my $section_context = "Context"; 289 290my $undescribed = "-- undescribed --"; 291 292reset_state(); 293 294while ($ARGV[0] =~ m/^-(.*)/) { 295 my $cmd = shift @ARGV; 296 if ($cmd eq "-html") { 297 $output_mode = "html"; 298 %highlights = %highlights_html; 299 $blankline = $blankline_html; 300 } elsif ($cmd eq "-man") { 301 $output_mode = "man"; 302 %highlights = %highlights_man; 303 $blankline = $blankline_man; 304 } elsif ($cmd eq "-text") { 305 $output_mode = "text"; 306 %highlights = %highlights_text; 307 $blankline = $blankline_text; 308 } elsif ($cmd eq "-docbook") { 309 $output_mode = "xml"; 310 %highlights = %highlights_xml; 311 $blankline = $blankline_xml; 312 } elsif ($cmd eq "-gnome") { 313 $output_mode = "gnome"; 314 %highlights = %highlights_gnome; 315 $blankline = $blankline_gnome; 316 } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document 317 $modulename = shift @ARGV; 318 } elsif ($cmd eq "-function") { # to only output specific functions 319 $function_only = 1; 320 $function = shift @ARGV; 321 $function_table{$function} = 1; 322 } elsif ($cmd eq "-nofunction") { # to only output specific functions 323 $function_only = 2; 324 $function = shift @ARGV; 325 $function_table{$function} = 1; 326 } elsif ($cmd eq "-v") { 327 $verbose = 1; 328 } elsif (($cmd eq "-h") || ($cmd eq "--help")) { 329 usage(); 330 } elsif ($cmd eq '-filelist') { 331 $filelist = shift @ARGV; 332 } 333} 334 335# get kernel version from env 336sub get_kernel_version() { 337 my $version; 338 339 if (defined($ENV{'KERNELVERSION'})) { 340 $version = $ENV{'KERNELVERSION'}; 341 } 342 return $version; 343} 344my $kernelversion = get_kernel_version(); 345 346# generate a sequence of code that will splice in highlighting information 347# using the s// operator. 348my $dohighlight = ""; 349foreach my $pattern (keys %highlights) { 350# print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n"; 351 $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n"; 352} 353 354## 355# dumps section contents to arrays/hashes intended for that purpose. 356# 357sub dump_section { 358 my $name = shift; 359 my $contents = join "\n", @_; 360 361 if ($name =~ m/$type_constant/) { 362 $name = $1; 363# print STDERR "constant section '$1' = '$contents'\n"; 364 $constants{$name} = $contents; 365 } elsif ($name =~ m/$type_param/) { 366# print STDERR "parameter def '$1' = '$contents'\n"; 367 $name = $1; 368 $parameterdescs{$name} = $contents; 369 } else { 370# print STDERR "other section '$name' = '$contents'\n"; 371 $sections{$name} = $contents; 372 push @sectionlist, $name; 373 } 374} 375 376## 377# output function 378# 379# parameterdescs, a hash. 380# function => "function name" 381# parameterlist => @list of parameters 382# parameterdescs => %parameter descriptions 383# sectionlist => @list of sections 384# sections => %section descriptions 385# 386 387sub output_highlight { 388 my $contents = join "\n",@_; 389 my $line; 390 391# DEBUG 392# if (!defined $contents) { 393# use Carp; 394# confess "output_highlight got called with no args?\n"; 395# } 396 397 if ($output_mode eq "html" || $output_mode eq "xml") { 398 $contents = local_unescape($contents); 399 # convert data read & converted thru xml_escape() into &xyz; format: 400 $contents =~ s/\\\\\\/&/g; 401 } 402# print STDERR "contents b4:$contents\n"; 403 eval $dohighlight; 404 die $@ if $@; 405# print STDERR "contents af:$contents\n"; 406 407 foreach $line (split "\n", $contents) { 408 if ($line eq ""){ 409 print $lineprefix, local_unescape($blankline); 410 } else { 411 $line =~ s/\\\\\\/\&/g; 412 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { 413 print "\\&$line"; 414 } else { 415 print $lineprefix, $line; 416 } 417 } 418 print "\n"; 419 } 420} 421 422#output sections in html 423sub output_section_html(%) { 424 my %args = %{$_[0]}; 425 my $section; 426 427 foreach $section (@{$args{'sectionlist'}}) { 428 print "<h3>$section</h3>\n"; 429 print "<blockquote>\n"; 430 output_highlight($args{'sections'}{$section}); 431 print "</blockquote>\n"; 432 } 433} 434 435# output enum in html 436sub output_enum_html(%) { 437 my %args = %{$_[0]}; 438 my ($parameter); 439 my $count; 440 print "<h2>enum ".$args{'enum'}."</h2>\n"; 441 442 print "<b>enum ".$args{'enum'}."</b> {<br>\n"; 443 $count = 0; 444 foreach $parameter (@{$args{'parameterlist'}}) { 445 print " <b>".$parameter."</b>"; 446 if ($count != $#{$args{'parameterlist'}}) { 447 $count++; 448 print ",\n"; 449 } 450 print "<br>"; 451 } 452 print "};<br>\n"; 453 454 print "<h3>Constants</h3>\n"; 455 print "<dl>\n"; 456 foreach $parameter (@{$args{'parameterlist'}}) { 457 print "<dt><b>".$parameter."</b>\n"; 458 print "<dd>"; 459 output_highlight($args{'parameterdescs'}{$parameter}); 460 } 461 print "</dl>\n"; 462 output_section_html(@_); 463 print "<hr>\n"; 464} 465 466# output typedef in html 467sub output_typedef_html(%) { 468 my %args = %{$_[0]}; 469 my ($parameter); 470 my $count; 471 print "<h2>typedef ".$args{'typedef'}."</h2>\n"; 472 473 print "<b>typedef ".$args{'typedef'}."</b>\n"; 474 output_section_html(@_); 475 print "<hr>\n"; 476} 477 478# output struct in html 479sub output_struct_html(%) { 480 my %args = %{$_[0]}; 481 my ($parameter); 482 483 print "<h2>".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."</h2>\n"; 484 print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n"; 485 foreach $parameter (@{$args{'parameterlist'}}) { 486 if ($parameter =~ /^#/) { 487 print "$parameter<br>\n"; 488 next; 489 } 490 my $parameter_name = $parameter; 491 $parameter_name =~ s/\[.*//; 492 493 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 494 $type = $args{'parametertypes'}{$parameter}; 495 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 496 # pointer-to-function 497 print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n"; 498 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 499 # bitfield 500 print " <i>$1</i> <b>$parameter</b>$2;<br>\n"; 501 } else { 502 print " <i>$type</i> <b>$parameter</b>;<br>\n"; 503 } 504 } 505 print "};<br>\n"; 506 507 print "<h3>Members</h3>\n"; 508 print "<dl>\n"; 509 foreach $parameter (@{$args{'parameterlist'}}) { 510 ($parameter =~ /^#/) && next; 511 512 my $parameter_name = $parameter; 513 $parameter_name =~ s/\[.*//; 514 515 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 516 print "<dt><b>".$parameter."</b>\n"; 517 print "<dd>"; 518 output_highlight($args{'parameterdescs'}{$parameter_name}); 519 } 520 print "</dl>\n"; 521 output_section_html(@_); 522 print "<hr>\n"; 523} 524 525# output function in html 526sub output_function_html(%) { 527 my %args = %{$_[0]}; 528 my ($parameter, $section); 529 my $count; 530 531 print "<h2>" .$args{'function'}." - ".$args{'purpose'}."</h2>\n"; 532 print "<i>".$args{'functiontype'}."</i>\n"; 533 print "<b>".$args{'function'}."</b>\n"; 534 print "("; 535 $count = 0; 536 foreach $parameter (@{$args{'parameterlist'}}) { 537 $type = $args{'parametertypes'}{$parameter}; 538 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 539 # pointer-to-function 540 print "<i>$1</i><b>$parameter</b>) <i>($2)</i>"; 541 } else { 542 print "<i>".$type."</i> <b>".$parameter."</b>"; 543 } 544 if ($count != $#{$args{'parameterlist'}}) { 545 $count++; 546 print ",\n"; 547 } 548 } 549 print ")\n"; 550 551 print "<h3>Arguments</h3>\n"; 552 print "<dl>\n"; 553 foreach $parameter (@{$args{'parameterlist'}}) { 554 my $parameter_name = $parameter; 555 $parameter_name =~ s/\[.*//; 556 557 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 558 print "<dt><b>".$parameter."</b>\n"; 559 print "<dd>"; 560 output_highlight($args{'parameterdescs'}{$parameter_name}); 561 } 562 print "</dl>\n"; 563 output_section_html(@_); 564 print "<hr>\n"; 565} 566 567# output intro in html 568sub output_intro_html(%) { 569 my %args = %{$_[0]}; 570 my ($parameter, $section); 571 my $count; 572 573 foreach $section (@{$args{'sectionlist'}}) { 574 print "<h3>$section</h3>\n"; 575 print "<ul>\n"; 576 output_highlight($args{'sections'}{$section}); 577 print "</ul>\n"; 578 } 579 print "<hr>\n"; 580} 581 582sub output_section_xml(%) { 583 my %args = %{$_[0]}; 584 my $section; 585 # print out each section 586 $lineprefix=" "; 587 foreach $section (@{$args{'sectionlist'}}) { 588 print "<refsect1>\n"; 589 print "<title>$section</title>\n"; 590 if ($section =~ m/EXAMPLE/i) { 591 print "<informalexample><programlisting>\n"; 592 } else { 593 print "<para>\n"; 594 } 595 output_highlight($args{'sections'}{$section}); 596 if ($section =~ m/EXAMPLE/i) { 597 print "</programlisting></informalexample>\n"; 598 } else { 599 print "</para>\n"; 600 } 601 print "</refsect1>\n"; 602 } 603} 604 605# output function in XML DocBook 606sub output_function_xml(%) { 607 my %args = %{$_[0]}; 608 my ($parameter, $section); 609 my $count; 610 my $id; 611 612 $id = "API-".$args{'function'}; 613 $id =~ s/[^A-Za-z0-9]/-/g; 614 615 print "<refentry id=\"$id\">\n"; 616 print "<refentryinfo>\n"; 617 print " <title>LINUX</title>\n"; 618 print " <productname>Kernel Hackers Manual</productname>\n"; 619 print " <date>$man_date</date>\n"; 620 print "</refentryinfo>\n"; 621 print "<refmeta>\n"; 622 print " <refentrytitle><phrase>".$args{'function'}."</phrase></refentrytitle>\n"; 623 print " <manvolnum>9</manvolnum>\n"; 624 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 625 print "</refmeta>\n"; 626 print "<refnamediv>\n"; 627 print " <refname>".$args{'function'}."</refname>\n"; 628 print " <refpurpose>\n"; 629 print " "; 630 output_highlight ($args{'purpose'}); 631 print " </refpurpose>\n"; 632 print "</refnamediv>\n"; 633 634 print "<refsynopsisdiv>\n"; 635 print " <title>Synopsis</title>\n"; 636 print " <funcsynopsis><funcprototype>\n"; 637 print " <funcdef>".$args{'functiontype'}." "; 638 print "<function>".$args{'function'}." </function></funcdef>\n"; 639 640 $count = 0; 641 if ($#{$args{'parameterlist'}} >= 0) { 642 foreach $parameter (@{$args{'parameterlist'}}) { 643 $type = $args{'parametertypes'}{$parameter}; 644 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 645 # pointer-to-function 646 print " <paramdef>$1<parameter>$parameter</parameter>)\n"; 647 print " <funcparams>$2</funcparams></paramdef>\n"; 648 } else { 649 print " <paramdef>".$type; 650 print " <parameter>$parameter</parameter></paramdef>\n"; 651 } 652 } 653 } else { 654 print " <void/>\n"; 655 } 656 print " </funcprototype></funcsynopsis>\n"; 657 print "</refsynopsisdiv>\n"; 658 659 # print parameters 660 print "<refsect1>\n <title>Arguments</title>\n"; 661 if ($#{$args{'parameterlist'}} >= 0) { 662 print " <variablelist>\n"; 663 foreach $parameter (@{$args{'parameterlist'}}) { 664 my $parameter_name = $parameter; 665 $parameter_name =~ s/\[.*//; 666 667 print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n"; 668 print " <listitem>\n <para>\n"; 669 $lineprefix=" "; 670 output_highlight($args{'parameterdescs'}{$parameter_name}); 671 print " </para>\n </listitem>\n </varlistentry>\n"; 672 } 673 print " </variablelist>\n"; 674 } else { 675 print " <para>\n None\n </para>\n"; 676 } 677 print "</refsect1>\n"; 678 679 output_section_xml(@_); 680 print "</refentry>\n\n"; 681} 682 683# output struct in XML DocBook 684sub output_struct_xml(%) { 685 my %args = %{$_[0]}; 686 my ($parameter, $section); 687 my $id; 688 689 $id = "API-struct-".$args{'struct'}; 690 $id =~ s/[^A-Za-z0-9]/-/g; 691 692 print "<refentry id=\"$id\">\n"; 693 print "<refentryinfo>\n"; 694 print " <title>LINUX</title>\n"; 695 print " <productname>Kernel Hackers Manual</productname>\n"; 696 print " <date>$man_date</date>\n"; 697 print "</refentryinfo>\n"; 698 print "<refmeta>\n"; 699 print " <refentrytitle><phrase>".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n"; 700 print " <manvolnum>9</manvolnum>\n"; 701 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 702 print "</refmeta>\n"; 703 print "<refnamediv>\n"; 704 print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n"; 705 print " <refpurpose>\n"; 706 print " "; 707 output_highlight ($args{'purpose'}); 708 print " </refpurpose>\n"; 709 print "</refnamediv>\n"; 710 711 print "<refsynopsisdiv>\n"; 712 print " <title>Synopsis</title>\n"; 713 print " <programlisting>\n"; 714 print $args{'type'}." ".$args{'struct'}." {\n"; 715 foreach $parameter (@{$args{'parameterlist'}}) { 716 if ($parameter =~ /^#/) { 717 print "$parameter\n"; 718 next; 719 } 720 721 my $parameter_name = $parameter; 722 $parameter_name =~ s/\[.*//; 723 724 defined($args{'parameterdescs'}{$parameter_name}) || next; 725 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 726 $type = $args{'parametertypes'}{$parameter}; 727 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 728 # pointer-to-function 729 print " $1 $parameter) ($2);\n"; 730 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 731 # bitfield 732 print " $1 $parameter$2;\n"; 733 } else { 734 print " ".$type." ".$parameter.";\n"; 735 } 736 } 737 print "};"; 738 print " </programlisting>\n"; 739 print "</refsynopsisdiv>\n"; 740 741 print " <refsect1>\n"; 742 print " <title>Members</title>\n"; 743 744 print " <variablelist>\n"; 745 foreach $parameter (@{$args{'parameterlist'}}) { 746 ($parameter =~ /^#/) && next; 747 748 my $parameter_name = $parameter; 749 $parameter_name =~ s/\[.*//; 750 751 defined($args{'parameterdescs'}{$parameter_name}) || next; 752 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 753 print " <varlistentry>"; 754 print " <term>$parameter</term>\n"; 755 print " <listitem><para>\n"; 756 output_highlight($args{'parameterdescs'}{$parameter_name}); 757 print " </para></listitem>\n"; 758 print " </varlistentry>\n"; 759 } 760 print " </variablelist>\n"; 761 print " </refsect1>\n"; 762 763 output_section_xml(@_); 764 765 print "</refentry>\n\n"; 766} 767 768# output enum in XML DocBook 769sub output_enum_xml(%) { 770 my %args = %{$_[0]}; 771 my ($parameter, $section); 772 my $count; 773 my $id; 774 775 $id = "API-enum-".$args{'enum'}; 776 $id =~ s/[^A-Za-z0-9]/-/g; 777 778 print "<refentry id=\"$id\">\n"; 779 print "<refentryinfo>\n"; 780 print " <title>LINUX</title>\n"; 781 print " <productname>Kernel Hackers Manual</productname>\n"; 782 print " <date>$man_date</date>\n"; 783 print "</refentryinfo>\n"; 784 print "<refmeta>\n"; 785 print " <refentrytitle><phrase>enum ".$args{'enum'}."</phrase></refentrytitle>\n"; 786 print " <manvolnum>9</manvolnum>\n"; 787 print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n"; 788 print "</refmeta>\n"; 789 print "<refnamediv>\n"; 790 print " <refname>enum ".$args{'enum'}."</refname>\n"; 791 print " <refpurpose>\n"; 792 print " "; 793 output_highlight ($args{'purpose'}); 794 print " </refpurpose>\n"; 795 print "</refnamediv>\n"; 796 797 print "<refsynopsisdiv>\n"; 798 print " <title>Synopsis</title>\n"; 799 print " <programlisting>\n"; 800 print "enum ".$args{'enum'}." {\n"; 801 $count = 0; 802 foreach $parameter (@{$args{'parameterlist'}}) { 803 print " $parameter"; 804 if ($count != $#{$args{'parameterlist'}}) { 805 $count++; 806 print ","; 807 } 808 print "\n"; 809 } 810 print "};"; 811 print " </programlisting>\n"; 812 print "</refsynopsisdiv>\n"; 813 814 print "<refsect1>\n"; 815 print " <title>Constants</title>\n"; 816 print " <variablelist>\n"; 817 foreach $parameter (@{$args{'parameterlist'}}) { 818 my $parameter_name = $parameter; 819 $parameter_name =~ s/\[.*//; 820 821 print " <varlistentry>"; 822 print " <term>$parameter</term>\n"; 823 print " <listitem><para>\n"; 824 output_highlight($args{'parameterdescs'}{$parameter_name}); 825 print " </para></listitem>\n"; 826 print " </varlistentry>\n"; 827 } 828 print " </variablelist>\n"; 829 print "</refsect1>\n"; 830 831 output_section_xml(@_); 832 833 print "</refentry>\n\n"; 834} 835 836# output typedef in XML DocBook 837sub output_typedef_xml(%) { 838 my %args = %{$_[0]}; 839 my ($parameter, $section); 840 my $id; 841 842 $id = "API-typedef-".$args{'typedef'}; 843 $id =~ s/[^A-Za-z0-9]/-/g; 844 845 print "<refentry id=\"$id\">\n"; 846 print "<refentryinfo>\n"; 847 print " <title>LINUX</title>\n"; 848 print " <productname>Kernel Hackers Manual</productname>\n"; 849 print " <date>$man_date</date>\n"; 850 print "</refentryinfo>\n"; 851 print "<refmeta>\n"; 852 print " <refentrytitle><phrase>typedef ".$args{'typedef'}."</phrase></refentrytitle>\n"; 853 print " <manvolnum>9</manvolnum>\n"; 854 print "</refmeta>\n"; 855 print "<refnamediv>\n"; 856 print " <refname>typedef ".$args{'typedef'}."</refname>\n"; 857 print " <refpurpose>\n"; 858 print " "; 859 output_highlight ($args{'purpose'}); 860 print " </refpurpose>\n"; 861 print "</refnamediv>\n"; 862 863 print "<refsynopsisdiv>\n"; 864 print " <title>Synopsis</title>\n"; 865 print " <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n"; 866 print "</refsynopsisdiv>\n"; 867 868 output_section_xml(@_); 869 870 print "</refentry>\n\n"; 871} 872 873# output in XML DocBook 874sub output_intro_xml(%) { 875 my %args = %{$_[0]}; 876 my ($parameter, $section); 877 my $count; 878 879 my $id = $args{'module'}; 880 $id =~ s/[^A-Za-z0-9]/-/g; 881 882 # print out each section 883 $lineprefix=" "; 884 foreach $section (@{$args{'sectionlist'}}) { 885 print "<refsect1>\n <title>$section</title>\n <para>\n"; 886 if ($section =~ m/EXAMPLE/i) { 887 print "<example><para>\n"; 888 } 889 output_highlight($args{'sections'}{$section}); 890 if ($section =~ m/EXAMPLE/i) { 891 print "</para></example>\n"; 892 } 893 print " </para>\n</refsect1>\n"; 894 } 895 896 print "\n\n"; 897} 898 899# output in XML DocBook 900sub output_function_gnome { 901 my %args = %{$_[0]}; 902 my ($parameter, $section); 903 my $count; 904 my $id; 905 906 $id = $args{'module'}."-".$args{'function'}; 907 $id =~ s/[^A-Za-z0-9]/-/g; 908 909 print "<sect2>\n"; 910 print " <title id=\"$id\">".$args{'function'}."</title>\n"; 911 912 print " <funcsynopsis>\n"; 913 print " <funcdef>".$args{'functiontype'}." "; 914 print "<function>".$args{'function'}." "; 915 print "</function></funcdef>\n"; 916 917 $count = 0; 918 if ($#{$args{'parameterlist'}} >= 0) { 919 foreach $parameter (@{$args{'parameterlist'}}) { 920 $type = $args{'parametertypes'}{$parameter}; 921 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 922 # pointer-to-function 923 print " <paramdef>$1 <parameter>$parameter</parameter>)\n"; 924 print " <funcparams>$2</funcparams></paramdef>\n"; 925 } else { 926 print " <paramdef>".$type; 927 print " <parameter>$parameter</parameter></paramdef>\n"; 928 } 929 } 930 } else { 931 print " <void>\n"; 932 } 933 print " </funcsynopsis>\n"; 934 if ($#{$args{'parameterlist'}} >= 0) { 935 print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n"; 936 print "<tgroup cols=\"2\">\n"; 937 print "<colspec colwidth=\"2*\">\n"; 938 print "<colspec colwidth=\"8*\">\n"; 939 print "<tbody>\n"; 940 foreach $parameter (@{$args{'parameterlist'}}) { 941 my $parameter_name = $parameter; 942 $parameter_name =~ s/\[.*//; 943 944 print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n"; 945 print " <entry>\n"; 946 $lineprefix=" "; 947 output_highlight($args{'parameterdescs'}{$parameter_name}); 948 print " </entry></row>\n"; 949 } 950 print " </tbody></tgroup></informaltable>\n"; 951 } else { 952 print " <para>\n None\n </para>\n"; 953 } 954 955 # print out each section 956 $lineprefix=" "; 957 foreach $section (@{$args{'sectionlist'}}) { 958 print "<simplesect>\n <title>$section</title>\n"; 959 if ($section =~ m/EXAMPLE/i) { 960 print "<example><programlisting>\n"; 961 } else { 962 } 963 print "<para>\n"; 964 output_highlight($args{'sections'}{$section}); 965 print "</para>\n"; 966 if ($section =~ m/EXAMPLE/i) { 967 print "</programlisting></example>\n"; 968 } else { 969 } 970 print " </simplesect>\n"; 971 } 972 973 print "</sect2>\n\n"; 974} 975 976## 977# output function in man 978sub output_function_man(%) { 979 my %args = %{$_[0]}; 980 my ($parameter, $section); 981 my $count; 982 983 print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; 984 985 print ".SH NAME\n"; 986 print $args{'function'}." \\- ".$args{'purpose'}."\n"; 987 988 print ".SH SYNOPSIS\n"; 989 if ($args{'functiontype'} ne "") { 990 print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n"; 991 } else { 992 print ".B \"".$args{'function'}."\n"; 993 } 994 $count = 0; 995 my $parenth = "("; 996 my $post = ","; 997 foreach my $parameter (@{$args{'parameterlist'}}) { 998 if ($count == $#{$args{'parameterlist'}}) { 999 $post = ");"; 1000 } 1001 $type = $args{'parametertypes'}{$parameter}; 1002 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1003 # pointer-to-function 1004 print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n"; 1005 } else { 1006 $type =~ s/([^\*])$/$1 /; 1007 print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n"; 1008 } 1009 $count++; 1010 $parenth = ""; 1011 } 1012 1013 print ".SH ARGUMENTS\n"; 1014 foreach $parameter (@{$args{'parameterlist'}}) { 1015 my $parameter_name = $parameter; 1016 $parameter_name =~ s/\[.*//; 1017 1018 print ".IP \"".$parameter."\" 12\n"; 1019 output_highlight($args{'parameterdescs'}{$parameter_name}); 1020 } 1021 foreach $section (@{$args{'sectionlist'}}) { 1022 print ".SH \"", uc $section, "\"\n"; 1023 output_highlight($args{'sections'}{$section}); 1024 } 1025} 1026 1027## 1028# output enum in man 1029sub output_enum_man(%) { 1030 my %args = %{$_[0]}; 1031 my ($parameter, $section); 1032 my $count; 1033 1034 print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1035 1036 print ".SH NAME\n"; 1037 print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n"; 1038 1039 print ".SH SYNOPSIS\n"; 1040 print "enum ".$args{'enum'}." {\n"; 1041 $count = 0; 1042 foreach my $parameter (@{$args{'parameterlist'}}) { 1043 print ".br\n.BI \" $parameter\"\n"; 1044 if ($count == $#{$args{'parameterlist'}}) { 1045 print "\n};\n"; 1046 last; 1047 } 1048 else { 1049 print ", \n.br\n"; 1050 } 1051 $count++; 1052 } 1053 1054 print ".SH Constants\n"; 1055 foreach $parameter (@{$args{'parameterlist'}}) { 1056 my $parameter_name = $parameter; 1057 $parameter_name =~ s/\[.*//; 1058 1059 print ".IP \"".$parameter."\" 12\n"; 1060 output_highlight($args{'parameterdescs'}{$parameter_name}); 1061 } 1062 foreach $section (@{$args{'sectionlist'}}) { 1063 print ".SH \"$section\"\n"; 1064 output_highlight($args{'sections'}{$section}); 1065 } 1066} 1067 1068## 1069# output struct in man 1070sub output_struct_man(%) { 1071 my %args = %{$_[0]}; 1072 my ($parameter, $section); 1073 1074 print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n"; 1075 1076 print ".SH NAME\n"; 1077 print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n"; 1078 1079 print ".SH SYNOPSIS\n"; 1080 print $args{'type'}." ".$args{'struct'}." {\n.br\n"; 1081 1082 foreach my $parameter (@{$args{'parameterlist'}}) { 1083 if ($parameter =~ /^#/) { 1084 print ".BI \"$parameter\"\n.br\n"; 1085 next; 1086 } 1087 my $parameter_name = $parameter; 1088 $parameter_name =~ s/\[.*//; 1089 1090 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1091 $type = $args{'parametertypes'}{$parameter}; 1092 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1093 # pointer-to-function 1094 print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; 1095 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1096 # bitfield 1097 print ".BI \" ".$1."\ \" ".$parameter.$2." \""."\"\n;\n"; 1098 } else { 1099 $type =~ s/([^\*])$/$1 /; 1100 print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; 1101 } 1102 print "\n.br\n"; 1103 } 1104 print "};\n.br\n"; 1105 1106 print ".SH Members\n"; 1107 foreach $parameter (@{$args{'parameterlist'}}) { 1108 ($parameter =~ /^#/) && next; 1109 1110 my $parameter_name = $parameter; 1111 $parameter_name =~ s/\[.*//; 1112 1113 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1114 print ".IP \"".$parameter."\" 12\n"; 1115 output_highlight($args{'parameterdescs'}{$parameter_name}); 1116 } 1117 foreach $section (@{$args{'sectionlist'}}) { 1118 print ".SH \"$section\"\n"; 1119 output_highlight($args{'sections'}{$section}); 1120 } 1121} 1122 1123## 1124# output typedef in man 1125sub output_typedef_man(%) { 1126 my %args = %{$_[0]}; 1127 my ($parameter, $section); 1128 1129 print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1130 1131 print ".SH NAME\n"; 1132 print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n"; 1133 1134 foreach $section (@{$args{'sectionlist'}}) { 1135 print ".SH \"$section\"\n"; 1136 output_highlight($args{'sections'}{$section}); 1137 } 1138} 1139 1140sub output_intro_man(%) { 1141 my %args = %{$_[0]}; 1142 my ($parameter, $section); 1143 my $count; 1144 1145 print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1146 1147 foreach $section (@{$args{'sectionlist'}}) { 1148 print ".SH \"$section\"\n"; 1149 output_highlight($args{'sections'}{$section}); 1150 } 1151} 1152 1153## 1154# output in text 1155sub output_function_text(%) { 1156 my %args = %{$_[0]}; 1157 my ($parameter, $section); 1158 my $start; 1159 1160 print "Name:\n\n"; 1161 print $args{'function'}." - ".$args{'purpose'}."\n"; 1162 1163 print "\nSynopsis:\n\n"; 1164 if ($args{'functiontype'} ne "") { 1165 $start = $args{'functiontype'}." ".$args{'function'}." ("; 1166 } else { 1167 $start = $args{'function'}." ("; 1168 } 1169 print $start; 1170 1171 my $count = 0; 1172 foreach my $parameter (@{$args{'parameterlist'}}) { 1173 $type = $args{'parametertypes'}{$parameter}; 1174 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1175 # pointer-to-function 1176 print $1.$parameter.") (".$2; 1177 } else { 1178 print $type." ".$parameter; 1179 } 1180 if ($count != $#{$args{'parameterlist'}}) { 1181 $count++; 1182 print ",\n"; 1183 print " " x length($start); 1184 } else { 1185 print ");\n\n"; 1186 } 1187 } 1188 1189 print "Arguments:\n\n"; 1190 foreach $parameter (@{$args{'parameterlist'}}) { 1191 my $parameter_name = $parameter; 1192 $parameter_name =~ s/\[.*//; 1193 1194 print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n"; 1195 } 1196 output_section_text(@_); 1197} 1198 1199#output sections in text 1200sub output_section_text(%) { 1201 my %args = %{$_[0]}; 1202 my $section; 1203 1204 print "\n"; 1205 foreach $section (@{$args{'sectionlist'}}) { 1206 print "$section:\n\n"; 1207 output_highlight($args{'sections'}{$section}); 1208 } 1209 print "\n\n"; 1210} 1211 1212# output enum in text 1213sub output_enum_text(%) { 1214 my %args = %{$_[0]}; 1215 my ($parameter); 1216 my $count; 1217 print "Enum:\n\n"; 1218 1219 print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n"; 1220 print "enum ".$args{'enum'}." {\n"; 1221 $count = 0; 1222 foreach $parameter (@{$args{'parameterlist'}}) { 1223 print "\t$parameter"; 1224 if ($count != $#{$args{'parameterlist'}}) { 1225 $count++; 1226 print ","; 1227 } 1228 print "\n"; 1229 } 1230 print "};\n\n"; 1231 1232 print "Constants:\n\n"; 1233 foreach $parameter (@{$args{'parameterlist'}}) { 1234 print "$parameter\n\t"; 1235 print $args{'parameterdescs'}{$parameter}."\n"; 1236 } 1237 1238 output_section_text(@_); 1239} 1240 1241# output typedef in text 1242sub output_typedef_text(%) { 1243 my %args = %{$_[0]}; 1244 my ($parameter); 1245 my $count; 1246 print "Typedef:\n\n"; 1247 1248 print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n"; 1249 output_section_text(@_); 1250} 1251 1252# output struct as text 1253sub output_struct_text(%) { 1254 my %args = %{$_[0]}; 1255 my ($parameter); 1256 1257 print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n"; 1258 print $args{'type'}." ".$args{'struct'}." {\n"; 1259 foreach $parameter (@{$args{'parameterlist'}}) { 1260 if ($parameter =~ /^#/) { 1261 print "$parameter\n"; 1262 next; 1263 } 1264 1265 my $parameter_name = $parameter; 1266 $parameter_name =~ s/\[.*//; 1267 1268 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1269 $type = $args{'parametertypes'}{$parameter}; 1270 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1271 # pointer-to-function 1272 print "\t$1 $parameter) ($2);\n"; 1273 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1274 # bitfield 1275 print "\t$1 $parameter$2;\n"; 1276 } else { 1277 print "\t".$type." ".$parameter.";\n"; 1278 } 1279 } 1280 print "};\n\n"; 1281 1282 print "Members:\n\n"; 1283 foreach $parameter (@{$args{'parameterlist'}}) { 1284 ($parameter =~ /^#/) && next; 1285 1286 my $parameter_name = $parameter; 1287 $parameter_name =~ s/\[.*//; 1288 1289 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1290 print "$parameter\n\t"; 1291 print $args{'parameterdescs'}{$parameter_name}."\n"; 1292 } 1293 print "\n"; 1294 output_section_text(@_); 1295} 1296 1297sub output_intro_text(%) { 1298 my %args = %{$_[0]}; 1299 my ($parameter, $section); 1300 1301 foreach $section (@{$args{'sectionlist'}}) { 1302 print " $section:\n"; 1303 print " -> "; 1304 output_highlight($args{'sections'}{$section}); 1305 } 1306} 1307 1308## 1309# generic output function for all types (function, struct/union, typedef, enum); 1310# calls the generated, variable output_ function name based on 1311# functype and output_mode 1312sub output_declaration { 1313 no strict 'refs'; 1314 my $name = shift; 1315 my $functype = shift; 1316 my $func = "output_${functype}_$output_mode"; 1317 if (($function_only==0) || 1318 ( $function_only == 1 && defined($function_table{$name})) || 1319 ( $function_only == 2 && !defined($function_table{$name}))) 1320 { 1321 &$func(@_); 1322 $section_counter++; 1323 } 1324} 1325 1326## 1327# generic output function - calls the right one based on current output mode. 1328sub output_intro { 1329 no strict 'refs'; 1330 my $func = "output_intro_".$output_mode; 1331 &$func(@_); 1332 $section_counter++; 1333} 1334 1335## 1336# takes a declaration (struct, union, enum, typedef) and 1337# invokes the right handler. NOT called for functions. 1338sub dump_declaration($$) { 1339 no strict 'refs'; 1340 my ($prototype, $file) = @_; 1341 my $func = "dump_".$decl_type; 1342 &$func(@_); 1343} 1344 1345sub dump_union($$) { 1346 dump_struct(@_); 1347} 1348 1349sub dump_struct($$) { 1350 my $x = shift; 1351 my $file = shift; 1352 1353 if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { 1354 $declaration_name = $2; 1355 my $members = $3; 1356 1357 # ignore embedded structs or unions 1358 $members =~ s/{.*?}//g; 1359 1360 # ignore members marked private: 1361 $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; 1362 $members =~ s/\/\*.*?private:.*//gos; 1363 # strip comments: 1364 $members =~ s/\/\*.*?\*\///gos; 1365 1366 create_parameterlist($members, ';', $file); 1367 1368 output_declaration($declaration_name, 1369 'struct', 1370 {'struct' => $declaration_name, 1371 'module' => $modulename, 1372 'parameterlist' => \@parameterlist, 1373 'parameterdescs' => \%parameterdescs, 1374 'parametertypes' => \%parametertypes, 1375 'sectionlist' => \@sectionlist, 1376 'sections' => \%sections, 1377 'purpose' => $declaration_purpose, 1378 'type' => $decl_type 1379 }); 1380 } 1381 else { 1382 print STDERR "Error(${file}:$.): Cannot parse struct or union!\n"; 1383 ++$errors; 1384 } 1385} 1386 1387sub dump_enum($$) { 1388 my $x = shift; 1389 my $file = shift; 1390 1391 $x =~ s@/\*.*?\*/@@gos; # strip comments. 1392 if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { 1393 $declaration_name = $1; 1394 my $members = $2; 1395 1396 foreach my $arg (split ',', $members) { 1397 $arg =~ s/^\s*(\w+).*/$1/; 1398 push @parameterlist, $arg; 1399 if (!$parameterdescs{$arg}) { 1400 $parameterdescs{$arg} = $undescribed; 1401 print STDERR "Warning(${file}:$.): Enum value '$arg' ". 1402 "not described in enum '$declaration_name'\n"; 1403 } 1404 1405 } 1406 1407 output_declaration($declaration_name, 1408 'enum', 1409 {'enum' => $declaration_name, 1410 'module' => $modulename, 1411 'parameterlist' => \@parameterlist, 1412 'parameterdescs' => \%parameterdescs, 1413 'sectionlist' => \@sectionlist, 1414 'sections' => \%sections, 1415 'purpose' => $declaration_purpose 1416 }); 1417 } 1418 else { 1419 print STDERR "Error(${file}:$.): Cannot parse enum!\n"; 1420 ++$errors; 1421 } 1422} 1423 1424sub dump_typedef($$) { 1425 my $x = shift; 1426 my $file = shift; 1427 1428 $x =~ s@/\*.*?\*/@@gos; # strip comments. 1429 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 1430 $x =~ s/\(*.\)\s*;$/;/; 1431 $x =~ s/\[*.\]\s*;$/;/; 1432 } 1433 1434 if ($x =~ /typedef.*\s+(\w+)\s*;/) { 1435 $declaration_name = $1; 1436 1437 output_declaration($declaration_name, 1438 'typedef', 1439 {'typedef' => $declaration_name, 1440 'module' => $modulename, 1441 'sectionlist' => \@sectionlist, 1442 'sections' => \%sections, 1443 'purpose' => $declaration_purpose 1444 }); 1445 } 1446 else { 1447 print STDERR "Error(${file}:$.): Cannot parse typedef!\n"; 1448 ++$errors; 1449 } 1450} 1451 1452sub create_parameterlist($$$) { 1453 my $args = shift; 1454 my $splitter = shift; 1455 my $file = shift; 1456 my $type; 1457 my $param; 1458 1459 # temporarily replace commas inside function pointer definition 1460 while ($args =~ /(\([^\),]+),/) { 1461 $args =~ s/(\([^\),]+),/$1#/g; 1462 } 1463 1464 foreach my $arg (split($splitter, $args)) { 1465 # strip comments 1466 $arg =~ s/\/\*.*\*\///; 1467 # strip leading/trailing spaces 1468 $arg =~ s/^\s*//; 1469 $arg =~ s/\s*$//; 1470 $arg =~ s/\s+/ /; 1471 1472 if ($arg =~ /^#/) { 1473 # Treat preprocessor directive as a typeless variable just to fill 1474 # corresponding data structures "correctly". Catch it later in 1475 # output_* subs. 1476 push_parameter($arg, "", $file); 1477 } elsif ($arg =~ m/\(.*\*/) { 1478 # pointer-to-function 1479 $arg =~ tr/#/,/; 1480 $arg =~ m/[^\(]+\(\*\s*([^\)]+)\)/; 1481 $param = $1; 1482 $type = $arg; 1483 $type =~ s/([^\(]+\(\*)$param/$1/; 1484 push_parameter($param, $type, $file); 1485 } elsif ($arg) { 1486 $arg =~ s/\s*:\s*/:/g; 1487 $arg =~ s/\s*\[/\[/g; 1488 1489 my @args = split('\s*,\s*', $arg); 1490 if ($args[0] =~ m/\*/) { 1491 $args[0] =~ s/(\*+)\s*/ $1/; 1492 } 1493 1494 my @first_arg; 1495 if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { 1496 shift @args; 1497 push(@first_arg, split('\s+', $1)); 1498 push(@first_arg, $2); 1499 } else { 1500 @first_arg = split('\s+', shift @args); 1501 } 1502 1503 unshift(@args, pop @first_arg); 1504 $type = join " ", @first_arg; 1505 1506 foreach $param (@args) { 1507 if ($param =~ m/^(\*+)\s*(.*)/) { 1508 push_parameter($2, "$type $1", $file); 1509 } 1510 elsif ($param =~ m/(.*?):(\d+)/) { 1511 push_parameter($1, "$type:$2", $file) 1512 } 1513 else { 1514 push_parameter($param, $type, $file); 1515 } 1516 } 1517 } 1518 } 1519} 1520 1521sub push_parameter($$$) { 1522 my $param = shift; 1523 my $type = shift; 1524 my $file = shift; 1525 1526 if (($anon_struct_union == 1) && ($type eq "") && 1527 ($param eq "}")) { 1528 return; # ignore the ending }; from anon. struct/union 1529 } 1530 1531 $anon_struct_union = 0; 1532 my $param_name = $param; 1533 $param_name =~ s/\[.*//; 1534 1535 if ($type eq "" && $param =~ /\.\.\.$/) 1536 { 1537 $type=""; 1538 $parameterdescs{$param} = "variable arguments"; 1539 } 1540 elsif ($type eq "" && ($param eq "" or $param eq "void")) 1541 { 1542 $type=""; 1543 $param="void"; 1544 $parameterdescs{void} = "no arguments"; 1545 } 1546 elsif ($type eq "" && ($param eq "struct" or $param eq "union")) 1547 # handle unnamed (anonymous) union or struct: 1548 { 1549 $type = $param; 1550 $param = "{unnamed_" . $param . "}"; 1551 $parameterdescs{$param} = "anonymous\n"; 1552 $anon_struct_union = 1; 1553 } 1554 1555 # warn if parameter has no description 1556 # (but ignore ones starting with # as these are not parameters 1557 # but inline preprocessor statements); 1558 # also ignore unnamed structs/unions; 1559 if (!$anon_struct_union) { 1560 if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) { 1561 1562 $parameterdescs{$param_name} = $undescribed; 1563 1564 if (($type eq 'function') || ($type eq 'enum')) { 1565 print STDERR "Warning(${file}:$.): Function parameter ". 1566 "or member '$param' not " . 1567 "described in '$declaration_name'\n"; 1568 } 1569 print STDERR "Warning(${file}:$.):". 1570 " No description found for parameter '$param'\n"; 1571 ++$warnings; 1572 } 1573 } 1574 1575 push @parameterlist, $param; 1576 $parametertypes{$param} = $type; 1577} 1578 1579## 1580# takes a function prototype and the name of the current file being 1581# processed and spits out all the details stored in the global 1582# arrays/hashes. 1583sub dump_function($$) { 1584 my $prototype = shift; 1585 my $file = shift; 1586 1587 $prototype =~ s/^static +//; 1588 $prototype =~ s/^extern +//; 1589 $prototype =~ s/^fastcall +//; 1590 $prototype =~ s/^asmlinkage +//; 1591 $prototype =~ s/^inline +//; 1592 $prototype =~ s/^__inline__ +//; 1593 $prototype =~ s/^__inline +//; 1594 $prototype =~ s/^__always_inline +//; 1595 $prototype =~ s/^noinline +//; 1596 $prototype =~ s/__devinit +//; 1597 $prototype =~ s/^#define\s+//; #ak added 1598 $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; 1599 1600 # Yes, this truly is vile. We are looking for: 1601 # 1. Return type (may be nothing if we're looking at a macro) 1602 # 2. Function name 1603 # 3. Function parameters. 1604 # 1605 # All the while we have to watch out for function pointer parameters 1606 # (which IIRC is what the two sections are for), C types (these 1607 # regexps don't even start to express all the possibilities), and 1608 # so on. 1609 # 1610 # If you mess with these regexps, it's a good idea to check that 1611 # the following functions' documentation still comes out right: 1612 # - parport_register_device (function pointer parameters) 1613 # - atomic_set (macro) 1614 # - pci_match_device, __copy_to_user (long return type) 1615 1616 if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1617 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1618 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1619 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1620 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1621 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1622 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1623 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1624 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1625 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1626 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1627 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1628 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1629 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1630 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1631 $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1632 $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { 1633 $return_type = $1; 1634 $declaration_name = $2; 1635 my $args = $3; 1636 1637 create_parameterlist($args, ',', $file); 1638 } else { 1639 print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n"; 1640 ++$errors; 1641 return; 1642 } 1643 1644 output_declaration($declaration_name, 1645 'function', 1646 {'function' => $declaration_name, 1647 'module' => $modulename, 1648 'functiontype' => $return_type, 1649 'parameterlist' => \@parameterlist, 1650 'parameterdescs' => \%parameterdescs, 1651 'parametertypes' => \%parametertypes, 1652 'sectionlist' => \@sectionlist, 1653 'sections' => \%sections, 1654 'purpose' => $declaration_purpose 1655 }); 1656} 1657 1658sub process_file($); 1659 1660# Read the file that maps relative names to absolute names for 1661# separate source and object directories and for shadow trees. 1662if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 1663 my ($relname, $absname); 1664 while(<SOURCE_MAP>) { 1665 chop(); 1666 ($relname, $absname) = (split())[0..1]; 1667 $relname =~ s:^/+::; 1668 $source_map{$relname} = $absname; 1669 } 1670 close(SOURCE_MAP); 1671} 1672 1673if ($filelist) { 1674 open(FLIST,"<$filelist") or die "Can't open file list $filelist"; 1675 while(<FLIST>) { 1676 chop; 1677 process_file($_); 1678 } 1679} 1680 1681foreach (@ARGV) { 1682 chomp; 1683 process_file($_); 1684} 1685if ($verbose && $errors) { 1686 print STDERR "$errors errors\n"; 1687} 1688if ($verbose && $warnings) { 1689 print STDERR "$warnings warnings\n"; 1690} 1691 1692exit($errors); 1693 1694sub reset_state { 1695 $function = ""; 1696 %constants = (); 1697 %parameterdescs = (); 1698 %parametertypes = (); 1699 @parameterlist = (); 1700 %sections = (); 1701 @sectionlist = (); 1702 $prototype = ""; 1703 1704 $state = 0; 1705} 1706 1707sub process_state3_function($$) { 1708 my $x = shift; 1709 my $file = shift; 1710 1711 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 1712 1713 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) { 1714 # do nothing 1715 } 1716 elsif ($x =~ /([^\{]*)/) { 1717 $prototype .= $1; 1718 } 1719 if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) { 1720 $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 1721 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1722 $prototype =~ s@^\s+@@gos; # strip leading spaces 1723 dump_function($prototype,$file); 1724 reset_state(); 1725 } 1726} 1727 1728sub process_state3_type($$) { 1729 my $x = shift; 1730 my $file = shift; 1731 1732 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1733 $x =~ s@^\s+@@gos; # strip leading spaces 1734 $x =~ s@\s+$@@gos; # strip trailing spaces 1735 $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 1736 1737 if ($x =~ /^#/) { 1738 # To distinguish preprocessor directive from regular declaration later. 1739 $x .= ";"; 1740 } 1741 1742 while (1) { 1743 if ( $x =~ /([^{};]*)([{};])(.*)/ ) { 1744 $prototype .= $1 . $2; 1745 ($2 eq '{') && $brcount++; 1746 ($2 eq '}') && $brcount--; 1747 if (($2 eq ';') && ($brcount == 0)) { 1748 dump_declaration($prototype,$file); 1749 reset_state(); 1750 last; 1751 } 1752 $x = $3; 1753 } else { 1754 $prototype .= $x; 1755 last; 1756 } 1757 } 1758} 1759 1760# xml_escape: replace <, >, and & in the text stream; 1761# 1762# however, formatting controls that are generated internally/locally in the 1763# kernel-doc script are not escaped here; instead, they begin life like 1764# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings 1765# are converted to their mnemonic-expected output, without the 4 * '\' & ':', 1766# just before actual output; (this is done by local_unescape()) 1767sub xml_escape($) { 1768 my $text = shift; 1769 if (($output_mode eq "text") || ($output_mode eq "man")) { 1770 return $text; 1771 } 1772 $text =~ s/\&/\\\\\\amp;/g; 1773 $text =~ s/\</\\\\\\lt;/g; 1774 $text =~ s/\>/\\\\\\gt;/g; 1775 return $text; 1776} 1777 1778# convert local escape strings to html 1779# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes) 1780sub local_unescape($) { 1781 my $text = shift; 1782 if (($output_mode eq "text") || ($output_mode eq "man")) { 1783 return $text; 1784 } 1785 $text =~ s/\\\\\\\\lt:/</g; 1786 $text =~ s/\\\\\\\\gt:/>/g; 1787 return $text; 1788} 1789 1790sub process_file($) { 1791 my $file; 1792 my $identifier; 1793 my $func; 1794 my $descr; 1795 my $initial_section_counter = $section_counter; 1796 1797 if (defined($ENV{'SRCTREE'})) { 1798 $file = "$ENV{'SRCTREE'}" . "/" . "@_"; 1799 } 1800 else { 1801 $file = "@_"; 1802 } 1803 if (defined($source_map{$file})) { 1804 $file = $source_map{$file}; 1805 } 1806 1807 if (!open(IN,"<$file")) { 1808 print STDERR "Error: Cannot open file $file\n"; 1809 ++$errors; 1810 return; 1811 } 1812 1813 $section_counter = 0; 1814 while (<IN>) { 1815 if ($state == 0) { 1816 if (/$doc_start/o) { 1817 $state = 1; # next line is always the function name 1818 $in_doc_sect = 0; 1819 } 1820 } elsif ($state == 1) { # this line is the function name (always) 1821 if (/$doc_block/o) { 1822 $state = 4; 1823 $contents = ""; 1824 if ( $1 eq "" ) { 1825 $section = $section_intro; 1826 } else { 1827 $section = $1; 1828 } 1829 } 1830 elsif (/$doc_decl/o) { 1831 $identifier = $1; 1832 if (/\s*([\w\s]+?)\s*-/) { 1833 $identifier = $1; 1834 } 1835 1836 $state = 2; 1837 if (/-(.*)/) { 1838 # strip leading/trailing/multiple spaces 1839 $descr= $1; 1840 $descr =~ s/^\s*//; 1841 $descr =~ s/\s*$//; 1842 $descr =~ s/\s+/ /; 1843 $declaration_purpose = xml_escape($descr); 1844 } else { 1845 $declaration_purpose = ""; 1846 } 1847 if ($identifier =~ m/^struct/) { 1848 $decl_type = 'struct'; 1849 } elsif ($identifier =~ m/^union/) { 1850 $decl_type = 'union'; 1851 } elsif ($identifier =~ m/^enum/) { 1852 $decl_type = 'enum'; 1853 } elsif ($identifier =~ m/^typedef/) { 1854 $decl_type = 'typedef'; 1855 } else { 1856 $decl_type = 'function'; 1857 } 1858 1859 if ($verbose) { 1860 print STDERR "Info(${file}:$.): Scanning doc for $identifier\n"; 1861 } 1862 } else { 1863 print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.", 1864 " - I thought it was a doc line\n"; 1865 ++$warnings; 1866 $state = 0; 1867 } 1868 } elsif ($state == 2) { # look for head: lines, and include content 1869 if (/$doc_sect/o) { 1870 $newsection = $1; 1871 $newcontents = $2; 1872 1873 if ($contents ne "") { 1874 if (!$in_doc_sect && $verbose) { 1875 print STDERR "Warning(${file}:$.): contents before sections\n"; 1876 ++$warnings; 1877 } 1878 dump_section($section, xml_escape($contents)); 1879 $section = $section_default; 1880 } 1881 1882 $in_doc_sect = 1; 1883 $contents = $newcontents; 1884 if ($contents ne "") { 1885 while ((substr($contents, 0, 1) eq " ") || 1886 substr($contents, 0, 1) eq "\t") { 1887 $contents = substr($contents, 1); 1888 } 1889 $contents .= "\n"; 1890 } 1891 $section = $newsection; 1892 } elsif (/$doc_end/) { 1893 1894 if ($contents ne "") { 1895 dump_section($section, xml_escape($contents)); 1896 $section = $section_default; 1897 $contents = ""; 1898 } 1899 1900 $prototype = ""; 1901 $state = 3; 1902 $brcount = 0; 1903# print STDERR "end of doc comment, looking for prototype\n"; 1904 } elsif (/$doc_content/) { 1905 # miguel-style comment kludge, look for blank lines after 1906 # @parameter line to signify start of description 1907 if ($1 eq "" && 1908 ($section =~ m/^@/ || $section eq $section_context)) { 1909 dump_section($section, xml_escape($contents)); 1910 $section = $section_default; 1911 $contents = ""; 1912 } else { 1913 $contents .= $1."\n"; 1914 } 1915 } else { 1916 # i dont know - bad line? ignore. 1917 print STDERR "Warning(${file}:$.): bad line: $_"; 1918 ++$warnings; 1919 } 1920 } elsif ($state == 3) { # scanning for function '{' (end of prototype) 1921 if ($decl_type eq 'function') { 1922 process_state3_function($_, $file); 1923 } else { 1924 process_state3_type($_, $file); 1925 } 1926 } elsif ($state == 4) { 1927 # Documentation block 1928 if (/$doc_block/) { 1929 dump_section($section, xml_escape($contents)); 1930 output_intro({'sectionlist' => \@sectionlist, 1931 'sections' => \%sections }); 1932 $contents = ""; 1933 $function = ""; 1934 %constants = (); 1935 %parameterdescs = (); 1936 %parametertypes = (); 1937 @parameterlist = (); 1938 %sections = (); 1939 @sectionlist = (); 1940 $prototype = ""; 1941 if ( $1 eq "" ) { 1942 $section = $section_intro; 1943 } else { 1944 $section = $1; 1945 } 1946 } 1947 elsif (/$doc_end/) 1948 { 1949 dump_section($section, xml_escape($contents)); 1950 output_intro({'sectionlist' => \@sectionlist, 1951 'sections' => \%sections }); 1952 $contents = ""; 1953 $function = ""; 1954 %constants = (); 1955 %parameterdescs = (); 1956 %parametertypes = (); 1957 @parameterlist = (); 1958 %sections = (); 1959 @sectionlist = (); 1960 $prototype = ""; 1961 $state = 0; 1962 } 1963 elsif (/$doc_content/) 1964 { 1965 if ( $1 eq "" ) 1966 { 1967 $contents .= $blankline; 1968 } 1969 else 1970 { 1971 $contents .= $1 . "\n"; 1972 } 1973 } 1974 } 1975 } 1976 if ($initial_section_counter == $section_counter) { 1977 print STDERR "Warning(${file}): no structured comments found\n"; 1978 if ($output_mode eq "xml") { 1979 # The template wants at least one RefEntry here; make one. 1980 print "<refentry>\n"; 1981 print " <refnamediv>\n"; 1982 print " <refname>\n"; 1983 print " ${file}\n"; 1984 print " </refname>\n"; 1985 print " <refpurpose>\n"; 1986 print " Document generation inconsistency\n"; 1987 print " </refpurpose>\n"; 1988 print " </refnamediv>\n"; 1989 print " <refsect1>\n"; 1990 print " <title>\n"; 1991 print " Oops\n"; 1992 print " </title>\n"; 1993 print " <warning>\n"; 1994 print " <para>\n"; 1995 print " The template for this document tried to insert\n"; 1996 print " the structured comment from the file\n"; 1997 print " <filename>${file}</filename> at this point,\n"; 1998 print " but none was found.\n"; 1999 print " This dummy section is inserted to allow\n"; 2000 print " generation to continue.\n"; 2001 print " </para>\n"; 2002 print " </warning>\n"; 2003 print " </refsect1>\n"; 2004 print "</refentry>\n"; 2005 } 2006 } 2007} 2008