# $Header: /a/rathlin/disk/src/master/edml/EDML4/fam.src/UPTODATE/RCS/Makefile,v 4.7 91/08/26 17:04:32 edml Exp $
# $Log:	Makefile,v $
# Revision 4.7  91/08/26  17:04:32  edml
# Incorporated srgp stuff from 4.6.2
# Ported to Silicaon Graphics Iris 4d machines
# Cleaned up makefile - default READLINE
# 
# Revision 4.6  90/11/27  16:32:26  rjg
# Branches for native code/srgp
# 
# Revision 4.4  90/07/04  11:09:33  rjg
# Readline version 4.1.00
# New bytecode OpPrompt 
# 
# Revision 4.0  89/09/20  13:28:00  rjg
# incorporated RCS
# 
# Revision 4.0  89/09/20  13:12:53  rjg
# incorporated RCS
# 
#
#	Add a new type of suffix so that we can build object code from
#	headers directly and avoid the pain of keeping two different
#	files in synchronization.
#
# NICK:	The magic suffix is now ".END", which is more obvious than ".tp".
#	All the temporary files created during a make have names beginning
#	with "_", which is more obvious than nothing at all.
#
.SUFFIXES: .h 
#
# 	You will need to configure the CFLAGS and LIBFLAGS variables 
#	depending on what features you regquire in the fam
#
#       The GNU Readline library (distributed with bash) may be used to 
#	allow line editing.  If you have this software available, 
#	add CFLAGS_RD to CFLAGS and LIBFLAGS_RD to LIBFLAGS
#       See the man pag for details on features available with Readline lib.
#
#
CFLAGS_RD = -DREADLINE -I/usr/local/include
LIBFLAGS_RD = -L/usr/local/lib -lreadline -ltermcap

#       The srgp library may be used if you want to use simple X 
#	window graphics.  Uncomment the relevant fields in CFLAGS and
# 	LIBFLAGS

CFLAGS_SRGP = -DSRGP_GRAPHICS -I/usr/local/include
LIBFLAGS_SRGP = -L/usr/local/lib -L/usr/local/lib/X11R4 -lsrgp -lX11

# uncomment if you want readline and/or srgp
CFLAGS =      $(CFLAGS_RD)    #$(CFLAGS_SRGP) -g
LIBFLAGS =    $(LIBFLAGS_RD)  #$(LIBFLAGS_SRGP)
LDFLAGS = 

#
#	NICK: never use an optimiser, if you expect your code to work
#	afterwards.
#
#	Making this a parameter allows the test target to be invoked
#	for different versions of the program.
#
VERSION = fam
#
#	Specify optional parameters for the ML interpreter itself.
#
MLPARMS = -h 180000 ml.new
#
#	Here is the rule for how to build an object module which holds
#	the storage allocation for all the external variables in a
#	header file.  The caveat with this particular rule is that you
#	should never have a header file and a C source file with the
#	same name.
#
#	Note that this allows the user to create header files which
#	contain all of the external declarations for external typing
#	and will allow external storage allocation to be done
#	automatically.  The form of the header files is as follows:
#
#	extern int	var /*/ = 0 /*/ ;
#
#	Note the very special form of comment markers, i.e. /*/, which
#	allows a distinctive form for removal.
#
.h.o:
	sed -e "s/extern//" -e "s/\/\*\///g" < $*.h > $*.c
	$(CC) -c $(CFLAGS) $*.c
	rm $*.c
.c.s:
	$(CC) -S $(CFLAGS) $*.c

.s.o:
	$(AS) -o $*.o $*.s

.c.o:
	$(CC) -c $(CFLAGS) $*.c

#
#	Define the list of all the primary targets which this makefile
#	creates.  This is most useful when it is used by clobber.
#
ALL = debug profile fam 
OTHER = _dumpcode.c _debug.c _version.c

all:	$(ALL)

#
#	Clean all extraneous files from this directory.
#
clean:
	rm -f *.o
#
#	Clean all generated files from this directory.
#
clobber:	clean
	rm -f $(ALL) $(OTHER)
#
#       Archive the files necessary to build an interpreter.
#       nuarchive archives a version suitable for export to a 
#       non-unix site.

ARCHIVEDIR = .

archive:	
	-rm -f $(OTHER)
	ar uv $(ARCHIVEDIR)/fam.a Makefile *.c *.h *.END
#
mailing:
# Several small archive files of the unix release
	-rm -f $(OTHER)
	ar uv $(ARCHIVEDIR)/fam.1.a Makefile *.h *.END
	ar uv $(ARCHIVEDIR)/fam.2.a [a-h]*.c io.c [j-z]*.c
	ar uv $(ARCHIVEDIR)/fam.3.a interp.c
# Best division; interp.c is a monster.

nuarchive:$(OTHER)
	ar uv $(ARCHIVEDIR)/primfam.a *.[ch]  
	-rm $(OTHER)

