#!/bin/csh -f
############################################################################
# RCS INFORMATION:
#
#       $RCSfile: charmc,v $
#       $Author: jyelon $      $Locker:  $              $State: Exp $
#       $Revision: 1.1 $        $Date: 1997/07/30 19:58:00 $
#
############################################################################
# DESCRIPTION:
#
############################################################################
# REVISION HISTORY:
#
############################################################################



##############################################################################
#
# Initialize the main controlling variables, setup error handler
#
# ALL variables used by this script should be initialized here.
#
##############################################################################

unsetenv MACHTYPE
unsetenv SEQUENTIAL
unsetenv LANGUAGE
unsetenv BALANCE
unsetenv MEMORY
unsetenv TRACEMODE
unsetenv VERBOSE
unsetenv SAVE
unsetenv PURIFY
unsetenv OVERRIDE_CC
unsetenv OVERRIDE_CXX
unsetenv OVERRIDE_LD
unsetenv OVERRIDE_LDXX
unsetenv OPTS_CPP       ; set OPTS_CPP = ()
unsetenv OPTS_LDRO      ; set OPTS_LDRO = ()
unsetenv OPTS_CC        ; set OPTS_CC = ()
unsetenv OPTS_CXX       ; set OPTS_CXX = ()
unsetenv OPTS_LD        ; set OPTS_LD = ()
unsetenv OPTS_LDXX      ; set OPTS_LDXX = ()
unsetenv OBJECT
unsetenv COPIES         ; set COPIES = ()
unsetenv LIBRARIES      ; set LIBRARIES = ()
unsetenv FILES          ; set FILES = ()
unsetenv OBJECTFILES    ; set OBJECTFILES = ()
unsetenv DELETE         ; set DELETE = ()
unsetenv MAINOBJ        ; set MAINOBJ = ()
unsetenv GENCPM         ; set GENCPM = ()
unsetenv DEBUG_MODE
unsetenv OPTIMIZE_MODE
unsetenv USE_RELIABLE_CC
unsetenv USE_FASTEST_CC
unsetenv ECHOCMD        ; set ECHOCMD=(unset echo)

##############################################################################
#
# Parse the arguments
#
# Don't do any analysis in here, just the parsing.
#
##############################################################################


