#!/usr/bin/perl
# Reads a file from STDIN and replaces ###SHELLPACK macros with code

use strict;

my $shellpack;
my $packdirectory = $ARGV[0];
my $ret=1;

my $script_sysctl="
if [ \"\$BUILDFLAGS_ENABLE_SYSCTL\" = \"yes\" ]; then
	if [ \"\$INSTALL_ONLY\" != \"yes\" ]; then
		SYSCTL_FLAGS=
		SYSCTL_BENCH=`echo \$P | sed -e 's/-bench//'`
		SYSCTL_FLAGS_ROOT=\"\$SHELLPACK_TOPLEVEL/configs/build-flags/\$SYSCTL_BENCH\"
		for FILE in \$SYSCTL_FLAGS_ROOT/sysctl \$SYSCTL_FLAGS_ROOT/`uname -m`/sysctl \$SYSCTL_FLAGS_ROOT/`uname -m`/sysctl-`hostname`; do
			if [ -f \$FILE ]; then
				SYSCTL_FLAGS=\$FILE
			fi
		done
		if [ \"\$SYSCTL_FLAGS\" != \"\" ]; then
			echo Reading \$SYSCTL_FLAGS
			. \$SYSCTL_FLAGS
		fi
	fi
fi
";

sub print_flag_case {
	my ($switch, $param) = @_;
	print <<EOC;
	$switch)
		$param=yes
		shift
		;;
EOC
}

sub print_arg_case {
	my ($switch, $param) = @_;
	print <<EOC;
	$switch)
		if [[ \$# -lt 2 ]] || [[ \$2 == -* ]]; then
			echo "Flag '$switch' specified without an associated value."
			exit 1
		fi
		$param=\$2
		shift 2
		;;
EOC
}

while (<STDIN>) {
	my $line = $_;
	if ($_ !~ /###SHELLPACK/) {
		print $_;
		next;
	}

	$ret=0;
	$line =~ s/.*###SHELLPACK //;

	my ($command, @details) = split(/\s+/, $line);
	print "# command: $command\n";

	if ($command eq "preamble") {
		my ($name, $version) = @details;
		my $dummy;
		my $index;
		($shellpack, $dummy) = split(/-/, $name);
		$index = rindex($name, "-");
		if ( $index == -1 ) {
			$shellpack = $name
		} else {
			$shellpack = substr($name, 0, $index);
		}
		print <<EOC
set \${MMTESTS_SH_DEBUG:-+x}
P=$name
DEFAULT_VERSION=$version
. \$SHELLPACK_INCLUDE/common.sh
TIME_CMD=`which time`
if [ "\$TIME_CMD" = "" ]; then
        TIMEFORMAT="%2Uuser %2Ssystem %Relapsed %P%%CPU"
        TIME_CMD="time"
fi

log_sysctl() {
	if [ ! -e \$SHELLPACK_LOG/sysctl.opts ]; then
		echo "Sysctl options" >> \$SHELLPACK_LOG/sysctl.opts
	fi
	echo "\$@" >> \$SHELLPACK_LOG/sysctl.opts
}

log_runtime() {
	if [ ! -e \$SHELLPACK_LOG/runtime.opts ]; then
		echo "Runtime options" > \$SHELLPACK_LOG/runtime.opts
	fi
	echo "\$@" >> \$SHELLPACK_LOG/runtime.opts
}

log_cmd() {
	log_runtime "Run: \$@"
	echo "\$@" >> \$LOGDIR_RESULTS/commands.log
}

log_linkages() {
	if [ "\$MMTESTS_TOOLCHAIN\" != "" -a "\$1" != "" ]; then
		log_runtime "Linkages: \$1"
		ldd \$1 >> \$SHELLPACK_LOG/runtime.opts
		echo >> \$SHELLPACK_LOG/runtime.opts
	fi
}
if [ "\$MMTESTS_TOOLCHAIN\" != "" -a "\$MMTESTS_MPI_USE_DISTRO\" != "yes" ]; then
	export MMTESTS_MPI_SELFBUILD=yes
fi

EOC
	} elsif ($command eq "parseargBegin") {
		print <<EOC;
# Basic argument parser
TASKSET_SERVER=
TASKSET_CLIENT=
TASKSET_ALL=
SERVERSIDE_COMMAND=none
SERVERSIDE_NAME=`date +%Y%m%d-%H%M-%S`

while [ "\$1" != "" ]; do
	case "\$1" in
EOC

		print_arg_case("-v", "VERSION");
		print_arg_case("--serverside-command", "SERVERSIDE_COMMAND");
		print_arg_case("--serverside_name", "SERVERSIDE_NAME");
	} elsif ($command eq "parseargInstall") {
		print_flag_case("--install-only", "INSTALL_ONLY");
		print_flag_case("--install-force", "INSTALL_FORCE");
	} elsif ($command eq "parseargParam") {
		my ($switch, $param) = @details;
		print_arg_case($switch, $param);
	} elsif ($command eq "parseargYes") {
		my ($switch, $param) = @details;
		print_flag_case($switch, $param);
	} elsif ($command eq "parseargBindings") {
		print <<EOC
	--bind-pinned)
		CPUA=`numactl --hardware | grep ^node | grep cpus: | head -1 | awk '{print \$4}'`
		TASKSET_SERVER="taskset -c \$CPUA"
		TASKSET_CLIENT="taskset -c \$CPUA"
		TASKSET_ALL="taskset -c \$CPUA"
		shift
		;;
	--bind-cross-node)
		CPUA=`numactl --hardware | grep ^node | grep cpus: | head -1 | awk '{print \$4}'`
		CPUB=`numactl --hardware | grep ^node | grep cpus: | tail -1 | awk '{print \$NF}'`
		TASKSET_SERVER="taskset -c \$CPUA"
		TASKSET_CLIENT="taskset -c \$CPUB"
		TASKSET_ALL="taskset -c \$CPUA,\$CPUB"
		shift
		;;
	--bind-cross-socket)
		CPUA=`numactl --hardware | grep ^node | grep cpus: | head -1 | awk '{print \$4}'`
		CPUB=`list-cpu-siblings.pl \$CPUA llc_cores 0 | awk -F , '{print \$1}'`
		TASKSET_SERVER="taskset -c \$CPUA"
		TASKSET_CLIENT="taskset -c \$CPUB"
		TASKSET_ALL="taskset -c \$CPUA,\$CPUB"
		shift
		;;
	--bind-cross-ht)
		CPUA=`numactl --hardware | grep ^node | grep cpus: | head -1 | awk '{print \$4}'`
		CPUB=`list-cpu-siblings.pl \$CPUA threads 0 | awk -F , '{print \$1}'`
		if [ "\$CPUB" = "" ]; then
			echo ERROR: Could not identify HT thread for CPU \$CPUA
			exit \$SHELLPACK_ERROR
		fi
		TASKSET_SERVER="taskset -c \$CPUA"
		TASKSET_CLIENT="taskset -c \$CPUB"
		TASKSET_ALL="taskset -c \$CPUA,\$CPUB"
		shift
		;;
EOC
	} elsif ($command eq "parseargEnd") {
		print <<EOC
	*)
		echo Unrecognised option: \$1
		shift
	esac
done
if [ "\$TASKSET_SERVER" != "" ]; then
	echo TASKSET_SERVER: \$TASKSET_SERVER
	echo TASKSET_CLIENT: \$TASKSET_CLIENT
fi
if [ -z "\$VERSION" ]; then
	VERSION=\$DEFAULT_VERSION
fi
EOC
	} elsif ($command eq "sources_fetch") {
		my ($tarfile, $srcdir) = @details;
		my $versionDir = "";
		if ($tarfile =~ /\//) {
			($versionDir,$tarfile) = split(/\//, $tarfile);
			$versionDir="$versionDir/";
		}

		print <<EOC
# Unconditionally fetch the tar to find out the real version number
TARFILE=$tarfile
sources_fetch \$WEB_LOCATION/$versionDir\$TARFILE \$MIRROR_LOCATION/\$TARFILE \$SHELLPACK_SOURCES/\$TARFILE \$WEB_LOCATION_ALT/$versionDir\$TARFILE
cd \$SHELLPACK_SOURCES
tar -xf \$TARFILE
if [ \$? -ne 0 ]; then
	error "\$P: tar xf $tarfile failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi

# Rename directory to something we expect.
DST_DIR=`tar tf \$TARFILE | head -n 1 | awk -F / '{print \$1}'`
mv \$DST_DIR $srcdir 2>/dev/null
pushd $srcdir > /dev/null || die Failed to rename tar
EOC
	} elsif ($command eq "sources_fetch_p0") {
		my ($tarfile, $srcdir) = @details;
		my $versionDir = "";
		if ($tarfile =~ /\//) {
			($versionDir,$tarfile) = split(/\//, $tarfile);
			$versionDir="$versionDir/";
		}

		print <<EOC
# Unconditionally fetch the tar to find out the real version number
TARFILE=$tarfile
sources_fetch \$WEB_LOCATION/$versionDir\$TARFILE \$MIRROR_LOCATION/\$TARFILE \$SHELLPACK_SOURCES/\$TARFILE
mkdir \$SHELLPACK_SOURCES/$srcdir
cd \$SHELLPACK_SOURCES/$srcdir
tar -xf ../\$TARFILE
if [ \$? -ne 0 ]; then
	error "\$P: tar xf $tarfile failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi
EOC
	} elsif ($command eq "git_fetch") {
		my ($tarfile, $srcdir) = @details;
		my $versionDir = "";
		if ($tarfile =~ /\//) {
			($versionDir,$tarfile) = split(/\//, $tarfile);
			$versionDir="$versionDir/";
		}

		print <<EOC
# Unconditionally fetch the tar to find out the real version number
TARFILE=$tarfile
if [ "\$GIT_FETCH_BRANCH" = "" ]; then
	GIT_FETCH_BRANCH=\$VERSION
fi
git_fetch \$GIT_LOCATION $srcdir \$MIRROR_LOCATION/\$TARFILE \$SHELLPACK_SOURCES/\$TARFILE \$GIT_FETCH_BRANCH
cd \$SHELLPACK_SOURCES
tar -xf \$TARFILE
if [ \$? -ne 0 ]; then
	error "\$P: tar xf $tarfile failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi

# Rename directory to something we expect.
DST_DIR=`tar tf \$TARFILE | head -n 1 | awk -F / '{print \$1}'`
mv \$DST_DIR $srcdir 2>/dev/null
pushd $srcdir > /dev/null || die Failed to rename tar
EOC
	} elsif ($command eq "build_start") {
		my ($srcdir) = @details;
		print <<EOC

build_callback() {
	echo -n
}

pushd \$SHELLPACK_SOURCES/$srcdir > /dev/null || die Failed to change to source directory

# Compiler optimisations from build-flags
if [ "\$BUILDFLAGS_ENABLE_COMPILEFLAGS" = "yes" ]; then
	BUILD_FLAGS=
	BUILD_FLAGS_ROOT="\$SHELLPACK_TOPLEVEL/configs/build-flags/`echo \$P | awk -F - '{print \$1}'`"
	for FILE in \$BUILD_FLAGS_ROOT/generic \$BUILD_FLAGS_ROOT/`uname -m`/generic \$BUILD_FLAGS_ROOT/`uname -m`/`hostname`; do
		if [ -f \$FILE ]; then
			BUILD_FLAGS=\$FILE
		fi
	done

	if [ -e \$SHELLPACK_TOPLEVEL/configs/build-flags/common ]; then
		. \$SHELLPACK_TOPLEVEL/configs/build-flags/common
	fi
fi
export MMTESTS_C_COMPILER=\${MMTESTS_C_COMPILER:-gcc}
export DEFAULT_OPTIMISATION_LEVEL="-O2"
if [ "\$BUILD_FLAGS" != "" ]; then
	echo ===================
	echo Loading build flags \$BUILD_FLAGS
	. \$BUILD_FLAGS
	cat \$BUILD_FLAGS
	echo ===================
	if [ -e \$SHELLPACK_TOPLEVEL/configs/build-flags/common-finalise ]; then
		. \$SHELLPACK_TOPLEVEL/configs/build-flags/common-finalise
	fi
fi

EOC
	} elsif ($command eq "build_start_alt") {
		my ($srcdir) = @details;
		print <<EOC
pushd \$SHELLPACK_SOURCES/$srcdir || die Failed to change to source directory
for FILE in `find -name "*"`; do
	touch \$FILE
done
mkdir \$SHELLPACK_SOURCES/$srcdir-build
pushd \$SHELLPACK_SOURCES/$srcdir-build || die Failed to change to build directory
EOC

	} elsif ($command eq "build_autogen") {
		print <<EOC
./autogen.sh || die "Failed to run autogen"
EOC
	} elsif ($command eq "build_autoreconf") {
		print <<EOC
touch NEWS
touch AUTHORS
autoreconf -f -i || die Failed to run autoreconf
EOC
	} elsif ($command eq "build_configure") {
		my ($srcdir, $dstdir) = @details[0];
		if ($dstdir eq "") {
			$dstdir="$srcdir-installed"
		}
		shift @details;
		print <<EOC
eval ./configure --prefix=\$SHELLPACK_SOURCES/$dstdir --libdir=\$SHELLPACK_SOURCES/$dstdir/\$MMTESTS_LIBDIR \$MMTESTS_BUILD_CONFIGURE @details
if [ \$? -ne 0 ]; then
	cp /usr/share/automake*/config.guess .
	cp /usr/share/automake*/config.sub .
	eval ./configure --prefix=\$SHELLPACK_SOURCES/$dstdir \$MMTESTS_BUILD_CONFIGURE @details
	if [ \$? -ne 0 ]; then
		error "\$P: configure failed"
		popd > /dev/null
		exit \$SHELLPACK_ERROR
	fi
fi
unset CFLAGS
EOC
	} elsif ($command eq "build_configure_py") {
		my $srcdir = @details[0];
		shift @details;
		print <<EOC
mkdir build
cd build
eval ../configure.py --prefix=\$SHELLPACK_SOURCES/$srcdir-installed \$MMTESTS_BUILD_CONFIGURE @details
if [ \$? -ne 0 ]; then
	error "\$P: configure failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi
unset CFLAGS
EOC

	} elsif ($command eq "self_extract") {
		my $selffile = @details[0];
		shift @details;
		print <<EOC
LINESTART=`grep -n "==== BEGIN $selffile" \$0 | tail -1 | awk -F : '{print \$1}'`
LINEEND=`grep -n "==== END $selffile" \$0 | tail -1 | awk -F : '{print \$1}'`
if [ "\$LINEEND" = "" ]; then
	LINECOUNT=`wc -l \$0 | awk '{print \$1}'`
fi
if [ "\$LINESTART" = "" ]; then
	die Failed to find start of file $selffile
fi
echo Extracting \$SHELLPACK_TEMP/$selffile
sed -n \$((LINESTART+1)),\$((LINEEND-1))p \$0 > \$SHELLPACK_TEMP/$selffile
EOC
	} elsif ($command eq "build_cmake") {
		my $builddir = @details[0];
		my $srcdir = @details[1];
		shift @details;
		shift @details;
		print <<EOC
cd \$SHELLPACK_SOURCES/$builddir || die Failed to change to builddir
cmake \$SHELLPACK_SOURCES/$srcdir -DCMAKE_INSTALL_PREFIX=\$SHELLPACK_SOURCES/$srcdir-installed -DCMAKE_VERBOSE_MAKEFILE=true @details
if [ \$? -ne 0 ]; then
	error "\$P: cmake failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi
EOC

	} elsif ($command eq "make") {
		my $opts = join(" ", @details);
		print <<EOC
MAKE_JOBS="-j\$NUMCPUS"
if [ "\$MMTESTS_BUILD_SERIAL" = "yes" ]; then
	MAKE_JOBS=
fi
if [ "\$MMTESTS_BUILD_VERBOSE" = "yes" ]; then
	MAKE_FLAGS+=" V=1"
fi
make \$MAKE_JOBS \$MAKE_FLAGS $opts
if [ \$? -ne 0 ]; then
	echo WARNING: make failed, retrying once
	make \$MAKE_JOBS \$MAKE_FLAGS $opts
	if [ \$? -ne 0 ]; then
		error "\$P: make failed"
		popd > /dev/null
		exit \$SHELLPACK_ERROR
	fi
fi
EOC
	} elsif ($command eq "make_clean") {
		print <<EOC
make clean
if [ \$? -ne 0 ]; then
	error "\$P: make clean failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi
EOC
	} elsif ($command eq "make_install") {
		my $opts = join(" ", @details);
		print <<EOC
make install \$MAKE_INSTALL_FLAGS
if [ \$? -ne 0 ]; then
	error "\$P: make install failed"
	popd > /dev/null
	exit \$SHELLPACK_ERROR
fi
EOC
	} elsif ($command eq "make_make_install") {
		my $opts = join(" ", @details);
		print <<EOC
###SHELLPACK make $opts
###SHELLPACK make_install $opts
EOC
	} elsif ($command eq "check_install_required") {
		my ($srcdir, @other) = @details;
		my $dstdir = "$srcdir-installed";

		print <<EOC
if [ "\$INSTALL_FORCE" = "yes" -a "\$INSTALL_ONLY" = "yes" ]; then
	echo Forcing installation $srcdir from scratch
	rm -rf \$SHELLPACK_SOURCES/$srcdir \$SHELLPACK_SOURCES/$srcdir-installed
fi
if [ ! -d \$SHELLPACK_SOURCES/$dstdir ]; then
	mmtests_activity source-install
	\$SHELLPACK_INCLUDE/shellpack-install-$shellpack -v \${VERSION} @other || die "$shellpack install script returned error"
	mmtests_activity source-installed
fi
cd \$SHELLPACK_SOURCES/$shellpack-\${VERSION}-installed || die "Failed to cd to $shellpack install directory"
###SHELLPACK init_complete
$script_sysctl
EOC
	} elsif ($command eq "check_install_required_continue") {
		my ($srcdir, @other) = @details;
		my $dstdir = "$srcdir-installed";

		print <<EOC
if [ "\$INSTALL_FORCE" = "yes" ]; then
	rm -rf \$SHELLPACK_SOURCES/$srcdir
fi
if [ ! -d \$SHELLPACK_SOURCES/$dstdir ]; then
	mmtests_activity source-install
	\$SHELLPACK_INCLUDE/shellpack-install-$shellpack -v \${VERSION} @other || die $shellpack install script returned error
	mmtests_activity source-installed
fi
cd \$SHELLPACK_SOURCES/$shellpack-\${VERSION}-installed || die Failed to cd to $shellpack install directory
$script_sysctl
EOC
	} elsif ($command eq "check_external_install_required") {
		my ($externalpack, $srcdir, $version, @other) = @details;
		my $dstdir = "$srcdir-installed";

		print <<EOC
if [ "\$INSTALL_FORCE" = "yes" ]; then
	rm -rf \$SHELLPACK_SOURCES/$srcdir
fi
if [ ! -d \$SHELLPACK_SOURCES/$dstdir ]; then
	mmtests_activity source-install
	if [ ! -e  \$SHELLPACK_INCLUDE/shellpack-install-$externalpack ]; then
		\$SHELLPACK_TOPLEVEL/shellpack_src/src/refresh.sh $externalpack
	fi
	\$SHELLPACK_INCLUDE/shellpack-install-$externalpack -v $version @other || die $externalpack install script returned error
	mmtests_activity source-installed
fi
if [ "\$INSTALL_DEPS_NOMERGE" != "yes" ]; then
	INSTALL_BASENAME=`echo \$P | awk -F - '{print \$1}'`
	###SHELLPACK install_merge $srcdir \${INSTALL_BASENAME}deps-installed
fi
cd \$SHELLPACK_SOURCES/$externalpack-$version-installed || die Failed to cd to $externalpack install directory
EOC
	} elsif ($command eq "init_only_start") {
	print <<EOC
if [ "\$INSTALL_ONLY" = "yes" ]; then
EOC
	} elsif ($command eq "init_only_end") {
		print "###SHELLPACK init_complete\nfi\n";
	} elsif ($command eq "init_only_continue") {
		print <<EOC
	cluster_replicate_packages
	echo Initialisation step complete, continuing
fi
EOC
	} elsif ($command eq "init_complete") {
		print <<EOC
if [ "\$INSTALL_ONLY" = "yes" ]; then
	cluster_replicate_packages
	echo $shellpack installed only as requested.
	exit \$SHELLPACK_SUCCESS
fi

INSTALL_BASENAME=`echo \$P | awk -F - '{print \$1}'`
if [ -e \$SHELLPACK_SOURCES/\${INSTALL_BASENAME}deps-installed/bin ]; then
	export PATH=\$SHELLPACK_SOURCES/\${INSTALL_BASENAME}deps-installed/bin:\$PATH
fi
if [ -e \$SHELLPACK_SOURCES/\${INSTALL_BASENAME}deps-installed/\$MMTESTS_LIBDIR ]; then
	export LD_LIBRARY_PATH=\$SHELLPACK_SOURCES/\${INSTALL_BASENAME}deps-installed/\$MMTESTS_LIBDIR:\$LD_LIBRARY_PATH
fi
EOC
	} elsif ($command eq "monitor_hooks") {
		print <<EOC
# Include monitor hooks
. \$SHELLPACK_INCLUDE/include-monitor.sh
EOC
	} elsif ($command eq "iteration_begin") {
		my ($iterations) = @details;
		print <<EOC
for ITERATION in `seq 1 $iterations`; do
	mmtests_wait_token \"iteration_begin\"
	mmtests_activity iteration \$ITERATION
EOC
	} elsif ($command eq "iteration_end") {
		print "sync\n";
		print "mmtests_wait_token \"iteration_end\"\n";
		print "done\n";
	} elsif ($command eq "threads_fib_begin") {
		my ($min_thread, $max_thread) = @details;
		print <<EOC
NR_THREADS=1
LAST_NR_THREADS=0
while [ \$NR_THREADS -lt $max_thread ]; do
	TMP_NR_THREADS=\$LAST_NR_THREADS
	LAST_NR_THREADS=\$NR_THREADS
	NR_THREADS=\$((NR_THREADS+TMP_NR_THREADS))
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	if [ \$NR_THREADS -gt $max_thread ]; then
		NR_THREADS=$max_thread
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_fib_end") {
		print "done\n";
	} elsif ($command eq "threads_powertwo_begin") {
		my ($min_thread, $max_thread) = @details;
		my $max_thread_varname = $max_thread;
		$max_thread_varname =~ s/^\$//;
		print <<EOC
NR_THREADS=$min_thread
if [ "\$NR_THREADS" = "" ]; then
	NR_THREADS=1
fi
THREADS=\$NR_THREADS
NR_THREADS=\$((NR_THREADS*2))
if [ "\$MMTESTS_THREAD_CUTOFF" != "" ]; then
	echo Forcing $max_thread_varname to \$MMTESTS_THREAD_CUTOFF
	$max_thread_varname=\$MMTESTS_THREAD_CUTOFF
fi

if [ \$NR_THREADS -ne 0 ]; then
	while [ \$NR_THREADS -le $max_thread ]; do
		THREADS="\$THREADS \$NR_THREADS"
		NR_THREADS=\$((NR_THREADS*2))
		if [ "\$NR_THREADS\" = "0" ]; then
			NR_THREADS=1
		fi
	done
	if [ `echo \$THREADS | awk '{print \$NF}'` -ne $max_thread ]; then
		THREADS="\$THREADS $max_thread"
	fi
fi
for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -gt $max_thread ]; then
		NR_THREADS=$max_thread
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_powertwo_end") {
		print <<EOC
done
EOC

	} elsif ($command eq "threads_iterate_begin") {
		my ($min_thread, $max_thread) = @details;
		print <<EOC
for NR_THREADS in `seq $min_thread $max_thread`; do
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_iterate_end") {
		print "done\n";
	} elsif ($command eq "threads_min_max_stride_begin") {
		my ($min_thread, $max_thread) = @details;
		print <<EOC
for NR_THREADS in $min_thread $max_thread; do
	mmtests_activity nr_threads \$NR_THREADS
EOC

	} elsif ($command eq "threads_stride_begin") {
		my ($min_thread, $max_thread) = @details;
		print <<EOC
THREADS=
START_THREAD=$min_thread
END_THREAD=$max_thread
if [ \$END_THREAD -gt 32 ]; then
	THREADS=`seq \$START_THREAD 8`
	THREADS="\$THREADS `seq 12 4 32`"
	THREADS="\$THREADS `seq 48 16 \$END_THREAD`"
elif [ \$END_THREAD -gt 8 ]; then
	THREADS=`seq \$START_THREAD 8`
	THREADS="\$THREADS `seq 12 4 \$END_THREAD`"
else
	THREADS=`seq \$START_THREAD \$END_THREAD`
fi
for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_large_stride_begin") {
		my ($min_thread, $max_thread) = @details;
		my $max_thread_varname = $max_thread;
		$max_thread_varname =~ s/^\$//;
		print <<EOC
THREADS=
START_THREAD=$min_thread
END_THREAD=$max_thread
if [ \$END_THREAD -gt 32 ]; then
	THREADS=`seq \$START_THREAD 3 8`
	THREADS="\$THREADS `seq 12 9 32`"
	THREADS="\$THREADS `seq 48 31 \$END_THREAD`"
elif [ \$END_THREAD -gt 8 ]; then
	THREADS=`seq \$START_THREAD 2 8`
	THREADS="\$THREADS `seq 12 6 \$END_THREAD`"
else
	THREADS=`seq \$START_THREAD 2 \$END_THREAD`
fi
if [ `echo \$THREADS | awk '{print \$NF}'` -ne \$END_THREAD ]; then
	THREADS="\$THREADS \$END_THREAD"
fi

for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	if [ "\$MMTESTS_THREAD_CUTOFF" != "" ]; then
		if [ \$NR_THREADS -gt \$MMTESTS_THREAD_CUTOFF ]; then
			echo Forcing $max_thread_varname to \$MMTESTS_THREAD_CUTOFF
			continue
		fi
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_huge_stride_begin") {
		my ($min_thread, $max_thread) = @details;
		my $max_thread_varname = $max_thread;
		$max_thread_varname =~ s/^\$//;
		print <<EOC
THREADS=
START_THREAD=$min_thread
if [ "\$MMTESTS_THREAD_CUTOFF" != "" ]; then
	echo Forcing $max_thread_varname to \$MMTESTS_THREAD_CUTOFF
	$max_thread_varname=\$MMTESTS_THREAD_CUTOFF
fi
END_THREAD=$max_thread
if [ \$END_THREAD -ge 32 ]; then
	THREADS=`seq \$START_THREAD 4 8`
	THREADS="\$THREADS `seq 12 9 32`"
	THREADS="\$THREADS `seq 48 31 \$END_THREAD`"
elif [ \$END_THREAD -ge 8 ]; then
	THREADS=`seq \$START_THREAD 3 8`
	THREADS="\$THREADS `seq 12 6 \$END_THREAD`"
else
	THREADS=`seq \$START_THREAD 2 \$END_THREAD`
fi
if [ `echo \$THREADS | awk '{print \$NF}'` -ne \$END_THREAD ]; then
	THREADS="\$THREADS \$END_THREAD"
fi
for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_stride_fixed_begin") {
		my ($min_thread, $max_thread, $samples) = @details;
		print <<EOC
THREADS="$min_thread"
THREAD_DIFF=\$(($max_thread-$min_thread))
if [ "\$THREAD_DIFF\" -lt $samples ]; then
	THREADS=`seq $min_thread $max_thread`
else
	for ITER in `seq 2 \$(($samples-1))`; do
		THREADS="\$THREADS \$((THREAD_DIFF/$samples*\$ITER))"
	done
	THREADS="\$THREADS $max_thread"
fi
for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_stride_alt_fixed_begin") {
		my ($min_thread, $max_thread, $samples) = @details;
		$samples--;
		print <<EOC
THREADS="$min_thread"
THREAD_DIFF=\$(($max_thread-$min_thread))
if [ "\$THREAD_DIFF\" -lt $samples ]; then
	THREADS=`seq $min_thread $max_thread`
else
	for ITER in `seq 1 \$(($samples-1))`; do
		THREADS="\$THREADS \$(($min_thread+THREAD_DIFF/$samples*\$ITER))"
	done
	THREADS="\$THREADS $max_thread"
fi
for NR_THREADS in \$THREADS; do
	if [ \$NR_THREADS -lt $min_thread ]; then
		continue
	fi
	mmtests_activity nr_threads \$NR_THREADS
EOC
	} elsif ($command eq "threads_stride_end") {
		print "done\n";
	} elsif ($command eq "addon") {
		my ($addon) = @details;

		print <<EOC
if [ ! -e \$SHELLPACK_ADDON/$addon/bin ]; then
	die "Shellpack addon $addon does not exist"
fi
export PATH=\$PATH:\$SHELLPACK_ADDON/$addon/bin
EOC
	} elsif ($command eq "include_file") {
		my ($file) = @details;

		if (! -e "$packdirectory/$file") {
			print "# WARNING: File $packdirectory/$file does not exist for inclusion\n";
		} else {
			print "==== BEGIN $file ====\n";
			open(my $input, "$packdirectory/$file");
			print <$input>;
			close($input);
			print "==== END $file ====\n";
		}
	} elsif ($command eq "mpich_setup_deps") {
		my ($mpi) = @details;
		print <<EOC
MPICH_INSTALL_DEPENDS=
# Install mpich requirements
if [ "\$$mpi" = "mpich" ]; then
	MPICH_INSTALL_DEPENDS="mpich mpich-devel"
	export SELFBUILD_MPICH_VERSION=v3.3.2
else
	if [ "\$MMTESTS_MPICH_SELFBUILD" = "yes" ]; then
		export SELFBUILD_MPICH_VERSION="\$$mpi"
	else
		die "Unrecognised mpich $mpi \$$mpi"
	fi
fi
if [ "\$MPICH_INSTALL_DEPENDS" != "" -a "\$MMTESTS_MPICH_SELFBUILD" != "yes" ]; then
	install-depends \$MPICH_INSTALL_DEPENDS
fi

EOC
	} elsif ($command eq "mpi_setup_deps") {
		my ($mpi) = @details;
		print <<EOC

MPI_INSTALL_DEPENDS=
# Install mpi requirements
if [ "\$$mpi" = "openmpi3" ]; then
	MPI_INSTALL_DEPENDS="openmpi3 openmpi3-devel"
	export SELFBUILD_OPENMPI_VERSION=v3.1.6
elif [ "\$$mpi" = "openmpi2" ]; then
	MPI_INSTALL_DEPENDS="openmpi2 openmpi2-devel"
	export SELFBUILD_OPENMPI_VERSION=v2.1.6
elif [ "\$$mpi" = "openmpi3" ]; then
	MPI_INSTALL_DEPENDS="openmpi3 openmpi3-devel"
	export SELFBUILD_OPENMPI_VERSION=v3.1.6
elif [ "\$$mpi" = "openmpi4" ]; then
	MPI_INSTALL_DEPENDS="openmpi4 openmpi4-devel"
	export SELFBUILD_OPENMPI_VERSION=v4.0.5
elif [ "\$$mpi" = "openmpi" ]; then
	MPI_INSTALL_DEPENDS="openmpi openmpi-devel"
	export SELFBUILD_OPENMPI_VERSION=v1.10.7
elif [ "\$$mpi" = "openmpi3-hpc" ]; then
	MPI_INSTALL_DEPENDS="openmpi3-gnu-hpc-devel"
	export SELFBUILD_OPENMPI_VERSION=v3.1.6
elif [ "\$$mpi" = "openmpi2-hpc" ]; then
	MPI_INSTALL_DEPENDS="openmpi2-gnu-hpc-devel"
else
	if [ "\$MMTESTS_MPI_SELFBUILD" = "yes" ]; then
		export SELFBUILD_OPENMPI_VERSION="\$$mpi"
	else
		die "Unrecognised MPI $mpi '\$$mpi'"
	fi
fi
if [ "\$MPI_INSTALL_DEPENDS" != "" -a "\$MMTESTS_MPI_SELFBUILD" != "yes" ]; then
	install-depends \$MPI_INSTALL_DEPENDS
fi
EOC
	} elsif ($command eq "mpi_setup_env") {
		my ($mpi, $mpipath, $mpilib, $opts) = @details;
		print <<EOC
if [ "\$MMTESTS_MPI_SELFBUILD" = "yes" ]; then
	###SHELLPACK check_external_install_required openmpibuild openmpibuild-\${SELFBUILD_OPENMPI_VERSION} \${SELFBUILD_OPENMPI_VERSION}
	export $mpipath="\$SHELLPACK_SOURCES/openmpibuild-\${SELFBUILD_OPENMPI_VERSION}-installed/bin"
	export $mpilib="\$SHELLPACK_SOURCES/openmpibuild-\${SELFBUILD_OPENMPI_VERSION}-installed/\$MMTESTS_LIBDIR"
fi
if [ "\$MMTESTS_MPICH_SELFBUILD" = "yes" ]; then
	###SHELLPACK check_external_install_required mpichbuild mpichbuild-\${SELFBUILD_MPICH_VERSION} \${SELFBUILD_MPICH_VERSION}
	export $mpipath="\$SHELLPACK_SOURCES/mpichbuild-\${SELFBUILD_MPICH_VERSION}-installed/bin"
	export $mpilib="\$SHELLPACK_SOURCES/mpichbuild-\${SELFBUILD_MPICH_VERSION}-installed/\$MMTESTS_LIBDIR"
fi

if [ "$opts" != "" ]; then
	if [ "`whoami`" = "root" ]; then
		$opts+=" --allow-run-as-root"
	fi
fi
if [ "\$$mpi" = "openmpi3-hpc" -a "\$MMTESTS_MPI_SELFBUILD" != "yes" ]; then
	module load gnu/7 openmpi/3 || die "Could not load openmpi/3 module"
	module li
elif [ "\$$mpi" = "openmpi2-hpc" -a "\$MMTESTS_MPI_SELFBUILD" != "yes" ]; then
	module load gnu/7 openmpi/2 || die "Could not load openmpi/2 module"
	module li
else
	# Setup mpi environment
	if [ "\$$mpipath" != "" ]; then
		export PATH=\$$mpipath:\$PATH
	fi

	if [ "\$$mpilib" != "" ]; then
		export LD_LIBRARY_PATH="\$$mpilib:\$LD_LIBRARY_PATH"
	fi

	export MPI_BASE_DIR=`dirname \$$mpipath`
	export MPI_DIR=`dirname \$$mpipath`
fi

if [ "\$BUILDFLAGS_ENABLE_MPIFLAGS" = "yes" ]; then
	if [ "\$INSTALL_ONLY" != "yes" ]; then
		MPIRUN_FLAGS=
		MPIRUN_BENCH=`echo \$P | sed -e 's/-bench//'`
		MPIRUN_FLAGS_ROOT="\$SHELLPACK_TOPLEVEL/configs/build-flags/\$MPIRUN_BENCH"
		for FILE in \$MPIRUN_FLAGS_ROOT/mpiflags \$MPIRUN_FLAGS_ROOT/`uname -m`/mpiflags \$MPIRUN_FLAGS_ROOT/`uname -m`/mpiflags-`hostname`; do
			if [ -f \$FILE ]; then
				MPIRUN_FLAGS=\$FILE
			fi
		done
		if [ "\$MPIRUN_FLAGS\" != "" ]; then
			echo Reading \$MPIRUN_FLAGS
			. \$MPIRUN_FLAGS
		fi
	fi
fi
EOC
	} elsif ($command eq "mpi_setup_shmem") {
	print <<EOC
export OMPI_TMPDIR=\$SHELLPACK_DATA
export TMPDIR=\$SHELLPACK_DATA
EOC
	} elsif ($command eq "install_clear") {
		my ($path) = @details;
		print <<EOC
rm -rf \$SHELLPACK_SOURCES/$path
EOC
	} elsif ($command eq "install_merge") {
		my ($src, $dst) = @details;
		print <<EOC
cd \$SHELLPACK_SOURCES/$src-installed || die "Failed to access source $src"
if [ ! -e \$SHELLPACK_SOURCES/$dst ]; then
	mkdir \$SHELLPACK_SOURCES/$dst || die "Failed to create dst $dst"
fi
tar -c * | tar -C \$SHELLPACK_SOURCES/$dst -x || die "Failed to merge $src to $dst"
if [ "\$MMTESTS_CHECK_LIBDIR" = "yes" ]; then
	if [ "\$MMTESTS_LIBDIR" = "lib64" -a -e \$SHELLPACK_SOURCES/$dst/lib ]; then
		die "Only lib64 expected but lib dir exists after merge to \$SHELLPACK_SOURCES/$dst"
	fi
fi
EOC
	} else {
		print "# WARNING: UNRECOGNISED command $command\n";
		print $_;
	}
	print "# command end: $command\n";
}

exit $ret;
