package ReDIF::init;

##  Copyright (c) 1997-2001 Ivan Kurmanov. All rights reserved.
##
##  This code is free software; you can redistribute it and/or modify it
##  under the same terms as Perl itself.

$VERSION = "0.1";

=pod

=head1 NAME

ReDIF::init - ReDIF configuration initializer module (perl)

=head1 SYNOPSIS

    use ReDIF::init;

    ReDIF::initialize( { conf_file_name => 'rech.conf',
			 conf_required  => 1 ,
			 print_results  => 1,
		         silent_init    => 0  } );

    ###  redif.spec file's full name
    my $redif_spec = $ReDIF::CONFIG{spec_full_name};

    ###  local data dir, e.g. RePEc archive dir
    my $data_path  = $ReDIF::CONFIG{data_path};

    ###  archive id
    my $archive_id = $ReDIF::CONFIG{archive_id};

    #  so on ...

=head1 DESCRIPTION

This module is part of ReDIF-perl suite.  It has been designed to
analyse the start-up command-line options, environment variables,
current filesystem (directory tree) to extract ReDIF configuration
information out of it and to prepare for using ReDIF tools.

ReDIF configuration information is a set of values (mainly file and
directory names), that some of the core tools (e.g. ReDIF parser)
depend upon.  Additionally, it will look for a user's configuration file
for your programme, if you ask it to.  Unless you turn off
user messages, it will report about the progress to the standard output. 

The module has one entry point - C<initialize()> function.  This
function will accept an optional hash reference as a parameter.  In
that hash several options will be recognized:

-   print_results (former: silent_init with negative meaning)

-   conf_file_name

-   conf_required

=over 4

=item B<print_results>

If set to non-zero will make initialize() to print out the
configuration it finds out in a message like this one: 

  ReDIF configuration:
          Specification file:     ./spec/redif.spec
          loaded ReDIF setup configuration module from perl's library
          ReDIF home dir:         /home/ivan/data/RePEc/wop
          Local data dir:         /home/ivan/data/RePEc/wop


=item B<conf_file_name>

Give the name of the configuration file (just name, e.g. "rech.conf")
that you expect from your users to maintain.  If not specified,
nothing is done about the prorgam's configuration file.  If specified,
the file will be searched for in the local configuration directory.
Used by the B<rech>.  See also I<$ReDIF::CONFIG{conf_full_name}>
below.

=item B<conf_required>

if set to a non-zero value, then absence of a appropriate
configuratoin file as given by the previos parameter
I<conf_file_name>, will trigger a fatal error.

=back

As a result of C<initialize()>, you get all necessary configuration
values in a special hash B<%ReDIF::CONFIG>.  In particular, there
shall be the following items:

-   redif_home	    

-   redif_home_type  

-   data_path	    

-   conf_full_name	

-   spec_full_name	

-   archive_id	 

-   authority_id	 

-   address	 

=over 4

=item B<$ReDIF::CONFIG{redif_home}>

=item B<$ReDIF::CONFIG{redif_home_type}>

Well, I<redif_home> is a path to the main directory where the user
stores ReDIF-related stuff. In terms of RePEc this means the directory
of the user's ReDIF archive (as set by the B<REDIFDIR> environment
variable, for example).

But here I also introduce a new notion - a stand-alone ReDIF home.  If
you do not have a RePEc archive and do not need one, but still need to
work with ReDIF, then this is for you.  Classic ReDIF/RePEc archive
shall be placed in a three-letter-named directory.  Inside it there
shall be the F<conf/> directory for the local configuration files.
Beside it there shall be the F<remo/> directory, where at least the
central "all" archive shall be mirrored.  The "all" archive shall
contain the global templates, provided software, and global
configuration files, including the ReDIF specification file
F<redif.spec>.

For a stand-alone home I suggest a completely different directory
structure: 

F<REDIFHOME/>       - ReDIF home directory

F<REDIFHOME/spec/>  - ReDIF specification directory (global)

F<REDIFHOME/lib/>   - ReDIF perl modules directory (optional)

F<REDIFHOME/data/>  - local data directory

F<REDIFHOME/etc/>   - local configuration files