set argindex=1
while ($argindex <= $#argv)
    set arg=$argv[$argindex]
    @ argindex = $argindex + 1

    switch ($arg)
        case "-machine"
            set MACHTYPE=$argv[$argindex]
            @ argindex = $argindex + 1
            breaksw

        case "-seq"
	    set SEQUENTIAL=yes
            breaksw

        case "-language"
            set LANGUAGE=$argv[$argindex]
            @ argindex = $argindex + 1
            breaksw

	case "-balance"
            set BALANCE=$argv[$argindex]
            @ argindex = $argindex + 1
            breaksw

        case "-queue"
            echo "Warning: -queue currently being ignored."
            @ argindex = $argindex + 1
            breaksw

        case "-memory"
            echo "Warning: -memory currently being ignored."
            @ argindex = $argindex + 1
            breaksw

	case "-tracemode"
            set TRACEMODE=$argv[$argindex]
            @ argindex = $argindex + 1
            breaksw

        case "-verbose"
            set VERBOSE=1
            set ECHOCMD=(set echo)
            breaksw

        case "-save"
            set SAVE=1
            breaksw

        case "-purify"
            set PURIFY=1
            breaksw

        case "-use-reliable-cc"
	    set USE_RELIABLE_CC=1
            breaksw

	case "-use-fastest-cc"
	    set USE_FASTEST_CC=1
            breaksw
 
        case "-cc"
            set OVERRIDE_CC=( $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-c++"
            set OVERRIDE_CXX=( $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-ld"
            set OVERRIDE_LD=( $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-ld++"
	    set OVERRIDE_LDXX=( $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-cpp-option"
	    set OPTS_CPP=( $OPTS_CPP $argv[$argindex] )
	    @ argindex = $argindex + 1
	    breaksw

        case "-ldro-option"
	    set OPTS_LDRO=( $OPTS_LDRO $argv[$argindex] )
	    @ argindex = $argindex + 1
            breaksw

        case "-cc-option"
            set OPTS_CC=( $OPTS_CC $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-c++-option"
            set OPTS_CXX=( $OPTS_CXX $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-ld-option"
            set OPTS_LD=( $OPTS_LD $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw

        case "-ld++-option"
	    set OPTS_LDXX=( $OPTS_LDXX $argv[$argindex] )
            @ argindex = $argindex + 1
            breaksw
	    
        case "-c":
            # This is ignored.
            breaksw

	case "-o":
            set OBJECT=$argv[$argindex]
            @ argindex = $argindex + 1
            breaksw

	case "-cp"
	    set COPIES=($argv[$argindex] $COPIES)
	    @ argindex = $argindex + 1
            breaksw

        case "-gen-cpm"
            set GENCPM=($GENCPM $argv[$argindex])
            @ argindex = $argindex + 1
            breaksw

        case "-D*"
            set OPTS_CPP=( $OPTS_CPP "$arg" )
            set OPTS_CC= ( $OPTS_CC  "$arg" )
            set OPTS_CXX=( $OPTS_CXX "$arg" )
            breaksw

        case "-I*"
            set OPTS_CPP=( $OPTS_CPP "$arg" )
            set OPTS_CC= ( $OPTS_CC  "$arg" )
            set OPTS_CXX=( $OPTS_CXX "$arg" )
            breaksw

        case "-L*"
            set OPTS_LDRO=( $OPTS_LDRO "$arg" )
            set OPTS_LD=  ( $OPTS_LD   "$arg" )
            set OPTS_LDXX=( $OPTS_LDXX "$arg" )
            breaksw

        case "-g"
	    set DEBUG_MODE=1
            breaksw

	case "-O"
	    set OPTIMIZE_MODE=1
            breaksw

	case "-NO"
	    unset OPTIMIZE_MODE
            breaksw

	case "-pg"
	    set OPTS_CC= ( $OPTS_CC $arg )
	    set OPTS_CXX= ( $OPTS_CC $arg )
	    set OPTS_LD= ( $OPTS_CC $arg )
	    set OPTS_LDXX= ( $OPTS_CC $arg )
            breaksw

        case "-O*"
            set OPTS_CC= ( $OPTS_CC $arg )
            set OPTS_CXX=( $OPTS_CXX $arg )
            breaksw

        case "-l*"
            set LIBRARIES=( $LIBRARIES $arg )
            breaksw

        case "-s"
            set OPTS_LD=  ( $OPTS_LD   $arg )
	    set OPTS_LDXX=( $OPTS_LDXX $arg )
            breaksw

        case "-*"
            echo "passing unrecognized option $arg to all compilers and linkers"
	    set OPTS_CPP= ( $OPTS_CPP  $arg )
            set OPTS_CC=  ( $OPTS_CC   $arg )
            set OPTS_CXX= ( $OPTS_CXX  $arg )
            set OPTS_LD=  ( $OPTS_LD   $arg )
	    set OPTS_LDXX=( $OPTS_LDXX $arg )
            set OPTS_LDRO=( $OPTS_LDRO $arg )
            breaksw

        case "*.*"
            set FILES=( $FILES "$arg" )
            breaksw
        
        default:
            echo "Unrecognized argument $arg"
            exit 1

    endsw
end

##############################################################################
#
# The following section identifies CHARMBIN, the charm binary-directory.
#
##############################################################################

set ORIGDIR=`pwd`

# Try to find CHARMBIN by looking in directory where charmc is

if ($?CHARMBIN == 0) then
    set SCRIPT=$0
    if ($SCRIPT:h != $SCRIPT:t) then
        cd $SCRIPT:h
        set SCRIPT=$SCRIPT:t
    else
        foreach dir ($path)
            if (-x $dir/$SCRIPT && ! -d $dir/$SCRIPT) then
                cd $dir
                break
            endif
        end
    endif
    while (x`find $SCRIPT -type l -print` == x$SCRIPT)
        set SCRIPT=`ls -al ./$SCRIPT:t | sed -e "s@.*-> @@"`
        if ($SCRIPT:h != $SCRIPT:t) then
            cd $SCRIPT:h
            set SCRIPT=$SCRIPT:t
        endif
    end
    set CHARMBIN=`pwd`
endif

# Give an error message

if ($?CHARMBIN == 0) then
    echo ''
    echo 'Error - cannot find the charm binary directory.'
    echo ''
    echo 'Normally, charmc and the other charm scripts automatically'
    echo 'locate the charm binary directory, using the following strategy:'
    echo ''
    echo '  Step 1. It looks in the directory specified in $CHARMBIN'
    echo ''
    echo '  Step 2. It looks in the directory from which charmc was run.'
    echo ''
    echo 'If it searches both these places, and doesnt find the charm'
    echo 'files, it will give up.'
    echo ''
    exit 1
    endif
endif

if ($?MACHTYPE) then
    if (-d $CHARMBIN/../../$MACHTYPE/bin) then
        cd $CHARMBIN/../../$MACHTYPE/bin
	set CHARMBIN=`pwd`
    else
        echo 'error - there is no installed charm for "'$MACHTYPE'"'
        exit 1
    endif
endif

if ($?CHARMLIB == 0) then
    cd $CHARMBIN/../lib
    set CHARMLIB=`pwd`
endif
if ($?CHARMINC == 0) then
    cd $CHARMBIN/../include
    set CHARMINC=`pwd`
endif

##############################################################################
#
# Load machine-specific configuration data, then handle overrides to it.
#
##############################################################################

source $CHARMINC/conv-mach.csh

if ( $?USE_RELIABLE_CC ) then
    set CMK_CC=( $CMK_CC_RELIABLE )
endif

if ( $?USE_FASTEST_CC ) then
    set CMK_CC=( $CMK_CC_FASTEST )
endif

if ($?SEQUENTIAL) then
    set CMK_CC=( $CMK_SEQ_CC )
    set CMK_LD=( $CMK_SEQ_LD )
    set CMK_CXX=( $CMK_SEQ_CXX )
    set CMK_LDXX=( $CMK_SEQ_LDXX )
endif

if ($?OVERRIDE_CC) then
    set CMK_CC[1]=""
    set CMK_CC = ( $OVERRIDE_CC $CMK_CC )
endif

if ($?OVERRIDE_CXX) then
    set CMK_CXX[1]=""
    set CMK_CXX = ( $OVERRIDE_CXX $CMK_CXX )
endif

if ($?OVERRIDE_LD) then
    set CMK_LD[1]=""
    set CMK_LD = ( $OVERRIDE_LD $CMK_LD )
endif

if ($?PURIFY == 1) then
    set CMK_LD = ( purify $CMK_LD )
    set CMK_LDXX = ( purify $CMK_LDXX )
endif

if ($?OVERRIDE_LDXX) then
    set CMK_LDXX[1]=""
    set CMK_LDXX = ( $OVERRIDE_LDXX $CMK_LDXX )
endif

if ($?DEBUG_MODE) then
    set OPTS_CC  = ( $CMK_C_DEBUG $OPTS_CC )
    set OPTS_CXX = ( $CMK_CXX_DEBUG $OPTS_CXX )
    set OPTS_LD  = ( $CMK_C_DEBUG $OPTS_LD )
    set OPTS_LDXX = ( $CMK_CXX_DEBUG $OPTS_LDXX )
endif

if ($?OPTIMIZE_MODE) then
    set OPTS_CC  = ( $CMK_C_OPTIMIZE $OPTS_CC )
    set OPTS_CXX = ( $CMK_CXX_OPTIMIZE $OPTS_CXX )
    set OPTS_LD  = ( $CMK_C_OPTIMIZE $OPTS_LD )
    set OPTS_LDXX = ( $CMK_CXX_OPTIMIZE $OPTS_LDXX )
endif

onintr failure

##############################################################################
#
# Check for valid choice of LANGUAGE
#
##############################################################################

if ($?LANGUAGE == 0) then
    set LANGUAGE=charm
    if ($?SEQUENTIAL) set LANGUAGE=c
endif

switch ($LANGUAGE)
    case "c"
    case "C"
    case "c++"
    case "C++"
	if ($?SEQUENTIAL == 0) then
	    echo "Language $LANGUAGE is for sequential programs"
	    goto failure
	endif
	breaksw
    case "charm" 
    case "charm++" 
    case "converse"
    case "converse++"
	if ($?SEQUENTIAL == 1) then
	    echo "Language $LANGUAGE is for parallel programs"
	    goto failure
	endif
        breaksw
    default:
        echo "charmc: Unrecognized choice of language $LANGUAGE"
	goto failure
endsw

cd $ORIGDIR

##############################################################################
#
# Preprocess the GEN-CPM files
#
##############################################################################

foreach FILE ($GENCPM)
    set BASE=$FILE:r
    set TMP=$BASE:t.TMP
    set DELETE=($DELETE $TMP.c $TMP.i)
    ($ECHOCMD ; /bin/rm -f $BASE.cpm.h $TMP.c)
    ($ECHOCMD ; touch $BASE.cpm.h)
    ($ECHOCMD ; /bin/ln -s $FILE $TMP.c)
    ($ECHOCMD ; $CMK_CPP_C $OPTS_CPP -I$CHARMINC $TMP.c > $TMP.i)
    if ($status) goto failure
    ($ECHOCMD ; $CHARMBIN/conv-cpm $TMP.i $BASE.cpm.h)
    if ($status) goto failure
end

##############################################################################
#
# Compile all specified files
#
# All temporary files named *.TMP.* for easy cleanup.
#
##############################################################################

foreach FILE ($FILES)
  set BASE=$FILE:r
  set TMP=$BASE:t.TMP
  if (${BASE}.o != $FILE) then
      if ($?VERBOSE) echo "compiling $FILE."
      /bin/rm -f $BASE.o $BASE.f.o
  endif
  switch ($FILE)
    case "*.p"
      set DELETE=($DELETE $BASE.headers)
      ($ECHOCMD ; $CMK_CPP_CHARM $OPTS_CPP -I$CHARMINC $BASE.p > $TMP.cpp)
      ($ECHOCMD ; $CHARMBIN/charmfilter < $TMP.cpp | $CMK_M4 > $TMP.space)
      ($ECHOCMD ; $CHARMBIN/charmxlat $TMP.space $TMP.c)
      if ($status) goto failure
      ($ECHOCMD ; $CMK_CC $OPTS_CC -I$CHARMINC -c $TMP.c -o $TMP.o)
      if ($status) goto failure
      if ($?OBJECT == 0) then
          ($ECHOCMD ; /bin/mv $TMP.o $BASE.o)
      else
          set OBJECTFILES=( $OBJECTFILES $TMP.o )
      endif
      breaksw
    case "*.P"
      # Put pgm.P into pgm.TMP.P.C because CC needs source files to end with .C
      echo '#include "ckdefs.h"' > $TMP.P.C
      echo '#include "chare.h"' >> $TMP.P.C
      echo '#include "c++interface.h"' >> $TMP.P.C
      echo '#line 1 "'$BASE.P'"' >> $TMP.P.C
      /bin/cat $BASE.P >> $TMP.P.C
      ($ECHOCMD ; $CMK_CXXPP $OPTS_CPP -I$CHARMINC $TMP.P.C > $TMP.cpp)
      ($ECHOCMD ; $CHARMBIN/$CMK_XLATPP $TMP.cpp $TMP.xlat)
      if ($status) goto failure
      ($ECHOCMD ; /bin/cat $BASE.headers > $TMP.$CMK_CPP_SUFFIX)
      ($ECHOCMD ; /bin/cat $TMP.xlat >> $TMP.$CMK_CPP_SUFFIX)
      ($ECHOCMD ; $CMK_CXX $OPTS_CXX -I$CHARMINC -c $TMP.$CMK_CPP_SUFFIX -o $TMP.o)
      if ($status) goto failure
      if ($?OBJECT == 0) then
        ($ECHOCMD ; /bin/mv $TMP.o $BASE.o)
      else
        set OBJECTFILES=( $OBJECTFILES $TMP.o )
      endif
      breaksw
    case "*.ci"
      ($ECHOCMD ; $CHARMBIN/charmxi $BASE.ci)
      if ($status) goto failure
      breaksw
    case "*.c"
      ($ECHOCMD ; $CMK_CC $OPTS_CC -I$CHARMINC -c $BASE.c -o $BASE.o)
      if ($status) goto failure
      if ($?OBJECT) then
	if ($OBJECT != $BASE.o) set DELETE=( $DELETE $BASE.o )
        set OBJECTFILES=( $OBJECTFILES $BASE.o )
      endif
      breaksw
    case "*.c"
      ($ECHOCMD ; $CMK_CC $OPTS_CC -I$CHARMINC -c $BASE.c -o $BASE.o)
      if ($status) goto failure
      if ($?OBJECT) then
	if ($OBJECT != $BASE.o) set DELETE=( $DELETE $BASE.o )
        set OBJECTFILES=( $OBJECTFILES $BASE.o )
      endif
      breaksw
    case "*.s"
      ($ECHOCMD ; $CMK_CC $OPTS_CC -I$CHARMINC -c $BASE.s -o $BASE.o)
      if ($status) goto failure
      if ($?OBJECT) then
	if ($OBJECT != $BASE.o) set DELETE=( $DELETE $BASE.o )
        set OBJECTFILES=( $OBJECTFILES $BASE.o )
      endif
      breaksw
    case "*.C"
      ($ECHOCMD ; $CMK_CXX $OPTS_CXX -I$CHARMINC -c $BASE.C -o $BASE.o)
      if ($status) goto failure
      if ($?OBJECT) then
	if ($OBJECT != $BASE.o) set DELETE=( $DELETE $BASE.o )
        set OBJECTFILES=( $OBJECTFILES $BASE.o )
      endif
      breaksw
    case "*.cxx"
      ($ECHOCMD ; $CMK_CXX $OPTS_CXX -I$CHARMINC -c $BASE.cxx -o $BASE.o)
      if ($status) goto failure
      if ($?OBJECT) then
	if ($OBJECT != $BASE.o) set DELETE=( $DELETE $BASE.o )
        set OBJECTFILES=( $OBJECTFILES $BASE.o )
      endif
      breaksw
    case "*.f"
    case "*.F"
    case "*.fc"
    case "*.FC"
      echo "charmc: I'm not yet smart enough to compile $FILE"
      goto failure
    case "*.o"
    case "*.a"
      set OBJECTFILES=( $OBJECTFILES $BASE.o )
      breaksw
    default:
      echo "file with unrecognized extension $FILE"
      goto failure
  endsw
end

##############################################################################
#
#                        POSSIBLY, SKIP LINK-STEP
#
# 1. No $OBJECT may be specified at all --- its just a compilation.
# 2. If $OBJECT is a ".a" file, a library is created from $OBJECTFILES.
# 3. If $OBJECT is a ".o" file, then an "LDRO" is created from $OBJECTFILES.
# 4. Language may be sequential.  Do a quick and easy linkage.
#
#               in any of these cases, the full link step is skipped.
#
##############################################################################

if ($?OBJECT == 0) goto success

switch ($OBJECT)
  case "*.o":
    if (($#FILES == 1)&&($#OBJECTFILES == 1)) then
        if ($OBJECT != $OBJECTFILES) then
            rm -f $OBJECT
            ($ECHOCMD ; /bin/mv $OBJECTFILES $OBJECT)
            if ($status) goto failure
        endif
    else
        rm -f $OBJECT
        ($ECHOCMD ; $CMK_LDRO $OBJECT $OPTS_LDRO $OBJECTFILES)
        if ($status) goto failure
    endif
    goto copyobj

  case "*.a":
    ($ECHOCMD ; rm -f $OBJECT)
    ($ECHOCMD ; $CMK_AR $OBJECT $OBJECTFILES)
    if ($status) goto failure
    ($ECHOCMD ; $CMK_RANLIB $OBJECT)
    if ($status) goto failure
    goto copyobj
endsw

switch ($LANGUAGE)
    case "c"
    case "C"
        ($ECHOCMD ; $CMK_SEQ_LD $OPTS_LD -o $OBJECT $OBJECTFILES -L$CHARMLIB $LIBRARIES $CMK_SEQ_LIBS)
        if ($status) goto failure
        goto copyobj
        breaksw
    case "c++"
    case "C++"    
        ($ECHOCMD ; $CMK_SEQ_LDXX $OPTS_LD -o $OBJECT $OBJECTFILES -L$CHARMLIB $LIBRARIES $CMK_SEQ_LIBS)
        if ($status) goto failure
        goto copyobj
        breaksw
endsw

##############################################################################
#
# Some quick consistency checks prior to full link-step
#
# Check for valid choice of TRACEMODE
# Check for valid choice of BALANCE
# Check for compatibility among BALANCE and TRACEMODE
#
##############################################################################

# Check for valid choice of TRACEMODE

if (($LANGUAGE == charm) || ($LANGUAGE == charm++)) then

    if (! -e $CHARMLIB/libck-trace-none.a) then
        echo "charmc: charm libraries not installed."
        goto failure
    endif
    
    if ($?TRACEMODE == 0) set TRACEMODE=none

    if (! -e $CHARMLIB/libck-trace-$TRACEMODE.a) then
       echo "charmc : No such tracemode $TRACEMODE"
       (cd $CHARMLIB ; ls -al libck-trace-*)
       goto failure
    endif

endif

# Check for valid choice of BALANCE

if (($LANGUAGE == charm) || ($LANGUAGE == charm++)) then

    if ($?BALANCE == 0) set BALANCE=rand

    # Check that TRACEMODE is compatible with BALANCE

    if ($TRACEMODE == replay) then
        if ($?BALANCE == 0) set BALANCE=replay
        if ($BALANCE != replay) then
            echo "Ignoring -balance $BALANCE, incompatible with -tracemode replay"
        endif
        set BALANCE=replay
    endif

endif

# Check that the BAL_OBJ exists

if (($LANGUAGE == charm) || ($LANGUAGE == charm++)) then

    if ($BALANCE:h == $BALANCE) then
       set BAL_OBJ = $CHARMLIB/libck-ldb-$BALANCE.o
    else
       set BAL_OBJ = $BALANCE
    endif
    
    if (! -e $BAL_OBJ) then
       if ($BALANCE == $BAL_OBJ) then
    	echo "charmc : Could not find load balancer object $BAL_OBJ"
       else
    	echo "charmc : Unknown load balancer $BALANCE"
    	(cd $CHARMLIB ; ls -al libck-ldb-*)
       endif
       goto failure
    endif

endif

###############################################################################
# 
# Make sure all temp-files created during linkage get deleted.
#
###############################################################################

set DELETE=(CHARMC-PRE.TMP.xxx CHARMC-PRE.TMP.nm $DELETE)
set DELETE=(CHARMC-MOD.TMP.dat CHARMC-MOD.TMP.c CHARMC-MOD.TMP.o $DELETE)
rm -f CHARMC-PRE.TMP.xxx CHARMC-PRE.TMP.nm
rm -f CHARMC-MOD.TMP.dat CHARMC-MOD.TMP.c CHARMC-MOD.TMP.o

###############################################################################
#
# 			Create CHARMC-MOD.TMP.c
#
# This file contains the function _CK_module_init_fn, which
# initializes each charm or charm++ module in turn.   Its creation
# is highly system-dependent, which is why I have all these
# nested if-statements here.
#
###############################################################################

if (($LANGUAGE == charm) || ($LANGUAGE == charm++)) then
    if ($LANGUAGE == charm) then
	echo '_CK_module_init_fn() {}' > CHARMC-MOD.TMP.c
	($ECHOCMD ; $CMK_CC $OPTS_CC -c -o CHARMC-MOD.TMP.o CHARMC-MOD.TMP.c)
        ($ECHOCMD ; $CMK_LD $OPTS_LD -o CHARMC-PRE.TMP.xxx -L$CHARMLIB \
                      $BAL_OBJ $OBJECTFILES $LIBRARIES \
		      CHARMC-MOD.TMP.o -lck-core -lck-trace-$TRACEMODE \
                      -lck-cplus-n -lconv-cplus-n -lconv-core \
		      -lck-defmain-std -lcharm $CMK_LIBS -lm)
    else if ($LANGUAGE == charm++) then
	echo '_CK_module_init_fn() {}' > CHARMC-MOD.TMP.c
	($ECHOCMD ; $CMK_CC $OPTS_CC -c -o CHARMC-MOD.TMP.o CHARMC-MOD.TMP.c)
        ($ECHOCMD ; $CMK_LDXX $OPTS_LDXX -o CHARMC-PRE.TMP.xxx -L$CHARMLIB \
		      $BAL_OBJ $OBJECTFILES $LIBRARIES \
		      CHARMC-MOD.TMP.o -lck-core -lck-trace-$TRACEMODE \
                      -lck-cplus-y -lconv-cplus-y -lconv-core \
		      -lck-defmain-cpp -lcharm $CMK_LIBS -lm)
    endif
    rm -f CHARMC-PRE.TMP.nm
    strings -a CHARMC-PRE.TMP.xxx | awk '/^charmc autoinit / { print $3; }' > CHARMC-PRE.TMP.nm
    sort < CHARMC-PRE.TMP.nm | uniq > CHARMC-MOD.TMP.dat
    echo 'Charm Modules: '`cat CHARMC-MOD.TMP.dat`
    rm -f CHARMC-MOD.TMP.c
    awk '{print "extern void _CK_"$1"_init();";}' < CHARMC-MOD.TMP.dat >> CHARMC-MOD.TMP.c
    echo '_CK_module_init_fn()' >> CHARMC-MOD.TMP.c
    echo '{' >> CHARMC-MOD.TMP.c
    awk '{print "_CK_"$1"_init();";}' < CHARMC-MOD.TMP.dat >> CHARMC-MOD.TMP.c
    echo '}' >> CHARMC-MOD.TMP.c
    ($ECHOCMD ; $CMK_CC $OPTS_CC -c CHARMC-MOD.TMP.c)
    if ($status) goto failure
endif

###############################################################################
#
#                               Finally, LINK
#
###############################################################################

switch ($LANGUAGE)
    case "charm"
        ($ECHOCMD ; $CMK_LD $OPTS_LD -o $OBJECT -L$CHARMLIB \
                      CHARMC-MOD.TMP.o $BAL_OBJ $OBJECTFILES \
                      $LIBRARIES -lck-core -lck-trace-$TRACEMODE \
                      -lck-cplus-n -lconv-cplus-n -lconv-core \
		      -lck-defmain-std -lcharm $CMK_LIBS -lm)
        breaksw
    case "charm++"
        ($ECHOCMD ; $CMK_LDXX $OPTS_LDXX -o $OBJECT -L$CHARMLIB \
		      CHARMC-MOD.TMP.o $BAL_OBJ $OBJECTFILES \
                      $LIBRARIES -lck-core -lck-trace-$TRACEMODE \
                      -lck-cplus-y -lconv-cplus-y -lconv-core \
		      -lck-defmain-cpp -lcharm $CMK_LIBS -lm)
        breaksw
    case "converse"
        ($ECHOCMD ; $CMK_LD $OPTS_LD -o $OBJECT -L$CHARMLIB \
		      $OBJECTFILES $LIBRARIES -lconv-cplus-n -lconv-core\
		      $CMK_LIBS -lm)
        breaksw
    case "converse++"
        ($ECHOCMD ; $CMK_LDXX $OPTS_LDXX -o $OBJECT -L$CHARMLIB \
		      $OBJECTFILES $LIBRARIES -lconv-cplus-y -lconv-core \
		      $CMK_LIBS -lm)
        breaksw
endsw

########################################################################
#
# Copy conv-host to user directory if it is present in installation.
#
########################################################################

if (-e $CHARMBIN/conv-host) then
    /bin/rm -f conv-host
    /bin/ln -s $CHARMBIN/conv-host conv-host
endif

########################################################################
#
# copyobj: if -cp specified, copy the resulting output file.
#
########################################################################

copyobj:

foreach x ($COPIES)
    if ($x != $OBJECT) then
	set COPY=$x
	if (-d $COPY) set COPY=$COPY/$OBJECT
        ($ECHOCMD ; /bin/rm -f $COPY ; /bin/cp $OBJECT $COPY)
    endif
end

goto success

########################################################################
#
# Clean up files and exit
#
########################################################################

success:

    set STATUS=0
    goto end

failure:

    echo 'charmc: aborting.'
    set STATUS=1
    goto end

end:

    if ($?SAVE == 0) then
        foreach FILE ($FILES)
            set BASE=$FILE:r
            set TMP=$BASE:t.TMP
            /bin/rm -f $TMP.P.C $TMP.cpp $TMP.space $TMP.xlat $TMP.o
            /bin/rm -f $TMP.c $TMP.c.0.h $TMP.c.1.h $TMP.c.2.h
            /bin/rm -f $TMP.i $TMP.$CMK_CPP_SUFFIX
        end
        rm -f core $DELETE
    endif
    exit ($STATUS)
