#! /bin/sh

## begin copyright #######################################################
#
#                        Mathematica source file
#
#        Copyright 1986 through 2012 by Wolfram Research Inc.
#
#         Program: mcc - Mathematica MathLink Template Compiler
#        Language: Bourne Shell
#
######################################################### end copyright ##

mcc_name="Wolfram Mathematica MathLink Template Compiler"

# Define mcc_verbose here so that it is visible in all the function definitions
mcc_verbose="no"
mcc_verbose_log="/tmp/mcc_verbose_$$.log"

# find_mldk_dir
# The function searches for the path to the MathLink Developer Kit CompilerAdditions directory
#
# Returns: a string with the path to the mcc directory
find_mldk_dir()
{
spath=`expr "$0"'/' : '\(/\)[^/]*//*$' \| "$0"'/' : \
            '\(.*[^/]\)//*[^/][^/]*//*$' \| .`

if [ "." = "$spath" ]; then
   MLPATH=`pwd`
else
   if [ ".`(echo $spath | grep \"^/\")`" = ".$spath" ]; then
      MLPATH="$spath"
   else
      MLPATH="`pwd`/$spath"
   fi
fi
echo ${MLPATH}
}


# find_default_C_compiler
# The function uses a list of default C compilers and searches all the
# directories available from $PATH for a compiler
#
# Arguments:
#        $1 - The platform ID (the result of `uname`)
#
# Returns: a string containing the path to the discovered C compiler
find_default_C_compiler()
{
if [ "$1" = "Darwin" ] ; then
	c_compilers="clang gcc cc"
else
	c_compilers="gcc cc"
fi

path_dirs=`echo $PATH | sed -e 's/:/ /g'`

for p in ${path_dirs}; do
	for c in ${c_compilers} ; do
		if [ -x "${p}/${c}" ] ; then
			c_compiler="${p}/${c}"
			break
		fi
	done
	if [ ! -z "${c_compiler}" ] ; then
		break
	fi
done

echo ${c_compiler}
}


# find_default_CXX_compiler
# The function uses a list of default C++ compilers and searches all the
# directories available from $PATH for a compiler
#
# Arguments:
#        $1 - The platform ID (the result of `uname`)
#
# Returns: a string containing the path to the discovered C++ compiler
find_default_CXX_compiler()
{
if [ "$1" = "Darwin" ] ; then
	cxx_compilers="clang++ g++ c++"
else
	cxx_compilers="g++ c++ gcc-c++"
fi

path_dirs=`echo $PATH | sed -e 's/:/ /g'`

for p in ${path_dirs}; do
	for c in ${cxx_compilers} ; do
		if [ -x "${p}/${c}" ] ; then
			cxx_compiler="${p}/${c}"
			break
		fi
	done
	
	if [ ! -z "${cxx_compiler}" ] ; then
		break
	fi
done

echo ${cxx_compiler}
}


# find_compilers
# The function checks $CC and $CXX first for compilers.  If
# $CC and/or $CXX are not set the function calls find_default_C_compiler
# and/or find_default_CXX_compiler to locate a suitable compiler
#
# Arguments
#       $1 - The platform ID (the result of `uname`)
#       $2 - String of either "C" or "C++" indicating which compiler value
#            to return
#
# Returns: either a string containing the path to the located C compiler
#          or the located C++ compiler
find_compilers()
{
if [ "$2" = "C" ] ; then
	if [ ! -z "${CC}" ] ; then
		echo ${CC}
	else
		echo `find_default_C_compiler $1`
	fi
elif [ "$2" = "C++" ] ; then
	if [ ! -z "${CXX}" ] ; then
		echo ${CXX}
	else
		echo `find_default_CXX_compiler $1`
	fi
fi
}

# Various string values used in the test program and later in this script
bit32="32"
bit64="64"
bit3264="32/64"


