#!/bin/sh
# $Id: omniDriver.in,v 1.53 2002/10/04 02:11:11 a-hasega Exp $
# $RWC_Release: Omni-1.6 $
# $RWC_Copyright:
#  Omni Compiler Software Version 1.5-1.6
#  Copyright (C) 2002 PC Cluster Consortium
#  
#  This software is free software; you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License version
#  2.1 published by the Free Software Foundation.
#  
#  Omni Compiler Software Version 1.0-1.4
#  Copyright (C) 1999, 2000, 2001.
#   Tsukuba Research Center, Real World Computing Partnership, Japan.
#  
#  Please check the Copyright and License information in the files named
#  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
#  Software release kit.
#  
#  
#  $

omniVersion=@omniVersion@

prefix=${OMNI_HOME:=@orgPrefix@}
exec_prefix=@orgExec_prefix@

bindir=${exec_prefix}/bin
libdir=${prefix}/lib

omnidir=${libdir}/openmp
omniincludedir=${omnidir}/include
omnilibexecdir=${omnidir}/libexec
omnilibdir=${omnidir}/lib
omniclassdir=${omnidir}/java
omnitmpldir=${omnidir}/template

OS=@OS@
CPU=@CPU@
threadList='@available_threads@'
lockList='@available_locks@'
defLock='@lock_type@'
defThread='@thread_type@'
ignoreCombo='@ignore_pair@'
haveST='@doStackThread@'
haveShmem='@doUnixShmem@'
haveScash='@doScash@'
scoreNickname='@scoreNickname@'
scoreDir=${RWCROOT:=@scoreDir@}
doJexc='@doJexcBackend@'
haveOpenGR='@doOpenGR@'
doOpenGR=0

javaCom=${OMNI_JAVAVM:=@JAVACOM@}
defCcCom='@CC@'
defCcType='@ccType@'
stGccCom='@STGCC@'

omniFpp="${omnilibexecdir}/fpp"

haveQReal='@doQReal@'
gmpIncOpt='@gmpIncOpt@'
gmpLibOpt='@gmpLibOpt@'

#------------
template=""
directTemplate=""

lockSpec=""
threadSpec=""
runtimeMode=""

directTmplMode=0

doOpenMP=1
hasDoubleAlign=0

CcCom=""
CxxCom=""
CcWrap=""
CcType=""
CcOpt=""
CcFlags=""

CppCom=""
CppFlags=""

CppOsDef=-D__OMNI_OS_`echo $OS | tr '[a-z]' '[A-Z]'`__
CppCpuDef=-D__OMNI_CPU_`echo $CPU | tr '[a-z]' '[A-Z]'`__
CppRuntimeDef=""
CppMTSafeDef=""
CppCCDependDef=""
CppOpt=""
CcCppOpt=""

FppCom=""
FppFlags=""

QueryCompilerType="no"
UnknownCompilerRequest="no"

LANG=C
LC_CTYPE=$LANG
LC_COLLATE=$LANG
LC_MESSAGES=$LANG
LC_MONETARY=$LANG
LC_NUMERIC=$LANG
LC_TIME=$LANG
LC_ALL=$LANG
export LANG LC_CTYPE LC_COLLATE LC_MESSAGES LC_NONETARY LC_NUMERIC LC_TIME LC_ALL


cleanMeUp () {
    if test ! -z "${template}"; then
	rm -f ${template}
    fi
    if test ! -z "${omniTemp}"; then
	rm -f ${omniTemp}*
    fi
}


ErrorExit () {
    cleanMeUp
    echo "${progName}: Error: $1" >&2
    exit 1
}


Warning () {
    echo "${progName}: Warning: $1" >&2
}


safeBasename () {
    last=`echo $1 | awk -F'.' '{ print $NF }'`
    basename $1 .${last}
}

getArgVal () {
    optName=`echo $1 | awk -F'=' '{ print $1 }'`
    echo $1 | sed "s:${optName}=::"
}

debugPrint () {
    echo debug: \'$1\' >&2
}

checkNull () {
    if test -z "$1"; then
	return 0
    else
	return 1
    fi
}

checkLock () {
    for i in `echo ${lockList}`
    do
	if test "x$i" = "x${lockSpec}"; then
	    unset i
	    return 1
	fi
    done
    echo "\"${lockSpec}\" is not in \"${lockList}\"." >&2
    echo "Available configurations:" >&2
    dumpSpec
    exit 1
}

checkThread () {
    for i in `echo ${threadList}`
    do
	if test "x$i" = "x${threadSpec}"; then
	    unset i
	    return 1
	fi
    done
    echo "\"${threadSpec}\" is not in \"${threadList}\"." >&2
    echo "Available configurations:" >&2
    dumpSpec
    exit 1
}


checkDoubleAlign () {
    if test "${CcType}" = "gcc"; then
	for i in $*
	do
	    case "$i" in
		-malign-double)
		    hasDoubleAlign=1;;
	    esac
	done
    fi
}


checkDoOpenMPGR () {
    for i in $*
    do
	case "$i" in
	    -omp)
		doOpenMP=0;;
	    -ogr)
		doOpenGR=0;;
	esac
    done
}


