This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #118175] prevent a similar overflow for POSIXA
[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 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
26use strict;
27
28if (@ARGV) {
29 my $workdir = shift;
30 chdir $workdir
31 or die "Couldn't chdir to '$workdir': $!";
32}
33require 'regen/regen_lib.pl';
34require '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
43my %docs;
44my %funcflags;
45my %macro = (
46 ax => 1,
47 items => 1,
48 ix => 1,
49 svtype => 1,
50 );
51my %missing;
52
53my $curheader = "Unknown section";
54
55sub autodoc ($$) { # parse a file and extract documentation info
56 my($fh,$file) = @_;
57 my($in, $doc, $line, $header_doc);
58FUNC:
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
81HDR_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 = "";
104DOC:
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
178sub 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
185future release of Perl. Do not use it for new code; remove it from
186existing code.\n\n$docs";
187 }
188 else {
189 $docs = "\n\nNOTE: this function is experimental and may change or be
190removed 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
253sub 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_';
285The following functions have been flagged as part of the public API,
286but are currently undocumented. Use them at your own risk, as the
287interfaces are subject to change. Functions that are not listed in this
288document are not intended for public use, and should NOT be used under any
289circumstances.
290
291If you use one of the undocumented functions below, you may wish to consider
292creating and submitting documentation for it. If your patch is accepted, this
293will indicate that the interface is stable (unless it is explicitly marked
294otherwise).
295
296=over
297
298_EOB_
299The following functions are currently undocumented. If you use one of
300them, you may wish to consider creating and submitting documentation for
301it.
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
316foreach (@{(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.
330open my $fh, '<', 'MANIFEST'
331 or die "Can't open MANIFEST: $!";
332while (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}
340close $fh or die "Error whilst reading MANIFEST: $!";
341
342for (sort keys %funcflags) {
343 next unless $funcflags{$_}{flags} =~ /d/;
344 warn "no docs for $_\n"
345}
346
347foreach (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.
361my @missing_api = grep $funcflags{$_}{flags} =~ /A/ && $funcflags{$_}{flags} !~ /[MD]/ && !$docs{api}{$_}, keys %funcflags;
362output('perlapi', <<'_EOB_', $docs{api}, \@missing_api, <<'_EOE_');
363=head1 NAME
364
365perlapi - autogenerated documentation for the perl public API
366
367=head1 DESCRIPTION
368X<Perl API> X<API> X<api>
369
370This file contains the documentation of the perl public API generated by
371F<embed.pl>, specifically a listing of functions, macros, flags, and variables
372that may be used by extension writers. L<At the end|/Undocumented functions>
373is a list of functions which have yet to be documented. The interfaces of
374those are subject to change without notice. Any functions not listed here are
375not part of the public API, and should not be used by extension writers at
376all. For these reasons, blindly using functions listed in proto.h is to be
377avoided when writing extensions.
378
379Note that all Perl API global variables must be referenced with the C<PL_>
380prefix. Some macros are provided for compatibility with the older,
381unadorned names, but this support may be disabled in a future release.
382
383Perl was originally written to handle US-ASCII only (that is characters
384whose ordinal numbers are in the range 0 - 127).
385And documentation and comments may still use the term ASCII, when
386sometimes in fact the entire range from 0 - 255 is meant.
387
388Note that Perl can be compiled and run under EBCDIC (See L<perlebcdic>)
389or ASCII. Most of the documentation (and even comments in the code)
390ignore the EBCDIC possibility.
391For almost all purposes the differences are transparent.
392As an example, under EBCDIC,
393instead of UTF-8, UTF-EBCDIC is used to encode Unicode strings, and so
394whenever this documentation refers to C<utf8>
395(and variants of that name, including in function names),
396it also (essentially transparently) means C<UTF-EBCDIC>.
397But the ordinals of characters differ between ASCII, EBCDIC, and
398the UTF- encodings, and a string encoded in UTF-EBCDIC may occupy more bytes
399than in UTF-8.
400
401The listing below is alphabetical, case insensitive.
402
403_EOB_
404
405=head1 AUTHORS
406
407Until May 1997, this document was maintained by Jeff Okamoto
408<okamoto@corp.hp.com>. It is now maintained as part of Perl itself.
409
410With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
411Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
412Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
413Stephen McCamant, and Gurusamy Sarathy.
414
415API Listing originally by Dean Roehrich <roehrich@cray.com>.
416
417Updated to be autogenerated from comments in the source by Benjamin Stuhl.
418
419=head1 SEE ALSO
420
421L<perlguts>, L<perlxs>, L<perlxstut>, L<perlintern>
422
423_EOE_
424
425# List of non-static internal functions
426my @missing_guts =
427 grep $funcflags{$_}{flags} !~ /[As]/ && !$docs{guts}{$_}, keys %funcflags;
428
429output('perlintern', <<'END', $docs{guts}, \@missing_guts, <<'END');
430=head1 NAME
431
432perlintern - autogenerated documentation of purely B<internal>
433 Perl functions
434
435=head1 DESCRIPTION
436X<internal Perl functions> X<interpreter functions>
437
438This file is the autogenerated documentation of functions in the
439Perl interpreter that are documented using Perl's internal documentation
440format but are not marked as part of the Perl API. In other words,
441B<they are not for use in extensions>!
442
443END
444
445=head1 AUTHORS
446
447The autodocumentation system was originally added to the Perl core by
448Benjamin Stuhl. Documentation is by whoever was kind enough to
449document their functions.
450
451=head1 SEE ALSO
452
453L<perlguts>, L<perlapi>
454
455END