This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
799852fc45ff3958ea19ca2f34cf439a24b5791a
[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 invoked as part of 'make all'
17 #
18 # '=head1' are the only headings looked for.  If the first non-blank line after
19 # the heading begins with a word character, it is considered to be the first 
20 # line of documentation that applies to the heading itself.  That is, it is 
21 # output immediately after the heading, before the first function, and not 
22 # indented. The next input line that is a pod directive terminates this 
23 # heading-level documentation.
24
25 # The meanings of the flags fields in embed.fnc and the source code is
26 # documented at the top of embed.fnc.
27
28 use strict;
29
30 if (@ARGV) {
31     my $workdir = shift;
32     chdir $workdir
33         or die "Couldn't chdir to '$workdir': $!";
34 }
35 require './regen/regen_lib.pl';
36 require './regen/embed_lib.pl';
37
38 my @specialized_docs = sort qw( perlguts
39                                 perlxs
40                                 perlxstut
41                                 perlclib
42                                 warnings
43                                 perlapio
44                                 perlcall
45                                 perlfilter
46                                 perlmroapi
47                                 config.h
48                               );
49 sub name_in_pod($) {
50     my $name = shift;
51     return "F<$name>" if $name =~ /\./;
52     return "L<$name>";
53 }
54 my $other_places_api = join " ",    map { name_in_pod($_) } sort @specialized_docs, 'perlintern';
55 my $other_places_intern = join " ", map { name_in_pod($_) } sort @specialized_docs, 'perlapi';
56
57 @specialized_docs = map { name_in_pod($_) } sort @specialized_docs;
58 $specialized_docs[-1] =~ s/^/and /;
59 my $specialized_docs = join ", ", @specialized_docs;
60
61 #
62 # See database of global and static function prototypes in embed.fnc
63 # This is used to generate prototype headers under various configurations,
64 # export symbols lists for different platforms, and macros to provide an
65 # implicit interpreter context argument.
66 #
67
68 my %docs;
69 my %funcflags;
70 my %missing;
71
72 my $curheader = "Unknown section";
73
74 sub autodoc ($$) { # parse a file and extract documentation info
75     my($fh,$file) = @_;
76     my($in, $doc, $line, $header_doc);
77
78     # Count lines easier
79     my $get_next_line = sub { $line++; return <$fh> };
80
81 FUNC:
82     while (defined($in = $get_next_line->())) {
83         if ($in=~ /^=head1 (.*)/) {
84             $curheader = $1;
85
86             # If the next non-space line begins with a word char, then it is
87             # the start of heading-level documentation.
88             if (defined($doc = $get_next_line->())) {
89                 # Skip over empty lines
90                 while ($doc =~ /^\s+$/) {
91                     if (! defined($doc = $get_next_line->())) {
92                         next FUNC;
93                     }
94                 }
95
96                 if ($doc !~ /^\w/) {
97                     $in = $doc;
98                     redo FUNC;
99                 }
100                 $header_doc = $doc;
101
102                 # Continue getting the heading-level documentation until read
103                 # in any pod directive (or as a fail-safe, find a closing
104                 # comment to this pod in a C language file
105 HDR_DOC:
106                 while (defined($doc = $get_next_line->())) {
107                     if ($doc =~ /^=\w/) {
108                         $in = $doc;
109                         redo FUNC;
110                     }
111
112                     if ($doc =~ m:^\s*\*/$:) {
113                         warn "=cut missing? $file:$line:$doc";;
114                         last HDR_DOC;
115                     }
116                     $header_doc .= $doc;
117                 }
118             }
119             next FUNC;
120         }
121         if ($in =~ /^=for\s+apidoc\s+(.*?)\s*\n/) {
122             my $proto_in_file = $1;
123             my $proto = $proto_in_file;
124             $proto = "||$proto" unless $proto =~ /\|/;
125             my($flags, $ret, $name, @args) = split /\s*\|\s*/, $proto;
126             $name or die <<EOS;
127 Bad apidoc at $file line $.:
128   $in
129 Expected:
130   =for apidoc flags|returntype|name|arg|arg|...
131   =for apidoc flags|returntype|name
132   =for apidoc name
133 EOS
134             die "flag $1 is not legal (for function $name (from $file))"
135                         if $flags =~ / ( [^AabCDdEefhiMmNnTOoPpRrSsUuWXx] ) /x;
136             next FUNC if $flags =~ /h/;
137
138             die "'u' flag must also have 'm' flag' for $name" if $flags =~ /u/ && $flags !~ /m/;
139             warn ("'$name' not \\w+ in '$proto_in_file' in $file")
140                         if $flags !~ /N/ && $name !~ / ^ [_[:alpha:]] \w* $ /x;
141             my $docs = "";
142 DOC:
143             while (defined($doc = $get_next_line->())) {
144
145                 # Other pod commands are considered part of the current
146                 # function's docs, so can have lists, etc.
147                 last DOC if $doc =~ /^=(cut|for\s+apidoc|head)/;
148                 if ($doc =~ m:^\*/$:) {
149                     warn "=cut missing? $file:$line:$doc";;
150                     last DOC;
151                 }
152                 $docs .= $doc;
153             }
154             $docs = "\n$docs" if $docs and $docs !~ /^\n/;
155
156             # If the entry is also in embed.fnc, it should be defined
157             # completely there, but not here
158             my $embed_docref = delete $funcflags{$name};
159             if ($embed_docref and %$embed_docref) {
160                 warn "embed.fnc entry overrides redundant information in"
161                    . " '$proto_in_file' in $file" if $flags || $ret || @args;
162                 $flags = $embed_docref->{'flags'};
163                 warn "embed.fnc entry '$name' missing 'd' flag"
164                                                             unless $flags =~ /d/;
165                 next FUNC if $flags =~ /h/;
166                 $ret = $embed_docref->{'retval'};
167                 @args = @{$embed_docref->{args}};
168             } elsif ($flags !~ /m/)  { # Not in embed.fnc, is missing if not a
169                                        # macro
170                 $missing{$name} = $file;
171             }
172
173             my $inline_where = $flags =~ /A/ ? 'api' : 'guts';
174
175             if (exists $docs{$inline_where}{$curheader}{$name}) {
176                 warn "$0: duplicate API entry for '$name' in $inline_where/$curheader\n";
177                 next;
178             }
179             $docs{$inline_where}{$curheader}{$name}
180                 = [$flags, $docs, $ret, $file, @args];
181
182             # Create a special entry with an empty-string name for the
183             # heading-level documentation.
184             if (defined $header_doc) {
185                 $docs{$inline_where}{$curheader}{""} = $header_doc;
186                 undef $header_doc;
187             }
188
189             if (defined $doc) {
190                 if ($doc =~ /^=(?:for|head)/) {
191                     $in = $doc;
192                     redo FUNC;
193                 }
194             } else {
195                 warn "$file:$line:$in";
196             }
197         }
198     }
199 }
200
201 sub docout ($$$) { # output the docs for one function
202     my($fh, $name, $docref) = @_;
203     my($flags, $docs, $ret, $file, @args) = @$docref;
204     $name =~ s/\s*$//;
205
206     if ($flags =~ /D/) {
207         $docs = "\n\nDEPRECATED!  It is planned to remove this function from a
208 future release of Perl.  Do not use it for new code; remove it from
209 existing code.\n\n$docs";
210     }
211     else {
212         $docs = "\n\nNOTE: this function is experimental and may change or be
213 removed without notice.\n\n$docs" if $flags =~ /x/;
214     }
215
216     # Is Perl_, but no #define foo # Perl_foo
217     my $p = $flags =~ /p/ && $flags =~ /o/ && $flags !~ /M/;
218
219     $docs .= "NOTE: the perl_ form of this function is deprecated.\n\n"
220          if $flags =~ /O/;
221     if ($p) {
222         $docs .= "NOTE: this function must be explicitly called as Perl_$name";
223         $docs .= " with an aTHX_ parameter" if $flags !~ /T/;
224         $docs .= ".\n\n"
225     }
226
227     print $fh "=item $name\nX<$name>\n$docs";
228
229     if ($flags =~ /U/) { # no usage
230         warn("U and s flags are incompatible") if $flags =~ /s/;
231         # nothing
232     } else {
233         if ($flags =~ /n/) { # no args
234             warn("n flag without m") unless $flags =~ /m/;
235             warn("n flag but apparently has args") if @args;
236             print $fh "\t$ret\t$name";
237         } else { # full usage
238             my $n            = "Perl_"x$p . $name;
239             my $large_ret    = length $ret > 7;
240             my $indent_size  = 7+8 # nroff: 7 under =head + 8 under =item
241                             +8+($large_ret ? 1 + length $ret : 8)
242                             +length($n) + 1;
243             my $indent;
244             print $fh "\t$ret" . ($large_ret ? ' ' : "\t") . "$n(";
245             my $long_args;
246             for (@args) {
247                 if ($indent_size + 2 + length > 79) {
248                     $long_args=1;
249                     $indent_size -= length($n) - 3;
250                     last;
251                 }
252             }
253             my $args = '';
254             if ($p && $flags !~ /T/) {
255                 $args = @args ? "pTHX_ " : "pTHX";
256                 if ($long_args) { print $fh $args; $args = '' }
257             }
258             $long_args and print $fh "\n";
259             my $first = !$long_args;
260             while () {
261                 if (!@args or
262                     length $args
263                     && $indent_size + 3 + length($args[0]) + length $args > 79
264                 ) {
265                     print $fh
266                     $first ? '' : (
267                         $indent //=
268                         "\t".($large_ret ? " " x (1+length $ret) : "\t")
269                         ." "x($long_args ? 4 : 1 + length $n)
270                     ),
271                     $args, (","x($args ne 'pTHX_ ') . "\n")x!!@args;
272                     $args = $first = '';
273                 }
274                 @args or last;
275                 $args .= ", "x!!(length $args && $args ne 'pTHX_ ')
276                     . shift @args;
277             }
278             if ($long_args) { print $fh "\n", substr $indent, 0, -4 }
279             print $fh ")";
280         }
281         print $fh ";" if $flags =~ /s/; # semicolon "dTHR;"
282         print $fh "\n\n";
283     }
284     print $fh "=for hackers\nFound in file $file\n\n";
285 }
286
287 sub sort_helper {
288     # Do a case-insensitive dictionary sort, with only alphabetics
289     # significant, falling back to using everything for determinancy
290     return (uc($a =~ s/[[:^alpha:]]//r) cmp uc($b =~ s/[[:^alpha:]]//r))
291            || uc($a) cmp uc($b)
292            || $a cmp $b;
293 }
294
295 sub output {
296     my ($podname, $header, $dochash, $missing, $footer) = @_;
297     #
298     # strip leading '|' from each line which had been used to hide
299     # pod from pod checkers.
300     s/^\|//gm for $header, $footer;
301
302     my $fh = open_new("pod/$podname.pod", undef,
303                       {by => "$0 extracting documentation",
304                        from => 'the C source files'}, 1);
305
306     print $fh $header;
307
308     my $key;
309     for $key (sort sort_helper keys %$dochash) {
310         my $section = $dochash->{$key}; 
311         print $fh "\n=head1 $key\n\n";
312
313         # Output any heading-level documentation and delete so won't get in
314         # the way later
315         if (exists $section->{""}) {
316             print $fh $section->{""} . "\n";
317             delete $section->{""};
318         }
319         print $fh "=over 8\n\n";
320
321         for my $key (sort sort_helper keys %$section) {
322             docout($fh, $key, $section->{$key});
323         }
324         print $fh "\n=back\n";
325     }
326
327     if (@$missing) {
328         print $fh "\n=head1 Undocumented functions\n\n";
329     print $fh $podname eq 'perlapi' ? <<'_EOB_' : <<'_EOB_';
330 The following functions have been flagged as part of the public API,
331 but are currently undocumented.  Use them at your own risk, as the
332 interfaces are subject to change.  Functions that are not listed in this
333 document are not intended for public use, and should NOT be used under any
334 circumstances.
335
336 If you feel you need to use one of these functions, first send email to
337 L<perl5-porters@perl.org|mailto:perl5-porters@perl.org>.  It may be
338 that there is a good reason for the function not being documented, and it
339 should be removed from this list; or it may just be that no one has gotten
340 around to documenting it.  In the latter case, you will be asked to submit a
341 patch to document the function.  Once your patch is accepted, it will indicate
342 that the interface is stable (unless it is explicitly marked otherwise) and
343 usable by you.
344 _EOB_
345 The following functions are currently undocumented.  If you use one of
346 them, you may wish to consider creating and submitting documentation for
347 it.
348 _EOB_
349     print $fh "\n=over\n\n";
350
351     for my $missing (sort @$missing) {
352         print $fh "=item $missing\nX<$missing>\n\n";
353     }
354     print $fh "=back\n\n";
355 }
356     print $fh $footer, "=cut\n";
357
358     read_only_bottom_close_and_rename($fh);
359 }
360
361 foreach (@{(setup_embed())[0]}) {
362     next if @$_ < 2;
363     my ($flags, $retval, $func, @args) = @$_;
364     s/\b(?:NN|NULLOK)\b\s+//g for @args;
365
366     $funcflags{$func} = {
367                          flags => $flags,
368                          retval => $retval,
369                          args => \@args,
370                         };
371 }
372
373 # glob() picks up docs from extra .c or .h files that may be in unclean
374 # development trees.
375 open my $fh, '<', 'MANIFEST'
376     or die "Can't open MANIFEST: $!";
377 while (my $line = <$fh>) {
378     next unless my ($file) = $line =~ /^(\S+\.(?:[ch]|pod))\t/;
379
380     open F, '<', $file or die "Cannot open $file for docs: $!\n";
381     $curheader = "Functions in file $file\n";
382     autodoc(\*F,$file);
383     close F or die "Error closing $file: $!\n";
384 }
385 close $fh or die "Error whilst reading MANIFEST: $!";
386
387 for (sort keys %funcflags) {
388     next unless $funcflags{$_}{flags} =~ /d/;
389     next if $funcflags{$_}{flags} =~ /h/;
390     warn "no docs for $_\n"
391 }
392
393 foreach (sort keys %missing) {
394     warn "Function '$_', documented in $missing{$_}, not listed in embed.fnc";
395 }
396
397 # walk table providing an array of components in each line to
398 # subroutine, printing the result
399
400 # List of funcs in the public API that aren't also marked as core-only,
401 # experimental nor deprecated.
402 my @missing_api = grep $funcflags{$_}{flags} =~ /A/
403                     && $funcflags{$_}{flags} !~ /[xD]/
404                     && !$docs{api}{$_}, keys %funcflags;
405 output('perlapi', <<"_EOB_", $docs{api}, \@missing_api, <<"_EOE_");
406 |=encoding UTF-8
407 |
408 |=head1 NAME
409 |
410 |perlapi - autogenerated documentation for the perl public API
411 |
412 |=head1 DESCRIPTION
413 |X<Perl API> X<API> X<api>
414 |
415 |This file contains most of the documentation of the perl public API, as
416 |generated by F<embed.pl>.  Specifically, it is a listing of functions,
417 |macros, flags, and variables that may be used by extension writers.  Some
418 |specialized items are instead documented in $specialized_docs.
419 |
420 |L<At the end|/Undocumented functions> is a list of functions which have yet
421 |to be documented.  Patches welcome!  The interfaces of these are subject to
422 |change without notice.
423 |
424 |Anything not listed here is not part of the public API, and should not be
425 |used by extension writers at all.  For these reasons, blindly using functions
426 |listed in proto.h is to be avoided when writing extensions.
427 |
428 |In Perl, unlike C, a string of characters may generally contain embedded
429 |C<NUL> characters.  Sometimes in the documentation a Perl string is referred
430 |to as a "buffer" to distinguish it from a C string, but sometimes they are
431 |both just referred to as strings.
432 |
433 |Note that all Perl API global variables must be referenced with the C<PL_>
434 |prefix.  Again, those not listed here are not to be used by extension writers,
435 |and can be changed or removed without notice; same with macros.
436 |Some macros are provided for compatibility with the older,
437 |unadorned names, but this support may be disabled in a future release.
438 |
439 |Perl was originally written to handle US-ASCII only (that is characters
440 |whose ordinal numbers are in the range 0 - 127).
441 |And documentation and comments may still use the term ASCII, when
442 |sometimes in fact the entire range from 0 - 255 is meant.
443 |
444 |The non-ASCII characters below 256 can have various meanings, depending on
445 |various things.  (See, most notably, L<perllocale>.)  But usually the whole
446 |range can be referred to as ISO-8859-1.  Often, the term "Latin-1" (or
447 |"Latin1") is used as an equivalent for ISO-8859-1.  But some people treat
448 |"Latin1" as referring just to the characters in the range 128 through 255, or
449 |somethimes from 160 through 255.
450 |This documentation uses "Latin1" and "Latin-1" to refer to all 256 characters.
451 |
452 |Note that Perl can be compiled and run under either ASCII or EBCDIC (See
453 |L<perlebcdic>).  Most of the documentation (and even comments in the code)
454 |ignore the EBCDIC possibility.
455 |For almost all purposes the differences are transparent.
456 |As an example, under EBCDIC,
457 |instead of UTF-8, UTF-EBCDIC is used to encode Unicode strings, and so
458 |whenever this documentation refers to C<utf8>
459 |(and variants of that name, including in function names),
460 |it also (essentially transparently) means C<UTF-EBCDIC>.
461 |But the ordinals of characters differ between ASCII, EBCDIC, and
462 |the UTF- encodings, and a string encoded in UTF-EBCDIC may occupy a different
463 |number of bytes than in UTF-8.
464 |
465 |The listing below is alphabetical, case insensitive.
466 |
467 _EOB_
468 |
469 |=head1 AUTHORS
470 |
471 |Until May 1997, this document was maintained by Jeff Okamoto
472 |<okamoto\@corp.hp.com>.  It is now maintained as part of Perl itself.
473 |
474 |With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
475 |Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
476 |Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
477 |Stephen McCamant, and Gurusamy Sarathy.
478 |
479 |API Listing originally by Dean Roehrich <roehrich\@cray.com>.
480 |
481 |Updated to be autogenerated from comments in the source by Benjamin Stuhl.
482 |
483 |=head1 SEE ALSO
484 |
485 $other_places_api
486 _EOE_
487
488 # List of non-static internal functions
489 my @missing_guts =
490  grep $funcflags{$_}{flags} !~ /[AS]/ && !$docs{guts}{$_}, keys %funcflags;
491
492 output('perlintern', <<'_EOB_', $docs{guts}, \@missing_guts, <<"_EOE_");
493 |=head1 NAME
494 |
495 |perlintern - autogenerated documentation of purely B<internal>
496 |Perl functions
497 |
498 |=head1 DESCRIPTION
499 |X<internal Perl functions> X<interpreter functions>
500 |
501 |This file is the autogenerated documentation of functions in the
502 |Perl interpreter that are documented using Perl's internal documentation
503 |format but are not marked as part of the Perl API.  In other words,
504 |B<they are not for use in extensions>!
505 |
506 _EOB_
507 |
508 |=head1 AUTHORS
509 |
510 |The autodocumentation system was originally added to the Perl core by
511 |Benjamin Stuhl.  Documentation is by whoever was kind enough to
512 |document their functions.
513 |
514 |=head1 SEE ALSO
515 |
516 $other_places_intern
517 _EOE_