This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
follow-up to #23765
[perl5.git] / autodoc.pl
1 #!/usr/bin/perl -w
2
3 require 5.003;  # keep this compatible, an old perl is all we may have before
4                 # we build the new one
5
6 BEGIN {
7   push @INC, 'lib';
8   require 'regen_lib.pl';
9 }
10
11
12 #
13 # See database of global and static function prototypes in embed.fnc
14 # This is used to generate prototype headers under various configurations,
15 # export symbols lists for different platforms, and macros to provide an
16 # implicit interpreter context argument.
17 #
18
19 open IN, "embed.fnc" or die $!;
20
21 # walk table providing an array of components in each line to
22 # subroutine, printing the result
23 sub walk_table (&@) {
24     my $function = shift;
25     my $filename = shift || '-';
26     my $leader = shift;
27     my $trailer = shift;
28     my $F;
29     local *F;
30     if (ref $filename) {        # filehandle
31         $F = $filename;
32     }
33     else {
34         safer_unlink $filename;
35         open F, ">$filename" or die "Can't open $filename: $!";
36         binmode F;
37         $F = \*F;
38     }
39     print $F $leader if $leader;
40     seek IN, 0, 0;              # so we may restart
41     while (<IN>) {
42         chomp;
43         next if /^:/;
44         while (s|\\\s*$||) {
45             $_ .= <IN>;
46             chomp;
47         }
48         s/\s+$//;
49         my @args;
50         if (/^\s*(#|$)/) {
51             @args = $_;
52         }
53         else {
54             @args = split /\s*\|\s*/, $_;
55         }
56         print $F $function->(@args);
57     }
58     print $F $trailer if $trailer;
59     unless (ref $filename) {
60         close $F or die "Error closing $filename: $!";
61     }
62 }
63
64 my %apidocs;
65 my %gutsdocs;
66 my %docfuncs;
67
68 my $curheader = "Unknown section";
69
70 sub autodoc ($$) { # parse a file and extract documentation info
71     my($fh,$file) = @_;
72     my($in, $doc, $line);
73 FUNC:
74     while (defined($in = <$fh>)) {
75         if ($in=~ /^=head1 (.*)/) {
76             $curheader = $1;
77             next FUNC;
78         }
79         $line++;
80         if ($in =~ /^=for\s+apidoc\s+(.*?)\s*\n/) {
81             my $proto = $1;
82             $proto = "||$proto" unless $proto =~ /\|/;
83             my($flags, $ret, $name, @args) = split /\|/, $proto;
84             my $docs = "";
85 DOC:
86             while (defined($doc = <$fh>)) {
87                 $line++;
88                 last DOC if $doc =~ /^=\w+/;
89                 if ($doc =~ m:^\*/$:) {
90                     warn "=cut missing? $file:$line:$doc";;
91                     last DOC;
92                 }
93                 $docs .= $doc;
94             }
95             $docs = "\n$docs" if $docs and $docs !~ /^\n/;
96             if ($flags =~ /m/) {
97                 if ($flags =~ /A/) {
98                     $apidocs{$curheader}{$name} = [$flags, $docs, $ret, $file, @args];
99                 }
100                 else {
101                     $gutsdocs{$curheader}{$name} = [$flags, $docs, $ret, $file, @args];
102                 }
103             }
104             else {
105                 $docfuncs{$name} = [$flags, $docs, $ret, $file, $curheader, @args];
106             }
107             if (defined $doc) {
108                 if ($doc =~ /^=(?:for|head)/) {
109                     $in = $doc;
110                     redo FUNC;
111                 }
112             } else {
113                 warn "$file:$line:$in";
114             }
115         }
116     }
117 }
118
119 sub docout ($$$) { # output the docs for one function
120     my($fh, $name, $docref) = @_;
121     my($flags, $docs, $ret, $file, @args) = @$docref;
122
123     $docs .= "NOTE: this function is experimental and may change or be
124 removed without notice.\n\n" if $flags =~ /x/;
125     $docs .= "NOTE: the perl_ form of this function is deprecated.\n\n"
126         if $flags =~ /p/;
127
128     print $fh "=item $name\n$docs";
129
130     if ($flags =~ /U/) { # no usage
131         # nothing
132     } elsif ($flags =~ /s/) { # semicolon ("dTHR;")
133         print $fh "\t\t$name;\n\n";
134     } elsif ($flags =~ /n/) { # no args
135         print $fh "\t$ret\t$name\n\n";
136     } else { # full usage
137         print $fh "\t$ret\t$name";
138         print $fh "(" . join(", ", @args) . ")";
139         print $fh "\n\n";
140     }
141     print $fh "=for hackers\nFound in file $file\n\n";
142 }
143
144 my $file;
145 # glob() picks up docs from extra .c or .h files that may be in unclean
146 # development trees.
147 my $MANIFEST = do {
148   local ($/, *FH);
149   open FH, "MANIFEST" or die "Can't open MANIFEST: $!";
150   <FH>;
151 };
152
153 for $file (($MANIFEST =~ /^(\S+\.c)\t/gm), ($MANIFEST =~ /^(\S+\.h)\t/gm)) {
154     open F, "< $file" or die "Cannot open $file for docs: $!\n";
155     $curheader = "Functions in file $file\n";
156     autodoc(\*F,$file);
157     close F or die "Error closing $file: $!\n";
158 }
159
160 safer_unlink "pod/perlapi.pod";
161 open (DOC, ">pod/perlapi.pod") or
162         die "Can't create pod/perlapi.pod: $!\n";
163 binmode DOC;
164
165 walk_table {    # load documented functions into approriate hash
166     if (@_ > 1) {
167         my($flags, $retval, $func, @args) = @_;
168         return "" unless $flags =~ /d/;
169         $func =~ s/\t//g; $flags =~ s/p//; # clean up fields from embed.pl
170         $retval =~ s/\t//;
171         my $docref = delete $docfuncs{$func};
172         if ($docref and @$docref) {
173             if ($flags =~ /A/) {
174                 $docref->[0].="x" if $flags =~ /M/;
175                 $apidocs{$docref->[4]}{$func} = 
176                     [$docref->[0] . 'A', $docref->[1], $retval,
177                                                 $docref->[3], @args];
178             } else {
179                 $gutsdocs{$docref->[4]}{$func} = 
180                     [$docref->[0], $docref->[1], $retval, $docref->[3], @args];
181             }
182         }
183         else {
184             warn "no docs for $func\n" unless $docref and @$docref;
185         }
186     }
187     return "";
188 } \*DOC;
189
190 for (sort keys %docfuncs) {
191     # Have you used a full for apidoc or just a func name?
192     # Have you used Ap instead of Am in the for apidoc?
193     warn "Unable to place $_!\n";
194 }
195
196 print DOC <<'_EOB_';
197 =head1 NAME
198
199 perlapi - autogenerated documentation for the perl public API
200
201 =head1 DESCRIPTION
202
203 This file contains the documentation of the perl public API generated by
204 embed.pl, specifically a listing of functions, macros, flags, and variables
205 that may be used by extension writers.  The interfaces of any functions that
206 are not listed here are subject to change without notice.  For this reason,
207 blindly using functions listed in proto.h is to be avoided when writing
208 extensions.
209
210 Note that all Perl API global variables must be referenced with the C<PL_>
211 prefix.  Some macros are provided for compatibility with the older,
212 unadorned names, but this support may be disabled in a future release.
213
214 The listing is alphabetical, case insensitive.
215
216 _EOB_
217
218 my $key;
219 # case insensitive sort, with fallback for determinacy
220 for $key (sort { uc($a) cmp uc($b) || $a cmp $b } keys %apidocs) {
221     my $section = $apidocs{$key}; 
222     print DOC "\n=head1 $key\n\n=over 8\n\n";
223     for my $key (sort { uc($a) cmp uc($b); } keys %$section) {
224         docout(\*DOC, $key, $section->{$key});
225     }
226     print DOC "\n=back\n";
227 }
228
229 print DOC <<'_EOE_';
230
231 =head1 AUTHORS
232
233 Until May 1997, this document was maintained by Jeff Okamoto
234 <okamoto@corp.hp.com>.  It is now maintained as part of Perl itself.
235
236 With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
237 Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
238 Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
239 Stephen McCamant, and Gurusamy Sarathy.
240
241 API Listing originally by Dean Roehrich <roehrich@cray.com>.
242
243 Updated to be autogenerated from comments in the source by Benjamin Stuhl.
244
245 =head1 SEE ALSO
246
247 perlguts(1), perlxs(1), perlxstut(1), perlintern(1)
248
249 _EOE_
250
251
252 close(DOC) or die "Error closing pod/perlapi.pod: $!";
253
254 safer_unlink "pod/perlintern.pod";
255 open(GUTS, ">pod/perlintern.pod") or
256                 die "Unable to create pod/perlintern.pod: $!\n";
257 binmode GUTS;
258 print GUTS <<'END';
259 =head1 NAME
260
261 perlintern - autogenerated documentation of purely B<internal>
262                  Perl functions
263
264 =head1 DESCRIPTION
265
266 This file is the autogenerated documentation of functions in the
267 Perl interpreter that are documented using Perl's internal documentation
268 format but are not marked as part of the Perl API. In other words,
269 B<they are not for use in extensions>!
270
271 END
272
273 for $key (sort { uc($a) cmp uc($b); } keys %gutsdocs) {
274     my $section = $gutsdocs{$key}; 
275     print GUTS "\n=head1 $key\n\n=over 8\n\n";
276     for my $key (sort { uc($a) cmp uc($b); } keys %$section) {
277         docout(\*GUTS, $key, $section->{$key});
278     }
279     print GUTS "\n=back\n";
280 }
281
282 print GUTS <<'END';
283
284 =head1 AUTHORS
285
286 The autodocumentation system was originally added to the Perl core by
287 Benjamin Stuhl. Documentation is by whoever was kind enough to
288 document their functions.
289
290 =head1 SEE ALSO
291
292 perlguts(1), perlapi(1)
293
294 END
295
296 close GUTS or die "Error closing pod/perlintern.pod: $!";