#############################################################################
#############################################################################
###***********************************************************************###
###* .oO0Oo.oO0Oo.oO0Oo.oO(:T:H:E: :B:A:S:T:A:R:D:)Oo.oO0Oo.oO0Oo.oO0Oo. *###
###*                                                                     *###
###*                                                                     *###
###*    Chief Makefile Architect : the grugq                             *###
###*    other people that did something:                                 *###
###*                                    mammon_ ReZiDeNt MO_K FBJ        *###
###*                                                                     *###
###*                                                                     *###
###***********************************************************************###
#############################################################################
#############################################################################



# ------------------------------------ Initialization -----------------
CC      = gcc
AR      = ar
TAR     = tar --exclude CVS -cf
UNTAR   = tar -xf
ZIP     = gzip -f
RM      = rm -rf
CP      = cp -r
LN      = ln -sf
MKDIR   = mkdir -p
#TERM    = -lcurses
TERM    = -lncurses
#TERM   = -ltermcap   # if you don't have ncurses
PROGRAM = bastard
INSTALL_DIR = /usr/local/bastard
INSTALL_BIN = /usr/local/bin
INSTALL_LIB = /usr/local/lib
VER     = 0.12
TOP     = $(PWD)

# ------------------------------------ Stuff in the ./src directory --
DEFINES  = -I./include -I./include/script -I./include/api -I/usr/local/include \
           -DREADLINE_LIBRARY
CFLAGS   = -ggdb -rdynamic $(DEFINES) -g
LIBS     = -lm -ldl -lreadline -lbastard $(TERM)
LDFLAGS  = -L. -L./lib \
            -Wl,-rpath . -Wl,-rpath ./lib
#           -Wl,-rpath $(INSTALL_DIR)/lib -Wl,-rpath . -Wl,-rpath ./lib

SRCDIR  = src
INCDIR  = include
OBJDIR  = src

SRCS    =       \
                ${SRCDIR}/cli/bastard.c     		\
                ${SRCDIR}/cli/cli_cmd.c      		\
                ${SRCDIR}/cli/cli_db.c      		\
                ${SRCDIR}/cli/parser.c    
OBJS    =       \
                ${OBJDIR}/cli/bastard.o     		\
                ${OBJDIR}/cli/cli_cmd.o      		\
                ${OBJDIR}/cli/cli_db.o      		\
                ${OBJDIR}/cli/parser.o    
HDRS    =       \
                ${INCDIR}/cli/bastard_main.h       \
                ${INCDIR}/cli/cli_cmd.h       \
                ${INCDIR}/cli/cli_db.h       \
                ${INCDIR}/cli/parser.h      

# ------------------------------------ LibBastard 
LIB_CFLAGS = -fPIC -I./include -I/usr/local/include -O3
LIB_ARFLAGS = -L./lib 
LIB_SRCS    =       \
					 ${SRCDIR}/api/api_address.c		\
					 ${SRCDIR}/api/api_code.c			\
					 ${SRCDIR}/api/api_disasm.c			\
					 ${SRCDIR}/api/api_env.c				\
					 ${SRCDIR}/api/api_functions.c		\
					 ${SRCDIR}/api/api_importexport.c	\
					 ${SRCDIR}/api/api_loadsave.c		\
					 ${SRCDIR}/api/api_macros.c			\
					 ${SRCDIR}/api/api_namecomment.c	\
                ${SRCDIR}/api/api_search.c			\
					 ${SRCDIR}/api/api_section.c		\
					 ${SRCDIR}/api/api_strings.c		\
					 ${SRCDIR}/api/api_structconst.c	\
					 ${SRCDIR}/api/api_system.c			\
					 ${SRCDIR}/api/api_xref.c			\
                ${SRCDIR}/config.c          		\
                ${SRCDIR}/db.c          		\
					 ${SRCDIR}/eic_wrappers.c     \
                ${SRCDIR}/extension.c            \
                ${SRCDIR}/macro.c            \
                ${SRCDIR}/vm.c            \
                ${SRCDIR}/util.c