User has many options to specify his ReDIF home directory to a
program: through a command-line option I<--rdir> or I<--redif.home>,
by setting an environment variable B<REDIFDIR> or B<REDIFHOME>, by
executing the script from that directory.  And maybe the most simple
way is to configure your ReDIF-perl installation for that directory
during before actually installing it.  (Then the ReDIF home directory
path will be stored together with the ReDIF parser modules somewhere
down the Perl's lib directory.)  During ReDIF-perl installation user
is asked to specify his ReDIF home directory and this setting will
then be automatically retrieved when necessary.

The priority of the different sources for redif_home is as follows:
(the first found will be used leaving all the rest unchecked)
command-line options, environment variables, default configuration
saved at installation stage, current working directory.

The candidate ReDIF home directory is always checked to contain
RePEc-like or stand-alone directory structure.  initialize () function
checkes that and sets the I<redif_home_type> value appropriately.  It
takes "RePEc" or "stand-alone" values respectively.

=item B<$ReDIF::CONFIG{data_path}>

That will be the path where the local user's data is stored. Used by
B<rech> when by default it checks local user's data.

=item B<$ReDIF::CONFIG{conf_full_name}>

If a program uses B<ReDIF::init> to find the user's configuration file
for itself, then the full file name will be in this variable. The
configuration file is searched for in F<REDIFHOME/conf/> or
F<REDIFHOME/etc/> directories, depending on the home type.  Note, that
no operation will be performed on that file, it is fully your
responsibility to load or process the configuration file.

This is used in B<rech>, for example.

=item B<$ReDIF::CONFIG{spec_full_name}>

ReDIF specification file pathname.  Necessary for the ReDIF parser.

=item B<$ReDIF::CONFIG{archive_id}>

=item B<$ReDIF::CONFIG{authority_id}>

=item B<$ReDIF::CONFIG{address}>

These three items are experimental.  As Guildford protocol requires,
the ReDIF archive directory shall be named according to the 3-letter
archive id code, which has been assigned by the RePEc authority.  That
gives the programs ability to identify the archive they are working with.

Authority id and address parameters are new and related to the
multi-authority development of ReDIF taking place now.
I<authority_id> is taken from the ReDIF home directory like-wise the
I<archive_id>, but from a previous part of the directory pathname.
That means that if ReDIF home is F</home/joe/RePEc/jar> then the
I<archive_id> will become "jar", and the I<authority_id> will become
"RePEc". And the I<address> is a combination of both.  In the example
above it will take the value of "RePEc:jar".

=back

=head2 ERROR HANDLING

I'm afraid the module is somewhat not careful enough about the calling
program and not too flexible about error handling.  It is too
self-confident about it's own importance and if something goes wrong,
it just quits with an error message.  Perl function I<exit> is used to
abort the program.  If this behaviour is too rude for your taste and
for your needs, let me know - I'll change it in the next version.

=head2 USER OUTPUT 

All user messages, generated by ReDIF::init.pm are printed to the
standard output, including error messages.  Each normal message starts
with "ReDIF-init: ", error messages start with "ReDIF-init-Error:".
For example module's output may look like this (as part of B<rech>'s
output):

 ReDIF configuration:
        Specification file:     ./spec/redif.spec
        loaded ReDIF setup configuration module from perl's library
        ReDIF home dir:         /home/ivan/data/RePEc/wop
        Local data dir:         /home/ivan/data/RePEc/wop


=head2 END-USER INSTRUCTIONS

ReDIF-perl software package consists of a number of scripts and perl
modules and helper-files.  Any tool that is dependent on ReDIF-perl
(e.g. remi and rewe scripts) must be able to locate all components and
use them.  In particular following components may require special
arrangements:

-  ReDIF specification file (if not default included redif.spec)

-  local ReDIF data (your own *.rdf files)

-  local configuration file for a specific program, e.g. remi.conf 

To make it work you need a directory which we would call a ReDIF home.
That is a directory, to which you have downloaded (mirrored) or
unpacked all ReDIF/RePEc stuff.  That directory shall contain iether
some of the etc/, spec/, data/ or alternatively it may be the
directory of your ReDIF (RePEc) archive, which holds your data files
and a conf/ directory.  In the former case you may have all
ReDIF-related files under that one ReDIF-home directory.  In the later
case, it is assumed that your archive's directory is named and placed
according to the Guildford protocol document (included into ReDIF-perl
package, doc/ directory).

