##############################################################################
#
# Makefile
#
# Make program to build the Aldor compiler or invoke various tools
#
# Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
#
##############################################################################
#
# Targets: all, src, junk, clean, quick
#
#    make all	 -- make the compiler and associated files
#    make src	 -- make only the machine-generated "source" files
#    make junk	 -- list files which are not part of the compiler
#    make clean -- remove generated files  (e.g. foo.c~)
#
#    make quick -- make a compiler only, without regenerating associated files
#
# Parameters:	ALDORROOT
#
#    To override defaults do, e.g.,
#	  make -e ALDORROOT=/usr/aldor/base/rs all
#    or
#	  setenv ALDORROOT /usr/aldor/base/rs; setenv MAKEFLAGS e; make all
#
##############################################################################
#
#  2006/Dec/22
#
#  On Solaris, the value of PWD does not change when make is invoked
#  recursively.  Consequently, it is necessary to explicitly set it
#  at the start of the makefile.
#
PWD = $(shell pwd)

SHELL	= /bin/sh

# Cflags for building the compiler.
#CFLAGS = -g -DTEST_ALL -DSTO_DEBUG_DISPLAY # -DSTO_CAN_BLACKLIST
#CFLAGS = -O2  -DTEST_ALL
#CFLAGS = -g -DTEST_ALL -DUnBPack 
#CFLAGS = -O -DTEST_ALL -DUnBPack 
#CFLAGS = -pg -DTEST_ALL -DNLOCAL
#CFLAGS = -O -DNDEBUG
#CFLAGS  = -g -DNDEBUG
#CFLAGS = -g -O -DTEST_ALL
#CFLAGS = -DTEST_ALL
#CFLAGS = -g3 -DTEST_ALL
#CFLAGS = -O -DNDEBUG -DTEST_ALL -DUSE_MEMORY_CLIMATE
#CFLAGS = -g -O3  -DNDEBUG -DTEST_ALL
CFLAGS = -g -O3  -DUNUSED_LABELS -DNDEBUG -DTEST_ALL

#ARFLAGS= rv
ARFLAGS = rlv

# $(ALDORROOT) is retrieved from the environment
ALDORINC=$(ALDORROOT)/include
ALDORBIN=$(ALDORROOT)/bin
ALDORALIB=$(ALDORROOT)/lib
ALDORSLIB=$(ALDORROOT)/srclib
ALDORTOOLS=$(ALDORROOT)/toolbin
ALDORRUNT=../runtime/links
ANCESTOR=/aldor/version/current/src
CONFIG=$(ALDORINC)/aldor.conf
TERMCONFIG=$(ALDORINC)/sample.terminfo

EXE=
PLATFORM=
UNICL=unicl
ifeq ($(MACHINE), win32gcc)
	PLATFORM ="-mingw"
	EXE	 = .exe
	UNICL    = unicl.sh
endif

#############################################################################
#
# Source is layered with each level referring to itself or lower levels only.
#
##############################################################################

#
# Level 4: Compiler Top Level
#
ALDORTOPC	   = axlcomp.c cmdline.c
ALDORTOPH	   = axl.h axltop.h $(ALDORTOPC:.c=.h)
ALDORTOPM	   = main.c main_t.c winmain.c
ALDORTOPP	   = Makefile $(ALDORTOPM) $(ALDORTOPH) $(ALDORTOPC)

#
# Level 3: Compiler Phases and Subordinates
#
ALDORPHASEY  = axl.y
ALDORPHASEC  = phase.c bloop.c \
		include.c scan.c syscmd.c linear.c parseby.c macex.c \
		abnorm.c abcheck.c abuse.c scobind.c \
		ti_decl.c \
		tinfer.c ti_bup.c ti_tdn.c ti_sef.c terror.c \
		genfoam.c gf_fortran.c gf_add.c gf_gener.c gf_imps.c \
		gf_excpt.c gf_reference.c gf_implicit.c \
		gf_prog.c gf_rtime.c gf_seq.c opttools.c \
		optfoam.c of_util.c  of_inlin.c of_cfold.c of_hfold.c \
		of_emerg.c of_env.c of_cprop.c of_jflow.c of_peep.c \
		of_deadv.c of_comex.c of_loops.c of_retyp.c of_deada.c \
		of_rrfmt.c of_killp.c \
		emit.c ccomp.c usedef.c flatten.c \
		inlutil.c genc.c genlisp.c fortran.c gencpp.c

ALDORPHASEH  = axlphase.h gf_util.h $(ALDORPHASEC:.c=.h)
ALDORPHASEP  = $(ALDORPHASEY) $(ALDORPHASEH) $(ALDORPHASEC)