canonicThreadName () {
    checkNull "${threadSpec}"
    if test $? -eq 0; then
	threadSpec=${defThread}
    else
	case "${threadSpec}" in
	    [Pp][Tt][Hh][Rr][Ee][Aa][Dd])
		threadSpec=pthread;;
	    [Ss][Oo][Ll][Aa][Rr][Ii][Ss])
		threadSpec=solaris;;
	    [Ss][Pp][Rr][Oo][Cc])
		threadSpec=sproc;;
	    *)
		true;;
	esac
    fi
}


checkExec () {
    com=$1
    sl=`echo $1 | grep '/' 2>/dev/null`
    if test "x${sl}" = "x"; then
	for i in `echo $PATH | sed 's/:/ /g'`
	do
	    if test -x ${i}/${com}; then
		return 1
	    fi
	done
	return 0
    else
	if test -x ${com}; then
	    return 1
	else
	    return 0
	fi
    fi
}


canonicLockName () {
    checkNull "${lockSpec}"
    if test $? -eq 0; then
	lockSpec=${defLock}
    else
	case "${lockSpec}" in
	    [Ss][Pp][Ii][Nn])
		lockSpec=spin;;
	    [Mm][Uu][Tt][Ee][Xx])
		lockSpec=mutex;;
	    *)
		true;;
	esac
    fi
}


checkGcc () {
    isGcc=0
    tmp=/tmp/.OmniConfCC.$$
    cCom=$1
    ${cCom} -v > $tmp 2>&1
    if test $? -eq 0; then
	chk=`tail -1 $tmp | awk '{ print $3 }'`
	case $chk in
	    egcs*|2.*)
		isGcc=1;;
	    *)
		isGcc=0;;
	esac
    fi
    rm -f $tmp
    return ${isGcc}
}


checkIntelCc () {
    isIntelCc=0
    tmp=/tmp/.OmniConfCC.$$
    cCom=$1
    ${cCom} -V > $tmp 2>&1
	x=`grep 'Intel(R) C++ Compiler ' $tmp`
    if test "X${x}" != "X"; then
	isIntelCc=1
    fi
    rm -f $tmp
    return ${isIntelCc}
}


checkPgiCc () {
    isPgiCc=0
    tmp=/tmp/.OmniConfCC.$$
    cCom=$1
    ${cCom} -V > $tmp 2>&1
	x=`grep 'The Portland Group' $tmp`
    if test "X${x}" != "X"; then
	isPgiCc=1
    fi
    rm -f $tmp
    return ${isPgiCc}
}


checkSunCc () {
    isSunCc=0
    tmp=/tmp/.OmniConfCC.$$
    cCom=$1
    ${cCom} -V > $tmp 2>&1
    if test ${CPU} = i386; then
	cStr='cc: PC'
    else
	cStr='WorkShop Compilers'
    fi
    x=`grep "$cStr" $tmp`
    if test "X${x}" != "X"; then
	isSunCc=1
    fi
    rm -f $tmp
    return ${isSunCc}
}


checkMipsCc () {
    isMipsCc=0
    tmp=/tmp/.OmniConfCC.$$
    cCom=$1
    ${cCom} -version > $tmp 2>&1
	x=`grep 'MIPSpro' $tmp`
    if test "X${x}" != "X"; then
	isMipsCc=1
    fi
    rm -f $tmp
    return ${isMipsCc}
}


getVendorCc () {
    defCc=$1
    defType=unknown

    case "${OS}" in
	aix)
	    defCc=${sysCc}
	    defType=AIXCC;;
	solaris)
	    checkSunCc $defCc
	    if test $? -eq 1; then
		defType=SunCC
	    fi;;
	irix)
	    checkMipsCc $defCc
	    if test $? -eq 1; then
		defType=MipsCC
	    fi;;
	*)
	    checkGcc $defCc
	    if test $? -eq 1; then
		defType=gcc
            else
	      checkIntelCc $defCc
	      if test $? -eq 1; then
		defType=IntelCC
              else
	        checkPgiCc $defCc
	        if test $? -eq 1; then
		  defType=PGICC
                fi
              fi
	    fi;;
    esac

    CcCom=${defCc}
    CcType=${defType}
}


getCxxCom () {
    case $2 in
	gcc)
	    CxxCom="g++";;
	*)
	    CxxCom="c++";;
    esac
}
		

genCcWrap () {
    case "${runtimeMode}" in
	scash)
	    case "${CcType}" in
	    gcc)
		CcWrap="${scoreDir}/bin/scorecc -scash -compiler=gnu -compiler-path=$1";;
	    IntelCC)
		CcWrap="${scoreDir}/bin/scorecc -scash -compiler=intel -compiler-path=$1";;
	    PGICC)
		CcWrap="${scoreDir}/bin/scorecc -scash -compiler=pgi -compiler-path=$1 -Masmkeyword";;
	    *)
		CcWrap="${scoreDir}/bin/scorecc -scash -compiler-path=$1";;
	    esac
	    ;;
	*)
	    CcWrap="";;
    esac
}


# backendCC:	'genuine'
#	|	'vendor'
#	|	'cc'
#	|	'gcc'
#	|	'IntelCC'
#	|	'PGICC'
#	|	'SunCC'
#	|	'MipsCC'
#	|	'AIXCC'
#	|	whatever C compiler
#	|	NUL

