## rules.mak
##
## This file defines a set of rules for building CCCC from source
## on any platform, given a set of predefined make variables
## which configure the compilation commands, flags etc on a given
## platform.
##
## I have attempted to put all the elements of the build which can
## be made consistent across platforms into this script, with 
## separate prefixes for each platform to contain the points
## of difference.  
##
## One of the points of difference supported is the difference
## in preprocessor syntax between Microsoft NMAKE.EXE and other
## makes including GNU Make.  The way I have dealt with this
## is to exclude use of preprocessor features from this file
## while using them freely in the platform-specific files.
##
## The following make variables must be defined before entering this
## file:
##
## PATHSEP=<the character(s) used as path separators on the platform>
## CCC=<the command to run the C++ compiler>
## CCC_OPTS=<general compiler flags>
## C_OFLAG=<the flag used to indicate the output file of a compiler run>
## LD=<the command to run the linker>
## LD_OPTS=<general linker flags>
## LD_OFLAG=<the flag used to indicate the output file of a linker run>
## OBJEXT=<the extension of an object file>
## CCCC_EXE=<the name of the final executable>

# PCCTS is now packaged as part of the CCCC distribution.
PCCTS=..$(PATHSEP)pccts
PCCTS_H=$(PCCTS)$(PATHSEP)h
PCCTS_BIN=$(PCCTS)$(PATHSEP)bin
# PCCTS_OBJDIR needs to be defined in the platform-specific makefile
# as some compilers put the obj file in $(PCCTS_H), others put it
# in the current directory.

# locations and flags for antlr and dlg (don't change the flags unless you 
# understand PCCTS)
ANTLR =         $(PCCTS_BIN)$(PATHSEP)antlr
DLG =           $(PCCTS_BIN)$(PATHSEP)dlg
# Flags for ANTLR:
# -CC       = generate C++ output
# -k 2      = use at least 2 tokens of lookahead
# -gd       = generate rule tracing code (calls to tracein() and traceout())
# -ge       = generate token classes to represent the initial set for 
#             each rule (called error sets, because their main use is
#             in simplifying error reporting when a rule fails).
# -rl 5000  = a limit on the size of the internal analysis network
#             used by the parser generator
# -w1       = basic error reporting
# The -gl flag is an option.  This causes ANTLR to emit #line directives
# which allow the compiler to generate line numbers relating to 
# positions in the .g file instead of the generated cpp files.  
# These can be useful to an IDE (jumping to error lines, e.g. in 
# emacs), or in the debugger.  
# At one time this option was broken to the extent that the code emitted 
# was actually illegal under some circumstances, but it is better now.  
# The problem is that there are still a lot of lines in the generated 
# source which do not correspond with lines in the .g file.  On balance,
# if I am debugging it is better to leave -gl off, while for onward
# development it is better to turn it on and enable the IDE features.
AFLAGS =        -CC -k 2 -gd -ge -rl 5000 -w1 -e3 
#AFLAGS =        -CC -k 2 -gd -ge -rl 5000 -w1 -e3

# Flags for DLG
DFLAGS =        -C2 -CC 

## list of files generated by the PCCTS utilities
CCCC_SPAWN =    cccc.cpp CParser.cpp CParser.h \
		Ctokens.h CLexer.cpp CLexer.h
JAVA_SPAWN =    java.cpp JParser.cpp JParser.h \
		Jtokens.h JLexer.cpp JLexer.h
ADA_SPAWN =     ada.cpp AdaPrser.cpp AdaPrser.h \
		Atokens.h ALexer.cpp ALexer.h

## the source files of the project itself
USR_G = cccc.g java.g ada.g

USR_C = ccccmain.cc cccc_tok.cc cccc_met.cc cccc_utl.cc \
		cccc_db.cc cccc_rec.cc cccc_ext.cc cccc_prj.cc cccc_mod.cc \
		cccc_mem.cc cccc_use.cc cccc_htm.cc cccc_xml.cc cccc_tbl.cc \
		cccc_tpl.cc cccc_new.cc cccc_itm.cc cccc_opt.cc

USR_H = cccc.h cccc_tok.h cccc_met.h cccc_utl.h \
		cccc_db.h cccc_htm.h cccc_tbl.h cccc_itm.h \
		cccc_opt.h

## documentation 
USR_DOC =       README.md cccc_ug.htm

## all source files
USR_SOURCE =    makefile cccc.mak cccc.dsw \
	$(USR_G) $(USR_H) $(USR_C) $(USR_DAT) $(USR_DOC)

## the final executable is linked from 3 groups of object files:

# object files compiled from PCCTS support code which does not change
PCCTS_OBJ = \
    AParser.$(OBJEXT) \
	DLexerBase.$(OBJEXT) \
	ATokenBuffer.$(OBJEXT) 

# object files compiled from C++ files generated by anltr and dlg
# They are now separated so that each language can be included or
# excluded by using make variables defined above.
CCCC_SPAWN_OBJ=cccc.$(OBJEXT) CLexer.$(OBJEXT) CParser.$(OBJEXT) 
CC_LANG_DEFINE=-DCC_INCLUDED

JAVA_SPAWN_OBJ=java.$(OBJEXT) JLexer.$(OBJEXT) JParser.$(OBJEXT) 
JAVA_LANG_DEFINE=-DJAVA_INCLUDED

