#!/bin/sh

# cccl
# Wrapper around MS's cl.exe and link.exe to make them act more like
# Unix cc and ld
#
# 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
}

case $MACHTYPE in
    *-msys)
        slash="-"
        ;;
    *)
        slash="/"
        ;;
esac
# 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="${slash}nologo ${slash}FS"
linkopt="${slash}nologo"
# gotparam is 0 if we didn't ever see a param, in which case we show usage()
gotparam=

# We want exceptions
clopt="$clopt ${slash}EHsc"

### 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 ${slash}Za"
        ;;

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

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

    -O0)
        clopt="$clopt ${slash}Od ${slash}D_DEBUG ${slash}MTd"
        ;;

    -O2)
        clopt="$clopt ${slash}O2 ${slash}MT"
        ;;

    -L*)
        path=`echo "$1" | sed 's/-L//'`
        linkopt="$linkopt ${slash}LIBPATH:$path"
        cl_linkopt="${slash}link ${slash}LIBPATH:\"$path\""
        ;;

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

        clopt="$clopt $lib"
        linkopt="$linkopt $lib"
        ;;

    -m386)
        clopt="$clopt ${slash}G3"
        ;;

    -m486)
        clopt="$clopt ${slash}G4"
        ;;

    -mpentium)
        clopt="$clopt ${slash}G5"
        ;;

    -mpentiumpro)
        clopt="$clopt ${slash}G6"
        ;;

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

    -pedantic)
        #ignore pedantic
        ;;

    -Wall)
        # not all warnings are implemented
        # the following is equivalent to
        # Wimplicit-function-declaration but we will issue a compiler
        # error
        clopt="$clopt ${slash}we4013"
        ;;

    -W*)
        #ignore warnings
        ;;

    -Q*)
        #ignore link warnings
        ;;

    -fno-strict-aliasing*)
        #ignore aliasing
        ;;

    -isystem)
        shift
        clopt="$clopt -I$1"
        ;;

    -MT)
        exit 0
        ;;

    -mno-cygwin)
        ;;

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

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

    *)
        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

# choose which opts we built up based on which program will actually run
if test x$prog = xcl ; then
    opts="$clopt $cl_linkopt"
else
    opts=$linkopt
fi

if test x$V = x1 ; then
    echo "$prog $opts"
fi
exec $prog $opts
exit 0