Probably the simplest way to ensure that all components are found at
their correct places is to configure ReDIF-perl appropriately at the
installation time.  When you execute 'perl Makefile.PL' it will ask
you about the ReDIF home directory setting.  If you agree to set it,
than that configuration information will be saved into a perl module
and installed with other modules into your perl's library tree and
then it will always be automatically used, if no other setting has
been supplied to the software.

If not configured at the installation time or if you want to override
that configuration, you can always use environment variable
B<REDIFDIR> (or B<REDIFHOME>) to your ReDIF home dir.

As an alternative to using an environment variable, you can supply
home directory of ReDIF explicitly on the command-line as an option.
Use I<'--rdir'> or I<'--redif.home'> options for that purpose.  E.g.:

     joe:~$ rech --rdir /home/joe/ReDIF

And at last you can correctly start a tool without explicitly naming
your ReDIF home directory, if you launch the command from that
particular directory.  That is, if no appropriate environment
variables found, no command-line options given, the program will check
if the current working directory looks like a ReDIF home dir.  E.g.

     joe:~/metadata/ReDIF$ rech 

A directory tree will be checked and if all necessary components will
be found in their default places, the script shall start well.

Default place for the ReDIF specification file is
F<REDIFHOME/spec/redif.spec>.  If ReDIF-perl is not installed into
local perl, then F<REDIFHOME/lib/> is checked to contain ReDIF perl
parser modules.  Default directory forconfiguration files is
F<REDIFHOME/etc/> and by convention such files are named
F<PROGNAME.conf>.

B<WARNING: The previous paragraph is not true for ReDIF-perl version
2.19.  That version has a built-in redif.spec and always by default
uses it.  "By default" here means "unless specified by the below
described options --spec or --redif.spec".>

To override the default ReDIF specification file name for the program
to use, you can give I<--spec> and I<--redif.spec> command line
options and a bare file name or a directory pathname or a full file
pathname after it. The value will be interpreted differently depending
on its type.  E.g.

 (1)   joe:~/metadata/ReDIF$ rech --spec my-redif.spec

 (2)   joe:~/metadata/ReDIF$ rech --spec ~/spec.my

 (3)   joe:~/metadata/ReDIF$ rech --spec ~/spec.my/redif.spec-new

In the first case shown the file F<my-redif.spec> will be searched for
in the default spec directory (which depends on the ReDIF home dir
used).

In the second case, the default named file F<redif.spec> will be
searched for in the specified F<~/spec.my/> directory. 

And in the last case, file F<~/spec.my/redif.spec-new> will be used as
a spec (if it exists).

To override the default configuration file name, you can use I<--conf>
command-line option and give the full conf file name after it. (Just
full name, no more complications like with I<--spec>...)

=head1 AUTHORS

Ivan Kurmanov (kurmanov@openlib.org),
with support from Thomas Krichel (krichel@openlib.org)
for the RePEc project

=cut
    
#==============================================================================
# code  code  code  code  code  code  code  code  code  code  code  code  code
#==============================================================================

{
;}    


package ReDIF;

%CONFIG = ();
%CONFIG_FLAGS = ();
use vars qw( $Options ) ;

use Cwd;

######## MAIN FUNCTION 

sub initialize {

#    $DEBUG = 1;

    my $options = shift;

    $Options = $options;

    config_set_defaults();

    if (ref $options) {
	foreach ( keys %$options ) {
	    $CONFIG{$_} = $options->{$_}; 
	}
    }

    if( $Options->{print_results} ) {
	print "ReDIF configuration: \n";
    }

    # - - - - - - - - - - -
    prepare_configuration()
	or return undef;
    # - - - - - - - - - - - 
    config_use();
    # - - - - - -
}

# setting
# default values:
#========
sub config_set_defaults {
#========
    
	$CONFIG{spec_file_name} = 'redif.spec';
	$CONFIG{lib_test_file}  = 'ReDIF/rc2.pm';

}

