This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
msgrcv: properly downgrade the receive buffer
[perl5.git] / autodoc.pl
index 27c5b9e..64491e7 100644 (file)
@@ -24,15 +24,21 @@ use Text::Tabs;
 # Throughout the files read by this script are lines like
 #
 # =for apidoc_section Section Name
+# =for apidoc_section $section_name_variable
 #
 # "Section Name" (after having been stripped of leading space) must be one of
-# the legal section names, or an error is thrown.  All API elements defined
-# between this line and the next 'apidoc_section' line will go into the
-# section "Section Name", sorted by dictionary order within it.  perlintern
-# and perlapi are parallel documents, each potentially with a section "Section
-# Name".  Each element is marked as to which document it goes into.  If there
-# are none for a particular section in perlapi, that section is
-# omitted.
+# the legal section names, or an error is thrown.  $section_name_variable must
+# be one of the legal section name variables defined below; these expand to
+# legal section names.  This form is used so that minor wording changes in
+# these titles can be confied to this file.  All the names of the variables
+# end in '_scn'; this suffix is optional in the apidoc_section lines.
+#
+# All API elements defined between this line and the next 'apidoc_section'
+# line will go into the section "Section Name" (or $section_name_variable),
+# sorted by dictionary order within it.  perlintern and perlapi are parallel
+# documents, each potentially with a section "Section Name".  Each element is
+# marked as to which document it goes into.  If there are none for a
+# particular section in perlapi, that section is omitted.
 #
 # Also, in .[ch] files, there may be
 #
@@ -44,7 +50,7 @@ use Text::Tabs;
 # are used as a heading for section "Section Name" (in both perlintern and
 # perlapi).  This includes any =head[2-5].  If more than one '=head1 Section
 # Name' line has content, they appear in the generated pod in an undefined
-# order.
+# order.  Note that you can't use a $section_name_variable in =head1 lines
 #
 # The next =head1, =for apidoc_section, or file end terminates what goes into
 # the current section
@@ -92,7 +98,7 @@ my $link_text = "Described in";
 my $description_indent = 4;
 my $usage_indent = 3;   # + initial blank yields 4 total
 
-my $av_scn = 'AV Handling';
+my $AV_scn = 'AV Handling';
 my $callback_scn = 'Callback Functions';
 my $casting_scn = 'Casting';
 my $casing_scn = 'Character case changing';
@@ -105,7 +111,8 @@ my $concurrency_scn = 'Concurrency';
 my $COP_scn = 'COP Hint Hashes';
 my $CV_scn = 'CV Handling';
 my $custom_scn = 'Custom Operators';
-my $dump_scn = 'Display and Dump functions';
+my $debugging_scn = 'Debugging';
+my $display_scn = 'Display functions';
 my $embedding_scn = 'Embedding and Interpreter Cloning';
 my $errno_scn = 'Errno';
 my $exceptions_scn = 'Exception Handling (simple) Macros';
@@ -120,10 +127,10 @@ my $HV_scn = 'HV Handling';
 my $io_scn = 'Input/Output';
 my $integer_scn = 'Integer configuration values';
 my $lexer_scn = 'Lexer interface';
-my $locales_scn = 'Locales';
+my $locale_scn = 'Locales';
 my $magic_scn = 'Magic';
 my $memory_scn = 'Memory Management';
-my $mro_scn = 'MRO';
+my $MRO_scn = 'MRO';
 my $multicall_scn = 'Multicall Functions';
 my $numeric_scn = 'Numeric Functions';
 my $optree_construction_scn = 'Optree construction';
@@ -149,10 +156,13 @@ my $unicode_scn = 'Unicode Support';
 my $utility_scn = 'Utility Functions';
 my $versioning_scn = 'Versioning';
 my $warning_scn = 'Warning and Dieing';
