#
# /+\
# +\	Copyright 1993, 1995 Christopher Seiwald.
# \+/
#
# This file is part of Jam - see jam.c for Copyright information.
#

#
# JAMBASE - jam 2.2 ruleset for use with the Minimalist GNU-Win32 package.
#
# This version of JAMBASE has been stripped down to provide GNU-Win32 support
# and not much else by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>. Many
# things have been removed and/or modified. If you need a real, multi-purpose
# Jambase you should download the real jam 2.2 package from www.perforce.com.
#

# Special targets defined in this file:
#
# all		- parent of first, files, lib, exe
# first		- first dependent of 'all', for potential initialization
# files		- parent of all File targets
# lib		- parent of all Library targets
# exe		- parent of all Main targets
# dirs		- parent of all MkDir targets
# clean		- removes all File, Library, and Main targets
#	

# Rules defined by this file:
#
# As obj.o : source.s ;			.s -> .o (using as or gas)
# Asm obj.o : source.asm ;		.asm -> .o (using nasm)
# Bulk dir : files ;			populate directory with many files
# Cc obj.o : source.c ;			.c -> .o
# C++ obj.o : source.cc ;		.cc -> .o
# Clean clean : sources ;		remove sources with 'jam clean'
# Dll image.dll : sources ;		create a dynamic link library
# Exports target : source.def ;         add exports from source to target.
# File dest : source ;			copy file
# GenFile source.c : program args ;	make custom file
# Gui target.exe ;			Sets 'gui build' options for target.
# GuiLibs target.exe ;                  Only adds gui libraries.
# HdrRule source : headers ;		handle #includes
# ImportLib lib : source.def sources ;  create an import library from the .def
# Lex source.c : source.l ;		.l -> .c
# Library lib : source ;		archive library from compiled sources
# LibraryFromObjects lib : objects ;	archive library from objects
# LinkLibraries images : libraries ;	bag libraries onto Mains
# Main image : source ;			link executable from compiled sources
# MainFromObjects image : objects ;	link executable from objects
# MkDir dir ;				make a directory, if not there
# Object object : source ;		compile object from source
# ObjectCcFlags source : flags ;	add compiler flags for object
# ObjectC++Flags source : flags ;	add compiler flags for object
# ObjectHdrs source : dirs ;		add include directories for object
# Objects sources ;			compile sources
# ResourceScript target.res : source.rc ; build a res file from an rc script
# Resource object : source.rc ;         build an object from a rc script
# RmTemps target : sources ;		remove temp sources after target made
# SubDir TOP d1 d2 ... ;		start a subdirectory Jamfile
# SubDirCcFlags flags ;			add compiler flags until next SubDir
# SubDirC++Flags flags ;		add compiler flags until next SubDir
# SubDirHdrs dirs ;			add include dirs until next SubDir
# SubInclude TOP d1 d2 ... ;		include a subdirectory Jamfile
# Undefines images : symbols ;		save undef's for linking
# UserObject object : source ;		handle unknown suffixes for Object
# Yacc source.c : source.y ;		.y -> .c (and .h)
#
# Utility rules that have no side effects:
#
# makeSubDir var : d1 d2 ... ;		$(var) = path to root
# addDirName var : d1 d2 ... ;		$(var) += path from root to dir
# makeDirName var : d1 d2 ... ;		$(var) = path from root to dir
# makeGrist var : d1 d2 ... ;		$(var) = grist form of dir
# makeGristedName var : value ;		$(var) = $(value:G=$(SOURCE_GRIST))
# makeCommon var1 : var2 ;		strip common initial elements
# makeRelPath var d1 : d2 ;		$(var) = rel path from d1 to d2
# makeSuffixed var $(SUF) : f1 f2 ... ; $(var) = $(>) with suffixes
# makeString var : value ... ;          $(var) = contatenated values
#

ECHO "Using Minimalist GNU-Win32 Jambase..." ;

AWK		default = awk ;
LEX		default = flex ;
RC		default = windres ;
RCFLAGS		default = ;
YACC		default = bison ;	# Use GNU bison
YACCFLAGS	default = ;
CP		default = copy ;
DOT		default	= . ;
DOTDOT		default	= .. ;
MKDIR		default = mkdir ;
MV		default = move ;
OS			= NT ;		# replace Windows_NT
RM		default = rm ;		# rm required (del doesn't cut it).
SED		default = sed ;
SLASH		default = / ;
SUFEXE		default = .exe ;
SUFLIB		default = .a ;
SUFOBJ		default = .o ;

