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