#! /bin/sh
#
# Update all of the derived files
# For best performance, execute this in the top-level directory.
# There are some experimental features to allow it to be executed in
# subdirectories
#
# Eventually, we want to allow this script to be executed anywhere in the
# mpich tree.  This is not yet implemented.
error_summary=""
acVersion=unknown
# finalStatus records whether there have been problems in updatefiles
# 1 = warning, 3 = fatal, 2 = reserved for future use, 
# 0 = no problems detected.
finalStatus=0
at_top=no
if [ -d maint -a -s maint/simplemake.in ] ; then
    at_top=yes
fi
#
# Default choices
# depend choices are dynamic, static, no
do_depend=dynamic
codecheck_args=""
do_geterrmsgs=yes
do_bindings=yes
do_f77=yes
use_patched_autoonf=no
do_build_configure=yes
autoconfdir=""
#
# Extract the arguments intended for updatefiles.  Any others are
# given to simplemake.  
temp_args=""
for arg in "$@" ; do
    case $arg in 
    -echo)
	set -x
	;;
    -with-codecheck=*|--with-codecheck=*)
	echo "codecheck not maintained and not available"
    ;;
    -with-codecheck|--with-codecheck)
	echo "codecheck not maintained and not available"
    ;;
    -without-codecheck|--without-codecheck)
    ;;

    -with-errmsgs|--with-errmsgs)
    do_geterrmsgs=yes
    ;;
    -without-errmsgs|--without-errmsgs)
    do_geterrmsgs=no
    ;;

    -with-bindings|--with-bindings)
    do_bindings=yes
    ;;
    -without-bindings|--without-bindings)
    do_bindings=no
    ;;

    -with-f77|--with-f77)
    do_f77=yes
    ;;
    -without-f77|--without-f77)
    do_f77=no
    ;;

    -with-patched-autoconf|--with-patched-autoconf)
    use_patched_autoonf=yes
    ;;
    -without-patched-autoconf|--without-patched-autoconf)
    use_patched_autoonf=no
    ;;

    -with-autoconf=*|--with-autoconf=*)
    # Select a location for a different autoconf
    autoconfdir=`echo "A$arg" | sed -e 's/.*=//'`
    ;;

    -distrib)
    do_depend=no
    do_build_configure=no
    temp_args="$temp_args $arg"
    ;;

    -help|--help|-usage|--usage)
    cat <<EOF
    updatefiles [ --with-autoconf=dir ]
                [ args for simplemake ] 
    Update the files in the MPICH2 build tree.  This file builds the 
    configure files, creates the Makefile.in files (using the simplemake
    program), extracts the error messages.

    You can use --with-autoconf=dir to specify a directory that contains
    an alternate autoconf and autoheader.  
EOF
    exit
    ;;
    *)
    temp_args="$temp_args $arg"
    ;;
    esac
done
# Reset the arguments.  Note that this doesn't handle arguments that contain
# blanks.  I hope that we don't need those.
set -- $temp_args
#
if [ $at_top = "no" ] ; then
    echo "Must execute at top level directory for now"
    exit 1
fi
#
# Determine the autoconf to use.  If --with-autoconf was set, use 
# autoconf and autoheader from that directory
if [ -n "$autoconfdir" ] ; then
    if [ -x $autoconfdir/autoconf -a -x $autoconfdir/autoheader ] ; then
        autoconf=$autoconfdir/autoconf
	autoheader=$autoconfdir/autoheader
	# Simplemake looks in environment variables for the autoconf
	# and autoheader to use
	AUTOCONF=$autoconf
	AUTOHEADER=$autoheader
	export AUTOCONF
	export AUTOHEADER
    else
        echo "Could not find executable autoconf and autoheader in $autoconfdir"
	exit 1
    fi
else
    autoconf=${AUTOCONF:-autoconf}
    autoheader=${AUTOHEADER:-autoheader}
