#! /usr/bin/env bash
#
# (C) Copyright IBM Corp. 2001, 2002, 2003, 2004
#
#$Id: jconfigure,v 1.392 2004/07/20 20:23:58 dgrove-oss Exp $
#
# Generate control files necessary to build a particular "configuration"
# of the Research Virtual Machine.
#
# See the usage message below, in section 1, the def. of function 
# help_message.  It gives much more information than is in this header comment.
#
# This script is organized into seven sections:
#    0 - Setup
#    1 - Documentation
#    2 - Definitions of constants
#    3 - Process RVM_TARGET_CONFIG
#    4 - ARGUMENT PARSING
#    5 - Definitions of functions
#    6 - Mainline Code that does the work
#
# @author Derek Lieber
# @date   19 Jan 2000
# @author Steven Augart (Bash version)
# @date 17 May 2003

## We can first do some simple version tests to keep from getting slipped Bash
## version 2.03 or earlier.
if ! echo D | read -n 1 > /dev/null 2>&1 ; then
    echo >&2 "$0: We are somehow running under a version of the shell that does not recognize the '-n' argument to the 'read' builtin.  This program absolutely requires Bash version 2.05 or better to run, and we recommend 2.05a or better.  Aborting execution."
    exit 1
fi



## Exit statuses:

## We exit with status 0 upon success, as is conventional.
## In case of trouble, we exit with the triggering exit status (if invoked via 'set -e'.
## Exit status 33: Invalid arguments.
declare -r -i Exit_Status_Bad_Args=33
## Exit status 2: trouble (configuration, etc.)
## Exit status 1: misc. complaints.
##
## Exit status 111: The master "jbuild" script (generated by jconfigure) uses
## exit status "111" to mean that it has gone as far as it could with a
## cross-platform build, and that the target itself now needs to 
## run the linker.
declare -r -i Exit_Status_Run_Linker=111

#----------------------#
# SECTION 0 - Setup    #
#----------------------#

# What is our name?
# Bash internal shorthand that works like the "basename" command.
ME="${0##*/}"

## get_bin_dir():
## Find what directory our aux. files are in.  Also confirms that
## RVM_ROOT is set to something reasonable.
## We print out the value of bin_dir at the end, or exit abnormally.
##
## This is horribly convoluted, and probably to no good purpose.
## I'm ashamed to admit that I wrote it. --Steve Augart
function get_bin_dir() {
    # Where are we?
    # Bash internal shorthand that works like the "dirname" command:
    local mydir="${0%/*}"			# temporary; directory we were run from

    ## The sole purpose of this next "if" statement is to set the
    ## variable bin_dir, and to verify that it is set to something
    ## reasonable that will allow us to load in "libjconfigure.bash".
    if [[ $mydir && $mydir != $ME ]]; then
	# Where to find library files and auxiliary programs:
	local bin_dir="${mydir}"
	local suffix=libjconfigure.bash
	local f=$bin_dir/$suffix
	if [[ ! -f $f ]]; then
	    echo >&2 "\
    $ME: Something is weird here.  I can't find a file named
	\"${f##*/}\" in \"$f\",
	but I was apparently run from the directory \"$bin_dir\".  
	Please use a version of jconfigure in the same source tree that 
	your sources are located in."
	    trap '' EXIT
	    exit 2
	fi
    else
	bin_dir="${RVM_ROOT:?$ME: This program won't work unless you've set the RVM_ROOT variable.}/rvm/bin"
	suffix=libjconfigure.bash
	f=$bin_dir/$suffix
	if [[ ! -f $f ]]; then
	    echo >&2 "\
    $ME: I can't find a file named \"${f##*/}\" at 
       RVM_ROOT/$suffix (that's 
       $f).
       You probably have RVM_ROOT set incorrectly.  Reset RVM_ROOT and try again."
	    trap '' EXIT
	    exit 2
	fi
    fi

    if [[ ${RVM_ROOT-UNSET} = UNSET ]]; then
	echo >&2 "$ME: RVM_ROOT is not set.  Set it and try again."
	trap '' EXIT
	exit 2
    fi

    if [[ ${RVM_ROOT} = "" ]]; then
	echo >&2 "$ME: RVM_ROOT set to the empty string.  Set it properly and try again."
	trap '' EXIT
	exit 2
    fi

    if [[ ${RVM_ROOT} != /* ]]; then
	echo >&2 "\
    $ME: RVM_ROOT must be set to an absolute path 
	(one starting with a /), not to
	\"$RVM_ROOT\".  Please set it properly and try again."
	trap '' EXIT
	exit 2
    fi

    suffix="rvm/bin/libjconfigure.bash"
    f="$RVM_ROOT/$suffix"
    if [[ ! -f $f  ]]; then
	echo >&2 "\
    $ME: Can't find a file named \"${f##*/}\" in 
	RVM_ROOT/$suffix (that's 
	\"$f\").  
	RVM_ROOT is probably set incorrectly.  Reset RVM_ROOT and try again."
	if [[ $bin_dir != $RVM_ROOT ]]; then
	    maybe_root=$bin_dir
	    if [[ $maybe_root != /* ]]; then
		$maybe_root=${PWD}/$maybe_root
	    fi
	    if [[ -d $maybe_root/rvm/_timestamp ]]; then
		echo >&2 "$ME: Try setting RVM_ROOT to \"$maybe_root\""
	    fi
	fi
	trap '' EXIT
	exit 2
    fi

    echo ${bin_dir}
}

function croak_nonusage () {
    ## If we have not loaded show_mesg() yet, substitute.
    [[ $(type -t show_mesg) = function ]] || function show_mesg () { echo "$ME: $@" ; }
    show_mesg "$*"  >&2;
    trap '' EXIT
    exit 2
}

function load () {
    local fname="$1";
    local short="${fname##*/}";	# short file name
    [[ -f $fname ]] || croak_nonusage "Internal error: Cannot find the 
 file $short ($fname); something is badly broken."
    [[ -r $fname ]] || croak_nonusage "Internal error: Cannot read the
 file $short ($fname); something is badly broken.  
 You might check the file permissions or user id you used 
 to extract Jikes RVM."
    . "${fname}";
}

bin_dir="$(get_bin_dir)"
load "${bin_dir}/sanity-envars.bash" ;  		# Defines checkenv()
load "${bin_dir}/libjconfigure.bash" ;

## There is a bug in BASH version 2.05b.0(1)-release
## (BASH_VERSINFO=([0]="2" [1]="05b" [2]="0" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu"))
## whereby we are getting complaints that the variable "midline" was
## used before being set.  Specifically:
##
##   $ jconfigure NoSuch
##   /homes/bilbo/augart/JikesRVM/Clean/rvm/bin/jconfigure: line 320: midline: unbound variable
##
## The complaint actually refers to line 320 of libjconfigure.bash.
## And the workaround below solves it.  The bug is not present in Bash
## 2.05a.0(1)-release 
## --Steve Augart

# ## Debugging code in case we have the weird problem again:
# echo "have_function_relative_LINENO is: ${have_function_relative_LINENO-UNSET}"
# echo "midline is: ${midline-UNSET}"
# : ${midline+}			# this should be a complete no-op, and IS
# midline=${midline-0}	  # More serious workaround for the Bash 2.05b bug.

## Another set of debugging output as well as a test case.  The
## output is fascinating; the first line printed is blank and the
## second one printed is the string "0"; in a working shell, both
## lines would be "0".
# set +o nounset
# echo $midline
# echo $midline
# set -o nounset

## WORKAROUND:
## This should be a no-op.  However, this works around the Bash 2.05b bug where
## it thinks midline is unset.
# echo ${midline-UNSET} > /dev/null		# "echo" fails miserably.
builtin echo ${midline-UNSET} > /dev/null
# Also problems with this one.  This one, too, breaks in bad places.
builtin echo ${have_function_relative_LINENO-UNSET} > /dev/null

## POSSIBLE FUTURE WORKAROUND:
## # Do the same thing for the other global variables that are set inside 
## # libjconfigure.bash, just in case the Bash bug should manifest
## # itself again:  

## Place where source files reside.
checkenv RVM_ROOT

## Place where RVM bootimage, booter, and runtime support files will be placed.
checkenv --may-not-exist RVM_BUILD

## What configuration will host the build process?
checkenv RVM_HOST_CONFIG

## What configuration will run the system?
[[ ${RVM_TARGET_CONFIG-} ]] || export RVM_TARGET_CONFIG="${RVM_HOST_CONFIG}"
checkenv RVM_TARGET_CONFIG

#---------------------------#
# SECTION 1a - DOCUMENTATION #
#---------------------------#

function help_message () {

    # If PAGER is not set, set it to "more".
    ${PAGER=more} <<- EOF
	Usage: ${ME} [flags]... <configuration-name>
	Usage: ${ME} -help

	Flags: 
	-nocleanse | -cleanse :
	  (Do not) throw away intermediate files in the build directory that 
          were generated during a previous run of ${ME}.  "-cleanse" is the 
	  default.  Has no effect if run on a build directory that has never
	  been used for building.  This is only useful if you know that you
	  haven't changed the build configuration.
	  
	-quiet :
	  Do not spit out (most of) the informative messages that go out during
	  a run of ${ME}.  This includes possible complaints if you're
	  running an old version of Bash.

	[-D <variable>=<value>]... :
	  This flag may be repeated an arbitrary number of times.  Sets configuration
	  variables that describe the kind of Jikes RVM you are trying to build.
	  Provides an alternative to writing configuration files just 
	  to change one or two variables.

	About ${ME}:
	This script generates control files necessary to build a
	particular "configuration" of the Research Virtual Machine.
	
	Normally it is invoked as:
	
	   $ME <configuration-name>
	
	Where <configuration-name> indicates the configuration to be
	created and an environment variable, \$RVM_BUILD, specifies a
	directory where files comprising the configuration are to be
	placed.
	
	We normally do not request warnings from the C, C++, and Java
	compilers.  

	If you want to see C and C++ warnings, edit the
	RVM_TARGET_CONFIG and RVM_HOST_CONFIG files, setting CC to
	something like "gcc \$CFLAGS" and CPLUS to something like 
	"g++ \$CXXFLAGS".  *Then* set the CFLAGS and CXXFLAGS environment
	variables before you invoke "jconfigure", or invoke jconfigure
	with the -DCFLAGS and -DCXXFLAGS options.

	If you want to see Java warnings, set the values of
	JAVAC_WARNING_FLAGS and JIKES_WARNING_FLAGS with -D
	in the arguments to jconfigure.  The default value for both
	is "-nowarn".

	You can invoke this script as "${ME} < /dev/null" in order to
	suppress interactive questions.

	This script creates the \$RVM_BUILD directory and populates it
	with a skeleton directory structure along with some scripts
	and control files.

	After running this script, you can build an RVM executable by typing:
	
	    cd \$RVM_BUILD
	    ./jbuild
	
	Your \$RVM_ROOT tree will be template-expanded,
	macro-processed, compiled, and linked into a bootimage.  The
	processed sources, class files, bootimage, and booter will be
	placed into the \$RVM_BUILD directory.
	
	To execute the resulting bootimage (from any directory), type:
	
	   rvm <vm-flags> classname <application-args>
	
	Later, if you make changes to your \$RVM_ROOT tree, type
	"jbuild" again.  Modified source files will be discovered,
	copied to the build directory, recompiled, and the bootimage
	will be rebuilt.
	
	Special Cases when running "jbuild"
	===================================
	
	To avoid unnecessarily rebuilding the bootimage (when, for
	example, you have only modified classes that are dynamically
	loaded and which are not part of the bootimage) type "jbuild
	-nolink".
	
	To avoid building the booter (when, for example, running on
	the AIX side of an AIX/Linux cross-compilation) type "jbuild
	-nobooter".
	
	To build only the booter (when, for example, running on Linux
	side of a cross-port to Linux) type "jbuild -booter".
	
	To force recompilation of all classes (when, for example,
	you have modified a global constant or have added/removed
	fields/methods from a class) type "jbuild -recompile".
	
	To restore the build directory to its original "unbuilt" state
	type "jbuild -clean".
	
	To monitor the build process in more detail type "jbuild
	-trace".  "jbuild -help" will print the suboptions to
	"-trace", and may also print information about other options
	to jbuild.
	
	To monitor the build in even more detail, "jbuild" will pass
	on the flag "-demographics" to the boot image writer.  This
	makes the boot image writer display a summary of how the boot
	image's space is used up.

	If you want to pass additional options to the boot compiler
	(the compiler used when the Boot Image Writer compiles the
	boot image), then you can set these at configuration time by
	running "jconfigure" with the OPT_ARGS variable set, like so:

	     -DOPT_ARGS="-X:bc:opt1=val1 -Xbc:opt2=val2..."

	You can also set boot compiler options at build time by
	setting the environment variable DEBUG_ARGS, like so:

	     export DEBUG_ARGS="-X:bc:opt3=val3 -Xbc:opt4=val4..."
	or:
	     setenv DEBUG_ARGS "-X:bc:opt3=val3 -Xbc:opt4=val4..."

	before you invoke "jbuild".

	EOF
}
   

#--------------------------------------#
# SECTION 1b - Loading Config Files    #
#--------------------------------------#

## setFromPath()
## Sample usage: setFromPath diff
## Usage: set [ <var> ] <cmd>
function setFromPath () {
    local var cmd
    if (( $# > 1 )); then
	var="$1"
	shift
    else
	var=$(echo $1 | tr a-z A-Z)
    fi
    cmd=$1
    [[ \${!var-} ]] || eval ${var}=$(type -p g${cmd} 2> /dev/null) 
    [[ ${!var-} ]] || eval ${var}=$(type -p ${cmd} 2> /dev/null) 
    [[ ${!var-} ]] || unset ${var}
}

function setSomeFromPath () {
    local c
    for c; do
	setFromPath $c
    done
}

function rationalize_config_file_settings () {
    ## HOST_VM_TYPE: Valid working values: Sun, Kaffe
    ##			In-progress values: JikesRVM, gij
    : ${HOST_VM_TYPE=Sun}	# the default

    case $HOST_VM_TYPE in
	gij)
	    if [[ ! ${JAVAH-} ]]; then
		setFromPath JAVAH gcjh
		[[ ${JAVAH} ]] && JAVAH="${JAVAH} -jni"
	    fi
	    ;;

	Kaffe)
	    [[ ${KAFFE_HOME-} ]] || export KAFFE_HOME=/usr/local/kaffe
	    [[ ${HOST_JAVA_HOME-} ]] || export HOST_JAVA_HOME=${KAFFE_HOME}
	    # The javah that comes with Kaffe balks at some of Jikes RVM's 
	    # different versions of the java.* classes.
	    export DO_NOT_RUN_JAVAH=true
	    ;;

	JikesRVM)
	    : ${DONOR_RVM_ROOT?$ME: In the config file ${CURRENT_CONFIG_FILE}, HOST_VM_TYPE=JikesRVM, so you need to set DONOR_RVM_ROOT too}
	    : ${DONOR_RVM_BUILD?$ME: In the config file ${CURRENT_CONFIG_FILE}, HOST_VM_TYPE=JikesRVM, so you need to set DONOR_RVM_BUILD too}
	    ## Doesn't ship with a "javah"

	    export DO_NOT_RUN_JAVAH=true
	    ;;

	Sun)
	    : ${HOST_JAVA_HOME?$ME: In the config file ${CURRENT_CONFIG_FILE}, HOST_VM_TYPE=Sun, so you need to set HOST_JAVA_HOME too}
	    export JAVAH=${HOST_JAVA_HOME}/bin/javah
	    ;;

	*)
	    echo >&2 "$ME: Config file ${CURRENT_CONFIG_FILE}: Unknown HOST_VM_TYPE: $HOST_VM_TYPE"
	    trap '' EXIT
	    exit $Exit_Status_Bad_Args
	    ;;
    esac

    if ! [[ ${HOST_VM_RT-} ]]; then
	## HOST_JAVA is deprecated; the free virtual machines haven't passed
	## the Java Compatibility Tests, so legally aren't "Java".
	! [[ ${HOST_JAVA-} ]] || export HOST_VM_RT=${HOST_JAVA}
    fi

    if ! [[ ${HOST_VM_RT-} ]]; then
	if [[ $HOST_VM_TYPE = gij ]]; then
	    setFromPath HOST_VM_RT gij
	    setFromPath FASTJAR jar
	elif [[ $HOST_VM_TYPE = Kaffe ]]; then
	    HOST_VM_RT=${KAFFE_HOME}/bin/kaffe
	elif [[ $HOST_VM_TYPE = Sun ]]; then
	    HOST_VM_RT=${HOST_JAVA_HOME}/bin/java
	    # the JDK java executable
	    export HOST_JAVA="$HOST_JAVA_HOME/bin/java"

	    # 1.4.x JDKs on Linux seem to require that LD_LIBRARY_PATH be set to include
	    # the JRE's various library paths (otherwise they don't find their .so files 
	    # when invoked from shell scripts and make).
	    # Here's how to do it to use HotSpot server with Blackdown 1.4.1
	    export HOST_JAVA_LD_LIBRARY_PATH="$HOST_JAVA_HOME/jre/lib/i386/:$HOST_JAVA_HOME/jre/lib/i386/server"
	    # Here's how to do it to using the IBM 1.4.1 DK 
	    #export HOST_JAVA_LD_LIBRARY_PATH="$HOST_JAVA_HOME/jre/bin/classic:$HOST_JAVA_HOME/jre/bin/"
	elif [[ $HOST_VM_TYPE = JikesRVM ]]; then
	    ## This blows up if either of the variables 
	    ## DONOR_RVM_ROOT or DONOR_RVM_BUILD contain spaces in their values.
	    HOST_VM_RT="${DONOR_RVM_ROOT}/rvm/bin/runrvm $HOME ${DONOR_RVM_ROOT} ${DONOR_RVM_BUILD}"
	fi
    fi
    
    if ! [[ ${TemplateExpander_HOST_VM_RT-} ]]; then
	TemplateExpander_HOST_VM_RT="${HOST_VM_RT}"
    fi

    if ! [[ ${HOST_JAVADOC-} ]] && [[ ${HOST_JAVA_HOME-} ]]; then
	# The JDK Javadoc executable
	# Might be replaceable with Doxygen, but I'm not holding my breath.
	export HOST_JAVADOC="$HOST_JAVA_HOME/bin/javadoc"
    fi

    # Path for the Jikes java-to-byte-code compiler.  A necessary part of 
    # the build process.
    if [[ $CURRENT_CONFIG_FILE = $RVM_HOST_CONFIG ]]	\
	&& ! [[ ${JIKES-} ]]				\
	&& ! export JIKES=$(type -p jikes)
    then
	## Note: This is quite possibly bogus if we're reading in the target
	## file instead of the host file, during a cross-build.
	show_mesg "I can't find the Jikes java-to-byte-code compiler.  Please set the variable JIKES in $CURRENT_CONFIG_FILE or put an executable named \"jikes\" in your command search path"
    fi

    ## HOST_JAVAC:
    ## The Java compiler.
    if [[ ! ${HOST_JAVAC-} ]]; then
	if [[ $HOST_VM_TYPE = gij ]]; then
	    ## -fjni isn't compatible with generating class files, so we will
	    ## leave it out.
	    export HOST_JAVAC="gcj -C"
	elif [[ $HOST_VM_TYPE = Sun ]]; then
	    ## Use the Sun compiler.
	    export HOST_JAVAC="$HOST_JAVA_HOME/bin/javac"
	elif [[ ${JIKES-} ]]; then	# always true
	    # JIKES_WARNING_FLAGS won't be set the first time we read 
	    # RVM_HOST_CONFIG; that is OK.  It will be set the second time,
	    #  before we generate the output.
	    export HOST_JAVAC="CLASSPATH=${RVM_BUILD}/RVM.classes:${RVM_BUILD}/RVM.classes/rvmrt.jar $JIKES ${JIKES_WARNING_FLAGS-}"
#	    if [[ $CURRENT_CONFIG_FILE = $RVM_HOST_CONFIG ]]; then
#		export HOST_JAVAC=$bin_dir/fake-javac
#	    else
#		export HOST_JAVAC=$JIKES # pray
#	    fi
	fi
    fi

    # HOST_REPOSITORIES:
    # the JDK standard library jar files
    # This should be renamed to DONOR_VM_REPOSITORIES
    if [[ ! ${HOST_REPOSITORIES-} ]]; then
	if [[ $HOST_VM_TYPE = Sun ]] && [[ ${HOST_JAVA_HOME-} ]]; then
	    # For some reason, Kaffe's jre/lib/rt.jar makes the 
	    # Jikes 1.19 compiler dump core when it compiles 
	    # GenerateFromTemplate.java.  So we limit this to the Sun compiler.
	    export HOST_REPOSITORIES="$HOST_JAVA_HOME/jre/lib/rt.jar"
	else
	    export HOST_REPOSITORIES=${RVM_BUILD}/RVM.classes/rvmrt.jar
	fi
    fi

    # HOST_TOOLS: 
    # The Sun-derived JDKs have this, which we only use for doing 
    # regression tests: 
    if [[ ! ${HOST_TOOLS-} ]] && [[ $HOST_VM_TYPE = Sun ]]; then
	export HOST_TOOLS="$HOST_JAVA_HOME/lib/tools.jar"
    fi

    # The "jar" executable program.
    # This has a convenient OSS replacement, fastjar
    # (Except that fastjar doesn't support -u)
    # Kaffe also comes with a "jar".
    if [[ ! ${JAR-} ]]; then
	if [[ ${HOST_JAR-} ]]; then
	    # obsolete name
	    export JAR=${HOST_JAR}
	elif [[ ${FASTJAR-} ]]; then
	    export JAR=${FASTJAR}
	elif [[ ${HOST_JAVA_HOME-} ]]; then
	    export JAR=${HOST_JAVA_HOME}/bin/jar
	fi
    fi

    # CC: What C compilers should be used?
    # This must be GCC.
    [[ ${CC-} ]] || export CC='gcc -w -g -O'

    # CPLUS: what C++ compilers should be used?
    [[ ${CPLUS-} ]] || export CPLUS="${CXX-g++ -w -g -O}"

    # LDSHARED:
    # how to link a shared C++ library (possibly also recompile one 
    # or more source files in it)
    [[ ${LDSHARED-} ]] || export LDSHARED="${CPLUS} -shared"

    # The configuration for building the user guide.
    # You may have to edit this file.
    [[ ${USER_GUIDE_CONFIG-} ]] || export USER_GUIDE_CONFIG="${RVM_ROOT}/rvm/doc/userguide/config.mk"

    ## Special GNU commands:
    setFromPath GNU_MAKE make
    # [[ ${GNU_MAKE-} ]] || export GNU_MAKE="/usr/bin/make"

    #  some Unix commands
    setFromPath awk
    # [[ ${AWK-} ]] || export AWK="/usr/bin/awk"

    setFromPath bash
    # [[ ${BASH} ]] || export BASH="/bin/bash"

    # You need one of Yacc or Bison (one will usually be installed)
    setFromPath bison
#     if ! [[ ${BISON-} ]]; then
# 	BISON=$(type -p bison 2> /dev/null) || unset BISON
#     fi

    setFromPath diff
    # [[ ${DIFF-} ]] || DIFF=$(type -p diff 2> /dev/null) || unset DIFF

    setFromPath GNU_TAR tar
    ## [[ ${GNU_TAR-} ]] || export GNU_TAR="/bin/tar"

    setSomeFromPath fgrep find grep md5sum ps sed wget xargs
    
#    [[ ${FGREP-} ]] || FGREP=$(type -p fgrep 2> /dev/null) || unset FGREP
    ## [[ ${FIND-} ]] || export FIND="/usr/bin/find"
    # [[ ${GREP-} ]] || export GREP="/bin/grep"
#     export MD5SUM="/usr/bin/md5sum"
#     export PS="/bin/ps"
#     export SED="/bin/sed"
#     export WGET="/usr/bin/wget"
#     export XARGS="/usr/bin/xargs"

    setFromPath UNZIP_CMD unzip
#     export UNZIP_CMD="/usr/bin/unzip"

}

