#!/usr/bin/perl -w
#
# make_widget_doc -	Extract YCP widget documentation from C++ sources
#			into to (multiple) HTML files.
#
# Usage:
#	make_widget_doc [-v] [-d] [-s srcdir]
#
#	-v	verbose
#	-d	debug
#
# Author: Stefan Hundhammer <sh@suse.de>
#
#
# The UI Interpreter main file (*widgets.cc) is read and scanned
# for keywords like
#
#	@keyword contents (may be a multi line string)
#
# The '@widget' keyword is required to be the first for each widget.
# Information about one widget is stored in a '%widget' hash that uses
# the keyword (minus the '@') as key. The contents are stored as
# either strings (for most keywords) or as a reference to a list of
# strings.
#
# For each widget the corresponding widget class C++ source file is
# read (as specified in the '@class' keyword + '.cc' file extension).
# This class file is scanned for '@property' or '@properties' keywords
# only. Those properties are stored in a list of strings outside the
# '%widget' hash.
#
# If there is no C++ source file that corresponds to a '@widget'
# section, an artificial class name in parentheses has to be used:
#
#	@class (Box)
#
# In this special case no class source file will be read. The
# specified name, however, will be used as the base for the
# corresponding HTML output file.
#
# For '@example' keywords all words specified will be treated as names
# of example files. Those files are read and copied verbatim as
# pre-formatted code into the HTML page.
#
# For each '@widget' section a separate HTML file will be generated
# with the information collected about the widget. This will happen
# whenever a new '@widget' section is found.
#
# The HTML files will be named according to the '@class' name
# specified, plus '-widget.html' (as to avoid clashes with C++ class
# autodocs from the same files).
#
# Along with those HTML files for each '@widget' section, a TOC (table
# of contents) file is generated that contains hyperlinks to the
# individual widget HTML files. This TOC file is generated at the very
# end of the program from information collected in the '%toc_target'
# and '%toc_description' hashes.
#
# The TOC will contain an entry for each word in each '@widget'
# section - some '@widget' sections describe more than one widget
# (e.g. Left Right Top Bottom HCenter VCenter HVCenter -> Alignment).


# TO DO:
# - integrate into Makefile.am

use strict;
use English;
use FileHandle;
use Getopt::Std;
use vars qw( $opt_v $opt_d $opt_s );


# Global variables.

my $verbose		= 0;
my $debug		= 0;
my $src_dir		= "../../src";
my $example_dir		= "../examples";
my $screenshot_dir	= $example_dir . "/screenshots";
my $html_dir		= ".";
my $generic_class_name  = "widget000";	# if no '@class' specified
my $toc_file_name       = "index.html";


# The following keywords are recognized by this script.
# Some may appear in singular or plural form; they will be normalized
# to the form on the right side.

my %normalized_keyword =
(
    "arg"		=> "arg",
    "args"		=> "arg",
    "builtin"		=> "builtin",	# will be ignored for this kind of doc
    "class"		=> "class",
    "description"	=> "description",
    "example"		=> "example",
    "examples"		=> "example",
    "optarg"		=> "optarg",
    "optargs"		=> "optargs",
    "opt_arg"		=> "optarg",
    "opt_args"		=> "optargs",
    "option"		=> "option",
    "options"		=> "option",
    "short"             => "short",
    "usage"		=> "usage",
    "widget"		=> "widget",
    "widgets"		=> "widget"
);

# Notice: "@properties" or "@property" are not allowed in the main
# file (*widgets.cc), just in the class file
# (e.g. YLabel.cc). Thus, those keywords are not mentioned here.


# Keywords that may occur multiple times for each widget.
# For these, the keyword contents will not be stored as a reference to
# a list of strings rather than a simple string.

my %multiple_occurence =
(
    "arg"	=> 1,
    "optarg"	=> 1,
    "option"	=> 1
);


my %toc_target;		# TOC (table of contents) hyperlink targets
my %toc_description;	# TOC descriptions


# Forward declarations.

sub main();


# Call the main function and exit.
# DO NOT enter any other code outside a sub -
# any variables would otherwise be global.


main();
exit 0;


#-----------------------------------------------------------------------------


# Main program.

