]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - scripts/kernel-doc
Merge tag 'pstore-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
[mirror_ubuntu-artful-kernel.git] / scripts / kernel-doc
index 659d529b99d8570a98384731d381e1dd447ed6bc..4f2e9049e8fa4219218b9ccc7ffd50d9558f1016 100755 (executable)
@@ -61,10 +61,10 @@ Output format selection (mutually exclusive):
 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.
+                        in any input FILE or -export-file FILE.
   -internal            Only output documentation for symbols that have NOT been
                        exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
-                       in the same FILE.
+                        in any input FILE or -export-file 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.
@@ -74,6 +74,11 @@ Output selection (mutually exclusive):
 
 Output selection modifiers:
   -no-doc-sections     Do not output DOC: sections.
+  -enable-lineno        Enable output of #define LINENO lines. Only works with
+                        reStructuredText format.
+  -export-file FILE     Specify an additional FILE in which to look for
+                        EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with
+                        -export or -internal. May be specified multiple times.
 
 Other parameters:
   -v                   Verbose output, more warnings and other information.
@@ -212,6 +217,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
@@ -280,10 +289,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";
@@ -309,6 +324,7 @@ my $verbose = 0;
 my $output_mode = "man";
 my $output_preformatted = 0;
 my $no_doc_sections = 0;
+my $enable_lineno = 0;
 my @highlights = @highlights_man;
 my $blankline = $blankline_man;
 my $modulename = "Kernel API";
@@ -323,6 +339,8 @@ use constant {
 my $output_selection = OUTPUT_ALL;
 my $show_not_found = 0;
 
+my @export_file_list;
+
 my @build_time;
 if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
     (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
@@ -341,6 +359,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
 # 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 $declaration_start_line;
 my ($type, $declaration_name, $return_type);
 my ($newsection, $newcontents, $prototype, $brcount, %source_map);
 
@@ -386,14 +405,14 @@ my $inline_doc_state;
 # '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]+):(.*)';
+# @params and a strictly limited set of supported section names
+my $doc_sect = $doc_com . 
+    '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)';
 my $doc_content = $doc_com_body . '(.*)';
 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
 my $doc_inline_start = '^\s*/\*\*\s*$';
@@ -401,15 +420,19 @@ 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 %parameterdesc_start_lines;
 my @parameterlist;
 my %sections;
 my @sectionlist;
+my %section_start_lines;
 my $sectcheck;
 my $struct_actual;
 
 my $contents = "";
+my $new_start_line = 0;
+
+# the canonical section names. see also $doc_sect above.
 my $section_default = "Description";   # default section
 my $section_intro = "Introduction";
 my $section = $section_default;
@@ -466,16 +489,21 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        $function_table{$function} = 1;
     } elsif ($cmd eq "-export") { # only exported symbols
        $output_selection = OUTPUT_EXPORTED;
-       %function_table = ()
+       %function_table = ();
     } elsif ($cmd eq "-internal") { # only non-exported symbols
        $output_selection = OUTPUT_INTERNAL;
-       %function_table = ()
+       %function_table = ();
+    } elsif ($cmd eq "-export-file") {
+       my $file = shift @ARGV;
+       push(@export_file_list, $file);
     } elsif ($cmd eq "-v") {
        $verbose = 1;
     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
        usage();
     } elsif ($cmd eq '-no-doc-sections') {
            $no_doc_sections = 1;
+    } elsif ($cmd eq '-enable-lineno') {
+           $enable_lineno = 1;
     } elsif ($cmd eq '-show-not-found') {
        $show_not_found = 1;
     }
@@ -493,6 +521,13 @@ sub get_kernel_version() {
     return $version;
 }
 
+#
+sub print_lineno {
+    my $lineno = shift;
+    if ($enable_lineno && defined($lineno)) {
+        print "#define LINENO " . $lineno . "\n";
+    }
+}
 ##
 # dumps section contents to arrays/hashes intended for that purpose.
 #
@@ -501,28 +536,32 @@ 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";
+    if ($name =~ m/$type_param/) {
        $name = $1;
        $parameterdescs{$name} = $contents;
        $sectcheck = $sectcheck . $name . " ";
+        $parameterdesc_start_lines{$name} = $new_start_line;
+        $new_start_line = 0;
     } elsif ($name eq "@\.\.\.") {
-#      print STDERR "parameter def '...' = '$contents'\n";
        $name = "...";
        $parameterdescs{$name} = $contents;
        $sectcheck = $sectcheck . $name . " ";
+        $parameterdesc_start_lines{$name} = $new_start_line;
+        $new_start_line = 0;
     } else {
-#      print STDERR "other section '$name' = '$contents'\n";
        if (defined($sections{$name}) && ($sections{$name} ne "")) {
-               print STDERR "${file}:$.: error: duplicate section name '$name'\n";
-               ++$errors;
+           # Only warn on user specified duplicate section names.
+           if ($name ne $section_default) {
+               print STDERR "${file}:$.: warning: duplicate section name '$name'\n";
+               ++$warnings;
+           }
+           $sections{$name} .= $contents;
+       } else {
+           $sections{$name} = $contents;
+           push @sectionlist, $name;
+            $section_start_lines{$name} = $new_start_line;
+            $new_start_line = 0;
        }
-       $sections{$name} = $contents;
-       push @sectionlist, $name;
     }
 }
 
