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