diff CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/mummer-3.23/scripts/Foundation.pm @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/mummer-3.23/scripts/Foundation.pm	Tue Mar 18 17:55:14 2025 -0400
@@ -0,0 +1,1838 @@
+package TIGR::Foundation;
+{
+ 
+=head1 NAME
+
+TIGR::Foundation - TIGR Foundation object
+
+=head1 SYNOPSIS
+
+  use TIGR::Foundation;
+  my $obj_instance = new TIGR::Foundation;
+
+=head1 DESCRIPTION
+
+This module defines a structure for Perl programs to utilize
+logging, version reporting, and dependency checking in a simple way.
+
+=cut
+
+   BEGIN {
+      require 5.006_00;                       # error if using Perl < v5.6.0  
+   }
+
+   use strict;
+   use Cwd;
+   use Cwd 'chdir';
+   use Cwd 'abs_path';
+   use File::Basename;
+   use Getopt::Long;
+   use IO::Handle;
+   use POSIX qw(strftime);
+   use Sys::Hostname;
+   use English;   
+
+   require Exporter;
+
+   our @ISA;
+   our @EXPORT;
+   @ISA = ('Exporter');
+   @EXPORT = qw(
+                isReadableFile
+                isWritableFile
+                isExecutableFile
+                isCreatableFile
+                isReadableDir
+                isWritableDir
+                isCreatableDir
+                isCreatablePath
+
+                getISODate
+                getSybaseDate
+                getMySQLDate
+                getFilelabelDate
+                getLogfileDate
+               );
+
+   ## internal variables and identifiers
+   our $REVISION = (qw$Revision: 1.1.1.1 $)[-1];
+   our $VERSION = '1.1'; 
+   our $VERSION_STRING = "$VERSION (Build $REVISION)";
+   our @DEPEND = ();                          # there are no dependencies
+
+
+   ## prototypes
+
+   # Functional Class : general
+   sub new();
+   sub getProgramInfo($);
+   sub runCommand($);
+
+   # Functional Class : depend
+   sub printDependInfo();
+   sub printDependInfoAndExit();
+   sub addDependInfo(@);
+
+   # Functional Class : version
+   sub getVersionInfo();
+   sub printVersionInfo();
+   sub printVersionInfoAndExit();
+   sub setVersionInfo($);
+
+   # Functional Class : help
+   sub printHelpInfo();
+   sub printHelpInfoAndExit();
+   sub setHelpInfo($);
+
+   # Functional Class : usage
+   sub printUsageInfo();
+   sub printUsageInfoAndExit();
+   sub setUsageInfo($);
+
+   # Functional Class : files
+   sub isReadableFile($);
+   sub isExecutableFile($);
+   sub isWritableFile($);
+   sub isCreatableFile($);
+   sub isReadableDir($);
+   sub isWritableDir($);
+   sub isCreatableDir($);
+   sub isCreatablePath($);
+
+   # Functional Class : date
+   sub getISODate(;@);
+   sub getSybaseDate(;@);
+   sub getMySQLDate(;@);
+   sub getFilelabelDate(;@);
+   sub getLogfileDate(;@);
+
+   # Functional Class : logging
+   sub setDebugLevel($;$);
+   sub getDebugLevel();
+   sub setLogFile($;$);
+   sub getLogFile();
+   sub getErrorFile();
+   sub printDependInfo();
+   sub invalidateLogFILES();
+   sub cleanLogFILES();
+   sub closeLogERROR();
+   sub closeLogMSG();
+   sub openLogERROR();
+   sub openLogMSG();
+   sub logAppend($;$);
+   sub debugPush();
+   sub debugPop();
+   sub logLocal($$);
+   sub logError($;$);
+   sub bail($;$);
+
+   # Functional Class : modified methods
+   sub TIGR_GetOptions(@);
+
+   ## Implementation
+   
+
+# Functional Class : general
+
+=over
+
+=item $obj_instance = new TIGR::Foundation;
+
+This function creates a new instance of the TIGR::Foundation
+object.  A reference pointing to the object is returned on success.  Otherwise,
+this method returns undefined.
+
+=cut
+
+
+   sub new() {
+      
+      my $self = {};
+      my $pkg = shift;
+      my $user_name = getpwuid($<);
+      my $host_name = hostname();
+
+      # create the object
+      bless $self, $pkg;
+
+      ## Instance variables and identifiers, by functional class
+      
+      # Functional Class : general
+      my $pname  = basename($0, ()); # extract the script name
+       
+      if((defined ($pname)) && ($pname =~ /^(.*)$/)) {
+          $pname = $1;
+	  $self->{program_name} = $pname ;
+      }
+      
+      if ($self->{program_name} =~ /^-$/) {     # check if '-' is the input
+         $self->{program_name} = "STDIN";
+      }
+      
+      my $pcommand = join (' ', @ARGV);
+      
+      if((defined ($pcommand)) && ($pcommand =~ /^(.*)$/)) {
+          $pcommand = $1;
+	  $self->{invocation} = $pcommand ;
+      }
+      
+      # The following four variables are to contain information specified by
+      # the 'host' program; there are methods of setting and retrieving each
+
+      # Functional Class : depend
+      @{$self->{depend_info}} = ();
+   
+      # Functional Class : version
+      $self->{version_info} = undef; 
+   
+      # Functional Class : help
+      $self->{help_info} = undef; 
+   
+      # Functional Class : usage
+      $self->{usage_info} = undef; 
+   
+      # Functional Class : logging
+      $self->{debug_level} = undef;             # default debug is not defined
+      @{$self->{debug_store}} = ();             # the backup debug level stack
+      @{$self->{debug_queue}} = ();             # queue used by MSG routine
+      @{$self->{error_queue}} = ();             # queue used by ERROR routine
+      $self->{max_debug_queue_size} = 100;      # maximum size for queue before
+                                                # log entries are expired
+      @{$self->{log_files}} =                   # these log files are consulted
+         ("$self->{program_name}.log",          # on file write error and are
+          "/tmp/$self->{program_name}.$$.log"); # modified by setLogFile
+      $self->{msg_file_open_flag} = 0;          # flag to check logLocal file
+      $self->{error_file_open_flag} = 0;        # flag to check logError file
+      $self->{msg_file_used} = 0;               # flag to indicate if log file
+      $self->{error_file_used} = 0;             #   has been written to
+      $self->{msg_append_flag} = 0;             # by default logs are truncated
+      $self->{error_append_flag} = 0;           # by default logs are truncated
+      $self->{log_append_setting} = 0;          # (truncate == 0)
+      $self->{static_log_file} = undef;         # user defined log file
+      $self->{start_time} = undef;              # program start time
+      $self->{finish_time} = undef;             # program stop time
+
+      # Log program invocation
+      $self->logLocal("START: " . "Username:$user_name, ".
+                      "Hostname: $host_name ". $self->getProgramInfo('name') .
+                      " " . $self->getProgramInfo('invocation'), 0);
+      $self->{start_time} = time;
+
+      return $self;
+   }
+
+
+
+=item $value = $obj_instance->getProgramInfo($field_type);
+
+This function returns field values for specified field types describing
+attributes of the program.  The C<$field_type> parameter must be a listed
+attribute: C<name>, C<invocation>, C<env_path>, C<abs_path>.
+The C<name> field specifies the bare name of the executable.  The
+C<invocation> field specifies the command line arguments passed to the
+executable.   The C<env_path> value returns the environment path to the
+working directory.  The C<abs_path> value specifies the absolute path to the
+working directory.  If C<env_path> is found to be inconsistent, then that
+value will return the C<abs_path> value.  If an invalid C<$field_type> is 
+passed, the function returns undefined.  
+
+=cut
+
+
+   sub getProgramInfo($) {
+      my $self = shift;
+      my $field_type = shift;
+      my $return_value = undef;
+      if (defined $field_type) {
+         $field_type =~ /^name$/ && do {
+            $return_value = $self->{program_name};
+         };
+         $field_type =~ /^invocation$/ && do {
+            $return_value = $self->{invocation};
+         };
+         $field_type =~ /^env_path$/ && do {
+            my $return_value = "";
+            if (
+                (defined $ENV{'PWD'}) &&
+                (abs_path($ENV{'PWD'}) eq abs_path(".")) &&
+                ($ENV{'PWD'} =~ /^(.*)$/)     
+               ) {
+	       $ENV{'PWD'} = $1;
+               $return_value = $ENV{'PWD'};
+            }
+            else {
+	       my $tmp_val = abs_path(".");
+
+               if((defined ($tmp_val)) && ($tmp_val =~ /^(.*)$/)) {
+                  $tmp_val = $1;
+	          $return_value = $tmp_val;
+               }
+            }
+            return $return_value;
+         };
+
+         $field_type =~ /^abs_path$/ && do {
+            my $tmp_val = abs_path(".");
+
+            if((defined ($tmp_val)) && ($tmp_val =~ /^(.*)$/)) {
+               $tmp_val = $1;
+	       $return_value = $tmp_val;
+            }
+         };
+      }
+      return $return_value;
+   }
+
+=item $exit_code = $obj_instance->runCommand($command_str);
+
+This function passes the argument C<$command_str> to /bin/sh
+for processing.  The return value is the exit code of the 
+C<$command_str>.  If the exit code is not defined, then either the signal or
+core dump value of the execution is returned, whichever is applicable.  Perl
+variables C<$?> and C<$!> are set accordingly.  If C<$command_str> is not 
+defined, this function returns undefined.  Log messages are recorded at log
+level 4 to indicate the type of exit status and the corresponding code.
+Invalid commands return -1.
+
+=cut
+
+
+   sub runCommand($) {
+       my $self = shift;
+       my $command_str = shift;
+       my $exit_code = undef; 
+       my $signal_num = undef;
+       my $dumped_core = undef;
+       my $invalid_command = undef;
+       my $return_value = undef;
+       my @info_arr = getpwuid($<);
+       my $len = @info_arr;
+       my $home_dir = $info_arr[7];
+       my $current_dir = $self->getProgramInfo("abs_path"); 
+       
+       if((defined ($ENV{PATH})) && ($ENV{PATH} =~ /^(.*)$/)) {#taint checking
+	  $ENV{PATH} = $1; 
+          my $path_var = $ENV{PATH};
+          my @paths = split /:/, $path_var;
+          my $pathval = undef;
+          my $i = 0;
+          my $paths_len = @paths;
+
+          for ($i = 0; $i < $paths_len ; $i++) {
+             #substituting ~ with the home pathname.
+	     $pathval = $paths[$i];
+	     $pathval =~ s/^~$/$home_dir/g;
+             my $home_root = $home_dir."\/";
+             $pathval =~ s/^~\//$home_root/g;
+             
+             #substituting . with the current pathname.
+             $pathval =~ s/^\.$/$current_dir/g;
+             my $current_root = $current_dir."\/";
+             $pathval =~ s/^\.\//$current_root/g;
+             $paths[$i] = $pathval;
+	  }
+          
+          $ENV{PATH} = join(":", @paths);
+       }
+
+       if((defined ($command_str)) && ($command_str =~ /^(.*)$/)) {#taint 
+                                                                   #checking
+          $command_str = $1;
+          system($command_str);
+          $exit_code = $? >> 8;
+          $signal_num = $? & 127;
+          $dumped_core = $? & 128;
+
+          if ($? == -1) {
+             $invalid_command = -1;
+          } 
+ 
+          if ( 
+             (!defined $invalid_command) &&
+             ($exit_code == 0) &&
+             ($signal_num == 0) &&
+             ($dumped_core != 0)
+             ) {
+            
+             $self->logLocal("Command '" . $command_str . "' core dumped", 4);
+             $return_value = $dumped_core;
+           }
+          elsif (
+                (!defined $invalid_command) &&
+                ($exit_code == 0) &&
+                ($signal_num != 0)
+                ) {
+             
+             $self->logLocal("Command '" . $command_str .
+                             "' exited on signal " . $signal_num, 4);
+             $return_value = $signal_num;
+          }
+          elsif ((!defined $invalid_command)) {
+             
+             $self->logLocal("Command '" . $command_str .
+                             "' exited with exit code " . $exit_code, 4);
+             $return_value = $exit_code;
+          }
+          else {
+           
+             $self->logLocal("Command '" . $command_str .
+                             "' exited with invalid code " . $?, 4);
+             $return_value = $?;
+          }
+       }
+       return $return_value;
+   }
+   
+
+# Functional Class : depend
+
+=item $obj_instance->printDependInfo();
+
+The C<printDependInfo()> function prints the dependency list created by
+C<addDependInfo()>.  One item is printed per line.
+
+=cut
+
+
+   sub printDependInfo() {
+      my $self = shift;
+      foreach my $dependent (@{$self->{depend_info}}) {
+         print STDERR $dependent, "\n";
+      }
+   }
+
+
+=item $obj_instance->printDependInfoAndExit();
+
+The C<printDependInfoAndExit()> function prints the dependency list created by
+C<addDependInfo()>.  One item is printed per line.  The function exits with
+exit code 0. 
+
+=cut
+
+
+   sub printDependInfoAndExit() {
+      my $self = shift;
+      $self->printDependInfo();
+      exit 0;
+   }
+
+
+=item $obj_instance->addDependInfo(@depend_list);
+
+The C<addDependInfo()> function adds C<@depend_list> information
+to the dependency list.  If C<@depend_list> is empty, the internal
+dependency list is emptied.  Contents of C<@depend_list> are not checked
+for validity (eg. they can be composed entirely of white space or
+multiple files per record).  The first undefined record in C<@depend_list>
+halts reading in of dependency information.
+
+=cut
+
+
+   sub addDependInfo(@) {
+      my $self = shift;
+      my $num_elts = 0;
+      while (my $data_elt = shift @_) {
+         push (@{$self->{depend_info}}, $data_elt);
+         $num_elts++;
+      }
+      if ($num_elts == 0) {
+         @{$self->{depend_info}} = ();
+      }
+   }
+
+
+# Functional Class : version
+
+=item $version_string = $obj_instance->getVersionInfo();
+
+The C<getVersionInfo()> function returns the version information set by the
+C<setVersionInfo()> function.
+
+=cut
+
+
+   sub getVersionInfo() {
+      my $self = shift;
+      return $self->{version_info};
+   }
+
+
+=item $obj_instance->printVersionInfo();
+
+The C<printVersionInfo()> function prints the version information set by the
+C<setVersionInfo()> function.  If there is no defined version information,
+a message is returned notifying the user.
+
+=cut
+
+
+   sub printVersionInfo() {
+      my $self = shift;
+      if (defined $self->getVersionInfo()) {
+         print STDERR $self->getProgramInfo('name'), 
+            " ", $self->getVersionInfo(), "\n";
+      }
+      else {
+         print STDERR $self->getProgramInfo('name'),
+            " has no defined version information\n";
+      }
+   }
+
+
+=item $obj_instance->printVersionInfoAndExit();
+
+The C<printVersionInfoAndExit()> function prints version info set by the
+C<setVersionInfo()> function.  If there is no defined version information,
+a message is printed notifying the user.  This function calls exit with
+exit code 0. 
+
+=cut
+
+
+   sub printVersionInfoAndExit() {
+      my $self = shift;
+      $self->printVersionInfo();
+      exit 0;
+   }
+
+
+=item $obj_instance->setVersionInfo($version_string);
+
+The C<setVersionInfo()> function sets the version information to be reported
+by C<getVersionInfo()>.  If C<$version_string> is empty, invalid, or
+undefined, the stored version information will be undefined.
+
+=cut
+
+
+   sub setVersionInfo($) {
+      my $self = shift;
+      my $v_info = shift;
+      if (
+          (defined $v_info) &&
+          ($v_info =~ /\S/) &&
+          ((ref $v_info) eq "")
+         ) {
+         $self->{version_info} = $v_info;
+      }
+      else {
+         $self->{version_info} = undef;
+      }
+   }
+
+
+# Functional Class : help
+
+=item $obj_instance->printHelpInfo();
+
+The C<printHelpInfo()> function prints the help information passed by the
+C<setHelpInfo()> function.
+
+=cut
+
+
+   sub printHelpInfo() {
+      my $self = shift;
+      if (defined $self->{help_info}) {
+         print STDERR $self->{help_info};
+      }
+      else {
+         print STDERR "No help information defined.\n";
+      }
+   }
+
+
+=item $obj_instance->printHelpInfoAndExit();
+
+The C<printHelpInfoAndExit()> function prints the help info passed by the
+C<setHelpInfo()> function.  This function exits with exit code 0.
+
+=cut
+
+
+   sub printHelpInfoAndExit() {
+      my $self = shift;
+      $self->printHelpInfo();
+      exit 0;
+   }
+
+
+=item $obj_instance->setHelpInfo($help_string);
+
+The C<setHelpInfo()> function sets the help information via C<$help_string>.
+If C<$help_string> is undefined, invalid, or empty, the help information 
+is undefined.
+
+=cut
+
+
+   sub setHelpInfo($) {
+      my $self = shift;
+      my $help_string = shift;
+      if (
+          (defined $help_string) &&
+          ($help_string =~ /\S/) &&
+          ((ref $help_string) eq "")
+         ) {
+	 chomp($help_string);#removing a new line if it is there.
+         $self->{help_info} = $help_string."\n";#adding a new line to help.
+      }
+      else {
+         $self->{help_info} = undef;
+      }
+   }
+
+
+# Functional Class : usage
+
+=item $obj_instance->printUsageInfo();
+
+The C<printUsageInfo()> function prints the usage information reported by the
+C<setUsageInfo()> function.  If no usage information is defined, but help
+information is defined, help information will be printed.
+
+=cut
+
+
+   sub printUsageInfo() {
+     
+      my $self = shift;
+      if (defined $self->{usage_info}) {
+         print STDERR $self->{usage_info};
+      }
+      elsif (defined $self->{help_info}) {
+         print STDERR $self->{help_info};
+      }
+      else {
+         print STDERR "No usage information defined.\n";
+      }
+   }
+
+
+=item $obj_instance->printUsageInfoAndExit();
+
+The C<printUsageInfoAndExit()> function prints the usage information the
+reported by the C<setUsageInfo()> function and exits with status 1.
+
+=cut
+
+
+   sub printUsageInfoAndExit() {
+      my $self = shift;
+      $self->printUsageInfo();
+      $self->bail("Incorrect command line");
+   }
+
+
+=item $obj_instance->setUsageInfo($usage_string);
+
+The C<setUsageInfo()> function sets the usage information via C<$usage_string>.
+If C<$usage_string> is undefined, invalid, or empty, the usage information 
+is undefined.
+
+=cut
+
+
+   sub setUsageInfo($) {
+      my $self = shift;
+      my $usage_string = shift;
+      if (
+          (defined $usage_string) &&
+          ($usage_string =~ /\S/) &&
+          ((ref $usage_string) eq "")
+         ) {
+	 chomp($usage_string); #removing a new line if it is there.
+         $self->{usage_info} = $usage_string."\n";#adding a new line to usage
+      }
+      else {
+         $self->{usage_info} = undef;
+      }
+   }
+
+
+# Functional Class : files
+
+=item $valid = isReadableFile($file_name);
+
+This function accepts a single scalar parameter containing a file name.
+If the file corresponding to the file name is a readable plain file or symbolic
+link, this function returns 1.  Otherwise, the function returns 0.  If the file
+name passed is undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isReadableFile($) {
+      my $file = shift;
+      if (scalar(@_) != 0) { #incase the method was invoked as an instance 
+                             #method
+         $file  = shift;
+      }
+ 
+      if (defined ($file) &&             # was a file name passed?
+          ((-f $file) || (-l $file)) &&  # is the file a file or sym. link?
+          (-r $file)                     # is the file readable?
+         ) {
+         return 1;
+      }
+      else {
+         return 0;
+      }
+   }
+
+
+=item $valid = isExecutableFile($file_name);
+
+This function accepts a single scalar parameter containing a file name.
+If the file corresponding to the file name is an executable plain file
+or symbolic link, this function returns 1.  Otherwise, the function returns 0.
+If the file name passed is undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isExecutableFile($) {
+      my $file = shift;
+       if (scalar(@_) != 0) { # incase the method was invoked as a instance
+                              # method
+         $file  = shift;
+      }
+ 
+      if (defined ($file) &&             # was a file name passed?
+          ((-f $file) || (-l $file)) &&  # is the file a file or sym. link?
+          (-x $file)                     # is the file executable?
+         ) {
+         return 1;
+      }
+      else {
+         return 0;
+      }
+   }
+
+
+=item $valid = isWritableFile($file_name);
+
+This function accepts a single scalar parameter containing a file name.
+If the file corresponding to the file name is a writable plain file
+or symbolic link, this function returns 1.  Otherwise, the function returns 0.
+If the file name passed is undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isWritableFile($) {
+      my $file = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as a instance
+                             #  method
+         $file  = shift;
+      }
+ 
+      if (defined ($file) &&             # was a file name passed?
+          ((-f $file) || (-l $file)) &&  # is the file a file or sym. link?
+          (-w $file)                     # is the file writable?
+         ) {
+         return 1;
+      }
+      else {
+         return 0;
+      }
+   }
+
+
+=item $valid = isCreatableFile($file_name);
+
+This function accepts a single scalar parameter containing a file name.  If
+the file corresponding to the file name is creatable this function returns 1.
+The function checks if the location of the file is writable by the effective
+user id (EUID).  If the file location does not exist or the location is not
+writable, the function returns 0.  If the file name passed is undefined,
+this function returns 0 as well.  Note that files with suffix F</> are not
+supported under UNIX platforms, and will return 0.
+
+=cut
+
+
+   sub isCreatableFile($) {
+      my $file = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as an instance
+                             # method
+         $file  = shift;
+      }
+
+      my $return_code = 0;
+
+      if (
+          (defined ($file)) &&
+          (! -e $file) &&
+          ($file !~ /\/$/) 
+         ) {
+         my $dirname = dirname($file);
+         # check the writability of the directory
+         $return_code = isWritableDir($dirname);
+      }
+      else {
+         # the file exists, it's not creatable
+         $return_code = 0;
+      }
+      return $return_code;
+   }
+
+
+=item $valid = isReadableDir($directory_name);
+
+This function accepts a single scalar parameter containing a directory name.
+If the name corresponding to the directory is a readable, searchable directory 
+entry, this function returns 1.  Otherwise, the function returns 0.  If the
+name passed is undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isReadableDir($) {
+      my $file = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as an instance
+                             # method
+         $file  = shift;
+      }
+ 
+      if (defined ($file) &&             # was a name passed?
+          (-d $file) &&                  # is the name a directory?
+          (-r $file) &&                  # is the directory readable?
+          (-x $file)                     # is the directory searchable?
+         ) {
+         return 1;
+      }
+      else {
+         return 0;
+      }
+   }
+
+
+=item $valid = isWritableDir($directory_name);
+
+This function accepts a single scalar parameter containing a directory name.
+If the name corresponding to the directory is a writable, searchable directory 
+entry, this function returns 1.  Otherwise, the function returns 0.  If the
+name passed is undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isWritableDir($) {
+      my $file = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as an instance
+                             # method
+         $file  = shift;
+      }
+ 
+      if (defined ($file) &&             # was a name passed?
+          (-d $file) &&                  # is the name a directory?
+          (-w $file) &&                  # is the directory writable?
+          (-x $file)                     # is the directory searchable?
+         ) {
+         return 1;
+      }
+      else {
+         return 0;
+      }
+   }
+
+
+=item $valid = isCreatableDir($directory_name);
+
+This function accepts a single scalar parameter containing a directory name.  
+If the name corresponding to the directory is creatable this function returns 
+1. The function checks if the immediate parent of the directory is writable by
+the effective user id (EUID).  If the parent directory does not exist or the 
+tree is not writable, the function returns 0.  If the directory name passed is
+undefined, this function returns 0 as well.
+
+=cut
+
+
+   sub isCreatableDir($) {
+      my $dir = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as an instance
+                             # method
+         $dir  = shift;
+      }
+      my $return_code = 0;
+
+      if (defined ($dir)) {
+         $dir =~ s/\/$//g;
+         $return_code = isCreatableFile($dir);
+      }
+      return $return_code;
+   }
+
+
+=item $valid = isCreatablePath($path_name);
+
+This function accepts a single scalar parameter containing a path name.  If
+the C<$path_name> is creatable this function returns 1. The function checks 
+if the directory hierarchy of the path is creatable or writable by the
+effective user id (EUID).  This function calls itself recursively until
+an existing directory node is found.  If that node is writable, ie. the path
+can be created in it, then this function returns 1.  Otherwise, the function
+returns 0.  This function also returns zero if the C<$path_name> supplied
+is disconnected from a reachable directory tree on the file system.
+If the path already exists, this function returns 0.  The C<$path_name> may
+imply either a path to a file or a directory.  Path names may be relative or
+absolute paths.  Any unresolvable relative paths will return 0 as well.  This
+includes paths with F<..> back references to nonexistent directories.
+This function is recursive whereas C<isCreatableFile()> and 
+C<isCreatableDir()> are not.
+
+=cut
+
+
+   sub isCreatablePath($) {
+      my $pathname = shift;
+      if (scalar(@_) != 0) { # incase the method was invoked as an instance
+                             # method
+         $pathname  = shift;
+      }
+      my $return_code = 0;
+
+      if (defined $pathname) {
+         # strip trailing '/'
+         $pathname =~ s/(.+)\/$/$1/g;
+         my $filename = basename($pathname);
+         my $dirname = dirname($pathname);
+         if (
+             (! -e $pathname) &&
+             ($dirname ne $pathname) &&
+             ($filename ne "..")
+            ) {
+            if (-e $dirname) {
+               $return_code = isWritableDir($dirname);
+            }
+            else {
+               $return_code = isCreatablePath($dirname);
+            }
+         }
+         else {
+            $return_code = 0;
+         }
+      }
+      return $return_code;
+   }
+         
+
+# Functional Class : date
+
+=item $date_string = getISODate($tm);
+
+This function returns the ISO 8601 datetime as a string given a time
+structure as returned by the C<time> function.  If no arguments
+are supplied, this function returns the current time.  If incorrect
+arguments are supplied, this function returns undefined.
+
+=cut
+
+
+   sub getISODate(;@) {
+      #checking if the function is invoked as an instance method.
+      if((defined(ref $_[0])) && ((ref $_[0]) eq "TIGR::Foundation")){
+         shift;
+      } 
+      my @time_val = @_;
+      my $time_str = undef;
+      if (scalar(@time_val) == 0) {
+         @time_val = localtime;
+      }
+      eval {
+         $time_str = strftime "%Y-%m-%d %H:%M:%S", @time_val;
+      };
+      return $time_str;
+   }
+
+
+=item $date_string = getSybaseDate(@tm);
+
+This function returns a Sybase formatted datetime as a string given a time
+structure as returned by the C<time> function.  If no arguments
+are supplied, this function returns the current time.  If incorrect
+arguments are supplied, this function returns undefined.  The date string
+returned is quoted according to Sybase requirements.
+
+=cut
+
+
+   sub getSybaseDate(;@) {
+      #checking if the function is invoked as an instance method.
+      if((defined(ref $_[0])) && ((ref $_[0]) eq "TIGR::Foundation")){
+         shift;
+      } 
+      my @time_val = @_;
+      my $time_str = undef;
+      if (scalar(@time_val) == 0) {
+         @time_val = localtime;
+      }
+      eval {
+         $time_str = strftime "\'%b %d %Y %I:%M%p\'", @time_val;
+      };
+      return $time_str;
+   }
+      
+
+=item $date_string = getMySQLDate(@tm);
+
+This function returns a MySQL formatted datetime as a string given a time
+structure as returned by the C<time> function.  If no arguments
+are supplied, this function returns the current time.  If incorrect
+arguments are supplied, this function returns undefined.  The datetime string
+returned is prequoted according to MySQL requirements.
+
+=cut
+
+
+   sub getMySQLDate(;@) {
+      #checking if the function is invoked as an instance method.
+      if((defined(ref $_[0])) && ((ref $_[0]) eq "TIGR::Foundation")){
+         shift;
+      }
+      my @time_val = @_;
+      my $time_str = undef;
+      if (scalar(@time_val) == 0) {
+         @time_val = localtime;
+      }
+      $time_str = getISODate(@time_val);
+      if (defined $time_str) {
+         $time_str = "\'$time_str\'";
+      }
+      return $time_str;
+   }
+      
+
+=item $date_string = getFilelabelDate(@tm);
+
+This function returns the date (not time) as a compressed string
+suitable for use as part of a file name.  The format is YYMMDD.
+The optional parameter should be a time structure as returned by 
+the C<time> function.  If no arguments are supplied, the current time
+is used.  If incorrect arguments are supplied, this function returns
+undefined.
+
+=cut
+
+
+   sub getFilelabelDate(;@) {
+      #checking if the function is invoked as an instance method.
+      if((defined(ref $_[0])) && ((ref $_[0]) eq "TIGR::Foundation")){
+         shift;
+      }
+      my @time_val = @_;
+      my $time_str = undef;
+      if (scalar(@time_val) == 0) {
+         @time_val = localtime;
+      }
+      eval {
+         $time_str = strftime "%y%m%d", @time_val;
+      };
+      return $time_str;
+   }
+      
+
+=item $date_string = $obj_instance->getLogfileDate(@tm);
+
+This function returns the datetime as a formatted string
+suitable for use as a log entry header.  The optional parameter
+should be a time structure as returned by the C<time> function.
+If no arguments are supplied, this function uses the current time.
+If incorrect arguments are supplied, this function sets the date/time fields
+of the log entry string to C< INVALID|XXXXXX|>.
+
+=cut
+
+
+   sub getLogfileDate(;@) {
+      #checking if the function is invoked as an instance method.
+      if((defined(ref $_[0])) && ((ref $_[0]) eq "TIGR::Foundation")){
+         shift;
+      } 
+      my @time_val = @_;
+      my $time_str = undef;
+      my $log_form = undef;
+      if (scalar(@time_val) == 0) {
+         @time_val = localtime;
+      }
+      eval {
+         $time_str = strftime("%Y%m%d|%H%M%S|", @time_val);
+      };
+      if (!defined $time_str) {
+         $time_str = " INVALID|XXXXXX|";
+      }
+      $log_form = $time_str . sprintf("%6d| ", $$);
+      return $log_form;
+   }
+      
+
+# Functional Class : logging
+
+=item $obj_instance->setDebugLevel($new_level);
+
+This function sets the level of debug reporting according to C<$new_level>.
+If the debug level is less than 0, all debug reporting is turned off.
+It is impossible to turn off error reporting from C<bail()>.  If C<$new_level>
+is undefined, the debug level is set to 0.  This function maintains 
+compatibility with C<GetOptions()>, and will accept a second parameter
+the debug level, provided it is an integer.  In such cases, the first parameter
+is checked only if the second parameter is invalid.  By default, the default
+level is undefined.  To turn on debugging, you must invoke this function.
+
+=cut
+
+
+   sub setDebugLevel($;$) {
+      my $self = shift;
+      my $new_level = shift;
+      my $getopts_new_level = shift;
+
+      if (
+          (defined $getopts_new_level) &&
+          ($getopts_new_level =~ /^-?\d+$/)
+         ) {
+         $new_level = $getopts_new_level;
+      }
+      elsif (
+          (!defined $new_level) ||
+          ($new_level !~ /^-?\d+$/)
+         ) {
+         $new_level = 0;
+         $self->logLocal("No or invalid parameter to setDebugLevel(), " .
+                         "setting debug level to 0", 3);
+      }
+
+      if ($new_level < 0) {
+         $new_level = -1;
+      }
+
+      $self->{debug_level} = $new_level;
+      $self->logLocal("Set debug level to " . $self->getDebugLevel(), 2);
+   }
+
+
+=item $level = $obj_instance->getDebugLevel();
+
+This function returns the current debug level.  If the current debug
+level is not defined, this function returns undefined.
+
+=cut
+
+
+   sub getDebugLevel() {
+      my $self = shift;
+      return $self->{debug_level};
+   }
+
+
+=item $obj_instance->setLogFile($log_file);
+
+This function sets the log file name for the C<logLocal()> function.
+B<The programmer should call this function before invoking C<setDebugLevel()>>
+if the default log file is not to be used.  The function takes one parameter,
+C<$log_file>, which defines the new log file name.  If a log file is already
+open, it is closed.  The old log file is not truncated or deleted.
+Future calls to C<logLocal()> or C<bail()> will log to C<$log_file> if it
+is successfully opened.  If the new log file is not successfully opened, 
+the function will try to open the default log file, F<program_name.log>.
+If that file cannot be opened, F</tmp/program_name.$process_id.log> will
+be used.  If no log file argument is passed, the function will try to open
+the default log file.  This function is C<GetOptions()> aware; it will accept
+two parameters, using the second one as the log file and ignoring the first if
+and only if two parameters are passed.  Any other usage specifies the first
+parameter as the log file name.
+
+=cut
+
+
+   sub setLogFile($;$) {
+      my $self = shift;
+      my $old_log_file = defined $self->{static_log_file} ? 
+         $self->{static_log_file} : undef;
+      $self->{static_log_file} = shift;
+      if (scalar(@_) == 1) {
+         $self->{static_log_file} = shift;
+      }
+
+      # only consider a new log file that is definable as a file
+      if ((defined ($self->{static_log_file})) &&
+          ($self->{static_log_file} !~ /^\s*$/)) {
+         # delete an old log file entry added by "setLogFile"
+         for (my $idx = 0;
+              ($idx <= $#{$self->{log_files}}) && defined($old_log_file);
+              $idx++) {
+            if ($self->{log_files}[$idx] eq $old_log_file) {
+               splice @{$self->{log_files}}, $idx, 1;
+               $old_log_file = undef;
+            }
+         }
+         unshift @{$self->{log_files}}, $self->{static_log_file};
+
+         # initialize the log file variables and file spaces
+         $self->{msg_file_used} = 0;
+         $self->{error_file_used} = 0;
+         $self->cleanLogFILES();
+      }
+   }
+
+
+=item $log_file_name = $obj_instance->getLogFile();
+
+This function returns the name of the log file to be used for printing
+log messages.  If no log file is available, this function returns undefined.
+
+=cut
+
+
+   sub getLogFile() {
+      my $self = shift;
+      my $return_val = undef;
+      if (
+          (scalar(@{$self->{log_files}}) != 0) &&
+          (defined($self->{log_files}[0]))
+         ) {
+         $return_val = $self->{log_files}[0];
+      }
+      return $return_val;
+   }
+
+
+=item $error_file_name = $obj_instance->getErrorFile();
+
+This function returns the name of the error file to be used for printing
+error messages.  The error file is derived from the log file; a F<.log>
+extension is replaced by a F<.error> extension.  If there is no F<.log>
+extension, then F<.error> is appended to the log file name.  If no
+log files are defined, this function returns undefined.
+
+=cut
+
+
+   sub getErrorFile() {
+      my $self = shift;
+      my $return_val = $self->getLogFile();
+      if (defined $return_val) {
+         $return_val =~ s/\.log$//g;
+         $return_val .= '.error';
+      }
+      return $return_val;
+   }
+
+
+   # the following private functions are used for logging
+
+
+   # push items onto the debug level stack
+   sub debugPush() {
+      my $self = shift;
+      if (defined ($self->{debug_level})) {
+         push @{$self->{debug_store}}, $self->{debug_level};
+      }
+      else {
+         push @{$self->{debug_store}}, "undef";
+      }
+      $self->{debug_level} = undef;
+   } 
+
+
+   # pop items from the debug level stack
+   sub debugPop() {
+      my $self = shift;
+      $self->{debug_level} = pop @{$self->{debug_store}};
+      if (
+          (!defined ($self->{debug_level})) || 
+          ($self->{debug_level} eq "undef")
+         ) {
+         $self->{debug_level} = undef;
+      }
+   }
+
+
+   # remove log files
+   sub removeLogERROR() {
+     
+      my $self = shift;
+      $self->debugPush();
+      if (
+          (defined $self->getErrorFile()) &&
+          (isWritableFile($self->getErrorFile()))
+         ) {
+	    unlink $self->getErrorFile() or
+            $self->logLocal("Unable to remove error file " .
+                             $self->getErrorFile(), 3);
+      }
+      $self->debugPop();
+   }
+
+
+   sub removeLogMSG() {
+      my $self = shift;
+      $self->debugPush();
+     
+      if (
+          (defined $self->getLogFile()) &&
+          (isWritableFile($self->getLogFile()))
+         ) {
+            unlink $self->getLogFile() or 
+            $self->logLocal("Unable to remove error file " .
+                             $self->getLogFile(), 3);
+      }
+      $self->debugPop();
+   }
+
+
+   # invalidate log files
+   sub invalidateLogFILES() {
+      my $self = shift;
+      $self->debugPush();
+      if (defined $self->getLogFile()) {
+         $self->logLocal("Invalidating " . $self->getLogFile(), 2); 
+         shift @{$self->{log_files}};
+         $self->{msg_append_flag} = $self->{error_append_flag} =
+            $self->{log_append_setting};
+         $self->{msg_file_used} = $self->{error_file_used} = 0;
+         $self->cleanLogFILES();
+      }
+      $self->debugPop();
+   }
+
+
+   # clean previous log files
+   sub cleanLogFILES() {
+      my $self = shift;
+      if ($self->{log_append_setting} == 0) {
+         if ($self->{msg_file_used} == 0) {
+            $self->removeLogMSG();
+         }
+         if ($self->{error_file_used} == 0) {
+            $self->removeLogERROR();
+         }
+      }
+   }
+
+
+   # close log files
+   sub closeLogERROR() {
+      my $self = shift;
+      my $return_code = 1; # need to return true for success, false for fail
+
+      $self->debugPush();
+      if (!close(ERRLOG) && (defined $self->getErrorFile())) {
+         $self->logLocal("Cannot close " . $self->getErrorFile(), 3);
+         $return_code = 0;
+      }
+      else {
+         $return_code = 1;
+      }
+      $self->{error_file_open_flag} = 0;
+      $self->debugPop();
+      return $return_code;
+   }   
+
+
+   sub closeLogMSG() {
+      my $self = shift;
+      my $return_code = 1; # need to return true for success, false for fail
+
+      $self->debugPush();
+      if (!close(MSGLOG) && (defined $self->getLogFile())) {
+         $self->logLocal("Cannot close " . $self->getLogFile(), 3);
+         $return_code = 0;
+      }
+      else {
+         $return_code = 1;
+      }
+      $self->{msg_file_open_flag} = 0;
+      $self->debugPop();
+      return $return_code;
+   }   
+
+
+   # open log files
+   sub openLogERROR() {
+      my $self = shift;
+      my $return_code = 1; # need to return true for success, false for fail
+
+      $self->debugPush();
+      if ((defined $self->getErrorFile()) &&
+          ($self->{error_file_open_flag} == 0)) {
+         my $fileop;
+         $self->{error_file_open_flag} = 1;
+         if ($self->{error_append_flag} == 0) {
+            $fileop = '>';
+            $self->{error_append_flag} = 1;
+         }
+         else {
+            $fileop = '>>';
+         }
+         if (open(ERRLOG, $fileop . $self->getErrorFile())) {
+            autoflush ERRLOG 1;
+         }
+         else {
+            $self->logLocal("Cannot open " . $self->getErrorFile() .
+               " for logging", 4);
+            $self->{error_file_open_flag} = 0;
+         }
+      }
+      $return_code = $self->{error_file_open_flag};
+      $self->debugPop();
+
+      # this is 1 if the file stream is open, 0 if not
+      return $return_code;
+   }
+
+
+   sub openLogMSG() {
+      my $self = shift;
+      my $return_code = 1; # need to return true for success, false for fail
+
+      $self->debugPush();
+      if ((defined $self->getLogFile()) && ($self->{msg_file_open_flag} == 0)){
+         my $fileop;
+         $self->{msg_file_open_flag} = 1;
+         if ($self->{msg_append_flag} == 0) {
+            $fileop = '>';
+            $self->{msg_append_flag} = 1;
+         }
+         else {
+            $fileop = '>>';
+         }
+
+         if (open(MSGLOG, $fileop . $self->getLogFile())) {
+            autoflush MSGLOG 1;
+         }
+         else {
+            $self->logLocal("Cannot open " . $self->getLogFile() . 
+                            " for logging", 4);
+            $self->{msg_file_open_flag} = 0;
+         }
+      }
+      $return_code = $self->{msg_file_open_flag};
+      $self->debugPop();
+
+      # this is 1 if the file stream is open, 0 if not
+      return $return_code;
+   }
+
+
+=item $obj_instance->logAppend($log_append_flag);
+
+The C<logAppend()> function takes either C<0> or C<1> as a flag to 
+disable or enable log file appending.  By default, log files are 
+truncated at the start of program execution or logging.  Error files are
+controlled by this variable as well.  Invalid or undefined calls are ignored.
+Calling this function with a C<0> argument after the log files have started
+to be written may cause them to be truncated undesirably.  This function is
+C<GetOptions()> compliant; if 2 and only 2 variables are passed, the second
+option is treated as C<$log_append_flag>.
+
+=cut
+
+
+   sub logAppend($;$) {
+      my $self = shift;
+      my $log_append_flag = shift;
+      if (defined $_[0]) {
+         $log_append_flag = shift;
+      }
+      if (
+          (defined ($log_append_flag)) &&
+          (($log_append_flag eq "0") ||
+           ($log_append_flag eq "1"))
+         ) {
+         $self->{log_append_setting} = $self->{msg_append_flag} = 
+            $self->{error_append_flag} = $log_append_flag;
+      }
+   } 
+
+
+=item $obj_instance->logLocal($log_message, $log_level);
+
+The C<logLocal()> function takes two arguments.  The C<$log_message>
+argument specifies the message to be written to the log file.  The
+C<$log_level> argument specifies the level at which C<$log_message> is printed.
+The active level of logging is set via the C<setDebugLevel()> function.
+Only messages at C<$log_level> less than or equal to the active debug
+level are logged.  The default debug level is undefined.  Note, a trailing
+new line, if it exists, is stripped from the log message.
+
+=cut
+
+
+   sub logLocal($$) {
+      my $self = shift;
+      my $log_message = shift;
+      my $log_level = shift;
+
+      if ((!defined $log_level) || ($log_level =~ /\D/)) {
+         $log_level = 1;
+      }
+
+      if (defined $log_message) {
+         chomp $log_message; # strip end new line, if it exists
+
+         $log_message = getLogfileDate() . $log_message;
+         push @{$self->{debug_queue}}, [ $log_message, $log_level ];
+
+         if ((defined ($self->getDebugLevel())) &&
+                      ($self->getDebugLevel() > -1)) {
+            while (
+                   (defined(my $log_record = $self->{debug_queue}[0])) &&
+                   (defined($self->getLogFile()))
+                  ) {
+               ($log_message, $log_level) = @{$log_record};
+               if (
+                   (
+                    ($log_level <= $self->getDebugLevel()) && # debug level
+                    ($self->openLogMSG())                  && # check log file
+                    (print MSGLOG "$log_message\n")        && # print message
+                    ($self->closeLogMSG())                 && # close log file
+                    ($self->{msg_file_used} = 1)              # log file used
+                   ) ||
+                   (
+                    ($log_level > $self->getDebugLevel())     # bad dbg level
+                   ) 
+                  ) {
+                  # log message is successfully processed, so shift it off
+                  shift @{$self->{debug_queue}};
+               }
+               else {
+                  $self->debugPush();
+                  $self->logLocal("Cannot log message \'$log_message\' to " .
+                     $self->getLogFile() . " = " .  $!, 9);
+                  $self->invalidateLogFILES(); 
+                  $self->debugPop();
+               }
+            }
+         }
+      }
+      else {
+         $self->logLocal("logLocal() called without any parameters!",3);
+      }
+
+      while ($#{$self->{debug_queue}} >= $self->{max_debug_queue_size}) {
+         # expire old entries; this needs to happen if $self->{debug_level}
+         # is undefined or there is no writable log file, otherwise the
+         # queue could exhaust RAM.
+         shift @{$self->{debug_queue}};
+      }
+   }
+   
+
+=item $obj_instance->logError($log_message,$flag);
+
+The C<logError()> function takes two arguments, the second one being optional. 
+The C<$log_message> argument specifies the message to be written to the error 
+file. If the C<$flag> argument is defined and is non-zero, the C<$log_message>
+is also written to STDERR. The C<$log_message> is also passed to C<logLocal>.
+A message passed via logError() will always get logged to the log file 
+regardles of the debug level.  Note, a trailing new line, if it exists, is 
+stripped from the log message.
+
+=cut
+
+
+   sub logError($;$) {
+      
+      my $self = shift;
+      my $log_message = shift;
+      my $flag = shift; 
+      if (defined $log_message) {
+         chomp $log_message;  # strip end new line, if it exists
+         $self->logLocal($log_message, 0);
+
+         #printing error message to STDERR if flag is non zero.
+         if((defined($flag)) && ($flag ne '0')) {
+            print STDERR "$log_message\n";
+         }        
+
+         $log_message = getLogfileDate() . $log_message;
+         push(@{$self->{error_queue}}, $log_message);
+        
+         while (
+                (defined(my $log_message = $self->{error_queue}[0])) &&
+                (defined($self->getErrorFile()))
+               ) {
+               
+            if (
+                ($self->openLogERROR()) &&     
+                (print ERRLOG "$log_message\n") &&
+                ($self->closeLogERROR()) &&
+                ($self->{error_file_used} = 1) # that is an '='
+               ) {
+	       shift @{$self->{error_queue}};
+            }
+            else {
+               $self->debugPush();
+               $self->logLocal("Cannot log message \'$log_message\' to " .
+                  $self->getErrorFile() . " = $!", 6);
+               $self->invalidateLogFILES(); 
+               $self->debugPop();
+            }
+         }
+      }
+      else {
+         $self->logLocal("logError() called without any parameters!",3);
+      }
+
+      while ($#{$self->{error_queue}} >= $self->{max_debug_queue_size}) {
+         # expire old entries; this needs to happen if $self->{debug_level}
+         # is undefined or there is no writable log file, otherwise the
+         # queue could exhaust RAM.
+         shift @{$self->{error_queue}};
+      }
+   }
+ 
+
+=item $obj_instance->bail($log_message);
+
+The C<bail()> function takes a single required argument.  The C<$log_message>
+argument specifies the message to be passed to C<logLocal()> and displayed
+to the screen in using the C<warn> function.  All messages passed to C<bail()>
+are logged regardless of the debug level.  The C<bail()> function
+calls C<exit(1)> to terminate the program.  Optionally, a second positive
+integer argument can be passed as the exit code to use.  Note, a trailing
+new line, if it exists, is stripped from the end of the line.
+
+=cut
+
+
+   sub bail($;$) {
+      my $self = shift;
+      my $log_message = shift;
+      my $exit_code = shift;
+
+      if (
+          (!defined $exit_code) ||
+          ($exit_code !~ /^\d+$/)
+         ) {
+         $exit_code = 1;
+      }
+      if (defined $log_message) {
+         chomp $log_message;  # strip end new line, if it exists
+
+         $self->logError($log_message);
+         print STDERR $log_message, "\n";
+      }
+
+      exit $exit_code;
+   }
+
+
+# Functional Class : modified methods
+
+=item $getopts_error_code = $obj_instance->TIGR_GetOptions(@getopts_arguments);
+
+This function extends C<Getopt::Long::GetOptions()>.  It may be used
+as C<GetOptions()> is used.  Extended functionality eliminates the need
+to C<eval {}> the block of code containing the function.  Further, TIGR
+standard options, such as C<-help>, are defined implicitly.  Using this
+function promotes proper module behavior.  Log and error files from 
+previous runs are removed if the log file append option, C<-appendlog>,
+is not set to 1.
+
+The following options are defined by this function:
+
+=over
+
+=item -appendlog APPEND_FLAG
+
+Passing '1' to this argument turns on log file appending.
+
+=item -debug DEBUG_LEVEL
+
+Set debugging to DEBUG_LEVEL.
+
+=item -logfile LOG_FILE_NAME
+
+Set the default TIGR Foundation log file to LOG_FILE_NAME.
+
+=item -version, -V
+
+Print version information and exit.
+
+=item -help, -h
+
+Print help information and exit.
+
+=item -depend
+
+Print dependency information and exit.
+
+=back
+
+Regular C<GetOptions()> may still be used, however the C<TIGR_GetOptions()>
+function eliminates some of the confusing issues with setting log files
+and debug levels.  B<The options defined by C<TIGR_GetOptions()> cannot be
+overridden or recorded>.  To get the log file and debug level after parsing
+the command line, use C<getLogFile()> and C<getDebugLevel()>.  C<GetOptions()>
+default variables, ie. those of the form C<$opt_I<optionname>>, are not
+supported.  This function will return 1 on success.
+
+=cut
+
+
+   sub TIGR_GetOptions(@) {
+      my $self = shift;
+      my @user_options = @_;
+
+      my $appendlog_var = undef;
+      my $logfile_var = undef;
+      my $debug_var = undef;
+      my $version_var = undef;
+      my $help_var = undef;
+      my $depend_var = undef;
+
+      # these foundation options support the defaults
+      my @foundation_options = (
+         "appendlog=i" => \$appendlog_var,
+         "logfile=s" => \$logfile_var,
+         "debug=i" => \$debug_var,
+         "version|V" => \$version_var,
+         "help|h" => \$help_var,
+         "depend" => \$depend_var
+      );
+
+      Getopt::Long::Configure('no_ignore_case');
+      my $getopt_code = eval 'GetOptions (@user_options, @foundation_options)';
+
+      if ((defined $help_var) && ($help_var =~ /^(.*)$/))  {
+         $self->printHelpInfoAndExit();
+      }
+
+      if ((defined $version_var) && ($version_var =~ /^(.*)$/)) {
+         $self->printVersionInfoAndExit();
+      }
+
+      if ((defined $depend_var) && ($depend_var =~ /^(.*)$/)) {
+         $self->printDependInfoAndExit();
+      }
+
+      if ((defined $appendlog_var) && ($appendlog_var =~ /^(.*)$/)) {
+	 $appendlog_var = $1;
+         $self->logAppend($appendlog_var);
+      }
+
+      if ((defined $logfile_var) && ($logfile_var =~ /^(.*)$/))  {
+	 $logfile_var = $1;
+         $self->setLogFile($logfile_var);
+      }
+
+      if ((defined $debug_var) && ($debug_var =~ /^(.*)$/)) {
+	 $debug_var = $1;
+         $self->setDebugLevel($debug_var);
+      }
+
+      # remove old log files, if necessary
+      for (
+           my $file_control_var = 0;
+           $file_control_var <= $#{$self->{log_files}};
+           $file_control_var++
+          ) {
+          $self->cleanLogFILES();
+          push(@{$self->{log_files}}, shift @{$self->{log_files}});
+      }
+      return $getopt_code;
+   }
+
+   DESTROY {
+      my $self = shift;
+      $self->{finish_time} = time;
+      my $time_difference = $self->{finish_time} - $self->{start_time};
+      my $num_days = int($time_difference / 86400); # there are 86400 sec/day
+      $time_difference -= $num_days * 86400;
+      my $num_hours = int($time_difference / 3600); # there are 3600 sec/hour
+      $time_difference -= $num_hours * 3600;
+      my $num_min = int($time_difference / 60); # there are 60 sec/hour
+      $time_difference -= $num_min * 60;
+      my $num_sec = $time_difference; # the left overs are seconds
+      my $time_str = sprintf "%03d-%02d:%02d:%02d", $num_days, $num_hours,
+         $num_min, $num_sec;
+      $self->logLocal("FINISH: " . $self->getProgramInfo('name') .
+         ", elapsed ".$time_str ,0);
+   }
+}
+
+=back
+
+=head1 USAGE
+
+To use this module, load the C<TIGR::Foundation> package
+via the C<use> function.  Then, create a new instance of the
+object via the C<new()> method, as shown below.  If applicable,
+C<START> and C<FINISH> log messages are printed when the object
+is created and destroyed, respectively.  It is advisable to 
+keep the instance of the object in scope for the whole program
+to achieve maximum functionality.
+
+An example script using this module follows:
+
+   use strict;
+   use TIGR::Foundation;
+
+   my $tfobject = new TIGR::Foundation;
+
+   MAIN: 
+   {
+      # The following dependencies are not used in
+      # this script, but are provided as an example.
+
+      my @DEPEND = ("/usr/bin/tee", "/sbin/stty");
+
+      # The user defined $VERSION variable is usable by Perl.
+      # The auto defined $REVISION variable stores the RCS/CVS revision
+      # The user defined $VERSION_STRING reports both.
+
+      my $VERSION = '1.0';
+      my $REVISION = (qw$Revision: 1.1.1.1 $)[-1];
+      my $VERSION_STRING = "$VERSION (Build $REVISION)";
+
+      my $HELP_INFO = "This is my help\n";
+
+      # All of the necessary information must be passed
+      # to the foundation object instance, as below.
+
+      $tfobject->addDependInfo(@DEPEND);
+      $tfobject->setVersionInfo($VERSION_STRING);
+      $tfobject->setHelpInfo($HELP_INFO);
+
+      my $input_file;
+      my $output_file;
+
+      $tfobject->TIGR_GetOptions("input=s" => \$input_file,
+                                 "output=s" => \$output_file);
+
+      # GetOptions(), and subsequently TIGR_GetOptions(), leaves
+      # the variables unchanged if no corresponding command line
+      # arguments are parsed.  The passed variables are checked below.
+
+      if (defined $input_file) {
+
+         # The log message is written only if debugging is turned on.
+         # By default, debugging is off.  To turn on debugging, use the
+         # '-debug DEBUG_LEVEL' option on the command line.
+         # In this example, '-debug 1' would set debugging to level 1
+         # and report these log messages.
+
+         $tfobject->logLocal("My input file is $input_file", 1);
+      }
+
+      print "Hello world", "\n";
+
+      # This case is similar to the previous one above...
+      if (defined $output_file) {
+         $tfobject->logLocal("My output file is $output_file.", 1);
+      }
+   }
+
+=cut
+
+1; 
+
+
+
+