RANLIB		default = ;

AR		default = ar -ru ;
AS		default = as ;
ASM		default = nasmw ;
ASMFLAGS	default = -f win32 ;
CC		default = gcc ;
C++		default = c++ ;
LINK		default = $(CC) ;
OPTIM		default = ;

# By default link the standard C++ library.
LINKLIBS	default = -lstdc++ ;

# If you put -s DEBUG=1 on your jam command line then you will get
# debugging information automatically.
if $(DEBUG)
{
	ECHO "Compiling with debugging information..." ;
	CCFLAGS		default = -g -DDEBUG=1 ;
	C++FLAGS	default = -g -DDEBUG=1 ;
	LINKFLAGS	default = $(CCFLAGS) -Wl,--stack,10000 ;
}
else
{
	CCFLAGS		default = ;
	C++FLAGS	default = ;
	LINKFLAGS	default = -s $(CCFLAGS) -Wl,--stack,10000 ;
	# NOTE: Linker is set to strip by default. Unstripped executables
	#       have been reported not to work on NT.
	# NOTE: Extra stack allocated by default. Some programs appear to
	#       work on 95 only if you get this extra stack (e.g. gvim).
}

STDLIBPATH	default = /egcs/lib/gcc-lib/i386-mingw32/egcs-2.91.57 /egcs/lib /egcs/i386-mingw32/lib /usr/local/lib ;
STDHDRS		default = /egcs/lib/gcc-lib/i386-mingw32/egcs-2.91.57/include /egcs/i386-mingw32/include /egcs/include/g++ /egcs/include /usr/local/include ;
NOLIBSCAN	default = true ;

DLLTOOLFLAGS	default = ;



JAMFILE		default = Jamfile ;
JAMRULES	default = Jamrules ;

HDRPATTERN = "^#[	 ]*include[	 ]*[<\"](.*)[\">].*$" ;

#
# Base dependencies - first for "bootstrap" kinds of rules
#

DEPENDS all : files lib exe obj ;
DEPENDS all files lib exe obj : first ;
NOTFILE all first files lib exe obj dirs clean ;
ALWAYS clean ;

#
# Rules
#

rule As
{
	DEPENDS $(<) : $(>) ;
	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
}

rule Asm
{
	DEPENDS $(<) : $(>) ;
	ASMFLAGS on $(<) += $(ASMFLAGS) $(SUBDIRASMFLAGS) ;
}

rule Bulk
{
	local i ;

	for i in $(>)
	{
	    File $(i:D=$(<)) : $(i) ;
	}
}

rule Cc
{
	DEPENDS $(<) : $(>) ;

	# Just to clarify here: this sets the per-target CCFLAGS to
	# be the current value of (global) CCFLAGS and SUBDIRCCFLAGS.

	CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
}

rule C++
{
	DEPENDS $(<) : $(>) ;
	C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;
}

# Added by Colin Peters
# Links a target from the sources given as a dll.
rule Dll
{
	MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
	Objects $(>) ;
	LINKFLAGS on $(<) = $(LINKFLAGS) -mdll ;

	# NOTE: There must be a .def file matching the output name.
	Exports $(<) : $(<:S=.def) ;
}

# Added by Colin Peters
# Use the given source as the .def file containing exports for the target
# (executable or dll).
rule Exports
{
	DLLTOOLFLAGS on $(<) = --def $(>) $(DLLTOOLFLAGS) ;
	DEPENDS $(<) : $(>) ;
}

rule File
{
	DEPENDS files : $(<) ;
	DEPENDS $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
}

rule Fortran
{
	DEPENDS $(<) : $(>) ;
}

rule GenFile 
{
	local s ;
	makeGristedName s : $(<) ;
	Depends $(s) : $(>[1]:S=$(SUFEXE)) $(>[2-]) ;
	GenFile1 $(s) : $(>[1]:S=$(SUFEXE)) $(>[2-]) ;
	Clean clean : $(s) ;
}

rule GenFile1
{
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
}