function load_config_file () {
    . "$1"
    export CURRENT_CONFIG_FILE="$1"
    rationalize_config_file_settings
}



#---------------------------------------------------------------------------#
# SECTION 1c -- Get HOST_CLASSPATH_ROOT					    #
#---------------------------------------------------------------------------#

load_config_file "${RVM_HOST_CONFIG}"

## We normally check for a variable named CLASSPATH_ROOT in the config file.
## An EXPERIMENTAL alternative is to set
## CLASSPATH_INSTALLATION in your config file.  If you've run "make install"
## in the default configuration, then CLASSPATH_INSTALLATION will be
## "/usr/local/classpath".
##
## This does not have the checks in it that we normally get

[[ ${CLASSPATH_ROOT-} ]]  && declare -r HOST_CLASSPATH_ROOT=${CLASSPATH_ROOT}
[[ ${CLASSPATH_INSTALLATION-} ]]  && declare -r HOST_CLASSPATH_INSTALLATION=${CLASSPATH_INSTALLATION} # XXX Experimental



#--------------------------------------#
# SECTION 2 - DEFINITIONS OF CONSTANTS #
#--------------------------------------#


# The places to put scripts and control files. 

# (The *_STR variants of these variables have their variables expanded
# when the emitted script is executed, rather than being expanded prior to
# emitting the script.  This gives the scripts a degree of location
# transparency.  The _STR1 variables are similar to the _STR variables, 
# but are used to produce the localization script.  They lack the '$' )

BUILD_DIRECTORY="$RVM_BUILD"
BUILD_DIRECTORY_STR1="JAL_BUILD"
BUILD_DIRECTORY_STR="\${$BUILD_DIRECTORY_STR1}"

ROOT_DIRECTORY="$RVM_ROOT"
ROOT_DIRECTORY_STR1="JAL_ROOT"
ROOT_DIRECTORY_STR="\${$ROOT_DIRECTORY_STR1}"

# source path for configuration files 
# eg, BaseBaseSemispace
#
CONFIGURATION_FILE_SOURCE="$ROOT_DIRECTORY/rvm/config/build"

# Place to remember what configuration we have built.
#
CONFIGURATION_SUMMARY="$BUILD_DIRECTORY/RVM.configuration"

# Place to keep list of source directories to be scanned by preprocessor.
#
SOURCE_LIST="$BUILD_DIRECTORY/RVM.sources"
SOURCE_LIST_STR="$BUILD_DIRECTORY_STR/RVM.sources"

# Place to remember, if a cleansing pass should precede the build.
#
CLEANSE_STATUS="${BUILD_DIRECTORY}/RVM.cleanseRequired"
CLEANSE_STATUS_STR="${BUILD_DIRECTORY_STR}/RVM.cleanseRequired"

# Place to remember if preprocessor has yielded new/modified source files.
#
CLASSES_INVALID="${BUILD_DIRECTORY}/RVM.classesInvalid"
CLASSES_INVALID_STR="${BUILD_DIRECTORY_STR}/RVM.classesInvalid"

# Place to put preprocessed .java files and compiled .class files.
#
CLASSES_DIRECTORY="${BUILD_DIRECTORY}/RVM.classes"
CLASSES_DIRECTORY_STR="${BUILD_DIRECTORY_STR}/RVM.classes"

# Place to put source files that are machine generated.
#
GENERATED_FILES_DIRECTORY="${BUILD_DIRECTORY}/RVM.generatedSources"
GENERATED_FILES_DIRECTORY_STR="${BUILD_DIRECTORY_STR}/RVM.generatedSources"
   
# Place to put compiled versions of build tools and other glop
# generated during the build process.
#
SCRATCH_DIRECTORY="${BUILD_DIRECTORY}/RVM.scratch"
SCRATCH_DIRECTORY_STR="${BUILD_DIRECTORY_STR}/RVM.scratch"

# Place to put the debugger, and other such tools.
#
TOOL_DIRECTORY="${BUILD_DIRECTORY}/RVM.tools"
TOOL_DIRECTORY_STR="${BUILD_DIRECTORY_STR}/RVM.tools"

# Place to keep list of classes comprising the bootimage.
#
PRIMORDIAL_CLASSES="${BUILD_DIRECTORY}/RVM.primordials"
PRIMORDIAL_CLASSES_STR="${BUILD_DIRECTORY_STR}/RVM.primordials"

# Place to keep list of .class files to be excluded from bootimage.
#
EXCLUDED_CLASSES="${BUILD_DIRECTORY}/RVM.exclusions"
EXCLUDED_CLASSES_STR="${BUILD_DIRECTORY_STR}/RVM.exclusions"

# Place to put bootimage.
#
BOOTIMAGE="${BUILD_DIRECTORY}/RVM.image"
BOOTIMAGE_STR="${BUILD_DIRECTORY_STR}/RVM.image"

# Place to put bootimage map.
#
BOOTIMAGE_MAP=${BUILD_DIRECTORY}/RVM.map
BOOTIMAGE_MAP_STR=${BUILD_DIRECTORY_STR}/RVM.map

# Place to put booter.
#
BOOTER=${BUILD_DIRECTORY}/JikesRVM
BOOTER_STR=${BUILD_DIRECTORY_STR}/JikesRVM

# Variables to allow configuration files to alter the list of
# directories, primordials, exclusions and top level sources.
#
CONF_SPECIFIC_SOURCES_LIST=""
CONF_SPECIFIC_PRIMORDIALS_LIST=""
CONF_SPECIFIC_EXCLUSIONS_LIST=""
CONF_SPECIFIC_TOP_LEVEL_SOURCES=""

# Strings to use in the scripts as the locations of various commands.
#
# These could be overridden by someone with -D on the command line, or 
# in the config file.
JIKES_STR1="JIKES"
JIKES_STR="\$$JIKES_STR1"
# HOST_JAVA is a deprecated alias for HOST_VM_RT
HOST_JAVA_STR1="HOST_JAVA_RT"
HOST_JAVA_STR="\$$HOST_JAVA_STR1"
HOST_VM_RT_STR1="HOST_VM_RT"
HOST_VM_RT_STR="\$$HOST_VM_RT_STR1"
HOST_VM_TYPE_STR1="HOST_VM_TYPE"
HOST_VM_TYPE_STR="\$$HOST_VM_TYPE_STR1"
HOST_JAVAC_STR1="HOST_JAVAC"
HOST_JAVAC_STR="\$$HOST_JAVAC_STR1"
HOST_JAVA_HOME_STR1="HOST_JAVA_HOME"
HOST_JAVA_HOME_STR="\$$HOST_JAVA_HOME_STR1"
HOST_JAVADOC_STR1="HOST_JAVADOC"
HOST_JAVADOC_STR="\$$HOST_JAVADOC_STR1"
JAR_STR1="JAR"
JAR_STR="\$$JAR_STR1"
HOST_REPOSITORIES_STR1="HOST_REPOSITORIES"
HOST_REPOSITORIES_STR="\$$HOST_REPOSITORIES_STR1"
HOST_TOOLS_STR1="HOST_JAVA_TOOLS"
HOST_TOOLS_STR="\$$HOST_TOOLS_STR1"
GNU_MAKE_STR1="GNU_MAKE"
GNU_MAKE_STR="\$$GNU_MAKE_STR1"
HOST_CC_STR1="CC"
HOST_CC_STR="\$$HOST_CC_STR1"
HOST_CPP_STR1="CPP"
HOST_CPP_STR="\$$HOST_CPP_STR1"
HOST_CPLUS_STR1="CPLUS"
HOST_CPLUS_STR="\$$HOST_CPLUS_STR1"
HOST_SHLD_STR1="HOST_SHLD"
HOST_SHLD_STR="\$$HOST_SHLD_STR1"
SED_STR1="SED"
SED_STR="\$$SED_STR1"

# Use Java warnings?
JIKES_WARNING_FLAGS=-nowarn
JAVAC_WARNING_FLAGS=-nowarn

# Generate map of bootimage?
#
declare -x -i GENERATE_MAP=1

f=$RVM_ROOT/rvm/_timestamp/timestamp
if [[ ! -f  $f ]]; then
    echo >&2 "$ME: RVM_ROOT is not set properly or the directory is
   corrupt; I can't find a file named
    \"$f\" (RVM_ROOT/rvm/_timestamp/timestamp)."
    trap ''
    exit 3
fi
# Current version of RVM
CVS_TIMESTAMP=$(cat $f)
JIKESRVM_VERSION="Jikes RVM 2.3.3"

# Default values for RunBootImage constants.
# Reasonable default values.
# To change the defaults for a paricular configuration, 
# redefine appropriate environment variables in the configuration's stanza.
#
DEFAULT_INITIAL_HEAP_SIZE=20   # in megabytes
DEFAULT_MAXIMUM_HEAP_SIZE=100  # in megabytes

# Here are the choices for target architecture.
#
declare -i RVM_FOR_POWERPC=0  # does not imply aix, nor Linux
declare -i RVM_FOR_IA32=0     # Implies Linux

# Here are the choices for target operating system.
#
declare -i RVM_FOR_AIX=0	   # Implies PPC
declare -i RVM_FOR_LINUX=0	   # Implies nothing.
declare -i RVM_FOR_OSX=0	   # Implies PPC.

# 32-bit or 64-bit address size
#
declare -i RVM_FOR_32_ADDR=0
declare -i RVM_FOR_64_ADDR=0
 
# Here are the choices for compiler components and extensions.
# Note: baseline compiler is always built into bootimage: its presence is not controlled by any flags.
#
declare -i RVM_WITH_OPT_COMPILER=0
declare -i RVM_WITH_ADAPTIVE_SYSTEM=0 # superset of opt
declare -i RVM_WITH_OPT_TEST_HARNESS=0  # superset of opt, for test/debug via OptTestHarness class

# Include support for hardware performance monitors (HPM)
declare -i RVM_WITH_HPM=0

## Memory Allocators and Garbage Collector options (JMTk)
declare -i RVM_WITH_SEMI_SPACE=0
declare -i RVM_WITH_MARK_SWEEP=0
declare -i RVM_WITH_GEN_COPY=0
declare -i RVM_WITH_GEN_MS=0
declare -i RVM_WITH_GEN_RC=0
declare -i RVM_WITH_COPY_MS=0
declare -i RVM_WITH_REF_COUNT=0
declare -i RVM_WITH_NO_GC=0
declare -i RVM_WITH_GCSPY=0
declare -i RVM_WITH_GCTRACE=0

# Here are the choices for compiler to generate code for classes that are loaded into bootimage.
#
declare -i RVM_WITH_BASE_BOOTIMAGE_COMPILER=0
declare -i RVM_WITH_OPT_BOOTIMAGE_COMPILER=0

# Here are the choices for the object model
#
declare -i RVM_WITH_DEFAULT_OBJECT_MODEL=1
declare -i RVM_WITH_ONE_WORD_MASK_OBJECT_MODEL=0
declare -i RVM_WITH_ONE_WORD_PTR_OBJECT_MODEL=0
declare -i RVM_WITH_ONE_WORD_INDEX_OBJECT_MODEL=0

# Here are the choices for additional components that are under development and/or are excluded from default build.
#
declare -i RVM_FOR_SINGLE_VIRTUAL_PROCESSOR=0   # use pThread library to access multiple CPU's (or not)
declare -i RVM_WITH_DETERMINISTIC_THREAD_SWITCHING=0 # thread switch after n method calls, do not use interrupts to drive preemption
declare -i RVM_WITHOUT_PREEMPTIVE_THREAD_SWITCHING=0 # thread switch only at explicit yield and wait calls
declare -i RVM_WITH_ALL_CLASSES=0   # include all vm classes in bootimage, not just those needed for startup
declare -i RVM_WITHOUT_ASSERTIONS=0 # exclude runtime assertion checks
declare -i RVM_WITH_EXTREME_ASSERTIONS=0 # include extra assertion checking 
declare -i RVM_WITHOUT_AOS_LOG=0    # turn off AOS logging
declare -i RVM_WITH_NATIVE_DAEMON_PROCESSOR=0

#
# intercept blocking system calls (currently Linux-only)
#
declare -x -i RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS=0

##
## Which ABI should VM_JNICompiler.java build for?
##
declare -i RVM_WITH_MACH_O_ABI=0 # OSX (Darwin)
declare -i RVM_WITH_POWEROPEN_ABI=0 # AIX; Linux: ppc64
declare -i RVM_WITH_SVR4_ABI=0	# Linux: x86, ppc32


# controls for diagnostic flags
declare -i RVM_FOR_STRESSGC=0

# using on stack replacement 
declare -i RVM_WITH_OSR=0

# These have Java preprocessor "//-#if" conditional directives that 
# test against them.   If we put the Java preprocessor into paranoid mode, it
# complains about any tests against undefined conditionals.
# Search for "BUILD_WITH_PARANOID_PREPROCESSOR" below and way below.

declare -i RVM_WITH_FREE_LOCK_BALANCING=0	# In VM_Lock.java
declare -i RVM_WITH_TENTATIVE_MICROLOCKING=0	
declare -i RVM_FOR_MCS_PROCESSOR_LOCKS=0
declare -i RVM_WITH_VARIABLE_LOCK_RETRY_LIMIT=0
declare -i RVM_WITH_LOCK_CONTENTION_TRACING=0
declare -i RVM_WITH_DEBUG=0

## Just affects the build process
declare -i BUILD_WITH_PARANOID_PREPROCESSOR=0

## MISC (to be categorized)
declare -i RVM_WITH_NOFLUSH=0
# : ${RVM_WITH_NOFLUSH=0}

## Consequences of the target Operating System.
## These are overridden in the OSX config file.
declare -i HAS_DLCOMPAT=0
# : ${HAS_DLCOMPAT=0}

## These should be flushed, since they are now almost hardwired
## with these values set (I added these definitions to shut up the
## "paranoid preprocessor". 
declare -r -i RVM_WITH_JNI_SETBOOLSTAR=1
declare -r -i RVM_WITH_OPT_INSTRUMENTATION=0
declare -r -i RVM_WITH_NON_BLOCKING_FDS_FOR_CLASSPATH=0

#---------------------------------------#
# SECTION 3 - PROCESS RVM_TARGET_CONFIG # 
#---------------------------------------#

## Turn off all of the environment variables that might be set by
## sourcing a configuration file, but that might not be set if we were
## to source a different such configuration file.  
function unsetEnvironment() {
    local flags="$-"
    set +e
    # Disable ERR Trap.  This only affects this function, not the 
    # global environment.  We do this (disable the ERR trap) in order to avoid
    # any errors that may arise from unsetting variables that are not already
    # set.
    #
    # As before, we redirect error messages to /dev/null.  This is because
    # some older Bash versions do not support the ERR trap.
    trap '' ERR 2> /dev/null || :

    unset JIKES $JIKES_STR1
    unset HOST_JAVA $HOST_JAVA_STR1 # Deprecated.
    unset HOST_VM_RT $HOST_VM_RT_STR1
    unset HOST_VM_TYPE $HOST_VM_TYPE_STR1
    unset HOST_JAVAC $HOST_JAVAC_STR1
    unset HOST_JAVA_HOME $HOST_JAVA_HOME_STR1 
    unset HOST_JAVADOC $HOST_JAVADOC_STR1 
    unset JAR $JAR_STR1 
    unset FASTJAR
    unset HOST_REPOSITORIES $HOST_REPOSITORIES_STR1 
    unset HOST_TOOLS $HOST_TOOLS_STR1 
    unset GNU_MAKE $GNU_MAKE_STR1 
    unset CC $HOST_CC_STR1 
    unset CPP $HOST_CPP_STR1 
    unset CPLUS $HOST_CPLUS_STR1 
    unset LDSHARED $HOST_SHLD_STR1 
    unset WGET XARGS UNZIP 
    unset HOST_JAVA_LD_LIBRARY_PATH
    unset BISON ANT_CMD ECLIPSE_INSTALL_DIR CLASSPATH_ROOT
    unset CLASSPATH_INSTALLATION # XXX Experimental
    unset PS MD5SUM GREP GNU_TAR FIND FGREP DIFF CVS BASH AWK
    unset BENCHMARK_ROOT
    set $flags;			# turn back on -e, if it was off.
}

# One use of the target_config file is to define
# directives that hold for all configurations 
# defined on the target. By sourcing it here,
# we define such directives for all configs on the target,
# but still allow them to be overridden on the command line
# or in a build-config file.

unsetEnvironment;
load_config_file "${RVM_TARGET_CONFIG}"
[[ ${CLASSPATH_ROOT-} ]]  && declare -r TARGET_CLASSPATH_ROOT=${CLASSPATH_ROOT}
[[ ${CLASSPATH_INSTALLATION-} ]]  && declare -r TARGET_CLASSPATH_INSTALLATION=${CLASSPATH_INSTALLATION}

# echo >&2 "I read RVM_TARGET_CONFIG=${RVM_TARGET_CONFIG} in section 3;  JIKES_WARNING_FLAGS=$JIKES_WARNING_FLAGS"  #DEBUG

#--------------------------------------#
# SECTION 4 - ARGUMENT PARSING         #
#--------------------------------------#

function croak_usage () {
    show_mesg >&2 "$*"
    show_mesg >&2 "Type \"${ME} -help\" for usage information."
    trap '' EXIT
    exit $Exit_Status_Bad_Args
}

declare -i quiet=0 cleanse=1
while (( $# > 0 ))
do
    case "$1" in 
	-help|--help ) 
	    help_message;
	    trap '' EXIT
	    exit 0; ;;
	-D )
 	    shift
	    export "$1";;
	
	-D* )
	    arg="$1";
	    arg="${arg#-D}"	# trim off the leading -D
	    export "$arg" ;;
	
	-quiet|--quiet ) 
	    quiet=1;;

	-cleanse|--cleanse ) 
	    cleanse=1;;

	-nocleanse|--nocleanse ) 
	    cleanse=0;;

	-*)  croak_usage "I do not understand the flag \"$1\""
	    ;;

	--) shift;
	    break;
	    ;;
	* ) break;;
    esac

    shift
done

# This is where we would want to do the check.  However, we get into
# trouble too fast (i.e., early on) with Bash 2.03, so we use a
# grosser kludge at the start of jconfigure in order to quickly throw
# out Bash 2.03 and earlier.
(( quiet )) || check_bash_version

