if ! $(CommonRules_INCLUDED) {
CommonRules_INCLUDED = TRUE ;

#
# Execute run-it : it : it-arg0 it-arg1 it-arg2 : prefix ;
#

rule Execute {
  local target = $(1) ;
  local executable = $(2) ;
  local arguments = $(3) ;
  local prefix = $(4) ;
  local outputFN = $(5) ;

  if $(TRACE_MODULE) = TRUE {
    Echo Execute $(target) . $(executable) . $(arguments) . $(prefix) . $(outputFN) ;
  }

  local target_exec_arg ;
  if $(arguments) {
    target_exec_arg = RUN_$(executable) ;
    local arg ;
    for arg in $(arguments) {
      target_exec_arg = "$(target_exec_arg).$(arg:B)$(arg:S)" ;
    }
  } else {
    target_exec_arg = RUN_$(executable) ;
  }
  Depends $(target) : $(target_exec_arg) ;
  ExecuteTarget $(target_exec_arg) : [ FAppendSuffix $(executable) : $(SUFEXE) ] : $(arguments) : $(prefix) : $(outputFN) ;
}

rule ExecuteTarget {
  local exec_arg = $(1) ;
  local executable = $(2) ;
  local arguments = $(3) ;
  local prefix = $(4) ; # E.g., "/usr/bin/time"
  local outputFN = $(5) ;

  if $(TRACE_MODULE) = TRUE {
    Echo ExecuteTarget $(exec_arg) . $(executable) . $(arguments) . $(prefix) . $(outputFN) ;
  }

  Depends $(exec_arg) : $(executable) ;
  SEARCH on $(executable) += $(SEARCH_SOURCE) ;
  ARGUMENTS on $(exec_arg) = $(arguments) ;
  PREFIX on $(exec_arg) = $(prefix) ;
  if $(outputFN) {
    OUTPUTFN on $(exec_arg) = $(outputFN) ;
  } else {
    OUTPUTFN on $(exec_arg) = "$(exec_arg).output" ;
  }
}

if ( PROFILE in $(VARIANTS) ) || ( ( CUSTOM in $(VARIANTS) ) && ( $(EUROPA_PROFILE) ) ) {
  actions ExecuteTarget {
    cd `dirname $(2)`
    rm -f gmon.out
    $(PREFIX) ./`basename "$(2)"` $(ARGUMENTS) > "$(OUTPUTFN)" && \
    ( ( test -s gmon.out && gprof -b `basename "$(2)"` gmon.out > "`basename "$(OUTPUTFN)" .output`.gprof" ) || true ) && \
    rm -f gmon.out
  }
} else {
  actions ExecuteTarget {
    cd `dirname $(2)`
    $(PREFIX) ./`basename "$(2)"` $(ARGUMENTS) > "$(OUTPUTFN)"
  }
}

#
# ExecuteSO run-it : it : it-arg0 it-arg1 it-arg2 : prefix ;
#    Executable output goes to stdio
#

rule ExecuteSO {
  local target = $(1) ;
  local executable = $(2) ;
  local arguments = $(3) ;
  local prefix = $(4) ;

  if $(TRACE_MODULE) = TRUE {
    Echo ExecuteSO $(target) . $(executable) . $(arguments) . $(prefix) ;
  }

  local target_exec_arg ;
  if $(arguments) {
    target_exec_arg = RUN_$(executable) ;
    local arg ;
    for arg in $(arguments) {
      target_exec_arg = "$(target_exec_arg).$(arg:B)$(arg:S)" ;
    }
  } else {
    target_exec_arg = RUN_$(executable) ;
  }
  Depends $(target) : $(target_exec_arg) ;
  ExecuteTargetSO $(target_exec_arg) : [ FAppendSuffix $(executable) : $(SUFEXE) ] : $(arguments) : $(prefix) ;
}

rule ExecuteTargetSO {
  local exec_arg = $(1) ;
  local executable = $(2) ;
  local arguments = $(3) ;
  local prefix = $(4) ; # E.g., "/usr/bin/time"

  if $(TRACE_MODULE) = TRUE {
    Echo ExecuteTargetSO $(exec_arg) . $(executable) . $(arguments) . $(prefix)  ;
  }

  Depends $(exec_arg) : $(executable) ;
  SEARCH on $(executable) += $(SEARCH_SOURCE) ;
  ARGUMENTS on $(exec_arg) = $(arguments) ;
  PREFIX on $(exec_arg) = $(prefix) ;
}

actions ExecuteTargetSO {
  cd `dirname $(2)`
  $(PREFIX) ./`basename $(2)` $(ARGUMENTS)
}

#
# utilities
#

# FRemoveItem <list> : <item> ;
# return a list without any instances of item in it
rule FRemoveItem {
  local list = $(1) ;
  local item = $(2) ;

  local result ;
  for i in $(list) {
    if $(i) != $(item) {
      result += $(i) ;
    }
  }
  return $(result) ;
}

# FMergeList <list1> : <list2> ;
# return a list of list1 + all elements from list2 not in list1
rule FMergeList {
  local list1 = $(1) ;
  local list2 = $(2) ;

  local result = $(list1) ;
  local i ;
  for i in $(list2) {
    if ! $(i) in $(result) {
      result += $(i) ;
    }
  }
  return $(result) ;
}

# thx to Dag Asheim <dash@linpro.no> from jamming@perforce.com list
#
# Return a list consisting of a string split where a regexp matches
#
# Usage: list = [ Split regexp : string ] ;
rule FSplit
{
  local re = $(1) ;
  if $(re) = "\\" {
    re = "\\\\" ; # A hack: make it easier to split on $(SLASH)
  }
  local match = [ MATCH "^(.*)("$(re)")(.*)" : $(2) ] ;
  local last ;
  local element ;

  if $(match) && $(match[2]) != $(2) {
    for element in $(match) {
      last = $(element) ;
    }
    return [ FSplit $(1) : $(match[1]) ] $(last) ;
  } else {
    return $(2) ;
  }
}

#
# Jambase level extensions [thx to OpenBeOS for "local" rules]
#

# FIsLocal : return whether or not we are in a local directory
 
rule FSubDirLocal
{
	local a = $(SUBDIR_UP) ;
	local b = $(SUBDIR_DOWN) ;
	if ! $(SUBDIR_UP) {
		local PATH = [ FSplit $(SLASH) : $(SUBDIR) ] ;
		if $(PATH[1]) != .. {
			return true ;
		} else {
			return ;
		}
	}

	# FIsPrefix <a> : <b> ;
	# Returns true, if list <a> is a prefix (a proper one or equal) of
	# list <b>, an empty list otherwise.
	while $(a) && $(a[1]) = $(b[1]) {
		a = $(a[2-]) ;
		b = $(b[2-]) ;
	}

	if $(a) {
		return ;
	} else {
		return true ;
	}
}

# LocalClean target : deps ;	a conditional Clean

rule LocalClean
{
	# LocalClean <targets> : <deps> ;
	# Like Clean, but has only effect in a Jamfile in the
	# directory or any of its subdirectories where jam has been invoked.

	if [ FSubDirLocal ] {
		Clean $(1) : $(2) ;
	}
}

# LocalDepends target : deps ;	a conditional Depends

rule LocalDepends
{
	# LocalDepends <targets> : <deps> ;
	# Like Depends, but has only effect in a Jamfile in the
	# directory or any of its subdirectories where jam has been invoked.

	if [ FSubDirLocal ] {
		Depends $(1) : $(2) ;
	}
}

# 

rule LinkSharedLibraries
{
#	Echo LinkSharedLibraries $(<) . $(>) . [ on $(<) return $(NEEDSHARES) ] ;
	# make library dependencies of target
    # set NEEDSHARES variable used by 'actions Link'

    local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
    Depends $(_t) : lib$(>:S=$(SUFSHARE)) ;
	NEEDSHARES on $(_t) = [ FMergeList [ on $(_t) return $(NEEDSHARES) ] : $(>) ] ;
}

rule LinkSharedLibrariesNoDeps
{
    # set NEEDSHARES variable used by 'actions Link'

    local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
	NEEDSHARES on $(_t) = [ FMergeList [ on $(_t) return $(NEEDSHARES) ] : $(>) ] ;
}

#
# Jambase modifications 
#

# preserve the current directory after returning from included directory
rule SubInclude {
	# SubInclude TOP d1 ... ;
	#
	# Include a subdirectory's Jamfile.

	# We use SubDir to get there, in case the included Jamfile
	# either doesn't have its own SubDir (naughty) or is a subtree
	# with its own TOP.

	if ! $($(<[1]))
	{
	    Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ;
	}

#	Echo SubIncludeIn . $(SUBDIR) ;
	{
		local $(<[1]) = $($(<[1])) ;
		local SUBDIR = $(SUBDIR) ;
		local SUBDIR_TOKENS = $(SUBDIR_TOKENS) ;
		local SEARCH_SOURCE = $(SEARCH_SOURCE) ;
		local LOCATE_SOURCE = $(LOCATE_SOURCE) ;
		local LOCATE_TARGET = $(LOCATE_TARGET) ;
		local SOURCE_GRIST = $(SOURCE_GRIST) ;
		local SUBDIR_UP = $(SUBDIR_UP) ;
		local SUBDIR_ROOT = $(SUBDIR_ROOT) ;
		local HDRGRIST = $(HDRGRIST) ;

		SubDir $(<) ;

#		Echo SubIncluding . $(SUBDIR) ;

		include $(JAMFILE:D=$(SUBDIR)) ;

	}
#	Echo SubIncludeOut . $(SUBDIR) ;
}

#
# "Local" versions
# 

rule File
{
	LocalDepends files : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
	MODE on $(<) = $(FILEMODE) ;
	Chmod $(<) ;
}

rule GenFile 
{
	local _t = [ FGristSourceFiles $(<) ] ;
	local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
	Depends $(_t) : $(_s) $(>[2-]) ;
	GenFile1 $(_t) : $(_s) $(>[2-]) ;
	LocalClean clean : $(_t) ;
}

rule HardLink
{
	LocalDepends files : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
}

rule InstallInto
{
	# InstallInto dir : sources ;

	local i t ;

	t = $(>:G=$(INSTALLGRIST)) ;

	# Arrange for jam install
	# Arrange for jam uninstall
	# sources are in SEARCH_SOURCE
	# targets are in dir

	LocalDepends install : $(t) ;
	LocalClean uninstall : $(t) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
	MakeLocate $(t) : $(<) ;

	# For each source, make gristed target name
	# and Install, Chmod, Chown, and Chgrp

	for i in $(>)
	{
	    local tt = $(i:G=$(INSTALLGRIST)) ;

	    Depends $(tt) : $(i) ;
	    Install $(tt) : $(i) ;
	    Chmod $(tt) ;

	    if $(OWNER) && $(CHOWN) 
	    { 
		Chown $(tt) ;
		OWNER on $(tt) = $(OWNER) ;
	    }

	    if $(GROUP) && $(CHGRP) 
	    { 
		Chgrp $(tt) ;
		GROUP on $(tt) = $(GROUP) ;
	    }
	}
}

rule Lex
{
	LexMv $(<) : $(>) ;
	Depends $(<) : $(>) ;
	MakeLocate $(<) : $(LOCATE_SOURCE) ;
	LocalClean clean : $(<) ;
}

rule LibraryFromObjects
{
	local _i _l _s ;

	# Add grist to file names

	_s = [ FGristFiles $(>) ] ;
	_l = $(<:S=$(SUFLIB)) ;

	# library depends on its member objects

	if $(KEEPOBJS)
	{
		if ! $(3) {
		    LocalDepends obj : $(_s) ;
		}
	}
	else
	{
		if ! $(3) {
		    LocalDepends 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) ;
	    }
	}

	LocalClean 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 .o's around.

	if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; }
}

