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