#! /bin/sh

#    Apr 04/06 - F.Majaess (Revised to handle varx='vary=varz' case)
#    Jul 24/02 - F.Majaess

#id  chkcrtcl- Checks consistency of critical parameter settings.

#    AUTHOR  - F.Majaess

#hd  PURPOSE - "chkcrtcl" script is used to check the consistency
#hd            of critical parameters, whose setting is supplied
#hd            in "arg1" file, versus the corresponding parameters
#hd            whose setting is passed in "arg2" file. 
#hd            If no entry for "arg2" is specified, the check is
#hd            done versus the corresponding active parameters 
#hd            setting in the current process.
#hd            NOTE: At least one argument (for "arg1") and no more
#hd                  than 2 can be specified.
#hd                  If 2 files are specified then, a straight "diff" 
#hd                  is attempted first, if that failed, then "arg2"
#hd                  is evaluated before proceeding with the check
#hd                  where each parameter specified in "arg1" is 
#hd                  expected to be as well present in "arg2".
#hd                  In the case where no "arg2" is specified, then
#hd                  each parameter setting specified in "arg1" is
#hd                  only checked if the corresponding parameter is
#hd                  set and active in the currently executing 
#hd                  process.

#pr  PARAMETERS:
#pr
#pr    PRIMARY
#pr
#pr      arg1   = name of file containing the list and setting of
#pr               critical parameters to be checked. 
#pr               (='rcvrd.critical')
#pr      arg2   = (optional); name of file containing the list and 
#pr               setting of parameters aginst whom "arg1" 
#pr               parameters setting is checked.

#ex  EXAMPLE:
#ex
#ex To check the user's specified critical section (in a model
#ex submission job) whose content is placed in "user.critical"
#ex file, versus the extracted "PARC" record contents from the
#ex restart file converted into character format and placed 
#ex in "rcvrd.critical", a one-to-one consistency check can
#ex be done by executing:
#ex
#ex   chkcrtcl rcvrd.critical user.critical
#ex   chkcrtcl user.critical rcvrd.critical
#ex
#ex To check current active process parameters setting versus
#ex the critical parameters which were extracted from "PARC" 
#ex record in the "GS" file, converted to character format 
#ex and placed in "rcvrd.critical" file, can be done by 
#ex executing:
#ex
#ex          chkcrtcl rcvrd.critical
#ex

unset Crtcl_prmsb_fil Crtcl_parm_fil Crtcl_Test_Passed All_critical_must_be_defined || : 

# Parse the entered command ...