decodeBackendSpec () {
    backSpec="$1"
    checkNull "${backSpec}"
    if test $? -eq 0; then
	if test "x${runtimeMode}" = "xst"; then
	    CcCom=${stGccCom}
	    CcType=gcc
	else
	    CcCom=${defCcCom}
	    CcType=${defCcType}
	fi
    else
	case "${backSpec}" in
	    cc|vendor|genuine)
		defCc=${sysCc}
		checkExec "${defCc}"
		if test $? -eq 0; then
		    ErrorExit "Can't find a vendor genuine C compiler."
		fi
		getVendorCc "${defCc}";;
	    gcc)
		CcCom=gcc
		CcType=${backSpec};;
 	    IntelCC)
		CcCom=icc
		CcType=${backSpec};;
 	    PGICC)
		CcCom=pgcc
		CcType=${backSpec};;
	    SunCC)
		if test "${OS}" = "solaris"; then
		    CcCom=${sysCc}
		    CcType=${backSpec}
		else
		    ErrorExit "'${backSpec}' is not supported on ${OS}."
		fi;;
	    AIXCC)
		if test "${OS}" = "aix"; then
		    CcCom=${sysCc}
		    CcType=${backSpec}
		else
		    ErrorExit "'${backSpec}' is not supported on ${OS}."
		fi;;
	    MipsCC)
		if test "${OS}" = "irix"; then
		    CcCom=${sysCc}
		    CcType=${backSpec}
		else
		    ErrorExit "'${backSpec}' is not supported on ${OS}."
		fi;;
	    *)
		cCom=`echo ${backSpec} | awk '{ print $1 }'`
		checkExec "${cCom}"
		if test $? -eq 0; then
		    ErrorExit "Can't execute '${cCom}'."
		fi
		getVendorCc "${cCom}"
		if test "${CcType}" = "unknown"; then
		    UnknownCompilerRequest="yes"
		    checkGcc "${cCom}"
		    if test $? -eq 1; then
			CcType=gcc
		    fi
		fi
		CcCom=${backSpec};;
	esac
    fi

    genCcWrap "${CcCom}"
    
    checkExec "${CcCom}"
    if test $? -eq 0; then
	case "$QueryCompilerType" in
	[Nn][On])
	    ErrorExit "Can't execute '${CcCom}'.";;
	esac
    fi

    if test "${lang}" = "C++"; then
	getCxxCom ${CcCom} ${CcType}
	checkExec "${CxxCom}"
	if test $? -eq 0; then
	    ErrorExit "Can't execute '${CxxCom}'."
	fi
    fi
}


# runtime:	lockSpec ':' threadSpec
#	|	'ST'
#	|	'DSM'
#	|	NUL

# lockSpec:	'spin'
#	|	'mutex'

# threadSpec:	'pthread'
#	|	'solaris'
#	|	'sproc'

doScashSMP=0
decodeOmniSpec () {
    runtimeSpec="$1"
    checkNull "${runtimeSpec}"
    if test $? -eq 0; then
	runtimeMode=thread
	lockSpec=${defLock}
	threadSpec=${defThread}
    else
	# check template first.
	if test -f "${omnitmpldir}/${runtimeSpec}.tmpl"; then
	    directTmplMode=1
	    directTemplate="${omnitmpldir}/${runtimeSpec}.tmpl"
	    return
	fi
	case "${runtimeSpec}" in
	    [Ss][Tt]|[Ss][Tt][Aa][Cc][Kk][Tt][Hh][Rr][Ee][Aa][Dd][Ss])
		runtimeMode=st;;
	    [Dd][Ss][Mm])
		runtimeMode=dsm;;
	    [Ss][Hh][Mm][Ee][Mm])
		runtimeMode=shmem;;
	    [Ss][Cc][Aa][Ss][Hh])
		runtimeMode=scash;;
	    [Ss][Cc][Aa][Ss][Hh]_[Ss][Mm][Pp])
		runtimeMode=scash
		doScashSMP=1;;
	    *)
		chk=`echo ${runtimeSpec} | grep '-' 2>/dev/null`
		checkNull "${chk}"
		if test $? -eq 0; then
		    lockSpec=${runtimeSpec}
		    threadSpec=""
		else
		    lockSpec=`echo ${runtimeSpec} | awk -F'-' '{ print $1 }'`
		    threadSpec=`echo ${runtimeSpec} | awk -F'-' '{ print $NF }'`
		fi
		canonicLockName
		canonicThreadName
		checkLock
		if test $? -eq 0; then
		    exit 1
		fi
		checkThread
		if test $? -eq 0; then
		    exit 1
		fi
		checkNull "${ignoreCombo}"
		if test $? -eq 0; then
		    true
		else
		    ignT=`echo ${ignoreCombo} | awk '{ print $1 }'`
		    ignL=`echo ${ignoreCombo} | awk '{ print $NF }'`
		    if test "${ignT}" = "${threadSpec}" -a "${ignL}" = "${lockSpec}"; then
			ErrorExit "A combination of '${ignL}' and '${ignT}' is not supported on ${OS}."
		    fi
		fi
		runtimeMode=thread;;
	esac
    fi
}