# get_compilation_flags
# The function uses the test program and stored compiler settings to 
# determine the proper compilation flags
#
# Arguments:
#        $1 - 32, 64, or 32/64 (as strings)
#        $2 - platform id (result of `uname`)
#        $3 - architecture id (generated by the test program)
#        $4 - compiler id (generated by the test program)
#        $5 - the C++ compiler
#        $6 - yes or no indicating whether to try all possible OSX architectures
#             or just use the default architecture of the currently running system
#
# Returns: a string containing the proper compiler flags for the identified compiler
get_compilation_flags()
{
bitsize=$1
platform=$2
archi=$3
compiler=$4
native_only=$5

# With Clang, target architecture is set by the -arch flag
if [ "${platform}" = "Darwin" ] ; then
	if [ "${native_only}" = "no" ] ; then
		if [ ${bitsize} = ${bit32} ] ; then
			arch_flags="-arch i386"
		elif [ ${bitsize} = ${bit64} ] && [ "${archi}" = "x86_64" ] ; then
			arch_flags="-arch x86_64"
		fi
	fi
else  # With gcc, target architecture is set by the -m32 and -m64 flags
	if [ ${bitsize} = ${bit32} ] ; then
		arch_flags="-m32"
	elif [ ${bitsize} = ${bit64} ] && [ "${archi}" = "x86_64" ] ; then
		arch_flags="-m64"
	fi
fi
echo ${arch_flags}
}


# get_linker_libraries
# The function determines the correct system libraries for use in
# linking the MathLink binary
#
# Arguments:
#        $1 - platform id (result of `uname`)
#        $2 - yes or no indicating whether to use the .a or the .so library
#             (currently not valid on OSX)
#        $3 - MathLink interface number
#        $4 - 32 or 64 (as strings)
#        $5 - path to MathLink Developer Kit CompilerAdditions directory
#
# Returns: a string containing the libraries to link into the MathLink program
get_linker_libraries()
{

platform=$1
dynamic=$2
interface=$3
bittype=$4
mldkpath=$5

if [ "${platform}" = "Darwin" ] ; then
	if [ "$dynamic" = "yes" ]; then
		libs="-lc++ -F ${mldkpath} -framework mathlink -framework Foundation"
	else
		libs="-lc++ ${mldkpath}/libMLi${interface}.a -framework Foundation"
	fi
elif [ "${platform}" = "Linux" ] ; then
	if [ ${bittype} = ${bit32} ] ; then
		libname="${mldkpath}/libML32i${interface}"
	elif [ ${bittype} = ${bit64} ] ; then
		libname="${mldkpath}/libML64i${interface}"
	fi

	if [ "${dynamic}" = "yes" ] ; then
		libs="${libname}.so -lm -lpthread -lrt -ldl -lstdc++ -luuid"
	else
		libs="${libname}.a -lm -lpthread -lrt -ldl -lstdc++ -luuid"
	fi
elif [ "${platform}" = "CYGWIN" ] ; then
	libs="-lstdc++ ${mldkpath}/../lib/libML32i${interface}.a -lGdi32"
fi

echo ${libs}
}


# messages with spaces need to be stored with _ instead of the spaces
# for generate_ok_message_awk_script() to correctly put the whole string
# into the awk script.
mcc_ok_compiler_messages="
-xarch=native_has_been_explicitly_specified
"

# generate_ok_messages_awk_script
# The function creates an script suitable for parsing compiler output.
# The goal is to swallow harmless compiler warnings from compilers such as
# the Sun Studio compiler that generates things like:
# 
# cc: Warning: -xarch=native has been explicitly specified, or implicitly 
# specified by a macro option, -xarch=native on this architecture implies 
# -xarch=sparcvis which generates code that does not run on pre UltraSPARC 
# processors
#
# The warning is perfectly harmless, but there is no good way to disable
# the warning without generating other equally harmless warnings.  Instead
# we just swallow the warnings and only spit back warnings/errors that do
# not match the list in ${mcc_ok_compiler_messages}
#
# Arguments
#        $1 - the file name that will hold the awk script
generate_ok_messages_awk_script()
{
filename=$1
touch ${filename}
for message in ${mcc_ok_compiler_messages}
do
	echo "! /${message}/ { print }" | sed -e 's/_/ /g' >> ${filename}
done
}


