blob: 9133afb98746a39e1af6afd66c6869ea58eb7230 [file] [log] [blame]
Eric Andersene13bc0b2001-02-22 22:47:06 +00001#!/usr/bin/perl -w
Eric Andersene13bc0b2001-02-22 22:47:06 +00002
3use strict;
John Beppu4a25d8c2001-02-23 02:33:28 +00004use Getopt::Long;
Eric Andersene13bc0b2001-02-22 22:47:06 +00005
John Beppu4a25d8c2001-02-23 02:33:28 +00006# collect lines continued with a '\' into an array
7sub continuation {
8 my $fh = shift;
9 my @line;
Eric Andersene13bc0b2001-02-22 22:47:06 +000010
John Beppu4a25d8c2001-02-23 02:33:28 +000011 while (<$fh>) {
12 my $s = $_;
13 $s =~ s/\\\s*$//;
John Beppu79359d82001-04-05 20:03:33 +000014 #$s =~ s/#.*$//;
John Beppu4a25d8c2001-02-23 02:33:28 +000015 push @line, $s;
16 last unless (/\\\s*$/);
17 }
18 return @line;
19}
Eric Andersene13bc0b2001-02-22 22:47:06 +000020
John Beppu4a25d8c2001-02-23 02:33:28 +000021# regex && eval away unwanted strings from documentation
22sub beautify {
23 my $text = shift;
John Beppudbfff6c2001-02-23 17:55:03 +000024 $text =~ s/USAGE_NOT\w+\(.*?"\s*\)//sxg;
John Beppudf1e9da2001-02-23 16:15:34 +000025 $text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg;
26 $text =~ s/"\s*"//sg;
John Beppu4a25d8c2001-02-23 02:33:28 +000027 my @line = split("\n", $text);
28 $text = join('',
John Beppu4a25d8c2001-02-23 02:33:28 +000029 map {
30 s/^\s*//;
31 s/"//g;
John Beppu7d597c42001-02-24 14:37:48 +000032 s/%/%%/g;
John Beppud11578f2001-02-26 02:50:11 +000033 s/\$/\\\$/g;
John Beppu79359d82001-04-05 20:03:33 +000034 eval qq[ sprintf(qq{$_}) ]
John Beppu7d597c42001-02-24 14:37:48 +000035 } @line
John Beppu4a25d8c2001-02-23 02:33:28 +000036 );
37 return $text;
38}
Eric Andersene13bc0b2001-02-22 22:47:06 +000039
John Beppu4a25d8c2001-02-23 02:33:28 +000040# generate POD for an applet
41sub pod_for_usage {
42 my $name = shift;
43 my $usage = shift;
44
John Beppu8373e702001-02-23 17:41:41 +000045 # make options bold
John Beppu4a25d8c2001-02-23 02:33:28 +000046 my $trivial = $usage->{trivial};
John Beppud11578f2001-02-26 02:50:11 +000047 $trivial =~ s/(?<!\w)(-\w+)/B<$1>/sxg;
John Beppu8373e702001-02-23 17:41:41 +000048 my @f0 =
John Beppu4a25d8c2001-02-23 02:33:28 +000049 map { $_ !~ /^\s/ && s/(?<!\w)(-\w+)/B<$1>/g; $_ }
John Beppu8373e702001-02-23 17:41:41 +000050 split("\n", $usage->{full});
John Beppu4a25d8c2001-02-23 02:33:28 +000051
John Beppu8373e702001-02-23 17:41:41 +000052 # add "\n" prior to certain lines to make indented
53 # lines look right
John Beppu7d597c42001-02-24 14:37:48 +000054 my @f1;
John Beppu8373e702001-02-23 17:41:41 +000055 my $len = @f0;
56 for (my $i = 0; $i < $len; $i++) {
57 push @f1, $f0[$i];
58 if (($i+1) != $len && $f0[$i] !~ /^\s/ && $f0[$i+1] =~ /^\s/) {
59 next if ($f0[$i] =~ /^$/);
60 push(@f1, "") unless ($f0[$i+1] =~ /^\s*$/s);
61 }
62 }
John Beppu8373e702001-02-23 17:41:41 +000063 my $full = join("\n", @f1);
John Beppud11578f2001-02-26 02:50:11 +000064
Eric Andersen0d3a02e2001-03-15 18:14:25 +000065 # prepare notes if they exists
66 my $notes = (defined $usage->{notes})
67 ? "$usage->{notes}\n\n"
68 : "";
69
John Beppud11578f2001-02-26 02:50:11 +000070 # prepare example if one exists
71 my $example = (defined $usage->{example})
John Beppue708cb52001-03-15 21:08:01 +000072 ?
73 "Example:\n\n" .
74 join ("\n",
75 map { "\t$_" }
76 split("\n", $usage->{example})) . "\n\n"
John Beppud11578f2001-02-26 02:50:11 +000077 : "";
78
John Beppu4a25d8c2001-02-23 02:33:28 +000079 return
John Beppu9a1395b2001-04-05 19:35:17 +000080 "=item B<$name>".
John Beppud11578f2001-02-26 02:50:11 +000081 "\n\n" .
John Beppu4a25d8c2001-02-23 02:33:28 +000082 "$name $trivial".
John Beppud11578f2001-02-26 02:50:11 +000083 "\n\n" .
84 $full .
85 "\n\n" .
Eric Andersen0d3a02e2001-03-15 18:14:25 +000086 $notes .
John Beppud11578f2001-02-26 02:50:11 +000087 $example.
88 "-------------------------------".
John Beppu4a25d8c2001-02-23 02:33:28 +000089 "\n\n"
90 ;
91}
92
John Beppu7d597c42001-02-24 14:37:48 +000093# FIXME | generate SGML for an applet
John Beppu4a25d8c2001-02-23 02:33:28 +000094sub sgml_for_usage {
95 my $name = shift;
96 my $usage = shift;
97 return
John Beppue6967b22001-02-23 17:51:08 +000098 "<fixme>\n".
99 " $name\n".
100 "</fixme>\n"
101 ;
John Beppu4a25d8c2001-02-23 02:33:28 +0000102}
103
John Beppu8c16bc52001-02-23 02:54:31 +0000104# the keys are applet names, and
105# the values will contain hashrefs of the form:
106#
John Beppu4a25d8c2001-02-23 02:33:28 +0000107# {
108# trivial => "...",
109# full => "...",
John Beppu138ece02001-03-06 19:25:25 +0000110# example => "...",
John Beppu4a25d8c2001-02-23 02:33:28 +0000111# }
112my %docs;
113
John Beppu7d597c42001-02-24 14:37:48 +0000114
John Beppu4a25d8c2001-02-23 02:33:28 +0000115# get command-line options
John Beppu7d597c42001-02-24 14:37:48 +0000116
John Beppu4a25d8c2001-02-23 02:33:28 +0000117my %opt;
118
119GetOptions(
120 \%opt,
121 "help|h",
122 "sgml|s",
123 "pod|p",
124 "verbose|v",
125);
126
127if (defined $opt{help}) {
128 print
129 "$0 [OPTION]... [FILE]...\n",
130 "\t--help\n",
131 "\t--sgml\n",
132 "\t--pod\n",
133 "\t--verbose\n",
134 ;
135 exit 1;
136}
137
John Beppu7d597c42001-02-24 14:37:48 +0000138
John Beppu4a25d8c2001-02-23 02:33:28 +0000139# collect documenation into %docs
John Beppu7d597c42001-02-24 14:37:48 +0000140
John Beppu4a25d8c2001-02-23 02:33:28 +0000141foreach (@ARGV) {
John Beppud11578f2001-02-26 02:50:11 +0000142 open(USAGE, $_) || die("$0: $_: $!");
John Beppu4a25d8c2001-02-23 02:33:28 +0000143 my $fh = *USAGE;
144 my ($applet, $type, @line);
145 while (<$fh>) {
John Beppu4a25d8c2001-02-23 02:33:28 +0000146 if (/^#define (\w+)_(\w+)_usage/) {
147 $applet = $1;
148 $type = $2;
149 @line = continuation($fh);
150 my $doc = $docs{$applet} ||= { };
John Beppu4a25d8c2001-02-23 02:33:28 +0000151 my $text = join("\n", @line);
152 $doc->{$type} = beautify($text);
Eric Andersene13bc0b2001-02-22 22:47:06 +0000153 }
Eric Andersene13bc0b2001-02-22 22:47:06 +0000154 }
155}
John Beppu4a25d8c2001-02-23 02:33:28 +0000156
John Beppu7d597c42001-02-24 14:37:48 +0000157
158# generate structured documentation
159
John Beppue6967b22001-02-23 17:51:08 +0000160my $generator = \&pod_for_usage;
161if (defined $opt{sgml}) {
John Beppu7d597c42001-02-24 14:37:48 +0000162 $generator = \&sgml_for_usage;
John Beppue6967b22001-02-23 17:51:08 +0000163}
John Beppu4a25d8c2001-02-23 02:33:28 +0000164
John Beppu7d597c42001-02-24 14:37:48 +0000165foreach my $applet (sort keys %docs) {
166 print $generator->($applet, $docs{$applet});
John Beppu4a25d8c2001-02-23 02:33:28 +0000167}
168
169exit 0;
170
171__END__
172
173=head1 NAME
174
175autodocifier.pl - generate docs for busybox based on usage.h
176
177=head1 SYNOPSIS
178
179autodocifier.pl usage.h > something
180
181=head1 DESCRIPTION
182
183The purpose of this script is to automagically generate documentation
184for busybox using its usage.h as the original source for content.
185Currently, the same content has to be duplicated in 3 places in
186slightly different formats -- F<usage.h>, F<docs/busybox.pod>, and
John Beppub249fbb2001-02-23 03:12:45 +0000187F<docs/busybox.sgml>. This is tedious, so Perl has come to the rescue.
John Beppu4a25d8c2001-02-23 02:33:28 +0000188
John Beppub249fbb2001-02-23 03:12:45 +0000189This script was based on a script by Erik Andersen (andersen@lineo.com).
John Beppu4a25d8c2001-02-23 02:33:28 +0000190
191=head1 OPTIONS
192
John Beppue6967b22001-02-23 17:51:08 +0000193=over 4
John Beppu4a25d8c2001-02-23 02:33:28 +0000194
John Beppu9a1395b2001-04-05 19:35:17 +0000195=item B<--help>
John Beppu4a25d8c2001-02-23 02:33:28 +0000196
197This displays the help message.
198
John Beppu9a1395b2001-04-05 19:35:17 +0000199=item B<--pod>
John Beppue6967b22001-02-23 17:51:08 +0000200
201Generate POD (this is the default)
202
John Beppu9a1395b2001-04-05 19:35:17 +0000203=item B<--sgml>
John Beppue6967b22001-02-23 17:51:08 +0000204
205Generate SGML
206
John Beppu9a1395b2001-04-05 19:35:17 +0000207=item B<--verbose>
John Beppue6967b22001-02-23 17:51:08 +0000208
209Be verbose (not implemented)
210
John Beppu4a25d8c2001-02-23 02:33:28 +0000211=back
212
John Beppu9a1395b2001-04-05 19:35:17 +0000213=head1 FORMAT
214
215The following is an example of some data this script might parse.
216
217 #define length_trivial_usage \
218 "STRING"
219 #define length_full_usage \
220 "Prints out the length of the specified STRING."
221 #define length_example_usage \
222 "$ length "Hello"\n" \
223 "5\n"
224
225Each entry is a cpp macro that defines a string. The macros are
226named systematically in the form:
227
228 $name_$type_usage
229
230$name is the name of the applet. $type can be "trivial", "full", "notes",
231or "example". Every documentation macro must end with "_usage".
232
233The definition of the types is as follows:
234
235=over 4
236
237=item B<trivial>
238
239This should be a brief, one-line description of parameters that
240the command expects. This will be displayed when B<-h> is issued to
241a command. I<REQUIRED>
242
243=item B<full>
244
245This should contain descriptions of each option. This will also
246be displayed along with the trivial help if BB_FEATURE_TRIVIAL_HELP
247is disabled. I<REQUIRED>
248
249=item B<notes>
250
251This is documentation that is intended to go in the POD or SGML, but
252not be output when a B<-h> is given to a command. To see an example
253of notes being used, see init_notes_usage. I<OPTIONAL>
254
255=item B<example>
256
257This should be an example of how the command is acutally used.
258I<OPTIONAL>
259
260=back
261
John Beppu4a25d8c2001-02-23 02:33:28 +0000262=head1 FILES
263
John Beppue6967b22001-02-23 17:51:08 +0000264F<usage.h>
John Beppu4a25d8c2001-02-23 02:33:28 +0000265
266=head1 COPYRIGHT
267
268Copyright (c) 2001 John BEPPU. All rights reserved. This program is
269free software; you can redistribute it and/or modify it under the same
270terms as Perl itself.
271
272=head1 AUTHOR
273
274John BEPPU <beppu@lineo.com>
275
276=cut
277
John Beppu79359d82001-04-05 20:03:33 +0000278# $Id: autodocifier.pl,v 1.19 2001/04/05 20:03:33 beppu Exp $