#!/bin/sh
# --------------------------------------------------------------------------- #
# sort_switch: Script to unify the way the switches are ordered in the switch #
#              file, while checking and correcting for missing switches.      #
#                                                                             #
# use        : sort_switch [options] switch_file                              #
#              See usage function for options.                                #
#                                                                             #
# error codes : Various error outputs with explanaition.                      #
#                                                                             #
# scripts used :                                                              #
#   make_makefile.sh   Script with all mandatory switches defined.            #
#                                                                             #
# remarks:                                                                    #
#   * Use all_switches to update data in 1.a.6.                               #
#                                                                             #
#                                                      Hendrik L. Tolman      #
#                                                      November 2013          #
#                                                                             #
#    Copyright 2013 National Weather Service (NWS),                           #
#       National Oceanic and Atmospheric Administration.  All rights          #
#       reserved.  WAVEWATCH III is a trademark of the NWS.                   #
#       No unauthorized use without permission.                               #
#                                                                             #
# --------------------------------------------------------------------------- #
# 1. Preparations                                                             #
# --------------------------------------------------------------------------- #
# 1.a Internal variables

  set -e

# 1.a.1 Setup file

# The following line must not be removed: it is a switch for local install
# so that all bin scripts point to the local wwatch3.env
  export ww3_env=$COAWST_WW3_DIR/wwatch3.env
# For manual install (without install_ww3_tar or install_ww3_svn) make sure to
# either use the generic ww3_env or to add your own ww3_env="${my_directory}"

  if [ ${WWATCH3_ENV} ]; then ww3_env="${WWATCH3_ENV}"; fi # alternate

  home_dir=`pwd`

# 1.a.2 Usage function

  scriptname="`basename $0`"
  optstr="a:e:ho:rsuv"

  usage ()
{
cat 2>&1 << EOF

Usage: $scriptname [options] switch_file
Required:
  switch_file: name of switch file to be processed
Options:
  -a switch_add    : switch to add to file.
  -e switch_ext    : switch to extract from file.
  -h               : help, print this.
  -o output_file   : name of output file
                      * default is switch_file.new
  -r               : replace old file
                      * overrides -o
  -s               : silent mode, no output at all
                      * overrides -v
  -u               : allow updating (adding) switches,
                     otherwse this gives an error exit
  -v               : verbose, show program output
EOF
}
 