LIB_HDRS    =       \
                ${INCDIR}/api/api_main.h           \
                ${INCDIR}/api/api_error.h     \
                ${INCDIR}/bastard.h       \
                ${INCDIR}/bdb.h           \
                ${INCDIR}/cfg.h           \
                ${INCDIR}/config.h            \
                ${INCDIR}/debug.h            \
                ${INCDIR}/db/db.h            \
                ${INCDIR}/db/db_main.h            \
                ${INCDIR}/db/environ.h       \
                ${INCDIR}/db/typhoon.h \
                ${INCDIR}/script/eic.h        \
                ${INCDIR}/script/eicval.h        \
                ${INCDIR}/script/macro.h         \
                ${INCDIR}/script/script_main.h   \
                ${INCDIR}/extension.h            \
                ${INCDIR}/vm.h            \
                ${INCDIR}/util.h         
LIB_OBJS    =       \
					 ${OBJDIR}/api/api_address.o		\
					 ${OBJDIR}/api/api_code.o			\
					 ${OBJDIR}/api/api_disasm.o			\
					 ${OBJDIR}/api/api_env.o				\
					 ${OBJDIR}/api/api_functions.o		\
					 ${OBJDIR}/api/api_importexport.o	\
					 ${OBJDIR}/api/api_loadsave.o		\
					 ${OBJDIR}/api/api_macros.o			\
					 ${OBJDIR}/api/api_namecomment.o	\
                ${OBJDIR}/api/api_search.o  		\
					 ${OBJDIR}/api/api_section.o		\
					 ${OBJDIR}/api/api_strings.o		\
					 ${OBJDIR}/api/api_structconst.o	\
					 ${OBJDIR}/api/api_system.o			\
					 ${OBJDIR}/api/api_xref.o			\
                ${OBJDIR}/config.o          		\
                ${OBJDIR}/db.o          		\
                ${OBJDIR}/macro.o            \
                ${OBJDIR}/util.o            \
                ${OBJDIR}/vm.o            \
                ${OBJDIR}/extension.o            \
					 ${OBJDIR}/eic_wrappers.o

# ------------------------------------ Stuff in the extension directories --
# Most of these defs are just for packaging/cleanup purposes
MOD_SOFLAGS =  -I./include -shared -lc -lm -ldl -Wl,-soname,

    # -- arch directory --
ARCHDIR = arch
ARCH_SOS     =       \
	             ${ARCHDIR}/libi386.so
ARCH_SRCS  =       \
	             ${SRCDIR}/${ARCHDIR}/i386.c
ARCH_HDRS  =       \
	             ${SRCDIR}/${ARCHDIR}/i386.h       \
	             ${SRCDIR}/${ARCHDIR}/i386.opcode.map
ARCH_OBJS  =       \
	             ${SRCDIR}/${ARCHDIR}/i386.o

	 # -- asm directory --
ASMDIR = asm
ASM_SOS   =      \
	             ${ASMDIR}/libintel.so
ASM_SRCS  =       \
	             ${SRCDIR}/${ASMDIR}/intel.c
ASM_HDRS  =       
ASM_OBJS  =       \
	             ${SRCDIR}/${ASMDIR}/intel.o

	 # -- lang directory --
LANGDIR    = lang
LANG_SOS   =       \
	             ${LANGDIR}/libC.so
LANG_SRCS  =       \
	             ${SRCDIR}/${LANGDIR}/C.c
LANG_HDRS  =       
LANG_OBJS  =       \
	             ${SRCDIR}/${LANGDIR}/C.o

	 # -- plugins directory --
PLUGINDIR    = plugins
PLUGIN_SOS   =       \
	             ${PLUGINDIR}/libdisasm.full.so \
	             ${PLUGINDIR}/libdisasm.dumb.so
PLUGIN_SRCS  =       \
	             ${SRCDIR}/${PLUGINDIR}/disasm_full.c \
	             ${SRCDIR}/${PLUGINDIR}/disasm_dumb.c
PLUGIN_HDRS  =       
PLUGIN_OBJS  =       \
	             ${SRCDIR}/${PLUGINDIR}/disasm_full.o \
	             ${SRCDIR}/${PLUGINDIR}/disasm_dumb.o

