package xm::o;
use strict;

BEGIN {
	use Exporter;
	use vars qw(@EXPORT_OK @EXPORT %EXPORT_TAGS %o);
        use subs qw(argv_stdin argv_filehash xx);
        @EXPORT = qw( %o %xm );
	@EXPORT_OK = qw( argv_stdin argv_filehash);
	%EXPORT_TAGS = ( FIELDS => [ @EXPORT, @EXPORT_OK ] );
}
use vars @EXPORT;
sub import { goto &Exporter::import }

# ---------------------------------------------------------------- #
sub xx
{
    return defined $_[0] ? $_[0] : ""
}
# ---------------------------------------------------------------- #

# scan the comandline, open everything that looks like a filename
# and feed it into $o{" "}. Everything that looks like an option
# is going to set a $o{name}-value. The default is "" for an empty
# value.
sub args_stdin 
{
    my $argv = shift;
    my $desc = shift;
#    local $_;

    if ($#$argv < 0)
    {
	$main::package = $0 if not defined $main::package;
	print STDERR "$$: $main::package @$argv\n";
	if (defined $desc)
	{
	    print STDERR "DESCRIPTION\n";
	    print STDERR $desc;
        }
        exit;
    }

    $o{" "} = "";
    $o{"="} = [ ];
    for (@$argv)
    {
        if (/^--help$/ or /^-\?/) 
      	{ print $desc if defined $desc; print " <$$>\n"; exit; }
        elsif (/^--?([\w-]+)=(.*)/) { $o{$1} = $2; }
        elsif (/^--?([\w-]+)/) { $o{$1} = ""; }
        elsif (/^-$/) { 
	    push @{$o{"="}}, $_;
	    $o{" "} .= join ("",<STDIN>); 
	}
        else { 
            push @{$o{"="}}, $_;
	    my $F = $_; 
	    if (open F, "<$F") { $o{" "} .= join("",<F>); close F; }
	    else { die "could not open $F", $1; }
	}
    }
    return $o{" "};
}

sub argv_stdin
{
    return args_stdin \@ARGV, @_;
}

# scan the comandline, open everything that looks like a filename
# and feed the content to the scalar value of a hash entry ${"filename"}.
# The hash is returned as a reference.  Everything that looks like an 
# option is going to set a $o{name}-value. The default is "" for an empty
# value. (usedby: xm::tab::argv_filehash)
sub argv_filehash 
{
    my $desc = shift;
    my $f = { }; # a hash-reference
#    local $_;

    if ($#ARGV < 0)
    {
	$main::package = $0 if not defined $main::package;
	print STDERR "$$: $main::package @ARGV\n";
	if (defined $desc)
	{
	    print STDERR "DESCRIPTION\n";
	    print STDERR $desc;
        }
        exit;
    }

    $o{" "} = "";
    $o{"="} = [ ];
    for (@ARGV)
    {
        if (/^--help$/) 
	{ print $desc if defined $desc; print " <$$>\n"; exit; }
        elsif (/^--?([\w-]+)=(.*)/) { $o{$1} = $2; }
        elsif (/^--?([\w-]+)/) { $o{$1} = ""; }
        elsif (/^-$/) { 
            push @{$o{"="}}, $_;
	    $$f{"-"} .= join ("",<STDIN>); 
	}
        else { 
            push @{$o{"="}}, $_;
	    my $F = $_; 
	    if (open F, "<$F") { $$f{$F} .= join("",<F>); close F; }
	    else { die "could not open $F", $1; }
	}
    }
    return $f;
}

# scan the comandline. Everything that looks like an 
# option is going to set a $o{name}-value. The default is "" for an empty
# value. Return the remaining args are assumed to be filename like and
# returned as an array. <STDIN>-lines will be pushed to the array too.
sub args_files
{
    my $argv = shift;
    my $desc = shift;
#    local $_;

    if ($#$argv < 0)
    {
	$main::package = $0 if not defined $main::package;
	print STDERR "$$: $main::package @$argv\n";
	if (defined $desc)
	{
	    print STDERR "DESCRIPTION\n";
	    print STDERR $desc;
        }
        exit;
    }

    $o{"="} = [ ];
    for (@$argv)
    {
        if (/^--help$/) 
	{ print $desc if defined $desc; print " <$$>\n"; exit; }
        elsif (/^--?([\w-]+)=(.*)/) { $o{$1} = $2; }
        elsif (/^--?([\w-]+)/) { $o{$1} = ""; }
        elsif (/^-@?$/) { # read filenames from stdin
	    my $f; 
	    while ($f = <STDIN>) 
	    { 
		if ($f !~ /^\s*/ and $f !~ /^\#\s/)
		{
		    push @{$o{"="}}, $f;
	        }
	    }
	}
        elsif (/^-@=(.*)$/) { # read arguments from a file
	    my $F = $1;
	    my $f; 
	    open F, "<$F" or next;
	    while ($f = <F>) 
	    { 
		if ($f !~ /^\s*/ and $f !~ /^\#\s/)
		{
		    push @{$o{"="}}, $f;
	        }
	    }
	    close F;
	}
        else { 
	    push @{$o{"="}}, $_;
	}
    }
    return $o{"="};
}

sub argv_files
{
    return args_files \@ARGV, @_;
}

# scan the comandline. Everything that looks like an 
# option is going to set a $o{name}-value. The default is "" for an empty
# value. The remaining args are assumed to be filename-like and they are
# returned as an array. 
sub args_command
{
    my $argv = shift;
    my $desc = shift;
#    local $_;

    if ($#$argv < 0)
    {
	$main::package = $0 if not defined $main::package;
	print STDERR "$$: $main::package @$argv\n";
	if (defined $desc)
	{
	    print STDERR "DESCRIPTION\n";
	    print STDERR $desc;
        }
        exit;
    }

    $o{"="} = [ ];
    for (@$argv)
    {
        if (/^--help$/) 
	{ print $desc if defined $desc; print " <$$>\n"; exit; }
        elsif (/^--?([\w-]+)=(.*)/) { $o{$1} = $2; }
        elsif (/^--?([\w-]+)/) { $o{$1} = ""; print STDERR "<?",$1,">"; }
        elsif (/^-@=(.*)$/) { # read arguments from a file
	    my $F = $1;
	    my $f; 
	    open F,"<$F" or next;
	    while ($f = <F>) 
	    { 
		if ($f !~ /^\s*/ and $f !~ /^\#\s/)
		{
		    push @{$o{"="}}, $f;
	        }
	    }
	    close F;
	}
        else { 
	    push @{$o{"="}}, $_;
	}
    }
    return $o{"="};
}

sub argv_command
{
    return args_command \@ARGV, @_;
}


1;