@@ -1767,6 +1806,7 @@ sub output_blockhead_rst(%) {
        if ($output_selection != OUTPUT_INCLUDE) {
            print "**$section**\n\n";
        }
+        print_lineno($section_start_lines{$section});
        output_highlight_rst($args{'sections'}{$section});
        print "\n";
     }
@@ -1783,19 +1823,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:: ";
@@ -1813,6 +1848,10 @@ sub output_function_rst(%) {
        }
        $count++;
        $type = $args{'parametertypes'}{$parameter};
+
+       # RST doesn't like address_space tags at function prototypes
+       $type =~ s/__(user|kernel|iomem|percpu|pmem|rcu)\s*//;
+
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
            # pointer-to-function
            print $1 . $parameter . ") (" . $2;
@@ -1820,30 +1859,37 @@ sub output_function_rst(%) {
            print $type . " " . $parameter;
        }
     }
-    print ")\n\n    " . $args{'purpose'} . "\n\n";
+    print ")\n\n";
+    print_lineno($declaration_start_line);
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
-    print ":Parameters:\n\n";
+    print "**Parameters**\n\n";
+    $lineprefix = "  ";
     foreach $parameter (@{$args{'parameterlist'}}) {
        my $parameter_name = $parameter;
        #$parameter_name =~ s/\[.*//;
        $type = $args{'parametertypes'}{$parameter};
 
        if ($type ne "") {
-           print "      ``$type $parameter``\n";
+           print "``$type $parameter``\n";
        } else {
-           print "      ``$parameter``\n";
+           print "``$parameter``\n";
        }
+
+        print_lineno($parameterdesc_start_lines{$parameter_name});
+
        if (defined($args{'parameterdescs'}{$parameter_name}) &&
            $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
-           my $oldprefix = $lineprefix;
-           $lineprefix = "        ";
            output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-           $lineprefix = $oldprefix;
        } else {
-           print "\n        _undescribed_\n";
+           print "  *undescribed*\n";
        }
        print "\n";
     }
+
+    $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
 
@@ -1851,10 +1897,11 @@ sub output_section_rst(%) {
     my %args = %{$_[0]};
     my $section;
     my $oldprefix = $lineprefix;
-    $lineprefix = "        ";
+    $lineprefix = "";
 
     foreach $section (@{$args{'sectionlist'}}) {
-       print ":$section:\n\n";
+       print "**$section**\n\n";
+        print_lineno($section_start_lines{$section});
        output_highlight_rst($args{'sections'}{$section});
        print "\n";
     }
@@ -1865,24 +1912,28 @@ 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";
+    print_lineno($declaration_start_line);
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
-    print "..\n\n:Constants:\n\n";
-    my $oldprefix = $lineprefix;
-    $lineprefix = "    ";
+    print "**Constants**\n\n";
+    $lineprefix = "  ";
     foreach $parameter (@{$args{'parameterlist'}}) {
-       print "  `$parameter`\n";
+       print "``$parameter``\n";
        if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
            output_highlight_rst($args{'parameterdescs'}{$parameter});
        } else {
-           print "    undescribed\n";
+           print "  *undescribed*\n";
        }
        print "\n";
     }
+
     $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
@@ -1890,30 +1941,37 @@ 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";
+    print_lineno($declaration_start_line);
+    $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";
+    print_lineno($declaration_start_line);
+    $lineprefix = "   ";
+    output_highlight_rst($args{'purpose'});
+    print "\n";
 
-    print ":Definition:\n\n";
-    print " ::\n\n";
+    print "**Definition**\n\n";
+    print "::\n\n";
     print "  " . $args{'type'} . " " . $args{'struct'} . " {\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
        if ($parameter =~ /^#/) {
-           print "    " . "$parameter\n";
+           print "  " . "$parameter\n";
            next;
        }
 
@@ -1934,7 +1992,8 @@ sub output_struct_rst(%) {
     }
     print "  };\n\n";
 
