#!/bin/bash
# this script is for developers only

stopfpm() { # {{{1
	if [[ -f $pidfile ]]; then
		pid=`cat $pidfile 2>/dev/null || true`
		if [[ $pid -gt 0 ]]; then
			echo
			echo Stopping fpm $pid @ $pidfile
			kill $pid || true
		fi
	fi
}

xtest() { # {{{1
	$MAKE -f devel/test.mak
}

prep() { # {{{1
	$MAKE -f devel/prepare.mak "$@"
}

mergepo() { # {{{1
	prep
	local i
	find htdocs -iname '*.po' | while read -r i; do
		if [[ -f $i-merged ]]; then
			mv $i-merged $i
		fi
	done
}

po2php() { # {{{1
	mergepo

	local phpfile
	find htdocs -iname '*.po' | while read -r i; do
		phpfile=${i/.po/.php}
		devel/po2php.awk < $i > $phpfile.tmp
		mv $phpfile.tmp $phpfile
	done
}

updatedeps() { # {{{1
	pwd=$(readlink -f "$(pwd)")
	builddir=$(readlink -f ../trunk-php5-debug-zts)
	if [[ -z $builddir ]]; then
		echo required ../trunk-php5-debug-zts not found
		return 1
	fi
	find . -iname \*.c | sort | while read -r sourceFile; do
		sourceFile=${sourceFile#./}
		case "$sourceFile" in
		includes.c)
			echo -n "\$(XCACHE_INCLUDES_I) "
			;;
		esac
		echo -n "\$(builddir)/${sourceFile%.c}.lo:"
		for dependency in $(gcc -M $sourceFile -I$HOME/test/php5-debug-zts/include/php/{,main,Zend,TSRM} -I. -I${builddir} -MG | sed 's#.*:##g' | sed 's#\\##g'); do
			dependency=$(readlink -f "$dependency")
			case "$dependency" in
			$pwd/*)
				dependency=${dependency#$pwd/}
				;;
			$builddir/*)
				dependency="\$(builddir)/"${dependency#$builddir/}
				;;
			esac

			case "$dependency" in
			/*) ;;
			$sourceFile) ;;
			\$\(builddir\)/xc_processor.h)
				echo -n " \$(XCACHE_PROC_H)"
				;;
			\$\(builddir\)/xc_processor.c.h)
				echo -n " \$(XCACHE_PROC_C)"
				;;
			*)
				if [[ -r $dependency ]]; then
					echo -n " \$(srcdir)/$dependency"
				else
					echo "$dependency not found" >&2
				fi
			esac
		done
		echo
	done > Makefile.frag.deps
}
# }}}1

set -e
MAKE=/usr/bin/make

. devel/run.cfg
PHPSDIR=${PHPSDIR:-$HOME/test}

if [[ $# -eq 0 ]]; then
	set -- "$action" "${args[@]}"
fi

if [[ $# -gt 0 ]]; then
	action=$1
	shift
fi

# devel actions
case "$action" in
prep*) prep "$@"; exit;;
tags) rm -f tags; prep tags "$@"; exit;;
po2php) po2php; exit;;
mergepo) mergepo; exit;;
dep*) updatedeps; exit;;
xtest) xtest; exit;;
esac

case "$1" in
fpm) pidfile=devel.pid; stopfpm;;
stopfpm) pidfile=devel.pid; stopfpm; exit;;
esac

# process each $dirs
basename=$(basename $(pwd))
if echo $basename | grep -- - >/dev/null; then :; else
	svn propget svn:ignore . > .svnignore

	dirs=${dirs:-php5-debug-zts}
	for dir in $dirs; do
		mkdir -p ../${basename}-${dir}
		cd ../${basename}-${dir} || exit
		lndir ../${basename} >/dev/null || true

		pwd
		$0 "$action" "$@"
	done
	exit
fi

phpbasename=${basename#*-}
xcachebasename=${basename%%-*}
xcachesrcdir=../$xcachebasename
pidfile=../$xcachebasename/devel.pid
phpize() { # {{{1
	if [[ ! -x $PHPSDIR/$phpbasename/bin/phpize ]]; then
		echo $PHPSDIR/$phpbasename/bin/phpize not found
		exit
	fi
	export PATH=$PHPSDIR/$phpbasename/bin:$PATH
	phpize --clean \
	&& phpize \
	&& CFLAGS="-g -O0 -pedantic-errors -Wno-variadic-macros -Wno-long-long -Wall -Wno-unused-parameter -Wno-unused-function -W -Wshadow -Werror=implicit-function-declaration -std=c89 -D_GNU_SOURCE -D_POSIX_SOURCE -Dinline=" ./configure \
		--enable-xcache-cacher \
		--enable-xcache-optimizer \
		--enable-xcache-encoder \
		--enable-xcache-decoder \
		--enable-xcache-disassembler \
		--enable-xcache-coverager \
		--enable-xcache-test \
		--enable-xcache-constant
}
make() { # {{{1
	LANG=C $MAKE $MAKEOPTS "$@" 2>&1 \
	| sed -ur \
		-e 's#Werror=implicit-function-declaration#We/rror=i/mplicit-function-declaration#' \
		-e 's#-pedantic-errors#-pedantic-e/rrors#' \
		-e 's#\./xc_processor\.h#'$PWD'/xc_processor.h#' \
		-e 's#\./xc_processor\.c\.h#'$PWD'/xc_processor.c.h#' \
	| hi error implicit warn FAIL
	ret=${PIPESTATUS[0]}
	if [[ $ret -ne 0 ]]; then
		exit $ret
	fi
}
# }}}

# prepare {{{1
case "$action" in
phpize)
	if [[ -r Makefile ]]; then
		$MAKE xcachesvnclean || true
	fi
	;;
esac

rm -f php-src
find -L . -type l | xargs rm -fv
lndir "$xcachesrcdir" >/dev/null || true
find . -iname .\*.swp | xargs rm -f
ln -sf ~/src/php/$phpbasename php-src
for i in ~/src/php/$phpbasename/sapi/cgi/php{,-cgi}; do
	if [[ -r $i ]]; then
		ln -sf "$i" php-cgi
	fi
done
ln -sf ~/src/php/$phpbasename/sapi/cli/php php-cli
ln -sf ~/src/php/$phpbasename/sapi/fpm/php-fpm php-fpm

case "$action" in
phpize) phpize; exit;;
make) make "$@"; exit;;
*) make;;
esac
# }}}1

if [[ -z $1 ]]; then
	set -- devel.php
fi

cmd=()
tracer=()

# run utils {{{1
case "$action" in
dc)
	exec ./php-cli -c devel.ini ./bin/phpdc.phpr $@ | tee decompiled.php
	;;
dop)
	exec ./php-cli -c devel.ini ./bin/phpdop.phpr $@
	;;
retest)
	exec $MAKE xcachetest "$@" TESTS="`grep '^/.*\.phpt$' php_test_results_*.txt | uniq | xargs`"
	;;
test)
	case "$1" in
	*.phpt)
		exec $MAKE xcachetest TEST_ARGS=-v TESTS="$*"
		;;
	*/)
		exec $MAKE xcachetest TESTS="$*"
		;;
	*)
		exec $MAKE xcachetest
		;;
	esac
	;;