fi
#
# Check that you have a working autoconf.  Autoconf 2.57 is not compatible with
# previous versions of autoconf (!!), even 2.52 (!!!).  
acIncDirFlag=-l
acVersion=ok
if test -d .tmp ; then rm -rf .tmp ; fi
if test -s .tmp ; then rm -f .tmp ; fi
if test ! -d .tmp ; then
    mkdir .tmp 2>&1 >/dev/null
fi
# Argh.  In autoconf 2.59, -B doesn't work.  You must use -I
# Find the configure version
# acSubversion is the version number minus 2.  (we assume autoconf 2.xx)
# -1 is used for unknown
acSubversion=-1
for ver in 60 59 58 57 56 55 54 53 52 51 50 13 11 0 ; do
    rm -f .tmp/configure.in .tmp/configure
    cat >.tmp/configure.in <<EOF
AC_PREREQ(2.$ver)
EOF
    if (cd .tmp && $autoconf >/dev/null 2>&1 ) ; then
	acSubversion=$ver
	break
    fi
done
rm -f .tmp/configure.in .tmp/configure
if [ "$acSubversion" -gt 57 -o "$acSubversion" -lt 0 ] ; then 
    if [ "$acSubversion" -gt 58 ] ; then
        acIncDirFlag=-I
    else 
        acIncDirFlag=-B
    fi
    if [ "$acSubversion" -gt 0 ] ; then
        acVersion="2.$acSubversion"
	echo "You have autoconf version $acVersion."
	error_summary="$error_summary \
Version $acVersion of autoconf may cause problems."
    else
	cat <<EOF
You either do not have autoconf in your path or updatefiles was unable to 
determine which version of autoconf you have.  You may be able to use
     autoconf --version
to see the version of autoconf (unfortunately, there is no standard 
format for the version output and it changes between autoconf versions.
In addition, some versions of autoconf choose among many versions and
provide incorrect output).
EOF
	error_summary="$error_summary \
No autoconf in path or unable to determine the version of autoconf."
        acVersion="Unknown"
    fi
    cat <<EOF

You either do not have autoconf in your path or you may have autoconf
version 2.57 or later.  Autoconf 2.57 is not compatible with previous
versions of autoconf, including autoconf 2.52 .  

This version of updatefiles attempts to workaround the incompatibilities
in autoconf 2.57 (and later), but problems remain.  In particular, you may run
into trouble if you need to execute
    make configure
on a platform different that the one you ran $0 on.

EOF
    error_summary="$error_summary \
Your do not have a usable version of autoconf (either no version found \
or version 2.57 or later)"
fi
rm -rf .tmp

#
# Create the bindings if necessary 
if [ $do_bindings = "yes" ] ; then
    if [ $do_f77 = "yes" ] ; then
        if [ ! -s src/binding/f77/abortf.c ] ; then 
	    build_f77=yes
        elif find . -name 'src/binding/f77/buildiface' -newer 'src/binding/f77/abortf.c' ; then
	    build_f77=yes
        else
	    build_f77=no
        fi
    else
        build_f77=no
    fi

    if [ $build_f77 = "yes" ] ; then
	echo "Building Fortran 77 interface"
	( cd src/binding/f77 && chmod a+x ./buildiface && ./buildiface )
    fi
    if [ ! -s src/binding/cxx/mpicxx.h ] ; then 
	build_cxx=yes
    elif find . -name 'src/binding/cxx/buildiface' -newer 'src/binding/cxx/mpicxx.h' ; then
	build_cxx=yes
    else
	build_cxx=no
    fi
    if [ $build_cxx = "yes" ] ; then
	echo "Building C++ interface"
    #    File code still needs work
    #    if [ ! -d src/mpi/romio ] ; then
#	    otherarg="-noromio"
    #    fi
	( cd src/binding/cxx && chmod a+x ./buildiface &&
	  ./buildiface -nosep $otherarg )
    fi

fi
#
# Capture the error messages
if [ ! -x maint/extracterrmsgs -a -s maint/extracterrmsgs ] ; then
    # grrr.  CVS doesn't maintain permissions correctly across Windows/Unix
    chmod a+x maint/extracterrmsgs