#
# Level 2: Compiler Structures
#
ALDOROBSC   = axlobs.c srcline.c token.c doc.c absyn.c absub.c ablogic.c \
		fint.c output.c simpl.c compcfg.c depdag.c \
		sefo.c syme.c freevar.c tform.c tfsat.c tposs.c tconst.c \
		tqual.c stab.c lib.c archive.c foam.c flog.c dflow.c spesym.c \
		abpretty.c version.c comsg.c loops.c
ALDOROBSH   = $(ALDOROBSC:.c=.h)
ALDOROBSP   = $(ALDOROBSH) $(ALDOROBSC) comsgdb.msg

#
# Level 1: General Library
# NB: Should split foam files
ALDORGENC   = debug.c format.c fluid.c util.c store.c memclim.c test.c \
		foam_c.c foam_i.c foam_cfp.c foamopt.c compopt.c dword.c \
		bigint.c bitv.c btree.c buffer.c dnf.c file.c fname.c list.c \
		msg.c path.c srcpos.c strops.c symbol.c table.c ccode.c \
		sexpr.c xfloat.c priq.c timer.c cfgfile.c \
		termtype.c textansi.c texthp.c textcolour.c
ALDORGENH   = axlgen.h axlgen0.h editlevels.h optcfg.h $(ALDORGENC:.c=.h)
ALDORGENT   = store1_t.c store2_t.c store3_t.c format_t.c fluid_t.c util_t.c \
	       	bigint_t.c bitv_t.c btree_t.c buffer_t.c dnf_t.c file_t.c \
		fname_t.c list_t.c msg_t.c strops_t.c symbol_t.c table_t.c \
	       	ccode_t.c xfloat_t.c link_t.c priq_t.c float_t.c
ALDORGENP   = $(ALDORGENH) $(ALDORGENC) $(ALDORGENT)

#
# Level 0: Portability
#
PORTH0        = axlport.h platform.h cconfig.h
STDCH0        = assert.h0 ctype.h0 errno.h0 float.h0 limits.h0	\
		locale.h0 math.h0 setjmp.h0 signal.h0 stdarg.h0 \
		stddef.h0 stdio.h0 stdlib.h0 string.h0 time.h0 \
		unistd.h0
OPSYSH0       = os_cms.c os_dos.c os_os2.c os_unix.c os_vms.c \
		os_macs7.c os_win32.c

ALDORPORTC   = stdc.c cport.c opsys.c
ALDORPORTH   = $(PORTH0) $(STDCH0) $(OPSYSH0) $(ALDORPORTC:.c=.h)
ALDORPORTT   = cport_t.c opsys_t.c
ALDORPORTP   = $(ALDORPORTH) $(ALDORPORTC) $(ALDORPORTT)

#ALDORASS     = any_as.s
#############################################################################
#
# File collections:
#
# PORTFILES lists files to bootstrap in a hostile environment.
# OKFILES   lists all files that should be in this directory.
#
#############################################################################

COMPC	  = $(ALDORTOPC) $(ALDORPHASEC) $(ALDOROBSC) $(ALDORGENC) $(ALDORPORTC)
COMPH	  = $(ALDORTOPH) $(ALDORPHASEH) $(ALDOROBSH) $(ALDORGENH) $(ALDORPORTH)
COMPT	  = $(ALDORGENT) $(ALDORPORTT)
COMPA     = $(ALDORASS)

PORTY	  = axl_y.yt axl_y.sed
PORTC	  = comsgdb.c axl_y.c
PORTH	  = comsgdb.h

CONFFILES = aldor.conf sample.terminfo

CFILES	  = $(COMPC) $(COMPT) $(PORTC)
HFILES	  = $(COMPH)	      $(PORTH)
ASFILES   = $(COMPA)

FFILES	  = aldor.lst aldor_a.lst aldor_t.lst 
GFILES	  = $(ALDORGENC) $(ALDORGENT) $(ALDORPORTC) $(ALDORPORTT)
AFILES	  = $(ALDORTOPM) $(CFILES)

SRCFILES  = $(ALDORTOPP) $(ALDORPHASEP) $(ALDOROBSP) $(ALDORGENP) \
	    $(ALDORPORTP) 

PORTFILES = $(PORTH) $(PORTY) $(PORTC) $(FFILES)
OKFILES	  = $(PORTFILES) $(SRCFILES) $(CONFFILES) $(ASFILES) ChangeLog

##############################################################################
#
# Targets
#
##############################################################################

#
# Generic targets
#
all:	aldor aldor_t $(CONFIG) $(TERMCONFIG) $(PORTFILES) \
	$(ALDORALIB)/comsgpig.cat $(ALDORINC)/platform.h \
	$(ALDORINC)/basic.typ $(ALDORALIB)/comsgdb.msg badzeros 