# 1.a.3 Process input (part 1)

  args=`getopt $optstr $*`

  if [ $? != 0 ]
  then
    usage
    exit 1
  fi

  set -- $args
  not_silent=1

  while :
  do
    case "$1" in
    -a) shift; add=$1 ;;
    -e) shift; extract=$1 ;;
    -h) help=1 ;;
    -o) shift; outp_file="$1" ;;
    -r) replace=1 ;;
    -s) not_silent=$NULL ;;
    -u) update=1 ;;
    -v) verbose=1 ;;
    --) break ;;
    esac
    shift
  done
  shift

  if [ -z "$not_silent" ] ; then
    verbose=$NULL ; fi

  if [ $help ]
  then
    usage
    exit 1
  fi

  if [ ! $# = 0 ]
  then
    switch_file="$1" ; shift
    if [ -z "$outp_file" ] ; then
      outp_file=$switch_file.new ; fi
    if [ "$replace" ] ; then
      outp_file=$switch_file ; fi
  else
    usage
    exit 2
  fi

# 1.a.4 Setup WW3 environment

  if [ -f $ww3_env ]
  then
    set `grep WWATCH3_DIR $ww3_env` ; shift
    main_dir="$*"
    set `grep WWATCH3_TMP $ww3_env` ; shift
    temp_dir="$*"
    set `grep WWATCH3_SOURCE $ww3_env` ; shift
    source="$*"
    set `grep WWATCH3_LIST $ww3_env` ; shift
    list="$*"
  else
    echo "*** Set-up file $ww3_env not found ***"; echo ' '
    exit 3
  fi

  bin_dir="$main_dir/exe"
  script="$main_dir/bin/make_makefile.sh"
  shorts="make_makefile.stripped"
 
# 1.a.5 Process input (part 2)

  mkdir -p $temp_dir

  if [ ! -f $switch_file ] ; then
    echo " *** cannot find $switch_file ***" ; exit 4 ; fi

  if [ ! -f $script ] ; then
    echo " *** cannot find $script ***" ; exit 5 ; fi
 
# 1.a.6 Additional setups

  outs="O0 O1 O2 O2a O2b O2c O3 O4 O5 O6 O7 O7a O7b O8 O9 O10 O11 O12 O13 O14 O15 O16"
  trace="S"
  tests="T T0 T1 T1a T2 T3 T38 T4 T5 T6 T7 T8 T9 MPIT TIDET SCRIPTST"

# 1.b ID header  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  if [ "$not_silent" ]
  then
    echo ' '
    echo '              **************************************'
    echo '            *** sorting WAVEWATCH III switch file ***'
    echo '              *************************************'
    echo ' '
    echo " Switch file       : $switch_file"
    echo " Output file       : $outp_file"
    echo " Local directory   : $home_dir"
    echo " Main directory    : $main_dir"
    echo " Scratch directory : $temp_dir"
    echo " Base script       : $script"
    if [ -n "$add" ] ; then
      echo " Add               : $add" ; fi
    if [ -n "$extract" ] ; then
      echo " Extract           : $extract" ; fi
    echo ' '
  fi

# 1.d Set up work space  - - - - - - - - - - - - - - - - - - - - - - - - - - - 

  cd $temp_dir

  rm -f tempfile*

# --------------------------------------------------------------------------- #
# 2. Setting up processing                                                    #
# --------------------------------------------------------------------------- #
# 2.a Unpack switch file

  if [ "$not_silent" ]
  then
    echo " Reading $switch_file ..."
  fi

  old_switches="`head -1 $home_dir/$switch_file`"

# add switch as requested

  found=0
  if [ -n "add" ]
  then
    work_sw="$old_switches"
    for sw in $work_sw
    do
      if [ "$sw" = "$add" ] ; then
        found=`expr $found + 1` ; fi
    done
    if [ "$found" = '0' ] ; then
      old_switches="$old_switches $add" ; fi
  fi

# remove switch as requested

  if [ -n "extract" ]
  then
    work_sw="$old_switches"
    old_switches=
    for sw in $work_sw
    do
      if [ "$sw" != "$extract" ]
      then
        if [ -z "$old_switches" ]
        then
          old_switches="$sw"
        else
          old_switches="$old_switches $sw"
        fi
      fi
    done
  fi

# spaces added to old_switches start and end to make searching easy

  old_switches=" $old_switches "

  work_sw="$old_switches"
  new_switches=
  i_tot='0'
  i_add='0'
  i_lft=`echo $old_switches | wc -w | awk '{ print $1 }'`
  i_old=$i_lft

# 2.b Getting keywords from make_makefile.sh

  if [ "$not_silent" ]
  then
    echo " Keywords from $script ..."
  fi

  sed -n /'for type in'/,/'do'/p $script > tempfile.$$

  sed -e 's/for type in//g' \
      -e 's/do//g' \
      -e 's/\\//g' \
      -e 's/\n//g' tempfile.$$ > tempfile2.$$

  set `cat tempfile2.$$`
  keywords="$*"

  rm -f tempfile.$$ tempfile2.$$

# 2.c Strip make_makefile.sh

  sed -n /'for type in'/,/'esac'/p $script > tempfile.$$

  sed -n /'case'/,/'esac'/p tempfile.$$ > $shorts
  rm -f tempfile.$$

# --------------------------------------------------------------------------- #
# 3. Looping over keywords                                                    #
# --------------------------------------------------------------------------- #
# 3.a start of keyword loop

  if [ "$not_silent" ]
  then
    echo ' '
    echo " Looping over keywords ..."
  fi

  for key in $keywords
  do

# 3.b Find setup in script

    sed -n /sort:$key:/,/\;\;/p $shorts | \
    sed -e "s/$key//g" -e 's/)//g' -e 's/\;//g'    > tempfile.$$

    lines=`wc -l tempfile.$$ | awk '{ print $1}'`
    if [ "$lines" = '0' ] ; then
      echo "keyword $key not found, abort" ; exit 6 ; fi

    . ./tempfile.$$

    rm -f tempfile.$$

# 3.c Process switches for keyword

    i_fnd='0'
    found=
    msg=

    for sw in $OK
    do
      for avail in $work_sw
      do
        if [ "$sw" = "$avail" ]
        then
          i_fnd=`expr $i_fnd + 1`
          if [ "$i_fnd" = '1' ]
          then
            found="$sw"
          else
            found="$found $sw"
          fi
        fi
      done
   
    done

#   if [ "$verbose" ]
#   then
#     echo "    $key $i_fnd $found [$OK]"
#   fi

# 3.d Too many switches found (error)

    case $TY in
     'upto2' ) i_tst='2' ;;
         *   ) i_tst='1' ;;
    esac

    if [ "$i_fnd" -gt "$i_tst" ] ; then
      echo "keyword $key $i_fnd hits (>1) [$found], abort" ; exit 7 ; fi

# 3.e process types
    case $TY in

# 3.e.1 process type 'one'

      'one'     )
        if [ "$i_fnd" = '0' ]
        then
          i_sec='0'
          for sw in $OK
          do
            for swf in $new_switches
            do
              if [ "$sw" = "$swf" ]
              then
                i_sec=`expr $i_sec + 1`
                found="$sw"
              fi
            done
          done
          if [ "$i_sec" = '0' ]
          then
            i_fnd='1'
            found=`echo $OK | awk '{ print $1}'`
            msg=' (added)'
            i_add=`expr $i_add + 1`
          else
            msg=' (dual use)'
          fi
        fi ;;