#
# Using %CONFIG values: 
#    libs_path, 
#    spec_full_name, 
#    conf_full_name;
# 
#===============
sub config_use {
#===============
# assuming that prepare_configuration has already been executed
# 
  if ($CONFIG_FLAGS{libs_path} eq 'set') {
      unshift @INC, $CONFIG{libs_path};
  }

  # load configuration file
 
  if ($CONFIG{conf_file_name}) {
      if( not $CONFIG{conf_full_name} ) {
	  if ( $CONFIG{conf_required} ) {
	      die "internal logic error";
	  } else {
	      config_report( "No configuration file found. Ignoring." );
	  }
      }
  }
}


#=========================
sub prepare_configuration { 
#=========================
    
    my %flag;

    config_report( "Cmdline params: ", join( ' | ', @ARGV ) )
        if $DEBUG;

        # Check if rr.pm perl module can load
        # without updating @INC array:
    
    my $test;
    $test = eval " use ReDIF::Parser::Output; " ;

    if (not $@) {
#        config_report( "Libs (modules) are installed in Perl" );
      	$CONFIG_FLAGS{libs_path} = 'not needed';
    } elsif ( $DEBUG ) {
	config_report( "not found ReDIF-perl libs!" ); 
    }

    # SPECIFICATION
    # first thing to do - check command line for
    #     '--spec' and '--redif.spec' parameters
    
    my $spec_path = get_commandline_opt( '--spec', '--redif.spec' );
    my $spec_found = 0;
    if ( $spec_path ) {
        if ( -d $spec_path ) {
            config_try_option( 'spec_full_name', 'specification file',
                               "$spec_path/$CONFIG{spec_file_name}",
                               'file' )
		or die "Bad ReDIF specification file path: $spec_path";  
	    $spec_found = 1;
        } else {
            
            # it is not a directory. hmm... then it may 
            # be a 
            if ( $spec_path =~ m#\/|\\# ) { 
                if ( -f $spec_path ) {
                    config_try_option( 'spec_full_name', 'specification file',
                               $spec_path,
                               'file' )
                        or die "Bad ReDIF specification file path: $spec_path";  
		    $spec_found = 1;
                } else {
                  # error: a path is not a valid file or directory  
                  # path, and not a separate spec-file name
                    
#                    config_report( 
#                       "Bad specification file path: '$spec_path'" );
		    die "Bad ReDIF specification file path: $spec_path";
		    $spec_found = 0;
                }
            } else {
                $CONFIG{spec_file_name} = $spec_path;
                config_report(
		   "Will look for specification file named: '$spec_path'" );
		
            }
        }
    } else {

	###  Use built-in redif.spec, unless specified with options!

	my $dir = $INC{'ReDIF/init.pm'} ;
	warn $dir if not $dir;
	$dir = reverse $dir; 
	$dir =~ s/^[^\/]+//g;
	$dir = reverse $dir;
	my $spec_path = join '', $dir, "redif.spec";
	warn "$spec_path: redif.spec?" if not -f $spec_path;
	config_try_option( 'spec_full_name', 'specification file',
			   $spec_path,
			   'file' ) 
	    or die;
    }

    #  EXPLICIT CONF FILE SETTING
    if ($CONFIG{conf_file_name}) {
       my $conf_file = get_commandline_opt( '--conf' );
       if ($conf_file) {
           $t = config_try_option ( 'conf_full_name', 'configuration file',
                $conf_file,
                 'file' );
           if (not $t) {
                config_error( 
		     "Not found specified config file: '$conf_file'" );
                exit;
           }
       }
    }

    # REDIF HOME DIRECTORY

    my $rhome = get_commandline_opt( '--rdir' , '--redif.home' );
    if ($rhome) {
        config_try_use_redif_home( $rhome, 1, 
            "command-line options (--rdir or --redif.home)" );

    } elsif ( ($rhome = $ENV{'REDIFDIR'}) 
	      or 
	      ($rhome = $ENV{'REDIFHOME'}) )  {
#            print "ENV\n";
	config_try_use_redif_home( $rhome, 1, 
	      	   "environment (REDIFDIR or REDIFHOME)" );

    } else {

	# check if spec file and home ReDIF dir are in the
	# ReDIF::setup_conf module
	my $test = eval {
	    require( 'ReDIF/setup_conf.pm' );
	};
	if ( ( not $@ ) 
	     and exists $ReDIF::CONFIG_candidate{'redif_home'} ) {
	    config_report( 
		     "loaded ReDIF setup configuration module from perl's library" );
	    config_try_candidates( );

	} else {
	    ### trying current directory (finally)

	    $rhome = getcwd();

	    if( not config_check_redif_home( 1, 2, $rhome ) ) {
		$ReDIF::CONFIG_candidate{'redif_home'} = $rhome;	    
		config_try_candidates( );
	    }
	    
#	    config_try_use_redif_home( $rhome, 1 );	    
	}
    }



    if ( not $CONFIG{spec_full_name} 
	 or 
	 not $CONFIG_FLAGS{libs_path} ){
	config_error( "Did not find some neccesary configuration components" );
	exit;
    }

    if ( not $CONFIG_FLAGS{redif_home} ){
	config_report( "[Warning] Did not find a valid ReDIF home dir" );
    }

    if ( $DEBUG ) {
        config_report( 'ENVIRONMENT:');
        foreach ( keys %ENV ) {
            config_report ( "$_ = $ENV{$_}" );
        }
    }
    
    config_report( "Cmdline params: ", join( ' | ', @ARGV ) ) 
        if $DEBUG;
    
#    config_use();
}

