SHELL		= /bin/sh
MAKE		= make

CC		= cc
CFLAGS		= -DNDEBUG
LDFLAGS		= $(CFLAGS)
#MACROS		= -DHNEFATAFL_ZHASH

PRGNAM		= hnefatafl
OBJ_A		= lib$(PRGNAM).a
OBJ_SO		= lib$(PRGNAM).so
OBJS		= board.o boardt.o\
		config.o\
		func.o\
		game.o gameutil.o\
		listm.o listmh.o listmht.o\
		movet.o\
		num.o numt.o\
		player.o playert.o\
		rread.o rreadt.o ruleset.o rvalid.o\
		type_piece.o type_square.o types.o\
#		zhash/zhash.o zhash/zhasht.o

HDR		= $(PRGNAM).h
HDRS		= boolt.h\
		config.h\
		funct.h\
		numt.h\
		movet.h moveht.h\
		listmt.h listmht.h\
		boardt.h\
		playert.h\
		types.h\
		gamet.h					\
		type_piecet.h type_squaret.h\
		rulesett.h\
		func.h\
		board.h\
		player.h\
		game.h gameutil.h\
		listm.h listmh.h\
		num.h\
		rread.h rvalid.h\
		type_piece.h type_square.h
#		gamet.h zhash/zhasht.h zhash/zhash.h	\

HDR_DIR		= .hdr
HDR_DCOMMENT	= $(HDR_DIR)/dcomment.awk
HDR_LICENSE	= $(HDR_DIR)/LICENSE

GLEIPNIR	= gleipnir
GLEIPNIR_DIR	= ../$(GLEIPNIR)

GLINE		= $(GLEIPNIR)_line
GLINE_A		= lib$(GLINE).a
GLINE_O		= $(GLINE).o
GLINE_H		= $(GLINE).h

GLINES		= $(GLEIPNIR)_lines
GLINES_A	= lib$(GLINES).a
GLINES_O	= $(GLINES).o
GLINES_H	= $(GLINES).h

GLINEREAD	= $(GLEIPNIR)_lineread
GLINEREAD_A	= lib$(GLINEREAD).a
GLINEREAD_O	= $(GLINEREAD).o
GLINEREAD_H	= $(GLINEREAD).h

DEPS_A		= $(GLEIPNIR_DIR)/$(GLINE_A)\
		$(GLEIPNIR_DIR)/$(GLINES_A)\
		$(GLEIPNIR_DIR)/$(GLINEREAD_A)
DEPS_O		= $(GLINE_O)\
		$(GLINES_O)\
		$(GLINEREAD_O)
DEPS_H		= $(GLEIPNIR_DIR)/$(GLINE_H)\
		$(GLEIPNIR_DIR)/$(GLINES_H)\
		$(GLEIPNIR_DIR)/$(GLINEREAD_H)

LDLIBS		= -lm
INC		= -I.\
		-Izhash\
		-I$(GLEIPNIR_DIR)
LIB		=

CLANG		= scan-build
CPPCHECK	= cppcheck --enable=all
GCC		= gcc -g -std=c89\
		-pedantic-errors -Waggregate-return -Wall\
		-Wbad-function-cast -Wcast-align -Wcast-qual -Wcomment\
		-Wconversion -Wdeclaration-after-statement\
		-Wdisabled-optimization -Wdouble-promotion -Werror\
		-Wextra -Wfloat-equal -Wformat=2\
		-Wframe-larger-than=256 -Winline -Winit-self\
		-Winvalid-pch -Wjump-misses-init -Wlarger-than=320\
		-Wlogical-op -Wlong-long -Wmissing-declarations\
		-Wmissing-format-attribute -Wmissing-include-dirs\
		-Wmissing-prototypes -Wnested-externs\
		-Wold-style-declaration -Wold-style-definition -Wpacked\
		-Wredundant-decls -Wshadow -Wstack-protector\
		-Wstack-usage=256 -Wstrict-aliasing -Wstrict-overflow=5\
		-Wstrict-prototypes -Wswitch-default -Wswitch-enum\
		-Wsync-nand -Wtrampolines -Wundef -Wuninitialized\
		-Wunreachable-code -Wunsafe-loop-optimizations -Wunused\
		-Wvector-operation-performance -Wvla -Wwrite-strings
LINT		= splint -strict -strict-lib -ansi89limits\
		-booltype HNEF_BOOL -boolfalse HNEF_FALSE\
		-booltrue HNEF_TRUE -systemdirerrors -exportany\
		-bounds +likelybounds

all: static

static: $(OBJ_A)

dynamic: $(OBJ_SO)

$(OBJ_A): $(DEPS_H) $(DEPS_O) $(OBJS)
	ar rcs $(OBJ_A) $(OBJS) $(DEPS_O)