FORMATDIR    = formats
ENGINEDIR    = engines
# -- define the modules superset --
MOD_SOS    = $(PLUGIN_SOS) $(LANG_SOS) $(ASM_SOS) $(ARCH_SOS)
MOD_SRCS   = $(PLUGIN_SRCS) $(LANG_SRCS) $(ASM_SRCS) $(ARCH_SRCS)
MOD_HDRS   = $(PLUGIN_HDRS) $(LANG_HDRS) $(ASM_HDRS) $(ARCH_HDRS)
MOD_OBJS   = $(PLUGIN_OBJS) $(LANG_OBJS) $(ASM_OBJS) $(ARCH_OBJS)
MOD_DIRS   = $(PLUGINDIR) $(LANGDIR) $(ASMDIR) $(ARCHDIR) $(FORMATDIR) \
             $(ENGINEDIR)

# ------------------------------------ LibDisasm Stuff ---------------
LIBDIS_SRC = ${SRCDIR}/libdisasm/i386.c \
             ${SRCDIR}/libdisasm/libdis.c \
             ${SRCDIR}/libdisasm/quikdis.c \
             ${SRCDIR}/libdisasm/Makefile 
LIBDIS_HDR = ${SRCDIR}/libdisasm/bastard.h \
             ${SRCDIR}/libdisasm/extension.h \
             ${SRCDIR}/libdisasm/i386.h \
             ${SRCDIR}/libdisasm/i386.opcode.map \
             ${SRCDIR}/libdisasm/libdis.h \
             ${SRCDIR}/libdisasm/vm.h 
LIBDIS_BIN = ${SRCDIR}/libdisasm/libdisasm.so \
             ${SRCDIR}/libdisasm/libdis.h \
             ${SRCDIR}/libdisasm/quikdis.c \
             ${SRCDIR}/libdisasm/quikdis
             
# ------------------------------------ Tarfile collections -----------
DOCS       = doc .license README.* TODO KNOWN_BUGS
XTRA       = src/EiC src/typhoon
SCRIPTS    = scripts formats engines ${INCDIR}/script/eic
TEMPLATES  = ${SRCDIR}/${ARCHDIR}/Template.c ${SRCDIR}/${ASMDIR}/Template.c \
             ${SRCDIR}/${LANGDIR}/Template.c ${SRCDIR}/${PLUGINDIR}/Template.c
DBD_FILES  = db/bdb.dbd db/cfg.dbd $(SRCDIR)/bdb.ddl $(SRCDIR)/cfg.ddl
REQ_FILES  = utils Makefile $(DBD_FILES) $(SCRIPTS) \
             ${INCDIR}/bastard.h ${INCDIR}/bdb.h $(MOD_DIRS) 
BAST_SRC   = $(SRCS) $(HDRS) $(TEMPLATES)\
             $(LIB_SRCS) $(LIB_HDRS) \
             $(MOD_SRCS) $(MOD_HDRS) \
             $(REQ_FILES) $(DOCS) $(XTRA)
BAST_BIN   = $(PROGRAM) $(MOD_SOS) $(REQ_FILES) $(DOCS) ./lib/libbastard.so
ARCH_SRC   =  $(LIBDIS_SRC)  $(LIBDIS_HDR) doc/libi386.txt \
             utils/op-conv.pl
ARCH_BIN   = $(LIBDIS_BIN) doc/libi386.txt  

# ------------------------------------ Actual Makefile Rulesets ------
all:            dirs third_party $(PROGRAM)

dirs:
	@$(MKDIR) $(TOP)/include/script/eic
	@$(MKDIR) $(TOP)/lib

install: release
# cheat using tar
	$(MKDIR) $(INSTALL_DIR)
	@$(TAR) tmp_$(PROGRAM)-$(VER).tar $(BAST_BIN)
	@$(UNTAR) tmp_$(PROGRAM)-$(VER).tar -C$(INSTALL_DIR)
	@$(RM) tmp_$(PROGRAM)-$(VER).tar
	@echo Installing bastardly binaries...
	$(LN) $(INSTALL_DIR)/$(PROGRAM) $(INSTALL_BIN)/$(PROGRAM)
	$(LN) $(INSTALL_DIR)/utils/lgb $(INSTALL_BIN)/lgb
	@echo Installing bastardly libraries...
	$(LN) $(INSTALL_DIR)/lib/libbastard.so $(INSTALL_lib)/libbastard.so
	@echo r00ting local machine...
	@ldconfig
	@echo j/k. Done with install.