#
# test and prepare to use
# a redif_home value
#===========
sub config_try_use_redif_home {
#===========

    my( $rhome, $critical, $source ) = @_;
    
    $CONFIG_candidate{redif_home} = $rhome;

    config_try_candidates( $critical );

}

#=========================
sub config_try_candidates{
#=========================

    my $critical = shift;
    my $t;

    ####  start with redif_home...

    if ( not $CONFIG_FLAGS{redif_home} and 
	 my ($rhome) = $CONFIG_candidate{redif_home}) { 
	     $t = config_try_option ( 'redif_home', 'ReDIF home dir', 
				      $rhome, 
				      'dir', \&config_check_redif_home ) ;

	     $CONFIG{redif_home_type} = $CONFIG_candidate{home_type};

	     if( defined $critical and $critical and not $t ) {
		 exit;
	     }
    }

    if ( not defined $CONFIG{spec_full_name} 
         or $CONFIG_FLAGS{spec_full_name} ne 'set' ){

       ###  now see if we can find our spec

       if (-e "$CONFIG_candidate{spec_path}/$CONFIG{spec_file_name}") {
           $t = config_try_option ( 'spec_full_name', 
	       	     'specification',
                     "$CONFIG_candidate{spec_path}/$CONFIG{spec_file_name}",
                     'file' ) ;
           if (not $t) { exit }
       } else { 
           config_error( "Cannot find specification file ",
            "(tried: $CONFIG_candidate{spec_path}/$CONFIG{spec_file_name})" ); 
           exit;
       }
    }

    # now see if we can find our libraries

    if ( $CONFIG_FLAGS{libs_path} ) {
	# do nothing then - everything has already been done :-)

    } elsif ( not -e 
        "$CONFIG_candidate{libs_path}/$CONFIG{lib_test_file}" ) {
        config_error( "Cannot find libraries" , 
		      " (tried: $CONFIG_candidate{libs_path}/" . 
		      "$CONFIG{lib_test_file})" ); 
        exit;
    } else {
        $t = config_try_option ( 'libs_path', 'ReDIF libs directory',
				 $CONFIG_candidate{libs_path}, 'dir' );
        if (not $t) { exit }  
    }

    # now see if we can find our conf file
    if ( $CONFIG{conf_file_name} 
        and 
         ( not defined $CONFIG_FLAGS{conf_full_name} 
	   or $CONFIG_FLAGS{conf_full_name} ne 'set') 
    ){
        if (-e "$CONFIG_candidate{conf_path}/$CONFIG{conf_file_name}") {
            $t = config_try_option ( 'conf_full_name', 
				     'configuration',
                 "$CONFIG_candidate{conf_path}/$CONFIG{conf_file_name}",
                 'file' );
            if (not $t) { exit }
        } elsif( $CONFIG{conf_required} ) { 
            config_error( "Cannot find configuration file" . 
			  " (tried: $CONFIG_candidate{conf_path}".
			  "/$CONFIG{conf_file_name})" ); 
            exit;
        }
    }

    ### looking for local data dir

    if(  (not defined $CONFIG_FLAGS{data_path} ) 
	 or 
	 ($CONFIG_FLAGS{data_path} ne 'set') 
	     ){
         if( defined $CONFIG_candidate{data_path} 
	     and -e $CONFIG_candidate{data_path} ) {
              $t = config_try_option ( 'data_path', 'local data dir',
                     	     $CONFIG_candidate{data_path}, 'dir' );
         }
    }
    
    ### looking at archive and authority identification

    if( not defined $CONFIG_FLAGS{address} 
	or $CONFIG_FLAGS{address} ne 'set' ){
	if( $CONFIG_candidate{archive_id} ) {
	    $CONFIG{archive_id} = $CONFIG_candidate{archive_id};
	    $CONFIG{authority_id} = $CONFIG_candidate{authority_id};
	    $CONFIG{address} = $CONFIG{authority_id} . ':' 
		. $CONFIG{archive_id} ;
	}
    }

}