junk:
	@ ls -d $(OKFILES) * | sort | grep -v CVS | uniq -u

clean:
	@ rm -f *~

TAGS:	$(CFILES) $(HFILES)
	@ etags $(CFILES) $(HFILES)

src:	$(PORTFILES) $(SRCFILES) $(ASFILES)

srcdir: $(ALDORROOT)/src

#
# How to make specific files
#
aldor:	  $(ALDORSLIB)/aldor.mak
	@(SRC="../src" ; cd $(ALDORSLIB) ; \
	 $(MAKE) -f aldor.mak SRC=$$SRC CC=$(UNICL) AS=doas \
                               CFLAGS="$(CFLAGS) -I$$SRC" \
                               ARFLAGS="$(ARFLAGS)" \
                    aldor)

aldor_t: $(ALDORSLIB)/aldor.mak
	@(SRC="../src" ; cd $(ALDORSLIB) ; \
	 $(MAKE) -f aldor.mak SRC=$$SRC BIN=$(ALDORTOOLS) CC=$(UNICL) AS=doas \
                               CFLAGS="$(CFLAGS) -I$$SRC" \
                               ARFLAGS="$(ARFLAGS)" \
                    aldor_t)

aldor.lst: Makefile
	@echon "Making aldor.lst..."
	@ls $(CFILES) | sed -e 's/\.c//' > $@
	@echo "done"

aldor_ass.lst: Makefile
	@echon "Making aldor_ass.lst..."
	@ls $(ASSFILES) | sed -e 's/\.s//' > $@
	@echo "done"

aldor_a.lst: Makefile
	@echon "Making aldor_a.lst..."
	@ls $(AFILES) | sed -e 's/\.c//' > $@
	@echo "done"

aldor_t.lst: Makefile
	@echon "Making aldor_t.lst..."
	@ls $(GFILES) | sed -e 's/\.c//' > $@
	@echo "done"

$(ALDORROOT)/src:
	@-(if ln -s `pwd` $@ > /dev/null 2>&1 ; then \
		echo "ln `pwd` $@" ; \
	   fi)

$(ALDORSLIB)/aldor.mak: $(SRCFILES) $(PORTFILES) $(SRCDIR)
	@echon "Making aldor.mak..."
	@$(ALDORTOOLS)/domkmk \
	$(PLATFORM) \
	-V'ALDORTOPH	= $(ALDORTOPH)' \
	-V'ALDORPHASEH = $(ALDORPHASEH)' \
	-V'ALDOROBSH	= $(ALDOROBSH)' \
	-V'ALDORGENH	= $(ALDORGENH)' \
	-V'ALDORPORTH	= $(ALDORPORTH)' \
	-X'aldor     = main.c libaxl.a libaxllo.a -lm' \
	-X'aldor_t   = main_t.c libaxllo.a -lm' \
	-L'libaxl.a    = $(ALDORTOPC) $(ALDORPHASEC) $(ALDOROBSC) $(PORTC)' \
	-L'libaxllo.a  = $(ALDORGENC) $(ALDORPORTC)  $(COMPT) $(ASFILES)' \
	> $@
	@echo "done"

grammar axl_y.c axl_y.yt: axl.y token.h axl_y.sed
	$(ALDORTOOLS)/zacc -p -y axl_y.yt -c axl_y.c axl.y
	@sed -f axl_y.sed axl_y.c > $(ALDORALIB)/axl_y.c
	@if diff axl_y.c $(ALDORALIB) > /dev/null ; then \
		rm $(ALDORALIB)/axl_y.c ; \
	else \
		echo "Applied fixups to axl_y.c" ; \
		mv $(ALDORALIB)/axl_y.c . ; \
	fi

comsgdb.h comsgdb.c: comsgdb.msg
	@if [ ! -f comsgdb.h ] ; then touch comsgdb.h ; fi
	@if [ ! -f comsgdb.c ] ; then touch comsgdb.c ; fi
	@cp comsgdb.msg $(ALDORALIB)
	@(cd $(ALDORALIB); $(ALDORBIN)/msgcat -h -c -detab comsgdb)
	@if diff comsgdb.h $(ALDORALIB)/comsgdb.h > /dev/null ; then \
		rm $(ALDORALIB)/comsgdb.h ; \
	else \
		echo "Created new version of comsgdb.h" ; \
		mv $(ALDORALIB)/comsgdb.h . ; \
	fi
	@if diff comsgdb.c $(ALDORALIB)/comsgdb.c > /dev/null ; then \
		rm $(ALDORALIB)/comsgdb.c ; \
	else \
		echo "Created new version of comsgdb.c" ; \
		mv $(ALDORALIB)/comsgdb.c . ; \
	fi

