LANGUAGE := conflate#    replace with your own language to be compiled
EXT := csg
#DIR := lang/$(LANGUAGE)
DIR := .
UPARSE=/home/gtoal/src/uparse/# source directory of unicode parser downloaded from github

# setting CC to gcc or clang explicitly should be OK.  Don't use tcc - seriously broken wchar_t support.
CC=cc 

REMAKE=-f $(DIR)/Makefile-$(LANGUAGE)

# Pick one:
#SAFEOPTS=-Ofast -DFAST   # for a factor of 3 speedup.
SAFEOPTS=-g -Wall 

# Pick one: (Note that two programs fail with runtime-checking options on, so those always use SAFEOPTS )
# btw running under valgrind gives it a clean bill of health.
OPTS=$(SAFEOPTS)
#OPTS=-DFAST -Wall -Wno-return-type -Wno-comment -fsanitize=undefined -fsanitize-undefined-trap-on-error  -fno-sanitize-recover=all -frecord-gcc-switches  -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow  -fstack-protector -O2  -ftrapv -grecord-gcc-switches  -ggdb3 # -fsanitize=address - always fails in getwc.

all: $(DIR)/$(LANGUAGE:%=%) $(DIR)/regen $(DIR)/Makefile # $(LANGUAGE:%=%.ng)  # mnemalyse
	# make $(REMAKE) regression-$(LANGUAGE)
	echo All up to date.

# This builds the actual compiler.  The demo only outputs the compiler source
# but with variables converted into upper case as a demonstration.
# Your own code could be an actual compiler, or perhaps a translator
# from your language to C.
$(DIR)/$(LANGUAGE:%=%): $(DIR)/$(LANGUAGE:%=%.h) Makefile regexp-lexer.o flex.o $(DIR)/uparse.o
	$(CC) $(OPTS) -static -o $(DIR)/$(LANGUAGE:%=%) $(DIR)/uparse.o regexp-lexer.o flex.o -lm

# This regenerates the skeleton compiler code (CST to AST conversion) from the grammar.
$(DIR)/$(LANGUAGE:%=%-ast.h): $(DIR)/regen
	./$(DIR)/regen > $(DIR)/$(LANGUAGE:%=%-ast.h)

# This regenerates the skeleton compiler code (CST to AST conversion) from the grammar.
$(DIR)/$(LANGUAGE:%=%-comp.h): $(DIR)/gencomp
	./$(DIR)/gencomp > $(DIR)/$(LANGUAGE:%=%-comp.h)

# This builds the tool to regenerate the skeleton compiler code from the grammar.
# It currently only builds the CST to AST conversion.
$(DIR)/regen: regen.c $(DIR)/$(LANGUAGE:%=%.h) parser.h flex.o $(DIR)/Makefile
	$(CC) $(SAFEOPTS) -o $(DIR)/regen -DGRAMMAR=\"$(DIR)/$(LANGUAGE:%=%.h)\" regen.c flex.o -lm

# This builds the tool to regenerate the skeleton compiler code from the grammar.
# It currently only builds the CST to AST conversion.
$(DIR)/gencomp: gencomp.c $(DIR)/$(LANGUAGE:%=%.h) parser.h flex.o $(DIR)/Makefile
	$(CC) $(SAFEOPTS) -o $(DIR)/gencomp -DGRAMMAR=\"$(DIR)/$(LANGUAGE:%=%.h)\" gencomp.c flex.o -lm

# This is a backup of the grammar extracted from the grammar tables.
# Only the basic rules are saved. Comments and some grammar extensions are dropped.
# It may be useful when making changes to the grammar after the compiler code is written.
$(DIR)/$(LANGUAGE:%=%.ng): $(DIR)/$(LANGUAGE:%=%-ast.h)
	sed -ne 's|\(.*\)//\\\\ \(.*\)|\2|gp' $(DIR)/$(LANGUAGE:%=%-ast.h) > $(DIR)/$(LANGUAGE:%=%.ng)


# This is the body of the parser.  It requires the grammar to have been converted to table form.
# uparse-main.c replaced by conflate-main.c

