- properly indent Examples section in pod generator
[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 notes if they exists
66         my $notes = (defined $usage->{notes})
67                 ? "$usage->{notes}\n\n"
68                 : "";
69
70         # prepare example if one exists
71         my $example = (defined $usage->{example})
72                 ? $usage->{example}
73                 : "";
74         $example = 
75                 "Example:\n\n" .
76                 join ("\n", 
77                 map  { "    $_" } 
78                 split("\n", $example)) . "\n\n";
79
80         return
81                 "=item I<$name>".
82                 "\n\n"  .
83                 "$name $trivial".
84                 "\n\n"  .
85                 $full   .
86                 "\n\n"  .
87                 $notes  .
88                 $example.
89                 "-------------------------------".
90                 "\n\n"
91         ;
92 }
93
94 # FIXME | generate SGML for an applet
95 sub sgml_for_usage {
96         my $name  = shift;
97         my $usage = shift;
98         return
99                 "<fixme>\n".
100                 "  $name\n".
101                 "</fixme>\n"
102         ;
103 }
104
105 # the keys are applet names, and 
106 # the values will contain hashrefs of the form:
107 #
108 # {
109 #     trivial => "...",
110 #     full    => "...",
111 #     example => "...",
112 # }
113 my %docs;
114
115
116 # get command-line options
117
118 my %opt;
119
120 GetOptions(
121         \%opt,
122         "help|h",
123         "sgml|s",
124         "pod|p",
125         "verbose|v",
126 );
127
128 if (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
139
140 # collect documenation into %docs
141
142 foreach (@ARGV) {
143         open(USAGE, $_) || die("$0: $_: $!");
144         my $fh = *USAGE;
145         my ($applet, $type, @line);
146         while (<$fh>) {
147                 if (/^#define (\w+)_(\w+)_usage/) {
148                         $applet = $1;
149                         $type   = $2;
150                         @line   = continuation($fh);
151                         my $doc = $docs{$applet} ||= { };
152                         my $text      = join("\n", @line);
153                         $doc->{$type} = beautify($text);
154                 }
155         }
156 }
157
158
159 # generate structured documentation
160
161 my $generator = \&pod_for_usage;
162 if (defined $opt{sgml}) {
163         $generator = \&sgml_for_usage;
164 }
165
166 foreach my $applet (sort keys %docs) {
167         print $generator->($applet, $docs{$applet});
168 }
169
170 exit 0;
171
172 __END__
173
174 =head1 NAME
175
176 autodocifier.pl - generate docs for busybox based on usage.h
177
178 =head1 SYNOPSIS
179
180 autodocifier.pl usage.h > something
181
182 =head1 DESCRIPTION
183
184 The purpose of this script is to automagically generate documentation
185 for busybox using its usage.h as the original source for content.
186 Currently, the same content has to be duplicated in 3 places in
187 slightly different formats -- F<usage.h>, F<docs/busybox.pod>, and
188 F<docs/busybox.sgml>.  This is tedious, so Perl has come to the rescue.
189
190 This script was based on a script by Erik Andersen (andersen@lineo.com).
191
192 =head1 OPTIONS
193
194 =over 4
195
196 =item --help
197
198 This displays the help message.
199
200 =item --pod
201
202 Generate POD (this is the default)
203
204 =item --sgml
205
206 Generate SGML
207
208 =item --verbose
209
210 Be verbose (not implemented)
211
212 =back
213
214 =head1 FILES
215
216 F<usage.h>
217
218 =head1 COPYRIGHT
219
220 Copyright (c) 2001 John BEPPU.  All rights reserved.  This program is
221 free software; you can redistribute it and/or modify it under the same
222 terms as Perl itself.
223
224 =head1 AUTHOR
225
226 John BEPPU <beppu@lineo.com>
227
228 =cut
229
230 # $Id: autodocifier.pl,v 1.16 2001/03/15 20:49:25 beppu Exp $