#!/bin/sh

# Crashing C compilers
# Copyright 2015-2019 Rivoreo

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

[ -z "$CC" ] && CC=gcc
if [ "$1" = "-h" -o "$1" = "--help" ]; then
	printf "Usage: %s [-j <n>] [-c] [--] [<compiler>](=\"%s\") [<csmith-options>] [...]\\n" "$0" "$CC"
	exit 255
fi
multi=1
compile_only=
while case "$1" in
	-j)
		if [ $# -lt 1 ]; then
			echo "Option -j requires an argument" 1>&2
			exit 255
		fi
		multi="$2"
		#if [ "$multi" -le 0 ]; then
		#	exit 1
		#fi
		shift
		;;
	-c)
		compile_only=1
		unset LIBS
		;;
	--)
		shift
		false
		;;
	-*)
		printf "%s: Invalid option '%s'\\n" "$0" "$1" 1>&2
		exit 255
		;;
	*)
		false
		;;
esac
do shift
done

#CODER=csmith64
CODER=src/csmith
[ ! -z "$1" ] && CC="$1" && shift
CFLAGS="-Iruntime -w"
[ "$compile_only" = 1 ] && CFLAGS="$CFLAGS -c"
printf %s "$CC" | grep -Eq -- ' -O[0-9a-z]' || CFLAGS="$CFLAGS -Os"
#coder_version="`$CODER --version | sed -r -e 1!d`"
#printf %s "$coder_version" | grep -Eq "^csmith [0-9]" && eval "`printf %s "$coder_version" | sed -r -e 's/^csmith /version_major=/' -e 's/\\./; version_minor=/' -e 's/\\..+/;/'`" && [ -n "$version_major" ] && [ -n "$version_minor" ] && { [ "$version_major" = 2 -a "$version_minor" -ge 2 ] || [ "$version_major" -gt 2 ]; } && ! { printf %s "$CC" | grep -Eq -- ' -D[[:space:]]*UNSAFE_FLOAT([[:space:]]|=|$)'; } && LIBS="$LIBS -lm"
i=1
set -e

if [ "$multi" -gt 1 ]; then
	pids=
	while [ "$multi" -gt 0 ]; do
		rm -f "test-job-$multi.c"
		while true; do
			printf "\\r[$multi] Generating [$i] 	"
			$CODER "$@" > "test-job-$multi.c"
			#printf "\\r		"
			printf "\\r[$multi] Compiling  [$i] 	"
			$CC $CFLAGS "test-job-$multi.c" $LIBS
			i=$((i+1))
		done & pids="$! $pids"
		multi=$((multi-1))
	done
	set +e
	trap "for pid in $pids; do kill \$pid; done; echo; exit" INT
	trap "for pid in $pids; do kill \$pid; done; exit" TERM
	#for pid in $pids; do
	#	while wait $pid && kill -s 0 $pid; do sleep 1 & wait $!; done
	#done
	wait $pids
else
	rm -f test.c
	while true
	do
		printf "\\rGenerating [$i]	"
		$CODER "$@" > test.c
		#printf \\r\	\	
		printf "\\rCompiling  [$i]	"
		$CC $CFLAGS test.c $LIBS
		i=$((i+1))
	done
fi