decodePragmaSpec () {
    pSpec=`echo "$1" | sed 's/:/ /g'`
    for i in / ${pSpec}
    do
	case ${i} in
	    /)
		continue;;
	    [Oo][Pp][Ee][Nn][Mm][Pp])
		doOpenMP=1;;
	    [Oo][Pp][Ee][Nn][Gg][Rr])
		doOpenGR=1;;
	    *)
		true;;
	esac
    done
}


gRPCDefs=''
gRPCLibs=''
GRPCInit () {
    if test ${doOpenGR} -eq 1; then
	if test "x${GLOBUS_INSTALL_PATH}" = "x"; then
	    ErrorExit "GLOBUS_INSTALL_PATH environmental variable not set. exit."
	fi
	if test "x${NS_DIR}" = "x"; then
	    ErrorExit "NS_DIR environmental variable not set. exit."
	fi
	if test -x "${NS_DIR}/bin/globusflags"; then
	    true
	else
	    ErrorExit "can't find ${NS_DIR}/bin/globusflags. exit."
	fi

	if test "x${gRPCFlavor}" = "x"; then
	    # XXX FIXME:
	    #	Can we use Globus thread-enabled libraries with Omni???
	    #	I don't think so :(
	    #	Inhibit it.
	    gRPCFlavor=-nothreads
	fi
	gRPCOpt=`sh ${NS_DIR}/bin/globusflags GLOBUS_GRAM_CLIENT GLOBUS_IO SSL LDAP ${gRPCFlavor} 2>/dev/null`
	if test $? -eq 0; then
	    for i in / ${gRPCOpt}
	    do
		case ${i} in
		    /)
			continue;;
		    -D*|-I*|-U*)
			gRPCDefs="${gRPCDefs} ${i}";;
		    -L*|-l*)
			gRPCLibs="${gRPCLibs} ${i}";;
		    *)
			true;;
		esac
	    done
	else
	    ErrorExit "can't exec ${NS_DIR}/bin/globusflags. exit."
	fi

	gRPCDefs="-I${NS_DIR}/include -I${NS_DIR}/include/expat ${gRPCDefs} -D_OPENGR"
	gRPCLibs="-L${NS_DIR}/lib -lnsclient -lnslib -lnsutil -lnet -lxmlread ${gRPCLibs}"
    fi
}


genCppRuntimeDef () {
    defs="-D__OMNI__ "
    if test "${runtimeMode}" = "thread"; then
	case "${lockSpec}" in
	    spin)
#		defs="${defs} -DUSE_SPIN_LOCK -D__OMNI_SPIN_LOCK__ ";;
		defs="${defs} -D__OMNI_SPIN_LOCK__ ";;
	    mutex)
		defs="${defs} -D__OMNI_MUTEX_LOCK__";;
	esac

	case "${threadSpec}" in
	    pthread)
#		defs="${defs} -DUSE_PTHREAD -D__OMNI_PTHREAD__";;
		defs="${defs} -D__OMNI_PTHREAD__";;
	    solaris)
#		defs="${defs} -DUSE_SOL_THREAD -D__OMNI_SOLARIS_THREAD__";;
		defs="${defs} -D__OMNI_SOLARIS_THREAD__";;
	    sproc)
#		defs="${defs} -DUSE_SPROC -D__OMNI_SPROC__";;
		defs="${defs} -D__OMNI_SPROC__";;
	esac
    else
	case "${runtimeMode}" in
	    shmem)
#		defs="${defs} -DUSE_UNIX_SHMEM -D__OMNI_SHMEM__";;
		defs="${defs} -D__OMNI_SHMEM__";;
	    scash)
#		defs="${defs} -I${scoreDir}/include -DUSE_SCASH -D__OMNI_SCASH__";;
#		defs="${defs} -I${scoreDir}/include -D__OMNI_SCASH__";;
		defs="${defs} -D__OMNI_SCASH__";;
	    st)
		defs="${defs} -D__OMNI_STACKTHREADS__";;
	esac
    fi
    CppRuntimeDef=${defs}
}


genCppMTSafeDef () {
    if test "${runtimeMode}" = "thread"; then
	CppMTSafeDef=${sysMtSafeDefs}
    else
	CppMTSafeDef=""
    fi
}


genCppCCDependDef () {
    defs=""

    case "${CcType}" in
	gcc)
	    case "${OS}" in
		netbsd*)
		    true;;
		*)
		    defs="-U__GNUC__";;
	    esac;;
	*)
	    true;;
    esac

    CppCCDependDef=${defs}
}


genCcCppOpt () {
    opts=""
    for i in $*
    do
	case "$i" in
	    # generic cc option
	    -D*|-U*|-I*|-c|-o|-S|-l*|-L*)
		true;;
	    # generic omni option
	    -v|-x|-X|-t|-omp)
		true;;
	    -*)
		opts="${opts} $i";;
	    *)
		true;;
	esac
    done

    cCom=`echo ${CcCom} | awk '{ print $1 }'`
    cComOpt=`echo ${CcCom} | sed "s:${cCom}::g"`
    for i in `echo ${cComOpt}`
    do
	case $i in
	    # generic cc option
	    -D*|-U*|-I*|-c|-o|-S|-l*|-L*)
		true;;
	    # generic omni option
	    -v|-x|-X|-t|-omp)
		true;;
	    -*)
		opts="${opts} $i";;
	    *)
		true;;
	esac
    done

    CcCppOpt=${opts}
}


