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