#!/usr/bin/make

DEBUG?=0
OS := $(shell uname -s)
TCL_VERSION := $(shell echo 'puts $$tcl_version' | tclsh)

ifeq ($(DEBUG),0)
	CFLAGS += -O2
else
	CFLAGS += -O0 -g -ggdb -DDEBUG
endif
ifeq ($(OS),Linux)
  PDSUF = pd_linux
  PDBUNDLEFLAGS = -shared -rdynamic
  LDSOFLAGS = -lm
endif
ifeq ($(OS),Darwin)
  PDSUF = pd_darwin
  INCLUDES = -I/Library/Frameworks/Tcl.framework/Headers
  PDBUNDLEFLAGS = -bundle -flat_namespace -undefined dynamic_lookup
  LDSOFLAGS = -lm
endif
ifeq (MINGW,$(findstring MINGW,$(UNAME)))
  PDSUF = dll
  PDBUNDLEFLAGS = -shared
  LDSOFLAGS = -lm
endif

LIBNAME = composer
INCLUDES =  -I../../pd/src -I/usr/include #-I/usr/include/tcl$(TCL_VERSION)
CFLAGS += -funroll-loops -fno-operator-names -fno-omit-frame-pointer -falign-functions=16
CFLAGS += -Wall -Wno-unused
CFLAGS += -fPIC
CFLAGS += -DPDSUF=\"$(PDSUF)\"
LDSHARED = $(CXX) $(PDBUNDLEFLAGS)

all: autogen_sources $(LIBNAME).$(PDSUF)
	@echo '-----------------------------------------------------------------------------'
	@echo ' $(LIBNAME).$(PDSUF) ('`test $(DEBUG) -eq 1 && echo debug || echo release`' build) '\
		'[size: '`ls -gGh $(LIBNAME).$(PDSUF) | cut -d " " -f 3`']'

$(PDSUF): all

clean:
	rm -f $(LIBNAME).$(PDSUF)
	rm -f *.o *~
	rm -f $(AUTOGENERATED_SOURCES)
	rm -f editor_tk.cpp

.SUFFIXES: .cpp .o

SRCS = HasMeta.cpp Song.cpp Pattern.cpp Track.cpp Editor.o PdClasses.cpp
OBJS = ${SRCS:.cpp=.o}
AUTOGENERATED_SOURCES = methods.hpp methods_pd.hpp methods_ed.hpp classsetup.cpp callwrappers_pd.cpp callwrappers_ed.cpp
HasMeta.o: HasMeta.cpp HasMeta.hpp
Song.o: Song.cpp Song.hpp
Pattern.o: Pattern.cpp Pattern.hpp
Track.o: Track.cpp Track.hpp
Editor.o: Editor.cpp Editor.hpp editor_tk.cpp
PdClasses.o: PdClasses.cpp PdClasses.hpp

.cpp.o: Makefile
	$(CXX) $(CFLAGS) $(INCLUDES) -xc++ -c $<

$(LIBNAME).$(PDSUF): Makefile $(OBJS)
	$(LDSHARED) $(LDSOFLAGS) $(CFLAGS) -xnone $(OBJS) -o $(LIBNAME).$(PDSUF)

editor_tk.cpp: editor.tk
	@echo "Generating $@..."
	@( echo 'static const char* editor_tk[] = {'; sed -e 's/\(["\\]\)/\\\1/g' -e 's/^/"/' -e 's/$$/",/' editor.tk; echo '"" };' ) > editor_tk.cpp

autogen_sources: $(AUTOGENERATED_SOURCES)

methods.hpp: PdClasses.hpp
	@echo "Generating $@..."
	@awk ' \
		/^\/\*#end methods\*\/$$/{M=0} \
		{if(M==1) print $$0} \
		/^\/\*#begin methods\*\/$$/{M=1}' \
		PdClasses.hpp \
	| sed \
		-e 's/\> *\(\**\) *\w\+\(,\|)\)/\1\2/g' \
		-e 's/(/( /' -e 's/)/ )/' \
	| awk '{ \
		for(x=1; x<NF; x++) { \
			if(x<=2||x==NF) \
				printf($$x" "); \
			else \
				printf($$x" arg"(x-3)", "); \
		} \
		printf("\n"); \
		}' \
	| sed \
		-e 's/,\( arg[0-9]\+\)/\1/g' \
		-e 's/, $$/);/' \
		-e 's/( /(/' \
	> methods.hpp

methods_pd.hpp: methods.hpp
	@echo "Generating $@..."
	@sed -e 's/\<track_proxy_\w\+\>/\0P/' methods.hpp > methods_pd.hpp

methods_ed.hpp: methods.hpp
	@echo "Generating $@..."
	@sed -e 's/\<track_proxy_\w\+\>/\0E/' methods.hpp > methods_ed.hpp

classsetup.cpp: methods.hpp
	@echo "Generating $@..."
	@sed \
		-e 's/\<track_proxy_\(\w\+\)\>/\0 \1/' \
		-e 's/);$$/, /' \
		-e 's/(t_track_proxy\* arg0,\?//' \
		-e 's/ arg[0-9]\+, / /g' \
		-e 's/\<t_symbol\* int t_atom\>\*/A_GIMME, /g' \
		-e 's/\<t_symbol\>\*/A_SYMBOL, /g' \
		-e 's/\<t_floatarg\>/A_FLOAT, /g' \
		methods.hpp \
	| awk '{ \
		printf("class_addmethod(track_proxy_class, (t_method)%sP, gensym(\"%s\"), ", $$2, $$3); \
		for(i=4; i<=NF; i++) printf("%s ", $$i); \
		printf("A_NULL);\n"); \
		\
		printf("class_addmethod(track_proxy_class, (t_method)%sE, gensym(\"%sE\"), ", $$2, $$3); \
		for(i=4; i<=NF; i++) printf("%s ", $$i); \
		printf("A_NULL);\n"); \
	}' \
	> classsetup.cpp

callwrappers_pd.cpp: methods.hpp
	@echo "Generating $@..."
	@sed \
		-e 's/;$$//' \
		-e 's/^\(.*\)\(\<track_proxy_\w\+\>\)\((.*)\)$$/\1\2P\3 {\n    \2\3;\/\/real call\n    track_proxy_send_result(arg0, 1, 0);\n    return 0;\n}/' \
		methods.hpp \
	| sed \
		-e '/\/\/real call/s/(t_track_proxy\* arg0/(arg0/' \
		-e '/\/\/real call/s/\(arg[0-9]\+, \)[A-Za-z_*]\+ \(arg[0-9]\+\)/\1\2/g' \
		-e '/\/\/real call/s/\(arg[0-9]\+, \)[A-Za-z_*]\+ \(arg[0-9]\+\)/\1\2/g' \
	> callwrappers_pd.cpp

callwrappers_ed.cpp: methods.hpp
	@echo "Generating $@..."
	@sed \
		-e 's/;$$//' \
		-e 's/^\(.*\)\(\<track_proxy_\w\+\>\)\((.*)\)$$/\1\2E\3 {\n    \2\3;\/\/real call\n    track_proxy_send_result(arg0, 0, 1);\n    return 0;\n}/' \
		methods.hpp \
	| sed \
		-e '/\/\/real call/s/(t_track_proxy\* arg0/(arg0/' \
		-e '/\/\/real call/s/\(arg[0-9]\+, \)[A-Za-z_*]\+ \(arg[0-9]\+\)/\1\2/g' \
		-e '/\/\/real call/s/\(arg[0-9]\+, \)[A-Za-z_*]\+ \(arg[0-9]\+\)/\1\2/g' \
	> callwrappers_ed.cpp