-    print ":Members:\n\n";
+    print "**Members**\n\n";
+    $lineprefix = "  ";
     foreach $parameter (@{$args{'parameterlist'}}) {
        ($parameter =~ /^#/) && next;
 
@@ -1943,14 +2002,14 @@ sub output_struct_rst(%) {
 
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
        $type = $args{'parametertypes'}{$parameter};
-       print "      `$type $parameter`" . "\n";
-       my $oldprefix = $lineprefix;
-       $lineprefix = "        ";
+        print_lineno($parameterdesc_start_lines{$parameter_name});
+       print "``$type $parameter``\n";
        output_highlight_rst($args{'parameterdescs'}{$parameter_name});
-       $lineprefix = $oldprefix;
        print "\n";
     }
     print "\n";
+
+    $lineprefix = $oldprefix;
     output_section_rst(@_);
 }
 
@@ -2506,7 +2565,6 @@ sub dump_function($$) {
 
 sub reset_state {
     $function = "";
-    %constants = ();
     %parameterdescs = ();
     %parametertypes = ();
     @parameterlist = ();
@@ -2580,7 +2638,7 @@ sub syscall_munge() {
        }
 }
 
-sub process_state3_function($$) {
+sub process_proto_function($$) {
     my $x = shift;
     my $file = shift;
 
@@ -2610,7 +2668,7 @@ sub process_state3_function($$) {
     }
 }
 
-sub process_state3_type($$) {
+sub process_proto_type($$) {
     my $x = shift;
     my $file = shift;
 
@@ -2684,40 +2742,58 @@ sub local_unescape($) {
        return $text;
 }
 
-sub process_file($) {
+sub map_filename($) {
     my $file;
-    my $identifier;
-    my $func;
-    my $descr;
-    my $in_purpose = 0;
-    my $initial_section_counter = $section_counter;
     my ($orig_file) = @_;
 
     if (defined($ENV{'SRCTREE'})) {
        $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
-    }
-    else {
+    } else {
        $file = $orig_file;
     }
+
     if (defined($source_map{$file})) {
        $file = $source_map{$file};
     }
 
+    return $file;
+}
+
+sub process_export_file($) {
+    my ($orig_file) = @_;
+    my $file = map_filename($orig_file);
+
     if (!open(IN,"<$file")) {
        print STDERR "Error: Cannot open file $file\n";
        ++$errors;
        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;
-           }
+    while (<IN>) {
+       if (/$export_symbol/) {
+           $function_table{$2} = 1;
        }
-       seek(IN, 0, 0);
+    }
+
+    close(IN);
+}
+
+sub process_file($) {
+    my $file;
+    my $identifier;
+    my $func;
+    my $descr;
+    my $in_purpose = 0;
+    my $initial_section_counter = $section_counter;
+    my ($orig_file) = @_;
+    my $leading_space;
+
+    $file = map_filename($orig_file);
+
+    if (!open(IN,"<$file")) {
+       print STDERR "Error: Cannot open file $file\n";
+       ++$errors;
+       return;
     }
 
     $. = 1;
@@ -2731,11 +2807,14 @@ sub process_file($) {
            if (/$doc_start/o) {
                $state = STATE_NAME;    # next line is always the function name
                $in_doc_sect = 0;
+               $declaration_start_line = $. + 1;
            }
        } elsif ($state == STATE_NAME) {# this line is the function name (always)
            if (/$doc_block/o) {
                $state = STATE_DOCBLOCK;
                $contents = "";
+                $new_start_line = $. + 1;
+
                if ( $1 eq "" ) {
                        $section = $section_intro;
                } else {
@@ -2749,6 +2828,11 @@ sub process_file($) {
                }
 
                $state = STATE_FIELD;
+               # if there's no @param blocks need to set up default section
+               # here
+               $contents = "";
+               $section = $section_default;
+               $new_start_line = $. + 1;
                if (/-(.*)/) {
                    # strip leading/trailing/multiple spaces
                    $descr= $1;
@@ -2789,10 +2873,22 @@ sub process_file($) {
                $state = STATE_NORMAL;
            }
        } elsif ($state == STATE_FIELD) {       # look for head: lines, and include content
-           if (/$doc_sect/o) {
+           if (/$doc_sect/i) { # case insensitive for supported section names
                $newsection = $1;
                $newcontents = $2;
 
+               # map the supported section names to the canonical names
+               if ($newsection =~ m/^description$/i) {
+                   $newsection = $section_default;
+               } elsif ($newsection =~ m/^context$/i) {
+                   $newsection = $section_context;
+               } elsif ($newsection =~ m/^returns?$/i) {
+                   $newsection = $section_return;
+               } elsif ($newsection =~ m/^\@return$/) {
+                   # special: @return is a section, not a param description
+                   $newsection = $section_return;
+               }
+
                if (($contents ne "") && ($contents ne "\n")) {
                    if (!$in_doc_sect && $verbose) {
                        print STDERR "${file}:$.: warning: contents before sections\n";
@@ -2805,14 +2901,16 @@ sub process_file($) {
                $in_doc_sect = 1;
                $in_purpose = 0;
                $contents = $newcontents;
+                $new_start_line = $.;
+               while ((substr($contents, 0, 1) eq " ") ||
+                      substr($contents, 0, 1) eq "\t") {
+                   $contents = substr($contents, 1);
+               }
                if ($contents ne "") {
-                   while ((substr($contents, 0, 1) eq " ") ||
-                       substr($contents, 0, 1) eq "\t") {
-                           $contents = substr($contents, 1);
-                   }
                    $contents .= "\n";
                }
                $section = $newsection;
+               $leading_space = undef;
            } elsif (/$doc_end/) {
                if (($contents ne "") && ($contents ne "\n")) {
                    dump_section($file, $section, xml_escape($contents));
@@ -2837,6 +2935,7 @@ sub process_file($) {
                        dump_section($file, $section, xml_escape($contents));
                        $section = $section_default;
                        $contents = "";
+                        $new_start_line = $.;
                    } else {
                        $contents .= "\n";
                    }
@@ -2847,7 +2946,19 @@ sub process_file($) {
                    $declaration_purpose .= " " . xml_escape($1);
                    $declaration_purpose =~ s/\s+/ /g;
                } else {
-                   $contents .= $1 . "\n";
+                   my $cont = $1;
+                   if ($section =~ m/^@/ || $section eq $section_context) {
+                       if (!defined $leading_space) {
+                           if ($cont =~ m/^(\s+)/) {
+                               $leading_space = $1;
+                           } else {
+                               $leading_space = "";
+                           }
+                       }
+
+                       $cont =~ s/^$leading_space//;
+                   }
+                   $contents .= $cont . "\n";
                }
            } else {
                # i dont know - bad line?  ignore.
@@ -2859,12 +2970,13 @@ sub process_file($) {
            if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
                $section = $1;
                $contents = $2;
+                $new_start_line = $.;
                if ($contents ne "") {
                    while ((substr($contents, 0, 1) eq " ") ||
                           substr($contents, 0, 1) eq "\t") {
                        $contents = substr($contents, 1);
                    }
-               $contents .= "\n";
+                   $contents .= "\n";
                }
                $inline_doc_state = STATE_INLINE_TEXT;
            # Documentation block end */
@@ -2880,9 +2992,13 @@ sub process_file($) {
            } elsif (/$doc_content/) {
                if ($inline_doc_state == STATE_INLINE_TEXT) {
                    $contents .= $1 . "\n";
+                   # nuke leading blank lines
+                   if ($contents =~ /^\s*$/) {
+                       $contents = "";
+                   }
                } elsif ($inline_doc_state == STATE_INLINE_NAME) {
                    $inline_doc_state = STATE_INLINE_ERROR;
-                   print STDERR "Warning(${file}:$.): ";
+                   print STDERR "${file}:$.: warning: ";
                    print STDERR "Incorrect use of kernel-doc format: $_";
                    ++$warnings;
                }
@@ -2892,35 +3008,17 @@ sub process_file($) {
                $state = STATE_INLINE;
                $inline_doc_state = STATE_INLINE_NAME;
            } elsif ($decl_type eq 'function') {
-               process_state3_function($_, $file);
+               process_proto_function($_, $file);
            } else {
-               process_state3_type($_, $file);
+               process_proto_type($_, $file);
            }
        } elsif ($state == STATE_DOCBLOCK) {
-               # Documentation block
-               if (/$doc_block/) {
-                       dump_doc_section($file, $section, xml_escape($contents));
-                       $contents = "";
-                       $function = "";
-                       %constants = ();
-                       %parameterdescs = ();
-                       %parametertypes = ();
-                       @parameterlist = ();
-                       %sections = ();
-                       @sectionlist = ();
-                       $prototype = "";
-                       if ( $1 eq "" ) {
-                               $section = $section_intro;
-                       } else {
-                               $section = $1;
-                       }
-               }
-               elsif (/$doc_end/)
+               if (/$doc_end/)
                {
                        dump_doc_section($file, $section, xml_escape($contents));
+                       $section = $section_default;
                        $contents = "";
                        $function = "";
-                       %constants = ();
                        %parameterdescs = ();
                        %parametertypes = ();
                        @parameterlist = ();
@@ -3003,6 +3101,17 @@ if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
        close(SOURCE_MAP);
 }
 
+if ($output_selection == OUTPUT_EXPORTED ||
+    $output_selection == OUTPUT_INTERNAL) {
+
+    push(@export_file_list, @ARGV);
+
+    foreach (@export_file_list) {
+       chomp;
+       process_export_file($_);
+    }
+}
+
 foreach (@ARGV) {
     chomp;
     process_file($_);