# Makefile - Don Yang (uguu.org)
#
# 11/25/11

# Platform-dependent rules
char = akari
source = $(char).c
ifeq ($(OSTYPE),cygwin)
eext = .exe
target = $(char)$(eext)
cc = i686-w64-mingw32-gcc
cflags = -O3 -Wall -ansi -pedantic -include binmode_main.h
else
eext =
target = $(char)
cc = gcc
cflags = -O3 -Wall -ansi -pedantic
endif

# Older netpbm distributions don't have ppmtoppm and pgmtopgm, use
# pnmcat as a substitute to convert text to binary.
ppmtoppm = pnmcat -tb
pgmtopgm = pnmcat -tb

# Use a custom version of ppmtopgm to ensure consistency
ppmtopgm = perl ppmtopgm.pl


all: $(target)

# Target binary
$(target): $(source)
	$(cc) $(cflags) $< -o $@

# All tests
test: test_dfa test_expand test_downsample test_downsample_source test_argv test_bf

# DFA test
test_dfa: test_output_ppm.bin test_output_pgm.bin test_output_txt.txt test_output_ppm2.bin test_output_pgm2.bin test_output_txt2.txt

test_output_ppm.bin: dfa.pl test_dfa_input.ppm
	perl dfa.pl -ppm test_dfa_input.ppm $@
	cmp test_dfa_expected_output_ppm.bin $@ || (rm $@ && false)

test_output_pgm.bin: dfa.pl test_dfa_input.pgm
	perl dfa.pl -pgm test_dfa_input.pgm $@
	cmp test_dfa_expected_output_pgm.bin $@ || (rm $@ && false)

test_output_txt.txt: dfa.pl test_dfa_input.txt
	perl dfa.pl -txt test_dfa_input.txt $@
	diff test_dfa_expected_output_txt.txt $@ || (rm $@ && false)

test_output_ppm2.bin: dfa.pl test_dfa_input2.ppm
	perl dfa2.pl -ppm test_dfa_input2.ppm $@
	cmp test_dfa_expected_output_ppm.bin $@ || (rm $@ && false)

test_output_pgm2.bin: dfa.pl test_dfa_input2.pgm
	perl dfa2.pl -pgm test_dfa_input2.pgm $@
	cmp test_dfa_expected_output_pgm.bin $@ || (rm $@ && false)

test_output_txt2.txt: dfa.pl test_dfa_input2.txt
	perl dfa2.pl -txt test_dfa_input2.txt $@
	diff test_dfa_expected_output_txt.txt $@ || (rm $@ && false)

test_dfa_input.ppm: test_dfa_input.ppm.txt
	$(ppmtoppm) < $< > $@

test_dfa_input.pgm: test_dfa_input.pgm.txt
	$(pgmtopgm) < $< > $@

test_dfa_input2.ppm: test_dfa_input2.ppm.txt
	$(ppmtoppm) < $< > $@

test_dfa_input2.pgm: test_dfa_input2.pgm.txt
	$(pgmtopgm) < $< > $@

# Expander test
test_expand: test_output_expand.txt

test_output_expand.txt: expand$(eext) test_expand_input.txt
	./expand$(eext) < test_expand_input.txt > $@
	diff -w test_expand_expected_output.txt $@ || (rm $@ && false)

expand$(eext): expand.c
	$(cc) $(cflags) $< -o $@

# Image downsampler test
prog = akari$(eext)
#prog = level0$(eext)

test_downsample: test_output_ppm_odd.ppm test_output_ppm_even.ppm test_output_pgm_odd.pgm test_output_pgm_even.pgm test_output_txt_odd.txt test_output_txt_even.txt

test_output_ppm_odd.ppm: $(prog) test_downsample_input.ppm
	./$(prog) test_downsample_input.ppm $@
	cmp $@ test_downsample_expected_ppm_odd.ppm || (rm $@ && false)

test_output_ppm_even.ppm: $(prog) test_downsample_input.ppm
	./$(prog) test_downsample_input.ppm $@ even
	cmp $@ test_downsample_expected_ppm_even.ppm || (rm $@ && false)

test_output_pgm_odd.pgm: $(prog) test_downsample_input.pgm
	./$(prog) test_downsample_input.pgm $@
	cmp $@ test_downsample_expected_pgm_odd.pgm || (rm $@ && false)

test_output_pgm_even.pgm: $(prog) test_downsample_input.pgm
	./$(prog) test_downsample_input.pgm $@ even
	cmp $@ test_downsample_expected_pgm_even.pgm || (rm $@ && false)

test_output_txt_odd.txt: $(prog) test_dfa_input.txt
	./$(prog) test_dfa_input.txt $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_txt_even.txt: $(prog) test_dfa_input2.txt
	./$(prog) test_dfa_input2.txt $@ even
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_downsample_input.ppm: generate_interlaced_ppm.pl
	perl $< | $(ppmtoppm) > $@

test_downsample_input.pgm: generate_interlaced_ppm.pl
	perl $< | $(ppmtopgm) | $(pgmtopgm) > $@

# Downsample source
test_downsample_source: test_output_downsample1$(eext) test_output_downsample2$(eext) test_output_downsample3$(eext)

test_output_downsample1$(eext): test_output_downsample1.c
	$(cc) $(cflags) $< -o $@

test_output_downsample2$(eext): test_output_downsample2.c
	$(cc) $(cflags) $< -o $@

test_output_downsample3$(eext): test_output_downsample3.c
	$(cc) $(cflags) $< -o $@

test_output_downsample1.c: $(target) $(source)
	./$(target) $(source) $@

test_output_downsample2.c: $(target) test_output_downsample1.c
	./$(target) test_output_downsample1.c $@

