]> git.imager.perl.org - imager.git/blob - apidocs.perl
67f108f3159c0e6e9d52cac42ea130efa0a5b63b
[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 print OUT <<'EOS';
83 Do not edit this file, it is generated automatically by apidocs.perl
84 from Imager's source files.
85
86 Each function description has a comment listing the source file where
87 you can find the documentation.
88
89 =head1 NAME
90
91 Imager::APIRef - Imager's C API - reference.
92
93 =head1 SYNOPSIS
94
95   i_color color;
96   color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255;
97
98 EOS
99
100 for my $cat (sort { lc $a cmp lc $b } keys %cats) {
101   print OUT "\n  # $cat\n";
102   for my $func (grep $funcsyns{$_}, sort { $order{$a} <=> $order{$b} } @{$cats{$cat}}) {
103     my $syn = $funcsyns{$func};
104     $syn =~ s/^/  /gm;
105     print OUT $syn;
106   }
107 }
108
109 print OUT <<'EOS';
110
111 =head1 DESCRIPTION
112
113 EOS
114
115 my %undoc = %funcs;
116
117 for my $cat (sort { lc $a cmp lc $b } keys %cats) {
118   print OUT "=head2 $cat\n\n=over\n\n";
119   my @ordered_funcs = sort {
120     $order{$a} <=> $order{$b}
121       || lc $a cmp lc $b
122     } @{$cats{$cat}};
123   for my $func (@ordered_funcs) {
124     print OUT @{$alldocs{$func}}, "\n";
125     print OUT "=for comment\nFrom: $from{$func}\n\n";
126     delete $undoc{$func};
127   }
128   print OUT "\n=back\n\n";
129 }
130
131 # see if we have an uncategorised section
132 if (grep $alldocs{$_}, keys %undoc) {
133   print OUT "=head2 Uncategorized functions\n\n=over\n\n";
134   #print join(",", grep !exists $order{$_}, @funcs), "\n";
135   for my $func (sort { $order{$a} <=> $order{$b} || $a cmp $b }
136                 grep $undoc{$_} && $alldocs{$_}, @funcs) {
137     print OUT @{$alldocs{$func}}, "\n";
138     print OUT "=for comment\nFrom: $from{$func}\n\n";
139     delete $undoc{$func};
140   }
141   print OUT "\n\n=back\n\n";
142 }
143
144 if (keys %undoc) {
145   print OUT <<'EOS';
146
147 =head1 UNDOCUMENTED
148
149 The following API functions are undocumented so far, hopefully this
150 will change:
151
152 =over
153
154 EOS
155
156   print OUT "=item *\n\nB<$_>\n\n" for sort keys %undoc;
157
158   print OUT "\n\n=back\n\n";
159 }
160
161 print OUT <<'EOS';
162
163 =head1 AUTHOR
164
165 Tony Cook <tonyc@cpan.org>
166
167 =head1 SEE ALSO
168
169 Imager, Imager::ExtUtils, Imager::Inline
170
171 =cut
172 EOS
173
174 close OUT;
175
176
177 sub make_func_list {
178   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);
179   open FUNCS, "< imexttypes.h"
180     or die "Cannot open imexttypes.h: $!\n";
181   my $in_struct;
182   while (<FUNCS>) {
183     /^typedef struct/ && ++$in_struct;
184     if ($in_struct && /\(\*f_(i_\w+)/) {
185       push @funcs, $1;
186     }
187     if (/^\} im_ext_funcs;$/) {
188       $in_struct
189         or die "Found end of functions structure but not the start";
190
191       close FUNCS;
192       return @funcs;
193     }
194   }
195   if ($in_struct) {
196     die "Found start of the functions structure but not the end\n";
197   }
198   else {
199     die "Found neither the start nor end of the functions structure\n";
200   }
201 }
202
203 =head1 NAME
204
205 apidocs.perl - parse Imager's source for POD documenting the C API
206
207 =head1 SYNOPSIS
208
209   perl apidocs.perl lib/Imager/APIRef.pod
210
211 =head1 DESCRIPTION
212
213 Parses Imager's C sources, including .c, .h and .im files searching
214 for function documentation.
215
216 Besides the normal POD markup, the following can be included:
217
218 =over
219
220 =item =category I<category-name>
221
222 The category the function should be in.
223
224 =item =synopsis I<sample-code>
225
226 Sample code using the function to include in the Imager::APIRef SYNOPSIS
227
228 =item =order I<integer>
229
230 Allows a function to be listed out of order.  If this isn't specified
231 it defaults to 50, so a value of 10 will cause the function to be
232 listed at the beginning of its category, or 90 to list at the end.
233
234 Functions with equal order are otherwise ordered by name.
235
236 =back
237
238 =head1 AUTHOR
239
240 Tony Cook <tonyc@cpan.org>
241
242 =cut
243