esac
# }}}
# pick sapi {{{1
case "$basename" in
*-apache1*)
	cmd=($HOME/apache1/bin/httpd -X)
	;;
*-apache*)
	exit 1
	;;
*)
	case "$1" in
	fcgi)
		cmd=(./php-cgi -q -c devel.ini)
		set -- -b 1026
		;;
	fpm)
		echo Starting fpm ...
		cmd=(./php-fpm -c devel.ini -y devel.fpm -g $(readlink -f $pidfile))
		set --
		;;
	*)
		cmd=(./php-cgi -q -c devel.ini)
		;;
	esac

	"${cmd[@]}" -v || true
esac
# }}}
# pick action {{{1
case "$action" in
ltr*)
	export USE_ZEND_ALLOC=0
	tracer=(ltrace -s1024 -e malloc,realloc,free,write)
	;;
str*)
	tracer=(strace -s1024 -T)
	;;
gdb)
	#USE_ZEND_ALLOC=0
	tracer=(gdb --args)
	;;
val*)
	export USE_ZEND_ALLOC=0
	tracer=(valgrind --gen-suppressions=all)
	;;
esac

# run {{{1
export XCACHE_SKIP_FCGI_WARNING=1
commandLine=("${tracer[@]}" "${cmd[@]}" "$@")

case "${cmd[0]}" in
*php-fpm*)
	stopfpm
	"${commandLine[@]}"
	echo -n "Ctrl-C to stop"
	trap stopfpm SIGINT SIGTERM exit
	cat > /dev/null || true
	stopfpm
	;;
*)
	exec "${commandLine[@]}"
	;;
esac
# }}}