rule MainFromObjects
{
	local _s _t ;
	local build_target = $(3) ;
	local nogrist = $(4) ;

	# Add grist to file names
	# Add suffix to exe

	if $(nogrist) {
	  _s = $(>) ;
	} else {
	  _s = [ FGristFiles $(>) ] ;
	}
	_t = [ FAppendSuffix $(<) : $(SUFEXE) ] ;

	# so 'jam foo' works when it's really foo.exe

	if $(_t) != $(<)
	{
	    Depends $(<) : $(_t) ;
	    NotFile $(<) ;
	}

	# make compiled sources a dependency of target

	if $(build_target) {
		LocalDepends $(build_target) : $(_t) ;
	} else {
		LocalDepends exe : $(_t) ;
	}
	Depends $(_t) : $(_s) ;
	MakeLocate $(_t) : $(LOCATE_TARGET) ;

	LocalClean clean : $(_t) ;

	Link $(_t) : $(_s) ;
}

rule MakeLocate
{
	# MakeLocate targets : directory ;

	# Sets special variable LOCATE on targets, and arranges
	# with MkDir to create target directory.

	# Note we grist the directory name with 'dir',
	# so that directory path components and other
	# targets don't conflict.

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

rule MkDir
{
	# MkDir directory ;

	# Make a directory and all its parent directories.

	# Ignore timestamps on directories: we only care if they 
	# exist.

	NoUpdate $(<) ;

	# Don't create . or any directory already created.

	if $(<:G=) != $(DOT) && ! $($(<)-mkdir) 
	{
	    # Cheesy gate to prevent multiple invocations on same dir
	    # Arrange for jam dirs
	    # MkDir1 has the actions 

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

	    # Recursively make parent directories.
	    # $(<:P) = $(<)'s parent, & we recurse until root

	    local s = $(<:P) ;

	    # Don't try to create A: or A:\ on windows

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

	    if $(s) = $(<)
	    {
		# The parent is the same as the dir.
		# We're at the root, which some OS's can't stat, so we mark
		# it as NotFile.

	        NotFile $(s) ;
	    }
	    else if $(s:G=)
	    {
		# There's a parent; recurse.

		Depends $(<) : $(s) ;
		MkDir $(s) ;
	    }
	}
}

rule Object
{
	# locate object and search for source, if wanted

	LocalClean 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_TARGET), possibly
	# different from $(SEARCH_SOURCE).

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

	# 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.

	# $(SEARCH_SOURCE:E) 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).

	HDRRULE on $(>) = HdrRule ;
	HDRSCAN on $(>) = $(HDRPATTERN) ;
	HDRSEARCH on $(>) = 
		$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;

	HDRGRIST on $(>) = $(HDRGRIST) ;

	# propagate target specific-defines

	DEFINES on $(<) += $(DEFINES) ;

	# if source is not .c, generate .c with specific rule

	switch $(>:S)
	{
	    case .asm : As $(<) : $(>) ;
	    case .c :	Cc $(<) : $(>) ;
	    case .C :	C++ $(<) : $(>) ;
	    case .cc :	C++ $(<) : $(>) ;
	    case .cpp : C++ $(<) : $(>) ;
	    case .f :	Fortran $(<) : $(>) ;
	    case .l :	Cc $(<) : $(<:S=.c) ;
			Lex $(<:S=.c) : $(>) ;
	    case .s :	As $(<) : $(>) ;
	    case .y :	Cc $(<) : $(<:S=$(YACCGEN)) ;
			Yacc $(<:S=$(YACCGEN)) : $(>) ;
	    case * :	UserObject $(<) : $(>) ;
	}
}