# compile_files
# The function process the list of input files and compiles them to object files.
# The function can compile either C or C++ source files.
#
# Arguments:
#        $1 - the compiler
#        $2 - the compiler arguments
#        $3 - the source files
#        $4 - the file extension to use for the output file.  This argument is used
#             to support the -P command line flag for mcc that outputs the preprocesses
#             source files to files ending in the .i extension
#        $5 - the awk script filename
#        $6 - yes or no indicating whether to be verbose and report actions.
#        $7 - The compiler output log filename
#
# Returns: a list of the compiled object file names
compile_files()
{
compiler=$1
args=$2
files=$3
fileextension=$4
verbose=$5
compile_log=$6
tmp_log="/tmp/mcc_tmp_$$.log"

for file in ${files}
do
	fileroot=`echo ${file} | sed -e 's/\(.*\)\..*/\1/'`
	fileoutputname=${fileroot}${fileextension}

	${compiler} ${args} -o ${fileoutputname} ${file} >> ${tmp_log} 2>&1
	
	if [ "${verbose}" = "yes" ] ; then
		echo "${compiler} ${args} -o ${fileoutputname} ${file}" >> ${compile_log}
		cat ${tmp_log} >> ${compile_log}
	else
		if [ -s ${tmp_log} ] ; then
			echo "${file}: `cat ${tmp_log}`" >> ${compile_log}
		fi
	fi

	rm -rf ${tmp_log}

	if [ -f ${fileoutputname} ] ; then
		object_files="${object_files} ${fileoutputname}"
	fi
done
echo ${object_files}
}


# handle_compiler_log
# The function handles the display of the compiler log file
#
# Arguments:
#        $1 - the compiler log file name.
#        $2 - the awk file name
handle_compiler_log()
{
logfile=$1
awkfile=$2
if [ -s ${logfile} ] ; then
	cat ${logfile} | awk -f ${awkfile}
	rm -rf ${logfile}
fi
}


# mcc_usage
# The function generates a usage message for mcc
mcc_usage()
{
  cat <<EOF
${mcc_name}
Usage: $0 [options]
Example: $0 addtwo.tm addtwo.c -o addtwo.exe
Description: this script automates the process of calling prep tool to build c-code files 
from  template (.tm) files and then calls the local compiler to build the resulting code. 
In addition to options listed below, compiler and linker options can be passed in. 
Options:
  --help     print this message
  --version  only print version information
  --verbose  print steps in compiling executable
  -g         keep the C file generated by mprep and pass the -g option
             to the C/C++ compilers to generate a symbol table for debugging
  -E         pass the .tm files through mprep, then run the C source files
             through the C compiler only, then run the C++ files through the 
             C++ compiler only, sending the output to stdout
  -P         pass the .tm files through mprep, then run the C source files
             through the C compiler only, then run the C++ files through the
             C++ compiler only, writing the output to files with .i suffixes
  -xo name   write the output in name/$1/name, to be located by
             Install["name"]
  -n         generate native only binaries, the -n flag will supercede other 
             architecture flags. [An OS X option only.  Currently available 
             OS X compilers generate ppc and i386 architectures as the default
             native architectures even if the system supports the ppc64 and/or 
             x86_64 architecture]         
  -dy        dynamically link mathlink (default is static) 
  -b32       generate a 32-bit binary
  -b64       generate a 64-bit binary
  -b32_64    generate a binary with both 32 and 64-bit architectures on 
             Mac OS X
EOF

  if [ "$1" = "MacOSX-x86-64" ] ; then
	cat <<EOF

  Mac OS X special considerations:

  $0 on Mac OS X by default will attempt to build Universal binaries.
  Currently, the template compiler can create MathLink programs for the 
  i386, and x86_64 CPU architectures.  The template compiler checks 
  the currently running system to see which architectures the compiler can 
  support and automatically builds that set of architectures into the 
  MathLink program. 

EOF
  fi


  exit 10

}


