# 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
#
# 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
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';
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';
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';
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 => {},
$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 => {},
$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 => {},
$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.
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
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};
$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;
$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;
}
}
+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) = @_;
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}->@*;
# 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
}
# 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);
$text .= <<~EOT;
- =head1 Undocumented functions
+ =head1 $undocumented_scn
EOT
if ($pod_name eq 'perlapi') {
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;
}
}
-
- 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});
}
&& !$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;
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
|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.
|
|
|=head1 SEE ALSO
|
-|F<config.h>, L<perlintern>, $other_places
+|F<config.h>, $places_other_than_api
_EOE_
# List of non-static internal functions
|
|=head1 SEE ALSO
|
-|F<config.h>, L<perlapi>, $other_places
+|F<config.h>, $places_other_than_intern
_EOE_