rule Objects
{
	local _i ;

	for _i in [ FGristFiles $(<) ]
	{
		Object $(_i:S=$(SUFOBJ)) : $(_i) ;
		LocalDepends obj : $(_i:S=$(SUFOBJ)) ;
	}
}

actions together SharedArchive bind NEEDLIBS
{
	$(LINK) $(LINKFLAGS) $(SHARED_FLAG) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) -l$(NEEDSHARES)
}

rule SharedLibraryFromObjects
{
	local _i _l _s ;
	local suppress_global_dependencies = $(3) ;
	local nogrist = $(4) ;

	# Add grist to file names

	if $(nogrist) {
	  _s = $(>) ;
	} else {
	  _s = [ FGristFiles $(>) ] ;
	}
	_l = $(<:S=$(SUFSHARE)) ;

	# library depends on its member objects

	if $(KEEPOBJS)
	{
		if ! $(suppress_global_dependencies) {
		    LocalDepends obj : $(_s) ;
		}
	}
	else
	{
		if ! $(suppress_global_dependencies) {
		    LocalDepends 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 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) ;

	LocalClean clean : $(_l) ;

	SharedArchive $(_l) : $(_s) ;
}

rule Shell
{
	LocalDepends shell : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
	MODE on $(<) = $(SHELLMODE) ;
	LocalClean clean : $(<) ;
	Chmod $(<) ;
}

rule SoftLink
{
	LocalDepends files : $(<) ;
	Depends $(<) : $(>) ;
	SEARCH on $(>) = $(SEARCH_SOURCE) ;
	LocalClean clean : $(<) ;
}

rule Yacc
{
	local _h ;

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

	# Some places don't have a yacc.

	MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;

	if $(YACC)
	{
	    Depends $(<) $(_h) : $(>) ;
	    Yacc1 $(<) $(_h) : $(>) ;
	    YaccMv $(<) $(_h) : $(>) ;
	    LocalClean clean : $(<) $(_h) ;
	}

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

	Includes $(<) : $(_h) ;
}

rule GenerateValid
{
	LOCATE on $(2).valid += $(LOCATE_TARGET) ; 
	ALWAYS $(2).valid ;

	for orig in $(2)
	{
		File $(orig).valid : $(orig) ;
	}

	LocalDepends $(1) : $(2).valid ;
}

rule Diff
{
	LocalDepends $(1) : $(2) ;
	SEARCH on $(2) = $(SEARCH_SOURCE) ;
}

actions Diff
{
	diff $(2)
}

actions together Chmod1
{
	$(CHMOD) $(MODE) $(<)
}

actions together Link bind NEEDLIBS
{
	$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) -l$(NEEDSHARES)
}

} # CommonRules_INCLUDED