(( $# >= 1 )) || croak_usage "Please specify <configuration-name>"
CONFIGURATION_NAME="$1"
shift

(( $# == 0 )) || croak_usage "Too many arguments; specify only one <configuration-name>."


if [[ -f "${CONFIGURATION_FILE_SOURCE}/${CONFIGURATION_NAME}" ]]; then
    # We pass the "${CONFIGURATION_FILE_SOURCE}" argument to the 
    # CONFIGURATION_NAME shell script.
    . "${CONFIGURATION_FILE_SOURCE}/${CONFIGURATION_NAME}" "${CONFIGURATION_FILE_SOURCE}"
else
    croak_usage "Unknown configuration ${CONFIGURATION_NAME}"
fi

# set the relative path to the object model.
if (( RVM_WITH_ONE_WORD_MASK_OBJECT_MODEL )); then
    OBJECT_MODEL_PATH_STR=objectModel/oneWordMaskTIB
elif (( RVM_WITH_ONE_WORD_PTR_OBJECT_MODEL )); then
    OBJECT_MODEL_PATH_STR=objectModel/oneWordTIBPtr
elif (( RVM_WITH_ONE_WORD_INDEX_OBJECT_MODEL )); then
    OBJECT_MODEL_PATH_STR=objectModel/oneWordIndexTIB
else
    OBJECT_MODEL_PATH_STR=objectModel/default
fi

if (( RVM_FOR_AIX || RVM_FOR_SINGLE_VIRTUAL_PROCESSOR == 1 )); then
    RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS=1
fi

if (( RVM_FOR_OSX )); then
    RVM_WITH_MACH_O_ABI=1
    RVM_WITH_POWEROPEN_ABI=0
    RVM_WITH_SVR4_ABI=0
elif (( RVM_FOR_AIX
	|| (( RVM_FOR_LINUX && RVM_FOR_POWERPC && RVM_FOR_64_ADDR )) ))
then
    RVM_WITH_MACH_O_ABI=0
    RVM_WITH_POWEROPEN_ABI=1
    RVM_WITH_SVR4_ABI=0
else				# Linux/x86; Linux/ppc32
    RVM_WITH_MACH_O_ABI=0
    RVM_WITH_POWEROPEN_ABI=0
    RVM_WITH_SVR4_ABI=1
fi


## Setting PREPROCESSOR_DEFINITIONS:
## We keep this variable with a newline-separated list of definitions.
# Convert configuration choices into preprocessor definitions.
#    RVM_FOR_xxx  --> -DRVM_FOR_xxx
#    RVM_WITH_xxx --> -DRVM_WITH_xxx
#    RVM_WITHOUT_xxx --> -DRVM_WITHOUT_xxx
#
## To find out which programmable conditions are still alive (i.e., which ones
## are currently in use in the program source code), look at 
## rvm/GNUmakefile, the 'conditionals' target.  
## The BUILD_WITH_PARANOID_PREPROCESSOR directive affects this.

## Remember, these numbers (BOOTIMAGE_LOAD_ADDRESS, MAXIMUM_MAPPABLE_ADDRESS) 
## are for the TARGET:
PREPROCESSOR_DEFINITIONS="-DBOOTIMAGE_LOAD_ADDRESS=${BOOTIMAGE_LOAD_ADDRESS}"
PREPROCESSOR_DEFINITIONS="${PREPROCESSOR_DEFINITIONS}
-DMAXIMUM_MAPPABLE_ADDRESS=${MAXIMUM_MAPPABLE_ADDRESS}"
CLEANUP='/bin/rm -f ${tmpf-}'	# used by EXIT trap.
tmpf=/tmp/jconfigure.$$
set | sed -n -e 's/^RVM_FOR_/-DRVM_FOR_/p' \
		-e 's/^RVM_WITH_/-DRVM_WITH_/p'			\
		-e 's/RVM_WITHOUT_/-DRVM_WITHOUT_/p' > $tmpf
if (( BUILD_WITH_PARANOID_PREPROCESSOR )); then
    from_vars="$(< $tmpf)"
else
    ## To cut down on the number of definitions that appear in our generated
    ## code, if we are not compiling with the paranoid preprocessor flags 
    ## enabled, we can remove all of the ones which just set to 
    ## the default value (zero) 
    from_vars="$(sed -e '/=0/d' $tmpf)"
fi
eval $CLEANUP   # rm -f $tmpf
CLEANUP=":"
# echo "from_vars are $from_vars"
PREPROCESSOR_DEFINITIONS="${PREPROCESSOR_DEFINITIONS}
${from_vars}"
unset from_vars
## We keep PREPROCESSOR_DEFINITIONS as a newline-separated list rather than
## turning it into a space-separated list.  That is because it is 
## convenient for us to be able to print out the definitions
## in the configuration summary.


if (( BUILD_WITH_PARANOID_PREPROCESSOR )); then
    PARANOID_PREPROCESSOR_FLAG=" --no-undefined-constants-in-conditions"
else
    PARANOID_PREPROCESSOR_FLAG=""
fi

# Place where bootimage runner lives.
#
BOOTIMAGE_RUNNER_DIR="${RVM_ROOT}/rvm/src/tools/bootImageRunner"
BOOTIMAGE_RUNNER_DIR_STR="${ROOT_DIRECTORY_STR}/rvm/src/tools/bootImageRunner"
if (( RVM_FOR_POWERPC )); then
    BOOTIMAGE_RUNNER_SUBDIR="${RVM_ROOT}/rvm/src/tools/bootImageRunner/powerPC"
    BOOTIMAGE_RUNNER_SUBDIR_STR="${ROOT_DIRECTORY_STR}/rvm/src/tools/bootImageRunner/powerPC"
elif (( RVM_FOR_IA32 )); then
    BOOTIMAGE_RUNNER_SUBDIR="${RVM_ROOT}/rvm/src/tools/bootImageRunner/IA32"
    BOOTIMAGE_RUNNER_SUBDIR_STR="${ROOT_DIRECTORY_STR}/rvm/src/tools/bootImageRunner/IA32"
else
    show_mesg_raw >&2 "$ME:$LINENO: Trouble is looming; neither RVM_FOR_POWERPC nor RVM_FOR_IA32 is defined."
    BOOTIMAGE_RUNNER_DIR="UNKNOWN_BOOTIMAGE_RUNNER_DIRECTORY"
    BOOTIMAGE_RUNNER_DIR_STR="UNKNOWN_BOOTIMAGE_RUNNER_DIRECTORY"
fi

# Place where bootimage writer lives.
#
BOOTIMAGE_WRITER_DIR="${RVM_ROOT}/rvm/src/tools/bootImageWriter"
BOOTIMAGE_WRITER_DIR_STR="${ROOT_DIRECTORY_STR}/rvm/src/tools/bootImageWriter"

#--------------------------------------#
# SECTION 5 - DEFINITIONS OF FUNCTIONS #
#--------------------------------------#

# Check configuration options for sanity.
function checkConfigurationOptions {
    if (( ! RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS )) \
	&& (( RVM_WITH_NATIVE_DAEMON_PROCESSOR ))
    then
	croak_nonusage "\
If RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS is not specified,\
then RVM_WITH_NATIVE_DAEMON_PROCESSOR must not be specified";
    fi
}


# Emit list of source tree directories whose Java files comprise
# the current configuration.
#
function emitSourceList () {

    if (( RVM_FOR_POWERPC )); then
	ARCH_DIR="powerPC"
    elif (( RVM_FOR_IA32 )); then
	ARCH_DIR="intel"
    else
	ARCH_DIR="UNSPECIFIED_ARCHITECTURE"
    fi

    # Common components.
    #
    cleanFileList <<- EOF
	$RVM_ROOT/rvm/src/vm
	$RVM_ROOT/rvm/src/vm/arch/$ARCH_DIR
	$RVM_ROOT/rvm/src/vm/arch/$ARCH_DIR/runtime
	$RVM_ROOT/rvm/src/vm/classLoader
	$RVM_ROOT/rvm/src/vm/jni
	$RVM_ROOT/rvm/src/vm/runtime
	$RVM_ROOT/rvm/src/vm/scheduler
	$RVM_ROOT/rvm/src/vm/utility
	$RVM_ROOT/rvm/src/vm/verifier
	$RVM_ROOT/rvm/src/vm/compilers/compiledCode
    

	$RVM_ROOT/rvm/src/vm/arch/$ARCH_DIR/jni

    # Baseline compiler components (always part of bootimage).
    #
	${RVM_ROOT}/rvm/src/vm/compilers/baseline           # architecture independent
	${RVM_ROOT}/rvm/src/vm/compilers/baseline/GCMap     # architecture independent
	${RVM_ROOT}/rvm/src/vm/compilers/baseline/profiling # architecture independent

	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/baseline    # architecture dependent
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/baseline/GCMap
	$( if [[ -e ${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/assembler ]]; then
	    echo ${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/assembler # architecture dependent
    	fi)
    
	${RVM_ROOT}/rvm/src/vm/objectModel
	${RVM_ROOT}/rvm/src/vm/objectModel/lockNursery
	${RVM_ROOT}/rvm/src/vm/${OBJECT_MODEL_PATH_STR}

    # other components
    #
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/disassembler

EOF
    # Optimizing compiler components.
    #
    if (( RVM_WITH_OPT_COMPILER )); then
	# core components
	#
	cleanFileList <<- EOF
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/driver
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/instrumentation
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/cfg
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/conversions/bc2hir
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/conversions/hir2lir
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/conversions/lir2mir
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/conversions/mir2mc
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/gcmap
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/instruction
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/instruction/operand
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/ir/util
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/control
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/control/dominators
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/coalesce
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/liveness
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/liveRangeSplitting
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/simpleSSA
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/simpleSSA/escape
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/abcd
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/builder
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/codePlacement
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/expressionFolding
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/gvn
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/loadElimination
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/redundantBranchElimination
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/global/ssa/storeElimination
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/ipa/inlining
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/ipa/specialization
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/ipa/summaries
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/local
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/local/depGraph
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/optimizations/local/instructionScheduler
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/regalloc/linearScan
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/regalloc/util
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/dataflowUtil
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/exception
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/graph
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/graph/vis
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/graph/vis/vcg
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/graph/vis/dot
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/list
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/dotgraph
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/util/set
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/vmInterface/classLoader
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/vmInterface/classLoader/jikesrvm
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/vmInterface/services
	${RVM_ROOT}/rvm/src/vm/compilers/optimizing/vmInterface

	# architecture-specific components
	#
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/ir/instruction
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/ir/instruction/operand
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/ir/conversions/lir2mir
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/ir/conversions/mir2mc
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/regalloc
	${RVM_ROOT}/rvm/src/vm/arch/${ARCH_DIR}/compilers/optimizing/vmInterface/services
EOF
    fi

    # Adaptive compiler components.
    #
    if (( RVM_WITH_ADAPTIVE_SYSTEM )); then
	cleanFileList <<- EOF
	${RVM_ROOT}/rvm/src/vm/adaptive/controller
	${RVM_ROOT}/rvm/src/vm/adaptive/recompilation
	${RVM_ROOT}/rvm/src/vm/adaptive/runtimeMeasurements
	${RVM_ROOT}/rvm/src/vm/adaptive/runtimeMeasurements/listeners
	${RVM_ROOT}/rvm/src/vm/adaptive/runtimeMeasurements/organizers
	${RVM_ROOT}/rvm/src/vm/adaptive/database
	${RVM_ROOT}/rvm/src/vm/adaptive/database/methodSamples
	${RVM_ROOT}/rvm/src/vm/adaptive/database/callGraph
	${RVM_ROOT}/rvm/src/vm/adaptive/recompilation/instrumentation
	${RVM_ROOT}/rvm/src/vm/adaptive/runtimeMeasurements/instrumentation
	${RVM_ROOT}/rvm/src/vm/adaptive/utility
EOF
    fi

    # On stack replacement components.
    #
    if (( RVM_WITH_OSR )); then
	cleanFileList <<- EOF
	$RVM_ROOT/rvm/src/vm/arch/$ARCH_DIR/executionState
	$RVM_ROOT/rvm/src/vm/adaptive/onStackReplacement/optCompilationWithOsr
	$RVM_ROOT/rvm/src/vm/adaptive/onStackReplacement/specialCompilation
	$RVM_ROOT/rvm/src/vm/adaptive/onStackReplacement/util
	$RVM_ROOT/rvm/src/vm/adaptive/onStackReplacement/executionState
	$RVM_ROOT/rvm/src/vm/adaptive/onStackReplacement/threadControls
EOF
    fi

    # architecture specific writebarrier support for baseline compilers
    #
    echo "$RVM_ROOT/rvm/src/vm/arch/$ARCH_DIR/compilers/baseline/writeBarrier"

    # Bootimage compiler components.
    #
    if (( ${RVM_WITH_BASE_BOOTIMAGE_COMPILER} )); then
	echo ${RVM_ROOT}/rvm/src/vm/compilers/harness/bootImage/baseline
    elif (( ${RVM_WITH_OPT_BOOTIMAGE_COMPILER} )); then
	echo ${RVM_ROOT}/rvm/src/vm/compilers/harness/bootImage/optimizing
    fi
    cleanFileList <<- EOF
    # Runtime compiler components.
    #
	${RVM_ROOT}/rvm/src/vm/compilers/harness/runtime

    # Common memory manager components.
    #
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/vmInterface
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/header
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/policy
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/utility
	$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/utility/statistics

    # Local projects (template)
    #
    #    $RVM_ROOT/projects/myproject
EOF
    # collector specific classes
    #
    if (( $RVM_WITH_SEMI_SPACE )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/semiSpace
    elif (( $RVM_WITH_MARK_SWEEP )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/markSweep
    elif (( $RVM_WITH_GEN_COPY )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/genCopy
    elif (( $RVM_WITH_GEN_MS )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/genMS
    elif (( $RVM_WITH_GEN_RC )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/genRC
    elif (( $RVM_WITH_COPY_MS )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/copyMS
    elif (( $RVM_WITH_REF_COUNT )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/refCount
    elif (( $RVM_WITH_GCTRACE )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/gcTrace
    elif (( $RVM_WITH_NO_GC )); then
        echo $RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/plan/noGC
    fi

    # GCSpy specific classes
    GCSPY_ROOT=$RVM_ROOT/rvm/src/vm/memoryManagers/JMTk/gcspy
    echo $GCSPY_ROOT
    echo $GCSPY_ROOT/util
    # TODO Would be better to load only drivers needed rather than all
    echo $GCSPY_ROOT/drivers

    # standard library support
    #
    cat <<EOF
	$RVM_ROOT/rvm/src/vm/libSupport
	$RVM_ROOT/rvm/src/vm/libSupport/java/lang
	$RVM_ROOT/rvm/src/vm/libSupport/java/lang/ref
	$RVM_ROOT/rvm/src/vm/libSupport/java/lang/reflect
	$RVM_ROOT/rvm/src/vm/libSupport/java/net
	$RVM_ROOT/rvm/src/vm/libSupport/java/io
EOF

    # Add support for hardware performance monitors on PowerPC
    #
    if (( $RVM_WITH_HPM )); then
	echo $RVM_ROOT/rvm/src/vm/adaptive/runtimeMeasurements/hardwarePerformanceMonitors
 	echo $RVM_ROOT/rvm/src/vm/HPM
	if (( RVM_FOR_LINUX )); then
	    echo $RVM_ROOT/rvm/src/vm/HPM/intel
	elif (( RVM_FOR_POWERPC )); then
	    echo $RVM_ROOT/rvm/src/vm/HPM/powerPC
	fi
    fi

    # Add the configuration specific directories
    #
    for dir in $CONF_SPECIFIC_SOURCES_LIST; do
        echo $RVM_ROOT/$dir
    done
}


# echo >&2 "before emitBoilerplate def!  JIKES_WARNING_FLAGS=$JIKES_WARNING_FLAGS" #DEBUG


## We only emit the boilerplate inline.
function emitBoilerplate () {
## NEW version:
    cat <<- 'EOF'
	## BEGIN inline Bash boilerplate.
	ME="${0##*/}"			# What is our name?
	set -e
	. ${JAL_ROOT?}/rvm/bin/libjconfigure.bash
	## END inline Bash boilerplate.
EOF
}

function emit_disable_exit_on_error () {
    # This has to be inline or in a source'd file; disabling ERR in 
    # a shell function does not affect the parent's environment.
    # (However, binding the ERR trap in a shell function does 
    # affect the parent's environment, iff ERR was not 
    # already being trapped!  Pretty odd, huh?)
    cat <<- 'EOF'
	## BEGIN disable_exit_on_error.
	set +e
	trap '' ERR 2> /dev/null || :
	## END disable_exit_on_error.
EOF
}

function emit_enable_exit_on_error () {
	echo "enable_exit_on_error;"
}



# Emit script which sets all shell variables relative to the
# shadow and build directory
function emitEnvironmentBash () {
    # read the target environment file
    #
    cat <<- EOF
	#! /bin/bash
	# Note: the above "#! /bin/bash" is there merely as documentation.
	# This file will not be run as a program directly, but rather sourced
	# by other routines.
	
	# This file was generated by jconfigure from the configuration file:
	#      $CURRENT_CONFIG_FILE
	
	# You may edit this file, but
	# all your changes will be lost if jconfigure is executed again
	# with the current directory ($RVM_BUILD) as RVM_BUILD.
	
	# FUNCTION: sets the environment for Bash programs.
	

	if [[ \${RVM_ROOT-UNSET} = UNSET ]]; then
	    export ${ROOT_DIRECTORY_STR1}=${RVM_ROOT}
	else
	    export ${ROOT_DIRECTORY_STR1}=\${RVM_ROOT}
	fi

	if [[ \${RVM_BUILD-UNSET} = UNSET ]]; then
	    export $BUILD_DIRECTORY_STR1=$RVM_BUILD
	else
	    export ${BUILD_DIRECTORY_STR1}=\${RVM_BUILD}
	fi

	
	export HOST_JIKES='$JIKES'		# Deprecated
	export $JIKES_STR1='$JIKES'
	export $HOST_JAVA_STR1='${HOST_VM_RT}'	# Deprecated
	export $HOST_VM_RT_STR1='${HOST_VM_RT}'
	export $HOST_JAVAC_STR1='$HOST_JAVAC'
EOF
    # Javadoc is optional; we won't always have free alternatives installed
    if [[ ${HOST_JAVADOC-} ]]; then
	echo "export $HOST_JAVADOC_STR1='$HOST_JAVADOC'"
    fi
    if [[ ${HOST_TOOLS-} ]]; then
	echo "export $HOST_TOOLS_STR1='$HOST_TOOLS'"
    fi
    if [[ ${HOST_REPOSITORIES-} ]]; then
	echo "export HOST_JAVA_REPOSITORIES='$HOST_REPOSITORIES' #Deprecated"
	echo "export $HOST_REPOSITORIES_STR1='$HOST_REPOSITORIES'"
    fi
    cat <<-EOF
	export HOST_JAR='$JAR'	# Deprecated
	export $JAR_STR1='$JAR'
	export $GNU_MAKE_STR1='$GNU_MAKE'
	
	export $HOST_CC_STR1='$CC'
	export $HOST_CPLUS_STR1='$CPLUS'
	export $HOST_SHLD_STR1='$LDSHARED'
	
	export AWK='$AWK'
	export BASH='$BASH'
EOF
    # We do not need CVS any more; we don't use it any more to check out GNU Classpath.
    [[ ! ${CVS-} ]] || export CVS='$CVS'
cat <<- EOF
	export DIFF='$DIFF'
	export FGREP='$FGREP'
	export FIND='$FIND'
	export GNU_TAR='$GNU_TAR'
	export GREP='$GREP'
	export MD5SUM='$MD5SUM'
	export PS='$PS'
	export SED='$SED'
	export WGET='$WGET'
	export XARGS='$XARGS'
	export UNZIP_CMD='$UNZIP_CMD'
	export CLASSPATH_LIBRARIES=YES
	export HOST_VM_TYPE='${HOST_VM_TYPE}'
	# JIKES_WARNING_FLAGS is read by the inferior program fake-javac.
	export JIKES_WARNING_FLAGS='${JIKES_WARNING_FLAGS}'

EOF
    [[ ${HOST_JAVA_HOME-} ]] && echo "export $HOST_JAVA_HOME_STR1='$HOST_JAVA_HOME'"
    if [ "${HOST_JAVA_LD_LIBRARY_PATH-}" ]; then
	cat <<- EOF
	[[ \${LD_LIBRARY_PATH-} ]] && LD_LIBRARY_PATH=:\${LD_LIBRARY_PATH}
	export LD_LIBRARY_PATH="${HOST_JAVA_LD_LIBRARY_PATH}\${LD_LIBRARY_PATH-}"
EOF
    fi

    [[ ! ${CPP-} ]] || echo "export $HOST_CPP_STR1='$CPP'"
    [[ ! ${FASTJAR-} ]] || echo "export FASTJAR='$FASTJAR'"
    [[ ! ${BISON-} ]] || echo "export BISON='$BISON'"  
    [[ ! ${ANT_CMD-} ]] || echo "export ANT_CMD='$ANT_CMD'"
    echo ""
    [[ ! ${ECLIPSE_INSTALL_DIR-} ]] || echo "export ECLIPSE_INSTALL_DIR='$ECLIPSE_INSTALL_DIR'"
    echo ""
    [[ ! ${CLASSPATH_ROOT-} ]] || echo "export CLASSPATH_ROOT=$CLASSPATH_ROOT"
    [[ ! ${CLASSPATH_INSTALLATION-} ]] || echo "export CLASSPATH_INSTALLATION=$CLASSPATH_INSTALLATION"	# XXX Experimental
    echo ""
    # For self-booting with Jikes RVM (work in progress)
    [[ ! ${DONOR_RVM_ROOT-} ]] || echo "export DONOR_RVM_ROOT=$DONOR_RVM_ROOT"
    [[ ! ${DONOR_RVM_BUILD-} ]] || echo "export DONOR_RVM_BUILD=$DONOR_RVM_BUILD"
    echo ""
}

#
# Emit Makefile
# 
function emitMakefile () {
    cat <<- EOF
	# -*-makefile-*-
	# environment specific make rules
	
	# This file is generated by jconfigure.  You may edit this file, but
	# all your changes will be lost if jconfigure is executed again using
	# the current directory as RVM_BUILD.
	
	# This file was generated from the configuration file:
	#      ${CURRENT_CONFIG_FILE}

	ifdef RVM_ROOT
	    ${ROOT_DIRECTORY_STR1}:=\${RVM_ROOT}
	else
	    ${ROOT_DIRECTORY_STR1}:=${RVM_ROOT}
	endif

        include $ROOT_DIRECTORY_STR/rvm/Make.rules.generic

	ifdef RVM_BUILD
	    ${BUILD_DIRECTORY_STR1}:=\${RVM_BUILD}
	else
	    ${BUILD_DIRECTORY_STR1}:=${RVM_BUILD}
	endif
	
	HOST_JIKES = $JIKES	# Deprecated
	$JIKES_STR1 = $JIKES
EOF
	
    # The configuration for building the user guide.
    # You may have to edit this file.
    [[ ! ${USER_GUIDE_CONFIG-} ]] || echo "USER_GUIDE_CONFIG := ${RVM_ROOT}/rvm/doc/userguide/config.mk"

    if (( RVM_FOR_32_ADDR )); then
	echo "RVM_FOR_32_ADDR := 1"
	echo "ADDRESS_SIZE := 32"
    elif (( RVM_FOR_64_ADDR )); then
	echo "RVM_FOR_64_ADDR := 1"
	echo "ADDRESS_SIZE := 64"
    else
	croak_nonusage "The configuration must specify one of RVM_FOR_32_ADDR or RVM_FOR_64_ADDR; it does not."
    fi
	

    [[ ! ${HOST_JAVA_HOME-} ]] || echo "HOST_JAVA_HOME = $HOST_JAVA_HOME"
    [[ ! ${DO_NOT_RUN_JAVAH-} ]] || echo "DO_NOT_RUN_JAVAH = $DO_NOT_RUN_JAVAH"
    [[ ! ${HOST_TOOLS-} ]] || echo "HOST_TOOLS = $HOST_TOOLS"
    [[ ! ${HOST_JAVADOC-} ]] || echo "HOST_JAVADOC := $HOST_JAVADOC"

    if [[ ${TemplateExpander_HOST_VM_RT-} ]]; then
	echo "# Experimental!"
	echo "TemplateExpander_HOST_VM_RT := ${TemplateExpander_HOST_VM_RT-}"
    fi

    cat <<- EOF
	HOST_JAVA = ${HOST_VM_RT}		# Deprecated
	HOST_VM_RT = ${HOST_VM_RT}
	HOST_VM_TYPE := ${HOST_VM_TYPE}
	HOST_JAVAC = $HOST_JAVAC
	HOST_JAR := ${JAR}	# Deprecated
	JAR = $JAR
	HOST_JAVA_REPOSITORIES = $HOST_REPOSITORIES # Deprecated
	HOST_REPOSITORIES = $HOST_REPOSITORIES
	
	CC = $CC
	CPLUS = $CPLUS
	CXX = $CPLUS
	LDSHARED = $LDSHARED
	
	AWK = $AWK
	BASH = $BASH
EOF
    [[ ! ${CVS-} ]] || echo "CVS = ${CVS}"
    cat <<- EOF
	DIFF = $DIFF
	FGREP = $FGREP
	FIND = $FIND
	GNU_TAR = $GNU_TAR
	GREP = $GREP
	MD5SUM = $MD5SUM
	PS= $PS
	SED = $SED
	WGET = $WGET
	XARGS = $XARGS
	UNZIP_CMD = $UNZIP_CMD


	JIKES_WARNING_FLAGS = ${JIKES_WARNING_FLAGS}
	CLASSPATH_LIBRARIES = YES
	EOF
    [[ ! ${BISON-} ]] || echo "BISON = '$BISON'"  
    [[ ! ${FASTJAR-} ]] || echo "FASTJAR = '$FASTJAR'"  
    [[ ! ${BENCHMARK_ROOT-} ]] || echo "BENCHMARK_ROOT = $BENCHMARK_ROOT"
    [[ ! ${DONOR_RVM_ROOT-} ]] || echo "DONOR_RVM_ROOT = $DONOR_RVM_ROOT"
    [[ ! ${DONOR_RVM_BUILD-} ]] || echo "DONOR_RVM_BUILD = $DONOR_RVM_BUILD"
}


# Emit a script to run each phase of vm builder in turn.

function emitController () {
    cat <<- EOF
	#! ${HOST_BASH}


	if [[ \${RVM_ROOT-UNSET} = UNSET ]]; then
	    export ${ROOT_DIRECTORY_STR1}=${RVM_ROOT}
	else
	    export ${ROOT_DIRECTORY_STR1}=\${RVM_ROOT}
	fi
    $(emitBoilerplate)
	# Run all phases of vm builder.

	# timeit() \$1: The command to run
	#	   \$2: That command's arguments.

	# The old (until 2003 June) KSH script displayed
	# seconds of precision to three decimal places.  The
	# SECONDS variable in my version of Bash only returns
	# integers.

	function timeit () {
	    # We can either do some modifications to the output
	    # format, and use TIMEFORMAT instead of SECONDS...
	    # TIMEFORMAT="%3lR"
	    # time "\$@"		
	    # ...Or we can just deal.with integer seconds.  Since the SECONDS
	    # variable is cumulative, it is compatible with the way we used to
	    # do this.

	    # The --via-RUN-BUILD-COPY flag adds text to one of the 
	    # error messages and makes sure we do not run the remote command
	    # with \$TRACE, \$VFLAG, and \$XFLAG
	    declare -i via_RUN_BUILD_COPY=0
	    if [[ \$1 = --via-RUN-BUILD-COPY ]]; then
		let ++via_RUN_BUILD_COPY
		shift
	    fi	
	    # Disable exit-on-error; inside "timeit", we can get a better
	    # exit message than the default one.
    $(emit_disable_exit_on_error)
	    local cmd="\$1"
	    shift
	    if (( via_RUN_BUILD_COPY )); then
	        "\${cmd}" "\$@"
	    else
	        "\${cmd}" \$TRACE_FLAG \$VFLAG \$XFLAG "\$@"
	    fi
	    local status=\$?
    $(emit_enable_exit_on_error)
	    echo "\$SECONDS s"
	    if (( status == $Exit_Status_Run_Linker )); then
		show_mesg >&2 "You need to run the linker on the appropriate platform."
		trap '' EXIT
		exit $Exit_Status_Run_Linker
	    elif (( status != 0 )); then
		if (( via_RUN_BUILD_COPY )); then
		    show_mesg >&2 "Possible difficulty with the remote command specified in RUN_BUILD_COPY:"
		fi
	        show_mesg >&2 "Trouble while running \"\$cmd \$*\" (exit status \$status); aborting execution"
	        trap '' EXIT
	        exit \$status;
	    fi
	    return \$status;	# will always return 0
	}

	DEMOGRAPHICS_FLAG="" RECOMPILE_FLAG="" NOLINK_FLAG="" BOOTER_FLAG="" NOBOOTER_FLAG=""
	while (( \$# > 0 )); do
	    arg="\$1"
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	       VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	       XFLAG=-x
	    elif [[ \$arg = -demographics ]]; then
	        DEMOGRAPHICS_FLAG=-demographics
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    elif [[ \$arg = -recompile ]]; then
	        RECOMPILE_FLAG=-recompile
	    elif [[ \$arg = -nolink ]]; then
	        NOLINK_FLAG=-nolink
	    elif [[ \$arg = -nobooter ]]; then
	        NOBOOTER_FLAG=-nobooter
	    elif [[ \$arg = -booter ]]; then
	        NOLINK_FLAG=-nolink
	        BOOTER_FLAG=-booter
	    else
	        echo >&2 \
	"Usage: \$ME [-trace[=<trace-opts>]] [-v] [-x] [-demographics] 
	          [-clean] [-recompile] [-nolink] [-nobooter] [-booter]

	   -trace: As if \"-trace=most\".  Some debugging information.
	
	   -trace=make:  Make is no longer run with --silent.  Make is run
	      with the -w option, which generates additional output useful for 
	      GNU Emacs's M-x compile mode.
	
	   -trace=ant:  Ant is no longer run with -quiet.
	
	   -trace=preprocessor: Follow the process of running the preprocessor 
	      on Java source code
	
	   -trace=BootImageWriter: Makes the Boot Image Writer send out lots of
	      information -- about 9420 lines in a BaseBaseCopyMS build.
	      (That is why "-trace" does not imply "-trace=BootImageWriter".)
	
	   -trace=jbuild:  Higher-level info as the build progresses.
	
	   -trace=most:   Same as -trace=all,no-BootImageWriter
	
	   -trace=all:   Everything.
	
	   "
	        echo >&2 \
       "   -v, -x: Turn on the -v and/or -x debugging flags in the subshells we spawn.
	   -nobooter: avoid building the booter (when, for example, running on
	      the AIX side of an AIX/Linux cross-compilation)

	   -booter:  Build only the booter (when, for example, running on
	      the Linux side of an AIX cross-build to Linux)

	   -nolink:  Avoid unnecessarily rebuilding the bootimage (when, 
	      for example, you have only modified classes that are dynamically 
	      loaded and which are not part of the bootimage)

	   -recompile:  Force recompilation of all classes (when, for example, 
	      you have modified a global constant or have added/removed
	      fields/methods from a class)

	   -clean:  Restore the build directory to its original unbuilt state

	There may be additional useful information not in this message
	that you can get by running \"jconfigure -help\"."

	        trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done

	[[ ! \${RVM_BUILD-} ]] || cd \$RVM_BUILD
	
	if [[ \$BOOTER_FLAG = -booter ]]; then
	  . ./environment.target
	else
	  . ./environment.host
	fi

	
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG

	# Copy the GNU Classpath JAR file:
	#
	# Copy over rvmrt.jar; we need that to get a working compiler
	# (at least when we're operating in open-source mode, under the 
	# Jikes compiler, which doesn't have a default bootclasspath)
EOF
    if [[ ${CLASSPATH_INSTALLATION-} ]]; then
	cat <<- EOF
	# Experimental; use a built GNU Classpath that was installed
	# with "make install".
	SRC=${CLASSPATH_INSTALLATION}/share/classpath/glibj.zip
EOF
    else
	## The classic, stable, documented, and recommended way
	cat <<- EOF
	# Ensure that we have the right version of the class libraries
	$ROOT_DIRECTORY_STR/rvm/bin/jBuildClasspathJar --check

	CPS="${HOST_CLASSPATH_ROOT-$RVM_ROOT/classpath}"
	SYSTEM_TYPE=\$(\${CPS}/classpath/config.guess)
	SRC=\$CPS/\$SYSTEM_TYPE/lib/glibj.zip
EOF
    fi
    cat <<- EOF
	DEST=${CLASSES_DIRECTORY_STR}/rvmrt.jar
	copyIfNewer "\$SRC" "\$DEST" -n "(classpath.jar copied) "
EOF
	
    cat <<- EOF
	if [[ \$CLEAN_FLAG = -clean ]]; then
	    rm -rf $TOOL_DIRECTORY_STR
	    timeit ./jbuild.expand      -clean
	    timeit ./jbuild.copy        -clean
	    timeit ./jbuild.compile     -clean
	    timeit ./jbuild.interfaceDeclarations     -clean
	    timeit ./jbuild.linkImage   \$DEMOGRAPHICS_FLAG -clean
	    timeit ./jbuild.linkBooter  -clean
	    trap '' EXIT
	    exit 0
	fi

	if [[ \$RECOMPILE_FLAG = -recompile ]]; then
	    timeit ./jbuild.compile -clean
	fi

	if [[ -e $CLEANSE_STATUS_STR ]]; then
	    rm -rf $TOOL_DIRECTORY_STR
	    timeit ./jbuild.expand     -clean
	    timeit ./jbuild.copy       -clean
	    timeit ./jbuild.compile    -clean
	    timeit ./jbuild.interfaceDeclarations    -clean
	    timeit ./jbuild.linkImage  \$DEMOGRAPHICS_FLAG -clean
	    timeit ./jbuild.linkBooter -clean
	    rm -f $CLEANSE_STATUS_STR
	elif [[ \$NOLINK_FLAG != -nolink ]]; then
	    timeit ./jbuild.interfaceDeclarations    -clean
	    timeit ./jbuild.linkImage  \$DEMOGRAPHICS_FLAG -clean
	    timeit ./jbuild.linkBooter -clean
	fi

	if [[ \$BOOTER_FLAG = -booter ]]; then
	    # Instead of running "jbuild.linkBooter", we can optionally
	    # run a command specified
	    # in the environment variable RUN_BUILD_COPY.
	    #
	    # For example, this variable could use rsh or ssh 
	    # to run the linkBooter command remotely on the target machine.
	    if [[ \${RUN_BUILD_COPY-} ]]; then
	         timeit --via-RUN-BUILD-COPY \$RUN_BUILD_COPY
	    else
	         timeit ./jbuild.linkBooter
	    fi
	else
	    timeit ./jbuild.expand 
	    timeit ./jbuild.copy   
	    timeit ./jbuild.compile
	    if [[ \$NOLINK_FLAG != -nolink ]]; then
		timeit ./jbuild.interfaceDeclarations
	        timeit ./jbuild.linkImage  \$DEMOGRAPHICS_FLAG
	        if [[ \$NOBOOTER_FLAG != -nobooter ]]; then
		    if [[ \${RUN_BUILD_COPY-} ]]; then
			timeit --via-RUN-BUILD-COPY \$RUN_BUILD_COPY
		    else
			timeit  ./jbuild.linkBooter
		    fi
		fi
	    fi
	fi
	
	if [[ -x JikesRVM ]] && [[ -f JikesRVM ]]; then
	    show_mesg "To execute the $CONFIGURATION_NAME RVM (from any directory) type:"
	    echo "\${ME}:    rvm <vm-args> classname <application-args>"
	    if ! type -p rvm > /dev/null; then
	        show_mesg "You will also need to add ${RVM_ROOT}/rvm/bin to your path"
	    fi
	fi
	trap '' EXIT
	EOF
}


# echo >&2  "HERE I AM! emitExpander" # DBG
# Emit script to generate VM source tree Java files that derive from templates.
# Taken:    .template files in source tree
# Returned: .java files in ${GENERATED_FILES_DIRECTORY}
#
function emitExpander () {
    cat <<- EOF
	#! ${HOST_BASH}
	# Generate VM sources that derive from templates.

	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	
	. ./environment.host
    $(emitBoilerplate)


	# Process command-line args   
	while (( \$# > 0 )); do
	    arg="\$1"
	    [[ \$arg != --?* ]] || arg=\${arg#-}
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	        VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "\$ME: Unknown argument: \$arg"
		trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done
	if tracing make; then
	    MFLAGS=-w
	fi

	echo -n "\${ME}: "

	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG
	if [[ \$CLEAN_FLAG ]]; then
	    rm -rf ${SCRATCH_DIRECTORY_STR}
	    mkdir -p ${SCRATCH_DIRECTORY_STR}/com/ibm/JikesRVM
	    cd ${GENERATED_FILES_DIRECTORY_STR}
	    echo *.* | \$XARGS rm -f
	EOF
    #if (( RVM_WITH_GCSPY )); then
	cat <<- EOF
            mkdir -p ${SCRATCH_DIRECTORY_STR}/org/mmtk/vm/gcspy
	EOF
    #fi
    if (( RVM_WITH_OPT_COMPILER )); then
	cat <<- EOF
	    cd ${GENERATED_FILES_DIRECTORY_STR}/instructionFormats
	    echo *.* | \$XARGS rm -f
	EOF
    fi
    cat <<- EOF

	    echo -n "(templates cleaned) "

	    trap '' EXIT
	    exit 0
	fi

	# Make the tools that we need to do template expansion
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C "${ROOT_DIRECTORY_STR}/rvm/src/tools/templateExpander" tool SCRATCH_DIR="${SCRATCH_DIRECTORY_STR}"
EOF
    if (( RVM_WITH_OPT_COMPILER )); then
	cat <<- EOF

	# Opt compiler only:
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -f ${ROOT_DIRECTORY_STR}/rvm/src/tools/jburg/Makefile -C ${SCRATCH_DIRECTORY_STR} VPATH=${ROOT_DIRECTORY_STR}/rvm/src/tools/jburg tool
	EOF
    fi
    cat <<- EOF

	# Build the command line options for the core VM
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/utility MakeTemplates GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
    
	# Build the command line options for JMTk
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/memoryManagers/JMTk/utility MakeTemplates GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
EOF

    if (( RVM_FOR_IA32 )); then
	cat <<- EOF

	# Build VM_Assembler on Intel
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/arch/intel/assembler GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR}
EOF
	if (( RVM_WITH_OPT_COMPILER )); then
	echo "\
run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/arch/intel/compilers/optimizing/ir/conversions/mir2mc GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR}"
	fi
    fi
    cat <<- EOF

	# Do the expansion
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/classLoader MakeTemplates GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR}
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/compilers/baseline MakeTemplates GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
EOF

    if (( RVM_WITH_OPT_COMPILER )); then
	cat <<- EOF
		# (OPT Compiler only:)
		run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/compilers/optimizing MakeTemplates ARCH_DIR=${ARCH_DIR} GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
EOF
	if (( RVM_WITH_EXTREME_ASSERTIONS )); then
	    cat <<- EOF
		# (OPT Compiler with extreme assertions only:)
		run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/compilers/optimizing/ir/instruction fatalInstructionFormat ARCH_DIR=${ARCH_DIR} GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
EOF
	fi
    fi
    if (( RVM_WITH_ADAPTIVE_SYSTEM )); then
	cat <<- EOF
		# (Adaptive system only)
		run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/vm/adaptive MakeTemplates GEN_FILES_DIR=${GENERATED_FILES_DIRECTORY_STR} SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
EOF
    fi
    cat <<EOF

trap "" EXIT
EOF
}
# echo >&2  "HERE I WAS! emitExpander" # DBG


# Emit script to copy/preprocess VM Java files from source tree to 
# build directory.
# Taken:    .java files in source tree
# Returned: .java files in build directory
#
# echo >&2  "HERE I AM! emitCopier" # DBG
function emitCopier () {
    cat <<- EOF
	#! ${HOST_BASH}
	# Copy or preprocess VM Java files from the source tree to 
	# the build directory.
	# Taken:    .java files in the source tree
	# Returned: .java files in the build directory

	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	. ./environment.host
	
    $(emitBoilerplate)
	

	# Process command-line args   
	while (( \$# > 0 )); do
	    arg="\$1"
	    if [[ \$arg = -- ]]; then
	        shift		# The end of the flag arguments
	        break;
	    fi
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	        VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "Unknown argument: \$arg"
	        trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done

	if tracing make; then
	    MFLAGS=-w
	fi
	echo -n "\${ME}: "

	if [[ \$CLEAN_FLAG ]]; then
	    if tracing jbuild; then
		open_paren "cleaning sources: nuking generated .java files"
	    else
		open_paren ""
	    fi
	    find ${CLASSES_DIRECTORY_STR} -name "*.java" -exec rm {} \;
	    builtin echo "This file indicates that some or all classes need to be recompiled" > ${CLASSES_INVALID_STR}
	    close_paren "sources cleaned"
	    trap '' EXIT
	    exit 0
	fi
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG
	# Make the preprocessor
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/tools/preprocessor INCLUDED_MAKEFILE=${BUILD_DIRECTORY_STR}/Make.rules.host tool SCRATCH_DIR=${SCRATCH_DIRECTORY_STR}
	copyIfNewer "${SCRATCH_DIRECTORY_STR}/preprocessModifiedFiles" "${BUILD_DIRECTORY_STR}/jbuild.prep.host" -n "(set up jbuild.prep.host) "

	# This may be reset in the loop below.
	FILES_HAVE_CHANGED=0

	# Update from directories containing sources that implement the virtual machine.
	#
	PREPROC_FLAGS="--only-boolean-constants-in-conditions ${PARANOID_PREPROCESSOR_FLAG}"
	if tracing preprocessor; then
	    PREPROC_FLAGS="-trace \$PREPROC_FLAGS"
	fi
	for d in \$(< ${SOURCE_LIST_STR} ); do
	    if tracing preprocessor; then
	         cleanline
	         echo -n "\${ME}: expanding \${d}: "
	    fi
	    shopt -s nullglob
	    # FILES may be empty.
	    FILES="\$(echo \${d}/*.java)"
EOF
    emit_disable_exit_on_error

    ## I abandoned using XARGS with jbuild.prep.host, because xargs will
    ## exit with status 123 upon nonzero exit status from jbuild.prep.host,
    ## but jbuild.prep.host will exit with status 1 when files are modified.
    ##
    ## So, all the non-zero return values get mapped to 123, but we
    ## want to distinguish 1 (some files changed) 
    ## from other non-zero return values (trouble).

    cat <<- EOF
	    if [[ ! \$FILES ]]; then
	        continue;
	    fi
EOF
    # The odd code below with $(echo  ...) is because 
    # we need to turn the PREPROCESSOR_DEFINITIONS from a 
    # newline-separated list to a space-separated list.
    cat <<- EOF
	    ${BUILD_DIRECTORY_STR}/jbuild.prep.host \${PREPROC_FLAGS} $(echo ${PREPROCESSOR_DEFINITIONS}) ${CLASSES_DIRECTORY_STR} \$FILES 
	    status=\$?
	    $(emit_enable_exit_on_error)
	    if (( status == 1 )); then
		FILES_HAVE_CHANGED=1
	    elif (( status != 0 )); then
		show_mesg >&2 "Trouble while running jbuild.prep.host (exit status \${status}).  Aborting execution."
		trap "" EXIT
		exit \$status
	    fi
	done


	# Update from directories containing machine generated source files.
	# Do this after we copy the "normal" files to allow us to
	# overwrite any dummy versions of the files we have sitting
	# around in the source tree.
	if tracing preprocessor; then
	    cleanline
	    echo -n "\${ME}: expanding ${GENERATED_FILES_DIRECTORY_STR}: "
	fi

	FILES=\$(\${FIND} ${GENERATED_FILES_DIRECTORY_STR}/ -name "*.java")
	$(emit_disable_exit_on_error)
	${BUILD_DIRECTORY_STR}/jbuild.prep.host \${PREPROC_FLAGS} $(echo ${PREPROCESSOR_DEFINITIONS}) ${CLASSES_DIRECTORY_STR} \${FILES}
	status=\$?
	$(emit_enable_exit_on_error)

	if [[ \${status} = 1 ]]; then
	    FILES_HAVE_CHANGED=1
	elif [[ \${status} != 0 ]]; then
	    show_mesg >&2 "Trouble while running jbuild.prep.host (exit status \${status}); aborting execution."
	    trap '' EXIT
	    exit \${status}
	fi

	if tracing preprocessor; then
	    cleanline
	    echo "\${ME}: All files expanded"
	fi
EOF


    cat <<- EOF
	# Remember if any new (or modified) source files were discovered.
	#
	if [[ \${FILES_HAVE_CHANGED} = 1 ]]; then
	    touch ${CLASSES_INVALID_STR}
	fi
	trap "" EXIT
EOF
}
    

# Emit script to generate VM class files from Java files.
# Taken:    .java files in build directory 
#            CLASSES_INVALID
# Returned: .class files in build directory
#
# echo >&2  "HERE I AM! emitCompiler" # DBG

function emitCompiler () {
#  echo >&2 "In emitCompiler!  JIKES_WARNING_FLAGS=$JIKES_WARNING_FLAGS" #DEBUG

    cat <<- EOF
	#! ${HOST_BASH}
	# Generate VM class files from Java files.
	# Taken:    .java files in build directory 
	#            CLASSES_INVALID
	# Returned: .class files in build directory

	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	. ./environment.host
    $(emitBoilerplate)

	while (( \$# > 0 )); do
	    arg="\$1"
	    if [[ \$arg = -- ]]; then
	        shift		# The end of the flag arguments
	        break;
	    fi
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
		TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	        VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "Unknown argument: \$arg"
	        trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done

	echo -n "\${ME}: "
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG

	if [[ \$CLEAN_FLAG ]]; then
	    open_paren 'cleaning .class files'
	    cd ${CLASSES_DIRECTORY_STR}
	    # This avoids any limits on the size of the command-line arguments.
	    # 'echo' is a bash builtin, and as such is unaffected by such O/S 
	    # limits. 
	    echo *.class | \$XARGS rm -f
	    touch ${CLASSES_INVALID_STR} 
	    close_paren "classes cleaned "
	    trap "" EXIT
	    exit 0
	fi
EOF
    # Generate classes
    #
    TOP_LEVEL_SOURCES="Dummy.java"
    if (( RVM_WITH_OPT_COMPILER )); then
	TOP_LEVEL_SOURCES="${TOP_LEVEL_SOURCES} OptDummy.java"
    fi
    if (( RVM_WITH_OPT_TEST_HARNESS )); then
	TOP_LEVEL_SOURCES="${TOP_LEVEL_SOURCES} OptDummy.java OptTestHarness.java"
    fi
    TOP_LEVEL_SOURCES="${TOP_LEVEL_SOURCES} ${CONF_SPECIFIC_TOP_LEVEL_SOURCES}"
    TOP_LEVEL_CLASSES="$(builtin echo ${TOP_LEVEL_SOURCES}| sed 's@\.java@.class@g')"

    cat <<- EOF
	if [[ -e $CLASSES_INVALID_STR ]]; then
	    chdir $CLASSES_DIRECTORY_STR
	    run rm -f $TOP_LEVEL_CLASSES
	    jikes_invocation="$JIKES_STR $JIKES_WARNING_FLAGS -g +U -classpath .:rvmrt.jar $TOP_LEVEL_SOURCES"
	    open_paren 'compiling classes'
	    if tracing jbuild || tracing make || tracing; then
	        cleanline
	        echo "  "\${jikes_invocation}
	    fi
	    if \${jikes_invocation}; then
	        close_paren 'classes compiled'
	    else
	        status=\$?
	        close_paren 'compilation FAILED'
	        echo >&2 "\$ME: The Jikes compiler exited with status \${status} while we were building the source file(s): $TOP_LEVEL_SOURCES"
	        echo >&2 "\$ME: We invoked the Jikes compiler in the directory $CLASSES_DIRECTORY_STR"
	        echo >&2 "\$ME: With the command-line: \$jikes_invocation"
	        exit \$status
	    fi

	    open_paren 'building jksvm.jar'
	    rm -f jksvm.jar
	    ## NB: "fastjar", the open-source program, has a broken -u flag,
	    ## at least temporarily.  However, it DOES have a very nice @ flag,
	    ## which the Sun-derived JDKs lack.
	    if [[ \${FASTJAR-} ]]; then
 	        \$FIND . -name '*.class' | \$FASTJAR -c0@f jksvm.jar
	    else
	        ## The Sun JAR manual page claims that '-O' (the letter Oh) 
	        ## is the flag for no-compression.  It is actually
	        ## '0' (the number zero), not the letter 'O'.
	        $JAR_STR -c0f jksvm.jar Dummy.class
	        \$FIND . -name '*.class' | \$XARGS $JAR_STR -u0f jksvm.jar
	    fi
	    close_paren 'jksvm.jar built'

	    open_paren 'building jksvmsrc.jar'
	    run rm -f jksvmsrc.jar
	    if [[ \${FASTJAR-} ]]; then
 	        \$FIND . -name '*.java' | \$FASTJAR -c0@f jksvmsrc.jar
	    else
	        run $JAR_STR -c0f jksvmsrc.jar Dummy.java
	        ## -r is XARGS's no-run-if-empty flag.
	        \$FIND . -name '*.java' | run \$XARGS $JAR_STR -u0f jksvmsrc.jar
	    fi
	    close_paren 'jksvmsrc.jar built'

	else
	    if tracing jbuild; then
	        echo -n "(nothing needed to be compiled) "
	    fi
	fi
	rm -f $CLASSES_INVALID_STR

	trap '' EXIT
	EOF
}

function emitInterfaceDeclarationsWriter () {
    cat <<- EOF
	#! ${HOST_BASH}
	# Taken:    .class files in build directory
	# Returned:  InterfaceDeclarations.h in build directory
	#

	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	
	. ./environment.host
    $(emitBoilerplate)

	while (( \$# > 0 )); do
	    arg="\$1"
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	       VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	       XFLAG=-x
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "Unknown argument: \$arg"
	        trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done

	echo -n "\${ME}: "
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG
	if tracing make; then
	    MFLAGS=-w
	fi
EOF
    ## List of the classes that make 
    ## up the program GenerateInterfaceDeclarations.  
    ## Keep these in brace-expansion-format 

    ## Brace expansion precedes variable expansion, so we'll have to
    ## expand this variable at the time of emitting the script, rather
    ## than at run time.
    generator_classes="{GenerateInterfaceDeclarations,AlternateRealityClassLoader,Emitters,IntEmitter,DoubleEmitter,FieldReader,OffsetEmitter,OffsetReader,Shared,Util}"
    cat <<-EOF
	declare -r interface=$SCRATCH_DIRECTORY_STR/InterfaceDeclarations.h

	function clean_InterfaceDeclarations() {
	    eval rm -f $SCRATCH_DIRECTORY_STR/${generator_classes}.java
	    eval rm -f $SCRATCH_DIRECTORY_STR/${generator_classes}.class
	    rm -f \$interface
	    echo >&2 -n "(interface cleaned) " 
	    
	}

	if [[ \$CLEAN_FLAG ]]; then
	    clean_InterfaceDeclarations;
	    trap "" EXIT
	    exit 0
	fi

	## Where are our sources?
	generator_class="GenerateInterfaceDeclarations"
	old_generator_dir=${BOOTIMAGE_RUNNER_DIR_STR}
	# The new_generator_dir is scaffolding for a work-in-progress
	# feature --Steve Augart, 26 May 2004

	new_generator_dir=${ROOT_DIRECTORY_STR}/rvm/src/tools/generateInterfaceDeclarations
	if [[ \${INTERFACE_GENERATOR_DIR-} ]]; then
	    generator_dir=\${INTERFACE_GENERATOR_DIR}
	elif [[ -f \$new_generator_dir/\${generator_class}.java ]]; then
	    generator_dir=\$new_generator_dir
	elif [[ -d \$old_generator_dir ]]; then
	    generator_dir=\$old_generator_dir
	fi

	# Preprocess and copy the java source files for the Generator.
	#

	PREPROC_FLAGS="--only-boolean-constants-in-conditions ${PARANOID_PREPROCESSOR_FLAG}"
	if tracing preprocessor; then
	    cleanline >&2
	    echo >&2 -n "\$ME: \${generator_dir}"/
	fi
	
	cd \${generator_dir}
	generator_sources=\$(for file in ${generator_classes}.java; do [[ ! -f \$file ]] || echo \$file; done)

 	run $BUILD_DIRECTORY_STR/jbuild.prep.host \
 		--disable-modification-exit-status \$PREPROC_FLAGS \
 		$(echo $PREPROCESSOR_DEFINITIONS) \
 		$SCRATCH_DIRECTORY_STR  \
		\${generator_sources}

	#
	# compile GenerateInterfaceDeclarations.java and its support files.
	#

	## We don't put it into its own package because right now
	## the VM thinks that it owns all of
	## the com.ibm.JikesRVM namespace, and gets upset if someone wants
	## to load applications using any other class loader.

	# generator_class="com.ibm.JikesRVM.GenerateInterfaceDeclarations.GenerateInterfaceDeclarations"
	# generator_source_file=com/ibm/JikesRVM/GenerateInterfaceDeclarations/GenerateInterfaceDeclarations.java
	generator_class="GenerateInterfaceDeclarations"
# 	generator_source_file="\${generator_class//./'/'}.java"
# 	# generator_source_file="GenerateInterfaceDeclarations.java"
# 	generator_prefix="\$(dirname \$generator_source_file)"

	chdir $SCRATCH_DIRECTORY_STR
	cp=.:$CLASSES_DIRECTORY_STR:$CLASSES_DIRECTORY_STR/rvmrt.jar

	eval run $HOST_JAVAC_STR $JAVAC_WARNING_FLAGS -g \
	  -classpath \$cp \
	  -bootclasspath \$cp \
	   \${generator_sources}

# 	eval run $HOST_JAVAC_STR $JAVAC_WARNING_FLAGS -g \
# 	  -classpath \$cp \
# 	  -bootclasspath \$cp \
# 	   \$generator_prefix/${generator_classes}.java

	#
	# generate InterfaceDeclarations.h
	#
	rm -f \$interface
	declare -a args=( -Xmx200M \
	   -classpath \$cp		\
	   \${generator_class} \
	   -ia $BOOTIMAGE_LOAD_ADDRESS \
	   -out \$interface )
	if [[ \$HOST_VM_TYPE == "JikesRVM" ]]; then
#	    args=("-X:vmClasses=.:\$DONOR_RVM_BUILD/RVM.classes/jksvm.jar:\$DONOR_RVM_BUILD/RVM.classes/rvmrt.jar" "\${args[@]}")
	    args=("\${args[@]}" -alternateRealityClasspath  "\$cp" )
	    args=("\${args[@]}" -alternateRealityNativeLibDir  \
					"$BUILD_DIRECTORY_STR" )
	fi
	run $HOST_VM_RT_STR "\${args[@]}"
	echo -n '(wrote interface) '
	trap '' EXIT
EOF
}

# echo >&2  "HERE I AM! emitImageLinker" # DBG
function emitImageLinker () {
    cat <<- EOF
	#! ${HOST_BASH}
	# Generate the VM bootimage.
	# Taken:    .class files in build directory
	# Returned: PRIMORDIAL_CLASSES and bootimage in build directory
	#
	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	. ./environment.host
    $(emitBoilerplate)

	# Process command-line args
	DEMOGRAPHICS_FLAG=""
	while (( \$# > 0 )); do
	    arg="\$1"
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	       VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	       XFLAG=-x
	    elif [[ \$arg = -demographics ]]; then
	        DEMOGRAPHICS_FLAG=-demographics
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "Unknown argument: \$arg"
	        trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done
	
	echo -n "\${ME}: "
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG
	if tracing make; then
	    MFLAGS=-w
	fi

	function clean_primordials() {
	    rm -f $PRIMORDIAL_CLASSES_STR $EXCLUDED_CLASSES_STR \
			$BOOTIMAGE_STR $BOOTIMAGE_MAP_STR
	    echo -n "(primordials cleaned) "
	    
	}
	function clean_bootimage() {
	    rm -f $SCRATCH_DIRECTORY_STR/BootImage*.java
	    rm -f $SCRATCH_DIRECTORY_STR/BootImage*.class
	    echo >&2 -n "(bootimage cleaned) " 
	}

	if [[ \$CLEAN_FLAG ]]; then
	    clean_primordials;
	    clean_bootimage;
	    trap "" EXIT
	    exit 0
	fi

	clean_bootimage;

	# Generate list of classes to include in the bootimage.
	#
	if [[ ! -e ${PRIMORDIAL_CLASSES_STR} ]]
	then

	# 
	# (1) Generate a list of Excluded classes that we do not want in the bootimage
	#

            cleanFileList > ${EXCLUDED_CLASSES_STR} <<- EOF_EXCLUDED_CLASSES
	# skip: needed to build bootimage, but not to run it
	    BootImageInterface.class
	    Dummy.class
	    OptDummy.class
	    BuildJNIFunctionTable.class

	# skip: JikesRVMSocketImpl; do not load native libs unless needed
	    JikesRVMSocketImpl.class

	# We can not carry these from bootimage writing to runtime 
	# without special treatment
	    java/lang/ref/PhantomReference.class
	    java/lang/ref/SoftReference.class
	    java/lang/ref/WeakReference.class
EOF_EXCLUDED_CLASSES
EOF

    # Add any configuration specific exclusions
    for exclusion in ${CONF_SPECIFIC_EXCLUSIONS_LIST}; do
	echo "    builtin echo '${exclusion}'          >> ${EXCLUDED_CLASSES_STR}"
    done

    # 
    # (2) Generate a list of primary classes (non-arrays, non compiler generated (Foo${bar})
    #     classes that will be included in the bootimage unless explicitly excluded.
    
    echo "    cd ${CLASSES_DIRECTORY_STR}"
    
    declare -i save_temps=0	# You might set save_temps=1 when debugging.
    if (( ! save_temps )); then
	echo "CLEANUP='rm -f $PRIMORDIAL_CLASSES_STR.want-these $PRIMORDIAL_CLASSES_STR.want-minus-exclusions $PRIMORDIAL_CLASSES_STR.in-gnu-classpath'"
    fi

    # Start a subshell where the output from a series of commands will go to
    # one output stream.
    echo "("
    # ${FIND}'s action defaults to -print if none is explicitly specified.
    if (( RVM_WITH_ALL_CLASSES )); then
        echo "    \${FIND} . -name '*.class'"
    else
	echo "    \$FIND . -name 'VM*.class'"
	if (( RVM_WITH_ADAPTIVE_SYSTEM )); then
	    echo "    \$FIND ./com/ibm/JikesRVM/opt -name '*.class'"
        fi
	if (( RVM_WITH_OSR )); then
	    echo "    \$FIND ./com/ibm/JikesRVM/OSR -name '*.class'"
        fi
	echo "    \$FIND ./com/ibm/JikesRVM/memoryManagers -name '*.class'"
	echo "    \$FIND ./org/mmtk -name '*.class'"
	echo "    \$FIND . -name JikesRVMSupport.class"
    fi
    echo ") > ${PRIMORDIAL_CLASSES_STR}.want-these"
    cat <<- EOF
cleanFileList >> ${PRIMORDIAL_CLASSES_STR}.want-these << EOF_PRIMORDIAL_CLASSES_STR_1
# VM daemon threads that do not start with VM for historical reasons
com/ibm/JikesRVM/FinalizerThread
com/ibm/JikesRVM/MainThread
com/ibm/JikesRVM/DebuggerThread

# Classes needed for OutOfMemory servicing which we can not afford to load when we are actually out of memory
com/ibm/JikesRVM/PrintLN
com/ibm/JikesRVM/PrintContainer

## Classes involved with the process of class loading...
# fundamental java classes
#
java/lang/Class
java/lang/Object
java/lang/Runtime
java/lang/String
java/lang/StringBuffer
java/util/StringTokenizer
java/lang/System
java/lang/Thread
java/lang/ThreadGroup

java/lang/OutOfMemoryError
java/lang/Cloneable
java/lang/VMObject
java/lang/VMSystem
java/lang/VMString
gnu/classpath/Configuration

    # reflection support
    #
java/lang/reflect/Field
java/lang/reflect/Method
java/lang/reflect/Member
java/lang/reflect/Constructor
java/lang/reflect/AccessibleObject

    # hardware runtime errors
    #
java/lang/ArithmeticException
java/lang/ArrayIndexOutOfBoundsException
java/lang/Exception
java/lang/Error
java/lang/IndexOutOfBoundsException
java/lang/LinkageError
java/lang/NullPointerException
java/lang/RuntimeException
java/lang/SecurityException
java/lang/StackOverflowError
java/lang/Throwable
java/lang/UnknownError
java/lang/VirtualMachineError

    # software runtime errors
    #
java/lang/IncompatibleClassChangeError
java/lang/ClassCastException
java/lang/ArrayStoreException
java/lang/NegativeArraySizeException
java/lang/AbstractMethodError
java/lang/StringIndexOutOfBoundsException
java/lang/UnsatisfiedLinkError
java/lang/InternalError
java/lang/IllegalMonitorStateException
java/lang/ExceptionInInitializerError

    # primitive wrapper types
    #
java/lang/Boolean
java/lang/Byte
java/lang/Character
java/lang/Double
java/lang/Float
java/lang/Integer
java/lang/Long
java/lang/Number
java/lang/Short
java/lang/Void

    # class loading errors
    #
java/io/IOException
java/io/EOFException
java/io/FileNotFoundException
java/lang/ClassNotFoundException
java/lang/ClassFormatError
java/lang/NoClassDefFoundError
java/util/zip/ZipException

    # util datastructures (needed by compilers, classloaders, etc)
    #
java/util/AbstractList
java/util/AbstractMap
java/util/AbstractSet
java/util/ArrayList
java/util/Arrays
java/util/HashMap
java/util/HashSet
java/util/Hashtable
java/util/List
java/util/ListResourceBundle
java/util/PropertyResourceBundle
java/util/MissingResourceException
java/util/Properties
java/util/ResourceBundle
java/util/Vector
java/util/AbstractCollection
java/util/Collections
java/util/Stack
java/util/WeakHashMap

    # class loaders
    #
java/lang/ClassLoader
java/lang/VMClassLoader
java/lang/VMSecurityManager
gnu/java/io/PlatformHelper
java/security/CodeSource
java/security/Policy
java/security/PermissionCollection
java/security/Permissions
java/security/Principal
gnu/java/locale/Calendar
java/lang/reflect/InvocationTargetException

    # ApplicationClassLoader
com/ibm/JikesRVM/classloader/ApplicationClassLoader # Uses URLClassLoader
java/net/URLClassLoader		# Uses java.util.HashMap
java/net/URL			# Used by URLClassLoader's initializer
gnu/java/net/protocol/file/Handler # by java/net/URL

# Not necessary, since we can class load from regular files at the point 
# it's needed, but used while booting, so it should save us time at 
# startup to just include it.
gnu/java/lang/reflect/TypeSignature # Used by ObjectStreamField

    # class loading from regular files
    #
java/io/File
java/io/DataInputStream
java/io/DataOutputStream
java/io/FilterInputStream
java/io/InputStream
java/io/FileInputStream
java/io/FileDescriptor
gnu/java/nio/channels/FileChannelImpl
EOF

	cat <<EOF
    # class loading from zip files
    #
java/util/zip/ZipFile
java/util/zip/ZipFile
java/util/zip/ZipEntry
java/util/zip/Inflater
java/util/zip/InflaterInputStream
java/util/zip/Deflater
java/util/zip/DeflaterOutputStream
java/util/zip/ZipException
java/util/zip/Adler32
java/util/zip/StreamManipulator
java/util/zip/OutputWindow
java/util/zip/InflaterHuffmanTree
java/util/zip/DeflaterHuffman
java/util/zip/InflaterDynHeader
java/io/InputStreamReader
java/io/BufferedReader
java/io/Reader
java/lang/Math
java/io/Serializable
java/util/Calendar
java/util/GregorianCalendar
java/util/Locale
java/util/Date
java/util/TimeZone
java/util/SimpleTimeZone
java/lang/Cloneable
java/security/AccessController
java/security/PrivilegedAction
java/util/PropertyPermission
java/security/BasicPermission
java/security/Permission
java/security/AllPermission
java/security/AllPermissionCollection
java/lang/RuntimePermission
EOF
    
    # the application class loader uses jar classes (which can be loaded or not)

    if (( RVM_WITH_ALL_CLASSES )); then
	cat <<- EOF
java/util/jar/JarException
java/util/jar/JarInputStream
java/util/jar/Attributes
java/util/jar/JarOutputStream
java/util/jar/JarEntry
java/util/jar/JarFile
java/util/jar/Manifest
	EOF

    fi

	cat <<- EOF
java/io/BufferedOutputStream
java/io/BufferedInputStream
java/io/ByteArrayInputStream
java/io/FileOutputStream
java/io/PrintStream
java/io/RandomAccessFile
java/io/ObjectStreamField
EOF
    if (( RVM_WITH_OSR )); then
	cat <<- EOF
	# on stack replacement
com/ibm/JikesRVM/adaptive/OSR_OnStackReplacementTrigger
com/ibm/JikesRVM/adaptive/OSR_OnStackReplacementEvent
com/ibm/JikesRVM/adaptive/OSR_OnStackReplacementPlan
com/ibm/JikesRVM/adaptive/OSR_OrganizerThread
EOF
    fi

	cat <<- EOF
java/io/PrintWriter
java/io/OutputStreamWriter
java/io/InputStreamReader
gnu/java/io/EncodingManager
gnu/java/io/decode/Decoder8859_1
gnu/java/io/decode/Decoder8859_2
gnu/java/io/decode/Decoder8859_3
gnu/java/io/decode/Decoder8859_4
gnu/java/io/decode/Decoder8859_5
gnu/java/io/decode/DecoderEightBitLookup
gnu/java/io/decode/DecoderUTF8
gnu/java/io/encode/Encoder8859_1
gnu/java/io/encode/Encoder8859_2
gnu/java/io/encode/Encoder8859_3
gnu/java/io/encode/Encoder8859_4
gnu/java/io/encode/Encoder8859_5
gnu/java/io/encode/EncoderEightBitLookup
gnu/java/io/encode/EncoderUTF8
java/lang/ref/Reference
java/lang/ref/ReferenceQueue
gnu/java/security/provider/DefaultPolicy
gnu/java/locale/Calendar_en
EOF
    if (( RVM_WITH_OPT_COMPILER )); then
	# data structures that need to carry over from boot image writing
	# and/or classes that opt wants to be in the bootimage to 
	# generate decent code (avoid dynamic linking, get them opt compiled)
	if (( RVM_WITH_OPT_BOOTIMAGE_COMPILER )); then
	cat <<- EOF
java/util/Enumeration
java/util/Dictionary
java/util/TreeMap
java/util/TreeSet
java/util/Stack

com/ibm/JikesRVM/opt/ir/OPT_CallSiteTreeNode
com/ibm/JikesRVM/opt/OPT_FieldAnalysis
com/ibm/JikesRVM/opt/OPT_FieldDatabase
com/ibm/JikesRVM/opt/OPT_SpecializedMethod
com/ibm/JikesRVM/opt/OPT_InvokeeThreadLocalContext
com/ibm/JikesRVM/opt/OPT_SpecializedMethodPool
com/ibm/JikesRVM/opt/OPT_SpecializationDatabase

com/ibm/JikesRVM/opt/OPT_ClassLoadingDependencyManager
com/ibm/JikesRVM/opt/OPT_InvalidationDatabase
com/ibm/JikesRVM/opt/OPT_InterfaceHierarchy
com/ibm/JikesRVM/opt/OPT_SummaryDatabase
com/ibm/JikesRVM/opt/OPT_MethodSummary
EOF
	fi

	if (( RVM_WITH_ADAPTIVE_SYSTEM )); then
	    echo com/ibm/JikesRVM/opt/OPT_ContextFreeInlinePlan
	fi
    fi

    if (( RVM_WITH_HPM )) ; then
	cat << EOF
com/ibm/JikesRVM/HPM_counters
com/ibm/JikesRVM/HPM_info
com/ibm/JikesRVM/Java2HPM
com/ibm/JikesRVM/VM_HardwarePerformanceMonitor
com/ibm/JikesRVM/VM_HardwarePerformanceMonitors
EOF
    fi
    cat <<- EOF
EOF_PRIMORDIAL_CLASSES_STR_1

	    # (3) Now that we have a big file of root classes to include:
	    #     (a) process the exclusions,
	    #     (b) delete all the compiler-generated classes (the ones 
	    #	  that contain dollar signs), and
	    #     (c) convert to internal names.
	    #
	    # At this line, get rid of any lines containing a literal '$'
	    #		delete any initial './' (from find's output)
	    #		delete any trailing .class (also from find)
	    \$FGREP -v -f $EXCLUDED_CLASSES_STR ${PRIMORDIAL_CLASSES_STR}.want-these | ${SED_STR} -e'/\\\$/d' -e 's@^\\./@@' -e 's@\.class\$@@' -e 's@^\\(.*\\)\$@\\1.class\\
\\1\$@' > ${PRIMORDIAL_CLASSES_STR}.want-minus-exclusions
	    $JAR_STR tf rvmrt.jar > $PRIMORDIAL_CLASSES_STR.in-gnu-classpath
	# Nuke leading "./" from the strings "find" prints out.
	    \$FIND . -name '*.class' -print | $SED_STR 's@^\./@@' >> $PRIMORDIAL_CLASSES_STR.in-gnu-classpath
	    > $PRIMORDIAL_CLASSES_STR # Create it clean
#	DEBUGGING -- lets us test for junk in the RVM.primordials file:
#	    echo fi > $PRIMORDIAL_CLASSES_STR
	# Convert from file names ending in .class "java/lang/String.class"
	# into internal form "Ljava/lang/String;"
	    \$FGREP -f $PRIMORDIAL_CLASSES_STR.want-minus-exclusions $PRIMORDIAL_CLASSES_STR.in-gnu-classpath | $SED_STR 's@\(.*\)\.class@L\1;@' >> $PRIMORDIAL_CLASSES_STR
	eval \$CLEANUP		# Remove temp files.
	# 
	# (4) Add Array types.  NOTE: These must be in internal form.
	#
        cleanFileList >> $PRIMORDIAL_CLASSES_STR << 'EOF_PRIMORDIAL_CLASSES_STR'
	[Ljava/util/AbstractSet;
	[Ljava/util/HashSet;
	[Ljava/util/HashMap\$HashEntry;
	[Ljava/util/WeakHashMap\$WeakBucket;
	[Ljava/security/Principal;

	[Ljava/util/zip/ZipEntry;
	[Lcom/ibm/JikesRVM/VM_LockNursery\$VM_LockBucket;
	[Lcom/ibm/JikesRVM/classloader/VM_Atom;
	[Lcom/ibm/JikesRVM/VM_BasicBlock;
	[Lcom/ibm/JikesRVM/classloader/VM_Field;
	[Lcom/ibm/JikesRVM/classloader/VM_Method;
	[Lcom/ibm/JikesRVM/classloader/VM_MemberReference;
	[Lcom/ibm/JikesRVM/classloader/VM_Type;
	[Lcom/ibm/JikesRVM/classloader/VM_TypeReference;
	[Lcom/ibm/JikesRVM/memoryManagers/mmInterface/VM_CollectorThread;
	[Lorg/mmtk/vm/SynchronizedCounter;
	[Lorg/mmtk/plan/Plan;
	[Lorg/mmtk/utility/VMResource;
	[Lorg/mmtk/utility/MemoryResource;
	[Lorg/mmtk/utility/statistics/Stats;
	[Lorg/mmtk/utility/statistics/Counter;
	[Lorg/mmtk/utility/statistics/EventCounter;
	[Lorg/mmtk/utility/statistics/LongCounter;
	[Lorg/mmtk/utility/statistics/SizeCounter;
	[Lorg/mmtk/utility/statistics/Timer;
	[Lorg/mmtk/utility/MMType;
	[Lorg/mmtk/utility/Scan;
	[Ljava/lang/Object;
	[[Ljava/lang/Object;
	[Ljava/lang/String;
	[Ljava/lang/Class;
	[Ljava/lang/reflect/Field;
	[Ljava/lang/reflect/Method;
	[Ljava/lang/reflect/Member;
	[Ljava/lang/reflect/Constructor;
	[Ljava/io/ObjectStreamField;
	[Ljava/security/ProtectionDomain;
	[Ljava/lang/Package;

	[B
	[C
	[I
	[F
	[D
	[J
	[S
	[Z
	[[I
	[[B
	[[D
	[[[I

	# These next arrays are really arrays of primitves to Jikes RVM 
	#  (even though Java does not think they are...)
	[Lcom/ibm/JikesRVM/VM_Address;
	[Lcom/ibm/JikesRVM/VM_Word;
	[Lcom/ibm/JikesRVM/VM_Offset;
	[Lcom/ibm/JikesRVM/VM_Extent;
	[Lcom/ibm/JikesRVM/VM_Code;
	    
	[Lcom/ibm/JikesRVM/VM_CodeArray;
        [Lcom/ibm/JikesRVM/VM_AddressArray;

	[Lcom/ibm/JikesRVM/classloader/VM_Class;
	[Lcom/ibm/JikesRVM/VM_UnusualMaps;
	[Lcom/ibm/JikesRVM/VM_Processor;
	[Lcom/ibm/JikesRVM/VM_Thread;
	[Lcom/ibm/JikesRVM/VM_Lock;
	[Lcom/ibm/JikesRVM/VM_CompiledMethod;
	[Lcom/ibm/JikesRVM/VM_DynamicLibrary;

	[Lcom/ibm/JikesRVM/classloader/VM_InterfaceMethodSignature; # For fast interface method invoker

	[Lcom/ibm/JikesRVM/VM_CommandLineArgs\$Prefix; # For command-line argument processing
	EOF
    if (( RVM_WITH_OPT_COMPILER )); then
	cat <<- EOF
		[[C
		[Ljava/util/HashSet;
	EOF
	if (( RVM_WITH_ALL_CLASSES )); then
	cat <<- EOF
		[Lcom/ibm/JikesRVM/opt/OPT_OperatorClass;
		[Lcom/ibm/JikesRVM/opt/OPT_ResourceReservation;
		[Lcom/ibm/JikesRVM/opt/ir/OPT_Operator;
		[Lcom/ibm/JikesRVM/opt/ir/OPT_Register;
	EOF
	fi

	if (( RVM_WITH_ALL_CLASSES && RVM_FOR_POWERPC )); then
	cat <<- EOF
		[Lcom/ibm/JikesRVM/opcodeXX;   # PPC Dissasembler
		[Lcom/ibm/JikesRVM/opcode_tab; # PPC Dissasembler
	EOF
	fi

	if (( RVM_WITH_ADAPTIVE_SYSTEM )); then
	cat <<- EOF
		[Lcom/ibm/JikesRVM/adaptive/VM_MethodListener;
		[Lcom/ibm/JikesRVM/adaptive/VM_EdgeListener;
		[Lcom/ibm/JikesRVM/adaptive/VM_ContextListener;
		[Lcom/ibm/JikesRVM/adaptive/VM_NullListener;
EOF
	fi
    fi

# Add the configuration specific primordials
#
    for primordial in $CONF_SPECIFIC_PRIMORDIALS_LIST; do
	echo $primordial
    done

cat <<-EOF
	EOF_PRIMORDIAL_CLASSES_STR
	echo >&2 -n "(primordial class names written) "
	fi

	# Create bootimage.
	#
EOF
    BOOTIMAGE_WRITER_ARGS="\$DEMOGRAPHICS_FLAG \$BOOTIMAGE_WRITER_TRACE_FLAG"

    BOOTIMAGE_WRITER_ARGS="$BOOTIMAGE_WRITER_ARGS"
    IMAGE_ADDRESS_ARG="-ia $BOOTIMAGE_LOAD_ADDRESS"

    if (( GENERATE_MAP )); then
	BOOTIMAGE_WRITER_ARGS="$BOOTIMAGE_WRITER_ARGS -m $BOOTIMAGE_MAP_STR"
    fi
    
    if (( RVM_FOR_IA32 )); then
	BOOTIMAGE_WRITER_ARGS="$BOOTIMAGE_WRITER_ARGS -littleEndian"
    fi
    # OPT_ARGS may be set at build time in jconfigure.
    cat <<- EOF

	# DEBUG_ARGS may be set at run time before invoking jbuild.linkImage
	OPT_ARGS="${OPT_ARGS-} \${DEBUG_ARGS-}"
EOF

    if (( RVM_WITH_NOFLUSH )); then
	echo ' OPT_ARGS="$OPT_ARGS -X:bc:no_cache_flush=true"'
    fi

    cat <<- EOF
	VERBOSE_STR=''
	if tracing BootImageWriter; then
	    OPT_ARGS="\$OPT_ARGS -X:bc:verbose=true"
	    VERBOSE_STR="VERBOSE_ARG=-verbose:gc"
	fi
	

	# copy and preprocess BootImageWriter sources
	#
	
	BOOTIMAGE_WRITER_TRACE_FLAG=
	if tracing BootImageWriter; then
	    BOOTIMAGE_WRITER_TRACE_FLAG=-trace
	fi
	PREPROC_FLAGS="--only-boolean-constants-in-conditions ${PARANOID_PREPROCESSOR_FLAG}"
	FILES=\$(echo $BOOTIMAGE_WRITER_DIR_STR/*.java)
	if ! [[ \$FILES ]]; then
	    show_mesg >&2 Trouble: Cannot find any files in $BOOTIMAGE_WRITER_DIR_STR!
	    trap '' EXIT
	    exit 2
	fi
	if tracing preprocessor; then
	    PREPROC_FLAGS="\${PREPROC_FLAGS}\${PREPROC_FLAGS+ }-trace"
	    cleanline >&2
	    echo >&2 -n "\$ME: '$BOOTIMAGE_WRITER_DIR_STR'/"
	fi

	builtin echo \$FILES | run \$XARGS $BUILD_DIRECTORY_STR/jbuild.prep.host --disable-modification-exit-status \$PREPROC_FLAGS $(echo $PREPROCESSOR_DEFINITIONS) $SCRATCH_DIRECTORY_STR 

	# compile BootImageWriter.java
	#
	chdir $SCRATCH_DIRECTORY_STR

	cp=.:$CLASSES_DIRECTORY_STR:$CLASSES_DIRECTORY_STR/rvmrt.jar
	run $HOST_JAVAC_STR $JAVAC_WARNING_FLAGS -g \
	   -classpath \$cp -bootclasspath \$cp \
	   BootImageWriter.java

	# "cd", not "chdir", since GNU Make will output the directory it is 
	# in, if the user wants directory-changing information.
	cd $BOOTIMAGE_WRITER_DIR_STR
    
	# Pick a specialized boot image writer Makefile, if available.
	BOOTIMAGE_WRITER_MAKEFILE=Makefile
	alt=Makefile.\${HOST_VM_TYPE}
	[[ -f \$alt ]] \
	    && BOOTIMAGE_WRITER_MAKEFILE=\${alt}

	run $GNU_MAKE_STR \$MFLAGS CFLAGS='' CXXFLAGS='' \
		-f \$BOOTIMAGE_WRITER_MAKEFILE \${VERBOSE_STR} \
		RVM_REPOSITORIES=$CLASSES_DIRECTORY_STR/jksvm.jar:$CLASSES_DIRECTORY_STR/rvmrt.jar \
		RVM_BOOTIMAGE_CLASSES=$PRIMORDIAL_CLASSES_STR \
		RVM_BOOTIMAGE=$BOOTIMAGE_STR \
		RVM_BOOTIMAGE_COMPILER_ARGS="\$OPT_ARGS" \
		RVM_BOOTIMAGE_WRITER_ARGS="$BOOTIMAGE_WRITER_ARGS" \
		IMAGE_ADDRESS_ARG="$IMAGE_ADDRESS_ARG" \
		SCRATCH_DIR=$SCRATCH_DIRECTORY_STR \
		$BOOTIMAGE_STR

	trap '' EXIT

EOF
}

function emitCheckIfIAmTheTarget () {
    echo "# Make sure that the architecture and O/S I am running on are"
    echo "# the ones I should be on in order to link native executables."
    echo "# (This assumes we can only link native executables on the"
    echo "# native software and O/S.)"


    if (( RVM_FOR_AIX )); then
	echo "if [[ \$(uname) != AIX ]]; then"
	echo '    echo "please run me on AIX"'
	echo '    trap "" EXIT'
	echo "    exit $Exit_Status_Run_Linker"
	echo 'fi'
   elif (( RVM_FOR_OSX )); then
	echo "if [[ \$(uname) != Darwin ]]; then"
	echo '   echo "please run me on Darwin/OSX"'
	echo '   exit 1'
	echo 'fi'
    elif (( RVM_FOR_LINUX )); then
	echo "if [[ \$(uname) != Linux ]]; then"
	echo '    echo "please run me on Linux"'
	echo '    trap "" EXIT'
	echo "    exit $Exit_Status_Run_Linker"
	echo 'fi'

        if (( RVM_FOR_POWERPC && RVM_FOR_64_ADDR )); then
            echo "if [[ \$(uname -m) != ppc64 ]]; then"
            echo '    echo "please run me on 64-bit Linux PowerPC"'
            echo '    trap "" EXIT'
            echo "    exit $Exit_Status_Run_Linker"
            echo 'fi'
	elif (( RVM_FOR_POWERPC )); then
	    echo "if [[ (\$(uname -m) != ppc) && (\$(uname -m) != ppc64)]]; then"
	    echo '    echo "please run me on Linux PowerPC"'
	    echo '    trap "" EXIT'
	    echo "    exit $Exit_Status_Run_Linker"
	    echo 'fi'
	elif (( RVM_FOR_IA32 )); then
	    echo "if [[ \$(uname -m) != i686 ]]; then"
	    echo '    echo "please run me on Linux IA32"'
	    echo '    trap "" EXIT'
	    echo "    exit $Exit_Status_Run_Linker"
	    echo 'fi'
	else
	    show_mesg_raw >&2 "$ME:$LINENO: Trouble is looming; neither RVM_FOR_POWERPC nor RVM_FOR_IA32 is defined."
	fi
    else
	show_mesg_raw >&2 "$ME:$LINENO: Configuration Trouble is looming; 
neither RVM_FOR_AIX nor RVM_FOR_LINUX nor RVM_FOR_OSX is defined."
    fi
    echo ""
}

# Emit script to generate jbuild.linkBooter, the vm booter, 
# echo >&2  "HERE I AM! emitBooterLinker" # DBG
function emitBooterLinker () {
    cat <<- EOF
	#! /usr/bin/env bash
	
	## This program is run both on the host (when we do the initial 
	## clean) and on the target (when we build the booter.)
	# Generate vm booter.
	
	# Taken:    InterfaceDeclarations.h in RVM.scratch directory
	# Returned: booter in build directory
	
	# Allow the build directory to be different between
	# the host/boot image
	# writing system and the target system.
	
	[[ ! \$RVM_BUILD ]] || cd \$RVM_BUILD
	. ./environment.target
    $(emitBoilerplate)

	while (( \$# > 0 )); do
	    arg="\$1"
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	    elif [[ \$arg = -v ]]; then
	        VFLAG=-v
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	    elif [[ \$arg = -clean ]]; then
	        CLEAN_FLAG=-clean
	    else
	        show_mesg >&2 "Unknown argument: \$arg"
		  trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    fi
	    shift
	done
 
	if tracing make; then
	    MFLAGS=-w
	fi
	echo -n "\$ME: "
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG

	
	# Here, we go ahead and delete some .o files because it takes
	# only a second or two to regenerate them, and there was a long
	# trail of problems getting the dependencies correct.
	rm -f libjni.a
	cd $SCRATCH_DIRECTORY_STR
	rm -f $BOOTER_STR RunBootImage.o initBootRecord.o sys.o bootThread.o bootThread.s libvm.o RunBootImage.h preprocessModifiedFiles
	if [[ \$CLEAN_FLAG ]]; then
	    rm -f disasm.o innpdsm.o
	fi
	echo -n "(booter cleaned) "
	if [[ \$CLEAN_FLAG ]]; then
	    trap "" EXIT
	    exit 0
	fi
	EOF

    emitCheckIfIAmTheTarget
    echo ""

    if	   [[ $RVM_HOST_CONFIG != $RVM_TARGET_CONFIG ]] \
	&& [[ ! ${TARGET_CLASSPATH_INSTALLATION-} ]]
    then
	echo "  $ROOT_DIRECTORY_STR/rvm/bin/jBuildClasspathJar --check"
    fi

    if [[ ${TARGET_CLASSPATH_INSTALLATION-} ]]; then
	if (( ! RVM_FOR_LINUX )); then
	    show_mesg  >&2 "XXX You will probably have to fix the handling of TARGET_CLASSPATH_INSTALLATION for your platform; it is currently only implemented on Linux.   The generated jbuild.linkBooter (called by jbuild) may not work.  As a workaround, don't set TARGET_CLASSPATH_INSTALLATION in your config file."
	fi
    else
	# copy native libraries
	CPS="${TARGET_CLASSPATH_ROOT-$RVM_ROOT/classpath}"
	echo "SYSTEM_TYPE=\$(${CPS}/classpath/config.guess)"
    fi

    if (( RVM_FOR_AIX )); then
	local -r shlib_suffix=.a

	cat <<- EOF

	## AIX requires that dynamically loaded libraries end in .a, 
	## so that dlopen() will find them.  Also, the classpath builder, 
	## on AIX, generates the files with the suffix ".so.0".  
	## We transform one to the other.
	for _library in "$CPS/\$SYSTEM_TYPE/native/jni/"*/.libs/*.so.0
	do
	    oldbase="\$(basename \${_library} .so.0)"
	    dest_lib="${BUILD_DIRECTORY_STR}/\${oldbase}${shlib_suffix}"
	    copyIfNewer "\$_library" "\$dest_lib"
	done
	unset oldbase dest_lib _library || :
EOF
    elif (( RVM_FOR_OSX )); then
	local -r shlib_suffix=.jnilib
cat <<- EOF
	## OSX requires that JNI libraries end in .jnilib, 
	## Also, the classpath builder, 
	## on OSX, generates the files with the suffix ".so".  
	## We transform one to the other.
	for _library in "$CPS/\$SYSTEM_TYPE/native/jni/"*/.libs/*.so
	do
	    oldbase="\$(basename \${_library} .so)"
	    dest_lib="${BUILD_DIRECTORY_STR}/\${oldbase}${shlib_suffix}"
	    copyIfNewer "\$_library" "\$dest_lib"
	done
	unset oldbase dest_lib _library || :
EOF
    elif (( RVM_FOR_LINUX )) && [[ ${TARGET_CLASSPATH_INSTALLATION-} ]]; then
	local -r shlib_suffix=.so
cat <<- EOF
	## On Linux, dynamically loaded libraries end in .so.
	## The classpath builder conveniently generates them with that suffix.
	for _library in ${TARGET_CLASSPATH_INSTALLATION}/lib/classpath/*.so
	do
	    copyIfNewer "\$_library" ${BUILD_DIRECTORY_STR}
	done
	unset oldbase dest_lib _library || :
EOF
    elif (( RVM_FOR_LINUX )); then
	local -r shlib_suffix=.so
cat <<- EOF
	## On Linux, dynamically loaded libraries end in .so.
	## The classpath builder conveniently generates them with that suffix.
	for _library in "$CPS/\$SYSTEM_TYPE/native/jni/"*/.libs/*${shlib_suffix}
	do
	    copyIfNewer "\$_library" "${BUILD_DIRECTORY_STR}"
	done
	unset oldbase dest_lib _library || :
EOF
    else
	show_mesg_raw >&2 "$ME:$LINENO: Configuration Trouble is looming; 
neither RVM_FOR_AIX nor RVM_FOR_LINUX nor RVM_FOR_OSX is defined."
    fi
    cat <<- EOF
	echo >&2  -n '(classpath native libraries copied) '
	CONFIG_H_DIR=${SCRATCH_DIRECTORY_STR}/Config.target

	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/tools/configuring CONFIG_H_DIR=\${CONFIG_H_DIR} 

	# Make a target platform preprocessor for use in gctest
	run ${GNU_MAKE_STR} \${MFLAGS} CFLAGS='' CXXFLAGS='' -C ${ROOT_DIRECTORY_STR}/rvm/src/tools/preprocessor INCLUDED_MAKEFILE=${BUILD_DIRECTORY_STR}/Make.rules.target tool SCRATCH_DIR=${SCRATCH_DIRECTORY_STR} 
	copyIfNewer "${SCRATCH_DIRECTORY_STR}/preprocessModifiedFiles" "${BUILD_DIRECTORY_STR}/jbuild.prep.target"  -n '(set up jbuild.prep.target) '
	## Create RunBootImage.h file.
EOF
    local tgt=RunBootImage.h
    local tmp=${tgt},tmp
    cat <<- EOF
    	cat << EOF_RUNBOOTIMAGE_H > ${tmp}
	// RunBootImage.C boot-time constants
	const unsigned heap_default_initial_size  = $DEFAULT_INITIAL_HEAP_SIZE*1024*1024;
	const unsigned heap_default_maximum_size      = $DEFAULT_MAXIMUM_HEAP_SIZE*1024*1024;
	const char *rvm_version              = "$JIKESRVM_VERSION";
        const char *rvm_cvstimestamp         = "$CVS_TIMESTAMP";
	const char *rvm_configuration        = "$CONFIGURATION_NAME";
	const char *rvm_host_configuration   = "$RVM_HOST_CONFIG";
	const char *rvm_target_configuration = "$RVM_TARGET_CONFIG";
EOF_RUNBOOTIMAGE_H
	{ [[ -f $tgt ]] && cmp -s $tgt $tmp ; } || mv -f $tmp $tgt
	rm -f $tmp

	# build the JNI library for creating processes
	chdir ${ROOT_DIRECTORY_STR}/rvm/src/tools/bootImageRunner/
EOF
    DEST="${BUILD_DIRECTORY_STR}/libjpnexec${shlib_suffix}"
    echo "run ${GNU_MAKE_STR} \$MFLAGS CFLAGS='' CXXFLAGS='' -f Makefile.proc DEST=\"$DEST\" \"$DEST\""

    if (( RVM_FOR_SINGLE_VIRTUAL_PROCESSOR )); then
	CC_DEFINES="-DRVM_FOR_SINGLE_VIRTUAL_PROCESSOR"
    else 
	CC_DEFINES="-URVM_FOR_SINGLE_VIRTUAL_PROCESSOR"
    fi

    if (( RVM_FOR_32_ADDR )); then
	CC_DEFINES="$CC_DEFINES -DRVM_FOR_32_ADDR -URVM_FOR_64_ADDR"
    elif (( RVM_FOR_64_ADDR )); then
	CC_DEFINES="$CC_DEFINES -DRVM_FOR_64_ADDR -URVM_FOR_32_ADDR"
    fi
  
    if (( RVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS )); then
	CC_DEFINES="$CC_DEFINES -DRVM_WITHOUT_INTERCEPT_BLOCKING_SYSTEM_CALLS"
    else
	# Build the blocking system call wrapper library, if requested
	DEST="$BUILD_DIRECTORY_STR/libsyswrap"${shlib_suffix}
	echo "run ${GNU_MAKE_STR} \$MFLAGS CFLAGS='' CXXFLAGS='' -f Makefile.syswrap DEST=\"$DEST\" CXXFLAGS+=\"$CC_DEFINES\" \"$DEST\""
    fi

    if (( RVM_WITH_GCTRACE )); then
        CC_DEFINES="$CC_DEFINES -DRVM_FOR_GCTRACE"
    else
        CC_DEFINES="$CC_DEFINES -URVM_FOR_GCTRACE"
    fi

    # Include GCspy libraries, if requested
    if (( $RVM_WITH_GCSPY )); then
	if (( RVM_FOR_SINGLE_VIRTUAL_PROCESSOR  )); then
	    show_mesg >&2 "Warning: RVM_FOR_SINGLE_VIRTUAL_PROCESSOR is set, as is RVM_WITH_GCSPY.  Those two options are not compatible, since the GCspy server's C runtime support code spawns a pthread.  If you use the GCspy support in this build, Jikes RVM may freeze up or crash."
	fi 
        echo "GCSPY_LIBS=\"-L$GCSPY_LIB_DIR -lgcspy\""
        echo "GCSPY_INCLUDES=\"-I$GCSPY_INCLUDE_DIR\""
    else
        echo "GCSPY_LIBS="
        echo "GCSPY_INCLUDES="
    fi

    if (( RVM_FOR_POWERPC && RVM_FOR_AIX )); then
	cat <<- EOF
		BOOTER_CXX="run $HOST_CPLUS_STR -O2 -DRVM_FOR_AIX -DRVM_FOR_POWERPC $CC_DEFINES"
		LDSHARED="$HOST_SHLD_STR"
		BOOTER_CXXM="\$BOOTER_CXX -M"
		CPP="$HOST_CC_STR -E $CC_DEFINES"

		CCLIBS="-lpthread -lm"
		IMAGE=
EOF
	if (( $RVM_WITH_GCSPY )); then
	    echo "BOOTER_CXX=\"\$BOOTER_CXX -DRVM_WITH_GCSPY\""
	fi

    elif (( RVM_FOR_POWERPC && RVM_FOR_OSX )); then
	echo "BOOTER_CXX=\"run $HOST_CPLUS_STR -O2 -DRVM_FOR_OSX -DRVM_FOR_POWERPC $CC_DEFINES\""
 	echo "LDSHARED=\"$HOST_SHLD_STR\""
	echo "BOOTER_CXXM=\$BOOTER_CXX"
	echo "CPP=\"$HOST_CPP_STR $CC_DEFINES\""

	echo 'CCLIBS="${EXTRA_CCLIBS-} -ldl -lm"'
	echo 'IMAGE="-DIMAGE_ADDRESS='${BOOTIMAGE_LOAD_ADDRESS}'"'

    elif (( RVM_FOR_POWERPC && RVM_FOR_LINUX && RVM_FOR_SINGLE_VIRTUAL_PROCESSOR )); then
	echo "BOOTER_CXX=\"run $HOST_CPLUS_STR -O2 -DRVM_FOR_LINUX -DRVM_FOR_POWERPC $CC_DEFINES\""
 	echo "LDSHARED=\"$HOST_SHLD_STR\""
	echo "BOOTER_CXXM=\$BOOTER_CXX"
	echo "CPP=\"$HOST_CPP_STR $CC_DEFINES\""

	echo '# A special one here... EXTRA_CCLIBS.  Expanded at run time, I assume.'
	echo '# And only sometimes set.'
	echo '# TODO Need to find out if it is still needed.  And if it is, 
# why not make it available for the other configs too? '
	echo 'CCLIBS="${EXTRA_CCLIBS-} -ldl -lm"'
	echo 'IMAGE="-DIMAGE_ADDRESS='${BOOTIMAGE_LOAD_ADDRESS}'"'

    elif (( RVM_FOR_POWERPC && RVM_FOR_LINUX && !RVM_FOR_SINGLE_VIRTUAL_PROCESSOR )); then
	echo "BOOTER_CXX=\"run $HOST_CPLUS_STR -O2 -rdynamic -DRVM_FOR_LINUX -DRVM_FOR_POWERPC $CC_DEFINES\""

	echo "LDSHARED=\"$HOST_SHLD_STR\""
	echo "BOOTER_CXXM=\$BOOTER_CXX"
	echo "CPP=\"$HOST_CPP_STR $CC_DEFINES\""
	
	echo 'CCLIBS="-lpthread -ldl -lm"'
	echo 'IMAGE="-DIMAGE_ADDRESS='${BOOTIMAGE_LOAD_ADDRESS}'"'

    elif (( RVM_FOR_IA32 && RVM_FOR_LINUX && !RVM_FOR_SINGLE_VIRTUAL_PROCESSOR )); then
	echo "declare -a gnu_compiler_flags
gnu_compiler_flags=(-O2 -rdynamic -DRVM_FOR_LINUX -DRVM_FOR_IA32 -D_REENTRANT $CC_DEFINES)"
	echo "BOOTER_CXX=\"run $HOST_CPLUS_STR \${gnu_compiler_flags[@]}\""
	echo "BOOTER_CC=\"run $HOST_CC_STR \${gnu_compiler_flags[@]}\""
	echo 'CCLIBS="-lpthread -ldl"'
	echo 'IMAGE='
	if (( $RVM_WITH_GCSPY )); then
	    echo "BOOTER_CXX=\"\$BOOTER_CXX -DRVM_WITH_GCSPY\""
	fi
    elif (( RVM_FOR_IA32 && RVM_FOR_LINUX && RVM_FOR_SINGLE_VIRTUAL_PROCESSOR )); then
	echo "declare -a gnu_compiler_flags
gnu_compiler_flags=(-O2 -DRVM_FOR_LINUX -DRVM_FOR_IA32 $CC_DEFINES)"
	echo "BOOTER_CXX=\"run $HOST_CPLUS_STR \${gnu_compiler_flags[@]}\""
	echo "BOOTER_CC=\"run $HOST_CC_STR \${gnu_compiler_flags[@]}\""
	echo 'CCLIBS="-ldl"'
	echo 'IMAGE='
	if (( $RVM_WITH_GCSPY )); then
            echo "BOOTER_CXX=\"\$BOOTER_CXX -DRVM_WITH_GCSPY\""
	    echo "CCLIBS=\$CCLIBS -lpthread"
        fi
    else
	show_mesg_raw >&2 "$ME:$LINENO: I do not know how to interpret the current configuration.  I give up (see line # $LINENO of $ME)"
	trap '' EXIT
	exit 2
    fi
    echo ""
    
    if (( HAS_DLCOMPAT )); then
	DLCOMPAT_DEFINE_FLAG=-DHAS_DLCOMPAT
    else
	DLCOMPAT_DEFINE_FLAG=
    fi
    echo 'declare -i linkedit=0'
    if (( RVM_FOR_POWERPC && ( RVM_FOR_AIX || RVM_FOR_LINUX || RVM_FOR_OSX ) ))
    then
	cat <<- EOF
	chdir $BOOTIMAGE_RUNNER_DIR_STR && \
	\$BOOTER_CXX -c -O -I$SCRATCH_DIRECTORY_STR -I\${CONFIG_H_DIR}	\
		-I$BOOTIMAGE_RUNNER_SUBDIR_STR                          \
		\$IMAGE -DRVM_BOOTIMAGE=\\"$BOOTIMAGE_STR\\"		\
		-o $SCRATCH_DIRECTORY_STR/RunBootImage.o RunBootImage.C

	chdir $BOOTIMAGE_RUNNER_SUBDIR_STR
	\$BOOTER_CXX -c -O -I. -I$SCRATCH_DIRECTORY_STR		        \
		-o $SCRATCH_DIRECTORY_STR/initBootRecord.o initBootRecord.C
	\$CPP -I$SCRATCH_DIRECTORY_STR -P                               \
		bootThread.c > $SCRATCH_DIRECTORY_STR/bootThread.s
	\$BOOTER_CXX -c -o $SCRATCH_DIRECTORY_STR/bootThread.o		\
		$SCRATCH_DIRECTORY_STR/bootThread.s
	\$BOOTER_CXX -c -I. -I$SCRATCH_DIRECTORY_STR                    \
		\$IMAGE -DRVM_BOOTIMAGE=\\"$BUILD_DIRECTORY_STR/RVM.image\\" \
		-o $SCRATCH_DIRECTORY_STR/libvm.o libvm.C
EOF

	if (( $RVM_WITH_HPM )); then
	    cat <<- EOF
		echo >&2 -n "(build libhpm.a library) "
		chdir $ROOT_DIRECTORY_STR/rvm/src/vm/HPM/powerPC
		\$BOOTER_CXX -c -O -o $SCRATCH_DIRECTORY_STR/hpm.o hpm.c

		chdir $SCRATCH_DIRECTORY_STR && \
		\$LDSHARED -o $BUILD_DIRECTORY_STR/libhpm.a hpm.o \
		  -L"$RVM_HPM_DIR" -lpmapi

		chdir $ROOT_DIRECTORY_STR/rvm/src/vm/HPM
		echo >&2 -n "(build libJava2HPM.a JNI library) "
		\$BOOTER_CXX -c -O -I$SCRATCH_DIRECTORY_STR \
		  -I$ROOT_DIRECTORY_STR/rvm/src/include \
		  -I$ROOT_DIRECTORY_STR/rvm/src/vm/HPM/$ARCH_DIR \
		  -I$ROOT_DIRECTORY_STR/rvm/src/tools/bootImageRunner \
		  -o $SCRATCH_DIRECTORY_STR/Java2HPM.o Java2HPM.C

		chdir $SCRATCH_DIRECTORY_STR 
		\$LDSHARED -o $BUILD_DIRECTORY_STR/libJava2HPM.a  Java2HPM.o \
		   -L"$RVM_HPM_DIR" -lpmapi -L"$BUILD_DIRECTORY_STR" -lhpm \
		   &> /dev/null

		echo >&2 -n "(build RunBootImage.o) "		
		chdir $BOOTIMAGE_RUNNER_DIR_STR &&\
		\$BOOTER_CXX -c -O -I$SCRATCH_DIRECTORY_STR \$GCSPY_INCLUDES -DRVM_WITH_HPM=1 \
		$DLCOMPAT_DEFINE_FLAG \
		-o $SCRATCH_DIRECTORY_STR/sys.o sys.C

		chdir ${SCRATCH_DIRECTORY_STR} &&\
		\$BOOTER_CXX -o $BOOTER_STR RunBootImage.o initBootRecord.o \
		    libvm.o sys.o bootThread.o \$GCSPY_LIBS \$CCLIBS \
		    -L"$RVM_HPM_DIR" -lpmapi -L"$BUILD_DIRECTORY_STR" -lhpm
EOF
	else
	    cat <<- EOF
	    echo >&2 -n "(build RunBootImage.o) "		
	    chdir ${BOOTIMAGE_RUNNER_DIR_STR} &&\
		\${BOOTER_CXX} -c -O -I${SCRATCH_DIRECTORY_STR} \$GCSPY_INCLUDES \
		${DLCOMPAT_DEFINE_FLAG} \
		-o ${SCRATCH_DIRECTORY_STR}/sys.o sys.C
	    
	    chdir ${SCRATCH_DIRECTORY_STR} &&\
		\${BOOTER_CXX} -o ${BOOTER_STR} RunBootImage.o initBootRecord.o \
		libvm.o sys.o bootThread.o \$GCSPY_LIBS \${CCLIBS}
EOF
	fi
	echo 'linkedit=1'

    elif (( RVM_FOR_IA32 && RVM_FOR_LINUX )); then

	# We would like to use -Wno-missing-noreturn because of 
	# the stubbed-out functions that call sysExit()
	# when compiled for Linux.  Regrettably, this appears to 
	# sometimes cause gripes from GCC version 2.96, although 
	# GCC 3.3 and 3.3.1 take it just fine. 

	# We would also like to use -Wno-unreachable-code to compile 
	# ihnpdsm.C because there 
	# are stub functions there for stuff not appropriate to this 
	# particular build, but which still has references to it in 
	# the Java code. 

	# We would also like to use -Wno-float-equal because we 
	# legitimately compare floats in sys.C. 

	cat <<- EOF
	chdir ${BOOTIMAGE_RUNNER_DIR_STR}
	\${BOOTER_CXX} -c -I${SCRATCH_DIRECTORY_STR}  -I\${CONFIG_H_DIR} \
	    \${IMAGE} -DRVM_BOOTIMAGE=\\"${BOOTIMAGE_STR}\\"             \
	    -o ${SCRATCH_DIRECTORY_STR}/RunBootImage.o RunBootImage.C

	chdir ${BOOTIMAGE_RUNNER_SUBDIR_STR}
	\${BOOTER_CXX} -c -I. -I${SCRATCH_DIRECTORY_STR}                 \
	    -o ${SCRATCH_DIRECTORY_STR}/initBootRecord.o initBootRecord.C
	\${BOOTER_CC} -c -I${SCRATCH_DIRECTORY_STR}                      \
	    -o ${SCRATCH_DIRECTORY_STR}/bootThread.o bootThread.S
	\${BOOTER_CXX} -c -I${SCRATCH_DIRECTORY_STR}                     \
	    -I${ROOT_DIRECTORY_STR}/rvm/src/vm/arch/intel/disassembler   \
	    -o ${SCRATCH_DIRECTORY_STR}/libvm.o libvm.C
	
	chdir ${ROOT_DIRECTORY_STR}/rvm/src/vm/arch/intel/disassembler
	\${BOOTER_CXX} -funsigned-bitfields -c -I${SCRATCH_DIRECTORY_STR}\
	    -o ${SCRATCH_DIRECTORY_STR}/disasm.o disasm.C
	\${BOOTER_CXX} \
	    -funsigned-bitfields -c -I${SCRATCH_DIRECTORY_STR}           \
	    -o ${SCRATCH_DIRECTORY_STR}/ihnpdsm.o ihnpdsm.C
EOF
	if (( $RVM_WITH_HPM )); then
	    cat <<- EOF
	    echo >&2 -n "(build libhpm.a library) "
	    chdir $ROOT_DIRECTORY_STR/rvm/src/vm/HPM/intel && \
		\$BOOTER_CXX -c -O -o $SCRATCH_DIRECTORY_STR/hpm.o hpm.c
	    
	    chdir $SCRATCH_DIRECTORY_STR && \
	    \$HOST_SHLD -o $BUILD_DIRECTORY_STR/libhpm.a hpm.o \
		-L"$RVM_HPM_DIR" -lpapi
	    
	    echo >&2 -n "(build libJava2HPM.a JNI library) "
	    chdir $ROOT_DIRECTORY_STR/rvm/src/vm/HPM && \
	    \$BOOTER_CXX -c -O -I$SCRATCH_DIRECTORY_STR \
		-I$ROOT_DIRECTORY_STR/rvm/src/include \
		-I$ROOT_DIRECTORY_STR/rvm/src/vm/HPM/$ARCH_DIR \
		-I$ROOT_DIRECTORY_STR/rvm/src/tools/bootImageRunner \
		-o $SCRATCH_DIRECTORY_STR/Java2HPM.o Java2HPM.C
	    
	    chdir $SCRATCH_DIRECTORY_STR && \
	    \$HOST_SHLD -o $BUILD_DIRECTORY_STR/libJava2HPM.so  Java2HPM.o \
		-L"$RVM_HPM_DIR" -lpapi -L"$BUILD_DIRECTORY_STR" -lhpm \
		&> /dev/null
	    
	    echo >&2 -n "(build RunBootImage) "
	    # -Wno-missing-noreturn is safe in GCC 2.96 and in 3.3.1, but causes
	    # a warning in g++ 2.96.  So we instead simply extract 
	    # the -Wmissing-noreturn flag.
	    chdir ${BOOTIMAGE_RUNNER_DIR_STR} && \
	    \${BOOTER_CXX//-Wmissing-noreturn/} \
		-c -I${SCRATCH_DIRECTORY_STR} \$GCSPY_INCLUDES -DRVM_WITH_HPM=1\
		-o ${SCRATCH_DIRECTORY_STR}/sys.o sys.C
	    
	    chdir $SCRATCH_DIRECTORY_STR && \
	    \$BOOTER_CXX -o $BOOTER_STR RunBootImage.o initBootRecord.o \
		sys.o bootThread.o libvm.o disasm.o ihnpdsm.o \$GCSPY_LIBS \${CCLIBS} \
		-L"$RVM_HPM_DIR" -lpapi -L"$BUILD_DIRECTORY_STR" -lhpm
	    
EOF
	else
	    cat <<- EOF

	# -Wno-missing-noreturn is safe in GCC 2.96 and in 3.3.1, but causes
	# a warning in g++ 2.96.  So we instead simply extract 
	# the -Wmissing-noreturn flag.
	    chdir ${BOOTIMAGE_RUNNER_DIR_STR} && \
	    \${BOOTER_CXX//-Wmissing-noreturn/} \
		-c -I${SCRATCH_DIRECTORY_STR} \$GCSPY_INCLUDES \
		-o ${SCRATCH_DIRECTORY_STR}/sys.o sys.C
	    
	    chdir ${SCRATCH_DIRECTORY_STR} && \
	    \${BOOTER_CXX} -o ${BOOTER_STR} RunBootImage.o initBootRecord.o \
		sys.o bootThread.o libvm.o disasm.o ihnpdsm.o \$GCSPY_LIBS \${CCLIBS}
EOF
        fi
	echo 'linkedit=1'
    else
	cat <<EOF
	show_mesg >&2 "I do not know how to link the booter"
	trap "" EXIT
	exit $Exit_Status_Run_Linker
EOF
    fi
    cat <<EOF
	if (( ! linkedit )); then 
	    show_mesg >&2 "Internal inconsistency; linkedit should be 1 at this point in the program"
	    exit \$Exit_Status_Run_Linker
	fi

	# We "echo" "(booter linked)", not "echo -n", since we want the last
	# line of jbuild to give us a total number of seconds on a line
	# by itself.
	echo "(booter linked)"
	trap "" EXIT
EOF
}

# Emit script to generate .class files for vm tools that are not part of 
# the build.   This becomes jbuild.tool
#
# echo >&2  "HERE I AM! emitToolCompiler" # DBG
function emitToolCompiler () {
    cat <<- EOF
	#! ${HOST_BASH}
	# Generate class files for vm tools that are not part of the build.
	# This runs the host's Java compiler with the
	# classpath and command-line flags set up so that we can just
	# make .class files for Jikes RVM to run.

	ME="\${0##*/}"			# What is my name?
	if [[ \${RVM_BUILD-UNSET} = UNSET ]]; then
	    echo >&2 "$ME: Please set your RVM_BUILD environment variable (for example, to \${HOME}/rvmBuild)"
	    exit $Exit_Status_Bad_Args
	fi
	set -e
	. \${RVM_BUILD}/environment.target
	. \${JAL_ROOT?}/rvm/bin/libjconfigure.bash

	declare -r usage_msg="Usage: \${ME} [ -trace[=<commands>] ] [ -classpath x:y:z ]\n     [ -- ] java-file [ java-file... ]"
	function usage () {
	    echo -e >&2 "\$usage_msg"
	    trap "" EXIT
	    exit $Exit_Status_Bad_Args
	}

	EXTRA_CPATH=""
	while :; do
	    if (( \$# == 0 )); then
		echo >&2 "\$ME: Not enough arguments" 
		usage;
	    fi
	    arg="\$1"
	    [[ \$arg != -- ]] || { shift ; break; }
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg = -help ]]; then
	        echo -e >&2 \$usage_msg
	        trap "" EXIT
	        exit 0
	    elif [[ \$arg = -classpath ]]; then
	        (( \$# > 1 )) || usage
	        EXTRA_CPATH=\$2\${EXTRA_CPATH+:}\${EXTRA_CPATH}
	        shift
	        shift
	    elif [[ \$arg = -v ]]; then
	        VFLAG=-v
	        shift
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	        shift
	    elif [[ \$arg == -trace* ]]; then
	        TRACE_FLAG=\$arg
	        shift
#	    elif [[ \$arg == -* ]]; then
#		echo >&2 "\${ME}: Unknown argument: \$arg"
#		exit 33
	    else
	        break # must be a regular argument or a flag we do not handle.
	    fi
	done
	CPATH=\${EXTRA_CPATH-.}:$CLASSES_DIRECTORY_STR:$CLASSES_DIRECTORY_STR/rvmrt.jar
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG
	
	run exec $HOST_JAVAC_STR $JAVAC_WARNING_FLAGS -g -classpath "\$CPATH" -bootclasspath "\$CPATH" "\$@"
EOF
}
  
# Emit script to run jbuild.prep.target on java files that are not part of the build
#
function emitToolPreprocessor () {
cat <<EOF
	#! ${TARGET_BASH}
	# Run Jikes RVM's preprocessor on some source code files.
	# Provides all of the standard preprocessor definitions we need for
	# the target environment.  Sticks the pure .java files that are the output
	# into the <output-directory> specified as the first non-flag
	# command-line argument.

	. "${RVM_BUILD?}/environment.target"
    $(emitBoilerplate)

	if (( \$# == 0 )); then
	    show_mesg_raw >&2 "usage: \$ME [ extra-preprocessor-flags...] output-directory java-file [ java-file... ]"
	    trap "" EXIT
	    exit $Exit_Status_Bad_Args
	fi

	exec "$RVM_BUILD/jbuild.prep.target" $(echo $PREPROCESSOR_DEFINITIONS) "\$@"

EOF
}

# Almost always run on the Target machine, but it really doesn't have to be!
function emitPluginBuilder () {
    cat <<- EOF
	#! /usr/bin/env bash
	# Build and install Jikes RVM launching plugin for Eclipse 2.x

	# Pick up the configuration to learn where Ant is
	# and to get the value Ant needs for JAVA_HOME
	. "\${RVM_BUILD?}/environment.target"
    $(emitBoilerplate)

	function emitPluginVersionNumber () {
	    # Put any non-numeric prefix or tail to the Jikes RVM Version Number 
	    # into some sort of numeric form.  The best I can think of to do 
	    # is to suffix it with a .999 if there are any non-numeric chars.
	    # we do not understand.
	    #
	    # Eclipse's assertions require a numeric first and third component,
	    # at least.  Sigh.
	    local vnum="${JIKESRVM_VERSION//*[jJ][iI][kK][eE][sS]*[rR][vV][mM]}";
	    # CVS or +cvs or .cvs turns into .99
	    vnum="\${vnum//[cC][vV][sS]/cvs}";
	    vnum="\${vnum//[^0-9]cvs/cvs}";
	    vnum="\${vnum//cvs[^0-9]/cvs}";
	    vnum="\${vnum/cvs?[hH][eE][aA][dD]/cvs}";
	    vnum="\${vnum/cvs[hH][eE][aA][dD]/cvs}";
	    vnum="\${vnum/(cvs)/cvs}";
	    while [[ \$vnum == *' '* ]]; do
		vnum="\${vnum// }"      # trim spaces if present (there usually 
				       # is at least one after the words "Jikes RVM")
	    done

	    if [[ \$vnum == *cvs* ]]; then
		vnum="\${vnum/cvs}.99" ;
	    fi
	    local -i warned=0;

	    case "\$vnum" in
		*[^.0-9]* ) 
	             show_mesg >&2 "Warning: When I converted the Jikes RVM
			 Version information, \\"$JIKESRVM_VERSION\\",
	   	         into a numeric form for use with the Eclipse plugin, 
			 I found a non-numeric component, even after 
			 the \\"CVS\\" transformation; the result looks like
			 this: \\"\$vnum\\".   This message is intended
			 primarily for Jikes RVM maintainers, and suggests 
			 that you try a numeric format for JIKESRVM_VERSION"
		    let warned=1
	    esac

	    # Strip out non-numeric information:
	    vnum="\${vnum//[^.0-9]}";
	    # Turn any string of multiple dots into single dots
	    while [[ \$vnum == *..* ]]; do
		vnum="\${vnum//../.}";
	    done
	    # trim leading or trailing dots (only single ones left!)
	    vnum="\${vnum%.}";
	    vnum="\${vnum#.}";
	    if (( warned )); then
		vnum="\${vnum}.000";	# add a .000 if we did any stripping.
		show_mesg >&2 "A Candidate version number for Eclipse is \$vnum";
	    fi
	    # if five or more components, trim it!
	    if [[ \$vnum == *.*.*.*.* ]]; then
		show_mesg >&2 "The candidate Eclipse plugin version number \$vnum has too many components; Eclipse misbehaves with more than four.  Chopping from tail."
		let warned=1
		while [[ \$vnum == *.*.*.*.* ]]; do
		    vnum="\${vnum%.*}"
		done
	    fi
	    show_mesg >&2 "The Eclipse plugin will be installed with version # \$vnum"
	    echo "\$vnum"
	}

	PLUGIN_VERSION_NUMBER="\$(emitPluginVersionNumber)"


	function emit_ant_properties () {
	    echo "eclipse.dir=\${ECLIPSE_INSTALL_DIR}"
	    echo "plugin.version=\${PLUGIN_VERSION_NUMBER}"
	    echo "# Show extra info when building?"
	    if tracing ant; then
	        echo "build.trace=true"
	    else
	        echo "build.trace=false"
	    fi
	    echo "# Taken from the RVM_BUILD envar"
	    echo "build.dir=\${build_dir}"
	}


	export JAVA_HOME=\${HOST_JAVA_HOME}

	usage () {
	    show_mesg_raw "Usage: \$ME [ --help ] [ -clean ] [ -verbose ] [ -trace[=<args>] ] [-v] [-x] [-target=<target-name>] [--] [ <eclipse-install-dir> ]"
	}

	help() {
	    usage;
	    echo "\$ME: To specify Eclipse's installation directory, do one"
	    echo "\$ME:  of the following (in order of decreasing precedence):" 
	    echo "  1: invoke this program as \$ME [<flags>] <eclipse-install-dir>"
	    echo "  2: set ECLIPSE_INSTALL_DIR in \${RVM_TARGET_CONFIG}, or"
	    echo "  3: set the environment variable ECLIPSE_INSTALL_DIR"
	}


	TARGET=install
	VERBOSE_ANT=
	while (( \$# > 0 )); do
	    arg="\$1"
	    if [[ \$arg = -- ]]; then
	        shift		# The end of the flag arguments
	        break;
	    fi
	    [[ \$arg != --?* ]] || arg="\${arg#-}"
	    if [[ \$arg = -v ]]; then
	        VFLAG=-v
		VERBOSE_ANT=-verbose
	        shift
	    elif [[ \$arg = -x ]]; then
	        XFLAG=-x
	        shift
	    elif [[ \$arg = -verbose ]]; then
	        VERBOSE_ANT=-verbose
	        shift
	    elif [[ \$arg == -clean ]]; then
	        TARGET="clean"
	        shift
	    elif [[ \$arg == -trace* ]]; then
	        TRACE_FLAG="\$arg"
	        shift
	    elif [[ \$arg == -target=* ]]; then
	        TARGET="\${arg#-target=}"
	        shift
	    elif [[ \$arg = -help ]]; then
	        shift
	        help
	        trap '' EXIT
	        exit 0
	    elif [[ \$arg == -* ]]; then
	        show_mesg >&2 "Unknown flag: \$arg"
	        usage >&2
		trap '' EXIT
	        exit $Exit_Status_Bad_Args
	    else
		break;		# Must have specified an Eclipse install dir 
				# on the commmand line.
	    fi
	done

	# allow user-specified Eclipse install to override env
	if [[ \${1-} ]]; then
	    ECLIPSE_INSTALL_DIR="\$1"
	    shift
	fi

	if (( \$# != 0 )); then
	    show_mesg >&2 "Too many arguments."
	    usage >&2
	    trap '' EXIT
	    exit $Exit_Status_Bad_Args;
	fi
	# must have Eclipse install dir specified 
	# via command line or via the process environment 
	# or via environment.target
	if [[ ! \${ECLIPSE_INSTALL_DIR} ]]; then
	    show_mesg >&2 "You must (but did not) specify the directory where Eclipse is installed."
	    help;
	    trap "" EXIT
	    exit 2
	fi >&2

	# must have Ant
	if [[ ! \${ANT_CMD-} ]]; then
	    echo "must specify ANT_CMD in \${RVM_TARGET_CONFIG}"
	    trap "" EXIT
	    exit 2
	fi

	# build the plugin
	[ ! "\$VFLAG\$XFLAG" ] || set \$VFLAG \$XFLAG

	# Get the name of the package we're building.  It changes with each
	# new version of Jikes RVM.
	if [[ \$TARGET = clean ]]; then
	    echo -n "Cleaning up "
	elif [[ \$TARGET == \*build\* ]]; then
	    echo -n "Building"
	elif  [[ \$TARGET == install ]] || [[ \$TARGET = reinstall ]]; then
	    echo "Installing"
	else
	    echo "Running \\"ant\\", with target=\$TARGET, on"
	fi
	echo " the JikesRVM-launching Eclipse plugin"

	build_dir="${BUILD_DIRECTORY_STR}/plugin.eclipse"
	mkdir -p \${build_dir}
	propfile="\$build_dir/ant.properties"
	if tracing jbuild || tracing ant; then
	    echo "Setting up \${propfile}"
	fi

	emit_ant_properties > \${propfile}

	srcdir=${ROOT_DIRECTORY_STR}/rvm/src/tools/eclipse/plugin2
	chdir \${srcdir}

	if tracing ant; then
	    QUIET_ANT=""
	else
	    QUIET_ANT=-quiet
	fi

	cmd="\${ANT_CMD} \$QUIET_ANT \${VERBOSE_ANT} \${TARGET}"
	if tracing jbuild || tracing ant || tracing make ; then
	    echo \$cmd
	fi
	\$cmd

	if [[ \$TARGET = install ]] || [[ \$TARGET = reinstall ]]; then
	    echo "Installed the Plugin with version # \${PLUGIN_VERSION_NUMBER}"
	fi
	trap '' EXIT
	EOF
}


emitInstaller() {
    cat <<- EOF
	#! /usr/bin/env bash
	#
	# jbuild.install
	# An auxiliary program that installs Jikes RVM wherever we want it 
	# to be.
	# This is not run as a part of the normal build process; it has
	# special applications

	# $BUILD_DIRECTORY_STR1=\$ROOT_DIR
	function usage() {
	    show_mesg >&2 "Usage: \$ME <destination-directory>"
	    exit $Exit_Status_Bad_Args
	}

	(( \$# == 1 )) || usage;
	. ./environment.host
    $(emitBoilerplate)
	dest="\$1"
	run mkdir -p \$dest
	shopt -s  nullglob
	run cp *.a *.so environment.target $BOOTIMAGE_STR $BOOTER_STR \$dest
	shopt -u nullglob
	run mkdir -p \$dest/RVM.classes
	run cp RVM.classes/*.jar \$dest/RVM.classes
	show_mesg "Now execute \\"export RVM_BUILD=\$dest\\""
	show_mesg "Then you can run Jikes RVM with the \\"rvm\\" command"
	trap '' EXIT
EOF
}


function emitConfigSummary () {
    echo "configuration name: ${CONFIGURATION_NAME}" 
    echo "preprocessor definitions:"
    echo "${PREPROCESSOR_DEFINITIONS}"
    echo "other definitions set in RVM.scratch/RunBootImage.h:"
    echo "JIKESRVM_VERSION=$JIKESRVM_VERSION"
    echo "DEFAULT_INITIAL_HEAP_SIZE=${DEFAULT_INITIAL_HEAP_SIZE}"
    echo "DEFAULT_MAXIMUM_HEAP_SIZE=${DEFAULT_MAXIMUM_HEAP_SIZE}"
    echo "CVS_TIMESTAMP=${CVS_TIMESTAMP}"
    echo "RVM_HOST_CONFIG=${RVM_HOST_CONFIG}"
    echo "RVM_TARGET_CONFIG=${RVM_TARGET_CONFIG}"
}

#------------------------------------------------#
# SECTION 6 - Mainline Code that does the work.  #
#------------------------------------------------#
    
echo "${ME}: setting up ${BUILD_DIRECTORY} for ${CONFIGURATION_NAME}"

# Ensure configuration options are sensible.
checkConfigurationOptions

# Make a fresh start.
#
if (( cleanse )) && [[ -e ${BUILD_DIRECTORY} ]] # old directory exists; 
then 
    if [ -t 0 ]    # keyboard is live (ie. this is not an automated build)
    then
	## && [[ ! $EMACS ]] 
	## It would be nice to test whether we are running under EMACS's 
	## M-x compile mode.   But I do not know how to do that. 
	declare -i got_EOF=0
	response="UNSET"
	if ! read -n 1 -p "${ME}: ${BUILD_DIRECTORY} already exists, replace it? (y/n) --> " response; then
	    # Shell does not let us distinguish EOF from I/O errors.
	    got_EOF=1
	fi
	# finish the line since our user did not type a newline' for us.
	echo ""
	if (( $got_EOF )); then
	    show_mesg >&2 "Got EOF (End of File).  We will not write anything."
	    response=EOF
	fi
	if [[ $response != y* ]]; then
	    show_mesg >&2 "Operation aborted; nothing written."
	    trap '' EXIT
	    exit $Exit_Status_Bad_Args
	fi
    fi
    ( chdir ${BUILD_DIRECTORY} && run rm -rf * )
fi
if ! (( cleanse )) && ! (( quiet )); then
    show_mesg "We shall write new jbuild* files, but not delete existing compilation results."
fi

# Create output directory structure.
#
mkdir -p ${BUILD_DIRECTORY}
mkdir -p ${GENERATED_FILES_DIRECTORY}
mkdir -p ${GENERATED_FILES_DIRECTORY}/instructionFormats
mkdir -p ${SCRATCH_DIRECTORY}
mkdir -p ${CLASSES_DIRECTORY}

(( quiet )) || echo -n "(directories created) "

# Create control files and scripts.
#
(( cleanse )) && touch ${CLEANSE_STATUS}

PERM=+r+w

s=${CONFIGURATION_SUMMARY}
emitConfigSummary > ${s}
chmod ${PERM} ${s}

HOST_BASH="/usr/bin/env bash"
TARGET_BASH="${BASH-${HOST_BASH}}"

f=$SOURCE_LIST
rm -f			$f
emitSourceList	      > $f
chmod ${PERM}		$f

f=${BUILD_DIRECTORY}/jbuild
rm -f			$f
emitController	      > $f
chmod +x${PERM}		$f

f=${BUILD_DIRECTORY}/jbuild.expand
rm -f			$f
emitExpander	      > $f
chmod +x${PERM}		$f

f=${BUILD_DIRECTORY}/jbuild.copy
rm -f			$f
emitCopier	      > $f
chmod +x${PERM}		$f

f=${BUILD_DIRECTORY}/jbuild.compile
rm -f			$f
emitCompiler	      > $f
chmod +x${PERM}		$f

f=${BUILD_DIRECTORY}/jbuild.interfaceDeclarations
rm -f			$f
emitInterfaceDeclarationsWriter	  > $f  
chmod +x${PERM}         $f


f=${BUILD_DIRECTORY}/jbuild.linkImage
rm -f			$f
emitImageLinker       > $f  
chmod +x${PERM}         $f

f=${BUILD_DIRECTORY}/jbuild.linkBooter
rm -f			$f
emitBooterLinker      > $f
chmod +x${PERM}         $f

f=${BUILD_DIRECTORY}/jbuild.tool
rm -f			$f
emitToolCompiler      > $f
chmod +x${PERM}         $f

f=${BUILD_DIRECTORY}/jbuild.toolPrep
rm -f			$f
emitToolPreprocessor  > $f
chmod +x$PERM           $f

f=${BUILD_DIRECTORY}/jbuild.plugin
rm -f			$f
emitPluginBuilder     > $f
chmod +x$PERM		$f

f=${BUILD_DIRECTORY}/jbuild.install
rm -f			$f
emitInstaller	      > $f
chmod +x${PERM}		$f

# Write the GNU Classpath security properties file
#
f=${BUILD_DIRECTORY}/security/JikesRVM.security
rm -f $f
mkdir -p $(dirname $f)
builtin echo "security.provider.1=gnu.java.security.provider.Gnu" > $f
chmod -x${PERM} $f


# Write the environment-specific configuration files
#

# We've already read in the target environment file.
# load_config_file ${RVM_TARGET_CONFIG}
# Now, generate the config files for the target.

f=${BUILD_DIRECTORY}/Make.rules.target
rm -f $f
emitMakefile > $f
chmod -x${PERM} $f

f=${BUILD_DIRECTORY}/environment.target
rm -f $f
emitEnvironmentBash > $f
chmod -x${PERM}	$f

## read the host environment file
unsetEnvironment;		# throw out leftovers
load_config_file ${RVM_HOST_CONFIG}
# echo >&2 "Just read RVM_HOST_CONFIG=${RVM_HOST_CONFIG}  JIKES_WARNING_FLAGS=$JIKES_WARNING_FLAGS" #DEBUG

f=${BUILD_DIRECTORY}/Make.rules.host
rm -f			$f
emitMakefile	      > $f
chmod -x${PERM}		$f

f=${BUILD_DIRECTORY}/environment.host
rm -f			$f
emitEnvironmentBash   >	$f
chmod -x${PERM}		$f


(( quiet )) || echo -n "(control files and scripts installed) "

if (( ! quiet )); then
    if [ -t 0 ]; then # The keyboard is live (this is not an automated build)
	echo ""
	echo "${ME}: ${CONFIGURATION_NAME} configuration is ready"
	echo "${ME}: To build it, type:"
	echo "${ME}:    cd ${BUILD_DIRECTORY}"
	echo "${ME}:    ./jbuild"
    else
	echo "done."
    fi
fi
trap '' EXIT