fi
if [ -x maint/extracterrmsgs -a $do_geterrmsgs = "yes" ] ; then
    echo "Extracting the error messages..."
    rm -rf .tmp
    rm -f .err
    maint/extracterrmsgs `cat maint/errmsgdirs` > .tmp 2>.err
    # (error here is ok)
    update_errdefs=yes
    if [ -s .err ] ; then 
       cat .err
       rm -f .err2
       grep -v "Warning:" .err > .err2
       if [ -s .err2 ] ; then
           echo "Because of errors in extracting error messages, the file"
           echo "src/mpi/errhan/defmsg.h was not updated."
	   error_summary="$error_summary \
Error message files in src/mpi/errhan were not updated."
           update_errdefs=no
	   finalStatus=1
	   rm -f .tmp
       fi
       rm -f .err .err2
    else
       # Incase it exists but has zero size
       rm -f .err
    fi
    if [ -s .tmp -a "$update_errdefs" = "yes" ] ; then
        mv .tmp src/mpi/errhan/defmsg.h
    fi
    if [ ! -s src/mpi/errhan/defmsg.h ] ; then
        echo "Creating a dummy defmsg.h file"
	cat > src/mpi/errhan/defmsg.h <<EOF
typedef struct { const char *short_name, *long_name; } msgpair;
static const int generic_msgs_len = 0;
static msgpair generic_err_msgs[] { {0, "no error catalog"}, };
static const int specific_msgs_len = 0;
static msgpair specific_err_msgs[] {  {0,0}, };
static int class_to_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0 }
EOF
    fi
fi
#
# Build scripts such as simplemake if necessary
made_simplemake=no
run_configure=no
# Later versions of autoconf put the autoconf version into the autom4te*.cache
# name.
if [ ! -x maint/configure ] ; then
    (cd maint && $autoconf && rm -rf autom4te*.cache )
elif find . -name 'maint/configure.in' -newer 'maint/configure' ; then
    # The above relies on the Unix find command
    (cd maint && $autoconf && rm -rf autom4te*.cache)
fi
if [ ! -x maint/simplemake -o ! -x maint/getstates ] ; then
    run_configure=yes
fi
#
# The following relies on the Unix find command
if [ -s maint/simplemake ] ; then
    if find . -name 'maint/simplemake.in' -newer 'maint/simplemake' ; then
        run_configure=yes
    fi
else
    run_configure=yes
fi
if [ -s maint/getstates ] ; then 
    if find . -name 'maint/getstates.in' -newer 'maint/getstates' ; then
        run_configure=yes
    fi
else
    run_configure=yes
fi

if [ "$run_configure" = "yes" ] ; then
    (cd maint && ./configure)
    made_simplemake=yes
fi

#
if [ ! -x maint/simplemake ] ; then
    echo "Could not create simplemake"
    echo "You can copy simplemake.in to simplemake, replacing @PERL@ with the"
    echo "path to Perl (version5).  Make sure the resulting file has"
    echo "execute permissions set."
    exit 1
fi

# Run some of the simple codes
#
if [ $made_simplemake != "no" ] ; then
    # Check that only the first line was changed:
    rm -f .t1 .t2
    sed -e 1d maint/simplemake.in > .t1
    sed -e 1d maint/simplemake > .t2
    if diff .t1 .t2 >/dev/null 2>&1 ; then
        :
    else
        echo "Something is wrong with simplemake; configure may have"
        echo "replaced variables that it should not have."
        diff .t1 .t2
        exit 1
    fi
    rm -f .t1 .t2
fi
#
# Create the Makefile.in files
# Make sure that these files exist so that the gcc dependency creation
# can work
rm_prepost=no
if [ ! -s src/include/mpidpre.h ] ; then
    rm_prepost=yes
fi
otherargs="$@"
# If there is no mpi.h file (and other files, but testing on mpi.h should
# be enough), don't generate the dependency information in the Makefiles
# with the static dependency target.  The new default in simplemake is
# dynamic dependency data
# Currently, the dependency generation relies on using gcc, so we may 
# want to test on that as well.
# 
# 
if [ $do_depend = static -a ! -s src/include/mpi.h ] ; then
    # Static dependencies require a mpi.h file
    echo "Turning off static generation of dependencies because there is no mpi.h file"
    do_depend=no
fi
if [ $do_depend = no ] ; then 
    otherargs="$otherargs -nodepend"
#else
#    # The next two files may be needed to build the dependency lists
#    touch src/include/mpidpre.h src/include/mpidpost.h
fi
# 
# autoconf 2.57 drastically changed the command line arguments.
# Up through 2.52, -l dir was the "localdir for searching"
# By 2.57, -l was no longer accepted, and -B dir or --prepend-include=DIR
# was used.  
# To make things more exciting, the format of autoconf --version has
# changed, making it very hard to automatically extract the version number
# so that programs like this can work around poor software engineering, 
# such as incompatible changes in a minor-numbered release.
#
# Just to make this even more interesting, the cygwin version of 
# autoconf selects a version.  But the code to so this causes --version 
# (and --help!) to fail unless there is a configure.in file in the current
# directory.  
#acversion=`autoconf --version | grep '[Aa]utoconf.*[0-9]' | \
#    sed -e 's/.*(0-9\.[0-9]*).*/\1/'`
if maint/simplemake -common=maint/makedefs \
    -docnamedefs='${master_top_srcdir}/maint/docnotes' \
    -autoconf="$acIncDirFlag ROOTDIR/confdb" \
    -libdir='${MPILIBNAME}'=ROOTDIR/lib $otherargs \
    Makefile.sm ; then
    :
else
    echo "Simplemake step failed!"
    exit 1
fi
#
# Create the configure files and run autoheader
# Eventually, make this a test for find available.  Perhaps
# find . -name configure.in > /dev/null 2>&1
# The problem is that even though cygnus has find, the DOS find
# is identified first.  We probably need a test for this case
find . -name 'configure.in' >/dev/null 2>&1
if [ $? = 0 ] ; then has_unix_find=yes ; else has_unix_find=no ; fi
# if [ $? = 0 ] ; then .. code with find
if [ "$has_unix_find" = "yes" -a "$do_build_configure" = "yes" ] ; then
    for dir in `find . -name 'configure.in' -print` ; do
        dir=`dirname $dir`
	allowFailure=no
	#echo $dir
	qmpe2dir=`echo $dir | sed -e 's%.*src/mpe2.*%FOUNDMPE2%'`
	if [ "$qmpe2dir" = "FOUNDMPE2" ] ; then
	    # echo "Found MPE2 directory; skipping"
	    # MPE2 has its own updatefiles script, which should 
	    # be used instead of this one.
	    continue
        fi
	if [ $dir = "./src/binding/f77" -a $do_f77 != yes ] ; then
	    # Skip building the f77 configure (it requires special 
	    # support because of bugs in the Fortran support in 
	    # various releases of autoconf)
	    continue
	fi
	if [ -s $dir/Makefile.in ] ; then 
            #echo "Found $dir/configure.in"
	    #
	    # Check for known problems
	    fixEndEOFBug=no
	    if [ \( $dir = "./src/binding/f77" -o $dir = "./test/mpi" \) -a \
		$use_patched_autoonf = no ] ; then
		# We need a *patched*, version 2.13 form of autoconf
		# Version 2.62 breaks the Fortran 90 extensions
		# to TRY_COMPILE, and stock 2.13 generates bogus 
		# code for language FORTRAN.

		# See if autoconf works
		rm -rf .ctmp
		mkdir .ctmp
		cd .ctmp
		cat >>configure.in <<EOF
