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