$(DIR)/uparse.o: uparse.c parser.h flex.h $(DIR)/Makefile $(DIR)/$(LANGUAGE:%=%.h) $(DIR)/$(LANGUAGE:%=%-ast.h) # $(DIR)/$(LANGUAGE:%=%-comp.h) conflate-main.c $(DIR)/$(LANGUAGE:%=%-filter.c)
	$(CC) $(OPTS) -o $(DIR)/uparse.o \
			-DGRAMMAR=\"$(DIR)/$(LANGUAGE:%=%.h)\" \
                        -DAPPCOMMAND=walk_csg \
			-DCST2AST=\"$(DIR)/$(LANGUAGE:%=%-ast.h)\" \
			-Wno-unused-variable -c uparse.c 

#                        -DPARSER_MAIN=\"conflate-main.c\" \
#  			-DAPPMODULE=\"$(DIR)/$(LANGUAGE:%=%-filter.c)\"


# This converts the grammar to table form.
$(DIR)/$(LANGUAGE:%=%.h): $(DIR)/$(LANGUAGE:%=%.g) takeon $(DIR)/Makefile
	./takeon $(DIR)/$(LANGUAGE:%=%.g) > $(DIR)/$(LANGUAGE:%=%.h)

# This builds the utility which converts the grammar to table form.
# NOTE: -fsanitize=address causes erroneous trap when running takeon.  Do not use that option here.

takeon: takeon.c takeon-output.c takeon-checks.c flex.h $(DIR)/Makefile flex.o
	$(CC) $(SAFEOPTS) -o takeon                                 takeon.c flex.o -lm

# This is a utility used in much of the code to support flex arrays, i.e. arrays
# which extend their allocated space as more elements are accessed.  It also
# supplies some checks on array bounds and unassigned variables.  These are
# relatively cheap to implement - the runtime of a program using flex arrays
# and checking is about 3 times that of the same program with static arrays
# and no checks.  Use the "-DFAST" option at the head of this file for a
# faster executable but only once the code is stable and ready for release testing.
flex.o: flex.c flex.h $(DIR)/Makefile
	$(CC) $(SAFEOPTS) -c flex.c

# This is an internal regular expression matcher which has been modified
# to support Unicode characters.
regexp-lexer.o: regexp-lexer.c Makefile parser.h # tools/mnemosyne.h
	$(CC) $(OPTS) -c regexp-lexer.c -Itools

# This is an old memory leak utility I used to use in the 80's - you can get
# equally good results nowadays by using valgrind instead.  It is off by default.
mnemosyne.o: tools/mnemosyne.c tools/mnemosyne.h Makefile
	$(CC) $(OPTS) -Wno-unused-variable -Wno-pointer-to-int-cast -c tools/mnemosyne.c -Itools

# The post-execution analyzer for mnemosyne (the Greek Goddess of memory)
mnemalyse: tools/mnemalyse.c tools/mnemosyne.h Makefile
	$(CC) $(OPTS) -o mnemalyse tools/mnemalyse.c -Itools

web:
	make $(REMAKE) clean
	cc -o grammar2html tools/grammar2html.c
	cc -o ctohtml tools/ctohtml.c
	./grammar2html $(DIR)/$(LANGUAGE:%=%.g) > $(DIR)/$(LANGUAGE:%=%.g.html)
	./grammar2html lang/calc/calc.g > lang/calc/calc.g.html
	./ctohtml takeon.c > takeon.c.html
	./ctohtml takeon-output.c > takeon-output.c.html
	./ctohtml takeon-checks.c > takeon-checks.c.html
	./ctohtml uparse.c > uparse.c.html
	./ctohtml $(DIR)/$(LANGUAGE:%=%.h) > $(DIR)/$(LANGUAGE:%=%.h.html)
	./ctohtml regexp-lexer.c > regexp-lexer.c.html
	./ctohtml regexp-lexer.h > regexp-lexer.h.html
	./ctohtml flex.c > flex.c.html
	./ctohtml flex.h > flex.h.html
	./ctohtml parser.h > parser.h.html
	./ctohtml regen.c > regen.c.html
	./ctohtml gencomp.c > gencomp.c.html
	./ctohtml lang/calc/calc-compile.c > lang/calc/calc-compile.c.html
	./ctohtml $(DIR)/$(LANGUAGE:%=%-ast.h) > $(DIR)/$(LANGUAGE:%=%-ast.h.html)
	./ctohtml $(DIR)/$(LANGUAGE:%=%-comp.h) > $(DIR)/$(LANGUAGE:%=%-comp.h.html)
	#./ctohtml $(DIR)/$(LANGUAGE:%=%-filter.c) > $(DIR)/$(LANGUAGE:%=%-filter.c.html)
	# vim was a bad choice and everyone may not have it installed.
	# vim's default is truly ugly and you need to add this to ~/.vimrc: colorscheme slate
	# bash -c 'vim -c TOhtml -c wqa build-parser.sh 2> /dev/null' || exit 0
	rm -f grammar2html ctohtml