genCppOpt () {
    opts=""

    case "${CcType}" in
	gcc)
#	    opts="-traditional-cpp";;
	    true;;
	SunCC)
	    opts="-Xa";;
	AIXCC)
	    opts="-qflag=w:w";;
	*)
	    true;;
    esac

    CppOpt=${opts}
}


genCcOpt () {
    opts=""

    case "${CcType}" in
	gcc)
	    opts="";;
	SunCC)
	    opts="-Xa";;
	AIXCC)
	    opts="-qflag=w:w";;
	*)
	    true;;
    esac

    CcOpt=${opts}
}



genCpp () {
    if test "${lang}" = "C++"; then
	cDrv=${CxxCom}
    else
	cDrv=${CcCom}
    fi
    if test "x${CcWrap}" = "x"; then
        CppCom="${cDrv} -E"
    else
        CppCom="${CcWrap} -E"
    fi
}


genFpp () {
    execAsCpp=0
    cppForF=""

    FppCom="${omniFpp} -ignore-error"

    if test "${CcType}" = "gcc"; then
	FppCom="${FppCom} -traditional -undef"
    else
	case "${OS}" in
	    solaris)
		if test "${CcType}" != "unknown"; then
		    defCpp=/usr/ccs/lib/cpp
		    if test -x ${defCpp}; then
			cCom=`echo ${CcCom} | awk '{ print $1 }'`
			cComOpt=`echo ${CcCom} | sed "s:${cCom}::g"`
			cppDefs=""
			for i in `echo ${cComOpt}`
			do
			    case $i in
				-D*|-U*|-I*)
				    cppDefs="${cppDefs} $i";;
			    esac
			done
			FppCom="${FppCom} -undef ${cppDefs}"
			execAsCpp=1
			cppForF=${defCpp}
		    fi
		fi;;
	esac
    fi

    cCom=`echo ${CcCom} | awk '{ print $1 }'`
    cComOpt=`echo ${CcCom} | sed "s:${cCom}::g"`
    FppCom="${FppCom} ${cComOpt}"
    if test $execAsCpp -eq 1; then
	OMNI_CC_FOR_F77_CPP_IS_CPP=yes
	export OMNI_CC_FOR_F77_CPP_IS_CPP
	OMNI_CC_FOR_F77_CPP=${cppForF}
    else
	OMNI_CC_FOR_F77_CPP=${cCom}
    fi
    export OMNI_CC_FOR_F77_CPP
}


emitEntry () {
    echo "$1" >> $template
}


genCCEntry () {
    if test "${lang}" = "C++"; then
	cDrv=${CxxCom}
    else
	cDrv=${CcCom}
    fi
    if test "x${CcWrap}" = "x"; then
        emitEntry "CC=${cDrv}"
    else
        emitEntry "CC=${CcWrap}"
    fi
}


IncDir=""
cppInited=0
genCppInit () {
    if test ${cppInited} -eq 0; then
	genCppRuntimeDef
	genCppMTSafeDef
	genCppCCDependDef
	genCppOpt
	genCpp
	genFpp

	IncDir="-I${omniincludedir}"

	CppFlags="${CcCppOpt} ${CppRuntimeDef} ${CppOsDef} ${CppCpuDef} ${CppCCDependDef} ${IncDir}"

	if test ${doOpenMP} -eq 1; then
	    CppFlags="${CppFlags} ${CppMTSafeDef}"
	fi

	if test ${doOpenGR} -eq 1; then
	    CppFlags="${CppFlags} ${gRPCDefs}"
	fi

	cppInited=1
    fi
}


genCppEntry () {
    genCppInit

    case "${lang}" in
	C++)
	    emitEntry "CPP=${CppCom} ${CppOpt} ${CppFlags}";;
	C)
	    emitEntry "CPP=${CppCom} ${CppOpt} ${CppFlags}";;
	F77)
	    emitEntry "CPP=${FppCom} ${CppFlags}";;
    esac
}


genFrontEntry () {
    emitEntry "CFRONT=${omnilibexecdir}/C-front"
    emitEntry "CXXFRONT=${omnilibexecdir}/Cxx-front"
    emitEntry "CFRONT_FLAGS="
    emitEntry "FFRONT=${omnilibexecdir}/F-front"
}


genCflagsEntry () {
    genCcOpt
    genCppInit

    cppccOpt=""
    for i in `echo ${CppFlags}`
    do
	case $i in
	    -D*|-U*|-I*)
		true;;
	    *)
		cppccOpt="${cppccOpt} $i";;
	esac
    done

    emitEntry "OMPC_CFLAGS=${CcOpt} ${cppccOpt}"
}