# mcc_no_argument_message
# The function generates a simple help message for mcc when mcc is called without arguments
mcc_no_argument_message()
{
  cat <<EOF
${mcc_name}
Usage: Use --help argument for more information.
EOF
}

# Check to see if we have actual arguments
if [ $# -eq 0 ] ; then
	mcc_no_argument_message
	exit 0
fi

# Detect the current system and set initial values

mcc_platform=`uname`
mcc_version=7.0.1
mcc_systemid=Linux-ARM
mcc_mathlink_interface=4
mcc_mldk_dir=`find_mldk_dir $0`
mcc_c_compiler=`find_compilers ${mcc_platform} "C"`
if [ "${mcc_c_compiler}" = "" ] ; then
	echo "$0: cannot find C compiler, $0 requires a C compiler"
	exit 11
fi

mcc_cxx_compiler=`find_compilers ${mcc_platform} "C++"`
if [ "${mcc_cxx_compiler}" = "" ] ; then
	echo "$0: cannot find C++ compiler, $0 requires a C++ compiler"
	exit 11
fi

if [ `uname -m` = "x86_64" ] || [ `uname -m` = "amd64" ]; then 
	mcc_architecture="x86_64"
else 
	mcc_architecture="x86" 
fi

mcc_awk_message_file="/tmp/mccawkmessage_$$.awk"
mcc_compiler_log="/tmp/mcc_compiler_output_$$.log"

# Set the default values for command-line oriented variables
mcc_preprocess_to_stdout="no"
mcc_preprocess_to_i="no"
mcc_compile_only="no"
mcc_output_filename="a.out"
mcc_native_only="no"
mcc_debug_compile="no"
mcc_generate_32bit_binary="no"
mcc_generate_64bit_binary="no"
mcc_generate_3264bit_binary="no"
mcc_object_file_extension=".o"
mcc_use_the_dynamic_library="no"
mcc_print_variable_values="no"

# Parse the command line options
count=$#
while [ $count -ne 0 ]
do
	case "$1" in
		--help|-h)
			mcc_usage ${mcc_systemid}
			exit 0
			;;
		--version|-v)
			echo ${mcc_version}
			exit 0
			;;
		--verbose)
			mcc_verbose="yes"
			;;
		-b32)
			mcc_generate_32bit_binary="yes"
			if [ "${mcc_generate_64bit_binary}" = "yes" -a "${mcc_platform}" = "Darwin" ] ; then
				mcc_generate_3264bit_binary="yes"
				mcc_generate_32bit_binary="no"
				mcc_generate_64bit_binary="no"
			elif [ "${mcc_generate_64bit_binary}" = "yes" -a ! "${mcc_platform}" = "Darwin" ] ; then
				echo "$0: -b32 and -b64 are mutually exclusive on this platform"
				exit 12
			fi
			;;
		-b64)
			mcc_generate_64bit_binary="yes"
			if [ "${mcc_generate_32bit_binary}" = "yes" -a "${mcc_platform}" = "Darwin" ] ; then
				mcc_generate_3264bit_binary="yes"
				mcc_generate_32bit_binary="no"
				mcc_generate_64bit_binary="no"
			elif [ "${mcc_generate_32bit_binary}" = "yes" -a ! "${mcc_platform}" = "Darwin" ] ; then
				echo "$0: -b64 and -b32 are mutually exclusive on this platform"
				exit 12
			fi
			;;
		-b32_64)
			mcc_generate_3264bit_binary="yes"
			if [ "${mcc_platform}" != "Darwin" ] ; then
				echo "$0: Multiple architecture binaries not supported on this platform"
				exit 12
			fi
			;;
		-E)
			mcc_preprocess_to_stdout="yes"
			if [ "${mcc_preprocess_to_i}" = "yes" ] ; then
				echo "$0: -E and -P arguments are mutually exclusive"
				exit 12
			fi
			mcc_extra_compile_flags="${mcc_extra_compile_flags} $1"
			mcc_native_only="yes"
			;;
		-P)
			mcc_preprocess_to_i="yes"
			if [ "${mcc_preprocess_to_stdout}" = "yes" ] ; then
				echo "$0: -P and -E arguments are mutually exclusive"
				exit 12
			fi
			mcc_extra_compile_flags="${mcc_extra_compile_flags} -E"
			mcc_native_only="yes"
			mcc_object_file_extension=".i"
			;;
		-c)
			mcc_compile_only="yes"
			;;
		-o)
			if [ -z "$2" ] ; then
				echo "$0: -o option, but no file name"
				exit 12
			fi
			mcc_output_filename=$2
			count=`expr $count - 1`
			shift
			;;
		-xo)
			if [ -z "$2" ] ; then
				echo "$0: -xo option, but no file name"
				exit 12
			fi
			
			if [ -f $2 -o -d $2 ] ; then
				echo "$0: aborting, $2 already exists"
				exit 12
			fi

			if [ -d $2 ] ; then
				rm -rf $2
			fi
			mkdir -p $2/${mcc_systemid}
			mcc_output_filename=$2/${mcc_systemid}/$2
			count=`expr $count - 1`
			shift
			;;
		-g)
			mcc_debug_compile="yes"
			mcc_extra_compile_flags="${mcc_extra_compile_flags} $1"
			;;
		-n)
			mcc_native_only="yes"
			;;
		-dy)
			mcc_use_the_dynamic_library="yes"
			;;
		--internals)
			mcc_print_variable_values="yes"
			;;
		*.tm)
			mcc_tm_files="${mcc_tm_files} $1"
			;;
		*.c)
			mcc_c_files="${mcc_c_files} $1"
			;;
		*.cc|*.CC|*.cpp|*.cxx)
			mcc_cxx_files="${mcc_cxx_files} $1"
			;;
		*)
			mcc_extra_compile_flags="${mcc_extra_compile_flags} $1"
			;;
	esac
	
	count=`expr $count - 1`
	shift
