#!/bin/bash

function print_usage {
    cat << EOF
Usage: hjc [options] <class-name> ...
where [options] includes:
    -classpath <path>        search path for class files
    -sourcepath <path>       search path for hj source files (must includes path to class-name)
    -destdir <path>          set the location where to output classes
    -rt <value>				 set the targeted hj runtime to compile class for. (s = work sharing (default) | h workstealing help first | w = workstealing work first )
    -v -verbose --verbose    print verbose debugging information
    -S<arg>                  [USE WITH CAUTION] pass <arg> directly to soot.
        					 e.g. -S-optName=value (if option has args, = is required and value shouldn't have one)
    -S-info					 print soot information 
    -S-hjVerbose			 print verbose hj related debugging information
    -h -help --help          print this message
    -version --version 	   	 print version number of the hj compiler

    Use "hjc -- -help" to get more detailed help on compiler options
EOF
    exit 1
}

CLASSNAME=
USER_CLASSPATH=
USER_SOURCEPATH=
RT=

RUNTIME_WSH="s"
RUNTIME_WST_HF="h"
RUNTIME_WST_WF="w"

function set_source_file_name() {
	FILENAME_PATH=`echo $args | sed "s/^ //g"`

	#We extract the source file name
	FILENAME=`echo ${FILENAME_PATH##*/}`
}

function set_sootargs() {
	soot_args_cleaned=""
	for opt in `echo $soot_args`; do
		#opt has the form optName=optValue
		#We want to remove the =
		newOpt=`echo $opt | sed 's/=/ /'`
		soot_args_cleaned="${soot_args_cleaned} $newOpt"
	done
	
	soot_args=${soot_args_cleaned}
}

function set_sourcepath() {
	set_source_file_name

	#We extract the path that prepend the source file name.
	PREPEND_PATH=`echo ${FILENAME_PATH%"$FILENAME"}`

	# if any, we add it to the sourcepath
	if [ ! -z "$PREPEND_PATH" ]; then
		if [ -z "$USER_SOURCEPATH" ]; then
			USER_SOURCEPATH="${PREPEND_PATH}"
		else
			USER_SOURCEPATH="${PREPEND_PATH}:${USER_SOURCEPATH}"
		fi
	fi	
}

function set_classname() {
	set_source_file_name

	#we need to remove .hj suffix, as soot only takes the classname as parameter
	CLASSNAME=`echo $FILENAME | sed 's/.hj$//g'`
}

[ -n "$JAVA_HOME" ] || JAVA_HOME='${env.JAVA_HOME}'

if [ -n "$JAVA_HOME" -a -e "$JAVA_HOME/bin/java" ]; then
    JAVA="$JAVA_HOME/bin/java"
elif [ -n "$JRE_HOME" -a -e "$JRE_HOME/bin/java" ]; then
    JAVA="$JRE_HOME/bin/java"
else
    echo "ERROR: JAVA_HOME ($JAVA_HOME) is not pointing to a JRE or a JDK"
    exit 1
fi

if [ -z "${HJ_HOME}" ]; then
	echo ""
	echo "ERROR: HJ_HOME environment variable must be defined and point to an HJ Distribution"
	echo ""
    exit 1
fi

SOOT_DIST_HOME=${HJ_HOME}
SOOT_DIST_LIB_DIR=${SOOT_DIST_HOME}/lib
SOOT_DIST_LIB_SRCDIR=${SOOT_DIST_LIB_DIR}/src

HJC_CLASSPATH=

for jar in `ls ${SOOT_DIST_LIB_DIR}/*.jar`; do
	HJC_CLASSPATH=${HJC_CLASSPATH}:$jar
done

HJC_SOURCEPATH=${SOOT_DIST_LIB_SRCDIR}

verbose=""
version=""
HjVERBOSE=
java_args=""
soot_args=""
args=""

parse=true
while [ -n "$1" ]; do
    if [ -z "$parse" ]; then
	args="$args $1"
        shift
        continue
    fi
    case "$1" in
        -h|-help|--help) print_usage; break;;
        -v|-verbose|--verbose) verbose="1";;
        -version|--version) version="1";;
        -classpath|-cp) shift; USER_CLASSPATH="$1";;
        -sourcepath|-sp) shift; USER_SOURCEPATH="$1";;
        -destdir|-d) shift; DEST_DIR="$1";;
        -rt) shift; RT="$1";;        
        -J*) java_args="${java_args} '${1##-J}'";;
        -S*) soot_args="${soot_args} ${1##-S}";;
        --) parse=;;
        *) args="$args $1";;
    esac
    shift
done

if [ ! -z "$version" ]; then
	JAVA_CMD="$JAVA -Xmx512m -classpath ${HJC_CLASSPATH} soot.Main -version"
	eval ${JAVA_CMD}
	exit $?
fi

if [ -z "$args" ]; then
	print_usage;
fi 

# soot only takes the Classname as argument, however it will still try to find 
# a Classname.hj file in its path. 
# This check ensures only .hj files will be submit to soot.
hj_src_pattern=*.hj

case $args in 
  $hj_src_pattern) echo "" ;;
  *help)  echo "" ;;
  *) echo "ERROR: Source file $args must have a .hj extension to be compiled"; exit 1;; 
esac


if [ ! -z "$RT" ]; then
	soot_args="${soot_args} -rt=${RT}"
fi

# convert soot option from '-opt=val' to '-opt val'
set_sootargs

#sets USER_SOURCEPATH
set_sourcepath

#sets CLASSNAME to be compiled
set_classname

if [ ! -z "${soot_args}" ]; then
	SOOT_OPTIONS="${SOOT_OPTIONS} ${soot_args}"
fi

if [ ! -z "$USER_SOURCEPATH" ]; then
	SOOT_OPTIONS="${SOOT_OPTIONS} -sp .:${HJC_SOURCEPATH}:${USER_SOURCEPATH}"
else
	SOOT_OPTIONS="${SOOT_OPTIONS} -sp .:${HJC_SOURCEPATH}"	
fi 

if [ ! -z "$USER_CLASSPATH" ]; then
	SOOT_OPTIONS="${SOOT_OPTIONS} -cp ${USER_CLASSPATH}"
	HJC_CLASSPATH="${HJC_CLASSPATH}:${USER_CLASSPATH}"
fi 

if [ ! -z "$DEST_DIR" ]; then
	SOOT_OPTIONS="${SOOT_OPTIONS} -d ${DEST_DIR}"
fi 


#File to compile, is filename without the .hj extension. That's how soot works...
JAVA_CMD="$JAVA -Xmx512m -classpath ${HJC_CLASSPATH} soot.Main ${SOOT_OPTIONS} -w -hj -pp '$CLASSNAME'"
	
[ -n "$verbose" ] && echo ${JAVA_CMD}

eval ${JAVA_CMD}
exit $?