# Added by Colin Peters
# Indicates a target (executable or dll) needs the basic gui libraries and
# to be marked as GUI subsystem (i.e. no console).
rule Gui
{
	LINKFLAGS on $(<) += -mwindows ;
}

# Added by Colin Peters
# Simply add the basic gui libraries to the target without marking the target
# as a GUI app (useful for hybrid apps or debug traces to the console).
rule GuiLibs
{
	LINKLIBS on $(<) += -lcomdlg32 -luser32 -lgdi32 ;
}

rule HdrRule
{
	# HdrRule source : headers ;

	# N.B.	This rule is called during binding, potentially after
	# the fate of many targets has been determined, and must be
	# used with caution: don't add dependencies to unrelated
	# targets, and don't set variables on $(<).

	# Tell Jam that anything depending on $(<) also depends on $(>),
	# set SEARCH so Jam can find the headers, but then say we don't
	# care if we can't actually find the headers (they may have been
	# within ifdefs),

	local s ;

	if $(HDRGRIST)
	{
		s = $(>:G=$(HDRGRIST)) ;
	} else {
		s = $(>) ;
	}

	INCLUDES $(<) : $(s) ;
	SEARCH on $(s) = $(HDRSEARCH) ;
	NOCARE $(s) ;

	# Propagate on $(<) to $(>)

	HDRSEARCH on $(s) = $(HDRSEARCH) ;
	HDRSCAN on $(s) = $(HDRSCAN) ;
	HDRRULE on $(s) = $(HDRRULE) ;
	HDRGRIST on $(s) = $(HDRGRIST) ;
}

# Added by Colin Peters
# This rule uses the first source as the .def file to create the import
# library. Any other sources given will be added to the import library
# after it is created by this rule's action.
rule ImportLib
{
	local	s o ;

	makeGristedName s : $(>[1]) ;

	if ! $(<:D)
	{
		MakeLocate $(<) : $(LOCATE_TARGET) ;
	}

	DEPENDS lib : $(<) ;
	DEPENDS $(<) : $(s) ;
	DLLNAME on $(<) = $(s:S=.dll) ;
	DLLTOOLFLAGS on $(<) = $(DLLTOOLFLAGS) ;

	o = $(>[2-]) ;
	if $(o)
	{
		# Add on the extra sources to the import library
		DEPENDS $(o) : $(s) ;
		Library $(<) : $(o) ;
	}
	else
	{
		# Add only if there aren't extra objects, because library
		# will add to the clean target.
		Clean clean : $(<) ;
	}
}

rule Lex
{
	DEPENDS $(<) : $(>) ;
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	Clean clean : $(<) ;
}

rule Library
{
	LibraryFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
	Objects $(>) ;
}

rule LibraryFromObjects
{
	local i l s ;

	# Add grist to file names
	makeGristedName s : $(>) ;

	# library depends on its member objects

	l = $(<:S=$(SUFLIB)) ;

	if $(KEEPOBJS)
	{
		DEPENDS obj : $(s) ;
	}
	else
	{
		DEPENDS lib : $(l) ;
	}

	# Set LOCATE for the library and its contents. The bound
	# value shows up as $(NEEDLIBS) on the Link actions.
	# For compatibility we only do this if the library doesn't
	# already have a path.

	if ! $(l:D)
	{
		MakeLocate $(l) $(l)($(s:BS)) : $(LOCATE_TARGET) ;
	}

	if $(NOARSCAN) 
	{ 
	    # If we can't scan the library to timestamp its contents,
	    # we have to just make the library depend directly on the
	    # on-disk object files.

	    DEPENDS $(l) : $(s) ;
	}
	else
	{
	    # If we can scan the library, we make the library depend
	    # on its members and each member depend on the on-disk
	    # object file.

	    DEPENDS $(l) : $(l)($(s:BS)) ;

	    for i in $(s)
	    {
		DEPENDS $(l)($(i:BS)) : $(i) ;
	    }
	}

	Clean clean : $(l) ;

	if $(CRELIB) { CreLib $(l) : $(s[1]) ; }

	Archive $(l) : $(s) ;

	if $(RANLIB) { Ranlib $(l) ; }

	# If we can't scan the library we have to leave the objects around.
	if ! ( $(NOARSCAN) || $(KEEPOBJS) )
	{
		RmTemps $(l) : $(s) ;
	}
}