#
# config_check_redif_home function
# 
# DESCR: this function is called by the config_try_option function,
# to check the "redif_home" config setting
#
#============================
sub config_check_redif_home {
#============================
    
    my(  $libs_path, $spec_path, $conf_path, $data_path, $home_type );
    if( $DEBUG ) {
	print 'check_redif_home: ', join( ' : ', @_ ) , "\n" ;
    }
    my $ReDIF_root;
    my $value = $_[2];
    
    die if not $value;

    $ReDIF_root = parse_ReDIF_dir_old( $value ) ;

    if (  
	  (-d "$ReDIF_root/remo/all/root")
	  )
    {   ### New-style home
	$home_type = "xA-2000" ;
	    
	if ( not ( 
                (-d "$ReDIF_root/remo/all/root/conf")
#                (-d "$ReDIF_root/remo/all/root/spec")  ### SPEC!!!!
		   or 
                (-d "$ReDIF_root/remo/all/root/soft")
		   ) )
	{
	    return "Bad new-style (xA-2000) ReDIF home: " . 
		"no all/root/conf or all/root/soft dir ($ReDIF_root)";
#		"no all/root/spec or all/root/soft dir ($ReDIF_root)"; ### SPEC
	}

	$CONFIG_candidate{conf_path} = "$value/conf";
	$CONFIG_candidate{spec_path} = "$ReDIF_root/remo/all/root/conf";
#	$CONFIG_candidate{libs_path} = "$ReDIF_root/remo/all/root/soft/RePEc/all";
	$CONFIG_candidate{data_path} = $value ;
	$CONFIG_candidate{home_type} = $home_type;
	return 0; 
    }


    if (  
	  not $ReDIF_home 
	  and 
	  (-d "$value/spec") 
	  and
	  (-d "$value/etc") )
    {   ### New stand-alone style home
	$home_type = "stand-alone" ;
	    
	$CONFIG_candidate{conf_path} = "$value/etc";
	$CONFIG_candidate{spec_path} = "$value/spec";
#	$CONFIG_candidate{libs_path} = "$value/lib";
	$CONFIG_candidate{data_path} = "$value/data";
	$CONFIG_candidate{home_type} = $home_type;
	return 0; 
    }
 


    if (  
	  (-d "$value/conf") 
	  and 
	  (-d "$ReDIF_root/remo"))
    {   ### Old-style home
	$home_type = "RePEc" ;
	    
	if ( not ( 
                (-d "$ReDIF_root/remo/all/conf")
		   or 
                (-d "$ReDIF_root/remo/all/soft")
		   ) )
	{
	    return "Bad old-style ReDIF home: " . 
		"no all/conf or all/soft dir ($ReDIF_root)";
	}

	$CONFIG_candidate{conf_path} = "$value/conf";
	$CONFIG_candidate{spec_path} = "$ReDIF_root/remo/all/conf";
#	$CONFIG_candidate{libs_path} = "$ReDIF_root/remo/all/soft/RePEc/all";
	$CONFIG_candidate{data_path} = $value ;
	$CONFIG_candidate{home_type} = $home_type;
	return 0; 
    }

    return "not a valid ReDIF home: $value";
}


