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