sub main()
{
    my $html_file_name	= "widgets.html";
    my $html_toc_name	= "widgets-index.html";

    # Extract command line options.
    # This will set a variable opt_? for any option,
    # e.g. opt_v if option '-v' is passed on the command line.

    getopts('vds:');

    $verbose	= 1 if $opt_v;
    $debug	= 1 if $opt_d;
    $src_dir    = $opt_s if $opt_s;

    print "src_dir: $src_dir\n";
    my @main_file_names	= glob( $src_dir . "/ycp-ui/YCPDialogParser.cc" );

    # Check for other (undesired) command line parameters.

    usage() if $#ARGV != -1;


    # Process the source files, generate HTML output and write TOC.

    my $main_file_name;

    foreach $main_file_name ( @main_file_names )
    {
	logf( "Reading $main_file_name" );
	read_main_file( $main_file_name );
    }
    write_toc();
}


#-----------------------------------------------------------------------------


# Read the main source file.
#
# Parameters:
#	$main_file_name	Name of the main source file.

sub read_main_file()
{
    my ( $main_file_name ) = @_;
    my $line;
    my $line_no = 0;
    my $keyword;
    my $contents;
    my $keyword_line_no;
    my %widget;
    my @prop;
    my @args;


    open ( MAIN, $main_file_name ) or die "FATAL: Can't open $main_file_name";

    # Read the main file.

    $line = <MAIN>;
    $line_no++;

    while ( $line )
    {
	# Check for '@xyz' keywords

	if ( $line =~ '^\s*\*?\s*@.*' )
	{
	    # '@xyz' keyword found

	    $line =~ s/^\s*\*?\s*@//;	# remove '  * @' at beginning of line
	    ( $keyword, $contents ) = split ( '\s+', $line, 2 );
	    $keyword_line_no = $line_no;


	    # Check and normalize keyword

	    if ( defined $normalized_keyword{ $keyword } )
	    {
		$keyword = $normalized_keyword{ $keyword };
	    }
	    else
	    {
		warning ( "WARNING: $main_file_name:$line_no: ",
			  "Unknown keyword \@$keyword - ignored" );
	    }


	    # Read follow-up lines for contents

	    $line = <MAIN>;
	    $line_no++;

	    while ( $line &&				# have one more line
		    ! ( $line =~ '^\s*\*?\s*@.*' ) &&	# no '@xyz' line
		    ! ( $line =~ '\s*\*/' ) )		# no */ line
	    {
		$line =~ s/^\s*\*?\s*//;	# remove '  * ' at beginning of line
		$contents .= $line;
		$line = <MAIN>;
		$line_no++;
	    }

	    chomp ( $contents );
	    # deb ( '@' . $keyword . ":", $contents );


	    # Write previously collected widget info to the HTML file if this
	    # is a  new '@widget' line

	    if ( $keyword eq "widget" &&		# found '@widget' or '@widgets'
		 defined ( $widget{'widget'} ) )	# and 'widget' hash filled
	    {
		if ( defined $widget{ 'class' } )
		{
		    if ( $widget{ 'class' } =~ '\(.*\)' )	# don't read Y(class-file).cc
		    {
		        # If we found a @class keyword with its contents in parentheses,
		        # this means we are not supposed to read a
		        # corresponding C++ source file (because there isn't one).

			@prop = ();
			$widget{ 'class' } =~ s:\( *([^ ]*) *\):$1:
		    }
		    else	# read Yclass-file.cc
		    {
			# Read the C++ source file corresponding to the widget class.
			# Assume a file name Y*.cc for it.

			@prop = read_class_file ( $widget{ 'widget' }, $widget{ 'class' } );
		    }
		}
		else
		{
		    $widget{ 'class' } = $generic_class_name++;
		    warning ( "WARNING: \@class not defined for $widget{'widget'} - using $generic_class_name" );
		    @prop = ();
		}


		# Add every single widget from the list of widgets to the TOC.

		my $single_widget;
		my $toc_target = $widget{'class'} . "-widget.html";

		foreach $single_widget ( split ( '\s', $widget{'widget'} ) )
		{
		    my $short = "";
		    $short = $widget{'short'} if defined $widget{'short'};

		    $toc_target     { $single_widget } = $toc_target;
		    $toc_description{ $single_widget } = $short;
		}

		write_widget_html_doc( \%widget, \@prop );
		undef %widget; # clear old hash contents
	    }


	    # Collect widget info in hash.

	    if ( $contents ne "" )
	    {
		if ( defined $multiple_occurence{ $keyword } )
		{
		    # The pathological case:
		    # This keyword may occur many times once per '@widget' section.
		    # Store the contents as a reference to a list of strings.

		    my $list_ref = $widget{ $keyword };

		    if ( defined $list_ref )
		    {
		        $widget{ $keyword } = [ @$list_ref, $contents ];
		    }
                    else
		    {
		        $widget{ $keyword } = [ $contents ];
		    }
		}
		else
		{
		    # The simple (standard) case:
		    # This keyword may appear just once per '@widget' section.
		    # Store the contents as a simple string.

		    $widget{ $keyword } = $contents;
		}
	    }
	    else
	    {
		warning ( "WARNING: $main_file_name:$keyword_line_no: ",
                          "No contents for \@$keyword specified" );
	    }
        }
        else
        {
	    # no keyword found

	    $line = <MAIN>;
	    $line_no++;
        }
    }


    if ( defined( $widget{'widget'} ) )	# anything left over that isn't written yet?
    {
	deb( "Writing last widget (left over)" );
	write_widget_html_doc( \%widget, \@prop );
    }

    close ( MAIN );
}