# Only for the author. These won't work for anyone else.
upload:
	exit 1
	make $(REMAKE) web
	tar -cvf $(LANGUAGE:%=%.tar) *.[cgh] Makefile skeleton-Makefile *.sh README.html tools/mnem*.[ch] tools/grammar2html.c tools/ctohtml.c tests-$(LANGUAGE)/*.$(EXT) *.[chg].html test.calc skeleton-Makefile #*.sh.html
	make $(REMAKE) clean
	scp Makefile $(LANGUAGE:%=%.tar) gtoal@gtoal.com:gtoal.com/languages/$(LANGUAGE:%=%)/new-unicode-parser/
	ssh gtoal@gtoal.com "( cd gtoal.com/languages/$(LANGUAGE:%=%)/new-unicode-parser ; make $(REMAKE) clean )"
	ssh gtoal@gtoal.com "( cd gtoal.com/languages/$(LANGUAGE:%=%)/new-unicode-parser ; tar -xvf $(LANGUAGE:%=%.tar) )"

# Parse test files
regression-$(LANGUAGE):
	find $(DIR)/tests -name '*.$(EXT)' > $(DIR)/REGRESSION-TESTS-$(LANGUAGE).sh
	# Oops. Does require ecce. Need to avoid that. Use sed instead?
	ecce $(DIR)/REGRESSION-TESTS-$(LANGUAGE).sh -command "(rli=./$(DIR)/$(LANGUAGE:%=%) =m)0m-0i.#!/bin/sh.b;%c"
	chmod +x $(DIR)/REGRESSION-TESTS-$(LANGUAGE).sh
	./$(DIR)/REGRESSION-TESTS-$(LANGUAGE).sh -x

# Mr Sheen.
clean:
	rm -f *~ $(DIR)/*~ *.o $(DIR)/*.o $(DIR)/$(LANGUAGE:%=%) mnemalyse takeon a60toul ecma_to_unicode fake2strop stropify regen gencomp ctohtml grammar2html a60tohtml unicode_to_jff \#*\# $(DIR)/\#*\# [a-z]*.[chg].html $(DIR)/[a-z]*.[chg].html $(DIR)/$(LANGUAGE)-ast.h $(DIR)/$(LANGUAGE)-comp.h #*.sh.html

#tidy:
#	rm -f *~ *.o $(DIR)/$(LANGUAGE:%=%) mnemalyse takeon a60toul ecma_to_unicode fake2strop stropify regen gencomp ctohtml grammar2html a60tohtml unicode_to_jff \#*\# 


takeon.c:
	 ln -s $(UPARSE)takeon.c takeon.c

takeon-output.c:
	 ln -s $(UPARSE)takeon-output.c takeon-output.c

takeon-checks.c:
	 ln -s $(UPARSE)takeon-checks.c takeon-checks.c

flex.h:
	 ln -s $(UPARSE)flex.h flex.h

flex.c:
	 ln -s $(UPARSE)flex.c flex.c

regexp-lexer.c:
	 ln -s $(UPARSE)regexp-lexer.c regexp-lexer.c

parser.h:
	 ln -s $(UPARSE)parser.h parser.h

regexp-lexer.h:
	 ln -s $(UPARSE)regexp-lexer.h regexp-lexer.h

uparse.c:
	 ln -s $(UPARSE)uparse.c uparse.c

uparse-main.c:
	 ln -s $(UPARSE)uparse-main.c uparse-main.c

regen.c:
	 ln -s $(UPARSE)regen.c regen.c

gencomp.c:
	 ln -s $(UPARSE)gencomp.c gencomp.c
