blob: e06a1dad80441525debcb8a0dd2499d53c3664ce [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 {
Matt Kraai4e853562001-04-10 00:00:05 +000030 s/^\s*"//;
31 s/"\s*$//;
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
John Beppu5d817682001-04-17 17:09:34 +000065 # prepare notes if they exist
Eric Andersen0d3a02e2001-03-15 18:14:25 +000066 my $notes = (defined $usage->{notes})
67 ? "$usage->{notes}\n\n"
68 : "";
69
John Beppu5d817682001-04-17 17:09:34 +000070 # prepare examples if they exist
John Beppud11578f2001-02-26 02:50:11 +000071 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 Beppu5d817682001-04-17 17:09:34 +0000110# notes => "...",
John Beppu138ece02001-03-06 19:25:25 +0000111# example => "...",
John Beppu4a25d8c2001-02-23 02:33:28 +0000112# }
113my %docs;
114
John Beppu7d597c42001-02-24 14:37:48 +0000115
John Beppu4a25d8c2001-02-23 02:33:28 +0000116# get command-line options
John Beppu7d597c42001-02-24 14:37:48 +0000117
John Beppu4a25d8c2001-02-23 02:33:28 +0000118my %opt;
119
120GetOptions(
121 \%opt,
122 "help|h",
123 "sgml|s",
124 "pod|p",
125 "verbose|v",
126);
127
128if (defined $opt{help}) {
129 print
130 "$0 [OPTION]... [FILE]...\n",
131 "\t--help\n",
132 "\t--sgml\n",
133 "\t--pod\n",
134 "\t--verbose\n",
135 ;
136 exit 1;
137}
138
John Beppu7d597c42001-02-24 14:37:48 +0000139
John Beppu4a25d8c2001-02-23 02:33:28 +0000140# collect documenation into %docs
John Beppu7d597c42001-02-24 14:37:48 +0000141
John Beppu4a25d8c2001-02-23 02:33:28 +0000142foreach (@ARGV) {
John Beppud11578f2001-02-26 02:50:11 +0000143 open(USAGE, $_) || die("$0: $_: $!");
John Beppu4a25d8c2001-02-23 02:33:28 +0000144 my $fh = *USAGE;
145 my ($applet, $type, @line);
146 while (<$fh>) {
John Beppu4a25d8c2001-02-23 02:33:28 +0000147 if (/^#define (\w+)_(\w+)_usage/) {
148 $applet = $1;
149 $type = $2;
150 @line = continuation($fh);
151 my $doc = $docs{$applet} ||= { };
John Beppu4a25d8c2001-02-23 02:33:28 +0000152 my $text = join("\n", @line);
153 $doc->{$type} = beautify($text);
Eric Andersene13bc0b2001-02-22 22:47:06 +0000154 }
Eric Andersene13bc0b2001-02-22 22:47:06 +0000155 }
156}
John Beppu4a25d8c2001-02-23 02:33:28 +0000157
John Beppu7d597c42001-02-24 14:37:48 +0000158
159# generate structured documentation
160
John Beppue6967b22001-02-23 17:51:08 +0000161my $generator = \&pod_for_usage;
162if (defined $opt{sgml}) {
John Beppu7d597c42001-02-24 14:37:48 +0000163 $generator = \&sgml_for_usage;
John Beppue6967b22001-02-23 17:51:08 +0000164}
John Beppu4a25d8c2001-02-23 02:33:28 +0000165
John Beppu7d597c42001-02-24 14:37:48 +0000166foreach my $applet (sort keys %docs) {
167 print $generator->($applet, $docs{$applet});
John Beppu4a25d8c2001-02-23 02:33:28 +0000168}
169
170exit 0;
171
172__END__
173
174=head1 NAME
175
176autodocifier.pl - generate docs for busybox based on usage.h
177
178=head1 SYNOPSIS
179
John Beppu5d817682001-04-17 17:09:34 +0000180autodocifier.pl [OPTION]... [FILE]...
181
182Example:
183
184 ( cat docs/busybox_header.pod; \
185 docs/autodocifier.pl usage.h; \
186 cat docs/busybox_footer.pod ) > docs/busybox.pod
John Beppu4a25d8c2001-02-23 02:33:28 +0000187
188=head1 DESCRIPTION
189
190The purpose of this script is to automagically generate documentation
191for busybox using its usage.h as the original source for content.
John Beppuce22fee2001-10-31 04:29:18 +0000192It used to be that same content has to be duplicated in 3 places in
John Beppu4a25d8c2001-02-23 02:33:28 +0000193slightly different formats -- F<usage.h>, F<docs/busybox.pod>, and
John Beppuce22fee2001-10-31 04:29:18 +0000194F<docs/busybox.sgml>. This was tedious and error-prone, so it was
195decided that F<usage.h> would contain all the text in a
196machine-readable form, and scripts could be used to transform this
197text into other forms if necessary.
John Beppu4a25d8c2001-02-23 02:33:28 +0000198
John Beppuce22fee2001-10-31 04:29:18 +0000199F<autodocifier.pl> is one such script.
Eric Andersencb81e642003-07-14 21:21:08 +0000200It was based on a script by Erik Andersen <andersen@codepoet.org>
201which was in turn based on a script by Mark Whitley <markw@codepoet.org>
John Beppu4a25d8c2001-02-23 02:33:28 +0000202
203=head1 OPTIONS
204
John Beppue6967b22001-02-23 17:51:08 +0000205=over 4
John Beppu4a25d8c2001-02-23 02:33:28 +0000206
John Beppu9a1395b2001-04-05 19:35:17 +0000207=item B<--help>
John Beppu4a25d8c2001-02-23 02:33:28 +0000208
209This displays the help message.
210
John Beppu9a1395b2001-04-05 19:35:17 +0000211=item B<--pod>
John Beppue6967b22001-02-23 17:51:08 +0000212
213Generate POD (this is the default)
214
John Beppu9a1395b2001-04-05 19:35:17 +0000215=item B<--sgml>
John Beppue6967b22001-02-23 17:51:08 +0000216
217Generate SGML
218
John Beppu9a1395b2001-04-05 19:35:17 +0000219=item B<--verbose>
John Beppue6967b22001-02-23 17:51:08 +0000220
221Be verbose (not implemented)
222
John Beppu4a25d8c2001-02-23 02:33:28 +0000223=back
224
John Beppu9a1395b2001-04-05 19:35:17 +0000225=head1 FORMAT
226
227The following is an example of some data this script might parse.
228
229 #define length_trivial_usage \
230 "STRING"
231 #define length_full_usage \
232 "Prints out the length of the specified STRING."
233 #define length_example_usage \
John Beppu5d817682001-04-17 17:09:34 +0000234 "$ length Hello\n" \
John Beppu9a1395b2001-04-05 19:35:17 +0000235 "5\n"
236
237Each entry is a cpp macro that defines a string. The macros are
238named systematically in the form:
239
240 $name_$type_usage
241
242$name is the name of the applet. $type can be "trivial", "full", "notes",
243or "example". Every documentation macro must end with "_usage".
244
245The definition of the types is as follows:
246
247=over 4
248
249=item B<trivial>
250
251This should be a brief, one-line description of parameters that
252the command expects. This will be displayed when B<-h> is issued to
253a command. I<REQUIRED>
254
255=item B<full>
256
257This should contain descriptions of each option. This will also
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000258be displayed along with the trivial help if CONFIG_FEATURE_TRIVIAL_HELP
John Beppu9a1395b2001-04-05 19:35:17 +0000259is disabled. I<REQUIRED>
260
261=item B<notes>
262
263This is documentation that is intended to go in the POD or SGML, but
John Beppu5d817682001-04-17 17:09:34 +0000264not be printed when a B<-h> is given to a command. To see an example
John Beppuce22fee2001-10-31 04:29:18 +0000265of notes being used, see init_notes_usage in F<usage.h>. I<OPTIONAL>
John Beppu9a1395b2001-04-05 19:35:17 +0000266
267=item B<example>
268
John Beppuce22fee2001-10-31 04:29:18 +0000269This should be an example of how the command is actually used.
John Beppu5d817682001-04-17 17:09:34 +0000270This will not be printed when a B<-h> is given to a command -- it
John Beppuce22fee2001-10-31 04:29:18 +0000271will only be included in the POD or SGML documentation. I<OPTIONAL>
John Beppu9a1395b2001-04-05 19:35:17 +0000272
273=back
274
John Beppu4a25d8c2001-02-23 02:33:28 +0000275=head1 FILES
276
John Beppue6967b22001-02-23 17:51:08 +0000277F<usage.h>
John Beppu4a25d8c2001-02-23 02:33:28 +0000278
279=head1 COPYRIGHT
280
281Copyright (c) 2001 John BEPPU. All rights reserved. This program is
282free software; you can redistribute it and/or modify it under the same
283terms as Perl itself.
284
285=head1 AUTHOR
286
John Beppuce22fee2001-10-31 04:29:18 +0000287John BEPPU <b@ax9.org>
John Beppu4a25d8c2001-02-23 02:33:28 +0000288
289=cut
290
Eric Andersencb81e642003-07-14 21:21:08 +0000291# $Id: autodocifier.pl,v 1.24 2003/07/14 21:20:48 andersen Exp $