#-----------------------------------------------------------------------------


# Read the widget class file.
# Search through it for '@property' or '@properties' lines.
#
# Parameters:
#	$widget_name	The widget name(s).
#	$class_name	Widget C++ class name.
#
# Return value:
#	A list of properties for the widget.

sub read_class_file()
{
    my ( $widget_name, $class_name ) = @_;
    my $line;
    my $line_no = 0;
    my $keyword;
    my $contents;
    my @prop;

    if ( $class_name eq "" )
    {
	warning ( "ERROR: Empty \@class specified for $widget_name" );
	return @prop;
    }

    my $class_file = FileHandle->new();

    my $class_file_name = $class_name . ".cc";
    $class_file_name	= $src_dir . "/" . $class_file_name unless $src_dir eq "";

    if ( ! open ( $class_file, $class_file_name ) )
    {
	warning ( "ERROR: Can't open $class_file_name required for $widget_name" );
	return @prop;
    }


    $line = <$class_file>;
    $line_no++;

    while ( $line )
    {
	# Check for '@xyz' keywords

	if ( $line =~ '^\s*\*?\s*@.*' )
	{
	    # '@xyz' keyword found

	    $line =~ s/^\s*\*?\s*@//;	# remove '  * @' at beginning of line
	    ( $keyword, $contents ) = split ( '\s+', $line, 2 );


	    # Read follow-up lines for contents

	    $line = <$class_file>;
	    $line_no++;

	    while ( $line &&				# have one more line
		    ! ( $line =~ '^\s*\*?\s*@.*' ) &&	# no '@xyz' line
		    ! ( $line =~ '\s*\*/' ) )		# no */ line
	    {
		$line =~ s/^\s*\*?\s*//;	# remove '  * ' at beginning of line
		$contents .= $line;
		$line = <$class_file>;
		$line_no++;
		# deb ( $line );
	    }

	    chomp ( $contents );
	    deb ( '@' . $keyword . ":", $contents );

	    if ( $keyword eq 'property'  ||
		 $keyword eq 'properties'   )
	    {
		push @prop, $contents;
	    }
	    else
	    {
		warning ( "$class_file_name:$line_no: " .
			  "WARNING: Undefined keyword \@$keyword - ignored" );
	    }
        }
        else
        {
	    # no keyword found

	    $line = <$class_file>;
        }
    }

    # $class_file will be closed automatically by its destructor.

    return @prop;
}


#-----------------------------------------------------------------------------

# Write a html doc file for one widget.
#
# Parameters:
#	%$w		Reference to widget hash to format.
#	@$prop		Reference to widget properties list.

sub write_widget_html_doc ()
{
    my ( $w_ref, $prop_ref ) = @_;

    my $html_file_name = $w_ref->{'class'} . "-widget.html";
    my $html_file = FileHandle->new();
    open ( $html_file, ">". $html_file_name ) or die "FATAL: Can't open $html_file_name";
    logf( "Generating $html_file_name" );

    write_html_header( $html_file, "YCP UI Widget Reference" );
    format_widget( $html_file, $w_ref, $prop_ref );
    write_html_footer( $html_file);

    # Notice: $html_file will be closed automatically by its destructor.

}