genMainEntry () {
    case "${runtimeMode}" in
	thread)
	    case "${lang}" in
		C|C++)
		    if test ${doOpenGR} -eq 1; then
			emitEntry "OMPC_MAIN=${omnilibdir}/ogr_main.o"
		    else
			emitEntry "OMPC_MAIN=${omnilibdir}/ompc_main.o"
		    fi;;
		F77)
		    emitEntry "OMPC_F_MAIN=${omnilibdir}/ompf77main.o"
		    emitEntry "OMPC_F_OMP_MAIN=${omnilibdir}/ompf77main_omp.o";;
	    esac;;
	st)
	    case "${lang}" in
		C)
		    emitEntry "OMPC_MAIN=${omnilibdir}/ompc_main_st.o";;
		F77)
		    ErrorExit "StackThreads runtime for Fortran is not avaliable yet. sorry.";;
	    esac;;
	shmem|scash)
	    case "${lang}" in
		C)
		    emitEntry "OMPC_MAIN=${omnilibdir}/ompc_main_sm.o";;
		F77)
		    emitEntry "OMPC_F_MAIN=${omnilibdir}/ompf77main.o"
		    emitEntry "OMPC_F_OMP_MAIN=${omnilibdir}/ompf77main_omp.o";;
	    esac;;
	dsm)
	    ErrorExit "DSM runtime is not avaliable yet. sorry.";;
    esac
}


libSuffix=""
genRuntimeSuffix () {
    case "${runtimeMode}" in
	st)
	    libSuffix="_st";;
	shmem|scash)
	    libSuffix="_sm";;
	dsm)
	    true;;
	thread)
	    libSuffix="_${lockSpec}_${threadSpec}";;
    esac
}


genSystemLibrary () {
    case "${runtimeMode}" in
	st)
	    true;;
	dsm)
	    true;;
	scash)
####	    sysLibs="-L${scoreDir}/lib/${scoreNickname} -lcscash -lscashcrt -lscoreusr -lscorecommon -lpm";;
##	    if test ${doScashSMP} -eq 1; then
####		libScash='-lscash_smp'
##		libScash='-lscash'
##	    else
##		libScash='-lscash'
##	    fi
##	    sysLibs="-L${scoreDir}/lib/${scoreNickname} ${libScash} -lscoreusr -lscorecommon -lpm -lscwrap";;
	    true;;
	thread)
	    case "${threadSpec}" in
		solaris)
		    sysLibs="-lthread";;
		pthread)
		    case "${OS}" in
			solaris)
			    sysLibs="-lpthread -lposix4";;
			freebsd)
			    sysLibs="-pthread";;
			netbsd*)
			    sysLibs="-L/usr/pkg/lib -lpthread";;
			aix)
			    true;;
			cygwin32)
			    true;;
			*)
			    sysLibs="-lpthread";;
		    esac;;
		*)
		   true;;
	    esac;;
    esac

    if test ${doOpenGR} -eq 1; then
	sysLibs="${gRPCLibs} ${sysLibs}"
    fi
}

    
gccLib=""
getLibGcc () {
    if test "${defCcType}" = "gcc" -a "${CcType}" != "gcc"; then
	tmp=/tmp/.OmniConfCC.$$
	${defCcCom} -v > $tmp 2>&1
	if test $? -eq 0; then
	    chk=`head -1 $tmp | awk '{ print $NF }' | sed 's:/specs$::'`
	    if test ! -z "${chk}"; then
		gccLib="-L${chk} -lgcc"
	    fi
	fi
    fi
}


genLinkerEntry () {
    genRuntimeSuffix
    genSystemLibrary
    getLibGcc

    case "${lang}" in
	C|C++)
	    if test ${doOpenGR} -eq 1; then
		emitEntry "OMPC_LDFLAGS=-L${omnilibdir} -logr -lompc${libSuffix} -ltlog -lompc${libSuffix} ${sysLibs} ${gccLib}"
	    else
		emitEntry "OMPC_LDFLAGS=-L${omnilibdir} -lompc${libSuffix} -ltlog -lompc${libSuffix} ${sysLibs} ${gccLib}"
	    fi;;
	F77)
	    libGmp=""
	    if test "x${haveQReal}" = "xyes"; then
		libGmp="${gmpLibOpt}"
	    fi
	    emitEntry "OMPC_F_LDFLAGS=-L${omnilibdir} -lf2c ${libGmp} ${gccLib} -lm"
	    emitEntry "OMPC_F_OMP_LDFLAGS=-L${omnilibdir} -lf2c${libSuffix} -lompc${libSuffix} -ltlog -lompc${libSuffix} ${sysLibs} ${libGmp} ${gccLib} -lm";;
    esac
}


genMiscEntry () {
    case "${lang}" in
	C|C++)
	    emitEntry "APPROVED_DATE=199810"
	    if test ${doOpenGR} -eq 1; then
		emitEntry "NS_DIR=${NS_DIR}"
	    fi;;
	F77)
	    true;;
    esac
}


CreateTemplate () {
    template="/tmp/omni_${lang}.tmpl.$$"
    rm -f ${template}
    touch ${template}

    genCCEntry
    genCppEntry
    genFrontEntry
    genCflagsEntry
    genMainEntry
    genLinkerEntry
    genMiscEntry
}


genTempName () {
    omniTemp="/tmp/omni_${lang}_$$"
}


