#! perl -w

=head1 NAME

cfx5pre - run CFX-Pre

=cut

#!/bin/sh
#==============================================================================
# @(#) $Id$
#-------------------------------------------------------------------------------
##
#H Name:
##
## cfx5pre
##
#H Purpose:
##
## Run the CFX Pre Processor
##
#H Synopsis:
##
## cfx5pre [-gui|-line|-batch <file>] [-port <port>]
##         [-graphics ogl|mesa] [-session <sessionfile>]
##         [-def <deffile>] [-cfx <cfxfile>]
##         [-display <display>] [-help] [-v]
##
## []  denotes an optional argument.
## |   separates mutually exclusive arguments.
## ... following an argument indicates that it may be repeated.
## <>  denotes that substitution of a suitable value is required. All other
##     arguments are keywords, some of which have a short form.
##
#H Arguments:
##
#A -batch <file>
##     Starts CFX-Pre in batch mode, with session file <file>.  The
##     session file is played, and then CFX-Pre exits.
##
#A -display <display>
#A -d <display>
##     Display the graphical user interface on the X11 server <display>
##     instead of using the X11 server defined by the DISPLAY environment
##     variable.
##
## -def <file>
##     Loads the named def file after starting
##
## -cfx <file>
##     Loads the named cfx file after starting
##
## -gtm <file>
##     Loads the named GTM file after starting
##
## -icem  <file>
##     Loads the named ICEM mesh file after starting
##
#A -graphics ogl|mesa
#A -gr ogl|mesa
##     Set the graphics mode to use for the GUI to the OpenGL (hardware)
##     or MESA (software)-based version.
##
#A -gui
##     Starts CFX-Pre in GUI mode.  This is the default.
##
#A -help
#A -h
##     Print this message.
##
#A -initial-ccl <text>
#A -e <text>
##     Specify some arbitary command language text to execute after
##     starting.  This option may be specified more than once.
##
#A -line
##     Starts CFX-Pre in line mode.
##
#A -session <file>
#A -s <file>
#A -play <file>
##     Plays the named session file after starting.
##
#A -verbose
#A -v
##     Specifying this option may result in additional output being sent to
##     the UNIX standard output file (normally the screen).
##
#U ****************************************************************************
#U *                                                                          *
#U *     The following features are supported only within CFX and are not     *
#U *     shown by the -help option when the command is run elsewhere.         *
#U *                                                                          *
#U ****************************************************************************
#U
#U -batch-mode
#U     Start in batch mode, but without a session file.
#U
#U -lang <lang>
#U     Set a language specifier.
#U
#U -local
#U     Rather than using the central version of CFX-Pre, assume that
#U     the current directory is the root of a locally-built version
#U     and run from that.
#U
#U -process-rules
#U     Process the input rules files, and uses the resulting data,
#U     rather than using the centrally-built versions.
#U
#U -rules-application <file>
#U     Overrides the location of the rules.application file.  Implies
#U     -process-rules.
#U
#U -rules-extra <file>
#U     Overrides the location of the RULES.EXTRA file.  Implies
#U     -process-rules.
#U
#U -rules-standard <file>
#U     Overrides the location of the RULES file used to generate the
#U     CFXPreRules.ccl and RULES_CHANGE files.  Implies
#U     -process-rules.
#U
#U -exec-rules-standard <file>
#U     Overrides the location of the execrules.ccl file.
#U
#U -physics-file <file>
#U     Overrides the location of the CFXPrePhysics.ccl file.
#U
#U -gui-file <file>
#U     Overrides the location of the CFXPrePhysics.ccl file.
#U
#U -run-with <cmd>
#U     Rather than running directly, uses <cmd> as a wrapper to invoke it.
#U
#U -wid <id>
#U     Sets the window ID in which to embed the CFX-Pre window
#U
#U -control-port <id>
#U     Sets the port number to which CFX-Pre will communicate (i.e. WB)
#U
#U -nogui
#U     Specifies whether to run the app with the GUI or without - usually
#U     used when running under WB.

# get the standard CFX-5 library directory
BEGIN {
  if ($0 =~ m!^([a-z]:)?[\\/]!i) {
    # it's an absolute path, use it as-is
    (my $nd=$0) =~ s!(perllib[\\/])?[^\\/]*$!!i;
    unshift @INC, "$nd/perllib";
  } else {
    # wrap this in an eval, and if it fails, pray ... for example,
    # this can fail on Windows if we're running off a share.
    eval {
      require FindBin;
      FindBin->import();
      unshift @INC, "$FindBin::Bin/perllib";
      my $dummy=$FindBin::Bin; # kill used only once warning
    };
    warn $@ if $@;
  }
  if (defined $ENV{CFX_LOCAL_PERLLIB}) {
     unshift @INC, $ENV{CFX_LOCAL_PERLLIB};
  }

}