# Used to test the message catalog code.
$(ALDORALIB)/comsgpig.cat: comsgdb.msg	
	(SRC=`pwd` ; cd $(ALDORALIB) ; \
	 $(ALDORTOOLS)/atinlay < $$SRC/comsgdb.msg > comsgpig.msg ; \
	 $(ALDORBIN)/msgcat -cat -detab comsgpig ; \
	 rm comsgpig.msg )

$(ALDORINC)/basic.typ: basic.typ
	cp basic.typ $(ALDORINC)

$(ALDORINC)/platform.h: platform.h
	cp platform.h $(ALDORINC)
	#
	#  2006/Dec/20
	#
	#  cconfig now needs to reside in $(ALDORINC) because it is included in
	#  foam_c.h in order to allow CC_SF_is_double to be checked
	#
	cp cconfig.h $(ALDORINC)

$(ALDORALIB)/comsgdb.msg: comsgdb.msg
	cp comsgdb.msg $(ALDORALIB)

conf: $(CONFIG) $(TERMCONFIG)

$(CONFIG): aldor.conf
	cp aldor.conf $(CONFIG)

$(TERMCONFIG): sample.terminfo
	cp sample.terminfo $(TERMCONFIG)

#
# Utilities
#

filelists: $(FFILES)

wc:	 ; wc $(SRCFILES)
wc-hi:	 ; wc $(ALDORTOPP) $(ALDORPHASEP) $(ALDOROBSP)
wc-lo:	 ; wc $(ALDORGENP) $(ALDORPORTP)
wc-port: ; wc $(ALDORPORTP)
wc-test: ; wc *_t.c

short_7.h: $(CFILES)
	cids $(CFLAGS) $(CFILES) | collide 7 | shorten > short_7.h

badzeros: 
	@ echo Checking for suspicious zeros in source files...
	@ badzeros $(COMPC) $(COMPT) $(COMPH)
	@ echo Done

lint:	; lint -Nd10000 -Nl30000 -Nn10000 -Nt10000 -D_IBMR2 $(CFILES)

quick:
	@(SRC="../src" ; cd $(ALDORSLIB) ; \
	 $(MAKE) -f aldor.mak SRC=$$SRC CC=$(UNICL) AS=doas \
                               CFLAGS="$(CFLAGS) -I$$SRC" \
                               ARFLAGS="$(ARFLAGS)" \
                    aldor)

dos: $(SRCFILES) $(PORTFILES) $(SRCDIR)
	@echon "Making aldor.mak..."
	@$(ALDORTOOLS)/domkmk \
	-msdos \
	-V'ALDORTOPH	= $(ALDORTOPH)' \
	-V'ALDORPHASEH = $(ALDORPHASEH)' \
	-V'ALDOROBSH	= $(ALDOROBSH)' \
	-V'ALDORGENH	= $(ALDORGENH)' \
	-V'ALDORPORTH	= $(ALDORPORTH)' \
	-X'aldor     = main.c libaxl.a libaxllo.a -lm' \
	-X'aldor_t   = main_t.c libaxllo.a -lm' \
	-L'libaxl.a    = $(ALDORTOPC) $(ALDORPHASEC) $(ALDOROBSC) $(PORTC)' \
	-L'libaxllo.a  = $(ALDORGENC) $(ALDORPORTC)  $(COMPT)' \
	> dos.mak
	@echo "done"


tests:	; ( cd ../test ; $(MAKE) )

enums:
	@ ( skimenum absyn.h abSynTag ; \
	    skimenum foam.h  foamTag  ; \
	    skimenum tform.h tformTag ; \
	    skimenum syme.h  symeTag  ) \
	  | awk '{ printf("%2s: %s\n", $$3, $$2); }' \
	  | pr -4t

print:
	echo "\part{Portability}"         > level0.tex
	echo "\part{General Library}"     > level1.tex
	echo "\part{Compiler Structures}" > level2.tex
	echo "\part{Compiler Phases}"     > level3.tex
	echo "\part{Compiler Top Level}"  > level4.tex
	$(ALDORTOOLS)/mksrctex \
		level4.tex $(ALDORTOPP) level3.tex $(ALDORPHASEP) \
		level2.tex $(ALDOROBSP) level1.tex $(ALDORGENP) \
		level0.tex $(ALDORPORTP)
	rm level0.tex level1.tex level2.tex level3.tex level4.tex

diffs:
	@rm -f diffs.out
	@- ( for f in  $(SRCFILES) ; do \
		echo	$$f ----------------------------------- ; \
		if diff $$f $(ANCESTOR) ; then \
			echo No difference ; \
		else \
		  echo $$f ----------------------------------- >> diffs.out ; \
		  diff $$f  $(ANCESTOR) >> diffs.out ; \
		fi ; \
	 done )