execBackend () {
    miscOpt=""

    # disabling followings when shmem translator is supported.
    if test "${doJexc}" = "yes"; then
	case "${runtimeMode}" in
	    shmem|scash|st)
		doJexc=no;;
	esac
    fi

    case "${lang}" in
	C|C++)
	    if test "${doJexc}" = "no"; then
		case "${runtimeMode}" in
		    shmem|scash)
			classTop="shm.shmcc";;
		    st)
			classTop="st.stcc";;
		    *)
			if test ${doOpenGR} -eq 1; then
			    classTop="exc.util.ogrcc"
			else
			    classTop="exc.util.ompcc"
			fi;;
		esac
	    else
		case "${runtimeMode}" in
		    shmem|scash)
			jBack="${omnilibexecdir}/C-back.sm";;
		    st)
			jBack="${omnilibexecdir}/C-back.st";;
		    *)
			if test ${doOpenGR} -eq 1; then
			    jBack="${omnilibexecdir}/C-back.ogr"
			else
			    jBack="${omnilibexecdir}/C-back"
			fi;;
		esac
	    fi;;
	F77)
	    if test "${doJexc}" = "no"; then
		case "${runtimeMode}" in
		    shmem|scash)
			classTop="shm.shmf77";;
		    st)
			classTop="st.stf77";;			
		    *)
			classTop="exc.util.ompf77";
		esac
	    else
		case "${runtimeMode}" in
		    shmem|scash)
			jBack="${omnilibexecdir}/F-back.sm";;
		    st)
			jBack="${omnilibexecdir}/F-back.st";;
		    *)
			jBack="${omnilibexecdir}/F-back";;
		esac
	    fi
	    if test ${hasDoubleAlign} -eq 1; then
		miscOpt="-doubleAlign"
	    fi
	    if test "x${gccUnionBug}" = "xyes" -a "${CcType}" = "gcc"; then
		miscOpt="$miscOpt --gcc-huge-common"
	    fi;;
	*)
	    ErrorExit "Unsupported language '${lang}'";;
    esac

    ompcDir=${prefix}
    if test "${doJexc}" = "no"; then
	if test -z "${CLASSPATH}"; then
	    CLASSPATH=${omniclassdir}/exc.jar
	else
	    CLASSPATH=${CLASSPATH}:${omniclassdir}/exc.jar
	fi
	export CLASSPATH

	if test ${directTmplMode} -eq 0; then
	    if test ${doVerbose} -eq 1; then
		echo ${javaCom} ${minJavaMem} ${maxJavaMem} ${maxJavaStack} -DOMPC_DIR=${ompcDir} -DOMPC_TEMPLATE=${template} -DOMPC_TMP=${omniTemp} ${classTop} ${miscOpt} ${1+"$@"}
	    fi
	    ${javaCom} ${minJavaMem} ${maxJavaMem} ${maxJavaStack} -DOMPC_DIR=${ompcDir} -DOMPC_TEMPLATE=${template} -DOMPC_TMP=${omniTemp} ${classTop} ${miscOpt} ${1+"$@"}
	else
	    if test ${doVerbose} -eq 1; then
		echo ${javaCom} ${minJavaMem} ${maxJavaMem} ${maxJavaStack} -DOMPC_DIR=${ompcDir} -DOMPC_TEMPLATE=${directTemplate} -DOMPC_TMP=${omniTemp} ${classTop} ${miscOpt} ${1+"$@"}
	    fi
	    ${javaCom} ${minJavaMem} ${maxJavaMem} ${maxJavaStack} -DOMPC_DIR=${ompcDir} -DOMPC_TEMPLATE=${directTemplate} -DOMPC_TMP=${omniTemp} ${classTop} ${miscOpt} ${1+"$@"}
	fi
    else
	if test ${directTmplMode} -eq 0; then
	    if test ${doVerbose} -eq 1; then
		echo ${jBack} --DOMPC_DIR=${ompcDir} --DOMPC_TEMPLATE=${template} --DOMPC_TMP=${omniTemp} ${miscOpt} ${1+"$@"}
	    fi
	    ${jBack} --DOMPC_DIR=${ompcDir} --DOMPC_TEMPLATE=${template} --DOMPC_TMP=${omniTemp} ${miscOpt} ${1+"$@"}
	else
	    if test ${doVerbose} -eq 1; then
		echo ${jBack} --DOMPC_DIR=${ompcDir} --DOMPC_TEMPLATE=${directTemplate} --DOMPC_TMP=${omniTemp} ${miscOpt} ${1+"$@"}
	    fi
	    ${jBack} --DOMPC_DIR=${ompcDir} --DOMPC_TEMPLATE=${directTemplate} --DOMPC_TMP=${omniTemp} ${miscOpt} ${1+"$@"}
	fi
    fi
}


stderr () {
    echo "$1" 1>&2
}


dumpSpec () {
    if test "x${haveST}" = "xyes"; then
	stderr "		StackThreads"
    fi
    if test "x${haveShmem}" = "xyes"; then
	stderr "		shmem"
    fi
    if test "x${haveScash}" = "xyes"; then
	stderr "		scash"
	stderr "		scash_smp"
    fi
    specs=`ls ${omnilibdir}/libompc_*_*.a | sed -e 's:\.a$::g' -e 's:libompc_::g' -e 's:_:-:g' -e "s:${omnilibdir}/::g"`
    for i in `echo $specs`
    do
	stderr "		$i"
    done
    stderr "		(default: ${defLock}-${defThread})"
}


