]> git.imager.perl.org - imager.git/blob - apidocs.perl
7c5016dee1c0745fec8bddcc9313d78a01aaf2f5
[imager.git] / apidocs.perl
1 #!perl -w
2 use strict;
3 use ExtUtils::Manifest 'maniread';
4
5 my $outname = shift || '-';
6
7 my @funcs = make_func_list();
8 my %funcs = map { $_ => 1 } @funcs;
9
10 # look for files to parse
11
12 my $mani = maniread;
13 my @files = grep /\.(c|im|h)$/, keys %$mani;
14
15 # scan each file for =item <func>\b
16 my $func;
17 my $start;
18 my %alldocs;
19 my @funcdocs;
20 my %from;
21 my $category;
22 my %funccats;
23 my %cats;
24 my $synopsis = '';
25 my %funcsyns;
26 my $order;
27 my %order;
28 for 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 ];
40         $from{$func} = "File $file";
41         if ($category) {
42           $funccats{$func} = $category;
43           push @{$cats{$category}}, $func;
44         }
45         if ($synopsis) {
46           $funcsyns{$func} = $synopsis;
47         }
48         defined $order or $order = 50;
49         $order{$func} = $order;
50       }
51       undef $func;
52       undef $category;
53       undef $order;
54       $synopsis = '';
55     }
56     elsif ($func) {
57       if (/^=category (.*)/) {
58         $category = $1;
59       }
60       elsif (/^=synopsis (.*)/) {
61         $synopsis .= "$1\n";
62       }
63       elsif (/^=order (.*)$/) {
64         $order = $1;
65         $order =~ /^\d+$/
66           or die "=order must specify a number for $func in $file\n";
67       }
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
79 open OUT, "> $outname"
80   or die "Cannot open $outname: $!";
81
82 # I keep this file in git and as part of the dist, make sure newlines
83 # don't mess me up
84 binmode OUT;
85
86 print OUT <<'EOS';
87 Do not edit this file, it is generated automatically by apidocs.perl
88 from Imager's source files.
89
90 Each function description has a comment listing the source file where
91 you can find the documentation.
92
93 =head1 NAME
94
95 Imager::APIRef - Imager's C API - reference.
96
97 =head1 SYNOPSIS
98
99   i_color color;
100   color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255;
101
102 EOS
103
104 for my $cat (sort { lc $a cmp lc $b } keys %cats) {
105   print OUT "\n  # $cat\n";
106   for my $func (grep $funcsyns{$_}, sort { $order{$a} <=> $order{$b} } @{$cats{$cat}}) {
107     my $syn = $funcsyns{$func};
108     $syn =~ s/^/  /gm;
109     print OUT $syn;
110   }
111 }
112
113 print OUT <<'EOS';
114
115 =head1 DESCRIPTION
116
117 EOS
118
119 my %undoc = %funcs;
120
121 for my $cat (sort { lc $a cmp lc $b } keys %cats) {
122   print OUT "=head2 $cat\n\n=over\n\n";
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) {
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
135 # see if we have an uncategorised section
136 if (grep $alldocs{$_}, keys %undoc) {
137   print OUT "=head2 Uncategorized functions\n\n=over\n\n";
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};
144   }
145   print OUT "\n\n=back\n\n";
146 }
147
148 if (keys %undoc) {
149   print OUT <<'EOS';
150
151 =head1 UNDOCUMENTED
152
153 The following API functions are undocumented so far, hopefully this
154 will change:
155
156 =over
157
158 EOS
159
160   print OUT "=item *\n\nB<$_>\n\n" for sort keys %undoc;
161
162   print OUT "\n\n=back\n\n";
163 }
164
165 print OUT <<'EOS';
166
167 =head1 AUTHOR
168
169 Tony Cook <tonyc@cpan.org>
170
171 =head1 SEE ALSO
172
173 Imager, Imager::ExtUtils, Imager::Inline
174
175 =cut
176 EOS
177
178 close OUT;
179
180
181 sub make_func_list {
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);
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 }
206
207 =head1 NAME
208
209 apidocs.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
217 Parses Imager's C sources, including .c, .h and .im files searching
218 for function documentation.
219
220 Besides the normal POD markup, the following can be included:
221
222 =over
223
224 =item =category I<category-name>
225
226 The category the function should be in.
227
228 =item =synopsis I<sample-code>
229
230 Sample code using the function to include in the Imager::APIRef SYNOPSIS
231
232 =item =order I<integer>
233
234 Allows a function to be listed out of order.  If this isn't specified
235 it defaults to 50, so a value of 10 will cause the function to be
236 listed at the beginning of its category, or 90 to list at the end.
237
238 Functions with equal order are otherwise ordered by name.
239
240 =back
241
242 =head1 AUTHOR
243
244 Tony Cook <tonyc@cpan.org>
245
246 =cut
247