export:	$(OTHER)
# NICK: No action, other than generating _*.c
#
#	Run a test of the ML interpreter which is at least substantial
#	in nature.
#
test:	$(VERSION)
	cd ../mlsys;echo 'use "test.ml";' | ../fam/$(VERSION) $(MLPARMS) \
	> ../output/`att date +%y%m%d.%T`.RUN 2>&1

#
#	How to retrieve the function which is used to call the
#	makefile with a test target.  This file will specify which
#	version of the interpreter to run and what parameters to
#	provide it with.
#
#	List all of the object modules needed to build the ML
#	interpreter.
#
FAM = fam.o interp.o io.o store.o system.o _dumpcode.o _debug.o _version.o

#
#	How to build the ML interpreter.
#

fam:	$(FAM)
	$(CC) -o fam $(CFLAGS) $(LDFLAGS) $(FAM) -lm $(LIBFLAGS)
	rm -f _*.c _*.o

fastfam:$(FAM)
	make "CFLAGS=-O" fam

#
#	How to make a debugging version of the ML interpreter.
#
debug:
	make "CFLAGS=$(CFLAGS)" clean debug2
#
#	How to make a debugging version without starting from scratch.
#
debug2:
	make "CFLAGS=$(CFLAGS) -gx -DDEBUGinterp=1 -DNOTRACE" fam
	mv fam debug

#
#	How to make a debugging version of the ML interpreter.
#
tdebug:
	make "CFLAGS=$(CFLAGS)" clean tdebug2
#
#	How to make a debugging version without starting from scratch.
#
tdebug2:
	make "CFLAGS=$(CFLAGS) -g -DDEBUGinterp=1" fam
	mv fam debug

#
#	How to make a profiling version of the interpreter.
#
profile:
	make "CFLAGS=-p" fam
	mv fam profile

#
#	Build an optimized version of the interpreter module.  To do
#	this, the source code must contain a 'case 0:' mapped to the 
#	default case as the smallest case value (a typical valid
#	circumstance).
#
#interp.o:
#	$(CC) -S $(CFLAGS) interp.c
#	awk -f opt.awk < interp.s > interp2.s
#	mv interp2.s interp.s
#	$(AS) -o interp.o interp.s
#	rm -f interp.s
#
#	Build the version routine which will place into the binary the
#	SCCS identifiers of the versions of the routines used to
#	create the binary.
#
_version.o: _version.c
	$(CC) -c $(CFLAGS) _version.c
	rm -f _version.c

_version.c: *.c *.h
# sccs	grep "@(#)" *.c *.h > _1
	grep "\$$Header" *.c *.h > _1
# sccs	sed 's/.*\(@(#)\) \(.*\)@(#).*/"\1\2",/' < _1 > _2
	sed 's/.*\/\([^\/]*\),v \([^ ]*\).*/"\1 \2",/' < _1 > _2
	echo "char VersionId[][80] = {" | cat - _2 > _version.c
	echo '"@(#)CFLAGS = $(CFLAGS)",' >> _version.c
	echo '"@(#)LDFLAGS = $(LDFLAGS)",' >> _version.c
	echo '"" } ;' >> _version.c
	rm -f _1 _2

#
#	Create the routine which will print a profile of the FAM
#	opcodes.  Note that this routine is built automatically from
#	the master list of opcodes.
#
_debug.o:_debug.c
	$(CC) -c $(CFLAGS) _debug.c

_debug.c:debug.h
	sed -e "s/extern//" -e "s/\/\*\///g" < debug.h > _debug.c

_dumpcode.o:	_dumpcode.c
	$(CC) -c $(CFLAGS) _dumpcode.c

_dumpcode.c:	dumpcode.END bcodes.h
	echo "#ifdef DEBUGinterp" > _dumpcode.c
	echo "char opstrings[][40] = {" >> _dumpcode.c
	sed -n 's/^#[ 	]*define[ 	]*\(Op[^ 	]*\)[ 	]*\(.*\)/"\1",/p' < bcodes.h >> _dumpcode.c
	echo '"INVALID_OPCODE"} ;' >> _dumpcode.c
	echo "int opcode[] = {" >> _dumpcode.c
	sed -n "s/^#[ 	]*define[ 	]*\(Op[^ 	]*\)[ 	]*\(.*\)/\2,/p" < bcodes.h >> _dumpcode.c
	echo '-1 } ;' >> _dumpcode.c
	cat dumpcode.END >> _dumpcode.c

#
#	Automatically build the list of dependencies between source
#	files and header files.  Note that this routine automatically
#	handles nested includes.
#
makefile:Makefile
	rm -f makefile
	cp Makefile makefile
	chmod +w makefile
	grep '^#[ 	]*include[ 	]*"' *.[chyl] | \
	sed -e "s/[cyl]:/o:/" \
		-e 's/#[ 	]*include[ 	]*"//' \
		-e 's/"[ 	]*//' >> makefile
