Remember to delete un-expandable variables, and do a better job of expanding
[oweals/busybox.git] / docs / autodocifier.pl
1 #!/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         $text =~ s/USAGE_NOT\w+\(.*?"\s*\)//sxg;
25         $text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg;
26         $text =~ s/"\s*"//sg;
27         my @line = split("\n", $text);
28         $text = join('',
29                 map { 
30                         s/^\s*//;
31                         s/"//g;
32                         s/%/%%/g;
33                         s/\$/\\\$/g;
34                         eval qq[ sprintf(qq#$_#) ]
35                 } @line
36         );
37         return $text;
38 }
39
40 # generate POD for an applet
41 sub pod_for_usage {
42         my $name  = shift;
43         my $usage = shift;
44
45         # make options bold
46         my $trivial = $usage->{trivial};
47         $trivial =~ s/(?<!\w)(-\w+)/B<$1>/sxg;
48         my @f0 = 
49                 map { $_ !~ /^\s/ && s/(?<!\w)(-\w+)/B<$1>/g; $_ }
50                 split("\n", $usage->{full});
51
52         # add "\n" prior to certain lines to make indented
53         # lines look right
54         my @f1;
55         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         }
63         my $full = join("\n", @f1);
64
65         # prepare example if one exists
66         my $example = (defined $usage->{example})
67                 ? "Example:\n\n$usage->{example}\n\n"
68                 : "";
69
70         return
71                 "=item I<$name>".
72                 "\n\n"  .
73                 "$name $trivial".
74                 "\n\n"  .
75                 $full   .
76                 "\n\n"  .
77                 $example.
78                 "-------------------------------".
79                 "\n\n"
80         ;
81 }
82
83 # FIXME | generate SGML for an applet
84 sub sgml_for_usage {
85         my $name  = shift;
86         my $usage = shift;
87         return
88                 "<fixme>\n".
89                 "  $name\n".
90                 "</fixme>\n"
91         ;
92 }
93
94 # the keys are applet names, and 
95 # the values will contain hashrefs of the form:
96 #
97 # {
98 #     trivial => "...",
99 #     full    => "...",
100 #     example => "...",
101 # }
102 my %docs;
103
104
105 # get command-line options
106
107 my %opt;
108
109 GetOptions(
110         \%opt,
111         "help|h",
112         "sgml|s",
113         "pod|p",
114         "verbose|v",
115 );
116
117 if (defined $opt{help}) {
118         print
119                 "$0 [OPTION]... [FILE]...\n",
120                 "\t--help\n",
121                 "\t--sgml\n",
122                 "\t--pod\n",
123                 "\t--verbose\n",
124         ;
125         exit 1;
126 }
127
128
129 # collect documenation into %docs
130
131 foreach (@ARGV) {
132         open(USAGE, $_) || die("$0: $_: $!");
133         my $fh = *USAGE;
134         my ($applet, $type, @line);
135         while (<$fh>) {
136                 if (/^#define (\w+)_(\w+)_usage/) {
137                         $applet = $1;
138                         $type   = $2;
139                         @line   = continuation($fh);
140                         my $doc = $docs{$applet} ||= { };
141                         my $text      = join("\n", @line);
142                         $doc->{$type} = beautify($text);
143                 }
144         }
145 }
146
147
148 # generate structured documentation
149
150 my $generator = \&pod_for_usage;
151 if (defined $opt{sgml}) {
152         $generator = \&sgml_for_usage;
153 }
154
155 foreach my $applet (sort keys %docs) {
156         print $generator->($applet, $docs{$applet});
157 }
158
159 exit 0;
160
161 __END__
162
163 =head1 NAME
164
165 autodocifier.pl - generate docs for busybox based on usage.h
166
167 =head1 SYNOPSIS
168
169 autodocifier.pl usage.h > something
170
171 =head1 DESCRIPTION
172
173 The purpose of this script is to automagically generate documentation
174 for busybox using its usage.h as the original source for content.
175 Currently, the same content has to be duplicated in 3 places in
176 slightly different formats -- F<usage.h>, F<docs/busybox.pod>, and
177 F<docs/busybox.sgml>.  This is tedious, so Perl has come to the rescue.
178
179 This script was based on a script by Erik Andersen (andersen@lineo.com).
180
181 =head1 OPTIONS
182
183 =over 4
184
185 =item --help
186
187 This displays the help message.
188
189 =item --pod
190
191 Generate POD (this is the default)
192
193 =item --sgml
194
195 Generate SGML
196
197 =item --verbose
198
199 Be verbose (not implemented)
200
201 =back
202
203 =head1 FILES
204
205 F<usage.h>
206
207 =head1 COPYRIGHT
208
209 Copyright (c) 2001 John BEPPU.  All rights reserved.  This program is
210 free software; you can redistribute it and/or modify it under the same
211 terms as Perl itself.
212
213 =head1 AUTHOR
214
215 John BEPPU <beppu@lineo.com>
216
217 =cut
218
219 # $Id: autodocifier.pl,v 1.14 2001/03/06 19:25:25 beppu Exp $