#! /usr/bin/env bash
#
# $Header: /u/gcmpack/MITgcm/tools/genmake2,v 1.74 2004/03/24 17:12:51 adcroft Exp $
#
# Makefile generator for MITgcm UV codes
#   created  by cnh 03/98
#   adapted  by aja 06/98
#   modified by aja 01/00
#   rewritten in bash by eh3 08/03

# Search for particular CPP #cmds associated with packages
# usage: test_for_package_in_cpp_options CPP_file package_name
test_for_package_in_cpp_options() {
    cpp_options=$1
    pkg=$2
    test_for_string_in_file $cpp_options "^[ ]*#define.*ALLOW_$pkg" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#undef.*ALLOW_$pkg" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#define.*DISABLE_$pkg" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#undef.*DISABLE_$pkg" || exit 99
}

# Search for particular CPP #cmds associated with MPI
# usage: test_for_mpi_in_cpp_eeoptions CPP_file
test_for_mpi_in_cpp_eeoptions() {
    cpp_options=$1
    test_for_string_in_file $cpp_options "^[ ]*#define.*ALLOW_USE_MPI" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#undef.*ALLOW_USE_MPI" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#define.*ALWAYS_USE_MPI" || exit 99
    test_for_string_in_file $cpp_options "^[ ]*#undef.*ALWAYS_USE_MPI" || exit 99
}

# Search for particular string in a file. Return 1 if detected, 0 if not
# usage: test_for_string_in_file file string
test_for_string_in_file() {
    file=$1
    strng=$2
    grep -i "$strng" $file > /dev/null 2>&1
    RETVAL=$?
    if test "x${RETVAL}" = x0 ; then
	printf "Error: In $file there is an illegal line: "
        grep -i "$strng" $file
	return 1
    fi
    return 0
}

# Read the $ROOTDIR/pkg/pkg_groups file and expand any references to
# the package list.
expand_pkg_groups() {
    new_packages=
    PKG_GROUPS=$ROOTDIR"/pkg/pkg_groups"
    if test -r $PKG_GROUPS ; then
	cat $PKG_GROUPS | sed -e 's/#.*$//g' | sed -e 's/:/ : /g' > ./p1.tmp
	cat ./p1.tmp | $AWK '(NF>2 && $2==":"){ print $0 }' > ./p2.tmp
	matched=0
	for i in $PACKAGES ; do
	    line=`grep "^ *$i" ./p2.tmp`
	    RETVAL=$?
	    if test "x$RETVAL" = x0 ; then
		matched=1
		replace=`echo $line | $AWK '{ $1=""; $2=""; print $0 }'`
		echo "    replacing \"$i\" with: $replace"
		new_packages="$new_packages $replace"
	    else
		new_packages="$new_packages $i"
	    fi
	done
	PACKAGES=$new_packages
	rm -f ./p[1,2].tmp
	return $matched
    else
	echo "Warning: can't read package groups definition file: $PKG_GROUPS"
    fi
}

