fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / scripts / kernel-doc
index aa7ffee..f50a70f 100755 (executable)
@@ -45,7 +45,7 @@ use strict;
 # Note: This only supports 'c'.
 
 # usage:
-# kerneldoc [ -docbook | -html | -text | -man ]
+# 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
@@ -57,9 +57,9 @@ use strict;
 #      other functions are ignored.
 #
 #  -nofunction funcname
-#      If set, then only generate documentation for the other function(s).  All
-#      other functions are ignored. Cannot be used with -function together
-#      (yes thats a bug - perl hackers can fix it 8))
+#      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
 #
@@ -90,45 +90,44 @@ use strict;
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
 #  *
-#  * Does my stuff explained. 
+#  * Does my stuff explained.
 #  */
 #
 #  or, could also use:
 # /**
 #  * my_function - does my stuff
 #  * @my_arg: its mine damnit
-#  * Description: Does my stuff explained. 
+#  * 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. In 
-# structs and unions you must declare one member per declaration 
-# (comma-separated members are not allowed -  the parser does not support 
-# this).
+# 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 
+#
+# 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 
+# empty line.
+# Example-sections should contain the string EXAMPLE so that they are marked
 # appropriately in DocBook.
 #
 # Example:
@@ -136,7 +135,7 @@ use strict;
 #  * user_function - function that can only be called in user context
 #  * @a: some argument
 #  * Context: !in_interrupt()
-#  * 
+#  *
 #  * Some description
 #  * Example:
 #  *    user_function(22);
@@ -173,14 +172,14 @@ my %highlights_html = ( $type_constant, "<i>\$1</i>",
                        $type_param, "<tt><b>\$1</b></tt>" );
 my $blankline_html = "<p>";
 
-# sgml, docbook format
-my %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
+# XML, docbook format
+my %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_sgml = "</para><para>\n";
+my $blankline_xml = "</para><para>\n";
 
 # gnome, docbook format
 my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
@@ -224,9 +223,9 @@ 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]] . 
+my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
+               'July', 'August', 'September', 'October',
+               'November', 'December')[(localtime)[4]] .
   " " . ((localtime)[5]+1900);
 
 # Essentially these are globals
@@ -237,7 +236,7 @@ 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 
+# 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
@@ -254,6 +253,7 @@ my $lineprefix="";
 # 3 - scanning prototype.
 # 4 - documentation block
 my $state;
+my $in_doc_sect;
 
 #declaration types: can be
 # 'function', 'struct', 'union', 'enum', 'typedef'
@@ -300,14 +300,14 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        %highlights = %highlights_text;
        $blankline = $blankline_text;
     } elsif ($cmd eq "-docbook") {
-       $output_mode = "sgml";
-       %highlights = %highlights_sgml;
-       $blankline = $blankline_sgml;
+       $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 sgml, inherits from calling document
+    } 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;
@@ -366,7 +366,7 @@ sub dump_section {
 #  parameterdescs => %parameter descriptions
 #  sectionlist => @list of sections
 #  sections => %descriont descriptions
-#  
+#
 
 sub output_highlight {
     my $contents = join "\n",@_;
@@ -401,7 +401,7 @@ sub output_section_html(%) {
        print "<blockquote>\n";
        output_highlight($args{'sections'}{$section});
        print "</blockquote>\n";
-    }  
+    }
 }
 
 # output enum in html
@@ -435,7 +435,7 @@ sub output_enum_html(%) {
     print "<hr>\n";
 }
 