#-----------------------------------------------------------------------------


# Write TOC (table of contents).
#
# Parameters:
#	---

sub write_toc ()
{
    my $toc_file = FileHandle->new();
    open ( $toc_file, ">". $toc_file_name ) or die "FATAL: Can't open $toc_file_name";
    logf( "Generating $toc_file_name" );

    write_html_header( $toc_file, "YCP UI Widget Reference" );

    print $toc_file <<"HTML-HEADER-END";

<h2>
    Alphabetical Widget Index
</h2>
<table>
HTML-HEADER-END

    my $widget;

    foreach $widget ( sort keys %toc_target )
    {
	print $toc_file <<"HTML-HEADER-END";
    <tr>
	<td>
	    <a href="$toc_target{$widget}">	$widget	</a>
	</td>
	<td>
            $toc_description{$widget}
        </td>
    </tr>
HTML-HEADER-END
    }

	print $toc_file <<"HTML-HEADER-END";
</table>
HTML-HEADER-END

    write_html_footer( $toc_file);

    # Notice: $toc_file will be closed automatically by its destructor.
}


#-----------------------------------------------------------------------------


# Write HTML header.
#
# Parameters:
#	$outfile	Open HTML file to write output to.
#	$title		The document title.

sub write_html_header()
{
    my ( $outfile, $title ) = @_;

    print $outfile <<"HTML-HEADER-END";
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
    <title>
	$title
    </title>
</head>

    <!-- This file is auto generated by make_widget_doc. -->
    <!-- DO NOT EDIT! -->

<body bgcolor=#c8c8c8>
    <table width="100%">
        <tr>
	    <td align=left valign=top>
		<i>YaST2 Developers Documentation: </i>
		<b> YCP UI Reference: Widgets</b>
            </td>
            <td align=right valign=top>
                <a href="/usr/share/doc/packages/yast2-doc/index.html">
                <img src="/usr/share/doc/packages/ydoc/images/yast2-mini.png" border=0></a>
            </td>
	</tr>
    </table>

    <hr>

    <table>
        <tr>
	    <td valign=top align=center>
                <img src="/usr/share/doc/packages/ydoc/images/yast2-half.png">
                <br>
                <br>
	    </td>
	    <td valign=top>

<h1>
    $title
</h1>

HTML-HEADER-END
}


#-----------------------------------------------------------------------------

# Write HTML footer.
#
# Parameters:
#	$outfile	Open HTML file to write output to.

sub write_html_footer()
{
    my ( $outfile ) = @_;

    my $time = localtime();

    print $outfile <<"HTML-FOOTER-END";

	</td>
    </tr>
</table>

<hr>

<table width="100%">
    <tr>
	<td align=left valign=top>
	    <i>YaST2 Developers Documentation: </i>
	    <b> YCP UI Reference: Widgets</b>
	</td>
	<td align=right valign=top>
	    <a href="/usr/share/doc/packages/yast2-doc/index.html">
		<img src="/usr/share/doc/packages/ydoc/images/yast2-mini.png" border=0>
	    </a>
	</td>
    </tr>
</table>


<p align=center>
    <small>
	Generated $time
    </small>
</p>

</body>
</html>
HTML-FOOTER-END
}


#-----------------------------------------------------------------------------


# Format info about a widget:
# Create a nice section of HTML output.
#
# Parameters:
#	$outfile	Opened HTML file to write the output to.
#	%$w		Reference to widget hash to format.
#	@$prop		Reference to widget properties list.

