--- /dev/null
+
+# Default flags
+
+AR ?= ar
+CC ?= gcc
+RANLIB ?= ranlib
+
+#INCLUDES += -I../debug -D__MEMORY_ALLOCATION__
+OFLAGS = -O4 -Os
+#OFLAGS = -O0
+#OFLAGS = -O4 -ffast-math -finline-functions
+#OFLAGS = -O4 -finline-functions
+#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow
+#OFLAGS += -minline-all-stringops -fsingle-precision-constant
+#OFLAGS += -malign-double
+CFLAGS += -W -Wall -Wextra -g
+#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
+#CFLAGS += -D_XOPEN_SOURCE=500
+CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS)
+LDFLAGS += -g $(LDOPTS) $(OPTIONS)
+
+LDOPT = linker
+AROPT = archive
+MV = mv
+ifneq (, $(findstring linux, $(MAKE_HOST)))
+# Linux
+else ifneq (, $(findstring mingw, $(MAKE_HOST)))
+# Windows MinGw
+CFLAGS += -DWIN32
+#LDLIBS += -lws2_32
+LDOPT = winlnk
+AROPT =
+else ifneq (, $(findstring cygwin, $(MAKE_HOST)))
+# Windows CygWin
+CFLAGS += -DWIN32
+LDOPT = winlnk
+AROPT =
+else ifneq (, $(findstring msdos, $(MAKE_HOST)))
+# MSDOS
+LDOPT = doslnk
+AROPT =
+MV = move
+endif
+
+ifeq ($(DESTDIR),)
+DESTDIR = /usr/local
+endif
+
+BINDIR = $(DESTDIR)/bin
+INCDIR = $(DESTDIR)/include
+LIBDIR = $(DESTDIR)/lib
+
+# Targets
+
+ALLEXE = $(shell for f in *.c; do grep -q '/\*\s*$(LDOPT):' $$f && echo $${f/.c}; done)
+
+ALLDLL = $(shell for f in *.c; do grep -q '/\*\s*$(AROPT):' $$f && echo lib$${f/.c}; done)
+
+SHELL = bash
+
+#MAKE = mingw32-make
+MAKEFLAGS += -s
+include $(wildcard .makefile)
+
+# Functions
+
+TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t"
+PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m"
+WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m"
+FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m"
+
+INSTALL = test -d $(2) || mkdir -p $(2) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2) $(addprefix $(2)/,$(1))
+
+VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; }
+
+GETCOMMENTS = awk '/\/\*[ \t]*$(1):/,/\*\// { sub(/.*\/\*[ \t]*$(1):/, ""); sub (/[ \t]*\*\/.*/, ""); print } /\/\/[ \t]*$(1):/ {sub (/.*\/\/[ \t]*$(1):/, ""); print }' $(2)
+#GETCOMMENTS = perl -- getcomments.pl -p='$(1):\s' -f='%' $(2)
+
+DATE = $(shell git log -1 HEAD --format=%ai|awk '{print $$1}')
+#DATE = $(shell hg log -r-1 --template '{date|isodate}'|awk '{print $$1}')
+
+## Generic rules
+
+all: depends
+ [ -z "$(ALLEXE)" ] || $(MAKE) exe
+ [ -z "$(ALLDLL)" ] || $(MAKE) lib
+
+analyze:
+ make purge
+ scan-build make
+ #scan-build -stats make
+
+count:
+ wc $(MAKEFILE_LIST) $(sort $(wildcard \
+ $(patsubst %.o,%.c,$(shell $(call GETCOMMENTS,$(LDOPT),$(ALLEXE:%=%.c) $(MAKEFILE_LIST)))) \
+ $(patsubst %.o,%.h,$(shell $(call GETCOMMENTS,$(LDOPT),$(ALLEXE:%=%.c) $(MAKEFILE_LIST)))) \
+ $(patsubst %.o,%.c,$(shell $(call GETCOMMENTS,$(AROPT),$(ALLDLL:lib%=%.c) $(MAKEFILE_LIST)))) \
+ $(patsubst %.o,%.h,$(shell $(call GETCOMMENTS,$(AROPT),$(ALLDLL:lib%=%.c) $(MAKEFILE_LIST))))))
+
+clean:
+ $(call TITLE, "Cleaning")
+ touch clean
+ rm -f clean $(wildcard \
+ $(shell $(call GETCOMMENTS,$(LDOPT),$(ALLEXE:%=%.c) $(MAKEFILE_LIST))) \
+ $(patsubst %.o,%.d,$(shell $(call GETCOMMENTS,$(LDOPT),$(ALLEXE:%=%.c) $(MAKEFILE_LIST)))) \
+ $(shell $(call GETCOMMENTS,$(AROPT),$(ALLDLL:lib%=%.c) $(MAKEFILE_LIST))) \
+ $(patsubst %.o,%.d,$(shell $(call GETCOMMENTS,$(AROPT),$(ALLDLL:lib%=%.c) $(MAKEFILE_LIST)))) \
+ *.d *.ld *.lld *.log *.o *.test .exec_* gmon.out)
+ $(call PASS, SUCCESS)
+
+depends:
+ [ "$(ALLEXE)" ] || $(call WARN,no exec to proceed)
+ for exe in $(ALLEXE); do INCLUDES="`$(call GETCOMMENTS,includes,$$exe.c)`" make `$(call GETCOMMENTS,$(LDOPT),$$exe.c) | sed 's/[^ ]*\.[^o]//g' | sed 's/\.o/.d/g'` $$exe.d || exit 1; done
+ [ -z "$(ALLEXE)" ] || make $(patsubst %, %.ld, $(ALLEXE))
+ [ "$(ALLDLL)" ] || $(call WARN,no library to proceed)
+ for dll in $(ALLDLL:lib%=%); do INCLUDES="`$(call GETCOMMENTS,includes,$$dll.c)`" make `$(call GETCOMMENTS,$(AROPT),$$dll.c) | sed 's/[^ ]*\.[^o]//g' | sed 's/\.o/.d/g'` $$dll.d || exit 1; done
+ [ -z "$(ALLDLL)" ] || make $(patsubst %, %.lld, $(ALLDLL))
+
+documentation: doxygen.conf $(shell test -f doxygen.conf && awk '{sub(/#.*/,"")} /^FILE_PATTERNS/,!/\\$$/ {sub(/\\$$/,"");sub(/.*=/,"");print}' doxygen.conf)
+ doxygen $<; true
+ sed -i s/__BEGIN_DECLS//g documentation/html/*.html
+ sed -i s/\\_\\-\\_BEGIN\\_\\-DECLS//g documentation/latex/*.tex
+
+exe: depends
+ [ "$(ALLEXE)" ] || { $(call FAIL,no exec to proceed); test; } && for exe in $(ALLEXE); do INCLUDES="`$(call GETCOMMENTS,includes,$$exe.c)`" CFLAGS="`$(call GETCOMMENTS,cflags,$$exe.c)`" $(MAKE) $$exe.exe || exit 1; done
+
+gcovs: wipe
+ $(MAKE) $(addprefix gcov_,$(ALLEXE))
+
+gprofs:
+ $(MAKE) $(addprefix gprof_,$(ALLEXE))
+
+lib: depends
+ [ "$(ALLDLL)" ] || { $(call FAIL,no exec to proceed); test; } && for dll in $(ALLDLL:lib%=%); do INCLUDES="`$(call GETCOMMENTS,includes,$$dll.c)`" CFLAGS="`$(call GETCOMMENTS,cflags,$$exe.c)`" $(MAKE) lib$$dll.a || exit 1; done
+
+purge: clean
+ $(call TITLE, "Purging")
+ touch purge
+ rm -f purge $(ALLEXE:%=%.exe) $(ALLDLL:%=%.a)
+ $(call PASS, SUCCESS)
+
+valgrinds:
+ $(MAKE) all
+ $(MAKE) $(addprefix valgrind_,$(ALLEXE))
+
+wipe: purge
+ $(call TITLE, "Wiping")
+ touch wipe
+ rm -f wipe $(wildcard *.gcda *.gcno *.gcov *.glog)
+ $(call PASS, SUCCESS)
+
+tests:
+ -rm -f $(ALLEXE:%=%.exe)
+ $(MAKE) all
+ $(MAKE) $(addprefix test_,$(ALLEXE))
+
+archive: wipe changelog
+ [ \! -f doxygen.conf ] || make documentation
+ name=`basename "$$(pwd)"`; cd ..; tar cvz --exclude='.git*' -f $$name-$(DATE).tgz $$name
+
+## Main rules
+
+include $(sort $(wildcard \
+ $(patsubst %.o,%.d,$(shell $(call GETCOMMENTS,$(LDOPT),$(ALLEXE:%=%.c) $(MAKEFILE_LIST))))) \
+ $(wildcard $(patsubst %.o,%.d,$(shell $(call GETCOMMENTS,$(AROPT),$(ALLDLL:lib%=%.c) $(MAKEFILE_LIST))))))
+include $(wildcard *.ld)
+include $(wildcard *.lld)
+
+gcov_%:
+ $(MAKE) purge
+ $(MAKE) depends
+ OPTIONS="-coverage -O0" $(MAKE) ${@:gcov_%=%}.exe
+ $(MAKE) test_$(@:gcov_%=%)
+ gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g;s/ -l[^ ]*//g' $(@:gcov_%=%.ld)`
+ $(MAKE) purge
+ grep '^ *#####' *.c.gcov || true
+
+gprof_%:
+ $(MAKE) purge
+ $(MAKE) depends
+ OPTIONS="-pg" $(MAKE) ${@:gprof_%=%}.exe
+ $(MAKE) ${@:gprof_%=%}.test
+ IFS=$$'\n'; id=1; \
+ for test in `cat ${@:gprof_%=%}.test | sed 's,${@:gprof_%=%}.exe,./${@:gprof_%=%}.exe,g'`; do \
+ log=${@:gprof_%=%}.prof-$$id.glog; \
+ $(call TITLE, test: $$test); \
+ echo $$test > $$log; \
+ eval $$test >> $$log; \
+ [ $$? -eq 0 ] \
+ && echo -e "\033[1;32mSUCCESS\033[0;0m" \
+ || echo -e "\033[1;31mFAILED\033[0;0m"; \
+ [ -f gmon.out ] && { gprof ${@:gprof_%=%}.exe gmon.out >> $$log; rm gmon.out; }; \
+ let id++; \
+ done;
+ $(MAKE) purge
+
+%.test: %.c
+ $(call TITLE, "Building $@")
+ $(call GETCOMMENTS,test, $<) > $@
+ $(call PASS, SUCCESS)
+ -rm -f _
+
+test_%: %.test %.exe
+ IFS=$$'\n'; RC=0; \
+ for test in `cat $< | sed 's,${<:.test=.exe},$(VALGRIND) ./${<:.test=.exe},g'`; do \
+ echo "=== $$test ==="; \
+ eval $$test; \
+ [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \
+ || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \
+ test "$$RC" = 1 -a "$(STOP)" = 1 && break; \
+ done; \
+ test "$$RC" -ne 1
+
+valgrind_%: %.exe
+ VALGRIND="valgrind -v --leak-check=full --log-fd=3"; \
+ export VALGRIND; \
+ $(MAKE) $(@:valgrind_%=test_%) 3>$@.log
+
+%.d: %.c
+ $(call TITLE, "Building $@")
+ $(CC) $(INCLUDES) -MM $< -o $@~
+ echo ${<:.c=.o}: $(shell $(call GETCOMMENTS,depend, $<)) >> $@~
+ $(MV) $@~ $@
+ $(call PASS, SUCCESS)
+
+lib%.lld: %.c
+ $(call TITLE, "Building $@")
+ echo ${@:.lld=.a}: $(shell $(call GETCOMMENTS,$(AROPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@
+ $(call PASS, SUCCESS)
+
+%.ld: %.c
+ $(call TITLE, "Building $@")
+ echo ${<:.c=.exe}: $(shell $(call GETCOMMENTS,$(LDOPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@
+ $(call PASS, SUCCESS)
+
+%.o: %.c
+ $(call TITLE, "Building $@")
+ $(CC) $(CFLAGS) $(INCLUDES) $(shell $(call GETCOMMENTS,cflags, $<)) -c $< -o $@
+ $(call PASS, SUCCESS)
+
+
+%.exe: %.c
+ INCLUDES="$(shell $(call GETCOMMENTS,includes, $<))" CFLAGS="$(shell $(call GETCOMMENTS,cflags, $<))" make $(<:.c=.d)
+ INCLUDES="$(shell $(call GETCOMMENTS,includes, $<))" CFLAGS="$(shell $(call GETCOMMENTS,cflags, $<))" make $(<:.c=.o)
+ $(call TITLE, "Building $@")
+ $(CC) $(LDFLAGS) ${<:.c=.o} $(shell $(call GETCOMMENTS,$(LDOPT), $<)) $(LDLIBS) -o $@
+ $(call PASS, SUCCESS)
+
+lib%.a: %.c
+ INCLUDES="$(shell $(call GETCOMMENTS,includes, $<))" CFLAGS="$(shell $(call GETCOMMENTS,cflags, $<))" make $(<:.c=.d)
+ INCLUDES="$(shell $(call GETCOMMENTS,includes, $<))" CFLAGS="$(shell $(call GETCOMMENTS,cflags, $<))" make $(<:.c=.o)
+ $(call TITLE, "Building $@")
+ $(AR) rc $@ ${<:.c=.o} $(shell $(call GETCOMMENTS,$(AROPT), $<))
+ $(RANLIB) $@
+ $(call PASS, SUCCESS)
+
+## install rules
+
+install_lib%: lib%.a
+ $(call TITLE, "Install $<")
+ $(call INSTALL, $(shell $(call GETCOMMENTS,include, `echo $< | sed 's/^lib//;s/\.a$$/.c/'`)), $(INCDIR)/`echo $< | sed 's/^lib//;s/\.a$$//'`)
+ sed -i 's/\(#include\) "\(.*\)"/\1 <'`echo $< | sed 's/^lib//;s/\.a$$//'`'\/\2>/' $(INCDIR)/`echo $< | sed 's/^lib//;s/\.a$$//'`/*.h
+ $(call INSTALL, $<, $(LIBDIR))
+ $(call PASS, SUCCESS)
+
+install_%: %.exe
+ $(call TITLE, "Install $<")
+ $(call INSTALL, $<, $(BINDIR))
+ $(call PASS, SUCCESS)
+
+install_lib:
+ make $(addprefix install_,$(ALLDLL))
+
+install_exe:
+ make $(addprefix install_,$(ALLEXE))
+
+changelog:
+ echo "Logs from $(DATE)" > $@.txt
+ git log --pretty=format:'- %s' >> $@.txt
+# hg log --template changelog >>$@.txt
+
+## Phony
+
+.PHONY: all analyze archive changelog clean count depends documentation exe gcovs gprofs install_lib install_exe lib purge tests valgrinds wipe
+
+## Precious
+
+.PRECIOUS: %.d %.o