#!/bin/sh
#
# cccl 
# Wrapper around MS's cl.exe and link.exe to make them act more like
# Unix cc and ld
#
# 2005 JuhaV: added fortran support with visual fortran 
#             - autoconf name mangling tests work now..
#             
# FFLAGS="" and FCFLAGS="" FC=cccl2 F77=cccl2 CC=cccl2 CXX=cccl2 ./configure
#
# Copyright (C) 2000-2003 Geoffrey Wossum (gwossum@acm.org)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

usage()
{
    cat <<EOF
Usage: cccl [OPTIONS]

cccl is a wrapper around Microsoft's cl.exe and link.exe.  It translates
parameters that Unix cc's and ld's understand to parameters that cl and link
understand.
EOF
    exit $1
}

# prog specifies the program that should be run (cl.exe or link.exe)
# We'll assume cl to start out
prog=cl
# opts specifies the command line to pass to the MSVC program
clopt="-nologo "
linkopt="-force:multiple "
# gotparam is 0 if we didn't ever see a param, in which case we show usage()
gotparam=
# if stuff is piped out, then don't print out the command
tobepiped=no
# preprocessing
preprocessing=no
#
fortran_progs=
c_source=
create_def_file=
objects=

### Run through every option and convert it to the proper MS one
while test $# -gt 0; do
    case "$1" in
    -D*) optarg= ;;
    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
    *) optarg= ;;
    esac
    gotparam=1

    case "$1" in
    --version)
	cat <<EOF
cccl 0.03

Copyright 2000-2003 Geoffrey Wossum
This is free software; see the source for copying conditions.  There is NO
waranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
EOF
	exit 1;
	;;

    -ansi)
	clopt="$clopt -Za"
	;;

    -v | -V | --verbose)
        # Verbose compiling needed for visual fortran
	clopt="$clopt -VERBOSE"
	;;

    -O1 | -O2 | -O | -O3)
        # note also, that fortran compiler has a different opt flag
        # this is done with sed in the end.
	clopt="$clopt -Ot"
	;;

    -O0)
        # disable optimizations
	clopt="$clopt -Od"
	;;

    -E*)
        # CPP might be piped to a file and we don't want to screw it up
        # -E -> -EP because fortran doesn't like #, this could be done 
        # better by grepping and seding..
	tobepiped=yes
	clopt="$clopt -EP"
	linkopt="$linkopt -EP"
	preprocessing=yes
	;;

    -c)
	# -c (compile only) is actually the same, but for clarity...
	clopt="$clopt -c"
	;;

    -g[0-9] | -g)
	# cl only supports one debugging level
	clopt="$clopt -Zi"
	;;

    -I*)
	path=`echo "$1" | sed 's#/#\\\#g'`
	linkopt="$linkopt $path"
	clopt="$clopt $path"
	;;

    -L*)
	path=`echo "$1" | sed 's/-L//'`
	linkopt="$linkopt -LIBPATH:$path"
	clopt="$clopt -LIBPATH:$path"
	;;

    -l*)
	lib=`echo "$1" | sed 's/-l//'`
	lib="$lib.lib"
	
	clopt="$clopt $lib"
	linkopt="$linkopt $lib"
	;;

    -m386)
	clopt="$clopt -G3"
	;;

    -m486)
	clopt="$clopt -G4"
	;;

    -mpentium)
	clopt="$clopt -G5"
	;;

    -shared)
	linkopt="$linkopt -dll"
	# 
	# windows doesn't export all symbols, we have to do it by ourselves
	create_def_file="yes"
	;;

    -mpentiumpro)
	clopt="$clopt -G6"
	;;

    -o)
	# specifying output file, is it an object or an executable
	shift
	case "$1" in
	*.o | *.obj)
	    clopt="$clopt -Fo$1"
	;;
	
	*.exe)
	    clopt="$clopt -Fe$1";
	    linkopt="$linkopt -out:$1"
	;;
	*)
	    clopt="$clopt -out:$1";
	    linkopt="$linkopt -out:$1"
	;;
	esac;;

    -pedantic)
	#ignore pedantic
	;;

    -W*)
        #ignore warnings
        ;;

    *.c)
        clopt="$clopt $1"
        c_source="$c_source $1"
    ;;
    *.cc | *.cxx | *.C)
	# C++ source file with non .cpp extension, make sure cl understand 
	# that it is C++
	clopt="$clopt -Tp$1"
	c_source="$c_source $1"
	;;

    *.f90 | *.fortran | *.F90 )
        clopt="$clopt $1"
	prog="f90"

	fortran_progs="$fortran_progs $1"
	;;
    *.F | *.f)
        clopt="$clopt $1"
	prog="f77"

	fortran_progs="$fortran_progs $1"
    
        ;;

    *.lib)
	# Object files/libraries seen, this command will require link
	# Switch the prog to link
	linkopt="$linkopt $1"
	clopt="$clopt $1"

	# prog="link"
	# luckily cl sometimes knows how to link.. 
	# up fortran tests in autoconf
	if test "$prog" != "f90"; then
	if test "$prog" != "f77"; then
	if test "$c_source" = ""; then
	    prog="link"
        fi
	fi
	fi

        ;;

    *.o | *.obj | *.a )
	# Object files/libraries seen, this command will require link
	# Switch the prog to link
	linkopt="$linkopt $1"
	clopt="$clopt $1"
	objects="$objects $1"

	# prog="link"
	# luckily cl sometimes knows how to link.. 
	# up fortran tests in autoconf
	if test "$prog" != "f90"; then
	if test "$prog" != "f77"; then
	if test "$c_source" = ""; then
	    prog="link"
        fi
	fi
	fi

	;;

    *)
	clopt="$clopt $1"
	linkopt="$linkopt $1"
	if test x$optarg != x ; then
	    clopt="$clopt=$optarg"
	    linkopt="$linkopt=$optarg"
	fi
	;;

    esac
    shift