AC_INIT(configure.in)
AC_LANG_FORTRAN77
AC_TRY_COMPILE(,[integer a],a=1,a=0)
EOF
		$autoconf
  	        cd ..
		# The bug is that the EOF doesn't go onto the next line
		if grep endEOF .ctmp/configure >/dev/null 2>&1 ; then
		    echo " "
   echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
		    echo "The available version of autoconf has a bug"
		    echo "in handling Fortran programs and should not be used."
		    echo "This bug is an improper placement of the EOF"
		    echo "token used to implement AC_TRY_COMPILE for Fortran."
		    echo "A patch for this version is available in "
		    echo "maint/ac2.13.diff ."
		    echo "A workaround will be attempted, but fixing "
		    echo "autoconf is a better solution."
   echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
		    echo " "
		    error_summary="$error_summary \
Your version of autoconf cannot properly handle Fortran.  See the diff \
in maint/ac2.13.diff for a possible patch.  updatefiles attempted a workaround."
		    fixEndEOFBug=yes
		fi
                rm -rf .ctmp
	    fi # dir = src/binding/f77

            if [ $dir = "./src/mpi/romio" ] ; then
		echo "Creating configure in $dir"
		# Using an explicit acIncDirFlag will force
		# a consistent choice of autoconf
		# Only use autoheader if AC_CONFIG_HEADER is
	 	# present
		if grep AC_CONFIG_HEADER $dir/configure.in >/dev/null 2>&1 ; then
		    (cd $dir && $autoheader $acIncDirFlag . )
		fi
		(cd $dir && \
			$autoconf $acIncDirFlag . && rm -rf autom4te*.cache )
	        if grep 'mpi2-other/info/Makefile \\
' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
                fi
	        # Add other tests here (sigh) as necessary
	        if [ $fixBackWhackCtrlMBug = yes ] ; then
		     rm -f c.tmp 
		     sed -e '/"\\
/d' -e 's/\\
//g' $dir/configure > c.tmp
		     rm -f $dir/configure
		     mv c.tmp $dir/configure
		     chmod a+x $dir/configure
	        fi
	        continue
	    elif [ $dir = "./src/mpe2" ] ; then
		# Use acIncDirFlag to ensure that a consistent
		# choice of autoconf is made by systems that 
		# support 2.1x and 2.57+
		echo "Creating configure in $dir"
 		if grep AC_CONFIG_HEADER $dir/configure.in >/dev/null 2>&1 ; then
		    (cd $dir && $autoheader $acIncDirFlag . )
		fi
		(cd $dir && $autoconf $acIncDirFlag . && rm -rf autom4te*.cache)
		continue
	    fi
	    # First, check for a configure target in Makefile.in
	    if grep 'configure:' $dir/Makefile.in >/dev/null 2>&1 ; then
 	        # The make -q checks whether the target is upto date first;
	        # if it isn't, we remake it.
	
		rm -f $dir/mf.out 
                (cd $dir && rm -f mf.tmp ; \
	        sed -e 's%^SHELL[ 	]*=.*%SHELL = /bin/sh%' \
		    -e "s%@srcdir@%.%g" \
		    -e '/include .deps/d' \
		    -e '/@SET_MAKE@/d' Makefile.in > mf.tmp ;\
		    if make -q -f mf.tmp configure >mf.out 2>&1 ; then \
                : ; else \
	        echo "Found $dir/configure.in; executing make configure target" ; \
	        make -f mf.tmp configure ; fi ; rm -f mf.tmp  \
	        )
		if [ ! -x $dir/configure ] ; then
		    echo "Error! Could not build configure in $dir with make configure"
	            finalStatus=3
	        elif grep PAC_ $dir/configure >/dev/null 2>&1 ; then
                    echo "Error! autoconf did not find local macro definitions for configure in $dir"
	            echo "The following (at most 40 lines) local macros were not found:"
		    grep PAC_ $dir/configure | head -40
		    if [ -s $dir/mf.out ] ; then
 	  	        echo "Output of make configure step was:"
		        cat mf.out
		    fi
		    finalStatus=3
		fi
	  	# Remove make output now that we no longer need it.
		rm -f $dir/mf.out
            else 
		if [ -x $dir/makeconfigure ] ; then
		    echo "Using makeconfigure in $dir"
		    (cd $dir && ./makeconfigure )
		else
		    # Check for old 1.7 configure files (in MPE, at least for
		    # now)
		    if egrep 'AC_ARG|AC_CHECK_FUNCS' $dir/configure.in >/dev/null 2>&1 ; then
		        echo "Trying simple autoheader/autoconf in $dir"
			if grep AC_CONFIG_HEADER $dir/configure.in >/dev/null 2>&1 ; then
		            (cd $dir && $autoheader $acIncDirFlag . )
			fi
			(cd $dir && $autoconf $acIncDirFlag . && rm -rf autom4te*.cache)
		    else
		        # Try autoconf-1.7; accepts failures gracefully
		        echo "Trying simple autoconf using 1.7 in $dir"
			# Don't panic if we can't build this configure; it
			# is too old.
			allowFailure=yes
			(cd $dir && autoconf-1.7)
		    fi
		fi
            fi
	    if [ $fixEndEOFBug = yes ] ; then
		if grep endEOF $dir/configure >/dev/null 2>&1 ; then
		    echo "Fixing endEOF error in generated configure"
		    rm -f c.tmp
 		    sed 's/endEOF/end\
EOF/g' $dir/configure > c.tmp
		    mv -f c.tmp $dir/configure
		    chmod a+x $dir/configure
		fi
	    fi
	    #
            # Under cygwin, sometimes (?) configure ends up containing \^M
	    # (that's <ctrl>-M).  We may need to add this sed step
	    # sed -e '/"\
