# @(#) makefile 1.48@(#) 95/05/22 #
# Makefile for ExFilter 1.1.2

SHELL=/bin/sh

.KEEP_STATE:

# V gives the code version we are producing.  This is built into the code!
V=1.1.3

#--------------------------------------------------------------------------
# Compute architecture types we can generate.

# ARCH is the applications architecture.
# KARCH is the kernel architecture.
# OSTYPE is the OS name, eg SunOS.
# OSMREV is the major revision level of the OS, eg 4 for SunOS 4.1.x,
#     5 for SunOS 5.x.
ARCH:sh=/bin/arch
KARCH:sh=/bin/arch -k
OSTYPE:sh=/bin/uname -s
OSMREV:sh=case `/bin/uname -s` in \
    SunOS) \
        case `/bin/uname -r` in 4.1*) echo 4;; 5*) echo 5;; *) exit 1;; esac;;\
    *) \
        exit 1;; \
    esac

# APPSARCH is the fully-qualified architechture (FQA) for non-kernel parts.
# KAPPSARCH is the FQA for kernel-dependent parts.
APPSARCH=$(ARCH)-$(OSTYPE)-$(OSMREV)
KAPPSARCH=$(ARCH)-$(KARCH)-$(OSTYPE)-$(OSMREV)

# GCC is localtion of gcc driver.
GCC=/usr/local/bin/gcc/bin/gcc

#--------------------------------------------------------------------------
# Compute target names and set default (`all') target.

# TARGETO is the name of the optimised executable.
# TARGETG is the name of the optimised gcc-compiled executable.
# TARGETc is the name of the crippled (demo) executable.
TARGETO=ExFilter.O.$(APPSARCH)
TARGETG=ExFilter.G.$(APPSARCH)
TARGETc=ExFilter.c.$(APPSARCH)

ALLTARGETS= \
     $(TARGETO) $(TARGETc) $(TARGETG)

all: $(ALLTARGETS)
	@(echo Made:; echo '    '`echo $(ALLTARGETS)`.) | fmt -c

# TARFILEsrc is a list of files to go in the tar archive for distribution.
# This does *not* include the crippled, demo versions.
TARFILEsrc=\
	ExFilter.O.sun3-SunOS-4 \
	ExFilter.O.sun4-SunOS-4 \
	ExFilter.G.sun4-SunOS-4 \
	README \
	tinyeg.conf \
	spec.dvi \
	unsupported/dp-2.3-patchlevel2-DamonMods.tar.Z \
	unsupported/sping \
	unsupported/100359-06.tar.Z

# DEMOTARFILEsrc is a list of files to go in the tar archive for a free demo.
# This includes the crippled, demo versions instead of the real ones.
# Only some very cut-down documentation is supplied.
# We don't supply PPP or Sun's STREAMS patch in this demo distribution.
# We compress this with `compress' for most convenient unpacking by BBS users,
# etc.
DEMOTARFILEsrc=\
	ExFilter.c.sun3-SunOS-4 \
	ExFilter.c.sun4-SunOS-4 \
	README.demo \
	tinyeg.conf \
	unsupported/sping

ExFilter.V$(V).distribution.tar.gz: $(TARFILEsrc)
	@rm -f $@
	tar cvf - $(TARFILEsrc) | gzip -9 -v > $@

ExFilter.V$(V).demo.tar.Z: $(DEMOTARFILEsrc)
	@rm -f $@
	tar cvf - $(DEMOTARFILEsrc) | compress -v > $@

#--------------------------------------------------------------------------
# Cleaning up, making distributions, etc.