sub format_widget()
{
    my ( $outfile, $w_ref, $prop_ref ) = @_;
    my %w		= %$w_ref;
    my @widget_props	= @$prop_ref;
    my $name;
    my $example;
    my $example_no	= 1;
    my $short_desc      = "";


    deb( "Formatting", $w{'widget'} );

    $name = $w{'widget'};

    # warning ( "WARNING: \@arg not defined for $name" )		unless defined $w{'arg'};
    warning ( "WARNING: \@description not defined for $name" )	unless defined $w{'description'};
    warning ( "WARNING: \@usage not defined for $name" )	unless defined $w{'usage'};

    $short_desc = $w{'short'} if defined $w{'short'};
    $w{'widget'} =~ s:\s+:<br>:g;

    print $outfile <<"HTML-END";
<p>
    <a href="$toc_file_name">
	Back to the widget index
    </a>
</p>
<table border=0 cellspacing=0 width=100% bgcolor="#f96500" cellpadding=1>
    <tr>
	<td>
	    <table width=100% bgcolor="#ffc080" cellspacing=0 cellpadding=3 border=0>
		<tr>
		    <td>
			<font size="+1">
			    <tt><b>$w{'widget'}</tt></b>
			</font>
		    </td>
		    <td align=left>
                        $short_desc
                    </td>
		</tr>
	    </table>
	</td>
    </tr>
</table>
<br>

<h3>Description</h3>
<blockquote>
<p>
$w{'description'}
</p>
</blockquote>
HTML-END

    # Create a table for @arg

	print $outfile <<"HTML-END";
<h3>Arguments</h3>
HTML-END

    if ( ! defined $w{'arg'} )	# No args
    {
	print $outfile <<"HTML-END";
<blockquote>
    <p>
    	<i>
    	    None
    	</i>
    </p>
</blockquote>
HTML-END
    }
    else			# Widget has args
    {
	my $lines = $w{'arg'};
	my $line;


	# Table header

	print $outfile <<"HTML-END";
<blockquote>
    <table cellspacing=7>
HTML-END

	foreach $line ( @$lines )
	{
	    my @args = split ( '\s+', $line, 3 );
	    my $arg_type = $args[0]; shift @args;
	    my $arg_name = $args[0]; shift @args;


	    # Table row

	    print $outfile <<"HTML-END";
    	<tr valign=top>
    	    <td>
    		<tt>$arg_type</tt>
    	    </td>
    	    <td>
    		    <i>$arg_name</i>
    	    </td>
    	    <td>
    		@args
    	    </td>
    	</tr>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
    </table>
</blockquote>
HTML-END

    }


    # Create a table for @optarg

    if ( defined $w{'optarg'} )	# No args
    {
	deb("optarg for $w{'widget'}");

	my $lines = $w{'optarg'};
	my $line;


	# Table header

	print $outfile <<"HTML-END";
<blockquote>
    <br>
    <h4>
	Optional
    </h4>
    <table cellspacing=7>
HTML-END

	foreach $line ( @$lines )
	{
	    my @args = split ( '\s+', $line, 3 );
	    my $arg_type = $args[0]; shift @args;
	    my $arg_name = $args[0]; shift @args;

	    deb("optarg for $w{'widget'}: $arg_name");

	    # Table row

	    print $outfile <<"HTML-END";
    	<tr valign=top>
    	    <td>
    		<tt>$arg_type</tt>
    	    </td>
    	    <td>
    		    <i>$arg_name</i>
    	    </td>
    	    <td>
    		@args
    	    </td>
    	</tr>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
    </table>
</blockquote>
HTML-END

    }


    # Create a table for @prop

	print $outfile <<"HTML-END";
<h3>Special Properties</h3>
HTML-END

    if ( $#widget_props < 0 )	# No properties
    {
	print $outfile <<"HTML-END";
<blockquote>
    <p>
    	<i>
	    None
	</i>
    </p>
</blockquote>
HTML-END
    }
    else			# Widget has properties
    {
	my $property;

	# Table header

	print $outfile <<"HTML-END";
<blockquote>
    <table cellspacing=7>
HTML-END

	foreach $property ( @widget_props )
	{
	    my @prop = split ( '\s+', $property, 3 );
	    my $prop_type = $prop[0]; shift @prop;
	    my $prop_name = $prop[0]; shift @prop;


	    # Table row

	    print $outfile <<"HTML-END";
    	<tr valign=top>
    	    <td>
    		<tt>$prop_type</tt>
    	    </td>
    	    <td>
    		    <i>$prop_name</i>
    	    </td>
    	    <td>
    		@prop
    	    </td>
    	</tr>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
    </table>
</blockquote>
HTML-END

    }



    # Create a table for @option

    if ( defined $w{'option'} )	# No opts
    {
	deb("option for $w{'widget'}");

	my $lines = $w{'option'};
	my $line;


	# Table header

	print $outfile <<"HTML-END";
<br>
<h3>
	Options
</h3>
<table cellspacing=7>
HTML-END

	foreach $line ( @$lines )
	{
	    my @opts = split ( '\s+', $line, 2 );
	    my $opt_name = $opts[0]; shift @opts;

	    deb("option for $w{'widget'}: $opt_name");

	    # Table row

	    print $outfile <<"HTML-END";
    	<tr valign=top>
    	    <td>
    		    `opt(`$opt_name)
    	    </td>
    	    <td>
    		@opts
    	    </td>
    	</tr>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
</table>
HTML-END

    }


    # Sample usage

    my $sample_usage = html_quote ( $w{'usage'} );

    print $outfile <<"HTML-END";

<h3>Sample Usage</h3>
<blockquote>
<tt>
$sample_usage
</tt>
</blockquote>

HTML-END


    # Examples

    if ( defined $w{'example'} )
    {
	# logf ( "\tFormatting example", $w{'example'} );

	foreach $example ( split ( '\s', $w{'example'} ) )
	{
	    if ( $example_no == 1 )
	    {
		print $outfile "<h3>Examples</h3>\n<blockquote>";
	    }
	    else
	    {
		print $outfile "<br>\n";
	    }

	    if ( open ( EXAMPLE, $example_dir . "/" . $example ) )
	    {
		print $outfile <<"HTML-END";
<h4>Example $example_no: <a href="$example_dir/$example"><tt>$example</tt></a></h4>
HTML-END
                my $screenshot = "$screenshot_dir/$example";
		$screenshot =~ s/\.ycp$/.png/;

                if ( -s $screenshot )	# exists and non-zero size
		{
		    print $outfile <<"HTML-END";
    <table border=2>
        <tr>
	    <td>
	        <img src="$screenshot">
	    </td>
        </tr>
    </table>
    <br>
HTML-END
		}

		print $outfile <<"HTML-END";
    <table cellpadding=12 bgcolor="#E0E0E0">
	<tr>
	    <td><font size="-1">
		<pre>
HTML-END
		# Copy the example into the HTML output

		while ( <EXAMPLE> )
		{
		    print $outfile &html_quote ( $_);
		}

		print $outfile <<"HTML-END";
		</td>
	    </tr>
	</pre></font>
    </table>
HTML-END
		close ( EXAMPLE );
		$example_no++;
	    }
	}

	print $outfile <<"HTML-END";
</blockquote>
HTML-END
    }

    print $outfile <<"HTML-END";
<br>
<p>
    <a href="$toc_file_name">
	Back to the widget index
    </a>
</p>
HTML-END
}


#-----------------------------------------------------------------------------


# Quote HTML special characters, e.g. '<', '>'
#
# Parameters:
#	$text	String to quote.
#
# Return value:
#	Quoted string.

sub html_quote()
{
    my ( $text) = @_;

    $text =~ s/</&lt;/g;
    $text =~ s/>/&gt;/g;

    return $text;
}


#-----------------------------------------------------------------------------


# Log a message to stderr.
#
# Parameters:
#	Messages to write (any number).

sub warning()
{
    my $msg;

    foreach $msg ( @_ )
    {
	print STDERR $msg . " ";
    }

    print STDERR "\n";
}


#-----------------------------------------------------------------------------


# Log a message to stdout if verbose mode is set
# (command line option '-v').
#
# Parameters:
#	Messages to write (any number).

sub logf()
{
    my $msg;

    if ( $verbose )
    {
	foreach $msg ( @_ )
	{
	    print $msg . " ";
	}

	print "\n";
    }
}


#-----------------------------------------------------------------------------


# Log a debugging message to stdout if debug mode is set
# (command line option '-d').
#
# Parameters:
#	Messages to write (any number).

sub deb()
{
    my $msg;

    if ( $debug )
    {
	foreach $msg ( @_ )
	{
	    print $msg . " ";
	}

	print "\n";
    }
}


#-----------------------------------------------------------------------------


# Print usage message and abort program.
#
# Parameters:
#	---

sub usage()
{
    die "Usage: $0 [-vd]";
}

# EOF