rule Link
{
	LINKFLAGS on $(<) = $(LINKFLAGS) ;
	LINKLIBS on $(<) = $(LINKLIBS) ;
	# Do nothing placeholder.
}

rule LinkLibraries
{
	# make library dependencies of target
	# set NEEDLIBS variable used by 'actions Main'

	if $(<:S)
	{
	    t = $(<) ;
	} else {
	    t = $(<:S=$(SUFEXE)) ;
	}

	DEPENDS $(t) : $(>:S=$(SUFLIB)) ;
	NEEDLIBS on $(t) += $(>:S=$(SUFLIB)) ;
}

rule Main
{
	MainFromObjects $(<) : $(>:S=$(SUFOBJ)) ;
	Objects $(>) ;
}

rule MainFromObjects
{
	local s t ;

	# Add grist to file names
	makeGristedName s : $(>) ;

	makeSuffixed t $(SUFEXE) : $(<) ;

	if $(t) != $(<)
	{
		DEPENDS $(<) : $(t) ;
		NOTFILE $(<) ;
	}

	# make compiled sources a dependency of target

	DEPENDS exe : $(t) ;
	DEPENDS $(t) : $(s) ;
	MakeLocate $(t) : $(LOCATE_TARGET) ;

	Clean clean : $(t) ;

	Link $(t) : $(s) ;
}

rule MakeLocate
{
	if $(>)
	{
	    LOCATE on $(<) = $(>) ;
	    Depends $(<) : $(>[1]) ;
	    MkDir $(>[1]) ;
	}
}

rule MkDir
{
	if $(<) != $(DOT) && ! $($(<)-mkdir)
	{
		local s ;

		# Cheesy gate to prevent multiple invocations on same dir
		# MkDir1 has the actions 
		# If dir exists, don't update it
		# Arrange for jam dirs

		$(<)-mkdir = true ;
		MkDir1 $(<) ;
		NOUPDATE $(<) ;
		Depends dirs : $(<) ;

		# Recursively make parent directories.
		# $(<:P) = $(<)'s parent and we recurse to the root.

		s = $(<:P) ;

		switch $(s)
		{
			case *:   : s = ;
			case *:\\ : s = ;
		}

		if $(s) && $(s) != $(<)
		{
			Depends $(<) : $(s) ;
			MkDir $(s) ;
		}
		else if $(s)
		{
			NOTFILE $(s) ;
		}
	}
}

rule Object
{
	local h DUMMY ;

	# locate object and search for source, if wanted

	# Don't clean directly included object files.
	if $(>:S) != $(SUFOBJ)
	{
		Clean clean : $(<) ;
	}

	MakeLocate $(<) : $(LOCATE_TARGET) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;

	# Save HDRS for -I$(HDRS) on compile.
	# We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
	# in the .c file's directory, but generated .c files (from
	# yacc, lex, etc) are located in $(LOCATE_SOURCE), possibly
	# different from $(SEARCH_SOURCE).

	HDRS on $(<) = $(SEARCH_SOURCE) $(HDRS) $(SUBDIRHDRS) ;

	# handle #includes for source: Jam scans for headers with
	# the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
	# with the scanned file as the target and the found headers
	# as the sources.  HDRSEARCH is the value of SEARCH used for
	# the found header files.  Finally, if jam must deal with
	# header files of the same name in different directories,
	# they can be distinguished with HDRGRIST.

	# $(h) is where cc first looks for #include "foo.h" files.
	# If the source file is in a distant directory, look there.
	# Else, look in "" (the current directory).

	if $(SEARCH_SOURCE)
	{
	    h = $(SEARCH_SOURCE) ;
	}
	else
	{
	    h = "" ;
	}

	HDRRULE on $(>) = HdrRule ;
	HDRSCAN on $(>) = $(HDRPATTERN) ;
	HDRSEARCH on $(>) = $(HDRS) $(SUBDIRHDRS) $(h) $(STDHDRS) ;
	HDRGRIST on $(>) = $(HDRGRIST) ;

	# Generate object file based on the extension of the source.
	# .res .rc and .o handling by Colin Peters.
	switch $(>:S)
	{
	    case .o :	DUMMY = 0 ;
		 	# Objects are linked directly
	    case .c :	Cc $(<) : $(>) ;
	    case .cc :	C++ $(<) : $(>) ;
	    case .cpp : C++ $(<) : $(>) ;
	    case .f :	Fortran $(<) : $(>) ;
	    case .l :	Cc $(<) : $(<:S=.c) ;
			Lex $(<:S=.c) : $(>) ;
	    case .s :	As $(<) : $(>) ;
	    case .asm : Asm $(<) : $(>) ;
	    case .y :	Cc $(<) : $(<:S=.c) ;
			Yacc $(<:S=.c) : $(>) ;
	    case .rc :  Resource $(<) : $(>) ;
	    case * :	UserObject $(<) : $(>) ;
	}
}

