#!/bin/bash -e
# --------------------------------------------------------------------------- #
# w3_source : Make a FORTRAN source code tar file for a selected WAVEWATCH    #
#             III program and put in a work directory.                        #
#                                                                             #
# use       : w3_source [program [...]]                                       #
#               program: program name(s) of WAVEWATCH III (sub)program(s).    #
#           - Source files and makefile are created in $WWATCH3_TMP.          #
#           - Gzipped tar file (e.g., ww3_grid.tar.gz) is created in          #
#             $WWATCH3_DIR/work.                                              #
#           - $WWATCH3_TMP is cleaned out after tar file is created.          #
#                                                                             #
# make variables:                                                             #
#   The following make variables are used in the created makefile for         #
#   compile settings:                                                         #
#       CC       : C compiler                                                 #
#       CFLAGS   : C compiler options                                         #
#       CPPFLAGS : C preprocessor options (used with both CC and FC)          #
#       FC       : Fortran compiler                                           #
#       FFLAGS   : Fortran compiler options                                   #
#       LDFLAGS  : Linker options                                             #
#       LIBS     : External libraries                                         #
#   No defaults are provided for these compile settings.  The variables       #
#   for which settings are required must be set in the user environment       #
#   when w3_source is invoked.                                                #
#                                                                             #
# error codes : Program ends if error occurs in make_makefile.sh or ad3.      #
#                                                                             #
# programs used :                                                             #
#       make_makefile.sh : Make the makefile.                                 #
#       ad3              : Preprocess ftn source files.                       #
#                                                                             #
#                                                      Hendrik L. Tolman      #
#                                                      May 2009               #
#                                                      Nov 2014               #
#                                                                             #
#    Copyright 2009-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 ID header  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo ''
  echo '               **************************************'
  echo '             ***  making WAVEWATCH III source codes ***'
  echo '               **************************************'
  echo ''

# 1.b Input arguments - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  if test "$#" = '0'
  then
    default_mode=1
    script_args=
  else
    default_mode=0
    script_args="$*"
  fi


# 1.c Get data from setup file - - - - - - - - - - - - - - - - - - - - - - - - 

  source $(dirname $0)/w3_setenv
  main_dir=$WWATCH3_DIR
  temp_dir=$WWATCH3_TMP
  source=$WWATCH3_SOURCE
  list=$WWATCH3_LIST

  echo "Main directory    : $main_dir"
  echo "Scratch directory : $temp_dir"
  echo "Save source codes : $source"
  echo "Save listings     : $list"