#========================
sub parse_ReDIF_dir_old {
#========================
    my( $dir ) = shift;
    my $ReDIF_root;
#    warn "parse_ReDIF_dir_old: $dir";
    if( $dir =~ m/^(.*[\/\\]([^\\\/]+))[\/\\]([^\\\/]+)[\/\\]?$/ ) {
	$ReDIF_root = $1;
	$CONFIG_candidate{authority_id} = $2;
	$CONFIG_candidate{archive_id}   = $3;
    } else {
	$CONFIG_candidate{authority_id} = undef;
	$CONFIG_candidate{archive_id}   = undef;
    }
    return $ReDIF_root;
}

#
# Output an error message 
#================
sub config_error{
#================

    print( "  Error: " , @_ , "\n");

}

# print out a user message. Synopsis:
#
#                config_report( MESSAGE_TEXT )
#
#=================
sub config_report {
#=================

    if( $Options->{print_results} ) {
	print "\t", @_, "\n";
    }
}



# config_try_option( OPTION, DESCRIPTION, VALUE, TYPE, CHECK_SUB );
#   
#  This checks an option value and sets $CONFIG{OPTION} 
#  if appropriate. 
#
#  Accepted types: 'file' or 'dir' 
#  (both are checked for existance and readability) 
#
#  CHECK_SUB allows to execute your 
#  own checking code for the option value, while 
#  leaving other logic in the general stream.
#
#=====================
sub config_try_option{
#=====================
    my( $option, $description, $value, $type, $check_sub ) = @_;
    my( $state, $result );
    if ($type eq 'file' or $type eq 'dir') {
                #   \u is a ucfirst() equivalent in 
                #   double-qouted strings

        if (not -e $value){ 
           config_error( "\u$type '$value' specified as $description doesn't exists");
           return 0;
        }

        if (not -r $value){ 
           config_error( "\u$type '$value' specified as $description is not readable");
           return 0;
        }

        if ($type eq 'dir') { 
            if (not -d $value){ 
               config_error( "\u$type '$value' specified as $description is not a directory");
               return 0;
            }
        }
        if ($type eq 'file') { 
            if (not -f $value){ 
               config_error( "\u$type '$value' specified as $description is not a file");
               return 0;
            }
        }

    } else {
        die "run-time error at ReDIF::config_try_option function,";
    }

    if ( defined $check_sub ) {
        $result = &$check_sub( $option, $description, $value );
    } else {
        $result = 0;
    }
    if ( $result ) {
        config_error( "Bad $description setting: '$value' ($result)" );
        return undef;
    }
    else {
        $CONFIG{$option} = $value;
        $CONFIG_FLAGS{$option} = 'set';
        config_report( "\u$description: \t$value");
        return 1;
    }
    
}


# get_commandline_opt( OPTION_NAME1, OPTION_NAME2, ... );
# 
# This function will scan the @ARGV array (command-line 
# arguments for the options and will fetch the value, which 
# comes next after the option on the line. Both elements will be 
# extracted and deleted from the @ARGV array. 
#
# If an option is repeated, this will be reported, but only the 
# first value will be accounted.
# 
# This functions uses config_report() sub to output 
# user error-message.
#
sub get_commandline_opt {
    
    my (@opt) = @_;
    my (%opt);
    my ( $index, $result, $found_flag );
    $index = 0;
    
    foreach ( @opt ){
        $opt{$_}=1;
    }
    foreach ( @ARGV ) {
        
        if ($opt{$_}) {
            if ($found_flag) {
                config_report ( 
                  "Duplicate command-line option: $_ $ARGV[$index+1]" );
                splice( @ARGV, $index, 2 );
            } else {
                #  now extract two elements, starting from current
                # from the ARGV array
                ($_,$result) = ( splice( @ARGV, $index, 2 ) );
                $found_flag=1;
            }
        }
        $index++;
    }
    # return the value
    return $result;
}

#  Checks if this or that command-line option present, without any value
#
#
sub check_commandline_opt {
    my (@opt) = @_;
    my (%opt);
    my ( $index, $found_flag, $res );
    
    foreach ( @opt ){
        $opt{$_}=1;
    }
    foreach ( @ARGV ) {
        
        if ($opt{$_}) {
                #  now extract that elements, starting from current
                # from the ARGV array
                ($res) = ( splice( @ARGV, $index, 1 ) );
                $found_flag=1;
        }
        $index++;
    }
    # return the value
    return $res;
}

1;


__END__









