#	Automatic tests for the bounds checking library.
#	By Richard W.M. Jones. June - July, '95.

# You can use the following make targets:
#	make all
#		- Compile test program and do all the tests
#	make clean
#		- Clean up object files and program
#	make distclean
#		- Same as `make clean'.
#	make veryclean
#		- Clean up `*.res' files too (** NOT recommended **).
#	make results
#		- Remake all `*.res' files (** NOT recommended **).
#	make TESTS="0 1 2" results
#		- Remake result files for tests 0, 1, 2. Only use this if you
#		know what you're doing: eg. if you've just added another test
#		to the program. Check the result file `test-xyz.res' by hand
#		before you use it.

#----------------------------------------------------------------------

# The directory where you compiled GCC. `../..' should be OK if these tests
# are left in `bounds/tests' subdirectory.

GCCDIR	= ../..

#----------------------------------------------------------------------

# Command used to run the compiler with bounds checking.

CC	= $(GCCDIR)/xgcc -B$(GCCDIR)/
BCOPTS	= -fbounds-checking -fno-builtin

# Other flags here. `-O' or `-O2' is recommended to check there are no
# problems with optimizing bounds checked code.

CCOPTS	= -O2 -Wall

# Include files, if necessary.

INCOPTS	=

# The complete list of flags.

CFLAGS	= $(BCOPTS) $(CCOPTS) $(INCOPTS)

# Object files making up program.

OBJS	= general-test.o

# Program name.

PROG	= general-test

# Libraries.

LIBS	=

#----------------------------------------------------------------------

SHELL	= /bin/sh

all: tests

distclean: clean

clean:
	rm -f $(OBJS) $(PROG) core *~ *.bak *.BAK *.old

# Don't use the following rule unless you know what you're doing ...
veryclean: clean
	rm -f *.res *.res.old

tests: $(PROG)
	@echo "Performing tests ..."; \
	GCC_BOUNDS_OPTS="-no-message -no-warn-unchecked-statics \
		-no-warn-unchecked-stack -no-warn-free-null \
		-no-warn-misc-strings -no-statistics"; export GCC_BOUNDS_OPTS;\
	if ./$(PROG); then \
		echo "Tests OK."; \
	else \
		echo "*** Error during tests."; \
	fi

$(PROG): $(OBJS)
	$(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROG)

.c.o:
	$(CC) $(CFLAGS) -c $< -o $@

#----------------------------------------------------------------------

# Remake the results files. This assumes that the program is currently
# working. Normally you should never need to do this. Use the following
# make command:
#	make TESTS="3 4 5" results
# (remakes results of tests 3, 4 and 5) or:
#	make TESTS=all results
#	make results
# (both remake all tests).
#
# Commentary (you will probably never need to know this):
# The rule for remaking the results files is a single `sh' command which
# automatically runs `general-test -$ -test N' for each test number `N'
# and processes the output with `sed'. In particular, we delete specific
# pointer values, since these will vary from machine to machine and day
# to day. The important thing is that we recognize pointers as NULL (0),
# ILLEGAL (-1) or ``other''. Notice that `general-test' writes pointers
# in the form `ptrnn-0xpppp' where `nn' is the pointer size (16, 32 or
# 64 bits) and `pppp' is the actual pointer value. This is so we can safely
# parse these pointers here. Also we convert 0xffff -> ILLEGAL -> 0xffff
# in the `sed' script. This is so it doesn't get mangled into `0x....' by
# the intervening lines in the script.
#
# The automatic processing done by `sed' here isn't foolproof, so you'll
# need to examine the results by hand if you add your own tests.

results: $(PROG)
	@GCC_BOUNDS_OPTS="-no-message -no-warn-unchecked-statics \
		-no-warn-unchecked-stack -no-warn-free-null \
		-no-warn-misc-strings -no-statistics"; export GCC_BOUNDS_OPTS;\
	if [ "x$(TESTS)" = xall -o "x$(TESTS)" = "x" ]; then \
		tests=`grep 'define.*NR_TESTS' general-test.c | \
			head -1 | \
			awk '{for (i = 0; i < $$3; ++i) print i;}'`; \
	else \
		tests="$(TESTS)"; \
	fi; \
	for test in $$tests; do \
		echo Making file test-$$test.res; \
		if [ -f test-$$test.res ]; then \
			mv test-$$test.res test-$$test.res.old; \
		fi; \
		./$(PROG) -$$ -test $$test 2>&1 | \
		sed -e 's/ointer value: 0x.*/ointer value: */g' \
		    -e 's/ddress in memory:    0x.*/ddress in memory:    */g' \
		    -e 's/ptr16-0xffff/ptr16-ILLEGAL/g' \
		    -e 's/ptr32-0xffffffff/ptr32-ILLEGAL/g' \
		    -e 's/ptr64-0xffffffffffffffff/ptr64-ILLEGAL/g' \
		    -e 's/ptr16-0xffff/ptr16-NULL/g' \
		    -e 's/ptr32-0x00000000/ptr32-NULL/g' \
		    -e 's/ptr64-0x0000000000000000/ptr64-NULL/g' \
		    -e 's/ptr16-0x[0-9a-f][0-9a-f][0-9a-f][0-9a-f]/ptr16-0x..../g' \
		    -e 's/ptr32-0x[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/ptr32-0x......../g' \
		    -e 's/ptr64-0x[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/ptr64-0x................/g' \
		    -e 's/ptr16-ILLEGAL/ptr16-0xffff/g' \
		    -e 's/ptr32-ILLEGAL/ptr32-0xffffffff/g' \
		    -e 's/ptr64-ILLEGAL/ptr64-0xffffffffffffffff/g' \
		    -e 's/ptr16-NULL/ptr16-0x0000/g' \
		    -e 's/ptr32-NULL/ptr32-0x00000000/g' \
		    -e 's/ptr64-NULL/ptr64-0x0000000000000000/g' \
		    -e '/IOT trap\/Abort/d' > test-$$test.res; \
	done
