srcdir     :=$(shell pwd)

CFLAGS= -Wall -Wno-parentheses -O
fixed-flags = -I$(srcdir) -I$(srcdir)/box
all-C-flags:= -ansi $(fixed-flags) $(CFLAGS)
non-ansi-flags :=  $(fixed-flags) $(CFLAGS)

CC = gcc # some compiler for ANSI/ISO C

# These settings should also be used in subdirectories:
export CC all-C-flags fixed-flags CFLAGS

CWEAVE = cweave -ph +mde -Ibox/
CTANGLE = ctangle -ph

.SUFFIXES:

%.o: %.c
	$(CC) -c $(CPPFLAGS) $(all-C-flags) $<

%.c %.h %type.h: %.w
	$(CTANGLE) $<

%.tex: %.w
	$(CWEAVE) $<

%.dvi: %.tex
	TEXINPUTS=.:$(srcdir)/macros $(TEX) $<

cweb_sources=\
 gettype.w getvalue.w init.w lexer.w main.w mem.w node.w onoff.w parseaux.w\
 print.w sym.w lie.w

c_sources=\
 non-ANSI.c bigint.c binmat.c creatop.c date.c getl.c learn.c mapleread.c\
 output.c poly.c

derived_headers=\
 lie.h parser.h lexer.h mem.h node.h gettype.h getvalue.h sym.h init.h\
 main.h onoff.h memtype.h nodetype.h

box_derived_headers=\
 box/coxeter.h box/decomp.h box/domchar.h box/grpdata.h box/plethysm.h\
 box/symg.h box/tensor.h box/weylloop.h

all_derived_headers= $(derived_headers) $(box_derived_headers)

common_objects=lexer.o parser.o\
 non-ANSI.o bigint.o binmat.o creatop.o gettype.o getvalue.o\
 init.o learn.o main.o mem.o node.o onoff.o output.o poly.o sym.o

objects=$(common_objects) print.o getl.o
GAP_objects=$(common_objects) gapprint.o gapgetl.o

# Global organisation (phony targets)

.PHONY: install all script finish no_readline
.PHONY:	math_functions binding_functions

# The first target makes everything to get an operational LiE program
install: all script INFO.a

# To 'make all', we first make sure the derived header files here are tangled,
# then descend into the subdirectories, and finally return to finish here.

all: $(all_derived_headers)
	$(MAKE) math_functions binding_functions
	$(MAKE) finish

finish: Lie.exe LEARN.ind INFO.ind # do not call 'make finish' directly

math_functions:
	$(MAKE) -C box all

binding_functions:
	$(MAKE) -C static

$(box_derived_headers):
	$(MAKE) -C box prepare

# Real dependencies 

# The name non-ANSI.c is not derived from its source file lie.w (which also
# generates the header file lie.h) to stress its unusual status: it is the
# only file for which the -ansi flag should not be given to the C compiler.

non-ANSI.c: lie.w
	$(CTANGLE) lie
non-ANSI.o: non-ANSI.c
	$(CC) -c $(CPPFLAGS) $(non-ansi-flags) $<


# The change file nowhere.ch removes some diagnostic code that serves only in
# debugging to locate the code that generated each object.

mem.c mem.h memtype.h: mem.w nowhere.ch
	$(CTANGLE) mem nowhere

# These object files depend on the data types declared in those .h files:

gettype.o getvalue.o init.o main.o mem.o node.o sym.o: memtype.h nodetype.h


# The parser is generated by bison (BSD-yacc will NOT do) and in compilation
# requires inclusion of parseaux.c (derived from parseaux.w).

parser.c parser.h: parser.y
	bison -d --output-file=parser.c parser.y
parser.o: parser.c parser.h parseaux.c

lexer.o: parser.h

# Binding to the GNU readline library is achieved by -Dpreprocessor below

getl.o:	getl.c
	$(CC) -c $(CPPFLAGS) -Dpreprocessor $(all-C-flags) $<
gapgetl.o: getl.c
	$(CC) -c $(CPPFLAGS) $(all-C-flags) -o gapgetl.o $<


# For coupling to GAP, the output routines have to be slightly modified:

gapprint.c: print.w gapprint.ch
	$(CTANGLE) print gapprint gapprint

# Though date.c never changes, it should be recompiled for each modifiaction.
# Since Liegap is a separate executable, it gets its own version of the date.
# Since global recompilation should be issued by 'make all' rather than by
# 'make Lie.exe', we may assume here that the '.last_compiled' dates have just
# been set to the most recent one of object files in the respective
# subdirectories, whence taking that dummy file as dependency suffices.

date.o: date.c $(objects) box/.last_compiled static/.last_compiled
	$(CC) -ansi -c date.c
gapdate.o: date.c $(GAP_objects) box/.last_compiled static/.last_compiled
	$(CC) -ansi -c -o gapdate.o date.c

Lie.exe: date.o
	$(CC) -o Lie.exe $(objects) date.o static/*.o box/*.o -lreadline
	chmod g+w Lie.exe
Liegap.exe: gapdate.o
	$(CC) -o Liegap.exe $(GAP_objects) gapdate.o static/*.o box/*.o
	chmod g+w Liegap.exe

noreadline: $(all_derived_headers)
	$(MAKE) math_functions binding_functions $(common_objects) print.o
	$(CC) -c $(CPPFLAGS) $(all-C-flags) getl.c
	$(MAKE) date.o
	$(CC) -o Lie.exe $(objects) date.o static/*.o box/*.o
	chmod g+w Lie.exe
	$(MAKE) LEARN.ind INFO.ind script INFO.a

script:
	./make_lie

INFO.ind:	INFO.0 INFO.1 INFO.2 INFO.3 INFO.4 infoind
	./infoind

LEARN.ind:	LEARN learnind
	./learnind

infoind: util/infoind.c $(all_derived_headers)
	$(MAKE) -C util ../infoind
learnind: util/learnind.c $(all_derived_headers)
	$(MAKE) -C util ../learnind

INFO.a: progs/maxsub progs/maxsub0 progs/eqrank
	rm -f INFO.a
	./Lie.exe < progs/maxsub

# TAGS file with identifier definitions for emacs perusal. The regexp matches
# identifiers directly followed by '(' or '=' (for functions and global
# variables, respectively) which are on unindented lines, with only
# identifiers or '*' preceding them. No '*' should be attached directly to the
# identifier being defined (attach it to the identifier before it instead).
# The reason we not also match identifiers followed by ';' is that this mainly
# leads to many spurious hits in the commentary part of CWEB sections.

TAGS:	$(c_sources) $(cweb_sources)
	etags --include=box/TAGS --include=static/TAGS $(c_sources)\
 --regex='/\([a-zA-Z0-9_\*]+[ \t]+\)*\([a-zA-Z0-9_]+\)[(=]/\2/' $(cweb_sources)


$(cweb_sources:.w=.tex) parseaux.tex: $(all_derived_headers)

dvifiles:
	$(MAKE) $(cweb_sources:.w=.dvi) parseaux.dvi
	$(MAKE) -C box dvifiles

.PHONY: clean
clean:
	$(MAKE) -C box clean
	$(MAKE) -C static clean
	rm -f *~ *.o *.log *.dvi parser.[ch] INFO.a LEARN.ind
	rm -f Lie.exe Liegap.exe infoind learnind util/*.o
	rm -f  $(cweb_sources:.w=.c) gapprint.c $(derived_headers)
	rm -f $(cweb_sources:.w=.tex) $(cweb_sources:.w=.toc)