if [ $# -gt 2 ] ; then

 # Abort if more than 2 arguments are specified.

 echo "\nchkcrtcl: Number of input parameters was exceeded!\n"
 exit 1

elif [ $# -eq 2 ] ; then

 # Capture "arg2" setting in "Crtcl_prmsb_fil".

 Crtcl_prmsb_fil="$2"

fi

if [ -n "$1" ] ; then

  # Capture "arg1" setting in "Crtcl_parm_fil".

  Crtcl_parm_fil="$1"

else

  # Default to "rcvrd.critical".

  Crtcl_parm_fil='rcvrd.critical'

fi

# Initialize check status switch.

Crtcl_Test_Passed='false'

# Set switch appropriately to [dis]allow applying difference test on splitted
# and sorted parameter files.
# Note: Duplicate entries for a given parameter may cause problem whereby the
#       test would pass where it should not have. 
 
# Allow_sort_diff=${Allow_sort_diff:='yes'}
Allow_sort_diff=${Allow_sort_diff:='no'}

# Proceed with the consistency check...

if [ -s "$Crtcl_parm_fil" ] ; then

 # Check if a file is pointed to by the second input argument...

 if [ -s "$Crtcl_prmsb_fil" ] ; then

  # Do a straight diff check first ....

  echo "\nchkcrtcl: Attempt straight difference of <$Crtcl_parm_fil> versus <$Crtcl_prmsb_fil> file"

  diff $Crtcl_parm_fil $Crtcl_prmsb_fil > /dev/null && Crtcl_Test_Passed='true' || Crtcl_Test_Passed='false'

  if [ "$Crtcl_Test_Passed" = 'true' ] ; then
    echo "\nchkcrtcl: Straight difference test passed\n"
  fi

 fi # of -s "$Crtcl_prmsb_fil"

 # Provided the test is not passed...
 # Attempt separating up to 9 variables per line into 
 # one variable per line ...
 
 if [ "$Crtcl_Test_Passed" != 'true' ] ; then
 
  # Setup "sed" directive file...
 
 (\rm -f chkcrtcl_sed_fil || : )

cat << '.eof' > chkcrtcl_sed_fil
 /^ *#/d
 /^ +/d
 /=/{
 s/ *; / ; /g
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7\
 \8\
 \9/
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7\
 \8/
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7/
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6/
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4\
 \5/
 s/\(;.*\)\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3\
 \4/
 s/\(;.*\)\(;.*\)\(;.*\)/\1\
 \2\
 \3/
 s/\(;.*\)\(;.*\)/\1\
 \2/
 s/\([^ ;]\{1,\}\)='/chkcv \1 Xcntrl='/g
 / Xcntrl=/!{
  s/\([^ ;]\{1,\}\)="/chkcv \1 Xcntrl="/g
 }
 / Xcntrl=/!{
  s/\([^ ;]\{1,\}\)=/chkcv \1 Xcntrl=/g
 }
 s/ *chkcv / chkcv /g
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7\
 \8\
 \9/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7\
 \8/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6\
 \7/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4\
 \5\
 \6/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4\
 \5/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3\
 \4/
 s/\(chkcv.*\)\(chkcv.*\)\(chkcv.*\)/\1\
 \2\
 \3/
 s/\(chkcv.*\)\(chkcv.*\)/\1\
 \2/
   }
.eof

  # Apply the procedure to "Crtcl_parm_fil" file ...

  (\rm -f chk_cnvrtd_exe_fil || : )
  cat $Crtcl_parm_fil | sed -e '/^ *#/d' | sed -e '/^ +/d' | tr '\073' '\012' | sed -f chkcrtcl_sed_fil | sed '/^ *$/d' > chk_cnvrtd_exe_fil

  if [ ! -s chk_cnvrtd_exe_fil ] ; then
   echo "\nchkcrtcl: No validly defined critical parameters to be checked are found"
   echo "          in $Crtcl_parm_fil file whose contents consisted of: \n"
   echo ">>>>>>>>>>>>"
   cat $Crtcl_parm_fil
   echo "<<<<<<<<<<<<"
   echo "\n"
   exit 2
  fi

  # If a file is pointed to by the second input argument...

  if [ -s "$Crtcl_prmsb_fil" ] ; then

   # Apply the same procedure to "Crtcl_prmsb_fil" file ...

   (\rm -f chk_cnvrtd_prmsb_fil || : )
   cat $Crtcl_prmsb_fil | sed -e '/^ *#/d' | sed -e '/^ +/d' | tr '\073' '\012' | sed -f chkcrtcl_sed_fil | sed '/^ *$/d' > chk_cnvrtd_prmsb_fil

  # Setup for "unsetting" all parameters to be checked
  # individually (if need be) later on   

  (\rm -f chk_unset_fil || : )
   cat chk_cnvrtd_exe_fil chk_cnvrtd_prmsb_fil | sed '
 /chkcv /{
 s/chkcv \(.*\) Xcntrl=.*$/unset \1 /g
    }
    ' | sort | uniq > chk_unset_fil
   
   if [ ! -s chk_unset_fil ] ; then
    echo "\nchkcrtcl: No variables to be checked were specified!\n"
    exit
   fi


   # Is splitted/sorted parameters check requested?

   if [ -s chk_cnvrtd_exe_fil -a -s chk_cnvrtd_prmsb_fil -a "$Allow_sort_diff" = 'yes' ] ; then

    # Setup and perform the check on the sorted parameters 

    (\rm -f s_chk_cnvrtd_exe_fil s_chk_cnvrtd_prmsb_fil || : )
    cat chk_cnvrtd_prmsb_fil | sort > s_chk_cnvrtd_prmsb_fil
    cat chk_cnvrtd_exe_fil | sort > s_chk_cnvrtd_exe_fil

    # Do a straight diff on the splitted/sorted resulting files ....

    echo "\nchkcrtcl: Attempt difference of splitted/sorted parameters files ..."
    diff s_chk_cnvrtd_exe_fil s_chk_cnvrtd_prmsb_fil > /dev/null && Crtcl_Test_Passed='true' || Crtcl_Test_Passed='false'

    if [ "$Crtcl_Test_Passed" = 'true' ] ; then
      echo "chkcrtcl: Same splitted/sorted parameters files\n"
    fi
    (\rm -f s_chk_cnvrtd_exe_fil || : )
   fi 
   (\rm -f s_chk_cnvrtd_prmsb_fil || : )
  fi 
 fi

 (\rm -f chkcrtcl_sed_fil || : )
 (\rm -f chk_cnvrtd_prmsb_fil || : )

 # Proceed with individual parameters check ...

 if [ "$Crtcl_Test_Passed" != 'true' ] ; then

  # Setup "chkcv" function...
 
  chkcv () { 
   #echo " $@ --> $#"
   IFS=' '   ; export IFS ;
   # set -x
   if [ "$#" -eq 2 ] ; then
    unset Xcntrl Ycntrl
    eval "Ycntrl=\${$1}"
    Ycntrl=${Ycntrl:='Ycntrl'}
    Xcntrl=`echo "$2"| sed -e 's/^.*Xcntrl=//'`
    if [ "$Ycntrl" != 'Ycntrl' ] ; then
     if [ "$Ycntrl" = "$Xcntrl" ] ; then
      :
      #echo "chkcrtcl: $@  --> $1 <-- defined (=$Ycntrl) and equivalent to the extracted critical value."
       echo "chkcrtcl: --> $1 <-- defined (=$Ycntrl) and equivalent to the extracted critical value."
     else
      :
      #echo "chkcrtcl: $@  **> $1 <** defined (=$Ycntrl) but NOT EQUIVALENT to the extracted critical value (=$Xcntrl)."
       echo "chkcrtcl: **> $1 <** defined (=$Ycntrl) but NOT EQUIVALENT to the extracted critical value (=$Xcntrl)."
       echo "chkcrtcl: **> $1 <** defined (=$Ycntrl) but NOT EQUIVALENT to the extracted critical value (=$Xcntrl)." >> haltit
       touch check_status_file
     fi
  
    else
      if [ "$All_critical_must_be_defined" = 'yes' ] ; then
      :
      #echo "chkcrtcl: $@  **> $1 <** parameter specified (=$Xcntrl) in <${Crtcl_parm_fil}> file is not defined in <${Crtcl_prmsb_fil}> file!"
       echo "chkcrtcl: **> $1 <** parameter specified (=$Xcntrl) in <${Crtcl_parm_fil}> file is not defined in <${Crtcl_prmsb_fil}> file!" 
       echo "chkcrtcl: **> $1 <** parameter specified (=$Xcntrl) in <${Crtcl_parm_fil}> file is not defined in <${Crtcl_prmsb_fil}> file!" >> haltit
       touch check_status_file
      else
       :
       #echo "chkcrtcl: $@  --> $1 <-- variable not defined; checking is skipped."
       #echo "chkcrtcl: --> $1 <-- variable not defined; checking is skipped."
      fi
    fi 
  
   else
  
     echo "chkcrtcl: Invalid use --> $@ <--; exactly 2 input parameters are expected/allowed on chkcv call!"
     #echo " $@ --> $#"
     set -x
     #exit 1
     (exit 1)
   fi ;
    }
 
  # set -x
  if [ -s "$Crtcl_prmsb_fil" ] ; then

   if [ -s "chk_unset_fil" ] ; then

    # Unset all variables involved in the validation check.

    . chk_unset_fil
 
     echo "\nchkcrtcl: All parameters in <$Crtcl_prmsb_fil> file are unset."

    (\rm -f chk_unset_fil || : )

    # Do not allow any parameter to be checked to be undefined.

    All_critical_must_be_defined='yes'

   fi

   # Evaluate "Crtcl_prmsb_fil" file insuring any lines starting with
   # " +" (if any) are eliminated from it.
   
   # set -x
   (\rm -f m_chk_cnvrtd_prmsb_fil || : )
   cat $Crtcl_prmsb_fil | sed -e '/^ +/d' > m_chk_cnvrtd_prmsb_fil

   . m_chk_cnvrtd_prmsb_fil

   (\rm -f m_chk_cnvrtd_prmsb_fil || : )

   echo "\nchkcrtcl: <$Crtcl_prmsb_fil> file was evaluated"

  fi

  # Perform the consistency check for each critical parameter...

  echo "\nchkcrtcl: Checking active setting versus those for `cat chk_cnvrtd_exe_fil | wc -l | sed -e 's/ *//g'` extracted critical parameters.\n"

  (\rm -f check_status_file || : )

  . chk_cnvrtd_exe_fil

  (\rm -f chk_cnvrtd_exe_fil || : )
  if [ -f "check_status_file" ] ; then
   echo "\nchkcrtcl: ****> Critical parameter check failed! <**** \n"
   (\rm -f check_status_file || : )
   exit 1
  else
   echo " "
  fi

 fi
 
else

 echo "\nchkcrtcl: Invalid critical parameters input file: $Crtcl_parm_fil \n"
 exit 1

fi