clean: FORCE
	rm -f obj/*.o $(ALLTARGETS)

tidy: FORCE
	rm -f obj/*.o *.c *.h strings

FORCE:

#--------------------------------------------------------------------------
# List source files, headers and standard suffixes.

# FOR RELEASE CODE WE PUT IN EXPLICIT TARGETS NAMING WHICH VERSIONS OF
# THE SOURCE FILES WE USE.

# SOURCETREE is the directory containing the main SCCS-controlled
# source tree from which we extract our source.
SOURCETREE=../..

README: $(SOURCETREE)/SCCS
	sccs get -r1.1 $(SOURCETREE)/$(@F) -G$@

README.demo: $(SOURCETREE)/SCCS
	sccs get -r1.2 $(SOURCETREE)/$(@F) -G$@

tinyeg.conf: $(SOURCETREE)/SCCS
	sccs get -r1.3 $(SOURCETREE)/$(@F) -G$@

route.c: $(SOURCETREE)/SCCS
	sccs get -r1.179 $(SOURCETREE)/$(@F) -G$@

stats.c: $(SOURCETREE)/SCCS
	sccs get -r1.7 $(SOURCETREE)/$(@F) -G$@

muxmsgU.c: $(SOURCETREE)/SCCS
	sccs get -r1.18 $(SOURCETREE)/$(@F) -G$@

muxmsgC.c: $(SOURCETREE)/SCCS
	sccs get -r1.13 $(SOURCETREE)/$(@F) -G$@

rtconfig.c: $(SOURCETREE)/SCCS
	sccs get -r1.35 $(SOURCETREE)/$(@F) -G$@

ifconfig.c: $(SOURCETREE)/SCCS
	sccs get -r1.27 $(SOURCETREE)/$(@F) -G$@

hci.c: $(SOURCETREE)/SCCS
	sccs get -r1.115 $(SOURCETREE)/$(@F) -G$@

main.c: $(SOURCETREE)/SCCS
	sccs get -r1.134 $(SOURCETREE)/$(@F) -G$@

version.c: $(SOURCETREE)/SCCS
	sccs get -r1.6 $(SOURCETREE)/$(@F) -G$@

conffile.h: $(SOURCETREE)/SCCS
	sccs get -r1.39 $(SOURCETREE)/$(@F) -G$@

filter.h: $(SOURCETREE)/SCCS
	sccs get -r1.85 $(SOURCETREE)/$(@F) -G$@

muxmsg.h: $(SOURCETREE)/SCCS
	sccs get -r1.18 $(SOURCETREE)/$(@F) -G$@

queue.h: $(SOURCETREE)/SCCS
	sccs get -r1.20 $(SOURCETREE)/$(@F) -G$@

route.h: $(SOURCETREE)/SCCS
	sccs get -r1.39 $(SOURCETREE)/$(@F) -G$@

stats.h: $(SOURCETREE)/SCCS
	sccs get -r1.36 $(SOURCETREE)/$(@F) -G$@

verbosity.h: $(SOURCETREE)/SCCS
	sccs get -r1.12 $(SOURCETREE)/$(@F) -G$@

#--------------------------------------------------------------------------
# CSRC is a list of the C source files.
# The most-used routines should be in files towards the start of the
# list so that pages from the end of the code area can be dropped more
# easily.  Those routines should be towards the start of their files.
CSRC=route.c stats.c muxmsgU.c muxmsgC.c \
	rtconfig.c ifconfig.c hci.c \
	main.c version.c

# CHDR is a list of the C header files.
CHDR= conffile.h filter.h muxmsg.h queue.h route.h stats.h verbosity.h

#--------------------------------------------------------------------------
# OD is the base directory for all the (intermediate) object files.
OD=obj

# OBJOE is the ending for maximally-optimised object files.
# OBJGE is the ending for maximally-optimised gcc object files.
OBJOE=.O.$(APPSARCH).o
OBJGE=.G.$(APPSARCH).o

# OBJSO is a list of executables for the current optimised target.
# OBJSG is a list of executables for the current optimised gcc target.
OBJSO=$(CSRC:%.c=$(OD)/%$(OBJOE))
OBJSG=$(CSRC:%.c=$(OD)/%$(OBJGE))

#--------------------------------------------------------------------------
# Force some explicit dependencies.

# Make all the objects depend on all the headers.
$(OBJSO) $(OBJSG): $(CHDR)

# Force ``version'' to depend on all headers since it includes the SCCS IDs
# of the headers for version identification.
version$(OBJOE) version$(OBJGE): $(CHDR)

#--------------------------------------------------------------------------
# CFLAGS is the common set of flags passed to non-optimised, optimised
# and linted code.  This flags are used for all .c compilations.
# Note that this release has no MUX code.
# CoreFlags is an architecture-independent subset, useful for, for example,
# building the `strings' database.
CoreFlags='-DVersion="$V"' -DNO_MUX
CFLAGS=-D$(ARCH) $(CoreFlags)

#--------------------------------------------------------------------------
# Generating optimised version, (TARGETO).

# COFLAGS is the set of C flags for the optimised version
# (all of normal flags + optimisation that won't change anything that
# lint cares about, ie no conditional-compilation changes EXCEPT
# the elimination of extra *internal* consistency checking with
# -DNO_PARANOIA).
#
# For first user release, compile with paranoid internal checking.
COFLAGS = $(CFLAGS) -O2 # -DNO_PARANOIA

# CGFLAGS is the set of C flags passed to the optimised gcc version
# instead of COFLAGS.  Just like COFLAGS, none of the switches in
# here should change any conditional compilation items in the source
# so semantically the executables are exactly the same as non-optimised
# and native-optimised ones. -DNO_PARANOIA is allowed.
#
# The first line choses which warnings to enable, and the general environment.
# The second line sets the optimisation options we use.
# The third line sets options to ensure we can safely link with /bin/cc code
# and the SunOS 4.1.x and 5.x kernels.
CGFLAGS = $(CFLAGS) -DNO_PARANOIA \
        -Wall -Wno-comment -ansi -fverbose-asm \
        -O2 -fomit-frame-pointer -funroll-loops -finline-functions \
        -fpcc-struct-return -fvolatile-global

# CcFLAGS is the set of flags passed to the crippled version (built
# with /bin/cc) that can go out as a free demo.
# With it we severely restrict the number of routes and interfaces
# supported and define the DEMO preprocessor variable.  Note that
# we also pick inefficient values for some variables.  There is also
# no streams-module support in this version.  We also shrilly announce
# that this is a demo version.  We also disable HUP processing, so that
# reconfiguration requires the daemon be killed and restarted.
#
# All this should shame/force the user into getting the real thing.
#
# We remove extra internal checking, optimise the code, strip the executable,
# and put the modules together in a different (less efficient!) order;
# all to try to minimise the chance of reverse engineering.
CcFLAGS = $(CFLAGS) -O2 -DNO_PARANOIA \
	-DRT_MAXRT=13 -DMAX_IFS=2 -DDEMO '-DOfficialName="ExFilter-demo"' \
	-DNO_MUX -DNO_DOHUP

# strings is the extracted-strings database and depends on all the source
# (non-kernel) C files of *non-DEMO* code only.
#
# Note that the STREAMS module is *not* optimised using the strings
# database.  Nor is DEMO code (to be compiled with -DDEMO).
#
# We move the existing database out of the way while we build a new
# one from scratch.  If the new and the old differ we keep the new
# (possibly optimal) one, else we restore the old one, keeping its
# datestamp.
#
# We make the strings database after preprocessing with the native
# C compiler---gcc compilation should not generate extra strings.

# The strings database is too valuable to loose!
.PRECIOUS: strings

strings: $(CHDR) $(CSRC)
	@if [ -f strings ]; then mv -f strings strings.old; fi
	cc -E $(CoreFlags) $(CSRC) | xstr -c -
	@if cmp -s strings strings.old; then \
		echo Preserving old strings database. ; \
		mv -f strings.old strings; \
	 else \
		echo Discarding old strings database. ; \
	 fi

# xs.$(ARCH).o is made from strings separately to allow it to be built after
# we've tried building all the real .o files that we care about.
#
# Make the data read-only and shared (and in the text segment).
#
# This alone doesn't need CFLAGS.
$(OD)/xs.$(ARCH).o: strings
	xstr
	cc -c -R xs.c -o $(OD)/xs.$(ARCH).o
	@rm -f xs.c

# Report any new strings added at compile time, presumably from
# conditionally-compiled code and/or from headers.
$(OD)/%$(OBJOE): strings %.c
	@echo Optimising cc compile $(@:$(OD)/%$(OBJOE)=%.c) to $@.
	@cc -E $(COFLAGS) $(DEBUG_FLAGS) $(@:$(OD)/%$(OBJOE)=%.c) | \
		xstr -v -c - && \
		cc -c $(COFLAGS) $(DEBUG_FLAGS) -o $@ x.c
	@rm -f x.c

# GCC code.
# We share our strings database with the non-gcc code.
# Report any new strings added at compile time, presumably from
# conditionally-compiled code and/or from headers.
$(OD)/%$(OBJGE): strings %.c
	@echo Optimising gcc compile $(@:$(OD)/%$(OBJGE)=%.c) to $@.
	@$(GCC) -E $(CGFLAGS) $(DEBUG_FLAGS) $(@:$(OD)/%$(OBJGE)=%.c) | \
		xstr -v -c - && \
		$(GCC) -c $(CGFLAGS) $(DEBUG_FLAGS) -o $@ x.c
	@rm -f x.c

# xs.$(ARCH).o is the shared strings library and is last to get all the other
# .o files compiled first.
$(TARGETO): $(CHDR) $(OBJSO) $(OD)/xs.$(ARCH).o
	cc $(COFLAGS) $(DEBUG_FLAGS) -o $@ $(OD)/xs.$(ARCH).o $(OBJSO)
	strip $@

# GCC optimised target.
# xs.$(ARCH).o is the shared strings library and is last to get all the other
# .o files compiled first.
$(TARGETG): $(CHDR) $(OBJSG) $(OD)/xs.$(ARCH).o
	$(GCC) $(CGFLAGS) $(DEBUG_FLAGS) -o $@ $(OD)/xs.$(ARCH).o $(OBJSG)
	strip $@

# Crippled target.  Note that it should be stripped.  It does not use xstr.
# All the .c files are compiled directly to make the executable.
# Note that we force the .h files to be brought out of the archive.
$(TARGETc): $(CHDR) $(CSRC)
	cc $(CcFLAGS) -o $@ `for f in $(CSRC); do echo $$f; done | sort -r`
	strip $@
