1937 lines · 52.0 KB · Text
RawDownload
#!/usr/bin/perl -w use strict; ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        #### Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          #### Copyright (C) 2001  Simon Huggins                             #### 								 #### #define enhancements by Armin Kuster <akuster@mvista.com>	 #### Copyright (c) 2000 MontaVista Software, Inc.			 #### 								 #### This software falls under the GNU General Public License.     #### Please read the COPYING file for more information             ## # w.o. 03-11-2000: added the '-filelist' option. # 18/01/2001 - 	Cleanups# 		Functions prototyped as foo(void) same as foo()# 		Stop eval'ing where we don't need to.# -- huggie@earth.li # 27/06/2001 -  Allowed whitespace after initial "/**" and#               allowed comments before function declarations.# -- Christian Kreibich <ck@whoop.org> # Still to do:# 	- add perldoc documentation# 	- Look more closely at some of the scarier bits :) # 26/05/2001 - 	Support for separate source and object trees.#		Return error code.# 		Keith Owens <kaos@ocs.com.au> # 23/09/2001 - Added support for typedefs, structs, enums and unions#              Support for Context section; can be terminated using empty line#              Small fixes (like spaces vs. \s in regex)# -- Tim Jansen <tim@tjansen.de>  ## This will read a 'c' file and scan for embedded comments in the# style of gnome comments (+minor extensions - see below).# # Note: This only supports 'c'. # usage:# kernel-doc [ -docbook | -html | -text | -man ]#           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile# or#           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile##  Set output format using one of -docbook -html -text or -man.  Default is man.##  -function funcname#	If set, then only generate documentation for the given function(s).  All#	other functions are ignored.##  -nofunction funcname#	If set, then only generate documentation for the other function(s).#	Cannot be used together with -function#	(yes, that's a bug -- perl hackers can fix it 8))##  c files - list of 'c' files to process##  All output goes to stdout, with errors to stderr. ## format of comments.# In the following table, (...)? signifies optional structure.#                         (...)* signifies 0 or more structure elements# /**#  * function_name(:)? (- short description)?# (* @parameterx: (description of parameter x)?)*# (* a blank line)?#  * (Description:)? (Description of function)?#  * (section header: (section description)? )*#  (*)?*/## So .. the trivial example would be:## /**#  * my_function#  **/## If the Description: header tag is omitted, then there must be a blank line# after the last parameter specification.# e.g.# /**#  * my_function - does my stuff#  * @my_arg: its mine damnit#  *#  * Does my stuff explained.#  */##  or, could also use:# /**#  * my_function - does my stuff#  * @my_arg: its mine damnit#  * Description: Does my stuff explained.#  */# etc.## Beside functions you can also write documentation for structs, unions,# enums and typedefs. Instead of the function name you must write the name# of the declaration;  the struct/union/enum/typedef must always precede# the name. Nesting of declarations is not supported.# Use the argument mechanism to document members or constants.# e.g.# /**#  * struct my_struct - short description#  * @a: first member#  * @b: second member#  *#  * Longer description#  */# struct my_struct {#     int a;#     int b;# /* private: */#     int c;# };## All descriptions can be multiline, except the short function description.## You can also add additional sections. When documenting kernel functions you# should document the "Context:" of the function, e.g. whether the functions# can be called form interrupts. Unlike other sections you can end it with an# empty line.# Example-sections should contain the string EXAMPLE so that they are marked# appropriately in DocBook.## Example:# /**#  * user_function - function that can only be called in user context#  * @a: some argument#  * Context: !in_interrupt()#  *#  * Some description#  * Example:#  *    user_function(22);#  */# ...### All descriptive text is further processed, scanning for the following special# patterns, which are highlighted appropriately.## 'funcname()' - function# '$ENVVAR' - environmental variable# '&struct_name' - name of a structure (up to two words including 'struct')# '@parameter' - name of a parameter# '%CONST' - name of a constant. my $errors = 0;my $warnings = 0; # match expressions used to find embedded type informationmy $type_constant = '\%([-_\w]+)';my $type_func = '(\w+)\(\)';my $type_param = '\@(\w+)';my $type_struct = '\&((struct\s*)?[_\w]+)';my $type_env = '(\$\w+)'; # Output conversion substitutions.#  One for each output format # these work fairly wellmy %highlights_html = ( $type_constant, "<i>\$1</i>",			$type_func, "<b>\$1</b>",			$type_struct, "<i>\$1</i>",			$type_param, "<tt><b>\$1</b></tt>" );my $blankline_html = "<p>"; # XML, docbook formatmy %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",			$type_constant, "<constant>\$1</constant>",			$type_func, "<function>\$1</function>",			$type_struct, "<structname>\$1</structname>",			$type_env, "<envar>\$1</envar>",			$type_param, "<parameter>\$1</parameter>" );my $blankline_xml = "</para><para>\n"; # gnome, docbook formatmy %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",			 $type_func, "<function>\$1</function>",			 $type_struct, "<structname>\$1</structname>",			 $type_env, "<envar>\$1</envar>",			 $type_param, "<parameter>\$1</parameter>" );my $blankline_gnome = "</para><para>\n"; # these are pretty roughmy %highlights_man = ( $type_constant, "\$1",		       $type_func, "\\\\fB\$1\\\\fP",		       $type_struct, "\\\\fI\$1\\\\fP",		       $type_param, "\\\\fI\$1\\\\fP" );my $blankline_man = ""; # text-modemy %highlights_text = ( $type_constant, "\$1",			$type_func, "\$1",			$type_struct, "\$1",			$type_param, "\$1" );my $blankline_text = "";  sub usage {    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";    print "         [ -function funcname [ -function funcname ...] ]\n";    print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";    print "         c source file(s) > outputfile\n";    exit 1;} # read argumentsif ($#ARGV==-1) {    usage();} my $verbose = 0;my $output_mode = "man";my %highlights = %highlights_man;my $blankline = $blankline_man;my $modulename = "Kernel API";my $function_only = 0;my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',		'July', 'August', 'September', 'October',		'November', 'December')[(localtime)[4]] .  " " . ((localtime)[5]+1900); # Essentially these are globals# They probably want to be tidied up made more localised or summat.# CAVEAT EMPTOR!  Some of the others I localised may not want to be which# could cause "use of undefined value" or other bugs.my ($function, %function_table,%parametertypes,$declaration_purpose);my ($type,$declaration_name,$return_type);my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map); # Generated docbook code is inserted in a template at a point where# docbook v3.1 requires a non-zero sequence of RefEntry's; see:# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html# We keep track of number of generated entries and generate a dummy# if needs be to ensure the expanded template can be postprocessed# into html.my $section_counter = 0; my $lineprefix=""; # states# 0 - normal code# 1 - looking for function name# 2 - scanning field start.# 3 - scanning prototype.# 4 - documentation blockmy $state;my $in_doc_sect; #declaration types: can be# 'function', 'struct', 'union', 'enum', 'typedef'my $decl_type; my $doc_special = "\@\%\$\&"; my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.my $doc_end = '\*/';my $doc_com = '\s*\*\s*';my $doc_decl = $doc_com.'(\w+)';my $doc_sect = $doc_com.'(['.$doc_special.']?[\w\s]+):(.*)';my $doc_content = $doc_com.'(.*)';my $doc_block = $doc_com.'DOC:\s*(.*)?'; my %constants;my %parameterdescs;my @parameterlist;my %sections;my @sectionlist; my $contents = "";my $section_default = "Description";	# default sectionmy $section_intro = "Introduction";my $section = $section_default;my $section_context = "Context"; my $undescribed = "-- undescribed --"; reset_state(); while ($ARGV[0] =~ m/^-(.*)/) {    my $cmd = shift @ARGV;    if ($cmd eq "-html") {	$output_mode = "html";	%highlights = %highlights_html;	$blankline = $blankline_html;    } elsif ($cmd eq "-man") {	$output_mode = "man";	%highlights = %highlights_man;	$blankline = $blankline_man;    } elsif ($cmd eq "-text") {	$output_mode = "text";	%highlights = %highlights_text;	$blankline = $blankline_text;    } elsif ($cmd eq "-docbook") {	$output_mode = "xml";	%highlights = %highlights_xml;	$blankline = $blankline_xml;    } elsif ($cmd eq "-gnome") {	$output_mode = "gnome";	%highlights = %highlights_gnome;	$blankline = $blankline_gnome;    } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document	$modulename = shift @ARGV;    } elsif ($cmd eq "-function") { # to only output specific functions	$function_only = 1;	$function = shift @ARGV;	$function_table{$function} = 1;    } elsif ($cmd eq "-nofunction") { # to only output specific functions	$function_only = 2;	$function = shift @ARGV;	$function_table{$function} = 1;    } elsif ($cmd eq "-v") {	$verbose = 1;    } elsif (($cmd eq "-h") || ($cmd eq "--help")) {	usage();    } elsif ($cmd eq '-filelist') {	    $filelist = shift @ARGV;    }}  # generate a sequence of code that will splice in highlighting information# using the s// operator.my $dohighlight = "";foreach my $pattern (keys %highlights) {#    print "scanning pattern $pattern ($highlights{$pattern})\n";    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";} ### dumps section contents to arrays/hashes intended for that purpose.#sub dump_section {    my $name = shift;    my $contents = join "\n", @_;     if ($name =~ m/$type_constant/) {	$name = $1;#	print STDERR "constant section '$1' = '$contents'\n";	$constants{$name} = $contents;    } elsif ($name =~ m/$type_param/) {#	print STDERR "parameter def '$1' = '$contents'\n";	$name = $1;	$parameterdescs{$name} = $contents;    } else {#	print STDERR "other section '$name' = '$contents'\n";	$sections{$name} = $contents;	push @sectionlist, $name;    }} ### output function## parameterdescs, a hash.#  function => "function name"#  parameterlist => @list of parameters#  parameterdescs => %parameter descriptions#  sectionlist => @list of sections#  sections => %section descriptions# sub output_highlight {    my $contents = join "\n",@_;    my $line; #   DEBUG#   if (!defined $contents) {#	use Carp;#	confess "output_highlight got called with no args?\n";#   }     eval $dohighlight;    die $@ if $@;    foreach $line (split "\n", $contents) {      if ($line eq ""){	    print $lineprefix, $blankline;	} else {            $line =~ s/\\\\\\/\&/g;	    print $lineprefix, $line;	}	print "\n";    }} #output sections in htmlsub output_section_html(%) {    my %args = %{$_[0]};    my $section;     foreach $section (@{$args{'sectionlist'}}) {	print "<h3>$section</h3>\n";	print "<blockquote>\n";	output_highlight($args{'sections'}{$section});	print "</blockquote>\n";    }} # output enum in htmlsub output_enum_html(%) {    my %args = %{$_[0]};    my ($parameter);    my $count;    print "<h2>enum ".$args{'enum'}."</h2>\n";     print "<b>enum ".$args{'enum'}."</b> {<br>\n";    $count = 0;    foreach $parameter (@{$args{'parameterlist'}}) {        print " <b>".$parameter."</b>";	if ($count != $#{$args{'parameterlist'}}) {	    $count++;	    print ",\n";	}	print "<br>";    }    print "};<br>\n";     print "<h3>Constants</h3>\n";    print "<dl>\n";    foreach $parameter (@{$args{'parameterlist'}}) {	print "<dt><b>".$parameter."</b>\n";	print "<dd>";	output_highlight($args{'parameterdescs'}{$parameter});    }    print "</dl>\n";    output_section_html(@_);    print "<hr>\n";} # output typedef in htmlsub output_typedef_html(%) {    my %args = %{$_[0]};    my ($parameter);    my $count;    print "<h2>typedef ".$args{'typedef'}."</h2>\n";     print "<b>typedef ".$args{'typedef'}."</b>\n";    output_section_html(@_);    print "<hr>\n";} # output struct in htmlsub output_struct_html(%) {    my %args = %{$_[0]};    my ($parameter);     print "<h2>".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."</h2>\n";    print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";    foreach $parameter (@{$args{'parameterlist'}}) {	if ($parameter =~ /^#/) {		print "$parameter<br>\n";		next;	}	my $parameter_name = $parameter;	$parameter_name =~ s/\[.*//;         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;	$type = $args{'parametertypes'}{$parameter};	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {	    # pointer-to-function	    print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";	} elsif ($type =~ m/^(.*?)\s*(:.*)/) {	    print " <i>$1</i> <b>$parameter</b>$2;<br>\n";	} else {	    print " <i>$type</i> <b>$parameter</b>;<br>\n";	}    }    print "};<br>\n";     print "<h3>Members</h3>\n";    print "<dl>\n";    foreach $parameter (@{$args{'parameterlist'}}) {	($parameter =~ /^#/) && next; 	my $parameter_name = $parameter;	$parameter_name =~ s/\[.*//;         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;	print "<dt><b>".$parameter."</b>\n";	print "<dd>";	output_highlight($args{'parameterdescs'}{$parameter_name});    }    print "</dl>\n";    output_section_html(@_);    print "<hr>\n";} # output function in htmlsub output_function_html(%) {    my %args = %{$_[0]};    my ($parameter, $section);    my $count;

Lines 1–500 of 1937.