test_output_downsample3.c: $(target) test_output_downsample2.c
	./$(target) test_output_downsample2.c $@

# Test command line processing
test_argv: test_output_stdin_stdout_odd.txt test_output_stdin_file_odd.txt test_output_file_stdout_odd.txt test_output_file_file_odd.txt test_output_stdin_stdout_even.txt test_output_stdin_file_even.txt test_output_file_stdout_even.txt test_output_file_file_even.txt

test_output_stdin_stdout_odd.txt: $(target) test_dfa_input.txt
	./$(target) < test_dfa_input.txt > $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_stdin_file_odd.txt: $(target) test_dfa_input.txt
	./$(target) - $@ < test_dfa_input.txt
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_file_stdout_odd.txt: $(target) test_dfa_input.txt
	./$(target) test_dfa_input.txt > $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_file_file_odd.txt: $(target) test_dfa_input.txt
	./$(target) test_dfa_input.txt $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_stdin_stdout_even.txt: $(target) test_dfa_input2.txt
	./$(target) - - even < test_dfa_input2.txt > $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_stdin_file_even.txt: $(target) test_dfa_input2.txt
	./$(target) - $@ even < test_dfa_input2.txt
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_file_stdout_even.txt: $(target) test_dfa_input2.txt
	./$(target) test_dfa_input2.txt - even > $@
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

test_output_file_file_even.txt: $(target) test_dfa_input2.txt
	./$(target) test_dfa_input2.txt $@ even
	diff $@ test_dfa_expected_output_txt.txt || (rm $@ && false)

# BF code
test_bf: test_output_bf.bf test_output_bf_bf.txt test_output_bf_c.txt

test_output_bf.bf: bf.c
	grep -n BF: $< > $@

test_output_bf_bf.txt: bf.c
	$(cc) $(cflags) $< -o test_output_bf_bf$(eext)
	./test_output_bf_bf$(eext) > $@
	diff $@ test_bf_expected_output.txt || (rm $@ && false)

test_output_bf_c.txt: $(source)
	perl bfi.pl $< > $@
	diff $@ test_bf_expected_output.txt || (rm $@ && false)


# DFA images
.SUFFIXES: .dot .ps .ppm .png

.dot.ps:
	dot -Tps -o $@ $<

.ps.ppm:
	gs -q -sDEVICE=ppmraw -dBATCH -dNOPAUSE -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sOutputFile=$@ -r300 $<

.ppm.png:
	pnmcrop -sides $< | \
	pnmpad -white -top 4 -bottom 4 -left 4 -right 4 | \
	pnmscale 0.5 | \
	pnmtopng -compression 9 > $@

downsize_dfa_images: downsize_ppm.png downsize_pgm.png downsize_txt.png downsize_ppm2.png downsize_pgm2.png downsize_txt2.png

downsize_ppm.png: downsize_ppm.dot

downsize_pgm.png: downsize_pgm.dot

downsize_txt.png: downsize_txt.dot

downsize_ppm2.png: downsize_ppm2.dot

downsize_pgm2.png: downsize_pgm2.dot

downsize_txt2.png: downsize_txt2.dot

# Expanded template
downsize_prog = $(target)
expand_prog = test_output_downsample1$(eext)
#expand_prog = expand$(eext)

mix_level0.txt: mix.pl $(expand_prog) $(char).txt mix_level1.txt
	./$(expand_prog) < mix_level1.txt | \
	perl clean_eol.pl | \
	perl remove_trailing_blank_lines.pl | \
	perl mix.pl $(char).txt - > $@

mix_level1.txt: mix.pl $(expand_prog) downsize_level1.txt mix_level2.txt
	./$(expand_prog) < mix_level2.txt | \
	perl clean_eol.pl | \
	perl remove_trailing_blank_lines.pl | \
	perl mix.pl downsize_level1.txt - > $@

mix_level2.txt: mix.pl $(expand_prog) downsize_level2.txt mix_level3.txt
	./$(expand_prog) < mix_level3.txt | \
	perl clean_eol.pl | \
	perl remove_trailing_blank_lines.pl | \
	perl mix.pl downsize_level2.txt - > $@

mix_level3.txt: $(downsize_prog) downsize_level2.txt
	./$(downsize_prog) downsize_level2.txt > $@

downsize_level2.txt: $(downsize_prog) downsize_level1.txt
	./$(downsize_prog) downsize_level1.txt > $@

downsize_level1.txt: $(downsize_prog) $(char).txt
	./$(downsize_prog) $(char).txt > $@

# Subsampled program test
level0$(eext): level0a.c
	$(cc) $(cflags) $< -o $@

level1$(eext): level1.c
	$(cc) $(cflags) $< -o $@

level2$(eext): level2.c
	$(cc) $(cflags) $< -o $@

level3$(eext): level3.c
	$(cc) $(cflags) $< -o $@

# Maintenance
clean:
	-rm -f $(target)
	-rm -f downsize_*.ps downsize_*.ppm downsize_*.png
	-rm -f test_dfa_input*.ppm test_dfa_input*.pgm
	-rm -f test_downsample_input.ppm test_downsample_input.pgm
	-rm -f test_output_*
	-rm -f expand$(eext) level0$(eext) level1$(eext) level2$(eext) level3$(eext)
	-rm -f downsize_level1.txt downsize_level2.txt
	-rm -f mix_level3.txt mix_level2.txt mix_level1.txt mix_level0.txt

backup:
	-rm -f backup.tar.xz
	tar cf backup.tar *.c *.pl *.dot *.txt *.bin *.pgm *.ppm Makefile
	xz -9 backup.tar
