X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=docs%2Fautodocifier.pl;h=3aa838eb40cc74b5ba4f8cb7cf1bd778e30b75dd;hb=f8138d1f91c913166bffb0077a0fe06831a77ecf;hp=2ce1edd7530fee02aabb064cd7df6dca87ed6348;hpb=e13bc0bc68363e8e8c413cdf0cb2ba6fd67c8b43;p=oweals%2Fbusybox.git diff --git a/docs/autodocifier.pl b/docs/autodocifier.pl index 2ce1edd75..3aa838eb4 100755 --- a/docs/autodocifier.pl +++ b/docs/autodocifier.pl @@ -1,88 +1,304 @@ #!/usr/bin/perl -w -# -# autodocufier.pl - extracts usage messages from busybox usage.c and -# pretty-prints them to stdout. use strict; +use Getopt::Long; + +# collect lines continued with a '\' into an array +sub continuation { + my $fh = shift; + my @line; + + while (<$fh>) { + my $s = $_; + $s =~ s/\\\s*$//; + #$s =~ s/#.*$//; + push @line, $s; + last unless (/\\\s*$/); + } + return @line; +} -my $line; -my $applet; -my $count; -my $full_usage; - -open(USAGE, 'usage.h') or die "usage.h: $!"; - -while (defined($line = )) { - $count=0; - if ($line =~ /^#define (\w+)_trivial_usage/) { - # grab the applet name - $applet = $1; - print "\n$applet:\n"; - - while (defined($line = )) { - if ( $count==0 ) { - $count++; - print "\t$applet "; - } else { print "\t"; } - $full_usage = $applet . "_full_usage"; - last if ( $line =~ /$full_usage/ ); - # Skip preprocessor stuff - next if $line =~ /^\s*#/; - # Strip the continuation char - $line =~ s/\\$//; - # strip quotes off - $line =~ s/^\s*"//; - $line =~ s/"\s*$//; - # substitute escape sequences - # (there's probably a better way to do this...) - $line =~ s/\\t/ /g; - $line =~ s/\\n//g; - # fix up preprocessor macros - $line =~ s/USAGE_\w+\([\s]*?(".*?").*?\)/$1/sg; - # Strip any empty quotes out - $line =~ s/"[\s]*"//sg; - # strip line end quotes, again - $line =~ s/^\s*"//; - $line =~ s/"\s*$//; - - # Finally, print it - print "$line\n"; +# regex && eval away unwanted strings from documentation +sub beautify { + my $text = shift; + for (;;) { + my $text2 = $text; + $text =~ s/SKIP_\w+\(.*?"\s*\)//sxg; + $text =~ s/USE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg; + $text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg; + last if ( $text2 eq $text ); + } + $text =~ s/"\s*"//sg; + my @line = split("\n", $text); + $text = join('', + map { + s/^\s*"//; + s/"\s*$//; + s/%/%%/g; + s/\$/\\\$/g; + eval qq[ sprintf(qq{$_}) ] + } @line + ); + return $text; +} + +# generate POD for an applet +sub pod_for_usage { + my $name = shift; + my $usage = shift; + + # Sigh. Fixup the known odd-name applets. + $name =~ s/dpkg_deb/dpkg-deb/g; + $name =~ s/fsck_minix/fsck.minix/g; + $name =~ s/mkfs_minix/mkfs.minix/g; + $name =~ s/run_parts/run-parts/g; + $name =~ s/start_stop_daemon/start-stop-daemon/g; + + # make options bold + my $trivial = $usage->{trivial}; + if (!defined $usage->{trivial}) { + $trivial = ""; + } else { + $trivial =~ s/(?/sxg; + } + my @f0 = + map { $_ !~ /^\s/ && s/(?/g; $_ } + split("\n", (defined $usage->{full} ? $usage->{full} : "")); + + # add "\n" prior to certain lines to make indented + # lines look right + my @f1; + my $len = @f0; + for (my $i = 0; $i < $len; $i++) { + push @f1, $f0[$i]; + if (($i+1) != $len && $f0[$i] !~ /^\s/ && $f0[$i+1] =~ /^\s/) { + next if ($f0[$i] =~ /^$/); + push(@f1, "") unless ($f0[$i+1] =~ /^\s*$/s); } - printf("\n"); - while (defined($line = )) { - if ( $count==0 ) { - $count++; - print "\t$applet "; - } else { print "\t"; } - # we're done if we hit a line lacking a '\' at the end - #last if ! $line !~ /\\$/; - if ( $line !~ /\\$/ ) { - #print "Got one at $line\n"; - last; - } - # Skip preprocessor stuff - next if $line =~ /^\s*#/; - # Strip the continuation char - $line =~ s/\\$//; - # strip quotes off - $line =~ s/^\s*"//; - $line =~ s/"\s*$//; - # substitute escape sequences - # (there's probably a better way to do this...) - $line =~ s/\\t/ /g; - $line =~ s/\\n//g; - # Automagically #define all preprocessor lines - #$line =~ s/USAGE_\w+\([\s]*?(".*?")\s,\s".*"\s\)/$1/sg; - $line =~ s/USAGE_\w+\(\s*?(".*").*\)/$1/sg; - # Strip any empty quotes out - $line =~ s/"[\s]*"//sg; - # strip line end quotes, again - $line =~ s/^\s*"//; - $line =~ s/"\s*$//; - - # Finally, print it - print "$line\n"; + } + my $full = join("\n", @f1); + + # prepare notes if they exist + my $notes = (defined $usage->{notes}) + ? "$usage->{notes}\n\n" + : ""; + + # prepare examples if they exist + my $example = (defined $usage->{example}) + ? + "Example:\n\n" . + join ("\n", + map { "\t$_" } + split("\n", $usage->{example})) . "\n\n" + : ""; + + # Pad the name so that the applet name gets a line + # by itself in BusyBox.txt + my $spaces = 10 - length($name); + if ($spaces > 0) { + $name .= " " x $spaces; + } + + return + "=item B<$name>". + "\n\n$name $trivial\n\n". + "$full\n\n" . + "$notes" . + "$example" . + "\n\n" + ; +} + +# the keys are applet names, and +# the values will contain hashrefs of the form: +# +# { +# trivial => "...", +# full => "...", +# notes => "...", +# example => "...", +# } +my %docs; + + +# get command-line options + +my %opt; + +GetOptions( + \%opt, + "help|h", + "pod|p", + "verbose|v", +); + +if (defined $opt{help}) { + print + "$0 [OPTION]... [FILE]...\n", + "\t--help\n", + "\t--pod\n", + "\t--verbose\n", + ; + exit 1; +} + + +# collect documenation into %docs + +foreach (@ARGV) { + open(USAGE, $_) || die("$0: $_: $!"); + my $fh = *USAGE; + my ($applet, $type, @line); + while (<$fh>) { + if (/^#define (\w+)_(\w+)_usage/) { + $applet = $1; + $type = $2; + @line = continuation($fh); + my $doc = $docs{$applet} ||= { }; + my $text = join("\n", @line); + $doc->{$type} = beautify($text); } - printf("\n\n"); } } + + +# generate structured documentation + +my $generator = \&pod_for_usage; + +my @names = sort keys %docs; +my $line = "\t[, [[, "; +for (my $i = 0; $i < $#names; $i++) { + if (length ($line.$names[$i]) >= 65) { + print "$line\n\t"; + $line = ""; + } + $line .= "$names[$i], "; +} +print $line . $names[-1]; + +print "\n\n=head1 COMMAND DESCRIPTIONS\n"; +print "\n=over 4\n\n"; + +foreach my $applet (@names) { + print $generator->($applet, $docs{$applet}); +} + +exit 0; + +__END__ + +=head1 NAME + +autodocifier.pl - generate docs for busybox based on usage.h + +=head1 SYNOPSIS + +autodocifier.pl [OPTION]... [FILE]... + +Example: + + ( cat docs/busybox_header.pod; \ + docs/autodocifier.pl usage.h; \ + cat docs/busybox_footer.pod ) > docs/busybox.pod + +=head1 DESCRIPTION + +The purpose of this script is to automagically generate +documentation for busybox using its usage.h as the original source +for content. It used to be that same content has to be duplicated +in 3 places in slightly different formats -- F, +F. This was tedious and error-prone, so it was +decided that F would contain all the text in a +machine-readable form, and scripts could be used to transform this +text into other forms if necessary. + +F is one such script. It is based on a script by +Erik Andersen which was in turn based on a +script by Mark Whitley + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +This displays the help message. + +=item B<--pod> + +Generate POD (this is the default) + +=item B<--verbose> + +Be verbose (not implemented) + +=back + +=head1 FORMAT + +The following is an example of some data this script might parse. + + #define length_trivial_usage \ + "STRING" + #define length_full_usage \ + "Prints out the length of the specified STRING." + #define length_example_usage \ + "$ length Hello\n" \ + "5\n" + +Each entry is a cpp macro that defines a string. The macros are +named systematically in the form: + + $name_$type_usage + +$name is the name of the applet. $type can be "trivial", "full", "notes", +or "example". Every documentation macro must end with "_usage". + +The definition of the types is as follows: + +=over 4 + +=item B + +This should be a brief, one-line description of parameters that +the command expects. This will be displayed when B<-h> is issued to +a command. I + +=item B + +This should contain descriptions of each option. This will also +be displayed along with the trivial help if CONFIG_FEATURE_TRIVIAL_HELP +is disabled. I + +=item B + +This is documentation that is intended to go in the POD or SGML, but +not be printed when a B<-h> is given to a command. To see an example +of notes being used, see init_notes_usage in F. I + +=item B + +This should be an example of how the command is actually used. +This will not be printed when a B<-h> is given to a command -- it +will only be included in the POD or SGML documentation. I + +=back + +=head1 FILES + +F + +=head1 COPYRIGHT + +Copyright (c) 2001 John BEPPU. All rights reserved. This program is +free software; you can redistribute it and/or modify it under the same +terms as Perl itself. + +=head1 AUTHOR + +John BEPPU + +=cut + +# $Id: autodocifier.pl,v 1.26 2004/04/06 15:26:25 andersen Exp $