source: trunk/third/perl/autodoc.pl @ 18450

Revision 18450, 7.2 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18449, which included commits to RCS files with non-trunk default branches.
Line 
1#!/usr/bin/perl -w
2
3require 5.003;  # keep this compatible, an old perl is all we may have before
4                # we build the new one
5
6BEGIN {  push @INC, 'lib' }     # glob() below requires File::Glob
7
8
9#
10# See database of global and static function prototypes in embed.fnc
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
16open IN, "embed.fnc" or die $!;
17
18# walk table providing an array of components in each line to
19# subroutine, printing the result
20sub 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
56my %apidocs;
57my %gutsdocs;
58my %docfuncs;
59
60my $curheader = "Unknown section";
61
62sub autodoc ($$) { # parse a file and extract documentation info
63    my($fh,$file) = @_;
64    my($in, $doc, $line);
65FUNC:
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 = "";
77DOC:
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
115sub 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
120removed 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
140my $file;
141for $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
148unlink "pod/perlapi.pod";
149open (DOC, ">pod/perlapi.pod") or
150        die "Can't create pod/perlapi.pod: $!\n";
151
152walk_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
173for (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
179print DOC <<'_EOB_';
180=head1 NAME
181
182perlapi - autogenerated documentation for the perl public API
183
184=head1 DESCRIPTION
185
186This file contains the documentation of the perl public API generated by
187embed.pl, specifically a listing of functions, macros, flags, and variables
188that may be used by extension writers.  The interfaces of any functions that
189are not listed here are subject to change without notice.  For this reason,
190blindly using functions listed in proto.h is to be avoided when writing
191extensions.
192
193Note that all Perl API global variables must be referenced with the C<PL_>
194prefix.  Some macros are provided for compatibility with the older,
195unadorned names, but this support may be disabled in a future release.
196
197The listing is alphabetical, case insensitive.
198
199_EOB_
200
201my $key;
202for $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
211print DOC <<'_EOE_';
212
213=head1 AUTHORS
214
215Until May 1997, this document was maintained by Jeff Okamoto
216<okamoto@corp.hp.com>.  It is now maintained as part of Perl itself.
217
218With lots of help and suggestions from Dean Roehrich, Malcolm Beattie,
219Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil
220Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer,
221Stephen McCamant, and Gurusamy Sarathy.
222
223API Listing originally by Dean Roehrich <roehrich@cray.com>.
224
225Updated to be autogenerated from comments in the source by Benjamin Stuhl.
226
227=head1 SEE ALSO
228
229perlguts(1), perlxs(1), perlxstut(1), perlintern(1)
230
231_EOE_
232
233
234close(DOC);
235
236open(GUTS, ">pod/perlintern.pod") or
237                die "Unable to create pod/perlintern.pod: $!\n";
238print GUTS <<'END';
239=head1 NAME
240
241perlintern - autogenerated documentation of purely B<internal>
242                 Perl functions
243
244=head1 DESCRIPTION
245
246This file is the autogenerated documentation of functions in the
247Perl interpreter that are documented using Perl's internal documentation
248format but are not marked as part of the Perl API. In other words,
249B<they are not for use in extensions>!
250
251END
252
253for $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
262print GUTS <<'END';
263
264=head1 AUTHORS
265
266The autodocumentation system was originally added to the Perl core by
267Benjamin Stuhl. Documentation is by whoever was kind enough to
268document their functions.
269
270=head1 SEE ALSO
271
272perlguts(1), perlapi(1)
273
274END
275
276close GUTS;
277
Note: See TracBrowser for help on using the repository browser.