#!/bin/sh
# --------------------------------------------------------------------------- #
# ad3   : Run fortran preprocessor w3adc of WAVEWATCH III on for a single     #
#         source code file. Switches are set in the file 'switch', which      #
#         has to be in the "bin" directory. After the preprocessing the code  #
#         is compiled using the script comp in  the "bin" directory.          #
#                                                                             #
# use   : ad3 basename [itest [icomp]]                                        #
#            basename: name of source code file without the '.ftn' extension. #
#                      file with .f or .f90 extension is not preprocessed.    #
#                      file with .c extension uses standard cc compiler.      #
#            itest   : test output switch.                                    #
#                       not defind or 0 : no test output                      #
#                       all other       : verbose mode                        #
#            icomp   : compiling switch.                                      #
#                       not defind or 0 : compile.                            #
#                       all other       : do not compile.                     #
#                                                                             #
# error codes :  1 : input error                                              #
#                2 : no environment file $ww3_env found.                      #
#                3 : error in creating scratch directory.                     #
#                4 : w3adc error.                                             #
#                5 : compiler error.                                          #
#                                                                             #
# programs used :                                                             #
#       w3adc : executable of proprocessing program.                          #
#       comp  : compiler script.                                              #
#                                                                             #
# remarks :                                                                   #
#                                                                             #
#  - Do not use itest in w3adc to avoid spurious error messages.              #
#  - The main WAVEWATCH directory ($main_dir) is obtained from the setup      #
#    file $ww3_env, as is the scratch directory ($temp_dir). The following    #
#    directories are used :                                                   #
#       $main_dir/ftn : Raw FORTRAN file ($basename.ftn). If extension is     #
#                       not .ftn, w3adc will be skipped. if the extension is  # 
#                       .c, then the simple cc compiler is used. The latter   #
#                       is now used for profiling code only.                  #
#       $main_dir/bin : File with preprocessor switches 'switch', and         #
#                       compiler script 'comp'.                               #
#       $main_dir/obj : Final object modules ($basename.o).                   #
#       $main_dir/mod : Final modules (*.mod).                                #
#                                                                             #
#    The following temporary files (in $temp_dir) are used and are removed    #
#    only if the corresponding step of ad3 is ompleted successfully :         #
#       w3adc.inp     : input file for w3adc.                                 #
#       w3adc.out     : output file for w3adc.                                #
#       w3adc.err     : eror file for w3adc.                                  #
#       comp.out      : input file for comp.                                  #
#       comp.err      : eror file for comp.                                   #
#       comp.stat     : status file of compiler, containing number of errors  #
#                       and number of warnings (generated by comp).           #
#                                                                             #
#  - Check the compress variable in section 1.b to print or suppress the_     #
#    documentation in the clean FORTRAN files.                                #
#                                                                             #
#                                                      Hendrik L. Tolman      #
#                                                      May 2009               #
#                                                      January 2014           #
#                                                                             #
#    Copyright 2009-2014 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 Check and process input

  if [ "$#" -gt '3' ] || [ "$#" -lt 1 ]
  then
    echo "usage: ad3 basename [itest [icomp]]" 1>&2 ; exit 1
  fi

  name=$1
  if [ "$#" -ge '2' ]
  then
    itst=$2
  else
    itst='0'
  fi
  if [ "$#" = '3' ]
  then
    icmp=$3
  else
    icmp='0'
  fi

# 1.b Internal variables - - - - - - - - - - - - - - - - - - - - - - - - - - -

# 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 setup file
  switch="switch"          # file containing switches
  compress=0               # source code compression par in w3adc
                           # if not 0, documentaion removed from .f90 file