done

if test x$gotparam = x ; then
    usage
    exit 1
fi

# revert back from any other program, if we are doing preprocessing
if test x$preprocessing = xyes ; then 
    prog=cl
fi

# todo:
#
#
# choose which opts we built up based on which program will actually run
# 
#
case "$prog" in 
	cl) 
	   # when linking with fortran, we really need everything to be stdcall.
	   # otherwise fuunctionpointers will have wrong calling conventions
	    clopt=`echo "$clopt" | sed 's/ -I\\\/ -IC:\\\msys\\\1.0\\\/g'` 
	    opts="$clopt -link -force:multiple"
	;;
	f90)
	    clopt=`echo "$clopt" | sed 's/ -Ot / -optimize:4 /'` 
	    clopt=`echo "$clopt" | sed 's/ -Od / -optimize:0 /'` 
	    opts=$clopt
	    # visual fortran goes berzerk on this one
	    unset F90
	;;

	f77)
	    clopt=`echo "$clopt" | sed 's/ -Ot / -optimize:4 /'` 
	    clopt=`echo "$clopt" | sed 's/ -Od / -optimize:0 /'` 
	    opts=$clopt
	    # visual fortran goes berzerk on this one
	    unset F77
	;;

	*)
	    if test "$create_def_file" = "yes"; then

	      # foreach object, create def file
	      dlltool -z tmp.def --export-all-symbols $objects 
	      # data_symbols=`grep "DATA$" tmp.def |gawk '{print $1}' |grep -v "^?" |grep -v "^_"`
	      func_symbols=`grep -v "DATA$" tmp.def |gawk '{print $1}' |grep "..*@[0-9][0-9]*" |grep -v "^?" |sed -e 's/.*/_\0/g' `

	      echo "EXPORTS"  > tmp.def
	      n="1"
	      # for s in $data_symbols; do
	      # 	  	echo "$s @ $n DATA"  >> tmp.def
	      # 		n=`expr $n + 1`
	      # done

	      for s in $func_symbols; do
		  echo "$s @ $n"  >> tmp.def
		  n=`expr $n + 1`
	      done

	      linkopt="$linkopt -def:tmp.def"

	    fi
	    opts=$linkopt
esac 

if test "$tobepiped" = "no"; then
    echo "$prog $opts"
fi
exec $prog $opts
exit 0