# 3.e.2 process type 'upto1'

      'upto1'   )
      ;;

# 3.e.3 process type 'upto2'

      'upto2'   )
      ;;

# 3.e.4 unknown default

     *  ) echo 'ooops' ; exit 99 ;;
    esac

    if [ "$verbose" ]
    then
      string=`echo "$key $i_fnd" | awk '{ printf "%-10.10s %1.1s", $1, $2 }'`
      echo "    $string  $found$msg"
    fi

# 3.f Add to new_switches

    if [ "$i_fnd" != '0' ]
    then
      if [ -z "$new_switches" ]
      then
        new_switches="$found"
        i_tot="$i_fnd"
      else
        for pfnd in $found
        do
          lines=`echo $new_switches |grep $pfnd | wc -l | awk '{ print $1}'`
          if [ "$lines" = '0' ]
          then
            new_switches="$new_switches $pfnd"
            i_tot=`expr $i_tot + 1`
          fi
        done
      fi
    fi

#   if [ "$verbose" ]
#   then
#     echo "       $i_tot $i_add $new_switches"
#   fi

# 3.g Remove from old_switches

    if [ "$i_fnd" != '0' ]
    then
      for pfnd in $found
      do
        temp_sw=`echo "$work_sw" | sed -e "s/ $pfnd / /g"`
        work_sw=$temp_sw
      done
      i_lft=`echo $work_sw | wc -w | awk '{ print $1 }' `
    fi

#   if [ "$verbose" ]
#   then
#     echo "       $work_sw"
#   fi

# 3.h End of keyword loop 3.a

  done

  rm -f $shorts

  if [ "$verbose" ]
  then
    echo ' '
    echo " Looping over keywords finished"
  fi

  if [ "$not_silent" ]
  then
    echo "    Found $i_tot, $i_add of which added to list, $i_lft left."
  fi

# --------------------------------------------------------------------------- #
# 4. Dealing with left over switches                                          #
# --------------------------------------------------------------------------- #
# 4.a Loop over additional types 

  for type in out strace test
  do

# 4.b Identify type

    case $type in
      out    ) switches=$outs
               ID='output options' ;;
      strace ) switches=$trace
               ID='subr. tracing' ;;
      test   ) switches=$tests
               ID='test output' ;;
    esac

    if [ "$not_silent" ]
    then
      echo ' '
      echo " Processing $ID ..."
    fi

# 4.c Loop over switchs

    for sw in $switches 
    do
      i_fnd='0'
      found=
      for avail in $work_sw
      do
        if [ "$sw" = "$avail" ]
        then
          if [ "$i_fnd" = '0' ]
          then
            i_fnd='1'
            found="$sw"
          fi
      fi
      done

# 4.d Switch found, process

      if [ "$i_fnd" = '1' ]
      then
        i_tot=`expr $i_tot + 1`
        new_switches="$new_switches $found"
        temp_sw=`echo "$work_sw" | sed -e "s/ $found / /g"`
        work_sw=$temp_sw
        i_lft=`echo $work_sw | wc -w | awk '{ print $1 }' `
      fi

      if [ "$verbose" ]
      then
        string=`echo "$sw $i_fnd" | awk '{ printf "%-10.10s %1.1s", $1, $2 }'`
        echo "    $string  $found"
      fi

    done

# 4.e End of main loop, generate output

    if [ "$verbose" ]
    then
      echo ' '
      echo " Looping for $ID finished"
    fi

    if [ "$not_silent" ]
    then
      echo "    Found $i_tot, $i_add of which added to list, $i_lft left."
    fi

  done

# --------------------------------------------------------------------------- #
# 5. Processing done, last checsk and output                                  #
# --------------------------------------------------------------------------- #

  if [ "$i_lft" != '0' ]
  then
    if [ "$not_silent" ]
    then
      echo ' '
    fi
    echo "sort_switch: could not process all switches [$work_sw] abort."
    exit 8
  fi

  if [ "$i_tot" != "$i_old" ] && [ ! "$update" ]
  then
    if [ "$not_silent" ]
    then
      echo ' '
    fi
    echo "sort_switch: number of switches not conserved [$i_old,$i_tot]."
    exit 8
  fi

  if [ "$not_silent" ]
  then
    echo ' '
    echo " Processing done, saving in $outp_file."
    if [ "$i_tot" != "$i_old" ]
    then
      echo "    Added $i_add switches."
    fi
  fi

  echo "$new_switches" > $home_dir/$outp_file

# --------------------------------------------------------------------------- #
# 6. End of program ID / clean up                                             #
# --------------------------------------------------------------------------- #

# cd $home_dir
# rm -rf $temp_dir

  if [ "$not_silent" ]
  then
    echo ' '
    echo '                     *************************'
    echo '                   *** end of switch sorting ***'
    echo '                     *************************'
    echo ' '
  fi

# End of sort_switch -------------------------------------------------------- #
