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