Contents of /tags/mkinitrd-6_1_7/busybox/docs/autodocifier.pl
Parent Directory | Revision Log
Revision 909 -
(show annotations)
(download)
Fri Oct 16 13:40:14 2009 UTC (14 years, 11 months ago) by niro
File MIME type: text/plain
File size: 6537 byte(s)
Fri Oct 16 13:40:14 2009 UTC (14 years, 11 months ago) by niro
File MIME type: text/plain
File size: 6537 byte(s)
tagged 'mkinitrd-6_1_7'
1 | #!/usr/bin/perl -w |
2 | # vi: set sw=4 ts=4: |
3 | |
4 | use strict; |
5 | use Getopt::Long; |
6 | |
7 | # collect lines continued with a '\' into an array |
8 | sub continuation { |
9 | my $fh = shift; |
10 | my @line; |
11 | |
12 | while (<$fh>) { |
13 | my $s = $_; |
14 | $s =~ s/\\\s*$//; |
15 | #$s =~ s/#.*$//; |
16 | push @line, $s; |
17 | last unless (/\\\s*$/); |
18 | } |
19 | return @line; |
20 | } |
21 | |
22 | # regex && eval away unwanted strings from documentation |
23 | sub beautify { |
24 | my $text = shift; |
25 | for (;;) { |
26 | my $text2 = $text; |
27 | $text =~ s/SKIP_\w+\(.*?"\s*\)//sxg; |
28 | $text =~ s/USE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg; |
29 | $text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg; |
30 | last if ( $text2 eq $text ); |
31 | } |
32 | $text =~ s/"\s*"//sg; |
33 | my @line = split("\n", $text); |
34 | $text = join('', |
35 | map { |
36 | s/^\s*"//; |
37 | s/"\s*$//; |
38 | s/%/%%/g; |
39 | s/\$/\\\$/g; |
40 | s/\@/\\\@/g; |
41 | eval qq[ sprintf(qq{$_}) ] |
42 | } @line |
43 | ); |
44 | return $text; |
45 | } |
46 | |
47 | # generate POD for an applet |
48 | sub pod_for_usage { |
49 | my $name = shift; |
50 | my $usage = shift; |
51 | |
52 | # Sigh. Fixup the known odd-name applets. |
53 | # Perhaps we can use some of APPLET_ODDNAME from include/applets.h ? |
54 | $name =~ s/dpkg_deb/dpkg-deb/g; |
55 | $name =~ s/fsck_minix/fsck.minix/g; |
56 | $name =~ s/mkfs_minix/mkfs.minix/g; |
57 | $name =~ s/run_parts/run-parts/g; |
58 | $name =~ s/start_stop_daemon/start-stop-daemon/g; |
59 | $name =~ s/ether_wake/ether-wake/g; |
60 | |
61 | # make options bold |
62 | my $trivial = $usage->{trivial}; |
63 | if (!defined $usage->{trivial}) { |
64 | $trivial = ""; |
65 | } else { |
66 | $trivial =~ s/(?<!\w)(-\w+)/B<$1>/sxg; |
67 | } |
68 | my @f0 = |
69 | map { $_ !~ /^\s/ && s/(?<!\w)(-\w+)/B<$1>/g; $_ } |
70 | split("\n", (defined $usage->{full} ? $usage->{full} : "")); |
71 | |
72 | # add "\n" prior to certain lines to make indented |
73 | # lines look right |
74 | my @f1; |
75 | my $len = @f0; |
76 | for (my $i = 0; $i < $len; $i++) { |
77 | push @f1, $f0[$i]; |
78 | if (($i+1) != $len && $f0[$i] !~ /^\s/ && $f0[$i+1] =~ /^\s/) { |
79 | next if ($f0[$i] =~ /^$/); |
80 | push(@f1, "") unless ($f0[$i+1] =~ /^\s*$/s); |
81 | } |
82 | } |
83 | my $full = join("\n", @f1); |
84 | |
85 | # prepare notes if they exist |
86 | my $notes = (defined $usage->{notes}) |
87 | ? "$usage->{notes}\n\n" |
88 | : ""; |
89 | |
90 | # prepare examples if they exist |
91 | my $example = (defined $usage->{example}) |
92 | ? |
93 | "Example:\n\n" . |
94 | join ("\n", |
95 | map { "\t$_" } |
96 | split("\n", $usage->{example})) . "\n\n" |
97 | : ""; |
98 | |
99 | # Pad the name so that the applet name gets a line |
100 | # by itself in BusyBox.txt |
101 | my $spaces = 10 - length($name); |
102 | if ($spaces > 0) { |
103 | $name .= " " x $spaces; |
104 | } |
105 | |
106 | return |
107 | "=item B<$name>". |
108 | "\n\n$name $trivial\n\n". |
109 | "$full\n\n" . |
110 | "$notes" . |
111 | "$example" . |
112 | "\n\n" |
113 | ; |
114 | } |
115 | |
116 | # the keys are applet names, and |
117 | # the values will contain hashrefs of the form: |
118 | # |
119 | # { |
120 | # trivial => "...", |
121 | # full => "...", |
122 | # notes => "...", |
123 | # example => "...", |
124 | # } |
125 | my %docs; |
126 | |
127 | |
128 | # get command-line options |
129 | |
130 | my %opt; |
131 | |
132 | GetOptions( |
133 | \%opt, |
134 | "help|h", |
135 | "pod|p", |
136 | "verbose|v", |
137 | ); |
138 | |
139 | if (defined $opt{help}) { |
140 | |
141 | "$0 [OPTION]... [FILE]...\n", |
142 | "\t--help\n", |
143 | "\t--pod\n", |
144 | "\t--verbose\n", |
145 | ; |
146 | exit 1; |
147 | } |
148 | |
149 | |
150 | # collect documenation into %docs |
151 | |
152 | foreach (@ARGV) { |
153 | open(USAGE, $_) || die("$0: $_: $!"); |
154 | my $fh = *USAGE; |
155 | my ($applet, $type, @line); |
156 | while (<$fh>) { |
157 | if (/^#define (\w+)_(\w+)_usage/) { |
158 | $applet = $1; |
159 | $type = $2; |
160 | @line = continuation($fh); |
161 | my $doc = $docs{$applet} ||= { }; |
162 | my $text = join("\n", @line); |
163 | $doc->{$type} = beautify($text); |
164 | } |
165 | } |
166 | } |
167 | |
168 | |
169 | # generate structured documentation |
170 | |
171 | my $generator = \&pod_for_usage; |
172 | |
173 | my @names = sort keys %docs; |
174 | my $line = "\t[, [[, "; |
175 | for (my $i = 0; $i < $#names; $i++) { |
176 | if (length ($line.$names[$i]) >= 65) { |
177 | print "$line\n\t"; |
178 | $line = ""; |
179 | } |
180 | $line .= "$names[$i], "; |
181 | } |
182 | print $line . $names[-1]; |
183 | |
184 | print "\n\n=head1 COMMAND DESCRIPTIONS\n"; |
185 | print "\n=over 4\n\n"; |
186 | |
187 | foreach my $applet (@names) { |
188 | print $generator->($applet, $docs{$applet}); |
189 | } |
190 | |
191 | exit 0; |
192 | |
193 | __END__ |
194 | |
195 | =head1 NAME |
196 | |
197 | autodocifier.pl - generate docs for busybox based on usage.h |
198 | |
199 | =head1 SYNOPSIS |
200 | |
201 | autodocifier.pl [OPTION]... [FILE]... |
202 | |
203 | Example: |
204 | |
205 | ( cat docs/busybox_header.pod; \ |
206 | docs/autodocifier.pl usage.h; \ |
207 | cat docs/busybox_footer.pod ) > docs/busybox.pod |
208 | |
209 | =head1 DESCRIPTION |
210 | |
211 | The purpose of this script is to automagically generate |
212 | documentation for busybox using its usage.h as the original source |
213 | for content. It used to be that same content has to be duplicated |
214 | in 3 places in slightly different formats -- F<usage.h>, |
215 | F<docs/busybox.pod>. This was tedious and error-prone, so it was |
216 | decided that F<usage.h> would contain all the text in a |
217 | machine-readable form, and scripts could be used to transform this |
218 | text into other forms if necessary. |
219 | |
220 | F<autodocifier.pl> is one such script. It is based on a script by |
221 | Erik Andersen <andersen@codepoet.org> which was in turn based on a |
222 | script by Mark Whitley <markw@codepoet.org> |
223 | |
224 | =head1 OPTIONS |
225 | |
226 | =over 4 |
227 | |
228 | =item B<--help> |
229 | |
230 | This displays the help message. |
231 | |
232 | =item B<--pod> |
233 | |
234 | Generate POD (this is the default) |
235 | |
236 | =item B<--verbose> |
237 | |
238 | Be verbose (not implemented) |
239 | |
240 | =back |
241 | |
242 | =head1 FORMAT |
243 | |
244 | The following is an example of some data this script might parse. |
245 | |
246 | #define length_trivial_usage \ |
247 | "STRING" |
248 | #define length_full_usage \ |
249 | "Prints out the length of the specified STRING." |
250 | #define length_example_usage \ |
251 | "$ length Hello\n" \ |
252 | "5\n" |
253 | |
254 | Each entry is a cpp macro that defines a string. The macros are |
255 | named systematically in the form: |
256 | |
257 | $name_$type_usage |
258 | |
259 | $name is the name of the applet. $type can be "trivial", "full", "notes", |
260 | or "example". Every documentation macro must end with "_usage". |
261 | |
262 | The definition of the types is as follows: |
263 | |
264 | =over 4 |
265 | |
266 | =item B<trivial> |
267 | |
268 | This should be a brief, one-line description of parameters that |
269 | the command expects. This will be displayed when B<-h> is issued to |
270 | a command. I<REQUIRED> |
271 | |
272 | =item B<full> |
273 | |
274 | This should contain descriptions of each option. This will also |
275 | be displayed along with the trivial help if CONFIG_FEATURE_TRIVIAL_HELP |
276 | is disabled. I<REQUIRED> |
277 | |
278 | =item B<notes> |
279 | |
280 | This is documentation that is intended to go in the POD or SGML, but |
281 | not be printed when a B<-h> is given to a command. To see an example |
282 | of notes being used, see init_notes_usage in F<usage.h>. I<OPTIONAL> |
283 | |
284 | =item B<example> |
285 | |
286 | This should be an example of how the command is actually used. |
287 | This will not be printed when a B<-h> is given to a command -- it |
288 | will only be included in the POD or SGML documentation. I<OPTIONAL> |
289 | |
290 | =back |
291 | |
292 | =head1 FILES |
293 | |
294 | F<usage.h> |
295 | |
296 | =head1 COPYRIGHT |
297 | |
298 | Copyright (c) 2001 John BEPPU. All rights reserved. This program is |
299 | free software; you can redistribute it and/or modify it under the same |
300 | terms as Perl itself. |
301 | |
302 | =head1 AUTHOR |
303 | |
304 | John BEPPU <b@ax9.org> |
305 | |
306 | =cut |
307 |
Properties
Name | Value |
---|---|
svn:executable | * |