0.84 release
[imager.git] / apidocs.perl
CommitLineData
92bda632
TC
1#!perl -w
2use strict;
fe415ad2 3use ExtUtils::Manifest 'maniread';
92bda632
TC
4
5my $outname = shift || '-';
6
92bda632
TC
7my @funcs = make_func_list();
8my %funcs = map { $_ => 1 } @funcs;
9
10# look for files to parse
11
fe415ad2 12my $mani = maniread;
bd8052a6 13my @files = grep /\.(c|im|h)$/, keys %$mani;
92bda632
TC
14
15# scan each file for =item <func>\b
16my $func;
17my $start;
18my %alldocs;
19my @funcdocs;
20my %from;
21my $category;
22my %funccats;
23my %cats;
24my $synopsis = '';
25my %funcsyns;
6cfee9d1
TC
26my $order;
27my %order;
92bda632
TC
28for my $file (@files) {
29 open SRC, "< $file"
30 or die "Cannot open $file for documentation: $!\n";
31 while (<SRC>) {
32 if (/^=item (\w+)\b/ && $funcs{$1}) {
33 $func = $1;
34 $start = $.;
35 @funcdocs = $_;
36 }
37 elsif ($func && /^=(cut|head)/) {
38 if ($funcs{$func}) { # only save the API functions
39 $alldocs{$func} = [ @funcdocs ];
5ca7e2ab 40 $from{$func} = "File $file";
92bda632
TC
41 if ($category) {
42 $funccats{$func} = $category;
43 push @{$cats{$category}}, $func;
44 }
45 if ($synopsis) {
46 $funcsyns{$func} = $synopsis;
47 }
6cfee9d1
TC
48 defined $order or $order = 50;
49 $order{$func} = $order;
92bda632
TC
50 }
51 undef $func;
52 undef $category;
6cfee9d1 53 undef $order;
92bda632
TC
54 $synopsis = '';
55 }
56 elsif ($func) {
57 if (/^=category (.*)/) {
58 $category = $1;
59 }
60 elsif (/^=synopsis (.*)/) {
61 $synopsis .= "$1\n";
62 }
6cfee9d1
TC
63 elsif (/^=order (.*)$/) {
64 $order = $1;
65 $order =~ /^\d+$/
66 or die "=order must specify a number for $func in $file\n";
67 }
92bda632
TC
68 else {
69 push @funcdocs, $_;
70 }
71 }
72 }
73 $func and
74 die "Documentation for $func not followed by =cut or =head in $file\n";
75
76 close SRC;
77}
78
79open OUT, "> $outname"
80 or die "Cannot open $outname: $!";
81
091760c5
TC
82# I keep this file in git and as part of the dist, make sure newlines
83# don't mess me up
84binmode OUT;
85
92bda632
TC
86print OUT <<'EOS';
87Do not edit this file, it is generated automatically by apidocs.perl
88from Imager's source files.
89
5ca7e2ab
TC
90Each function description has a comment listing the source file where
91you can find the documentation.
92bda632
TC
92
93=head1 NAME
94
6cfee9d1 95Imager::APIRef - Imager's C API - reference.
92bda632
TC
96
97=head1 SYNOPSIS
98
99 i_color color;
6cfee9d1 100 color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255;
92bda632
TC
101
102EOS
103
104for my $cat (sort { lc $a cmp lc $b } keys %cats) {
105 print OUT "\n # $cat\n";
6cfee9d1 106 for my $func (grep $funcsyns{$_}, sort { $order{$a} <=> $order{$b} } @{$cats{$cat}}) {
92bda632
TC
107 my $syn = $funcsyns{$func};
108 $syn =~ s/^/ /gm;
109 print OUT $syn;
110 }
111}
112
113print OUT <<'EOS';
114
92bda632
TC
115=head1 DESCRIPTION
116
117EOS
118
119my %undoc = %funcs;
120
121for my $cat (sort { lc $a cmp lc $b } keys %cats) {
122 print OUT "=head2 $cat\n\n=over\n\n";
6cfee9d1
TC
123 my @ordered_funcs = sort {
124 $order{$a} <=> $order{$b}
125 || lc $a cmp lc $b
126 } @{$cats{$cat}};
127 for my $func (@ordered_funcs) {
92bda632
TC
128 print OUT @{$alldocs{$func}}, "\n";
129 print OUT "=for comment\nFrom: $from{$func}\n\n";
130 delete $undoc{$func};
131 }
132 print OUT "\n=back\n\n";
133}
134
50c75381 135# see if we have an uncategorised section
92bda632
TC
136if (grep $alldocs{$_}, keys %undoc) {
137 print OUT "=head2 Uncategorized functions\n\n=over\n\n";
6cfee9d1
TC
138 #print join(",", grep !exists $order{$_}, @funcs), "\n";
139 for my $func (sort { $order{$a} <=> $order{$b} || $a cmp $b }
140 grep $undoc{$_} && $alldocs{$_}, @funcs) {
141 print OUT @{$alldocs{$func}}, "\n";
142 print OUT "=for comment\nFrom: $from{$func}\n\n";
143 delete $undoc{$func};
92bda632
TC
144 }
145 print OUT "\n\n=back\n\n";
146}
147
148if (keys %undoc) {
149 print OUT <<'EOS';
150
151=head1 UNDOCUMENTED
152
153The following API functions are undocumented so far, hopefully this
154will change:
155
156=over
157
158EOS
159
160 print OUT "=item *\n\nB<$_>\n\n" for sort keys %undoc;
161
162 print OUT "\n\n=back\n\n";
163}
164
165print OUT <<'EOS';
166
167=head1 AUTHOR
168
5b480b14 169Tony Cook <tonyc@cpan.org>
92bda632
TC
170
171=head1 SEE ALSO
172
173Imager, Imager::ExtUtils, Imager::Inline
174
175=cut
176EOS
177
178close OUT;
179
180
181sub make_func_list {
6cfee9d1 182 my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log i_img_color_channels i_img_has_alpha i_img_dim);
92bda632
TC
183 open FUNCS, "< imexttypes.h"
184 or die "Cannot open imexttypes.h: $!\n";
185 my $in_struct;
186 while (<FUNCS>) {
187 /^typedef struct/ && ++$in_struct;
188 if ($in_struct && /\(\*f_(i_\w+)/) {
189 push @funcs, $1;
190 }
191 if (/^\} im_ext_funcs;$/) {
192 $in_struct
193 or die "Found end of functions structure but not the start";
194
195 close FUNCS;
196 return @funcs;
197 }
198 }
199 if ($in_struct) {
200 die "Found start of the functions structure but not the end\n";
201 }
202 else {
203 die "Found neither the start nor end of the functions structure\n";
204 }
205}
6cfee9d1
TC
206
207=head1 NAME
208
209apidocs.perl - parse Imager's source for POD documenting the C API
210
211=head1 SYNOPSIS
212
213 perl apidocs.perl lib/Imager/APIRef.pod
214
215=head1 DESCRIPTION
216
217Parses Imager's C sources, including .c, .h and .im files searching
218for function documentation.
219
220Besides the normal POD markup, the following can be included:
221
222=over
223
224=item =category I<category-name>
225
226The category the function should be in.
227
228=item =synopsis I<sample-code>
229
230Sample code using the function to include in the Imager::APIRef SYNOPSIS
231
232=item =order I<integer>
233
234Allows a function to be listed out of order. If this isn't specified
235it defaults to 50, so a value of 10 will cause the function to be
236listed at the beginning of its category, or 90 to list at the end.
237
238Functions with equal order are otherwise ordered by name.
239
240=back
241
242=head1 AUTHOR
243
244Tony Cook <tonyc@cpan.org>
245
246=cut
247