#
# Generate an unique session ID for the ANSYS help system.
#
if(! $ENV{ANSHELP_SESSION_ID})
{
	srand (time ^ $$ ^ unpack "%L*", rand());
	my $ANSHELP_SESSION_ID = "";
	for ($i = 1; $i <= 64; $i++)
	{
		$ANSHELP_SESSION_ID = $ANSHELP_SESSION_ID . sprintf("%x", int(rand(16)));
	}
	$ENV{ANSHELP_SESSION_ID} = $ANSHELP_SESSION_ID;
}

use CFX5::Init;
CFX5::Init::init();

use vars qw($CVSVersion);
sub BEGIN {
  $CVSVersion='@(#) $Id$\n';
}

use strict;

use CFX5::Output qw(:all);
use CFX5::Config qw(%Config export_conf append_to_libpath prepend_to_libpath append_to_execpath prepend_to_execpath setconf check_gui_support);
use CFX5::PrintConfig;

use CFX5::PkgLoader qw(cfx5_require);
use CFX5::CmdLine qw(:util parse_cmdline);

use CFX5::PathManip qw(join_file split_file fullpath basename dirname change_cwd);
use CFX5::FileTests;
#use CFX5::FileOps qw(link_files copy_file_for_read move_file move_file_to_backup glob_suffix create_empty_file);
#use File::Path qw(rmtree);

use CFX5::ExitRoutines qw(:tidyup);

use CFX5::System qw(assert_can_window);

use CFX5::FrameServ;
use CFX5::LIST;

use CFX5::Commands qw(do_cmd do_cmd_quiet handle_rv parse_rv get_cmd_output);

use CFX5::CCLI qw(export_parser_conf);
use CFX5::CUEI;

CFX5::Config::read_config();

use vars qw(%args $def_file $cfx_file $gtm_file $icem_file $mode $port $chdir $session $viewer_port $remote_host $wid $control_port $process_rules $process_rules_only $no_physical_rules_gen $process_rules_outdir @initccl);

$chdir=0;
$mode='gui';
$port=10_000 + ($$ % 10_000);

%args=(
   '-batch+'        => sub { $mode='batch';
			     conf_datafile(\$session,   "CFX-Pre session file %%", @_); },
   '-batch-mode'    => sub { $mode='batch' },
   '-cfx+'          => sub { conf_datafile(\$cfx_file,  "CFX-Pre cfx file %%", @_); },
   '-chdir'         => sub { $chdir=1 },
   '-custom-data-dir+'
                    => \$Config{CFX_CUSTOM_DATA_DIR},
   '-def+'          => sub { conf_datafile(\$def_file,  "CFX-Pre def file %%", @_); },
   '-gtm+'          => sub { conf_datafile(\$gtm_file,  "GTM database file %%", @_); },
   '-icem+'         => sub { conf_datafile(\$icem_file, "ICEM mesh file %%", @_); },
   '-graphics+'     => \$Config{CUE_GRAPHICS},
   '-gr+'           => '-graphics',
   -gui             => sub { $mode='gui'; },
   -line            => sub { $mode='line'; },
   '-lang+'         => \$Config{CFX_LANGUAGE},
   -local           => \$Config{CUE_ISLOCAL},

   '-local-root+'   => sub {
     $Config{CUE_ISLOCAL}=1;
     conf_datadir(\$Config{CUE_ROOT}, "Local CUE root directory %%", @_);
   },

   '-no-custom-data'=> \$Config{CFX_NO_CUSTOM_DATA},
   -nogui           => sub { $mode='nogui'; },
   '-play+'         => '-session',
   '-port+'         => \$port,
   '-remote+'       => sub {
     $mode='remote';
     $remote_host=$_[1];
   },

   '-run-with+'     => \$Config{CFX_RUN_WITH},
   '-server'        => sub { $mode='server'; },
   '-s+'            => '-session',
   '-session+'      => sub { conf_datafile(\$session, "CFX-Pre session file %%", @_); },
   '-viewer-port+'  => \$viewer_port,
   '-viewerport+'   => '-viewer-port',
   '-wid+'          => \$wid,
   '-control-port+' => \$control_port,
   '-initial-ccl+'  => \@initccl,
   '-e+'            => \@initccl,
   
   '-process-rules' => \$process_rules,
   '-process-rules-only' => sub {
     $process_rules_only++;
     $process_rules++;
   },
   '-process-rules-only-no-phys' => sub {
     $process_rules_only++;
     $process_rules++;
     $no_physical_rules_gen=1;
   },
   '-process-rules-outdir+'  => \$process_rules_outdir,
   '-exec-rules-standard+'   => sub { conf_datafile(\$Config{CFX_PRE_EXEC_RULES_ORIG},   
						    "Input exec rules file %% for CFX-Pre", @_); 
				      $process_rules++; },
   '-rules-standard+'        => sub { conf_datafile(\$Config{CFX_PRE_RULES_ORIG},       
						    "Input rules file %% for CFX-Pre", @_); 
				      $process_rules++; },
   '-rules-application+'     => sub { conf_datafile(\$Config{CFX_PRE_RULES_APPLICATION},
						    "Input rules.application file %% for CFX-Pre", @_);
				      $process_rules++; },
   '-rules-extra+'           => sub { conf_datafile(\$Config{CFX_PRE_RULES_EXTRA}, 
						    "Input RULES.EXTRA file %% for CFX-Pre", @_);
				      $process_rules++; },
   '-physics-file+'          => sub { conf_datafile(\$Config{CFX_PRE_PHYSICS_LIB},  
						    "Input Physics file %% for CFX-Pre", @_);},
   '-gui-file+'              => sub { conf_datafile(\$Config{CFX_PRE_GUI_LIB},
						    "Input GUI file %% for CFX-Pre", @_);},
);