"/d' -e 's/\
//g'
	    # (the first removes case statements on \^M, the second
	    # removes the \^M from the ac_config_files statement
	    fixBackWhackCtrlMBug=no
	    if [ ! -s $dir/configure -a "$allowFailure" != yes ] ; then 
		echo "PANIC: Could not make configure from configure.in"
		echo "In directory $dir"
		exit 1
	    elif [ -s $dir/configure ] ; then
	        if grep 'src/Makefile \\ src' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
	        elif grep 'src/Makefile \\
 src' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
	        elif grep 'attr/Makefile \\ util' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
	        elif grep 'attr/Makefile \\
' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
	        elif grep 'mpi2-other/info/Makefile \\
' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
	        elif grep 'maint/testmerge \\
' $dir/configure 2>&1 >/dev/null ; then 
		    fixBackWhackCtrlMBug=yes
                fi
 	        # Add other tests here (sigh) as necessary
	        if [ $fixBackWhackCtrlMBug = yes ] ; then
		    rm -f c.tmp 
  	  	    sed -e '/"\\
/d' -e 's/\\
//g' $dir/configure > c.tmp
		    rm -f $dir/configure
		    mv c.tmp $dir/configure
		    chmod a+x $dir/configure
	        fi
            fi
        fi
    if [ ! -x $dir/configure -a "$allowFailure" != yes ] ; then
        # Check for a few allowed exceptions
        if [ "$dir" = "./src/pmi/winmpd" ] ; then
	    continue
        fi
        echo "Could not build configure from configure.in in $dir"
	echo "Aborting updatefiles!"
	exit 1
    fi
    done
elif [ "$has_unix_find" = no ] ; then
    echo "You need to install find (in findutils)"
    exit 1
else 
    echo "Skipping creation of configure files"
fi
if [ -f src/mpe2/maint/updatefiles -a "$do_build_configure" = "yes" ] ; then
    # If we have the mpe2 updatefiles, execute it from the mpe directory
    (cd src/mpe2 && chmod a+x maint/updatefiles && maint/updatefiles )
fi
if [ $rm_prepost = yes ] ; then
    rm -f src/include/mpidpre.h src/include/mpidpost.h
fi
#
# The following must be the last statements executed
if [ -n "$error_summary" ] ; then
    echo " "
    echo "Problems encountered while running updatefiles."
    echo "These may cause problems when configuring or building MPICH2."
    echo "$error_summary"
fi
case $finalStatus in 
   0) # all is well
	;;
   1) # warnings
 	;;
   2) # reserved for future use
	;;
   3) # fatal, cannot continue
	echo "updatefiles step failed!  Review the output and fix the problem"
        echo "before continuing"
        exit 1
	;;	
   *) # unknown
	echo "Internal error in updatefiles; finalStatus=$finalStatus"
	exit 1
	;;
esac