-# output tyepdef in html
+# output typedef in html
 sub output_typedef_html(%) {
     my %args = %{$_[0]};
     my ($parameter);
@@ -455,7 +455,14 @@ sub output_struct_html(%) {
     print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
     print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       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
@@ -471,10 +478,15 @@ sub output_struct_html(%) {
     print "<h3>Members</h3>\n";
     print "<dl>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       ($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});
+       output_highlight($args{'parameterdescs'}{$parameter_name});
     }
     print "</dl>\n";
     output_section_html(@_);
@@ -510,10 +522,13 @@ sub output_function_html(%) {
     print "<h3>Arguments</h3>\n";
     print "<dl>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || 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});
+       output_highlight($args{'parameterdescs'}{$parameter_name});
     }
     print "</dl>\n";
     output_section_html(@_);
@@ -535,26 +550,31 @@ sub output_intro_html(%) {
     print "<hr>\n";
 }
 
-sub output_section_sgml(%) {
+sub output_section_xml(%) {
     my %args = %{$_[0]};
-    my $section;    
+    my $section;
     # print out each section
     $lineprefix="   ";
     foreach $section (@{$args{'sectionlist'}}) {
-       print "<refsect1>\n <title>$section</title>\n <para>\n";
+       print "<refsect1>\n";
+       print "<title>$section</title>\n";
        if ($section =~ m/EXAMPLE/i) {
-           print "<example><para>\n";
+           print "<informalexample><programlisting>\n";
+       } else {
+           print "<para>\n";
        }
        output_highlight($args{'sections'}{$section});
        if ($section =~ m/EXAMPLE/i) {
-           print "</para></example>\n";
+           print "</programlisting></informalexample>\n";
+       } else {
+           print "</para>\n";
        }
-       print " </para>\n</refsect1>\n";
+       print "</refsect1>\n";
     }
 }
 
-# output function in sgml DocBook
-sub output_function_sgml(%) {
+# output function in XML DocBook
+sub output_function_xml(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $count;
@@ -564,8 +584,14 @@ sub output_function_sgml(%) {
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'function'}."</refname>\n";
@@ -595,7 +621,7 @@ sub output_function_sgml(%) {
            }
        }
     } else {
-       print "  <void>\n";
+       print "  <void/>\n";
     }
     print "  </funcprototype></funcsynopsis>\n";
     print "</refsynopsisdiv>\n";
@@ -605,10 +631,13 @@ sub output_function_sgml(%) {
     if ($#{$args{'parameterlist'}} >= 0) {
        print " <variablelist>\n";
        foreach $parameter (@{$args{'parameterlist'}}) {
+           my $parameter_name = $parameter;
+           $parameter_name =~ s/\[.*//;
+
            print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
            print "   <listitem>\n    <para>\n";
            $lineprefix="     ";
-           output_highlight($args{'parameterdescs'}{$parameter});
+           output_highlight($args{'parameterdescs'}{$parameter_name});
            print "    </para>\n   </listitem>\n  </varlistentry>\n";
        }
        print " </variablelist>\n";
@@ -617,12 +646,12 @@ sub output_function_sgml(%) {
     }
     print "</refsect1>\n";
 
-    output_section_sgml(@_);
+    output_section_xml(@_);
     print "</refentry>\n\n";
 }
 
-# output struct in sgml DocBook
-sub output_struct_sgml(%) {
+# output struct in XML DocBook
+sub output_struct_xml(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $id;
@@ -631,8 +660,14 @@ sub output_struct_sgml(%) {
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
@@ -647,8 +682,16 @@ sub output_struct_sgml(%) {
     print "  <programlisting>\n";
     print $args{'type'}." ".$args{'struct'}." {\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-       defined($args{'parameterdescs'}{$parameter}) || next;
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       if ($parameter =~ /^#/) {
+           print "$parameter\n";
+           next;
+       }
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       defined($args{'parameterdescs'}{$parameter_name}) || next;
+        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
@@ -668,25 +711,30 @@ sub output_struct_sgml(%) {
 
     print "  <variablelist>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-      defined($args{'parameterdescs'}{$parameter}) || next;
-      ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+      ($parameter =~ /^#/) && next;
+
+      my $parameter_name = $parameter;
+      $parameter_name =~ s/\[.*//;
+
+      defined($args{'parameterdescs'}{$parameter_name}) || next;
+      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
       print "    <varlistentry>";
       print "      <term>$parameter</term>\n";
       print "      <listitem><para>\n";
-      output_highlight($args{'parameterdescs'}{$parameter});
+      output_highlight($args{'parameterdescs'}{$parameter_name});
       print "      </para></listitem>\n";
       print "    </varlistentry>\n";
     }
     print "  </variablelist>\n";
     print " </refsect1>\n";
 
-    output_section_sgml(@_);
+    output_section_xml(@_);
 
     print "</refentry>\n\n";
 }
 
-# output enum in sgml DocBook
-sub output_enum_sgml(%) {
+# output enum in XML DocBook
+sub output_enum_xml(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $count;
@@ -696,8 +744,14 @@ sub output_enum_sgml(%) {
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>enum ".$args{'enum'}."</refname>\n";
@@ -725,26 +779,29 @@ sub output_enum_sgml(%) {
     print "</refsynopsisdiv>\n";
 
     print "<refsect1>\n";
-    print " <title>Constants</title>\n";    
+    print " <title>Constants</title>\n";
     print "  <variablelist>\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
+      my $parameter_name = $parameter;
+      $parameter_name =~ s/\[.*//;
+
       print "    <varlistentry>";
       print "      <term>$parameter</term>\n";
       print "      <listitem><para>\n";
-      output_highlight($args{'parameterdescs'}{$parameter});
+      output_highlight($args{'parameterdescs'}{$parameter_name});
       print "      </para></listitem>\n";
       print "    </varlistentry>\n";
     }
     print "  </variablelist>\n";
     print "</refsect1>\n";
 
-    output_section_sgml(@_);
+    output_section_xml(@_);
 
     print "</refentry>\n\n";
 }
 
-# output typedef in sgml DocBook
-sub output_typedef_sgml(%) {
+# output typedef in XML DocBook
+sub output_typedef_xml(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $id;
@@ -753,8 +810,14 @@ sub output_typedef_sgml(%) {
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>typedef ".$args{'typedef'}."</refname>\n";
@@ -769,13 +832,13 @@ sub output_typedef_sgml(%) {
     print "  <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
     print "</refsynopsisdiv>\n";
 
-    output_section_sgml(@_);
+    output_section_xml(@_);
 
     print "</refentry>\n\n";
 }
 
-# output in sgml DocBook
-sub output_intro_sgml(%) {
+# output in XML DocBook
+sub output_intro_xml(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
     my $count;
@@ -800,7 +863,7 @@ sub output_intro_sgml(%) {
     print "\n\n";
 }
 
-# output in sgml DocBook
+# output in XML DocBook
 sub output_function_gnome {
     my %args = %{$_[0]};
     my ($parameter, $section);
@@ -842,10 +905,13 @@ sub output_function_gnome {
        print "<colspec colwidth=\"8*\">\n";
        print "<tbody>\n";
        foreach $parameter (@{$args{'parameterlist'}}) {
+           my $parameter_name = $parameter;
+           $parameter_name =~ s/\[.*//;
+
            print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
            print "   <entry>\n";
            $lineprefix="     ";
-           output_highlight($args{'parameterdescs'}{$parameter});
+           output_highlight($args{'parameterdescs'}{$parameter_name});
            print "    </entry></row>\n";
        }
        print " </tbody></tgroup></informaltable>\n";
@@ -909,8 +975,11 @@ sub output_function_man(%) {
 
     print ".SH ARGUMENTS\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
        print ".IP \"".$parameter."\" 12\n";
-       output_highlight($args{'parameterdescs'}{$parameter});
+       output_highlight($args{'parameterdescs'}{$parameter_name});
     }
     foreach $section (@{$args{'sectionlist'}}) {
        print ".SH \"", uc $section, "\"\n";
@@ -947,8 +1016,11 @@ sub output_enum_man(%) {
 
     print ".SH Constants\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
        print ".IP \"".$parameter."\" 12\n";
-       output_highlight($args{'parameterdescs'}{$parameter});
+       output_highlight($args{'parameterdescs'}{$parameter_name});
     }
     foreach $section (@{$args{'sectionlist'}}) {
        print ".SH \"$section\"\n";
@@ -968,17 +1040,24 @@ sub output_struct_man(%) {
     print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
 
     print ".SH SYNOPSIS\n";
-    print $args{'type'}." ".$args{'struct'}." {\n";
+    print $args{'type'}." ".$args{'struct'}." {\n.br\n";
 
     foreach my $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
-       print "\n.br\n";
+       if ($parameter =~ /^#/) {
+           print ".BI \"$parameter\"\n.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 ".BI \"    ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
-           print ".BI \"    ".$1."\" ".$parameter.$2." \""."\"\n;\n";
+           # bitfield
+           print ".BI \"    ".$1."\ \" ".$parameter.$2." \""."\"\n;\n";
        } else {
            $type =~ s/([^\*])$/$1 /;
            print ".BI \"    ".$type."\" ".$parameter." \""."\"\n;\n";
@@ -987,11 +1066,16 @@ sub output_struct_man(%) {
     }
     print "};\n.br\n";
 
-    print ".SH Arguments\n";
+    print ".SH Members\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       ($parameter =~ /^#/) && next;
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print ".IP \"".$parameter."\" 12\n";
-       output_highlight($args{'parameterdescs'}{$parameter});
+       output_highlight($args{'parameterdescs'}{$parameter_name});
     }
     foreach $section (@{$args{'sectionlist'}}) {
        print ".SH \"$section\"\n";
@@ -1035,7 +1119,10 @@ sub output_function_text(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
 
-    print "Function:\n\n";
+    print "Name:\n\n";
+    print $args{'function'}." - ".$args{'purpose'}."\n";
+
+    print "\nSynopsis:\n\n";
     my $start=$args{'functiontype'}." ".$args{'function'}." (";
     print $start;
     my $count = 0;
@@ -1058,7 +1145,10 @@ sub output_function_text(%) {
 
     print "Arguments:\n\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-       print $parameter."\n\t".$args{'parameterdescs'}{$parameter}."\n";
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n";
     }
     output_section_text(@_);
 }
@@ -1072,7 +1162,7 @@ sub output_section_text(%) {
     foreach $section (@{$args{'sectionlist'}}) {
        print "$section:\n\n";
        output_highlight($args{'sections'}{$section});
-    }  
+    }
     print "\n\n";
 }
 
@@ -1083,6 +1173,7 @@ sub output_enum_text(%) {
     my $count;
     print "Enum:\n\n";
 
+    print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n";
     print "enum ".$args{'enum'}." {\n";
     $count = 0;
     foreach $parameter (@{$args{'parameterlist'}}) {
@@ -1111,7 +1202,7 @@ sub output_typedef_text(%) {
     my $count;
     print "Typedef:\n\n";
 
-    print "typedef ".$args{'typedef'}."\n";
+    print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n";
     output_section_text(@_);
 }
 
@@ -1120,10 +1211,18 @@ sub output_struct_text(%) {
     my %args = %{$_[0]};
     my ($parameter);
 
-    print $args{'type'}." ".$args{'struct'}.":\n\n";
+    print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n";
     print $args{'type'}." ".$args{'struct'}." {\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       if ($parameter =~ /^#/) {
+           print "$parameter\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
@@ -1138,9 +1237,14 @@ sub output_struct_text(%) {
 
     print "Members:\n\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
-        ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+       ($parameter =~ /^#/) && next;
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        print "$parameter\n\t";
-       print $args{'parameterdescs'}{$parameter}."\n";
+       print $args{'parameterdescs'}{$parameter_name}."\n";
     }
     print "\n";
     output_section_text(@_);
@@ -1158,14 +1262,16 @@ sub output_intro_text(%) {
 }
 
 ##
-# generic output function for typedefs
+# generic output function for all types (function, struct/union, typedef, enum);
+# calls the generated, variable output_ function name based on
+# functype and output_mode
 sub output_declaration {
     no strict 'refs';
     my $name = shift;
     my $functype = shift;
     my $func = "output_${functype}_$output_mode";
-    if (($function_only==0) || 
-       ( $function_only == 1 && defined($function_table{$name})) || 
+    if (($function_only==0) ||
+       ( $function_only == 1 && defined($function_table{$name})) ||
        ( $function_only == 2 && !defined($function_table{$name})))
     {
         &$func(@_);
@@ -1174,8 +1280,7 @@ sub output_declaration {
 }
 
 ##
-# generic output function - calls the right one based
-# on current output mode.
+# generic output function - calls the right one based on current output mode.
 sub output_intro {
     no strict 'refs';
     my $func = "output_intro_".$output_mode;
@@ -1184,7 +1289,7 @@ sub output_intro {
 }
 
 ##
-# takes a declaration (struct, union, enum, typedef) and 
+# takes a declaration (struct, union, enum, typedef) and
 # invokes the right handler. NOT called for functions.
 sub dump_declaration($$) {
     no strict 'refs';
@@ -1208,6 +1313,12 @@ sub dump_struct($$) {
        # ignore embedded structs or unions
        $members =~ s/{.*?}//g;
 
+       # ignore members marked private:
+       $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
+       $members =~ s/\/\*.*?private:.*//gos;
+       # strip comments:
+       $members =~ s/\/\*.*?\*\///gos;
+
        create_parameterlist($members, ';', $file);
 
        output_declaration($declaration_name,
@@ -1233,6 +1344,7 @@ sub dump_enum($$) {
     my $x = shift;
     my $file = shift;
 
+    $x =~ s@/\*.*?\*/@@gos;    # strip comments.
     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
         $declaration_name = $1;
         my $members = $2;
@@ -1247,7 +1359,7 @@ sub dump_enum($$) {
            }
 
        }
-       
+
        output_declaration($declaration_name,
                           'enum',
                           {'enum' => $declaration_name,
@@ -1269,6 +1381,7 @@ sub dump_typedef($$) {
     my $x = shift;
     my $file = shift;
 
+    $x =~ s@/\*.*?\*/@@gos;    # strip comments.
     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
         $x =~ s/\(*.\)\s*;$/;/;
        $x =~ s/\[*.\]\s*;$/;/;
@@ -1299,10 +1412,11 @@ sub create_parameterlist($$$) {
     my $type;
     my $param;
 
+    # temporarily replace commas inside function pointer definition
     while ($args =~ /(\([^\),]+),/) {
         $args =~ s/(\([^\),]+),/$1#/g;
     }
-    
+
     foreach my $arg (split($splitter, $args)) {
        # strip comments
        $arg =~ s/\/\*.*\*\///;
@@ -1311,35 +1425,59 @@ sub create_parameterlist($$$) {
        $arg =~ s/\s*$//;
        $arg =~ s/\s+/ /;
 
-       if ($arg =~ m/\(/) {
+       if ($arg =~ /^#/) {
+           # Treat preprocessor directive as a typeless variable just to fill
+           # corresponding data structures "correctly". Catch it later in
+           # output_* subs.
+           push_parameter($arg, "", $file);
+       } elsif ($arg =~ m/\(.*\*/) {
            # pointer-to-function
            $arg =~ tr/#/,/;
            $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
            $param = $1;
            $type = $arg;
            $type =~ s/([^\(]+\(\*)$param/$1/;
-       } else {
-           # evil magic to get fixed array parameters to work
-           $arg =~ s/(.+\s+)(.+)\[.*/$1* $2/;
-           my @args = split('\s', $arg);
-       
-           $param = pop @args;
-           if ($param =~ m/^(\*+)(.*)/) {
-               $param = $2;
-               push @args, $1;
-           } 
-           elsif ($param =~ m/(.*?)\s*:\s*(\d+)/) {
-               $param = $1;
-               push @args, ":$2";
+           push_parameter($param, $type, $file);
+       } elsif ($arg) {
+           $arg =~ s/\s*:\s*/:/g;
+           $arg =~ s/\s*\[/\[/g;
+
+           my @args = split('\s*,\s*', $arg);
+           if ($args[0] =~ m/\*/) {
+               $args[0] =~ s/(\*+)\s*/ $1/;
+           }
+           my @first_arg = split('\s+', shift @args);
+           unshift(@args, pop @first_arg);
+           $type = join " ", @first_arg;
+
+           foreach $param (@args) {
+               if ($param =~ m/^(\*+)\s*(.*)/) {
+                   push_parameter($2, "$type $1", $file);
+               }
+               elsif ($param =~ m/(.*?):(\d+)/) {
+                   push_parameter($1, "$type:$2", $file)
+               }
+               else {
+                   push_parameter($param, $type, $file);
+               }
            }
-           $type = join " ", @args;
        }
+    }
+}
+
+sub push_parameter($$$) {
+       my $param = shift;
+       my $type = shift;
+       my $file = shift;
+       my $anon = 0;
+
+       my $param_name = $param;
+       $param_name =~ s/\[.*//;
 
-       if ($type eq "" && $param eq "...")
+       if ($type eq "" && $param =~ /\.\.\.$/)
        {
-           $type="...";
-           $param="...";
-           $parameterdescs{"..."} = "variable arguments";
+           $type="";
+           $parameterdescs{$param} = "variable arguments";
        }
        elsif ($type eq "" && ($param eq "" or $param eq "void"))
        {
@@ -1347,8 +1485,23 @@ sub create_parameterlist($$$) {
            $param="void";
            $parameterdescs{void} = "no arguments";
        }
-       if (defined $type && $type && !defined $parameterdescs{$param}) {
-           $parameterdescs{$param} = $undescribed;
+       elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
+       # handle unnamed (anonymous) union or struct:
+       {
+               $type = $param;
+               $param = "{unnamed_" . $param. "}";
+               $parameterdescs{$param} = "anonymous\n";
+               $anon = 1;
+       }
+
+       # warn if parameter has no description
+       # (but ignore ones starting with # as these are not parameters
+       # but inline preprocessor statements);
+       # also ignore unnamed structs/unions;
+       if (!$anon) {
+       if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
+
+           $parameterdescs{$param_name} = $undescribed;
 
            if (($type eq 'function') || ($type eq 'enum')) {
                print STDERR "Warning(${file}:$.): Function parameter ".
@@ -1359,10 +1512,10 @@ sub create_parameterlist($$$) {
                         " No description found for parameter '$param'\n";
            ++$warnings;
         }
+        }
 
        push @parameterlist, $param;
        $parametertypes{$param} = $type;
-    }
 }
 
 ##
@@ -1375,8 +1528,14 @@ sub dump_function($$) {
 
     $prototype =~ s/^static +//;
     $prototype =~ s/^extern +//;
+    $prototype =~ s/^fastcall +//;
+    $prototype =~ s/^asmlinkage +//;
     $prototype =~ s/^inline +//;
     $prototype =~ s/^__inline__ +//;
+    $prototype =~ s/^__inline +//;
+    $prototype =~ s/^__always_inline +//;
+    $prototype =~ s/^noinline +//;
+    $prototype =~ s/__devinit +//;
     $prototype =~ s/^#define +//; #ak added
     $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//;
 
@@ -1394,7 +1553,7 @@ sub dump_function($$) {
     # the following functions' documentation still comes out right:
     # - parport_register_device (function pointer parameters)
     # - atomic_set (macro)
-    # - pci_match_device (long return type)
+    # - pci_match_device, __copy_to_user (long return type)
 
     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
@@ -1409,7 +1568,9 @@ sub dump_function($$) {
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
-       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
        $return_type = $1;
        $declaration_name = $2;
        my $args = $3;
@@ -1421,7 +1582,7 @@ sub dump_function($$) {
        return;
     }
 
-    output_declaration($declaration_name, 
+    output_declaration($declaration_name,
                       'function',
                       {'function' => $declaration_name,
                        'module' => $modulename,
@@ -1480,21 +1641,21 @@ sub reset_state {
     %sections = ();
     @sectionlist = ();
     $prototype = "";
-    
+
     $state = 0;
 }
 
-sub process_state3_function($$) { 
+sub process_state3_function($$) {
     my $x = shift;
     my $file = shift;
 
-    if ($x =~ m#\s*/\*\s+MACDOC\s*#io) {
+    if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) {
        # do nothing
     }
     elsif ($x =~ /([^\{]*)/) {
         $prototype .= $1;
     }
-    if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) {
+    if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {
         $prototype =~ s@/\*.*?\*/@@gos;        # strip comments.
        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
        $prototype =~ s@^\s+@@gos; # strip leading spaces
@@ -1503,14 +1664,17 @@ sub process_state3_function($$) {
     }
 }
 
-sub process_state3_type($$) { 
+sub process_state3_type($$) {
     my $x = shift;
     my $file = shift;
 
-    $x =~ s@/\*.*?\*/@@gos;    # strip comments.
     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
     $x =~ s@^\s+@@gos; # strip leading spaces
     $x =~ s@\s+$@@gos; # strip trailing spaces
+    if ($x =~ /^#/) {
+       # To distinguish preprocessor directive from regular declaration later.
+       $x .= ";";
+    }
 
     while (1) {
         if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
@@ -1530,12 +1694,30 @@ sub process_state3_type($$) {
     }
 }
 
+# replace <, >, and &
+sub xml_escape($) {
+       my $text = shift;
+       if (($output_mode eq "text") || ($output_mode eq "man")) {
+               return $text;
+       }
+       $text =~ s/\&/\\\\\\amp;/g;
+       $text =~ s/\</\\\\\\lt;/g;
+       $text =~ s/\>/\\\\\\gt;/g;
+       return $text;
+}
+
 sub process_file($) {
-    my ($file) = @_;
+    my $file;
     my $identifier;
     my $func;
     my $initial_section_counter = $section_counter;
 
+    if (defined($ENV{'SRCTREE'})) {
+       $file = "$ENV{'SRCTREE'}" . "/" . "@_";
+    }
+    else {
+       $file = "@_";
+    }
     if (defined($source_map{$file})) {
        $file = $source_map{$file};
     }
@@ -1551,6 +1733,7 @@ sub process_file($) {
        if ($state == 0) {
            if (/$doc_start/o) {
                $state = 1;             # next line is always the function name
+               $in_doc_sect = 0;
            }
        } elsif ($state == 1) { # this line is the function name (always)
            if (/$doc_block/o) {
@@ -1570,7 +1753,7 @@ sub process_file($) {
 
                $state = 2;
                if (/-(.*)/) {
-                   $declaration_purpose = $1;
+                   $declaration_purpose = xml_escape($1);
                } else {
                    $declaration_purpose = "";
                }
@@ -1601,25 +1784,28 @@ sub process_file($) {
                $newcontents = $2;
 
                if ($contents ne "") {
-                   $contents =~ s/\&/\\\\\\amp;/g;
-                   $contents =~ s/\</\\\\\\lt;/g;
-                   $contents =~ s/\>/\\\\\\gt;/g;
-                   dump_section($section, $contents);
+                   if (!$in_doc_sect && $verbose) {
+                       print STDERR "Warning(${file}:$.): contents before sections\n";
+                       ++$warnings;
+                   }
+                   dump_section($section, xml_escape($contents));
                    $section = $section_default;
                }
 
+               $in_doc_sect = 1;
                $contents = $newcontents;
                if ($contents ne "") {
+                   while ((substr($contents, 0, 1) eq " ") ||
+                       substr($contents, 0, 1) eq "\t") {
+                           $contents = substr($contents, 1);
+                   }
                    $contents .= "\n";
                }
                $section = $newsection;
            } elsif (/$doc_end/) {
 
                if ($contents ne "") {
-                   $contents =~ s/\&/\\\\\\amp;/g;
-                   $contents =~ s/\</\\\\\\lt;/g;
-                   $contents =~ s/\>/\\\\\\gt;/g;
-                   dump_section($section, $contents);
+                   dump_section($section, xml_escape($contents));
                    $section = $section_default;
                    $contents = "";
                }
@@ -1627,16 +1813,13 @@ sub process_file($) {
                $prototype = "";
                $state = 3;
                $brcount = 0;
-#          print STDERR "end of doc comment, looking for prototype\n";
+#              print STDERR "end of doc comment, looking for prototype\n";
            } elsif (/$doc_content/) {
                # miguel-style comment kludge, look for blank lines after
                # @parameter line to signify start of description
-               if ($1 eq "" && 
+               if ($1 eq "" &&
                        ($section =~ m/^@/ || $section eq $section_context)) {
-                   $contents =~ s/\&/\\\\\\amp;/g;
-                   $contents =~ s/\</\\\\\\lt;/g;
-                   $contents =~ s/\>/\\\\\\gt;/g;
-                   dump_section($section, $contents);
+                   dump_section($section, xml_escape($contents));
                    $section = $section_default;
                    $contents = "";
                } else {
@@ -1644,10 +1827,10 @@ sub process_file($) {
                }
            } else {
                # i dont know - bad line?  ignore.
-               print STDERR "Warning(${file}:$.): bad line: $_"; 
+               print STDERR "Warning(${file}:$.): bad line: $_";
                ++$warnings;
            }
-       } elsif ($state == 3) { # scanning for function { (end of prototype)
+       } elsif ($state == 3) { # scanning for function '{' (end of prototype)
            if ($decl_type eq 'function') {
                process_state3_function($_, $file);
            } else {
@@ -1699,13 +1882,13 @@ sub process_file($) {
                        else
                        {
                                $contents .= $1 . "\n";
-                       }       
+                       }
                }
           }
     }
     if ($initial_section_counter == $section_counter) {
        print STDERR "Warning(${file}): no structured comments found\n";
-       if ($output_mode eq "sgml") {
+       if ($output_mode eq "xml") {
            # The template wants at least one RefEntry here; make one.
            print "<refentry>\n";
            print " <refnamediv>\n";