]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - scripts/kernel-doc
kernel-doc/rst: blank lines in output are not needed
[karo-tx-linux.git] / scripts / kernel-doc
index 2fc8fad5195e8994a320013cd8c731a0d9469f63..a89ff3ca366ca505a73f92321057b28d79be4cae 100755 (executable)
@@ -59,6 +59,12 @@ Output format selection (mutually exclusive):
   -text                        Output plain text format.
 
 Output selection (mutually exclusive):
+  -export              Only output documentation for symbols that have been
+                       exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
+                       in the same FILE.
+  -internal            Only output documentation for symbols that have NOT been
+                       exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
+                       in the same FILE.
   -function NAME       Only output documentation for the given function(s)
                        or DOC: section title(s). All other functions and DOC:
                        sections are ignored. May be specified multiple times.
@@ -206,6 +212,10 @@ my $type_struct_xml = '\\&((struct\s*)*[_\w]+)';
 my $type_env = '(\$\w+)';
 my $type_enum_full = '\&(enum)\s*([_\w]+)';
 my $type_struct_full = '\&(struct)\s*([_\w]+)';
+my $type_typedef_full = '\&(typedef)\s*([_\w]+)';
+my $type_union_full = '\&(union)\s*([_\w]+)';
+my $type_member = '\&([_\w]+)((\.|->)[_\w]+)';
+my $type_member_func = $type_member . '\(\)';
 
 # Output conversion substitutions.
 #  One for each output format