done


# Determine compilation flags

if [ "${mcc_platform}" = "CYGWIN" ] ; then
	mcc_extra_include_path='/../include'
fi

mcc_32bit_compiler_flags=`get_compilation_flags ${bit32} ${mcc_platform} ${mcc_architecture} ${mcc_cxx_compiler} ${mcc_native_only}`
mcc_64bit_compiler_flags=`get_compilation_flags ${bit64} ${mcc_platform} ${mcc_architecture} ${mcc_cxx_compiler} ${mcc_native_only}`

mcc_include_path="-I${mcc_mldk_dir}${mcc_extra_include_path}"
mcc_compile_flags32="${mcc_include_path} ${mcc_32bit_compiler_flags}"
mcc_compile_flags64="${mcc_include_path} ${mcc_64bit_compiler_flags}"
mcc_compile_flags32_64="${mcc_include_path} ${mcc_32bit_compiler_flags} ${mcc_64bit_compiler_flags}"


# Determine if this platform can make the 32 or 64-bit binaries
if [ "${mcc_generate_32bit_binary}" = "yes" -a -z "${mcc_32bit_compiler_flags}" ] ; then
	echo "$0: Unable to generate 32-bit binaries on this platform"
	exit 13
elif [ "${mcc_generate_64bit_binary}" = "yes" -a -z "${mcc_64bit_compiler_flags}" ] ; then
	echo "$0: Unable to generate 64-bit binaries on this platform"
	exit 13
elif [ "${mcc_generate_3264bit_binary}" = "yes" ] ; then
	if [ -z "${mcc_32bit_compiler_flags}" -o -z "${mcc_64bit_compiler_flags}" ] ; then
		echo "$0: Unable to generate 32 and 64-bit architectures on this platform"
		exit 13
	fi
fi


# Pick the correct compiler flags for 32 or 64 bit compiles
if [ "${mcc_generate_32bit_binary}" = "yes" ] ; then
	mcc_compile_flags=${mcc_compile_flags32}
	mcc_library_bit_type=${bit32}