-my $xs_scn = 'XS';
+my $XS_scn = 'XS';
+
+# Kept separate at end
+my $undocumented_scn = 'Undocumented elements';
 
 my %valid_sections = (
-    $av_scn => {},
+    $AV_scn => {},
     $callback_scn => {},
     $casting_scn => {},
     $casing_scn => {},
@@ -162,9 +172,17 @@ my %valid_sections = (
     $directives_scn => {},
     $concurrency_scn => {},
     $COP_scn => {},
-    $CV_scn => {},
+    $CV_scn => {
+        header => <<~'EOT',
+            This section documents functions to manipulate CVs which are
+            code-values, meaning subroutines.  For more information, see
+            L<perlguts>.
+            EOT
+    },
+
     $custom_scn => {},
-    $dump_scn => {},
+    $debugging_scn => {},
+    $display_scn => {},
     $embedding_scn => {},
     $errno_scn => {},
     $exceptions_scn => {},
@@ -271,10 +289,10 @@ my %valid_sections = (
     $io_scn => {},
     $integer_scn => {},
     $lexer_scn => {},
-    $locales_scn => {},
+    $locale_scn => {},
     $magic_scn => {},
     $memory_scn => {},
-    $mro_scn => {},
+    $MRO_scn => {},
     $multicall_scn => {},
     $numeric_scn => {},
     $optree_construction_scn => {},
@@ -298,19 +316,29 @@ my %valid_sections = (
     $filters_scn => {},
     $stack_scn => {},
     $string_scn => {
-        header => <<~'EOT',
-            See also C<L</Unicode Support>>.
+        header => <<~EOT,
+            See also C<L</$unicode_scn>>.
             EOT
       },
     $SV_flags_scn => {},
     $SV_scn => {},
     $time_scn => {},
     $typedefs_scn => {},
-    $unicode_scn => {},
+    $unicode_scn => {
+        header => <<~EOT,
+            L<perlguts/Unicode Support> has an introduction to this API.
+
+            See also C<L</$classification_scn>>,
+            C<L</$casing_scn>>,
+            and C<L</$string_scn>>.
+            Various functions outside this section also work specially with
+            Unicode.  Search for the string "utf8" in this document.
+            EOT
+      },
     $utility_scn => {},
     $versioning_scn => {},
     $warning_scn => {},
-    $xs_scn => {},
+    $XS_scn => {},
 );
 
 # Somewhat loose match for an apidoc line so we can catch minor typos.
@@ -376,10 +404,49 @@ sub embed_override($) {
     return ($flags, $embed_docref->{'ret_type'}, $embed_docref->{args}->@*);
 }
 
+# The section that is in effect at the beginning of the given file.  If not
+# listed here, an apidoc_section line must precede any apidoc lines.
+# This allows the files listed here that generally are single-purpose, to not
+# have to worry about the autodoc section
+my %initial_file_section = (
+                            'av.c' => $AV_scn,
+                            'av.h' => $AV_scn,
+                            'cv.h' => $CV_scn,
+                            'doio.c' => $io_scn,
+                            'gv.c' => $GV_scn,
+                            'gv.h' => $GV_scn,
+                            'hv.h' => $HV_scn,
+                            'locale.c' => $locale_scn,
+                            'malloc.c' => $memory_scn,
+                            'numeric.c' => $numeric_scn,
+                            'opnames.h' => $optree_construction_scn,
+                            'pad.h'=> $pad_scn,
+                            'patchlevel.h' => $versioning_scn,
+                            'perlio.h' => $io_scn,
+                            'pod/perlapio.pod' => $io_scn,
+                            'pod/perlcall.pod' => $callback_scn,
+                            'pod/perlembed.pod' => $embedding_scn,
+                            'pod/perlfilter.pod' => $filters_scn,
+                            'pod/perliol.pod' => $io_scn,
+                            'pod/perlmroapi.pod' => $MRO_scn,
+                            'pod/perlreguts.pod' => $regexp_scn,
+                            'pp_pack.c' => $pack_scn,
+                            'pp_sort.c' => $SV_scn,
+                            'regcomp.c' => $regexp_scn,
+                            'regexp.h' => $regexp_scn,
+                            'unicode_constants.h' => $unicode_scn,
+                            'utf8.c' => $unicode_scn,
+                            'utf8.h' => $unicode_scn,
+                            'vutil.c' => $versioning_scn,
+                           );
+
 sub autodoc ($$) { # parse a file and extract documentation info
     my($fh,$file) = @_;
     my($in, $line_num, $header, $section);
 
+    $section = $initial_file_section{$file}
+                                    if defined $initial_file_section{$file};
+
     my $file_is_C = $file =~ / \. [ch] $ /x;
 
     # Count lines easier
@@ -404,6 +471,11 @@ sub autodoc ($$) { # parse a file and extract documentation info
         if ($in=~ /^ = (?: for [ ]+ apidoc_section | head1 ) [ ]+ (.*) /x) {
 
             $section = $1;
+            if ($section =~ / ^ \$ /x) {
+                $section .= '_scn' unless $section =~ / _scn $ /;
+                $section = eval "$section";
+                die "Unknown \$section variable '$section' in $file: $@" if $@;
+            }
             die "Unknown section name '$section' in $file near line $.\n"
                                     unless defined $valid_sections{$section};
 
@@ -963,7 +1035,7 @@ sub parse_config_h {
                 $configs{$name}{'section'} = $formats_scn;
             }
             elsif ($name =~ / BACKTRACE /x) {
-                $configs{$name}{'section'} = $dump_scn;
+                $configs{$name}{'section'} = $debugging_scn;
             }
             elsif ($name =~ / ALLOC $sb /x) {
                 $configs{$name}{'section'} = $memory_scn;
@@ -1000,7 +1072,7 @@ sub parse_config_h {
                 $configs{$name}{'section'} = $paths_scn;
             }
             elsif ($name =~ / $sb LC_ | LOCALE | langinfo /xi) {
-                $configs{$name}{'section'} = $locales_scn;
+                $configs{$name}{'section'} = $locale_scn;
             }
             elsif ($configs{$name}{pod} =~ /  GCC | C99 | C\+\+ /xi) {
                 $configs{$name}{'section'} = $compiler_scn;
@@ -1095,6 +1167,33 @@ sub parse_config_h {
     }
 }
 
+sub format_pod_indexes($) {
+    my $entries_ref = shift;
+
+    # Output the X<> references to the names, packed since they don't get
+    # displayed, but not too many per line so that when someone is editing the
+    # file, it doesn't run on
+
+    my $text ="";
+    my $line_length = 0;
+    for my $name (sort dictionary_order $entries_ref->@*) {
+        my $entry = "X<$name>";
+        my $entry_length = length $entry;
+
+        # Don't loop forever if we have a verrry long name, and don't go too
+        # far to the right.
+        if ($line_length > 0 && $line_length + $entry_length > $max_width) {
+            $text .= "\n";
+            $line_length = 0;
+        }
+
+        $text .= $entry;
+        $line_length += $entry_length;
+    }
+
+    return $text;
+}
+
 sub docout ($$$) { # output the docs for one function
     my($fh, $element_name, $docref) = @_;
 
@@ -1227,6 +1326,9 @@ sub docout ($$$) { # output the docs for one function
             my $name_indent = $indent + $longest_ret;
             $name_indent += $ret_name_sep_length if $longest_ret;
 
+            my $this_max_width =
+                               $max_width - $description_indent - $usage_indent;
+
             for my $item (@items) {
                 my $ret_type = $item->{ret_type};
                 my @args = $item->{args}->@*;
@@ -1280,7 +1382,7 @@ sub docout ($$$) { # output the docs for one function
                         #                                    short2,
                         #                                    very_long_argument,
                         #                                    short3)
-                        if ($total_length > $max_width) {
+                        if ($total_length > $this_max_width) {
 
                             # If this is the first continuation line,
                             # calculate the longest argument; this will be the
@@ -1309,9 +1411,10 @@ sub docout ($$$) { # output the docs for one function
                                 }
 
                                 # Calculate the new indent if necessary.
-                                $arg_indent = $max_width - $longest_arg_length
+                                $arg_indent =
+                                        $this_max_width - $longest_arg_length
                                         if $arg_indent + $longest_arg_length
-                                                                > $max_width;
+                                                            > $this_max_width;
                             }
 
                             print $fh "\n", (" " x $arg_indent);
@@ -1352,7 +1455,7 @@ sub construct_missings_section {
 
     $text .= <<~EOT;
 
-        =head1 Undocumented functions
+        =head1 $undocumented_scn
 
         EOT
     if ($pod_name eq 'perlapi') {
@@ -1382,29 +1485,13 @@ sub construct_missings_section {
             EOT
     }
 
-    $text .= "\n";
+    $text .= "\n" . format_pod_indexes($missings_ref);
 
     # Sort the elements.
     my @missings = sort dictionary_order $missings_ref->@*;
 
-    # Output the X<> references to the names, packed since they don't get
-    # displayed, but not too many per line so that when someone is editing the
-    # file, it doesn't run on
-    my $line_length = 0;
-    for my $missing (sort dictionary_order @missings) {
-        my $entry = "X<$missing>";
-        my $entry_length = length $entry;
-
-        # Don't loop forever if we have a verrry long name, and don't go too
-        # far to the right.
-        if ($line_length > 0 && $line_length + $entry_length > $max_width) {
-            $text .= "\n";
-            $line_length = 0;
-        }
 
-        $text .= $entry;
-        $line_length += $entry_length;
-    }
+    $text .= "\n";
 
     use integer;
 
@@ -1548,8 +1635,7 @@ sub output {
             }
         }
 
-
-        if ($section_info) {
+        if ($section_info && keys $section_info->%*) {
             for my $function_name (sort dictionary_order keys %$section_info) {
                 docout($fh, $function_name, $section_info->{$function_name});
             }
@@ -1618,8 +1704,11 @@ my @missing_api = grep $funcflags{$_}{flags} =~ /A/
                     && !$docs{api}{$_}, keys %funcflags;
 push @missing_api, keys %missing_macros;
 
-my $other_places = join ", ", map { "L<$_>" } sort dictionary_order qw( perlclib perlxs),
-                                                               keys %described_elsewhere;
+my @other_places = ( qw(perlclib perlxs), keys %described_elsewhere );
+my $places_other_than_intern = join ", ",
+            map { "L<$_>" } sort dictionary_order 'perlapi', @other_places;
+my $places_other_than_api = join ", ",
+            map { "L<$_>" } sort dictionary_order 'perlintern', @other_places;
 
 # The S< > makes things less densely packed, hence more readable
 my $has_defs_text .= join ",S< > ", map { "C<$_>" } sort dictionary_order @has_defs;
@@ -1630,7 +1719,9 @@ $valid_sections{$genconfig_scn}{footer} =~ s/__HAS_R_LIST__/$has_r_defs_text/;
 my $include_defs_text .= join ",S< > ", map { "C<$_>" } sort dictionary_order @include_defs;
 $valid_sections{$genconfig_scn}{footer} =~ s/__INCLUDE_LIST__/$include_defs_text/;
 
-my $section_list = join "\n\n", map { "=item L</$_>" } sort dictionary_order keys %valid_sections;
+my $section_list = join "\n\n", map { "=item L</$_>" }
+                                sort(dictionary_order keys %valid_sections),
+                                $undocumented_scn;  # Keep last
 
 output('perlapi', <<"_EOB_", $docs{api}, \@missing_api, <<"_EOE_");
 |=encoding UTF-8
@@ -1648,7 +1739,7 @@ output('perlapi', <<"_EOB_", $docs{api}, \@missing_api, <<"_EOE_");
 |L<perlintern> and F<config.h>, some items are listed here as being actually
 |documented in another pod.
 |
-|L<At the end|/Undocumented functions> is a list of functions which have yet
+|L<At the end|/$undocumented_scn> is a list of functions which have yet
 |to be documented.  Patches welcome!  The interfaces of these are subject to
 |change without notice.
 |
@@ -1733,7 +1824,7 @@ _EOB_
 |
 |=head1 SEE ALSO
 |
-|F<config.h>, L<perlintern>, $other_places
+|F<config.h>, $places_other_than_api
 _EOE_
 
 # List of non-static internal functions
@@ -1766,5 +1857,5 @@ _EOB_
 |
 |=head1 SEE ALSO
 |
-|F<config.h>, L<perlapi>, $other_places
+|F<config.h>, $places_other_than_intern
 _EOE_