# 1.c Read data from the environment file  - - - - - - - - - - - - - - - - - -

  if [ ${WWATCH3_DIR} ] && [ ${WWATCH3_TMP} ]
  then
    main_dir=${WWATCH3_DIR}
    temp_dir=${WWATCH3_TMP}
  elif [ -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 ***"
    exit 2
  fi

# 1.d Set up paths etc.  - - - - - - - - - - - - - - - - - - - - - - - - - - -

  path_b="$main_dir/bin"
  path_w="$temp_dir"
  path_i="$main_dir/ftn"
  path_o="$main_dir/obj"
  path_m="$main_dir/mod"
  path_e="$main_dir/exe"
  if [ -n "`echo $name | grep scrip_ 2>/dev/null`" ]
  then
    path_i="$path_i/SCRIP"
  fi

  sw_str=`cat $path_b/$switch`

  if [ ! -d $path_w ]
  then
    if ! `mkdir $path_w`
    then
      echo '      *** w3adc error ***'
      echo "          Cannot create $path_w"
      exit 3
    fi
  fi

# 1.e Test necessity of running w3adc - - - - - - - - - - - - - - - - - - - -

  if [ -f $path_i/$name.ftn ]
  then
    w3adc='yes'
    idstr=
  else
    w3adc='no'
    idstr='[no w3adc]'
  fi

# 1.f Set appropriate Fortran file suffix  - - - - - - - - - - - - - - - - - -

  suffixes="ftn f F f90 F90 c"
  fexti=none
  for s in $suffixes
  do
    if [ -f $path_i/$name.$s ]
    then
      fexti=$s
      break
    fi
  done
  if [ "$fexti" = 'none' ]
  then
    echo '      *** ad3 error ***'
    echo "          Source file $path_i/$name.* not found"
    echo "          Source file suffixes checked: $suffixes"
    exit 2
  fi
  if [ "$fexti" = 'ftn' ]
  then
    fexto=F90
  else
    fexto=$fexti
  fi
  fext=$fexto

# 1.g Output - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "ad3 : processing $name $idstr"

  if [ "$itst" != '0' ]
  then
    echo ' ' ; echo 'Test output ad3 ' ; echo '----------------'
    echo "  bin directory    : $path_b "
    echo "  work directory   : $path_w "
    echo "  input directory  : $path_i "
    echo "  object directory : $path_o "
    echo "  module directory : $path_m "
    echo "  executable dir.  : $path_e "
    echo "  switches file    : $switch " ; echo ' '
    echo "  switches         : $sw_str"
    echo ' '
  fi

# 1.h Final preparations - - - - - - - - - - - - - - - - - - - - - - - - - - -

  cd $path_w
  rm -f $name.$fext
  rm -f $name.l
  ln -s $main_dir/bin/w3list . 2> /dev/null

# --------------------------------------------------------------------------- #
# 2. Run w3adc                                                                #
# --------------------------------------------------------------------------- #
# 2.a Make input file

  if [ "$w3adc" = 'yes' ]
  then


# jcw Run cpp on files we added ifdefs to.
    if [ "$name" = "cwstwvcp" ] || [ "$name" = "mctww3pa" ] || [ "$name" = "ww3_shel" ] || [ "$name" = "w3wavemd" ] || [ "$name" = "w3updtmd" ]
    then
      headpre="$(echo ${COAWST_APPLICATION} | tr '[A-Z]' '[a-z]')"
      HEADER=$headpre.h
      if [ -f ${MY_HEADER_DIR}/$HEADER ]
      then
        GLOBAL_DEFS_FILE="${MY_ROMS_SRC}/ROMS/Include/globaldefs.h"
      fi
      CPPFLAGS1="PROJECT_HEADER=\"${MY_HEADER_DIR}/$HEADER\""
      CPPFLAGS2="GLOBAL_DEFS=\"${GLOBAL_DEFS_FILE}\""
      /usr/bin/cpp -P -traditional -D${CPPFLAGS1} -D${CPPFLAGS2} -I{COAWST_WW3_DIR}/ftn < $path_i/$name.ftn >$name.cpp

      echo "0 $compress"                             > w3adc.inp
      echo "'$path_w/$name.cpp' '$name.$fext'"      >> w3adc.inp
      echo "'$sw_str'"                              >> w3adc.inp

    else

      echo "0 $compress"                             > w3adc.inp
      echo "'$path_i/$name.ftn' '$name.$fext'"      >> w3adc.inp
      echo "'$sw_str'"                              >> w3adc.inp

    fi

# 2.b Add NCEP/NCO docmentation  - - - - - - - - - - - - - - - - - - - - - - -

# Obsolete feature, removed

# 2.b Run w3adc  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    if [ "$itst" != '0' ]
    then
      echo '-- input file w3adc.inp -------------------------------------------'
      cat w3adc.inp
      echo '-- end of file ----------------------------------------------------'
    fi

#   Here is where we cp ftn/* to tmp*.
    $path_b/w3adc < w3adc.inp > w3adc.out 2> w3adc.err

# 2.c Test the output of w3adc - - - - - - - - - - - - - - - - - - - - - - - -

    ad3_tst="`grep ERROR w3adc.out`"
    if [ -n "$ad3_tst" ]
    then
      echo '      *** w3adc error ***'
      echo "     $ad3_tst" ; exit 4
    fi

    if [ ! -f $name.$fext ]
    then
      echo '      *** w3adc error ***'
      echo "          file $name.$fext not found (1)."
      cat w3adc.out ; cat w3adc.err  ; exit 4
    fi

    if [ "`wc -l $name.$fext | awk '{ print $1}'`" -lt '2'  ]
    then
      echo '      *** w3adc error ***'
      echo "          file $name.$fext not found (2)."
      cat w3adc.out ; cat w3adc.err  ; exit 4
    fi

    if [ "$itst" != '0' ]
    then
      cat w3adc.out
    fi

# 2.d Clean up - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    rm -f w3adc.*

# 2.e Add switches in w3initmd - - - - - - - - - - - - - - - - - - - - - -

    if [ "$name" = "w3initmd" ]
    then
      sw_1=''
      cp $path_w/w3initmd.$fext  $path_w/w3initmd.ft1
      for line in 1 2 3
        do
          sw_1=`echo $sw_str  | fold -w100 | sed -n "${line}p"`
          sw_old="PUT_SW$line"
          # echo $line  $sw_1 $sw_old
          sed -e "s/$sw_old/$sw_1/"  $path_w/w3initmd.ft1 > $path_w/w3initmd.ft2
          mv  $path_w/w3initmd.ft2 $path_w/w3initmd.ft1
        done
      mv $path_w/w3initmd.ft1 $path_w/w3initmd.$fext
      echo "'$path_w/$name.fts' '$name.$fext'"        >> w3adc.inp
    fi

  else

# 2.f No w3adc, just copy file - - - - - - - - - - - - - - - - - - - - - - - -

    cp $path_i/$name.$fext .

  fi

  if [ ! -f $name.$fext ]
  then
    echo '      *** adc error ***'
    echo "          file $name.$fext not found."
    exit 5
  fi

# 2.g Stop if requested  - - - - - - - - - - - - - - - - - - - - - - - - - - -

  if [ "$icmp" != '0' ]
  then
    rm -f w3list
    exit 0
  fi

  rm -f $path_o/$name.o
  rm -f *.mod

# --------------------------------------------------------------------------- #
# 3. Compile source code f / f90                                              #
# --------------------------------------------------------------------------- #

export fext    # for use by comp
export path_m  # for use by comp
export path_i  # for use by comp

if [ ! -f $name.c ]
then

# 3.a Run compile program

  error='0'

  if $path_b/comp $name > comp.out 2> comp.err
  then
    rm -f comp.err
    rm -f comp.out

# 3.b Check comp.stat  - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    if [ -f comp.stat ]
    then
      nr_err=`grep ERROR comp.stat | awk '{ print $2 }'`
      nr_war=`grep WARNING comp.stat | awk '{ print $2 }'`
      rm -f comp.stat
      if [ "$nr_err" != '0' ]
      then
        echo "      $nr_err errors found, see $path_w/$name.l"
        list='yes'
      else
        if [ "$nr_war" != '0' ]
        then
          echo "      $nr_war warnings found, see $path_w/$name.l"
          list='yes'
        fi
      fi
    else
      echo '      *** compile error ***'
      echo '          file comp.stat not found'
      error='5'
      nr_err='1'
      rm -f $name.o
    fi

# 3.c process object file  - - - - - - - - - - - - - - - - - - - - - - - - - -

    if [ "$nr_err" != '0' ] && [ ! -f $name.o ] && [ "$error" = '0' ]
    then
      echo '      *** compile error ***'
      echo "          file $name.o not found"
      error='5'
    fi

    if [ "$nr_err" != '0' ]
    then
      rm -f $name.o
    else
      mv $name.o $path_o/.
      mods=`ls *.mod 2> /dev/null`
      if [ -n "$mods" ]
      then
        for mod in $mods
        do
          mv $mod $path_m/.
          echo "         $mod"
        done
      fi
    fi

# Note: the need for moving the .mod file and therefore the printing of the
#       $mod depend on the compiler behavior.

# 3.d Error escape location  - - - - - - - - - - - - - - - - - - - - - - - - -

  else
    echo '      *** compile error ***'
    echo '          error in comp'
    echo '--- comp output -------------------------------------------------'
    cat comp.out
    echo '--- comp error output -------------------------------------------'
    cat comp.err
    echo '-----------------------------------------------------------------'
    rm -f comp.*
    error='6'
  fi

# 3.e process output files - - - - - - - - - - - - - - - - - - - - - - - - - -

  rm -f $name.o
  rm -f w3list

  if [ "$source" != 'yes' ]
  then
    rm -f $name.f $name.$fext
  fi
  if [ "$list" != 'yes' ] && [ "$error" = '0' ]
  then
    rm -f $name.l
  fi

  exit $error

# --------------------------------------------------------------------------- #
# 4. Compile source code c                                                    #
# --------------------------------------------------------------------------- #
# For now only diagnostics / profiling codes compiled with simple cc compiler

else

# 4.a Compile

  cc -c $name.c

# 4.b Save object file

  if [ -f $name.o ]
  then
    mv $name.o $path_o/.
  else
    echo '      *** compile error ***'
    echo "          file $name.o not found"
    error='6'
  fi

fi

# End of ad3 ---------------------------------------------------------------- #