elif [ "${mcc_generate_64bit_binary}" = "yes" ] ; then
	mcc_compile_flags=${mcc_compile_flags64}
	mcc_library_bit_type=${bit64}
elif [ "${mcc_generate_3264bit_binary}" = "yes" ] ; then
	mcc_compile_flags=${mcc_compile_flags32_64}
	mcc_library_bit_type=${bit64} # This value does not matter in this case (Darwin only)	
else
	if [ "${mcc_platform}" = "Darwin" ] ; then
		mcc_compile_flags=${mcc_compile_flags32_64}
		mcc_library_bit_type=${bit64}
	else
		if [ -z "${mcc_64bit_compiler_flags}" ] ; then
			mcc_compile_flags=${mcc_compile_flags32}
			mcc_library_bit_type=${bit32}
		else
			mcc_compile_flags=${mcc_compile_flags64}
			mcc_library_bit_type=${bit64}
		fi
	fi
fi

# Finalize the compiler flags and get the linker libraries
mcc_compile_flags="${mcc_compile_flags} ${mcc_extra_compile_flags}"
mcc_linker_libs=`get_linker_libraries ${mcc_platform} ${mcc_use_the_dynamic_library} ${mcc_mathlink_interface} ${mcc_library_bit_type} ${mcc_mldk_dir}`

if [ "${mcc_print_variable_values}" = "yes" ] ; then
	echo "Version: ${mcc_version}"
	echo "SystemID: ${mcc_systemid}"
	echo "MathLink Interface: ${mcc_mathlink_interface}"
	echo "MLDK Directory: ${mcc_mldk_dir}"
	echo "C Compiler: ${mcc_c_compiler}"
	echo "C++ Compiler: ${mcc_cxx_compiler}"
	echo "Machine Architecture: ${mcc_architecture}"
	echo "Awk Message File Name: ${mcc_awk_message_file}"
	echo "Compiler Log File Name: ${mcc_compiler_log}"

	echo "Mprep Arguments: ${mcc_mprep_arguments}"
	echo "Preprocess to stdout: ${mcc_preprocess_to_stdout}"
	echo "Preprocess to i: ${mcc_preprocess_to_i}"
	echo "Compile Only: ${mcc_compile_only}"
	echo "Output Filename: ${mcc_output_filename}"
	echo "Native Only: ${mcc_native_only}"
	echo "Debug Compile: ${mcc_debug_compile}"
	echo "Generate 32-bit Binary: ${mcc_generate_32bit_binary}"
	echo "Generate 64-bit Binary: ${mcc_generate_64bit_binary}"
	echo "Generate 32/64-bit Binary: ${mcc_generate_3264bit_binary}"
	echo "Object File Extension: ${mcc_object_file_extension}"
	echo "Use Dynamic Library: ${mcc_use_the_dynamic_library}"

	echo "32-bit Compiler Flags: ${mcc_32bit_compiler_flags}"
	echo "64-bit Compiler Flags: ${mcc_64bit_compiler_flags}"
	echo "Compile Flags 32: ${mcc_compile_flags32}"
	echo "Compile Flags 64: ${mcc_compile_flags64}"
	echo "Compile Flags 32/64: ${mcc_compile_flags32_64}"

	echo "Compile Flags: ${mcc_compile_flags}"
	echo "Library Bit Type: ${mcc_library_bit_type}"
	echo "Linker Libraries: ${mcc_linker_libs}"

	exit 0
fi

# Convert the .tm files to .c files using mprep
if [ ! -z "${mcc_tm_files}" ] ; then
	mcc_tm_c_file=${mcc_output_filename}.tm.c
	if [ "${mcc_verbose}" = "yes" ] ; then
		echo "${mcc_mldk_dir}/mprep ${mcc_mprep_arguments} ${mcc_tm_files} -o ${mcc_tm_c_file}"
	fi
	${mcc_mldk_dir}/mprep ${mcc_mprep_arguments} ${mcc_tm_files} -o ${mcc_tm_c_file}
	mcc_c_files="${mcc_c_files} ${mcc_tm_c_file}"