rule ObjectCcFlags
{
	local s ;

	makeGristedName s : $(<:S=$(SUFOBJ)) ;

	CCFLAGS on $(s) += $(>) ;
}

rule ObjectC++Flags
{
	local s ;

	makeGristedName s : $(<:S=$(SUFOBJ)) ;

	C++FLAGS on $(s) += $(>) ;
}

rule ObjectHdrs
{
	local s ;

	makeGristedName s : $(<:S=$(SUFOBJ)) ;

	HDRS on $(s) += $(>) ;
}

rule Objects
{
	local i s ;

	makeGristedName s : $(<) ;

	for i in $(s)
	{
		Object $(i:S=$(SUFOBJ)) : $(i) ;
		DEPENDS obj : $(i:S=$(SUFOBJ)) ;
	}
}

# Added by Colin Peters
# Resource doesn't add it's target to clean, because usually it will be
# invoked from Object, and that automatically sets up the target to be
# cleaned.
rule Resource
{
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	DEPENDS $(<) : $(>) ;
}

# Added by Colin Peters
rule ResourceScript
{
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	DEPENDS $(<) : $(>) ;
	Clean clean : $(<) ;
}

rule RmTemps
{
	TEMPORARY $(>) ;
}

rule SubDir
{
	local r s ;

	#
	# SubDir TOP d1 [ ... ]
	#
	# This introduces a Jamfile that is part of a project tree 
	# rooted at $(TOP).  It (only once) includes the project-specific
	# rules file $(TOP)/Jamrules and then sets search & locate stuff.
	#
	# If the variable $(TOPRULES) is set (where TOP is the first arg 
	# to SubDir), that file is included instead of $(TOP)/Jamrules.
	#
	# d1 ... are the directory elements that lead to this directory 
	# from $(TOP).  We construct the system dependent path from these
	# directory elements in order to set search&locate stuff.
	# 

	if ! $($(<[1]))
	{
		if ! $(<[1])
		{
			EXIT SubDir syntax error ;
		}

		makeSubDir $(<[1]) : $(<[2-]) ;
	}

	#
	# If $(TOP)/Jamrules hasn't been included, do so.
	#

	if ! $($(<[1])-included)
	{
	    # Gated entry.

	    $(<[1])-included = TRUE ;

	    # File is $(TOPRULES) or $(TOP)/Jamrules.

	    r = $($(<[1])RULES) ;

	    if ! $(r)
	    {
		r = $(JAMRULES:R=$($(<[1]))) ;
	    }

	    # Include it.

	    include $(r) ;

	}

	# Get the path to current directory from root using makeSubDir.
	# Save dir tokens for other potential uses.

	makeDirName s : $(<[2-]) ;
	SUBDIR = $(s:R=$($(<[1]))) ;
        SUBDIR_TOKENS = $(<[2-]) ;

	# Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
	# These can be reset if needed.	 For example, if the source
	# directory should not hold object files, LOCATE_TARGET can
	# subsequently be redefined.

	SEARCH_SOURCE = $(SUBDIR) ;
	LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
	LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
	makeGrist SOURCE_GRIST : $(<[2-]) ;

	# Reset per-directory ccflags, hdrs

	SUBDIRCCFLAGS = ;
	SUBDIRC++FLAGS = ;
	SUBDIRHDRS = ;
}

rule SubDirCcFlags
{
	SUBDIRCCFLAGS += $(<) ;
}

rule SubDirC++Flags
{
	SUBDIRC++FLAGS += $(<) ;
}

rule SubDirHdrs
{
	SUBDIRHDRS += $(<) ;
}