my @nonopt=parse_cmdline(\@ARGV, 'ALLOW_NON_OPTION', 'INCLUDE_STD', %args);
exit_if_error();

if (@nonopt) {
  my $file=shift @nonopt;
  if ($file =~ m!\.cfx$!i) {
    unless (defined $cfx_file) {
      $cfx_file=$file;
      CFX5::FileTests::datafile($cfx_file, "CFX-Pre cfx file $cfx_file");
    } else {
      _error("You may specify only one case file on the command line");
    }
  } elsif ($file =~ m!\.def$!i) {
    unless (defined $def_file) {
      $def_file=$file;
      CFX5::FileTests::datafile($def_file, "CFX-5 Solver Input File $def_file");
    } else {
      _error("You may specify only one CFX-5 Solver Input File on the command line");
    }
  } elsif ($file =~ m!\.gtm$!i) {
    unless (defined $gtm_file) {
      $gtm_file=$file;
      CFX5::FileTests::datafile($gtm_file, "CFX-5 GTM File $gtm_file");
    } else {
      _error("You may specify only one CFX-5 GTM File on the command line");
    }
  } elsif ($file =~ m!\.pre$!i) {
    unless (defined $session) {
      $session=$file;
      CFX5::FileTests::datafile($session, "CFX-Pre Session File $session");
    } else {
      _error("You may specify only one CFX-Pre Session File on the command line");
    }
  } else {
    _error("Cannot determine type of file $file");
  }
}

if (@nonopt) {
  _error("Unexpected arguments", @nonopt, "without an associated argument were found on the command line.");
}

#
# argument consistency checks
#

if ($mode eq 'gui' ){
  _error("GUIs are not supported on this platform") unless check_gui_support();
  exit_if_error();
}

if ($mode eq 'remote') {
  _error("You must use the -port argument with -remote" . CFX5::Help::usage_msg_once())
    unless defined $port;
  _error("You must use the -viewer-port argument with -remote" . CFX5::Help::usage_msg_once())
    unless defined $viewer_port;
}

exit_if_error();

#
# On DECs the _RLD_ARGS environemnt variable will be set if CFX-Pre is
# started from CFX-Build. However the setting used by CFX-Build will
# cause CFX-Visualise to crash, and might affect pre too. So we'll unset
# it.
#
delete $ENV{_RLD_ARGS};

# Note: The 'process_rules' section must come before the 'export_pre_conf' otherwise
#       the CFX_PRE_RULES_CCL variable does not take effect when explicitly set by the user.
if ($process_rules) {
  
  cfx5_require('CFX5::PreRulesProcessor');
  CFX5::PreRulesProcessor->new()->go($process_rules_outdir, $no_physical_rules_gen);

  if ( $process_rules_only ) {
    exit_if_error();
    exit(0);
  }
}