fi


# Generate the awk file for compiler message handling
generate_ok_messages_awk_script ${mcc_awk_message_file}

# Check to see if the script should generate preprocessed output sent to stdout
if [ "${mcc_preprocess_to_stdout}" = "yes" ] ; then
	mcc_c_preprocessed_files=`compile_files ${mcc_c_compiler} "${mcc_compile_flags} -E" "${mcc_c_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
	handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

	mcc_cxx_preprocessed_files=`compile_files ${mcc_cxx_compiler} "${mcc_compile_flags} -E" "${mcc_cxx_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
	handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

	for file in ${mcc_c_preprocessed_files}
	do
		cat ${file}
	done

	for file in ${mcc_cxx_preprocessed_files}
	do
		cat ${file}
	done

	# Clean up the leftover files if necessary
	if [ "${mcc_debug_compile}" = "no" ] ; then
		rm -rf ${mcc_c_preprocessed_files}
		rm -rf ${mcc_cxx_preprocessed_files}
	fi
	if [ "${mcc_debug_compile}" = "no" ] ; then
		if [ ! -z "${mcc_tm_c_file}" ] ; then
			rm -rf ${mcc_tm_c_file}
		fi
	fi
	exit 0
fi


# Check to see if the script should generate preprocessed output and store them in files with the .i extension
if [ "${mcc_preprocess_to_i}" = "yes" ] ; then
	mcc_c_preprocessed_files=`compile_files ${mcc_c_compiler} "${mcc_compile_flags} -E" "${mcc_c_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
	handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

	mcc_cxx_preprocessed_files=`compile_files ${mcc_cxx_compiler} "${mcc_compile_flags} -E" "${mcc_cxx_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
	handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

	# Clean up the leftover files if necessary
	if [ "${mcc_debug_compile}" = "no" ] ; then
		if [ ! -z "${mcc_tm_c_file}" ] ; then
			rm -rf ${mcc_tm_c_file}
		fi
	fi
	exit 0
fi


# Compile the C files
mcc_c_object_files=`compile_files ${mcc_c_compiler} "${mcc_compile_flags} -c" "${mcc_c_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

# Compile the C++ files
mcc_cxx_object_files=`compile_files ${mcc_cxx_compiler} "${mcc_compile_flags} -c" "${mcc_cxx_files}" ${mcc_object_file_extension} ${mcc_verbose} ${mcc_compiler_log}`
handle_compiler_log ${mcc_compiler_log} ${mcc_awk_message_file}

# Echo any output from the compile stages if verbose mode is active
if [ "${mcc_verbose}" = "yes" -a -f ${mcc_verbose_log} ] ; then
	cat ${mcc_verbose_log} | awk -f ${mcc_awk_message_file}
	rm ${mcc_verbose_log}
fi


mcc_mldk_link_dir_flag="-L${mcc_mldk_dir}"

# Link the object files using the C++ compiler
if [ "${mcc_verbose}" = "yes" ] ; then
	echo "${mcc_cxx_compiler} ${mcc_compile_flags} -o ${mcc_output_filename} ${mcc_c_object_files} ${mcc_cxx_object_files} ${mcc_mldk_link_dir_flag} ${mcc_linker_libs}"
fi
${mcc_cxx_compiler} ${mcc_compile_flags} -o ${mcc_output_filename} ${mcc_c_object_files} ${mcc_cxx_object_files} ${mcc_mldk_link_dir_flag} ${mcc_linker_libs} 2>&1 | awk -f ${mcc_awk_message_file}

# Remove the awk script
rm -rf ${mcc_awk_message_file}

# Clean up leftover files if necessary
if [ "${mcc_debug_compile}" = "no" ] ; then
	if [ ! -z "${mcc_tm_c_file}" ] ; then
		rm -rf ${mcc_tm_c_file}
	fi
	
	for file in ${mcc_c_object_files}
	do
		rm -rf ${file}
	done
	
	for file in ${mcc_cxx_object_files}
	do
		rm -rf ${file}
	done
fi