rule SubInclude
{
	local i s ;

	# That's
	#	SubInclude TOP d1 [ d2 [ d3 [ d4 ] ] ]
	#
	# to include a subdirectory's Jamfile.

	if ! $($(<[1]))
	{
	    EXIT Top level of source tree has not been set with $(<[1]) ;
	}

	s = $(<[2]) ;

	for i in $(<[3-])
	{
	    s = $(s)$(SLASH)$(i) ;
	}

	include $(JAMFILE:D=$(s):R=$($(<[1]))) ;
}

rule Undefines
{
	local t ;

	if $(<:S)
	{
	    t = $(<) ;
	} else {
	    t = $(<:S=$(SUFEXE)) ;
	}

	UNDEFS on $(t) += $(UNDEFFLAG)$(>) ;
}

rule UserObject
{
	EXIT "Unknown suffix on" $(>) "- see UserObject rule in Jamfile(5)." ;
}

rule Yacc
{
	local h ;

	# Put the generated .c and .h files in the source directory
	MakeLocate $(<) : $(LOCATE_SOURCE) ;

	h = $(<:BS=.h) ;

	DEPENDS $(<) $(h) : $(>) ;
	Clean clean : $(<) $(h) ;

	# make sure someone includes $(h) else it will be
	# a deadly independent target

	INCLUDES $(<) : $(h) ;
}

#
# Utility rules; no side effects on these
#

rule makeString
{
	local _t ;

	$(<) = $(>[1]) ;
	for _t in $(>[2-])
	{
		$(<) = $($(<))$(_t) ;
	}
}

rule makeSubDir
{
	local _i _d ;

	# If $(>) is the path to the current directory, compute the
	# path (using ../../ etc) back to that root directory.
	# Sets result in $(<)

	if ! $(>[1]) 
	{
	    _d = $(DOT) ;
	} 
	else
	{
	    _d = $(DOTDOT) ;

	    for _i in $(>[2-])
	    {
		_d = $(_d:R=$(DOTDOT)) ;
	    }
	}

	$(<) = $(_d) ;
}

rule addDirName
{
	local _s _i ;

	# Turn individual elements in $(>) into a usable path.
	# Add result to $(<).

	if ! $(>)
	{
	    _s = $(DOT) ;
	}
	else
	{
	    _s = $(>[1]) ; 

	    for _i in $(>[2-])
	    {
		_s = $(_i:R=$(_s)) ;
	    }
	}

	$(<) += $(_s) ;
}

rule makeDirName
{
	$(<) = ; addDirName $(<) : $(>) ;
}

rule makeGrist
{
	local _g _i ;

	# Turn individual elements in $(>) into grist.
	# Return result in $(<)

	_g = $(>[1]) ;

	for _i in $(>[2-])
	{
	    _g = $(_g)!$(_i) ;
	}

	$(<) = $(_g) ;
}

rule makeGristedName
{
	local _i _o ;

	# Produce name with grist in it, if SOURCE_GRIST is set.

	if ! $(SOURCE_GRIST)
	{
	    $(<) = $(>) ;
	}
	else 
	{
	    _o = ;
	    for _i in $(>)
	    {
		switch $(_i)
		{
		case *.h :	_o += $(_i) ;
		case * : 	_o += $(_i:G=$(SOURCE_GRIST)) ;
		}
	    }
	    $(<) = $(_o) ;
	}
}

rule makeCommon
{
	if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
	{
	    $(<) = $($(<)[2-]) ;
	    $(>) = $($(>)[2-]) ;
	    makeCommon $(<) : $(>) ;
	}
}

rule makeRelPath 
{
	local _l _r ;

	# first strip off common parts

	_l = $(<[2-]) ;
	_r = $(>) ;

	makeCommon _l : _r ;

	# now make path to root and path down

	makeSubDir _l : $(_l) ;
	makeDirName _r : $(_r) ;

	# Concatenate and save

	# XXX This should be better

	if $(_r) = $(DOT) {
	    $(<[1]) = $(_l) ;
	} else {
	    $(<[1]) = $(_r:R=$(_l)) ;
	}
}