# 1.d Check / make directories   - - - - - - - - - - - - - - - - - - - - - - -

  # switch file
  switch_file=$main_dir/bin/switch
  if [ ! -e $switch_file ] || [ ! -r $switch_file ]
  then
    echo ' '
    echo "[ERROR] switch file $switch_file not found"
    echo "        Please run $main_dir/bin/w3_setup <main_dir> -c <comp> -s <switch>"
    exit 1
  fi
  switch_file_old=$main_dir/bin/switch.old
  switches=$(cat $switch_file)


  # work dir
  work_dir=$main_dir/work
  if [ ! -d $work_dir ]
  then
    if [ ! $(mkdir -p $work_dir) ]
    then
      echo ' '
      echo "[ERROR] Directory $work_dir cannot be created"
      echo '        Please check the permissions'
    fi
  fi

  # temp dir
  rm -rf $temp_dir/*


# 1.e Setup suffix list  - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  suffixes="f F f90 F90 c"

# 1.f Setup program lists  - - - - - - - - - - - - - - - - - - - - - - - - - - 

# reg_programs = non-NetCDF programs
  reg_programs="ww3_grid"
  reg_programs="$reg_programs ww3_strt"
  reg_programs="$reg_programs ww3_bound"
  reg_programs="$reg_programs ww3_prep"
  reg_programs="$reg_programs ww3_shel"
  reg_programs="$reg_programs ww3_outf"
  reg_programs="$reg_programs ww3_outp"
  reg_programs="$reg_programs ww3_trck"
  reg_programs="$reg_programs ww3_grib"
  reg_programs="$reg_programs ww3_gspl"
  reg_programs="$reg_programs ww3_gint"
  reg_programs="$reg_programs gx_outf"
  reg_programs="$reg_programs gx_outp"

  if [ -n "`grep TIDE $switch_file`" ]
  then
    reg_programs="$reg_programs ww3_prtide"
  fi

# cdf_programs = NetCDF programs
  cdf_programs="ww3_prnc"
  cdf_programs="$cdf_programs ww3_ounf"
  cdf_programs="$cdf_programs ww3_ounp"
  cdf_programs="$cdf_programs ww3_bounc"
  cdf_programs="$cdf_programs ww3_trnc"

  if [ -n "`grep TRKNC $switch_file`" ]
  then
  cdf_programs="$cdf_programs ww3_systrk"
  else
  reg_programs="$reg_programs ww3_systrk"
  fi

  if [ -n "`grep SCRIPNC $switch_file`" ]
  then
    cdf_programs="$cdf_programs ww3_multi"
    cdf_programs="$cdf_programs ww3_multi_esmf"
    cdf_programs="$cdf_programs ww3_sbs1"
  else
    reg_programs="$reg_programs ww3_multi"
    reg_programs="$reg_programs ww3_multi_esmf"
    reg_programs="$reg_programs ww3_sbs1"
  fi

# all_programs = all possible programs
  all_programs="$reg_programs $cdf_programs"

# progs = programs requested to compile
  if [ $default_mode -eq 1 ]
  then
    progs="$all_programs"
  else
    progs="$script_args"
  fi


# 1.g Prepare makefile - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo 'Making main makefile ...'
  cd $main_dir
  if $main_dir/bin/make_makefile.sh
  then
    \cp -f $switch_file $switch_file_old
  else
    exit 1
  fi
  echo ''
  main_makefile=$main_dir/ftn/makefile

# 1.h Define some useful functions - - - - - - - - - - - - - - - - - - - - - -

# get make dependencies
  get_depend () {
    file=$1
    make=$2
    # get target line(s)
    target=$(awk \
      'BEGIN { found=0 ; value="" } \
         /^[[:blank:]]*\@\$\(aPb\)\/ad3[[:blank:]]?'$file'/ { print value ; exit 0 } \
         /^[[:blank:]]*\$\(aPo\)\/'$file'\.o[[:blank:]]*\:/ { found=1 } \
         { if (found==1) value=(value $0) } \
       END { if (found==0) {print "'$file' target not found"; exit 1} }' \
       $make 2>&1 || return 1) || { echo "awk for $file target failed"; return 1; }
    # get dependency list
    depend=$(echo "$target" | \
      sed -e 's/^[[:blank:]]*$(aPo)\/'$file'.o[[:blank:]]*:[[:blank:]]*//g' \
          -e 's/$(aPo)\///g' -e 's/SCRIP\///g' -e 's/ftn/F90/g' -e 's/\\//g' \
      2>&1 || return 1) || { echo "sed for $file target failed"; return 1; }
    # echo w/o quotes to get rid of all extra whitespace
    echo $depend
    return 0
  }

# check make variable and issue warning
  check_make_variable () {
    nam=$1
    val=$2
    if [ -z "$val" ]
    then
      echo "*** WARNING ***  make variable not set: $nam"
    fi
  }

# --------------------------------------------------------------------------- #
# 2. Make code for all requests                                               #
# --------------------------------------------------------------------------- #

# 2.a Loop over all requests - - - - - - - - - - - - - - - - - - - - - - - - -

  for prog in $progs
  do
    echo ''
    echo "Processing $prog"
    echo '-----------------------'
    echo ''
    tarfile=$work_dir/$prog.tar.gz
    cd $main_dir

# 2.b Get file list from makefile  - - - - - - - - - - - - - - - - - - - - - - 

    set `grep "link $prog" $main_makefile`
    until [ "$1" = "$prog" ]
    do
      shift
    done
    files=$*
    srcs=
    incs="w3macros.h"

# 2.c Run ad3 to generate source files - - - - - - - - - - - - - - - - - - - - 

    for file in $files
    do
      if ${main_dir}/bin/ad3 $file 0 1
      then
        fext=none
        for s in $suffixes
        do
          if [ -f $temp_dir/$file.$s ]
          then
            fext=$s
            break
          fi
        done
        if [ "$fext" = 'none' ]
        then
          echo "Source file $temp_dir/$file.* not found"
          echo "Source file suffixes checked: $suffixes"
          exit 1
        fi
        if [ -z "$srcs" ]
        then
          srcs="$file.$fext"
        else
          srcs="$srcs $file.$fext"
        fi
      else
        exit 1
      fi
    done

# 2.d Copy include files - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    for inc in $incs
    do
      if [ -e $main_dir/ftn/$inc ]
      then
        \cp -f $main_dir/ftn/$inc $temp_dir/.
      else
        echo "Include file $main_dir/ftn/$inc not found"
        exit 1
      fi
    done

