o echo_example_usage
    needed to escape some backslashes in an inner quote
  o find_full_usage
    missing a \n at the end of the -name line
  ? getopt_full_usage
    the -o line has tab issues, but I didn't fix them.
  o length_example_usage
    removed some double-quotes that were within an inner quotes
  o printf_example_usage
    needed to escape a backslash in an inner quote
  o sort_example_usage
    needed to escape some backslashes and double quotes in an inner quote
  o tftp_full_usage
    s/nameing/naming/;
  o umount_full_usage
    remove colons after options for consistency w/ other full_usage messages
  o uniq_example_usage
    needed to escape some backslashes and double quotes in an inner quote
- TODO                          xargs -l ?
- docs/autodocifier.pl          POD && comment updates
- docs/busybox_footer.pod       added Larry Doolittle and Sterling Huxley
		
	
		
			
				
	
	
		
			288 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/perl -w
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
# regex && eval away unwanted strings from documentation
 | 
						|
sub beautify {
 | 
						|
	my $text = shift;
 | 
						|
	$text =~ s/USAGE_NOT\w+\(.*?"\s*\)//sxg;
 | 
						|
	$text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg;
 | 
						|
	$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;
 | 
						|
 | 
						|
	# make options bold
 | 
						|
	my $trivial = $usage->{trivial};
 | 
						|
	$trivial =~ s/(?<!\w)(-\w+)/B<$1>/sxg;
 | 
						|
	my @f0 = 
 | 
						|
		map { $_ !~ /^\s/ && s/(?<!\w)(-\w+)/B<$1>/g; $_ }
 | 
						|
		split("\n", $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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	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"
 | 
						|
		: "";
 | 
						|
 | 
						|
	return
 | 
						|
		"=item B<$name>".
 | 
						|
		"\n\n"  .
 | 
						|
		"$name $trivial".
 | 
						|
		"\n\n"  .
 | 
						|
		$full   .
 | 
						|
		"\n\n"  .
 | 
						|
		$notes  .
 | 
						|
		$example.
 | 
						|
		"-------------------------------".
 | 
						|
		"\n\n"
 | 
						|
	;
 | 
						|
}
 | 
						|
 | 
						|
# FIXME | generate SGML for an applet
 | 
						|
sub sgml_for_usage {
 | 
						|
	my $name  = shift;
 | 
						|
	my $usage = shift;
 | 
						|
	return
 | 
						|
		"<fixme>\n".
 | 
						|
		"  $name\n".
 | 
						|
		"</fixme>\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",
 | 
						|
	"sgml|s",
 | 
						|
	"pod|p",
 | 
						|
	"verbose|v",
 | 
						|
);
 | 
						|
 | 
						|
if (defined $opt{help}) {
 | 
						|
	print
 | 
						|
		"$0 [OPTION]... [FILE]...\n",
 | 
						|
		"\t--help\n",
 | 
						|
		"\t--sgml\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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# generate structured documentation
 | 
						|
 | 
						|
my $generator = \&pod_for_usage;
 | 
						|
if (defined $opt{sgml}) {
 | 
						|
	$generator = \&sgml_for_usage;
 | 
						|
}
 | 
						|
 | 
						|
foreach my $applet (sort keys %docs) {
 | 
						|
	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.
 | 
						|
Currently, the same content has to be duplicated in 3 places in
 | 
						|
slightly different formats -- F<usage.h>, F<docs/busybox.pod>, and
 | 
						|
F<docs/busybox.sgml>.  This is tedious, so Perl has come to the rescue.
 | 
						|
 | 
						|
This script was based on a script by Erik Andersen <andersen@lineo.com>
 | 
						|
which was in turn based on a script by Mark Whitley <markw@lineo.com>
 | 
						|
 | 
						|
=head1 OPTIONS
 | 
						|
 | 
						|
=over 4
 | 
						|
 | 
						|
=item B<--help>
 | 
						|
 | 
						|
This displays the help message.
 | 
						|
 | 
						|
=item B<--pod>
 | 
						|
 | 
						|
Generate POD (this is the default)
 | 
						|
 | 
						|
=item B<--sgml>
 | 
						|
 | 
						|
Generate SGML
 | 
						|
 | 
						|
=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<trivial>
 | 
						|
 | 
						|
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<REQUIRED>
 | 
						|
 | 
						|
=item B<full>
 | 
						|
 | 
						|
This should contain descriptions of each option.  This will also
 | 
						|
be displayed along with the trivial help if BB_FEATURE_TRIVIAL_HELP
 | 
						|
is disabled.  I<REQUIRED>
 | 
						|
 | 
						|
=item B<notes>
 | 
						|
 | 
						|
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.  I<OPTIONAL>
 | 
						|
 | 
						|
=item B<example>
 | 
						|
 | 
						|
This should be an example of how the command is acutally used.
 | 
						|
This will not be printed when a B<-h> is given to a command -- it
 | 
						|
is inteded only for the POD or SGML documentation.  I<OPTIONAL>
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head1 FILES
 | 
						|
 | 
						|
F<usage.h>
 | 
						|
 | 
						|
=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 <beppu@lineo.com>
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
# $Id: autodocifier.pl,v 1.21 2001/04/17 17:09:34 beppu Exp $
 |