usage () {
    stderr "Usage:"
    stderr "	$progName [driver-options] [compiler-options] ...."
    stderr
    stderr "driver-options:"
    stderr
    stderr "	-help			display this"
    stderr "	-omniVersion		display Omni version"
    stderr "	-omniconfig=name	specify a name of configuration, listed below:"
    dumpSpec
    stderr "	-omnicc=backend-cc	specify a backend C compiler (default: @CC@)"
    stderr
    stderr "compiler-options:"
    stderr
}

#--------

lang=""
spec=""
backendCcSpec=""
doVerbose=0
pragmaSpec=""
if test ${doOpenMP} -eq 1; then
    pragmaSpec="openmp"
fi
gRPCFlavor=""

progName=`safeBasename $0`

while case "$1" in
    -omniVersion)
	stderr "RWCP Omni OpenMP Compiler version $omniVersion"
	true;;
    -omnilang=*)
	lang=`getArgVal "$1"`
	true;;
    -omniconfig=*)
	spec=`getArgVal "$1"`
	true;;
    -omniVerbose)
	doVerbose=1
	true;;
    -omnicc=*)
	backendCcSpec=`getArgVal "$1"`
	true;;
    -omnitmpl=*)
	tmpl=`getArgVal "$1"`
	if test -f "${omnitmpldir}/${tmpl}.tmpl"; then
	    directTmplMode=1
	    directTemplate="${omnitmpldir}/${tmpl}.tmpl"
	else
	    ErrorExit "can't find template '${omnitmpldir}/${tmpl}.tmpl'"
	fi
	true;;
    -omniForceJavaBackend)
	doJexc="no"
	true;;
    -omnipragma=*)
	pragmaSpec=`getArgVal "$1"`
	true;;
    -omniGridRPCFlavor=*)
	gRPCFlavor=`getArgVal "$1"`
	true;;
    -omniQueryCompilerType)
        QueryCompilerType="yes"
        true;; 
    *)
	false;;
    esac
do
    shift
done


checkNull "${lang}"
if test $? -eq 0; then
    ErrorExit "A language is not specified."
fi

case "${lang}" in
    [Cc]++)
	lang=C++
	progName=omc++;;
    [Cc])
	lang=C
	progName=omcc;;
    [Ff][Oo][Rr][Tt][Rr][Aa][Nn]*|[Ff]77)
	lang=F77
	progName=omf77;;
    *)
	ErrorExit "Unknown language '$lang'";;
esac

doHelp=0
for i in $*
do
    if test "x${i}" = "x-help"; then
	doHelp=1
	break
    fi
done
if test ${doHelp} -eq 1; then
    usage
fi

# signal handler
# HUP
trap "cleanMeUp" 1
# INT
trap "cleanMeUp" 2
# TERM
trap "cleanMeUp" 15

if test -f ${omnitmpldir}/system.conf; then
    . ${omnitmpldir}/system.conf
fi

decodePragmaSpec "${pragmaSpec}"
decodeOmniSpec "${spec}"
if test ${directTmplMode} -eq 0; then
    decodeBackendSpec "${backendCcSpec}"

    if test "${runtimeMode}" = "st"; then
	if test "${haveST}" = "no"; then
	    ErrorExit "StackThreads runtime is not enabled at configuration time of Omni."
	else
	    if test "${lang}" = "F77"; then
		ErrorExit "StackThreads runtime for Fortran is not available yet. sorry."
	    fi
	    if test "${CcCom}" != "${stGccCom}"; then
		Warning "The specified backend C compiler '${CcCom}' is overriden to '${stGccCom}' forcibly."
	    fi
	    CcCom="${stGccCom}"
	    CcType=gcc
	fi
    fi

    if test "${runtimeMode}" = "scash" -a "${haveScash}" = "no"; then
	ErrorExit "Scash runtime is not enabled at configuration time of Omni."
    fi
    if test "${runtimeMode}" = "shmem" -a "${haveShmem}" = "no"; then
	ErrorExit "Shmem runtime is not enabled at configuration time of Omni."
    fi

    if test ${runtimeMode} = "dsm"; then
	ErrorExit "DSM runtime is not enabled with this compile driver yet. sorry."
    fi

    if test "${lang}" = "C"; then
	genCcCppOpt ${1+"$@"}
    fi
fi

checkDoubleAlign ${1+"$@"}
checkDoOpenMPGR ${1+"$@"}

genTempName

if test ${directTmplMode} -eq 0; then
    GRPCInit
    CreateTemplate
    if test ${doVerbose} -eq 1; then
	cat $template
    fi
fi

case "$QueryCompilerType" in
[Yy][Ee][Ss])
    if test "$UnknownCompilerRequest" = "yes"; then
      echo ""
    else 
      echo "${CcType}"
    fi
    cleanMeUp
    exit 0
    ;;
*)
    ;;
esac


execBackend ${1+"$@"}
exitCode=$?
cleanMeUp

exit $?