#ADA_SPAWN_OBJ=ada.$(OBJEXT) ALexer.$(OBJEXT) AdaPrser.$(OBJEXT)
#ADA_LANG_DEFINE=-DADA_INCLUDED

SPAWN_OBJ = $(CCCC_SPAWN_OBJ) $(JAVA_SPAWN_OBJ) $(ADA_SPAWN_OBJ)
LANG_DEFINES = $(CC_LANG_DEFINE) $(JAVA_LANG_DEFINE) $(ADA_LANG_DEFINE)

# object files compiled from .cc files which are part of the cccc source
USR_OBJ = \
	ccccmain.$(OBJEXT) cccc_utl.$(OBJEXT) cccc_opt.$(OBJEXT) \
	cccc_db.$(OBJEXT)  cccc_rec.$(OBJEXT) cccc_ext.$(OBJEXT) \
	cccc_prj.$(OBJEXT) cccc_mod.$(OBJEXT) cccc_mem.$(OBJEXT) \
	cccc_use.$(OBJEXT) cccc_met.$(OBJEXT) cccc_htm.$(OBJEXT) cccc_xml.$(OBJEXT) \
	cccc_tok.$(OBJEXT) cccc_tbl.$(OBJEXT) \
	cccc_tpl.$(OBJEXT) cccc_new.$(OBJEXT) cccc_itm.$(OBJEXT) \


ALL_OBJ = $(SPAWN_OBJ) $(USR_OBJ) $(PCCTS_OBJ) 



all: $(CCCC_EXE) 


$(CCCC_EXE): $(USR_G) $(ANLTR_SPAWN) $(DLG_SPAWN) $(USR_H) $(USR_C) $(ALL_OBJ)
	$(CCC) $(ALL_OBJ) $(LD_OPTS)  $(LD_EXTRA_LIBS) $(LD_OFLAG)$(CCCC_EXE)

.SUFFIXES: .cc .$(OBJEXT) .cpp .cxx .g .g_info

## ANTLR can give us some very useful documentation including a 
## cross reference of the rules and a list of first token sets
## for each rule

.g.g_info:
	$(ANTLR) $(AFLAGS) -gc -gx -pa $< > $*.1st
	$(ANTLR) $(AFLAGS) -gc -gx -cr $< > $*.xrf

ccccmain.$(OBJEXT) : ccccmain.cc 
	$(CCC) $(CCC_OPTS) $(LANG_DEFINES) ccccmain.cc


.cc.$(OBJEXT):
	$(CCC) $(CCC_OPTS) $< $(C_OFLAG)$*.$(OBJEXT)

.cpp.$(OBJEXT):
	$(CCC) $(CCC_OPTS) $< $(C_OFLAG)$*.$(OBJEXT)

.cxx.$(OBJEXT):
	$(CCC) -c $(CCC_OPTS) $< $(C_OFLAG)$*.$(OBJEXT)

# Different compilers handle the source file being in a 
# different directory in different ways.  The easiest way
# to cover this is to add explicit rules for the three
# PCCTS support files which give rise to linkable object
# files.
AParser.$(OBJEXT): $(PCCTS_H)$(PATHSEP)AParser.cpp
	$(CCC) $(CCC_OPTS) $(PCCTS_H)$(PATHSEP)AParser.cpp $(C_OFLAG)$*.$(OBJEXT)

DLexerBase.$(OBJEXT): $(PCCTS_H)$(PATHSEP)DLexerBase.cpp
	$(CCC) $(CCC_OPTS) $(PCCTS_H)$(PATHSEP)DLexerBase.cpp $(C_OFLAG)$*.$(OBJEXT)

ATokenBuffer.$(OBJEXT): $(PCCTS_H)$(PATHSEP)ATokenBuffer.cpp
	$(CCC) $(CCC_OPTS) $(PCCTS_H)$(PATHSEP)ATokenBuffer.cpp $(C_OFLAG)$*.$(OBJEXT)



$(CCCC_SPAWN) : cccc.g
	$(ANTLR) $(AFLAGS) -ft Ctokens.h cccc.g
	$(DLG) $(DFLAGS) -cl CLexer parser.dlg

$(JAVA_SPAWN) : java.g
	$(ANTLR) $(AFLAGS) -ft Jtokens.h java.g
	$(DLG) $(DFLAGS) -cl JLexer parser.dlg

## -ci argument to DLG is because unlike C\C++\Java, Ada is defined as being
## case insensitive
## NB CCCC does not map case: if the code processed is not consistent in
## capitalisation of the name of a package, the reports will treat it as 
## two different packages
$(ADA_SPAWN) : ada.g
	$(ANTLR) $(AFLAGS) -ft Atokens.h ada.g
	$(DLG) $(DFLAGS) -ci -cl ALexer parser.dlg

# touch enables us to mark everything up to date to avoid enormous 
# recompilations (particularly after checking everything in and out of RCS)

touch:
	touch cccc.g
	touch *.cpp
	touch *.cxx
	touch *.cc
	touch *.h
	touch *.$(OBJEXT)
	touch cccc

clean:
	-$(RM) *.cpp
	-$(RM) *.$(OBJEXT)
	-$(RM) $(CCCC_EXE)