rule makeSuffixed
{
   # E.g., "makeSuffixed s_exe $(SUFEXE) : yacc lex foo.bat ;"
   # sets $(s_exe) to (yacc,lex,foo.bat) on Unix and 
   # (yacc.exe,lex.exe,foo.bat) on NT.

	if $(<[2])
	{
	    local _i ;

	    $(<[1]) = ;

	    for _i in $(>)
	    {
		if $(_i:S)
		{
		    $(<[1]) += $(_i) ;
		}
		else
		{
		    $(<[1]) += $(_i:S=$(<[2])) ;
		}
	    }
	}
	else
	{
	    $(<[1]) = $(>) ;
	}
}

rule unmakeDir
{
    if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\ 
    {
        unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
    }
    else
    {
        $(<) = $(>) ;
    }
}

#
# Actions
#


actions updated together piecemeal Archive
{
$(AR) $(<) $(>)
}

actions As
{
$(AS) $(ASFLAGS) -I$(HDRS) -o $(<) $(>)
}

actions Asm
{
$(ASM) $(ASMFLAGS) $(>) -o $(<)
}

actions C++
{
$(C++) -c $(C++FLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
}

actions Cc
{
$(CC) -c $(CCFLAGS) $(OPTIM) -I$(HDRS) -o $(<) $(>)
}

actions piecemeal existing Clean
{
$(RM) $(>)
}

actions File
{
$(RM) $(<)
$(CP) $(>) $(<)
}

actions Fortran
{
$(FORTRAN) $(FORTRANFLAGS) -o $(<) $(>)
}

actions GenFile1
{
$(>[1]) $(<) $(>[2-])
}

actions ImportLib
{
dlltool --dllname $(DLLNAME) --def $(>) --output-lib $(<) $(DLLTOOLFLAGS)
}

actions Lex
{
$(LEX) -o$(<) $(>)
}

actions MkDir1
{
$(MKDIR) $(<)
}

# This odd link action builds an executable with relocation information
# and can also be used to build DLLs. Unpleasantly complex, but there it
# is. The first pass with the linker and dlltool create an exports file
# (_temp.exp) containing the base relocations (written into _temp.base)
# by the linker) and possibly exports in a .def file if the DLLTOOLFLAGS
# contains a --def option. The second pass rebuilds the relocations to
# compensate for including the exports file into the executable (relocations
# may be invalidated by exports), and produces a new exports file with the
# proper relocations. Then, finally, the actual executable or dll is linked
# with the exports file.
#
# NOTE: Because it uses fixed file names this cannot be run twice in the
#       same directory at the same time! TODO
#
actions Link bind NEEDLIBS
{
$(LINK) $(LINKFLAGS) -o $(<) -Wl,--base-file,$(<:S=.b) $(UNDEFS) $(>) $(LINKLIBS) $(NEEDLIBS) 
dlltool --dllname $(<:BS) --base-file $(<:S=.b) --output-exp $(<:S=.e) $(DLLTOOLFLAGS)
$(LINK) $(LINKFLAGS) -o $(<) -Wl,--base-file,$(<:S=.b) $(UNDEFS) $(>) $(LINKLIBS) $(NEEDLIBS) -Wl,$(<:S=.e)
dlltool --dllname $(<:BS) --base-file $(<:S=.b) --output-exp $(<:S=.e) $(DLLTOOLFLAGS)
$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(LINKLIBS) $(NEEDLIBS) -Wl,$(<:S=.e)
$(RM) $(<:S=.b)
$(RM) $(<:S=.e)
}

actions together Ranlib
{
$(RANLIB) $(<)
}

# The action for compiling resources, now directly from .rc to .o
#
actions Resource
{
$(RC) -i $(>) -o $(<)
}

# No longer used action for compiling resources from .rc to .res.
# The current version assumes that the target will have the correct extension
# of .res, or else windres will not do the right thing.
#
# With lrc use:
#	lrc /o$(<) $(>)
# with RC set to rcl use:
#       $(RC) $(RCFLAGS) -i $(>) -r $(<)
# With RC set to rc (from MS) use
#       $(RC) $(RCFLAGS) /fo $(<) $(>) 
# and make sure to include the windows include directories as /i arguments
# in RCFLAGS:
#
actions ResourceScript
{
$(RC) -i $(>) -o $(<)
}

actions quietly updated piecemeal RmTemps
{
$(RM) $(>)
}

actions Yacc
{
$(YACC) $(YACCFLAGS) -d -o $(<) $(>)
}

#
# Now include the user's Jamfile.
#

{
	if $(JAMFILE) { include $(JAMFILE) ; }
}