@@ -274,10 +284,16 @@ my $blankline_text = "";
 # rst-mode
 my @highlights_rst = (
                        [$type_constant, "``\$1``"],
-                       [$type_func, "\\:c\\:func\\:`\$1`"],
+                       # Note: need to escape () to avoid func matching later
+                       [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"],
+                       [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"],
+                       [$type_func, "\\:c\\:func\\:`\$1()`"],
                        [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
                        [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
-                       [$type_struct, "\\:c\\:type\\:`struct \$1 <\$1>`"],
+                       [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
+                       [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
+                       # in rst this can refer to any type
+                       [$type_struct, "\\:c\\:type\\:`\$1`"],
                        [$type_param, "**\$1**"]
                      );
 my $blankline_rst = "\n";
@@ -306,7 +322,15 @@ my $no_doc_sections = 0;
 my @highlights = @highlights_man;
 my $blankline = $blankline_man;
 my $modulename = "Kernel API";
-my $function_only = 0;
+
+use constant {
+    OUTPUT_ALL          => 0, # output all symbols and doc sections
+    OUTPUT_INCLUDE      => 1, # output only specified symbols
+    OUTPUT_EXCLUDE      => 2, # output everything except specified symbols
+    OUTPUT_EXPORTED     => 3, # output exported symbols
+    OUTPUT_INTERNAL     => 4, # output non-exported symbols
+};
+my $output_selection = OUTPUT_ALL;
 my $show_not_found = 0;
 
 my @build_time;
@@ -344,44 +368,47 @@ my $section_counter = 0;
 
 my $lineprefix="";
 
-# states
-# 0 - normal code
-# 1 - looking for function name
-# 2 - scanning field start.
-# 3 - scanning prototype.
-# 4 - documentation block
-# 5 - gathering documentation outside main block
+# Parser states
+use constant {
+    STATE_NORMAL        => 0, # normal code
+    STATE_NAME          => 1, # looking for function name
+    STATE_FIELD         => 2, # scanning field start
+    STATE_PROTO         => 3, # scanning prototype
+    STATE_DOCBLOCK      => 4, # documentation block
+    STATE_INLINE        => 5, # gathering documentation outside main block
+};
 my $state;
 my $in_doc_sect;
 
-# Split Doc State
-# 0 - Invalid (Before start or after finish)
-# 1 - Is started (the /** was found inside a struct)
-# 2 - The @parameter header was found, start accepting multi paragraph text.
-# 3 - Finished (the */ was found)
-# 4 - Error - Comment without header was found. Spit a warning as it's not
-#     proper kernel-doc and ignore the rest.
-my $split_doc_state;
+# Inline documentation state
+use constant {
+    STATE_INLINE_NA     => 0, # not applicable ($state != STATE_INLINE)
+    STATE_INLINE_NAME   => 1, # looking for member name (@foo:)
+    STATE_INLINE_TEXT   => 2, # looking for member documentation
+    STATE_INLINE_END    => 3, # done
+    STATE_INLINE_ERROR  => 4, # error - Comment without header was found.
+                              # Spit a warning as it's not
+                              # proper kernel-doc and ignore the rest.
+};
+my $inline_doc_state;
 
 #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_com_body = '\s*\* ?';
 my $doc_decl = $doc_com . '(\w+)';
-my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
+my $doc_sect = $doc_com . '(\@?[\w\s]+):(.*)';
 my $doc_content = $doc_com_body . '(.*)';
 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
-my $doc_split_start = '^\s*/\*\*\s*$';
-my $doc_split_sect = '\s*\*\s*(@[\w\s]+):(.*)';
-my $doc_split_end = '^\s*\*/\s*$';
+my $doc_inline_start = '^\s*/\*\*\s*$';
+my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
+my $doc_inline_end = '^\s*\*/\s*$';
+my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
 
-my %constants;
 my %parameterdescs;
 my @parameterlist;
 my %sections;
@@ -437,13 +464,19 @@ while ($ARGV[0] =~ m/^-(.*)/) {
     } 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;
+       $output_selection = OUTPUT_INCLUDE;
        $function = shift @ARGV;
        $function_table{$function} = 1;
-    } elsif ($cmd eq "-nofunction") { # to only output specific functions
-       $function_only = 2;
+    } elsif ($cmd eq "-nofunction") { # output all except specific functions
+       $output_selection = OUTPUT_EXCLUDE;
        $function = shift @ARGV;
        $function_table{$function} = 1;
+    } elsif ($cmd eq "-export") { # only exported symbols
+       $output_selection = OUTPUT_EXPORTED;
+       %function_table = ()
+    } elsif ($cmd eq "-internal") { # only non-exported symbols
+       $output_selection = OUTPUT_INTERNAL;
+       %function_table = ()
     } elsif ($cmd eq "-v") {
        $verbose = 1;
     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
@@ -475,11 +508,7 @@ 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/) {
+    if ($name =~ m/$type_param/) {
 #      print STDERR "parameter def '$1' = '$contents'\n";
        $name = $1;
        $parameterdescs{$name} = $contents;
@@ -512,15 +541,17 @@ sub dump_doc_section {
         return;
     }
 
-    if (($function_only == 0) ||
-       ( $function_only == 1 && defined($function_table{$name})) ||
-       ( $function_only == 2 && !defined($function_table{$name})))
+    if (($output_selection == OUTPUT_ALL) ||
+       ($output_selection == OUTPUT_INCLUDE &&
+        defined($function_table{$name})) ||
+       ($output_selection == OUTPUT_EXCLUDE &&
+        !defined($function_table{$name})))
     {
        dump_section($file, $name, $contents);
        output_blockhead({'sectionlist' => \@sectionlist,
                          'sections' => \%sections,
                          'module' => $modulename,
-                         'content-only' => ($function_only != 0), });
+                         'content-only' => ($output_selection != OUTPUT_ALL), });
     }
 }
 
@@ -1736,7 +1767,9 @@ sub output_blockhead_rst(%) {
     my ($parameter, $section);
 
     foreach $section (@{$args{'sectionlist'}}) {
-       print "**$section**\n\n";
+       if ($output_selection != OUTPUT_INCLUDE) {
+           print "**$section**\n\n";
+       }
        output_highlight_rst($args{'sections'}{$section});
        print "\n";
     }
@@ -1753,19 +1786,14 @@ sub output_highlight_rst {
     die $@ if $@;
 
     foreach $line (split "\n", $contents) {
-       if ($line eq "") {
-           print $lineprefix, $blankline;
-       } else {
-           $line =~ s/\\\\\\/\&/g;
-           print $lineprefix, $line;
-       }
-       print "\n";
+       print $lineprefix . $line . "\n";
     }
 }
 
 sub output_function_rst(%) {
     my %args = %{$_[0]};
     my ($parameter, $section);
+    my $oldprefix = $lineprefix;
     my $start;
 
     print ".. c:function:: ";
@@ -1790,9 +1818,13 @@ sub output_function_rst(%) {
            print $type . " " . $parameter;
        }
     }
-    print ")\n\n    " . $args{'purpose'} . "\n\n";
+    print ")\n\n";
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
     print ":Parameters:\n\n";
+    $lineprefix = "        ";
     foreach $parameter (@{$args{'parameterlist'}}) {
        my $parameter_name = $parameter;
        #$parameter_name =~ s/\[.*//;
@@ -1803,16 +1835,16 @@ sub output_function_rst(%) {
        } else {
            print "      ``$parameter``\n";
        }
-       if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) {
-           my $oldprefix = $lineprefix;
-           $lineprefix = "        ";
+       if (defined($args{'parameterdescs'}{$parameter_name}) &&
+           $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
            output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-           $lineprefix = $oldprefix;
        } else {
            print "\n        _undescribed_\n";
        }
        print "\n";
     }
+
+    $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
 
@@ -1834,14 +1866,16 @@ sub output_section_rst(%) {
 sub output_enum_rst(%) {
     my %args = %{$_[0]};
     my ($parameter);
+    my $oldprefix = $lineprefix;
     my $count;
     my $name = "enum " . $args{'enum'};
 
     print "\n\n.. c:type:: " . $name . "\n\n";
-    print "    " . $args{'purpose'} . "\n\n";
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
     print "..\n\n:Constants:\n\n";
-    my $oldprefix = $lineprefix;
     $lineprefix = "    ";
     foreach $parameter (@{$args{'parameterlist'}}) {
        print "  `$parameter`\n";
@@ -1852,6 +1886,7 @@ sub output_enum_rst(%) {
        }
        print "\n";
     }
+
     $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
@@ -1859,23 +1894,29 @@ sub output_enum_rst(%) {
 sub output_typedef_rst(%) {
     my %args = %{$_[0]};
     my ($parameter);
-    my $count;
+    my $oldprefix = $lineprefix;
     my $name = "typedef " . $args{'typedef'};
 
     ### FIXME: should the name below contain "typedef" or not?
     print "\n\n.. c:type:: " . $name . "\n\n";
-    print "    " . $args{'purpose'} . "\n\n";
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
+    $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
 
 sub output_struct_rst(%) {
     my %args = %{$_[0]};
     my ($parameter);
+    my $oldprefix = $lineprefix;
     my $name = $args{'type'} . " " . $args{'struct'};
 
     print "\n\n.. c:type:: " . $name . "\n\n";
-    print "    " . $args{'purpose'} . "\n\n";
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
     print ":Definition:\n\n";
     print " ::\n\n";
@@ -1904,6 +1945,7 @@ sub output_struct_rst(%) {
     print "  };\n\n";
 
     print ":Members:\n\n";
+    $lineprefix = "        ";
     foreach $parameter (@{$args{'parameterlist'}}) {
        ($parameter =~ /^#/) && next;
 
@@ -1913,13 +1955,12 @@ sub output_struct_rst(%) {
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
        print "      `$type $parameter`" . "\n";
-       my $oldprefix = $lineprefix;
-       $lineprefix = "        ";
        output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-       $lineprefix = $oldprefix;
        print "\n";
     }
     print "\n";
+
+    $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
 
@@ -1969,9 +2010,13 @@ sub output_declaration {
     my $name = shift;
     my $functype = shift;
     my $func = "output_${functype}_$output_mode";
-    if (($function_only==0) ||
-       ( $function_only == 1 && defined($function_table{$name})) ||
-       ( $function_only == 2 && !($functype eq "function" && defined($function_table{$name}))))
+    if (($output_selection == OUTPUT_ALL) ||
+       (($output_selection == OUTPUT_INCLUDE ||
+         $output_selection == OUTPUT_EXPORTED) &&
+        defined($function_table{$name})) ||
+       (($output_selection == OUTPUT_EXCLUDE ||
+         $output_selection == OUTPUT_INTERNAL) &&
+        !($functype eq "function" && defined($function_table{$name}))))
     {
        &$func(@_);
        $section_counter++;
@@ -2471,7 +2516,6 @@ sub dump_function($$) {
 
 sub reset_state {
     $function = "";
-    %constants = ();
     %parameterdescs = ();
     %parametertypes = ();
     @parameterlist = ();
@@ -2481,8 +2525,8 @@ sub reset_state {
     $struct_actual = "";
     $prototype = "";
 
-    $state = 0;
-    $split_doc_state = 0;
+    $state = STATE_NORMAL;
+    $inline_doc_state = STATE_INLINE_NA;
 }
 
 sub tracepoint_munge($) {
@@ -2674,6 +2718,17 @@ sub process_file($) {
        return;
     }
 
+    # two passes for -export and -internal
+    if ($output_selection == OUTPUT_EXPORTED ||
+       $output_selection == OUTPUT_INTERNAL) {
+       while (<IN>) {
+           if (/$export_symbol/o) {
+               $function_table{$2} = 1;
+           }
+       }
+       seek(IN, 0, 0);
+    }
+
     $. = 1;
 
     $section_counter = 0;
@@ -2681,14 +2736,14 @@ sub process_file($) {
        while (s/\\\s*$//) {
            $_ .= <IN>;
        }
-       if ($state == 0) {
+       if ($state == STATE_NORMAL) {
            if (/$doc_start/o) {
-               $state = 1;             # next line is always the function name
+               $state = STATE_NAME;    # next line is always the function name
                $in_doc_sect = 0;
            }
-       } elsif ($state == 1) { # this line is the function name (always)
+       } elsif ($state == STATE_NAME) {# this line is the function name (always)
            if (/$doc_block/o) {
-               $state = 4;
+               $state = STATE_DOCBLOCK;
                $contents = "";
                if ( $1 eq "" ) {
                        $section = $section_intro;
@@ -2702,7 +2757,7 @@ sub process_file($) {
                    $identifier = $1;
                }
 
-               $state = 2;
+               $state = STATE_FIELD;
                if (/-(.*)/) {
                    # strip leading/trailing/multiple spaces
                    $descr= $1;
@@ -2740,9 +2795,9 @@ sub process_file($) {
                print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
                " - I thought it was a doc line\n";
                ++$warnings;
-               $state = 0;
+               $state = STATE_NORMAL;
            }
-       } elsif ($state == 2) { # look for head: lines, and include content
+       } elsif ($state == STATE_FIELD) {       # look for head: lines, and include content
            if (/$doc_sect/o) {
                $newsection = $1;
                $newcontents = $2;
@@ -2780,7 +2835,7 @@ sub process_file($) {
                }
 
                $prototype = "";
-               $state = 3;
+               $state = STATE_PROTO;
                $brcount = 0;
 #              print STDERR "end of doc comment, looking for prototype\n";
            } elsif (/$doc_content/) {
@@ -2808,9 +2863,9 @@ sub process_file($) {
                print STDERR "${file}:$.: warning: bad line: $_";
                ++$warnings;
            }
-       } elsif ($state == 5) { # scanning for split parameters
+       } elsif ($state == STATE_INLINE) { # scanning for inline parameters
            # First line (state 1) needs to be a @parameter
-           if ($split_doc_state == 1 && /$doc_split_sect/o) {
+           if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
                $section = $1;
                $contents = $2;
                if ($contents ne "") {
@@ -2818,45 +2873,44 @@ sub process_file($) {
                           substr($contents, 0, 1) eq "\t") {
                        $contents = substr($contents, 1);
                    }
-               $contents .= "\n";
+                   $contents .= "\n";
                }
-               $split_doc_state = 2;
+               $inline_doc_state = STATE_INLINE_TEXT;
            # Documentation block end */
-           } elsif (/$doc_split_end/) {
+           } elsif (/$doc_inline_end/) {
                if (($contents ne "") && ($contents ne "\n")) {
                    dump_section($file, $section, xml_escape($contents));
                    $section = $section_default;
                    $contents = "";
                }
-               $state = 3;
-               $split_doc_state = 0;
+               $state = STATE_PROTO;
+               $inline_doc_state = STATE_INLINE_NA;
            # Regular text
            } elsif (/$doc_content/) {
-               if ($split_doc_state == 2) {
+               if ($inline_doc_state == STATE_INLINE_TEXT) {
                    $contents .= $1 . "\n";
-               } elsif ($split_doc_state == 1) {
-                   $split_doc_state = 4;
+               } elsif ($inline_doc_state == STATE_INLINE_NAME) {
+                   $inline_doc_state = STATE_INLINE_ERROR;
                    print STDERR "Warning(${file}:$.): ";
                    print STDERR "Incorrect use of kernel-doc format: $_";
                    ++$warnings;
                }
            }
-       } elsif ($state == 3) { # scanning for function '{' (end of prototype)
-           if (/$doc_split_start/) {
-               $state = 5;
-               $split_doc_state = 1;
+       } elsif ($state == STATE_PROTO) {       # scanning for function '{' (end of prototype)
+           if (/$doc_inline_start/) {
+               $state = STATE_INLINE;
+               $inline_doc_state = STATE_INLINE_NAME;
            } elsif ($decl_type eq 'function') {
                process_state3_function($_, $file);
            } else {
                process_state3_type($_, $file);
            }
-       } elsif ($state == 4) {
+       } elsif ($state == STATE_DOCBLOCK) {
                # Documentation block
                if (/$doc_block/) {
                        dump_doc_section($file, $section, xml_escape($contents));
                        $contents = "";
                        $function = "";
-                       %constants = ();
                        %parameterdescs = ();
                        %parametertypes = ();
                        @parameterlist = ();
@@ -2874,14 +2928,13 @@ sub process_file($) {
                        dump_doc_section($file, $section, xml_escape($contents));
                        $contents = "";
                        $function = "";
-                       %constants = ();
                        %parameterdescs = ();
                        %parametertypes = ();
                        @parameterlist = ();
                        %sections = ();
                        @sectionlist = ();
                        $prototype = "";
-                       $state = 0;
+                       $state = STATE_NORMAL;
                }
                elsif (/$doc_content/)
                {
@@ -2898,7 +2951,7 @@ sub process_file($) {
     }
     if ($initial_section_counter == $section_counter) {
        print STDERR "${file}:1: warning: no structured comments found\n";
-       if (($function_only == 1) && ($show_not_found == 1)) {
+       if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
            print STDERR "    Was looking for '$_'.\n" for keys %function_table;
        }
        if ($output_mode eq "xml") {