$(OBJ_SO): $(DEPS_H) $(DEPS_O) $(OBJS)
	$(CC) $(LDFLAGS) $(LDLIBS) $(INC) $(LIB) $(MACROS)\
		-shared -Wl,-soname,$(OBJ_SO) -o $(OBJ_SO)\
		$(OBJS) $(DEPS_O)

$(GLINE_O): $(GLEIPNIR_DIR)/$(GLINE_A)
	ar x $(GLEIPNIR_DIR)/$(GLINE_A)

$(GLINES_O): $(GLEIPNIR_DIR)/$(GLINES_A)
	ar x $(GLEIPNIR_DIR)/$(GLINES_A)

$(GLINEREAD_O): $(GLEIPNIR_DIR)/$(GLINEREAD_A)
	ar x $(GLEIPNIR_DIR)/$(GLINEREAD_A)

board.o: board.c board.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o board.o board.c

boardt.o: boardt.c boardt.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o boardt.o boardt.c

config.o: config.c config.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o config.o config.c

func.o: func.c func.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o func.o func.c

game.o: game.c game.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o game.o game.c

gameutil.o: gameutil.c gameutil.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o gameutil.o gameutil.c

listm.o: listm.c listm.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o listm.o listm.c

listmh.o: listmh.c listmh.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o listmh.o listmh.c

listmht.o: listmht.c listmht.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o listmht.o listmht.c

movet.o: movet.c movet.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o movet.o movet.c

num.o: num.c num.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o num.o num.c

numt.o: numt.c numt.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o numt.o numt.c

player.o: player.c player.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o player.o player.c

playert.o: playert.c playert.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o playert.o playert.c

rread.o: rread.c rread.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o rread.o rread.c

rreadt.o: rreadt.c rreadt.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o rreadt.o rreadt.c

ruleset.o: ruleset.c ruleset.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o ruleset.o ruleset.c

rvalid.o: rvalid.c rvalid.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o rvalid.o rvalid.c

type_piece.o: type_piece.c type_piece.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o type_piece.o type_piece.c

type_square.o: type_square.c type_square.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o type_square.o type_square.c

types.o: types.c types.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o types.o types.c

zhash/zhash.o: zhash/zhash.c zhash/zhash.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o zhash/zhash.o zhash/zhash.c

zhash/zhasht.o: zhash/zhasht.c zhash/zhasht.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o zhash/zhasht.o zhash/zhasht.c

$(GLEIPNIR_DIR)/$(GLINE_A): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINE_A)\
					CC="$(CC)"\
					CFLAGS="$(CFLAGS)"

$(GLEIPNIR_DIR)/$(GLINES_A): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINES_A)\
					CC="$(CC)"\
					CFLAGS="$(CFLAGS)"

$(GLEIPNIR_DIR)/$(GLINEREAD_A): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINEREAD_A)\
					CC="$(CC)"\
					CFLAGS="$(CFLAGS)"

$(GLEIPNIR_DIR)/$(GLINE_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINE_H)

$(GLEIPNIR_DIR)/$(GLINES_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINES_H)

$(GLEIPNIR_DIR)/$(GLINEREAD_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINEREAD_H)

clean:
	rm -f $(OBJS) $(DEPS_O)
	rm -f zhash*\.o

mrproper: clean
	rm -f $(OBJ_A) $(OBJ_SO)

clean-dist: mrproper
	rm -f $(HDR)

dist: clean-dist
	$(MAKE) $(HDR)

$(HDR): $(HDRS)
	cat $(HDR_LICENSE)				> $(HDR)
	printf '%s\n%s\n%s\n%s\n%s\n'\
		'#ifndef HNEFATAFL_CORE'\
		'#define HNEFATAFL_CORE'\
		'#include "gleipnir_line.h"'\
		'#include "gleipnir_lines.h"'\
		'#include "gleipnir_lineread.h"'	>> $(HDR)
	printf '%s' $(MACROS)\
		| grep "HNEFATAFL_ZHASH"\
		&& printf '#define HNEFATAFL_ZHASH\n'	>> $(HDR)\
		|| true
	printf '#endif\n\n'				>> $(HDR)
	$(HDR_DCOMMENT) $(HDRS)				>> $(HDR)

clang: clean
	$(CLANG) $(CC) -g -std=c99 -O0 $(INC) -c *.c */*.c

cppcheck:
	$(CPPCHECK) $(INC) *.c

gcc: clean
	$(MAKE) dynamic CC="$(GCC)" CFLAGS="" LDFLAGS=""

lint:
	$(LINT) $(INC) $(MACROS) -systemdirs\
		"/usr/include:$(GLEIPNIR_DIR)"\
		*.c */*.c

.PHONY: all clean mrproper\
	dynamic static\
	clean-dist dist\
	clang cppcheck gcc lint

FORCE:

