#!/bin/bash

# A script to test the compilation of a particular PHP script. In particular, this copies originals to the local directory, and generates readable C which can be used to debug the assembly. Pass -g as the second argument to run the debugger.

# parse command line parms

PHC_ARGS=""
DEBUG_PHC=0
OPTIMIZE=0
GDB="libtool --mode=execute gdb --args"
VALGRIND="libtool --mode=execute valgrind"
for var in $@
do
	if [ "-$NEXT_IS_COMMAND" = "-1" ]
	then
		PHC_ARGS="$PHC_ARGS $var"
		NEXT_IS_COMMAND=0
	elif [ "-$var" = "--g" ] # debug
	then
		EXEC_NAME="$GDB "
		DEBUG_PHC=1
	elif [ "-$var" = "--V" ] # valgrind
	then
		EXEC_NAME="$VALGRIND "
	elif [ "-$var" = "--M" ] # Massif
	then
		EXEC_NAME="$VALGRIND --tool=massif "
	elif [ "-$var" = "--C" ]
	then
		NEXT_IS_COMMAND=1
	elif [ "-$var" = "--B" ] # Benchmark
	then
		EXEC_NAME="$VALGRIND --tool=cachegrind --branch-sim=yes "
	elif [ "-$var" = "--O" ] # Optimize
	then
		PHC_ARGS="$PHC_ARGS -O3"
		OPTIMIZE=1
	elif [ "-$var" = "--S" ] # Statistics
	then
		PHC_ARGS="$PHC_ARGS --rt-stats"
		STATS=1
	elif [ "-$var" = "--R" ] # raise-globals
	then
		PHC_ARGS="$PHC_ARGS --run plugins/tests/raise_globals.la"
	elif [ "-$var" = "--F" ] # Generate FDO
	then
		GCC_ARGS="$GCC_ARGS -fprofile-generate"
	elif [ "-$var" = "--f" ] # Use FDO
	then
		GCC_ARGS="$GCC_ARGS -fprofile-use"
	elif [ "-$var" = "--r" ] # references
	then
		PHC_ARGS="$PHC_ARGS --run plugins/tools/debug_zval.la"
	elif [ "-$var" = "--d" ] # demi-eval
	then
		PHC_ARGS="$PHC_ARGS --run plugins/tools/demi_eval.la --r-option=true"
	elif [ "-$var" = "--D" ] # also demi-eval
	then
		PHC_ARGS="$PHC_ARGS --run plugins/tools/demi_eval.la --r-option=false"
	elif [ "-$var" = "--v" ] # verbose
	then
		set -x
	elif [ "-$var" = "--i" ] # include
	then
		PHC_ARGS="$PHC_ARGS --include"
	else
		PHP_NAME=$var
	fi
done

NAME=`basename $PHP_NAME` # remove the filename suffix
NAME=${NAME%.php}
OUT_NAME=$NAME.out
EXEC_NAME="$EXEC_NAME./$OUT_NAME"
DIRNAME=`dirname $PHP_NAME`
PHC_ARGS="$PHC_ARGS -d include_path=.:test/subjects:$DIRNAME"
#PHC_ARGS="$PHC_ARGS "

cp $PHP_NAME $NAME.orig.php || exit 1;

# generate HIR
#src/phc $PHP_NAME $PHC_ARGS --dump=hir > $NAME.hir.php
#if [[ $? != 0 ]]; then
#	if [[ $DEBUG_PHC != 0 ]]; then 
#		exec $GDB src/phc $PHP_NAME $PHC_ARGS --dump=hir
#	fi
#	exit 1
#fi

# generate MIR
#src/phc $PHP_NAME $PHC_ARGS --dump=generate-c > $NAME.mir.php
#if [[ $? != 0 ]]; then
#	if [[ $DEBUG_PHC != 0 ]]; then 
#		exec $GDB src/phc $PHP_NAME $PHC_ARGS --dump=generate-c
#	fi
#	exit 1
#fi

# generate uppered HIR
#src/phc $PHP_NAME $PHC_ARGS --udump=AST-to-HIR > $NAME.uhir.php
#if [[ $? != 0 ]]; then
#	if [[ $DEBUG_PHC != 0 ]]; then 
#		exec gdb --args src/phc $PHP_NAME $PHC_ARGS --udump=AST-to-HIR
#	fi
#	exit 1
#fi

# generate C
src/phc --generate-c $PHC_ARGS $PHP_NAME > $NAME.c
if [[ $? != 0 ]]; then 
	if [[ $DEBUG_PHC  != 0 ]]; then 
		exec $GDB src/phc --generate-c $PHC_ARGS $PHP_NAME
	fi
	exit 1
fi
indent $NAME.c
# indent assumes 8-space tabs; make sure vim agrees
echo "// vi:set ts=8:" >> $NAME.c

# compile it, using phc's verbose output as the command. Pass an empty program so it doesnt compile twice, and if optimizing, 
GCC_COMMAND=`echo '<?php ?>' | src/phc -v -c $PHC_ARGS -o $OUT_NAME | grep ^gcc | sed "s# - # $NAME.c #"` || exit 1
if [[ $OPTIMIZE != 0 ]]
then
	if [[ -d '/usr/local/php-opt' ]]; then
		GCC_COMMAND=`echo $GCC_COMMAND | sed 's#/usr/local/#/usr/local/php-opt/#g'` || exit 1
	else
		echo '-O relies on presence of /usr/local/php-opt/'
		exit 1
	fi
fi

GCC_COMMAND="$GCC_COMMAND $GCC_ARGS"

$GCC_COMMAND
if [[ $? != 0 ]]; then 
	if [[ $DEBUG_PHC != 0 ]]; then 
		exec $GDB src/phc --generate-c $PHC_ARGS $PHP_NAME
	fi
	exit 1
fi


#if [[ $STATS == 1 ]]; then
#   exec $EXEC_NAME 2>$NAME.stats
#   exec misc/counter_stats $NAME.stats
#fi

exec $EXEC_NAME