uninstall:
	@echo You Bastard! 
	@echo Removing vital binaries...
	@$(RM) $(INSTALL_BIN)/$(PROGRAM) $(INSTALL_BIN)/lgb
	@echo Removing vital libraries...
	@$(RM) $(INSTALL_lib)/libbastard.so
	@echo Trashing /usr filesystem in retribution for our fallen comrade...
	@$(RM) $(INSTALL_DIR) 
	@echo Done with uninstall.

# ================================ Third Party Libs =====================
third_party: typhoon eic

# --------------------------------- Typhoon
typhoon: $(TOP)/lib/libtyphoon.a

$(TOP)/doc/typhoon.txt:
	@cp $(TOP)/src/typhoon/man/manual.asc $(TOP)/doc/typhoon.txt
	@cp $(TOP)/src/typhoon/man/*.1 $(TOP)/doc/man

$(TOP)/lib/libtyphoon.a: dirs
	@echo "   Compiling Typhoon embedded relational database..."
	@cd $(TOP)/src/typhoon; ./configure; make install
	@cp $(TOP)/src/typhoon/util/dbdview  $(TOP)/utils
	@cp $(TOP)/src/typhoon/util/ddlp $(TOP)/utils
	@cp $(TOP)/src/typhoon/util/tyexport $(TOP)/utils
	@cp $(TOP)/src/typhoon/util/tyimport $(TOP)/utils

# --------------------------------- EiC
eic: $(TOP)/lib/libeic.a $(TOP)/doc/EiC.ps
	@cp $(TOP)/src/EiC/eic.man* $(TOP)/doc/man/eic.1

$(TOP)/doc/EiC.ps: 
	@[ -f `which latex` ] && cd $(TOP)/src/EiC/doc  && make EiC.dvi
	@[ -f ./src/EiC/doc/EiC.ps ] && cp ./src/EiC/doc/EiC.ps ./doc/EiC.ps
	@[ -f ./src/EiC/doc/EiC.ps ] && pstotext ./src/EiC/doc/EiC.ps > ./doc/EiC.txt


$(TOP)/lib/libeic.a: dirs 
	@echo "   Compiling EiC embedded interpreter..."
	@cd $(TOP)/src/EiC; config/makeconfig; make install
	@cp $(TOP)/src/EiC/lib/libeic.a $(TOP)/lib
	@cp $(TOP)/src/EiC/include/eic* $(TOP)/include/script/
	@cp -r  $(TOP)/src/EiC/include/* $(TOP)/include/script/eic/
	

$(TOP)/lib/libstdClib.a: $(TOP)/lib/libeic.a 
	@cp $(TOP)/src/EiC/lib/libstdClib.a $(TOP)/lib


# ================================ Extension =====================
## Rules for all extensions 
modules: $(MOD_SOS)


# This is obsolete ...  but may be used later for libdisasm
#$(ARCH_ARS): $(ARCH_OBJS)
#	$(AR) rcs $@ $^ 

# Compile all extension object files
$(MOD_OBJS): $(MOD_SRCS)
	$(CC) $(LIB_CFLAGS) -o $@ -c $(subst .o,.c,$@) 

# Now do each extension shared library
${ARCHDIR}/libi386.so: ${SRCDIR}/${ARCHDIR}/i386.c
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^

${ASMDIR}/libintel.so: ${SRCDIR}/${ASMDIR}/intel.o
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^

${LANGDIR}/libC.so: ${SRCDIR}/${LANGDIR}/C.o
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^

${PLUGINDIR}/libdisasm.full.so :  ${SRCDIR}/${PLUGINDIR}/disasm_full.o
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^

${PLUGINDIR}/libdisasm.dumb.so : ${SRCDIR}/${PLUGINDIR}/disasm_dumb.o
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^



# ================================ Bastard .so =====================
$(TOP)/lib/libbastard.a: $(LIB_OBJS)
	$(AR) rcs $@ $^ 
	
$(TOP)/lib/libbastard.so: $(LIB_OBJS) $(TOP)/lib/libeic.a \
                     $(TOP)/lib/libstdClib.a $(TOP)/lib/libtyphoon.a 
	$(CC) $(MOD_SOFLAGS)$@ -o $@ $^

#.c.o: ./lib/libeic.a ./lib/libstdClib.a ./lib/libtyphoon.a  $(SRCS) 
.c.o: $(SRCS) 
	$(CC) $(CFLAGS) -o $@ -c $<


# ================================ The Bastard =====================
$(PROGRAM):  $(TOP)/lib/libbastard.so $(OBJS) $(MOD_SOS)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS) 
	@ [ -f /etc/debian_version ]  || echo "Real Bastards use Debian!"



# =============================== Utility Rules ===================
release: $(PROGRAM)
	@$(RM) $(OBJS)
	@$(RM) $(LIB_OBJS)
	@$(RM) $(MOD_OBJS)
	@strip $(PROGRAM)
	@strip ./utils/ddlp
	@strip ./utils/dbdview
	@strip ./utils/tyexport
	@strip ./utils/tyimport

# ----------------------------- Cleanup
clean:
	@echo Cleaning directories...
	@$(RM) $(PROGRAM) $(OBJS) ${SRCDIR}/*~ *core ./lib/libbastard.so
	@$(RM) $(LIB_OBJS)
	@$(RM) $(MOD_OBJS)
	@$(RM) ./lib/libeic.a  ./lib/libstdClib.a ./lib/libtyphoon.a
	@$(RM) ./include/script/eic/*
	@$(RM) ./utils/dbdview ./utils/ddlp
	@$(RM) ./utils/tyexport ./utils/tyimport
	@cd    ./src/EiC; rm lib/*.a ; make clobber
	@cd    ./src/typhoon; make clean
	@echo Done.

distclean: clean
	@cd src/typhoon; make distclean
	@$(RM) doc/man/catl/*
	@$(RM) doc/.*.swp
	@$(RM) doc/*~

# ----------------------------- Tarballs
tgz: tgz_bin tgz_src 
	@mv $(PROGRAM)-$(VER).tar.gz $(PROGRAM)-$(VER).tgz
	@mv $(PROGRAM)_bin-$(VER).tar.gz $(PROGRAM)_bin-$(VER).tgz
	@mv libdisasm-$(VER).tar.gz libdisasm-$(VER).tgz
	@mv libdisasm_bin-$(VER).tar.gz libdisasm_bin-$(VER).tgz
	@echo Done.

tgz_bin: $(ARCH_ARS) release  
	@echo Making binary tarballs...
	@$(TAR) $(PROGRAM)_bin-$(VER).tar $(BAST_BIN)
	@$(MKDIR) ./$(PROGRAM)-$(VER)
	@$(UNTAR) $(PROGRAM)_bin-$(VER).tar -C./$(PROGRAM)-$(VER)
	@$(RM) $(PROGRAM)_bin-$(VER).tar
	@$(TAR) $(PROGRAM)_bin-$(VER).tar $(PROGRAM)-$(VER)
	@$(RM) ./$(PROGRAM)-$(VER)
	@$(ZIP) $(PROGRAM)_bin-$(VER).tar

	@$(TAR) libdisasm_bin-$(VER).tar $(ARCH_BIN) 
	@$(MKDIR) ./libdisasm-$(VER)
	@$(UNTAR) libdisasm_bin-$(VER).tar -C./libdisasm-$(VER)
	@$(RM) libdisasm-$(VER).tar
	$(TAR) libdisasm_bin-$(VER).tar ./libdisasm-$(VER)
	@$(RM) ./libdisasm-$(VER)
	@$(ZIP) libdisasm_bin-$(VER).tar


tgz_src: distclean
	@echo Making source tarballs...
	@$(TAR) $(PROGRAM)-$(VER).tar $(BAST_SRC)
	@$(MKDIR) ./$(PROGRAM)_src-$(VER)
	@$(UNTAR) $(PROGRAM)-$(VER).tar -C./$(PROGRAM)_src-$(VER)
	@$(RM) $(PROGRAM)-$(VER).tar 
	@$(TAR) $(PROGRAM)-$(VER).tar $(PROGRAM)_src-$(VER)
	@$(RM) ./$(PROGRAM)_src-$(VER)
	@$(ZIP) $(PROGRAM)-$(VER).tar

	@$(TAR) libdisasm-$(VER).tar $(ARCH_SRC) 
	@$(MKDIR) ./libdisasm_src-$(VER)
	@$(UNTAR) libdisasm-$(VER).tar -C./libdisasm_src-$(VER)
	@$(RM) libdisasm-$(VER).tar
	@$(TAR) libdisasm-$(VER).tar ./libdisasm_src-$(VER)
	@$(RM) ./libdisasm_src-$(VER)
	@$(ZIP) libdisasm-$(VER).tar

