1#!/usr/bin/perl -w 2# 3# Unconditionally regenerate: 4# 5# pod/perlintern.pod 6# pod/perlapi.pod 7# 8# from information stored in 9# 10# embed.fnc 11# plus all the .c and .h files listed in MANIFEST 12# 13# Has an optional arg, which is the directory to chdir to before reading 14# MANIFEST and *.[ch]. 15# 16# This script is normally invoked as part of 'make all', but is also 17# called from from regen.pl. 18 19use strict; 20 21# 22# See database of global and static function prototypes in embed.fnc 23# This is used to generate prototype headers under various configurations, 24# export symbols lists for different platforms, and macros to provide an 25# implicit interpreter context argument. 26# 27 28my %docs; 29my %funcflags; 30my %macro = ( 31 ax => 1, 32 items => 1, 33 ix => 1, 34 svtype => 1, 35 ); 36my %missing; 37 38my $curheader = "Unknown section"; 39 40sub autodoc ($$) { # parse a file and extract documentation info 41 my($fh,$file) = @_; 42 my($in, $doc, $line); 43FUNC: 44 while (defined($in = <$fh>)) { 45 if ($in =~ /^#\s*define\s+([A-Za-z_][A-Za-z_0-9]+)\(/ && 46 ($file ne 'embed.h' || $file ne 'proto.h')) { 47 $macro{$1} = $file; 48 next FUNC; 49 } 50 if ($in=~ /^=head1 (.*)/) { 51 $curheader = $1; 52 next FUNC; 53 } 54 $line++; 55 if ($in =~ /^=for\s+apidoc\s+(.*?)\s*\n/) { 56 my $proto = $1; 57 $proto = "||$proto" unless $proto =~ /\|/; 58 my($flags, $ret, $name, @args) = split /\|/, $proto; 59 my $docs = ""; 60DOC: 61 while (defined($doc = <$fh>)) { 62 $line++; 63 last DOC if $doc =~ /^=\w+/; 64 if ($doc =~ m:^\*/$:) { 65 warn "=cut missing? $file:$line:$doc";; 66 last DOC; 67 } 68 $docs .= $doc; 69 } 70 $docs = "\n$docs" if $docs and $docs !~ /^\n/; 71 72 # Check the consistency of the flags 73 my ($embed_where, $inline_where); 74 my ($embed_may_change, $inline_may_change); 75 76 my $docref = delete $funcflags{$name}; 77 if ($docref and %$docref) { 78 $embed_where = $docref->{flags} =~ /A/ ? 'api' : 'guts'; 79 $embed_may_change = $docref->{flags} =~ /M/; 80 } else { 81 $missing{$name} = $file; 82 } 83 if ($flags =~ /m/) { 84 $inline_where = $flags =~ /A/ ? 'api' : 'guts'; 85 $inline_may_change = $flags =~ /x/; 86 87 if (defined $embed_where && $inline_where ne $embed_where) { 88 warn "Function '$name' inconsistency: embed.fnc says $embed_where, Pod says $inline_where"; 89 } 90 91 if (defined $embed_may_change 92 && $inline_may_change ne $embed_may_change) { 93 my $message = "Function '$name' inconsistency: "; 94 if ($embed_may_change) { 95 $message .= "embed.fnc says 'may change', Pod does not"; 96 } else { 97 $message .= "Pod says 'may change', embed.fnc does not"; 98 } 99 warn $message; 100 } 101 } elsif (!defined $embed_where) { 102 warn "Unable to place $name!\n"; 103 next; 104 } else { 105 $inline_where = $embed_where; 106 $flags .= 'x' if $embed_may_change; 107 @args = @{$docref->{args}}; 108 $ret = $docref->{retval}; 109 } 110 111 $docs{$inline_where}{$curheader}{$name} 112 = [$flags, $docs, $ret, $file, @args]; 113 114 if (defined $doc) { 115 if ($doc =~ /^=(?:for|head)/) { 116 $in = $doc; 117 redo FUNC; 118 } 119 } else { 120 warn "$file:$line:$in"; 121 } 122 } 123 } 124} 125 126sub docout ($$$) { # output the docs for one function 127 my($fh, $name, $docref) = @_; 128 my($flags, $docs, $ret, $file, @args) = @$docref; 129 $name =~ s/\s*$//; 130 131 $docs .= "NOTE: this function is experimental and may change or be 132removed without notice.\n\n" if $flags =~ /x/; 133 $docs .= "NOTE: the perl_ form of this function is deprecated.\n\n" 134 if $flags =~ /p/; 135 136 print $fh "=item $name\nX<$name>\n$docs"; 137 138 if ($flags =~ /U/) { # no usage 139 # nothing 140 } elsif ($flags =~ /s/) { # semicolon ("dTHR;") 141 print $fh "\t\t$name;\n\n"; 142 } elsif ($flags =~ /n/) { # no args 143 print $fh "\t$ret\t$name\n\n"; 144 } else { # full usage 145 print $fh "\t$ret\t$name"; 146 print $fh "(" . join(", ", @args) . ")"; 147 print $fh "\n\n"; 148 } 149 print $fh "=for hackers\nFound in file $file\n\n"; 150} 151 152sub output { 153 my ($podname, $header, $dochash, $missing, $footer) = @_; 154 my $filename = "pod/$podname.pod"; 155 open my $fh, '>', $filename or die "Can't open $filename: $!"; 156 157 print $fh <<"_EOH_", $header; 158-*- buffer-read-only: t -*- 159 160!!!!!!! DO NOT EDIT THIS FILE !!!!!!! 161This file is built by $0 extracting documentation from the C source 162files. 163 164_EOH_ 165 166 my $key; 167 # case insensitive sort, with fallback for determinacy 168 for $key (sort { uc($a) cmp uc($b) || $a cmp $b } keys %$dochash) { 169 my $section = $dochash->{$key}; 170 print $fh "\n=head1 $key\n\n=over 8\n\n"; 171 # Again, fallback for determinacy 172 for my $key (sort { uc($a) cmp uc($b) || $a cmp $b } keys %$section) { 173 docout($fh, $key, $section->{$key}); 174 } 175 print $fh "\n=back\n"; 176 } 177 178 if (@$missing) { 179 print $fh "\n=head1 Undocumented functions\n\n"; 180 print $fh "These functions are currently undocumented:\n\n=over\n\n"; 181 for my $missing (sort @$missing) { 182 print $fh "=item $missing\nX<$missing>\n\n"; 183 } 184 print $fh "=back\n\n"; 185 } 186 187 print $fh $footer, <<'_EOF_'; 188=cut 189 190 ex: set ro: 191_EOF_ 192 193 close $fh or die "Can't close $filename: $!"; 194} 195 196if (@ARGV) { 197 my $workdir = shift; 198 chdir $workdir 199 or die "Couldn't chdir to '$workdir': $!"; 200} 201 202open IN, "embed.fnc" or die $!; 203 204while (<IN>) { 205 chomp; 206 next if /^:/; 207 while (s|\\\s*$||) { 208 $_ .= <IN>; 209 chomp; 210 } 211 s/\s+$//; 212 next if /^\s*(#|$)/; 213 214 my ($flags, $retval, $func, @args) = split /\s*\|\s*/, $_; 215 216 next unless $func; 217 218 s/\b(NN|NULLOK)\b\s+//g for @args; 219 $func =~ s/\t//g; # clean up fields from embed.pl 220 $retval =~ s/\t//; 221 222 $funcflags{$func} = { 223 flags => $flags, 224 retval => $retval, 225 args => \@args, 226 }; 227} 228 229my $file; 230# glob() picks up docs from extra .c or .h files that may be in unclean 231# development trees. 232my $MANIFEST = do { 233 local ($/, *FH); 234 open FH, "MANIFEST" or die "Can't open MANIFEST: $!"; 235 <FH>; 236}; 237 238for $file (($MANIFEST =~ /^(\S+\.c)\t/gm), ($MANIFEST =~ /^(\S+\.h)\t/gm)) { 239 open F, "< $file" or die "Cannot open $file for docs: $!\n"; 240 $curheader = "Functions in file $file\n"; 241 autodoc(\*F,$file); 242 close F or die "Error closing $file: $!\n"; 243} 244 245for (sort keys %funcflags) { 246 next unless $funcflags{$_}{flags} =~ /d/; 247 warn "no docs for $_\n" 248} 249 250foreach (sort keys %missing) { 251 next if $macro{$_}; 252 # Heuristics for known not-a-function macros: 253 next if /^[A-Z]/; 254 next if /^dj?[A-Z]/; 255 256 warn "Function '$_', documented in $missing{$_}, not listed in embed.fnc"; 257} 258 259# walk table providing an array of components in each line to 260# subroutine, printing the result 261 262my @missing_api = grep $funcflags{$_}{flags} =~ /A/ && !$docs{api}{$_}, keys %funcflags; 263output('perlapi', <<'_EOB_', $docs{api}, \@missing_api, <<'_EOE_'); 264=head1 NAME 265 266perlapi - autogenerated documentation for the perl public API 267 268=head1 DESCRIPTION 269X<Perl API> X<API> X<api> 270 271This file contains the documentation of the perl public API generated by 272embed.pl, specifically a listing of functions, macros, flags, and variables 273that may be used by extension writers. The interfaces of any functions that 274are not listed here are subject to change without notice. For this reason, 275blindly using functions listed in proto.h is to be avoided when writing 276extensions. 277 278Note that all Perl API global variables must be referenced with the C<PL_> 279prefix. Some macros are provided for compatibility with the older, 280unadorned names, but this support may be disabled in a future release. 281 282Perl was originally written to handle US-ASCII only (that is characters 283whose ordinal numbers are in the range 0 - 127). 284And documentation and comments may still use the term ASCII, when 285sometimes in fact the entire range from 0 - 255 is meant. 286 287Note that Perl can be compiled and run under EBCDIC (See L<perlebcdic>) 288or ASCII. Most of the documentation (and even comments in the code) 289ignore the EBCDIC possibility. 290For almost all purposes the differences are transparent. 291As an example, under EBCDIC, 292instead of UTF-8, UTF-EBCDIC is used to encode Unicode strings, and so 293whenever this documentation refers to C<utf8> 294(and variants of that name, including in function names), 295it also (essentially transparently) means C<UTF-EBCDIC>. 296But the ordinals of characters differ between ASCII, EBCDIC, and 297the UTF- encodings, and a string encoded in UTF-EBCDIC may occupy more bytes 298than in UTF-8. 299 300Also, on some EBCDIC machines, functions that are documented as operating on 301US-ASCII (or Basic Latin in Unicode terminology) may in fact operate on all 302256 characters in the EBCDIC range, not just the subset corresponding to 303US-ASCII. 304 305The listing below is alphabetical, case insensitive. 306 307_EOB_ 308 309=head1 AUTHORS 310 311Until May 1997, this document was maintained by Jeff Okamoto 312<okamoto@corp.hp.com>. It is now maintained as part of Perl itself. 313 314With lots of help and suggestions from Dean Roehrich, Malcolm Beattie, 315Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil 316Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer, 317Stephen McCamant, and Gurusamy Sarathy. 318 319API Listing originally by Dean Roehrich <roehrich@cray.com>. 320 321Updated to be autogenerated from comments in the source by Benjamin Stuhl. 322 323=head1 SEE ALSO 324 325L<perlguts>, L<perlxs>, L<perlxstut>, L<perlintern> 326 327_EOE_ 328 329my @missing_guts = grep $funcflags{$_}{flags} !~ /A/ && !$docs{guts}{$_}, keys %funcflags; 330 331output('perlintern', <<'END', $docs{guts}, \@missing_guts, <<'END'); 332=head1 NAME 333 334perlintern - autogenerated documentation of purely B<internal> 335 Perl functions 336 337=head1 DESCRIPTION 338X<internal Perl functions> X<interpreter functions> 339 340This file is the autogenerated documentation of functions in the 341Perl interpreter that are documented using Perl's internal documentation 342format but are not marked as part of the Perl API. In other words, 343B<they are not for use in extensions>! 344 345END 346 347=head1 AUTHORS 348 349The autodocumentation system was originally added to the Perl core by 350Benjamin Stuhl. Documentation is by whoever was kind enough to 351document their functions. 352 353=head1 SEE ALSO 354 355L<perlguts>, L<perlapi> 356 357END 358