If not building threaded, never mind the threaded prototypes.
[p5sagit/p5-mst-13.2.git] / autodoc.pl
1 #!/usr/bin/perl -w
2
3 require 5.003;  # keep this compatible, an old perl is all we may have before
4                 # we build the new one
5
6 BEGIN {  push @INC, 'lib' }     # glob() below requires File::Glob
7
8
9 #
10 # See database of global and static function prototypes at the __END__.
11 # This is used to generate prototype headers under various configurations,
12 # export symbols lists for different platforms, and macros to provide an
13 # implicit interpreter context argument.
14 #
15
16 open IN, "embed.fnc" or die $!;
17
18 # walk table providing an array of components in each line to
19 # subroutine, printing the result
20 sub walk_table (&@) {
21     my $function = shift;
22     my $filename = shift || '-';
23     my $leader = shift;
24     my $trailer = shift;
25     my $F;
26     local *F;
27     if (ref $filename) {        # filehandle
28         $F = $filename;
29     }
30     else {
31         open F, ">$filename" or die "Can't open $filename: $!";
32         $F = \*F;
33     }
34     print $F $leader if $leader;
35     seek IN, 0, 0;              # so we may restart
36     while (<IN>) {
37         chomp;
38         next if /^:/;
39         while (s|\\$||) {
40             $_ .= <IN>;
41             chomp;
42         }
43         my @args;
44         if (/^\s*(#|$)/) {
45             @args = $_;
46         }
47         else {
48             @args = split /\s*\|\s*/, $_;
49         }
50         print $F $function->(@args);
51     }
52     print $F $trailer if $trailer;
53     close $F unless ref $filename;
54 }
55
56 my %apidocs;
57 my %gutsdocs;
58 my %docfuncs;
59
60 my $curheader = "Unknown section";
61
62 sub autodoc ($$) { # parse a file and extract documentation info
63     my($fh,$file) = @_;
64     my($in, $doc, $line);
65 FUNC:
66     while (defined($in = <$fh>)) {
67         if ($in=~ /^=head1 (.*)/) {
68             $curheader = $1;
69             next FUNC;
70         }
71         $line++;
72         if ($in =~ /^=for\s+apidoc\s+(.*)\n/) {
73             my $proto = $1;
74             $proto = "||$proto" unless $proto =~ /\|/;
75             my($flags, $ret, $name, @args) = split /\|/, $proto;
76             my $docs = "";
77 DOC:
78             while (defined($doc = <$fh>)) {
79                 if ($doc =~ /^=head1 (.*)/) {
80                     $curheader = $1;
81                     next DOC;
82                 }
83                 $line++;
84                 last DOC if $doc =~ /^=\w+/;
85                 if ($doc =~ m:^\*/$:) {
86                     warn "=cut missing? $file:$line:$doc";;
87                     last DOC;
88                 }
89                 $docs .= $doc;
90             }
91             $docs = "\n$docs" if $docs and $docs !~ /^\n/;
92             if ($flags =~ /m/) {
93                 if ($flags =~ /A/) {
94                     $apidocs{$curheader}{$name} = [$flags, $docs, $ret, $file, @args];
95                 }
96                 else {
97                     $gutsdocs{$curheader}{$name} = [$flags, $docs, $ret, $file, @args];
98                 }
99             }
100             else {
101                 $docfuncs{$name} = [$flags, $docs, $ret, $file, $curheader, @args];
102             }
103             if (defined $doc) {
104                 if ($doc =~ /^=for/) {
105                     $in = $doc;
106                     redo FUNC;
107                 }
108             } else {
109                 warn "$file:$line:$in";
110             }
111         }
112     }
113 }
114
115 sub docout ($$$) { # output the docs for one function
116     my($fh, $name, $docref) = @_;
117     my($flags, $docs, $ret, $file, @args) = @$docref;
118
119     $docs .= "NOTE: this function is experimental and may change or be
120 removed without notice.\n\n" if $flags =~ /x/;
121     $docs .= "NOTE: the perl_ form of this function is deprecated.\n\n"
122         if $flags =~ /p/;
123
124     print $fh "=item $name\n$docs";
125
126     if ($flags =~ /U/) { # no usage
127         # nothing
128     } elsif ($flags =~ /s/) { # semicolon ("dTHR;")
129         print $fh "\t\t$name;\n\n";
130     } elsif ($flags =~ /n/) { # no args
131         print $fh "\t$ret\t$name\n\n";
132     } else { # full usage
133         print $fh "\t$ret\t$name";
134         print $fh "(" . join(", ", @args) . ")";
135         print $fh "\n\n";
136     }
137     print $fh "=for hackers\nFound in file $file\n\n";
138 }
139
140 my $file;
141 for $file (glob('*.c'), glob('*.h')) {
142     open F, "< $file" or die "Cannot open $file for docs: $!\n";
143     $curheader = "Functions in file $file\n";
144     autodoc(\*F,$file);
145     close F or die "Error closing $file: $!\n";
146 }
147
148 unlink "pod/perlapi.pod";
149 open (DOC, ">pod/perlapi.pod") or
150         die "Can't create pod/perlapi.pod: $!\n";
151
152 walk_table {    # load documented functions into approriate hash
153     if (@_ > 1) {
154         my($flags, $retval, $func, @args) = @_;
155         return "" unless $flags =~ /d/;
156         $func =~ s/\t//g; $flags =~ s/p//; # clean up fields from embed.pl
157         $retval =~ s/\t//;
158         if ($flags =~ /A/) {
159             my $docref = delete $docfuncs{$func};
160             warn "no docs for $func\n" unless $docref and @$docref;
161             $docref->[0].="x" if $flags =~ /M/;
162             $apidocs{$docref->[4]}{$func} = 
163                 [$docref->[0] . 'A', $docref->[1], $retval, $docref->[3], @args];
164         } else {
165             my $docref = delete $docfuncs{$func};
166             $gutsdocs{$docref->[4]}{$func} = 
167                 [$docref->[0], $docref->[1], $retval, $docref->[3], @args];
168         }
169     }
170     return "";
171 } \*DOC;
172
173 for (sort keys %docfuncs) {
174     # Have you used a full for apidoc or just a func name?
175     # Have you used Ap instead of Am in the for apidoc?
176     warn "Unable to place $_!\n";
177 }
178
179 print DOC <<'_EOB_';
180 =head1 NAME
181
182 perlapi - autogenerated documentation for the perl public API
183
184 =head1 DESCRIPTION
185
186 This file contains the documentation of the perl public API generated by
187 embed.pl, specifically a listing of functions, macros, flags, and variables
188 that may be used by extension writers.  The interfaces of any functions that
189 are not listed here are subject to change without notice.  For this reason,
190 blindly using functions listed in proto.h is to be avoided when writing
191 extensions.
192
193 Note that all Perl API global variables must be referenced with the C<PL_>
194 prefix.  Some macros are provided for compatibility with the older,
195 unadorned names, but this support may be disabled in a future release.
196
197 The listing is alphabetical, case insensitive.
198
199 _EOB_
200
201 my $key;
202 for $key (sort { uc($a) cmp uc($b); } keys %apidocs) { # case insensitive sort
203     my $section = $apidocs{$key}; 
204     print DOC "\n=head1 $key\n\n=over 8\n\n";
205     for my $key (sort { uc($a) cmp uc($b); } keys %$section) {
206         docout(\*DOC, $key, $section->{$key});
207     }
208     print DOC "\n=back\n";
209 }
210
211 print DOC <<'_EOE_';
212
213 =head1 AUTHORS
214
215 Until May 1997, this document was maintained by Jeff Okamoto
216 <okamoto@corp.hp.com>.  It is now maintained as part of Perl itself.
217
218 With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
219 Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
220 Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
221 Stephen McCamant, and Gurusamy Sarathy.
222
223 API Listing originally by Dean Roehrich <roehrich@cray.com>.
224
225 Updated to be autogenerated from comments in the source by Benjamin Stuhl.
226
227 =head1 SEE ALSO
228
229 perlguts(1), perlxs(1), perlxstut(1), perlintern(1)
230
231 _EOE_
232
233
234 close(DOC);
235
236 open(GUTS, ">pod/perlintern.pod") or
237                 die "Unable to create pod/perlintern.pod: $!\n";
238 print GUTS <<'END';
239 =head1 NAME
240
241 perlintern - autogenerated documentation of purely B<internal>
242                  Perl functions
243
244 =head1 DESCRIPTION
245
246 This file is the autogenerated documentation of functions in the
247 Perl interpreter that are documented using Perl's internal documentation
248 format but are not marked as part of the Perl API. In other words,
249 B<they are not for use in extensions>!
250
251 END
252
253 for $key (sort { uc($a) cmp uc($b); } keys %gutsdocs) {
254     my $section = $gutsdocs{$key}; 
255     print GUTS "\n=head1 $key\n\n=over 8\n\n";
256     for my $key (sort { uc($a) cmp uc($b); } keys %$section) {
257         docout(\*GUTS, $key, $section->{$key});
258     }
259     print GUTS "\n=back\n";
260 }
261
262 print GUTS <<'END';
263
264 =head1 AUTHORS
265
266 The autodocumentation system was originally added to the Perl core by
267 Benjamin Stuhl. Documentation is by whoever was kind enough to
268 document their functions.
269
270 =head1 SEE ALSO
271
272 perlguts(1), perlapi(1)
273
274 END
275
276 close GUTS;
277