CFX5::CUEI::export_pre_conf();
export_conf(qw(CFX_DATA_DIR CFX5ROOT CFX_CMD_DIR
               CFX_TOOLS_ROOT CFX_OS CFX5OS CFX_HOST 
               LM_LICENSE_FILE CFX_LICENSE_FILE
               CFX_PRE_ROOT CUE_DIR CFX5PERL
               ANSYS_COMMON_ROOT ANSYS_COMMON_IMAGES_DIR
               AFDSTART
              ));

# check for DISPLAY
assert_can_window() unless ( $mode eq 'batch' || $mode eq 'server' || $mode eq 'nogui' ) ;

exit_if_error();

CFX5::PrintConfig::show_vars_by_verbosity();

my @guiargs;
my @args;

if (defined $session) {
  push @args, '-s', $session;
}

if (defined $cfx_file) {
  push @args, '-cfx', $cfx_file;
  change_cwd(dirname($cfx_file)) if $chdir;
}

if (defined $def_file) {
  push @args, '-def', $def_file;
  change_cwd(dirname($def_file)) if $chdir;
}

if (defined $gtm_file) {
  push @args, '-gtm', $gtm_file;
  change_cwd(dirname($gtm_file)) if $chdir;
}

if (defined $icem_file) {
  push @args, '-icem', $icem_file;
  change_cwd(dirname($icem_file)) if $chdir;
}

if (defined $wid) {
  push @guiargs, -w => $wid;
}

if (defined $control_port) {
  push @args, -x => $control_port;
}

if ( @initccl ) {
  push @args, -e => join("\n", @initccl);
}

CFX5::FileTests::execfile($Config{"CUE_PREENGINE_EXE"},
                          "CFX-PRE Engine executable ".$Config{"CUE_PREENGINE_EXE"});

#CFX5::FileTests::execfile($Config{"CUE_VIEWER_EXE"},
#                          "CFX-PRE viewer executable ".$Config{CUE_VIEWER_EXE});
if ($mode eq 'gui') {
  CFX5::FileTests::execfile($Config{"CUE_PREGUI_EXE"},
                            "CFX-PRE GUI executable ".$Config{"CUE_PREGUI_EXE"});
}

exit_if_error();

my @runwith;
if (defined $Config{CFX_RUN_WITH}) {
  @runwith = $Config{CFX_RUN_WITH};
}

if ($mode eq 'gui') {
  my $rv=handle_rv(do_cmd(@runwith, $Config{"CUE_PREGUI_EXE"}, '-p', $port, @args, @guiargs));
  _warn("CFX-PRE exited with return code $rv")
    if ($rv);
  exit($rv);
} elsif ($mode eq 'line') {
  my $rv=handle_rv(do_cmd(@runwith, $Config{"CUE_PREENGINE_EXE"}, '-v', @args));
  _warn("CFX-PRE exited with return code $rv")
    if ($rv);
  exit($rv);
} elsif ($mode eq 'batch') {
  CFX5::Config::def->import(TASC_VIEWER_NOWINDOW => sub { '1'; });
  export_conf('TASC_VIEWER_NOWINDOW');
  my $rv=handle_rv(do_cmd(@runwith, $Config{"CUE_PREENGINE_EXE"}, '-v', '-b', @args));
  _warn("CFX-PRE exited with return code $rv")
    if ($rv);
  exit($rv);
} elsif ($mode eq 'nogui') {
  CFX5::Config::def->import(TASC_VIEWER_NOWINDOW => sub { '1'; });
  export_conf('TASC_VIEWER_NOWINDOW');
  my $rv=handle_rv(do_cmd(@runwith, $Config{"CUE_PREENGINE_EXE"}, '-v', '-nogui', @args));
  _warn("CFX-PRE exited with return code $rv")
    if ($rv);
  exit($rv);
} elsif ($mode eq 'remote') {
  push @args, '-u', '-h', $remote_host, '-p', $port, '-v', $viewer_port;
  my $rv=handle_rv(do_cmd_quiet(@runwith, $Config{"CUE_PREGUI_EXE"}, @args));
  _warn("CFX-Pre exited with return code $rv")
    if ($rv);
  exit($rv);
} elsif ($mode eq 'server') {
  my $rv=handle_rv(do_cmd(@runwith, $Config{"CUE_PREENGINE_EXE"}, '-v', '-g', @args));
  _warn("CFX-Pre exited with return code $rv")
    if ($rv);
  exit($rv);
} else {
  internal_error("Invalid mode specification $mode");
}