# 2.e Create makefile  - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    cd $temp_dir
    \rm -f makefile
    touch makefile

    echo '########################################################'>> makefile
    echo "PROGRAM  = $prog"                                        >> makefile
    echo '########################################################'>> makefile
    echo ''                                                        >> makefile
    echo 'SHELL    = /bin/sh'                                      >> makefile
    echo ''                                                        >> makefile
    echo "CC       = $CC"                                          >> makefile
    echo "CFLAGS   = $CFLAGS"                                      >> makefile
    echo "CPPFLAGS = $CPPFLAGS"                                    >> makefile
    echo "FC       = $FC"                                          >> makefile
    echo "FFLAGS   = $FFLAGS"                                      >> makefile
    echo "LDFLAGS  = $LDFLAGS"                                     >> makefile
    echo "LIBS     = $LIBS"                                        >> makefile
    echo ''                                                        >> makefile
    echo "INCS     = $incs"                                        >> makefile
    echo "SRCS     = $srcs"                                        >> makefile
    echo 'OBJS     = $(addsuffix .o, $(basename $(SRCS)))'         >> makefile
    echo ''                                                        >> makefile
    echo "SWITCHES = $switches"                                    >> makefile
    echo ''                                                        >> makefile
    echo '########################################################'>> makefile
    echo '# targets'                                               >> makefile
    echo '########################################################'>> makefile
    echo 'default : $(PROGRAM)'                                    >> makefile
    echo ''                                                        >> makefile
    echo '$(PROGRAM) : $(OBJS)'                                    >> makefile
    echo '	$(FC) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS)'    >> makefile
    echo ''                                                        >> makefile
    echo 'clean :'                                                 >> makefile
    echo '	\rm -f *.o *.mod'                                  >> makefile
    echo ''                                                        >> makefile
    echo '########################################################'>> makefile
    echo '# compile rules'                                         >> makefile
    echo '########################################################'>> makefile
    echo '.SUFFIXES : .f .f90 .F .F90 .c'                          >> makefile
    echo ''                                                        >> makefile
    echo '%.o : %.c'                                               >> makefile
    echo '	$(CC) -c $(CFLAGS) $<'                             >> makefile
    echo ''                                                        >> makefile
    echo '%.o : %.f90'                                             >> makefile
    echo '	$(FC) -c $(FFLAGS) $<'                             >> makefile
    echo ''                                                        >> makefile
    echo '%.o : %.F90'                                             >> makefile
    echo '	$(FC) -c $(FFLAGS) $<'                             >> makefile
    echo ''                                                        >> makefile
    echo '%.o : %.f'                                               >> makefile
    echo '	$(FC) -c $(FFLAGS) $<'                             >> makefile
    echo ''                                                        >> makefile
    echo '%.o : %.F'                                               >> makefile
    echo '	$(FC) -c $(FFLAGS) $<'                             >> makefile
    echo ''                                                        >> makefile
    echo '########################################################'>> makefile
    echo '# dependencies'                                          >> makefile
    echo '########################################################'>> makefile
    for file in $files
    do
      target="$file.o"
      depend=$(get_depend $file $main_makefile || return 1) || exit 1
      echo ''                                                      >> makefile
      echo "$target : $depend"                                     >> makefile
    done

# 2.f Create tarfile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    echo ''
    echo "Create tarfile: $tarfile"
    tar -czf $tarfile $srcs $incs makefile
    \rm -f $srcs $incs makefile

# 2.g End loop over all requests - - - - - - - - - - - - - - - - - - - - - - -

  done
  echo ''

# 2.h Check make variables and print warnings  - - - - - - - - - - - - - - - -

  check_make_variable CC       "$CC"
  check_make_variable CFLAGS   "$CFLAGS"
  check_make_variable CPPFLAGS "$CPPFLAGS"
  check_make_variable FC       "$FC"
  check_make_variable FFLAGS   "$FFLAGS"
  check_make_variable LDFLAGS  "$LDFLAGS"
  check_make_variable LIBS     "$LIBS"


# --------------------------------------------------------------------------- #
# 3. End of program ID.                                                       #
# --------------------------------------------------------------------------- #

  echo ''
  echo '                  *********************************'
  echo '                *** end of source code generation ***'
  echo '                  *********************************'
  echo ''

# End of w3_source ---------------------------------------------------------- #