# Guess possible config options for this host
find_possible_configs()  {

    tmp1=`uname`"_"`uname -m`
    tmp2=`echo $tmp1 | sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
    tmp3=`echo $tmp2 | sed -e 's/power macintosh/ppc/'`
    tmp1=`echo $tmp3 | sed -e 's|x86_64|amd64|'`
    tmp2=`echo $tmp1 | sed -e 's/i[3-6]86/ia32/' | sed -e 's/athlon/ia32/'`
    tmp3=`echo $tmp2 | sed -e 's/cray sv1/craysv1/'`
    PLATFORM=$tmp3
    OFLIST=`(cd $ROOTDIR/tools/build_options; ls | grep "^$PLATFORM")`
    echo "  The platform appears to be:  $PLATFORM"
    
    echo "test" > test
    ln -s ./test link
    RETVAL=$?
    if test "x${RETVAL}" = x0 ; then
	LN="ln -s"
    else
	echo "Error: \"ln -s\" does not appear to work on this system!"
	echo "  For help, please contact <MITgcm-support@mitgcm.org>."
	exit 1
    fi
    rm -f test link

    if test "x$CPP" = x ; then
	CPP="cpp -traditional -P"
    fi

    #  The "original" makedepend is part of the Imake system that is
    #  most often distributed with XFree86 or with an XFree86 source
    #  package.  As a result, many machines (eg. generic Linux) do not
    #  have a system-default "makedepend" available.  For those
    #  systems, we have two fall-back options:
    #
    #    1) a makedepend implementation shipped with the cyrus-imapd
    #       package:  ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/
    #
    #    2) a known-buggy xmakedpend shell script
    #
    #  So the choices are, in order:
    #
    #    1) use the user-specified program
    #    2) use a system-wide default
    #    3) locally build and use the cyrus implementation
    #    4) fall back to the buggy local xmakedpend script
    #
    if test "x${MAKEDEPEND}" = x ; then
      which makedepend > /dev/null 2>&1
      RETVAL=$?
      if test ! "x${RETVAL}" = x0 ; then
         echo "    a system-default makedepend was not found."

	 #  Try to build the cyrus impl
	 rm -f ./genmake_cy_md
	 (
	     cd $ROOTDIR/tools/cyrus-imapd-makedepend  \
		 &&  ./configure > /dev/null 2>&1  \
		 &&  make > /dev/null 2>&1  \
		 &&  ./makedepend ifparser.c > /dev/null 2>&1  \
		 &&  echo "true"
	 ) > ./genmake_cy_md
	 grep true ./genmake_cy_md > /dev/null 2>&1
	 RETVAL=$?
	 if test "x$RETVAL" = x0 ; then
	     MAKEDEPEND='$(TOOLSDIR)/cyrus-imapd-makedepend/makedepend'
	 else
	     MAKEDEPEND='$(TOOLSDIR)/xmakedepend'
	 fi
	 rm -f ./genmake_cy_md
      fi
    fi

    # look for possible fortran compilers
    tmp="$MITGCM_FC $FC efc g77 f77 pgf77 pgf95 ifc f90 f95 mpif77 mpf77 mpxlf95"
    p_FC=
    for c in $tmp ; do
	rm -f ./hello.f ./hello
	cat >> hello.f <<EOF
      program hello
      do i=1,3
        print *, 'hello world : ', i
      enddo
      end
EOF
	$c -o hello hello.f > /dev/null 2>&1
	RETVAL=$?
	if test "x${RETVAL}" = x0 ; then
	    p_FC="$p_FC $c"
	fi
    done
    rm -f ./hello.f ./hello
    if test "x${p_FC}" = x ; then
	cat 1>&2 <<EOF

Error: No Fortran compilers were found in your path.  Please specify one using:

    1) an "optfile" on (eg. "-optfile=path/to/OPTFILE"),
    2) a command-line option (eg. "-fc NAME"), or
    3) the MITGCM_FC environment variable.

EOF
	exit 1
    else
	echo "  The possible FORTRAN compilers found in your path are:"
	echo "   "$p_FC
	if test "x$FC" = x ; then
	    FC=`echo $p_FC | $AWK '{print $1}'`
	    echo "  Setting FORTRAN compiler to: "$FC
	fi
    fi

    if test "x$OPTFILE" = x ; then
	OPTFILE=$ROOTDIR"/tools/build_options/"$PLATFORM"_"$FC
	if test ! -r $OPTFILE ; then
             echo "  I looked for the file "$OPTFILE" but did not find it"
        fi
    fi
#    echo "  The options file:  $p_OF"
#    echo "    appears to match so we'll use it."
#   for i in $p_FC ; do
#p_OF=$ROOTDIR"/tools/build_options/"$PLATFORM"_"$i
#if test -r $p_OF ; then
#    OPTFILE=$p_OF
#    echo "  The options file:  $p_OF"
#    echo "    appears to match so we'll use it."
#    break
#fi
#   done
    if test "x$OPTFILE" = x ; then
	cat 1>&2 <<EOF

Error: No options file was found in:  $ROOTDIR/tools/build_options/
  that matches this platform ("$PLATFORM") and the compilers found in
  your path.  Please specify an "optfile" using:

    1) the command line (eg. "-optfile=path/to/OPTFILE"), or
    2) the MITGCM_OF environment variable.

  If you need help, please contact the developers at <MITgcm-support@mitgcm.org>.

EOF
	exit 1
    fi
    
#     # look for possible MPI libraries
#     mpi_libs=
#     mpi_fort=`which mpif77 2>/dev/null`
#     RETVAL=$?
#     if test "x${RETVAL}" = x0 ; then
# 	cat >>test.f <<EOF
#       PROGRAM HELLO
#       DO 10, I=1,10
#       PRINT *,'Hello World'
#    10 CONTINUE
#       STOP
#       END
# EOF
# 	eval "$mpi_fort -showme test.f > out"
# 	RETVAL=$?
# 	if test "x${RETVAL}" = x0 ; then
# 	    a=`cat out`
# 	    for i in $a ; do
# 		case $i in 
# 		    -*)
# 			mpi_libs="$mpi_libs $i" ;;
# 		esac
# 	    done
# 	    echo "The MPI libs appear to be:"
# 	    echo "  "$mpi_libs
# 	fi
# 	rm -f test.f out
#     fi

}

#  Parse the package dependency information
get_pdepend_list()  {

    #  strip the comments and then convert the dependency file into
    #  two arrays: PNAME, DNAME
    cat $1 | sed -e 's/#.*$//g' \
	| $AWK 'BEGIN{nn=0;} (NF>0){ for(i=2;i<=NF;i++){nn++; print "PNAME["nn"]="$1"\nDNAME["nn"]="$i} }' \
	> ./.pd_tmp
    . ./.pd_tmp
    rm -f ./.pd_tmp

    printf "PNAME = "${}
}


#  Explain usage
usage()  {
cat <<EOF

Usage: "$0" [OPTIONS]
  where [OPTIONS] can be:

    -help | --help | -h | --h
          Print this help message and exit.

    -nooptfile | --nooptfile
      -optfile NAME | --optfile NAME | -of NAME | --of NAME
      -optfile=NAME | --optfile=NAME | -of=NAME | --of=NAME
          Use "NAME" as the optfile.  By default, an attempt will be
          made to find an appropriate "standard" optfile in the 
          tools/build_options/ directory.

    -pdepend NAME | --pdepend NAME
      -pdepend=NAME | --pdepend=NAME
          Get package dependency information from "NAME".

    -pdefault NAME | --pdefault NAME
      -pdefault=NAME | --pdefault=NAME
          Get the default package list from "NAME".

    -make NAME | -m NAME
      --make=NAME | -m=NAME
          Use "NAME" for the MAKE program. The default is "make" but 
          many platforms, "gmake" is the preferred choice.

    -makefile NAME | -mf NAME
      --makefile=NAME | -mf=NAME
          Call the makefile "NAME".  The default is "Makefile".

    -makedepend NAME | -md NAME
      --makedepend=NAME | -md=NAME
          Use "NAME" for the MAKEDEPEND program.

    -rootdir NAME | --rootdir NAME | -rd NAME | --rd NAME
      -rootdir=NAME | --rootdir=NAME | -rd=NAME | --rd=NAME
          Specify the location of the MITgcm ROOTDIR as "NAME".
          By default, genamke will try to find the location by 
          looking in parent directories (up to the 5th parent).

    -mods NAME | --mods NAME | -mo NAME | --mo NAME
      -mods=NAME | --mods=NAME | -mo=NAME | --mo=NAME
          Here, "NAME" specifies a list of directories that are 
          used for additional source code.  Files found in the 
          "mods list" are given preference over files of the same 
          name found elsewhere.

    -disable NAME | --disable NAME
      -disable=NAME | --disable=NAME
          Here "NAME" specifies a list of packages that we don't 
          want to use.  If this violates package dependencies, 
          genamke will exit with an error message.

    -enable NAME | --enable NAME
      -enable=NAME | --enable=NAME
          Here "NAME" specifies a list of packages that we wish 
          to specifically enable.  If this violates package 
          dependencies, genamke will exit with an error message.

    -standarddirs NAME | --standarddirs NAME
      -standarddirs=NAME | --standarddirs=NAME
          Here, "NAME" specifies a list of directories to be 
          used as the "standard" code.

    -fortran NAME | --fortran NAME | -fc NAME | --fc NAME
      -fc=NAME | --fc=NAME
          Use "NAME" as the fortran compiler.  By default, genmake 
          will search for a working compiler by trying a list of
          "usual suspects" such as g77, f77, etc.

    -[no]ieee | --[no]ieee
          Do or don't use IEEE numerics.  Note that this option 
          *only* works if it is supported by the OPTFILE that 
          is being used.

    -mpi | --mpi
          Include MPI header files and link to MPI libraries
    -mpi=PATH | --mpi=PATH
          Include MPI header files and link to MPI libraries using MPI_ROOT
          set to PATH. i.e. Include files from $PATH/include, link to libraries
          from $PATH/lib and use binaries from $PATH/bin.

    -bash NAME
          Explicitly specify the Bourne or BASH shell to use

  While it is most often a single word, the "NAME" variables specified 
  above can in many cases be a space-delimited string such as:

    --enable pkg1   --enable 'pkg1 pkg2'   --enable 'pkg1 pkg2 pkg3'
    -mods=dir1   -mods='dir1'   -mods='dir1 dir2 dir3'
    -foptim='-Mvect=cachesize:512000,transform -xtypemap=real:64,double:64,integer:32'

  which, depending upon your shell, may need to be single-quoted.

  For more detailed genmake documentation, please see:

    http://mitgcm.org/devel_HOWTO/

EOF

    exit 1
}

#  Build a CPP macro to automate calling C routines from FORTRAN
get_fortran_c_namemangling()  {
    default_nm="#define FC_NAMEMANGLE(X) X ## _"
    
    cat > genmake_test.c <<EOF
void tcall( char * string ) { tsub( string ); }
EOF
    $MAKE genmake_test.o >> genmake_warnings 2>&1
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	FC_NAMEMANGLE=$default_nm
	cat <<EOF>> genmake_errors

WARNING: C test compile fails
WARNING: We'll try to use: FC_NAMEMANGLE='$FC_NAMEMANGLE'
WARNING: Please contact <MITgcm-support@mitgcm.org> if you need help here
EOF
	return 1
    fi
    c_tcall=`nm genmake_test.o | grep 'T ' | grep tcall | cut -d ' ' -f 3`
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	FC_NAMEMANGLE=$default_nm
	cat <<EOF>> genmake_warnings

WARNING: The "nm" command failed.
WARNING: We'll try to use: FC_NAMEMANGLE='$FC_NAMEMANGLE'
WARNING: Please contact <MITgcm-support@mitgcm.org> if you need help here
EOF
	return 1
    fi
    cat > genmake_tcomp.f <<EOF
      subroutine tcall( string )
      character*(*) string
      call tsub( string )
      end
EOF
    $FC $FFLAGS $DEFINES -c genmake_tcomp.f >> genmake_warnings 2>&1
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	FC_NAMEMANGLE=$default_nm
	cat <<EOF>> genmake_warnings

WARNING: FORTRAN test compile fails -- please see "genmake_errors"
WARNING: We'll try to use: FC_NAMEMANGLE='$FC_NAMEMANGLE'
WARNING: Please contact <MITgcm-support@mitgcm.org> if you need help here.
EOF
	return 1
    fi
    f_tcall=`nm genmake_tcomp.o | grep 'T ' | grep tcall | cut -d ' ' -f 3`
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	FC_NAMEMANGLE=$default_nm
	cat <<EOF>> genmake_warnings

WARNING: The "nm" command failed.
WARNING: We'll try to use: FC_NAMEMANGLE='$FC_NAMEMANGLE'
WARNING: Please contact <MITgcm-support@mitgcm.org> if you need help here.
EOF
	return 1
    fi

    c_a=`echo $c_tcall | sed -e 's|tcall|Y Y|' | cut -d ' ' -f 1 | sed -e 's|Y||'`
    f_a=`echo $f_tcall | sed -e 's|tcall|Y Y|' | cut -d ' ' -f 1 | sed -e 's|Y||'`
    c_b=`echo $c_tcall | sed -e 's|tcall|Y Y|' | cut -d ' ' -f 2 | sed -e 's|Y||'`
    f_b=`echo $f_tcall | sed -e 's|tcall|Y Y|' | cut -d ' ' -f 2 | sed -e 's|Y||'`

    nmangle="X"
    if test "x$c_a" != "x$f_a" ; then
	comm="echo x$f_a | sed -e 's|x$c_a||'"
	a=`eval $comm`
	nmangle="$a ## $nmangle"
    fi
    if test "x$c_b" != "x$f_b" ; then
	comm="echo x$f_b | sed -e 's|x$c_b||'"
	b=`eval $comm`
	nmangle="$nmangle ## $b"
    fi

    FC_NAMEMANGLE="#define FC_NAMEMANGLE(X)  $nmangle"

    #  cleanup the testing files
    rm -f genmake_tcomp.* genmake_test.*
}


check_HAVE_CLOC()  {
    get_fortran_c_namemangling
    cat <<EOF > genmake_tc_1.c
$FC_NAMEMANGLE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/time.h>
void FC_NAMEMANGLE(cloc) ( double *curtim )
{
 struct timeval tv1;
 gettimeofday(&tv1 , (void *)NULL );
 *curtim =  (double)((tv1.tv_usec)+(tv1.tv_sec)*1.E6);
 *curtim = *curtim/1.E6;
}
EOF
    make genmake_tc_1.o >> genmake_tc.log 2>&1
    RET_C=$?
    cat <<EOF > genmake_tc_2.f
      program hello
      Real*8 wtime
      external cloc
      call cloc(wtime)
      print *," HELLO WORLD", wtime
      end program hello
EOF
    $FC $FFLAGS -o genmake_tc genmake_tc_2.f genmake_tc_1.o >> genmake_tc.log 2>&1
    RET_F=$?
    test -x ./genmake_tc  &&  ./genmake_tc >> genmake_tc.log 2>&1
    RETVAL=$?
    if test "x$RETVAL" = x0 ; then
	HAVE_CLOC=t
	DEFINES="$DEFINES -DHAVE_CLOC"
    fi
    rm -f genmake_tc*
}


check_netcdf_libs()  {
    cat <<EOF > genmake_tnc.F
      program fgennc
#include "netcdf.inc"
      integer iret, ncid, xid
      iret = nf_create('genmake_tnc.nc', NF_CLOBBER, ncid)
      IF (iret .NE. NF_NOERR) write(*,*) NF_STRERROR(iret)
      iret = nf_def_dim(ncid, 'X', 11, xid)
      IF (iret .NE. NF_NOERR) write(*,*) NF_STRERROR(iret)
      iret = nf_close(ncid)
      IF (iret .NE. NF_NOERR) write(*,*) NF_STRERROR(iret)
      end
EOF
    $CPP genmake_tnc.F > genmake_tnc.f  \
	&&  $FC $FFLAGS $FOPTIM -o genmake_tnc genmake_tnc.f $LIBS >> genmake_tnc.log 2>&1
    RET_COMPILE=$?
    test -x ./genmake_tnc  &&  ./genmake_tnc >> genmake_tnc.log 2>&1
    RETVAL=$?
    if test "x$RET_COMPILE" = x0 -a "x$RETVAL" = x0 ; then
	HAVE_NETCDF=t
    else
	# try again with "-lnetcdf" added to the libs
	$CPP genmake_tnc.F > genmake_tnc.f  \
	    &&  $FC $FFLAGS $FOPTIM -o genmake_tnc genmake_tnc.f \
	    $LIBS -lnetcdf >> genmake_tnc_2.log 2>&1
	RET_COMPILE=$?
	test -x ./genmake_tnc  &&  ./genmake_tnc >> genmake_tnc.log 2>&1
	RETVAL=$?
	if test "x$RET_COMPILE" = x0 -a "x$RETVAL" = x0 ; then
	    LIBS="$LIBS -lnetcdf"
	    HAVE_NETCDF=t
	else
	    cat genmake_tnc.log >> genmake_warnings
	fi
    fi
    rm -f genmake_tnc*
}



###############################################################################
#   Sequential part of script starts here
###############################################################################

#  Set defaults here
COMMANDL="$0 $@"

PLATFORM=
LN=
S64=
KPP=
FC=
CPP=
LINK=
DEFINES=
PACKAGES=
ENABLE=
DISABLE=
MAKEFILE=
MAKEDEPEND=
PDEPEND=
DUMPSTATE=t
PDEFAULT=
OPTFILE=
INCLUDES="-I."
FFLAGS=
FOPTIM=
CFLAGS=
KFLAGS1=
KFLAGS2=
#LDADD=
LIBS=
KPPFILES=
NOOPTFILES=
NOOPTFLAGS=
MPI=
MPIPATH=

# DEFINES checked by test compilation
HAVE_SYSTEM=
HAVE_FDATE=
FC_NAMEMANGLE=
HAVE_CLOC=
HAVE_NETCDF=

MODS=
TOOLSDIR=
SOURCEDIRS=
INCLUDEDIRS=
STANDARDDIRS="USE_THE_DEFAULT"

G2ARGS=
BASH=
PWD=`pwd`
MAKE=make
AWK=awk
THISHOSTNAME=`hostname`
THISCWD=`pwd`
THISDATE=`date`
MACHINE=`uname -a`
EXECUTABLE=
EXEHOOK=
EXEDIR=
PACKAGES_CONF=
IEEE=
if test "x$MITGCM_IEEE" != x ; then
    IEEE=$MITGCM_IEEE
fi

AUTODIFF_PKG_USED=f
AD_OPTFILE=
TAF=
AD_TAF_FLAGS=
FTL_TAF_FLAGS=
SVD_TAF_FLAGS=
TAF_EXTRA=
TAMC=
AD_TAMC_FLAGS=
FTL_TAF_FLAGS=
SVD_TAMC_FLAGS=
TAMC_EXTRA=


#  The following state can be set directly by command-line switches
gm_s1="OPTFILE PDEPEND PDEFAULT MAKEFILE PLATFORM ROOTDIR MODS DISABLE ENABLE"
gm_s2="FC CPP IEEE MPI JAM DUMPSTATE STANDARDDIRS"

#  The following state is not directly set by command-line switches
gm_s3="LN S64 KPP LINK PACKAGES MAKEDEPEND PDEPEND PDEFAULT INCLUDES FFLAGS FOPTIM "
gm_s4="CFLAGS KFLAGS1 KFLAGS2 LIBS KPPFILES NOOPTFILES NOOPTFLAGS"
gm_s5="TOOLSDIR SOURCEDIRS INCLUDEDIRS PWD MAKE THISHOSTNAME THISDATE MACHINE"
gm_s6="EXECUTABLE EXEHOOK EXEDIR PACKAGES_CONF"
gm_s7="HAVE_SYSTEM HAVE_FDATE FC_NAMEMANGLE"

#  The following are all related to adjoint/tangent-linear stuff
gm_s10="AUTODIFF_PKG_USED AD_OPTFILE TAMC TAF AD_TAMC_FLAGS AD_TAF_FLAGS"
gm_s11="FTL_TAMC_FLAGS FTL_TAF_FLAGS SVD_TAMC_FLAGS SVD_TAF_FLAGS"
gm_s12="TAF_EXTRA TAMC_EXTRA"

gm_state="COMMANDL $gm_s1 $gm_s2 $gm_s3 $gm_s4 $gm_s5 $gm_s6 $gm_s7"
gm_state="$gm_state $gm_s10 $gm_s11 $gm_s12"

cat <<EOF

GENMAKE :

A program for GENerating MAKEfiles for the MITgcm project.  For a
quick list of options, use "genmake -h" or for more detail see:

  http://mitgcm.org/devel_HOWTO/

EOF

echo "===  Processing options files and arguments  ==="
gm_local="genmake_local"
for i in . $MODS ; do
    if test -r $i/$gm_local ; then
	. $i/$gm_local
	break
    fi
done
printf "  getting local config information:  "
if test -e $gm_local ; then
    echo "using $gm_local"
    . $gm_local
    # echo "DISABLE=$DISABLE"
    # echo "ENABLE=$ENABLE"
else
    echo "none found"
fi

#  echo "$0::$1:$2:$3:$4:$5:$6:$7:"
#OPTIONS=
#n=0
#for i ; do 
#   echo "$i  $n"
#   setvar="OPTIONS[$n]='$i'"
#   #  echo "  $setvar"
#   eval "$setvar"
#   n=$(( $n + 1 ))
#done
#parse_options
ac_prev=
for ac_option ; do

    G2ARGS="$G2ARGS \"$ac_option\""

    # If the previous option needs an argument, assign it.
    if test -n "$ac_prev"; then
	eval "$ac_prev=\$ac_option"
	ac_prev=
	continue
    fi
    
    ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
    
    case $ac_option in
	
	-help | --help | -h | --h)
	    usage ;;
	
	-nooptfile | --nooptfile)
	    OPTFILE="NONE" ;;
	-optfile | --optfile | -of | --of)
	    ac_prev=OPTFILE ;;
	-optfile=* | --optfile=* | -of=* | --of=*)
	    OPTFILE=$ac_optarg ;;
	
	-adoptfile | --adoptfile | -adof | --adof)
	    ac_prev=AD_OPTFILE ;;
	-adoptfile=* | --adoptfile=* | -adof=* | --adof=*)
	    AD_OPTFILE=$ac_optarg ;;
	
	-pdepend | --pdepend)
	    ac_prev=PDEPEND ;;
	-pdepend=* | --pdepend=*)
	    PDEPEND=$ac_optarg ;;
	
	-pdefault | --pdefault)
	    ac_prev=PDEFAULT ;;
	-pdefault=* | --pdefault=*)
	    PDEFAULT=$ac_optarg ;;
	
	-make | --make | -m | --m)
	    ac_prev=MAKE ;;
	-make=* | --make=* | -m=* | --m=*)
	    MAKE=$ac_optarg ;;
	
	-bash | --bash)
	    ac_prev=BASH ;;
	-bash=* | --bash=*)
	    BASH=$ac_optarg ;;
	
	-makedepend | --makedepend | -md | --md)
	    ac_prev=MAKEDEPEND ;;
	-makedepend=* | --makedepend=* | -md=* | --md=*)
	    MAKEDEPEND=$ac_optarg ;;
	
	-makefile | --makefile | -ma | --ma)
	    ac_prev=MAKEFILE ;;
	-makefile=* | --makefile=* | -ma=* | --ma=*)
	    MAKEFILE=$ac_optarg ;;
	
	-platform | --platform | -pl | --pl | -platform=* | --platform=* | -pl=* | --pl=*)
	    echo "ERROR: The platform option has been removed.  Please specify"
	    echo "  the build options using the \"optfile\" mechanism."
	    echo
	    usage
	    ;;
	
	-rootdir | --rootdir | -rd | --rd)
	    ac_prev=ROOTDIR ;;
	-rootdir=* | --rootdir=* | -rd=* | --rd=*)
	    ROOTDIR=$ac_optarg ;;
	
	-mods | --mods | -mo | --mo)
	    ac_prev=MODS ;;
	-mods=* | --mods=* | -mo=* | --mo=*)
	    MODS=$ac_optarg ;;
	
	-disable | --disable)
	    ac_prev=DISABLE ;;
	-disable=* | --disable=*)
	    DISABLE=$ac_optarg ;;
	
	-enable | --enable)
	    ac_prev=ENABLE ;;
	-enable=* | --enable=*)
	    ENABLE=$ac_optarg ;;
	
	-standarddirs | --standarddirs)
	    ac_prev=STANDARDDIRS ;;
	-standarddirs=* | --standarddirs=*)
	    STANDARDDIRS=$ac_optarg ;;

#	    -cpp | --cpp)
#		ac_prev=cpp ;;
#	    -cpp=* | --cpp=*)
#		CPP=$ac_optarg ;;
	    
	-fortran | --fortran | -fc | --fc)
	    ac_prev=FC ;;
	-fc=* | --fc=*)
	    FC=$ac_optarg ;;
	
	-ieee | --ieee)
	    IEEE=true ;;
	-noieee | --noieee)
	    IEEE= ;;

	-mpi | --mpi)
	    MPI=true ;;
	-mpi=* | --mpi=*)
	    MPIPATH=$ac_optarg
	    MPI=true ;;
	
#	-jam | --jam)
#	    JAM=1 ;;
#	-nojam | --nojam)
#	    JAM=0 ;;
	
	-ds | --ds)
	    DUMPSTATE=t ;;
	
	-taf_extra | --taf_extra)
	    ac_prev=TAF_EXTRA ;;
	-taf_extra=* | --taf_extra=*)
	    TAF_EXTRA=$ac_optarg ;;

	-tamc_extra | --tamc_extra)
	    ac_prev=TAMC_EXTRA ;;
	-tamc_extra=* | --tamc_extra=*)
	    TAMC_EXTRA=$ac_optarg ;;

	-*)
	    echo "Error: unrecognized option: "$ac_option
	    usage
	    ;;
	
	*)
	    echo "Error: unrecognized argument: "$ac_option
	    usage
	    ;;
	
    esac
    
done

if test -f ./.genmakerc ; then
    echo
    echo "WARNING: genmake2 has detected a copy of the old-style \"./.genmakerc\""
    echo "  file.  This file format is no longer supported.  Please see:"
    echo 
    echo "    http://mitgcm.org/devel_HOWTO/"
    echo
    echo "  for directions on how to setup and use the new \"genmake2\" input"
    echo "  files and send an email to MITgcm-support@mitgcm.org if you want help."
    echo 
fi

if test "x${ROOTDIR}" = x ; then
    if test "${PWD##/*/}" = "bin" -a -d ../model -a -d ../eesup -a -d ../pkg ; then
	ROOTDIR=".."
    else
	for d in . .. ../.. ../../.. ../../../.. ../../../../.. ; do
	    if [ -d "$d/model" -a -d "$d/eesupp" -a -d "$d/pkg" ]; then
		ROOTDIR=$d
		printf "Warning:  ROOTDIR was not specified but there appears to be"
		echo " a copy of MITgcm at \"$ROOTDIR\" so we'll try it."
		break
	    fi
	done
    fi
fi
if test "x${ROOTDIR}" = x ; then
    echo "Error: Cannot determine ROOTDIR for MITgcm code."
    echo "  Please specify a ROOTDIR using either an options "
    echo "  file or a command-line option."
    exit 1
fi
if test ! -d ${ROOTDIR} ; then
    echo "Error: the specified ROOTDIR (\"$ROOTDIR\") does not exist!"
    exit 1
fi

echo "  getting OPTFILE information:  "
if test "x${OPTFILE}" = x ; then
    if test "x$MITGCM_OF" = x ; then
	echo "Warning: no OPTFILE specified so we'll look for possible settings"
	printf "\n===  Searching for possible settings for OPTFILE  ===\n"
	find_possible_configs
    else
	OPTFILE=$MITGCM_OF
    fi
fi
if test "x$OPTFILE" != xNONE ; then
    if test -f "$OPTFILE" -a -r "$OPTFILE" ; then
	echo "    using OPTFILE=\"$OPTFILE\""
	. "$OPTFILE"
	RETVAL=$?
	if test "x$RETVAL" != x0 ; then
	    printf "Error: failed to source OPTFILE \"$OPTFILE\""
	    echo "--please check that variable syntax is bash-compatible"
	    exit 1
	fi
	if test "x$DUMPSTATE" != xf ; then
	    cp -f $OPTFILE "genmake_optfile"
	fi
    else
	echo "Error: can't read OPTFILE=\"$OPTFILE\""
	exit 1
    fi
fi

echo "  getting AD_OPTFILE information:  "
if test "x${AD_OPTFILE}" = x ; then
    if test "x$MITGCM_AD_OF" = x ; then
	AD_OPTFILE=$ROOTDIR/tools/adjoint_options/adjoint_default
    else
	AD_OPTFILE=$MITGCM_AD_OF
    fi
fi
if test "x${AD_OPTFILE}" != xNONE ; then
    if test -f "$AD_OPTFILE" -a -r "$AD_OPTFILE" ; then
	echo "    using AD_OPTFILE=\"$AD_OPTFILE\""
	. "$AD_OPTFILE"
	RETVAL=$?
	if test "x$RETVAL" != x0 ; then
	    printf "Error: failed to source AD_OPTFILE \"$AD_OPTFILE\""
	    echo "--please check that variable syntax is bash-compatible"
	    exit 1
	fi
	if test "x$DUMPSTATE" != xf ; then
	    cp -f $AD_OPTFILE "genmake_ad_optfile"
	fi
    else
	echo "Error: can't read AD_OPTFILE=\"$AD_OPTFILE\""
	exit 1
    fi
fi

#  Check that FC, LINK, CPP, S64, LN, and MAKE are defined.  If not,
#  either set defaults or complain and abort!
if test ! "x$BASH" = x ; then
    # add a trailing space so that it works within the Makefile syntax (see below)
    BASH="$BASH "
fi
if test "x$FC" = x ; then
    cat <<EOF 1>&2

Error: no Fortran compiler: please specify using one of the following:
  1) within the options file ("FC=...") as specified by "-of=OPTFILE"
  2) the "-fc=XXX" command-line option
  3) the "./genmake_local" file
EOF
    exit 1
fi
if test "x$LINK" = x ; then
    LINK=$FC
fi
if test "x$MAKE" = x ; then
    MAKE="make"
fi
if test "x$CPP" = x ; then
    CPP=cpp
fi
#EH3 === UGLY ===
#  The following an ugly little hack to check for $CPP in /lib/ and it
#  should eventually be replaced with a more general function that
#  searches a combo of the user's path and a list of "usual suspects"
#  to find the correct location for binaries such as $CPP.
for i in " " "/lib/" ; do
    echo "#define A a" | $i$CPP > test_cpp 2>&1 && CPP=$i$CPP
done
#EH3 === UGLY ===
echo "#define A a" | $CPP > test_cpp 2>&1
RETVAL=$?
if test "x$RETVAL" != x0 ; then
    cat <<EOF 1>&2

Error: C pre-processor "$CPP" failed the test case: please specify using:

  1) within the options file ("CPP=...") as specified by "-of=OPTFILE"
  2) the "./genmake_local" file
  3) with the CPP environment variable

EOF
    exit 1
else
    rm -f test_cpp
fi
if test "x$MAKEDEPEND" = x ; then
    MAKEDEPEND=makedepend
fi
if test "x$LN" = x ; then
    LN="ln -s"
fi
echo "test" > genmake_test_ln
$LN genmake_test_ln genmake_tlink
RETVAL=$?
if test "x$RETVAL" != x0 ; then
    cat <<EOF 1>&2

Error: The command "ln -s" failed -- please specify a working soft-link
  command in the optfile.

EOF
    exit 1
fi
rm -f genmake_test_ln genmake_tlink

if test ! "x$MPI" = x ; then
      echo "  Turning on MPI cpp macros"
      DEFINES="$DEFINES -DALLOW_USE_MPI -DALWAYS_USE_MPI"
fi

printf "\n===  Checking system libraries  ===\n"
printf "  Do we have the system() command using $FC...  "
cat > genmake_tcomp.f <<EOF
      program hello
      call system('echo hi')
      end
EOF
$FC $FFLAGS $DEFINES -o genmake_tcomp genmake_tcomp.f > genmake_tcomp.log 2>&1
RETVAL=$?
if test "x$RETVAL" = x0 ; then
    HAVE_SYSTEM=t
    DEFINES="$DEFINES -DHAVE_SYSTEM"
    echo "yes"
else
    HAVE_SYSTEM=
    echo "no"
fi
rm -f genmake_tcomp*

printf "  Do we have the fdate() command using $FC...  "
cat > genmake_tcomp.f <<EOF
      program hello
      CHARACTER(128) string
      string = ' '
      call fdate( string )
      print *, string
      end
EOF
$FC $FFLAGS $DEFINES -o genmake_tcomp genmake_tcomp.f > genmake_tcomp.log 2>&1
RETVAL=$?
if test "x$RETVAL" = x0 ; then
    HAVE_FDATE=t
    DEFINES="$DEFINES -DHAVE_FDATE"
    echo "yes"
else
    HAVE_FDATE=
    echo "no"
fi
rm -f genmake_tcomp*

printf "  Can we call simple C routines (here, \"cloc()\") using $FC...  "
check_HAVE_CLOC
if test "x$HAVE_CLOC" != x ; then
    echo "yes"
else
    echo "no"
fi
rm -f genmake_t*

printf "  Can we create NetCDF-enabled binaries...  "
check_netcdf_libs
if test "x$HAVE_NETCDF" != x ; then
    echo "yes"
else
    echo "no"
fi


printf "\n===  Setting defaults  ===\n"
printf "  Adding MODS directories:  "
for d in $MODS ; do
    if test ! -d $d ; then
	echo
	echo "Error: MODS directory \"$d\" not found!"
	exit 1
    else
	printf " $d"
	SOURCEDIRS="$SOURCEDIRS $d"
	INCLUDEDIRS="$INCLUDEDIRS $d"
    fi
done
echo

if test "x$MAKEFILE" = x ; then
    MAKEFILE="Makefile"
fi
if test "x${PLATFORM}" = x ; then
    PLATFORM=$p_PLATFORM
fi

if test "x${EXEDIR}" = x ; then
    if test "${PWD##/*/}" = "bin" -a -d ../exe -a $ROOTDIR = .. ; then
	EXEDIR=../exe
    else
	EXEDIR=.
    fi
fi
if test ! -d ${EXEDIR} ; then
    echo "Error:  the specified EXEDIR (\"$EXEDIR\") does not exist!"
    exit 1
fi

if test "x${TOOLSDIR}" = x ; then
    TOOLSDIR="$ROOTDIR/tools"
fi
if test ! -d ${TOOLSDIR} ; then
    echo "Error: the specified TOOLSDIR (\"$TOOLSDIR\") does not exist!"
    exit 1
fi
if test "x$S64" = x ; then
    S64='$(TOOLSDIR)/set64bitConst.sh'
fi
THIS_SCRIPT=`echo ${0} | sed 's:'$TOOLSDIR':\$(TOOLSDIR):'`

EXECUTABLE=${EXECUTABLE:-mitgcmuv}

#  We have a special set of source files in eesupp/src which are
#  generated from some template source files. We'll make them first so
#  they appear as regular source code
if test -r $ROOTDIR"/eesupp/src/Makefile" ; then
    echo "  Making source files in eesupp from templates"
    ( cd $ROOTDIR"/eesupp/src/" && $MAKE ) > make_eesupp.errors 2>&1
    RETVAL=$?
    if test "x${RETVAL}" = x0 ; then
	rm -f make_eesupp.errors
    else
	echo "Error: problem encountered while building source files in eesupp:"
	cat make_eesupp.errors 1>&2
	exit 1
    fi
fi

#same for exch2
if test -r $ROOTDIR"/pkg/exch2/Makefile" ; then
    echo "  Making source files in exch2 from  templates"
    ( cd $ROOTDIR"/pkg/exch2/" && $MAKE ) > make_exch2.errors 2>&1
    RETVAL=$?
    if test "x${RETVAL}" = x0 ; then
        rm -f make_exch2.errors
    else
        echo "Error: problem encountered while building source files in exch2:"
        cat make_exch2.errors 1>&2
        exit 1
    fi
fi

printf "\n===  Determining package settings  ===\n"
if  test "x${PDEPEND}" = x ; then
    tmp=$ROOTDIR"/pkg/pkg_depend"
    if test -r $tmp ; then
	PDEPEND=$tmp
    else
	echo "Warning:  No package dependency information was specified."
	echo "  Please check that ROOTDIR/pkg/pkg_depend exists."
    fi
else
    if test ! -r ${PDEPEND} ; then
	echo "Error:  can't read package dependency info from PDEPEND=\"$PDEPEND\""
	exit 1
    fi
fi
echo "  getting package dependency info from  $PDEPEND"
#  Strip the comments and then convert the dependency file into
#  two arrays: PNAME, DNAME
cat $PDEPEND | sed -e 's/#.*$//g' \
    | $AWK 'BEGIN{nn=-1;} (NF>0){ for(i=2;i<=NF;i++){nn++; print "PNAME_"nn"="$1"\nDNAME_"nn"="$i}} END{print "nname="nn}' \
    > ./.pd_tmp
RETVAL=$?
if test ! "x${RETVAL}" = x0 ; then
    echo "Error: unable to parse package dependencies -- please check PDEPEND=\"$PDEPEND\""
    exit 1
fi
. ./.pd_tmp
rm -f ./.pd_tmp

#  Search for default packages.  Note that a "$ROOTDIR/pkg/pkg_groups"
#  file should eventually be added so that, for convenience, one can 
#  specify groups of packages using names like "ocean" and "atmosphere".
echo "  checking default package list:  "
if test "x${PDEFAULT}" = x ; then
    for i in "." $MODS ; do
	if test -r $i"/packages.conf" ; then
		PDEFAULT=$i"/packages.conf"
		break
	fi
    done
fi
if test "x${PDEFAULT}" = x ; then
    PDEFAULT="$ROOTDIR/pkg/pkg_default"
fi
if test "x${PDEFAULT}" = xNONE ; then
    echo "    default packages file disabled"
else
    if test ! -r $PDEFAULT ; then
	echo "Warning:  can't read default packages from PDEFAULT=\"$PDEFAULT\""
    else
	echo "    using PDEFAULT=\"$PDEFAULT\""
        #  Strip the comments and add all the names
	def=`cat $PDEFAULT | sed -e 's/#.*$//g' | $AWK '(NF>0){print $0}'`
	RETVAL=$?
	if test "x${RETVAL}" != x0 ; then
	    printf "Error: can't parse default package list "
	    echo "-- please check PDEFAULT=\"$PDEFAULT\""
	    exit 1
	fi
	for i in $def ; do
	    PACKAGES="$PACKAGES $i"
	done
	echo "    before group expansion packages are: $PACKAGES"
	while ! expand_pkg_groups; do echo > /dev/null; done
	echo "    after group expansion packages are:  $PACKAGES"
    fi
fi

echo "  applying DISABLE settings"
for i in $PACKAGES ; do
    echo $i >> ./.tmp_pack
done
for i in `grep  "-" ./.tmp_pack` ; do
    j=`echo $i | sed 's/[-]//'`
    DISABLE="$DISABLE $j"
done
pack=
for p in $PACKAGES ; do
    addit="t"
    for d in $DISABLE ; do
	if test "x$p" = "x$d" ; then
	    addit="f"
	fi
    done
    if test "x$addit" = xt ; then
	pack="$pack $p"
    fi
done
PACKAGES="$pack"
echo "  applying ENABLE settings"
echo "" > ./.tmp_pack
PACKAGES="$PACKAGES $ENABLE"
# Test if each explicitly referenced package exists
for i in $PACKAGES ; do
    j=`echo $i | sed 's/[-+]//'`
    if test ! -d "$ROOTDIR/pkg/$j" ; then
	echo "Error: can't find package $i at \"$ROOTDIR/pkg/$i\""
 	exit 1
    fi
    echo $i >> ./.tmp_pack
done
PACKAGES=
for i in `grep -v "-" ./.tmp_pack | sort | uniq` ; do
    PACKAGES="$PACKAGES $i"
done
rm -f ./.tmp_pack
echo "    packages are:  $PACKAGES"

echo "  applying package dependency rules"
ck=
while test "x$ck" != xtt ; do
    i=0
    # rtot=${#PNAME[@]}
    rtot=$nname
    while test $i -lt $rtot ; do

	#  Is $pname in the current $PACKAGES list?
	#  pname=${PNAME[$i]}
	tmp="pname=\"\$PNAME_$i\""
	eval $tmp
	pin="f"
	for p in $PACKAGES ; do
	    if test "x$p" = "x$pname" ; then
		pin="t"
	    fi
	done

	#  Is the DNAME entry a (+) or (-) rule ?
	tmp="dname=\"\$DNAME_$i\""
	eval $tmp
	plus="-"
	echo $dname | grep '^+' > /dev/null 2>&1
	RETVAL=$?
	if test "x$RETVAL" = x0 ; then
	    plus="+"
	fi

	#  Is $dname in the current $PACKAGES list?
	dname=`echo $dname | sed -e 's/^[+-]//'`
	din="f"
	for p in $PACKAGES ; do
	    if test "x$p" = "x$dname" ; then
		din="t"
	    fi
	done

	#  Do we need to add $dname according to the dependency rules?
	if test "x$pin" = xt -a "x$plus" = "x+" -a "x$din" = xf ; then
	    in_dis="f"
	    for dis in $DISABLE ; do
		if test "x$dis" = "x$dname" ; then
		    in_dis="t"
		fi
	    done
	    if test "x$in_dis" = xt ; then
		echo "Error: can't satisfy package dependencies:"
		echo "  \"$dname\" is required by the dependency rules"
		echo "  but is disallowed by the DISABLE settings"
		exit 1
	    else
		PACKAGES="$PACKAGES $dname"
		ck=
	    fi
	fi

	#  Do we need to get rid of $dname according to the dependency rules?
	if test "x$pin" = xt -a "x$plus" = "x-" -a "x$din" = xt; then
	    echo "Error: can't satisfy package dependencies:"
	    echo "  \"$pname\" was requested but is disallowed by" 
	    echo "  the dependency rules for \"$dname\""
	    exit 1
	fi
	i=$(( $i + 1 ))
    done
    ck=$ck"t"
done
echo "    packages are:  $PACKAGES"
for i in $PACKAGES ; do
    adr="$ROOTDIR/pkg/$i"
    if test -d $adr ; then
	SOURCEDIRS="$SOURCEDIRS $adr"
	INCLUDEDIRS="$INCLUDEDIRS $adr"
	if test "x$i" = xautodiff ; then
	    AUTODIFF_PKG_USED=t
	fi
    else
	echo "Error: the directory \"$adr\" for package $i doesn't exist"
	exit 1
    fi
done

#  Build MNC templates and check for ability to build and use NetCDF
echo $PACKAGES | grep ' mnc ' > /dev/null 2>&1
RETVAL=$?
if test "x$RETVAL" = x0 ; then
    ( cd $ROOTDIR"/pkg/mnc" && $MAKE templates ) > make_mnc.errors 2>&1
    RETVAL=$?
    if test "x${RETVAL}" = x0 ; then
	rm -f make_mnc.errors
    else
	echo "Error: problem encountered while building source files in pkg/mnc:"
	cat make_mnc.errors 1>&2
	exit 1
    fi
    if test "x$HAVE_NETCDF" != xt ; then
	cat <<EOF

WARNING: the "mnc" package has been enabled but tests failed to 
  compile and/or execute NetCDF applications.  Please check that:

  1) NetCDF is installed for your compiler and
  2) the LIBS variable (within the 'optfile") specifies the correct 
       NetCDF library to link against.
  
EOF
    fi
fi

# Create a list of #define and #undef to enable/disable packages
PACKAGES_DOT_H=PACKAGES_CONFIG.h
#  The following UGLY HACK sets multiple "#undef"s and it needs to go 
#  away.  On 2003-08-12, CNH, JMC, and EH3 agreed that the CPP_OPTIONS.h 
#  file would eventually be split up so that all package-related #define
#  statements could be separated and handled only by genmake.
names=`ls -1 "$ROOTDIR/pkg"`
all_pack=
DISABLED_PACKAGES=
for n in $names ; do
    if test -d "$ROOTDIR/pkg/$n" -a "x$n" != xCVS ; then
	has_pack="f"
	for pack in $PACKAGES ; do
	    if test "x$pack" = "x$n" ; then
		has_pack="t"
		break
	    fi
	done
	if test "x$has_pack" = xf ; then
	    undef=`echo "ALLOW_$n" | $AWK '{print toupper($0)}'`
            DISABLED_PACKAGES="$DISABLED_PACKAGES -U$undef"
	fi
    fi
done
ENABLED_PACKAGES=
for i in $PACKAGES ; do
    def=`echo "ALLOW_$i" | $AWK '{print toupper($0)}'`
    ENABLED_PACKAGES="$ENABLED_PACKAGES -D$def"
#eh3 DEFINES="$DEFINES -D$def"

#EH3  WARNING :  This is an UGLY HACK that needs to be removed!!!
    case $i in 
	aim_v23)
            ENABLED_PACKAGES="$ENABLED_PACKAGES -DALLOW_AIM"
	    echo "Warning: ALLOW_AIM is set to enable aim_v23."
	    ;;
    esac
#EH3  WARNING :  This is an UGLY HACK that needs to be removed!!!

done

echo "  Adding STANDARDDIRS"
BUILDDIR=${BUILDDIR:-.}
if test "x$STANDARDDIRS" = xUSE_THE_DEFAULT ; then
    STANDARDDIRS="eesupp model"
fi
if test "x$STANDARDDIRS" != x ; then
    for d in $STANDARDDIRS ; do
	adr="$ROOTDIR/$d/src"
	if test ! -d $adr ; then
	    echo "Error:  directory $adr not found -- please check that ROOTDIR=\"$ROOTDIR\""
	    echo "  is correct and that you correctly specified the STANDARDDIRS option"
	    exit 1
	else
	    SOURCEDIRS="$SOURCEDIRS $adr"
	fi
	adr="$ROOTDIR/$d/inc"
	if test ! -d $adr ; then
	    echo "Error:  directory $adr not found -- please check that ROOTDIR=\"$ROOTDIR\""
	    echo "  is correct and that you correctly specified the STANDARDDIRS option"
	    exit 1
	else
	    INCLUDEDIRS="$INCLUDEDIRS $adr"
	fi
    done
fi

echo "  Searching for *OPTIONS.h files in order to warn about the presence"
echo "    of \"#define \"-type statements that are no longer allowed:"
CPP_OPTIONS=
CPP_EEOPTIONS=
spaths=". $INCLUDEDIRS"
names=`ls -1 "$ROOTDIR/pkg"`
for i in $spaths ; do
    try="$i/CPP_OPTIONS.h"
    if test -f $try -a -r $try -a "x$CPP_OPTIONS" = x ; then
	echo "    found CPP_OPTIONS=\"$try\""
	CPP_OPTIONS="$try"
        # New safety test: make sure packages are not mentioned in CPP_OPTIONS.h
        for n in $names ; do
            test_for_package_in_cpp_options $CPP_OPTIONS $n
        done
    fi
    try="$i/CPP_EEOPTIONS.h"
    if test -f $try -a -r $try -a "x$CPP_EEOPTIONS" = x ; then
	echo "    found CPP_EEOPTIONS=\"$try\""
        # New safety test: make sure MPI is not determined by CPP_EEOPTIONS.h
#**** not yet enabled ****
#        test_for_mpi_in_cpp_eeoptions $try
#**** not yet enabled ****
	CPP_EEOPTIONS="$try"
    fi
done
if test "x$CPP_OPTIONS" = x ; then
    echo "Error: can't find \"CPP_OPTIONS.h\" in the path list: $spaths"
    exit 1
fi

#  Here, we build the list of files to be "run through" the adjoint
#  compiler.
if test -f ./ad_files ; then
    rm -f ./ad_files
fi
echo "  Creating the list of files for the adjoint compiler."
for i in $SOURCEDIRS ; do
    list_files=`( cd $i && ls -1 *.list 2>/dev/null )`
    for j in $list_files ; do
	cat $i/$j >> ad_files
    done
done


echo
echo "===  Creating the Makefile  ==="
echo "  setting INCLUDES"
for i in $INCLUDEDIRS ; do
    if ! test -d $i ; then
#	INCLUDES="$INCLUDES -I$i"
#   else
	echo "Warning: can't find INCLUDEDIRS=\"$i\""
    fi
done

echo "  Determining the list of source and include files"
rm -rf .links.tmp
mkdir .links.tmp
echo "# This section creates symbolic links" > srclinks.tmp
echo "" >> srclinks.tmp
printf 'SRCFILES = '    > srclist.inc
printf 'CSRCFILES = '   > csrclist.inc
printf 'F90SRCFILES = ' > f90srclist.inc
printf 'HEADERFILES = ' > hlist.inc
printf 'AD_FLOW_FILES = ' > ad_flow_files.inc
alldirs="$SOURCEDIRS $INCLUDEDIRS ."
for d in $alldirs ; do
    deplist=
    sfiles=`( cd $d; echo *.[h,c,F] *.flow )`
    sfiles=`( echo $sfiles; cd $d; echo *.F90 )`
    for sf in $sfiles ; do
	if test ! -r ".links.tmp/$sf" ; then
	    if test -f "$d/$sf" ; then
                case $d/$sf in
                  ./$PACKAGES_DOT_H)
			;;
                  ./AD_CONFIG.h)
			;;
                  ./FC_NAMEMANGLE.h)
			;;
                  *)
		  	touch .links.tmp/$sf
		  	deplist="$deplist $sf"
			;;
                esac
		extn=`echo $sf | $AWK -F '.' '{print $NF}'`
		case $extn in
		    F)
			echo    " \\"  >> srclist.inc
			printf " $sf" >> srclist.inc
			;;
		    F90)
			echo    " \\"  >> f90srclist.inc
			printf " $sf" >> f90srclist.inc
			;;
		    c)
			echo    " \\"  >> csrclist.inc
			printf " $sf" >> csrclist.inc
			;;
		    h)
			echo    " \\"  >> hlist.inc
			printf " $sf" >> hlist.inc
			;;
		    flow)
			echo    " \\"  >> ad_flow_files.inc
			printf " $sf" >> ad_flow_files.inc
			;;
		esac
	    fi
	fi
    done
    if test "x$deplist" != x ; then
	echo "" >> srclinks.tmp
	echo "#  These files are linked from $d" >> srclinks.tmp
	echo "$deplist :" >> srclinks.tmp
	printf "\t\$(LN) %s/\$@ \$@\n" $d >> srclinks.tmp
    fi
done
rm -rf .links.tmp
echo "" >> srclist.inc
echo "" >> csrclist.inc
echo "" >> f90srclist.inc
echo "" >> hlist.inc
echo "" >> ad_flow_files.inc

if test -e $MAKEFILE ; then
    mv -f $MAKEFILE "$MAKEFILE.bak"
fi
echo "  Writing makefile: $MAKEFILE"
echo "# Multithreaded + multi-processing makefile for:" > $MAKEFILE
echo "#    $MACHINE" >> $MAKEFILE
echo "# This makefile was generated automatically on" >> $MAKEFILE
echo "#    $THISDATE" >> $MAKEFILE
echo "# by the command:" >> $MAKEFILE
echo "#    $0 $G2ARGS" >> $MAKEFILE
echo "# executed by:" >> $MAKEFILE
echo "#    $USER@${THISHOSTNAME}:${THISCWD}" >> $MAKEFILE

EXE_AD=$EXECUTABLE"_ad"
EXE_FTL=$EXECUTABLE"_ftl"
EXE_SVD=$EXECUTABLE"_svd"

cat >>$MAKEFILE <<EOF
#
# OPTFILE="$OPTFILE"
# 
# BUILDDIR     : Directory where object files are written
# SOURCEDIRS   : Directories containing the source (.F) files
# INCLUDEDIRS  : Directories containing the header-source (.h) files
# EXEDIR       : Directory where executable that is generated is written
# EXECUTABLE   : Full path of executable binary
#
# CPP          : C-preprocessor command
# INCLUDES     : Directories searched for header files
# DEFINES      : Macro definitions for CPP
# MAKEDEPEND   : Dependency generator
# KPP          : Special preprocessor command (specific to platform)
# KFLAGS       : Flags for KPP
# FC           : Fortran compiler command
# FFLAGS       : Configuration/debugging options for FC
# FOPTIM       : Optimization options for FC
# LINK         : Command for link editor program
# LIBS         : Library flags /or/ additional optimization/debugging flags

ROOTDIR     = ${ROOTDIR}
BUILDDIR    = ${BUILDDIR}  
SOURCEDIRS  = ${SOURCEDIRS}
INCLUDEDIRS = ${INCLUDEDIRS}
EXEDIR      = ${EXEDIR}
EXECUTABLE  = \$(EXEDIR)/${EXECUTABLE}
TOOLSDIR    = ${TOOLSDIR}

#eh3  new defines for the adjoint work
AUTODIFF    = ${ROOTDIR}/pkg/autodiff
EXE_AD      = ${EXE_AD}
EXE_FTL     = ${EXE_FTL}
EXE_SVD     = ${EXE_SVD}

ENABLED_PACKAGES = ${ENABLED_PACKAGES}
DISABLED_PACKAGES = ${DISABLED_PACKAGES}

# These files are created by Makefile
SPECIAL_FILES = ${PACKAGES_DOT_H} AD_CONFIG.h FC_NAMEMANGLE.h

EOF

#  Note: figure out some way to add Hyades JAM libraries here
 
cat >>$MAKEFILE <<EOF
# Unix ln (link)
LN = ${LN}
# C preprocessor
CPP = cat \$< | ${S64} | ${CPP}
# Dependency generator
MAKEDEPEND = ${MAKEDEPEND}
# Special preprocessor (KAP on DECs, FPP on Crays)
KPP = ${KPP}
# Fortran compiler
FC = ${FC}
# Fortran compiler
F90C = ${F90C}
# Link editor
LINK = ${LINK} ${LDADD}

# Defines for CPP
DEFINES = ${DEFINES}
# Includes for CPP
INCLUDES = ${INCLUDES}
# Flags for KPP
KFLAGS1 = ${KFLAGS1}
KFLAGS2 = ${KFLAGS2}
# Optim./debug for FC
FFLAGS = ${FFLAGS}
FOPTIM = ${FOPTIM}
# Optim./debug for FC
F90FLAGS = ${F90FLAGS}
F90OPTIM = ${F90OPTIM}
# Flags for CC
CFLAGS = ${CFLAGS}
# Files that should not be optimized
NOOPTFILES = ${NOOPTFILES}
NOOPTFLAGS = ${NOOPTFLAGS}
# Flags and libraries needed for linking
LIBS = ${LIBS} \$(XLIBS)
# Name of the Mekfile
MAKEFILE=${MAKEFILE}

EOF

cat srclist.inc       >> $MAKEFILE
cat csrclist.inc      >> $MAKEFILE
cat f90srclist.inc    >> $MAKEFILE
cat hlist.inc         >> $MAKEFILE
cat ad_flow_files.inc >> $MAKEFILE
echo               >> $MAKEFILE
echo 'F77FILES =  $(SRCFILES:.F=.f)'                                           >> $MAKEFILE
echo 'F90FILES =  $(F90SRCFILES:.F90=.f90)'                                    >> $MAKEFILE
echo 'OBJFILES =  $(SRCFILES:.F=.o) $(CSRCFILES:.c=.o) $(F90SRCFILES:.F90=.o)' >> $MAKEFILE

rm -f srclist.inc csrclist.inc hlist.inc flist.tmp clist.tmp f90srclist.inc
rm -f ad_flow_files.inc

cat >>$MAKEFILE <<EOF

.SUFFIXES:
.SUFFIXES: .o .f .p .F .c .F90 .f90

all: \$(EXECUTABLE)
\$(EXECUTABLE): \$(SPECIAL_FILES) \$(SRCFILES) \$(CSRCFILES) \$(HEADERFILES) \$(F90SRCFILES) \$(OBJFILES)
	@echo Creating \$@ ...
	\$(LINK) -o \$@ \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) \$(LIBS)
depend:
	@make links
	\$(MAKEDEPEND) -o .f \$(DEFINES) \$(INCLUDES) \$(SRCFILES)
	\$(TOOLSDIR)/f90mkdepend >> \$(MAKEFILE)
	-rm -f makedepend.out

links: \$(SRCFILES) \$(CSRCFILES) \$(HEADERFILES) \$(F90SRCFILES) \$(SPECIAL_FILES)

small_f: \$(F77FILES) \$(F90FILES)

output.txt: \$(EXECUTABLE)
	@printf 'running ... '
	@\$(EXECUTABLE) > \$@

clean:
	-rm -rf *.o *.f *.p *.f90 *.mod ${RMFILES} work.{pc,pcl} *.template
Clean:
	@make clean
	@make cleanlinks
	-rm -f \$(SPECIAL_FILES)
	-rm -f genmake_state genmake_*optfile genmake_warnings make.log run.log *.bak
CLEAN:
	@make Clean
	-find \$(EXEDIR) -name "*.meta" -exec rm {} \;
	-find \$(EXEDIR) -name "*.data" -exec rm {} \;
	-find \$(EXEDIR) -name "fort.*" -exec rm {} \;
	-rm -f \$(EXECUTABLE) output.txt

#eh3 Makefile: makefile
makefile:
	$THIS_SCRIPT $G2ARGS
cleanlinks:
	-find . -type l -exec rm {} \;

# Special targets ($SPECIAL_FILES) which are create by make
${PACKAGES_DOT_H}:
	@echo Creating \$@ ...
	@$BASH\$(TOOLSDIR)/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -bPACKAGES_CONFIG_H "Disabled packages:" \$(DISABLED_PACKAGES) " " "Enabled packages:" \$(ENABLED_PACKAGES) > \$@
AD_CONFIG.h:
	@echo Creating \$@ ...
	@$BASH\$(TOOLSDIR)/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -bAD_CONFIG_H -UALLOW_ADJOINT_RUN -UALLOW_TANGENTLINEAR_RUN -UALLOW_ECCO_OPTIMIZATION > \$@
FC_NAMEMANGLE.h:
	@echo Creating \$@ ...
	echo "$FC_NAMEMANGLE" > \$@

# The normal chain of rules is (  .F - .f - .o  )
.F.f:
	\$(CPP) \$(DEFINES) \$(INCLUDES) > \$@
.f.o:
	\$(FC) \$(FFLAGS) \$(FOPTIM) -c \$<
.F90.f90:
	\$(CPP) \$(DEFINES) \$(INCLUDES) > \$@
.f90.o:
	\$(F90C) \$(F90FLAGS) \$(F90OPTIM) -c \$<
.c.o:
	\$(CC) \$(CFLAGS) -c \$<

# Special exceptions that use the ( .F - .p - .f - .o ) rule-chain
.F.p:
	\$(CPP) \$(DEFINES) \$(INCLUDES) > \$@
.p.f:
	\$(KPP) \$(KFLAGS1)\$@ \$(KFLAGS2) \$<

#=========================================
#===  Automatic Differentiation Rules  ===

TAMC           = ${TAMC}
TAF            = ${TAF}

TAF_EXTRA      = ${TAF_EXTRA}
TAMC_EXTRA     = ${TAMC_EXTRA}

EOF

ad_vars="AD_TAMC_FLAGS AD_TAF_FLAGS"
ad_vars="$ad_vars FTL_TAMC_FLAGS FTL_TAF_FLAGS"
ad_vars="$ad_vars SVD_TAMC_FLAGS SVD_TAF_FLAGS"
for i in $ad_vars ; do
    name=$i
    t1="t2=\$"`echo $i`
    eval $t1
    printf "%-20s = " $name >> $MAKEFILE
    echo $t2 >> $MAKEFILE
done

echo "  Add the source list for AD code generation"
echo >> $MAKEFILE
printf "AD_FILES = " >> $MAKEFILE
AD_FILES=`cat ad_files`
for i in $AD_FILES ; do
    echo    " \\" >> $MAKEFILE
    printf " $i" >> $MAKEFILE
done
echo >> $MAKEFILE
rm -f ad_files

cat >>$MAKEFILE <<EOF

# ... AD ...
adall: ad_taf
adtaf: ad_taf_output.f
adtamc: ad_tamc_output.f

ad_input_code.f: \$(AD_FILES) \$(HEADERFILES)
	@$BASH\$(TOOLSDIR)/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -DALLOW_ADJOINT_RUN -UALLOW_TANGENTLINEAR_RUN -UALLOW_ECCO_OPTIMIZATION > ad_config.template
	cmp ad_config.template AD_CONFIG.h || cat ad_config.template > AD_CONFIG.h
	-rm -f ad_config.template
	@make \$(F77FILES)
	@make \$(AD_FLOW_FILES)
	cat \$(AD_FLOW_FILES) \$(AD_FILES) > ad_input_code.f

ad_taf_output.f: ad_input_code.f
	\$(TAF) \$(AD_TAF_FLAGS) \$(TAF_EXTRA) ad_input_code.f
	cat ad_input_code_ad.f | sed -f \$(TOOLSDIR)/adjoint_sed > ad_taf_output.f

adtafonly:
	\$(TAF) \$(AD_TAF_FLAGS) \$(TAF_EXTRA) ad_input_code.f
	cat ad_input_code_ad.f | sed -f \$(TOOLSDIR)/adjoint_sed > ad_taf_output.f

ad_taf: ad_taf_output.o \$(OBJFILES)
	\$(LINK) -o ${EXE_AD} \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) ad_taf_output.o \$(LIBS) 

ad_tamc_output.f: ad_input_code.f
	\$(TAMC) \$(AD_TAMC_FLAGS) \$(TAMC_EXTRA) ad_input_code.f
	cat ad_input_code_ad.f | sed -f \$(TOOLSDIR)/adjoint_sed > ad_tamc_output.f

ad_tamc: ad_tamc_output.o \$(OBJFILES)
	\$(LINK) -o ${EXE_AD} \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) ad_tamc_output.o \$(LIBS) 


# ... FTL ...
ftlall: ftl_taf
ftltaf: ftl_taf_output.f
ftltamc: ftl_tamc_output.f

ftl_input_code.f: \$(AD_FILES) \$(HEADERFILES)
	@$BASH\$(TOOLSDIR)/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -UALLOW_ADJOINT_RUN -DALLOW_TANGENTLINEAR_RUN -UALLOW_ECCO_OPTIMIZATION > ftl_config.template
	cmp ftl_config.template AD_CONFIG.h || cat ftl_config.template > AD_CONFIG.h
	-rm -f ftl_config.template
	@make \$(F77FILES)
	@make \$(AD_FLOW_FILES)
	cat \$(AD_FLOW_FILES) \$(AD_FILES) > ftl_input_code.f

ftl_taf_output.f: ftl_input_code.f
	\$(TAF) \$(FTL_TAF_FLAGS) \$(TAF_EXTRA) ftl_input_code.f
	cat ftl_input_code_ftl.f | sed -f \$(TOOLSDIR)/adjoint_sed > ftl_taf_output.f

ftltafonly:
	\$(TAF) \$(FTL_TAF_FLAGS) \$(TAF_EXTRA) ftl_input_code.f
	cat ftl_input_code_ftl.f | sed -f \$(TOOLSDIR)/adjoint_sed > ftl_taf_output.f

ftl_taf: ftl_taf_output.o \$(OBJFILES)
	\$(LINK) -o ${EXE_FTL} \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) ftl_taf_output.o \$(LIBS) 

ftl_tamc_output.f: ftl_input_code.f
	\$(TAMC) \$(FTL_TAMC_FLAGS) \$(TAMC_EXTRA) ftl_input_code.f
	cat ftl_input_code_ftl.f | sed -f \$(TOOLSDIR)/adjoint_sed > ftl_tamc_output.f

ftl_tamc: ftl_tamc_output.o \$(OBJFILES)
	\$(LINK) -o ${EXE_FTL} \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) ftl_tamc_output.o \$(LIBS) 


# ... SVD ...
svdtaf: ad_taf_output.f ftl_taf_output.f
svdall: svd_taf

svd_taf: ad_taf_output.o ftl_taf_output.o \$(OBJFILES)
	\$(LINK) -o mitgcmuv_svd \$(FFLAGS) \$(FOPTIM) \$(OBJFILES) ad_taf_output.o ftl_taf_output.o \$(LIBS)


#=========================================

EOF

if test "x$EXEHOOK" != x ; then
    printf "\nexehook:\n\t%s\n" $EXEHOOK >> $MAKEFILE
fi

echo "  Making list of \"exceptions\" that need \".p\" files"
for i in $KPPFILES ; do
    base=`echo $i | sed -e 's/\/.*\///g' | sed -e 's/\..*$//g'`
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	echo "Error: unable to add file \"$i\" to the exceptions list"
    fi
    echo "$base.f: $base.p" >> $MAKEFILE
done

echo "  Making list of NOOPTFILES"
for i in $NOOPTFILES ; do
    base=`echo $i | sed -e 's/\/.*\///g' | sed -e 's/\..*$//g'`
    RETVAL=$?
    if test "x$RETVAL" != x0 ; then
	echo "Error: unable to add file \"$i\" to the exceptions list"
    fi
    echo "$base.o: $base.f" >> $MAKEFILE
    printf "\t\$(FC) \$(FFLAGS) \$(NOOPTFLAGS) -c \$<\n" >> $MAKEFILE
done

echo "  Add rules for links"
cat srclinks.tmp >> $MAKEFILE
rm -f srclinks.tmp

echo "  Adding makedepend marker"
printf "\n\n# DO NOT DELETE\n" >> $MAKEFILE

printf "\n===  Done  ===\n"

# Create special header files
$BASH $TOOLSDIR/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -bPACKAGES_CONFIG_H "Disabled packages:" $DISABLED_PACKAGES " " "Enabled packages:" $ENABLED_PACKAGES > $PACKAGES_DOT_H".tmp" 
if test ! -f $PACKAGES_DOT_H ; then
    mv -f $PACKAGES_DOT_H".tmp" $PACKAGES_DOT_H
else
    cmp $PACKAGES_DOT_H".tmp" $PACKAGES_DOT_H > /dev/null 2>&1
    RETVAL=$?
    if test "x$RETVAL" = x0 ; then
	rm -f $PACKAGES_DOT_H".tmp"
    else
	mv -f $PACKAGES_DOT_H $PACKAGES_DOT_H".bak"
	mv -f $PACKAGES_DOT_H".tmp" $PACKAGES_DOT_H
    fi
fi
if test ! -f AD_CONFIG.h ; then
    $BASH $TOOLSDIR/convert_cpp_cmd2defines "Warning - this file is automatically generated - do NOT edit" -UALLOW_ADJOINT_RUN -UALLOW_TANGENTLINEAR_RUN -UALLOW_ECCO_OPTIMIZATION > AD_CONFIG.h
fi


#  Write the "state" for future records
if test "x$DUMPSTATE" != xf ; then
    printf "" > genmake_state
    for i in $gm_state ; do
	t1="t2=\$$i"
	eval $t1
	echo "$i='$t2'" >> genmake_state
    done
fi
