#!/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  = "ref000";	# if no '@class' specified
my $toc_file_name       = "refenteries.xml";


# 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;

    my $ent_file = FileHandle->new();
    my $ent_file_call = FileHandle->new();
    open ( $ent_file, "> refenteries.ent"  ) or die "FATAL: Can't open refenteries.ent";
    open ( $ent_file_call, "> refenteries.xml"  ) or die "FATAL: Can't open refenteries.xml";
    foreach $main_file_name ( @main_file_names )
    {
	logf( "Reading $main_file_name" );
	read_main_file( $main_file_name , $ent_file, $ent_file_call);
    }
    #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, $ent_file, $ent_file_call ) = @_;
    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 );
                print $ent_file "<!ENTITY $widget{'class'}-widget   SYSTEM \"$widget{'class'}-widget.xml\">\n";
                print $ent_file_call "&$widget{'class'}-widget;\n";
		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.xml";
    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";

<informaltable>
  <tgroup cols="3">
  <tbody>
HTML-HEADER-END

    my $widget;

    foreach $widget ( sort keys %toc_target )
    {
	print $toc_file <<"HTML-HEADER-END";
    <row>
	<entry>
	    <ulink url="$toc_target{$widget}">	$widget	</ulink>
	</entry>
	<entry>
            $toc_description{$widget}
        </entry>
    </row>
HTML-HEADER-END
    }

	print $toc_file <<"HTML-HEADER-END";
        </tbody>
        </tgroup>
</informaltable>
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";

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


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";

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'};
    my $refname = $w{'widget'};
    $refname =~ s:\s+:</refname>\n<refname>:g;
    $w{'widget'} =~ s:\s+:,:g;
    my $id = $w_ref->{'class'};
    $id =~ s:Y(.*):$1:g;
    $id = $id . "_widget";

    print $outfile <<"HTML-END";
    <refentry id="$id">
      <refmeta>
         <refentrytitle>$w{'widget'}</refentrytitle>
         <manvolnum>1</manvolnum>
      </refmeta>
      <refnamediv>
        <refname>$refname</refname>
        <refpurpose>$short_desc</refpurpose>
      </refnamediv>

HTML-END


    print $outfile <<"HTML-END";
    <refsynopsisdiv>
      <funcsynopsis>
HTML-END

    if ( ! defined $w{'arg'} )	# No args
    {
	print $outfile <<"HTML-END";
        <funcprototype>
            <funcdef><function>$w{'widget'}</function></funcdef>
            <void/>
HTML-END

    }
    else			# Widget has args
    {
	my $lines = $w{'arg'};
	my $line;
	my $optlines = $w{'optarg'};
	my $optline;


	# Table header


	print $outfile <<"HTML-END";
        <funcprototype>
            <funcdef><function>$w{'widget'}</function></funcdef>
HTML-END

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

	    print $outfile <<"HTML-END";
            <paramdef choice="req">
                <type>$arg_type</type> 
                <parameter>$arg_name</parameter>
            </paramdef>
HTML-END
        }

        # Optional
	foreach $optline ( @$optlines )
	{
	    my @args = split ( '\s+', $optline, 3 );
	    my $arg_type = $args[0]; shift @args;
	    my $arg_name = $args[0]; shift @args;

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


	    print $outfile <<"HTML-END";
            <paramdef choice="opt">
                <type>$arg_type</type>
                <parameter>$arg_name</parameter>
            </paramdef>
HTML-END
        }

}
	print $outfile <<"HTML-END";
        </funcprototype>
      </funcsynopsis>
    </refsynopsisdiv>

HTML-END


	print $outfile <<"HTML-END";
      <refsect1><title>Description</title>
$w{'description'}
      </refsect1>
HTML-END

if (0) {

    # Create a table for @arg

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

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


	# Table header

	print $outfile <<"HTML-END";
        <informaltable>
            <tgroup cols="3" colsep='1' rowsep='1'>
                <tbody>
HTML-END

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


	    # Table row

	    print $outfile <<"HTML-END";
            <row>
              <entry>
    		<replaceable>$arg_type</replaceable>
    	      </entry>
    	      <entry>
    		    <emphasis role="i">$arg_name</emphasis>
    	      </entry>
    	      <entry>
    	      </entry>
    	</row>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
        </tbody>
        </tgroup>
    </informaltable>
    </refsect1>
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";
	<refsect1>
            <title>Optional</title>
            <variablelist>
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";
                <varlistentry>
                    <term><type>$arg_type</type> <property>$arg_name</property></term>
                    <listitem>
                        <para>@args</para>
                    </listitem>
                </varlistentry>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
            </variablelist>
    </refsect1>
HTML-END

    }


    # Create a table for @prop

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

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

	# Table header

	print $outfile <<"HTML-END";
            <variablelist>
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";
                <varlistentry>
                    <term><type>$prop_type</type> <property>$prop_name</property></term>
                    <listitem>
                        <para>@prop</para>
                    </listitem>
                </varlistentry>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
            </variablelist>
    </refsect1>
HTML-END

    }



    # Create a table for @option

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

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


	print $outfile <<"HTML-END";
	<refsect1>
            <title>Options</title>
            <variablelist>
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");

	    print $outfile <<"HTML-END";
                <varlistentry>
                    <term><option>`opt(`$opt_name)</option></term>
                    <listitem>
                        <para>@opts</para>
                    </listitem>
                </varlistentry>
HTML-END
        }


	# Table footer

	print $outfile <<"HTML-END";
            </variablelist>
        </refsect1>
HTML-END

    }


    # Sample usage

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

    print $outfile <<"HTML-END";

<refsect1><title>Sample Usage</title>
<para>
<replaceable>
$sample_usage
</replaceable>
</para>
</refsect1>
HTML-END


    # Examples

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

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

	    if ( open ( EXAMPLE,  $example_dir . "/" . $example ) )
	    {
		print $outfile <<"HTML-END";
<example>
    <title>$example</title>
<para><ulink
url="$example_dir/$example">$example Source Code</ulink></para>
HTML-END
                my $screenshot = "$screenshot_dir/$example";
		$screenshot =~ s/\.ycp$/.png/;

                if ( -s $screenshot )	# exists and non-zero size
		{
		    print $outfile <<"HTML-END";
                    <para>
      <informalfigure id="$w{'class'}_$example">
        <mediaobject>
          <imageobject>
            <imagedata fileref="$screenshot"  revision="1" format="PNG" />
          </imageobject>
        </mediaobject>
      </informalfigure>
      </para>

HTML-END
		}

		print $outfile <<"HTML-END";
                <para>
                <programlisting id="$example">

                    <xi:include href="$example_dir/$example" parse="text"
                    xmlns:xi="http://www.w3.org/2001/XInclude"/>
                </programlisting>
                </para>
            </example>

HTML-END
		close ( EXAMPLE );
		$example_no++;
	    }
	}

	print $outfile <<"HTML-END";
        </refsect1>
        </refentry>
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
