[cig-commits] r4235 - in cs/scons: . scons-local-0.96.92 scons-local-0.96.92/SCons scons-local-0.96.92/SCons/Node scons-local-0.96.92/SCons/Optik scons-local-0.96.92/SCons/Options scons-local-0.96.92/SCons/Platform scons-local-0.96.92/SCons/Scanner scons-local-0.96.92/SCons/Script scons-local-0.96.92/SCons/Sig scons-local-0.96.92/SCons/Tool

walter at geodynamics.org walter at geodynamics.org
Fri Aug 4 23:50:06 PDT 2006


Author: walter
Date: 2006-08-04 23:49:51 -0700 (Fri, 04 Aug 2006)
New Revision: 4235

Added:
   cs/scons/scons-local-0.96.92/
   cs/scons/scons-local-0.96.92/SCons/
   cs/scons/scons-local-0.96.92/SCons/Action.py
   cs/scons/scons-local-0.96.92/SCons/Builder.py
   cs/scons/scons-local-0.96.92/SCons/Conftest.py
   cs/scons/scons-local-0.96.92/SCons/Debug.py
   cs/scons/scons-local-0.96.92/SCons/Defaults.py
   cs/scons/scons-local-0.96.92/SCons/Environment.py
   cs/scons/scons-local-0.96.92/SCons/Errors.py
   cs/scons/scons-local-0.96.92/SCons/Executor.py
   cs/scons/scons-local-0.96.92/SCons/Job.py
   cs/scons/scons-local-0.96.92/SCons/Memoize.py
   cs/scons/scons-local-0.96.92/SCons/Node/
   cs/scons/scons-local-0.96.92/SCons/Node/Alias.py
   cs/scons/scons-local-0.96.92/SCons/Node/FS.py
   cs/scons/scons-local-0.96.92/SCons/Node/Python.py
   cs/scons/scons-local-0.96.92/SCons/Node/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Optik/
   cs/scons/scons-local-0.96.92/SCons/Optik/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Optik/errors.py
   cs/scons/scons-local-0.96.92/SCons/Optik/option.py
   cs/scons/scons-local-0.96.92/SCons/Optik/option_parser.py
   cs/scons/scons-local-0.96.92/SCons/Options/
   cs/scons/scons-local-0.96.92/SCons/Options/BoolOption.py
   cs/scons/scons-local-0.96.92/SCons/Options/EnumOption.py
   cs/scons/scons-local-0.96.92/SCons/Options/ListOption.py
   cs/scons/scons-local-0.96.92/SCons/Options/PackageOption.py
   cs/scons/scons-local-0.96.92/SCons/Options/PathOption.py
   cs/scons/scons-local-0.96.92/SCons/Options/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Platform/
   cs/scons/scons-local-0.96.92/SCons/Platform/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Platform/aix.py
   cs/scons/scons-local-0.96.92/SCons/Platform/cygwin.py
   cs/scons/scons-local-0.96.92/SCons/Platform/darwin.py
   cs/scons/scons-local-0.96.92/SCons/Platform/hpux.py
   cs/scons/scons-local-0.96.92/SCons/Platform/irix.py
   cs/scons/scons-local-0.96.92/SCons/Platform/os2.py
   cs/scons/scons-local-0.96.92/SCons/Platform/posix.py
   cs/scons/scons-local-0.96.92/SCons/Platform/sunos.py
   cs/scons/scons-local-0.96.92/SCons/Platform/win32.py
   cs/scons/scons-local-0.96.92/SCons/SConf.py
   cs/scons/scons-local-0.96.92/SCons/SConsign.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/
   cs/scons/scons-local-0.96.92/SCons/Scanner/C.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/D.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/Dir.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/Fortran.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/IDL.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/LaTeX.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/Prog.py
   cs/scons/scons-local-0.96.92/SCons/Scanner/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Script/
   cs/scons/scons-local-0.96.92/SCons/Script/Main.py
   cs/scons/scons-local-0.96.92/SCons/Script/SConscript.py
   cs/scons/scons-local-0.96.92/SCons/Script/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Sig/
   cs/scons/scons-local-0.96.92/SCons/Sig/MD5.py
   cs/scons/scons-local-0.96.92/SCons/Sig/TimeStamp.py
   cs/scons/scons-local-0.96.92/SCons/Sig/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Subst.py
   cs/scons/scons-local-0.96.92/SCons/Taskmaster.py
   cs/scons/scons-local-0.96.92/SCons/Tool/
   cs/scons/scons-local-0.96.92/SCons/Tool/386asm.py
   cs/scons/scons-local-0.96.92/SCons/Tool/BitKeeper.py
   cs/scons/scons-local-0.96.92/SCons/Tool/CVS.py
   cs/scons/scons-local-0.96.92/SCons/Tool/JavaCommon.py
   cs/scons/scons-local-0.96.92/SCons/Tool/Perforce.py
   cs/scons/scons-local-0.96.92/SCons/Tool/PharLapCommon.py
   cs/scons/scons-local-0.96.92/SCons/Tool/RCS.py
   cs/scons/scons-local-0.96.92/SCons/Tool/SCCS.py
   cs/scons/scons-local-0.96.92/SCons/Tool/Subversion.py
   cs/scons/scons-local-0.96.92/SCons/Tool/__init__.py
   cs/scons/scons-local-0.96.92/SCons/Tool/aixc++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/aixcc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/aixf77.py
   cs/scons/scons-local-0.96.92/SCons/Tool/aixlink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/applelink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/ar.py
   cs/scons/scons-local-0.96.92/SCons/Tool/as.py
   cs/scons/scons-local-0.96.92/SCons/Tool/bcc32.py
   cs/scons/scons-local-0.96.92/SCons/Tool/c++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/cc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/cvf.py
   cs/scons/scons-local-0.96.92/SCons/Tool/default.py
   cs/scons/scons-local-0.96.92/SCons/Tool/dmd.py
   cs/scons/scons-local-0.96.92/SCons/Tool/dvi.py
   cs/scons/scons-local-0.96.92/SCons/Tool/dvipdf.py
   cs/scons/scons-local-0.96.92/SCons/Tool/dvips.py
   cs/scons/scons-local-0.96.92/SCons/Tool/f77.py
   cs/scons/scons-local-0.96.92/SCons/Tool/f90.py
   cs/scons/scons-local-0.96.92/SCons/Tool/f95.py
   cs/scons/scons-local-0.96.92/SCons/Tool/fortran.py
   cs/scons/scons-local-0.96.92/SCons/Tool/g++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/g77.py
   cs/scons/scons-local-0.96.92/SCons/Tool/gas.py
   cs/scons/scons-local-0.96.92/SCons/Tool/gcc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/gnulink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/gs.py
   cs/scons/scons-local-0.96.92/SCons/Tool/hpc++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/hpcc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/hplink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/icc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/icl.py
   cs/scons/scons-local-0.96.92/SCons/Tool/ifl.py
   cs/scons/scons-local-0.96.92/SCons/Tool/ifort.py
   cs/scons/scons-local-0.96.92/SCons/Tool/ilink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/ilink32.py
   cs/scons/scons-local-0.96.92/SCons/Tool/intelc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/jar.py
   cs/scons/scons-local-0.96.92/SCons/Tool/javac.py
   cs/scons/scons-local-0.96.92/SCons/Tool/javah.py
   cs/scons/scons-local-0.96.92/SCons/Tool/latex.py
   cs/scons/scons-local-0.96.92/SCons/Tool/lex.py
   cs/scons/scons-local-0.96.92/SCons/Tool/link.py
   cs/scons/scons-local-0.96.92/SCons/Tool/linkloc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/m4.py
   cs/scons/scons-local-0.96.92/SCons/Tool/masm.py
   cs/scons/scons-local-0.96.92/SCons/Tool/midl.py
   cs/scons/scons-local-0.96.92/SCons/Tool/mingw.py
   cs/scons/scons-local-0.96.92/SCons/Tool/mslib.py
   cs/scons/scons-local-0.96.92/SCons/Tool/mslink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/msvc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/msvs.py
   cs/scons/scons-local-0.96.92/SCons/Tool/mwcc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/mwld.py
   cs/scons/scons-local-0.96.92/SCons/Tool/nasm.py
   cs/scons/scons-local-0.96.92/SCons/Tool/pdf.py
   cs/scons/scons-local-0.96.92/SCons/Tool/pdflatex.py
   cs/scons/scons-local-0.96.92/SCons/Tool/pdftex.py
   cs/scons/scons-local-0.96.92/SCons/Tool/qt.py
   cs/scons/scons-local-0.96.92/SCons/Tool/rmic.py
   cs/scons/scons-local-0.96.92/SCons/Tool/rpcgen.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sgiar.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sgic++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sgicc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sgilink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sunar.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sunc++.py
   cs/scons/scons-local-0.96.92/SCons/Tool/suncc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/sunlink.py
   cs/scons/scons-local-0.96.92/SCons/Tool/swig.py
   cs/scons/scons-local-0.96.92/SCons/Tool/tar.py
   cs/scons/scons-local-0.96.92/SCons/Tool/tex.py
   cs/scons/scons-local-0.96.92/SCons/Tool/tlib.py
   cs/scons/scons-local-0.96.92/SCons/Tool/yacc.py
   cs/scons/scons-local-0.96.92/SCons/Tool/zip.py
   cs/scons/scons-local-0.96.92/SCons/Util.py
   cs/scons/scons-local-0.96.92/SCons/Warnings.py
   cs/scons/scons-local-0.96.92/SCons/__init__.py
   cs/scons/scons-local-0.96.92/SCons/dblite.py
   cs/scons/scons-local-0.96.92/SCons/exitfuncs.py
Removed:
   cs/scons/scons-LICENSE
   cs/scons/scons-README
   cs/scons/scons-local-0.96.1/
Modified:
   cs/scons/scons.py
   cs/scons/sconsign.py
Log:
Upgrade to 0.96.92 because we need framework support on OS X for static builds

Deleted: cs/scons/scons-LICENSE
===================================================================
--- cs/scons/scons-LICENSE	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-LICENSE	2006-08-05 06:49:51 UTC (rev 4235)
@@ -1,25 +0,0 @@
-        Copyright and license for SCons - a software construction tool
-
-        This copyright and license do not apply to any other software
-        with which this software may have been included.
-
-Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Deleted: cs/scons/scons-README
===================================================================
--- cs/scons/scons-README	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-README	2006-08-05 06:49:51 UTC (rev 4235)
@@ -1,204 +0,0 @@
-# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
-
-                 SCons - a software construction tool
-
-This is the scons-README file for a version of SCons packaged for local
-execution--that is, execution out of a specific local directory, without
-having to install SCons as a system-wide utility.
-
-You are likely reading this file in one of the following two situations:
-
-    1)  You have unpacked an scons-local-{version} package and are
-        examining the contents.
-
-        In this case, you are presumably interested in using this
-        package to include a local copy of SCons with some other
-        software that you package, so that you can use SCons to build
-        your software without forcing all of your users to have it fully
-        installed.  Instructions for this can be found below.
-
-        If you are not looking to use SCons in this way, then please
-        use either the scons-{version} package to install SCons on your
-        system, or the scons-src-{version} package if you want the full
-        source to SCons, including its packaging code and underlying
-        tests and testing infrastructure.
-
-    2)  This file was included in some other software package so that
-        the package could be built using SCons.
-
-        In this case, follow the instructions provided with the
-        rest of the software package for how to use SCons to build
-        and/or install the software.  The file containing build and
-        installation instructions will typically be named README or
-        INSTALL.
-
-LATEST VERSION
-==============
-
-Before going further, you can check for the latest version of the
-scons-local package, or any SCons package, at the SCons download page:
-
-        http://www.scons.org/download.html
-
-
-EXECUTION REQUIREMENTS
-======================
-
-Running SCons requires Python version 1.5.2 or later.  There should be
-no other dependencies or requirements to run SCons.
-
-The default SCons configuration assumes use of the Microsoft Visual C++
-compiler suite on WIN32 systems, and assumes a C compiler named 'cc',
-a C++ compiler named 'c++', and a Fortran compiler named 'g77' (such
-as found in the GNU C compiler suite) on any other type of system.
-You may, of course, override these default values by appropriate
-configuration of Environment construction variables.
-
-
-INSTALLATION
-============
-
-Installation of this package should be as simple as unpacking the
-archive (either .tar.gz or .zip) in any directory (top-level or a
-subdirectory) within the software package with which you want to ship
-SCons.
-
-Once you have installed this package, you should write an SConstruct
-file at the top level of your source tree to build your software as you
-see fit.
-
-Then modify the build/install instructions for your package to instruct
-your users to execute SCons as follows (if you installed this package in
-your top-level directory):
-
-        $ python scons.py
-
-Or (if, for example, you installed this package in a subdirectory named
-"scons"):
-
-        $ python scons/scons.py
-
-That should be all you have to do.  (If it isn't that simple, please let
-us know!)
-
-
-CONTENTS OF THIS PACKAGE
-========================
-
-This scons-local package consists of the following:
-
-scons-LICENSE
-        A copy of the copyright and terms under which SCons is
-        distributed (the Open Source Initiative-approved MIT license).
-
-        A disclaimer has been added to the beginning to make clear that
-        this license applies only to SCons, and not to any separate
-        software you've written with which you're planning to package
-        SCons.
-
-scons-README
-        What you're looking at right now.
-
-scons-local-{version}/
-        The SCons build engine.  This is structured as a Python
-        library.
-
-scons.py
-        The SCons script itself.  The script sets up the Python
-        sys.path variable to use the build engine found in the
-        scons-local-{version}/ directory in preference to any other
-        SCons build engine installed on your system.
-
-
-DOCUMENTATION
-=============
-
-Because this package is intended to be included with other software by
-experienced users, we have not included any SCons documentation in this
-package (other than this scons-README file you're reading right now).
-
-If, however, you need documentation about SCons, then consult any of the
-following from the corresponding scons-{version} or scons-src-{version}
-package:
-
-        The RELEASE.txt file (src/RELEASE.txt file in the
-        scons-src-{version} package), which contains notes about this
-        specific release, including known problems.
-
-        The CHANGES.txt file (src/CHANGES.txt file in the
-        scons-src-{version} package), which contains a list of changes
-        since the previous release.
-
-        The scons.1 man page (doc/man/scons.1 in the scons-src-{version}
-        package), which contains a section of small examples for getting
-        started using SCons.
-
-Additional documentation for SCons is available at:
-
-        http://www.scons.org/doc.html
-
-
-LICENSING
-=========
-
-SCons is distributed under the MIT license, a full copy of which is
-available in the scons-LICENSE file in this package. The MIT license is
-an approved Open Source license, which means:
-
-        This software is OSI Certified Open Source Software.  OSI
-        Certified is a certification mark of the Open Source Initiative.
-
-More information about OSI certifications and Open Source software is
-available at:
-
-        http://www.opensource.org/
-
-
-REPORTING BUGS
-==============
-
-You can report bugs either by following the "Tracker - Bugs" link
-on the SCons project page:
-
-        http://sourceforge.net/projects/scons/
-
-or by sending mail to the SCons developers mailing list:
-
-        scons-devel at lists.sourceforge.net
-
-
-MAILING LISTS
-=============
-
-A mailing list for users of SCons is available.  You may send questions
-or comments to the list at:
-
-        scons-users at lists.sourceforge.net
-
-You may subscribe to the scons-users mailing list at:
-
-        http://lists.sourceforge.net/lists/listinfo/scons-users
-
-
-FOR MORE INFORMATION
-====================
-
-Check the SCons web site at:
-
-        http://www.scons.org/
-
-
-AUTHOR INFO
-===========
-
-Steven Knight
-knight at baldmt dot com
-http://www.baldmt.com/~knight/
-
-With plenty of help from the SCons Development team:
-        Chad Austin
-        Charles Crain
-        Steve Leblanc
-        Anthony Roach
-        Terrel Shumway
-

Added: cs/scons/scons-local-0.96.92/SCons/Action.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Action.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Action.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,815 @@
+"""SCons.Action
+
+This encapsulates information about executing any sort of action that
+can build one or more target Nodes (typically files) from one or more
+source Nodes (also typically files) given a specific Environment.
+
+The base class here is ActionBase.  The base class supplies just a few
+OO utility methods and some generic methods for displaying information
+about an Action in response to the various commands that control printing.
+
+A second-level base class is _ActionAction.  This extends ActionBase
+by providing the methods that can be used to show and perform an
+action.  True Action objects will subclass _ActionAction; Action
+factory class objects will subclass ActionBase.
+
+The heavy lifting is handled by subclasses for the different types of
+actions we might execute:
+
+    CommandAction
+    CommandGeneratorAction
+    FunctionAction
+    ListAction
+
+The subclasses supply the following public interface methods used by
+other modules:
+
+    __call__()
+        THE public interface, "calling" an Action object executes the
+        command or Python function.  This also takes care of printing
+        a pre-substitution command for debugging purposes.
+
+    get_contents()
+        Fetches the "contents" of an Action for signature calculation.
+        This is what the Sig/*.py subsystem uses to decide if a target
+        needs to be rebuilt because its action changed.
+
+    genstring()
+        Returns a string representation of the Action *without*
+        command substitution, but allows a CommandGeneratorAction to
+        generate the right action based on the specified target,
+        source and env.  This is used by the Signature subsystem
+        (through the Executor) to obtain an (imprecise) representation
+        of the Action operation for informative purposes.
+
+
+Subclasses also supply the following methods for internal use within
+this module:
+
+    __str__()
+        Returns a string approximation of the Action; no variable
+        substitution is performed.
+        
+    execute()
+        The internal method that really, truly, actually handles the
+        execution of a command or Python function.  This is used so
+        that the __call__() methods can take care of displaying any
+        pre-substitution representations, and *then* execute an action
+        without worrying about the specific Actions involved.
+
+    strfunction()
+        Returns a substituted string representation of the Action.
+        This is used by the _ActionAction.show() command to display the
+        command/function that will be executed to generate the target(s).
+
+There is a related independent ActionCaller class that looks like a
+regular Action, and which serves as a wrapper for arbitrary functions
+that we want to let the user specify the arguments to now, but actually
+execute later (when an out-of-date check determines that it's needed to
+be executed, for example).  Objects of this class are returned by an
+ActionFactory class that provides a __call__() method as a convenient
+way for wrapping up the functions.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Action.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import dis
+import os
+import os.path
+import re
+import string
+import sys
+
+from SCons.Debug import logInstanceCreation
+import SCons.Errors
+import SCons.Util
+
+class _Null:
+    pass
+
+_null = _Null
+
+print_actions = 1
+execute_actions = 1
+print_actions_presub = 0
+
+default_ENV = None
+
+def rfile(n):
+    try:
+        return n.rfile()
+    except AttributeError:
+        return n
+
+def default_exitstatfunc(s):
+    return s
+
+try:
+    SET_LINENO = dis.SET_LINENO
+    HAVE_ARGUMENT = dis.HAVE_ARGUMENT
+except AttributeError:
+    remove_set_lineno_codes = lambda x: x
+else:
+    def remove_set_lineno_codes(code):
+        result = []
+        n = len(code)
+        i = 0
+        while i < n:
+            c = code[i]
+            op = ord(c)
+            if op >= HAVE_ARGUMENT:
+                if op != SET_LINENO:
+                    result.append(code[i:i+3])
+                i = i+3
+            else:
+                result.append(c)
+                i = i+1
+        return string.join(result, '')
+
+def _actionAppend(act1, act2):
+    # This function knows how to slap two actions together.
+    # Mainly, it handles ListActions by concatenating into
+    # a single ListAction.
+    a1 = Action(act1)
+    a2 = Action(act2)
+    if a1 is None or a2 is None:
+        raise TypeError, "Cannot append %s to %s" % (type(act1), type(act2))
+    if isinstance(a1, ListAction):
+        if isinstance(a2, ListAction):
+            return ListAction(a1.list + a2.list)
+        else:
+            return ListAction(a1.list + [ a2 ])
+    else:
+        if isinstance(a2, ListAction):
+            return ListAction([ a1 ] + a2.list)
+        else:
+            return ListAction([ a1, a2 ])
+
+def _do_create_action(act, *args, **kw):
+    """This is the actual "implementation" for the
+    Action factory method, below.  This handles the
+    fact that passing lists to Action() itself has
+    different semantics than passing lists as elements
+    of lists.
+
+    The former will create a ListAction, the latter
+    will create a CommandAction by converting the inner
+    list elements to strings."""
+
+    if isinstance(act, ActionBase):
+        return act
+    if SCons.Util.is_List(act):
+        return apply(CommandAction, (act,)+args, kw)
+    if callable(act):
+        try:
+            gen = kw['generator']
+            del kw['generator']
+        except KeyError:
+            gen = 0
+        if gen:
+            action_type = CommandGeneratorAction
+        else:
+            action_type = FunctionAction
+        return apply(action_type, (act,)+args, kw)
+    if SCons.Util.is_String(act):
+        var=SCons.Util.get_environment_var(act)
+        if var:
+            # This looks like a string that is purely an Environment
+            # variable reference, like "$FOO" or "${FOO}".  We do
+            # something special here...we lazily evaluate the contents
+            # of that Environment variable, so a user could put something
+            # like a function or a CommandGenerator in that variable
+            # instead of a string.
+            return apply(LazyAction, (var,)+args, kw)
+        commands = string.split(str(act), '\n')
+        if len(commands) == 1:
+            return apply(CommandAction, (commands[0],)+args, kw)
+        else:
+            listCmdActions = map(lambda x, args=args, kw=kw:
+                                 apply(CommandAction, (x,)+args, kw),
+                                 commands)
+            return ListAction(listCmdActions)
+    return None
+
+def Action(act, *args, **kw):
+    """A factory for action objects."""
+    if SCons.Util.is_List(act):
+        acts = map(lambda a, args=args, kw=kw:
+                          apply(_do_create_action, (a,)+args, kw),
+                   act)
+        acts = filter(None, acts)
+        if len(acts) == 1:
+            return acts[0]
+        else:
+            return ListAction(acts)
+    else:
+        return apply(_do_create_action, (act,)+args, kw)
+
+class ActionBase:
+    """Base class for all types of action objects that can be held by
+    other objects (Builders, Executors, etc.)  This provides the
+    common methods for manipulating and combining those actions."""
+    
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __cmp__(self, other):
+        return cmp(self.__dict__, other)
+
+    def genstring(self, target, source, env):
+        return str(self)
+
+    def __add__(self, other):
+        return _actionAppend(self, other)
+
+    def __radd__(self, other):
+        return _actionAppend(other, self)
+
+    def presub_lines(self, env):
+        # CommandGeneratorAction needs a real environment
+        # in order to return the proper string here, since
+        # it may call LazyAction, which looks up a key
+        # in that env.  So we temporarily remember the env here,
+        # and CommandGeneratorAction will use this env
+        # when it calls its _generate method.
+        self.presub_env = env
+        lines = string.split(str(self), '\n')
+        self.presub_env = None      # don't need this any more
+        return lines
+
+    def get_executor(self, env, overrides, tlist, slist, executor_kw):
+        """Return the Executor for this Action."""
+        return SCons.Executor.Executor(self, env, overrides,
+                                       tlist, slist, executor_kw)
+
+if SCons.Memoize.use_old_memoization():
+    _Base = ActionBase
+    class ActionBase(SCons.Memoize.Memoizer, _Base):
+        "Cache-backed version of ActionBase"
+        def __init__(self, *args, **kw):
+            apply(_Base.__init__, (self,)+args, kw)
+            SCons.Memoize.Memoizer.__init__(self)
+
+
+class _ActionAction(ActionBase):
+    """Base class for actions that create output objects."""
+    def __init__(self, strfunction=_null, presub=_null, chdir=None, exitstatfunc=None, **kw):
+        if not strfunction is _null:
+            self.strfunction = strfunction
+        if presub is _null:
+            presub = print_actions_presub
+        self.presub = presub
+        self.chdir = chdir
+        if not exitstatfunc:
+            exitstatfunc = default_exitstatfunc
+        self.exitstatfunc = exitstatfunc
+
+    def print_cmd_line(self, s, target, source, env):
+        sys.stdout.write(s + "\n")
+
+    def __call__(self, target, source, env,
+                               exitstatfunc=_null,
+                               presub=_null,
+                               show=_null,
+                               execute=_null,
+                               chdir=_null):
+        if not SCons.Util.is_List(target):
+            target = [target]
+        if not SCons.Util.is_List(source):
+            source = [source]
+        if exitstatfunc is _null: exitstatfunc = self.exitstatfunc
+        if presub is _null:  presub = self.presub
+        if show is _null:  show = print_actions
+        if execute is _null:  execute = execute_actions
+        if chdir is _null: chdir = self.chdir
+        save_cwd = None
+        if chdir:
+            save_cwd = os.getcwd()
+            try:
+                chdir = str(chdir.abspath)
+            except AttributeError:
+                if not SCons.Util.is_String(chdir):
+                    chdir = str(target[0].dir)
+        if presub:
+            t = string.join(map(str, target), ' and ')
+            l = string.join(self.presub_lines(env), '\n  ')
+            out = "Building %s with action:\n  %s\n" % (t, l)
+            sys.stdout.write(out)
+        s = None
+        if show and self.strfunction:
+            s = self.strfunction(target, source, env)
+            if s:
+                if chdir:
+                    s = ('os.chdir(%s)\n' % repr(chdir)) + s
+                try:
+                    get = env.get
+                except AttributeError:
+                    print_func = self.print_cmd_line
+                else:
+                    print_func = get('PRINT_CMD_LINE_FUNC')
+                    if not print_func:
+                        print_func = self.print_cmd_line
+                print_func(s, target, source, env)
+        stat = 0
+        if execute:
+            if chdir:
+                os.chdir(chdir)
+            try:
+                stat = self.execute(target, source, env)
+                stat = exitstatfunc(stat)
+            finally:
+                if save_cwd:
+                    os.chdir(save_cwd)
+        if s and save_cwd:
+            print_func('os.chdir(%s)' % repr(save_cwd), target, source, env)
+        return stat
+
+
+def _string_from_cmd_list(cmd_list):
+    """Takes a list of command line arguments and returns a pretty
+    representation for printing."""
+    cl = []
+    for arg in map(str, cmd_list):
+        if ' ' in arg or '\t' in arg:
+            arg = '"' + arg + '"'
+        cl.append(arg)
+    return string.join(cl)
+
+class CommandAction(_ActionAction):
+    """Class for command-execution actions."""
+    def __init__(self, cmd, cmdstr=None, *args, **kw):
+        # Cmd can actually be a list or a single item; if it's a
+        # single item it should be the command string to execute; if a
+        # list then it should be the words of the command string to
+        # execute.  Only a single command should be executed by this
+        # object; lists of commands should be handled by embedding
+        # these objects in a ListAction object (which the Action()
+        # factory above does).  cmd will be passed to
+        # Environment.subst_list() for substituting environment
+        # variables.
+        if __debug__: logInstanceCreation(self, 'Action.CommandAction')
+        apply(_ActionAction.__init__, (self,)+args, kw)
+        if SCons.Util.is_List(cmd):
+            if filter(SCons.Util.is_List, cmd):
+                raise TypeError, "CommandAction should be given only " \
+                      "a single command"
+        self.cmd_list = cmd
+        self.cmdstr = cmdstr
+
+    def __str__(self):
+        if SCons.Util.is_List(self.cmd_list):
+            return string.join(map(str, self.cmd_list), ' ')
+        return str(self.cmd_list)
+
+    def process(self, target, source, env):
+        result = env.subst_list(self.cmd_list, 0, target, source)
+        silent = None
+        ignore = None
+        while 1:
+            try: c = result[0][0][0]
+            except IndexError: c = None
+            if c == '@': silent = 1
+            elif c == '-': ignore = 1
+            else: break
+            result[0][0] = result[0][0][1:]
+        try:
+            if not result[0][0]:
+                result[0] = result[0][1:]
+        except IndexError:
+            pass
+        return result, ignore, silent
+
+    def strfunction(self, target, source, env):
+        if not self.cmdstr is None:
+            c = env.subst(self.cmdstr, 0, target, source)
+            if c:
+                return c
+        cmd_list, ignore, silent = self.process(target, source, env)
+        if silent:
+            return ''
+        return _string_from_cmd_list(cmd_list[0])
+
+    def execute(self, target, source, env):
+        """Execute a command action.
+
+        This will handle lists of commands as well as individual commands,
+        because construction variable substitution may turn a single
+        "command" into a list.  This means that this class can actually
+        handle lists of commands, even though that's not how we use it
+        externally.
+        """
+        from SCons.Subst import escape_list
+        from SCons.Util import is_String, is_List, flatten
+
+        try:
+            shell = env['SHELL']
+        except KeyError:
+            raise SCons.Errors.UserError('Missing SHELL construction variable.')
+
+        try:
+            spawn = env['SPAWN']
+        except KeyError:
+            raise SCons.Errors.UserError('Missing SPAWN construction variable.')
+
+        escape = env.get('ESCAPE', lambda x: x)
+
+        try:
+            ENV = env['ENV']
+        except KeyError:
+            global default_ENV
+            if not default_ENV:
+                import SCons.Environment
+                default_ENV = SCons.Environment.Environment()['ENV']
+            ENV = default_ENV
+
+        # Ensure that the ENV values are all strings:
+        for key, value in ENV.items():
+            if not is_String(value):
+                if is_List(value):
+                    # If the value is a list, then we assume it is a
+                    # path list, because that's a pretty common list-like
+                    # value to stick in an environment variable:
+                    value = flatten(value)
+                    ENV[key] = string.join(map(str, value), os.pathsep)
+                else:
+                    # If it isn't a string or a list, then we just coerce
+                    # it to a string, which is the proper way to handle
+                    # Dir and File instances and will produce something
+                    # reasonable for just about everything else:
+                    ENV[key] = str(value)
+
+        cmd_list, ignore, silent = self.process(target, map(rfile, source), env)
+
+        # Use len() to filter out any "command" that's zero-length.
+        for cmd_line in filter(len, cmd_list):
+            # Escape the command line for the interpreter we are using.
+            cmd_line = escape_list(cmd_line, escape)
+            result = spawn(shell, escape, cmd_line[0], cmd_line, ENV)
+            if not ignore and result:
+                return result
+        return 0
+
+    def get_contents(self, target, source, env):
+        """Return the signature contents of this action's command line.
+
+        This strips $(-$) and everything in between the string,
+        since those parts don't affect signatures.
+        """
+        from SCons.Subst import SUBST_SIG
+        cmd = self.cmd_list
+        if SCons.Util.is_List(cmd):
+            cmd = string.join(map(str, cmd))
+        else:
+            cmd = str(cmd)
+        return env.subst_target_source(cmd, SUBST_SIG, target, source)
+
+class CommandGeneratorAction(ActionBase):
+    """Class for command-generator actions."""
+    def __init__(self, generator, *args, **kw):
+        if __debug__: logInstanceCreation(self, 'Action.CommandGeneratorAction')
+        self.generator = generator
+        self.gen_kw = kw
+
+    def _generate(self, target, source, env, for_signature):
+        # ensure that target is a list, to make it easier to write
+        # generator functions:
+        if not SCons.Util.is_List(target):
+            target = [target]
+
+        ret = self.generator(target=target, source=source, env=env, for_signature=for_signature)
+        gen_cmd = apply(Action, (ret,), self.gen_kw)
+        if not gen_cmd:
+            raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret))
+        return gen_cmd
+
+    def __str__(self):
+        try:
+            env = self.presub_env or {}
+        except AttributeError:
+            env = {}
+        act = self._generate([], [], env, 1)
+        return str(act)
+
+    def genstring(self, target, source, env):
+        return self._generate(target, source, env, 1).genstring(target, source, env)
+
+    def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
+                 show=_null, execute=_null, chdir=_null):
+        act = self._generate(target, source, env, 0)
+        return act(target, source, env, exitstatfunc, presub,
+                   show, execute, chdir)
+
+    def get_contents(self, target, source, env):
+        """Return the signature contents of this action's command line.
+
+        This strips $(-$) and everything in between the string,
+        since those parts don't affect signatures.
+        """
+        return self._generate(target, source, env, 1).get_contents(target, source, env)
+
+
+
+# A LazyAction is a kind of hybrid generator and command action for
+# strings of the form "$VAR".  These strings normally expand to other
+# strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also
+# want to be able to replace them with functions in the construction
+# environment.  Consequently, we want lazy evaluation and creation of
+# an Action in the case of the function, but that's overkill in the more
+# normal case of expansion to other strings.
+#
+# So we do this with a subclass that's both a generator *and*
+# a command action.  The overridden methods all do a quick check
+# of the construction variable, and if it's a string we just call
+# the corresponding CommandAction method to do the heavy lifting.
+# If not, then we call the same-named CommandGeneratorAction method.
+# The CommandGeneratorAction methods work by using the overridden
+# _generate() method, that is, our own way of handling "generation" of
+# an action based on what's in the construction variable.
+
+class LazyAction(CommandGeneratorAction, CommandAction):
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self, var, *args, **kw):
+        if __debug__: logInstanceCreation(self, 'Action.LazyAction')
+        apply(CommandAction.__init__, (self, '$'+var)+args, kw)
+        self.var = SCons.Util.to_String(var)
+        self.gen_kw = kw
+
+    def get_parent_class(self, env):
+        c = env.get(self.var)
+        if SCons.Util.is_String(c) and not '\n' in c:
+            return CommandAction
+        return CommandGeneratorAction
+
+    def _generate_cache(self, env):
+        """__cacheable__"""
+        c = env.get(self.var, '')
+        gen_cmd = apply(Action, (c,), self.gen_kw)
+        if not gen_cmd:
+            raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c)))
+        return gen_cmd
+
+    def _generate(self, target, source, env, for_signature):
+        return self._generate_cache(env)
+
+    def __call__(self, target, source, env, *args, **kw):
+        args = (self, target, source, env) + args
+        c = self.get_parent_class(env)
+        return apply(c.__call__, args, kw)
+
+    def get_contents(self, target, source, env):
+        c = self.get_parent_class(env)
+        return c.get_contents(self, target, source, env)
+
+if not SCons.Memoize.has_metaclass:
+    _Base = LazyAction
+    class LazyAction(SCons.Memoize.Memoizer, _Base):
+        def __init__(self, *args, **kw):
+            SCons.Memoize.Memoizer.__init__(self)
+            apply(_Base.__init__, (self,)+args, kw)
+
+
+
+class FunctionAction(_ActionAction):
+    """Class for Python function actions."""
+
+    def __init__(self, execfunction, *args, **kw):
+        if __debug__: logInstanceCreation(self, 'Action.FunctionAction')
+        self.execfunction = execfunction
+        apply(_ActionAction.__init__, (self,)+args, kw)
+        self.varlist = kw.get('varlist', [])
+
+    def function_name(self):
+        try:
+            return self.execfunction.__name__
+        except AttributeError:
+            try:
+                return self.execfunction.__class__.__name__
+            except AttributeError:
+                return "unknown_python_function"
+
+    def strfunction(self, target, source, env):
+        def array(a):
+            def quote(s):
+                return '"' + str(s) + '"'
+            return '[' + string.join(map(quote, a), ", ") + ']'
+        try:
+            strfunc = self.execfunction.strfunction
+        except AttributeError:
+            pass
+        else:
+            if strfunc is None:
+                return None
+            if callable(strfunc):
+                return strfunc(target, source, env)
+        name = self.function_name()
+        tstr = array(target)
+        sstr = array(source)
+        return "%s(%s, %s)" % (name, tstr, sstr)
+
+    def __str__(self):
+        name = self.function_name()
+        if name == 'ActionCaller':
+            return str(self.execfunction)
+        return "%s(target, source, env)" % name
+
+    def execute(self, target, source, env):
+        rsources = map(rfile, source)
+        try:
+            result = self.execfunction(target=target, source=rsources, env=env)
+        except EnvironmentError, e:
+            # If an IOError/OSError happens, raise a BuildError.
+            # Report the name of the file or directory that caused the
+            # error, which might be different from the target being built
+            # (for example, failure to create the directory in which the
+            # target file will appear).
+            try: filename = e.filename
+            except AttributeError: filename = None
+            raise SCons.Errors.BuildError(node=target,
+                                          errstr=e.strerror,
+                                          filename=filename)
+        return result
+
+    def get_contents(self, target, source, env):
+        """Return the signature contents of this callable action.
+
+        By providing direct access to the code object of the
+        function, Python makes this extremely easy.  Hooray!
+
+        Unfortunately, older versions of Python include line
+        number indications in the compiled byte code.  Boo!
+        So we remove the line number byte codes to prevent
+        recompilations from moving a Python function.
+        """
+        execfunction = self.execfunction
+        try:
+            # Test if execfunction is a function.
+            code = execfunction.func_code.co_code
+        except AttributeError:
+            try:
+                # Test if execfunction is a method.
+                code = execfunction.im_func.func_code.co_code
+            except AttributeError:
+                try:
+                    # Test if execfunction is a callable object.
+                    code = execfunction.__call__.im_func.func_code.co_code
+                except AttributeError:
+                    try:
+                        # See if execfunction will do the heavy lifting for us.
+                        gc = self.execfunction.get_contents
+                    except AttributeError:
+                        # This is weird, just do the best we can.
+                        contents = str(self.execfunction)
+                    else:
+                        contents = gc(target, source, env)
+                else:
+                    contents = str(code)
+            else:
+                contents = str(code)
+        else:
+            contents = str(code)
+        contents = remove_set_lineno_codes(contents)
+        return contents + env.subst(string.join(map(lambda v: '${'+v+'}',
+                                                     self.varlist)))
+
+class ListAction(ActionBase):
+    """Class for lists of other actions."""
+    def __init__(self, list):
+        if __debug__: logInstanceCreation(self, 'Action.ListAction')
+        def list_of_actions(x):
+            if isinstance(x, ActionBase):
+                return x
+            return Action(x)
+        self.list = map(list_of_actions, list)
+
+    def genstring(self, target, source, env):
+        return string.join(map(lambda a, t=target, s=source, e=env:
+                                  a.genstring(t, s, e),
+                               self.list),
+                           '\n')
+
+    def __str__(self):
+        return string.join(map(str, self.list), '\n')
+    
+    def presub_lines(self, env):
+        return SCons.Util.flatten(map(lambda a, env=env:
+                                      a.presub_lines(env),
+                                      self.list))
+
+    def get_contents(self, target, source, env):
+        """Return the signature contents of this action list.
+
+        Simple concatenation of the signatures of the elements.
+        """
+        return string.join(map(lambda x, t=target, s=source, e=env:
+                                      x.get_contents(t, s, e),
+                               self.list),
+                           "")
+
+    def __call__(self, target, source, env, exitstatfunc=_null, presub=_null,
+                 show=_null, execute=_null, chdir=_null):
+        for act in self.list:
+            stat = act(target, source, env, exitstatfunc, presub,
+                       show, execute, chdir)
+            if stat:
+                return stat
+        return 0
+
+class ActionCaller:
+    """A class for delaying calling an Action function with specific
+    (positional and keyword) arguments until the Action is actually
+    executed.
+
+    This class looks to the rest of the world like a normal Action object,
+    but what it's really doing is hanging on to the arguments until we
+    have a target, source and env to use for the expansion.
+    """
+    def __init__(self, parent, args, kw):
+        self.parent = parent
+        self.args = args
+        self.kw = kw
+    def get_contents(self, target, source, env):
+        actfunc = self.parent.actfunc
+        try:
+            # "self.actfunc" is a function.
+            contents = str(actfunc.func_code.co_code)
+        except AttributeError:
+            # "self.actfunc" is a callable object.
+            try:
+                contents = str(actfunc.__call__.im_func.func_code.co_code)
+            except AttributeError:
+                # No __call__() method, so it might be a builtin
+                # or something like that.  Do the best we can.
+                contents = str(actfunc)
+        contents = remove_set_lineno_codes(contents)
+        return contents
+    def subst(self, s, target, source, env):
+        # Special-case hack:  Let a custom function wrapped in an
+        # ActionCaller get at the environment through which the action
+        # was called by using this hard-coded value as a special return.
+        if s == '$__env__':
+            return env
+        else:
+            return env.subst(s, 0, target, source)
+    def subst_args(self, target, source, env):
+        return map(lambda x, self=self, t=target, s=source, e=env:
+                          self.subst(x, t, s, e),
+                   self.args)
+    def subst_kw(self, target, source, env):
+        kw = {}
+        for key in self.kw.keys():
+            kw[key] = self.subst(self.kw[key], target, source, env)
+        return kw
+    def __call__(self, target, source, env):
+        args = self.subst_args(target, source, env)
+        kw = self.subst_kw(target, source, env)
+        return apply(self.parent.actfunc, args, kw)
+    def strfunction(self, target, source, env):
+        args = self.subst_args(target, source, env)
+        kw = self.subst_kw(target, source, env)
+        return apply(self.parent.strfunc, args, kw)
+    def __str__(self):
+        return apply(self.parent.strfunc, self.args, self.kw)
+
+class ActionFactory:
+    """A factory class that will wrap up an arbitrary function
+    as an SCons-executable Action object.
+
+    The real heavy lifting here is done by the ActionCaller class.
+    We just collect the (positional and keyword) arguments that we're
+    called with and give them to the ActionCaller object we create,
+    so it can hang onto them until it needs them.
+    """
+    def __init__(self, actfunc, strfunc):
+        self.actfunc = actfunc
+        self.strfunc = strfunc
+    def __call__(self, *args, **kw):
+        ac = ActionCaller(self, args, kw)
+        action = Action(ac, strfunction=ac.strfunction)
+        return action

Added: cs/scons/scons-local-0.96.92/SCons/Builder.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Builder.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Builder.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,831 @@
+"""SCons.Builder
+
+Builder object subsystem.
+
+A Builder object is a callable that encapsulates information about how
+to execute actions to create a target Node (file) from source Nodes
+(files), and how to create those dependencies for tracking.
+
+The main entry point here is the Builder() factory method.  This provides
+a procedural interface that creates the right underlying Builder object
+based on the keyword arguments supplied and the types of the arguments.
+
+The goal is for this external interface to be simple enough that the
+vast majority of users can create new Builders as necessary to support
+building new types of files in their configurations, without having to
+dive any deeper into this subsystem.
+
+The base class here is BuilderBase.  This is a concrete base class which
+does, in fact, represent most Builder objects that we (or users) create.
+
+There is (at present) one subclasses:
+
+    MultiStepBuilder
+
+        This is a Builder that knows how to "chain" Builders so that
+        users can specify a source file that requires multiple steps
+        to turn into a target file.  A canonical example is building a
+        program from yacc input file, which requires invoking a builder
+        to turn the .y into a .c, the .c into a .o, and the .o into an
+        executable program.
+
+There is also two proxies that look like Builders:
+
+    CompositeBuilder
+
+        This proxies for a Builder with an action that is actually a
+        dictionary that knows how to map file suffixes to a specific
+        action.  This is so that we can invoke different actions
+        (compilers, compile options) for different flavors of source
+        files.
+
+    ListBuilder
+
+        This proxies for a Builder *invocation* where the target
+        is a list of files, not a single file.
+
+Builders and their proxies have the following public interface methods
+used by other modules:
+
+    __call__()
+        THE public interface.  Calling a Builder object (with the
+        use of internal helper methods) sets up the target and source
+        dependencies, appropriate mapping to a specific action, and the
+        environment manipulation necessary for overridden construction
+        variable.  This also takes care of warning about possible mistakes
+        in keyword arguments.
+
+    targets()
+        Returns the list of targets for a specific builder instance.
+
+    add_emitter()
+        Adds an emitter for a specific file suffix, used by some Tool
+        modules to specify that (for example) a yacc invocation on a .y
+        can create a .h *and* a .c file.
+
+    add_action()
+        Adds an action for a specific file suffix, heavily used by
+        Tool modules to add their specific action(s) for turning
+        a source file into an object file to the global static
+        and shared object file Builders.
+
+There are the following methods for internal use within this module:
+
+    _execute()
+        The internal method that handles the heavily lifting when a
+        Builder is called.  This is used so that the __call__() methods
+        can set up warning about possible mistakes in keyword-argument
+        overrides, and *then* execute all of the steps necessary so that
+        the warnings only occur once.
+
+    get_name()
+        Returns the Builder's name within a specific Environment,
+        primarily used to try to return helpful information in error
+        messages.
+
+    adjust_suffix()
+    get_prefix()
+    get_suffix()
+    get_src_suffix()
+    set_src_suffix()
+        Miscellaneous stuff for handling the prefix and suffix
+        manipulation we use in turning source file names into target
+        file names.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Builder.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import UserDict
+import UserList
+
+import SCons.Action
+from SCons.Debug import logInstanceCreation
+from SCons.Errors import InternalError, UserError
+import SCons.Executor
+import SCons.Node
+import SCons.Node.FS
+import SCons.Util
+import SCons.Warnings
+
+class _Null:
+    pass
+
+_null = _Null
+
+class DictCmdGenerator(SCons.Util.Selector):
+    """This is a callable class that can be used as a
+    command generator function.  It holds on to a dictionary
+    mapping file suffixes to Actions.  It uses that dictionary
+    to return the proper action based on the file suffix of
+    the source file."""
+
+    def src_suffixes(self):
+        return self.keys()
+
+    def add_action(self, suffix, action):
+        """Add a suffix-action pair to the mapping.
+        """
+        self[suffix] = action
+
+    def __call__(self, target, source, env, for_signature):
+        if not source:
+            return []
+
+        ext = None
+        for src in map(str, source):
+            my_ext = SCons.Util.splitext(src)[1]
+            if ext and my_ext != ext:
+                raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" % (repr(map(str, target)), src, ext, my_ext))
+            ext = my_ext
+
+        if not ext:
+            raise UserError("While building `%s': Cannot deduce file extension from source files: %s" % (repr(map(str, target)), repr(map(str, source))))
+
+        try:
+            ret = SCons.Util.Selector.__call__(self, env, source)
+        except KeyError, e:
+            raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e[0], e[1], e[2]))
+        if ret is None:
+            raise UserError("While building `%s': Don't know how to build a file with suffix `%s'." % (repr(map(str, target)), ext))
+        return ret
+
+class CallableSelector(SCons.Util.Selector):
+    """A callable dictionary that will, in turn, call the value it
+    finds if it can."""
+    def __call__(self, env, source):
+        value = SCons.Util.Selector.__call__(self, env, source)
+        if callable(value):
+            value = value(env, source)
+        return value
+
+class DictEmitter(SCons.Util.Selector):
+    """A callable dictionary that maps file suffixes to emitters.
+    When called, it finds the right emitter in its dictionary for the
+    suffix of the first source file, and calls that emitter to get the
+    right lists of targets and sources to return.  If there's no emitter
+    for the suffix in its dictionary, the original target and source are
+    returned.
+    """
+    def __call__(self, target, source, env):
+        emitter = SCons.Util.Selector.__call__(self, env, source)
+        if emitter:
+            target, source = emitter(target, source, env)
+        return (target, source)
+
+class ListEmitter(UserList.UserList):
+    """A callable list of emitters that calls each in sequence,
+    returning the result.
+    """
+    def __call__(self, target, source, env):
+        for e in self.data:
+            target, source = e(target, source, env)
+        return (target, source)
+
+# These are a common errors when calling a Builder;
+# they are similar to the 'target' and 'source' keyword args to builders,
+# so we issue warnings when we see them.  The warnings can, of course,
+# be disabled.
+misleading_keywords = {
+    'targets'   : 'target',
+    'sources'   : 'source',
+}
+
+class OverrideWarner(UserDict.UserDict):
+    """A class for warning about keyword arguments that we use as
+    overrides in a Builder call.
+
+    This class exists to handle the fact that a single MultiStepBuilder
+    call can actually invoke multiple builders as a result of a single
+    user-level Builder call.  This class only emits the warnings once,
+    no matter how many Builders are invoked.
+    """
+    def __init__(self, dict):
+        UserDict.UserDict.__init__(self, dict)
+        if __debug__: logInstanceCreation(self, 'Builder.OverrideWarner')
+        self.already_warned = None
+    def warn(self):
+        if self.already_warned:
+            return
+        for k in self.keys():
+            try:
+                alt = misleading_keywords[k]
+            except KeyError:
+                pass
+            else:
+                SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning,
+                                    "Did you mean to use `%s' instead of `%s'?" % (alt, k))
+        self.already_warned = 1
+
+def Builder(**kw):
+    """A factory for builder objects."""
+    composite = None
+    if kw.has_key('generator'):
+        if kw.has_key('action'):
+            raise UserError, "You must not specify both an action and a generator."
+        kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'])
+        del kw['generator']
+    elif kw.has_key('action'):
+        if SCons.Util.is_Dict(kw['action']):
+            composite = DictCmdGenerator(kw['action'])
+            kw['action'] = SCons.Action.CommandGeneratorAction(composite)
+            kw['src_suffix'] = composite.src_suffixes()
+        else:
+            kw['action'] = SCons.Action.Action(kw['action'])
+
+    if kw.has_key('emitter'):
+        emitter = kw['emitter']
+        if SCons.Util.is_String(emitter):
+            # This allows users to pass in an Environment
+            # variable reference (like "$FOO") as an emitter.
+            # We will look in that Environment variable for
+            # a callable to use as the actual emitter.
+            var = SCons.Util.get_environment_var(emitter)
+            if not var:
+                raise UserError, "Supplied emitter '%s' does not appear to refer to an Environment variable" % emitter
+            kw['emitter'] = EmitterProxy(var)
+        elif SCons.Util.is_Dict(emitter):
+            kw['emitter'] = DictEmitter(emitter)
+        elif SCons.Util.is_List(emitter):
+            kw['emitter'] = ListEmitter(emitter)
+
+    if kw.has_key('src_builder'):
+        ret = apply(MultiStepBuilder, (), kw)
+    else:
+        ret = apply(BuilderBase, (), kw)
+
+    if not composite is None:
+        ret = CompositeBuilder(ret, composite)
+
+    return ret
+
+def _node_errors(builder, env, tlist, slist):
+    """Validate that the lists of target and source nodes are
+    legal for this builder and environment.  Raise errors or
+    issue warnings as appropriate.
+    """
+
+    # First, figure out if there are any errors in the way the targets
+    # were specified.
+    for t in tlist:
+        if t.side_effect:
+            raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
+        if t.has_explicit_builder():
+            if not t.env is None and not t.env is env:
+                action = t.builder.action
+                t_contents = action.get_contents(tlist, slist, t.env)
+                contents = action.get_contents(tlist, slist, env)
+
+                if t_contents == contents:
+                    SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning,
+                                        "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s"%(str(t), action.genstring(tlist, slist, t.env)))
+
+                else:
+                    raise UserError, "Two environments with different actions were specified for the same target: %s"%str(t)
+
+            if builder.multi:
+                if t.builder != builder:
+                    if isinstance(t.builder, ListBuilder) and isinstance(builder, ListBuilder) and t.builder.builder == builder.builder:
+                        raise UserError, "Two different target sets have a target in common: %s"%str(t)
+                    else:
+                        raise UserError, "Two different builders (%s and %s) were specified for the same target: %s"%(t.builder.get_name(env), builder.get_name(env), str(t))
+                elif isinstance(t.builder, ListBuilder) ^ isinstance(builder, ListBuilder):
+                    raise UserError, "Cannot build same target `%s' as singular and list"%str(t)
+            elif t.sources != slist:
+                raise UserError, "Multiple ways to build the same target were specified for: %s  (from %s and from %s)" % (str(t), map(str,t.sources), map(str,slist))
+
+    if builder.single_source:
+        if len(slist) > 1:
+            raise UserError, "More than one source given for single-source builder: targets=%s sources=%s" % (map(str,tlist), map(str,slist))
+
+class EmitterProxy:
+    """This is a callable class that can act as a
+    Builder emitter.  It holds on to a string that
+    is a key into an Environment dictionary, and will
+    look there at actual build time to see if it holds
+    a callable.  If so, we will call that as the actual
+    emitter."""
+    def __init__(self, var):
+        self.var = SCons.Util.to_String(var)
+
+    def __call__(self, target, source, env):
+        emitter = self.var
+
+        # Recursively substitute the variable.
+        # We can't use env.subst() because it deals only
+        # in strings.  Maybe we should change that?
+        while SCons.Util.is_String(emitter) and env.has_key(emitter):
+            emitter = env[emitter]
+        if callable(emitter):
+            target, source = emitter(target, source, env)
+        elif SCons.Util.is_List(emitter):
+            for e in emitter:
+                target, source = e(target, source, env)
+
+        return (target, source)
+
+
+    def __cmp__(self, other):
+        return cmp(self.var, other.var)
+
+class BuilderBase:
+    """Base class for Builders, objects that create output
+    nodes (files) from input nodes (files).
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self,  action = None,
+                        prefix = '',
+                        suffix = '',
+                        src_suffix = '',
+                        target_factory = None,
+                        source_factory = None,
+                        target_scanner = None,
+                        source_scanner = None,
+                        emitter = None,
+                        multi = 0,
+                        env = None,
+                        single_source = 0,
+                        name = None,
+                        chdir = _null,
+                        is_explicit = 1,
+                        **overrides):
+        if __debug__: logInstanceCreation(self, 'Builder.BuilderBase')
+        self.action = action
+        self.multi = multi
+        if SCons.Util.is_Dict(prefix):
+            prefix = CallableSelector(prefix)
+        self.prefix = prefix
+        if SCons.Util.is_Dict(suffix):
+            suffix = CallableSelector(suffix)
+        self.env = env
+        self.single_source = single_source
+        if overrides.has_key('overrides'):
+            SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
+                "The \"overrides\" keyword to Builder() creation has been deprecated;\n" +\
+                "\tspecify the items as keyword arguments to the Builder() call instead.")
+            overrides.update(overrides['overrides'])
+            del overrides['overrides']
+        if overrides.has_key('scanner'):
+            SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
+                                "The \"scanner\" keyword to Builder() creation has been deprecated;\n"
+                                "\tuse: source_scanner or target_scanner as appropriate.")
+            del overrides['scanner']
+        self.overrides = overrides
+
+        self.set_suffix(suffix)
+        self.set_src_suffix(src_suffix)
+
+        self.target_factory = target_factory
+        self.source_factory = source_factory
+        self.target_scanner = target_scanner
+        self.source_scanner = source_scanner
+
+        self.emitter = emitter
+
+        # Optional Builder name should only be used for Builders
+        # that don't get attached to construction environments.
+        if name:
+            self.name = name
+        self.executor_kw = {}
+        if not chdir is _null:
+            self.executor_kw['chdir'] = chdir
+        self.is_explicit = is_explicit
+
+    def __nonzero__(self):
+        raise InternalError, "Do not test for the Node.builder attribute directly; use Node.has_builder() instead"
+
+    def get_name(self, env):
+        """Attempts to get the name of the Builder.
+
+        Look at the BUILDERS variable of env, expecting it to be a
+        dictionary containing this Builder, and return the key of the
+        dictionary.  If there's no key, then return a directly-configured
+        name (if there is one) or the name of the class (by default)."""
+
+        try:
+            index = env['BUILDERS'].values().index(self)
+            return env['BUILDERS'].keys()[index]
+        except (AttributeError, KeyError, TypeError, ValueError):
+            try:
+                return self.name
+            except AttributeError:
+                return str(self.__class__)
+
+    def __cmp__(self, other):
+        return cmp(self.__dict__, other.__dict__)
+
+    def splitext(self, path, env=None):
+        if not env:
+            env = self.env
+        if env:
+            matchsuf = filter(lambda S,path=path: path[-len(S):] == S,
+                              self.src_suffixes(env))
+            if matchsuf:
+                suf = max(map(None, map(len, matchsuf), matchsuf))[1]
+                return [path[:-len(suf)], path[-len(suf):]]
+        return SCons.Util.splitext(path)
+
+    def get_single_executor(self, env, tlist, slist, executor_kw):
+        if not self.action:
+            raise UserError, "Builder %s must have an action to build %s."%(self.get_name(env or self.env), map(str,tlist))
+        return self.action.get_executor(env or self.env,
+                                        [],  # env already has overrides
+                                        tlist,
+                                        slist,
+                                        executor_kw)
+
+    def get_multi_executor(self, env, tlist, slist, executor_kw):
+        try:
+            executor = tlist[0].get_executor(create = 0)
+        except (AttributeError, IndexError):
+            return self.get_single_executor(env, tlist, slist, executor_kw)
+        else:
+            executor.add_sources(slist)
+            return executor
+
+    def _create_nodes(self, env, target = None, source = None):
+        """Create and return lists of target and source nodes.
+        """
+        def _adjustixes(files, pre, suf):
+            if not files:
+                return []
+            result = []
+            if not SCons.Util.is_List(files):
+                files = [files]
+
+            for f in files:
+                if SCons.Util.is_String(f):
+                    f = SCons.Util.adjustixes(f, pre, suf)
+                result.append(f)
+            return result
+
+        src_suf = self.get_src_suffix(env)
+
+        target_factory = env.get_factory(self.target_factory)
+        source_factory = env.get_factory(self.source_factory)
+
+        source = _adjustixes(source, None, src_suf)
+        slist = env.arg2nodes(source, source_factory)
+
+        pre = self.get_prefix(env, slist)
+        suf = self.get_suffix(env, slist)
+
+        if target is None:
+            try:
+                t_from_s = slist[0].target_from_source
+            except AttributeError:
+                raise UserError("Do not know how to create a target from source `%s'" % slist[0])
+            except IndexError:
+                tlist = []
+            else:
+                splitext = lambda S,self=self,env=env: self.splitext(S,env)
+                tlist = [ t_from_s(pre, suf, splitext) ]
+        else:
+            target = _adjustixes(target, pre, suf)
+            tlist = env.arg2nodes(target, target_factory)
+
+        if self.emitter:
+            # The emitter is going to do str(node), but because we're
+            # being called *from* a builder invocation, the new targets
+            # don't yet have a builder set on them and will look like
+            # source files.  Fool the emitter's str() calls by setting
+            # up a temporary builder on the new targets.
+            new_targets = []
+            for t in tlist:
+                if not t.is_derived():
+                    t.builder_set(self)
+                    new_targets.append(t)
+
+            target, source = self.emitter(target=tlist, source=slist, env=env)
+
+            # Now delete the temporary builders that we attached to any
+            # new targets, so that _node_errors() doesn't do weird stuff
+            # to them because it thinks they already have builders.
+            for t in new_targets:
+                if t.builder is self:
+                    # Only delete the temporary builder if the emitter
+                    # didn't change it on us.
+                    t.builder_set(None)
+
+            # Have to call arg2nodes yet again, since it is legal for
+            # emitters to spit out strings as well as Node instances.
+            tlist = env.arg2nodes(target, target_factory)
+            slist = env.arg2nodes(source, source_factory)
+
+        tlist = map(lambda n: n.disambiguate(), tlist)
+        slist = map(lambda n: n.disambiguate(), slist)
+
+        return tlist, slist
+
+    def _execute(self, env, target, source, overwarn={}, executor_kw={}):
+        # We now assume that target and source are lists or None.
+        if self.single_source and len(source) > 1 and target is None:
+            result = []
+            if target is None: target = [None]*len(source)
+            for tgt, src in zip(target, source):
+                if not tgt is None: tgt = [tgt]
+                if not src is None: src = [src]
+                result.extend(self._execute(env, tgt, src, overwarn))
+            return result
+
+        overwarn.warn()
+        
+        tlist, slist = self._create_nodes(env, target, source)
+
+        if len(tlist) == 1:
+            builder = self
+        else:
+            builder = ListBuilder(self, env, tlist)
+
+        # Check for errors with the specified target/source lists.
+        _node_errors(builder, env, tlist, slist)
+
+        # The targets are fine, so find or make the appropriate Executor to
+        # build this particular list of targets from this particular list of
+        # sources.
+        if builder.multi:
+            get_executor = builder.get_multi_executor
+        else:
+            get_executor = builder.get_single_executor
+        executor = get_executor(env, tlist, slist, executor_kw)
+
+        # Now set up the relevant information in the target Nodes themselves.
+        for t in tlist:
+            t.cwd = env.fs.getcwd()
+            t.builder_set(builder)
+            t.env_set(env)
+            t.add_source(slist)
+            t.set_executor(executor)
+            t.set_explicit(builder.is_explicit)
+
+        return SCons.Node.NodeList(tlist)
+
+    def __call__(self, env, target=None, source=None, chdir=_null, **kw):
+        # We now assume that target and source are lists or None.
+        # The caller (typically Environment.BuilderWrapper) is
+        # responsible for converting any scalar values to lists.
+        if chdir is _null:
+            ekw = self.executor_kw
+        else:
+            ekw = self.executor_kw.copy()
+            ekw['chdir'] = chdir
+        if kw:
+            if self.overrides:
+                env_kw = self.overrides.copy()
+                env_kw.update(kw)
+            else:
+                env_kw = kw
+        else:
+            env_kw = self.overrides
+        env = env.Override(env_kw)
+        return self._execute(env, target, source, OverrideWarner(kw), ekw)
+
+    def adjust_suffix(self, suff):
+        if suff and not suff[0] in [ '.', '_', '$' ]:
+            return '.' + suff
+        return suff
+
+    def get_prefix(self, env, sources=[]):
+        prefix = self.prefix
+        if callable(prefix):
+            prefix = prefix(env, sources)
+        return env.subst(prefix)
+
+    def set_suffix(self, suffix):
+        if not callable(suffix):
+            suffix = self.adjust_suffix(suffix)
+        self.suffix = suffix
+
+    def get_suffix(self, env, sources=[]):
+        suffix = self.suffix
+        if callable(suffix):
+            suffix = suffix(env, sources)
+        return env.subst(suffix)
+
+    def src_suffixes(self, env):
+        "__cacheable__"
+        return map(lambda x, s=self, e=env: e.subst(x), self.src_suffix)
+
+    def set_src_suffix(self, src_suffix):
+        if not src_suffix:
+            src_suffix = []
+        elif not SCons.Util.is_List(src_suffix):
+            src_suffix = [ src_suffix ]
+        adjust = lambda suf, s=self: \
+                        callable(suf) and suf or s.adjust_suffix(suf)
+        self.src_suffix = map(adjust, src_suffix)
+
+    def get_src_suffix(self, env):
+        """Get the first src_suffix in the list of src_suffixes."""
+        ret = self.src_suffixes(env)
+        if not ret:
+            return ''
+        return ret[0]
+
+    def targets(self, node):
+        """Return the list of targets for this builder instance.
+
+        For most normal builders, this is just the supplied node.
+        """
+        return [ node ]
+
+    def add_emitter(self, suffix, emitter):
+        """Add a suffix-emitter mapping to this Builder.
+
+        This assumes that emitter has been initialized with an
+        appropriate dictionary type, and will throw a TypeError if
+        not, so the caller is responsible for knowing that this is an
+        appropriate method to call for the Builder in question.
+        """
+        self.emitter[suffix] = emitter
+
+if SCons.Memoize.use_old_memoization():
+    _Base = BuilderBase
+    class BuilderBase(SCons.Memoize.Memoizer, _Base):
+        "Cache-backed version of BuilderBase"
+        def __init__(self, *args, **kw):
+            apply(_Base.__init__, (self,)+args, kw)
+            SCons.Memoize.Memoizer.__init__(self)
+
+class ListBuilder(SCons.Util.Proxy):
+    """A Proxy to support building an array of targets (for example,
+    foo.o and foo.h from foo.y) from a single Action execution.
+    """
+
+    def __init__(self, builder, env, tlist):
+        if __debug__: logInstanceCreation(self, 'Builder.ListBuilder')
+        SCons.Util.Proxy.__init__(self, builder)
+        self.builder = builder
+        self.target_scanner = builder.target_scanner
+        self.source_scanner = builder.source_scanner
+        self.env = env
+        self.tlist = tlist
+        self.multi = builder.multi
+        self.single_source = builder.single_source
+
+    def targets(self, node):
+        """Return the list of targets for this builder instance.
+        """
+        return self.tlist
+
+    def get_name(self, env):
+        """Attempts to get the name of the Builder."""
+
+        return "ListBuilder(%s)" % self.builder.get_name(env)
+
+class MultiStepBuilder(BuilderBase):
+    """This is a builder subclass that can build targets in
+    multiple steps.  The src_builder parameter to the constructor
+    accepts a builder that is called to build sources supplied to
+    this builder.  The targets of that first build then become
+    the sources of this builder.
+
+    If this builder has a src_suffix supplied, then the src_builder
+    builder is NOT invoked if the suffix of a source file matches
+    src_suffix.
+    """
+    def __init__(self,  src_builder,
+                        action = None,
+                        prefix = '',
+                        suffix = '',
+                        src_suffix = '',
+                        target_factory = None,
+                        source_factory = None,
+                        target_scanner = None,
+                        source_scanner = None,
+                        emitter=None,
+                        single_source=0):
+        if __debug__: logInstanceCreation(self, 'Builder.MultiStepBuilder')
+        BuilderBase.__init__(self, action, prefix, suffix, src_suffix,
+                             target_factory, source_factory,
+                             target_scanner, source_scanner, emitter,
+                             single_source = single_source)
+        if not SCons.Util.is_List(src_builder):
+            src_builder = [ src_builder ]
+        self.src_builder = src_builder
+
+    def _get_sdict(self, env):
+        "__cacheable__"
+        sdict = {}
+        for bld in self.src_builder:
+            if SCons.Util.is_String(bld):
+                try:
+                    bld = env['BUILDERS'][bld]
+                except KeyError:
+                    continue
+            for suf in bld.src_suffixes(env):
+                sdict[suf] = bld
+        return sdict
+        
+    def _execute(self, env, target, source, overwarn={}, executor_kw={}):
+        # We now assume that target and source are lists or None.
+        source_factory = env.get_factory(self.source_factory)
+        slist = env.arg2nodes(source, source_factory)
+        final_sources = []
+
+        sdict = self._get_sdict(env)
+
+        src_suffixes = self.src_suffixes(env)
+
+        lengths_dict = {}
+        for l in map(len, src_suffixes):
+            lengths_dict[l] = None
+        lengths = lengths_dict.keys()
+
+        def match_src_suffix(node, src_suffixes=src_suffixes, lengths=lengths):
+            node_suffixes = map(lambda l, n=node: n.name[-l:], lengths)
+            for suf in src_suffixes:
+                if suf in node_suffixes:
+                    return suf
+            return None
+
+        for snode in slist:
+            match_suffix = match_src_suffix(snode)
+            if match_suffix:
+                try:
+                    bld = sdict[match_suffix]
+                except KeyError:
+                    final_sources.append(snode)
+                else:
+                    tlist = bld._execute(env, None, [snode], overwarn)
+                    # If the subsidiary Builder returned more than one
+                    # target, then filter out any sources that this
+                    # Builder isn't capable of building.
+                    if len(tlist) > 1:
+                        tlist = filter(match_src_suffix, tlist)
+                    final_sources.extend(tlist)
+            else:
+                final_sources.append(snode)
+
+        return BuilderBase._execute(self, env, target, final_sources, overwarn)
+
+    def get_src_builders(self, env):
+        """Return all the src_builders for this Builder.
+
+        This is essentially a recursive descent of the src_builder "tree."
+        """
+        ret = []
+        for bld in self.src_builder:
+            if SCons.Util.is_String(bld):
+                # All Environments should have a BUILDERS
+                # variable, so no need to check for it.
+                try:
+                    bld = env['BUILDERS'][bld]
+                except KeyError:
+                    continue
+            ret.append(bld)
+        return ret
+
+    def src_suffixes(self, env):
+        """Return a list of the src_suffix attributes for all
+        src_builders of this Builder.
+        __cacheable__
+        """
+        suffixes = BuilderBase.src_suffixes(self, env)
+        for builder in self.get_src_builders(env):
+            suffixes.extend(builder.src_suffixes(env))
+        return suffixes
+
+class CompositeBuilder(SCons.Util.Proxy):
+    """A Builder Proxy whose main purpose is to always have
+    a DictCmdGenerator as its action, and to provide access
+    to the DictCmdGenerator's add_action() method.
+    """
+
+    def __init__(self, builder, cmdgen):
+        if __debug__: logInstanceCreation(self, 'Builder.CompositeBuilder')
+        SCons.Util.Proxy.__init__(self, builder)
+
+        # cmdgen should always be an instance of DictCmdGenerator.
+        self.cmdgen = cmdgen
+        self.builder = builder
+
+    def add_action(self, suffix, action):
+        self.cmdgen.add_action(suffix, action)
+        self.set_src_suffix(self.cmdgen.src_suffixes())

Added: cs/scons/scons-local-0.96.92/SCons/Conftest.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Conftest.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Conftest.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,506 @@
+"""SCons.Conftest
+
+Autoconf-like configuration support; low level implementation of tests.
+"""
+
+#
+# Copyright (c) 2003 Stichting NLnet Labs
+# Copyright (c) 2001, 2002, 2003 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+#
+# The purpose of this module is to define how a check is to be performed.
+# Use one of the Check...() functions below.
+#
+
+#
+# A context class is used that defines functions for carrying out the tests,
+# logging and messages.  The following methods and members must be present:
+#
+# context.Display(msg)  Function called to print messages that are normally
+#                       displayed for the user.  Newlines are explicitly used.
+#                       The text should also be written to the logfile!
+#
+# context.Log(msg)      Function called to write to a log file.
+#
+# context.BuildProg(text, ext)
+#                       Function called to build a program, using "ext" for the
+#                       file extention.  Must return an empty string for
+#                       success, an error message for failure.
+#                       For reliable test results building should be done just
+#                       like an actual program would be build, using the same
+#                       command and arguments (including configure results so
+#                       far).
+#
+# context.CompileProg(text, ext)
+#                       Function called to compile a program, using "ext" for
+#                       the file extention.  Must return an empty string for
+#                       success, an error message for failure.
+#                       For reliable test results compiling should be done just
+#                       like an actual source file would be compiled, using the
+#                       same command and arguments (including configure results
+#                       so far).
+#
+# context.AppendLIBS(lib_name_list)
+#                       Append "lib_name_list" to the value of LIBS.
+#                       "lib_namelist" is a list of strings.
+#                       Return the value of LIBS before changing it (any type
+#                       can be used, it is passed to SetLIBS() later.
+#
+# context.SetLIBS(value)
+#                       Set LIBS to "value".  The type of "value" is what
+#                       AppendLIBS() returned.
+#                       Return the value of LIBS before changing it (any type
+#                       can be used, it is passed to SetLIBS() later.
+#
+# context.headerfilename
+#                       Name of file to append configure results to, usually
+#                       "confdefs.h".
+#                       The file must not exist or be empty when starting.
+#                       Empty or None to skip this (some tests will not work!).
+#
+# context.config_h      (may be missing). If present, must be a string, which
+#                       will be filled with the contents of a config_h file.
+#
+# context.vardict       Dictionary holding variables used for the tests and
+#                       stores results from the tests, used for the build
+#                       commands.
+#                       Normally contains "CC", "LIBS", "CPPFLAGS", etc.
+#
+# context.havedict      Dictionary holding results from the tests that are to
+#                       be used inside a program.
+#                       Names often start with "HAVE_".  These are zero
+#                       (feature not present) or one (feature present).  Other
+#                       variables may have any value, e.g., "PERLVERSION" can
+#                       be a number and "SYSTEMNAME" a string.
+#
+
+import re
+import string
+from types import IntType
+
+#
+# PUBLIC VARIABLES
+#
+
+LogInputFiles = 1    # Set that to log the input files in case of a failed test
+LogErrorMessages = 1 # Set that to log Conftest-generated error messages
+
+#
+# PUBLIC FUNCTIONS
+#
+
+# Generic remarks:
+# - When a language is specified which is not supported the test fails.  The
+#   message is a bit different, because not all the arguments for the normal
+#   message are available yet (chicken-egg problem).
+
+
+def CheckBuilder(context, text = None, language = None):
+    """
+    Configure check to see if the compiler works.
+    Note that this uses the current value of compiler and linker flags, make
+    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+    "language" should be "C" or "C++" and is used to select the compiler.
+    Default is "C".
+    "text" may be used to specify the code to be build.
+    Returns an empty string for success, an error message for failure.
+    """
+    lang, suffix, msg = _lang2suffix(language)
+    if msg:
+        context.Display("%s\n" % msg)
+        return msg
+
+    if not text:
+        text = """
+int main() {
+    return 0;
+}
+"""
+
+    context.Display("Checking if building a %s file works... " % lang)
+    ret = context.BuildProg(text, suffix)
+    _YesNoResult(context, ret, None, text)
+    return ret
+
+
+def CheckFunc(context, function_name, header = None, language = None):
+    """
+    Configure check for a function "function_name".
+    "language" should be "C" or "C++" and is used to select the compiler.
+    Default is "C".
+    Optional "header" can be defined to define a function prototype, include a
+    header file or anything else that comes before main().
+    Sets HAVE_function_name in context.havedict according to the result.
+    Note that this uses the current value of compiler and linker flags, make
+    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+    Returns an empty string for success, an error message for failure.
+    """
+
+    # Remarks from autoconf:
+    # - Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h>
+    #   which includes <sys/select.h> which contains a prototype for select.
+    #   Similarly for bzero.
+    # - assert.h is included to define __stub macros and hopefully few
+    #   prototypes, which can conflict with char $1(); below.
+    # - Override any gcc2 internal prototype to avoid an error.
+    # - We use char for the function declaration because int might match the
+    #   return type of a gcc2 builtin and then its argument prototype would
+    #   still apply.
+    # - The GNU C library defines this for functions which it implements to
+    #   always fail with ENOSYS.  Some functions are actually named something
+    #   starting with __ and the normal name is an alias.
+
+    if context.headerfilename:
+        includetext = '#include "%s"' % context.headerfilename
+    else:
+        includetext = ''
+    if not header:
+        header = """
+#ifdef __cplusplus
+extern "C"
+#endif
+char %s();""" % function_name
+
+    lang, suffix, msg = _lang2suffix(language)
+    if msg:
+        context.Display("Cannot check for %s(): %s\n" % (function_name, msg))
+        return msg
+
+    text = """
+%(include)s
+#include <assert.h>
+%(hdr)s
+
+int main() {
+#if defined (__stub_%(name)s) || defined (__stub___%(name)s)
+  fail fail fail
+#else
+  %(name)s();
+#endif
+
+  return 0;
+}
+""" % { 'name': function_name,
+        'include': includetext,
+        'hdr': header }
+
+    context.Display("Checking for %s function %s()... " % (lang, function_name))
+    ret = context.BuildProg(text, suffix)
+    _YesNoResult(context, ret, "HAVE_" + function_name, text)
+    return ret
+
+
+def CheckHeader(context, header_name, header = None, language = None,
+                                                        include_quotes = None):
+    """
+    Configure check for a C or C++ header file "header_name".
+    Optional "header" can be defined to do something before including the
+    header file (unusual, supported for consistency).
+    "language" should be "C" or "C++" and is used to select the compiler.
+    Default is "C".
+    Sets HAVE_header_name in context.havedict according to the result.
+    Note that this uses the current value of compiler and linker flags, make
+    sure $CFLAGS and $CPPFLAGS are set correctly.
+    Returns an empty string for success, an error message for failure.
+    """
+    # Why compile the program instead of just running the preprocessor?
+    # It is possible that the header file exists, but actually using it may
+    # fail (e.g., because it depends on other header files).  Thus this test is
+    # more strict.  It may require using the "header" argument.
+    #
+    # Use <> by default, because the check is normally used for system header
+    # files.  SCons passes '""' to overrule this.
+
+    # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+    if context.headerfilename:
+        includetext = '#include "%s"\n' % context.headerfilename
+    else:
+        includetext = ''
+    if not header:
+        header = ""
+
+    lang, suffix, msg = _lang2suffix(language)
+    if msg:
+        context.Display("Cannot check for header file %s: %s\n"
+                                                          % (header_name, msg))
+        return msg
+
+    if not include_quotes:
+        include_quotes = "<>"
+
+    text = "%s%s\n#include %s%s%s\n\n" % (includetext, header,
+                             include_quotes[0], header_name, include_quotes[1])
+
+    context.Display("Checking for %s header file %s... " % (lang, header_name))
+    ret = context.CompileProg(text, suffix)
+    _YesNoResult(context, ret, "HAVE_" + header_name, text)
+    return ret
+
+
+def CheckType(context, type_name, fallback = None,
+                                               header = None, language = None):
+    """
+    Configure check for a C or C++ type "type_name".
+    Optional "header" can be defined to include a header file.
+    "language" should be "C" or "C++" and is used to select the compiler.
+    Default is "C".
+    Sets HAVE_type_name in context.havedict according to the result.
+    Note that this uses the current value of compiler and linker flags, make
+    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+    Returns an empty string for success, an error message for failure.
+    """
+
+    # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+    if context.headerfilename:
+        includetext = '#include "%s"' % context.headerfilename
+    else:
+        includetext = ''
+    if not header:
+        header = ""
+
+    lang, suffix, msg = _lang2suffix(language)
+    if msg:
+        context.Display("Cannot check for %s type: %s\n" % (type_name, msg))
+        return msg
+
+    # Remarks from autoconf about this test:
+    # - Grepping for the type in include files is not reliable (grep isn't
+    #   portable anyway).
+    # - Using "TYPE my_var;" doesn't work for const qualified types in C++.
+    #   Adding an initializer is not valid for some C++ classes.
+    # - Using the type as parameter to a function either fails for K&$ C or for
+    #   C++.
+    # - Using "TYPE *my_var;" is valid in C for some types that are not
+    #   declared (struct something).
+    # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable.
+    # - Using the previous two together works reliably.
+    text = """
+%(include)s
+%(header)s
+
+int main() {
+  if ((%(name)s *) 0)
+    return 0;
+  if (sizeof (%(name)s))
+    return 0;
+}
+""" % { 'include': includetext,
+        'header': header,
+        'name': type_name }
+
+    context.Display("Checking for %s type %s... " % (lang, type_name))
+    ret = context.BuildProg(text, suffix)
+    _YesNoResult(context, ret, "HAVE_" + type_name, text)
+    if ret and fallback and context.headerfilename:
+        f = open(context.headerfilename, "a")
+        f.write("typedef %s %s;\n" % (fallback, type_name))
+        f.close()
+
+    return ret
+
+
+def CheckLib(context, libs, func_name, header = None,
+                 extra_libs = None, call = None, language = None, autoadd = 1):
+    """
+    Configure check for a C or C++ libraries "libs".  Searches through
+    the list of libraries, until one is found where the test succeeds.
+    Tests if "func_name" or "call" exists in the library.  Note: if it exists
+    in another library the test succeeds anyway!
+    Optional "header" can be defined to include a header file.  If not given a
+    default prototype for "func_name" is added.
+    Optional "extra_libs" is a list of library names to be added after
+    "lib_name" in the build command.  To be used for libraries that "lib_name"
+    depends on.
+    Optional "call" replaces the call to "func_name" in the test code.  It must
+    consist of complete C statements, including a trailing ";".
+    There must either be a "func_name" or a "call" argument (or both).
+    "language" should be "C" or "C++" and is used to select the compiler.
+    Default is "C".
+    Note that this uses the current value of compiler and linker flags, make
+    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
+    Returns an empty string for success, an error message for failure.
+    """
+    # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H.
+    if context.headerfilename:
+        includetext = '#include "%s"' % context.headerfilename
+    else:
+        includetext = ''
+    if not header:
+        header = ""
+
+    text = """
+%s
+%s""" % (includetext, header)
+
+    # Add a function declaration if needed.
+    if func_name and func_name != "main" and not header:
+        text = text + """
+#ifdef __cplusplus
+extern "C"
+#endif
+char %s();
+""" % func_name
+
+    # The actual test code.
+    if not call:
+        call = "%s();" % func_name
+    text = text + """
+int
+main() {
+  %s
+return 0;
+}
+""" % call
+
+    i = string.find(call, "\n")
+    if i > 0:
+        calltext = call[:i] + ".."
+    elif call[-1] == ';':
+        calltext = call[:-1]
+    else:
+        calltext = call
+
+    for lib_name in libs:
+
+        lang, suffix, msg = _lang2suffix(language)
+        if msg:
+            context.Display("Cannot check for library %s: %s\n" % (lib_name, msg))
+            return msg
+
+        context.Display("Checking for %s in %s library %s... "
+                        % (calltext, lang, lib_name))
+        if lib_name:
+            l = [ lib_name ]
+            if extra_libs:
+                l.extend(extra_libs)
+            oldLIBS = context.AppendLIBS(l)
+            sym = "HAVE_LIB" + lib_name
+        else:
+            oldLIBS = -1
+            sym = None
+
+        ret = context.BuildProg(text, suffix)
+
+        _YesNoResult(context, ret, sym, text)
+        if oldLIBS != -1 and (ret or not autoadd):
+            context.SetLIBS(oldLIBS)
+            
+        if not ret:
+            return ret
+
+    return ret
+
+#
+# END OF PUBLIC FUNCTIONS
+#
+
+def _YesNoResult(context, ret, key, text):
+    """
+    Handle the result of a test with a "yes" or "no" result.
+    "ret" is the return value: empty if OK, error message when not.
+    "key" is the name of the symbol to be defined (HAVE_foo).
+    "text" is the source code of the program used for testing.
+    """
+    if key:
+        _Have(context, key, not ret)
+    if ret:
+        context.Display("no\n")
+        _LogFailed(context, text, ret)
+    else:
+        context.Display("yes\n")
+
+
+def _Have(context, key, have):
+    """
+    Store result of a test in context.havedict and context.headerfilename.
+    "key" is a "HAVE_abc" name.  It is turned into all CAPITALS and non-
+    alphanumerics are replaced by an underscore.
+    The value of "have" can be:
+    1      - Feature is defined, add "#define key".
+    0      - Feature is not defined, add "/* #undef key */".
+             Adding "undef" is what autoconf does.  Not useful for the
+             compiler, but it shows that the test was done.
+    number - Feature is defined to this number "#define key have".
+             Doesn't work for 0 or 1, use a string then.
+    string - Feature is defined to this string "#define key have".
+             Give "have" as is should appear in the header file, include quotes
+             when desired and escape special characters!
+    """
+    key_up = string.upper(key)
+    key_up = re.sub('[^A-Z0-9_]', '_', key_up)
+    context.havedict[key_up] = have
+    if have == 1:
+        line = "#define %s\n" % key_up
+    elif have == 0:
+        line = "/* #undef %s */\n" % key_up
+    elif type(have) == IntType:
+        line = "#define %s %d\n" % (key_up, have)
+    else:
+        line = "#define %s %s\n" % (key_up, str(have))
+    
+    if context.headerfilename:
+        f = open(context.headerfilename, "a")
+        f.write(line)
+        f.close()
+    elif hasattr(context,'config_h'):
+        context.config_h = context.config_h + line
+
+
+def _LogFailed(context, text, msg):
+    """
+    Write to the log about a failed program.
+    Add line numbers, so that error messages can be understood.
+    """
+    if LogInputFiles:
+        context.Log("Failed program was:\n")
+        lines = string.split(text, '\n')
+        if len(lines) and lines[-1] == '':
+            lines = lines[:-1]              # remove trailing empty line
+        n = 1
+        for line in lines:
+            context.Log("%d: %s\n" % (n, line))
+            n = n + 1
+    if LogErrorMessages:
+        context.Log("Error message: %s\n" % msg)
+
+
+def _lang2suffix(lang):
+    """
+    Convert a language name to a suffix.
+    When "lang" is empty or None C is assumed.
+    Returns a tuple (lang, suffix, None) when it works.
+    For an unrecognized language returns (None, None, msg).
+    Where:
+        lang   = the unified language name
+        suffix = the suffix, including the leading dot
+        msg    = an error message
+    """
+    if not lang or lang in ["C", "c"]:
+        return ("C", ".c", None)
+    if lang in ["c++", "C++", "cpp", "CXX", "cxx"]:
+        return ("C++", ".cpp", None)
+
+    return None, None, "Unsupported language: %s" % lang
+
+
+# vim: set sw=4 et sts=4 tw=79 fo+=l:

Added: cs/scons/scons-local-0.96.92/SCons/Debug.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Debug.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Debug.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,197 @@
+"""SCons.Debug
+
+Code for debugging SCons internal things.  Not everything here is
+guaranteed to work all the way back to Python 1.5.2, and shouldn't be
+needed by most users.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Debug.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import string
+import sys
+
+# Recipe 14.10 from the Python Cookbook.
+try:
+    import weakref
+except ImportError:
+    def logInstanceCreation(instance, name=None):
+        pass
+else:
+    def logInstanceCreation(instance, name=None):
+        if name is None:
+            name = instance.__class__.__name__
+        if not tracked_classes.has_key(name):
+            tracked_classes[name] = []
+        tracked_classes[name].append(weakref.ref(instance))
+
+
+
+tracked_classes = {}
+
+def string_to_classes(s):
+    if s == '*':
+        c = tracked_classes.keys()
+        c.sort()
+        return c
+    else:
+        return string.split(s)
+
+def fetchLoggedInstances(classes="*"):
+    classnames = string_to_classes(classes)
+    return map(lambda cn: (cn, len(tracked_classes[cn])), classnames)
+  
+def countLoggedInstances(classes, file=sys.stdout):
+    for classname in string_to_classes(classes):
+        file.write("%s: %d\n" % (classname, len(tracked_classes[classname])))
+
+def listLoggedInstances(classes, file=sys.stdout):
+    for classname in string_to_classes(classes):
+        file.write('\n%s:\n' % classname)
+        for ref in tracked_classes[classname]:
+            obj = ref()
+            if obj is not None:
+                file.write('    %s\n' % repr(obj))
+
+def dumpLoggedInstances(classes, file=sys.stdout):
+    for classname in string_to_classes(classes):
+        file.write('\n%s:\n' % classname)
+        for ref in tracked_classes[classname]:
+            obj = ref()
+            if obj is not None:
+                file.write('    %s:\n' % obj)
+                for key, value in obj.__dict__.items():
+                    file.write('        %20s : %s\n' % (key, value))
+
+
+
+if sys.platform[:5] == "linux":
+    # Linux doesn't actually support memory usage stats from getrusage().
+    def memory():
+        mstr = open('/proc/self/stat').read()
+        mstr = string.split(mstr)[22]
+        return int(mstr)
+else:
+    try:
+        import resource
+    except ImportError:
+        try:
+            import win32process
+            import win32api
+        except ImportError:
+            def memory():
+                return 0
+        else:
+            def memory():
+                process_handle = win32api.GetCurrentProcess()
+                memory_info = win32process.GetProcessMemoryInfo( process_handle )
+                return memory_info['PeakWorkingSetSize']
+    else:
+        def memory():
+            res = resource.getrusage(resource.RUSAGE_SELF)
+            return res[4]
+
+
+
+caller_dicts = {}
+
+def caller(back=0):
+    import traceback
+    tb = traceback.extract_stack(limit=3+back)
+    key = tb[1][:3]
+    try:
+        entry = caller_dicts[key]
+    except KeyError:
+        entry = caller_dicts[key] = {}
+    key = tb[0][:3]
+    try:
+        entry[key] = entry[key] + 1
+    except KeyError:
+        entry[key] = 1
+    return '%s:%d(%s)' % func_shorten(key)
+
+def dump_caller_counts(file=sys.stdout):
+    keys = caller_dicts.keys()
+    keys.sort()
+    for k in keys:
+        file.write("Callers of %s:%d(%s):\n" % func_shorten(k))
+        counts = caller_dicts[k]
+        callers = counts.keys()
+        callers.sort()
+        for c in callers:
+            #file.write("    counts[%s] = %s\n" % (c, counts[c]))
+            t = ((counts[c],) + func_shorten(c))
+            file.write("    %6d %s:%d(%s)\n" % t)
+
+shorten_list = [
+    ( '/scons/SCons/',          1),
+    ( '/src/engine/SCons/',     1),
+    ( '/usr/lib/python',        0),
+]
+
+if os.sep != '/':
+   def platformize(t):
+       return (string.replace(t[0], '/', os.sep), t[1])
+   shorten_list = map(platformize, shorten_list)
+   del platformize
+
+def func_shorten(func_tuple):
+    f = func_tuple[0]
+    for t in shorten_list:
+        i = string.find(f, t[0])
+        if i >= 0:
+            if t[1]:
+                i = i + len(t[0])
+            f = f[i:]
+            break
+    return (f,)+func_tuple[1:]
+
+
+
+TraceFP = {}
+if sys.platform == 'win32':
+    TraceDefault = 'con'
+else:
+    TraceDefault = '/dev/tty'
+
+def Trace(msg, file=None, mode='w'):
+    """Write a trace message to a file.  Whenever a file is specified,
+    it becomes the default for the next call to Trace()."""
+    global TraceDefault
+    if file is None:
+        file = TraceDefault
+    else:
+        TraceDefault = file
+    try:
+        fp = TraceFP[file]
+    except KeyError:
+        try:
+            fp = TraceFP[file] = open(file, mode)
+        except TypeError:
+            # Assume we were passed an open file pointer.
+            fp = file
+    fp.write(msg)

Added: cs/scons/scons-local-0.96.92/SCons/Defaults.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Defaults.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Defaults.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,356 @@
+"""SCons.Defaults
+
+Builders and other things for the local site.  Here's where we'll
+duplicate the functionality of autoconf until we move it into the
+installation procedure or use something like qmconf.
+
+The code that reads the registry to find MSVC components was borrowed
+from distutils.msvccompiler.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Defaults.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+
+import os
+import os.path
+import shutil
+import stat
+import string
+import time
+import types
+import sys
+
+import SCons.Action
+import SCons.Builder
+import SCons.Environment
+import SCons.Tool
+import SCons.Sig
+import SCons.Subst
+
+# A placeholder for a default Environment (for fetching source files
+# from source code management systems and the like).  This must be
+# initialized later, after the top-level directory is set by the calling
+# interface.
+_default_env = None
+
+# Lazily instantiate the default environment so the overhead of creating
+# it doesn't apply when it's not needed.
+def DefaultEnvironment(*args, **kw):
+    global _default_env
+    if not _default_env:
+        _default_env = apply(SCons.Environment.Environment, args, kw)
+        _default_env._build_signature = 1
+        _default_env._calc_module = SCons.Sig.default_module
+    return _default_env
+
+# Emitters for setting the shared attribute on object files,
+# and an action for checking that all of the source files
+# going into a shared library are, in fact, shared.
+def StaticObjectEmitter(target, source, env):
+    for tgt in target:
+        tgt.attributes.shared = None
+    return (target, source)
+
+def SharedObjectEmitter(target, source, env):
+    for tgt in target:
+        tgt.attributes.shared = 1
+    return (target, source)
+
+def SharedFlagChecker(source, target, env):
+    same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME')
+    if same == '0' or same == '' or same == 'False':
+        for src in source:
+            try:
+                shared = src.attributes.shared
+            except AttributeError:
+                shared = None
+            if not shared:
+                raise SCons.Errors.UserError, "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])
+
+SharedCheck = SCons.Action.Action(SharedFlagChecker, None)
+
+# Some people were using these variable name before we made
+# SourceFileScanner part of the public interface.  Don't break their
+# SConscript files until we've given them some fair warning and a
+# transition period.
+CScan = SCons.Tool.CScanner
+DScan = SCons.Tool.DScanner
+LaTeXScan = SCons.Tool.LaTeXScanner
+ObjSourceScan = SCons.Tool.SourceFileScanner
+ProgScan = SCons.Tool.ProgramScanner
+
+# This isn't really a tool scanner, so it doesn't quite belong with
+# the rest of those in Tool/__init__.py, but I'm not sure where else it
+# should go.  Leave it here for now.
+import SCons.Scanner.Dir
+DirScanner = SCons.Scanner.Dir.DirScanner()
+DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner()
+
+# Actions for common languages.
+CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR")
+ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR")
+CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR")
+ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR")
+
+ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR")
+ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR")
+
+LinkAction = SCons.Action.Action("$LINKCOM", "$LINKCOMSTR")
+ShLinkAction = SCons.Action.Action("$SHLINKCOM", "$SHLINKCOMSTR")
+
+LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR")
+
+# Common tasks that we allow users to perform in platform-independent
+# ways by creating ActionFactory instances.
+ActionFactory = SCons.Action.ActionFactory
+
+Chmod = ActionFactory(os.chmod,
+                      lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
+
+def copy_func(dest, src):
+    if os.path.isfile(src):
+        return shutil.copy(src, dest)
+    else:
+        return shutil.copytree(src, dest, 1)
+
+Copy = ActionFactory(copy_func,
+                     lambda dest, src: 'Copy("%s", "%s")' % (dest, src))
+
+def delete_func(entry, must_exist=0):
+    if not must_exist and not os.path.exists(entry):
+        return None
+    if not os.path.exists(entry) or os.path.isfile(entry):
+        return os.unlink(entry)
+    else:
+        return shutil.rmtree(entry, 1)
+
+def delete_strfunc(entry, must_exist=0):
+    return 'Delete("%s")' % entry
+
+Delete = ActionFactory(delete_func, delete_strfunc)
+
+Mkdir = ActionFactory(os.makedirs,
+                      lambda dir: 'Mkdir("%s")' % dir)
+
+Move = ActionFactory(lambda dest, src: os.rename(src, dest),
+                     lambda dest, src: 'Move("%s", "%s")' % (dest, src))
+
+def touch_func(file):
+    mtime = int(time.time())
+    if os.path.exists(file):
+        atime = os.path.getatime(file)
+    else:
+        open(file, 'w')
+        atime = mtime
+    return os.utime(file, (atime, mtime))
+
+Touch = ActionFactory(touch_func,
+                      lambda file: 'Touch("%s")' % file)
+
+# Internal utility functions
+def copyFunc(dest, source, env):
+    """Install a source file into a destination by copying it (and its
+    permission/mode bits)."""
+    shutil.copy2(source, dest)
+    st = os.stat(source)
+    os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+    return 0
+
+def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
+    """Creates a new list from 'list' by first interpolating each
+    element in the list using the 'env' dictionary and then calling f
+    on the list, and finally concatenating 'prefix' and 'suffix' onto
+    each element of the list. A trailing space on 'prefix' or leading
+    space on 'suffix' will cause them to be put into separate list
+    elements rather than being concatenated."""
+    
+    if not list:
+        return list
+
+    if SCons.Util.is_List(list):
+        list = SCons.Util.flatten(list)
+    list = f(env.subst_path(list, target=target, source=source))
+
+    result = []
+
+    # ensure that prefix and suffix are strings
+    prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
+    suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
+
+    for x in list:
+        if isinstance(x, SCons.Node.FS.File):
+            result.append(x)
+            continue
+        x = str(x)
+        if x:
+
+            if prefix:
+                if prefix[-1] == ' ':
+                    result.append(prefix[:-1])
+                elif x[:len(prefix)] != prefix:
+                    x = prefix + x
+
+            result.append(x)
+
+            if suffix:
+                if suffix[0] == ' ':
+                    result.append(suffix[1:])
+                elif x[-len(suffix):] != suffix:
+                    result[-1] = result[-1]+suffix
+
+    return result
+
+def _stripixes(prefix, list, suffix, stripprefix, stripsuffix, env, c=None):
+    """This is a wrapper around _concat() that checks for the existence
+    of prefixes or suffixes on list elements and strips them where it
+    finds them.  This is used by tools (like the GNU linker) that need
+    to turn something like 'libfoo.a' into '-lfoo'."""
+    
+    if not callable(c):
+        if callable(env["_concat"]):
+            c = env["_concat"]
+        else:
+            c = _concat
+    def f(list, sp=stripprefix, ss=stripsuffix):
+        result = []
+        for l in list:
+            if isinstance(l, SCons.Node.FS.File):
+                result.append(l)
+                continue
+            if not SCons.Util.is_String(l):
+                l = str(l)
+            if l[:len(sp)] == sp:
+                l = l[len(sp):]
+            if l[-len(ss):] == ss:
+                l = l[:-len(ss)]
+            result.append(l)
+        return result
+    return c(prefix, list, suffix, env, f)
+
+def _defines(prefix, defs, suffix, env, c=_concat):
+    """A wrapper around _concat that turns a list or string
+    into a list of C preprocessor command-line definitions.
+    """
+    if SCons.Util.is_List(defs):
+        l = []
+        for d in defs:
+            if SCons.Util.is_List(d) or type(d) is types.TupleType:
+                l.append(str(d[0]) + '=' + str(d[1]))
+            else:
+                l.append(str(d))
+    elif SCons.Util.is_Dict(defs):
+        # The items in a dictionary are stored in random order, but
+        # if the order of the command-line options changes from
+        # invocation to invocation, then the signature of the command
+        # line will change and we'll get random unnecessary rebuilds.
+        # Consequently, we have to sort the keys to ensure a
+        # consistent order...
+        l = []
+        keys = defs.keys()
+        keys.sort()
+        for k in keys:
+            v = defs[k]
+            if v is None:
+                l.append(str(k))
+            else:
+                l.append(str(k) + '=' + str(v))
+    else:
+        l = [str(defs)]
+    return c(prefix, l, suffix, env)
+    
+class NullCmdGenerator:
+    """This is a callable class that can be used in place of other
+    command generators if you don't want them to do anything.
+
+    The __call__ method for this class simply returns the thing
+    you instantiated it with.
+
+    Example usage:
+    env["DO_NOTHING"] = NullCmdGenerator
+    env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
+    """
+
+    def __init__(self, cmd):
+        self.cmd = cmd
+
+    def __call__(self, target, source, env, for_signature=None):
+        return self.cmd
+
+class Variable_Method_Caller:
+    """A class for finding a construction variable on the stack and
+    calling one of its methods.
+
+    We use this to support "construction variables" in our string
+    eval()s that actually stand in for methods--specifically, use
+    of "RDirs" in call to _concat that should actually execute the
+    "TARGET.RDirs" method.  (We used to support this by creating a little
+    "build dictionary" that mapped RDirs to the method, but this got in
+    the way of Memoizing construction environments, because we had to
+    create new environment objects to hold the variables.)
+    """
+    def __init__(self, variable, method):
+        self.variable = variable
+        self.method = method
+    def __call__(self, *args, **kw):
+        try: 1/0
+        except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
+        variable = self.variable
+        while frame:
+            if frame.f_locals.has_key(variable):
+                v = frame.f_locals[variable]
+                if v:
+                    method = getattr(v, self.method)
+                    return apply(method, args, kw)
+            frame = frame.f_back
+        return None
+
+ConstructionEnvironment = {
+    'BUILDERS'      : {},
+    'SCANNERS'      : [],
+    'CONFIGUREDIR'  : '#/.sconf_temp',
+    'CONFIGURELOG'  : '#/config.log',
+    'INSTALLSTR'    : 'Install file: "$SOURCE" as "$TARGET"',
+    'CPPSUFFIXES'   : SCons.Tool.CSuffixes,
+    'DSUFFIXES'     : SCons.Tool.DSuffixes,
+    'IDLSUFFIXES'   : SCons.Tool.IDLSuffixes,
+    'LATEXSUFFIXES' : SCons.Tool.LaTeXSuffixes,
+    'ENV'           : {},
+    'INSTALL'       : copyFunc,
+    '_concat'       : _concat,
+    '_defines'      : _defines,
+    '_stripixes'    : _stripixes,
+    '_LIBFLAGS'     : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
+    '_LIBDIRFLAGS'  : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+    '_CPPINCFLAGS'  : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
+    '_CPPDEFFLAGS'  : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
+    'TEMPFILE'      : NullCmdGenerator,
+    'Dir'           : Variable_Method_Caller('TARGET', 'Dir'),
+    'Dirs'          : Variable_Method_Caller('TARGET', 'Dirs'),
+    'File'          : Variable_Method_Caller('TARGET', 'File'),
+    'RDirs'         : Variable_Method_Caller('TARGET', 'RDirs'),
+}

Added: cs/scons/scons-local-0.96.92/SCons/Environment.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Environment.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Environment.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,1638 @@
+"""SCons.Environment
+
+Base class for construction Environments.  These are
+the primary objects used to communicate dependency and
+construction information to the build engine.
+
+Keyword arguments supplied when the construction Environment
+is created are construction variables used to initialize the
+Environment 
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Environment.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+import copy
+import os
+import os.path
+import string
+from UserDict import UserDict
+
+import SCons.Action
+import SCons.Builder
+from SCons.Debug import logInstanceCreation
+import SCons.Defaults
+import SCons.Errors
+import SCons.Node
+import SCons.Node.Alias
+import SCons.Node.FS
+import SCons.Node.Python
+import SCons.Platform
+import SCons.SConsign
+import SCons.Sig
+import SCons.Sig.MD5
+import SCons.Sig.TimeStamp
+import SCons.Subst
+import SCons.Tool
+import SCons.Util
+import SCons.Warnings
+
+class _Null:
+    pass
+
+_null = _Null
+
+CleanTargets = {}
+CalculatorArgs = {}
+
+# Pull UserError into the global name space for the benefit of
+# Environment().SourceSignatures(), which has some import statements
+# which seem to mess up its ability to reference SCons directly.
+UserError = SCons.Errors.UserError
+
+def installFunc(target, source, env):
+    """Install a source file into a target using the function specified
+    as the INSTALL construction variable."""
+    try:
+        install = env['INSTALL']
+    except KeyError:
+        raise SCons.Errors.UserError('Missing INSTALL construction variable.')
+    return install(target[0].path, source[0].path, env)
+
+def installString(target, source, env):
+    return env.subst(env['INSTALLSTR'], 0, target, source)
+
+installAction = SCons.Action.Action(installFunc, installString)
+
+InstallBuilder = SCons.Builder.Builder(action=installAction,
+                                       name='InstallBuilder')
+
+def alias_builder(env, target, source):
+    pass
+
+AliasBuilder = SCons.Builder.Builder(action = alias_builder,
+                                     target_factory = SCons.Node.Alias.default_ans.Alias,
+                                     source_factory = SCons.Node.FS.Entry,
+                                     multi = 1,
+                                     is_explicit = None,
+                                     name='AliasBuilder')
+
+def our_deepcopy(x):
+   """deepcopy lists and dictionaries, and just copy the reference
+   for everything else."""
+   if SCons.Util.is_Dict(x):
+       copy = {}
+       for key in x.keys():
+           copy[key] = our_deepcopy(x[key])
+   elif SCons.Util.is_List(x):
+       copy = map(our_deepcopy, x)
+       try:
+           copy = x.__class__(copy)
+       except AttributeError:
+           pass
+   else:
+       copy = x
+   return copy
+
+def apply_tools(env, tools, toolpath):
+    # Store the toolpath in the Environment.
+    if toolpath is not None:
+        env['toolpath'] = toolpath
+
+    if not tools:
+        return
+    # Filter out null tools from the list.
+    for tool in filter(None, tools):
+        if SCons.Util.is_List(tool) or type(tool)==type(()):
+            toolname = tool[0]
+            toolargs = tool[1] # should be a dict of kw args
+            tool = apply(env.Tool, [toolname], toolargs)
+        else:
+            env.Tool(tool)
+
+# These names are controlled by SCons; users should never set or override
+# them.  This warning can optionally be turned off, but scons will still
+# ignore the illegal variable names even if it's off.
+reserved_construction_var_names = \
+    ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']
+
+def copy_non_reserved_keywords(dict):
+    result = our_deepcopy(dict)
+    for k in result.keys():
+        if k in reserved_construction_var_names:
+            SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
+                                "Ignoring attempt to set reserved variable `%s'" % k)
+            del result[k]
+    return result
+
+def _set_reserved(env, key, value):
+    msg = "Ignoring attempt to set reserved variable `%s'" % key
+    SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg)
+
+def _set_BUILDERS(env, key, value):
+    try:
+        bd = env._dict[key]
+        for k in bd.keys():
+            del bd[k]
+    except KeyError:
+        env._dict[key] = BuilderDict(kwbd, env)
+    env._dict[key].update(value)
+
+def _set_SCANNERS(env, key, value):
+    env._dict[key] = value
+    env.scanner_map_delete()
+
+class BuilderWrapper:
+    """Wrapper class that associates an environment with a Builder at
+    instantiation."""
+    def __init__(self, env, builder):
+        self.env = env
+        self.builder = builder
+
+    def __call__(self, target=None, source=_null, *args, **kw):
+        if source is _null:
+            source = target
+            target = None
+        if not target is None and not SCons.Util.is_List(target):
+            target = [target]
+        if not source is None and not SCons.Util.is_List(source):
+            source = [source]
+        return apply(self.builder, (self.env, target, source) + args, kw)
+
+    # This allows a Builder to be executed directly
+    # through the Environment to which it's attached.
+    # In practice, we shouldn't need this, because
+    # builders actually get executed through a Node.
+    # But we do have a unit test for this, and can't
+    # yet rule out that it would be useful in the
+    # future, so leave it for now.
+    def execute(self, **kw):
+        kw['env'] = self.env
+        apply(self.builder.execute, (), kw)
+
+class BuilderDict(UserDict):
+    """This is a dictionary-like class used by an Environment to hold
+    the Builders.  We need to do this because every time someone changes
+    the Builders in the Environment's BUILDERS dictionary, we must
+    update the Environment's attributes."""
+    def __init__(self, dict, env):
+        # Set self.env before calling the superclass initialization,
+        # because it will end up calling our other methods, which will
+        # need to point the values in this dictionary to self.env.
+        self.env = env
+        UserDict.__init__(self, dict)
+
+    def __setitem__(self, item, val):
+        UserDict.__setitem__(self, item, val)
+        try:
+            self.setenvattr(item, val)
+        except AttributeError:
+            # Have to catch this because sometimes __setitem__ gets
+            # called out of __init__, when we don't have an env
+            # attribute yet, nor do we want one!
+            pass
+
+    def setenvattr(self, item, val):
+        """Set the corresponding environment attribute for this Builder.
+
+        If the value is already a BuilderWrapper, we pull the builder
+        out of it and make another one, so that making a copy of an
+        existing BuilderDict is guaranteed separate wrappers for each
+        Builder + Environment pair."""
+        try:
+            builder = val.builder
+        except AttributeError:
+            builder = val
+        setattr(self.env, item, BuilderWrapper(self.env, builder))
+
+    def __delitem__(self, item):
+        UserDict.__delitem__(self, item)
+        delattr(self.env, item)
+
+    def update(self, dict):
+        for i, v in dict.items():
+            self.__setitem__(i, v)
+
+class SubstitutionEnvironment:
+    """Base class for different flavors of construction environments.
+
+    This class contains a minimal set of methods that handle contruction
+    variable expansion and conversion of strings to Nodes, which may or
+    may not be actually useful as a stand-alone class.  Which methods
+    ended up in this class is pretty arbitrary right now.  They're
+    basically the ones which we've empirically determined are common to
+    the different construction environment subclasses, and most of the
+    others that use or touch the underlying dictionary of construction
+    variables.
+
+    Eventually, this class should contain all the methods that we
+    determine are necessary for a "minimal" interface to the build engine.
+    A full "native Python" SCons environment has gotten pretty heavyweight
+    with all of the methods and Tools and construction variables we've
+    jammed in there, so it would be nice to have a lighter weight
+    alternative for interfaces that don't need all of the bells and
+    whistles.  (At some point, we'll also probably rename this class
+    "Base," since that more reflects what we want this class to become,
+    but because we've released comments that tell people to subclass
+    Environment.Base to create their own flavors of construction
+    environment, we'll save that for a future refactoring when this
+    class actually becomes useful.)
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self, **kw):
+        """Initialization of an underlying SubstitutionEnvironment class.
+        """
+        if __debug__: logInstanceCreation(self, 'Environment.SubstitutionEnvironment')
+        self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS()
+        self.ans = SCons.Node.Alias.default_ans
+        self.lookup_list = SCons.Node.arg2nodes_lookups
+        self._dict = kw.copy()
+        self._init_special()
+
+    def _init_special(self):
+        """Initial the dispatch table for special handling of
+        special construction variables."""
+        self._special = {}
+        for key in reserved_construction_var_names:
+            self._special[key] = _set_reserved
+        self._special['BUILDERS'] = _set_BUILDERS
+        self._special['SCANNERS'] = _set_SCANNERS
+
+    def __cmp__(self, other):
+        return cmp(self._dict, other._dict)
+
+    def __delitem__(self, key):
+        "__cache_reset__"
+        del self._dict[key]
+
+    def __getitem__(self, key):
+        return self._dict[key]
+
+    def __setitem__(self, key, value):
+        "__cache_reset__"
+        special = self._special.get(key)
+        if special:
+            special(self, key, value)
+        else:
+            if not SCons.Util.is_valid_construction_var(key):
+                raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
+            self._dict[key] = value
+
+    def get(self, key, default=None):
+        "Emulates the get() method of dictionaries."""
+        return self._dict.get(key, default)
+
+    def has_key(self, key):
+        return self._dict.has_key(key)
+
+    def items(self):
+        return self._dict.items()
+
+    def arg2nodes(self, args, node_factory=_null, lookup_list=_null):
+        if node_factory is _null:
+            node_factory = self.fs.File
+        if lookup_list is _null:
+            lookup_list = self.lookup_list
+
+        if not args:
+            return []
+
+        if SCons.Util.is_List(args):
+            args = SCons.Util.flatten(args)
+        else:
+            args = [args]
+
+        nodes = []
+        for v in args:
+            if SCons.Util.is_String(v):
+                n = None
+                for l in lookup_list:
+                    n = l(v)
+                    if not n is None:
+                        break
+                if not n is None:
+                    if SCons.Util.is_String(n):
+                        n = self.subst(n, raw=1)
+                        if node_factory:
+                            n = node_factory(n)
+                    if SCons.Util.is_List(n):
+                        nodes.extend(n)
+                    else:
+                        nodes.append(n)
+                elif node_factory:
+                    v = node_factory(self.subst(v, raw=1))
+                    if SCons.Util.is_List(v):
+                        nodes.extend(v)
+                    else:
+                        nodes.append(v)
+            else:
+                nodes.append(v)
+    
+        return nodes
+
+    def gvars(self):
+        return self._dict
+
+    def lvars(self):
+        return {}
+
+    def subst(self, string, raw=0, target=None, source=None, conv=None):
+        """Recursively interpolates construction variables from the
+        Environment into the specified string, returning the expanded
+        result.  Construction variables are specified by a $ prefix
+        in the string and begin with an initial underscore or
+        alphabetic character followed by any number of underscores
+        or alphanumeric characters.  The construction variable names
+        may be surrounded by curly braces to separate the name from
+        trailing characters.
+        """
+        gvars = self.gvars()
+        lvars = self.lvars()
+        lvars['__env__'] = self
+        return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv)
+
+    def subst_kw(self, kw, raw=0, target=None, source=None):
+        nkw = {}
+        for k, v in kw.items():
+            k = self.subst(k, raw, target, source)
+            if SCons.Util.is_String(v):
+                v = self.subst(v, raw, target, source)
+            nkw[k] = v
+        return nkw
+
+    def subst_list(self, string, raw=0, target=None, source=None, conv=None):
+        """Calls through to SCons.Subst.scons_subst_list().  See
+        the documentation for that function."""
+        gvars = self.gvars()
+        lvars = self.lvars()
+        lvars['__env__'] = self
+        return SCons.Subst.scons_subst_list(string, self, raw, target, source, gvars, lvars, conv)
+
+    def subst_path(self, path, target=None, source=None):
+        """Substitute a path list, turning EntryProxies into Nodes
+        and leaving Nodes (and other objects) as-is."""
+
+        if not SCons.Util.is_List(path):
+            path = [path]
+
+        def s(obj):
+            """This is the "string conversion" routine that we have our
+            substitutions use to return Nodes, not strings.  This relies
+            on the fact that an EntryProxy object has a get() method that
+            returns the underlying Node that it wraps, which is a bit of
+            architectural dependence that we might need to break or modify
+            in the future in response to additional requirements."""
+            try:
+                get = obj.get
+            except AttributeError:
+                pass
+            else:
+                obj = get()
+            return obj
+
+        r = []
+        for p in path:
+            if SCons.Util.is_String(p):
+                p = self.subst(p, target=target, source=source, conv=s)
+                if SCons.Util.is_List(p):
+                    if len(p) == 1:
+                        p = p[0]
+                    else:
+                        # We have an object plus a string, or multiple
+                        # objects that we need to smush together.  No choice
+                        # but to make them into a string.
+                        p = string.join(map(SCons.Util.to_String, p), '')
+            else:
+                p = s(p)
+            r.append(p)
+        return r
+
+    subst_target_source = subst
+
+    def Override(self, overrides):
+        """
+        Produce a modified environment whose variables are overriden by
+        the overrides dictionaries.  "overrides" is a dictionary that
+        will override the variables of this environment.
+
+        This function is much more efficient than Copy() or creating
+        a new Environment because it doesn't copy the construction
+        environment dictionary, it just wraps the underlying construction
+        environment, and doesn't even create a wrapper object if there
+        are no overrides.
+        """
+        if overrides:
+            o = copy_non_reserved_keywords(overrides)
+            overrides = {}
+            for key, value in o.items():
+                overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
+        if overrides:
+            env = OverrideEnvironment(self, overrides)
+            return env
+        else:
+            return self
+
+class Base(SubstitutionEnvironment):
+    """Base class for "real" construction Environments.  These are the
+    primary objects used to communicate dependency and construction
+    information to the build engine.
+
+    Keyword arguments supplied when the construction Environment
+    is created are construction variables used to initialize the
+    Environment.
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    #######################################################################
+    # This is THE class for interacting with the SCons build engine,
+    # and it contains a lot of stuff, so we're going to try to keep this
+    # a little organized by grouping the methods.
+    #######################################################################
+
+    #######################################################################
+    # Methods that make an Environment act like a dictionary.  These have
+    # the expected standard names for Python mapping objects.  Note that
+    # we don't actually make an Environment a subclass of UserDict for
+    # performance reasons.  Note also that we only supply methods for
+    # dictionary functionality that we actually need and use.
+    #######################################################################
+
+    def __init__(self,
+                 platform=None,
+                 tools=None,
+                 toolpath=None,
+                 options=None,
+                 **kw):
+        """
+        Initialization of a basic SCons construction environment,
+        including setting up special construction variables like BUILDER,
+        PLATFORM, etc., and searching for and applying available Tools.
+
+        Note that we do *not* call the underlying base class
+        (SubsitutionEnvironment) initialization, because we need to
+        initialize things in a very specific order that doesn't work
+        with the much simpler base class initialization.
+        """
+        if __debug__: logInstanceCreation(self, 'Environment.Base')
+        self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS()
+        self.ans = SCons.Node.Alias.default_ans
+        self.lookup_list = SCons.Node.arg2nodes_lookups
+        self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment)
+        self._init_special()
+
+        self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
+
+        if platform is None:
+            platform = self._dict.get('PLATFORM', None)
+            if platform is None:
+                platform = SCons.Platform.Platform()
+        if SCons.Util.is_String(platform):
+            platform = SCons.Platform.Platform(platform)
+        self._dict['PLATFORM'] = str(platform)
+        platform(self)
+
+        # Apply the passed-in variables and customizable options to the
+        # environment before calling the tools, because they may use
+        # some of them during initialization.
+        apply(self.Replace, (), kw)
+        if options:
+            options.Update(self)
+
+        if tools is None:
+            tools = self._dict.get('TOOLS', None)
+            if tools is None:
+                tools = ['default']
+        apply_tools(self, tools, toolpath)
+
+        # Now re-apply the passed-in variables and customizable options
+        # to the environment, since the values the user set explicitly
+        # should override any values set by the tools.
+        apply(self.Replace, (), kw)
+        if options:
+            options.Update(self)
+
+    #######################################################################
+    # Utility methods that are primarily for internal use by SCons.
+    # These begin with lower-case letters.
+    #######################################################################
+
+    def get_builder(self, name):
+        """Fetch the builder with the specified name from the environment.
+        """
+        try:
+            return self._dict['BUILDERS'][name]
+        except KeyError:
+            return None
+
+    def get_calculator(self):
+        "__cacheable__"
+        try:
+            module = self._calc_module
+            c = apply(SCons.Sig.Calculator, (module,), CalculatorArgs)
+        except AttributeError:
+            # Note that we're calling get_calculator() here, so the
+            # DefaultEnvironment() must have a _calc_module attribute
+            # to avoid infinite recursion.
+            c = SCons.Defaults.DefaultEnvironment().get_calculator()
+        return c
+
+    def get_factory(self, factory, default='File'):
+        """Return a factory function for creating Nodes for this
+        construction environment.
+        __cacheable__
+        """
+        name = default
+        try:
+            is_node = issubclass(factory, SCons.Node.Node)
+        except TypeError:
+            # The specified factory isn't a Node itself--it's
+            # most likely None, or possibly a callable.
+            pass
+        else:
+            if is_node:
+                # The specified factory is a Node (sub)class.  Try to
+                # return the FS method that corresponds to the Node's
+                # name--that is, we return self.fs.Dir if they want a Dir,
+                # self.fs.File for a File, etc.
+                try: name = factory.__name__
+                except AttributeError: pass
+                else: factory = None
+        if not factory:
+            # They passed us None, or we picked up a name from a specified
+            # class, so return the FS method.  (Note that we *don't*
+            # use our own self.{Dir,File} methods because that would
+            # cause env.subst() to be called twice on the file name,
+            # interfering with files that have $$ in them.)
+            factory = getattr(self.fs, name)
+        return factory
+
+    def _gsm(self):
+        "__cacheable__"
+        try:
+            scanners = self._dict['SCANNERS']
+        except KeyError:
+            return None
+
+        sm = {}
+        # Reverse the scanner list so that, if multiple scanners
+        # claim they can scan the same suffix, earlier scanners
+        # in the list will overwrite later scanners, so that
+        # the result looks like a "first match" to the user.
+        if not SCons.Util.is_List(scanners):
+            scanners = [scanners]
+        else:
+            scanners = scanners[:] # copy so reverse() doesn't mod original
+        scanners.reverse()
+        for scanner in scanners:
+            for k in scanner.get_skeys(self):
+                sm[k] = scanner
+        return sm
+        
+    def get_scanner(self, skey):
+        """Find the appropriate scanner given a key (usually a file suffix).
+        """
+        sm = self._gsm()
+        try: return sm[skey]
+        except (KeyError, TypeError): return None
+
+    def _smd(self):
+        "__reset_cache__"
+        pass
+    
+    def scanner_map_delete(self, kw=None):
+        """Delete the cached scanner map (if we need to).
+        """
+        if not kw is None and not kw.has_key('SCANNERS'):
+            return
+        self._smd()
+
+    def _update(self, dict):
+        """Update an environment's values directly, bypassing the normal
+        checks that occur when users try to set items.
+        __cache_reset__
+        """
+        self._dict.update(dict)
+
+    def use_build_signature(self):
+        try:
+            return self._build_signature
+        except AttributeError:
+            b = SCons.Defaults.DefaultEnvironment()._build_signature
+            self._build_signature = b
+            return b
+
+    #######################################################################
+    # Public methods for manipulating an Environment.  These begin with
+    # upper-case letters.  The essential characteristic of methods in
+    # this section is that they do *not* have corresponding same-named
+    # global functions.  For example, a stand-alone Append() function
+    # makes no sense, because Append() is all about appending values to
+    # an Environment's construction variables.
+    #######################################################################
+
+    def Append(self, **kw):
+        """Append values to existing construction variables
+        in an Environment.
+        """
+        kw = copy_non_reserved_keywords(kw)
+        for key, val in kw.items():
+            # It would be easier on the eyes to write this using
+            # "continue" statements whenever we finish processing an item,
+            # but Python 1.5.2 apparently doesn't let you use "continue"
+            # within try:-except: blocks, so we have to nest our code.
+            try:
+                orig = self._dict[key]
+            except KeyError:
+                # No existing variable in the environment, so just set
+                # it to the new value.
+                self._dict[key] = val
+            else:
+                try:
+                    # Most straightforward:  just try to add them
+                    # together.  This will work in most cases, when the
+                    # original and new values are of compatible types.
+                    self._dict[key] = orig + val
+                except TypeError:
+                    try:
+                        # Try to update a dictionary value with another.
+                        # If orig isn't a dictionary, it won't have an
+                        # update() method; if val isn't a dictionary,
+                        # it won't have a keys() method.  Either way,
+                        # it's an AttributeError.
+                        orig.update(val)
+                    except AttributeError:
+                        try:
+                            # Check if the original is a list.
+                            add_to_orig = orig.append
+                        except AttributeError:
+                            # The original isn't a list, but the new
+                            # value is (by process of elimination),
+                            # so insert the original in the new value
+                            # (if there's one to insert) and replace
+                            # the variable with it.
+                            if orig:
+                                val.insert(0, orig)
+                            self._dict[key] = val
+                        else:
+                            # The original is a list, so append the new
+                            # value to it (if there's a value to append).
+                            if val:
+                                add_to_orig(val)
+        self.scanner_map_delete(kw)
+
+    def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
+        """Append path elements to the path 'name' in the 'ENV'
+        dictionary for this environment.  Will only add any particular
+        path once, and will normpath and normcase all paths to help
+        assure this.  This can also handle the case where the env
+        variable is a list instead of a string.
+        """
+
+        orig = ''
+        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
+            orig = self._dict[envname][name]
+
+        nv = SCons.Util.AppendPath(orig, newpath, sep)
+            
+        if not self._dict.has_key(envname):
+            self._dict[envname] = {}
+
+        self._dict[envname][name] = nv
+
+    def AppendUnique(self, **kw):
+        """Append values to existing construction variables
+        in an Environment, if they're not already there.
+        """
+        kw = copy_non_reserved_keywords(kw)
+        for key, val in kw.items():
+            if not self._dict.has_key(key) or not self._dict[key]:
+                self._dict[key] = val
+            elif SCons.Util.is_Dict(self._dict[key]) and \
+                 SCons.Util.is_Dict(val):
+                self._dict[key].update(val)
+            elif SCons.Util.is_List(val):
+                dk = self._dict[key]
+                if not SCons.Util.is_List(dk):
+                    dk = [dk]
+                val = filter(lambda x, dk=dk: x not in dk, val)
+                self._dict[key] = dk + val
+            else:
+                dk = self._dict[key]
+                if SCons.Util.is_List(dk):
+                    # By elimination, val is not a list.  Since dk is a
+                    # list, wrap val in a list first.
+                    if not val in dk:
+                        self._dict[key] = dk + [val]
+                else:
+                    self._dict[key] = self._dict[key] + val
+        self.scanner_map_delete(kw)
+
+    def Copy(self, tools=[], toolpath=None, **kw):
+        """Return a copy of a construction Environment.  The
+        copy is like a Python "deep copy"--that is, independent
+        copies are made recursively of each objects--except that
+        a reference is copied when an object is not deep-copyable
+        (like a function).  There are no references to any mutable
+        objects in the original Environment.
+        """
+        clone = copy.copy(self)
+        clone._dict = our_deepcopy(self._dict)
+        try:
+            cbd = clone._dict['BUILDERS']
+            clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
+        except KeyError:
+            pass
+        
+        apply_tools(clone, tools, toolpath)
+
+        # Apply passed-in variables after the new tools.
+        kw = copy_non_reserved_keywords(kw)
+        new = {}
+        for key, value in kw.items():
+            new[key] = SCons.Subst.scons_subst_once(value, self, key)
+        apply(clone.Replace, (), new)
+        if __debug__: logInstanceCreation(self, 'Environment.EnvironmentCopy')
+        return clone
+
+    def Detect(self, progs):
+        """Return the first available program in progs.  __cacheable__
+        """
+        if not SCons.Util.is_List(progs):
+            progs = [ progs ]
+        for prog in progs:
+            path = self.WhereIs(prog)
+            if path: return prog
+        return None
+
+    def Dictionary(self, *args):
+        if not args:
+            return self._dict
+        dlist = map(lambda x, s=self: s._dict[x], args)
+        if len(dlist) == 1:
+            dlist = dlist[0]
+        return dlist
+
+    def Dump(self, key = None):
+        """
+        Using the standard Python pretty printer, dump the contents of the
+        scons build environment to stdout.
+
+        If the key passed in is anything other than None, then that will
+        be used as an index into the build environment dictionary and
+        whatever is found there will be fed into the pretty printer. Note
+        that this key is case sensitive.
+        """
+        import pprint
+        pp = pprint.PrettyPrinter(indent=2)
+        if key:
+            dict = self.Dictionary(key)
+        else:
+            dict = self.Dictionary()
+        return pp.pformat(dict)
+
+    def FindIxes(self, paths, prefix, suffix):
+        """
+        Search a list of paths for something that matches the prefix and suffix.
+
+        paths - the list of paths or nodes.
+        prefix - construction variable for the prefix.
+        suffix - construction variable for the suffix.
+        """
+
+        suffix = self.subst('$'+suffix)
+        prefix = self.subst('$'+prefix)
+
+        for path in paths:
+            dir,name = os.path.split(str(path))
+            if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: 
+                return path
+
+    def ParseConfig(self, command, function=None, unique=1):
+        """
+        Use the specified function to parse the output of the command
+        in order to modify the current environment. The 'command' can
+        be a string or a list of strings representing a command and
+        it's arguments. 'Function' is an optional argument that takes
+        the environment and the output of the command. If no function is
+        specified, the output will be treated as the output of a typical
+        'X-config' command (i.e. gtk-config) and used to append to the
+        ASFLAGS, CCFLAGS, CPPFLAGS, CPPPATH, LIBPATH, LIBS, LINKFLAGS
+        and CCFLAGS variables.
+        """
+
+        # the default parse function
+        def parse_conf(env, output, fs=self.fs, unique=unique):
+            dict = {
+                'ASFLAGS'       : [],
+                'CCFLAGS'       : [],
+                'CPPFLAGS'      : [],
+                'CPPPATH'       : [],
+                'LIBPATH'       : [],
+                'LIBS'          : [],
+                'LINKFLAGS'     : [],
+            }
+    
+            params = string.split(output)
+            append_next_arg_to=''       # for multi-word args
+            for arg in params:
+                if append_next_arg_to:
+                    dict[append_next_arg_to].append(arg)
+                    append_next_arg_to = ''
+                elif arg[0] != '-':
+                    dict['LIBS'].append(fs.File(arg))
+                elif arg[:2] == '-L':
+                    if arg[2:]:
+                        dict['LIBPATH'].append(arg[2:])
+                    else:
+                        append_next_arg_to = 'LIBPATH'
+                elif arg[:2] == '-l':
+                    if arg[2:]:
+                        dict['LIBS'].append(arg[2:])
+                    else:
+                        append_next_arg_to = 'LIBS'
+                elif arg[:2] == '-I':
+                    if arg[2:]:
+                        dict['CPPPATH'].append(arg[2:])
+                    else:
+                        append_next_arg_to = 'CPPPATH'
+                elif arg[:4] == '-Wa,':
+                    dict['ASFLAGS'].append(arg)
+                elif arg[:4] == '-Wl,':
+                    dict['LINKFLAGS'].append(arg)
+                elif arg[:4] == '-Wp,':
+                    dict['CPPFLAGS'].append(arg)
+                elif arg == '-framework':
+                    dict['LINKFLAGS'].append(arg)
+                    append_next_arg_to='LINKFLAGS'
+                elif arg == '-mno-cygwin':
+                    dict['CCFLAGS'].append(arg)
+                    dict['LINKFLAGS'].append(arg)
+                elif arg == '-mwindows':
+                    dict['LINKFLAGS'].append(arg)
+                elif arg == '-pthread':
+                    dict['CCFLAGS'].append(arg)
+                    dict['LINKFLAGS'].append(arg)
+                else:
+                    dict['CCFLAGS'].append(arg)
+            if unique:
+                appender = env.AppendUnique
+            else:
+                appender = env.Append
+            apply(appender, (), dict)
+    
+        if function is None:
+            function = parse_conf
+        if type(command) is type([]):
+            command = string.join(command)
+        command = self.subst(command)
+        return function(self, os.popen(command).read())
+
+    def ParseDepends(self, filename, must_exist=None, only_one=0):
+        """
+        Parse a mkdep-style file for explicit dependencies.  This is
+        completely abusable, and should be unnecessary in the "normal"
+        case of proper SCons configuration, but it may help make
+        the transition from a Make hierarchy easier for some people
+        to swallow.  It can also be genuinely useful when using a tool
+        that can write a .d file, but for which writing a scanner would
+        be too complicated.
+        """
+        filename = self.subst(filename)
+        try:
+            fp = open(filename, 'r')
+        except IOError:
+            if must_exist:
+                raise
+            return
+        lines = SCons.Util.LogicalLines(fp).readlines()
+        lines = filter(lambda l: l[0] != '#', lines)
+        tdlist = []
+        for line in lines:
+            try:
+                target, depends = string.split(line, ':', 1)
+            except (AttributeError, TypeError, ValueError):
+                # Python 1.5.2 throws TypeError if line isn't a string,
+                # Python 2.x throws AttributeError because it tries
+                # to call line.split().  Either can throw ValueError
+                # if the line doesn't split into two or more elements.
+                pass
+            else:
+                tdlist.append((string.split(target), string.split(depends)))
+        if only_one:
+            targets = reduce(lambda x, y: x+y, map(lambda p: p[0], tdlist))
+            if len(targets) > 1:
+                raise SCons.Errors.UserError, "More than one dependency target found in `%s':  %s" % (filename, targets)
+        for target, depends in tdlist:
+            self.Depends(target, depends)
+
+    def Platform(self, platform):
+        platform = self.subst(platform)
+        return SCons.Platform.Platform(platform)(self)
+
+    def Prepend(self, **kw):
+        """Prepend values to existing construction variables
+        in an Environment.
+        """
+        kw = copy_non_reserved_keywords(kw)
+        for key, val in kw.items():
+            # It would be easier on the eyes to write this using
+            # "continue" statements whenever we finish processing an item,
+            # but Python 1.5.2 apparently doesn't let you use "continue"
+            # within try:-except: blocks, so we have to nest our code.
+            try:
+                orig = self._dict[key]
+            except KeyError:
+                # No existing variable in the environment, so just set
+                # it to the new value.
+                self._dict[key] = val
+            else:
+                try:
+                    # Most straightforward:  just try to add them
+                    # together.  This will work in most cases, when the
+                    # original and new values are of compatible types.
+                    self._dict[key] = val + orig
+                except TypeError:
+                    try:
+                        # Try to update a dictionary value with another.
+                        # If orig isn't a dictionary, it won't have an
+                        # update() method; if val isn't a dictionary,
+                        # it won't have a keys() method.  Either way,
+                        # it's an AttributeError.
+                        orig.update(val)
+                    except AttributeError:
+                        try:
+                            # Check if the added value is a list.
+                            add_to_val = val.append
+                        except AttributeError:
+                            # The added value isn't a list, but the
+                            # original is (by process of elimination),
+                            # so insert the the new value in the original
+                            # (if there's one to insert).
+                            if val:
+                                orig.insert(0, val)
+                        else:
+                            # The added value is a list, so append
+                            # the original to it (if there's a value
+                            # to append).
+                            if orig:
+                                add_to_val(orig)
+                            self._dict[key] = val
+        self.scanner_map_delete(kw)
+
+    def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
+        """Prepend path elements to the path 'name' in the 'ENV'
+        dictionary for this environment.  Will only add any particular
+        path once, and will normpath and normcase all paths to help
+        assure this.  This can also handle the case where the env
+        variable is a list instead of a string.
+        """
+
+        orig = ''
+        if self._dict.has_key(envname) and self._dict[envname].has_key(name):
+            orig = self._dict[envname][name]
+
+        nv = SCons.Util.PrependPath(orig, newpath, sep)
+            
+        if not self._dict.has_key(envname):
+            self._dict[envname] = {}
+
+        self._dict[envname][name] = nv
+
+    def PrependUnique(self, **kw):
+        """Append values to existing construction variables
+        in an Environment, if they're not already there.
+        """
+        kw = copy_non_reserved_keywords(kw)
+        for key, val in kw.items():
+            if not self._dict.has_key(key) or not self._dict[key]:
+                self._dict[key] = val
+            elif SCons.Util.is_Dict(self._dict[key]) and \
+                 SCons.Util.is_Dict(val):
+                self._dict[key].update(val)
+            elif SCons.Util.is_List(val):
+                dk = self._dict[key]
+                if not SCons.Util.is_List(dk):
+                    dk = [dk]
+                val = filter(lambda x, dk=dk: x not in dk, val)
+                self._dict[key] = val + dk
+            else:
+                dk = self._dict[key]
+                if SCons.Util.is_List(dk):
+                    # By elimination, val is not a list.  Since dk is a
+                    # list, wrap val in a list first.
+                    if not val in dk:
+                        self._dict[key] = [val] + dk
+                else:
+                    self._dict[key] = val + dk
+        self.scanner_map_delete(kw)
+
+    def Replace(self, **kw):
+        """Replace existing construction variables in an Environment
+        with new construction variables and/or values.
+        """
+        try:
+            kwbd = our_deepcopy(kw['BUILDERS'])
+            del kw['BUILDERS']
+            self.__setitem__('BUILDERS', kwbd)
+        except KeyError:
+            pass
+        kw = copy_non_reserved_keywords(kw)
+        self._update(our_deepcopy(kw))
+        self.scanner_map_delete(kw)
+
+    def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
+        """
+        Replace old_prefix with new_prefix and old_suffix with new_suffix.
+
+        env - Environment used to interpolate variables.
+        path - the path that will be modified.
+        old_prefix - construction variable for the old prefix.
+        old_suffix - construction variable for the old suffix.
+        new_prefix - construction variable for the new prefix.
+        new_suffix - construction variable for the new suffix.
+        """
+        old_prefix = self.subst('$'+old_prefix)
+        old_suffix = self.subst('$'+old_suffix)
+
+        new_prefix = self.subst('$'+new_prefix)
+        new_suffix = self.subst('$'+new_suffix)
+
+        dir,name = os.path.split(str(path))
+        if name[:len(old_prefix)] == old_prefix:
+            name = name[len(old_prefix):]
+        if name[-len(old_suffix):] == old_suffix:
+            name = name[:-len(old_suffix)]
+        return os.path.join(dir, new_prefix+name+new_suffix)
+
+    def SetDefault(self, **kw):
+        for k in kw.keys():
+            if self._dict.has_key(k):
+                del kw[k]
+        apply(self.Replace, (), kw)
+
+    def Tool(self, tool, toolpath=None, **kw):
+        if SCons.Util.is_String(tool):
+            tool = self.subst(tool)
+            if toolpath is None:
+                toolpath = self.get('toolpath', [])
+            toolpath = map(self.subst, toolpath)
+            tool = apply(SCons.Tool.Tool, (tool, toolpath), kw)
+        tool(self)
+
+    def WhereIs(self, prog, path=None, pathext=None, reject=[]):
+        """Find prog in the path.  __cacheable__
+        """
+        if path is None:
+            try:
+                path = self['ENV']['PATH']
+            except KeyError:
+                pass
+        elif SCons.Util.is_String(path):
+            path = self.subst(path)
+        if pathext is None:
+            try:
+                pathext = self['ENV']['PATHEXT']
+            except KeyError:
+                pass
+        elif SCons.Util.is_String(pathext):
+            pathext = self.subst(pathext)
+        path = SCons.Util.WhereIs(prog, path, pathext, reject)
+        if path: return path
+        return None
+
+    #######################################################################
+    # Public methods for doing real "SCons stuff" (manipulating
+    # dependencies, setting attributes on targets, etc.).  These begin
+    # with upper-case letters.  The essential characteristic of methods
+    # in this section is that they all *should* have corresponding
+    # same-named global functions.
+    #######################################################################
+
+    def Action(self, *args, **kw):
+        nargs = self.subst(args)
+        nkw = self.subst_kw(kw)
+        return apply(SCons.Action.Action, nargs, nkw)
+
+    def AddPreAction(self, files, action):
+        nodes = self.arg2nodes(files, self.fs.Entry)
+        action = SCons.Action.Action(action)
+        uniq = {}
+        for executor in map(lambda n: n.get_executor(), nodes):
+            uniq[executor] = 1
+        for executor in uniq.keys():
+            executor.add_pre_action(action)
+        return nodes
+
+    def AddPostAction(self, files, action):
+        nodes = self.arg2nodes(files, self.fs.Entry)
+        action = SCons.Action.Action(action)
+        uniq = {}
+        for executor in map(lambda n: n.get_executor(), nodes):
+            uniq[executor] = 1
+        for executor in uniq.keys():
+            executor.add_post_action(action)
+        return nodes
+
+    def Alias(self, target, source=[], action=None, **kw):
+        tlist = self.arg2nodes(target, self.ans.Alias)
+        if not SCons.Util.is_List(source):
+            source = [source]
+        source = filter(None, source)
+
+        if not action:
+            if not source:
+                # There are no source files and no action, so just
+                # return a target list of classic Alias Nodes, without
+                # any builder.  The externally visible effect is that
+                # this will make the wrapping Script.BuildTask class
+                # say that there's "Nothing to be done" for this Alias,
+                # instead of that it's "up to date."
+                return tlist
+
+            # No action, but there are sources.  Re-call all the target
+            # builders to add the sources to each target.
+            result = []
+            for t in tlist:
+                bld = t.get_builder(AliasBuilder)
+                result.extend(bld(self, t, source))
+            return result
+
+        nkw = self.subst_kw(kw)
+        nkw.update({
+            'action'            : SCons.Action.Action(action),
+            'source_factory'    : self.fs.Entry,
+            'multi'             : 1,
+            'is_explicit'       : None,
+        })
+        bld = apply(SCons.Builder.Builder, (), nkw)
+
+        # Apply the Builder separately to each target so that the Aliases
+        # stay separate.  If we did one "normal" Builder call with the
+        # whole target list, then all of the target Aliases would be
+        # associated under a single Executor.
+        result = []
+        for t in tlist:
+            # Calling the convert() method will cause a new Executor to be
+            # created from scratch, so we have to explicitly initialize
+            # it with the target's existing sources, plus our new ones,
+            # so nothing gets lost.
+            b = t.get_builder()
+            if b is None or b is AliasBuilder:
+                b = bld
+            else:
+                nkw['action'] = b.action + action
+                b = apply(SCons.Builder.Builder, (), nkw)
+            t.convert()
+            result.extend(b(self, t, t.sources + source))
+        return result
+
+    def AlwaysBuild(self, *targets):
+        tlist = []
+        for t in targets:
+            tlist.extend(self.arg2nodes(t, self.fs.File))
+        for t in tlist:
+            t.set_always_build()
+        return tlist
+
+    def BuildDir(self, build_dir, src_dir, duplicate=1):
+        build_dir = self.arg2nodes(build_dir, self.fs.Dir)[0]
+        src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0]
+        self.fs.BuildDir(build_dir, src_dir, duplicate)
+
+    def Builder(self, **kw):
+        nkw = self.subst_kw(kw)
+        return apply(SCons.Builder.Builder, [], nkw)
+
+    def CacheDir(self, path):
+        self.fs.CacheDir(self.subst(path))
+
+    def Clean(self, targets, files):
+        global CleanTargets
+        tlist = self.arg2nodes(targets, self.fs.Entry)
+        flist = self.arg2nodes(files, self.fs.Entry)
+        for t in tlist:
+            try:
+                CleanTargets[t].extend(flist)
+            except KeyError:
+                CleanTargets[t] = flist
+
+    def Configure(self, *args, **kw):
+        nargs = [self]
+        if args:
+            nargs = nargs + self.subst_list(args)[0]
+        nkw = self.subst_kw(kw)
+        nkw['_depth'] = kw.get('_depth', 0) + 1
+        try:
+            nkw['custom_tests'] = self.subst_kw(nkw['custom_tests'])
+        except KeyError:
+            pass
+        return apply(SCons.SConf.SConf, nargs, nkw)
+
+    def Command(self, target, source, action, **kw):
+        """Builds the supplied target files from the supplied
+        source files using the supplied action.  Action may
+        be any type that the Builder constructor will accept
+        for an action."""
+        bkw = {
+            'action' : action,
+            'target_factory' : self.fs.Entry,
+            'source_factory' : self.fs.Entry,
+        }
+        try: bkw['source_scanner'] = kw['source_scanner']
+        except KeyError: pass
+        else: del kw['source_scanner']
+        bld = apply(SCons.Builder.Builder, (), bkw)
+        return apply(bld, (self, target, source), kw)
+
+    def Depends(self, target, dependency):
+        """Explicity specify that 'target's depend on 'dependency'."""
+        tlist = self.arg2nodes(target, self.fs.Entry)
+        dlist = self.arg2nodes(dependency, self.fs.Entry)
+        for t in tlist:
+            t.add_dependency(dlist)
+        return tlist
+
+    def Dir(self, name, *args, **kw):
+        """
+        """
+        return apply(self.fs.Dir, (self.subst(name),) + args, kw)
+
+    def NoClean(self, *targets):
+        """Tags a target so that it will not be cleaned by -c"""
+        tlist = []
+        for t in targets:
+            tlist.extend(self.arg2nodes(t, self.fs.Entry))
+        for t in tlist:
+            t.set_noclean()
+        return tlist
+
+    def Entry(self, name, *args, **kw):
+        """
+        """
+        return apply(self.fs.Entry, (self.subst(name),) + args, kw)
+
+    def Environment(self, **kw):
+        return apply(SCons.Environment.Environment, [], self.subst_kw(kw))
+
+    def Execute(self, action, *args, **kw):
+        """Directly execute an action through an Environment
+        """
+        action = apply(self.Action, (action,) + args, kw)
+        return action([], [], self)
+
+    def File(self, name, *args, **kw):
+        """
+        """
+        return apply(self.fs.File, (self.subst(name),) + args, kw)
+
+    def FindFile(self, file, dirs):
+        file = self.subst(file)
+        nodes = self.arg2nodes(dirs, self.fs.Dir)
+        return SCons.Node.FS.find_file(file, tuple(nodes))
+
+    def Flatten(self, sequence):
+        return SCons.Util.flatten(sequence)
+
+    def GetBuildPath(self, files):
+        result = map(str, self.arg2nodes(files, self.fs.Entry))
+        if SCons.Util.is_List(files):
+            return result
+        else:
+            return result[0]
+
+    def Ignore(self, target, dependency):
+        """Ignore a dependency."""
+        tlist = self.arg2nodes(target, self.fs.Entry)
+        dlist = self.arg2nodes(dependency, self.fs.Entry)
+        for t in tlist:
+            t.add_ignore(dlist)
+        return tlist
+
+    def Install(self, dir, source):
+        """Install specified files in the given directory."""
+        try:
+            dnodes = self.arg2nodes(dir, self.fs.Dir)
+        except TypeError:
+            raise SCons.Errors.UserError, "Target `%s' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?" % str(dir)
+        try:
+            sources = self.arg2nodes(source, self.fs.File)
+        except TypeError:
+            if SCons.Util.is_List(source):
+                raise SCons.Errors.UserError, "Source `%s' of Install() contains one or more non-files.  Install() source must be one or more files." % repr(map(str, source))
+            else:
+                raise SCons.Errors.UserError, "Source `%s' of Install() is not a file.  Install() source must be one or more files." % str(source)
+        tgt = []
+        for dnode in dnodes:
+            for src in sources:
+                target = self.fs.File(src.name, dnode)
+                tgt.extend(InstallBuilder(self, target, src))
+        return tgt
+
+    def InstallAs(self, target, source):
+        """Install sources as targets."""
+        sources = self.arg2nodes(source, self.fs.File)
+        targets = self.arg2nodes(target, self.fs.File)
+        result = []
+        for src, tgt in map(lambda x, y: (x, y), sources, targets):
+            result.extend(InstallBuilder(self, tgt, src))
+        return result
+
+    def Literal(self, string):
+        return SCons.Subst.Literal(string)
+
+    def Local(self, *targets):
+        ret = []
+        for targ in targets:
+            if isinstance(targ, SCons.Node.Node):
+                targ.set_local()
+                ret.append(targ)
+            else:
+                for t in self.arg2nodes(targ, self.fs.Entry):
+                   t.set_local()
+                   ret.append(t)
+        return ret
+
+    def Precious(self, *targets):
+        tlist = []
+        for t in targets:
+            tlist.extend(self.arg2nodes(t, self.fs.Entry))
+        for t in tlist:
+            t.set_precious()
+        return tlist
+
+    def Repository(self, *dirs, **kw):
+        dirs = self.arg2nodes(list(dirs), self.fs.Dir)
+        apply(self.fs.Repository, dirs, kw)
+
+    def Scanner(self, *args, **kw):
+        nargs = []
+        for arg in args:
+            if SCons.Util.is_String(arg):
+                arg = self.subst(arg)
+            nargs.append(arg)
+        nkw = self.subst_kw(kw)
+        return apply(SCons.Scanner.Scanner, nargs, nkw)
+
+    def SConsignFile(self, name=".sconsign", dbm_module=None):
+        if not name is None:
+            name = self.subst(name)
+            if not os.path.isabs(name):
+                name = os.path.join(str(self.fs.SConstruct_dir), name)
+        SCons.SConsign.File(name, dbm_module)
+
+    def SideEffect(self, side_effect, target):
+        """Tell scons that side_effects are built as side 
+        effects of building targets."""
+        side_effects = self.arg2nodes(side_effect, self.fs.Entry)
+        targets = self.arg2nodes(target, self.fs.Entry)
+
+        for side_effect in side_effects:
+            if side_effect.multiple_side_effect_has_builder():
+                raise SCons.Errors.UserError, "Multiple ways to build the same target were specified for: %s" % str(side_effect)
+            side_effect.add_source(targets)
+            side_effect.side_effect = 1
+            self.Precious(side_effect)
+            for target in targets:
+                target.side_effects.append(side_effect)
+        return side_effects
+
+    def SourceCode(self, entry, builder):
+        """Arrange for a source code builder for (part of) a tree."""
+        entries = self.arg2nodes(entry, self.fs.Entry)
+        for entry in entries:
+            entry.set_src_builder(builder)
+        return entries
+
+    def SourceSignatures(self, type):
+        type = self.subst(type)
+        if type == 'MD5':
+            import SCons.Sig.MD5
+            self._calc_module = SCons.Sig.MD5
+        elif type == 'timestamp':
+            import SCons.Sig.TimeStamp
+            self._calc_module = SCons.Sig.TimeStamp
+        else:
+            raise UserError, "Unknown source signature type '%s'"%type
+
+    def Split(self, arg):
+        """This function converts a string or list into a list of strings
+        or Nodes.  This makes things easier for users by allowing files to
+        be specified as a white-space separated list to be split.
+        The input rules are:
+            - A single string containing names separated by spaces. These will be
+              split apart at the spaces.
+            - A single Node instance
+            - A list containing either strings or Node instances. Any strings
+              in the list are not split at spaces.
+        In all cases, the function returns a list of Nodes and strings."""
+        if SCons.Util.is_List(arg):
+            return map(self.subst, arg)
+        elif SCons.Util.is_String(arg):
+            return string.split(self.subst(arg))
+        else:
+            return [self.subst(arg)]
+
+    def TargetSignatures(self, type):
+        type = self.subst(type)
+        if type == 'build':
+            self._build_signature = 1
+        elif type == 'content':
+            self._build_signature = 0
+        else:
+            raise SCons.Errors.UserError, "Unknown target signature type '%s'"%type
+
+    def Value(self, value):
+        """
+        """
+        return SCons.Node.Python.Value(value)
+
+class OverrideEnvironment(Base):
+    """A proxy that overrides variables in a wrapped construction
+    environment by returning values from an overrides dictionary in
+    preference to values from the underlying subject environment.
+
+    This is a lightweight (I hope) proxy that passes through most use of
+    attributes to the underlying Environment.Base class, but has just
+    enough additional methods defined to act like a real construction
+    environment with overridden values.  It can wrap either a Base
+    construction environment, or another OverrideEnvironment, which
+    can in turn nest arbitrary OverrideEnvironments...
+
+    Note that we do *not* call the underlying base class
+    (SubsitutionEnvironment) initialization, because we get most of those
+    from proxying the attributes of the subject construction environment.
+    But because we subclass SubstitutionEnvironment, this class also
+    has inherited arg2nodes() and subst*() methods; those methods can't
+    be proxied because they need *this* object's methods to fetch the
+    values from the overrides dictionary.
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self, subject, overrides={}):
+        if __debug__: logInstanceCreation(self, 'Environment.OverrideEnvironment')
+        self.__dict__['__subject'] = subject
+        self.__dict__['overrides'] = overrides
+
+    # Methods that make this class act like a proxy.
+    def __getattr__(self, name):
+        return getattr(self.__dict__['__subject'], name)
+    def __setattr__(self, name, value):
+        return setattr(self.__dict__['__subject'], name, value)
+
+    # Methods that make this class act like a dictionary.
+    def __getitem__(self, key):
+        try:
+            return self.__dict__['overrides'][key]
+        except KeyError:
+            return self.__dict__['__subject'].__getitem__(key)
+    def __setitem__(self, key, value):
+        if not SCons.Util.is_valid_construction_var(key):
+            raise SCons.Errors.UserError, "Illegal construction variable `%s'" % key
+        self.__dict__['overrides'][key] = value
+    def __delitem__(self, key):
+        try:
+            del self.__dict__['overrides'][key]
+        except KeyError:
+            deleted = 0
+        else:
+            deleted = 1
+        try:
+            result = self.__dict__['__subject'].__delitem__(key)
+        except KeyError:
+            if not deleted:
+                raise
+            result = None
+        return result
+    def get(self, key, default=None):
+        """Emulates the get() method of dictionaries."""
+        try:
+            return self.__dict__['overrides'][key]
+        except KeyError:
+            return self.__dict__['__subject'].get(key, default)
+    def has_key(self, key):
+        try:
+            self.__dict__['overrides'][key]
+            return 1
+        except KeyError:
+            return self.__dict__['__subject'].has_key(key)
+    def Dictionary(self):
+        """Emulates the items() method of dictionaries."""
+        d = self.__dict__['__subject'].Dictionary().copy()
+        d.update(self.__dict__['overrides'])
+        return d
+    def items(self):
+        """Emulates the items() method of dictionaries."""
+        return self.Dictionary().items()
+
+    # Overridden private construction environment methods.
+    def _update(self, dict):
+        """Update an environment's values directly, bypassing the normal
+        checks that occur when users try to set items.
+        """
+        self.__dict__['overrides'].update(dict)
+
+    def gvars(self):
+        return self.__dict__['__subject'].gvars()
+
+    def lvars(self):
+        lvars = self.__dict__['__subject'].lvars()
+        lvars.update(self.__dict__['overrides'])
+        return lvars
+
+    # Overridden public construction environment methods.
+    def Replace(self, **kw):
+        kw = copy_non_reserved_keywords(kw)
+        self.__dict__['overrides'].update(our_deepcopy(kw))
+
+# The entry point that will be used by the external world
+# to refer to a construction environment.  This allows the wrapper
+# interface to extend a construction environment for its own purposes
+# by subclassing SCons.Environment.Base and then assigning the
+# class to SCons.Environment.Environment.
+
+Environment = Base
+
+# An entry point for returning a proxy subclass instance that overrides
+# the subst*() methods so they don't actually perform construction
+# variable substitution.  This is specifically intended to be the shim
+# layer in between global function calls (which don't want construction
+# variable substitution) and the DefaultEnvironment() (which would
+# substitute variables if left to its own devices)."""
+#
+# We have to wrap this in a function that allows us to delay definition of
+# the class until it's necessary, so that when it subclasses Environment
+# it will pick up whatever Environment subclass the wrapper interface
+# might have assigned to SCons.Environment.Environment.
+
+def NoSubstitutionProxy(subject):
+    class _NoSubstitutionProxy(Environment):
+        def __init__(self, subject):
+            self.__dict__['__subject'] = subject
+        def __getattr__(self, name):
+            return getattr(self.__dict__['__subject'], name)
+        def __setattr__(self, name, value):
+            return setattr(self.__dict__['__subject'], name, value)
+        def raw_to_mode(self, dict):
+            try:
+                raw = dict['raw']
+            except KeyError:
+                pass
+            else:
+                del dict['raw']
+                dict['mode'] = raw
+        def subst(self, string, *args, **kwargs):
+            return string
+        def subst_kw(self, kw, *args, **kwargs):
+            return kw
+        def subst_list(self, string, *args, **kwargs):
+            nargs = (string, self,) + args
+            nkw = kwargs.copy()
+            nkw['gvars'] = {}
+            self.raw_to_mode(nkw)
+            return apply(SCons.Subst.scons_subst_list, nargs, nkw)
+        def subst_target_source(self, string, *args, **kwargs):
+            nargs = (string, self,) + args
+            nkw = kwargs.copy()
+            nkw['gvars'] = {}
+            self.raw_to_mode(nkw)
+            return apply(SCons.Subst.scons_subst, nargs, nkw)
+    return _NoSubstitutionProxy(subject)
+
+if SCons.Memoize.use_old_memoization():
+    _Base = Base
+    class Base(SCons.Memoize.Memoizer, _Base):
+        def __init__(self, *args, **kw):
+            SCons.Memoize.Memoizer.__init__(self)
+            apply(_Base.__init__, (self,)+args, kw)
+    Environment = Base
+

Added: cs/scons/scons-local-0.96.92/SCons/Errors.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Errors.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Errors.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+"""SCons.Errors
+
+This file contains the exception classes used to handle internal
+and user errors in SCons.
+
+"""
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Errors.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+
+class BuildError(Exception):
+    def __init__(self, node=None, errstr="Unknown error", filename=None, *args):
+        self.node = node
+        self.errstr = errstr
+        self.filename = filename
+        apply(Exception.__init__, (self,) + args)
+
+class InternalError(Exception):
+    pass
+
+class UserError(Exception):
+    pass
+
+class StopError(Exception):
+    pass
+
+class ExplicitExit(Exception):
+    def __init__(self, node=None, status=None, *args):
+        self.node = node
+        self.status = status
+        apply(Exception.__init__, (self,) + args)
+
+class TaskmasterException(Exception):
+    def __init__(self, node=None, exc_info=(None, None, None), *args):
+        self.node = node
+        self.errstr = "Exception"
+        self.exc_info = exc_info
+        apply(Exception.__init__, (self,) + args)

Added: cs/scons/scons-local-0.96.92/SCons/Executor.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Executor.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Executor.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,268 @@
+"""SCons.Executor
+
+A module for executing actions with specific lists of target and source
+Nodes.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Executor.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+
+from SCons.Debug import logInstanceCreation
+import SCons.Util
+
+
+class Executor:
+    """A class for controlling instances of executing an action.
+
+    This largely exists to hold a single association of an action,
+    environment, list of environment override dictionaries, targets
+    and sources for later processing as needed.
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self, action, env=None, overridelist=[{}],
+                 targets=[], sources=[], builder_kw={}):
+        if __debug__: logInstanceCreation(self, 'Executor.Executor')
+        self.set_action_list(action)
+        self.pre_actions = []
+        self.post_actions = []
+        self.env = env
+        self.overridelist = overridelist
+        self.targets = targets
+        self.sources = sources[:]
+        self.builder_kw = builder_kw
+
+    def set_action_list(self, action):
+        if not SCons.Util.is_List(action):
+            if not action:
+                raise SCons.Errors.UserError, "Executor must have an action."
+            action = [action]
+        self.action_list = action
+
+    def get_action_list(self):
+        return self.pre_actions + self.action_list + self.post_actions
+
+    def get_build_env(self):
+        """Fetch or create the appropriate build Environment
+        for this Executor.
+        __cacheable__
+        """
+        # Create the build environment instance with appropriate
+        # overrides.  These get evaluated against the current
+        # environment's construction variables so that users can
+        # add to existing values by referencing the variable in
+        # the expansion.
+        overrides = {}
+        for odict in self.overridelist:
+            overrides.update(odict)
+
+        import SCons.Defaults
+        env = self.env or SCons.Defaults.DefaultEnvironment()
+        build_env = env.Override(overrides)
+
+        return build_env
+
+    def get_build_scanner_path(self, scanner):
+        """Fetch the scanner path for this executor's targets
+        and sources.
+        """
+        env = self.get_build_env()
+        try:
+            cwd = self.targets[0].cwd
+        except (IndexError, AttributeError):
+            cwd = None
+        return scanner.path(env, cwd, self.targets, self.sources)
+
+    def get_kw(self, kw={}):
+        result = self.builder_kw.copy()
+        result.update(kw)
+        return result
+
+    def do_nothing(self, target, exitstatfunc, kw):
+        pass
+
+    def do_execute(self, target, exitstatfunc, kw):
+        """Actually execute the action list."""
+        env = self.get_build_env()
+        kw = self.get_kw(kw)
+        for act in self.get_action_list():
+            apply(act,
+                  (self.targets, self.sources, env, exitstatfunc),
+                  kw)
+
+    # use extra indirection because with new-style objects (Python 2.2
+    # and above) we can't override special methods, and nullify() needs
+    # to be able to do this.
+
+    def __call__(self, target, exitstatfunc, **kw):
+        self.do_execute(target, exitstatfunc, kw)
+
+    def cleanup(self):
+        "__reset_cache__"
+        pass
+
+    def add_sources(self, sources):
+        """Add source files to this Executor's list.  This is necessary
+        for "multi" Builders that can be called repeatedly to build up
+        a source file list for a given target."""
+        slist = filter(lambda x, s=self.sources: x not in s, sources)
+        self.sources.extend(slist)
+
+    def add_pre_action(self, action):
+        self.pre_actions.append(action)
+
+    def add_post_action(self, action):
+        self.post_actions.append(action)
+
+    # another extra indirection for new-style objects and nullify...
+
+    def my_str(self):
+        env = self.get_build_env()
+        get = lambda action, t=self.targets, s=self.sources, e=env: \
+                     action.genstring(t, s, e)
+        return string.join(map(get, self.get_action_list()), "\n")
+
+
+    def __str__(self):
+        "__cacheable__"
+        return self.my_str()
+
+    def nullify(self):
+        "__reset_cache__"
+        self.do_execute = self.do_nothing
+        self.my_str     = lambda S=self: ''
+
+    def get_contents(self):
+        """Fetch the signature contents.  This, along with
+        get_raw_contents(), is the real reason this class exists, so we
+        can compute this once and cache it regardless of how many target
+        or source Nodes there are.
+        __cacheable__
+        """
+        env = self.get_build_env()
+        get = lambda action, t=self.targets, s=self.sources, e=env: \
+                     action.get_contents(t, s, e)
+        return string.join(map(get, self.get_action_list()), "")
+
+    def get_timestamp(self):
+        """Fetch a time stamp for this Executor.  We don't have one, of
+        course (only files do), but this is the interface used by the
+        timestamp module.
+        """
+        return 0
+
+    def scan_targets(self, scanner):
+        self.scan(scanner, self.targets)
+
+    def scan_sources(self, scanner):
+        if self.sources:
+            self.scan(scanner, self.sources)
+
+    def scan(self, scanner, node_list):
+        """Scan a list of this Executor's files (targets or sources) for
+        implicit dependencies and update all of the targets with them.
+        This essentially short-circuits an N*M scan of the sources for
+        each individual target, which is a hell of a lot more efficient.
+        """
+        env = self.get_build_env()
+        select_specific_scanner = lambda t: (t[0], t[1].select(t[0]))
+        remove_null_scanners = lambda t: not t[1] is None
+        add_scanner_path = lambda t, s=self: \
+                                  (t[0], t[1], s.get_build_scanner_path(t[1]))
+        if scanner:
+            scanner_list = map(lambda n, s=scanner: (n, s), node_list)
+        else:
+            kw = self.get_kw()
+            get_initial_scanners = lambda n, e=env, kw=kw: \
+                                          (n, n.get_env_scanner(e, kw))
+            scanner_list = map(get_initial_scanners, node_list)
+            scanner_list = filter(remove_null_scanners, scanner_list)
+
+        scanner_list = map(select_specific_scanner, scanner_list)
+        scanner_list = filter(remove_null_scanners, scanner_list)
+        scanner_path_list = map(add_scanner_path, scanner_list)
+        deps = []
+        for node, scanner, path in scanner_path_list:
+            deps.extend(node.get_implicit_deps(env, scanner, path))
+
+        for tgt in self.targets:
+            tgt.add_to_implicit(deps)
+
+    def get_missing_sources(self):
+        """
+        __cacheable__
+        """
+        return filter(lambda s: s.missing(), self.sources)
+
+    def get_unignored_sources(self, ignore):
+        """__cacheable__"""
+        sourcelist = self.sources
+        if ignore:
+            sourcelist = filter(lambda s, i=ignore: not s in i, sourcelist)
+        return sourcelist
+
+    def process_sources(self, func, ignore=[]):
+        """__cacheable__"""
+        return map(func, self.get_unignored_sources(ignore))
+
+
+_Executor = Executor
+
+class Null(_Executor):
+    """A null Executor, with a null build Environment, that does
+    nothing when the rest of the methods call it.
+
+    This might be able to disapper when we refactor things to
+    disassociate Builders from Nodes entirely, so we're not
+    going to worry about unit tests for this--at least for now.
+    """
+    def __init__(self, *args, **kw):
+        if __debug__: logInstanceCreation(self, 'Executor.Null')
+        kw['action'] = []
+        apply(_Executor.__init__, (self,), kw)
+    def get_build_env(self):
+        class NullEnvironment:
+            def get_scanner(self, key):
+                return None
+        return NullEnvironment()
+    def get_build_scanner_path(self):
+        return None
+    def cleanup(self):
+        pass
+
+
+
+if SCons.Memoize.use_old_memoization():
+    _Base = Executor
+    class Executor(SCons.Memoize.Memoizer, _Base):
+        def __init__(self, *args, **kw):
+            SCons.Memoize.Memoizer.__init__(self)
+            apply(_Base.__init__, (self,)+args, kw)
+

Added: cs/scons/scons-local-0.96.92/SCons/Job.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Job.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Job.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,265 @@
+"""SCons.Job
+
+This module defines the Serial and Parallel classes that execute tasks to
+complete a build. The Jobs class provides a higher level interface to start,
+stop, and wait on jobs.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Job.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+class Jobs:
+    """An instance of this class initializes N jobs, and provides
+    methods for starting, stopping, and waiting on all N jobs.
+    """
+
+    def __init__(self, num, taskmaster):
+        """
+        create 'num' jobs using the given taskmaster.
+
+        If 'num' is 1 or less, then a serial job will be used,
+        otherwise a parallel job with 'num' worker threads will
+        be used.
+
+        The 'num_jobs' attribute will be set to the actual number of jobs
+        allocated.  If more than one job is requested but the Parallel
+        class can't do it, it gets reset to 1.  Wrapping interfaces that
+        care should check the value of 'num_jobs' after initialization.
+        """
+
+        self.job = None
+        if num > 1:
+            try:
+                self.job = Parallel(taskmaster, num)
+                self.num_jobs = num
+            except NameError:
+                pass
+        if self.job is None:
+            self.job = Serial(taskmaster)
+            self.num_jobs = 1
+
+    def run(self):
+        """run the job"""
+        try:
+            self.job.start()
+        except KeyboardInterrupt:
+            # mask any further keyboard interrupts so that scons
+            # can shutdown cleanly:
+            # (this only masks the keyboard interrupt for Python,
+            #  child processes can still get the keyboard interrupt)
+            import signal
+            signal.signal(signal.SIGINT, signal.SIG_IGN)
+            raise
+
+class Serial:
+    """This class is used to execute tasks in series, and is more efficient
+    than Parallel, but is only appropriate for non-parallel builds. Only
+    one instance of this class should be in existence at a time.
+
+    This class is not thread safe.
+    """
+
+    def __init__(self, taskmaster):
+        """Create a new serial job given a taskmaster. 
+
+        The taskmaster's next_task() method should return the next task
+        that needs to be executed, or None if there are no more tasks. The
+        taskmaster's executed() method will be called for each task when it
+        is successfully executed or failed() will be called if it failed to
+        execute (e.g. execute() raised an exception). The taskmaster's
+        is_blocked() method will not be called.  """
+        
+        self.taskmaster = taskmaster
+
+    def start(self):
+        """Start the job. This will begin pulling tasks from the taskmaster
+        and executing them, and return when there are no more tasks. If a task
+        fails to execute (i.e. execute() raises an exception), then the job will
+        stop."""
+        
+        while 1:
+            task = self.taskmaster.next_task()
+
+            if task is None:
+                break
+
+            try:
+                task.prepare()
+                task.execute()
+            except KeyboardInterrupt:
+                raise
+            except:
+                task.exception_set()
+                # Let the failed() callback function arrange for the
+                # build to stop if that's appropriate.
+                task.failed()
+            else:
+                task.executed()
+
+            task.postprocess()
+
+
+# Trap import failure so that everything in the Job module but the
+# Parallel class (and its dependent classes) will work if the interpreter
+# doesn't support threads.
+try:
+    import Queue
+    import threading
+except ImportError:
+    pass
+else:
+    class Worker(threading.Thread):
+        """A worker thread waits on a task to be posted to its request queue,
+        dequeues the task, executes it, and posts a tuple including the task
+        and a boolean indicating whether the task executed successfully. """
+
+        def __init__(self, requestQueue, resultsQueue):
+            threading.Thread.__init__(self)
+            self.setDaemon(1)
+            self.requestQueue = requestQueue
+            self.resultsQueue = resultsQueue
+            self.start()
+
+        def run(self):
+            while 1:
+                task = self.requestQueue.get()
+
+                try:
+                    task.execute()
+                except KeyboardInterrupt:
+                    # be explicit here for test/interrupts.py
+                    ok = False
+                except:
+                    task.exception_set()
+                    ok = 0
+                else:
+                    ok = 1
+
+                self.resultsQueue.put((task, ok))
+
+    class ThreadPool:
+        """This class is responsible for spawning and managing worker threads."""
+
+        def __init__(self, num):
+            """Create the request and reply queues, and 'num' worker threads."""
+            self.requestQueue = Queue.Queue(0)
+            self.resultsQueue = Queue.Queue(0)
+
+            # Create worker threads
+            for i in range(num):
+                Worker(self.requestQueue, self.resultsQueue)
+
+        def put(self, obj):
+            """Put task into request queue."""
+            self.requestQueue.put(obj)
+
+        def get(self, block = 1):
+            """Remove and return a result tuple from the results queue."""
+            return self.resultsQueue.get(block)
+
+        def preparation_failed(self, obj):
+            self.resultsQueue.put((obj, 0))
+
+    class Parallel:
+        """This class is used to execute tasks in parallel, and is somewhat 
+        less efficient than Serial, but is appropriate for parallel builds.
+
+        This class is thread safe.
+        """
+
+        def __init__(self, taskmaster, num):
+            """Create a new parallel job given a taskmaster.
+
+            The taskmaster's next_task() method should return the next task
+            that needs to be executed, or None if there are no more tasks. The
+            taskmaster's executed() method will be called for each task when it
+            is successfully executed or failed() will be called if the task
+            failed to execute (i.e. execute() raised an exception).  The
+            taskmaster's is_blocked() method should return true iff there are
+            more tasks, but they can't be executed until one or more other
+            tasks have been executed. next_task() will be called iff
+            is_blocked() returned false.
+
+            Note: calls to taskmaster are serialized, but calls to execute() on
+            distinct tasks are not serialized, because that is the whole point
+            of parallel jobs: they can execute multiple tasks
+            simultaneously. """
+
+            self.taskmaster = taskmaster
+            self.tp = ThreadPool(num)
+
+            self.maxjobs = num
+
+        def start(self):
+            """Start the job. This will begin pulling tasks from the
+            taskmaster and executing them, and return when there are no
+            more tasks. If a task fails to execute (i.e. execute() raises
+            an exception), then the job will stop."""
+
+            jobs = 0
+            
+            while 1:
+                # Start up as many available tasks as we're
+                # allowed to.
+                while jobs < self.maxjobs:
+                    task = self.taskmaster.next_task()
+                    if task is None:
+                        break
+
+                    # prepare task for execution
+                    try:
+                        task.prepare()
+                    except KeyboardInterrupt:
+                        raise
+                    except:
+                        # Let the failed() callback function arrange
+                        # for the build to stop if that's appropriate.
+                        task.exception_set()
+                        self.tp.preparation_failed(task)
+                        jobs = jobs + 1
+                        continue
+
+                    # dispatch task
+                    self.tp.put(task)
+                    jobs = jobs + 1
+
+                if not task and not jobs: break
+
+                # Let any/all completed tasks finish up before we go
+                # back and put the next batch of tasks on the queue.
+                while 1:
+                    task, ok = self.tp.get()
+
+                    jobs = jobs - 1
+                    if ok:
+                        task.executed()
+                    else:
+                        task.failed()
+
+                    task.postprocess()
+
+                    if self.tp.resultsQueue.empty():
+                        break

Added: cs/scons/scons-local-0.96.92/SCons/Memoize.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Memoize.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Memoize.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,832 @@
+"""Memoizer
+
+Memoizer -- base class to provide automatic, optimized caching of
+method return values for subclassed objects.  Caching is activated by
+the presence of "__cacheable__" in the doc of a method (acts like a
+decorator).  The presence of "__cache_reset__" or "__reset_cache__"
+in the doc string instead indicates a method that should reset the
+cache, discarding any currently cached values.
+
+Note: current implementation is optimized for speed, not space.  The
+cache reset operation does not actually discard older results, and in
+fact, all cached results (and keys) are held indefinitely.
+
+Most of the work for this is done by copying and modifying the class
+definition itself, rather than the object instances.  This will
+therefore allow all instances of a class to get caching activated
+without requiring lengthy initialization or other management of the
+instance.
+
+[This could also be done using metaclassing (which would require
+Python 2.2) and decorators (which would require Python 2.4).  Current
+implementation is used due to Python 1.5.2 compatability requirement
+contraint.]
+
+A few notes:
+
+    * All local methods/attributes use a prefix of "_MeMoIZeR" to avoid
+      namespace collisions with the attributes of the objects
+      being cached.
+
+    * Based on performance evaluations of dictionaries, caching is
+      done by providing each object with a unique key attribute and
+      using the value of that attribute as an index for dictionary
+      lookup.  If an object doesn't have one of these attributes,
+      fallbacks are utilized (although they will be somewhat slower).
+
+      * To support this unique-value attribute correctly, it must be
+        removed whenever a __cmp__ operation is performed, and it must
+        be updated whenever a copy.copy or copy.deepcopy is performed,
+        so appropriate manipulation is provided by the Caching code
+        below.
+
+    * Cached values are stored in the class (indexed by the caching
+      key attribute, then by the name of the method called and the
+      constructed key of the arguments passed).  By storing them here
+      rather than on the instance, the instance can be compared,
+      copied, and pickled much easier.
+
+Some advantages:
+
+    * The method by which caching is implemented can be changed in a
+      single location and it will apply globally.
+
+    * Greatly simplified client code: remove lots of try...except or
+      similar handling of cached lookup.  Also usually more correct in
+      that it based caching on all input arguments whereas many
+      hand-implemented caching operations often miss arguments that
+      might affect results.
+
+    * Caching can be globally disabled very easily (for testing, etc.)
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Memoize.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+#TBD: for pickling, should probably revert object to unclassed state...
+
+import copy
+import os
+import string
+import sys
+
+# A flag controlling whether or not we actually use memoization.
+use_memoizer = 1
+
+#
+# Generate a key for an object that is to be used as the caching key
+# for that object.
+#
+# Current implementation: singleton generating a monotonically
+# increasing integer
+
+class MemoizerKey:
+    def __init__(self):
+        self._next_keyval = 0
+    def __call__(self):
+        r = self._next_keyval
+        self._next_keyval = self._next_keyval + 1
+        return str(r)
+Next_Memoize_Key = MemoizerKey()
+
+
+#
+# Memoized Class management.
+#
+# Classes can be manipulated just like object instances; we are going
+# to do some of that here, without the benefit of metaclassing
+# introduced in Python 2.2 (it would be nice to use that, but this
+# attempts to maintain backward compatibility to Python 1.5.2).
+#
+# The basic implementation therefore is to update the class definition
+# for any objects that we want to enable caching for.  The updated
+# definition performs caching activities for those methods
+# appropriately marked in the original class.
+#
+# When an object is created, its class is switched to this updated,
+# cache-enabled class definition, thereby enabling caching operations.
+#
+# To get an instance to used the updated, caching class, the instance
+# must declare the Memoizer as a base class and make sure to call the
+# Memoizer's __init__ during the instance's __init__.  The Memoizer's
+# __init__ will perform the class updating.
+
+# For Python 2.2 and later, where metaclassing is supported, it is
+# sufficient to provide a "__metaclass__ = Memoized_Metaclass" as part
+# of the class definition; the metaclassing will automatically invoke
+# the code herein properly.
+
+##import cPickle
+##def ALT0_MeMoIZeR_gen_key(argtuple, kwdict):
+##    return cPickle.dumps( (argtuple,kwdict) )
+
+def ALT1_MeMoIZeR_gen_key(argtuple, kwdict):
+    return repr(argtuple) + '|' + repr(kwdict)
+
+def ALT2_MeMoIZeR_gen_key(argtuple, kwdict):
+    return string.join(map(lambda A:
+                           getattr(A, '_MeMoIZeR_Key', str(A)),
+                           argtuple) + \
+                       map(lambda D:
+                           str(D[0])+
+                           getattr(D[1], '_MeMoIZeR_Key', str(D[1])),
+                           kwdict.items()),
+                       '|')
+
+def ALT3_MeMoIZeR_gen_key(argtuple, kwdict):
+    ret = []
+    for A in argtuple:
+        X = getattr(A, '_MeMoIZeR_Key', None)
+        if X:
+            ret.append(X)
+        else:
+            ret.append(str(A))
+    for K,V in kwdict.items():
+        ret.append(str(K))
+        X = getattr(V, '_MeMoIZeR_Key', None)
+        if X:
+            ret.append(X)
+        else:
+            ret.append(str(V))
+    return string.join(ret, '|')
+
+def ALT4_MeMoIZeR_gen_key(argtuple, kwdict):
+    if kwdict:
+        return string.join(map(lambda A:
+                               getattr(A, '_MeMoIZeR_Key', None) or str(A),
+                               argtuple) + \
+                           map(lambda D:
+                               str(D[0])+
+                               (getattr(D[1], '_MeMoIZeR_Key', None) or str(D[1])),
+                               kwdict.items()),
+                           '|')
+    return string.join(map(lambda A:
+                        getattr(A, '_MeMoIZeR_Key', None) or str(A),
+                        argtuple),
+                       '!')
+
+def ALT5_MeMoIZeR_gen_key(argtuple, kwdict):
+    A = string.join(map(str, argtuple), '|')
+    K = ''
+    if kwdict:
+        I = map(lambda K,D=kwdict: str(K)+'='+str(D[K]), kwdict.keys())
+        K = string.join(I, '|')
+    return string.join([A,K], '!')
+
+def ALT6_MeMoIZeR_gen_key(argtuple, kwdict):
+    A = string.join(map(str, map(id, argtuple)), '|')
+    K = ''
+    if kwdict:
+        I = map(lambda K,D=kwdict: str(K)+'='+str(id(D[K])), kwdict.keys())
+        K = string.join(I, '|')
+    return string.join([A,K], '!')
+
+def ALT7_MeMoIZeR_gen_key(argtuple, kwdict):
+    A = string.join(map(repr, argtuple), '|')
+    K = ''
+    if kwdict:
+        I = map(lambda K,D=kwdict: repr(K)+'='+repr(D[K]), kwdict.keys())
+        K = string.join(I, '|')
+    return string.join([A,K], '!')
+
+def ALT8_MeMoIZeR_gen_key(argtuple, kwdict):
+    ret = []
+    for A in argtuple:
+        X = getattr(A, '_MeMoIZeR_Key', None)
+        if X:
+            ret.append(X)
+        else:
+            ret.append(repr(A))
+    for K,V in kwdict.items():
+        ret.append(str(K))
+        X = getattr(V, '_MeMoIZeR_Key', None)
+        if X:
+            ret.append(X)
+        else:
+            ret.append(repr(V))
+    return string.join(ret, '|')
+
+def ALT9_MeMoIZeR_gen_key(argtuple, kwdict):
+    ret = []
+    for A in argtuple:
+        try:
+            X = A.__dict__.get('_MeMoIZeR_Key', None) or repr(A)
+        except (AttributeError, KeyError):
+            X = repr(A)
+        ret.append(X)
+    for K,V in kwdict.items():
+        ret.append(str(K))
+        ret.append('=')
+        try:
+            X = V.__dict__.get('_MeMoIZeR_Key', None) or repr(V)
+        except (AttributeError, KeyError):
+            X = repr(V)
+        ret.append(X)
+    return string.join(ret, '|')
+
+#_MeMoIZeR_gen_key = ALT9_MeMoIZeR_gen_key    # 8.8, 0.20
+_MeMoIZeR_gen_key = ALT8_MeMoIZeR_gen_key    # 8.5, 0.18
+#_MeMoIZeR_gen_key = ALT7_MeMoIZeR_gen_key    # 8.7, 0.17
+#_MeMoIZeR_gen_key = ALT6_MeMoIZeR_gen_key    #
+#_MeMoIZeR_gen_key = ALT5_MeMoIZeR_gen_key    # 9.7, 0.20
+#_MeMoIZeR_gen_key = ALT4_MeMoIZeR_gen_key    # 8.6, 0.19
+#_MeMoIZeR_gen_key = ALT3_MeMoIZeR_gen_key    # 8.5, 0.20
+#_MeMoIZeR_gen_key = ALT2_MeMoIZeR_gen_key    # 10.1, 0.22
+#_MeMoIZeR_gen_key = ALT1_MeMoIZeR_gen_key    # 8.6 0.18
+
+
+
+## This is really the core worker of the Memoize module.  Any
+## __cacheable__ method ends up calling this function which tries to
+## return a previously cached value if it exists, and which calls the
+## actual function and caches the return value if it doesn't already
+## exist.
+##
+## This function should be VERY efficient: it will get called a lot
+## and its job is to be faster than what would be called.
+
+def Memoizer_cache_get(func, cdict, args, kw):
+    """Called instead of name to see if this method call's return
+    value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return."""
+
+    obj = args[0]
+
+    ckey = obj._MeMoIZeR_Key + ':' + _MeMoIZeR_gen_key(args, kw)
+
+##    try:
+##        rval = cdict[ckey]
+##    except KeyError:
+##        rval = cdict[ckey] = apply(func, args, kw)
+
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = apply(func, args, kw)
+
+##    rval = cdict.setdefault(ckey, apply(func, args, kw))
+
+##    if cdict.has_key(ckey):
+##        rval = cdict[ckey]
+##    else:
+##        rval = cdict[ckey] = apply(func, args, kw)
+
+    return rval
+
+def Memoizer_cache_get_self(func, cdict, self):
+    """Called instead of func(self) to see if this method call's
+    return value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return.
+    Optimized version of Memoizer_cache_get for methods that take the
+    object instance as the only argument."""
+
+    ckey = self._MeMoIZeR_Key
+
+##    try:
+##        rval = cdict[ckey]
+##    except KeyError:
+##        rval = cdict[ckey] = func(self)
+
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = func(self)
+
+##    rval = cdict.setdefault(ckey, func(self)))
+
+##    if cdict.has_key(ckey):
+##        rval = cdict[ckey]
+##    else:
+##        rval = cdict[ckey] = func(self)
+
+    return rval
+
+def Memoizer_cache_get_one(func, cdict, self, arg):
+    """Called instead of func(self, arg) to see if this method call's
+    return value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return.
+    Optimized version of Memoizer_cache_get for methods that take the
+    object instance and one other argument only."""
+
+##    X = getattr(arg, "_MeMoIZeR_Key", None)
+##    if X:
+##        ckey = self._MeMoIZeR_Key +':'+ X
+##    else:
+##        ckey = self._MeMoIZeR_Key +':'+ str(arg)
+    ckey = self._MeMoIZeR_Key + ':' + \
+           (getattr(arg, "_MeMoIZeR_Key", None) or repr(arg))
+
+##    try:
+##        rval = cdict[ckey]
+##    except KeyError:
+##        rval = cdict[ckey] = func(self, arg)
+
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = func(self, arg)
+
+##    rval = cdict.setdefault(ckey, func(self, arg)))
+
+##    if cdict.has_key(ckey):
+##        rval = cdict[ckey]
+##    else:
+##        rval = cdict[ckey] = func(self, arg)
+
+    return rval
+
+#
+# Caching stuff is tricky, because the tradeoffs involved are often so
+# non-obvious, so we're going to support an alternate set of functions
+# that also count the hits and misses, to try to get a concrete idea of
+# which Memoizations seem to pay off.
+#
+# Because different configurations can have such radically different
+# performance tradeoffs, interpreting the hit/miss results will likely be
+# more of an art than a science.  In other words, don't assume that just
+# because you see no hits in one configuration that it's not worthwhile
+# Memoizing that method.
+#
+# Note that these are essentially cut-and-paste copies of the above
+# Memozer_cache_get*() implementations, with the addition of the
+# counting logic.  If the above implementations change, the
+# corresponding change should probably be made down below as well,
+# just to try to keep things in sync.
+#
+
+class CounterEntry:
+    def __init__(self):
+        self.hit = 0
+        self.miss = 0
+
+import UserDict
+class Counter(UserDict.UserDict):
+    def __call__(self, obj, methname):
+        k = obj.__class__.__name__ + '.' + methname
+        try:
+            return self[k]
+        except KeyError:
+            c = self[k] = CounterEntry()
+            return c
+
+CacheCount = Counter()
+CacheCountSelf = Counter()
+CacheCountOne = Counter()
+
+def Dump():
+    items = CacheCount.items() + CacheCountSelf.items() + CacheCountOne.items()
+    items.sort()
+    for k, v in items:
+        print "    %7d hits %7d misses   %s()" % (v.hit, v.miss, k)
+
+def Count_cache_get(name, func, cdict, args, kw):
+    """Called instead of name to see if this method call's return
+    value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return."""
+
+    obj = args[0]
+
+    ckey = obj._MeMoIZeR_Key + ':' + _MeMoIZeR_gen_key(args, kw)
+
+    c = CacheCount(obj, name)
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = apply(func, args, kw)
+        c.miss = c.miss + 1
+    else:
+        c.hit = c.hit + 1
+
+    return rval
+
+def Count_cache_get_self(name, func, cdict, self):
+    """Called instead of func(self) to see if this method call's
+    return value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return.
+    Optimized version of Memoizer_cache_get for methods that take the
+    object instance as the only argument."""
+
+    ckey = self._MeMoIZeR_Key
+
+    c = CacheCountSelf(self, name)
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = func(self)
+        c.miss = c.miss + 1
+    else:
+        c.hit = c.hit + 1
+
+    return rval
+
+def Count_cache_get_one(name, func, cdict, self, arg):
+    """Called instead of func(self, arg) to see if this method call's
+    return value has been cached.  If it has, just return the cached
+    value; if not, call the actual method and cache the return.
+    Optimized version of Memoizer_cache_get for methods that take the
+    object instance and one other argument only."""
+
+    ckey = self._MeMoIZeR_Key + ':' + \
+           (getattr(arg, "_MeMoIZeR_Key", None) or repr(arg))
+
+    c = CacheCountOne(self, name)
+    rval = cdict.get(ckey, "_MeMoIZeR")
+    if rval is "_MeMoIZeR":
+        rval = cdict[ckey] = func(self, arg)
+        c.miss = c.miss + 1
+    else:
+        c.hit = c.hit + 1
+
+    return rval
+
+MCG_dict = {
+    'MCG'  : Memoizer_cache_get,
+    'MCGS' : Memoizer_cache_get_self,
+    'MCGO' : Memoizer_cache_get_one,
+}
+
+MCG_lambda = "lambda *args, **kw: MCG(methcode, methcached, args, kw)"
+MCGS_lambda = "lambda self: MCGS(methcode, methcached, self)"
+MCGO_lambda = "lambda self, arg: MCGO(methcode, methcached, self, arg)"
+
+def EnableCounting():
+    """Enable counting of Memoizer hits and misses by overriding the
+    globals that hold the non-counting versions of the functions and
+    lambdas we call with the counting versions.
+    """
+    global MCG_dict
+    global MCG_lambda
+    global MCGS_lambda
+    global MCGO_lambda
+
+    MCG_dict = {
+        'MCG'  : Count_cache_get,
+        'MCGS' : Count_cache_get_self,
+        'MCGO' : Count_cache_get_one,
+    }
+
+    MCG_lambda = "lambda *args, **kw: MCG(methname, methcode, methcached, args, kw)"
+    MCGS_lambda = "lambda self: MCGS(methname, methcode, methcached, self)"
+    MCGO_lambda = "lambda self, arg: MCGO(methname, methcode, methcached, self, arg)"
+
+
+
+class _Memoizer_Simple:
+
+    def __setstate__(self, state):
+        self.__dict__.update(state)
+        self.__dict__['_MeMoIZeR_Key'] = Next_Memoize_Key()
+        #kwq: need to call original's setstate if it had one...
+
+    def _MeMoIZeR_reset(self):
+        self.__dict__['_MeMoIZeR_Key'] = Next_Memoize_Key()
+        return 1
+
+
+class _Memoizer_Comparable:
+
+    def __setstate__(self, state):
+        self.__dict__.update(state)
+        self.__dict__['_MeMoIZeR_Key'] = Next_Memoize_Key()
+        #kwq: need to call original's setstate if it had one...
+
+    def _MeMoIZeR_reset(self):
+        self.__dict__['_MeMoIZeR_Key'] = Next_Memoize_Key()
+        return 1
+
+    def __cmp__(self, other):
+        """A comparison might use the object dictionaries to
+        compare, so the dictionaries should contain caching
+        entries.  Make new dictionaries without those entries
+        to use with the underlying comparison."""
+
+        if self is other:
+            return 0
+
+        # We are here as a cached object, but cmp will flip its
+        # arguments back and forth and recurse attempting to get base
+        # arguments for the comparison, so we might have already been
+        # stripped.
+
+        try:
+            saved_d1 = self.__dict__
+            d1 = copy.copy(saved_d1)
+            del d1['_MeMoIZeR_Key']
+        except KeyError:
+            return self._MeMoIZeR_cmp(other)
+        self.__dict__ = d1
+
+        # Same thing for the other, but we should try to convert it
+        # here in case the _MeMoIZeR_cmp compares __dict__ objects
+        # directly.
+
+        saved_other = None
+        try:
+            if other.__dict__.has_key('_MeMoIZeR_Key'):
+                saved_other = other.__dict__
+                d2 = copy.copy(saved_other)
+                del d2['_MeMoIZeR_Key']
+                other.__dict__ = d2
+        except (AttributeError, KeyError):
+            pass
+
+        # Both self and other have been prepared: perform the test,
+        # then restore the original dictionaries and exit
+
+        rval = self._MeMoIZeR_cmp(other)
+
+        self.__dict__ = saved_d1
+        if saved_other:
+            other.__dict__ = saved_other
+
+        return rval
+
+
+def Analyze_Class(klass):
+    if klass.__dict__.has_key('_MeMoIZeR_converted'): return klass
+
+    original_name = str(klass)
+
+    D,R,C = _analyze_classmethods(klass.__dict__, klass.__bases__)
+
+    if C:
+        modelklass = _Memoizer_Comparable
+        lcldict = {'_MeMoIZeR_cmp':C}
+    else:
+        modelklass = _Memoizer_Simple
+        lcldict = {}
+
+    klass.__dict__.update(memoize_classdict(klass, modelklass, lcldict, D, R))
+
+    return klass
+
+
+# Note that each eval("lambda...") has a few \n's prepended to the
+# lambda, and furthermore that each of these evals has a different
+# number of \n's prepended.  This is to provide a little bit of info
+# for traceback or profile output, which generate things like 'File
+# "<string>", line X'.  X will be the number of \n's plus 1.
+
+# Also use the following routine to specify the "filename" portion so
+# that it provides useful information.  In addition, make sure it
+# contains 'os.sep + "SCons" + os.sep' for the
+# SCons.Script.find_deepest_user_frame operation.
+
+def whoami(memoizer_funcname, real_funcname):
+    return '...'+os.sep+'SCons'+os.sep+'Memoizer-'+ \
+           memoizer_funcname+'-lambda<'+real_funcname+'>'
+
+def memoize_classdict(klass, modelklass, new_klassdict, cacheable, resetting):
+    new_klassdict.update(modelklass.__dict__)
+    new_klassdict['_MeMoIZeR_converted'] = 1
+
+    for name,code in cacheable.items():
+        eval_dict = {
+            'methname' : name,
+            'methcode' : code,
+            'methcached' : {},
+        }
+        eval_dict.update(MCG_dict)
+        fc = code.func_code
+        if fc.co_argcount == 1 and not fc.co_flags & 0xC:
+            compiled = compile("\n"*1 + MCGS_lambda,
+                               whoami('cache_get_self', name),
+                               "eval")
+        elif fc.co_argcount == 2 and not fc.co_flags & 0xC:
+            compiled = compile("\n"*2 + MCGO_lambda,
+                               whoami('cache_get_one', name),
+                               "eval")
+        else:
+            compiled = compile("\n"*3 + MCG_lambda,
+                               whoami('cache_get', name),
+                               "eval")
+        newmethod = eval(compiled, eval_dict, {})
+        new_klassdict[name] = newmethod
+
+    for name,code in resetting.items():
+        newmethod = eval(
+            compile(
+            "lambda obj_self, *args, **kw: (obj_self._MeMoIZeR_reset(), apply(rmethcode, (obj_self,)+args, kw))[1]",
+            whoami('cache_reset', name),
+            'eval'),
+            {'rmethcode':code}, {})
+        new_klassdict[name] = newmethod
+
+    return new_klassdict
+
+def _analyze_classmethods(klassdict, klassbases):
+    """Given a class, performs a scan of methods for that class and
+    all its base classes (recursively). Returns aggregated results of
+    _scan_classdict calls where subclass methods are superimposed over
+    base class methods of the same name (emulating instance->class
+    method lookup)."""
+
+    D = {}
+    R = {}
+    C = None
+
+    # Get cache/reset/cmp methods from subclasses
+
+    for K in klassbases:
+        if K.__dict__.has_key('_MeMoIZeR_converted'): continue
+        d,r,c = _analyze_classmethods(K.__dict__, K.__bases__)
+        D.update(d)
+        R.update(r)
+        C = c or C
+
+    # Delete base method info if current class has an override
+
+    for M in D.keys():
+        if M == '__cmp__': continue
+        if klassdict.has_key(M):
+            del D[M]
+    for M in R.keys():
+        if M == '__cmp__': continue
+        if klassdict.has_key(M):
+            del R[M]
+
+    # Get cache/reset/cmp from current class
+
+    d,r,c = _scan_classdict(klassdict)
+
+    # Update accumulated cache/reset/cmp methods
+
+    D.update(d)
+    R.update(r)
+    C = c or C
+
+    return D,R,C
+
+
+def _scan_classdict(klassdict):
+    """Scans the method dictionary of a class to find all methods
+    interesting to caching operations.  Returns a tuple of these
+    interesting methods:
+
+      ( dict-of-cachable-methods,
+        dict-of-cache-resetting-methods,
+        cmp_method_val or None)
+
+    Each dict has the name of the method as a key and the corresponding
+    value is the method body."""
+
+    cache_setters = {}
+    cache_resetters = {}
+    cmp_if_exists = None
+    already_cache_modified = 0
+
+    for attr,val in klassdict.items():
+        if not callable(val): continue
+        if attr == '__cmp__':
+            cmp_if_exists = val
+            continue  # cmp can't be cached and can't reset cache
+        if attr == '_MeMoIZeR_cmp':
+            already_cache_modified = 1
+            continue
+        if not val.__doc__: continue
+        if string.find(val.__doc__, '__cache_reset__') > -1:
+            cache_resetters[attr] = val
+            continue
+        if string.find(val.__doc__, '__reset_cache__') > -1:
+            cache_resetters[attr] = val
+            continue
+        if string.find(val.__doc__, '__cacheable__') > -1:
+            cache_setters[attr] = val
+            continue
+    if already_cache_modified: cmp_if_exists = 'already_cache_modified'
+    return cache_setters, cache_resetters, cmp_if_exists
+
+#
+# Primary Memoizer class.  This should be a base-class for any class
+# that wants method call results to be cached.  The sub-class should
+# call this parent class's __init__ method, but no other requirements
+# are made on the subclass (other than appropriate decoration).
+
+class Memoizer:
+    """Object which performs caching of method calls for its 'primary'
+    instance."""
+
+    def __init__(self):
+        self.__class__ = Analyze_Class(self.__class__)
+        self._MeMoIZeR_Key =  Next_Memoize_Key()
+
+# Find out if we are pre-2.2
+
+try:
+    vinfo = sys.version_info
+except AttributeError:
+    """Split an old-style version string into major and minor parts.  This
+    is complicated by the fact that a version string can be something
+    like 3.2b1."""
+    import re
+    version = string.split(string.split(sys.version, ' ')[0], '.')
+    vinfo = (int(version[0]), int(re.match('\d+', version[1]).group()))
+    del re
+
+need_version = (2, 2) # actual
+#need_version = (33, 0)  # always
+#need_version = (0, 0)  # never
+
+has_metaclass =  (vinfo[0] > need_version[0] or \
+                  (vinfo[0] == need_version[0] and
+                   vinfo[1] >= need_version[1]))
+
+if not has_metaclass:
+
+    class Memoized_Metaclass:
+        # Just a place-holder so pre-metaclass Python versions don't
+        # have to have special code for the Memoized classes.
+        pass
+
+else:
+
+    # Initialization is a wee bit of a hassle.  We want to do some of
+    # our own work for initialization, then pass on to the actual
+    # initialization function.  However, we have to be careful we
+    # don't interfere with (a) the super()'s initialization call of
+    # it's superclass's __init__, and (b) classes we are Memoizing
+    # that don't have their own __init__ but which have a super that
+    # has an __init__.  To do (a), we eval a lambda below where the
+    # actual init code is locally bound and the __init__ entry in the
+    # class's dictionary is replaced with the _MeMoIZeR_init call.  To
+    # do (b), we use _MeMoIZeR_superinit as a fallback if the class
+    # doesn't have it's own __init__.  Note that we don't use getattr
+    # to obtain the __init__ because we don't want to re-instrument
+    # parent-class __init__ operations (and we want to avoid the
+    # Object object's slot init if the class has no __init__).
+
+    def _MeMoIZeR_init(actual_init, self, args, kw):
+        self.__dict__['_MeMoIZeR_Key'] =  Next_Memoize_Key()
+        apply(actual_init, (self,)+args, kw)
+
+    def _MeMoIZeR_superinit(self, cls, args, kw):
+        apply(super(cls, self).__init__, args, kw)
+
+    class Memoized_Metaclass(type):
+        def __init__(cls, name, bases, cls_dict):
+            # Note that cls_dict apparently contains a *copy* of the
+            # attribute dictionary of the class; modifying cls_dict
+            # has no effect on the actual class itself.
+            D,R,C = _analyze_classmethods(cls_dict, bases)
+            if C:
+                modelklass = _Memoizer_Comparable
+                cls_dict['_MeMoIZeR_cmp'] = C
+            else:
+                modelklass = _Memoizer_Simple
+            klassdict = memoize_classdict(cls, modelklass, cls_dict, D, R)
+
+            init = klassdict.get('__init__', None)
+            if not init:
+                # Make sure filename has os.sep+'SCons'+os.sep so that
+                # SCons.Script.find_deepest_user_frame doesn't stop here
+                import inspect # It's OK, can't get here for Python < 2.1
+                superinitcode = compile(
+                    "lambda self, *args, **kw: MPI(self, cls, args, kw)",
+                    inspect.getsourcefile(_MeMoIZeR_superinit) or '<unknown>',
+                    "eval")
+                superinit = eval(superinitcode,
+                                 {'cls':cls,
+                                  'MPI':_MeMoIZeR_superinit})
+                init = superinit
+
+            newinitcode = compile(
+                "\n"*(init.func_code.co_firstlineno-1) +
+                "lambda self, args, kw: _MeMoIZeR_init(real_init, self, args, kw)",
+                whoami('init', init.func_code.co_filename),
+                'eval')
+            newinit = eval(newinitcode,
+                           {'real_init':init,
+                            '_MeMoIZeR_init':_MeMoIZeR_init},
+                           {})
+            klassdict['__init__'] = lambda self, *args, **kw: newinit(self, args, kw)
+
+            super(Memoized_Metaclass, cls).__init__(name, bases, klassdict)
+            # Now, since klassdict doesn't seem to have affected the class
+            # definition itself, apply klassdict.
+            for attr in klassdict.keys():
+                setattr(cls, attr, klassdict[attr])
+
+def DisableMemoization():
+    global use_memoizer
+    use_memoizer = None
+
+def use_old_memoization():
+    return use_memoizer and not has_metaclass

Added: cs/scons/scons-local-0.96.92/SCons/Node/Alias.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Node/Alias.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Node/Alias.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,112 @@
+
+"""scons.Node.Alias
+
+Alias nodes.
+
+This creates a hash of global Aliases (dummy targets).
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Node/Alias.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+import UserDict
+
+import SCons.Errors
+import SCons.Node
+import SCons.Util
+
+class AliasNameSpace(UserDict.UserDict):
+    def Alias(self, name, **kw):
+        if isinstance(name, SCons.Node.Alias.Alias):
+            return name
+        try:
+            a = self[name]
+        except KeyError:
+            a = apply(SCons.Node.Alias.Alias, (name,), kw)
+            self[name] = a
+        return a
+
+    def lookup(self, name, **kw):
+        try:
+            return self[name]
+        except KeyError:
+            return None
+
+class AliasNodeInfo(SCons.Node.NodeInfoBase):
+    pass
+
+class AliasBuildInfo(SCons.Node.BuildInfoBase):
+    pass
+
+class Alias(SCons.Node.Node):
+
+    NodeInfo = AliasNodeInfo
+    BuildInfo = AliasBuildInfo
+
+    def __init__(self, name):
+        SCons.Node.Node.__init__(self)
+        self.name = name
+
+    def __str__(self):
+        return self.name
+
+    really_build = SCons.Node.Node.build
+    current = SCons.Node.Node.children_are_up_to_date
+
+    def is_under(self, dir):
+        # Make Alias nodes get built regardless of
+        # what directory scons was run from. Alias nodes
+        # are outside the filesystem:
+        return 1
+
+    def get_contents(self):
+        """The contents of an alias is the concatenation
+        of all the contents of its sources"""
+        contents = map(lambda n: n.get_contents(), self.children())
+        return string.join(contents, '')
+
+    def sconsign(self):
+        """An Alias is not recorded in .sconsign files"""
+        pass
+
+    #
+    #
+    #
+
+    def build(self):
+        """A "builder" for aliases."""
+        pass
+
+    def convert(self):
+        try: del self.builder
+        except AttributeError: pass
+        self.reset_executor()
+        self.build = self.really_build
+
+default_ans = AliasNameSpace()
+
+SCons.Node.arg2nodes_lookups.append(default_ans.lookup)

Added: cs/scons/scons-local-0.96.92/SCons/Node/FS.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Node/FS.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Node/FS.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,2144 @@
+"""scons.Node.FS
+
+File system nodes.
+
+These Nodes represent the canonical external objects that people think
+of when they think of building software: files and directories.
+
+This holds a "default_fs" variable that should be initialized with an FS
+that can be used by scripts or modules looking for the canonical default.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Node/FS.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import shutil
+import stat
+import string
+import sys
+import time
+import cStringIO
+
+import SCons.Action
+from SCons.Debug import logInstanceCreation
+import SCons.Errors
+import SCons.Node
+import SCons.Sig.MD5
+import SCons.Subst
+import SCons.Util
+import SCons.Warnings
+
+from SCons.Debug import Trace
+
+# The max_drift value:  by default, use a cached signature value for
+# any file that's been untouched for more than two days.
+default_max_drift = 2*24*60*60
+
+#
+# We stringify these file system Nodes a lot.  Turning a file system Node
+# into a string is non-trivial, because the final string representation
+# can depend on a lot of factors:  whether it's a derived target or not,
+# whether it's linked to a repository or source directory, and whether
+# there's duplication going on.  The normal technique for optimizing
+# calculations like this is to memoize (cache) the string value, so you
+# only have to do the calculation once.
+#
+# A number of the above factors, however, can be set after we've already
+# been asked to return a string for a Node, because a Repository() or
+# BuildDir() call or the like may not occur until later in SConscript
+# files.  So this variable controls whether we bother trying to save
+# string values for Nodes.  The wrapper interface can set this whenever
+# they're done mucking with Repository and BuildDir and the other stuff,
+# to let this module know it can start returning saved string values
+# for Nodes.
+#
+Save_Strings = None
+
+def save_strings(val):
+    global Save_Strings
+    Save_Strings = val
+
+#
+# SCons.Action objects for interacting with the outside world.
+#
+# The Node.FS methods in this module should use these actions to
+# create and/or remove files and directories; they should *not* use
+# os.{link,symlink,unlink,mkdir}(), etc., directly.
+#
+# Using these SCons.Action objects ensures that descriptions of these
+# external activities are properly displayed, that the displays are
+# suppressed when the -s (silent) option is used, and (most importantly)
+# the actions are disabled when the the -n option is used, in which case
+# there should be *no* changes to the external file system(s)...
+#
+
+def _copy_func(src, dest):
+    shutil.copy2(src, dest)
+    st=os.stat(src)
+    os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+
+Valid_Duplicates = ['hard-soft-copy', 'soft-hard-copy',
+                    'hard-copy', 'soft-copy', 'copy']
+
+Link_Funcs = [] # contains the callables of the specified duplication style
+
+def set_duplicate(duplicate):
+    # Fill in the Link_Funcs list according to the argument
+    # (discarding those not available on the platform).
+
+    # Set up the dictionary that maps the argument names to the
+    # underlying implementations.  We do this inside this function,
+    # not in the top-level module code, so that we can remap os.link
+    # and os.symlink for testing purposes.
+    try:
+        _hardlink_func = os.link
+    except AttributeError:
+        _hardlink_func = None
+
+    try:
+        _softlink_func = os.symlink
+    except AttributeError:
+        _softlink_func = None
+
+    link_dict = {
+        'hard' : _hardlink_func,
+        'soft' : _softlink_func,
+        'copy' : _copy_func
+    }
+
+    if not duplicate in Valid_Duplicates:
+        raise SCons.Errors.InternalError, ("The argument of set_duplicate "
+                                           "should be in Valid_Duplicates")
+    global Link_Funcs
+    Link_Funcs = []
+    for func in string.split(duplicate,'-'):
+        if link_dict[func]:
+            Link_Funcs.append(link_dict[func])
+
+def LinkFunc(target, source, env):
+    # Relative paths cause problems with symbolic links, so
+    # we use absolute paths, which may be a problem for people
+    # who want to move their soft-linked src-trees around. Those
+    # people should use the 'hard-copy' mode, softlinks cannot be
+    # used for that; at least I have no idea how ...
+    src = source[0].abspath
+    dest = target[0].abspath
+    dir, file = os.path.split(dest)
+    if dir and not target[0].fs.isdir(dir):
+        os.makedirs(dir)
+    if not Link_Funcs:
+        # Set a default order of link functions.
+        set_duplicate('hard-soft-copy')
+    # Now link the files with the previously specified order.
+    for func in Link_Funcs:
+        try:
+            func(src,dest)
+            break
+        except (IOError, OSError):
+            # An OSError indicates something happened like a permissions
+            # problem or an attempt to symlink across file-system
+            # boundaries.  An IOError indicates something like the file
+            # not existing.  In either case, keeping trying additional
+            # functions in the list and only raise an error if the last
+            # one failed.
+            if func == Link_Funcs[-1]:
+                # exception of the last link method (copy) are fatal
+                raise
+            else:
+                pass
+    return 0
+
+Link = SCons.Action.Action(LinkFunc, None)
+def LocalString(target, source, env):
+    return 'Local copy of %s from %s' % (target[0], source[0])
+
+LocalCopy = SCons.Action.Action(LinkFunc, LocalString)
+
+def UnlinkFunc(target, source, env):
+    t = target[0]
+    t.fs.unlink(t.abspath)
+    return 0
+
+Unlink = SCons.Action.Action(UnlinkFunc, None)
+
+def MkdirFunc(target, source, env):
+    t = target[0]
+    if not t.exists():
+        t.fs.mkdir(t.abspath)
+    return 0
+
+Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None)
+
+MkdirBuilder = None
+
+def get_MkdirBuilder():
+    global MkdirBuilder
+    if MkdirBuilder is None:
+        import SCons.Builder
+        import SCons.Defaults
+        # "env" will get filled in by Executor.get_build_env()
+        # calling SCons.Defaults.DefaultEnvironment() when necessary.
+        MkdirBuilder = SCons.Builder.Builder(action = Mkdir,
+                                             env = None,
+                                             explain = None,
+                                             is_explicit = None,
+                                             target_scanner = SCons.Defaults.DirEntryScanner,
+                                             name = "MkdirBuilder")
+    return MkdirBuilder
+
+def CacheRetrieveFunc(target, source, env):
+    t = target[0]
+    fs = t.fs
+    cachedir, cachefile = t.cachepath()
+    if fs.exists(cachefile):
+        if SCons.Action.execute_actions:
+            fs.copy2(cachefile, t.path)
+            st = fs.stat(cachefile)
+            fs.chmod(t.path, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+        return 0
+    return 1
+
+def CacheRetrieveString(target, source, env):
+    t = target[0]
+    cachedir, cachefile = t.cachepath()
+    if t.fs.exists(cachefile):
+        return "Retrieved `%s' from cache" % t.path
+    return None
+
+CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)
+
+CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None)
+
+def CachePushFunc(target, source, env):
+    t = target[0]
+    fs = t.fs
+    cachedir, cachefile = t.cachepath()
+    if fs.exists(cachefile):
+        # Don't bother copying it if it's already there.
+        return
+
+    if not fs.isdir(cachedir):
+        fs.makedirs(cachedir)
+
+    tempfile = cachefile+'.tmp'
+    try:
+        fs.copy2(t.path, tempfile)
+        fs.rename(tempfile, cachefile)
+        st = fs.stat(t.path)
+        fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+    except (IOError, OSError):
+        # It's possible someone else tried writing the file at the
+        # same time we did, or else that there was some problem like
+        # the CacheDir being on a separate file system that's full.
+        # In any case, inability to push a file to cache doesn't affect
+        # the correctness of the build, so just print a warning.
+        SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning,
+                            "Unable to copy %s to cache. Cache file is %s"
+                                % (str(target), cachefile))
+        return
+
+CachePush = SCons.Action.Action(CachePushFunc, None)
+
+class _Null:
+    pass
+
+_null = _Null()
+
+DefaultSCCSBuilder = None
+DefaultRCSBuilder = None
+
+def get_DefaultSCCSBuilder():
+    global DefaultSCCSBuilder
+    if DefaultSCCSBuilder is None:
+        import SCons.Builder
+        # "env" will get filled in by Executor.get_build_env()
+        # calling SCons.Defaults.DefaultEnvironment() when necessary.
+        act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR')
+        DefaultSCCSBuilder = SCons.Builder.Builder(action = act,
+                                                   env = None,
+                                                   name = "DefaultSCCSBuilder")
+    return DefaultSCCSBuilder
+
+def get_DefaultRCSBuilder():
+    global DefaultRCSBuilder
+    if DefaultRCSBuilder is None:
+        import SCons.Builder
+        # "env" will get filled in by Executor.get_build_env()
+        # calling SCons.Defaults.DefaultEnvironment() when necessary.
+        act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR')
+        DefaultRCSBuilder = SCons.Builder.Builder(action = act,
+                                                  env = None,
+                                                  name = "DefaultRCSBuilder")
+    return DefaultRCSBuilder
+
+# Cygwin's os.path.normcase pretends it's on a case-sensitive filesystem.
+_is_cygwin = sys.platform == "cygwin"
+if os.path.normcase("TeSt") == os.path.normpath("TeSt") and not _is_cygwin:
+    def _my_normcase(x):
+        return x
+else:
+    def _my_normcase(x):
+        return string.upper(x)
+
+
+
+class DiskChecker:
+    def __init__(self, type, do, ignore):
+        self.type = type
+        self.do = do
+        self.ignore = ignore
+        self.set_do()
+    def set_do(self):
+        self.__call__ = self.do
+    def set_ignore(self):
+        self.__call__ = self.ignore
+    def set(self, list):
+        if self.type in list:
+            self.set_do()
+        else:
+            self.set_ignore()
+
+def do_diskcheck_match(node, predicate, errorfmt):
+    path = node.abspath
+    if predicate(path):
+        raise TypeError, errorfmt % path
+
+def ignore_diskcheck_match(node, predicate, errorfmt):
+    pass
+
+def do_diskcheck_rcs(node, name):
+    try:
+        rcs_dir = node.rcs_dir
+    except AttributeError:
+        if node.entry_exists_on_disk('RCS'):
+            rcs_dir = node.Dir('RCS')
+        else:
+            rcs_dir = None
+        node.rcs_dir = rcs_dir
+    if rcs_dir:
+        return rcs_dir.entry_exists_on_disk(name+',v')
+    return None
+
+def ignore_diskcheck_rcs(node, name):
+    return None
+
+def do_diskcheck_sccs(node, name):
+    try:
+        sccs_dir = node.sccs_dir
+    except AttributeError:
+        if node.entry_exists_on_disk('SCCS'):
+            sccs_dir = node.Dir('SCCS')
+        else:
+            sccs_dir = None
+        node.sccs_dir = sccs_dir
+    if sccs_dir:
+        return sccs_dir.entry_exists_on_disk('s.'+name)
+    return None
+
+def ignore_diskcheck_sccs(node, name):
+    return None
+
+diskcheck_match = DiskChecker('match', do_diskcheck_match, ignore_diskcheck_match)
+diskcheck_rcs = DiskChecker('rcs', do_diskcheck_rcs, ignore_diskcheck_rcs)
+diskcheck_sccs = DiskChecker('sccs', do_diskcheck_sccs, ignore_diskcheck_sccs)
+
+diskcheckers = [
+    diskcheck_match,
+    diskcheck_rcs,
+    diskcheck_sccs,
+]
+
+def set_diskcheck(list):
+    for dc in diskcheckers:
+        dc.set(list)
+
+def diskcheck_types():
+    return map(lambda dc: dc.type, diskcheckers)
+
+
+
+class EntryProxy(SCons.Util.Proxy):
+    def __get_abspath(self):
+        entry = self.get()
+        return SCons.Subst.SpecialAttrWrapper(entry.get_abspath(),
+                                             entry.name + "_abspath")
+
+    def __get_filebase(self):
+        name = self.get().name
+        return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[0],
+                                             name + "_filebase")
+
+    def __get_suffix(self):
+        name = self.get().name
+        return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[1],
+                                             name + "_suffix")
+
+    def __get_file(self):
+        name = self.get().name
+        return SCons.Subst.SpecialAttrWrapper(name, name + "_file")
+
+    def __get_base_path(self):
+        """Return the file's directory and file name, with the
+        suffix stripped."""
+        entry = self.get()
+        return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(entry.get_path())[0],
+                                             entry.name + "_base")
+
+    def __get_posix_path(self):
+        """Return the path with / as the path separator,
+        regardless of platform."""
+        if os.sep == '/':
+            return self
+        else:
+            entry = self.get()
+            r = string.replace(entry.get_path(), os.sep, '/')
+            return SCons.Subst.SpecialAttrWrapper(r, entry.name + "_posix")
+
+    def __get_windows_path(self):
+        """Return the path with \ as the path separator,
+        regardless of platform."""
+        if os.sep == '\\':
+            return self
+        else:
+            entry = self.get()
+            r = string.replace(entry.get_path(), os.sep, '\\')
+            return SCons.Subst.SpecialAttrWrapper(r, entry.name + "_windows")
+
+    def __get_srcnode(self):
+        return EntryProxy(self.get().srcnode())
+
+    def __get_srcdir(self):
+        """Returns the directory containing the source node linked to this
+        node via BuildDir(), or the directory of this node if not linked."""
+        return EntryProxy(self.get().srcnode().dir)
+
+    def __get_rsrcnode(self):
+        return EntryProxy(self.get().srcnode().rfile())
+
+    def __get_rsrcdir(self):
+        """Returns the directory containing the source node linked to this
+        node via BuildDir(), or the directory of this node if not linked."""
+        return EntryProxy(self.get().srcnode().rfile().dir)
+
+    def __get_dir(self):
+        return EntryProxy(self.get().dir)
+    
+    dictSpecialAttrs = { "base"     : __get_base_path,
+                         "posix"    : __get_posix_path,
+                         "windows"  : __get_windows_path,
+                         "win32"    : __get_windows_path,
+                         "srcpath"  : __get_srcnode,
+                         "srcdir"   : __get_srcdir,
+                         "dir"      : __get_dir,
+                         "abspath"  : __get_abspath,
+                         "filebase" : __get_filebase,
+                         "suffix"   : __get_suffix,
+                         "file"     : __get_file,
+                         "rsrcpath" : __get_rsrcnode,
+                         "rsrcdir"  : __get_rsrcdir,
+                       }
+
+    def __getattr__(self, name):
+        # This is how we implement the "special" attributes
+        # such as base, posix, srcdir, etc.
+        try:
+            attr_function = self.dictSpecialAttrs[name]
+        except KeyError:
+            try:
+                attr = SCons.Util.Proxy.__getattr__(self, name)
+            except AttributeError:
+                entry = self.get()
+                classname = string.split(str(entry.__class__), '.')[-1]
+                if classname[-2:] == "'>":
+                    # new-style classes report their name as:
+                    #   "<class 'something'>"
+                    # instead of the classic classes:
+                    #   "something"
+                    classname = classname[:-2]
+                raise AttributeError, "%s instance '%s' has no attribute '%s'" % (classname, entry.name, name)
+            return attr
+        else:
+            return attr_function(self)
+
+class Base(SCons.Node.Node):
+    """A generic class for file system entries.  This class is for
+    when we don't know yet whether the entry being looked up is a file
+    or a directory.  Instances of this class can morph into either
+    Dir or File objects by a later, more precise lookup.
+
+    Note: this class does not define __cmp__ and __hash__ for
+    efficiency reasons.  SCons does a lot of comparing of
+    Node.FS.{Base,Entry,File,Dir} objects, so those operations must be
+    as fast as possible, which means we want to use Python's built-in
+    object identity comparisons.
+    """
+
+    def __init__(self, name, directory, fs):
+        """Initialize a generic Node.FS.Base object.
+        
+        Call the superclass initialization, take care of setting up
+        our relative and absolute paths, identify our parent
+        directory, and indicate that this node should use
+        signatures."""
+        if __debug__: logInstanceCreation(self, 'Node.FS.Base')
+        SCons.Node.Node.__init__(self)
+
+        self.name = name
+        self.fs = fs
+
+        assert directory, "A directory must be provided"
+
+        self.abspath = directory.entry_abspath(name)
+        if directory.path == '.':
+            self.path = name
+        else:
+            self.path = directory.entry_path(name)
+        if directory.tpath == '.':
+            self.tpath = name
+        else:
+            self.tpath = directory.entry_tpath(name)
+        self.path_elements = directory.path_elements + [self]
+
+        self.dir = directory
+        self.cwd = None # will hold the SConscript directory for target nodes
+        self.duplicate = directory.duplicate
+
+    def clear(self):
+        """Completely clear a Node.FS.Base object of all its cached
+        state (so that it can be re-evaluated by interfaces that do
+        continuous integration builds).
+        __cache_reset__
+        """
+        SCons.Node.Node.clear(self)
+
+    def get_dir(self):
+        return self.dir
+
+    def get_suffix(self):
+        "__cacheable__"
+        return SCons.Util.splitext(self.name)[1]
+
+    def rfile(self):
+        return self
+
+    def __str__(self):
+        """A Node.FS.Base object's string representation is its path
+        name."""
+        global Save_Strings
+        if Save_Strings:
+            return self._save_str()
+        return self._get_str()
+
+    def _save_str(self):
+        "__cacheable__"
+        return self._get_str()
+
+    def _get_str(self):
+        if self.duplicate or self.is_derived():
+            return self.get_path()
+        return self.srcnode().get_path()
+
+    rstr = __str__
+
+    def stat(self):
+        "__cacheable__"
+        try: return self.fs.stat(self.abspath)
+        except os.error: return None
+
+    def exists(self):
+        "__cacheable__"
+        return not self.stat() is None
+
+    def rexists(self):
+        "__cacheable__"
+        return self.rfile().exists()
+
+    def getmtime(self):
+        st = self.stat()
+        if st: return st[stat.ST_MTIME]
+        else: return None
+
+    def getsize(self):
+        st = self.stat()
+        if st: return st[stat.ST_SIZE]
+        else: return None
+
+    def isdir(self):
+        st = self.stat()
+        return not st is None and stat.S_ISDIR(st[stat.ST_MODE])
+
+    def isfile(self):
+        st = self.stat()
+        return not st is None and stat.S_ISREG(st[stat.ST_MODE])
+
+    if hasattr(os, 'symlink'):
+        def islink(self):
+            try: st = self.fs.lstat(self.abspath)
+            except os.error: return 0
+            return stat.S_ISLNK(st[stat.ST_MODE])
+    else:
+        def islink(self):
+            return 0                    # no symlinks
+
+    def is_under(self, dir):
+        if self is dir:
+            return 1
+        else:
+            return self.dir.is_under(dir)
+
+    def set_local(self):
+        self._local = 1
+
+    def srcnode(self):
+        """If this node is in a build path, return the node
+        corresponding to its source file.  Otherwise, return
+        ourself.
+        __cacheable__"""
+        dir=self.dir
+        name=self.name
+        while dir:
+            if dir.srcdir:
+                srcnode = self.fs.Entry(name, dir.srcdir,
+                                        klass=self.__class__)
+                return srcnode
+            name = dir.name + os.sep + name
+            dir = dir.up()
+        return self
+
+    def get_path(self, dir=None):
+        """Return path relative to the current working directory of the
+        Node.FS.Base object that owns us."""
+        if not dir:
+            dir = self.fs.getcwd()
+        if self == dir:
+            return '.'
+        path_elems = self.path_elements
+        try: i = path_elems.index(dir)
+        except ValueError: pass
+        else: path_elems = path_elems[i+1:]
+        path_elems = map(lambda n: n.name, path_elems)
+        return string.join(path_elems, os.sep)
+
+    def set_src_builder(self, builder):
+        """Set the source code builder for this node."""
+        self.sbuilder = builder
+        if not self.has_builder():
+            self.builder_set(builder)
+
+    def src_builder(self):
+        """Fetch the source code builder for this node.
+
+        If there isn't one, we cache the source code builder specified
+        for the directory (which in turn will cache the value from its
+        parent directory, and so on up to the file system root).
+        """
+        try:
+            scb = self.sbuilder
+        except AttributeError:
+            scb = self.dir.src_builder()
+            self.sbuilder = scb
+        return scb
+
+    def get_abspath(self):
+        """Get the absolute path of the file."""
+        return self.abspath
+
+    def for_signature(self):
+        # Return just our name.  Even an absolute path would not work,
+        # because that can change thanks to symlinks or remapped network
+        # paths.
+        return self.name
+
+    def get_subst_proxy(self):
+        try:
+            return self._proxy
+        except AttributeError:
+            ret = EntryProxy(self)
+            self._proxy = ret
+            return ret
+
+    def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext):
+        return self.dir.Entry(prefix + splitext(self.name)[0] + suffix)
+
+class Entry(Base):
+    """This is the class for generic Node.FS entries--that is, things
+    that could be a File or a Dir, but we're just not sure yet.
+    Consequently, the methods in this class really exist just to
+    transform their associated object into the right class when the
+    time comes, and then call the same-named method in the transformed
+    class."""
+
+    def diskcheck_match(self):
+        pass
+
+    def disambiguate(self):
+        if self.isdir():
+            self.__class__ = Dir
+            self._morph()
+        else:
+            self.__class__ = File
+            self._morph()
+            self.clear()
+        return self
+
+    def rfile(self):
+        """We're a generic Entry, but the caller is actually looking for
+        a File at this point, so morph into one."""
+        self.__class__ = File
+        self._morph()
+        self.clear()
+        return File.rfile(self)
+
+    def scanner_key(self):
+        return self.get_suffix()
+
+    def get_contents(self):
+        """Fetch the contents of the entry.
+        
+        Since this should return the real contents from the file
+        system, we check to see into what sort of subclass we should
+        morph this Entry."""
+        if self.isfile():
+            self.__class__ = File
+            self._morph()
+            return self.get_contents()
+        if self.isdir():
+            self.__class__ = Dir
+            self._morph()
+            return self.get_contents()
+        if self.islink():
+            return ''             # avoid errors for dangling symlinks
+        raise AttributeError
+
+    def must_be_a_Dir(self):
+        """Called to make sure a Node is a Dir.  Since we're an
+        Entry, we can morph into one."""
+        self.__class__ = Dir
+        self._morph()
+        return self
+
+    # The following methods can get called before the Taskmaster has
+    # had a chance to call disambiguate() directly to see if this Entry
+    # should really be a Dir or a File.  We therefore use these to call
+    # disambiguate() transparently (from our caller's point of view).
+    #
+    # Right now, this minimal set of methods has been derived by just
+    # looking at some of the methods that will obviously be called early
+    # in any of the various Taskmasters' calling sequences, and then
+    # empirically figuring out which additional methods are necessary
+    # to make various tests pass.
+
+    def exists(self):
+        """Return if the Entry exists.  Check the file system to see
+        what we should turn into first.  Assume a file if there's no
+        directory."""
+        return self.disambiguate().exists()
+
+    def rel_path(self, other):
+        d = self.disambiguate()
+        if d.__class__ == Entry:
+            raise "rel_path() could not disambiguate File/Dir"
+        return d.rel_path(other)
+
+# This is for later so we can differentiate between Entry the class and Entry
+# the method of the FS class.
+_classEntry = Entry
+
+
+class LocalFS:
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+    
+    # This class implements an abstraction layer for operations involving
+    # a local file system.  Essentially, this wraps any function in
+    # the os, os.path or shutil modules that we use to actually go do
+    # anything with or to the local file system.
+    #
+    # Note that there's a very good chance we'll refactor this part of
+    # the architecture in some way as we really implement the interface(s)
+    # for remote file system Nodes.  For example, the right architecture
+    # might be to have this be a subclass instead of a base class.
+    # Nevertheless, we're using this as a first step in that direction.
+    #
+    # We're not using chdir() yet because the calling subclass method
+    # needs to use os.chdir() directly to avoid recursion.  Will we
+    # really need this one?
+    #def chdir(self, path):
+    #    return os.chdir(path)
+    def chmod(self, path, mode):
+        return os.chmod(path, mode)
+    def copy2(self, src, dst):
+        return shutil.copy2(src, dst)
+    def exists(self, path):
+        return os.path.exists(path)
+    def getmtime(self, path):
+        return os.path.getmtime(path)
+    def getsize(self, path):
+        return os.path.getsize(path)
+    def isdir(self, path):
+        return os.path.isdir(path)
+    def isfile(self, path):
+        return os.path.isfile(path)
+    def link(self, src, dst):
+        return os.link(src, dst)
+    def lstat(self, path):
+        return os.lstat(path)
+    def listdir(self, path):
+        return os.listdir(path)
+    def makedirs(self, path):
+        return os.makedirs(path)
+    def mkdir(self, path):
+        return os.mkdir(path)
+    def rename(self, old, new):
+        return os.rename(old, new)
+    def stat(self, path):
+        return os.stat(path)
+    def symlink(self, src, dst):
+        return os.symlink(src, dst)
+    def open(self, path):
+        return open(path)
+    def unlink(self, path):
+        return os.unlink(path)
+
+    if hasattr(os, 'symlink'):
+        def islink(self, path):
+            return os.path.islink(path)
+    else:
+        def islink(self, path):
+            return 0                    # no symlinks
+
+if SCons.Memoize.use_old_memoization():
+    _FSBase = LocalFS
+    class LocalFS(SCons.Memoize.Memoizer, _FSBase):
+        def __init__(self, *args, **kw):
+            apply(_FSBase.__init__, (self,)+args, kw)
+            SCons.Memoize.Memoizer.__init__(self)
+
+
+#class RemoteFS:
+#    # Skeleton for the obvious methods we might need from the
+#    # abstraction layer for a remote filesystem.
+#    def upload(self, local_src, remote_dst):
+#        pass
+#    def download(self, remote_src, local_dst):
+#        pass
+
+
+class FS(LocalFS):
+
+    def __init__(self, path = None):
+        """Initialize the Node.FS subsystem.
+
+        The supplied path is the top of the source tree, where we
+        expect to find the top-level build file.  If no path is
+        supplied, the current directory is the default.
+
+        The path argument must be a valid absolute path.
+        """
+        if __debug__: logInstanceCreation(self, 'Node.FS')
+
+        self.Root = {}
+        self.SConstruct_dir = None
+        self.CachePath = None
+        self.cache_force = None
+        self.cache_show = None
+        self.max_drift = default_max_drift
+
+        self.Top = None
+        if path is None:
+            self.pathTop = os.getcwd()
+        else:
+            self.pathTop = path
+        self.defaultDrive = _my_normcase(os.path.splitdrive(self.pathTop)[0])
+
+        self.Top = self._doLookup(Dir, os.path.normpath(self.pathTop))
+        self.Top.path = '.'
+        self.Top.tpath = '.'
+        self._cwd = self.Top
+
+    def clear_cache(self):
+        "__cache_reset__"
+        pass
+    
+    def set_SConstruct_dir(self, dir):
+        self.SConstruct_dir = dir
+
+    def get_max_drift(self):
+        return self.max_drift
+
+    def set_max_drift(self, max_drift):
+        self.max_drift = max_drift
+
+    def getcwd(self):
+        return self._cwd
+
+    def __checkClass(self, node, klass):
+        if isinstance(node, klass) or klass == Entry:
+            return node
+        if node.__class__ == Entry:
+            node.__class__ = klass
+            node._morph()
+            return node
+        raise TypeError, "Tried to lookup %s '%s' as a %s." % \
+              (node.__class__.__name__, node.path, klass.__name__)
+        
+    def _doLookup(self, fsclass, name, directory = None, create = 1):
+        """This method differs from the File and Dir factory methods in
+        one important way: the meaning of the directory parameter.
+        In this method, if directory is None or not supplied, the supplied
+        name is expected to be an absolute path.  If you try to look up a
+        relative path with directory=None, then an AssertionError will be
+        raised.
+        __cacheable__"""
+
+        if not name:
+            # This is a stupid hack to compensate for the fact that the
+            # POSIX and Windows versions of os.path.normpath() behave
+            # differently in older versions of Python.  In particular,
+            # in POSIX:
+            #   os.path.normpath('./') == '.'
+            # in Windows:
+            #   os.path.normpath('./') == ''
+            #   os.path.normpath('.\\') == ''
+            #
+            # This is a definite bug in the Python library, but we have
+            # to live with it.
+            name = '.'
+        path_orig = string.split(name, os.sep)
+        path_norm = string.split(_my_normcase(name), os.sep)
+
+        first_orig = path_orig.pop(0)   # strip first element
+        first_norm = path_norm.pop(0)   # strip first element
+
+        drive, path_first = os.path.splitdrive(first_orig)
+        if path_first:
+            path_orig = [ path_first, ] + path_orig
+            path_norm = [ _my_normcase(path_first), ] + path_norm
+        else:
+            # Absolute path
+            drive = _my_normcase(drive)
+            try:
+                directory = self.Root[drive]
+            except KeyError:
+                if not create:
+                    raise SCons.Errors.UserError
+                directory = RootDir(drive, self)
+                self.Root[drive] = directory
+                if not drive:
+                    self.Root[self.defaultDrive] = directory
+                elif drive == self.defaultDrive:
+                    self.Root[''] = directory
+
+        if not path_orig:
+            return directory
+
+        last_orig = path_orig.pop()     # strip last element
+        last_norm = path_norm.pop()     # strip last element
+            
+        # Lookup the directory
+        for orig, norm in map(None, path_orig, path_norm):
+            try:
+                entries = directory.entries
+            except AttributeError:
+                # We tried to look up the entry in either an Entry or
+                # a File.  Give whatever it is a chance to do what's
+                # appropriate: morph into a Dir or raise an exception.
+                directory.must_be_a_Dir()
+                entries = directory.entries
+            try:
+                directory = entries[norm]
+            except KeyError:
+                if not create:
+                    raise SCons.Errors.UserError
+
+                d = Dir(orig, directory, self)
+
+                # Check the file system (or not, as configured) to make
+                # sure there isn't already a file there.
+                d.diskcheck_match()
+
+                directory.entries[norm] = d
+                directory.add_wkid(d)
+                directory = d
+
+        directory.must_be_a_Dir()
+
+        try:
+            e = directory.entries[last_norm]
+        except KeyError:
+            if not create:
+                raise SCons.Errors.UserError
+
+            result = fsclass(last_orig, directory, self)
+
+            # Check the file system (or not, as configured) to make
+            # sure there isn't already a directory at the path on
+            # disk where we just created a File node, and vice versa.
+            result.diskcheck_match()
+
+            directory.entries[last_norm] = result 
+            directory.add_wkid(result)
+        else:
+            result = self.__checkClass(e, fsclass)
+        return result 
+
+    def _transformPath(self, name, directory):
+        """Take care of setting up the correct top-level directory,
+        usually in preparation for a call to doLookup().
+
+        If the path name is prepended with a '#', then it is unconditionally
+        interpreted as relative to the top-level directory of this FS.
+
+        If directory is None, and name is a relative path,
+        then the same applies.
+        """
+        if not SCons.Util.is_String(name):
+            # This handles cases where the object is a Proxy wrapping
+            # a Node.FS.File object (e.g.).  It would be good to handle
+            # this more directly some day by having the callers of this
+            # function recognize that a Proxy can be treated like the
+            # underlying object (that is, get rid of the isinstance()
+            # calls that explicitly look for a Node.FS.Base object).
+            name = str(name)
+        if name and name[0] == '#':
+            directory = self.Top
+            name = name[1:]
+            if name and (name[0] == os.sep or name[0] == '/'):
+                # Correct such that '#/foo' is equivalent
+                # to '#foo'.
+                name = name[1:]
+            name = os.path.join('.', os.path.normpath(name))
+        elif not directory:
+            directory = self._cwd
+        return (os.path.normpath(name), directory)
+
+    def chdir(self, dir, change_os_dir=0):
+        """Change the current working directory for lookups.
+        If change_os_dir is true, we will also change the "real" cwd
+        to match.
+        """
+        curr=self._cwd
+        try:
+            if not dir is None:
+                self._cwd = dir
+                if change_os_dir:
+                    os.chdir(dir.abspath)
+        except OSError:
+            self._cwd = curr
+            raise
+
+    def Entry(self, name, directory = None, create = 1, klass=None):
+        """Lookup or create a generic Entry node with the specified name.
+        If the name is a relative path (begins with ./, ../, or a file
+        name), then it is looked up relative to the supplied directory
+        node, or to the top level directory of the FS (supplied at
+        construction time) if no directory is supplied.
+        """
+
+        if not klass:
+            klass = Entry
+
+        if isinstance(name, Base):
+            return self.__checkClass(name, klass)
+        else:
+            if directory and not isinstance(directory, Dir):
+                directory = self.Dir(directory)
+            name, directory = self._transformPath(name, directory)
+            return self._doLookup(klass, name, directory, create)
+    
+    def File(self, name, directory = None, create = 1):
+        """Lookup or create a File node with the specified name.  If
+        the name is a relative path (begins with ./, ../, or a file name),
+        then it is looked up relative to the supplied directory node,
+        or to the top level directory of the FS (supplied at construction
+        time) if no directory is supplied.
+
+        This method will raise TypeError if a directory is found at the
+        specified path.
+        """
+
+        return self.Entry(name, directory, create, File)
+    
+    def Dir(self, name, directory = None, create = 1):
+        """Lookup or create a Dir node with the specified name.  If
+        the name is a relative path (begins with ./, ../, or a file name),
+        then it is looked up relative to the supplied directory node,
+        or to the top level directory of the FS (supplied at construction
+        time) if no directory is supplied.
+
+        This method will raise TypeError if a normal file is found at the
+        specified path.
+        """
+
+        return self.Entry(name, directory, create, Dir)
+    
+    def BuildDir(self, build_dir, src_dir, duplicate=1):
+        """Link the supplied build directory to the source directory
+        for purposes of building files."""
+        
+        if not isinstance(src_dir, SCons.Node.Node):
+            src_dir = self.Dir(src_dir)
+        if not isinstance(build_dir, SCons.Node.Node):
+            build_dir = self.Dir(build_dir)
+        if src_dir.is_under(build_dir):
+            raise SCons.Errors.UserError, "Source directory cannot be under build directory."
+        if build_dir.srcdir:
+            if build_dir.srcdir == src_dir:
+                return # We already did this.
+            raise SCons.Errors.UserError, "'%s' already has a source directory: '%s'."%(build_dir, build_dir.srcdir)
+        build_dir.link(src_dir, duplicate)
+
+    def Repository(self, *dirs):
+        """Specify Repository directories to search."""
+        for d in dirs:
+            if not isinstance(d, SCons.Node.Node):
+                d = self.Dir(d)
+            self.Top.addRepository(d)
+
+    def Rfindalldirs(self, pathlist, cwd):
+        """__cacheable__"""
+        if SCons.Util.is_String(pathlist):
+            pathlist = string.split(pathlist, os.pathsep)
+        if not SCons.Util.is_List(pathlist):
+            pathlist = [pathlist]
+        result = []
+        for path in filter(None, pathlist):
+            if isinstance(path, SCons.Node.Node):
+                result.append(path)
+                continue
+            path, dir = self._transformPath(path, cwd)
+            dir = dir.Dir(path)
+            result.extend(dir.get_all_rdirs())
+        return result
+
+    def CacheDir(self, path):
+        self.CachePath = path
+
+    def build_dir_target_climb(self, orig, dir, tail):
+        """Create targets in corresponding build directories
+
+        Climb the directory tree, and look up path names
+        relative to any linked build directories we find.
+        __cacheable__
+        """
+        targets = []
+        message = None
+        fmt = "building associated BuildDir targets: %s"
+        start_dir = dir
+        while dir:
+            for bd in dir.build_dirs:
+                if start_dir.is_under(bd):
+                    # If already in the build-dir location, don't reflect
+                    return [orig], fmt % str(orig)
+                p = apply(os.path.join, [bd.path] + tail)
+                targets.append(self.Entry(p))
+            tail = [dir.name] + tail
+            dir = dir.up()
+        if targets:
+            message = fmt % string.join(map(str, targets))
+        return targets, message
+
+class DirNodeInfo(SCons.Node.NodeInfoBase):
+    pass
+
+class DirBuildInfo(SCons.Node.BuildInfoBase):
+    pass
+
+class Dir(Base):
+    """A class for directories in a file system.
+    """
+
+    NodeInfo = DirNodeInfo
+    BuildInfo = DirBuildInfo
+
+    def __init__(self, name, directory, fs):
+        if __debug__: logInstanceCreation(self, 'Node.FS.Dir')
+        Base.__init__(self, name, directory, fs)
+        self._morph()
+
+    def _morph(self):
+        """Turn a file system Node (either a freshly initialized directory
+        object or a separate Entry object) into a proper directory object.
+
+        Set up this directory's entries and hook it into the file
+        system tree.  Specify that directories (this Node) don't use
+        signatures for calculating whether they're current.
+        __cache_reset__"""
+
+        self.repositories = []
+        self.srcdir = None
+
+        self.entries = {}
+        self.entries['.'] = self
+        self.entries['..'] = self.dir
+        self.cwd = self
+        self.searched = 0
+        self._sconsign = None
+        self.build_dirs = []
+
+        # Don't just reset the executor, replace its action list,
+        # because it might have some pre-or post-actions that need to
+        # be preserved.
+        self.builder = get_MkdirBuilder()
+        self.get_executor().set_action_list(self.builder.action)
+
+    def diskcheck_match(self):
+        diskcheck_match(self, self.fs.isfile,
+                           "File %s found where directory expected.")
+
+    def __clearRepositoryCache(self, duplicate=None):
+        """Called when we change the repository(ies) for a directory.
+        This clears any cached information that is invalidated by changing
+        the repository."""
+
+        for node in self.entries.values():
+            if node != self.dir:
+                if node != self and isinstance(node, Dir):
+                    node.__clearRepositoryCache(duplicate)
+                else:
+                    node.clear()
+                    try:
+                        del node._srcreps
+                    except AttributeError:
+                        pass
+                    if duplicate != None:
+                        node.duplicate=duplicate
+    
+    def __resetDuplicate(self, node):
+        if node != self:
+            node.duplicate = node.get_dir().duplicate
+
+    def Entry(self, name):
+        """Create an entry node named 'name' relative to this directory."""
+        return self.fs.Entry(name, self)
+
+    def Dir(self, name):
+        """Create a directory node named 'name' relative to this directory."""
+        return self.fs.Dir(name, self)
+
+    def File(self, name):
+        """Create a file node named 'name' relative to this directory."""
+        return self.fs.File(name, self)
+
+    def link(self, srcdir, duplicate):
+        """Set this directory as the build directory for the
+        supplied source directory."""
+        self.srcdir = srcdir
+        self.duplicate = duplicate
+        self.__clearRepositoryCache(duplicate)
+        srcdir.build_dirs.append(self)
+
+    def getRepositories(self):
+        """Returns a list of repositories for this directory.
+        __cacheable__"""
+        if self.srcdir and not self.duplicate:
+            return self.srcdir.get_all_rdirs() + self.repositories
+        return self.repositories
+
+    def get_all_rdirs(self):
+        """__cacheable__"""
+        result = [self]
+        fname = '.'
+        dir = self
+        while dir:
+            for rep in dir.getRepositories():
+                result.append(rep.Dir(fname))
+            fname = dir.name + os.sep + fname
+            dir = dir.up()
+        return result
+
+    def addRepository(self, dir):
+        if dir != self and not dir in self.repositories:
+            self.repositories.append(dir)
+            dir.tpath = '.'
+            self.__clearRepositoryCache()
+
+    def up(self):
+        return self.entries['..']
+
+    def rel_path(self, other):
+        """Return a path to "other" relative to this directory.
+        __cacheable__"""
+        if isinstance(other, Dir):
+            name = []
+        else:
+            try:
+                name = [other.name]
+                other = other.dir
+            except AttributeError:
+                return str(other)
+        if self is other:
+            return name and name[0] or '.'
+        i = 0
+        for x, y in map(None, self.path_elements, other.path_elements):
+            if not x is y:
+                break
+            i = i + 1
+        path_elems = ['..']*(len(self.path_elements)-i) \
+                   + map(lambda n: n.name, other.path_elements[i:]) \
+                   + name
+             
+        return string.join(path_elems, os.sep)
+
+    def get_env_scanner(self, env, kw={}):
+        return SCons.Defaults.DirEntryScanner
+
+    def get_target_scanner(self):
+        return SCons.Defaults.DirEntryScanner
+
+    def get_found_includes(self, env, scanner, path):
+        """Return the included implicit dependencies in this file.
+        Cache results so we only scan the file once per path
+        regardless of how many times this information is requested.
+        __cacheable__"""
+        if not scanner:
+            return []
+        # Clear cached info for this Dir.  If we already visited this
+        # directory on our walk down the tree (because we didn't know at
+        # that point it was being used as the source for another Node)
+        # then we may have calculated build signature before realizing
+        # we had to scan the disk.  Now that we have to, though, we need
+        # to invalidate the old calculated signature so that any node
+        # dependent on our directory structure gets one that includes
+        # info about everything on disk.
+        self.clear()
+        return scanner(self, env, path)
+
+    def build(self, **kw):
+        """A null "builder" for directories."""
+        global MkdirBuilder
+        if not self.builder is MkdirBuilder:
+            apply(SCons.Node.Node.build, [self,], kw)
+
+    def _create(self):
+        """Create this directory, silently and without worrying about
+        whether the builder is the default or not."""
+        listDirs = []
+        parent = self
+        while parent:
+            if parent.exists():
+                break
+            listDirs.append(parent)
+            p = parent.up()
+            if p is None:
+                raise SCons.Errors.StopError, parent.path
+            parent = p
+        listDirs.reverse()
+        for dirnode in listDirs:
+            try:
+                # Don't call dirnode.build(), call the base Node method
+                # directly because we definitely *must* create this
+                # directory.  The dirnode.build() method will suppress
+                # the build if it's the default builder.
+                SCons.Node.Node.build(dirnode)
+                dirnode.get_executor().nullify()
+                # The build() action may or may not have actually
+                # created the directory, depending on whether the -n
+                # option was used or not.  Delete the _exists and
+                # _rexists attributes so they can be reevaluated.
+                dirnode.clear()
+            except OSError:
+                pass
+
+    def multiple_side_effect_has_builder(self):
+        global MkdirBuilder
+        return not self.builder is MkdirBuilder and self.has_builder()
+
+    def alter_targets(self):
+        """Return any corresponding targets in a build directory.
+        """
+        return self.fs.build_dir_target_climb(self, self, [])
+
+    def scanner_key(self):
+        """A directory does not get scanned."""
+        return None
+
+    def get_contents(self):
+        """Return aggregate contents of all our children."""
+        contents = map(lambda n: n.get_contents(), self.children())
+        return  string.join(contents, '')
+
+    def prepare(self):
+        pass
+
+    def do_duplicate(self, src):
+        pass
+
+    def current(self, calc=None):
+        """If any child is not up-to-date, then this directory isn't,
+        either."""
+        if not self.builder is MkdirBuilder and not self.exists():
+            return 0
+        up_to_date = SCons.Node.up_to_date
+        for kid in self.children():
+            if kid.get_state() > up_to_date:
+                return 0
+        return 1
+
+    def rdir(self):
+        "__cacheable__"
+        if not self.exists():
+            norm_name = _my_normcase(self.name)
+            for dir in self.dir.get_all_rdirs():
+                try: node = dir.entries[norm_name]
+                except KeyError: node = dir.dir_on_disk(self.name)
+                if node and node.exists() and \
+                    (isinstance(dir, Dir) or isinstance(dir, Entry)):
+                        return node
+        return self
+
+    def sconsign(self):
+        """Return the .sconsign file info for this directory,
+        creating it first if necessary."""
+        if not self._sconsign:
+            import SCons.SConsign
+            self._sconsign = SCons.SConsign.ForDirectory(self)
+        return self._sconsign
+
+    def srcnode(self):
+        """Dir has a special need for srcnode()...if we
+        have a srcdir attribute set, then that *is* our srcnode."""
+        if self.srcdir:
+            return self.srcdir
+        return Base.srcnode(self)
+
+    def get_timestamp(self):
+        """Return the latest timestamp from among our children"""
+        stamp = 0
+        for kid in self.children():
+            if kid.get_timestamp() > stamp:
+                stamp = kid.get_timestamp()
+        return stamp
+
+    def entry_abspath(self, name):
+        return self.abspath + os.sep + name
+
+    def entry_path(self, name):
+        return self.path + os.sep + name
+
+    def entry_tpath(self, name):
+        return self.tpath + os.sep + name
+
+    def must_be_a_Dir(self):
+        """Called to make sure a Node is a Dir.  Since we're already
+        one, this is a no-op for us."""
+        return self
+
+    def entry_exists_on_disk(self, name):
+        """__cacheable__"""
+        try:
+            d = self.on_disk_entries
+        except AttributeError:
+            d = {}
+            try:
+                entries = os.listdir(self.abspath)
+            except OSError:
+                pass
+            else:
+                for entry in map(_my_normcase, entries):
+                    d[entry] = 1
+            self.on_disk_entries = d
+        return d.has_key(_my_normcase(name))
+
+    def srcdir_list(self):
+        """__cacheable__"""
+        result = []
+
+        dirname = '.'
+        dir = self
+        while dir:
+            if dir.srcdir:
+                d = dir.srcdir.Dir(dirname)
+                if d.is_under(dir):
+                    # Shouldn't source from something in the build path:
+                    # build_dir is probably under src_dir, in which case
+                    # we are reflecting.
+                    break
+                result.append(d)
+            dirname = dir.name + os.sep + dirname
+            dir = dir.up()
+
+        return result
+
+    def srcdir_duplicate(self, name):
+        for dir in self.srcdir_list():
+            if dir.entry_exists_on_disk(name):
+                srcnode = dir.File(name)
+                if self.duplicate:
+                    node = self.File(name)
+                    node.do_duplicate(srcnode)
+                    return node
+                else:
+                    return srcnode
+        return None
+
+    def srcdir_find_file(self, filename):
+        """__cacheable__"""
+        def func(node):
+            if (isinstance(node, File) or isinstance(node, Entry)) and \
+               (node.is_derived() or node.is_pseudo_derived() or node.exists()):
+                    return node
+            return None
+
+        norm_name = _my_normcase(filename)
+
+        for rdir in self.get_all_rdirs():
+            try: node = rdir.entries[norm_name]
+            except KeyError: node = rdir.file_on_disk(filename)
+            else: node = func(node)
+            if node:
+                return node, self
+
+        for srcdir in self.srcdir_list():
+            for rdir in srcdir.get_all_rdirs():
+                try: node = rdir.entries[norm_name]
+                except KeyError: node = rdir.file_on_disk(filename)
+                else: node = func(node)
+                if node:
+                    return File(filename, self, self.fs), srcdir
+
+        return None, None
+
+    def dir_on_disk(self, name):
+        if self.entry_exists_on_disk(name):
+            try: return self.Dir(name)
+            except TypeError: pass
+        return None
+
+    def file_on_disk(self, name):
+        if self.entry_exists_on_disk(name) or \
+           diskcheck_rcs(self, name) or \
+           diskcheck_sccs(self, name):
+            try: return self.File(name)
+            except TypeError: pass
+        return self.srcdir_duplicate(name)
+
+class RootDir(Dir):
+    """A class for the root directory of a file system.
+
+    This is the same as a Dir class, except that the path separator
+    ('/' or '\\') is actually part of the name, so we don't need to
+    add a separator when creating the path names of entries within
+    this directory.
+    """
+    def __init__(self, name, fs):
+        if __debug__: logInstanceCreation(self, 'Node.FS.RootDir')
+        # We're going to be our own parent directory (".." entry and .dir
+        # attribute) so we have to set up some values so Base.__init__()
+        # won't gag won't it calls some of our methods.
+        self.abspath = ''
+        self.path = ''
+        self.tpath = ''
+        self.path_elements = []
+        self.duplicate = 0
+        Base.__init__(self, name, self, fs)
+
+        # Now set our paths to what we really want them to be: the
+        # initial drive letter (the name) plus the directory separator.
+        self.abspath = name + os.sep
+        self.path = name + os.sep
+        self.tpath = name + os.sep
+        self._morph()
+
+    def __str__(self):
+        return self.abspath
+
+    def entry_abspath(self, name):
+        return self.abspath + name
+
+    def entry_path(self, name):
+        return self.path + name
+
+    def entry_tpath(self, name):
+        return self.tpath + name
+
+    def is_under(self, dir):
+        if self is dir:
+            return 1
+        else:
+            return 0
+
+    def up(self):
+        return None
+
+    def get_dir(self):
+        return None
+
+    def src_builder(self):
+        return _null
+
+class FileNodeInfo(SCons.Node.NodeInfoBase):
+    def __init__(self, node):
+        SCons.Node.NodeInfoBase.__init__(self, node)
+        self.update(node)
+    def __cmp__(self, other):
+        try: return cmp(self.bsig, other.bsig)
+        except AttributeError: return 1
+    def update(self, node):
+        self.timestamp = node.get_timestamp()
+        self.size = node.getsize()
+
+class FileBuildInfo(SCons.Node.BuildInfoBase):
+    def __init__(self, node):
+        SCons.Node.BuildInfoBase.__init__(self, node)
+        self.node = node
+    def convert_to_sconsign(self):
+        """Convert this FileBuildInfo object for writing to a .sconsign file
+
+        We hung onto the node that we refer to so that we can translate
+        the lists of bsources, bdepends and bimplicit Nodes into strings
+        relative to the node, but we don't want to write out that Node
+        itself to the .sconsign file, so we delete the attribute in
+        preparation.
+        """
+        rel_path = self.node.rel_path
+        delattr(self, 'node')
+        for attr in ['bsources', 'bdepends', 'bimplicit']:
+            try:
+                val = getattr(self, attr)
+            except AttributeError:
+                pass
+            else:
+                setattr(self, attr, map(rel_path, val))
+    def convert_from_sconsign(self, dir, name):
+        """Convert a newly-read FileBuildInfo object for in-SCons use
+
+        An on-disk BuildInfo comes without a reference to the node for
+        which it's intended, so we have to convert the arguments and add
+        back a self.node attribute.  We don't worry here about converting
+        the bsources, bdepends and bimplicit lists from strings to Nodes
+        because they're not used in the normal case of just deciding
+        whether or not to rebuild things.
+        """
+        self.node = dir.Entry(name)
+    def prepare_dependencies(self):
+        """Prepare a FileBuildInfo object for explaining what changed
+
+        The bsources, bdepends and bimplicit lists have all been stored
+        on disk as paths relative to the Node for which they're stored
+        as dependency info.  Convert the strings to actual Nodes (for
+        use by the --debug=explain code and --implicit-cache).
+        """
+        Entry_func = self.node.dir.Entry
+        for attr in ['bsources', 'bdepends', 'bimplicit']:
+            try:
+                val = getattr(self, attr)
+            except AttributeError:
+                pass
+            else:
+                setattr(self, attr, map(Entry_func, val))
+    def format(self):
+        result = [ self.ninfo.format() ]
+        bkids = self.bsources + self.bdepends + self.bimplicit
+        bkidsigs = self.bsourcesigs + self.bdependsigs + self.bimplicitsigs
+        for i in xrange(len(bkids)):
+            result.append(str(bkids[i]) + ': ' + bkidsigs[i].format())
+        return string.join(result, '\n')
+
+class NodeInfo(FileNodeInfo):
+    pass
+
+class BuildInfo(FileBuildInfo):
+    pass
+
+class File(Base):
+    """A class for files in a file system.
+    """
+
+    NodeInfo = FileNodeInfo
+    BuildInfo = FileBuildInfo
+
+    def diskcheck_match(self):
+        diskcheck_match(self, self.fs.isdir,
+                           "Directory %s found where file expected.")
+
+    def __init__(self, name, directory, fs):
+        if __debug__: logInstanceCreation(self, 'Node.FS.File')
+        Base.__init__(self, name, directory, fs)
+        self._morph()
+
+    def Entry(self, name):
+        """Create an entry node named 'name' relative to
+        the SConscript directory of this file."""
+        return self.fs.Entry(name, self.cwd)
+
+    def Dir(self, name):
+        """Create a directory node named 'name' relative to
+        the SConscript directory of this file."""
+        return self.fs.Dir(name, self.cwd)
+
+    def Dirs(self, pathlist):
+        """Create a list of directories relative to the SConscript
+        directory of this file."""
+        return map(lambda p, s=self: s.Dir(p), pathlist)
+
+    def File(self, name):
+        """Create a file node named 'name' relative to
+        the SConscript directory of this file."""
+        return self.fs.File(name, self.cwd)
+
+    def RDirs(self, pathlist):
+        """Search for a list of directories in the Repository list."""
+        return self.fs.Rfindalldirs(pathlist, self.cwd)
+
+    #def generate_build_dict(self):
+    #    """Return an appropriate dictionary of values for building
+    #    this File."""
+    #    return {'Dir' : self.Dir,
+    #            'File' : self.File,
+    #            'RDirs' : self.RDirs}
+
+    def _morph(self):
+        """Turn a file system node into a File object.  __cache_reset__"""
+        self.scanner_paths = {}
+        if not hasattr(self, '_local'):
+            self._local = 0
+
+    def scanner_key(self):
+        return self.get_suffix()
+
+    def get_contents(self):
+        if not self.rexists():
+            return ''
+        return open(self.rfile().abspath, "rb").read()
+
+    def get_timestamp(self):
+        if self.rexists():
+            return self.rfile().getmtime()
+        else:
+            return 0
+
+    def store_info(self, obj):
+        # Merge our build information into the already-stored entry.
+        # This accomodates "chained builds" where a file that's a target
+        # in one build (SConstruct file) is a source in a different build.
+        # See test/chained-build.py for the use case.
+        entry = self.get_stored_info()
+        entry.merge(obj)
+        self.dir.sconsign().set_entry(self.name, entry)
+
+    def get_stored_info(self):
+        "__cacheable__"
+        try:
+            stored = self.dir.sconsign().get_entry(self.name)
+        except (KeyError, OSError):
+            return self.new_binfo()
+        else:
+            if not hasattr(stored, 'ninfo'):
+                # Transition:  The .sconsign file entry has no NodeInfo
+                # object, which means it's a slightly older BuildInfo.
+                # Copy over the relevant attributes.
+                ninfo = stored.ninfo = self.new_ninfo()
+                for attr in ninfo.__dict__.keys():
+                    try:
+                        setattr(ninfo, attr, getattr(stored, attr))
+                    except AttributeError:
+                        pass
+            return stored
+
+    def get_stored_implicit(self):
+        binfo = self.get_stored_info()
+        binfo.prepare_dependencies()
+        try: return binfo.bimplicit
+        except AttributeError: return None
+
+    def rel_path(self, other):
+        return self.dir.rel_path(other)
+
+    def get_found_includes(self, env, scanner, path):
+        """Return the included implicit dependencies in this file.
+        Cache results so we only scan the file once per path
+        regardless of how many times this information is requested.
+        __cacheable__"""
+        if not scanner:
+            return []
+        return scanner(self, env, path)
+
+    def _createDir(self):
+        # ensure that the directories for this node are
+        # created.
+        self.dir._create()
+
+    def retrieve_from_cache(self):
+        """Try to retrieve the node's content from a cache
+
+        This method is called from multiple threads in a parallel build,
+        so only do thread safe stuff here. Do thread unsafe stuff in
+        built().
+
+        Note that there's a special trick here with the execute flag
+        (one that's not normally done for other actions).  Basically
+        if the user requested a noexec (-n) build, then
+        SCons.Action.execute_actions is set to 0 and when any action
+        is called, it does its showing but then just returns zero
+        instead of actually calling the action execution operation.
+        The problem for caching is that if the file does NOT exist in
+        cache then the CacheRetrieveString won't return anything to
+        show for the task, but the Action.__call__ won't call
+        CacheRetrieveFunc; instead it just returns zero, which makes
+        the code below think that the file *was* successfully
+        retrieved from the cache, therefore it doesn't do any
+        subsequent building.  However, the CacheRetrieveString didn't
+        print anything because it didn't actually exist in the cache,
+        and no more build actions will be performed, so the user just
+        sees nothing.  The fix is to tell Action.__call__ to always
+        execute the CacheRetrieveFunc and then have the latter
+        explicitly check SCons.Action.execute_actions itself.
+
+        Returns true iff the node was successfully retrieved.
+        """
+        b = self.is_derived()
+        if not b and not self.has_src_builder():
+            return None
+        if b and self.fs.CachePath:
+            if self.fs.cache_show:
+                if CacheRetrieveSilent(self, [], None, execute=1) == 0:
+                    self.build(presub=0, execute=0)
+                    return 1
+            elif CacheRetrieve(self, [], None, execute=1) == 0:
+                return 1
+        return None
+
+    def built(self):
+        """Called just after this node is successfully built.
+        __cache_reset__"""
+        # Push this file out to cache before the superclass Node.built()
+        # method has a chance to clear the build signature, which it
+        # will do if this file has a source scanner.
+        if self.fs.CachePath and self.exists():
+            CachePush(self, [], None)
+        self.fs.clear_cache()
+        SCons.Node.Node.built(self)
+
+    def visited(self):
+        if self.fs.CachePath and self.fs.cache_force and self.exists():
+            CachePush(self, None, None)
+
+    def has_src_builder(self):
+        """Return whether this Node has a source builder or not.
+
+        If this Node doesn't have an explicit source code builder, this
+        is where we figure out, on the fly, if there's a transparent
+        source code builder for it.
+
+        Note that if we found a source builder, we also set the
+        self.builder attribute, so that all of the methods that actually
+        *build* this file don't have to do anything different.
+        """
+        try:
+            scb = self.sbuilder
+        except AttributeError:
+            if self.rexists():
+                scb = None
+            else:
+                scb = self.dir.src_builder()
+                if scb is _null:
+                    if diskcheck_sccs(self.dir, self.name):
+                        scb = get_DefaultSCCSBuilder()
+                    elif diskcheck_rcs(self.dir, self.name):
+                        scb = get_DefaultRCSBuilder()
+                    else:
+                        scb = None
+                if scb is not None:
+                    self.builder_set(scb)
+            self.sbuilder = scb
+        return not scb is None
+
+    def alter_targets(self):
+        """Return any corresponding targets in a build directory.
+        """
+        if self.is_derived():
+            return [], None
+        return self.fs.build_dir_target_climb(self, self.dir, [self.name])
+
+    def is_pseudo_derived(self):
+        "__cacheable__"
+        return self.has_src_builder()
+
+    def _rmv_existing(self):
+        '__cache_reset__'
+        Unlink(self, [], None)
+        
+    def prepare(self):
+        """Prepare for this file to be created."""
+        SCons.Node.Node.prepare(self)
+
+        if self.get_state() != SCons.Node.up_to_date:
+            if self.exists():
+                if self.is_derived() and not self.precious:
+                    self._rmv_existing()
+            else:
+                try:
+                    self._createDir()
+                except SCons.Errors.StopError, drive:
+                    desc = "No drive `%s' for target `%s'." % (drive, self)
+                    raise SCons.Errors.StopError, desc
+
+    def remove(self):
+        """Remove this file."""
+        if self.exists() or self.islink():
+            self.fs.unlink(self.path)
+            return 1
+        return None
+
+    def do_duplicate(self, src):
+        self._createDir()
+        try:
+            Unlink(self, None, None)
+        except SCons.Errors.BuildError:
+            pass
+        try:
+            Link(self, src, None)
+        except SCons.Errors.BuildError, e:
+            desc = "Cannot duplicate `%s' in `%s': %s." % (src.path, self.dir.path, e.errstr)
+            raise SCons.Errors.StopError, desc
+        self.linked = 1
+        # The Link() action may or may not have actually
+        # created the file, depending on whether the -n
+        # option was used or not.  Delete the _exists and
+        # _rexists attributes so they can be reevaluated.
+        self.clear()
+
+    def exists(self):
+        "__cacheable__"
+        # Duplicate from source path if we are set up to do this.
+        if self.duplicate and not self.is_derived() and not self.linked:
+            src = self.srcnode()
+            if src is self:
+                return Base.exists(self)
+            # At this point, src is meant to be copied in a build directory.
+            src = src.rfile()
+            if src.abspath != self.abspath:
+                if src.exists():
+                    self.do_duplicate(src)
+                    # Can't return 1 here because the duplication might
+                    # not actually occur if the -n option is being used.
+                else:
+                    # The source file does not exist.  Make sure no old
+                    # copy remains in the build directory.
+                    if Base.exists(self) or self.islink():
+                        self.fs.unlink(self.path)
+                    # Return None explicitly because the Base.exists() call
+                    # above will have cached its value if the file existed.
+                    return None
+        return Base.exists(self)
+
+    #
+    # SIGNATURE SUBSYSTEM
+    #
+
+    def get_csig(self, calc=None):
+        """
+        Generate a node's content signature, the digested signature
+        of its content.
+
+        node - the node
+        cache - alternate node to use for the signature cache
+        returns - the content signature
+        """
+        try:
+            return self.binfo.ninfo.csig
+        except AttributeError:
+            pass
+
+        if calc is None:
+            calc = self.calculator()
+
+        max_drift = self.fs.max_drift
+        mtime = self.get_timestamp()
+        use_stored = max_drift >= 0 and (time.time() - mtime) > max_drift
+
+        csig = None
+        if use_stored:
+            old = self.get_stored_info().ninfo
+            try:
+                if old.timestamp and old.csig and old.timestamp == mtime:
+                    csig = old.csig
+            except AttributeError:
+                pass
+        if csig is None:
+            csig = calc.module.signature(self)
+
+        binfo = self.get_binfo()
+        ninfo = binfo.ninfo
+        ninfo.csig = csig
+        ninfo.update(self)
+
+        if use_stored:
+            self.store_info(binfo)
+
+        return csig
+
+    #
+    #
+    #
+
+    def is_up_to_date(self, node=None, bi=None):
+        """Returns if the node is up-to-date with respect to stored
+        BuildInfo.  The default is to compare it against our own
+        previously stored BuildInfo, but the stored BuildInfo from another
+        Node (typically one in a Repository) can be used instead."""
+        if bi is None:
+            if node is None:
+                node = self
+            bi = node.get_stored_info()
+        new = self.get_binfo()
+        return new == bi
+
+    def current(self, calc=None):
+        self.binfo = self.gen_binfo(calc)
+        return self._cur2()
+    def _cur2(self):
+        "__cacheable__"
+        if self.always_build:
+            return None
+        if not self.exists():
+            # The file doesn't exist locally...
+            r = self.rfile()
+            if r != self:
+                # ...but there is one in a Repository...
+                if self.is_up_to_date(r):
+                    # ...and it's even up-to-date...
+                    if self._local:
+                        # ...and they'd like a local copy.
+                        LocalCopy(self, r, None)
+                        self.store_info(self.get_binfo())
+                    return 1
+            return None
+        else:
+            return self.is_up_to_date()
+
+    def rfile(self):
+        "__cacheable__"
+        if not self.exists():
+            norm_name = _my_normcase(self.name)
+            for dir in self.dir.get_all_rdirs():
+                try: node = dir.entries[norm_name]
+                except KeyError: node = dir.file_on_disk(self.name)
+                if node and node.exists() and \
+                   (isinstance(node, File) or isinstance(node, Entry) \
+                    or not node.is_derived()):
+                        return node
+        return self
+
+    def rstr(self):
+        return str(self.rfile())
+
+    def cachepath(self):
+        if not self.fs.CachePath:
+            return None, None
+        ninfo = self.get_binfo().ninfo
+        if not hasattr(ninfo, 'bsig'):
+            raise SCons.Errors.InternalError, "cachepath(%s) found no bsig" % self.path
+        elif ninfo.bsig is None:
+            raise SCons.Errors.InternalError, "cachepath(%s) found a bsig of None" % self.path
+        # Add the path to the cache signature, because multiple
+        # targets built by the same action will all have the same
+        # build signature, and we have to differentiate them somehow.
+        cache_sig = SCons.Sig.MD5.collect([ninfo.bsig, self.path])
+        subdir = string.upper(cache_sig[0])
+        dir = os.path.join(self.fs.CachePath, subdir)
+        return dir, os.path.join(dir, cache_sig)
+
+    def must_be_a_Dir(self):
+        """Called to make sure a Node is a Dir.  Since we're already a
+        File, this is a TypeError..."""
+        raise TypeError, "Tried to lookup File '%s' as a Dir." % self.path
+
+default_fs = None
+
+def find_file(filename, paths, verbose=None):
+    """
+    find_file(str, [Dir()]) -> [nodes]
+
+    filename - a filename to find
+    paths - a list of directory path *nodes* to search in.  Can be
+            represented as a list, a tuple, or a callable that is
+            called with no arguments and returns the list or tuple.
+
+    returns - the node created from the found file.
+
+    Find a node corresponding to either a derived file or a file
+    that exists already.
+
+    Only the first file found is returned, and none is returned
+    if no file is found.
+    __cacheable__
+    """
+    if verbose:
+        if not SCons.Util.is_String(verbose):
+            verbose = "find_file"
+        if not callable(verbose):
+            verbose = '  %s: ' % verbose
+            verbose = lambda s, v=verbose: sys.stdout.write(v + s)
+    else:
+        verbose = lambda x: x
+
+    if callable(paths):
+        paths = paths()
+
+    # Give Entries a chance to morph into Dirs.
+    paths = map(lambda p: p.must_be_a_Dir(), paths)
+
+    filedir, filename = os.path.split(filename)
+    if filedir:
+        def filedir_lookup(p, fd=filedir):
+            try:
+                return p.Dir(fd)
+            except TypeError:
+                # We tried to look up a Dir, but it seems there's already
+                # a File (or something else) there.  No big.
+                return None
+        paths = filter(None, map(filedir_lookup, paths))
+
+    for dir in paths:
+        verbose("looking for '%s' in '%s' ...\n" % (filename, dir))
+        node, d = dir.srcdir_find_file(filename)
+        if node:
+            verbose("... FOUND '%s' in '%s'\n" % (filename, d))
+            return node
+    return None
+
+def find_files(filenames, paths):
+    """
+    find_files([str], [Dir()]) -> [nodes]
+
+    filenames - a list of filenames to find
+    paths - a list of directory path *nodes* to search in
+
+    returns - the nodes created from the found files.
+
+    Finds nodes corresponding to either derived files or files
+    that exist already.
+
+    Only the first file found is returned for each filename,
+    and any files that aren't found are ignored.
+    """
+    nodes = map(lambda x, paths=paths: find_file(x, paths), filenames)
+    return filter(None, nodes)

Added: cs/scons/scons-local-0.96.92/SCons/Node/Python.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Node/Python.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Node/Python.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,88 @@
+"""scons.Node.Python
+
+Python nodes.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Node/Python.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Node
+
+class ValueNodeInfo(SCons.Node.NodeInfoBase):
+    pass
+
+class ValueBuildInfo(SCons.Node.BuildInfoBase):
+    pass
+
+class Value(SCons.Node.Node):
+    """A class for Python variables, typically passed on the command line 
+    or generated by a script, but not from a file or some other source.
+    """
+
+    NodeInfo = ValueNodeInfo
+    BuildInfo = ValueBuildInfo
+
+    def __init__(self, value):
+        SCons.Node.Node.__init__(self)
+        self.value = value
+
+    def __str__(self):
+        return repr(self.value)
+
+    def build(self):
+        """A "builder" for Values."""
+        pass
+
+    current = SCons.Node.Node.children_are_up_to_date
+
+    def is_under(self, dir):
+        # Make Value nodes get built regardless of 
+        # what directory scons was run from. Value nodes
+        # are outside the filesystem:
+        return 1
+
+    def get_contents(self):
+        """The contents of a Value are the concatenation
+        of all the contents of its sources with the node's value itself."""
+        contents = str(self.value)
+        for kid in self.children(None):
+            contents = contents + kid.get_contents()
+        return contents
+
+    def get_csig(self, calc=None):
+        """Because we're a Python value node and don't have a real
+        timestamp, we get to ignore the calculator and just use the
+        value contents."""
+        try:
+            binfo = self.binfo
+        except AttributeError:
+            binfo = self.binfo = self.new_binfo()
+        try:
+            return binfo.ninfo.csig
+        except AttributeError:
+            binfo.ninfo.csig = self.get_contents()
+            self.store_info(binfo)
+            return binfo.ninfo.csig

Added: cs/scons/scons-local-0.96.92/SCons/Node/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Node/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Node/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,1172 @@
+"""SCons.Node
+
+The Node package for the SCons software construction utility.
+
+This is, in many ways, the heart of SCons.
+
+A Node is where we encapsulate all of the dependency information about
+any thing that SCons can build, or about any thing which SCons can use
+to build some other thing.  The canonical "thing," of course, is a file,
+but a Node can also represent something remote (like a web page) or
+something completely abstract (like an Alias).
+
+Each specific type of "thing" is specifically represented by a subclass
+of the Node base class:  Node.FS.File for files, Node.Alias for aliases,
+etc.  Dependency information is kept here in the base class, and
+information specific to files/aliases/etc. is in the subclass.  The
+goal, if we've done this correctly, is that any type of "thing" should
+be able to depend on any other type of "thing."
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Node/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+
+import copy
+import string
+import UserList
+
+from SCons.Debug import logInstanceCreation
+import SCons.Executor
+import SCons.SConsign
+import SCons.Util
+
+# Node states
+#
+# These are in "priority" order, so that the maximum value for any
+# child/dependency of a node represents the state of that node if
+# it has no builder of its own.  The canonical example is a file
+# system directory, which is only up to date if all of its children
+# were up to date.
+no_state = 0
+pending = 1
+executing = 2
+up_to_date = 3
+executed = 4
+failed = 5
+stack = 6 # nodes that are in the current Taskmaster execution stack
+
+StateString = {
+    0 : "0",
+    1 : "pending",
+    2 : "executing",
+    3 : "up_to_date",
+    4 : "executed",
+    5 : "failed",
+    6 : "stack",
+}
+
+# controls whether implicit dependencies are cached:
+implicit_cache = 0
+
+# controls whether implicit dep changes are ignored:
+implicit_deps_unchanged = 0
+
+# controls whether the cached implicit deps are ignored:
+implicit_deps_changed = 0
+
+# A variable that can be set to an interface-specific function be called
+# to annotate a Node with information about its creation.
+def do_nothing(node): pass
+
+Annotate = do_nothing
+
+# Classes for signature info for Nodes.
+
+class NodeInfoBase:
+    """
+    The generic base class for signature information for a Node.
+
+    Node subclasses should subclass NodeInfoBase to provide their own
+    logic for dealing with their own Node-specific signature information.
+    """
+    def __init__(self, node):
+        """A null initializer so that subclasses have a superclass
+        initialization method to call for future use.
+        """
+        pass
+    def __cmp__(self, other):
+        return cmp(self.__dict__, other.__dict__)
+    def update(self, node):
+        pass
+    def merge(self, other):
+        for key, val in other.__dict__.items():
+            self.__dict__[key] = val
+    def prepare_dependencies(self):
+        pass
+    def format(self):
+        try:
+            field_list = self.field_list
+        except AttributeError:
+            field_list = self.__dict__.keys()
+            field_list.sort()
+        fields = []
+        for field in field_list:
+            try:
+                f = getattr(self, field)
+            except AttributeError:
+                f = None
+            fields.append(str(f))
+        return string.join(fields, " ")
+
+class BuildInfoBase:
+    """
+    The generic base clasee for build information for a Node.
+
+    This is what gets stored in a .sconsign file for each target file.
+    It contains a NodeInfo instance for this node (signature information
+    that's specific to the type of Node) and direct attributes for the
+    generic build stuff we have to track:  sources, explicit dependencies,
+    implicit dependencies, and action information.
+    """
+    def __init__(self, node):
+        self.ninfo = node.NodeInfo(node)
+        self.bsourcesigs = []
+        self.bdependsigs = []
+        self.bimplicitsigs = []
+        self.bactsig = None
+    def __cmp__(self, other):
+        return cmp(self.ninfo, other.ninfo)
+    def merge(self, other):
+        for key, val in other.__dict__.items():
+            try:
+                merge = self.__dict__[key].merge
+            except (AttributeError, KeyError):
+                self.__dict__[key] = val
+            else:
+                merge(val)
+
+class Node:
+    """The base Node class, for entities that we know how to
+    build, or use to build other Nodes.
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    class Attrs:
+        pass
+
+    def __init__(self):
+        if __debug__: logInstanceCreation(self, 'Node.Node')
+        # Note that we no longer explicitly initialize a self.builder
+        # attribute to None here.  That's because the self.builder
+        # attribute may be created on-the-fly later by a subclass (the
+        # canonical example being a builder to fetch a file from a
+        # source code system like CVS or Subversion).
+
+        # Each list of children that we maintain is accompanied by a
+        # dictionary used to look up quickly whether a node is already
+        # present in the list.  Empirical tests showed that it was
+        # fastest to maintain them as side-by-side Node attributes in
+        # this way, instead of wrapping up each list+dictionary pair in
+        # a class.  (Of course, we could always still do that in the
+        # future if we had a good reason to...).
+        self.sources = []       # source files used to build node
+        self.sources_dict = {}
+        self.depends = []       # explicit dependencies (from Depends)
+        self.depends_dict = {}
+        self.ignore = []        # dependencies to ignore
+        self.ignore_dict = {}
+        self.implicit = None    # implicit (scanned) dependencies (None means not scanned yet)
+        self.waiting_parents = []
+        self.wkids = None       # Kids yet to walk, when it's an array
+
+        self.env = None
+        self.state = no_state
+        self.precious = None
+        self.noclean = 0
+        self.always_build = None
+        self.found_includes = {}
+        self.includes = None
+        self.attributes = self.Attrs() # Generic place to stick information about the Node.
+        self.side_effect = 0 # true iff this node is a side effect
+        self.side_effects = [] # the side effects of building this target
+        self.pre_actions = []
+        self.post_actions = []
+        self.linked = 0 # is this node linked to the build directory? 
+
+        # Let the interface in which the build engine is embedded
+        # annotate this Node with its own info (like a description of
+        # what line in what file created the node, for example).
+        Annotate(self)
+
+    def disambiguate(self):
+        return self
+
+    def get_suffix(self):
+        return ''
+
+    def get_build_env(self):
+        """Fetch the appropriate Environment to build this node.
+        __cacheable__"""
+        return self.get_executor().get_build_env()
+
+    def get_build_scanner_path(self, scanner):
+        """Fetch the appropriate scanner path for this node."""
+        return self.get_executor().get_build_scanner_path(scanner)
+
+    def set_executor(self, executor):
+        """Set the action executor for this node."""
+        self.executor = executor
+
+    def get_executor(self, create=1):
+        """Fetch the action executor for this node.  Create one if
+        there isn't already one, and requested to do so."""
+        try:
+            executor = self.executor
+        except AttributeError:
+            if not create:
+                raise
+            try:
+                act = self.builder.action
+            except AttributeError:
+                executor = SCons.Executor.Null(targets=[self])
+            else:
+                executor = SCons.Executor.Executor(act,
+                                                   self.env or self.builder.env,
+                                                   [self.builder.overrides],
+                                                   [self],
+                                                   self.sources)
+            self.executor = executor
+        return executor
+
+    def executor_cleanup(self):
+        """Let the executor clean up any cached information."""
+        try:
+            executor = self.get_executor(create=None)
+        except AttributeError:
+            pass
+        else:
+            executor.cleanup()
+
+    def reset_executor(self):
+        "Remove cached executor; forces recompute when needed."
+        try:
+            delattr(self, 'executor')
+        except AttributeError:
+            pass
+
+    def retrieve_from_cache(self):
+        """Try to retrieve the node's content from a cache
+
+        This method is called from multiple threads in a parallel build,
+        so only do thread safe stuff here. Do thread unsafe stuff in
+        built().
+
+        Returns true iff the node was successfully retrieved.
+        """
+        return 0
+        
+    def build(self, **kw):
+        """Actually build the node.
+
+        This method is called from multiple threads in a parallel build,
+        so only do thread safe stuff here. Do thread unsafe stuff in
+        built().
+        """
+        def exitstatfunc(stat, node=self):
+            if stat:
+                msg = "Error %d" % stat
+                raise SCons.Errors.BuildError(node=node, errstr=msg)
+        executor = self.get_executor()
+        apply(executor, (self, exitstatfunc), kw)
+
+    def built(self):
+        """Called just after this node is successfully built."""
+
+        # Clear the implicit dependency caches of any Nodes
+        # waiting for this Node to be built.
+        for parent in self.waiting_parents:
+            parent.implicit = None
+            parent.del_binfo()
+        
+        try:
+            new = self.binfo
+        except AttributeError:
+            # Node arrived here without build info; apparently it
+            # doesn't need it, so don't bother calculating or storing
+            # it.
+            new = None
+
+        # Reset this Node's cached state since it was just built and
+        # various state has changed.
+        self.clear()
+        
+        if new:
+            # It had build info, so it should be stored in the signature
+            # cache.  However, if the build info included a content
+            # signature then it must be recalculated before being stored.
+            if hasattr(new.ninfo, 'csig'):
+                self.get_csig()
+            else:
+                new.ninfo.update(self)
+                self.binfo = new
+            self.store_info(self.binfo)
+
+    def add_to_waiting_parents(self, node):
+        self.waiting_parents.append(node)
+
+    def call_for_all_waiting_parents(self, func):
+        func(self)
+        for parent in self.waiting_parents:
+            parent.call_for_all_waiting_parents(func)
+
+    def postprocess(self):
+        """Clean up anything we don't need to hang onto after we've
+        been built."""
+        self.executor_cleanup()
+
+    def clear(self):
+        """Completely clear a Node of all its cached state (so that it
+        can be re-evaluated by interfaces that do continuous integration
+        builds).
+        __reset_cache__
+        """
+        self.executor_cleanup()
+        self.del_binfo()
+        try:
+            delattr(self, '_calculated_sig')
+        except AttributeError:
+            pass
+        self.includes = None
+        self.found_includes = {}
+        self.implicit = None
+
+        self.waiting_parents = []
+
+    def visited(self):
+        """Called just after this node has been visited
+        without requiring a build.."""
+        pass
+
+    def builder_set(self, builder):
+        "__cache_reset__"
+        self.builder = builder
+
+    def has_builder(self):
+        """Return whether this Node has a builder or not.
+
+        In Boolean tests, this turns out to be a *lot* more efficient
+        than simply examining the builder attribute directly ("if
+        node.builder: ..."). When the builder attribute is examined
+        directly, it ends up calling __getattr__ for both the __len__
+        and __nonzero__ attributes on instances of our Builder Proxy
+        class(es), generating a bazillion extra calls and slowing
+        things down immensely.
+        """
+        try:
+            b = self.builder
+        except AttributeError:
+            # There was no explicit builder for this Node, so initialize
+            # the self.builder attribute to None now.
+            self.builder = None
+            b = self.builder
+        return not b is None
+
+    def set_explicit(self, is_explicit):
+        self.is_explicit = is_explicit
+
+    def has_explicit_builder(self):
+        """Return whether this Node has an explicit builder
+
+        This allows an internal Builder created by SCons to be marked
+        non-explicit, so that it can be overridden by an explicit
+        builder that the user supplies (the canonical example being
+        directories)."""
+        try:
+            return self.is_explicit
+        except AttributeError:
+            self.is_explicit = None
+            return self.is_explicit
+
+    def get_builder(self, default_builder=None):
+        """Return the set builder, or a specified default value"""
+        try:
+            return self.builder
+        except AttributeError:
+            return default_builder
+
+    multiple_side_effect_has_builder = has_builder
+
+    def is_derived(self):
+        """
+        Returns true iff this node is derived (i.e. built).
+
+        This should return true only for nodes whose path should be in
+        the build directory when duplicate=0 and should contribute their build
+        signatures when they are used as source files to other derived files. For
+        example: source with source builders are not derived in this sense,
+        and hence should not return true.
+        __cacheable__
+        """
+        return self.has_builder() or self.side_effect
+
+    def is_pseudo_derived(self):
+        """
+        Returns true iff this node is built, but should use a source path
+        when duplicate=0 and should contribute a content signature (i.e.
+        source signature) when used as a source for other derived files.
+        """
+        return 0
+
+    def alter_targets(self):
+        """Return a list of alternate targets for this Node.
+        """
+        return [], None
+
+    def get_found_includes(self, env, scanner, path):
+        """Return the scanned include lines (implicit dependencies)
+        found in this node.
+
+        The default is no implicit dependencies.  We expect this method
+        to be overridden by any subclass that can be scanned for
+        implicit dependencies.
+        """
+        return []
+
+    def get_implicit_deps(self, env, scanner, path):
+        """Return a list of implicit dependencies for this node.
+
+        This method exists to handle recursive invocation of the scanner
+        on the implicit dependencies returned by the scanner, if the
+        scanner's recursive flag says that we should.
+        """
+        if not scanner:
+            return []
+
+        # Give the scanner a chance to select a more specific scanner
+        # for this Node.
+        #scanner = scanner.select(self)
+
+        nodes = [self]
+        seen = {}
+        seen[self] = 1
+        deps = []
+        while nodes:
+            n = nodes.pop(0)
+            d = filter(lambda x, seen=seen: not seen.has_key(x),
+                       n.get_found_includes(env, scanner, path))
+            if d:
+                deps.extend(d)
+                for n in d:
+                    seen[n] = 1
+                nodes.extend(scanner.recurse_nodes(d))
+
+        return deps
+
+    def get_env_scanner(self, env, kw={}):
+        return env.get_scanner(self.scanner_key())
+
+    def get_target_scanner(self):
+        return self.builder.target_scanner
+
+    def get_source_scanner(self, node):
+        """Fetch the source scanner for the specified node
+
+        NOTE:  "self" is the target being built, "node" is
+        the source file for which we want to fetch the scanner.
+
+        Implies self.has_builder() is true; again, expect to only be
+        called from locations where this is already verified.
+
+        This function may be called very often; it attempts to cache
+        the scanner found to improve performance.
+        """
+        scanner = None
+        try:
+            scanner = self.builder.source_scanner
+        except AttributeError:
+            pass
+        if not scanner:
+            # The builder didn't have an explicit scanner, so go look up
+            # a scanner from env['SCANNERS'] based on the node's scanner
+            # key (usually the file extension).
+            scanner = self.get_env_scanner(self.get_build_env())
+        if scanner:
+            scanner = scanner.select(node)
+        return scanner
+
+    def add_to_implicit(self, deps):
+        if not hasattr(self, 'implicit') or self.implicit is None:
+            self.implicit = []
+            self.implicit_dict = {}
+            self._children_reset()
+        self._add_child(self.implicit, self.implicit_dict, deps)
+
+    def scan(self):
+        """Scan this node's dependents for implicit dependencies."""
+        # Don't bother scanning non-derived files, because we don't
+        # care what their dependencies are.
+        # Don't scan again, if we already have scanned.
+        if not self.implicit is None:
+            return
+        self.implicit = []
+        self.implicit_dict = {}
+        self._children_reset()
+        if not self.has_builder():
+            return
+
+        build_env = self.get_build_env()
+
+        # Here's where we implement --implicit-cache.
+        if implicit_cache and not implicit_deps_changed:
+            implicit = self.get_stored_implicit()
+            if implicit:
+                factory = build_env.get_factory(self.builder.source_factory)
+                nodes = []
+                for i in implicit:
+                    try:
+                        n = factory(i)
+                    except TypeError:
+                        # The implicit dependency was cached as one type
+                        # of Node last time, but the configuration has
+                        # changed (probably) and it's a different type
+                        # this time.  Just ignore the mismatch and go
+                        # with what our current configuration says the
+                        # Node is.
+                        pass
+                    else:
+                        nodes.append(n)
+                self._add_child(self.implicit, self.implicit_dict, nodes)
+                calc = build_env.get_calculator()
+                if implicit_deps_unchanged or self.current(calc):
+                    return
+                # one of this node's sources has changed, so
+                # we need to recalculate the implicit deps,
+                # and the bsig:
+                self.implicit = []
+                self.implicit_dict = {}
+                self._children_reset()
+                self.del_binfo()
+
+        executor = self.get_executor()
+
+        # Have the executor scan the sources.
+        executor.scan_sources(self.builder.source_scanner)
+
+        # If there's a target scanner, have the executor scan the target
+        # node itself and associated targets that might be built.
+        scanner = self.get_target_scanner()
+        if scanner:
+            executor.scan_targets(scanner)
+
+    def scanner_key(self):
+        return None
+
+    def select_scanner(self, scanner):
+        """Selects a scanner for this Node.
+
+        This is a separate method so it can be overridden by Node
+        subclasses (specifically, Node.FS.Dir) that *must* use their
+        own Scanner and don't select one the Scanner.Selector that's
+        configured for the target.
+        """
+        return scanner.select(self)
+
+    def env_set(self, env, safe=0):
+        if safe and self.env:
+            return
+        self.env = env
+
+    #
+    # SIGNATURE SUBSYSTEM
+    #
+
+    NodeInfo = NodeInfoBase
+    BuildInfo = BuildInfoBase
+
+    def calculator(self):
+        import SCons.Defaults
+        
+        env = self.env or SCons.Defaults.DefaultEnvironment()
+        return env.get_calculator()
+
+    def calc_signature(self, calc=None):
+        """
+        Select and calculate the appropriate build signature for a node.
+        __cacheable__
+
+        self - the node
+        calc - the signature calculation module
+        returns - the signature
+        """
+        if self.is_derived():
+            import SCons.Defaults
+
+            env = self.env or SCons.Defaults.DefaultEnvironment()
+            if env.use_build_signature():
+                return self.get_bsig(calc)
+        elif not self.rexists():
+            return None
+        return self.get_csig(calc)
+
+    def new_ninfo(self):
+        return self.NodeInfo(self)
+
+    def new_binfo(self):
+        return self.BuildInfo(self)
+
+    def get_binfo(self):
+        try:
+            return self.binfo
+        except AttributeError:
+            self.binfo = self.new_binfo()
+            return self.binfo
+
+    def del_binfo(self):
+        """Delete the build info from this node."""
+        try:
+            delattr(self, 'binfo')
+        except AttributeError:
+            pass
+
+    def gen_binfo(self, calc=None, scan=1):
+        """
+        Generate a node's build signature, the digested signatures
+        of its dependency files and build information.
+
+        node - the node whose sources will be collected
+        cache - alternate node to use for the signature cache
+        returns - the build signature
+
+        This no longer handles the recursive descent of the
+        node's children's signatures.  We expect that they're
+        already built and updated by someone else, if that's
+        what's wanted.
+        __cacheable__
+        """
+
+        if calc is None:
+            calc = self.calculator()
+
+        binfo = self.get_binfo()
+
+        if scan:
+            self.scan()
+
+        executor = self.get_executor()
+        def calc_signature(node, calc=calc):
+            return node.calc_signature(calc)
+
+        sources = executor.process_sources(None, self.ignore)
+        sourcesigs = executor.process_sources(calc_signature, self.ignore)
+
+        depends = self.depends
+        implicit = self.implicit or []
+
+        if self.ignore:
+            depends = filter(self.do_not_ignore, depends)
+            implicit = filter(self.do_not_ignore, implicit)
+
+        dependsigs = map(calc_signature, depends)
+        implicitsigs = map(calc_signature, implicit)
+
+        sigs = sourcesigs + dependsigs + implicitsigs
+
+        if self.has_builder():
+            binfo.bact = str(executor)
+            binfo.bactsig = calc.module.signature(executor)
+            sigs.append(binfo.bactsig)
+
+        binfo.bsources = sources
+        binfo.bdepends = depends
+        binfo.bimplicit = implicit
+
+        binfo.bsourcesigs = sourcesigs
+        binfo.bdependsigs = dependsigs
+        binfo.bimplicitsigs = implicitsigs
+
+        binfo.ninfo.bsig = calc.module.collect(filter(None, sigs))
+
+        return binfo
+
+    def get_bsig(self, calc=None):
+        binfo = self.get_binfo()
+        try:
+            return binfo.ninfo.bsig
+        except AttributeError:
+            self.binfo = self.gen_binfo(calc)
+            return self.binfo.ninfo.bsig
+
+    def get_csig(self, calc=None):
+        binfo = self.get_binfo()
+        try:
+            return binfo.ninfo.csig
+        except AttributeError:
+            if calc is None:
+                calc = self.calculator()
+            csig = binfo.ninfo.csig = calc.module.signature(self)
+            return csig
+
+    def store_info(self, obj):
+        """Make the build signature permanent (that is, store it in the
+        .sconsign file or equivalent)."""
+        pass
+
+    def get_stored_info(self):
+        return None
+
+    def get_stored_implicit(self):
+        """Fetch the stored implicit dependencies"""
+        return None
+
+    #
+    #
+    #
+
+    def set_precious(self, precious = 1):
+        """Set the Node's precious value."""
+        self.precious = precious
+
+    def set_noclean(self, noclean = 1):
+        """Set the Node's noclean value."""
+        # Make sure noclean is an integer so the --debug=stree
+        # output in Util.py can use it as an index.
+        self.noclean = noclean and 1 or 0
+
+    def set_always_build(self, always_build = 1):
+        """Set the Node's always_build value."""
+        self.always_build = always_build
+
+    def exists(self):
+        """Does this node exists?"""
+        # All node exist by default:
+        return 1
+    
+    def rexists(self):
+        """Does this node exist locally or in a repositiory?"""
+        # There are no repositories by default:
+        return self.exists()
+
+    def missing(self):
+        """__cacheable__"""
+        return not self.is_derived() and \
+               not self.is_pseudo_derived() and \
+               not self.linked and \
+               not self.rexists()
+    
+    def prepare(self):
+        """Prepare for this Node to be created.
+        The default implemenation checks that all children either exist
+        or are derived.
+        """
+        l = self.depends
+        if not self.implicit is None:
+            l = l + self.implicit
+        missing_sources = self.get_executor().get_missing_sources() \
+                          + filter(lambda c: c.missing(), l)
+        if missing_sources:
+            desc = "Source `%s' not found, needed by target `%s'." % (missing_sources[0], self)
+            raise SCons.Errors.StopError, desc
+
+    def remove(self):
+        """Remove this Node:  no-op by default."""
+        return None
+
+    def add_dependency(self, depend):
+        """Adds dependencies."""
+        try:
+            self._add_child(self.depends, self.depends_dict, depend)
+        except TypeError, e:
+            e = e.args[0]
+            if SCons.Util.is_List(e):
+                s = map(str, e)
+            else:
+                s = str(e)
+            raise SCons.Errors.UserError("attempted to add a non-Node dependency to %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
+
+    def add_ignore(self, depend):
+        """Adds dependencies to ignore."""
+        try:
+            self._add_child(self.ignore, self.ignore_dict, depend)
+        except TypeError, e:
+            e = e.args[0]
+            if SCons.Util.is_List(e):
+                s = map(str, e)
+            else:
+                s = str(e)
+            raise SCons.Errors.UserError("attempted to ignore a non-Node dependency of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
+
+    def add_source(self, source):
+        """Adds sources."""
+        try:
+            self._add_child(self.sources, self.sources_dict, source)
+        except TypeError, e:
+            e = e.args[0]
+            if SCons.Util.is_List(e):
+                s = map(str, e)
+            else:
+                s = str(e)
+            raise SCons.Errors.UserError("attempted to add a non-Node as source of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e)))
+
+    def _add_child(self, collection, dict, child):
+        """Adds 'child' to 'collection', first checking 'dict' to see
+        if it's already present."""
+        if type(child) is not type([]):
+            child = [child]
+        for c in child:
+            if not isinstance(c, Node):
+                raise TypeError, c
+        added = None
+        for c in child:
+            if not dict.has_key(c):
+                collection.append(c)
+                dict[c] = 1
+                added = 1
+        if added:
+            self._children_reset()
+
+    def add_wkid(self, wkid):
+        """Add a node to the list of kids waiting to be evaluated"""
+        if self.wkids != None:
+            self.wkids.append(wkid)
+
+    def _children_reset(self):
+        "__cache_reset__"
+        # We need to let the Executor clear out any calculated
+        # bsig info that it's cached so we can re-calculate it.
+        self.executor_cleanup()
+
+    def do_not_ignore(self, node):
+        return node not in self.ignore
+
+    def _all_children_get(self):
+        # The return list may contain duplicate Nodes, especially in
+        # source trees where there are a lot of repeated #includes
+        # of a tangle of .h files.  Profiling shows, however, that
+        # eliminating the duplicates with a brute-force approach that
+        # preserves the order (that is, something like:
+        #
+        #       u = []
+        #       for n in list:
+        #           if n not in u:
+        #               u.append(n)"
+        #
+        # takes more cycles than just letting the underlying methods
+        # hand back cached values if a Node's information is requested
+        # multiple times.  (Other methods of removing duplicates, like
+        # using dictionary keys, lose the order, and the only ordered
+        # dictionary patterns I found all ended up using "not in"
+        # internally anyway...)
+        if self.implicit is None:
+            return self.sources + self.depends
+        else:
+            return self.sources + self.depends + self.implicit
+
+    def _children_get(self):
+        "__cacheable__"
+        children = self._all_children_get()
+        if self.ignore:
+            children = filter(self.do_not_ignore, children)
+        return children
+
+    def all_children(self, scan=1):
+        """Return a list of all the node's direct children."""
+        if scan:
+            self.scan()
+        return self._all_children_get()
+
+    def children(self, scan=1):
+        """Return a list of the node's direct children, minus those
+        that are ignored by this node."""
+        if scan:
+            self.scan()
+        return self._children_get()
+
+    def set_state(self, state):
+        self.state = state
+
+    def get_state(self):
+        return self.state
+
+    def current(self, calc=None):
+        """Default check for whether the Node is current: unknown Node
+        subtypes are always out of date, so they will always get built."""
+        return None
+
+    def children_are_up_to_date(self, calc=None):
+        """Alternate check for whether the Node is current:  If all of
+        our children were up-to-date, then this Node was up-to-date, too.
+
+        The SCons.Node.Alias and SCons.Node.Python.Value subclasses
+        rebind their current() method to this method."""
+        # Allow the children to calculate their signatures.
+        self.binfo = self.gen_binfo(calc)
+        if self.always_build:
+            return None
+        state = 0
+        for kid in self.children(None):
+            s = kid.get_state()
+            if s and (not state or s > state):
+                state = s
+        return (state == 0 or state == SCons.Node.up_to_date)
+
+    def is_literal(self):
+        """Always pass the string representation of a Node to
+        the command interpreter literally."""
+        return 1
+
+    def render_include_tree(self):
+        """
+        Return a text representation, suitable for displaying to the
+        user, of the include tree for the sources of this node.
+        """
+        if self.is_derived() and self.env:
+            env = self.get_build_env()
+            for s in self.sources:
+                scanner = self.get_source_scanner(s)
+                path = self.get_build_scanner_path(scanner)
+                def f(node, env=env, scanner=scanner, path=path):
+                    return node.get_found_includes(env, scanner, path)
+                return SCons.Util.render_tree(s, f, 1)
+        else:
+            return None
+
+    def get_abspath(self):
+        """
+        Return an absolute path to the Node.  This will return simply
+        str(Node) by default, but for Node types that have a concept of
+        relative path, this might return something different.
+        """
+        return str(self)
+
+    def for_signature(self):
+        """
+        Return a string representation of the Node that will always
+        be the same for this particular Node, no matter what.  This
+        is by contrast to the __str__() method, which might, for
+        instance, return a relative path for a file Node.  The purpose
+        of this method is to generate a value to be used in signature
+        calculation for the command line used to build a target, and
+        we use this method instead of str() to avoid unnecessary
+        rebuilds.  This method does not need to return something that
+        would actually work in a command line; it can return any kind of
+        nonsense, so long as it does not change.
+        """
+        return str(self)
+
+    def get_string(self, for_signature):
+        """This is a convenience function designed primarily to be
+        used in command generators (i.e., CommandGeneratorActions or
+        Environment variables that are callable), which are called
+        with a for_signature argument that is nonzero if the command
+        generator is being called to generate a signature for the
+        command line, which determines if we should rebuild or not.
+
+        Such command generators should use this method in preference
+        to str(Node) when converting a Node to a string, passing
+        in the for_signature parameter, such that we will call
+        Node.for_signature() or str(Node) properly, depending on whether
+        we are calculating a signature or actually constructing a
+        command line."""
+        if for_signature:
+            return self.for_signature()
+        return str(self)
+
+    def get_subst_proxy(self):
+        """
+        This method is expected to return an object that will function
+        exactly like this Node, except that it implements any additional
+        special features that we would like to be in effect for
+        Environment variable substitution.  The principle use is that
+        some Nodes would like to implement a __getattr__() method,
+        but putting that in the Node type itself has a tendency to kill
+        performance.  We instead put it in a proxy and return it from
+        this method.  It is legal for this method to return self
+        if no new functionality is needed for Environment substitution.
+        """
+        return self
+
+    def explain(self):
+        if not self.exists():
+            return "building `%s' because it doesn't exist\n" % self
+
+        old = self.get_stored_info()
+        if old is None:
+            return None
+        old.prepare_dependencies()
+
+        def dictify(result, kids, sigs):
+            for k, s in zip(kids, sigs):
+                result[k] = s
+
+        try:
+            osig = {}
+            dictify(osig, old.bsources, old.bsourcesigs)
+            dictify(osig, old.bdepends, old.bdependsigs)
+            dictify(osig, old.bimplicit, old.bimplicitsigs)
+        except AttributeError:
+            return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self
+
+        new = self.get_binfo()
+
+        nsig = {}
+        dictify(nsig, new.bsources, new.bsourcesigs)
+        dictify(nsig, new.bdepends, new.bdependsigs)
+        dictify(nsig, new.bimplicit, new.bimplicitsigs)
+
+        old_bkids = old.bsources + old.bdepends + old.bimplicit
+        new_bkids = new.bsources + new.bdepends + new.bimplicit
+
+        # The sources and dependencies we'll want to report are all stored
+        # as relative paths to this target's directory, but we want to
+        # report them relative to the top-level SConstruct directory,
+        # so we only print them after running them through this lambda
+        # to turn them into the right relative Node and then return
+        # its string.
+        stringify = lambda s, E=self.dir.Entry: str(E(s))
+
+        lines = []
+
+        removed = filter(lambda x, nk=new_bkids: not x in nk, old_bkids)
+        if removed:
+            removed = map(stringify, removed)
+            fmt = "`%s' is no longer a dependency\n"
+            lines.extend(map(lambda s, fmt=fmt: fmt % s, removed))
+
+        for k in new_bkids:
+            if not k in old_bkids:
+                lines.append("`%s' is a new dependency\n" % stringify(k))
+            elif osig[k] != nsig[k]:
+                lines.append("`%s' changed\n" % stringify(k))
+
+        if len(lines) == 0 and old_bkids != new_bkids:
+            lines.append("the dependency order changed:\n" +
+                         "%sold: %s\n" % (' '*15, map(stringify, old_bkids)) +
+                         "%snew: %s\n" % (' '*15, map(stringify, new_bkids)))
+
+        if len(lines) == 0:
+            def fmt_with_title(title, strlines):
+                lines = string.split(strlines, '\n')
+                sep = '\n' + ' '*(15 + len(title))
+                return ' '*15 + title + string.join(lines, sep) + '\n'
+            if old.bactsig != new.bactsig:
+                if old.bact == new.bact:
+                    lines.append("the contents of the build action changed\n" +
+                                 fmt_with_title('action: ', new.bact))
+                else:
+                    lines.append("the build action changed:\n" +
+                                 fmt_with_title('old: ', old.bact) +
+                                 fmt_with_title('new: ', new.bact))
+
+        if len(lines) == 0:
+            return "rebuilding `%s' for unknown reasons\n" % self
+
+        preamble = "rebuilding `%s' because" % self
+        if len(lines) == 1:
+            return "%s %s"  % (preamble, lines[0])
+        else:
+            lines = ["%s:\n" % preamble] + lines
+            return string.join(lines, ' '*11)
+
+l = [1]
+ul = UserList.UserList([2])
+try:
+    l.extend(ul)
+except TypeError:
+    def NodeList(l):
+        return l
+else:
+    class NodeList(UserList.UserList):
+        def __str__(self):
+            return str(map(str, self.data))
+del l
+del ul
+
+if SCons.Memoize.use_old_memoization():
+    _Base = Node
+    class Node(SCons.Memoize.Memoizer, _Base):
+        def __init__(self, *args, **kw):
+            apply(_Base.__init__, (self,)+args, kw)
+            SCons.Memoize.Memoizer.__init__(self)
+
+
+def get_children(node, parent): return node.children()
+def ignore_cycle(node, stack): pass
+def do_nothing(node, parent): pass
+
+class Walker:
+    """An iterator for walking a Node tree.
+
+    This is depth-first, children are visited before the parent.
+    The Walker object can be initialized with any node, and
+    returns the next node on the descent with each next() call.
+    'kids_func' is an optional function that will be called to
+    get the children of a node instead of calling 'children'.
+    'cycle_func' is an optional function that will be called
+    when a cycle is detected.
+
+    This class does not get caught in node cycles caused, for example,
+    by C header file include loops.
+    """
+    def __init__(self, node, kids_func=get_children,
+                             cycle_func=ignore_cycle,
+                             eval_func=do_nothing):
+        self.kids_func = kids_func
+        self.cycle_func = cycle_func
+        self.eval_func = eval_func
+        node.wkids = copy.copy(kids_func(node, None))
+        self.stack = [node]
+        self.history = {} # used to efficiently detect and avoid cycles
+        self.history[node] = None
+
+    def next(self):
+        """Return the next node for this walk of the tree.
+
+        This function is intentionally iterative, not recursive,
+        to sidestep any issues of stack size limitations.
+        """
+
+        while self.stack:
+            if self.stack[-1].wkids:
+                node = self.stack[-1].wkids.pop(0)
+                if not self.stack[-1].wkids:
+                    self.stack[-1].wkids = None
+                if self.history.has_key(node):
+                    self.cycle_func(node, self.stack)
+                else:
+                    node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
+                    self.stack.append(node)
+                    self.history[node] = None
+            else:
+                node = self.stack.pop()
+                del self.history[node]
+                if node:
+                    if self.stack:
+                        parent = self.stack[-1]
+                    else:
+                        parent = None
+                    self.eval_func(node, parent)
+                return node
+        return None
+
+    def is_done(self):
+        return not self.stack
+
+
+arg2nodes_lookups = []

Added: cs/scons/scons-local-0.96.92/SCons/Optik/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Optik/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Optik/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,32 @@
+"""optik
+
+A powerful, extensible, and easy-to-use command-line parser for Python.
+
+By Greg Ward <gward at python.net>
+
+See http://optik.sourceforge.net/
+"""
+
+# Copyright (c) 2001 Gregory P. Ward.  All rights reserved.
+# See the README.txt distributed with Optik for licensing terms.
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+# Original Optik revision this is based on:
+__Optik_revision__ = "__init__.py,v 1.11 2002/04/11 19:17:34 gward Exp"
+
+__version__ = "1.3"
+
+
+# Re-import these for convenience
+from SCons.Optik.option import Option
+from SCons.Optik.option_parser import \
+     OptionParser, SUPPRESS_HELP, SUPPRESS_USAGE
+from SCons.Optik.errors import OptionValueError
+
+
+# Some day, there might be many Option classes.  As of Optik 1.3, the
+# preferred way to instantiate Options is indirectly, via make_option(),
+# which will become a factory function when there are many Option
+# classes.
+make_option = Option

Added: cs/scons/scons-local-0.96.92/SCons/Optik/errors.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Optik/errors.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Optik/errors.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,55 @@
+"""optik.errors
+
+Exception classes used by Optik.
+"""
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Optik/errors.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+# Original Optik revision this is based on:
+__Optik_revision__ = "errors.py,v 1.5 2002/02/13 23:29:47 gward Exp"
+
+# Copyright (c) 2001 Gregory P. Ward.  All rights reserved.
+# See the README.txt distributed with Optik for licensing terms.
+
+# created 2001/10/17 GPW (from optik.py)
+
+
+class OptikError (Exception):
+    def __init__ (self, msg):
+        self.msg = msg
+
+    def __str__ (self):
+        return self.msg
+
+
+class OptionError (OptikError):
+    """
+    Raised if an Option instance is created with invalid or
+    inconsistent arguments.
+    """
+
+    def __init__ (self, msg, option):
+        self.msg = msg
+        self.option_id = str(option)
+
+    def __str__ (self):
+        if self.option_id:
+            return "option %s: %s" % (self.option_id, self.msg)
+        else:
+            return self.msg
+
+class OptionConflictError (OptionError):
+    """
+    Raised if conflicting options are added to an OptionParser.
+    """
+
+class OptionValueError (OptikError):
+    """
+    Raised if an invalid option value is encountered on the command
+    line.
+    """
+
+class BadOptionError (OptikError):
+    """
+    Raised if an invalid or ambiguous option is seen on the command-line.
+    """

Added: cs/scons/scons-local-0.96.92/SCons/Optik/option.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Optik/option.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Optik/option.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,388 @@
+"""optik.option
+
+Defines the Option class and some standard value-checking functions.
+"""
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Optik/option.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+# Original Optik revision this is based on:
+__Optik_revision__ = "option.py,v 1.19.2.1 2002/07/23 01:51:14 gward Exp" 
+
+# Copyright (c) 2001 Gregory P. Ward.  All rights reserved.
+# See the README.txt distributed with Optik for licensing terms.
+
+# created 2001/10/17, GPW (from optik.py)
+
+import sys
+import string
+from types import TupleType, ListType, DictType
+from SCons.Optik.errors import OptionError, OptionValueError
+
+_builtin_cvt = { "int" : (int, "integer"),
+                 "long" : (long, "long integer"),
+                 "float" : (float, "floating-point"),
+                 "complex" : (complex, "complex") }
+
+def check_builtin (option, opt, value):
+    (cvt, what) = _builtin_cvt[option.type]
+    try:
+        return cvt(value)
+    except ValueError:
+        raise OptionValueError(
+            #"%s: invalid %s argument %s" % (opt, what, repr(value)))
+            "option %s: invalid %s value: %s" % (opt, what, repr(value)))
+
+def check_choice(option, opt, value):
+    if value in option.choices:
+        return value
+    else:
+        choices = string.join(map(repr, option.choices),", ")
+        raise OptionValueError(
+            "option %s: invalid choice: %s (choose from %s)"
+            % (opt, repr(value), choices))
+
+# Not supplying a default is different from a default of None,
+# so we need an explicit "not supplied" value.
+NO_DEFAULT = "NO"+"DEFAULT"
+
+
+class Option:
+    """
+    Instance attributes:
+      _short_opts : [string]
+      _long_opts : [string]
+
+      action : string
+      type : string
+      dest : string
+      default : any
+      nargs : int
+      const : any
+      choices : [string]
+      callback : function
+      callback_args : (any*)
+      callback_kwargs : { string : any }
+      help : string
+      metavar : string
+    """
+
+    # The list of instance attributes that may be set through
+    # keyword args to the constructor.
+    ATTRS = ['action',
+             'type',
+             'dest',
+             'default',
+             'nargs',
+             'const',
+             'choices',
+             'callback',
+             'callback_args',
+             'callback_kwargs',
+             'help',
+             'metavar']
+
+    # The set of actions allowed by option parsers.  Explicitly listed
+    # here so the constructor can validate its arguments.
+    ACTIONS = ("store",
+               "store_const",
+               "store_true",
+               "store_false",
+               "append",
+               "count",
+               "callback",
+               "help",
+               "version")
+
+    # The set of actions that involve storing a value somewhere;
+    # also listed just for constructor argument validation.  (If
+    # the action is one of these, there must be a destination.)
+    STORE_ACTIONS = ("store",
+                     "store_const",
+                     "store_true",
+                     "store_false",
+                     "append",
+                     "count")
+
+    # The set of actions for which it makes sense to supply a value
+    # type, ie. where we expect an argument to this option.
+    TYPED_ACTIONS = ("store",
+                     "append",
+                     "callback")
+
+    # The set of known types for option parsers.  Again, listed here for
+    # constructor argument validation.
+    TYPES = ("string", "int", "long", "float", "complex", "choice")
+
+    # Dictionary of argument checking functions, which convert and
+    # validate option arguments according to the option type.
+    # 
+    # Signature of checking functions is:
+    #   check(option : Option, opt : string, value : string) -> any
+    # where
+    #   option is the Option instance calling the checker
+    #   opt is the actual option seen on the command-line
+    #     (eg. "-a", "--file")
+    #   value is the option argument seen on the command-line
+    #
+    # The return value should be in the appropriate Python type
+    # for option.type -- eg. an integer if option.type == "int".
+    # 
+    # If no checker is defined for a type, arguments will be
+    # unchecked and remain strings.
+    TYPE_CHECKER = { "int"    : check_builtin,
+                     "long"   : check_builtin,
+                     "float"  : check_builtin,
+                     "complex"  : check_builtin,
+                     "choice" : check_choice,
+                   }
+
+
+    # CHECK_METHODS is a list of unbound method objects; they are called
+    # by the constructor, in order, after all attributes are
+    # initialized.  The list is created and filled in later, after all
+    # the methods are actually defined.  (I just put it here because I
+    # like to define and document all class attributes in the same
+    # place.)  Subclasses that add another _check_*() method should
+    # define their own CHECK_METHODS list that adds their check method
+    # to those from this class.
+    CHECK_METHODS = None
+                    
+
+    # -- Constructor/initialization methods ----------------------------
+
+    def __init__ (self, *opts, **attrs):
+        # Set _short_opts, _long_opts attrs from 'opts' tuple
+        opts = self._check_opt_strings(opts)
+        self._set_opt_strings(opts)
+
+        # Set all other attrs (action, type, etc.) from 'attrs' dict
+        self._set_attrs(attrs)
+
+        # Check all the attributes we just set.  There are lots of
+        # complicated interdependencies, but luckily they can be farmed
+        # out to the _check_*() methods listed in CHECK_METHODS -- which
+        # could be handy for subclasses!  The one thing these all share
+        # is that they raise OptionError if they discover a problem.
+        for checker in self.CHECK_METHODS:
+            checker(self)
+
+    def _check_opt_strings (self, opts):
+        # Filter out None because early versions of Optik had exactly
+        # one short option and one long option, either of which
+        # could be None.
+        opts = filter(None, opts)
+        if not opts:
+            raise OptionError("at least one option string must be supplied",
+                              self)
+        return opts
+
+    def _set_opt_strings (self, opts):
+        self._short_opts = []
+        self._long_opts = []
+        for opt in opts:
+            if len(opt) < 2:
+                raise OptionError(
+                    "invalid option string %s: "
+                    "must be at least two characters long" % (`opt`,), self)
+            elif len(opt) == 2:
+                if not (opt[0] == "-" and opt[1] != "-"):
+                    raise OptionError(
+                        "invalid short option string %s: "
+                        "must be of the form -x, (x any non-dash char)" % (`opt`,),
+                        self)
+                self._short_opts.append(opt)
+            else:
+                if not (opt[0:2] == "--" and opt[2] != "-"):
+                    raise OptionError(
+                        "invalid long option string %s: "
+                        "must start with --, followed by non-dash" % (`opt`,),
+                        self)
+                self._long_opts.append(opt)
+
+    def _set_attrs (self, attrs):
+        for attr in self.ATTRS:
+            if attrs.has_key(attr):
+                setattr(self, attr, attrs[attr])
+                del attrs[attr]
+            else:
+                if attr == 'default':
+                    setattr(self, attr, NO_DEFAULT)
+                else:
+                    setattr(self, attr, None)
+        if attrs:
+            raise OptionError(
+                "invalid keyword arguments: %s" % string.join(attrs.keys(),", "),
+                self)
+
+
+    # -- Constructor validation methods --------------------------------
+
+    def _check_action (self):
+        if self.action is None:
+            self.action = "store"
+        elif self.action not in self.ACTIONS:
+            raise OptionError("invalid action: %s" % (`self.action`,), self)
+
+    def _check_type (self):
+        if self.type is None:
+            # XXX should factor out another class attr here: list of
+            # actions that *require* a type
+            if self.action in ("store", "append"):
+                if self.choices is not None:
+                    # The "choices" attribute implies "choice" type.
+                    self.type = "choice"
+                else:
+                    # No type given?  "string" is the most sensible default.
+                    self.type = "string"
+        else:
+            if self.type not in self.TYPES:
+                raise OptionError("invalid option type: %s" % (`self.type`,), self)
+            if self.action not in self.TYPED_ACTIONS:
+                raise OptionError(
+                    "must not supply a type for action %s" % (`self.action`,), self)
+
+    def _check_choice(self):
+        if self.type == "choice":
+            if self.choices is None:
+                raise OptionError(
+                    "must supply a list of choices for type 'choice'", self)
+            elif type(self.choices) not in (TupleType, ListType):
+                raise OptionError(
+                    "choices must be a list of strings ('%s' supplied)"
+                    % string.split(str(type(self.choices)),"'")[1], self)
+        elif self.choices is not None:
+            raise OptionError(
+                "must not supply choices for type %s" % (repr(self.type),), self)
+
+    def _check_dest (self):
+        if self.action in self.STORE_ACTIONS and self.dest is None:
+            # No destination given, and we need one for this action.
+            # Glean a destination from the first long option string,
+            # or from the first short option string if no long options.
+            if self._long_opts:
+                # eg. "--foo-bar" -> "foo_bar"
+                self.dest = string.replace(self._long_opts[0][2:],'-', '_')
+            else:
+                self.dest = self._short_opts[0][1]
+
+    def _check_const (self):
+        if self.action != "store_const" and self.const is not None:
+            raise OptionError(
+                "'const' must not be supplied for action %s" % (repr(self.action),),
+                self)
+        
+    def _check_nargs (self):
+        if self.action in self.TYPED_ACTIONS:
+            if self.nargs is None:
+                self.nargs = 1
+        elif self.nargs is not None:
+            raise OptionError(
+                "'nargs' must not be supplied for action %s" % (repr(self.action),),
+                self)
+
+    def _check_callback (self):
+        if self.action == "callback":
+            if not callable(self.callback):
+                raise OptionError(
+                    "callback not callable: %s" % (repr(self.callback),), self)
+            if (self.callback_args is not None and
+                type(self.callback_args) is not TupleType):
+                raise OptionError(
+                    "callback_args, if supplied, must be a tuple: not %s"
+                    % (repr(self.callback_args),), self)
+            if (self.callback_kwargs is not None and
+                type(self.callback_kwargs) is not DictType):
+                raise OptionError(
+                    "callback_kwargs, if supplied, must be a dict: not %s"
+                    % (repr(self.callback_kwargs),), self)
+        else:
+            if self.callback is not None:
+                raise OptionError(
+                    "callback supplied (%s) for non-callback option"
+                    % (repr(self.callback),), self)
+            if self.callback_args is not None:
+                raise OptionError(
+                    "callback_args supplied for non-callback option", self)
+            if self.callback_kwargs is not None:
+                raise OptionError(
+                    "callback_kwargs supplied for non-callback option", self)
+
+
+    CHECK_METHODS = [_check_action,
+                     _check_type,
+                     _check_choice,
+                     _check_dest,
+                     _check_const,
+                     _check_nargs,
+                     _check_callback]
+        
+
+    # -- Miscellaneous methods -----------------------------------------
+
+    def __str__ (self):
+        if self._short_opts or self._long_opts:
+            return string.join(self._short_opts + self._long_opts,"/")
+        else:
+            raise RuntimeError, "short_opts and long_opts both empty!"
+
+    def takes_value (self):
+        return self.type is not None
+
+
+    # -- Processing methods --------------------------------------------
+
+    def check_value (self, opt, value):
+        checker = self.TYPE_CHECKER.get(self.type)
+        if checker is None:
+            return value
+        else:
+            return checker(self, opt, value)
+
+    def process (self, opt, value, values, parser):
+
+        # First, convert the value(s) to the right type.  Howl if any
+        # value(s) are bogus.
+        if value is not None:
+            if self.nargs == 1:
+                value = self.check_value(opt, value)
+            else:
+                def cv(v,check=self.check_value,o=opt):
+                    return check(o,v)
+
+                value = tuple(map(cv,value))
+
+        # And then take whatever action is expected of us.
+        # This is a separate method to make life easier for
+        # subclasses to add new actions.
+        return self.take_action(
+            self.action, self.dest, opt, value, values, parser)
+
+    def take_action (self, action, dest, opt, value, values, parser):
+        if action == "store":
+            setattr(values, dest, value)
+        elif action == "store_const":
+            setattr(values, dest, self.const)
+        elif action == "store_true":
+            setattr(values, dest, 1)
+        elif action == "store_false":
+            setattr(values, dest, 0)
+        elif action == "append":
+            values.ensure_value(dest, []).append(value)
+        elif action == "count":
+            setattr(values, dest, values.ensure_value(dest, 0) + 1)
+        elif action == "callback":
+            args = self.callback_args or ()
+            kwargs = self.callback_kwargs or {}
+            apply( self.callback, (self, opt, value, parser,)+ args, kwargs)
+        elif action == "help":
+            parser.print_help()
+            sys.exit(0)
+        elif action == "version":
+            parser.print_version()
+            sys.exit(0)
+        else:
+            raise RuntimeError, "unknown action %s" % (repr(self.action),)
+
+        return 1
+
+# class Option

Added: cs/scons/scons-local-0.96.92/SCons/Optik/option_parser.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Optik/option_parser.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Optik/option_parser.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,730 @@
+"""optik.option_parser
+
+Provides the OptionParser and Values classes.
+"""
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Optik/option_parser.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+# Original Optik revision this is based on:
+__Optik_revision__ = "option_parser.py,v 1.38.2.1 2002/07/23 01:51:14 gward Exp"
+
+# Copyright (c) 2001 Gregory P. Ward.  All rights reserved.
+# See the README.txt distributed with Optik for licensing terms.
+
+# created 2001/10/17, GPW (from optik.py)
+
+import sys, os
+import string
+import types
+from SCons.Optik.option import Option, NO_DEFAULT
+from SCons.Optik.errors import OptionConflictError, OptionValueError, BadOptionError
+
+def get_prog_name ():
+    return os.path.basename(sys.argv[0])
+
+
+SUPPRESS_HELP = "SUPPRESS"+"HELP"
+SUPPRESS_USAGE = "SUPPRESS"+"USAGE"
+
+class Values:
+
+    def __init__ (self, defaults=None):
+        if defaults:
+            for (attr, val) in defaults.items():
+                setattr(self, attr, val)
+
+
+    def _update_careful (self, dict):
+        """
+        Update the option values from an arbitrary dictionary, but only
+        use keys from dict that already have a corresponding attribute
+        in self.  Any keys in dict without a corresponding attribute
+        are silently ignored.
+        """
+        for attr in dir(self):
+            if dict.has_key(attr):
+                dval = dict[attr]
+                if dval is not None:
+                    setattr(self, attr, dval)
+
+    def _update_loose (self, dict):
+        """
+        Update the option values from an arbitrary dictionary,
+        using all keys from the dictionary regardless of whether
+        they have a corresponding attribute in self or not.
+        """
+        self.__dict__.update(dict)
+
+    def _update (self, dict, mode):
+        if mode == "careful":
+            self._update_careful(dict)
+        elif mode == "loose":
+            self._update_loose(dict)
+        else:
+            raise ValueError, "invalid update mode: %s" % (repr(mode),)
+
+    def read_module (self, modname, mode="careful"):
+        __import__(modname)
+        mod = sys.modules[modname]
+        self._update(vars(mod), mode)
+
+    def read_file (self, filename, mode="careful"):
+        vars = {}
+        execfile(filename, vars)
+        self._update(vars, mode)
+
+    def ensure_value (self, attr, value):
+        if not hasattr(self, attr) or getattr(self, attr) is None:
+            setattr(self, attr, value)
+        return getattr(self, attr)
+
+
+class OptionParser:
+    """
+    Class attributes:
+      standard_option_list : [Option]
+        list of standard options that will be accepted by all instances
+        of this parser class (intended to be overridden by subclasses).
+
+    Instance attributes:
+      usage : string
+        a usage string for your program.  Before it is displayed
+        to the user, "%prog" will be expanded to the name of
+        your program (os.path.basename(sys.argv[0])).
+      option_list : [Option]
+        the list of all options accepted on the command-line of
+        this program
+      _short_opt : { string : Option }
+        dictionary mapping short option strings, eg. "-f" or "-X",
+        to the Option instances that implement them.  If an Option
+        has multiple short option strings, it will appears in this
+        dictionary multiple times.
+      _long_opt : { string : Option }
+        dictionary mapping long option strings, eg. "--file" or
+        "--exclude", to the Option instances that implement them.
+        Again, a given Option can occur multiple times in this
+        dictionary.
+      defaults : { string : any }
+        dictionary mapping option destination names to default
+        values for each destination.
+
+      allow_interspersed_args : boolean = true
+        if true, positional arguments may be interspersed with options.
+        Assuming -a and -b each take a single argument, the command-line
+          -ablah foo bar -bboo baz
+        will be interpreted the same as
+          -ablah -bboo -- foo bar baz
+        If this flag were false, that command line would be interpreted as
+          -ablah -- foo bar -bboo baz
+        -- ie. we stop processing options as soon as we see the first
+        non-option argument.  (This is the tradition followed by
+        Python's getopt module, Perl's Getopt::Std, and other argument-
+        parsing libraries, but it is generally annoying to users.)
+
+      rargs : [string]
+        the argument list currently being parsed.  Only set when
+        parse_args() is active, and continually trimmed down as
+        we consume arguments.  Mainly there for the benefit of
+        callback options.
+      largs : [string]
+        the list of leftover arguments that we have skipped while
+        parsing options.  If allow_interspersed_args is false, this
+        list is always empty.
+      values : Values
+        the set of option values currently being accumulated.  Only
+        set when parse_args() is active.  Also mainly for callbacks.
+
+    Because of the 'rargs', 'largs', and 'values' attributes,
+    OptionParser is not thread-safe.  If, for some perverse reason, you
+    need to parse command-line arguments simultaneously in different
+    threads, use different OptionParser instances.
+    
+    """ 
+
+    standard_option_list = []
+
+
+    def __init__ (self,
+                  usage=None,
+                  option_list=None,
+                  option_class=Option,
+                  version=None,
+                  conflict_handler="error"):
+        self.set_usage(usage)
+        self.option_class = option_class
+        self.version = version
+        self.set_conflict_handler(conflict_handler)
+        self.allow_interspersed_args = 1
+
+        # Create the various lists and dicts that constitute the
+        # "option list".  See class docstring for details about
+        # each attribute.
+        self._create_option_list()
+
+        # Populate the option list; initial sources are the
+        # standard_option_list class attribute, the 'option_list'
+        # argument, and the STD_VERSION_OPTION global (if 'version'
+        # supplied).
+        self._populate_option_list(option_list)
+
+        self._init_parsing_state()
+
+    # -- Private methods -----------------------------------------------
+    # (used by the constructor)
+
+    def _create_option_list (self):
+        self.option_list = []
+        self._short_opt = {}            # single letter -> Option instance
+        self._long_opt = {}             # long option -> Option instance
+        self.defaults = {}              # maps option dest -> default value
+
+    def _populate_option_list (self, option_list):
+        if self.standard_option_list:
+            self.add_options(self.standard_option_list)
+        if option_list:
+            self.add_options(option_list)
+        
+    def _init_parsing_state (self):
+        # These are set in parse_args() for the convenience of callbacks.
+        self.rargs = None
+        self.largs = None
+        self.values = None
+
+
+    # -- Simple modifier methods ---------------------------------------
+
+    def set_usage (self, usage):
+        if usage is None:
+            self.usage = "usage: %prog [options]"
+        elif usage is SUPPRESS_USAGE:
+            self.usage = None
+        else:
+            self.usage = usage
+
+    def enable_interspersed_args (self):
+        self.allow_interspersed_args = 1
+
+    def disable_interspersed_args (self):
+        self.allow_interspersed_args = 0
+
+    def set_conflict_handler (self, handler):
+        if handler not in ("ignore", "error", "resolve"):
+            raise ValueError, "invalid conflict_resolution value %s" % (repr(handler),)
+        self.conflict_handler = handler
+
+    def set_default (self, dest, value):
+        self.defaults[dest] = value
+
+    def set_defaults (self, **kwargs):
+        self.defaults.update(kwargs)
+
+    def get_default_values(self):
+        return Values(self.defaults)
+
+
+    # -- Option-adding methods -----------------------------------------
+
+    def _check_conflict (self, option):
+        conflict_opts = []
+        for opt in option._short_opts:
+            if self._short_opt.has_key(opt):
+                conflict_opts.append((opt, self._short_opt[opt]))
+        for opt in option._long_opts:
+            if self._long_opt.has_key(opt):
+                conflict_opts.append((opt, self._long_opt[opt]))
+
+        if conflict_opts:
+            handler = self.conflict_handler
+            if handler == "ignore":     # behaviour for Optik 1.0, 1.1
+                pass
+            elif handler == "error":    # new in 1.2
+                raise OptionConflictError(
+                    "conflicting option string(s): %s"
+                    % string.join( map( lambda x: x[0], conflict_opts),", "),
+                    option)
+            elif handler == "resolve":  # new in 1.2
+                for (opt, c_option) in conflict_opts:
+                    if len(opt)>2 and opt[:2]=="--":
+                        c_option._long_opts.remove(opt)
+                        del self._long_opt[opt]
+                    else:
+                        c_option._short_opts.remove(opt)
+                        del self._short_opt[opt]
+                    if not (c_option._short_opts or c_option._long_opts):
+                        self.option_list.remove(c_option)
+
+
+    def add_option (self, *args, **kwargs):
+        """add_option(Option)
+           add_option(opt_str, ..., kwarg=val, ...)
+        """
+        if type(args[0]) is types.StringType:
+            option = apply(self.option_class,args, kwargs)
+        elif len(args) == 1 and not kwargs:
+            option = args[0]
+            if not isinstance(option, Option):
+                raise TypeError, "not an Option instance: %s" % (repr(option),)
+        else:
+            raise TypeError, "invalid arguments"
+
+        self._check_conflict(option)
+
+        self.option_list.append(option)
+        for opt in option._short_opts:
+            self._short_opt[opt] = option
+        for opt in option._long_opts:
+            self._long_opt[opt] = option
+
+        if option.dest is not None:     # option has a dest, we need a default
+            if option.default is not NO_DEFAULT:
+                self.defaults[option.dest] = option.default
+            elif not self.defaults.has_key(option.dest):
+                self.defaults[option.dest] = None
+
+    def add_options (self, option_list):
+        for option in option_list:
+            self.add_option(option)
+
+
+    # -- Option query/removal methods ----------------------------------
+
+    def get_option (self, opt_str):
+        return (self._short_opt.get(opt_str) or
+                self._long_opt.get(opt_str))
+
+    def has_option (self, opt_str):
+        return (self._short_opt.has_key(opt_str) or
+                self._long_opt.has_key(opt_str))
+
+
+    def remove_option (self, opt_str):
+        option = self._short_opt.get(opt_str)
+        if option is None:
+            option = self._long_opt.get(opt_str)
+        if option is None:
+            raise ValueError("no such option %s" % (repr(opt_str),))
+
+        for opt in option._short_opts:
+            del self._short_opt[opt]
+        for opt in option._long_opts:
+            del self._long_opt[opt]
+        self.option_list.remove(option)
+
+
+    # -- Option-parsing methods ----------------------------------------
+
+    def _get_args (self, args):
+        if args is None:
+            return sys.argv[1:]
+        else:
+            return args[:]              # don't modify caller's list
+
+    def parse_args (self, args=None, values=None):
+        """
+        parse_args(args : [string] = sys.argv[1:],
+                   values : Values = None)
+        -> (values : Values, args : [string])
+
+        Parse the command-line options found in 'args' (default:
+        sys.argv[1:]).  Any errors result in a call to 'error()', which
+        by default prints the usage message to stderr and calls
+        sys.exit() with an error message.  On success returns a pair
+        (values, args) where 'values' is an Values instance (with all
+        your option values) and 'args' is the list of arguments left
+        over after parsing options.
+        """
+        rargs = self._get_args(args)
+        if values is None:
+            values = self.get_default_values()
+
+        # Store the halves of the argument list as attributes for the
+        # convenience of callbacks:
+        #   rargs
+        #     the rest of the command-line (the "r" stands for
+        #     "remaining" or "right-hand")
+        #   largs
+        #     the leftover arguments -- ie. what's left after removing
+        #     options and their arguments (the "l" stands for "leftover"
+        #     or "left-hand")
+        self.rargs = rargs
+        self.largs = largs = []
+        self.values = values
+
+        try:
+            stop = self._process_args(largs, rargs, values)
+        except (BadOptionError, OptionValueError), err:
+            self.error(err.msg)
+
+        args = largs + rargs
+        return self.check_values(values, args)
+
+    def check_values (self, values, args):
+        """
+        check_values(values : Values, args : [string])
+        -> (values : Values, args : [string])
+
+        Check that the supplied option values and leftover arguments are
+        valid.  Returns the option values and leftover arguments
+        (possibly adjusted, possibly completely new -- whatever you
+        like).  Default implementation just returns the passed-in
+        values; subclasses may override as desired.
+        """
+        return (values, args)
+
+    def _process_args (self, largs, rargs, values):
+        """_process_args(largs : [string],
+                         rargs : [string],
+                         values : Values)
+
+        Process command-line arguments and populate 'values', consuming
+        options and arguments from 'rargs'.  If 'allow_interspersed_args' is
+        false, stop at the first non-option argument.  If true, accumulate any
+        interspersed non-option arguments in 'largs'.
+        """
+        while rargs:
+            arg = rargs[0]
+            # We handle bare "--" explicitly, and bare "-" is handled by the
+            # standard arg handler since the short arg case ensures that the
+            # len of the opt string is greater than 1.
+            if arg == "--":
+                del rargs[0]
+                return
+            elif arg[0:2] == "--":
+                # process a single long option (possibly with value(s))
+                self._process_long_opt(rargs, values)
+            elif arg[:1] == "-" and len(arg) > 1:
+                # process a cluster of short options (possibly with
+                # value(s) for the last one only)
+                self._process_short_opts(rargs, values)
+            elif self.allow_interspersed_args:
+                largs.append(arg)
+                del rargs[0]
+            else:
+                return                  # stop now, leave this arg in rargs
+
+        # Say this is the original argument list:
+        # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
+        #                            ^
+        # (we are about to process arg(i)).
+        #
+        # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of
+        # [arg0, ..., arg(i-1)] (any options and their arguments will have
+        # been removed from largs).
+        #
+        # The while loop will usually consume 1 or more arguments per pass.
+        # If it consumes 1 (eg. arg is an option that takes no arguments),
+        # then after _process_arg() is done the situation is:
+        #
+        #   largs = subset of [arg0, ..., arg(i)]
+        #   rargs = [arg(i+1), ..., arg(N-1)]
+        #
+        # If allow_interspersed_args is false, largs will always be
+        # *empty* -- still a subset of [arg0, ..., arg(i-1)], but
+        # not a very interesting subset!
+        
+    def _match_long_opt (self, opt):
+        """_match_long_opt(opt : string) -> string
+
+        Determine which long option string 'opt' matches, ie. which one
+        it is an unambiguous abbrevation for.  Raises BadOptionError if
+        'opt' doesn't unambiguously match any long option string.
+        """
+        return _match_abbrev(opt, self._long_opt)
+
+    def _process_long_opt (self, rargs, values):
+        arg = rargs.pop(0)
+
+        # Value explicitly attached to arg?  Pretend it's the next
+        # argument.
+        if "=" in arg:
+            (opt, next_arg) = string.split(arg,"=", 1)
+            rargs.insert(0, next_arg)
+            had_explicit_value = 1
+        else:
+            opt = arg
+            had_explicit_value = 0
+
+        opt = self._match_long_opt(opt)
+        option = self._long_opt[opt]
+        if option.takes_value():
+            nargs = option.nargs
+            if len(rargs) < nargs:
+                if nargs == 1:
+                    self.error("%s option requires a value" % opt)
+                else:
+                    self.error("%s option requires %d values"
+                               % (opt, nargs))
+            elif nargs == 1:
+                value = rargs.pop(0)
+            else:
+                value = tuple(rargs[0:nargs])
+                del rargs[0:nargs]
+
+        elif had_explicit_value:
+            self.error("%s option does not take a value" % opt)
+
+        else:
+            value = None
+
+        option.process(opt, value, values, self)
+
+    def _process_short_opts (self, rargs, values):
+        arg = rargs.pop(0)
+        stop = 0
+        i = 1
+        for ch in arg[1:]:
+            opt = "-" + ch
+            option = self._short_opt.get(opt)
+            i = i+1                      # we have consumed a character
+
+            if not option:
+                self.error("no such option: %s" % opt)
+            if option.takes_value():
+                # Any characters left in arg?  Pretend they're the
+                # next arg, and stop consuming characters of arg.
+                if i < len(arg):
+                    rargs.insert(0, arg[i:])
+                    stop = 1
+
+                nargs = option.nargs
+                if len(rargs) < nargs:
+                    if nargs == 1:
+                        self.error("%s option requires a value" % opt)
+                    else:
+                        self.error("%s option requires %s values"
+                                   % (opt, nargs))
+                elif nargs == 1:
+                    value = rargs.pop(0)
+                else:
+                    value = tuple(rargs[0:nargs])
+                    del rargs[0:nargs]
+
+            else:                       # option doesn't take a value
+                value = None
+
+            option.process(opt, value, values, self)
+
+            if stop:
+                break
+
+
+    # -- Output/error methods ------------------------------------------
+
+    def error (self, msg):
+        """error(msg : string)
+
+        Print a usage message incorporating 'msg' to stderr and exit.
+        If you override this in a subclass, it should not return -- it
+        should either exit or raise an exception.
+        """
+        self.print_usage(sys.stderr)
+        sys.stderr.write("\nSCons error: %s\n" % msg)
+        sys.exit(2)
+
+    def print_usage (self, file=None):
+        """print_usage(file : file = stdout)
+
+        Print the usage message for the current program (self.usage) to
+        'file' (default stdout).  Any occurence of the string "%prog" in
+        self.usage is replaced with the name of the current program
+        (basename of sys.argv[0]).  Does nothing if self.usage is empty
+        or not defined.
+        """
+        if file is None:
+            file = sys.stdout
+        if self.usage:
+            usage = string.replace(self.usage,"%prog", get_prog_name())
+            file.write(usage + "\n")
+
+    def print_version (self, file=None):
+        """print_version(file : file = stdout)
+
+        Print the version message for this program (self.version) to
+        'file' (default stdout).  As with print_usage(), any occurence
+        of "%prog" in self.version is replaced by the current program's
+        name.  Does nothing if self.version is empty or undefined.
+        """
+        if file is None:
+            file = sys.stdout
+        if self.version:
+            version = string.replace(self.version,"%prog", get_prog_name())
+            file.write(version+"\n")
+
+    def print_help (self, file=None):
+        """print_help(file : file = stdout)
+
+        Print an extended help message, listing all options and any
+        help text provided with them, to 'file' (default stdout).
+        """
+        # SCons:  don't import wrap_text from distutils, use the
+        # copy we've included below, so we can avoid being dependent
+        # on having the right version of distutils installed.
+        #from distutils.fancy_getopt import wrap_text
+        
+        if file is None:
+            file = sys.stdout
+
+        self.print_usage(file)
+
+        # The help for each option consists of two parts:
+        #   * the opt strings and metavars
+        #     eg. ("-x", or "-fFILENAME, --file=FILENAME")
+        #   * the user-supplied help string
+        #     eg. ("turn on expert mode", "read data from FILENAME")
+        #
+        # If possible, we write both of these on the same line:
+        #   -x      turn on expert mode
+        # 
+        # But if the opt string list is too long, we put the help
+        # string on a second line, indented to the same column it would
+        # start in if it fit on the first line.
+        #   -fFILENAME, --file=FILENAME
+        #           read data from FILENAME
+
+        file.write("Options:\n")
+        width = 78                      # assume 80 cols for now
+
+        option_help = []                # list of (string, string) tuples
+        lengths = []
+
+        for option in self.option_list:
+            takes_value = option.takes_value()
+            if takes_value:
+                metavar = option.metavar or string.upper(option.dest)
+
+            opts = []               # list of "-a" or "--foo=FILE" strings
+            if option.help is SUPPRESS_HELP:
+                continue
+
+            if takes_value:
+                for sopt in option._short_opts:
+                    opts.append(sopt + ' ' + metavar)
+                for lopt in option._long_opts:
+                    opts.append(lopt + "=" + metavar)
+            else:
+                for opt in option._short_opts + option._long_opts:
+                    opts.append(opt)
+
+            opts = string.join(opts,", ")
+            option_help.append((opts, option.help))
+            lengths.append(len(opts))
+
+        max_opts = min(max(lengths), 26)
+
+        for (opts, help) in option_help:
+            # how much to indent lines 2 .. N of help text
+            indent_rest = 2 + max_opts + 2 
+            help_width = width - indent_rest
+
+            if len(opts) > max_opts:
+                opts = "  " + opts + "\n"
+                indent_first = indent_rest
+            else:                       # start help on same line as opts
+                opts = "  %-*s  " % (max_opts, opts)
+                indent_first = 0
+
+            file.write(opts)
+
+            if help:
+                help_lines = wrap_text(help, help_width)
+                file.write( "%*s%s\n" % (indent_first, "", help_lines[0]))
+                for line in help_lines[1:]:
+                    file.write("  %*s%s\n" % (indent_rest, "", line))
+            elif opts[-1] != "\n":
+                file.write("\n")
+
+# class OptionParser
+
+
+def _match_abbrev (s, wordmap):
+    """_match_abbrev(s : string, wordmap : {string : Option}) -> string
+
+    Return the string key in 'wordmap' for which 's' is an unambiguous
+    abbreviation.  If 's' is found to be ambiguous or doesn't match any of
+    'words', raise BadOptionError.
+    """
+    # Is there an exact match?
+    if wordmap.has_key(s):
+        return s
+    else:
+        # Isolate all words with s as a prefix.
+        possibilities = []
+        ls = len(s)
+        for word in wordmap.keys():
+            if len(word)>=ls and word[:ls]==s:
+                possibilities.append(word)
+        # No exact match, so there had better be just one possibility.
+        if len(possibilities) == 1:
+            return possibilities[0]
+        elif not possibilities:
+            raise BadOptionError("no such option: %s" % s)
+        else:
+            # More than one possible completion: ambiguous prefix.
+            raise BadOptionError("ambiguous option: %s (%s?)"
+                                 % (s, string.join(possibilities,", ")))
+
+# SCons:  Include a snarfed copy of wrap_text(), so we're not dependent
+# on the right version of distutils being installed.
+import re
+
+WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
+
+def wrap_text (text, width):
+    """wrap_text(text : string, width : int) -> [string]
+
+    Split 'text' into multiple lines of no more than 'width' characters
+    each, and return the list of strings that results.
+    """
+
+    if text is None:
+        return []
+    if len(text) <= width:
+        return [text]
+
+    text = string.expandtabs(text)
+    text = string.translate(text, WS_TRANS)
+    chunks = re.split(r'( +|-+)', text)
+    chunks = filter(None, chunks)      # ' - ' results in empty strings
+    lines = []
+
+    while chunks:
+
+        cur_line = []                   # list of chunks (to-be-joined)
+        cur_len = 0                     # length of current line
+
+        while chunks:
+            l = len(chunks[0])
+            if cur_len + l <= width:    # can squeeze (at least) this chunk in
+                cur_line.append(chunks[0])
+                del chunks[0]
+                cur_len = cur_len + l
+            else:                       # this line is full
+                # drop last chunk if all space
+                if cur_line and cur_line[-1][0] == ' ':
+                    del cur_line[-1]
+                break
+
+        if chunks:                      # any chunks left to process?
+
+            # if the current line is still empty, then we had a single
+            # chunk that's too big too fit on a line -- so we break
+            # down and break it up at the line width
+            if cur_len == 0:
+                cur_line.append(chunks[0][0:width])
+                chunks[0] = chunks[0][width:]
+
+            # all-whitespace chunks at the end of a line can be discarded
+            # (and we know from the re.split above that if a chunk has
+            # *any* whitespace, it is *all* whitespace)
+            if chunks[0][0] == ' ':
+                del chunks[0]
+
+        # and store this line in the list-of-all-lines -- as a single
+        # string, of course!
+        lines.append(string.join(cur_line, ''))
+
+    # while chunks
+
+    return lines
+
+# wrap_text ()

Added: cs/scons/scons-local-0.96.92/SCons/Options/BoolOption.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/BoolOption.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/BoolOption.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,88 @@
+"""engine.SCons.Options.BoolOption
+
+This file defines the option type for SCons implementing true/false values.
+
+Usage example:
+
+  opts = Options()
+  opts.Add(BoolOption('embedded', 'build for an embedded system', 0))
+  ...
+  if env['embedded'] == 1:
+    ...
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/BoolOption.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+__all__ = ('BoolOption', 'True', 'False')
+
+import string
+
+import SCons.Errors
+
+__true_strings  = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
+__false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
+
+# we need this since SCons should work version indepentant
+True, False = 1, 0
+
+
+def _text2bool(val):
+    """
+    Converts strings to True/False depending on the 'truth' expressed by
+    the string. If the string can't be converted, the original value
+    will be returned.
+
+    See '__true_strings' and '__false_strings' for values considered
+    'true' or 'false respectivly.
+
+    This is usable as 'converter' for SCons' Options.
+    """
+    lval = string.lower(val)
+    if lval in __true_strings: return True
+    if lval in __false_strings: return False
+    raise ValueError("Invalid value for boolean option: %s" % val)
+
+
+def _validator(key, val, env):
+    """
+    Validates the given value to be either '0' or '1'.
+    
+    This is usable as 'validator' for SCons' Options.
+    """
+    if not env[key] in (True, False):
+        raise SCons.Errors.UserError(
+            'Invalid value for boolean option %s: %s' % (key, env[key]))
+
+
+def BoolOption(key, help, default):
+    """
+    The input parameters describe a boolen option, thus they are
+    returned with the correct converter and validator appended. The
+    'help' text will by appended by '(yes|no) to show the valid
+    valued. The result is usable for input to opts.Add().
+    """
+    return (key, '%s (yes|no)' % help, default,
+            _validator, _text2bool)

Added: cs/scons/scons-local-0.96.92/SCons/Options/EnumOption.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/EnumOption.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/EnumOption.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,101 @@
+"""engine.SCons.Options.EnumOption
+
+This file defines the option type for SCons allowing only specified
+input-values.
+
+Usage example:
+
+  opts = Options()
+  opts.Add(EnumOption('debug', 'debug output and symbols', 'no',
+                      allowed_values=('yes', 'no', 'full'),
+                      map={}, ignorecase=2))
+  ...
+  if env['debug'] == 'full':
+    ...
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/EnumOption.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+__all__ = ('EnumOption',)
+
+import string
+
+import SCons.Errors
+
+def _validator(key, val, env, vals):
+    if not val in vals:
+        raise SCons.Errors.UserError(
+            'Invalid value for option %s: %s' % (key, val))
+
+
+def EnumOption(key, help, default, allowed_values, map={}, ignorecase=0):
+    """
+    The input parameters describe a option with only certain values
+    allowed. They are returned with an appropriate converter and
+    validator appended. The result is usable for input to
+    Options.Add().
+
+    'key' and 'default' are the values to be passed on to Options.Add().
+
+    'help' will be appended by the allowed values automatically
+
+    'allowed_values' is a list of strings, which are allowed as values
+    for this option.
+
+    The 'map'-dictionary may be used for converting the input value
+    into canonical values (eg. for aliases).
+
+    'ignorecase' defines the behaviour of the validator:
+
+    If ignorecase == 0, the validator/converter are case-sensitive.
+    If ignorecase == 1, the validator/converter are case-insensitive.
+    If ignorecase == 2, the validator/converter is case-insensitive and
+                        the converted value will always be lower-case.
+
+    The 'validator' tests whether the value is in the list of allowed
+    values. The 'converter' converts input values according to the
+    given 'map'-dictionary (unmapped input values are returned
+    unchanged). 
+    """
+    help = '%s (%s)' % (help, string.join(allowed_values, '|'))
+    # define validator
+    if ignorecase >= 1:
+        validator = lambda key, val, env, vals=allowed_values: \
+                    _validator(key, string.lower(val), env, vals)
+    else:
+        validator = lambda key, val, env, vals=allowed_values: \
+                    _validator(key, val, env, vals)
+    # define converter
+    if ignorecase == 2:
+        converter = lambda val, map=map: \
+                    string.lower(map.get(string.lower(val), val))
+    elif ignorecase == 1:
+        converter = lambda val, map=map: \
+                    map.get(string.lower(val), val)
+    else:
+        converter = lambda val, map=map: \
+                    map.get(val, val)
+    return (key, help, default, validator, converter)

Added: cs/scons/scons-local-0.96.92/SCons/Options/ListOption.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/ListOption.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/ListOption.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,133 @@
+"""engine.SCons.Options.ListOption
+
+This file defines the option type for SCons implementing 'lists'.
+
+A 'list' option may either be 'all', 'none' or a list of names
+separated by comma. After the option has been processed, the option
+value holds either the named list elements, all list elemens or no
+list elements at all.
+
+Usage example:
+
+  list_of_libs = Split('x11 gl qt ical')
+
+  opts = Options()
+  opts.Add(ListOption('shared',
+                      'libraries to build as shared libraries',
+                      'all',
+                      elems = list_of_libs))
+  ...
+  for lib in list_of_libs:
+     if lib in env['shared']:
+         env.SharedObject(...)
+     else:
+         env.Object(...)
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/ListOption.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+# Know Bug: This should behave like a Set-Type, but does not really,
+# since elements can occur twice.
+
+__all__ = ('ListOption',)
+
+import string
+import UserList
+
+import SCons.Util
+
+
+class _ListOption(UserList.UserList):
+    def __init__(self, initlist=[], allowedElems=[]):
+        UserList.UserList.__init__(self, filter(None, initlist))
+        self.allowedElems = allowedElems[:]
+        self.allowedElems.sort()
+        
+    def __cmp__(self, other):
+        raise NotImplementedError
+    def __eq__(self, other):
+        raise NotImplementedError
+    def __ge__(self, other):
+        raise NotImplementedError
+    def __gt__(self, other):
+        raise NotImplementedError
+    def __le__(self, other):
+        raise NotImplementedError
+    def __lt__(self, other):
+        raise NotImplementedError
+    def __str__(self):
+        if len(self) == 0:
+            return 'none'
+        self.data.sort()
+        if self.data == self.allowedElems:
+            return 'all'
+        else:
+            return string.join(self, ',')
+    def __repr__(self):
+        return self.__str__()
+    
+def _converter(val, allowedElems, mapdict):
+    """
+    """
+    if val == 'none':
+        val = []
+    elif val == 'all':
+        val = allowedElems
+    else:
+        val = filter(None, string.split(val, ','))
+        val = map(lambda v, m=mapdict: m.get(v, v), val)
+        notAllowed = filter(lambda v, aE=allowedElems: not v in aE, val)
+        if notAllowed:
+            raise ValueError("Invalid value(s) for option: %s" %
+                             string.join(notAllowed, ','))
+    return _ListOption(val, allowedElems)
+
+
+## def _validator(key, val, env):
+##     """
+##     """
+##     # todo: write validater for pgk list
+##     return 1
+
+
+def ListOption(key, help, default, names, map={}):
+    """
+    The input parameters describe a 'package list' option, thus they
+    are returned with the correct converter and validater appended. The
+    result is usable for input to opts.Add() .
+
+    A 'package list' option may either be 'all', 'none' or a list of
+    package names (separated by space).
+    """
+    names_str = 'allowed names: %s' % string.join(names, ' ')
+    if SCons.Util.is_List(default):
+        default = string.join(default, ',')
+    help = string.join(
+        (help, '(all|none|comma-separated list of names)', names_str),
+        '\n    ')
+    return (key, help, default,
+            None, #_validator,
+            lambda val, elems=names, m=map: _converter(val, elems, m))

Added: cs/scons/scons-local-0.96.92/SCons/Options/PackageOption.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/PackageOption.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/PackageOption.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,106 @@
+"""engine.SCons.Options.PackageOption
+
+This file defines the option type for SCons implementing 'package
+activation'.
+
+To be used whenever a 'package' may be enabled/disabled and the
+package path may be specified.
+
+Usage example:
+
+  Examples:
+      x11=no   (disables X11 support)
+      x11=yes  (will search for the package installation dir)
+      x11=/usr/local/X11 (will check this path for existance)
+
+  To replace autoconf's --with-xxx=yyy 
+
+  opts = Options()
+  opts.Add(PackageOption('x11',
+                         'use X11 installed here (yes = search some places',
+                         'yes'))
+  ...
+  if env['x11'] == True:
+      dir = ... search X11 in some standard places ...
+      env['x11'] = dir 
+  if env['x11']:
+      ... build with x11 ...
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/PackageOption.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+__all__ = ('PackageOption', 'True', 'False')
+
+import string
+
+from BoolOption import True, False
+import SCons.Errors
+
+__enable_strings  = (str(True), 'yes', 'true',  'on', 'enable', 'search')
+__disable_strings = (str(False), 'no',  'false', 'off', 'disable')
+
+def _converter(val):
+    """
+    """
+    lval = string.lower(val)
+    if lval in __enable_strings: return True
+    if lval in __disable_strings: return False
+    #raise ValueError("Invalid value for boolean option: %s" % val)
+    return val
+
+
+def _validator(key, val, env, searchfunc):
+    # NB: searchfunc is currenty undocumented and unsupported
+    """
+    """
+    # todo: write validator, check for path
+    import os
+    if env[key] == False:
+        pass
+    elif env[key] == True:
+        if searchfunc:
+            env[key] = searchfunc(key, val)
+    elif not os.path.exists(val):
+        raise SCons.Errors.UserError(
+            'Path does not exist for option %s: %s' % (key, val))
+
+
+def PackageOption(key, help, default, searchfunc=None):
+    # NB: searchfunc is currenty undocumented and unsupported
+    """
+    The input parameters describe a 'package list' option, thus they
+    are returned with the correct converter and validator appended. The
+    result is usable for input to opts.Add() .
+
+    A 'package list' option may either be 'all', 'none' or a list of
+    package names (seperated by space).
+    """
+    help = string.join(
+        (help, '( yes | no | /path/to/%s )' % key),
+        '\n    ')
+    return (key, help, default,
+            lambda k, v, e, f=searchfunc: _validator(k,v,e,f),
+            _converter)

Added: cs/scons/scons-local-0.96.92/SCons/Options/PathOption.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/PathOption.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/PathOption.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,134 @@
+"""SCons.Options.PathOption
+
+This file defines an option type for SCons implementing path settings.
+
+To be used whenever a a user-specified path override should be allowed.
+
+Arguments to PathOption are:
+  option-name  = name of this option on the command line (e.g. "prefix")
+  option-help  = help string for option
+  option-dflt  = default value for this option
+  validator    = [optional] validator for option value.  Predefined
+                 validators are:
+
+                     PathAccept -- accepts any path setting; no validation
+                     PathIsDir  -- path must be an existing directory
+                     PathIsDirCreate -- path must be a dir; will create
+                     PathIsFile -- path must be a file
+                     PathExists -- path must exist (any type) [default]
+
+                 The validator is a function that is called and which
+                 should return True or False to indicate if the path
+                 is valid.  The arguments to the validator function
+                 are: (key, val, env).  The key is the name of the
+                 option, the val is the path specified for the option,
+                 and the env is the env to which the Otions have been
+                 added.
+
+Usage example:
+
+  Examples:
+      prefix=/usr/local
+
+  opts = Options()
+
+  opts = Options()
+  opts.Add(PathOption('qtdir',
+                      'where the root of Qt is installed',
+                      qtdir, PathIsDir))
+  opts.Add(PathOption('qt_includes',
+                      'where the Qt includes are installed',
+                      '$qtdir/includes', PathIsDirCreate))
+  opts.Add(PathOption('qt_libraries',
+                      'where the Qt library is installed',
+                      '$qtdir/lib'))
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/PathOption.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+
+import SCons.Errors
+
+class _PathOptionClass:
+
+    def PathAccept(self, key, val, env):
+        """Accepts any path, no checking done."""
+        pass
+    
+    def PathIsDir(self, key, val, env):
+        """Validator to check if Path is a directory."""
+        if not os.path.isdir(val):
+            if os.path.isfile(val):
+                m = 'Directory path for option %s is a file: %s'
+            else:
+                m = 'Directory path for option %s does not exist: %s'
+            raise SCons.Errors.UserError(m % (key, val))
+
+    def PathIsDirCreate(self, key, val, env):
+        """Validator to check if Path is a directory,
+           creating it if it does not exist."""
+        if os.path.isfile(val):
+            m = 'Path for option %s is a file, not a directory: %s'
+            raise SCons.Errors.UserError(m % (key, val))
+        if not os.path.isdir(val):
+            os.makedirs(val)
+
+    def PathIsFile(self, key, val, env):
+        """validator to check if Path is a file"""
+        if not os.path.isfile(val):
+            if os.path.isdir(val):
+                m = 'File path for option %s is a directory: %s'
+            else:
+                m = 'File path for option %s does not exist: %s'
+            raise SCons.Errors.UserError(m % (key, val))
+
+    def PathExists(self, key, val, env):
+        """validator to check if Path exists"""
+        if not os.path.exists(val):
+            m = 'Path for option %s does not exist: %s'
+            raise SCons.Errors.UserError(m % (key, val))
+
+    def __call__(self, key, help, default, validator=None):
+        # NB: searchfunc is currenty undocumented and unsupported
+        """
+        The input parameters describe a 'path list' option, thus they
+        are returned with the correct converter and validator appended. The
+        result is usable for input to opts.Add() .
+
+        The 'default' option specifies the default path to use if the
+        user does not specify an override with this option.
+
+        validator is a validator, see this file for examples
+        """
+        if validator is None:
+            validator = self.PathExists
+        return (key, '%s ( /path/to/%s )' % (help, key), default,
+                validator, None)
+
+PathOption = _PathOptionClass()

Added: cs/scons/scons-local-0.96.92/SCons/Options/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Options/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Options/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,244 @@
+"""engine.SCons.Options
+
+This file defines the Options class that is used to add user-friendly
+customizable variables to an SCons build.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Options/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import string
+
+import SCons.Errors
+import SCons.Util
+import SCons.Warnings
+
+from BoolOption import BoolOption, True, False  # okay
+from EnumOption import EnumOption  # okay
+from ListOption import ListOption  # naja
+from PackageOption import PackageOption # naja
+from PathOption import PathOption # okay
+
+
+class Options:
+    """
+    Holds all the options, updates the environment with the variables,
+    and renders the help text.
+    """
+    def __init__(self, files=None, args={}):
+        """
+        files - [optional] List of option configuration files to load
+            (backward compatibility) If a single string is passed it is 
+                                     automatically placed in a file list
+        """
+
+        self.options = []
+        self.args = args
+        self.files = None
+        if SCons.Util.is_String(files):
+           self.files = [ files ]
+        elif files:
+           self.files = files
+
+    def _do_add(self, key, help="", default=None, validator=None, converter=None):
+        class Option:
+            pass
+
+        option = Option()
+        option.key = key
+        option.help = help
+        option.default = default
+        option.validator = validator
+        option.converter = converter
+
+        self.options.append(option)
+
+
+    def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
+        """
+        Add an option.
+
+        key - the name of the variable, or a list or tuple of arguments
+        help - optional help text for the options
+        default - optional default value
+        validator - optional function that is called to validate the option's value
+                    Called with (key, value, environment)
+        converter - optional function that is called to convert the option's value before
+                    putting it in the environment.
+        """
+
+        if SCons.Util.is_List(key) or type(key) == type(()):
+            apply(self._do_add, key)
+            return
+
+        if not SCons.Util.is_String(key) or \
+           not SCons.Util.is_valid_construction_var(key):
+            raise SCons.Errors.UserError, "Illegal Options.Add() key `%s'" % str(key)
+
+        self._do_add(key, help, default, validator, converter)
+
+
+    def AddOptions(self, *optlist):
+        """
+        Add a list of options.
+
+        Each list element is a tuple/list of arguments to be passed on
+        to the underlying method for adding options.
+        
+        Example:
+          opt.AddOptions(
+            ('debug', '', 0),
+            ('CC', 'The C compiler'),
+            ('VALIDATE', 'An option for testing validation', 'notset',
+             validator, None),
+            )
+        """
+        for o in optlist:
+            apply(self._do_add, o)
+
+
+    def Update(self, env, args=None):
+        """
+        Update an environment with the option variables.
+
+        env - the environment to update.
+        """
+
+        values = {}
+
+        # first set the defaults:
+        for option in self.options:
+            if not option.default is None:
+                values[option.key] = option.default
+
+        # next set the value specified in the options file
+        if self.files:
+           for filename in self.files:
+              if os.path.exists(filename):
+                 execfile(filename, values)
+
+        # finally set the values specified on the command line
+        if args is None:
+            args = self.args
+        values.update(args)
+
+        # put the variables in the environment:
+        # (don't copy over variables that are not declared
+        #  as options)
+        for option in self.options:
+            try:
+                env[option.key] = values[option.key]
+            except KeyError:
+                pass
+
+        # Call the convert functions:
+        for option in self.options:
+            if option.converter and values.has_key(option.key):
+                value = env.subst('${%s}'%option.key)
+                try:
+                    env[option.key] = option.converter(value)
+                except ValueError, x:
+                    raise SCons.Errors.UserError, 'Error converting option: %s\n%s'%(option.key, x)
+
+
+        # Finally validate the values:
+        for option in self.options:
+            if option.validator and values.has_key(option.key):
+                option.validator(option.key, env.subst('${%s}'%option.key), env)
+
+    def Save(self, filename, env):
+        """
+        Saves all the options in the given file.  This file can
+        then be used to load the options next run.  This can be used
+        to create an option cache file.
+
+        filename - Name of the file to save into
+        env - the environment get the option values from
+        """
+
+        # Create the file and write out the header
+        try:
+            fh = open(filename, 'w')
+
+            try:
+                # Make an assignment in the file for each option within the environment
+                # that was assigned a value other than the default.
+                for option in self.options:
+                    try:
+                        value = env[option.key]
+                        try:
+                            eval(repr(value))
+                        except KeyboardInterrupt:
+                            raise
+                        except:
+                            # Convert stuff that has a repr() that
+                            # cannot be evaluated into a string
+                            value = SCons.Util.to_String(value)
+                        
+                        defaultVal = env.subst(SCons.Util.to_String(option.default))
+                        if option.converter:
+                            defaultVal = option.converter(defaultVal)
+
+                        if str(env.subst('${%s}' % option.key)) != str(defaultVal):
+                            fh.write('%s = %s\n' % (option.key, repr(value)))
+                    except KeyError:
+                        pass
+            finally:
+                fh.close()
+
+        except IOError, x:
+            raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
+
+    def GenerateHelpText(self, env, sort=None):
+        """
+        Generate the help text for the options.
+
+        env - an environment that is used to get the current values
+              of the options.
+        """
+
+        help_text = ""
+
+        if sort:
+            options = self.options[:]
+            options.sort(lambda x,y,func=sort: func(x.key,y.key))
+        else:
+            options = self.options
+
+        def format(opt, self=self, env=env):
+            if env.has_key(opt.key):
+                actual = env.subst('${%s}' % opt.key)
+            else:
+                actual = None
+            return self.FormatOptionHelpText(env, opt.key, opt.help, opt.default, actual)
+        lines = filter(None, map(format, options))
+
+        return string.join(lines, '')
+
+    format = '\n%s: %s\n    default: %s\n    actual: %s\n'
+
+    def FormatOptionHelpText(self, env, key, help, default, actual):
+        return self.format % (key, help, default, actual)

Added: cs/scons/scons-local-0.96.92/SCons/Platform/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,209 @@
+"""SCons.Platform
+
+SCons platform selection.
+
+This looks for modules that define a callable object that can modify a
+construction environment as appropriate for a given platform.
+
+Note that we take a more simplistic view of "platform" than Python does.
+We're looking for a single string that determines a set of
+tool-independent variables with which to initialize a construction
+environment.  Consequently, we'll examine both sys.platform and os.name
+(and anything else that might come in to play) in order to return some
+specification which is unique enough for our purposes.
+
+Note that because this subsysem just *selects* a callable that can
+modify a construction environment, it's possible for people to define
+their own "platform specification" in an arbitrary callable function.
+No one needs to use or tie in to this subsystem in order to roll
+their own platform definition.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+# 
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import imp
+import os
+import string
+import sys
+import tempfile
+
+import SCons.Errors
+import SCons.Tool
+
+def platform_default():
+    """Return the platform string for our execution environment.
+
+    The returned value should map to one of the SCons/Platform/*.py
+    files.  Since we're architecture independent, though, we don't
+    care about the machine architecture.
+    """
+    osname = os.name
+    if osname == 'java':
+        osname = os._osType
+    if osname == 'posix':
+        if sys.platform == 'cygwin':
+            return 'cygwin'
+        elif string.find(sys.platform, 'irix') != -1:
+            return 'irix'
+        elif string.find(sys.platform, 'sunos') != -1:
+            return 'sunos'
+        elif string.find(sys.platform, 'hp-ux') != -1:
+            return 'hpux'
+        elif string.find(sys.platform, 'aix') != -1:
+            return 'aix'
+        elif string.find(sys.platform, 'darwin') != -1:
+            return 'darwin'
+        else:
+            return 'posix'
+    elif os.name == 'os2':
+        return 'os2'
+    else:
+        return sys.platform
+
+def platform_module(name = platform_default()):
+    """Return the imported module for the platform.
+
+    This looks for a module name that matches the specified argument.
+    If the name is unspecified, we fetch the appropriate default for
+    our execution environment.
+    """
+    full_name = 'SCons.Platform.' + name
+    if not sys.modules.has_key(full_name):
+        if os.name == 'java':
+            eval(full_name)
+        else:
+            try:
+                file, path, desc = imp.find_module(name,
+                                        sys.modules['SCons.Platform'].__path__)
+                mod = imp.load_module(full_name, file, path, desc)
+                setattr(SCons.Platform, name, mod)
+            except ImportError:
+                raise SCons.Errors.UserError, "No platform named '%s'" % name
+            if file:
+                file.close()
+    return sys.modules[full_name]
+
+def DefaultToolList(platform, env):
+    """Select a default tool list for the specified platform.
+    """
+    return SCons.Tool.tool_list(platform, env)
+
+class PlatformSpec:
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return self.name
+        
+class TempFileMunge:
+    """A callable class.  You can set an Environment variable to this,
+    then call it with a string argument, then it will perform temporary
+    file substitution on it.  This is used to circumvent the long command
+    line limitation.
+
+    Example usage:
+    env["TEMPFILE"] = TempFileMunge
+    env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}"
+
+    By default, the name of the temporary file used begins with a
+    prefix of '@'.  This may be configred for other tool chains by
+    setting '$TEMPFILEPREFIX'.
+
+    env["TEMPFILEPREFIX"] = '-@'        # diab compiler
+    env["TEMPFILEPREFIX"] = '-via'      # arm tool chain
+    """
+    def __init__(self, cmd):
+        self.cmd = cmd
+
+    def __call__(self, target, source, env, for_signature):
+        if for_signature:
+            return self.cmd
+        cmd = env.subst_list(self.cmd, 0, target, source)[0]
+        try:
+            maxline = int(env.subst('$MAXLINELENGTH'))
+        except ValueError:
+            maxline = 2048
+
+        if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
+            return self.cmd
+
+        # We do a normpath because mktemp() has what appears to be
+        # a bug in Windows that will use a forward slash as a path
+        # delimiter.  Windows's link mistakes that for a command line
+        # switch and barfs.
+        #
+        # We use the .lnk suffix for the benefit of the Phar Lap
+        # linkloc linker, which likes to append an .lnk suffix if
+        # none is given.
+        tmp = os.path.normpath(tempfile.mktemp('.lnk'))
+        native_tmp = SCons.Util.get_native_path(tmp)
+
+        if env['SHELL'] and env['SHELL'] == 'sh':
+            # The sh shell will try to escape the backslashes in the
+            # path, so unescape them.
+            native_tmp = string.replace(native_tmp, '\\', r'\\\\')
+            # In Cygwin, we want to use rm to delete the temporary
+            # file, because del does not exist in the sh shell.
+            rm = env.Detect('rm') or 'del'
+        else:
+            # Don't use 'rm' if the shell is not sh, because rm won't
+            # work with the Windows shells (cmd.exe or command.com) or
+            # Windows path names.
+            rm = 'del'
+
+        prefix = env.subst('$TEMPFILEPREFIX')
+        if not prefix:
+            prefix = '@'
+
+        args = map(SCons.Subst.quote_spaces, cmd[1:])
+        open(tmp, 'w').write(string.join(args, " ") + "\n")
+        # XXX Using the SCons.Action.print_actions value directly
+        # like this is bogus, but expedient.  This class should
+        # really be rewritten as an Action that defines the
+        # __call__() and strfunction() methods and lets the
+        # normal action-execution logic handle whether or not to
+        # print/execute the action.  The problem, though, is all
+        # of that is decided before we execute this method as
+        # part of expanding the $TEMPFILE construction variable.
+        # Consequently, refactoring this will have to wait until
+        # we get more flexible with allowing Actions to exist
+        # independently and get strung together arbitrarily like
+        # Ant tasks.  In the meantime, it's going to be more
+        # user-friendly to not let obsession with architectural
+        # purity get in the way of just being helpful, so we'll
+        # reach into SCons.Action directly.
+        if SCons.Action.print_actions:
+            print("Using tempfile "+native_tmp+" for command line:\n"+
+                  str(cmd[0]) + " " + string.join(args," "))
+        return [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ]
+    
+def Platform(name = platform_default()):
+    """Select a canned Platform specification.
+    """
+    module = platform_module(name)
+    spec = PlatformSpec(name)
+    spec.__call__ = module.generate
+    return spec

Added: cs/scons/scons-local-0.96.92/SCons/Platform/aix.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/aix.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/aix.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,65 @@
+"""engine.SCons.Platform.aix
+
+Platform-specific initialization for IBM AIX systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/aix.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import string
+
+import posix
+
+def get_xlc(env, xlc=None, xlc_r=None, packages=[]):
+    # Use the AIX package installer tool lslpp to figure out where a
+    # given xl* compiler is installed and what version it is.
+    xlcPath = None
+    xlcVersion = None
+
+    if xlc is None:
+        xlc = env.get('CC', 'xlc')
+    if xlc_r is None:
+        xlc_r = xlc + '_r'
+    for package in packages:
+        cmd = "lslpp -fc " + package + " 2>/dev/null | egrep '" + xlc + "([^-_a-zA-Z0-9].*)?$'"
+        line = os.popen(cmd).readline()
+        if line:
+            v, p = string.split(line, ':')[1:3]
+            xlcVersion = string.split(v)[1]
+            xlcPath = string.split(p)[0]
+            xlcPath = xlcPath[:xlcPath.rindex('/')]
+            break
+    return (xlcPath, xlc, xlc_r, xlcVersion)
+
+def generate(env):
+    posix.generate(env)
+    #Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion
+    env['MAXLINELENGTH']  = 21576
+

Added: cs/scons/scons-local-0.96.92/SCons/Platform/cygwin.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/cygwin.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/cygwin.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,49 @@
+"""SCons.Platform.cygwin
+
+Platform-specific initialization for Cygwin systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/cygwin.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import posix
+from SCons.Platform import TempFileMunge
+
+def generate(env):
+    posix.generate(env)
+
+    env['PROGPREFIX']  = ''
+    env['PROGSUFFIX']  = '.exe'
+    env['SHLIBPREFIX'] = ''
+    env['SHLIBSUFFIX'] = '.dll'
+    env['LIBPREFIXES'] = [ '$LIBPREFIX', '$SHLIBPREFIX' ]
+    env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
+    env['TEMPFILE']    = TempFileMunge
+    env['TEMPFILEPREFIX'] = '@'
+    env['MAXLINELENGTH']  = 2048

Added: cs/scons/scons-local-0.96.92/SCons/Platform/darwin.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/darwin.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/darwin.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,41 @@
+"""engine.SCons.Platform.darwin
+
+Platform-specific initialization for Mac OS X systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/darwin.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import posix
+import os
+
+def generate(env):
+    posix.generate(env)
+    env['SHLIBSUFFIX'] = '.dylib'
+    env['ENV']['PATH'] = env['ENV']['PATH'] + ':/sw/bin'

Added: cs/scons/scons-local-0.96.92/SCons/Platform/hpux.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/hpux.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/hpux.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,40 @@
+"""engine.SCons.Platform.hpux
+
+Platform-specific initialization for HP-UX systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/hpux.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import posix
+
+def generate(env):
+    posix.generate(env)
+    #Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion
+    env['MAXLINELENGTH']  = 2045000

Added: cs/scons/scons-local-0.96.92/SCons/Platform/irix.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/irix.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/irix.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,38 @@
+"""SCons.Platform.irix
+
+Platform-specific initialization for SGI IRIX systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/irix.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import posix
+
+def generate(env):
+    posix.generate(env)

Added: cs/scons/scons-local-0.96.92/SCons/Platform/os2.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/os2.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/os2.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,49 @@
+"""SCons.Platform.os2
+
+Platform-specific initialization for OS/2 systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/os2.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+def generate(env):
+    if not env.has_key('ENV'):
+        env['ENV']        = {}
+    env['OBJPREFIX']      = ''
+    env['OBJSUFFIX']      = '.obj'
+    env['SHOBJPREFIX']    = '$OBJPREFIX'
+    env['SHOBJSUFFIX']    = '$OBJSUFFIX'
+    env['PROGPREFIX']     = ''
+    env['PROGSUFFIX']     = '.exe'
+    env['LIBPREFIX']      = ''
+    env['LIBSUFFIX']      = '.lib'
+    env['SHLIBPREFIX']    = ''
+    env['SHLIBSUFFIX']    = '.dll'
+    env['LIBPREFIXES']    = '$LIBPREFIX'
+    env['LIBSUFFIXES']    = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]

Added: cs/scons/scons-local-0.96.92/SCons/Platform/posix.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/posix.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/posix.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,251 @@
+"""SCons.Platform.posix
+
+Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/posix.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import popen2
+import string
+import sys
+import select
+
+import SCons.Util
+from SCons.Platform import TempFileMunge
+
+exitvalmap = {
+    2 : 127,
+    13 : 126,
+}
+
+def escape(arg):
+    "escape shell special characters"
+    slash = '\\'
+    special = '"$'
+
+    arg = string.replace(arg, slash, slash+slash)
+    for c in special:
+        arg = string.replace(arg, c, slash+c)
+
+    return '"' + arg + '"'
+
+def exec_system(l, env):
+    stat = os.system(string.join(l))
+    if stat & 0xff:
+        return stat | 0x80
+    return stat >> 8
+
+def exec_spawnvpe(l, env):
+    stat = os.spawnvpe(os.P_WAIT, l[0], l, env)
+    # os.spawnvpe() returns the actual exit code, not the encoding
+    # returned by os.waitpid() or os.system().
+    return stat
+
+def exec_fork(l, env):
+    pid = os.fork()
+    if not pid:
+        # Child process.
+        exitval = 127
+        try:
+            os.execvpe(l[0], l, env)
+        except OSError, e:
+            exitval = exitvalmap[e[0]]
+            sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
+        os._exit(exitval)
+    else:
+        # Parent process.
+        pid, stat = os.waitpid(pid, 0)
+        if stat & 0xff:
+            return stat | 0x80
+        return stat >> 8
+
+def _get_env_command(sh, escape, cmd, args, env):
+    s = string.join(args)
+    if env:
+        l = ['env', '-'] + \
+            map(lambda t, e=escape: t[0]+'='+e(t[1]), env.items()) + \
+            [sh, '-c', escape(s)]
+        s = string.join(l)
+    return s
+
+def env_spawn(sh, escape, cmd, args, env):
+    return exec_system([_get_env_command( sh, escape, cmd, args, env)], env)
+
+def spawnvpe_spawn(sh, escape, cmd, args, env):
+    return exec_spawnvpe([sh, '-c', string.join(args)], env)
+
+def fork_spawn(sh, escape, cmd, args, env):
+    return exec_fork([sh, '-c', string.join(args)], env)
+
+def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr):
+    stdout_eof = stderr_eof = 0
+    while not (stdout_eof and stderr_eof):
+        (i,o,e) = select.select([cmd_stdout, cmd_stderr], [], [])
+        if cmd_stdout in i:
+            str = cmd_stdout.read()
+            if len(str) == 0:
+                stdout_eof = 1
+            elif stdout != None:
+                stdout.write(str)
+        if cmd_stderr in i:
+            str = cmd_stderr.read()
+            if len(str) == 0:
+                #sys.__stderr__.write( "stderr_eof=1\n" )
+                stderr_eof = 1
+            else:
+                #sys.__stderr__.write( "str(stderr) = %s\n" % str )
+                stderr.write(str)
+
+def exec_popen3(l, env, stdout, stderr):
+    proc = popen2.Popen3(string.join(l), 1)
+    process_cmd_output(proc.fromchild, proc.childerr, stdout, stderr)
+    stat = proc.wait()
+    if stat & 0xff:
+        return stat | 0x80
+    return stat >> 8
+
+def exec_piped_fork(l, env, stdout, stderr):
+    # spawn using fork / exec and providing a pipe for the command's
+    # stdout / stderr stream
+    if stdout != stderr:
+        (rFdOut, wFdOut) = os.pipe()
+        (rFdErr, wFdErr) = os.pipe()
+    else:
+        (rFdOut, wFdOut) = os.pipe()
+        rFdErr = rFdOut
+        wFdErr = wFdOut
+    # do the fork
+    pid = os.fork()
+    if not pid:
+        # Child process
+        os.close( rFdOut )
+        if rFdOut != rFdErr:
+            os.close( rFdErr )
+        os.dup2( wFdOut, 1 ) # is there some symbolic way to do that ?
+        os.dup2( wFdErr, 2 )
+        os.close( wFdOut )
+        if stdout != stderr:
+            os.close( wFdErr )
+        exitval = 127
+        try:
+            os.execvpe(l[0], l, env)
+        except OSError, e:
+            exitval = exitvalmap[e[0]]
+            stderr.write("scons: %s: %s\n" % (l[0], e[1]))
+        os._exit(exitval)
+    else:
+        # Parent process
+        pid, stat = os.waitpid(pid, 0)
+        os.close( wFdOut )
+        if stdout != stderr:
+            os.close( wFdErr )
+        childOut = os.fdopen( rFdOut )
+        if stdout != stderr:
+            childErr = os.fdopen( rFdErr )
+        else:
+            childErr = childOut
+        process_cmd_output(childOut, childErr, stdout, stderr)
+        os.close( rFdOut )
+        if stdout != stderr:
+            os.close( rFdErr )
+        if stat & 0xff:
+            return stat | 0x80
+        return stat >> 8
+
+def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr):
+    # spawn using Popen3 combined with the env command
+    # the command name and the command's stdout is written to stdout
+    # the command's stderr is written to stderr
+    return exec_popen3([_get_env_command(sh, escape, cmd, args, env)],
+                       env, stdout, stderr)
+
+def piped_fork_spawn(sh, escape, cmd, args, env, stdout, stderr):
+    # spawn using fork / exec and providing a pipe for the command's
+    # stdout / stderr stream
+    return exec_piped_fork([sh, '-c', string.join(args)],
+                           env, stdout, stderr)
+
+
+
+def generate(env):
+    # If os.spawnvpe() exists, we use it to spawn commands.  Otherwise
+    # if the env utility exists, we use os.system() to spawn commands,
+    # finally we fall back on os.fork()/os.exec().  
+    #
+    # os.spawnvpe() is prefered because it is the most efficient.  But
+    # for Python versions without it, os.system() is prefered because it
+    # is claimed that it works better with threads (i.e. -j) and is more
+    # efficient than forking Python.
+    #
+    # NB: Other people on the scons-users mailing list have claimed that
+    # os.fork()/os.exec() works better than os.system().  There may just
+    # not be a default that works best for all users.
+
+    if os.__dict__.has_key('spawnvpe'):
+        spawn = spawnvpe_spawn
+    elif env.Detect('env'):
+        spawn = env_spawn
+    else:
+        spawn = fork_spawn
+
+    if env.Detect('env'):
+        pspawn = piped_env_spawn
+    else:
+        pspawn = piped_fork_spawn
+
+    if not env.has_key('ENV'):
+        env['ENV']        = {}
+    env['ENV']['PATH']    = '/usr/local/bin:/opt/bin:/bin:/usr/bin'
+    env['OBJPREFIX']      = ''
+    env['OBJSUFFIX']      = '.o'
+    env['SHOBJPREFIX']    = '$OBJPREFIX'
+    env['SHOBJSUFFIX']    = '$OBJSUFFIX'
+    env['PROGPREFIX']     = ''
+    env['PROGSUFFIX']     = ''
+    env['LIBPREFIX']      = 'lib'
+    env['LIBSUFFIX']      = '.a'
+    env['SHLIBPREFIX']    = '$LIBPREFIX'
+    env['SHLIBSUFFIX']    = '.so'
+    env['LIBPREFIXES']    = '$LIBPREFIX'
+    env['LIBSUFFIXES']    = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ]
+    env['PSPAWN']         = pspawn
+    env['SPAWN']          = spawn
+    env['SHELL']          = 'sh'
+    env['ESCAPE']         = escape
+    env['TEMPFILE']       = TempFileMunge
+    env['TEMPFILEPREFIX'] = '@'
+    #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion
+    #Note: specific platforms might rise or lower this value
+    env['MAXLINELENGTH']  = 128072
+
+    # This platform supports RPATH specifications.
+    env['__RPATH'] = '$_RPATH'

Added: cs/scons/scons-local-0.96.92/SCons/Platform/sunos.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/sunos.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/sunos.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,44 @@
+"""engine.SCons.Platform.sunos
+
+Platform-specific initialization for Sun systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/sunos.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import posix
+
+def generate(env):
+    posix.generate(env)
+    # Based on sunSparc 8:32bit
+    # ARG_MAX=1048320 - 3000 for environment expansion
+    env['MAXLINELENGTH']  = 1045320
+    env['PKGINFO'] = 'pkginfo'
+    env['PKGCHK'] = '/usr/sbin/pkgchk'
+    env['ENV']['PATH'] = env['ENV']['PATH'] + ':/usr/ccs/bin'

Added: cs/scons/scons-local-0.96.92/SCons/Platform/win32.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Platform/win32.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Platform/win32.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,264 @@
+"""SCons.Platform.win32
+
+Platform-specific initialization for Win32 systems.
+
+There normally shouldn't be any need to import this module directly.  It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Platform/win32.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import string
+import sys
+import tempfile
+
+from SCons.Platform.posix import exitvalmap
+from SCons.Platform import TempFileMunge
+
+# XXX See note below about why importing SCons.Action should be
+# eventually refactored.
+import SCons.Action
+import SCons.Util
+
+
+# The upshot of all this is that, if you are using Python 1.5.2,
+# you had better have cmd or command.com in your PATH when you run
+# scons.
+
+def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
+    # There is no direct way to do that in python. What we do
+    # here should work for most cases:
+    #   In case stdout (stderr) is not redirected to a file,
+    #   we redirect it into a temporary file tmpFileStdout
+    #   (tmpFileStderr) and copy the contents of this file
+    #   to stdout (stderr) given in the argument
+    if not sh:
+        sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
+        return 127
+    else:
+        # one temporary file for stdout and stderr
+        tmpFileStdout = os.path.normpath(tempfile.mktemp())
+        tmpFileStderr = os.path.normpath(tempfile.mktemp())
+
+        # check if output is redirected
+        stdoutRedirected = 0
+        stderrRedirected = 0
+        for arg in args:
+            # are there more possibilities to redirect stdout ?
+            if (string.find( arg, ">", 0, 1 ) != -1 or
+                string.find( arg, "1>", 0, 2 ) != -1):
+                stdoutRedirected = 1
+            # are there more possibilities to redirect stderr ?
+            if string.find( arg, "2>", 0, 2 ) != -1:
+                stderrRedirected = 1
+
+        # redirect output of non-redirected streams to our tempfiles
+        if stdoutRedirected == 0:
+            args.append(">" + str(tmpFileStdout))
+        if stderrRedirected == 0:
+            args.append("2>" + str(tmpFileStderr))
+
+        # actually do the spawn
+        try:
+            args = [sh, '/C', escape(string.join(args)) ]
+            ret = os.spawnve(os.P_WAIT, sh, args, env)
+        except OSError, e:
+            # catch any error
+            ret = exitvalmap[e[0]]
+            if stderr != None:
+                stderr.write("scons: %s: %s\n" % (cmd, e[1]))
+        # copy child output from tempfiles to our streams
+        # and do clean up stuff
+        if stdout != None and stdoutRedirected == 0:
+            try:
+                stdout.write(open( tmpFileStdout, "r" ).read())
+                os.remove( tmpFileStdout )
+            except (IOError, OSError):
+                pass
+
+        if stderr != None and stderrRedirected == 0:
+            try:
+                stderr.write(open( tmpFileStderr, "r" ).read())
+                os.remove( tmpFileStderr )
+            except (IOError, OSError):
+                pass
+        return ret
+
+def exec_spawn(l, env):
+    try:
+        result = os.spawnve(os.P_WAIT, l[0], l, env)
+    except OSError, e:
+        result = exitvalmap[e[0]]
+        sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
+    return result
+
+def spawn(sh, escape, cmd, args, env):
+    if not sh:
+        sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
+        return 127
+    return exec_spawn([sh, '/C', escape(string.join(args))], env)
+
+# Windows does not allow special characters in file names anyway, so
+# no need for a complex escape function, we will just quote the arg.
+escape = lambda x: '"' + x + '"'
+
+# Get the windows system directory name
+def get_system_root():
+    # A resonable default if we can't read the registry
+    try:
+        val = os.environ['SYSTEMROOT']
+    except KeyError:
+        val = "C:/WINDOWS"
+        pass
+
+    # First see if we can look in the registry...
+    if SCons.Util.can_read_reg:
+        try:
+            # Look for Windows NT system root
+            k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                      'Software\\Microsoft\\Windows NT\\CurrentVersion')
+            val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
+        except SCons.Util.RegError:
+            try:
+                # Okay, try the Windows 9x system root
+                k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                          'Software\\Microsoft\\Windows\\CurrentVersion')
+                val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
+            except KeyboardInterrupt:
+                raise
+            except:
+                pass
+    return val
+
+# Get the location of the program files directory
+def get_program_files_dir():
+    # Now see if we can look in the registry...
+    val = ''
+    if SCons.Util.can_read_reg:
+        try:
+            # Look for Windows Program Files directory
+            k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                      'Software\\Microsoft\\Windows\\CurrentVersion')
+            val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir')
+        except SCons.Util.RegError:
+            val = ''
+            pass
+
+    if val == '':
+        # A reasonable default if we can't read the registry
+        # (Actually, it's pretty reasonable even if we can :-)
+        val = os.path.join(os.path.dirname(get_system_root()),"Program Files")
+        
+    return val
+
+def generate(env):
+    # Attempt to find cmd.exe (for WinNT/2k/XP) or
+    # command.com for Win9x
+    cmd_interp = ''
+    # First see if we can look in the registry...
+    if SCons.Util.can_read_reg:
+        try:
+            # Look for Windows NT system root
+            k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                          'Software\\Microsoft\\Windows NT\\CurrentVersion')
+            val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
+            cmd_interp = os.path.join(val, 'System32\\cmd.exe')
+        except SCons.Util.RegError:
+            try:
+                # Okay, try the Windows 9x system root
+                k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                              'Software\\Microsoft\\Windows\\CurrentVersion')
+                val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
+                cmd_interp = os.path.join(val, 'command.com')
+            except KeyboardInterrupt:
+                raise
+            except:
+                pass
+
+    # For the special case of not having access to the registry, we
+    # use a temporary path and pathext to attempt to find the command
+    # interpreter.  If we fail, we try to find the interpreter through
+    # the env's PATH.  The problem with that is that it might not
+    # contain an ENV and a PATH.
+    if not cmd_interp:
+        systemroot = r'C:\Windows'
+        if os.environ.has_key('SYSTEMROOT'):
+            systemroot = os.environ['SYSTEMROOT']
+        tmp_path = systemroot + os.pathsep + \
+                   os.path.join(systemroot,'System32')
+        tmp_pathext = '.com;.exe;.bat;.cmd'
+        if os.environ.has_key('PATHEXT'):
+            tmp_pathext = os.environ['PATHEXT'] 
+        cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext)
+        if not cmd_interp:
+            cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext)
+
+    if not cmd_interp:
+        cmd_interp = env.Detect('cmd')
+        if not cmd_interp:
+            cmd_interp = env.Detect('command')
+
+    
+    if not env.has_key('ENV'):
+        env['ENV']        = {}
+
+    # Import things from the external environment to the construction
+    # environment's ENV.  This is a potential slippery slope, because we
+    # *don't* want to make builds dependent on the user's environment by
+    # default.  We're doing this for SYSTEMROOT, though, because it's
+    # needed for anything that uses sockets, and seldom changes, and
+    # for SYSTEMDRIVE because it's related.
+    #
+    # Weigh the impact carefully before adding other variables to this list.
+    import_env = [ 'SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'TMP' ]
+    for var in import_env:
+        v = os.environ.get(var)
+        if v:
+            env['ENV'][var] = v
+
+    env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
+    env['OBJPREFIX']      = ''
+    env['OBJSUFFIX']      = '.obj'
+    env['SHOBJPREFIX']    = '$OBJPREFIX'
+    env['SHOBJSUFFIX']    = '$OBJSUFFIX'
+    env['PROGPREFIX']     = ''
+    env['PROGSUFFIX']     = '.exe'
+    env['LIBPREFIX']      = ''
+    env['LIBSUFFIX']      = '.lib'
+    env['SHLIBPREFIX']    = ''
+    env['SHLIBSUFFIX']    = '.dll'
+    env['LIBPREFIXES']    = [ '$LIBPREFIX' ]
+    env['LIBSUFFIXES']    = [ '$LIBSUFFIX' ]
+    env['PSPAWN']         = piped_spawn
+    env['SPAWN']          = spawn
+    env['SHELL']          = cmd_interp
+    env['TEMPFILE']       = TempFileMunge
+    env['TEMPFILEPREFIX'] = '@'
+    env['MAXLINELENGTH']  = 2048
+    env['ESCAPE']         = escape

Added: cs/scons/scons-local-0.96.92/SCons/SConf.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/SConf.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/SConf.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,874 @@
+"""SCons.SConf
+
+Autoconf-like configuration support.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/SConf.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import re
+import string
+import StringIO
+import sys
+import traceback
+import types
+
+import SCons.Action
+import SCons.Builder
+import SCons.Errors
+import SCons.Node.FS
+import SCons.Taskmaster
+import SCons.Util
+import SCons.Warnings
+import SCons.Conftest
+
+# Turn off the Conftest error logging
+SCons.Conftest.LogInputFiles = 0
+SCons.Conftest.LogErrorMessages = 0
+
+# to be set, if we are in dry-run mode
+dryrun = 0
+
+AUTO=0  # use SCons dependency scanning for up-to-date checks
+FORCE=1 # force all tests to be rebuilt
+CACHE=2 # force all tests to be taken from cache (raise an error, if necessary)
+cache_mode = AUTO
+
+def SetCacheMode(mode):
+    """Set the Configure cache mode. mode must be one of "auto", "force",
+    or "cache"."""
+    global cache_mode
+    if mode == "auto":
+        cache_mode = AUTO
+    elif mode == "force":
+        cache_mode = FORCE
+    elif mode == "cache":
+        cache_mode = CACHE
+    else:
+        raise ValueError, "SCons.SConf.SetCacheMode: Unknown mode " + mode
+
+progress_display = SCons.Util.display # will be overwritten by SCons.Script
+def SetProgressDisplay(display):
+    """Set the progress display to use (called from SCons.Script)"""
+    global progress_display
+    progress_display = display
+
+SConfFS = None
+
+_ac_build_counter = 0 # incremented, whenever TryBuild is called
+_ac_config_logs = {}  # all config.log files created in this build
+_ac_config_hs   = {}  # all config.h files created in this build
+sconf_global = None   # current sconf object
+
+def _createConfigH(target, source, env):
+    t = open(str(target[0]), "w")
+    defname = re.sub('[^A-Za-z0-9_]', '_', string.upper(str(target[0])))
+    t.write("""#ifndef %(DEFNAME)s_SEEN
+#define %(DEFNAME)s_SEEN
+
+""" % {'DEFNAME' : defname})
+    t.write(source[0].get_contents())
+    t.write("""
+#endif /* %(DEFNAME)s_SEEN */
+""" % {'DEFNAME' : defname})
+    t.close()
+
+def _stringConfigH(target, source, env):
+    return "scons: Configure: creating " + str(target[0])
+
+def CreateConfigHBuilder(env):
+    """Called just before the building targets phase begins."""
+    if len(_ac_config_hs) == 0:
+        return
+    action = SCons.Action.Action(_createConfigH,
+                                 _stringConfigH)
+    sconfigHBld = SCons.Builder.Builder(action=action)
+    env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} )
+    for k in _ac_config_hs.keys():
+        env.SConfigHBuilder(k, env.Value(_ac_config_hs[k]))
+    
+class SConfWarning(SCons.Warnings.Warning):
+    pass
+SCons.Warnings.enableWarningClass(SConfWarning)
+
+# some error definitions
+class SConfError(SCons.Errors.UserError):
+    def __init__(self,msg):
+        SCons.Errors.UserError.__init__(self,msg)
+
+class ConfigureDryRunError(SConfError):
+    """Raised when a file or directory needs to be updated during a Configure
+    process, but the user requested a dry-run"""
+    def __init__(self,target):
+        if not isinstance(target, SCons.Node.FS.File):
+            msg = 'Cannot create configure directory "%s" within a dry-run.' % str(target)
+        else:
+            msg = 'Cannot update configure test "%s" within a dry-run.' % str(target)
+        SConfError.__init__(self,msg)
+
+class ConfigureCacheError(SConfError):
+    """Raised when a use explicitely requested the cache feature, but the test
+    is run the first time."""
+    def __init__(self,target):
+        SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target))
+
+# define actions for building text files
+def _createSource( target, source, env ):
+    fd = open(str(target[0]), "w")
+    fd.write(source[0].get_contents())
+    fd.close()
+def _stringSource( target, source, env ):
+    import string
+    return (str(target[0]) + ' <-\n  |' +
+            string.replace( source[0].get_contents(),
+                            '\n', "\n  |" ) )
+
+# python 2.2 introduces types.BooleanType
+BooleanTypes = [types.IntType]
+if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType)
+
+class SConfBuildInfo(SCons.Node.FS.FileBuildInfo):
+    """
+    Special build info for targets of configure tests. Additional members
+    are result (did the builder succeed last time?) and string, which
+    contains messages of the original build phase.
+    """
+    result = None # -> 0/None -> no error, != 0 error
+    string = None # the stdout / stderr output when building the target
+    
+    def __init__(self, node, result, string, sig):
+        SCons.Node.FS.FileBuildInfo.__init__(self, node)
+        self.result = result
+        self.string = string
+        self.ninfo.bsig = sig
+
+
+class Streamer:
+    """
+    'Sniffer' for a file-like writable object. Similar to the unix tool tee.
+    """
+    def __init__(self, orig):
+        self.orig = orig
+        self.s = StringIO.StringIO()
+
+    def write(self, str):
+        if self.orig:
+            self.orig.write(str)
+        self.s.write(str)
+
+    def writelines(self, lines):
+        for l in lines:
+            self.write(l + '\n')
+
+    def getvalue(self):
+        """
+        Return everything written to orig since the Streamer was created.
+        """
+        return self.s.getvalue()
+        
+
+class SConfBuildTask(SCons.Taskmaster.Task):
+    """
+    This is almost the same as SCons.Script.BuildTask. Handles SConfErrors
+    correctly and knows about the current cache_mode.
+    """
+    def display(self, message):
+        if sconf_global.logstream:
+            sconf_global.logstream.write("scons: Configure: " + message + "\n")
+
+    def display_cached_string(self, bi):
+        """
+        Logs the original builder messages, given the SConfBuildInfo instance
+        bi.
+        """
+        if not isinstance(bi, SConfBuildInfo):
+            SCons.Warnings.warn(SConfWarning,
+              "The stored build information has an unexpected class.")
+        else:
+            self.display("The original builder output was:\n" +
+                         string.replace("  |" + str(bi.string),
+                                        "\n", "\n  |"))
+
+    def failed(self):
+        # check, if the reason was a ConfigureDryRunError or a
+        # ConfigureCacheError and if yes, reraise the exception
+        exc_type = self.exc_info()[0]
+        if issubclass(exc_type, SConfError):
+            raise
+        elif issubclass(exc_type, SCons.Errors.BuildError):
+            # we ignore Build Errors (occurs, when a test doesn't pass)
+            pass
+        else:
+            self.display('Caught exception while building "%s":\n' %
+                         self.targets[0])
+            try:
+                excepthook = sys.excepthook
+            except AttributeError:
+                # Earlier versions of Python don't have sys.excepthook...
+                def excepthook(type, value, tb):
+                    import traceback
+                    traceback.print_tb(tb)
+                    print type, value
+            apply(excepthook, self.exc_info())
+        return SCons.Taskmaster.Task.failed(self)
+
+    def collect_node_states(self):
+        # returns (is_up_to_date, cached_error, cachable)
+        # where is_up_to_date is 1, if the node(s) are up_to_date
+        #       cached_error  is 1, if the node(s) are up_to_date, but the
+        #                           build will fail
+        #       cachable      is 0, if some nodes are not in our cache
+        is_up_to_date = 1
+        cached_error = 0
+        cachable = 1
+        for t in self.targets:
+            bi = t.get_stored_info()
+            c_bi = isinstance(bi, SConfBuildInfo)
+            if c_bi:
+                if cache_mode == CACHE:
+                    t.set_state(SCons.Node.up_to_date)
+                else:
+                    new_bsig = t.calc_signature(sconf_global.calc)
+                    if t.env.use_build_signature():
+                        old_bsig = bi.ninfo.bsig
+                    else:
+                        old_bsig = bi.ninfo.csig
+                    is_up_to_date = (is_up_to_date and new_bsig == old_bsig)
+                cached_error = cached_error or bi.result
+            else:
+                # the node hasn't been built in a SConf context or doesn't
+                # exist
+                cachable = 0
+                is_up_to_date = 0
+        return (is_up_to_date, cached_error, cachable)
+
+    def execute(self):
+        sconf = sconf_global
+
+        is_up_to_date, cached_error, cachable = self.collect_node_states()
+
+        if cache_mode == CACHE and not cachable:
+            raise ConfigureCacheError(self.targets[0])
+        elif cache_mode == FORCE:
+            is_up_to_date = 0
+
+        if cached_error and is_up_to_date:
+            self.display("Building \"%s\" failed in a previous run and all "
+                         "its sources are up to date." % str(self.targets[0]))
+            self.display_cached_string(self.targets[0].get_stored_info())
+            raise SCons.Errors.BuildError # will be 'caught' in self.failed
+        elif is_up_to_date:            
+            self.display("\"%s\" is up to date." % str(self.targets[0]))
+            self.display_cached_string(self.targets[0].get_stored_info())
+        elif dryrun:
+            raise ConfigureDryRunError(self.targets[0])
+        else:
+            # note stdout and stderr are the same here
+            s = sys.stdout = sys.stderr = Streamer(sys.stdout)
+            try:
+                env = self.targets[0].get_build_env()
+                env['PSTDOUT'] = env['PSTDERR'] = s
+                try:
+                    sconf.cached = 0
+                    self.targets[0].build()
+                finally:
+                    sys.stdout = sys.stderr = env['PSTDOUT'] = \
+                                 env['PSTDERR'] = sconf.logstream
+            except KeyboardInterrupt:
+                raise
+            except SystemExit:
+                exc_value = sys.exc_info()[1]
+                raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code)
+            except:
+                for t in self.targets:
+                    sig = t.calc_signature(sconf.calc)
+                    string = s.getvalue()
+                    binfo = SConfBuildInfo(t,1,string,sig)
+                    t.dir.sconsign().set_entry(t.name, binfo)
+                raise
+            else:
+                for t in self.targets:
+                    sig = t.calc_signature(sconf.calc)
+                    string = s.getvalue()
+                    binfo = SConfBuildInfo(t,0,string,sig)
+                    t.dir.sconsign().set_entry(t.name, binfo)
+
+class SConf:
+    """This is simply a class to represent a configure context. After
+    creating a SConf object, you can call any tests. After finished with your
+    tests, be sure to call the Finish() method, which returns the modified
+    environment.
+    Some words about caching: In most cases, it is not necessary to cache
+    Test results explicitely. Instead, we use the scons dependency checking
+    mechanism. For example, if one wants to compile a test program
+    (SConf.TryLink), the compiler is only called, if the program dependencies
+    have changed. However, if the program could not be compiled in a former
+    SConf run, we need to explicitely cache this error.
+    """
+
+    def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR',
+                 log_file='$CONFIGURELOG', config_h = None, _depth = 0): 
+        """Constructor. Pass additional tests in the custom_tests-dictinary,
+        e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest
+        defines a custom test.
+        Note also the conf_dir and log_file arguments (you may want to
+        build tests in the BuildDir, not in the SourceDir)
+        """
+        global SConfFS
+        if not SConfFS:
+            SConfFS = SCons.Node.FS.default_fs or \
+                      SCons.Node.FS.FS(env.fs.pathTop)
+        if not sconf_global is None:
+            raise (SCons.Errors.UserError,
+                   "Only one SConf object may be active at one time")
+        self.env = env
+        if log_file != None:
+            log_file = SConfFS.File(env.subst(log_file))
+        self.logfile = log_file
+        self.logstream = None
+        self.lastTarget = None
+        self.depth = _depth
+        self.cached = 0 # will be set, if all test results are cached
+
+        # add default tests
+        default_tests = {
+                 'CheckFunc'          : CheckFunc,
+                 'CheckType'          : CheckType,
+                 'CheckHeader'        : CheckHeader,
+                 'CheckCHeader'       : CheckCHeader,
+                 'CheckCXXHeader'     : CheckCXXHeader,
+                 'CheckLib'           : CheckLib,
+                 'CheckLibWithHeader' : CheckLibWithHeader
+               }
+        self.AddTests(default_tests)
+        self.AddTests(custom_tests)
+        self.confdir = SConfFS.Dir(env.subst(conf_dir))
+        self.calc = None
+        if not config_h is None:
+            config_h = SConfFS.File(config_h)
+        self.config_h = config_h
+        self._startup()
+
+    def Finish(self):
+        """Call this method after finished with your tests:
+        env = sconf.Finish()"""
+        self._shutdown()
+        return self.env
+
+    def BuildNodes(self, nodes):
+        """
+        Tries to build the given nodes immediately. Returns 1 on success,
+        0 on error.
+        """
+        if self.logstream != None:
+            # override stdout / stderr to write in log file
+            oldStdout = sys.stdout
+            sys.stdout = self.logstream
+            oldStderr = sys.stderr
+            sys.stderr = self.logstream
+
+        # the engine assumes the current path is the SConstruct directory ...
+        old_fs_dir = SConfFS.getcwd()
+        old_os_dir = os.getcwd()
+        SConfFS.chdir(SConfFS.Top, change_os_dir=1)
+
+        ret = 1
+
+        try:
+            # ToDo: use user options for calc
+            save_max_drift = SConfFS.get_max_drift()
+            SConfFS.set_max_drift(0)
+            tm = SCons.Taskmaster.Taskmaster(nodes, SConfBuildTask)
+            # we don't want to build tests in parallel
+            jobs = SCons.Job.Jobs(1, tm )
+            jobs.run()
+            for n in nodes:
+                state = n.get_state()
+                if (state != SCons.Node.executed and
+                    state != SCons.Node.up_to_date):
+                    # the node could not be built. we return 0 in this case
+                    ret = 0
+        finally:
+            SConfFS.set_max_drift(save_max_drift)
+            os.chdir(old_os_dir)
+            SConfFS.chdir(old_fs_dir, change_os_dir=0)
+            if self.logstream != None:
+                # restore stdout / stderr
+                sys.stdout = oldStdout
+                sys.stderr = oldStderr
+        return ret
+
+    def pspawn_wrapper(self, sh, escape, cmd, args, env):
+        """Wrapper function for handling piped spawns.
+
+        This looks to the calling interface (in Action.py) like a "normal"
+        spawn, but associates the call with the PSPAWN variable from
+        the construction environment and with the streams to which we
+        want the output logged.  This gets slid into the construction
+        environment as the SPAWN variable so Action.py doesn't have to
+        know or care whether it's spawning a piped command or not.
+        """
+        return self.pspawn(sh, escape, cmd, args, env, self.logstream, self.logstream)
+
+
+    def TryBuild(self, builder, text = None, extension = ""):
+        """Low level TryBuild implementation. Normally you don't need to
+        call that - you can use TryCompile / TryLink / TryRun instead
+        """
+        global _ac_build_counter
+
+        # Make sure we have a PSPAWN value, and save the current
+        # SPAWN value.
+        try:
+            self.pspawn = self.env['PSPAWN']
+        except KeyError:
+            raise SCons.Errors.UserError('Missing PSPAWN construction variable.')
+        try:
+            save_spawn = self.env['SPAWN']
+        except KeyError:
+            raise SCons.Errors.UserError('Missing SPAWN construction variable.')
+
+        nodesToBeBuilt = []
+
+        f = "conftest_" + str(_ac_build_counter)
+        pref = self.env.subst( builder.builder.prefix )
+        suff = self.env.subst( builder.builder.suffix )
+        target = self.confdir.File(pref + f + suff)
+
+        try:
+            # Slide our wrapper into the construction environment as
+            # the SPAWN function.
+            self.env['SPAWN'] = self.pspawn_wrapper
+            sourcetext = self.env.Value(text)
+
+            if text != None:
+                textFile = self.confdir.File(f + extension)
+                textFileNode = self.env.SConfSourceBuilder(target=textFile,
+                                                           source=sourcetext)
+                nodesToBeBuilt.extend(textFileNode)
+                source = textFileNode
+            else:
+                source = None
+
+            nodes = builder(target = target, source = source)
+            if not SCons.Util.is_List(nodes):
+                nodes = [nodes]
+            nodesToBeBuilt.extend(nodes)
+            result = self.BuildNodes(nodesToBeBuilt)
+
+        finally:
+            # Restor the SPAWN value to the environment.
+            self.env['SPAWN'] = save_spawn
+
+        _ac_build_counter = _ac_build_counter + 1
+        if result:
+            self.lastTarget = nodes[0]
+        else:
+            self.lastTarget = None
+
+        return result
+
+    def TryAction(self, action, text = None, extension = ""):
+        """Tries to execute the given action with optional source file
+        contents <text> and optional source file extension <extension>,
+        Returns the status (0 : failed, 1 : ok) and the contents of the
+        output file.
+        """
+        builder = SCons.Builder.Builder(action=action)
+        self.env.Append( BUILDERS = {'SConfActionBuilder' : builder} )
+        ok = self.TryBuild(self.env.SConfActionBuilder, text, extension)
+        del self.env['BUILDERS']['SConfActionBuilder']
+        if ok:
+            outputStr = self.lastTarget.get_contents()
+            return (1, outputStr)
+        return (0, "")
+
+    def TryCompile( self, text, extension):
+        """Compiles the program given in text to an env.Object, using extension
+        as file extension (e.g. '.c'). Returns 1, if compilation was
+        successful, 0 otherwise. The target is saved in self.lastTarget (for
+        further processing).
+        """
+        return self.TryBuild(self.env.Object, text, extension)
+
+    def TryLink( self, text, extension ):
+        """Compiles the program given in text to an executable env.Program,
+        using extension as file extension (e.g. '.c'). Returns 1, if
+        compilation was successful, 0 otherwise. The target is saved in
+        self.lastTarget (for further processing).
+        """
+        return self.TryBuild(self.env.Program, text, extension )
+
+    def TryRun(self, text, extension ):
+        """Compiles and runs the program given in text, using extension
+        as file extension (e.g. '.c'). Returns (1, outputStr) on success,
+        (0, '') otherwise. The target (a file containing the program's stdout)
+        is saved in self.lastTarget (for further processing).
+        """
+        ok = self.TryLink(text, extension)
+        if( ok ):
+            prog = self.lastTarget
+            pname = str(prog)
+            output = SConfFS.File(pname+'.out')
+            node = self.env.Command(output, prog, [ [ pname, ">", "${TARGET}"] ])
+            ok = self.BuildNodes(node)
+            if ok:
+                outputStr = output.get_contents()
+                return( 1, outputStr)
+        return (0, "")
+
+    class TestWrapper:
+        """A wrapper around Tests (to ensure sanity)"""
+        def __init__(self, test, sconf):
+            self.test = test
+            self.sconf = sconf
+        def __call__(self, *args, **kw):
+            if not self.sconf.active:
+                raise (SCons.Errors.UserError,
+                       "Test called after sconf.Finish()")
+            context = CheckContext(self.sconf)
+            ret = apply(self.test, (context,) +  args, kw)
+            if not self.sconf.config_h is None:
+                self.sconf.config_h_text = self.sconf.config_h_text + context.config_h
+            context.Result("error: no result")
+            return ret
+
+    def AddTest(self, test_name, test_instance):
+        """Adds test_class to this SConf instance. It can be called with
+        self.test_name(...)"""
+        setattr(self, test_name, SConf.TestWrapper(test_instance, self))
+
+    def AddTests(self, tests):
+        """Adds all the tests given in the tests dictionary to this SConf
+        instance
+        """
+        for name in tests.keys():
+            self.AddTest(name, tests[name])
+
+    def _createDir( self, node ):
+        dirName = str(node)
+        if dryrun:
+            if not os.path.isdir( dirName ):
+                raise ConfigureDryRunError(dirName)
+        else:
+            if not os.path.isdir( dirName ):
+                os.makedirs( dirName )
+                node._exists = 1
+
+    def _startup(self):
+        """Private method. Set up logstream, and set the environment
+        variables necessary for a piped build
+        """
+        global _ac_config_logs
+        global sconf_global
+        global SConfFS
+        
+        self.lastEnvFs = self.env.fs
+        self.env.fs = SConfFS
+        self._createDir(self.confdir)
+        self.confdir.up().add_ignore( [self.confdir] )
+
+        if self.logfile != None and not dryrun:
+            # truncate logfile, if SConf.Configure is called for the first time
+            # in a build
+            if _ac_config_logs.has_key(self.logfile):
+                log_mode = "a"
+            else:
+                _ac_config_logs[self.logfile] = None
+                log_mode = "w"
+            self.logstream = open(str(self.logfile), log_mode)
+            # logfile may stay in a build directory, so we tell
+            # the build system not to override it with a eventually
+            # existing file with the same name in the source directory
+            self.logfile.dir.add_ignore( [self.logfile] )
+
+            tb = traceback.extract_stack()[-3-self.depth]
+            old_fs_dir = SConfFS.getcwd()
+            SConfFS.chdir(SConfFS.Top, change_os_dir=0)
+            self.logstream.write('file %s,line %d:\n\tConfigure(confdir = %s)\n' %
+                                 (tb[0], tb[1], str(self.confdir)) )
+            SConfFS.chdir(old_fs_dir)
+        else: 
+            self.logstream = None
+        # we use a special builder to create source files from TEXT
+        action = SCons.Action.Action(_createSource,
+                                     _stringSource)
+        sconfSrcBld = SCons.Builder.Builder(action=action)
+        self.env.Append( BUILDERS={'SConfSourceBuilder':sconfSrcBld} )
+        self.config_h_text = _ac_config_hs.get(self.config_h, "")
+        self.active = 1
+        # only one SConf instance should be active at a time ...
+        sconf_global = self
+
+    def _shutdown(self):
+        """Private method. Reset to non-piped spawn"""
+        global sconf_global, _ac_config_hs
+
+        if not self.active:
+            raise SCons.Errors.UserError, "Finish may be called only once!"
+        if self.logstream != None and not dryrun:
+            self.logstream.write("\n")
+            self.logstream.close()
+            self.logstream = None
+        # remove the SConfSourceBuilder from the environment
+        blds = self.env['BUILDERS']
+        del blds['SConfSourceBuilder']
+        self.env.Replace( BUILDERS=blds )
+        self.active = 0
+        sconf_global = None
+        if not self.config_h is None:
+            _ac_config_hs[self.config_h] = self.config_h_text
+        self.env.fs = self.lastEnvFs
+
+class CheckContext:
+    """Provides a context for configure tests. Defines how a test writes to the
+    screen and log file.
+
+    A typical test is just a callable with an instance of CheckContext as
+    first argument:
+
+    def CheckCustom(context, ...)
+    context.Message('Checking my weird test ... ')
+    ret = myWeirdTestFunction(...)
+    context.Result(ret)
+
+    Often, myWeirdTestFunction will be one of
+    context.TryCompile/context.TryLink/context.TryRun. The results of
+    those are cached, for they are only rebuild, if the dependencies have
+    changed.
+    """
+
+    def __init__(self, sconf):
+        """Constructor. Pass the corresponding SConf instance."""
+        self.sconf = sconf
+        self.did_show_result = 0
+
+        # for Conftest.py:
+        self.vardict = {}
+        self.havedict = {}
+        self.headerfilename = None
+        self.config_h = "" # config_h text will be stored here
+        # we don't regenerate the config.h file after each test. That means,
+        # that tests won't be able to include the config.h file, and so
+        # they can't do an #ifdef HAVE_XXX_H. This shouldn't be a major
+        # issue, though. If it turns out, that we need to include config.h
+        # in tests, we must ensure, that the dependencies are worked out
+        # correctly. Note that we can't use Conftest.py's support for config.h,
+        # cause we will need to specify a builder for the config.h file ...
+
+    def Message(self, text):
+        """Inform about what we are doing right now, e.g.
+        'Checking for SOMETHING ... '
+        """
+        self.Display(text)
+        self.sconf.cached = 1
+        self.did_show_result = 0
+
+    def Result(self, res):
+        """Inform about the result of the test. res may be an integer or a
+        string. In case of an integer, the written text will be 'ok' or
+        'failed'.
+        The result is only displayed when self.did_show_result is not set.
+        """
+        if type(res) in BooleanTypes:
+            if res:
+                text = "yes"
+            else:
+                text = "no"
+        elif type(res) == types.StringType:
+            text = res
+        else:
+            raise TypeError, "Expected string, int or bool, got " + str(type(res))
+
+        if self.did_show_result == 0:
+            # Didn't show result yet, do it now.
+            self.Display(text + "\n")
+            self.did_show_result = 1
+
+    def TryBuild(self, *args, **kw):
+        return apply(self.sconf.TryBuild, args, kw)
+
+    def TryAction(self, *args, **kw):
+        return apply(self.sconf.TryAction, args, kw)
+
+    def TryCompile(self, *args, **kw):
+        return apply(self.sconf.TryCompile, args, kw)
+
+    def TryLink(self, *args, **kw):
+        return apply(self.sconf.TryLink, args, kw)
+
+    def TryRun(self, *args, **kw):
+        return apply(self.sconf.TryRun, args, kw)
+
+    def __getattr__( self, attr ):
+        if( attr == 'env' ):
+            return self.sconf.env
+        elif( attr == 'lastTarget' ):
+            return self.sconf.lastTarget
+        else:
+            raise AttributeError, "CheckContext instance has no attribute '%s'" % attr
+
+    #### Stuff used by Conftest.py (look there for explanations).
+
+    def BuildProg(self, text, ext):
+        self.sconf.cached = 1
+        # TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
+        return not self.TryBuild(self.env.Program, text, ext)
+
+    def CompileProg(self, text, ext):
+        self.sconf.cached = 1
+        # TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
+        return not self.TryBuild(self.env.Object, text, ext)
+
+    def AppendLIBS(self, lib_name_list):
+        oldLIBS = self.env.get( 'LIBS', [] )
+        self.env.Append(LIBS = lib_name_list)
+        return oldLIBS
+
+    def SetLIBS(self, val):
+        oldLIBS = self.env.get( 'LIBS', [] )
+        self.env.Replace(LIBS = val)
+        return oldLIBS
+
+    def Display(self, msg):
+        if self.sconf.cached:
+            # We assume that Display is called twice for each test here
+            # once for the Checking for ... message and once for the result.
+            # The self.sconf.cached flag can only be set between those calls
+            msg = "(cached) " + msg
+            self.sconf.cached = 0
+        progress_display(msg, append_newline=0)
+        self.Log("scons: Configure: " + msg + "\n")
+
+    def Log(self, msg):
+        if self.sconf.logstream != None:
+            self.sconf.logstream.write(msg)
+
+    #### End of stuff used by Conftest.py.
+
+
+def CheckFunc(context, function_name, header = None, language = None):
+    res = SCons.Conftest.CheckFunc(context, function_name, header = header, language = language)
+    context.did_show_result = 1
+    return not res
+
+def CheckType(context, type_name, includes = "", language = None):
+    res = SCons.Conftest.CheckType(context, type_name,
+                                        header = includes, language = language)
+    context.did_show_result = 1
+    return not res
+
+def createIncludesFromHeaders(headers, leaveLast, include_quotes = '""'):
+    # used by CheckHeader and CheckLibWithHeader to produce C - #include
+    # statements from the specified header (list)
+    if not SCons.Util.is_List(headers):
+        headers = [headers]
+    l = []
+    if leaveLast:
+        lastHeader = headers[-1]
+        headers = headers[:-1]
+    else:
+        lastHeader = None
+    for s in headers:
+        l.append("#include %s%s%s\n"
+                 % (include_quotes[0], s, include_quotes[1]))
+    return string.join(l, ''), lastHeader
+
+def CheckHeader(context, header, include_quotes = '<>', language = None):
+    """
+    A test for a C or C++ header file.
+    """
+    prog_prefix, hdr_to_check = \
+                 createIncludesFromHeaders(header, 1, include_quotes)
+    res = SCons.Conftest.CheckHeader(context, hdr_to_check, prog_prefix,
+                                     language = language,
+                                     include_quotes = include_quotes)
+    context.did_show_result = 1
+    return not res
+
+# Bram: Make this function obsolete?  CheckHeader() is more generic.
+
+def CheckCHeader(context, header, include_quotes = '""'):
+    """
+    A test for a C header file.
+    """
+    return CheckHeader(context, header, include_quotes, language = "C")
+
+
+# Bram: Make this function obsolete?  CheckHeader() is more generic.
+
+def CheckCXXHeader(context, header, include_quotes = '""'):
+    """
+    A test for a C++ header file.
+    """
+    return CheckHeader(context, header, include_quotes, language = "C++")
+
+
+def CheckLib(context, library = None, symbol = "main",
+             header = None, language = None, autoadd = 1):
+    """
+    A test for a library. See also CheckLibWithHeader.
+    Note that library may also be None to test whether the given symbol
+    compiles without flags.
+    """
+
+    if library == []:
+        library = [None]
+
+    if not SCons.Util.is_List(library):
+        library = [library]
+    
+    # ToDo: accept path for the library
+    res = SCons.Conftest.CheckLib(context, library, symbol, header = header,
+                                        language = language, autoadd = autoadd)
+    context.did_show_result = 1
+    return not res
+
+# XXX
+# Bram: Can only include one header and can't use #ifdef HAVE_HEADER_H.
+
+def CheckLibWithHeader(context, libs, header, language,
+                       call = "main();", autoadd = 1):
+    # ToDo: accept path for library. Support system header files.
+    """
+    Another (more sophisticated) test for a library.
+    Checks, if library and header is available for language (maybe 'C'
+    or 'CXX'). Call maybe be a valid expression _with_ a trailing ';'.
+    As in CheckLib, we support library=None, to test if the call compiles
+    without extra link flags.
+    """
+    prog_prefix, dummy = \
+                 createIncludesFromHeaders(header, 0)
+    if libs == []:
+        libs = [None]
+
+    if not SCons.Util.is_List(libs):
+        libs = [libs]
+
+    res = SCons.Conftest.CheckLib(context, libs, "main", prog_prefix,
+            call = call, language = language, autoadd = autoadd)
+    context.did_show_result = 1
+    return not res

Added: cs/scons/scons-local-0.96.92/SCons/SConsign.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/SConsign.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/SConsign.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,338 @@
+"""SCons.SConsign
+
+Writing and reading information to the .sconsign file or files.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/SConsign.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import cPickle
+import os
+import os.path
+import string
+import time
+
+import SCons.dblite
+import SCons.Sig
+import SCons.Warnings
+
+def corrupt_dblite_warning(filename):
+    SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
+                        "Ignoring corrupt .sconsign file: %s"%filename)
+
+SCons.dblite.ignore_corrupt_dbfiles = 1
+SCons.dblite.corruption_warning = corrupt_dblite_warning
+
+#XXX Get rid of the global array so this becomes re-entrant.
+sig_files = []
+
+# Info for the database SConsign implementation (now the default):
+# "DataBase" is a dictionary that maps top-level SConstruct directories
+# to open database handles.
+# "DB_Module" is the Python database module to create the handles.
+# "DB_Name" is the base name of the database file (minus any
+# extension the underlying DB module will add).
+DataBase = {}
+DB_Module = SCons.dblite
+DB_Name = ".sconsign"
+DB_sync_list = []
+
+def Get_DataBase(dir):
+    global DataBase, DB_Module, DB_Name
+    top = dir.fs.Top
+    if not os.path.isabs(DB_Name) and top.repositories:
+        mode = "c"
+        for d in [top] + top.repositories:
+            if dir.is_under(d):
+                try:
+                    return DataBase[d], mode
+                except KeyError:
+                    path = d.entry_abspath(DB_Name)
+                    try: db = DataBase[d] = DB_Module.open(path, mode)
+                    except (IOError, OSError): pass
+                    else:
+                        if mode != "r":
+                            DB_sync_list.append(db)
+                        return db, mode
+            mode = "r"
+    try:
+        return DataBase[top], "c"
+    except KeyError:
+        db = DataBase[top] = DB_Module.open(DB_Name, "c")
+        DB_sync_list.append(db)
+        return db, "c"
+    except TypeError:
+        print "DataBase =", DataBase
+        raise
+
+def Reset():
+    """Reset global state.  Used by unit tests that end up using
+    SConsign multiple times to get a clean slate for each test."""
+    global sig_files, DB_sync_list
+    sig_files = []
+    DB_sync_list = []
+
+normcase = os.path.normcase
+
+def write():
+    global sig_files
+    for sig_file in sig_files:
+        sig_file.write(sync=0)
+    for db in DB_sync_list:
+        try:
+            syncmethod = db.sync
+        except AttributeError:
+            pass # Not all anydbm modules have sync() methods.
+        else:
+            syncmethod()
+
+class Base:
+    """
+    This is the controlling class for the signatures for the collection of
+    entries associated with a specific directory.  The actual directory
+    association will be maintained by a subclass that is specific to
+    the underlying storage method.  This class provides a common set of
+    methods for fetching and storing the individual bits of information
+    that make up signature entry.
+    """
+    def __init__(self, module=None):
+        """
+        module - the signature module being used
+        """
+
+        self.module = module or SCons.Sig.default_calc.module
+        self.entries = {}
+        self.dirty = 0
+
+    def get_entry(self, filename):
+        """
+        Fetch the specified entry attribute.
+        """
+        return self.entries[filename]
+
+    def set_entry(self, filename, obj):
+        """
+        Set the entry.
+        """
+        self.entries[filename] = obj
+        self.dirty = 1
+
+    def do_not_set_entry(self, filename, obj):
+        pass
+
+class DB(Base):
+    """
+    A Base subclass that reads and writes signature information
+    from a global .sconsign.db* file--the actual file suffix is
+    determined by the specified database module.
+    """
+    def __init__(self, dir, module=None):
+        Base.__init__(self, module)
+
+        self.dir = dir
+
+        db, mode = Get_DataBase(dir)
+
+        # Read using the path relative to the top of the Repository
+        # (self.dir.tpath) from which we're fetching the signature
+        # information.
+        path = normcase(dir.tpath)
+        try:
+            rawentries = db[path]
+        except KeyError:
+            pass
+        else:
+            try:
+                self.entries = cPickle.loads(rawentries)
+                if type(self.entries) is not type({}):
+                    self.entries = {}
+                    raise TypeError
+            except KeyboardInterrupt:
+                raise
+            except Exception, e:
+                SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
+                                    "Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.tpath, e))
+            for key, entry in self.entries.items():
+                entry.convert_from_sconsign(dir, key)
+
+        if mode == "r":
+            # This directory is actually under a repository, which means
+            # likely they're reaching in directly for a dependency on
+            # a file there.  Don't actually set any entry info, so we
+            # won't try to write to that .sconsign.dblite file.
+            self.set_entry = self.do_not_set_entry
+
+        global sig_files
+        sig_files.append(self)
+
+    def write(self, sync=1):
+        if not self.dirty:
+            return
+
+        db, mode = Get_DataBase(self.dir)
+
+        # Write using the path relative to the top of the SConstruct
+        # directory (self.dir.path), not relative to the top of
+        # the Repository; we only write to our own .sconsign file,
+        # not to .sconsign files in Repositories.
+        path = normcase(self.dir.path)
+        for key, entry in self.entries.items():
+            entry.convert_to_sconsign()
+        db[path] = cPickle.dumps(self.entries, 1)
+
+        if sync:
+            try:
+                syncmethod = db.sync
+            except AttributeError:
+                # Not all anydbm modules have sync() methods.
+                pass
+            else:
+                syncmethod()
+
+class Dir(Base):
+    def __init__(self, fp=None, module=None):
+        """
+        fp - file pointer to read entries from
+        module - the signature module being used
+        """
+        Base.__init__(self, module)
+
+        if fp:
+            self.entries = cPickle.load(fp)
+            if type(self.entries) is not type({}):
+                self.entries = {}
+                raise TypeError
+
+class DirFile(Dir):
+    """
+    Encapsulates reading and writing a per-directory .sconsign file.
+    """
+    def __init__(self, dir, module=None):
+        """
+        dir - the directory for the file
+        module - the signature module being used
+        """
+
+        self.dir = dir
+        self.sconsign = os.path.join(dir.path, '.sconsign')
+
+        try:
+            fp = open(self.sconsign, 'rb')
+        except IOError:
+            fp = None
+
+        try:
+            Dir.__init__(self, fp, module)
+        except KeyboardInterrupt:
+            raise
+        except:
+            SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
+                                "Ignoring corrupt .sconsign file: %s"%self.sconsign)
+
+        global sig_files
+        sig_files.append(self)
+
+    def get_entry(self, filename):
+        """
+        Fetch the specified entry attribute, converting from .sconsign
+        format to in-memory format.
+        """
+        entry = Dir.get_entry(self, filename)
+        entry.convert_from_sconsign(self.dir, filename)
+        return entry
+
+    def write(self, sync=1):
+        """
+        Write the .sconsign file to disk.
+
+        Try to write to a temporary file first, and rename it if we
+        succeed.  If we can't write to the temporary file, it's
+        probably because the directory isn't writable (and if so,
+        how did we build anything in this directory, anyway?), so
+        try to write directly to the .sconsign file as a backup.
+        If we can't rename, try to copy the temporary contents back
+        to the .sconsign file.  Either way, always try to remove
+        the temporary file at the end.
+        """
+        if self.dirty:
+            temp = os.path.join(self.dir.path, '.scons%d' % os.getpid())
+            try:
+                file = open(temp, 'wb')
+                fname = temp
+            except IOError:
+                try:
+                    file = open(self.sconsign, 'wb')
+                    fname = self.sconsign
+                except IOError:
+                    return
+            for key, entry in self.entries.items():
+                entry.convert_to_sconsign()
+            cPickle.dump(self.entries, file, 1)
+            file.close()
+            if fname != self.sconsign:
+                try:
+                    mode = os.stat(self.sconsign)[0]
+                    os.chmod(self.sconsign, 0666)
+                    os.unlink(self.sconsign)
+                except (IOError, OSError):
+                    # Try to carry on in the face of either OSError
+                    # (things like permission issues) or IOError (disk
+                    # or network issues).  If there's a really dangerous
+                    # issue, it should get re-raised by the calls below.
+                    pass
+                try:
+                    os.rename(fname, self.sconsign)
+                except OSError:
+                    # An OSError failure to rename may indicate something
+                    # like the directory has no write permission, but
+                    # the .sconsign file itself might still be writable,
+                    # so try writing on top of it directly.  An IOError
+                    # here, or in any of the following calls, would get
+                    # raised, indicating something like a potentially
+                    # serious disk or network issue.
+                    open(self.sconsign, 'wb').write(open(fname, 'rb').read())
+                    os.chmod(self.sconsign, mode)
+            try:
+                os.unlink(temp)
+            except (IOError, OSError):
+                pass
+
+ForDirectory = DB
+
+def File(name, dbm_module=None):
+    """
+    Arrange for all signatures to be stored in a global .sconsign.db*
+    file.
+    """
+    global ForDirectory, DB_Name, DB_Module
+    if name is None:
+        ForDirectory = DirFile
+        DB_Module = None
+    else:
+        ForDirectory = DB
+        DB_Name = name
+        if not dbm_module is None:
+            DB_Module = dbm_module

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/C.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/C.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/C.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,42 @@
+"""SCons.Scanner.C
+
+This module implements the depenency scanner for C/C++ code. 
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/C.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Node.FS
+import SCons.Scanner
+
+def CScanner():
+    """Return a prototype Scanner instance for scanning source files
+    that use the C pre-processor"""
+    cs = SCons.Scanner.ClassicCPP("CScanner",
+                                  "$CPPSUFFIXES",
+                                  "CPPPATH",
+                                  '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
+    return cs

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/D.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/D.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/D.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,54 @@
+"""SCons.Scanner.D
+
+Scanner for the Digital Mars "D" programming language.
+
+Coded by Andy Friesen
+17 Nov 2003
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/D.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+
+import SCons.Scanner
+
+def DScanner():
+    """Return a prototype Scanner instance for scanning D source files"""
+    ds = D(name = "DScanner",
+           suffixes = '$DSUFFIXES',
+           path_variable = 'DPATH',
+           regex = 'import\s+([^\;]*)\;')
+    return ds
+
+class D(SCons.Scanner.Classic):
+    def find_include(self, include, source_dir, path):
+        if callable(path): path=path()
+        # translate dots (package separators) to slashes
+        inc = string.replace(include, '.', '/')
+
+        i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path)
+        return i, include

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/Dir.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/Dir.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/Dir.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/Dir.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+
+import SCons.Node.FS
+import SCons.Scanner
+
+def only_dirs(nodes):
+    is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir)
+    return filter(is_Dir, nodes)
+
+def DirScanner(**kw):
+    """Return a prototype Scanner instance for scanning
+    directories for on-disk files"""
+    kw['node_factory'] = SCons.Node.FS.Entry
+    kw['recursive'] = only_dirs
+    return apply(SCons.Scanner.Base, (scan_on_disk, "DirScanner"), kw)
+
+def DirEntryScanner(**kw):
+    """Return a prototype Scanner instance for "scanning"
+    directory Nodes for their in-memory entries"""
+    kw['node_factory'] = SCons.Node.FS.Entry
+    kw['recursive'] = None
+    return apply(SCons.Scanner.Base, (scan_in_memory, "DirEntryScanner"), kw)
+
+skip_entry = {}
+
+skip_entry_list = [
+   '.',
+   '..',
+   '.sconsign',
+   # Used by the native dblite.py module.
+   '.sconsign.dblite',
+   # Used by dbm and dumbdbm.
+   '.sconsign.dir',
+   # Used by dbm.
+   '.sconsign.pag',
+   # Used by dumbdbm.
+   '.sconsign.dat',
+   '.sconsign.bak',
+   # Used by some dbm emulations using Berkeley DB.
+   '.sconsign.db',
+]
+
+for skip in skip_entry_list:
+    skip_entry[skip] = 1
+    skip_entry[SCons.Node.FS._my_normcase(skip)] = 1
+
+do_not_scan = lambda k: not skip_entry.has_key(k)
+
+def scan_on_disk(node, env, path=()):
+    """
+    Scans a directory for on-disk files and directories therein.
+
+    Looking up the entries will add these to the in-memory Node tree
+    representation of the file system, so all we have to do is just
+    that and then call the in-memory scanning function.
+    """
+    try:
+        flist = node.fs.listdir(node.abspath)
+    except (IOError, OSError):
+        return []
+    e = node.Entry
+    for f in  filter(do_not_scan, flist):
+        # Add ./ to the beginning of the file name so if it begins with a
+        # '#' we don't look it up relative to the top-level directory.
+        e('./' + f)
+    return scan_in_memory(node, env, path)
+
+def scan_in_memory(node, env, path=()):
+    """
+    "Scans" a Node.FS.Dir for its in-memory entries.
+    """
+    entry_list = filter(do_not_scan, node.entries.keys())
+    entry_list.sort()
+    return map(lambda n, e=node.entries: e[n], entry_list)

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/Fortran.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/Fortran.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/Fortran.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,313 @@
+"""SCons.Scanner.Fortran
+
+This module implements the dependency scanner for Fortran code.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/Fortran.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import re
+import string
+
+import SCons.Node
+import SCons.Node.FS
+import SCons.Scanner
+import SCons.Util
+import SCons.Warnings
+
+class F90Scanner(SCons.Scanner.Classic):
+    """
+    A Classic Scanner subclass for Fortran source files which takes
+    into account both USE and INCLUDE statements.  This scanner will
+    work for both F77 and F90 (and beyond) compilers.
+
+    Currently, this scanner assumes that the include files do not contain
+    USE statements.  To enable the ability to deal with USE statements
+    in include files, add logic right after the module names are found
+    to loop over each include file, search for and locate each USE
+    statement, and append each module name to the list of dependencies.
+    Caching the search results in a common dictionary somewhere so that
+    the same include file is not searched multiple times would be a
+    smart thing to do.
+    """
+
+    def __init__(self, name, suffixes, path_variable,
+                 use_regex, incl_regex, def_regex, *args, **kw):
+
+        self.cre_use = re.compile(use_regex, re.M)
+        self.cre_incl = re.compile(incl_regex, re.M)
+        self.cre_def = re.compile(def_regex, re.M)
+
+        def _scan(node, env, path, self=self):
+            node = node.rfile()
+
+            if not node.exists():
+                return []
+
+            return self.scan(node, env, path)
+
+        kw['function'] = _scan
+        kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable)
+        kw['recursive'] = 1
+        kw['skeys'] = suffixes
+        kw['name'] = name
+
+        apply(SCons.Scanner.Current.__init__, (self,) + args, kw)
+
+    def scan(self, node, env, path=()):
+        "__cacheable__"
+
+        # cache the includes list in node so we only scan it once:
+        if node.includes != None:
+            mods_and_includes = node.includes
+        else:
+            # retrieve all included filenames
+            includes = self.cre_incl.findall(node.get_contents())
+            # retrieve all USE'd module names
+            modules = self.cre_use.findall(node.get_contents())
+            # retrieve all defined module names
+            defmodules = self.cre_def.findall(node.get_contents())
+
+            # Remove all USE'd module names that are defined in the same file
+            d = {}
+            for m in defmodules:
+                d[m] = 1
+            modules = filter(lambda m, d=d: not d.has_key(m), modules)
+            #modules = self.undefinedModules(modules, defmodules)
+
+            # Convert module name to a .mod filename
+            suffix = env.subst('$FORTRANMODSUFFIX')
+            modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
+            # Remove unique items from the list
+            mods_and_includes = SCons.Util.unique(includes+modules)
+            node.includes = mods_and_includes
+
+        # This is a hand-coded DSU (decorate-sort-undecorate, or
+        # Schwartzian transform) pattern.  The sort key is the raw name
+        # of the file as specifed on the USE or INCLUDE line, which lets
+        # us keep the sort order constant regardless of whether the file
+        # is actually found in a Repository or locally.
+        nodes = []
+        source_dir = node.get_dir()
+        for dep in mods_and_includes:
+            n, i = self.find_include(dep, source_dir, path)
+
+            if n is None:
+                SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
+                                    "No dependency generated for file: %s (referenced by: %s) -- file not found" % (i, node))
+            else:
+                sortkey = self.sort_key(dep)
+                nodes.append((sortkey, n))
+
+        nodes.sort()
+        nodes = map(lambda pair: pair[1], nodes)
+        return nodes
+
+def FortranScan(path_variable="FORTRANPATH"):
+    """Return a prototype Scanner instance for scanning source files
+    for Fortran USE & INCLUDE statements"""
+
+#   The USE statement regex matches the following:
+#
+#   USE module_name
+#   USE :: module_name
+#   USE, INTRINSIC :: module_name
+#   USE, NON_INTRINSIC :: module_name
+#
+#   Limitations
+#
+#   --  While the regex can handle multiple USE statements on one line,
+#       it cannot properly handle them if they are commented out.
+#       In either of the following cases:
+#
+#            !  USE mod_a ; USE mod_b         [entire line is commented out]
+#               USE mod_a ! ; USE mod_b       [in-line comment of second USE statement]
+#
+#       the second module name (mod_b) will be picked up as a dependency
+#       even though it should be ignored.  The only way I can see
+#       to rectify this would be to modify the scanner to eliminate
+#       the call to re.findall, read in the contents of the file,
+#       treating the comment character as an end-of-line character
+#       in addition to the normal linefeed, loop over each line,
+#       weeding out the comments, and looking for the USE statements.
+#       One advantage to this is that the regex passed to the scanner
+#       would no longer need to match a semicolon.
+#
+#   --  I question whether or not we need to detect dependencies to
+#       INTRINSIC modules because these are built-in to the compiler.
+#       If we consider them a dependency, will SCons look for them, not
+#       find them, and kill the build?  Or will we there be standard
+#       compiler-specific directories we will need to point to so the
+#       compiler and SCons can locate the proper object and mod files?
+
+#   Here is a breakdown of the regex:
+#
+#   (?i)               : regex is case insensitive
+#   ^                  : start of line
+#   (?:                : group a collection of regex symbols without saving the match as a "group"
+#      ^|;             : matches either the start of the line or a semicolon - semicolon
+#   )                  : end the unsaved grouping
+#   \s*                : any amount of white space
+#   USE                : match the string USE, case insensitive
+#   (?:                : group a collection of regex symbols without saving the match as a "group"
+#      \s+|            : match one or more whitespace OR ....  (the next entire grouped set of regex symbols)
+#      (?:             : group a collection of regex symbols without saving the match as a "group"
+#         (?:          : establish another unsaved grouping of regex symbols
+#            \s*          : any amount of white space
+#            ,         : match a comma
+#            \s*       : any amount of white space
+#            (?:NON_)? : optionally match the prefix NON_, case insensitive
+#            INTRINSIC : match the string INTRINSIC, case insensitive
+#         )?           : optionally match the ", INTRINSIC/NON_INTRINSIC" grouped expression
+#         \s*          : any amount of white space
+#         ::           : match a double colon that must appear after the INTRINSIC/NON_INTRINSIC attribute
+#      )               : end the unsaved grouping
+#   )                  : end the unsaved grouping
+#   \s*                : match any amount of white space
+#   (\w+)              : match the module name that is being USE'd
+#
+#
+    use_regex = "(?i)(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)"
+
+
+#   The INCLUDE statement regex matches the following:
+#
+#   INCLUDE 'some_Text'
+#   INCLUDE "some_Text"
+#   INCLUDE "some_Text" ; INCLUDE "some_Text"
+#   INCLUDE kind_"some_Text"
+#   INCLUDE kind_'some_Text"
+#
+#   where some_Text can include any alphanumeric and/or special character
+#   as defined by the Fortran 2003 standard.
+#
+#   Limitations:
+#
+#   --  The Fortran standard dictates that a " or ' in the INCLUDE'd
+#       string must be represented as a "" or '', if the quotes that wrap
+#       the entire string are either a ' or ", respectively.   While the
+#       regular expression below can detect the ' or " characters just fine,
+#       the scanning logic, presently is unable to detect them and reduce
+#       them to a single instance.  This probably isn't an issue since,
+#       in practice, ' or " are not generally used in filenames.
+#
+#   --  This regex will not properly deal with multiple INCLUDE statements
+#       when the entire line has been commented out, ala
+#
+#           ! INCLUDE 'some_file' ; INCLUDE 'some_file'
+#
+#       In such cases, it will properly ignore the first INCLUDE file,
+#       but will actually still pick up the second.  Interestingly enough,
+#       the regex will properly deal with these cases:
+#
+#             INCLUDE 'some_file'
+#             INCLUDE 'some_file' !; INCLUDE 'some_file'
+#
+#       To get around the above limitation, the FORTRAN programmer could
+#       simply comment each INCLUDE statement separately, like this
+#
+#           ! INCLUDE 'some_file' !; INCLUDE 'some_file'
+#
+#       The way I see it, the only way to get around this limitation would
+#       be to modify the scanning logic to replace the calls to re.findall
+#       with a custom loop that processes each line separately, throwing
+#       away fully commented out lines before attempting to match against
+#       the INCLUDE syntax.
+#
+#   Here is a breakdown of the regex:
+#
+#   (?i)               : regex is case insensitive
+#   (?:                : begin a non-saving group that matches the following:
+#      ^               :    either the start of the line
+#      |               :                or
+#      ['">]\s*;       :    a semicolon that follows a single quote,
+#                           double quote or greater than symbol (with any
+#                           amount of whitespace in between).  This will
+#                           allow the regex to match multiple INCLUDE
+#                           statements per line (although it also requires
+#                           the positive lookahead assertion that is
+#                           used below).  It will even properly deal with
+#                           (i.e. ignore) cases in which the additional
+#                           INCLUDES are part of an in-line comment, ala
+#                                           "  INCLUDE 'someFile' ! ; INCLUDE 'someFile2' "
+#   )                  : end of non-saving group
+#   \s*                : any amount of white space
+#   INCLUDE            : match the string INCLUDE, case insensitive
+#   \s+                : match one or more white space characters
+#   (?\w+_)?           : match the optional "kind-param _" prefix allowed by the standard
+#   [<"']              : match the include delimiter - an apostrophe, double quote, or less than symbol
+#   (.+?)              : match one or more characters that make up
+#                        the included path and file name and save it
+#                        in a group.  The Fortran standard allows for
+#                        any non-control character to be used.  The dot
+#                        operator will pick up any character, including
+#                        control codes, but I can't conceive of anyone
+#                        putting control codes in their file names.
+#                        The question mark indicates it is non-greedy so
+#                        that regex will match only up to the next quote,
+#                        double quote, or greater than symbol
+#   (?=["'>])          : positive lookahead assertion to match the include
+#                        delimiter - an apostrophe, double quote, or
+#                        greater than symbol.  This level of complexity
+#                        is required so that the include delimiter is
+#                        not consumed by the match, thus allowing the
+#                        sub-regex discussed above to uniquely match a
+#                        set of semicolon-separated INCLUDE statements
+#                        (as allowed by the F2003 standard)
+
+    include_regex = """(?i)(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])"""
+
+#   The MODULE statement regex finds module definitions by matching
+#   the following:
+#
+#   MODULE module_name
+#
+#   but *not* the following:
+#
+#   MODULE PROCEDURE procedure_name
+#
+#   Here is a breakdown of the regex:
+#
+#   (?i)               : regex is case insensitive
+#   ^\s*               : any amount of white space
+#   MODULE             : match the string MODULE, case insensitive
+#   \s+                : match one or more white space characters
+#   (?!PROCEDURE)      : but *don't* match if the next word matches
+#                        PROCEDURE (negative lookahead assertion),
+#                        case insensitive
+#   (\w+)              : match one or more alphanumeric characters
+#                        that make up the defined module name and
+#                        save it in a group
+
+    def_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
+
+    scanner = F90Scanner("FortranScan",
+                         "$FORTRANSUFFIXES",
+                         path_variable,
+                         use_regex,
+                         include_regex,
+                         def_regex)
+    return scanner

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/IDL.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/IDL.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/IDL.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,42 @@
+"""SCons.Scanner.IDL
+
+This module implements the depenency scanner for IDL (Interface
+Definition Language) files.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/IDL.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Node.FS
+import SCons.Scanner
+
+def IDLScan():
+    """Return a prototype Scanner instance for scanning IDL source files"""
+    cs = SCons.Scanner.ClassicCPP("IDLScan",
+                                  "$IDLSUFFIXES",
+                                  "CPPPATH",
+                                  '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")')
+    return cs

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/LaTeX.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/LaTeX.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/LaTeX.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,66 @@
+"""SCons.Scanner.LaTeX
+
+This module implements the dependency scanner for LaTeX code.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/LaTeX.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+import SCons.Scanner
+
+def LaTeXScanner(fs = SCons.Node.FS.default_fs):
+    """Return a prototype Scanner instance for scanning LaTeX source files"""
+    ds = LaTeX(name = "LaTeXScanner",
+               suffixes =  '$LATEXSUFFIXES',
+               path_variable = 'TEXINPUTS',
+               regex = '\\\\(include|includegraphics(?:\[[^\]]+\])?|input){([^}]*)}',
+               recursive = 0)
+    return ds
+
+class LaTeX(SCons.Scanner.Classic):
+    """Class for scanning LaTeX files for included files.
+
+    Unlike most scanners, which use regular expressions that just
+    return the included file name, this returns a tuple consisting
+    of the keyword for the inclusion ("include", "includegraphics" or
+    "input"), and then the file name itself.  Base on a quick look at
+    LaTeX documentation, it seems that we need a should append .tex
+    suffix for "include" and "input" keywords, but leave the file name
+    untouched for "includegraphics."
+    """
+    def latex_name(self, include):
+        filename = include[1]
+        if include[0][:15] != 'includegraphics':
+            filename = filename + '.tex'
+        return filename
+    def sort_key(self, include):
+        return SCons.Node.FS._my_normcase(self.latex_name(include))
+    def find_include(self, include, source_dir, path):
+        if callable(path): path=path()
+        i = SCons.Node.FS.find_file(self.latex_name(include),
+                                    (source_dir,) + path)
+        return i, include

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/Prog.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/Prog.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/Prog.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,98 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/Prog.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+
+import SCons.Node
+import SCons.Node.FS
+import SCons.Scanner
+import SCons.Util
+
+# global, set by --debug=findlibs
+print_find_libs = None
+
+def ProgramScanner(**kw):
+    """Return a prototype Scanner instance for scanning executable
+    files for static-lib dependencies"""
+    kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH')
+    ps = apply(SCons.Scanner.Base, [scan, "ProgramScanner"], kw)
+    return ps
+
+def scan(node, env, libpath = ()):
+    """
+    This scanner scans program files for static-library
+    dependencies.  It will search the LIBPATH environment variable
+    for libraries specified in the LIBS variable, returning any
+    files it finds as dependencies.
+    """
+    try:
+        libs = env['LIBS']
+    except KeyError:
+        # There are no LIBS in this environment, so just return a null list:
+        return []
+    if SCons.Util.is_String(libs):
+        libs = string.split(libs)
+    elif SCons.Util.is_List(libs):
+        libs = SCons.Util.flatten(libs)
+    else:
+        libs = [libs]
+
+    try:
+        prefix = env['LIBPREFIXES']
+        if not SCons.Util.is_List(prefix):
+            prefix = [ prefix ]
+    except KeyError:
+        prefix = [ '' ]
+
+    try:
+        suffix = env['LIBSUFFIXES']
+        if not SCons.Util.is_List(suffix):
+            suffix = [ suffix ]
+    except KeyError:
+        suffix = [ '' ]
+
+    pairs = []
+    for suf in map(env.subst, suffix):
+        for pref in map(env.subst, prefix):
+            pairs.append((pref, suf))
+
+    result = []
+
+    if callable(libpath): libpath = libpath()
+    
+    find_file = SCons.Node.FS.find_file
+    adjustixes = SCons.Util.adjustixes
+    for lib in libs:
+        if SCons.Util.is_String(lib):
+            lib = env.subst(lib)
+            for pref, suf in pairs:
+                l = adjustixes(lib, pref, suf)
+                l = find_file(l, libpath, verbose=print_find_libs)
+                if l:
+                    result.append(l)
+        else:
+            result.append(lib)
+
+    return result

Added: cs/scons/scons-local-0.96.92/SCons/Scanner/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Scanner/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Scanner/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,399 @@
+"""SCons.Scanner
+
+The Scanner package for the SCons software construction utility.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Scanner/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import re
+import string
+
+import SCons.Node.FS
+import SCons.Sig
+import SCons.Util
+
+
+class _Null:
+    pass
+
+# This is used instead of None as a default argument value so None can be
+# used as an actual argument value.
+_null = _Null
+
+def Scanner(function, *args, **kw):
+    """Public interface factory function for creating different types
+    of Scanners based on the different types of "functions" that may
+    be supplied."""
+    if SCons.Util.is_Dict(function):
+        return apply(Selector, (function,) + args, kw)
+    else:
+        return apply(Base, (function,) + args, kw)
+
+
+class _Binder:
+    def __init__(self, bindval):
+        self._val = bindval
+    def __call__(self):
+        return self._val
+    def __str__(self):
+        return str(self._val)
+        #debug: return 'B<%s>'%str(self._val)
+
+BinderDict = {}
+
+def Binder(path):
+    try:
+        return BinderDict[path]
+    except KeyError:
+        b = _Binder(path)
+        BinderDict[path] = b
+        return b
+
+
+class FindPathDirs:
+    """A class to bind a specific *PATH variable name to a function that
+    will return all of the *path directories."""
+    def __init__(self, variable):
+        self.variable = variable
+    def __call__(self, env, dir, target=None, source=None, argument=None):
+        # The goal is that we've made caching this unnecessary
+        # because the caching takes place at higher layers.
+        try:
+            path = env[self.variable]
+        except KeyError:
+            return ()
+
+        path = env.subst_path(path, target=target, source=source)
+        path_tuple = tuple(env.fs.Rfindalldirs(path, dir))
+        return Binder(path_tuple)
+
+class Base:
+    """
+    The base class for dependency scanners.  This implements
+    straightforward, single-pass scanning of a single file.
+    """
+
+    if SCons.Memoize.use_memoizer:
+        __metaclass__ = SCons.Memoize.Memoized_Metaclass
+
+    def __init__(self,
+                 function,
+                 name = "NONE",
+                 argument = _null,
+                 skeys = [],
+                 path_function = None,
+                 node_class = SCons.Node.FS.Entry,
+                 node_factory = None,
+                 scan_check = None,
+                 recursive = None):
+        """
+        Construct a new scanner object given a scanner function.
+
+        'function' - a scanner function taking two or three
+        arguments and returning a list of strings.
+
+        'name' - a name for identifying this scanner object.
+
+        'argument' - an optional argument that, if specified, will be
+        passed to both the scanner function and the path_function.
+
+        'skeys' - an optional list argument that can be used to determine
+        which scanner should be used for a given Node. In the case of File
+        nodes, for example, the 'skeys' would be file suffixes.
+
+        'path_function' - a function that takes one to three arguments
+        (a construction environment, optional directory, and optional
+        argument for this instance) and returns a tuple of the
+        directories that can be searched for implicit dependency files.
+        May also return a callable() which is called with no args and
+        returns the tuple (supporting Bindable class).
+
+        'node_class' - the class of Nodes which this scan will return.
+        If node_class is None, then this scanner will not enforce any
+        Node conversion and will return the raw results from the
+        underlying scanner function.
+
+        'node_factory' - the factory function to be called to translate
+        the raw results returned by the scanner function into the
+        expected node_class objects.
+
+        'scan_check' - a function to be called to first check whether
+        this node really needs to be scanned.
+
+        'recursive' - specifies that this scanner should be invoked
+        recursively on all of the implicit dependencies it returns
+        (the canonical example being #include lines in C source files).
+        May be a callable, which will be called to filter the list
+        of nodes found to select a subset for recursive scanning
+        (the canonical example being only recursively scanning
+        subdirectories within a directory).
+
+        The scanner function's first argument will be a Node that should
+        be scanned for dependencies, the second argument will be an
+        Environment object, the third argument will be the tuple of paths
+        returned by the path_function, and the fourth argument will be
+        the value passed into 'argument', and the returned list should
+        contain the Nodes for all the direct dependencies of the file.
+
+        Examples:
+
+        s = Scanner(my_scanner_function)
+
+        s = Scanner(function = my_scanner_function)
+
+        s = Scanner(function = my_scanner_function, argument = 'foo')
+
+        """
+
+        # Note: this class could easily work with scanner functions that take
+        # something other than a filename as an argument (e.g. a database
+        # node) and a dependencies list that aren't file names. All that
+        # would need to be changed is the documentation.
+
+        self.function = function
+        self.path_function = path_function
+        self.name = name
+        self.argument = argument
+        self.skeys = skeys
+        self.node_class = node_class
+        self.node_factory = node_factory
+        self.scan_check = scan_check
+        if callable(recursive):
+            self.recurse_nodes = recursive
+        elif recursive:
+            self.recurse_nodes = self._recurse_all_nodes
+        else:
+            self.recurse_nodes = self._recurse_no_nodes
+
+    def path(self, env, dir=None, target=None, source=None):
+        if not self.path_function:
+            return ()
+        if not self.argument is _null:
+            return self.path_function(env, dir, target, source, self.argument)
+        else:
+            return self.path_function(env, dir, target, source)
+
+    def __call__(self, node, env, path = ()):
+        """
+        This method scans a single object. 'node' is the node
+        that will be passed to the scanner function, and 'env' is the
+        environment that will be passed to the scanner function. A list of
+        direct dependency nodes for the specified node will be returned.
+        """
+        if self.scan_check and not self.scan_check(node, env):
+            return []
+
+        if not self.argument is _null:
+            list = self.function(node, env, path, self.argument)
+        else:
+            list = self.function(node, env, path)
+        kw = {}
+        if hasattr(node, 'dir'):
+            kw['directory'] = node.dir
+        node_factory = env.get_factory(self.node_factory)
+        nodes = []
+        for l in list:
+            if self.node_class and not isinstance(l, self.node_class):
+                l = apply(node_factory, (l,), kw)
+            nodes.append(l)
+        return nodes
+
+    def __cmp__(self, other):
+        try:
+            return cmp(self.__dict__, other.__dict__)
+        except AttributeError:
+            # other probably doesn't have a __dict__
+            return cmp(self.__dict__, other)
+
+    def __hash__(self):
+        return id(self)
+
+    def __str__(self):
+        return self.name
+
+    def add_skey(self, skey):
+        """Add a skey to the list of skeys"""
+        self.skeys.append(skey)
+
+    def get_skeys(self, env=None):
+        if SCons.Util.is_String(self.skeys):
+            return env.subst_list(self.skeys)[0]
+        return self.skeys
+
+    def select(self, node):
+        return self
+
+    def _recurse_all_nodes(self, nodes):
+        return nodes
+
+    def _recurse_no_nodes(self, nodes):
+        return []
+
+    recurse_nodes = _recurse_no_nodes
+
+if SCons.Memoize.use_old_memoization():
+    _Base = Base
+    class Base(SCons.Memoize.Memoizer, _Base):
+        "Cache-backed version of Scanner Base"
+        def __init__(self, *args, **kw):
+            apply(_Base.__init__, (self,)+args, kw)
+            SCons.Memoize.Memoizer.__init__(self)
+
+
+class Selector(Base):
+    """
+    A class for selecting a more specific scanner based on the
+    scanner_key() (suffix) for a specific Node.
+    """
+    def __init__(self, dict, *args, **kw):
+        apply(Base.__init__, (self, None,)+args, kw)
+        self.dict = dict
+
+    def __call__(self, node, env, path = ()):
+        return self.select(node)(node, env, path)
+
+    def select(self, node):
+        try:
+            return self.dict[node.scanner_key()]
+        except KeyError:
+            return None
+
+    def add_scanner(self, skey, scanner):
+        self.dict[skey] = scanner
+
+
+class Current(Base):
+    """
+    A class for scanning files that are source files (have no builder)
+    or are derived files and are current (which implies that they exist,
+    either locally or in a repository).
+    """
+
+    def __init__(self, *args, **kw):
+        def current_check(node, env):
+            c = not node.has_builder() or node.current(env.get_calculator())
+            return c
+        kw['scan_check'] = current_check
+        apply(Base.__init__, (self,) + args, kw)
+
+class Classic(Current):
+    """
+    A Scanner subclass to contain the common logic for classic CPP-style
+    include scanning, but which can be customized to use different
+    regular expressions to find the includes.
+
+    Note that in order for this to work "out of the box" (without
+    overriding the find_include() and sort_key() methods), the regular
+    expression passed to the constructor must return the name of the
+    include file in group 0.
+    """
+
+    def __init__(self, name, suffixes, path_variable, regex, *args, **kw):
+
+        self.cre = re.compile(regex, re.M)
+
+        def _scan(node, env, path=(), self=self):
+            node = node.rfile()
+            if not node.exists():
+                return []
+            return self.scan(node, path)
+
+        kw['function'] = _scan
+        kw['path_function'] = FindPathDirs(path_variable)
+        kw['recursive'] = 1
+        kw['skeys'] = suffixes
+        kw['name'] = name
+
+        apply(Current.__init__, (self,) + args, kw)
+
+    def find_include(self, include, source_dir, path):
+        "__cacheable__"
+        if callable(path): path = path()
+        n = SCons.Node.FS.find_file(include, (source_dir,) + tuple(path))
+        return n, include
+
+    def sort_key(self, include):
+        return SCons.Node.FS._my_normcase(include)
+
+    def scan(self, node, path=()):
+        "__cacheable__"
+
+        # cache the includes list in node so we only scan it once:
+        if node.includes != None:
+            includes = node.includes
+        else:
+            includes = self.cre.findall(node.get_contents())
+            node.includes = includes
+
+        # This is a hand-coded DSU (decorate-sort-undecorate, or
+        # Schwartzian transform) pattern.  The sort key is the raw name
+        # of the file as specifed on the #include line (including the
+        # " or <, since that may affect what file is found), which lets
+        # us keep the sort order constant regardless of whether the file
+        # is actually found in a Repository or locally.
+        nodes = []
+        source_dir = node.get_dir()
+        for include in includes:
+            n, i = self.find_include(include, source_dir, path)
+
+            if n is None:
+                SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
+                                    "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node))
+            else:
+                sortkey = self.sort_key(include)
+                nodes.append((sortkey, n))
+
+        nodes.sort()
+        nodes = map(lambda pair: pair[1], nodes)
+        return nodes
+
+class ClassicCPP(Classic):
+    """
+    A Classic Scanner subclass which takes into account the type of
+    bracketing used to include the file, and uses classic CPP rules
+    for searching for the files based on the bracketing.
+
+    Note that in order for this to work, the regular expression passed
+    to the constructor must return the leading bracket in group 0, and
+    the contained filename in group 1.
+    """
+    def find_include(self, include, source_dir, path):
+        "__cacheable__"
+        if callable(path):
+            path = path()   #kwq: extend callable to find_file...
+
+        if include[0] == '"':
+            paths = Binder( (source_dir,) + tuple(path) )
+        else:
+            paths = Binder( tuple(path) + (source_dir,) )
+
+        n = SCons.Node.FS.find_file(include[1], paths)
+
+        return n, include[1]
+
+    def sort_key(self, include):
+        return SCons.Node.FS._my_normcase(string.join(include))

Added: cs/scons/scons-local-0.96.92/SCons/Script/Main.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Script/Main.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Script/Main.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,1354 @@
+"""SCons.Script
+
+This file implements the main() function used by the scons script.
+
+Architecturally, this *is* the scons script, and will likely only be
+called from the external "scons" wrapper.  Consequently, anything here
+should not be, or be considered, part of the build engine.  If it's
+something that we expect other software to want to use, it should go in
+some other module.  If it's specific to the "scons" script invocation,
+it goes here.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Script/Main.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import random
+import string
+import sys
+import time
+import traceback
+
+# Strip the script directory from sys.path() so on case-insensitive
+# (Windows) systems Python doesn't think that the "scons" script is the
+# "SCons" package.  Replace it with our own version directory so, if
+# if they're there, we pick up the right version of the build engine
+# modules.
+#sys.path = [os.path.join(sys.prefix,
+#                         'lib',
+#                         'scons-%d' % SCons.__version__)] + sys.path[1:]
+
+import SCons.Debug
+import SCons.Defaults
+import SCons.Environment
+import SCons.Errors
+import SCons.Job
+import SCons.Node
+import SCons.Node.FS
+from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError
+import SCons.SConf
+import SCons.Sig
+import SCons.Taskmaster
+import SCons.Util
+import SCons.Warnings
+
+#
+display = SCons.Util.display
+progress_display = SCons.Util.DisplayEngine()
+
+# Task control.
+#
+class BuildTask(SCons.Taskmaster.Task):
+    """An SCons build task."""
+    def display(self, message):
+        display('scons: ' + message)
+
+    def execute(self):
+        for target in self.targets:
+            if target.get_state() == SCons.Node.up_to_date: 
+                continue
+            if target.has_builder() and not hasattr(target.builder, 'status'):
+                if print_time:
+                    start_time = time.time()
+                SCons.Taskmaster.Task.execute(self)
+                if print_time:
+                    finish_time = time.time()
+                    global command_time
+                    command_time = command_time+finish_time-start_time
+                    print "Command execution time: %f seconds"%(finish_time-start_time)
+                break
+        else:
+            if self.top and target.has_builder():
+                display("scons: `%s' is up to date." % str(self.node))
+
+    def do_failed(self, status=2):
+        global exit_status
+        if ignore_errors:
+            SCons.Taskmaster.Task.executed(self)
+        elif keep_going_on_error:
+            SCons.Taskmaster.Task.fail_continue(self)
+            exit_status = status
+        else:
+            SCons.Taskmaster.Task.fail_stop(self)
+            exit_status = status
+            
+    def executed(self):
+        t = self.targets[0]
+        if self.top and not t.has_builder() and not t.side_effect:
+            if not t.exists():
+                sys.stderr.write("scons: *** Do not know how to make target `%s'." % t)
+                if not keep_going_on_error:
+                    sys.stderr.write("  Stop.")
+                sys.stderr.write("\n")
+                self.do_failed()
+            else:
+                print "scons: Nothing to be done for `%s'." % t
+                SCons.Taskmaster.Task.executed(self)
+        else:
+            SCons.Taskmaster.Task.executed(self)
+
+    def failed(self):
+        # Handle the failure of a build task.  The primary purpose here
+        # is to display the various types of Errors and Exceptions
+        # appropriately.
+        status = 2
+        exc_info = self.exc_info()
+        try:
+            t, e, tb = exc_info
+        except ValueError:
+            t, e = exc_info
+            tb = None
+        if t is None:
+            # The Taskmaster didn't record an exception for this Task;
+            # see if the sys module has one.
+            t, e = sys.exc_info()[:2]
+
+        def nodestring(n):
+            if not SCons.Util.is_List(n):
+                n = [ n ]
+            return string.join(map(str, n), ', ')
+
+        errfmt = "scons: *** [%s] %s\n"
+
+        if t == SCons.Errors.BuildError:
+            tname = nodestring(e.node)
+            errstr = e.errstr
+            if e.filename:
+                errstr = e.filename + ': ' + errstr
+            sys.stderr.write(errfmt % (tname, errstr))
+        elif t == SCons.Errors.TaskmasterException:
+            tname = nodestring(e.node)
+            sys.stderr.write(errfmt % (tname, e.errstr))
+            type, value, trace = e.exc_info
+            traceback.print_exception(type, value, trace)
+        elif t == SCons.Errors.ExplicitExit:
+            status = e.status
+            tname = nodestring(e.node)
+            errstr = 'Explicit exit, status %s' % status
+            sys.stderr.write(errfmt % (tname, errstr))
+        else:
+            if e is None:
+                e = t
+            s = str(e)
+            if t == SCons.Errors.StopError and not keep_going_on_error:
+                s = s + '  Stop.'
+            sys.stderr.write("scons: *** %s\n" % s)
+
+            if tb and print_stacktrace:
+                sys.stderr.write("scons: internal stack trace:\n")
+                traceback.print_tb(tb, file=sys.stderr)
+
+        self.do_failed(status)
+
+        self.exc_clear()
+
+    def postprocess(self):
+        if self.top:
+            t = self.targets[0]
+            if print_tree:
+                print
+                SCons.Util.print_tree(t, get_all_children)
+            if print_stree:
+                print
+                SCons.Util.print_tree(t, get_all_children, showtags=2)
+            if print_dtree:
+                print
+                SCons.Util.print_tree(t, get_derived_children)
+            if print_includes:
+                tree = t.render_include_tree()
+                if tree:
+                    print
+                    print tree
+        SCons.Taskmaster.Task.postprocess(self)
+
+    def make_ready(self):
+        """Make a task ready for execution"""
+        SCons.Taskmaster.Task.make_ready(self)
+        if self.out_of_date and print_explanations:
+            explanation = self.out_of_date[0].explain()
+            if explanation:
+                sys.stdout.write("scons: " + explanation)
+
+class CleanTask(SCons.Taskmaster.Task):
+    """An SCons clean task."""
+    def dir_index(self, directory):
+        dirname = lambda f, d=directory: os.path.join(d, f)
+        files = map(dirname, os.listdir(directory))
+
+        # os.listdir() isn't guaranteed to return files in any specific order,
+        # but some of the test code expects sorted output.
+        files.sort()
+        return files
+
+    def fs_delete(self, path, remove=1):
+        try:
+            if os.path.exists(path):
+                if os.path.isfile(path):
+                    if remove: os.unlink(path)
+                    display("Removed " + path)
+                elif os.path.isdir(path) and not os.path.islink(path):
+                    # delete everything in the dir
+                    for p in self.dir_index(path):
+                        if os.path.isfile(p):
+                            if remove: os.unlink(p)
+                            display("Removed " + p)
+                        else:
+                            self.fs_delete(p, remove)
+                    # then delete dir itself
+                    if remove: os.rmdir(path)
+                    display("Removed directory " + path)
+        except (IOError, OSError), e:
+            print "scons: Could not remove '%s':" % str(path), e.strerror
+
+    def show(self):
+        target = self.targets[0]
+        if (target.has_builder() or target.side_effect) and not target.noclean:
+            for t in self.targets:
+                if not t.isdir():
+                    display("Removed " + str(t))
+        if SCons.Environment.CleanTargets.has_key(target):
+            files = SCons.Environment.CleanTargets[target]
+            for f in files:
+                self.fs_delete(str(f), 0)
+
+    def remove(self):
+        target = self.targets[0]
+        if (target.has_builder() or target.side_effect) and not target.noclean:
+            for t in self.targets:
+                try:
+                    removed = t.remove()
+                except OSError, e:
+                    # An OSError may indicate something like a permissions
+                    # issue, an IOError would indicate something like
+                    # the file not existing.  In either case, print a
+                    # message and keep going to try to remove as many
+                    # targets aa possible.
+                    print "scons: Could not remove '%s':" % str(t), e.strerror
+                else:
+                    if removed:
+                        display("Removed " + str(t))
+        if SCons.Environment.CleanTargets.has_key(target):
+            files = SCons.Environment.CleanTargets[target]
+            for f in files:
+                self.fs_delete(str(f))
+
+    execute = remove
+
+    # Have the taskmaster arrange to "execute" all of the targets, because
+    # we'll figure out ourselves (in remove() or show() above) whether
+    # anything really needs to be done.
+    make_ready = SCons.Taskmaster.Task.make_ready_all
+
+    def prepare(self):
+        pass
+
+class QuestionTask(SCons.Taskmaster.Task):
+    """An SCons task for the -q (question) option."""
+    def prepare(self):
+        pass
+    
+    def execute(self):
+        if self.targets[0].get_state() != SCons.Node.up_to_date:
+            global exit_status
+            exit_status = 1
+            self.tm.stop()
+
+    def executed(self):
+        pass
+
+# Global variables
+
+keep_going_on_error = 0
+print_dtree = 0
+print_explanations = 0
+print_includes = 0
+print_objects = 0
+print_memoizer = 0
+print_stacktrace = 0
+print_stree = 0
+print_time = 0
+print_tree = 0
+ignore_errors = 0
+sconscript_time = 0
+command_time = 0
+exit_status = 0 # exit status, assume success by default
+repositories = []
+num_jobs = 1 # this is modifed by SConscript.SetJobs()
+
+diskcheck_all = SCons.Node.FS.diskcheck_types()
+diskcheck_option_set = None
+
+def diskcheck_convert(value):
+    if value is None:
+        return []
+    if not SCons.Util.is_List(value):
+        value = string.split(value, ',')
+    result = []
+    for v in map(string.lower, value):
+        if v == 'all':
+            result = diskcheck_all
+        elif v == 'none':
+            result = []
+        elif v in diskcheck_all:
+            result.append(v)
+        else:
+            raise ValueError, v
+    return result
+
+#
+class Stats:
+    def __init__(self):
+        self.stats = []
+        self.labels = []
+        self.append = self.do_nothing
+        self.print_stats = self.do_nothing
+    def enable(self, outfp):
+        self.outfp = outfp
+        self.append = self.do_append
+        self.print_stats = self.do_print
+    def do_nothing(self, *args, **kw):
+        pass
+
+class CountStats(Stats):
+    def do_append(self, label):
+        self.labels.append(label)
+        self.stats.append(SCons.Debug.fetchLoggedInstances())
+    def do_print(self):
+        stats_table = {}
+        for s in self.stats:
+            for n in map(lambda t: t[0], s):
+                stats_table[n] = [0, 0, 0, 0]
+        i = 0
+        for s in self.stats:
+            for n, c in s:
+                stats_table[n][i] = c
+            i = i + 1
+        keys = stats_table.keys()
+        keys.sort()
+        self.outfp.write("Object counts:\n")
+        pre = ["   "]
+        post = ["   %s\n"]
+        l = len(self.stats)
+        fmt1 = string.join(pre + [' %7s']*l + post, '')
+        fmt2 = string.join(pre + [' %7d']*l + post, '')
+        labels = self.labels[:l]
+        labels.append(("", "Class"))
+        self.outfp.write(fmt1 % tuple(map(lambda x: x[0], labels)))
+        self.outfp.write(fmt1 % tuple(map(lambda x: x[1], labels)))
+        for k in keys:
+            r = stats_table[k][:l] + [k]
+            self.outfp.write(fmt2 % tuple(r))
+
+count_stats = CountStats()
+
+class MemStats(Stats):
+    def do_append(self, label):
+        self.labels.append(label)
+        self.stats.append(SCons.Debug.memory())
+    def do_print(self):
+        fmt = 'Memory %-32s %12d\n'
+        for label, stats in map(None, self.labels, self.stats):
+            self.outfp.write(fmt % (label, stats))
+
+memory_stats = MemStats()
+
+# utility functions
+
+def get_all_children(node): return node.all_children()
+
+def get_derived_children(node):
+    children = node.all_children(None)
+    return filter(lambda x: x.has_builder(), children)
+
+def _scons_syntax_error(e):
+    """Handle syntax errors. Print out a message and show where the error
+    occurred.
+    """
+    etype, value, tb = sys.exc_info()
+    lines = traceback.format_exception_only(etype, value)
+    for line in lines:
+        sys.stderr.write(line+'\n')
+    sys.exit(2)
+
+def find_deepest_user_frame(tb):
+    """
+    Find the deepest stack frame that is not part of SCons.
+
+    Input is a "pre-processed" stack trace in the form
+    returned by traceback.extract_tb() or traceback.extract_stack()
+    """
+    
+    tb.reverse()
+
+    # find the deepest traceback frame that is not part
+    # of SCons:
+    for frame in tb:
+        filename = frame[0]
+        if string.find(filename, os.sep+'SCons'+os.sep) == -1:
+            return frame
+    return tb[0]
+
+def _scons_user_error(e):
+    """Handle user errors. Print out a message and a description of the
+    error, along with the line number and routine where it occured. 
+    The file and line number will be the deepest stack frame that is
+    not part of SCons itself.
+    """
+    global print_stacktrace
+    etype, value, tb = sys.exc_info()
+    if print_stacktrace:
+        traceback.print_exception(etype, value, tb)
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
+    sys.stderr.write("\nscons: *** %s\n" % value)
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+    sys.exit(2)
+
+def _scons_user_warning(e):
+    """Handle user warnings. Print out a message and a description of
+    the warning, along with the line number and routine where it occured.
+    The file and line number will be the deepest stack frame that is
+    not part of SCons itself.
+    """
+    etype, value, tb = sys.exc_info()
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
+    sys.stderr.write("\nscons: warning: %s\n" % e)
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+
+def _scons_internal_warning(e):
+    """Slightly different from _scons_user_warning in that we use the
+    *current call stack* rather than sys.exc_info() to get our stack trace.
+    This is used by the warnings framework to print warnings."""
+    filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
+    sys.stderr.write("\nscons: warning: %s\n" % e[0])
+    sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+
+def _scons_internal_error():
+    """Handle all errors but user errors. Print out a message telling
+    the user what to do in this case and print a normal trace.
+    """
+    print 'internal error'
+    traceback.print_exc()
+    sys.exit(2)
+
+def _varargs(option, parser):
+    value = None
+    if parser.rargs:
+        arg = parser.rargs[0]
+        if arg[0] != "-":
+            value = arg
+            del parser.rargs[0]
+    return value
+
+def _setup_warn(arg):
+    """The --warn option.  An argument to this option
+    should be of the form <warning-class> or no-<warning-class>.
+    The warning class is munged in order to get an actual class
+    name from the SCons.Warnings module to enable or disable.
+    The supplied <warning-class> is split on hyphens, each element
+    is captialized, then smushed back together.  Then the string
+    "SCons.Warnings." is added to the front and "Warning" is added
+    to the back to get the fully qualified class name.
+
+    For example, --warn=deprecated will enable the
+    SCons.Warnings.DeprecatedWarning class.
+
+    --warn=no-dependency will disable the
+    SCons.Warnings.DependencyWarning class.
+
+    As a special case, --warn=all and --warn=no-all
+    will enable or disable (respectively) the base
+    class of all warnings, which is SCons.Warning.Warning."""
+
+    elems = string.split(string.lower(arg), '-')
+    enable = 1
+    if elems[0] == 'no':
+        enable = 0
+        del elems[0]
+
+    if len(elems) == 1 and elems[0] == 'all':
+        class_name = "Warning"
+    else:
+        def _capitalize(s):
+            if s[:5] == "scons":
+                return "SCons" + s[5:]
+            else:
+                return string.capitalize(s)
+        class_name = string.join(map(_capitalize, elems), '') + "Warning"
+    try:
+        clazz = getattr(SCons.Warnings, class_name)
+    except AttributeError:
+        sys.stderr.write("No warning type: '%s'\n" % arg)
+    else:
+        if enable:
+            SCons.Warnings.enableWarningClass(clazz)
+        else:
+            SCons.Warnings.suppressWarningClass(clazz)
+
+def _SConstruct_exists(dirname=''):
+    """This function checks that an SConstruct file exists in a directory.
+    If so, it returns the path of the file. By default, it checks the
+    current directory.
+    """
+    global repositories
+    for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
+        sfile = os.path.join(dirname, file)
+        if os.path.isfile(sfile):
+            return sfile
+        if not os.path.isabs(sfile):
+            for rep in repositories:
+                if os.path.isfile(os.path.join(rep, sfile)):
+                    return sfile
+    return None
+
+def _set_globals(options):
+    global keep_going_on_error, ignore_errors
+    global count_stats, print_dtree
+    global print_explanations, print_includes, print_memoizer
+    global print_objects, print_stacktrace, print_stree
+    global print_time, print_tree
+    global memory_stats
+
+    keep_going_on_error = options.keep_going
+    try:
+        debug_values = options.debug
+        if debug_values is None:
+            debug_values = []
+    except AttributeError:
+        pass
+    else:
+        if "count" in debug_values:
+            count_stats.enable(sys.stdout)
+        if "dtree" in debug_values:
+            print_dtree = 1
+        if "explain" in debug_values:
+            print_explanations = 1
+        if "findlibs" in debug_values:
+            SCons.Scanner.Prog.print_find_libs = "findlibs"
+        if "includes" in debug_values:
+            print_includes = 1
+        if "memoizer" in debug_values:
+            print_memoizer = 1
+        if "memory" in debug_values:
+            memory_stats.enable(sys.stdout)
+        if "objects" in debug_values:
+            print_objects = 1
+        if "presub" in debug_values:
+            SCons.Action.print_actions_presub = 1
+        if "stacktrace" in debug_values:
+            print_stacktrace = 1
+        if "stree" in debug_values:
+            print_stree = 1
+        if "time" in debug_values:
+            print_time = 1
+        if "tree" in debug_values:
+            print_tree = 1
+    ignore_errors = options.ignore_errors
+
+def _create_path(plist):
+    path = '.'
+    for d in plist:
+        if os.path.isabs(d):
+            path = d
+        else:
+            path = path + '/' + d
+    return path
+
+
+class OptParser(OptionParser):
+    def __init__(self):
+        import __main__
+        import SCons
+        parts = ["SCons by Steven Knight et al.:\n"]
+        try:
+            parts.append("\tscript: v%s.%s, %s, by %s on %s\n" % (__main__.__version__,
+                                                                  __main__.__build__,
+                                                                  __main__.__date__,
+                                                                  __main__.__developer__,
+                                                                  __main__.__buildsys__))
+        except KeyboardInterrupt:
+            raise
+        except:
+            # On Windows there is no scons.py, so there is no
+            # __main__.__version__, hence there is no script version.
+            pass 
+        parts.append("\tengine: v%s.%s, %s, by %s on %s\n" % (SCons.__version__,
+                                                              SCons.__build__,
+                                                              SCons.__date__,
+                                                              SCons.__developer__,
+                                                              SCons.__buildsys__))
+        parts.append("Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation")
+        OptionParser.__init__(self, version=string.join(parts, ''),
+                              usage="usage: scons [OPTION] [TARGET] ...")
+
+        # options ignored for compatibility
+        def opt_ignore(option, opt, value, parser):
+            sys.stderr.write("Warning:  ignoring %s option\n" % opt)
+        self.add_option("-b", "-m", "-S", "-t", "--no-keep-going", "--stop",
+                        "--touch", action="callback", callback=opt_ignore,
+                        help="Ignored for compatibility.")
+
+        self.add_option('-c', '--clean', '--remove', action="store_true",
+                        dest="clean",
+                        help="Remove specified targets and dependencies.")
+
+        self.add_option('-C', '--directory', type="string", action = "append",
+                        metavar="DIR",
+                        help="Change to DIR before doing anything.")
+
+        self.add_option('--cache-disable', '--no-cache',
+                        action="store_true", dest='cache_disable', default=0,
+                        help="Do not retrieve built targets from CacheDir.")
+
+        self.add_option('--cache-force', '--cache-populate',
+                        action="store_true", dest='cache_force', default=0,
+                        help="Copy already-built targets into the CacheDir.")
+
+        self.add_option('--cache-show',
+                        action="store_true", dest='cache_show', default=0,
+                        help="Print build actions for files from CacheDir.")
+
+        config_options = ["auto", "force" ,"cache"]
+
+        def opt_config(option, opt, value, parser, c_options=config_options):
+            if value in c_options:
+                parser.values.config = value
+            else:
+                raise OptionValueError("Warning:  %s is not a valid config type" % value)
+        self.add_option('--config', action="callback", type="string",
+                        callback=opt_config, nargs=1, dest="config",
+                        metavar="MODE", default="auto",
+                        help="Controls Configure subsystem: "
+                             "%s." % string.join(config_options, ", "))
+
+        def opt_not_yet(option, opt, value, parser):
+            sys.stderr.write("Warning:  the %s option is not yet implemented\n" % opt)
+            sys.exit(0)
+        self.add_option('-d', action="callback",
+                        callback=opt_not_yet,
+                        help = "Print file dependency information.")
+        
+        self.add_option('-D', action="store_const", const=2, dest="climb_up",
+                        help="Search up directory tree for SConstruct,       "
+                             "build all Default() targets.")
+
+        debug_options = ["count", "dtree", "explain", "findlibs",
+                         "includes", "memoizer", "memory",
+                         "nomemoizer", "objects",
+                         "pdb", "presub", "stacktrace", "stree",
+                         "time", "tree"]
+
+        def opt_debug(option, opt, value, parser, debug_options=debug_options):
+            if value in debug_options:
+                try:
+                    if parser.values.debug is None:
+                        parser.values.debug = []
+                except AttributeError:
+                    parser.values.debug = []
+                parser.values.debug.append(value)
+            else:
+                raise OptionValueError("Warning:  %s is not a valid debug type" % value)
+        self.add_option('--debug', action="callback", type="string",
+                        callback=opt_debug, nargs=1, dest="debug",
+                        metavar="TYPE",
+                        help="Print various types of debugging information: "
+                             "%s." % string.join(debug_options, ", "))
+
+        def opt_diskcheck(option, opt, value, parser):
+            try:
+                global diskcheck_option_set
+                diskcheck_option_set = diskcheck_convert(value)
+                SCons.Node.FS.set_diskcheck(diskcheck_option_set)
+            except ValueError, e:
+                raise OptionValueError("Warning: `%s' is not a valid diskcheck type" % e)
+
+            
+        self.add_option('--diskcheck', action="callback", type="string",
+                        callback=opt_diskcheck, dest='diskcheck',
+                        metavar="TYPE",
+                        help="Enable specific on-disk checks.")
+
+        def opt_duplicate(option, opt, value, parser):
+            if not value in SCons.Node.FS.Valid_Duplicates:
+                raise OptionValueError("`%s' is not a valid duplication style." % value)
+            parser.values.duplicate = value
+            # Set the duplicate style right away so it can affect linking
+            # of SConscript files.
+            SCons.Node.FS.set_duplicate(value)
+        self.add_option('--duplicate', action="callback", type="string",
+                        callback=opt_duplicate, nargs=1, dest="duplicate",
+                        help="Set the preferred duplication methods. Must be one of "
+                        + string.join(SCons.Node.FS.Valid_Duplicates, ", "))
+
+        self.add_option('-f', '--file', '--makefile', '--sconstruct',
+                        action="append", nargs=1,
+                        help="Read FILE as the top-level SConstruct file.")
+
+        self.add_option('-h', '--help', action="store_true", default=0,
+                        dest="help_msg",
+                        help="Print defined help message, or this one.")
+
+        self.add_option("-H", "--help-options",
+                        action="help",
+                        help="Print this message and exit.")
+
+        self.add_option('-i', '--ignore-errors', action="store_true",
+                        default=0, dest='ignore_errors',
+                        help="Ignore errors from build actions.")
+
+        self.add_option('-I', '--include-dir', action="append",
+                        dest='include_dir', metavar="DIR",
+                        help="Search DIR for imported Python modules.")
+
+        self.add_option('--implicit-cache', action="store_true",
+                        dest='implicit_cache',
+                        help="Cache implicit dependencies")
+
+        self.add_option('--implicit-deps-changed', action="store_true",
+                        default=0, dest='implicit_deps_changed',
+                        help="Ignore cached implicit dependencies.")
+        self.add_option('--implicit-deps-unchanged', action="store_true",
+                        default=0, dest='implicit_deps_unchanged',
+                        help="Ignore changes in implicit dependencies.")
+
+        def opt_j(option, opt, value, parser):
+            value = int(value)
+            parser.values.num_jobs = value
+        self.add_option('-j', '--jobs', action="callback", type="int",
+                        callback=opt_j, metavar="N",
+                        help="Allow N jobs at once.")
+
+        self.add_option('-k', '--keep-going', action="store_true", default=0,
+                        dest='keep_going',
+                        help="Keep going when a target can't be made.")
+
+        self.add_option('--max-drift', type="int", action="store",
+                        dest='max_drift', metavar="N",
+                        help="Set maximum system clock drift to N seconds.")
+
+        self.add_option('-n', '--no-exec', '--just-print', '--dry-run',
+                        '--recon', action="store_true", dest='noexec',
+                        default=0, help="Don't build; just print commands.")
+
+        self.add_option('--profile', action="store",
+                        dest="profile_file", metavar="FILE",
+                        help="Profile SCons and put results in FILE.")
+
+        self.add_option('-q', '--question', action="store_true", default=0,
+                        help="Don't build; exit status says if up to date.")
+
+        self.add_option('-Q', dest='no_progress', action="store_true",
+                        default=0,
+                        help="Suppress \"Reading/Building\" progress messages.")
+
+        self.add_option('--random', dest="random", action="store_true",
+                        default=0, help="Build dependencies in random order.")
+
+        self.add_option('-s', '--silent', '--quiet', action="store_true",
+                        default=0, help="Don't print commands.")
+
+        self.add_option('--taskmastertrace', action="store",
+                        dest="taskmastertrace_file", metavar="FILE",
+                        help="Trace Node evaluation to FILE.")
+
+        self.add_option('-u', '--up', '--search-up', action="store_const",
+                        dest="climb_up", default=0, const=1,
+                        help="Search up directory tree for SConstruct,       "
+                             "build targets at or below current directory.")
+        self.add_option('-U', action="store_const", dest="climb_up",
+                        default=0, const=3,
+                        help="Search up directory tree for SConstruct,       "
+                             "build Default() targets from local SConscript.")
+
+        self.add_option("-v", "--version",
+                        action="version",
+                        help="Print the SCons version number and exit.")
+
+        self.add_option('--warn', '--warning', nargs=1, action="store",
+                        metavar="WARNING-SPEC",
+                        help="Enable or disable warnings.")
+
+        self.add_option('-Y', '--repository', nargs=1, action="append",
+                        help="Search REPOSITORY for source and target files.")
+
+        self.add_option('-e', '--environment-overrides', action="callback",
+                        callback=opt_not_yet,
+                        # help="Environment variables override makefiles."
+                        help=SUPPRESS_HELP)
+        self.add_option('-l', '--load-average', '--max-load', action="callback",
+                        callback=opt_not_yet, type="int", dest="load_average",
+                        # action="store",
+                        # help="Don't start multiple jobs unless load is below "
+                        #      "LOAD-AVERAGE."
+                        # type="int",
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-derived', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files that would be built."
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-actions', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files and build actions."
+                        help=SUPPRESS_HELP)
+        self.add_option('--list-where', action="callback",
+                        callback=opt_not_yet,
+                        # help="Don't build; list files and where defined."
+                        help=SUPPRESS_HELP)
+        self.add_option('-o', '--old-file', '--assume-old', action="callback",
+                        callback=opt_not_yet, type="string", dest="old_file",
+                        # help = "Consider FILE to be old; don't rebuild it."
+                        help=SUPPRESS_HELP)
+        self.add_option('--override', action="callback", dest="override",
+                        callback=opt_not_yet, type="string",
+                        # help="Override variables as specified in FILE."
+                        help=SUPPRESS_HELP)
+        self.add_option('-p', action="callback",
+                        callback=opt_not_yet,
+                        # help="Print internal environments/objects."
+                        help=SUPPRESS_HELP)
+        self.add_option('-r', '-R', '--no-builtin-rules',
+                        '--no-builtin-variables', action="callback",
+                        callback=opt_not_yet,
+                        # help="Clear default environments and variables."
+                        help=SUPPRESS_HELP)
+        self.add_option('-w', '--print-directory', action="callback",
+                        callback=opt_not_yet,
+                        # help="Print the current directory."
+                        help=SUPPRESS_HELP)
+        self.add_option('--no-print-directory', action="callback",
+                        callback=opt_not_yet,
+                        # help="Turn off -w, even if it was turned on implicitly."
+                        help=SUPPRESS_HELP)
+        self.add_option('--write-filenames', action="callback",
+                        callback=opt_not_yet, type="string", dest="write_filenames",
+                        # help="Write all filenames examined into FILE."
+                        help=SUPPRESS_HELP)
+        self.add_option('-W', '--what-if', '--new-file', '--assume-new',
+                        dest="new_file",
+                        action="callback", callback=opt_not_yet, type="string",
+                        # help="Consider FILE to be changed."
+                        help=SUPPRESS_HELP)
+        self.add_option('--warn-undefined-variables', action="callback",
+                        callback=opt_not_yet,
+                        # help="Warn when an undefined variable is referenced."
+                        help=SUPPRESS_HELP)
+
+    def parse_args(self, args=None, values=None):
+        opt, arglist = OptionParser.parse_args(self, args, values)
+        if opt.implicit_deps_changed or opt.implicit_deps_unchanged:
+            opt.implicit_cache = 1
+        return opt, arglist
+
+class SConscriptSettableOptions:
+    """This class wraps an OptParser instance and provides
+    uniform access to options that can be either set on the command
+    line or from a SConscript file. A value specified on the command
+    line always overrides a value set in a SConscript file.
+    Not all command line options are SConscript settable, and the ones
+    that are must be explicitly added to settable dictionary and optionally
+    validated and coerced in the set() method."""
+    
+    def __init__(self, options):
+        self.options = options
+
+        # This dictionary stores the defaults for all the SConscript
+        # settable options, as well as indicating which options
+        # are SConscript settable. 
+        self.settable = {'num_jobs':1,
+                         'max_drift':SCons.Node.FS.default_max_drift,
+                         'implicit_cache':0,
+                         'clean':0,
+                         'duplicate':'hard-soft-copy',
+                         'diskcheck':diskcheck_all}
+
+    def get(self, name):
+        if not self.settable.has_key(name):
+            raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
+        if hasattr(self.options, name) and getattr(self.options, name) is not None:
+            return getattr(self.options, name)
+        else:
+            return self.settable[name]
+
+    def set(self, name, value):
+        if not self.settable.has_key(name):
+            raise SCons.Errors.UserError, "This option is not settable from a SConscript file: %s"%name
+
+        if name == 'num_jobs':
+            try:
+                value = int(value)
+                if value < 1:
+                    raise ValueError
+            except ValueError:
+                raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
+        elif name == 'max_drift':
+            try:
+                value = int(value)
+            except ValueError:
+                raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
+        elif name == 'duplicate':
+            try:
+                value = str(value)
+            except ValueError:
+                raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
+            if not value in SCons.Node.FS.Valid_Duplicates:
+                raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
+            # Set the duplicate stye right away so it can affect linking
+            # of SConscript files.
+            SCons.Node.FS.set_duplicate(value)
+        elif name == 'diskcheck':
+            try:
+                value = diskcheck_convert(value)
+            except ValueError, v:
+                raise SCons.Errors.UserError, "Not a valid diskcheck value: %s"%v
+            if not diskcheck_option_set:
+                SCons.Node.FS.set_diskcheck(value)
+
+        self.settable[name] = value
+    
+
+def _main(args, parser):
+    # Here's where everything really happens.
+
+    # First order of business:  set up default warnings and and then
+    # handle the user's warning options, so we can warn about anything
+    # that happens appropriately.
+    default_warnings = [ SCons.Warnings.CorruptSConsignWarning,
+                         SCons.Warnings.DeprecatedWarning,
+                         SCons.Warnings.DuplicateEnvironmentWarning,
+                         SCons.Warnings.MissingSConscriptWarning,
+                         SCons.Warnings.NoParallelSupportWarning,
+                         SCons.Warnings.MisleadingKeywordsWarning, ]
+    for warning in default_warnings:
+        SCons.Warnings.enableWarningClass(warning)
+    SCons.Warnings._warningOut = _scons_internal_warning
+    if options.warn:
+        _setup_warn(options.warn)
+
+    # Next, we want to create the FS object that represents the outside
+    # world's file system, as that's central to a lot of initialization.
+    # To do this, however, we need to be in the directory from which we
+    # want to start everything, which means first handling any relevant
+    # options that might cause us to chdir somewhere (-C, -D, -U, -u).
+    if options.directory:
+        cdir = _create_path(options.directory)
+        try:
+            os.chdir(cdir)
+        except OSError:
+            sys.stderr.write("Could not change directory to %s\n" % cdir)
+
+    # The SConstruct file may be in a repository, so initialize those
+    # before we start the search up our path for one.
+    global repositories
+    if options.repository:
+        repositories.extend(options.repository)
+
+    target_top = None
+    if options.climb_up:
+        target_top = '.'  # directory to prepend to targets
+        script_dir = os.getcwd()  # location of script
+        while script_dir and not _SConstruct_exists(script_dir):
+            script_dir, last_part = os.path.split(script_dir)
+            if last_part:
+                target_top = os.path.join(last_part, target_top)
+            else:
+                script_dir = ''
+        if script_dir:
+            display("scons: Entering directory `%s'" % script_dir)
+            os.chdir(script_dir)
+
+    # Now that we're in the top-level SConstruct directory, go ahead
+    # and initialize the FS object that represents the file system,
+    # and make it the build engine default.
+    fs = SCons.Node.FS.default_fs = SCons.Node.FS.FS()
+
+    for rep in repositories:
+        fs.Repository(rep)
+
+    # Now that we have the FS object, the next order of business is to
+    # check for an SConstruct file (or other specified config file).
+    # If there isn't one, we can bail before doing any more work.
+    scripts = []
+    if options.file:
+        scripts.extend(options.file)
+    if not scripts:
+        sfile = _SConstruct_exists()
+        if sfile:
+            scripts.append(sfile)
+
+    if not scripts:
+        if options.help_msg:
+            # There's no SConstruct, but they specified -h.
+            # Give them the options usage now, before we fail
+            # trying to read a non-existent SConstruct file.
+            parser.print_help()
+            sys.exit(0)
+        raise SCons.Errors.UserError, "No SConstruct file found."
+
+    if scripts[0] == "-":
+        d = fs.getcwd()
+    else:
+        d = fs.File(scripts[0]).dir
+    fs.set_SConstruct_dir(d)
+
+    # Now that we have the FS object and it's intialized, set up (most
+    # of) the rest of the options.
+    global ssoptions
+    ssoptions = SConscriptSettableOptions(options)
+
+    _set_globals(options)
+    SCons.Node.implicit_cache = options.implicit_cache
+    SCons.Node.implicit_deps_changed = options.implicit_deps_changed
+    SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
+    if options.noexec:
+        SCons.SConf.dryrun = 1
+        SCons.Action.execute_actions = None
+        CleanTask.execute = CleanTask.show
+    if options.question:
+        SCons.SConf.dryrun = 1
+    SCons.SConf.SetCacheMode(options.config)
+    SCons.SConf.SetProgressDisplay(progress_display)
+
+    if options.no_progress or options.silent:
+        progress_display.set_mode(0)
+    if options.silent:
+        display.set_mode(0)
+    if options.silent:
+        SCons.Action.print_actions = None
+    if options.cache_disable:
+        def disable(self): pass
+        fs.CacheDir = disable
+    if options.cache_force:
+        fs.cache_force = 1
+    if options.cache_show:
+        fs.cache_show = 1
+
+    if options.include_dir:
+        sys.path = options.include_dir + sys.path
+
+    # That should cover (most of) the options.  Next, set up the variables
+    # that hold command-line arguments, so the SConscript files that we
+    # read and execute have access to them.
+    targets = []
+    xmit_args = []
+    for a in args:
+        if '=' in a:
+            xmit_args.append(a)
+        else:
+            targets.append(a)
+    SCons.Script._Add_Targets(targets)
+    SCons.Script._Add_Arguments(xmit_args)
+
+    class Unbuffered:
+        def __init__(self, file):
+            self.file = file
+        def write(self, arg):
+            self.file.write(arg)
+            self.file.flush()
+        def __getattr__(self, attr):
+            return getattr(self.file, attr)
+
+    sys.stdout = Unbuffered(sys.stdout)
+
+    memory_stats.append('before reading SConscript files:')
+    count_stats.append(('pre-', 'read'))
+
+    progress_display("scons: Reading SConscript files ...")
+
+    start_time = time.time()
+    try:
+        for script in scripts:
+            SCons.Script._SConscript._SConscript(fs, script)
+    except SCons.Errors.StopError, e:
+        # We had problems reading an SConscript file, such as it
+        # couldn't be copied in to the BuildDir.  Since we're just
+        # reading SConscript files and haven't started building
+        # things yet, stop regardless of whether they used -i or -k
+        # or anything else.
+        global exit_status
+        sys.stderr.write("scons: *** %s  Stop.\n" % e)
+        exit_status = 2
+        sys.exit(exit_status)
+    global sconscript_time
+    sconscript_time = time.time() - start_time
+    SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
+    progress_display("scons: done reading SConscript files.")
+
+    # Tell the Node.FS subsystem that we're all done reading the
+    # SConscript files and calling Repository() and BuildDir() and the
+    # like, so it can go ahead and start memoizing the string values of
+    # file system nodes.
+    SCons.Node.FS.save_strings(1)
+
+    memory_stats.append('after reading SConscript files:')
+    count_stats.append(('post-', 'read'))
+
+    fs.chdir(fs.Top)
+
+    if options.help_msg:
+        help_text = SCons.Script.help_text
+        if help_text is None:
+            # They specified -h, but there was no Help() inside the
+            # SConscript files.  Give them the options usage.
+            parser.print_help(sys.stdout)
+        else:
+            print help_text
+            print "Use scons -H for help about command-line options."
+        sys.exit(0)
+
+    # Now that we've read the SConscripts we can set the options
+    # that are SConscript settable:
+    SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
+    SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
+    fs.set_max_drift(ssoptions.get('max_drift'))
+
+    lookup_top = None
+    if targets or SCons.Script.BUILD_TARGETS != SCons.Script._build_plus_default:
+        # They specified targets on the command line or modified
+        # BUILD_TARGETS in the SConscript file(s), so if they used -u,
+        # -U or -D, we have to look up targets relative to the top,
+        # but we build whatever they specified.
+        if target_top:
+            lookup_top = fs.Dir(target_top)
+            target_top = None
+
+        targets = SCons.Script.BUILD_TARGETS
+    else:
+        # There are no targets specified on the command line,
+        # so if they used -u, -U or -D, we may have to restrict
+        # what actually gets built.
+        d = None
+        if target_top:
+            if options.climb_up == 1:
+                # -u, local directory and below
+                target_top = fs.Dir(target_top)
+                lookup_top = target_top
+            elif options.climb_up == 2:
+                # -D, all Default() targets
+                target_top = None
+                lookup_top = None
+            elif options.climb_up == 3:
+                # -U, local SConscript Default() targets
+                target_top = fs.Dir(target_top)
+                def check_dir(x, target_top=target_top):
+                    if hasattr(x, 'cwd') and not x.cwd is None:
+                        cwd = x.cwd.srcnode()
+                        return cwd == target_top
+                    else:
+                        # x doesn't have a cwd, so it's either not a target,
+                        # or not a file, so go ahead and keep it as a default
+                        # target and let the engine sort it out:
+                        return 1                
+                d = filter(check_dir, SCons.Script.DEFAULT_TARGETS)
+                SCons.Script.DEFAULT_TARGETS[:] = d
+                target_top = None
+                lookup_top = None
+
+        targets = SCons.Script._Get_Default_Targets(d, fs)
+
+    if not targets:
+        sys.stderr.write("scons: *** No targets specified and no Default() targets found.  Stop.\n")
+        sys.exit(2)
+
+    def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
+        if isinstance(x, SCons.Node.Node):
+            node = x
+        else:
+            node = None
+            # Why would ltop be None? Unfortunately this happens.
+            if ltop == None: ltop = ''
+            # Curdir becomes important when SCons is called with -u, -C,
+            # or similar option that changes directory, and so the paths
+            # of targets given on the command line need to be adjusted.
+            curdir = os.path.join(os.getcwd(), str(ltop))
+            for lookup in SCons.Node.arg2nodes_lookups:
+                node = lookup(x, curdir=curdir)
+                if node != None:
+                    break
+            if node is None:
+                node = fs.Entry(x, directory=ltop, create=1)
+        if ttop and not node.is_under(ttop):
+            if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
+                node = ttop
+            else:
+                node = None
+        return node
+
+    nodes = filter(None, map(Entry, targets))
+
+    task_class = BuildTask      # default action is to build targets
+    opening_message = "Building targets ..."
+    closing_message = "done building targets."
+    if keep_going_on_error:
+        failure_message = "done building targets (errors occurred during build)."
+    else:
+        failure_message = "building terminated because of errors."
+    if options.question:
+        task_class = QuestionTask
+    try:
+        if ssoptions.get('clean'):
+            task_class = CleanTask
+            opening_message = "Cleaning targets ..."
+            closing_message = "done cleaning targets."
+            if keep_going_on_error:
+                closing_message = "done cleaning targets (errors occurred during clean)."
+            else:
+                failure_message = "cleaning terminated because of errors."
+    except AttributeError:
+        pass
+
+    if options.random:
+        def order(dependencies):
+            """Randomize the dependencies."""
+            # This is cribbed from the implementation of
+            # random.shuffle() in Python 2.X.
+            d = dependencies
+            for i in xrange(len(d)-1, 0, -1):
+                j = int(random.random() * (i+1))
+                d[i], d[j] = d[j], d[i]
+            return d
+    else:
+        def order(dependencies):
+            """Leave the order of dependencies alone."""
+            return dependencies
+
+    progress_display("scons: " + opening_message)
+    if options.taskmastertrace_file == '-':
+        tmtrace = sys.stdout
+    elif options.taskmastertrace_file:
+        tmtrace = open(options.taskmastertrace_file, 'wb')
+    else:
+        tmtrace = None
+    taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)
+
+    nj = ssoptions.get('num_jobs')
+    jobs = SCons.Job.Jobs(nj, taskmaster)
+    if nj > 1 and jobs.num_jobs == 1:
+        msg = "parallel builds are unsupported by this version of Python;\n" + \
+              "\tignoring -j or num_jobs option.\n"
+        SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
+
+    memory_stats.append('before building targets:')
+    count_stats.append(('pre-', 'build'))
+
+    try:
+        jobs.run()
+    finally:
+        if exit_status:
+            progress_display("scons: " + failure_message)
+        else:
+            progress_display("scons: " + closing_message)
+        if not options.noexec:
+            SCons.SConsign.write()
+
+    memory_stats.append('after building targets:')
+    count_stats.append(('post-', 'build'))
+
+def _exec_main():
+    all_args = sys.argv[1:]
+    try:
+        all_args = string.split(os.environ['SCONSFLAGS']) + all_args
+    except KeyError:
+            # it's OK if there's no SCONSFLAGS
+            pass
+    parser = OptParser()
+    global options
+    options, args = parser.parse_args(all_args)
+    if type(options.debug) == type([]) and "pdb" in options.debug:
+        import pdb
+        pdb.Pdb().runcall(_main, args, parser)
+    elif options.profile_file:
+        import profile
+        prof = profile.Profile()
+        try:
+            prof.runcall(_main, args, parser)
+        except SystemExit:
+            pass
+        prof.dump_stats(options.profile_file)
+    else:
+        _main(args, parser)
+
+def main():
+    global exit_status
+    
+    try:
+        _exec_main()
+    except SystemExit, s:
+        if s:
+            exit_status = s
+    except KeyboardInterrupt:
+        print "Build interrupted."
+        sys.exit(2)
+    except SyntaxError, e:
+        _scons_syntax_error(e)
+    except SCons.Errors.InternalError:
+        _scons_internal_error()
+    except SCons.Errors.UserError, e:
+        _scons_user_error(e)
+    except:
+        # An exception here is likely a builtin Python exception Python
+        # code in an SConscript file.  Show them precisely what the
+        # problem was and where it happened.
+        SCons.Script._SConscript.SConscript_exception()
+        sys.exit(2)
+
+    memory_stats.print_stats()
+    count_stats.print_stats()
+
+    if print_objects:
+        SCons.Debug.listLoggedInstances('*')
+        #SCons.Debug.dumpLoggedInstances('*')
+
+    if print_memoizer:
+        print "Memoizer (memory cache) hits and misses:"
+        SCons.Memoize.Dump()
+
+    # Dump any development debug info that may have been enabled.
+    # These are purely for internal debugging during development, so
+    # there's no need to control them with --debug= options; they're
+    # controlled by changing the source code.
+    SCons.Debug.dump_caller_counts()
+    SCons.Taskmaster.dump_stats()
+
+    if print_time:
+        total_time = time.time()-SCons.Script.start_time
+        scons_time = total_time-sconscript_time-command_time
+        print "Total build time: %f seconds"%total_time
+        print "Total SConscript file execution time: %f seconds"%sconscript_time
+        print "Total SCons execution time: %f seconds"%scons_time
+        print "Total command execution time: %f seconds"%command_time
+
+    sys.exit(exit_status)

Added: cs/scons/scons-local-0.96.92/SCons/Script/SConscript.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Script/SConscript.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Script/SConscript.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,577 @@
+"""SCons.Script.SConscript
+
+This module defines the Python API provided to SConscript and SConstruct
+files.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Script/SConscript.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Environment
+import SCons.Errors
+import SCons.Node
+import SCons.Node.Alias
+import SCons.Node.FS
+import SCons.Options
+import SCons.Platform
+import SCons.SConf
+import SCons.Script.Main
+import SCons.Tool
+import SCons.Util
+
+import os
+import os.path
+import re
+import string
+import sys
+import traceback
+import types
+import UserList
+
+# The following variables used to live in this module.  Some
+# SConscript files out there may have referred to them directly as
+# SCons.Script.SConscript.*.  This is now supported by some special
+# handling towards the bottom of the SConscript.__init__.py module.
+#Arguments = {}
+#ArgList = []
+#BuildTargets = TargetList()
+#CommandLineTargets = []
+#DefaultTargets = []
+
+launch_dir = os.path.abspath(os.curdir)
+
+GlobalDict = None
+
+# global exports set by Export():
+global_exports = {}
+
+# chdir flag
+sconscript_chdir = 1
+
+def get_calling_namespaces():
+    """Return the locals and globals for the function that called
+    into this module in the current call stack."""
+    try: 1/0
+    except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
+
+    # Find the first frame that *isn't* from this file.  This means
+    # that we expect all of the SCons frames that implement an Export()
+    # or SConscript() call to be in this file, so that we can identify
+    # the first non-Script.SConscript frame as the user's local calling
+    # environment, and the locals and globals dictionaries from that
+    # frame as the calling namespaces.  See the comment below preceding
+    # the DefaultEnvironmentCall block for even more explanation.
+    while frame.f_globals.get("__name__") == __name__:
+        frame = frame.f_back
+
+    return frame.f_locals, frame.f_globals
+
+
+def compute_exports(exports):
+    """Compute a dictionary of exports given one of the parameters
+    to the Export() function or the exports argument to SConscript()."""
+
+    loc, glob = get_calling_namespaces()
+
+    retval = {}
+    try:
+        for export in exports:
+            if SCons.Util.is_Dict(export):
+                retval.update(export)
+            else:
+                try:
+                    retval[export] = loc[export]
+                except KeyError:
+                    retval[export] = glob[export]
+    except KeyError, x:
+        raise SCons.Errors.UserError, "Export of non-existent variable '%s'"%x
+
+    return retval
+
+class Frame:
+    """A frame on the SConstruct/SConscript call stack"""
+    def __init__(self, fs, exports, sconscript):
+        self.globals = BuildDefaultGlobals()
+        self.retval = None
+        self.prev_dir = fs.getcwd()
+        self.exports = compute_exports(exports)  # exports from the calling SConscript
+        # make sure the sconscript attr is a Node.
+        if isinstance(sconscript, SCons.Node.Node):
+            self.sconscript = sconscript
+        else:
+            self.sconscript = fs.File(str(sconscript))
+
+# the SConstruct/SConscript call stack:
+call_stack = []
+
+# For documentation on the methods in this file, see the scons man-page
+
+def Return(*vars):
+    retval = []
+    try:
+        for var in vars:
+            for v in string.split(var):
+                retval.append(call_stack[-1].globals[v])
+    except KeyError, x:
+        raise SCons.Errors.UserError, "Return of non-existent variable '%s'"%x
+
+    if len(retval) == 1:
+        call_stack[-1].retval = retval[0]
+    else:
+        call_stack[-1].retval = tuple(retval)
+
+
+stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :)
+
+def _SConscript(fs, *files, **kw):
+    top = fs.Top
+    sd = fs.SConstruct_dir.rdir()
+    exports = kw.get('exports', [])
+
+    # evaluate each SConscript file
+    results = []
+    for fn in files:
+        call_stack.append(Frame(fs, exports, fn))
+        old_sys_path = sys.path
+        try:
+            SCons.Script.sconscript_reading = SCons.Script.sconscript_reading + 1
+            if fn == "-":
+                exec sys.stdin in call_stack[-1].globals
+            else:
+                if isinstance(fn, SCons.Node.Node):
+                    f = fn
+                else:
+                    f = fs.File(str(fn))
+                _file_ = None
+
+                # Change directory to the top of the source
+                # tree to make sure the os's cwd and the cwd of
+                # fs match so we can open the SConscript.
+                fs.chdir(top, change_os_dir=1)
+                if f.rexists():
+                    _file_ = open(f.rstr(), "r")
+                elif f.has_src_builder():
+                    # The SConscript file apparently exists in a source
+                    # code management system.  Build it, but then clear
+                    # the builder so that it doesn't get built *again*
+                    # during the actual build phase.
+                    f.build()
+                    f.builder_set(None)
+                    if f.exists():
+                        _file_ = open(str(f), "r")
+                if _file_:
+                    # Chdir to the SConscript directory.  Use a path
+                    # name relative to the SConstruct file so that if
+                    # we're using the -f option, we're essentially
+                    # creating a parallel SConscript directory structure
+                    # in our local directory tree.
+                    #
+                    # XXX This is broken for multiple-repository cases
+                    # where the SConstruct and SConscript files might be
+                    # in different Repositories.  For now, cross that
+                    # bridge when someone comes to it.
+                    ldir = fs.Dir(f.dir.get_path(sd))
+                    try:
+                        fs.chdir(ldir, change_os_dir=sconscript_chdir)
+                    except OSError:
+                        # There was no local directory, so we should be
+                        # able to chdir to the Repository directory.
+                        # Note that we do this directly, not through
+                        # fs.chdir(), because we still need to
+                        # interpret the stuff within the SConscript file
+                        # relative to where we are logically.
+                        fs.chdir(ldir, change_os_dir=0)
+                        os.chdir(f.rfile().dir.get_abspath())
+
+                    # Append the SConscript directory to the beginning
+                    # of sys.path so Python modules in the SConscript
+                    # directory can be easily imported.
+                    sys.path = [ f.dir.get_abspath() ] + sys.path
+
+                    # This is the magic line that actually reads up
+                    # and executes the stuff in the SConscript file.
+                    # The locals for this frame contain the special
+                    # bottom-of-the-stack marker so that any
+                    # exceptions that occur when processing this
+                    # SConscript can base the printed frames at this
+                    # level and not show SCons internals as well.
+                    call_stack[-1].globals.update({stack_bottom:1})
+                    exec _file_ in call_stack[-1].globals
+                else:
+                    SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning,
+                             "Ignoring missing SConscript '%s'" % f.path)
+
+        finally:
+            SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1
+            sys.path = old_sys_path
+            frame = call_stack.pop()
+            try:
+                fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
+            except OSError:
+                # There was no local directory, so chdir to the
+                # Repository directory.  Like above, we do this
+                # directly.
+                fs.chdir(frame.prev_dir, change_os_dir=0)
+                rdir = frame.prev_dir.rdir()
+                rdir._create()  # Make sure there's a directory there.
+                os.chdir(rdir.get_abspath())
+
+            results.append(frame.retval)
+
+    # if we only have one script, don't return a tuple
+    if len(results) == 1:
+        return results[0]
+    else:
+        return tuple(results)
+
+def SConscript_exception(file=sys.stderr):
+    """Print an exception stack trace just for the SConscript file(s).
+    This will show users who have Python errors where the problem is,
+    without cluttering the output with all of the internal calls leading
+    up to where we exec the SConscript."""
+    exc_type, exc_value, exc_tb = sys.exc_info()
+    tb = exc_tb
+    while tb and not tb.tb_frame.f_locals.has_key(stack_bottom):
+        tb = tb.tb_next
+    if not tb:
+        # We did not find our exec statement, so this was actually a bug
+        # in SCons itself.  Show the whole stack.
+        tb = exc_tb
+    stack = traceback.extract_tb(tb)
+    type = str(exc_type)
+    if type[:11] == "exceptions.":
+        type = type[11:]
+    file.write('%s: %s:\n' % (type, exc_value))
+    for fname, line, func, text in stack:
+        file.write('  File "%s", line %d:\n' % (fname, line))
+        file.write('    %s\n' % text)
+
+def annotate(node):
+    """Annotate a node with the stack frame describing the
+    SConscript file and line number that created it."""
+    tb = exc_tb = sys.exc_info()[2]
+    while tb and not tb.tb_frame.f_locals.has_key(stack_bottom):
+        tb = tb.tb_next
+    if not tb:
+        # We did not find any exec of an SConscript file: what?!
+        raise InternalError, "could not find SConscript stack frame"
+    node.creator = traceback.extract_stack(tb)[0]
+
+# The following line would cause each Node to be annotated using the
+# above function.  Unfortunately, this is a *huge* performance hit, so
+# leave this disabled until we find a more efficient mechanism.
+#SCons.Node.Annotate = annotate
+
+class SConsEnvironment(SCons.Environment.Base):
+    """An Environment subclass that contains all of the methods that
+    are particular to the wrapper SCons interface and which aren't
+    (or shouldn't be) part of the build engine itself.
+
+    Note that not all of the methods of this class have corresponding
+    global functions, there are some private methods.
+    """
+
+    #
+    # Private methods of an SConsEnvironment.
+    #
+    def _exceeds_version(self, major, minor, v_major, v_minor):
+        """Return 1 if 'major' and 'minor' are greater than the version
+        in 'v_major' and 'v_minor', and 0 otherwise."""
+        return (major > v_major or (major == v_major and minor > v_minor))
+
+    def _get_major_minor_revision(self, version_string):
+        """Split a version string into major, minor and (optionally)
+        revision parts.
+
+        This is complicated by the fact that a version string can be
+        something like 3.2b1."""
+        version = string.split(string.split(version_string, ' ')[0], '.')
+        v_major = int(version[0])
+        v_minor = int(re.match('\d+', version[1]).group())
+        if len(version) >= 3:
+            v_revision = int(re.match('\d+', version[2]).group())
+        else:
+            v_revision = 0
+        return v_major, v_minor, v_revision
+
+    def _get_SConscript_filenames(self, ls, kw):
+        """
+        Convert the parameters passed to # SConscript() calls into a list
+        of files and export variables.  If the parameters are invalid,
+        throws SCons.Errors.UserError. Returns a tuple (l, e) where l
+        is a list of SConscript filenames and e is a list of exports.
+        """
+        exports = []
+
+        if len(ls) == 0:
+            try:
+                dirs = kw["dirs"]
+            except KeyError:
+                raise SCons.Errors.UserError, \
+                      "Invalid SConscript usage - no parameters"
+
+            if not SCons.Util.is_List(dirs):
+                dirs = [ dirs ]
+            dirs = map(str, dirs)
+
+            name = kw.get('name', 'SConscript')
+
+            files = map(lambda n, name = name: os.path.join(n, name), dirs)
+
+        elif len(ls) == 1:
+
+            files = ls[0]
+
+        elif len(ls) == 2:
+
+            files   = ls[0]
+            exports = self.Split(ls[1])
+
+        else:
+
+            raise SCons.Errors.UserError, \
+                  "Invalid SConscript() usage - too many arguments"
+
+        if not SCons.Util.is_List(files):
+            files = [ files ]
+
+        if kw.get('exports'):
+            exports.extend(self.Split(kw['exports']))
+
+        build_dir = kw.get('build_dir')
+        if build_dir:
+            if len(files) != 1:
+                raise SCons.Errors.UserError, \
+                    "Invalid SConscript() usage - can only specify one SConscript with a build_dir"
+            duplicate = kw.get('duplicate', 1)
+            src_dir = kw.get('src_dir')
+            if not src_dir:
+                src_dir, fname = os.path.split(str(files[0]))
+            else:
+                if not isinstance(src_dir, SCons.Node.Node):
+                    src_dir = self.fs.Dir(src_dir)
+                fn = files[0]
+                if not isinstance(fn, SCons.Node.Node):
+                    fn = self.fs.File(fn)
+                if fn.is_under(src_dir):
+                    # Get path relative to the source directory.
+                    fname = fn.get_path(src_dir)
+                else:
+                    # Fast way to only get the terminal path component of a Node.
+                    fname = fn.get_path(fn.dir)
+            self.fs.BuildDir(build_dir, src_dir, duplicate)
+            files = [os.path.join(str(build_dir), fname)]
+
+        return (files, exports)
+
+    #
+    # Public methods of an SConsEnvironment.  These get
+    # entry points in the global name space so they can be called
+    # as global functions.
+    #
+
+    def Configure(self, *args, **kw):
+        if not SCons.Script.sconscript_reading:
+            raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
+        kw['_depth'] = kw.get('_depth', 0) + 1
+        return apply(SCons.Environment.Base.Configure, (self,)+args, kw)
+
+    def Default(self, *targets):
+        SCons.Script._Set_Default_Targets(self, targets)
+
+    def EnsureSConsVersion(self, major, minor, revision=0):
+        """Exit abnormally if the SCons version is not late enough."""
+        scons_ver = self._get_major_minor_revision(SCons.__version__)
+        if scons_ver < (major, minor, revision):
+            if revision:
+                scons_ver_string = '%d.%d.%d' % (major, minor, revision)
+            else:
+                scons_ver_string = '%d.%d' % (major, minor)
+            print "SCons %s or greater required, but you have SCons %s" % \
+                  (scons_ver_string, SCons.__version__)
+            sys.exit(2)
+
+    def EnsurePythonVersion(self, major, minor):
+        """Exit abnormally if the Python version is not late enough."""
+        try:
+            v_major, v_minor, v_micro, release, serial = sys.version_info
+            python_ver = (v_major, v_minor)
+        except AttributeError:
+            python_ver = self._get_major_minor_revision(sys.version)[:2]
+        if python_ver < (major, minor):
+            v = string.split(sys.version, " ", 1)[0]
+            print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
+            sys.exit(2)
+
+    def Exit(self, value=0):
+        sys.exit(value)
+
+    def Export(self, *vars):
+        for var in vars:
+            global_exports.update(compute_exports(self.Split(var)))
+
+    def GetLaunchDir(self):
+        global launch_dir
+        return launch_dir
+
+    def GetOption(self, name):
+        name = self.subst(name)
+        return SCons.Script.Main.ssoptions.get(name)
+
+    def Help(self, text):
+        text = self.subst(text, raw=1)
+        SCons.Script.HelpFunction(text)
+
+    def Import(self, *vars):
+        try:
+            frame = call_stack[-1]
+            globals = frame.globals
+            exports = frame.exports
+            for var in vars:
+                var = self.Split(var)
+                for v in var:
+                    if v == '*':
+                        globals.update(global_exports)
+                        globals.update(exports)
+                    else:
+                        if exports.has_key(v):
+                            globals[v] = exports[v]
+                        else:
+                            globals[v] = global_exports[v]
+        except KeyError,x:
+            raise SCons.Errors.UserError, "Import of non-existent variable '%s'"%x
+
+    def SConscript(self, *ls, **kw):
+        def subst_element(x, subst=self.subst):
+            if SCons.Util.is_List(x):
+                x = map(subst, x)
+            else:
+                x = subst(x)
+            return x
+        ls = map(subst_element, ls)
+        subst_kw = {}
+        for key, val in kw.items():
+            if SCons.Util.is_String(val):
+                val = self.subst(val)
+            elif SCons.Util.is_List(val):
+                result = []
+                for v in val:
+                    if SCons.Util.is_String(v):
+                        v = self.subst(v)
+                    result.append(v)
+                val = result
+            subst_kw[key] = val
+
+        files, exports = self._get_SConscript_filenames(ls, subst_kw)
+
+        return apply(_SConscript, [self.fs,] + files, {'exports' : exports})
+
+    def SConscriptChdir(self, flag):
+        global sconscript_chdir
+        sconscript_chdir = flag
+
+    def SetOption(self, name, value):
+        name = self.subst(name)
+        SCons.Script.Main.ssoptions.set(name, value)
+
+#
+#
+#
+SCons.Environment.Environment = SConsEnvironment
+
+def Configure(*args, **kw):
+    if not SCons.Script.sconscript_reading:
+        raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
+    kw['_depth'] = 1
+    return apply(SCons.SConf.SConf, args, kw)
+
+# It's very important that the DefaultEnvironmentCall() class stay in this
+# file, with the get_calling_namespaces() function, the compute_exports()
+# function, the Frame class and the SConsEnvironment.Export() method.
+# These things make up the calling stack leading up to the actual global
+# Export() or SConscript() call that the user issued.  We want to allow
+# users to export local variables that they define, like so:
+#
+#       def func():
+#           x = 1
+#           Export('x')
+#
+# To support this, the get_calling_namespaces() function assumes that
+# the *first* stack frame that's not from this file is the local frame
+# for the Export() or SConscript() call.
+
+_DefaultEnvironmentProxy = None
+
+def get_DefaultEnvironmentProxy():
+    global _DefaultEnvironmentProxy
+    if not _DefaultEnvironmentProxy:
+        default_env = SCons.Defaults.DefaultEnvironment()
+        _DefaultEnvironmentProxy = SCons.Environment.NoSubstitutionProxy(default_env)
+    return _DefaultEnvironmentProxy
+
+class DefaultEnvironmentCall:
+    """A class that implements "global function" calls of
+    Environment methods by fetching the specified method from the
+    DefaultEnvironment's class.  Note that this uses an intermediate
+    proxy class instead of calling the DefaultEnvironment method
+    directly so that the proxy can override the subst() method and
+    thereby prevent expansion of construction variables (since from
+    the user's point of view this was called as a global function,
+    with no associated construction environment)."""
+    def __init__(self, method_name, subst=0):
+        self.method_name = method_name
+        if subst:
+            self.factory = SCons.Defaults.DefaultEnvironment
+        else:
+            self.factory = get_DefaultEnvironmentProxy
+    def __call__(self, *args, **kw):
+        env = self.factory()
+        method = getattr(env, self.method_name)
+        return apply(method, args, kw)
+
+
+def BuildDefaultGlobals():
+    """
+    Create a dictionary containing all the default globals for
+    SConstruct and SConscript files.
+    """
+
+    global GlobalDict
+    if GlobalDict is None:
+        GlobalDict = {}
+
+        import SCons.Script
+        d = SCons.Script.__dict__
+        def not_a_module(m, d=d, mtype=type(SCons.Script)):
+             return type(d[m]) != mtype
+        for m in filter(not_a_module, dir(SCons.Script)):
+             GlobalDict[m] = d[m]
+
+    return GlobalDict.copy()

Added: cs/scons/scons-local-0.96.92/SCons/Script/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Script/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Script/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,370 @@
+"""SCons.Script
+
+This file implements the main() function used by the scons script.
+
+Architecturally, this *is* the scons script, and will likely only be
+called from the external "scons" wrapper.  Consequently, anything here
+should not be, or be considered, part of the build engine.  If it's
+something that we expect other software to want to use, it should go in
+some other module.  If it's specific to the "scons" script invocation,
+it goes here.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Script/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import time
+start_time = time.time()
+
+import os
+import string
+import sys
+import UserList
+
+# Special chicken-and-egg handling of the "--debug=memoizer"
+# and "--debug=nomemoizer" flags:
+#
+# SCons.Memoize contains a metaclass implementation that affects how
+# the other classes are instantiated.  The Memoizer handles optional
+# counting of the hits and misses by using a different, parallel set of
+# functions, so we don't slow down normal operation any more than we
+# have to.  We can also tell it disable memoization completely.
+#
+# If we wait to enable the counting or disable memoization completely
+# until we've parsed the command line options normally, it will be too
+# late, because the Memoizer will have already analyzed the classes
+# that it's Memoizing and bound the (non-counting) versions of the
+# functions.  So we have to use a special-case, up-front check for
+# the "--debug=memoizer" and "--debug=nomemoizer" flags and do what's
+# appropriate before we import any of the other modules that use it.
+_args = sys.argv + string.split(os.environ.get('SCONSFLAGS', ''))
+if "--debug=memoizer" in _args:
+    import SCons.Memoize
+    SCons.Memoize.EnableCounting()
+if "--debug=nomemoizer" in _args:
+    import SCons.Memoize
+    SCons.Memoize.DisableMemoization()
+del _args
+
+import SCons.Action
+import SCons.Builder
+import SCons.Environment
+import SCons.Node.FS
+import SCons.Options
+import SCons.Platform
+import SCons.Scanner
+import SCons.SConf
+import SCons.Tool
+import SCons.Util
+import SCons.Defaults
+
+import Main
+
+main                    = Main.main
+
+# The following are global class definitions and variables that used to
+# live directly in this module back before 0.96.90, when it contained
+# a lot of code.  Some SConscript files in widely-distributed packages
+# (Blender is the specific example) actually reached into SCons.Script
+# directly to use some of these.  Rather than break those SConscript
+# files, we're going to propagate these names into the SCons.Script
+# namespace here.
+#
+# Some of these are commented out because it's *really* unlikely anyone
+# used them, but we're going to leave the comment here to try to make
+# it obvious what to do if the situation arises.
+BuildTask               = Main.BuildTask
+CleanTask               = Main.CleanTask
+QuestionTask            = Main.QuestionTask
+#PrintHelp               = Main.PrintHelp
+OptParser               = Main.OptParser
+SConscriptSettableOptions = Main.SConscriptSettableOptions
+
+keep_going_on_error     = Main.keep_going_on_error
+print_dtree             = Main.print_dtree
+print_explanations      = Main.print_explanations
+print_includes          = Main.print_includes
+print_objects           = Main.print_objects
+print_time              = Main.print_time
+print_tree              = Main.print_tree
+memory_stats            = Main.memory_stats
+ignore_errors           = Main.ignore_errors
+#sconscript_time         = Main.sconscript_time
+#command_time            = Main.command_time
+#exit_status             = Main.exit_status
+#profiling               = Main.profiling
+repositories            = Main.repositories
+#num_jobs                = Main.num_jobs     # settable by SConscript.SetJobs()
+
+#
+import SConscript
+_SConscript = SConscript
+
+call_stack              = _SConscript.call_stack
+
+#
+Action                  = SCons.Action.Action
+BoolOption              = SCons.Options.BoolOption
+Builder                 = SCons.Builder.Builder
+Configure               = _SConscript.Configure
+EnumOption              = SCons.Options.EnumOption
+Environment             = SCons.Environment.Environment
+ListOption              = SCons.Options.ListOption
+PackageOption           = SCons.Options.PackageOption
+PathOption              = SCons.Options.PathOption
+Platform                = SCons.Platform.Platform
+Return                  = _SConscript.Return
+Scanner                 = SCons.Scanner.Base
+Tool                    = SCons.Tool.Tool
+WhereIs                 = SCons.Util.WhereIs
+
+# Action factories.
+Chmod                   = SCons.Defaults.Chmod
+Copy                    = SCons.Defaults.Copy
+Delete                  = SCons.Defaults.Delete
+Mkdir                   = SCons.Defaults.Mkdir
+Move                    = SCons.Defaults.Move
+Touch                   = SCons.Defaults.Touch
+
+# Pre-made, public scanners.
+CScanner                = SCons.Tool.CScanner
+DScanner                = SCons.Tool.DScanner
+DirScanner              = SCons.Defaults.DirScanner
+ProgramScanner          = SCons.Tool.ProgramScanner
+SourceFileScanner       = SCons.Tool.SourceFileScanner
+
+# Functions we might still convert to Environment methods.
+CScan                   = SCons.Defaults.CScan
+DefaultEnvironment      = SCons.Defaults.DefaultEnvironment
+
+# Other variables we provide.
+class TargetList(UserList.UserList):
+    def _do_nothing(self, *args, **kw):
+        pass
+    def _add_Default(self, list):
+        self.extend(list)
+    def _clear(self):
+        del self[:]
+
+ARGUMENTS               = {}
+ARGLIST                 = []
+BUILD_TARGETS           = TargetList()
+COMMAND_LINE_TARGETS    = []
+DEFAULT_TARGETS         = []
+
+# BUILD_TARGETS can be modified in the SConscript files.  If so, we
+# want to treat the modified BUILD_TARGETS list as if they specified
+# targets on the command line.  To do that, though, we need to know if
+# BUILD_TARGETS was modified through "official" APIs or by hand.  We do
+# this by updating two lists in parallel, the documented BUILD_TARGETS
+# list, above, and this internal _build_plus_default targets list which
+# should only have "official" API changes.  Then Script/Main.py can
+# compare these two afterwards to figure out if the user added their
+# own targets to BUILD_TARGETS.
+_build_plus_default = TargetList()
+
+def _Add_Arguments(alist):
+    for arg in alist:
+        a, b = string.split(arg, '=', 1)
+        ARGUMENTS[a] = b
+        ARGLIST.append((a, b))
+
+def _Add_Targets(tlist):
+    if tlist:
+        COMMAND_LINE_TARGETS.extend(tlist)
+        BUILD_TARGETS.extend(tlist)
+        BUILD_TARGETS._add_Default = BUILD_TARGETS._do_nothing
+        BUILD_TARGETS._clear = BUILD_TARGETS._do_nothing
+        _build_plus_default.extend(tlist)
+        _build_plus_default._add_Default = _build_plus_default._do_nothing
+        _build_plus_default._clear = _build_plus_default._do_nothing
+
+def _Set_Default_Targets_Has_Been_Called(d, fs):
+    return DEFAULT_TARGETS
+
+def _Set_Default_Targets_Has_Not_Been_Called(d, fs):
+    if d is None:
+        d = [fs.Dir('.')]
+    return d
+
+_Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called
+
+def _Set_Default_Targets(env, tlist):
+    global DEFAULT_TARGETS
+    global _Get_Default_Targets
+    _Get_Default_Targets = _Set_Default_Targets_Has_Been_Called
+    for t in tlist:
+        if t is None:
+            # Delete the elements from the list in-place, don't
+            # reassign an empty list to DEFAULT_TARGETS, so that the
+            # variables will still point to the same object we point to.
+            del DEFAULT_TARGETS[:]
+            BUILD_TARGETS._clear()
+            _build_plus_default._clear()
+        elif isinstance(t, SCons.Node.Node):
+            DEFAULT_TARGETS.append(t)
+            BUILD_TARGETS._add_Default([t])
+            _build_plus_default._add_Default([t])
+        else:
+            nodes = env.arg2nodes(t, env.fs.Entry)
+            DEFAULT_TARGETS.extend(nodes)
+            BUILD_TARGETS._add_Default(nodes)
+            _build_plus_default._add_Default(nodes)
+
+#
+help_text = None
+
+def HelpFunction(text):
+    global help_text
+    if SCons.Script.help_text is None:
+        SCons.Script.help_text = text
+    else:
+        help_text = help_text + text
+
+#
+# Will be non-zero if we are reading an SConscript file.
+sconscript_reading = 0
+
+#
+def Options(files=None, args=ARGUMENTS):
+    return SCons.Options.Options(files, args)
+
+# The list of global functions to add to the SConscript name space
+# that end up calling corresponding methods or Builders in the
+# DefaultEnvironment().
+GlobalDefaultEnvironmentFunctions = [
+    # Methods from the SConsEnvironment class, above.
+    'Default',
+    'EnsurePythonVersion',
+    'EnsureSConsVersion',
+    'Exit',
+    'Export',
+    'GetLaunchDir',
+    'GetOption',
+    'Help',
+    'Import',
+    #'SConscript', is handled separately, below.
+    'SConscriptChdir',
+    'SetOption',
+
+    # Methods from the Environment.Base class.
+    'AddPostAction',
+    'AddPreAction',
+    'Alias',
+    'AlwaysBuild',
+    'BuildDir',
+    'CacheDir',
+    'Clean',
+    #The Command() method is handled separately, below.
+    'Depends',
+    'Dir',
+    'NoClean',
+    'Entry',
+    'Execute',
+    'File',
+    'FindFile',
+    'Flatten',
+    'GetBuildPath',
+    'Ignore',
+    'Install',
+    'InstallAs',
+    'Literal',
+    'Local',
+    'ParseDepends',
+    'Precious',
+    'Repository',
+    'SConsignFile',
+    'SideEffect',
+    'SourceCode',
+    'SourceSignatures',
+    'Split',
+    'TargetSignatures',
+    'Value',
+]
+
+GlobalDefaultBuilders = [
+    # Supported builders.
+    'CFile',
+    'CXXFile',
+    'DVI',
+    'Jar',
+    'Java',
+    'JavaH',
+    'Library',
+    'M4',
+    'MSVSProject',
+    'Object',
+    'PCH',
+    'PDF',
+    'PostScript',
+    'Program',
+    'RES',
+    'RMIC',
+    'SharedLibrary',
+    'SharedObject',
+    'StaticLibrary',
+    'StaticObject',
+    'Tar',
+    'TypeLibrary',
+    'Zip',
+]
+
+for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
+    exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))
+
+# There are a handful of variables that used to live in the
+# Script/SConscript.py module that some SConscript files out there were
+# accessing directly as SCons.Script.SConscript.*.  The problem is that
+# "SConscript" in this namespace is no longer a module, it's a global
+# function call--or more precisely, an object that implements a global
+# function call through the default Environment.  Nevertheless, we can
+# maintain backwards compatibility for SConscripts that were reaching in
+# this way by hanging some attributes off the "SConscript" object here.
+SConscript = _SConscript.DefaultEnvironmentCall('SConscript')
+
+SConscript.Arguments = ARGUMENTS
+SConscript.ArgList = ARGLIST
+SConscript.BuildTargets = BUILD_TARGETS
+SConscript.CommandLineTargets = COMMAND_LINE_TARGETS
+SConscript.DefaultTargets = DEFAULT_TARGETS
+
+# The global Command() function must be handled differently than the
+# global functions for other construction environment methods because
+# we want people to be able to use Actions that must expand $TARGET
+# and $SOURCE later, when (and if) the Action is invoked to build
+# the target(s).  We do this with the subst=1 argument, which creates
+# a DefaultEnvironmentCall instance that wraps up a normal default
+# construction environment that performs variable substitution, not a
+# proxy that doesn't.
+#
+# There's a flaw here, though, because any other $-variables on a command
+# line will *also* be expanded, each to a null string, but that should
+# only be a problem in the unusual case where someone was passing a '$'
+# on a command line and *expected* the $ to get through to the shell
+# because they were calling Command() and not env.Command()...  This is
+# unlikely enough that we're going to leave this as is and cross that
+# bridge if someone actually comes to it.
+Command = _SConscript.DefaultEnvironmentCall('Command', subst=1)

Added: cs/scons/scons-local-0.96.92/SCons/Sig/MD5.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Sig/MD5.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Sig/MD5.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,104 @@
+"""SCons.Sig.MD5
+
+The MD5 signature package for the SCons software construction
+utility.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Sig/MD5.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import imp
+import string
+
+# Force Python to load the builtin "md5" module.  If we do this with a
+# normal import statement, then case-insensitive systems (Windows) get
+# confused and thinks there's a case mismatch with *this* MD5.py module.
+file, name, desc = imp.find_module('md5')
+try:
+    md5 = imp.load_module('md5', file, name, desc)
+finally:
+    if file:
+        file.close()
+
+def current(new, old):
+    """Return whether a new signature is up-to-date with
+    respect to an old signature.
+    """
+    return new == old
+
+try:
+    md5.new('').hexdigest
+except AttributeError:
+    # The md5 objects created by the module have no native hexdigest()
+    # method (*cough* 1.5.2 *cough*) so provide an equivalent.
+    class new_md5:
+        def __init__(self, s):
+            self.m = md5.new(str(s))
+        #def copy(self):
+        #    return self.m.copy()
+        def digest(self):
+            return self.m.digest()
+        def hexdigest(self):
+            h = string.hexdigits
+            r = ''
+            for c in self.m.digest():
+                i = ord(c)
+                r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+            return r
+        def update(self, s):
+            return self.m.update(s)
+
+else:
+    new_md5 = lambda s: md5.new(str(s))
+
+def collect(signatures):
+    """
+    Collect a list of signatures into an aggregate signature.
+
+    signatures - a list of signatures
+    returns - the aggregate signature
+    """
+    if len(signatures) == 1:
+        return signatures[0]
+    else:
+        return new_md5(string.join(signatures, ', ')).hexdigest()
+
+def signature(obj):
+    """Generate a signature for an object
+    """
+    try:
+        gc = obj.get_contents
+    except AttributeError:
+        raise AttributeError, "unable to fetch contents of '%s'" % str(obj)
+    return new_md5(gc()).hexdigest()
+
+def to_string(signature):
+    """Convert a signature to a string"""
+    return signature
+
+def from_string(string):
+    """Convert a string to a signature"""
+    return string

Added: cs/scons/scons-local-0.96.92/SCons/Sig/TimeStamp.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Sig/TimeStamp.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Sig/TimeStamp.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,75 @@
+"""SCons.Sig.TimeStamp
+
+The TimeStamp signature package for the SCons software construction
+utility.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Sig/TimeStamp.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+def current(new, old):
+    """Return whether a new timestamp is up-to-date with
+    respect to an old timestamp.
+    """
+    return not old is None and new <= old
+
+def collect(signatures):
+    """
+    Collect a list of timestamps, returning
+    the most-recent timestamp from the list 
+
+    signatures - a list of timestamps
+    returns - the most recent timestamp
+    """
+
+    if len(signatures) == 0:
+        return 0
+    elif len(signatures) == 1:
+        return signatures[0]
+    else:
+        return max(signatures)
+
+def signature(obj):
+    """Generate a timestamp.
+    """
+    return obj.get_timestamp()
+
+def to_string(signature):
+    """Convert a timestamp to a string"""
+    return str(signature)
+
+def from_string(string):
+    """Convert a string to a timestamp"""
+    try:
+        return int(string)
+    except ValueError:
+        # if the signature isn't an int, then
+        # the user probably just switched from
+        # MD5 signatures to timestamp signatures,
+        # so ignore the error:
+        return None
+
+

Added: cs/scons/scons-local-0.96.92/SCons/Sig/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Sig/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Sig/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,53 @@
+"""SCons.Sig
+
+The Signature package for the scons software construction utility.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Sig/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+try:
+    import MD5
+    default_module = MD5
+except ImportError:
+    import TimeStamp
+    default_module = TimeStamp
+
+class Calculator:
+    """
+    Encapsulates signature calculations and .sconsign file generating
+    for the build engine.
+    """
+
+    def __init__(self, module=default_module):
+        """
+        Initialize the calculator.
+
+        module - the signature module to use for signature calculations
+        """
+        self.module = module
+
+default_calc = Calculator()

Added: cs/scons/scons-local-0.96.92/SCons/Subst.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Subst.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Subst.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,834 @@
+"""SCons.Subst
+
+SCons string substitution.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Subst.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import __builtin__
+import re
+import string
+import types
+import UserList
+
+import SCons.Errors
+
+from SCons.Util import is_String, is_List
+
+# Indexed by the SUBST_* constants below.
+_strconv = [SCons.Util.to_String,
+            SCons.Util.to_String,
+            SCons.Util.to_String_for_signature]
+
+class Literal:
+    """A wrapper for a string.  If you use this object wrapped
+    around a string, then it will be interpreted as literal.
+    When passed to the command interpreter, all special
+    characters will be escaped."""
+    def __init__(self, lstr):
+        self.lstr = lstr
+
+    def __str__(self):
+        return self.lstr
+
+    def escape(self, escape_func):
+        return escape_func(self.lstr)
+
+    def for_signature(self):
+        return self.lstr
+
+    def is_literal(self):
+        return 1
+
+class SpecialAttrWrapper:
+    """This is a wrapper for what we call a 'Node special attribute.'
+    This is any of the attributes of a Node that we can reference from
+    Environment variable substitution, such as $TARGET.abspath or
+    $SOURCES[1].filebase.  We implement the same methods as Literal
+    so we can handle special characters, plus a for_signature method,
+    such that we can return some canonical string during signature
+    calculation to avoid unnecessary rebuilds."""
+
+    def __init__(self, lstr, for_signature=None):
+        """The for_signature parameter, if supplied, will be the
+        canonical string we return from for_signature().  Else
+        we will simply return lstr."""
+        self.lstr = lstr
+        if for_signature:
+            self.forsig = for_signature
+        else:
+            self.forsig = lstr
+
+    def __str__(self):
+        return self.lstr
+
+    def escape(self, escape_func):
+        return escape_func(self.lstr)
+
+    def for_signature(self):
+        return self.forsig
+
+    def is_literal(self):
+        return 1
+
+def quote_spaces(arg):
+    """Generic function for putting double quotes around any string that
+    has white space in it."""
+    if ' ' in arg or '\t' in arg:
+        return '"%s"' % arg
+    else:
+        return str(arg)
+
+class CmdStringHolder(SCons.Util.UserString):
+    """This is a special class used to hold strings generated by
+    scons_subst() and scons_subst_list().  It defines a special method
+    escape().  When passed a function with an escape algorithm for a
+    particular platform, it will return the contained string with the
+    proper escape sequences inserted.
+
+    This should really be a subclass of UserString, but that module
+    doesn't exist in Python 1.5.2."""
+    def __init__(self, cmd, literal=None):
+        SCons.Util.UserString.__init__(self, cmd)
+        self.literal = literal
+
+    def is_literal(self):
+        return self.literal
+
+    def escape(self, escape_func, quote_func=quote_spaces):
+        """Escape the string with the supplied function.  The
+        function is expected to take an arbitrary string, then
+        return it with all special characters escaped and ready
+        for passing to the command interpreter.
+
+        After calling this function, the next call to str() will
+        return the escaped string.
+        """
+
+        if self.is_literal():
+            return escape_func(self.data)
+        elif ' ' in self.data or '\t' in self.data:
+            return quote_func(self.data)
+        else:
+            return self.data
+
+def escape_list(list, escape_func):
+    """Escape a list of arguments by running the specified escape_func
+    on every object in the list that has an escape() method."""
+    def escape(obj, escape_func=escape_func):
+        try:
+            e = obj.escape
+        except AttributeError:
+            return obj
+        else:
+            return e(escape_func)
+    return map(escape, list)
+
+class NLWrapper:
+    """A wrapper class that delays turning a list of sources or targets
+    into a NodeList until it's needed.  The specified function supplied
+    when the object is initialized is responsible for turning raw nodes
+    into proxies that implement the special attributes like .abspath,
+    .source, etc.  This way, we avoid creating those proxies just
+    "in case" someone is going to use $TARGET or the like, and only
+    go through the trouble if we really have to.
+
+    In practice, this might be a wash performance-wise, but it's a little
+    cleaner conceptually...
+    """
+    
+    def __init__(self, list, func):
+        self.list = list
+        self.func = func
+    def _return_nodelist(self):
+        return self.nodelist
+    def _gen_nodelist(self):
+        list = self.list
+        if list is None:
+            list = []
+        elif not is_List(list):
+            list = [list]
+        # The map(self.func) call is what actually turns
+        # a list into appropriate proxies.
+        self.nodelist = SCons.Util.NodeList(map(self.func, list))
+        self._create_nodelist = self._return_nodelist
+        return self.nodelist
+    _create_nodelist = _gen_nodelist
+    
+
+class Targets_or_Sources(UserList.UserList):
+    """A class that implements $TARGETS or $SOURCES expansions by in turn
+    wrapping a NLWrapper.  This class handles the different methods used
+    to access the list, calling the NLWrapper to create proxies on demand.
+
+    Note that we subclass UserList.UserList purely so that the is_List()
+    function will identify an object of this class as a list during
+    variable expansion.  We're not really using any UserList.UserList
+    methods in practice.
+    """
+    def __init__(self, nl):
+        self.nl = nl
+    def __getattr__(self, attr):
+        nl = self.nl._create_nodelist()
+        return getattr(nl, attr)
+    def __getitem__(self, i):
+        nl = self.nl._create_nodelist()
+        return nl[i]
+    def __getslice__(self, i, j):
+        nl = self.nl._create_nodelist()
+        i = max(i, 0); j = max(j, 0)
+        return nl[i:j]
+    def __str__(self):
+        nl = self.nl._create_nodelist()
+        return str(nl)
+    def __repr__(self):
+        nl = self.nl._create_nodelist()
+        return repr(nl)
+
+class Target_or_Source:
+    """A class that implements $TARGET or $SOURCE expansions by in turn
+    wrapping a NLWrapper.  This class handles the different methods used
+    to access an individual proxy Node, calling the NLWrapper to create
+    a proxy on demand.
+    """
+    def __init__(self, nl):
+        self.nl = nl
+    def __getattr__(self, attr):
+        nl = self.nl._create_nodelist()
+        try:
+            nl0 = nl[0]
+        except IndexError:
+            # If there is nothing in the list, then we have no attributes to
+            # pass through, so raise AttributeError for everything.
+            raise AttributeError, "NodeList has no attribute: %s" % attr
+        return getattr(nl0, attr)
+    def __str__(self):
+        nl = self.nl._create_nodelist()
+        if nl:
+            return str(nl[0])
+        return ''
+    def __repr__(self):
+        nl = self.nl._create_nodelist()
+        if nl:
+            return repr(nl[0])
+        return ''
+
+def subst_dict(target, source):
+    """Create a dictionary for substitution of special
+    construction variables.
+
+    This translates the following special arguments:
+
+    target - the target (object or array of objects),
+             used to generate the TARGET and TARGETS
+             construction variables
+
+    source - the source (object or array of objects),
+             used to generate the SOURCES and SOURCE
+             construction variables
+    """
+    dict = {}
+
+    if target:
+        tnl = NLWrapper(target, lambda x: x.get_subst_proxy())
+        dict['TARGETS'] = Targets_or_Sources(tnl)
+        dict['TARGET'] = Target_or_Source(tnl)
+    else:
+        dict['TARGETS'] = None
+        dict['TARGET'] = None
+
+    if source:
+        def get_src_subst_proxy(node):
+            try:
+                rfile = node.rfile
+            except AttributeError:
+                pass
+            else:
+                node = rfile()
+            return node.get_subst_proxy()
+        snl = NLWrapper(source, get_src_subst_proxy)
+        dict['SOURCES'] = Targets_or_Sources(snl)
+        dict['SOURCE'] = Target_or_Source(snl)
+    else:
+        dict['SOURCES'] = None
+        dict['SOURCE'] = None
+
+    return dict
+
+# Constants for the "mode" parameter to scons_subst_list() and
+# scons_subst().  SUBST_RAW gives the raw command line.  SUBST_CMD
+# gives a command line suitable for passing to a shell.  SUBST_SIG
+# gives a command line appropriate for calculating the signature
+# of a command line...if this changes, we should rebuild.
+SUBST_CMD = 0
+SUBST_RAW = 1
+SUBST_SIG = 2
+
+_rm = re.compile(r'\$[()]')
+_remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)')
+
+# Indexed by the SUBST_* constants above.
+_regex_remove = [ _rm, None, _remove ]
+
+# Regular expressions for splitting strings and handling substitutions,
+# for use by the scons_subst() and scons_subst_list() functions:
+#
+# The first expression compiled matches all of the $-introduced tokens
+# that we need to process in some way, and is used for substitutions.
+# The expressions it matches are:
+#
+#       "$$"
+#       "$("
+#       "$)"
+#       "$variable"             [must begin with alphabetic or underscore]
+#       "${any stuff}"
+#
+# The second expression compiled is used for splitting strings into tokens
+# to be processed, and it matches all of the tokens listed above, plus
+# the following that affect how arguments do or don't get joined together:
+#
+#       "   "                   [white space]
+#       "non-white-space"       [without any dollar signs]
+#       "$"                     [single dollar sign]
+#
+_dollar_exps_str = r'\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}'
+_dollar_exps = re.compile(r'(%s)' % _dollar_exps_str)
+_separate_args = re.compile(r'(%s|\s+|[^\s\$]+|\$)' % _dollar_exps_str)
+
+# This regular expression is used to replace strings of multiple white
+# space characters in the string result from the scons_subst() function.
+_space_sep = re.compile(r'[\t ]+(?![^{]*})')
+
+def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None):
+    """Expand a string containing construction variable substitutions.
+
+    This is the work-horse function for substitutions in file names
+    and the like.  The companion scons_subst_list() function (below)
+    handles separating command lines into lists of arguments, so see
+    that function if that's what you're looking for.
+    """
+    if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0:
+        return strSubst
+
+    class StringSubber:
+        """A class to construct the results of a scons_subst() call.
+
+        This binds a specific construction environment, mode, target and
+        source with two methods (substitute() and expand()) that handle
+        the expansion.
+        """
+        def __init__(self, env, mode, target, source, conv, gvars):
+            self.env = env
+            self.mode = mode
+            self.target = target
+            self.source = source
+            self.conv = conv
+            self.gvars = gvars
+
+        def expand(self, s, lvars):
+            """Expand a single "token" as necessary, returning an
+            appropriate string containing the expansion.
+
+            This handles expanding different types of things (strings,
+            lists, callables) appropriately.  It calls the wrapper
+            substitute() method to re-expand things as necessary, so that
+            the results of expansions of side-by-side strings still get
+            re-evaluated separately, not smushed together.
+            """
+            if is_String(s):
+                try:
+                    s0, s1 = s[:2]
+                except (IndexError, ValueError):
+                    return s
+                if s0 != '$':
+                    return s
+                if s1 == '$':
+                    return '$'
+                elif s1 in '()':
+                    return s
+                else:
+                    key = s[1:]
+                    if key[0] == '{' or string.find(key, '.') >= 0:
+                        if key[0] == '{':
+                            key = key[1:-1]
+                        try:
+                            s = eval(key, self.gvars, lvars)
+                        except AttributeError, e:
+                            raise SCons.Errors.UserError, \
+                                  "Error trying to evaluate `%s': %s" % (s, e)
+                        except (IndexError, NameError, TypeError):
+                            return ''
+                        except SyntaxError,e:
+                            if self.target:
+                                raise SCons.Errors.BuildError, (self.target[0], "Syntax error `%s' trying to evaluate `%s'" % (e,s))
+                            else:
+                                raise SCons.Errors.UserError, "Syntax error `%s' trying to evaluate `%s'" % (e,s)
+                    else:
+                        if lvars.has_key(key):
+                            s = lvars[key]
+                        elif self.gvars.has_key(key):
+                            s = self.gvars[key]
+                        else:
+                            return ''
+    
+                    # Before re-expanding the result, handle
+                    # recursive expansion by copying the local
+                    # variable dictionary and overwriting a null
+                    # string for the value of the variable name
+                    # we just expanded.
+                    #
+                    # This could potentially be optimized by only
+                    # copying lvars when s contains more expansions,
+                    # but lvars is usually supposed to be pretty
+                    # small, and deeply nested variable expansions
+                    # are probably more the exception than the norm,
+                    # so it should be tolerable for now.
+                    lv = lvars.copy()
+                    var = string.split(key, '.')[0]
+                    lv[var] = ''
+                    return self.substitute(s, lv)
+            elif is_List(s):
+                def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars):
+                    return conv(substitute(l, lvars))
+                r = map(func, s)
+                return string.join(r)
+            elif callable(s):
+                try:
+                    s = s(target=self.target,
+                         source=self.source,
+                         env=self.env,
+                         for_signature=(self.mode != SUBST_CMD))
+                except TypeError:
+                    # This probably indicates that it's a callable
+                    # object that doesn't match our calling arguments
+                    # (like an Action).
+                    s = str(s)
+                return self.substitute(s, lvars)
+            elif s is None:
+                return ''
+            else:
+                return s
+
+        def substitute(self, args, lvars):
+            """Substitute expansions in an argument or list of arguments.
+
+            This serves as a wrapper for splitting up a string into
+            separate tokens.
+            """
+            if is_String(args) and not isinstance(args, CmdStringHolder):
+                try:
+                    def sub_match(match, conv=self.conv, expand=self.expand, lvars=lvars):
+                        return conv(expand(match.group(1), lvars))
+                    result = _dollar_exps.sub(sub_match, args)
+                except TypeError:
+                    # If the internal conversion routine doesn't return
+                    # strings (it could be overridden to return Nodes, for
+                    # example), then the 1.5.2 re module will throw this
+                    # exception.  Back off to a slower, general-purpose
+                    # algorithm that works for all data types.
+                    args = _separate_args.findall(args)
+                    result = []
+                    for a in args:
+                        result.append(self.conv(self.expand(a, lvars)))
+                    try:
+                        result = string.join(result, '')
+                    except TypeError:
+                        if len(result) == 1:
+                            result = result[0]
+                return result
+            else:
+                return self.expand(args, lvars)
+
+    if conv is None:
+        conv = _strconv[mode]
+
+    # Doing this every time is a bit of a waste, since the Executor
+    # has typically already populated the OverrideEnvironment with
+    # $TARGET/$SOURCE variables.  We're keeping this (for now), though,
+    # because it supports existing behavior that allows us to call
+    # an Action directly with an arbitrary target+source pair, which
+    # we use in Tool/tex.py to handle calling $BIBTEX when necessary.
+    # If we dropped that behavior (or found another way to cover it),
+    # we could get rid of this call completely and just rely on the
+    # Executor setting the variables.
+    d = subst_dict(target, source)
+    if d:
+        lvars = lvars.copy()
+        lvars.update(d)
+
+    # We're (most likely) going to eval() things.  If Python doesn't
+    # find a __builtin__ value in the global dictionary used for eval(),
+    # it copies the current __builtin__ values for you.  Avoid this by
+    # setting it explicitly and then deleting, so we don't pollute the
+    # construction environment Dictionary(ies) that are typically used
+    # for expansion.
+    gvars['__builtin__'] = __builtin__
+
+    ss = StringSubber(env, mode, target, source, conv, gvars)
+    result = ss.substitute(strSubst, lvars)
+
+    try:
+        del gvars['__builtin__']
+    except KeyError:
+        pass
+
+    if is_String(result):
+        # Remove $(-$) pairs and any stuff in between,
+        # if that's appropriate.
+        remove = _regex_remove[mode]
+        if remove:
+            result = remove.sub('', result)
+        if mode != SUBST_RAW:
+            # Compress strings of white space characters into
+            # a single space.
+            result = string.strip(_space_sep.sub(' ', result))
+
+    return result
+
+#Subst_List_Strings = {}
+
+def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None):
+    """Substitute construction variables in a string (or list or other
+    object) and separate the arguments into a command list.
+
+    The companion scons_subst() function (above) handles basic
+    substitutions within strings, so see that function instead
+    if that's what you're looking for.
+    """
+#    try:
+#        Subst_List_Strings[strSubst] = Subst_List_Strings[strSubst] + 1
+#    except KeyError:
+#        Subst_List_Strings[strSubst] = 1
+#    import SCons.Debug
+#    SCons.Debug.caller(1)
+    class ListSubber(UserList.UserList):
+        """A class to construct the results of a scons_subst_list() call.
+
+        Like StringSubber, this class binds a specific construction
+        environment, mode, target and source with two methods
+        (substitute() and expand()) that handle the expansion.
+
+        In addition, however, this class is used to track the state of
+        the result(s) we're gathering so we can do the appropriate thing
+        whenever we have to append another word to the result--start a new
+        line, start a new word, append to the current word, etc.  We do
+        this by setting the "append" attribute to the right method so
+        that our wrapper methods only need ever call ListSubber.append(),
+        and the rest of the object takes care of doing the right thing
+        internally.
+        """
+        def __init__(self, env, mode, target, source, conv, gvars):
+            UserList.UserList.__init__(self, [])
+            self.env = env
+            self.mode = mode
+            self.target = target
+            self.source = source
+            self.conv = conv
+            self.gvars = gvars
+
+            if self.mode == SUBST_RAW:
+                self.add_strip = lambda x, s=self: s.append(x)
+            else:
+                self.add_strip = lambda x, s=self: None
+            self.in_strip = None
+            self.next_line()
+
+        def expand(self, s, lvars, within_list):
+            """Expand a single "token" as necessary, appending the
+            expansion to the current result.
+
+            This handles expanding different types of things (strings,
+            lists, callables) appropriately.  It calls the wrapper
+            substitute() method to re-expand things as necessary, so that
+            the results of expansions of side-by-side strings still get
+            re-evaluated separately, not smushed together.
+            """
+
+            if is_String(s):
+                try:
+                    s0, s1 = s[:2]
+                except (IndexError, ValueError):
+                    self.append(s)
+                    return
+                if s0 != '$':
+                    self.append(s)
+                    return
+                if s1 == '$':
+                    self.append('$')
+                elif s1 == '(':
+                    self.open_strip('$(')
+                elif s1 == ')':
+                    self.close_strip('$)')
+                else:
+                    key = s[1:]
+                    if key[0] == '{' or string.find(key, '.') >= 0:
+                        if key[0] == '{':
+                            key = key[1:-1]
+                        try:
+                            s = eval(key, self.gvars, lvars)
+                        except AttributeError, e:
+                            raise SCons.Errors.UserError, \
+                                  "Error trying to evaluate `%s': %s" % (s, e)
+                        except (IndexError, NameError, TypeError):
+                            return
+                        except SyntaxError,e:
+                            if self.target:
+                                raise SCons.Errors.BuildError, (self.target[0], "Syntax error `%s' trying to evaluate `%s'" % (e,s))
+                            else:
+                                raise SCons.Errors.UserError, "Syntax error `%s' trying to evaluate `%s'" % (e,s)
+                    else:
+                        if lvars.has_key(key):
+                            s = lvars[key]
+                        elif self.gvars.has_key(key):
+                            s = self.gvars[key]
+                        else:
+                            return
+
+                    # Before re-expanding the result, handle
+                    # recursive expansion by copying the local
+                    # variable dictionary and overwriting a null
+                    # string for the value of the variable name
+                    # we just expanded.
+                    lv = lvars.copy()
+                    var = string.split(key, '.')[0]
+                    lv[var] = ''
+                    self.substitute(s, lv, 0)
+                    self.this_word()
+            elif is_List(s):
+                for a in s:
+                    self.substitute(a, lvars, 1)
+                    self.next_word()
+            elif callable(s):
+                try:
+                    s = s(target=self.target,
+                         source=self.source,
+                         env=self.env,
+                         for_signature=(self.mode != SUBST_CMD))
+                except TypeError:
+                    # This probably indicates that it's a callable
+                    # object that doesn't match our calling arguments
+                    # (like an Action).
+                    s = str(s)
+                self.substitute(s, lvars, within_list)
+            elif s is None:
+                self.this_word()
+            else:
+                self.append(s)
+
+        def substitute(self, args, lvars, within_list):
+            """Substitute expansions in an argument or list of arguments.
+
+            This serves as a wrapper for splitting up a string into
+            separate tokens.
+            """
+
+            if is_String(args) and not isinstance(args, CmdStringHolder):
+                args = _separate_args.findall(args)
+                for a in args:
+                    if a[0] in ' \t\n\r\f\v':
+                        if '\n' in a:
+                            self.next_line()
+                        elif within_list:
+                            self.append(a)
+                        else:
+                            self.next_word()
+                    else:
+                        self.expand(a, lvars, within_list)
+            else:
+                self.expand(args, lvars, within_list)
+
+        def next_line(self):
+            """Arrange for the next word to start a new line.  This
+            is like starting a new word, except that we have to append
+            another line to the result."""
+            UserList.UserList.append(self, [])
+            self.next_word()
+
+        def this_word(self):
+            """Arrange for the next word to append to the end of the
+            current last word in the result."""
+            self.append = self.add_to_current_word
+
+        def next_word(self):
+            """Arrange for the next word to start a new word."""
+            self.append = self.add_new_word
+
+        def add_to_current_word(self, x):
+            """Append the string x to the end of the current last word
+            in the result.  If that is not possible, then just add
+            it as a new word.  Make sure the entire concatenated string
+            inherits the object attributes of x (in particular, the
+            escape function) by wrapping it as CmdStringHolder."""
+
+            if not self.in_strip or self.mode != SUBST_SIG:
+                try:
+                    current_word = self[-1][-1]
+                except IndexError:
+                    self.add_new_word(x)
+                else:
+                    # All right, this is a hack and it should probably
+                    # be refactored out of existence in the future.
+                    # The issue is that we want to smoosh words together
+                    # and make one file name that gets escaped if
+                    # we're expanding something like foo$EXTENSION,
+                    # but we don't want to smoosh them together if
+                    # it's something like >$TARGET, because then we'll
+                    # treat the '>' like it's part of the file name.
+                    # So for now, just hard-code looking for the special
+                    # command-line redirection characters...
+                    try:
+                        last_char = str(current_word)[-1]
+                    except IndexError:
+                        last_char = '\0'
+                    if last_char in '<>|':
+                        self.add_new_word(x)
+                    else:
+                        y = current_word + x
+
+                        # We used to treat a word appended to a literal
+                        # as a literal itself, but this caused problems
+                        # with interpreting quotes around space-separated
+                        # targets on command lines.  Removing this makes
+                        # none of the "substantive" end-to-end tests fail,
+                        # so we'll take this out but leave it commented
+                        # for now in case there's a problem not covered
+                        # by the test cases and we need to resurrect this.
+                        #literal1 = self.literal(self[-1][-1])
+                        #literal2 = self.literal(x)
+                        y = self.conv(y)
+                        if is_String(y):
+                            #y = CmdStringHolder(y, literal1 or literal2)
+                            y = CmdStringHolder(y, None)
+                        self[-1][-1] = y
+
+        def add_new_word(self, x):
+            if not self.in_strip or self.mode != SUBST_SIG:
+                literal = self.literal(x)
+                x = self.conv(x)
+                if is_String(x):
+                    x = CmdStringHolder(x, literal)
+                self[-1].append(x)
+            self.append = self.add_to_current_word
+
+        def literal(self, x):
+            try:
+                l = x.is_literal
+            except AttributeError:
+                return None
+            else:
+                return l()
+
+        def open_strip(self, x):
+            """Handle the "open strip" $( token."""
+            self.add_strip(x)
+            self.in_strip = 1
+
+        def close_strip(self, x):
+            """Handle the "close strip" $) token."""
+            self.add_strip(x)
+            self.in_strip = None
+
+    if conv is None:
+        conv = _strconv[mode]
+
+    # Doing this every time is a bit of a waste, since the Executor
+    # has typically already populated the OverrideEnvironment with
+    # $TARGET/$SOURCE variables.  We're keeping this (for now), though,
+    # because it supports existing behavior that allows us to call
+    # an Action directly with an arbitrary target+source pair, which
+    # we use in Tool/tex.py to handle calling $BIBTEX when necessary.
+    # If we dropped that behavior (or found another way to cover it),
+    # we could get rid of this call completely and just rely on the
+    # Executor setting the variables.
+    d = subst_dict(target, source)
+    if d:
+        lvars = lvars.copy()
+        lvars.update(d)
+
+    # We're (most likely) going to eval() things.  If Python doesn't
+    # find a __builtin__ value in the global dictionary used for eval(),
+    # it copies the current __builtin__ values for you.  Avoid this by
+    # setting it explicitly and then deleting, so we don't pollute the
+    # construction environment Dictionary(ies) that are typically used
+    # for expansion.
+    gvars['__builtins__'] = __builtins__
+
+    ls = ListSubber(env, mode, target, source, conv, gvars)
+    ls.substitute(strSubst, lvars, 0)
+
+    try:
+        del gvars['__builtins__']
+    except KeyError:
+        pass
+
+    return ls.data
+
+def scons_subst_once(strSubst, env, key):
+    """Perform single (non-recursive) substitution of a single
+    construction variable keyword.
+
+    This is used when setting a variable when copying or overriding values
+    in an Environment.  We want to capture (expand) the old value before
+    we override it, so people can do things like:
+
+        env2 = env.Copy(CCFLAGS = '$CCFLAGS -g')
+
+    We do this with some straightforward, brute-force code here...
+    """
+    if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0:
+        return strSubst
+
+    matchlist = ['$' + key, '${' + key + '}']
+    val = env.get(key, '')
+    def sub_match(match, val=val, matchlist=matchlist):
+        a = match.group(1)
+        if a in matchlist:
+            a = val
+        if is_List(a):
+            return string.join(map(str, a))
+        else:
+            return str(a)
+
+    if is_List(strSubst):
+        result = []
+        for arg in strSubst:
+            if is_String(arg):
+                if arg in matchlist:
+                    arg = val
+                    if is_List(arg):
+                        result.extend(arg)
+                    else:
+                        result.append(arg)
+                else:
+                    result.append(_dollar_exps.sub(sub_match, arg))
+            else:
+                result.append(arg)
+        return result
+    elif is_String(strSubst):
+        return _dollar_exps.sub(sub_match, strSubst)
+    else:
+        return strSubst

Added: cs/scons/scons-local-0.96.92/SCons/Taskmaster.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Taskmaster.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Taskmaster.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,566 @@
+"""SCons.Taskmaster
+
+Generic Taskmaster.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Taskmaster.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+import sys
+import traceback
+
+import SCons.Node
+import SCons.Errors
+
+# A subsystem for recording stats about how different Nodes are handled by
+# the main Taskmaster loop.  There's no external control here (no need for
+# a --debug= option); enable it by changing the value of CollectStats.
+
+CollectStats = None
+
+class Stats:
+    def __init__(self):
+        self.considered  = 0
+        self.already_handled  = 0
+        self.problem  = 0
+        self.child_failed  = 0
+        self.not_started  = 0
+        self.not_built  = 0
+        self.side_effects  = 0
+        self.build  = 0
+
+StatsNodes = []
+
+fmt = "%(considered)3d "\
+      "%(already_handled)3d " \
+      "%(problem)3d " \
+      "%(child_failed)3d " \
+      "%(not_started)3d " \
+      "%(not_built)3d " \
+      "%(side_effects)3d " \
+      "%(build)3d "
+
+def dump_stats():
+    StatsNodes.sort(lambda a, b: cmp(str(a), str(b)))
+    for n in StatsNodes:
+        print (fmt % n.stats.__dict__) + str(n)
+
+class Task:
+    """Default SCons build engine task.
+
+    This controls the interaction of the actual building of node
+    and the rest of the engine.
+
+    This is expected to handle all of the normally-customizable
+    aspects of controlling a build, so any given application
+    *should* be able to do what it wants by sub-classing this
+    class and overriding methods as appropriate.  If an application
+    needs to customze something by sub-classing Taskmaster (or
+    some other build engine class), we should first try to migrate
+    that functionality into this class.
+
+    Note that it's generally a good idea for sub-classes to call
+    these methods explicitly to update state, etc., rather than
+    roll their own interaction with Taskmaster from scratch."""
+    def __init__(self, tm, targets, top, node):
+        self.tm = tm
+        self.targets = targets
+        self.top = top
+        self.node = node
+        self.exc_clear()
+
+    def display(self, message):
+        """Allow the calling interface to display a message
+        """
+        pass
+
+    def prepare(self):
+        """Called just before the task is executed.
+
+        This unlinks all targets and makes all directories before
+        building anything."""
+
+        # Now that it's the appropriate time, give the TaskMaster a
+        # chance to raise any exceptions it encountered while preparing
+        # this task.
+        self.exception_raise()
+
+        if self.tm.message:
+            self.display(self.tm.message)
+            self.tm.message = None
+
+        for t in self.targets:
+            t.prepare()
+            for s in t.side_effects:
+                s.prepare()
+
+    def execute(self):
+        """Called to execute the task.
+
+        This method is called from multiple threads in a parallel build,
+        so only do thread safe stuff here.  Do thread unsafe stuff in
+        prepare(), executed() or failed()."""
+
+        try:
+            everything_was_cached = 1
+            for t in self.targets:
+                if not t.retrieve_from_cache():
+                    everything_was_cached = 0
+                    break
+            if not everything_was_cached:
+                self.targets[0].build()
+        except KeyboardInterrupt:
+            raise
+        except SystemExit:
+            exc_value = sys.exc_info()[1]
+            raise SCons.Errors.ExplicitExit(self.targets[0], exc_value.code)
+        except SCons.Errors.UserError:
+            raise
+        except SCons.Errors.BuildError:
+            raise
+        except:
+            raise SCons.Errors.TaskmasterException(self.targets[0],
+                                                   sys.exc_info())
+
+    def get_target(self):
+        """Fetch the target being built or updated by this task.
+        """
+        return self.node
+
+    def executed(self):
+        """Called when the task has been successfully executed.
+
+        This may have been a do-nothing operation (to preserve
+        build order), so check the node's state before updating
+        things.  Most importantly, this calls back to the
+        Taskmaster to put any node tasks waiting on this one
+        back on the pending list."""
+        for t in self.targets:
+            if t.get_state() == SCons.Node.executing:
+                for side_effect in t.side_effects:
+                    side_effect.set_state(SCons.Node.no_state)
+                t.set_state(SCons.Node.executed)
+                t.built()
+            else:
+                t.visited()
+
+        self.tm.executed(self.node)
+
+    def failed(self):
+        """Default action when a task fails:  stop the build."""
+        self.fail_stop()
+
+    def fail_stop(self):
+        """Explicit stop-the-build failure."""
+        for t in self.targets:
+            t.set_state(SCons.Node.failed)
+        self.tm.failed(self.node)
+        next_top = self.tm.next_top_level_candidate()
+        self.tm.stop()
+
+        if next_top:
+            # We're stopping because of a build failure, but give the
+            # calling Task class a chance to postprocess() the top-level
+            # target under which the build failure occurred.
+            self.targets = [next_top]
+            self.top = 1
+
+    def fail_continue(self):
+        """Explicit continue-the-build failure.
+
+        This sets failure status on the target nodes and all of
+        their dependent parent nodes.
+        """
+        for t in self.targets:
+            # Set failure state on all of the parents that were dependent
+            # on this failed build.
+            def set_state(node): node.set_state(SCons.Node.failed)
+            t.call_for_all_waiting_parents(set_state)
+
+        self.tm.executed(self.node)
+
+    def make_ready_all(self):
+        """Mark all targets in a task ready for execution.
+
+        This is used when the interface needs every target Node to be
+        visited--the canonical example being the "scons -c" option.
+        """
+        self.out_of_date = self.targets[:]
+        for t in self.targets:
+            for s in t.side_effects:
+                s.set_state(SCons.Node.executing)
+            t.set_state(SCons.Node.executing)
+
+    def make_ready_current(self):
+        """Mark all targets in a task ready for execution if any target
+        is not current.
+
+        This is the default behavior for building only what's necessary.
+        """
+        self.out_of_date = []
+        for t in self.targets:
+            if t.disambiguate().current():
+                t.set_state(SCons.Node.up_to_date)
+            else:
+                self.out_of_date.append(t)
+                for s in t.side_effects:
+                    s.set_state(SCons.Node.executing)
+                t.set_state(SCons.Node.executing)
+
+    make_ready = make_ready_current
+
+    def postprocess(self):
+        """Post process a task after it's been executed."""
+        for t in self.targets:
+            t.postprocess()
+
+    def exc_info(self):
+        return self.exception
+
+    def exc_clear(self):
+        self.exception = (None, None, None)
+        self.exception_raise = self._no_exception_to_raise
+
+    def exception_set(self, exception=None):
+        if not exception:
+            exception = sys.exc_info()
+        self.exception = exception
+        self.exception_raise = self._exception_raise
+
+    def _no_exception_to_raise(self):
+        pass
+
+    def _exception_raise(self):
+        """Raise a pending exception that was recorded while
+        getting a Task ready for execution."""
+        self.tm.exception_raise(self.exc_info())
+
+
+def order(dependencies):
+    """Re-order a list of dependencies (if we need to)."""
+    return dependencies
+
+
+class Taskmaster:
+    """A generic Taskmaster for handling a bunch of targets.
+
+    Classes that override methods of this class should call
+    the base class method, so this class can do its thing.
+    """
+
+    def __init__(self, targets=[], tasker=Task, order=order, trace=None):
+        self.targets = targets # top level targets
+        self.candidates = targets[:] # nodes that might be ready to be executed
+        self.candidates.reverse()
+        self.executing = [] # nodes that are currently executing
+        self.pending = [] # nodes that depend on a currently executing node
+        self.tasker = tasker
+        self.ready = None # the next task that is ready to be executed
+        self.order = order
+        self.message = None
+        self.trace = trace
+
+        # See if we can alter the target list to find any
+        # corresponding targets in linked build directories
+        for node in self.targets:
+            alt, message = node.alter_targets()
+            if alt:
+                self.message = message
+                self.candidates.extend(self.order(alt))
+                continue
+
+    def _find_next_ready_node(self):
+        """Find the next node that is ready to be built"""
+
+        if self.ready:
+            return
+
+        self.ready_exc = None
+
+        T = self.trace
+
+        while self.candidates:
+            node = self.candidates.pop().disambiguate()
+            state = node.get_state()
+
+            if CollectStats:
+                if not hasattr(node, 'stats'):
+                    node.stats = Stats()
+                    StatsNodes.append(node)
+                S = node.stats
+                S.considered = S.considered + 1
+            else:
+                S = None
+
+            if T: T.write('Taskmaster: %s:' % repr(str(node)))
+
+            # Skip this node if it has already been handled:
+            if not state in [ SCons.Node.no_state, SCons.Node.stack ]:
+                if S: S.already_handled = S.already_handled + 1
+                if T: T.write(' already handled\n')
+                continue
+
+            # Mark this node as being on the execution stack:
+            node.set_state(SCons.Node.stack)
+
+            try:
+                children = node.children()
+            except SystemExit:
+                exc_value = sys.exc_info()[1]
+                e = SCons.Errors.ExplicitExit(node, exc_value.code)
+                self.ready_exc = (SCons.Errors.ExplicitExit, e)
+                self.ready = node
+                if T: T.write(' SystemExit\n')
+                break
+            except KeyboardInterrupt:
+                if T: T.write(' KeyboardInterrupt\n')
+                raise
+            except:
+                # We had a problem just trying to figure out the
+                # children (like a child couldn't be linked in to a
+                # BuildDir, or a Scanner threw something).  Arrange to
+                # raise the exception when the Task is "executed."
+                self.ready_exc = sys.exc_info()
+                self.ready = node
+                if S: S.problem = S.problem + 1
+                if T: T.write(' exception\n')
+                break
+            else:
+                c = map(str, children)
+                c.sort()
+                if T: T.write(' children:\n    %s\n   ' % c)
+
+            childinfo = map(lambda N: (N.get_state(),
+                                       N.is_derived() or N.is_pseudo_derived(),
+                                       N), children)
+
+            # Skip this node if any of its children have failed.  This
+            # catches the case where we're descending a top-level target
+            # and one of our children failed while trying to be built
+            # by a *previous* descent of an earlier top-level target.
+            failed_children = filter(lambda I: I[0] == SCons.Node.failed,
+                                     childinfo)
+            if failed_children:
+                node.set_state(SCons.Node.failed)
+                if S: S.child_failed = S.child_failed + 1
+                if T:
+                    c = map(str, failed_children)
+                    c.sort()
+                    T.write(' children failed:\n    %s\n' % c)
+                continue
+
+            # Detect dependency cycles:
+            cycle = filter(lambda I: I[0] == SCons.Node.stack, childinfo)
+            if cycle:
+                # The node we popped from the candidate stack is part of
+                # the cycle we detected, so put it back before generating
+                # the message to report.
+                self.candidates.append(node)
+                nodes = filter(lambda N: N.get_state() == SCons.Node.stack,
+                               self.candidates) + \
+                               map(lambda I: I[2], cycle)
+                nodes.reverse()
+                desc = "Dependency cycle: " + string.join(map(str, nodes), " -> ")
+                if T: T.write(' dependency cycle\n')
+                raise SCons.Errors.UserError, desc
+
+            # Select all of the dependencies that are derived targets
+            # (that is, children who have builders or are side effects).
+            derived_children = filter(lambda I: I[1], childinfo)
+
+            not_started = filter(lambda I: not I[0], derived_children)
+            if not_started:
+                not_started = map(lambda I: I[2], not_started)
+
+                # We're waiting on one more derived targets that have
+                # not yet started building.  Add this node to the
+                # waiting_parents lists of those derived files so that
+                # when they've finished building, our implicit dependency
+                # list will get cleared and we'll re-scan the newly-built
+                # file(s) for updated implicit dependencies.
+                map(lambda n, P=node: n.add_to_waiting_parents(P), not_started)
+
+                # Now we add these derived targets to the candidates
+                # list so they can be examined and built.  We have to
+                # add ourselves back to the list first, though, so we get
+                # a chance to re-scan and build after the dependencies.
+                #
+                # We reverse the order in which the children are added
+                # to the candidates stack so the order in which they're
+                # popped matches the order in which they show up in our
+                # children's list.  This is more logical / efficient for
+                # builders with multiple targets, since the "primary"
+                # target will be examined first.
+                self.candidates.append(node)
+                not_started.reverse()
+                self.candidates.extend(self.order(not_started))
+                if S: S.not_started = S.not_started + 1
+                if T:
+                    c = map(str, not_started)
+                    c.sort()
+                    T.write(' waiting on unstarted children:\n    %s\n' % c)
+                continue
+
+            not_built = filter(lambda I: I[0] <= SCons.Node.executing, derived_children)
+            if not_built:
+                not_built = map(lambda I: I[2], not_built)
+
+                # We're waiting on one or more derived targets that have
+                # started building but not yet finished.  Add this node
+                # to the waiting parents lists of those derived files
+                # so that when they've finished building, our implicit
+                # dependency list will get cleared and we'll re-scan the
+                # newly-built file(s) for updated implicit dependencies.
+                map(lambda n, P=node: n.add_to_waiting_parents(P), not_built)
+
+                # And add this node to the "pending" list, so it can get
+                # put back on the candidates list when appropriate.
+                self.pending.append(node)
+                node.set_state(SCons.Node.pending)
+                if S: S.not_built = S.not_built + 1
+                if T:
+                    c = map(str, not_built)
+                    c.sort()
+                    T.write(' waiting on unfinished children:\n    %s\n' % c)
+                continue
+
+            # Skip this node if it has side-effects that are
+            # currently being built:
+            side_effects = reduce(lambda E,N:
+                                  E or N.get_state() == SCons.Node.executing,
+                                  node.side_effects,
+                                  0)
+            if side_effects:
+                self.pending.append(node)
+                node.set_state(SCons.Node.pending)
+                if S: S.side_effects = S.side_effects + 1
+                if T:
+                    c = map(str, side_effects)
+                    c.sort()
+                    T.write(' waiting on side effects:\n    %s\n' % c)
+                continue
+
+            # The default when we've gotten through all of the checks above:
+            # this node is ready to be built.
+            self.ready = node
+            if S: S.build = S.build + 1
+            if T: T.write(' evaluating\n')
+            break
+
+    def next_task(self):
+        """Return the next task to be executed."""
+
+        self._find_next_ready_node()
+
+        node = self.ready
+
+        if node is None:
+            return None
+
+        try:
+            tlist = node.builder.targets(node)
+        except AttributeError:
+            tlist = [node]
+        self.executing.extend(tlist)
+        self.executing.extend(node.side_effects)
+
+        task = self.tasker(self, tlist, node in self.targets, node)
+        try:
+            task.make_ready()
+        except KeyboardInterrupt:
+            raise
+        except:
+            # We had a problem just trying to get this task ready (like
+            # a child couldn't be linked in to a BuildDir when deciding
+            # whether this node is current).  Arrange to raise the
+            # exception when the Task is "executed."
+            self.ready_exc = sys.exc_info()
+
+        if self.ready_exc:
+            task.exception_set(self.ready_exc)
+
+        self.ready = None
+        self.ready_exc = None
+
+        return task
+
+    def is_blocked(self):
+        self._find_next_ready_node()
+
+        return not self.ready and (self.pending or self.executing)
+
+    def next_top_level_candidate(self):
+        candidates = self.candidates[:]
+        candidates.reverse()
+        for c in candidates:
+            if c in self.targets:
+                return c
+        return None
+
+    def stop(self):
+        """Stop the current build completely."""
+        self.candidates = []
+        self.ready = None
+        self.pending = []
+
+    def failed(self, node):
+        try:
+            tlist = node.builder.targets(node)
+        except AttributeError:
+            tlist = [node]
+        for t in tlist:
+            self.executing.remove(t)
+        for side_effect in node.side_effects:
+            self.executing.remove(side_effect)
+
+    def executed(self, node):
+        try:
+            tlist = node.builder.targets(node)
+        except AttributeError:
+            tlist = [node]
+        for t in tlist:
+            self.executing.remove(t)
+        for side_effect in node.side_effects:
+            self.executing.remove(side_effect)
+
+        # move the current pending nodes to the candidates list:
+        # (they may not all be ready to build, but _find_next_ready_node()
+        #  will figure out which ones are really ready)
+        for node in self.pending:
+            node.set_state(SCons.Node.no_state)
+        self.pending.reverse()
+        self.candidates.extend(self.pending)
+        self.pending = []
+
+    def exception_raise(self, exception):
+        exc = exception[:]
+        try:
+            exc_type, exc_value, exc_traceback = exc
+        except ValueError:
+            exc_type, exc_value = exc
+            exc_traceback = None
+        raise exc_type, exc_value, exc_traceback

Added: cs/scons/scons-local-0.96.92/SCons/Tool/386asm.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/386asm.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/386asm.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,55 @@
+"""SCons.Tool.386asm
+
+Tool specification for the 386ASM assembler for the Phar Lap ETS embedded
+operating system.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/386asm.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+from SCons.Tool.PharLapCommon import addPharLapPaths
+import SCons.Util
+
+import as
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    as.generate(env)
+
+    env['AS']        = '386asm'
+    env['ASFLAGS']   = SCons.Util.CLVar('')
+    env['ASPPFLAGS'] = '$ASFLAGS'
+    env['ASCOM']     = '$AS $ASFLAGS $SOURCES -o $TARGET'
+    env['ASPPCOM']   = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES -o $TARGET'
+
+    addPharLapPaths(env)
+
+def exists(env):
+    return env.Detect('386asm')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/BitKeeper.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/BitKeeper.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/BitKeeper.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,61 @@
+"""SCons.Tool.BitKeeper.py
+
+Tool-specific initialization for the BitKeeper source code control
+system.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/BitKeeper.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    BitKeeper to an Environment."""
+
+    def BitKeeperFactory(env=env):
+        """ """
+        act = SCons.Action.Action("$BITKEEPERCOM", "$BITKEEPERCOMSTR")
+        return SCons.Builder.Builder(action = act, env = env)
+
+    #setattr(env, 'BitKeeper', BitKeeperFactory)
+    env.BitKeeper = BitKeeperFactory
+
+    env['BITKEEPER']         = 'bk'
+    env['BITKEEPERGET']      = '$BITKEEPER get'
+    env['BITKEEPERGETFLAGS'] = SCons.Util.CLVar('')
+    env['BITKEEPERCOM']      = '$BITKEEPERGET $BITKEEPERGETFLAGS $TARGET'
+
+def exists(env):
+    return env.Detect('bk')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/CVS.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/CVS.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/CVS.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,67 @@
+"""SCons.Tool.CVS.py
+
+Tool-specific initialization for CVS.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/CVS.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    CVS to an Environment."""
+
+    def CVSFactory(repos, module='', env=env):
+        """ """
+        # fail if repos is not an absolute path name?
+        if module != '':
+           # Don't use os.path.join() because the name we fetch might
+           # be across a network and must use POSIX slashes as separators.
+           module = module + '/'
+           env['CVSCOM']   = '$CVS $CVSFLAGS co $CVSCOFLAGS -d ${TARGET.dir} $CVSMODULE${TARGET.posix}'
+        act = SCons.Action.Action('$CVSCOM', '$CVSCOMSTR')
+        return SCons.Builder.Builder(action = act,
+                                     env = env,
+                                     CVSREPOSITORY = repos,
+                                     CVSMODULE = module)
+
+    #setattr(env, 'CVS', CVSFactory)
+    env.CVS = CVSFactory
+
+    env['CVS']        = 'cvs'
+    env['CVSFLAGS']   = SCons.Util.CLVar('-d $CVSREPOSITORY')
+    env['CVSCOFLAGS'] = SCons.Util.CLVar('')
+    env['CVSCOM']     = '$CVS $CVSFLAGS co $CVSCOFLAGS ${TARGET.posix}'
+
+def exists(env):
+    return env.Detect('cvs')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/JavaCommon.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/JavaCommon.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/JavaCommon.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,237 @@
+"""SCons.Tool.JavaCommon
+
+Stuff for processing Java.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/JavaCommon.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import re
+import string
+
+java_parsing = 1
+
+if java_parsing:
+    # Parse Java files for class names.
+    #
+    # This is a really cool parser from Charles Crain
+    # that finds appropriate class names in Java source.
+
+    # A regular expression that will find, in a java file:
+    #     newlines;
+    #     double-backslashes;
+    #     a single-line comment "//";
+    #     single or double quotes preceeded by a backslash;
+    #     single quotes, double quotes, open or close braces, semi-colons;
+    #     any alphanumeric token (keyword, class name, specifier);
+    #     the multi-line comment begin and end tokens /* and */;
+    #     array declarations "[]";
+    #     semi-colons.
+    _reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;]|' +
+                          r'[A-Za-z_][\w\.]*|/\*|\*/|\[\])')
+
+    class OuterState:
+        """The initial state for parsing a Java file for classes,
+        interfaces, and anonymous inner classes."""
+        def __init__(self):
+            self.listClasses = []
+            self.listOutputs = []
+            self.stackBrackets = []
+            self.brackets = 0
+            self.nextAnon = 1
+            self.package = None
+
+        def trace(self):
+            pass
+
+        def __getClassState(self):
+            try:
+                return self.classState
+            except AttributeError:
+                ret = ClassState(self)
+                self.classState = ret
+                return ret
+
+        def __getPackageState(self):
+            try:
+                return self.packageState
+            except AttributeError:
+                ret = PackageState(self)
+                self.packageState = ret
+                return ret
+
+        def __getAnonClassState(self):
+            try:
+                return self.anonState
+            except AttributeError:
+                ret = SkipState(1, AnonClassState(self))
+                self.anonState = ret
+                return ret
+
+        def __getSkipState(self):
+            try:
+                return self.skipState
+            except AttributeError:
+                ret = SkipState(1, self)
+                self.skipState = ret
+                return ret
+
+        def parseToken(self, token):
+            if token[:2] == '//':
+                return IgnoreState('\n', self)
+            elif token == '/*':
+                return IgnoreState('*/', self)
+            elif token == '{':
+                self.brackets = self.brackets + 1
+            elif token == '}':
+                self.brackets = self.brackets - 1
+                if len(self.stackBrackets) and \
+                   self.brackets == self.stackBrackets[-1]:
+                    self.listOutputs.append(string.join(self.listClasses, '$'))
+                    self.listClasses.pop()
+                    self.stackBrackets.pop()
+            elif token in [ '"', "'" ]:
+                return IgnoreState(token, self)
+            elif token == "new":
+                # anonymous inner class
+                if len(self.listClasses) > 0:
+                    return self.__getAnonClassState()
+                return self.__getSkipState() # Skip the class name
+            elif token in ['class', 'interface', 'enum']:
+                if len(self.listClasses) == 0:
+                    self.nextAnon = 1
+                self.stackBrackets.append(self.brackets)
+                return self.__getClassState()
+            elif token == 'package':
+                return self.__getPackageState()
+            return self
+
+        def addAnonClass(self):
+            """Add an anonymous inner class"""
+            clazz = self.listClasses[0]
+            self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
+            self.brackets = self.brackets + 1
+            self.nextAnon = self.nextAnon + 1
+
+        def setPackage(self, package):
+            self.package = package
+
+    class AnonClassState:
+        """A state that looks for anonymous inner classes."""
+        def __init__(self, outer_state):
+            # outer_state is always an instance of OuterState
+            self.outer_state = outer_state
+            self.tokens_to_find = 2
+        def parseToken(self, token):
+            # This is an anonymous class if and only if the next token
+            # is a bracket
+            if token == '{':
+                self.outer_state.addAnonClass()
+            elif token in ['"', "'"]:
+                return IgnoreState(token, self)
+            return self.outer_state
+
+    class SkipState:
+        """A state that will skip a specified number of tokens before
+        reverting to the previous state."""
+        def __init__(self, tokens_to_skip, old_state):
+            self.tokens_to_skip = tokens_to_skip
+            self.old_state = old_state
+        def parseToken(self, token):
+            self.tokens_to_skip = self.tokens_to_skip - 1
+            if self.tokens_to_skip < 1:
+                return self.old_state
+            return self
+
+    class ClassState:
+        """A state we go into when we hit a class or interface keyword."""
+        def __init__(self, outer_state):
+            # outer_state is always an instance of OuterState
+            self.outer_state = outer_state
+        def parseToken(self, token):
+            # the next non-whitespace token should be the name of the class
+            if token == '\n':
+                return self
+            self.outer_state.listClasses.append(token)
+            return self.outer_state
+
+    class IgnoreState:
+        """A state that will ignore all tokens until it gets to a
+        specified token."""
+        def __init__(self, ignore_until, old_state):
+            self.ignore_until = ignore_until
+            self.old_state = old_state
+        def parseToken(self, token):
+            if self.ignore_until == token:
+                return self.old_state
+            return self
+
+    class PackageState:
+        """The state we enter when we encounter the package keyword.
+        We assume the next token will be the package name."""
+        def __init__(self, outer_state):
+            # outer_state is always an instance of OuterState
+            self.outer_state = outer_state
+        def parseToken(self, token):
+            self.outer_state.setPackage(token)
+            return self.outer_state
+
+    def parse_java_file(fn):
+        return parse_java(open(fn, 'r').read())
+
+    def parse_java(contents, trace=None):
+        """Parse a .java file and return a double of package directory,
+        plus a list of .class files that compiling that .java file will
+        produce"""
+        package = None
+        initial = OuterState()
+        currstate = initial
+        for token in _reToken.findall(contents):
+            # The regex produces a bunch of groups, but only one will
+            # have anything in it.
+            currstate = currstate.parseToken(token)
+            if trace: trace(token, currstate)
+        if initial.package:
+            package = string.replace(initial.package, '.', os.sep)
+        return (package, initial.listOutputs)
+
+else:
+    # Don't actually parse Java files for class names.
+    #
+    # We might make this a configurable option in the future if
+    # Java-file parsing takes too long (although it shouldn't relative
+    # to how long the Java compiler itself seems to take...).
+
+    def parse_java_file(fn):
+        """ "Parse" a .java file.
+
+        This actually just splits the file name, so the assumption here
+        is that the file name matches the public class name, and that
+        the path to the file is the same as the package name.
+        """
+        return os.path.split(file)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/Perforce.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/Perforce.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/Perforce.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,98 @@
+"""SCons.Tool.Perforce.py
+
+Tool-specific initialization for Perforce Source Code Management system.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/Perforce.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+
+import SCons.Action
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Util
+
+# This function should maybe be moved to SCons.Util?
+from SCons.Tool.PharLapCommon import addPathIfNotExists
+
+
+
+# Variables that we want to import from the base OS environment.
+_import_env = [ 'P4PORT', 'P4CLIENT', 'P4USER', 'USER', 'USERNAME', 'P4PASSWD',
+                'P4CHARSET', 'P4LANGUAGE', 'SYSTEMROOT' ]
+
+PerforceAction = SCons.Action.Action('$P4COM', '$P4COMSTR')
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    Perforce to an Environment."""
+
+    def PerforceFactory(env=env):
+        """ """
+        return SCons.Builder.Builder(action = PerforceAction, env = env)
+
+    #setattr(env, 'Perforce', PerforceFactory)
+    env.Perforce = PerforceFactory
+
+    env['P4']      = 'p4'
+    env['P4FLAGS'] = SCons.Util.CLVar('')
+    env['P4COM']   = '$P4 $P4FLAGS sync $TARGET'
+    try:
+        environ = env['ENV']
+    except KeyError:
+        environ = {}
+        env['ENV'] = environ
+
+    # Perforce seems to use the PWD environment variable rather than
+    # calling getcwd() for itself, which is odd.  If no PWD variable
+    # is present, p4 WILL call getcwd, but this seems to cause problems
+    # with good ol' Windows's tilde-mangling for long file names.
+    environ['PWD'] = env.Dir('#').get_abspath()
+
+    for var in _import_env:
+        v = os.environ.get(var)
+        if v:
+            environ[var] = v
+
+    if SCons.Util.can_read_reg:
+        # If we can read the registry, add the path to Perforce to our environment.
+        try:
+            k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
+                                      'Software\\Perforce\\environment')
+            val, tok = SCons.Util.RegQueryValueEx(k, 'P4INSTROOT')
+            addPathIfNotExists(environ, 'PATH', val)
+        except SCons.Util.RegError:
+            # Can't detect where Perforce is, hope the user has it set in the
+            # PATH.
+            pass
+
+def exists(env):
+    return env.Detect('p4')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/PharLapCommon.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/PharLapCommon.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/PharLapCommon.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,132 @@
+"""SCons.Tool.PharLapCommon
+
+This module contains common code used by all Tools for the
+Phar Lap ETS tool chain.  Right now, this is linkloc and
+386asm.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/PharLapCommon.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import SCons.Errors
+import SCons.Util
+import re
+import string
+
+def getPharLapPath():
+    """Reads the registry to find the installed path of the Phar Lap ETS
+    development kit.
+
+    Raises UserError if no installed version of Phar Lap can
+    be found."""
+
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+    try:
+        k=SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+                                  'SOFTWARE\\Pharlap\\ETS')
+        val, type = SCons.Util.RegQueryValueEx(k, 'BaseDir')
+
+        # The following is a hack...there is (not surprisingly)
+        # an odd issue in the Phar Lap plug in that inserts
+        # a bunch of junk data after the phar lap path in the
+        # registry.  We must trim it.
+        idx=val.find('\0')
+        if idx >= 0:
+            val = val[:idx]
+                    
+        return os.path.normpath(val)
+    except SCons.Util.RegError:
+        raise SCons.Errors.UserError, "Cannot find Phar Lap ETS path in the registry.  Is it installed properly?"
+
+REGEX_ETS_VER = re.compile(r'#define\s+ETS_VER\s+([0-9]+)')
+
+def getPharLapVersion():
+    """Returns the version of the installed ETS Tool Suite as a
+    decimal number.  This version comes from the ETS_VER #define in
+    the embkern.h header.  For example, '#define ETS_VER 1010' (which
+    is what Phar Lap 10.1 defines) would cause this method to return
+    1010. Phar Lap 9.1 does not have such a #define, but this method
+    will return 910 as a default.
+
+    Raises UserError if no installed version of Phar Lap can
+    be found."""
+
+    include_path = os.path.join(getPharLapPath(), os.path.normpath("include/embkern.h"))
+    if not os.path.exists(include_path):
+        raise SCons.Errors.UserError, "Cannot find embkern.h in ETS include directory.\nIs Phar Lap ETS installed properly?"
+    mo = REGEX_ETS_VER.search(open(include_path, 'r').read())
+    if mo:
+        return int(mo.group(1))
+    # Default return for Phar Lap 9.1
+    return 910
+
+def addPathIfNotExists(env_dict, key, path, sep=os.pathsep):
+    """This function will take 'key' out of the dictionary
+    'env_dict', then add the path 'path' to that key if it is not
+    already there.  This treats the value of env_dict[key] as if it
+    has a similar format to the PATH variable...a list of paths
+    separated by tokens.  The 'path' will get added to the list if it
+    is not already there."""
+    try:
+        is_list = 1
+        paths = env_dict[key]
+        if not SCons.Util.is_List(env_dict[key]):
+            paths = string.split(paths, sep)
+            is_list = 0
+        if not os.path.normcase(path) in map(os.path.normcase, paths):
+            paths = [ path ] + paths
+        if is_list:
+            env_dict[key] = paths
+        else:
+            env_dict[key] = string.join(paths, sep)
+    except KeyError:
+        env_dict[key] = path
+
+def addPharLapPaths(env):
+    """This function adds the path to the Phar Lap binaries, includes,
+    and libraries, if they are not already there."""
+    ph_path = getPharLapPath()
+
+    try:
+        env_dict = env['ENV']
+    except KeyError:
+        env_dict = {}
+        env['ENV'] = env_dict
+    addPathIfNotExists(env_dict, 'PATH',
+                       os.path.join(ph_path, 'bin'))
+    addPathIfNotExists(env_dict, 'INCLUDE',
+                       os.path.join(ph_path, 'include'))
+    addPathIfNotExists(env_dict, 'LIB',
+                       os.path.join(ph_path, 'lib'))
+    addPathIfNotExists(env_dict, 'LIB',
+                       os.path.join(ph_path, os.path.normpath('lib/vclib')))
+    
+    env['PHARLAP_PATH'] = getPharLapPath()
+    env['PHARLAP_VERSION'] = str(getPharLapVersion())
+    

Added: cs/scons/scons-local-0.96.92/SCons/Tool/RCS.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/RCS.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/RCS.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,58 @@
+"""SCons.Tool.RCS.py
+
+Tool-specific initialization for RCS.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/RCS.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    RCS to an Environment."""
+
+    def RCSFactory(env=env):
+        """ """
+        act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR')
+        return SCons.Builder.Builder(action = act, env = env)
+
+    #setattr(env, 'RCS', RCSFactory)
+    env.RCS = RCSFactory
+
+    env['RCS']          = 'rcs'
+    env['RCS_CO']       = 'co'
+    env['RCS_COFLAGS']  = SCons.Util.CLVar('')
+    env['RCS_COCOM']    = '$RCS_CO $RCS_COFLAGS $TARGET'
+
+def exists(env):
+    return env.Detect('rcs')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/SCCS.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/SCCS.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/SCCS.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,58 @@
+"""SCons.Tool.SCCS.py
+
+Tool-specific initialization for SCCS.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/SCCS.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    SCCS to an Environment."""
+
+    def SCCSFactory(env=env):
+        """ """
+        act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR')
+        return SCons.Builder.Builder(action = act, env = env)
+
+    #setattr(env, 'SCCS', SCCSFactory)
+    env.SCCS = SCCSFactory
+
+    env['SCCS']         = 'sccs'
+    env['SCCSFLAGS']    = SCons.Util.CLVar('')
+    env['SCCSGETFLAGS'] = SCons.Util.CLVar('')
+    env['SCCSCOM']      = '$SCCS $SCCSFLAGS get $SCCSGETFLAGS $TARGET'
+
+def exists(env):
+    return env.Detect('sccs')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/Subversion.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/Subversion.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/Subversion.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,65 @@
+"""SCons.Tool.Subversion.py
+
+Tool-specific initialization for Subversion.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/Subversion.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add a Builder factory function and construction variables for
+    Subversion to an Environment."""
+
+    def SubversionFactory(repos, module='', env=env):
+        """ """
+        # fail if repos is not an absolute path name?
+        if module != '':
+            module = os.path.join(module, '')
+        act = SCons.Action.Action('$SVNCOM', '$SVNCOMSTR')
+        return SCons.Builder.Builder(action = act,
+                                     env = env,
+                                     SVNREPOSITORY = repos,
+                                     SVNMODULE = module)
+
+    #setattr(env, 'Subversion', SubversionFactory)
+    env.Subversion = SubversionFactory
+
+    env['SVN']      = 'svn'
+    env['SVNFLAGS'] = SCons.Util.CLVar('')
+    env['SVNCOM']   = '$SVN $SVNFLAGS cat $SVNREPOSITORY/$SVNMODULE$TARGET > $TARGET'
+
+def exists(env):
+    return env.Detect('svn')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,436 @@
+"""SCons.Tool
+
+SCons tool selection.
+
+This looks for modules that define a callable object that can modify
+a construction environment as appropriate for a given tool (or tool
+chain).
+
+Note that because this subsystem just *selects* a callable that can
+modify a construction environment, it's possible for people to define
+their own "tool specification" in an arbitrary callable function.  No
+one needs to use or tie in to this subsystem in order to roll their own
+tool definition.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+# 
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/__init__.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import imp
+import sys
+
+import SCons.Errors
+import SCons.Scanner
+import SCons.Scanner.C
+import SCons.Scanner.D
+import SCons.Scanner.LaTeX
+import SCons.Scanner.Prog
+
+CScanner = SCons.Scanner.C.CScanner()
+DScanner = SCons.Scanner.D.DScanner()
+LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
+ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
+SourceFileScanner = SCons.Scanner.Scanner({}, name='SourceFileScanner')
+
+CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
+             ".h", ".H", ".hxx", ".hpp", ".hh",
+             ".F", ".fpp", ".FPP",
+             ".m", ".mm",
+             ".S", ".spp", ".SPP"]
+
+DSuffixes = ['.d']
+
+IDLSuffixes = [".idl", ".IDL"]
+
+LaTeXSuffixes = [".tex", ".ltx", ".latex"]
+
+for suffix in CSuffixes:
+    SourceFileScanner.add_scanner(suffix, CScanner)
+
+for suffix in DSuffixes:
+    SourceFileScanner.add_scanner(suffix, DScanner)
+
+for suffix in LaTeXSuffixes:
+     SourceFileScanner.add_scanner(suffix, LaTeXScanner)
+
+class Tool:
+    def __init__(self, name, toolpath=[], **kw):
+        self.name = name
+        self.toolpath = toolpath
+        # remember these so we can merge them into the call
+        self.init_kw = kw
+
+        module = self._tool_module()
+        self.generate = module.generate
+        self.exists = module.exists
+
+    def _tool_module(self):
+        oldpythonpath = sys.path
+        sys.path = self.toolpath + sys.path
+
+        try:
+            try:
+                file, path, desc = imp.find_module(self.name, self.toolpath)
+                try:
+                    return imp.load_module(self.name, file, path, desc)
+                finally:
+                    if file:
+                        file.close()
+            except ImportError, e:
+                pass
+        finally:
+            sys.path = oldpythonpath
+
+        full_name = 'SCons.Tool.' + self.name
+        try:
+            return sys.modules[full_name]
+        except KeyError:
+            try:
+                smpath = sys.modules['SCons.Tool'].__path__
+                file, path, desc = imp.find_module(self.name, smpath)
+                try:
+                    module = imp.load_module(full_name, file, path, desc)
+                    setattr(SCons.Tool, self.name, module)
+                    return module
+                finally:
+                    if file:
+                        file.close()
+            except ImportError, e:
+                m = "No tool named '%s': %s" % (self.name, e)
+                raise SCons.Errors.UserError, m
+
+    def __call__(self, env, *args, **kw):
+        if self.init_kw is not None:
+            # Merge call kws into init kws;
+            # but don't bash self.init_kw.
+            if kw is not None:
+                call_kw = kw
+                kw = self.init_kw.copy()
+                kw.update(call_kw)
+            else:
+                kw = self.init_kw
+        env.Append(TOOLS = [ self.name ])
+        apply(self.generate, ( env, ) + args, kw)
+
+    def __str__(self):
+        return self.name
+
+def createProgBuilder(env):
+    """This is a utility function that creates the Program
+    Builder in an Environment if it is not there already.
+
+    If it is already there, we return the existing one.
+    """
+
+    try:
+        program = env['BUILDERS']['Program']
+    except KeyError:
+        import SCons.Defaults
+        program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction,
+                                        emitter = '$PROGEMITTER',
+                                        prefix = '$PROGPREFIX',
+                                        suffix = '$PROGSUFFIX',
+                                        src_suffix = '$OBJSUFFIX',
+                                        src_builder = 'Object',
+                                        target_scanner = ProgramScanner)
+        env['BUILDERS']['Program'] = program
+
+    return program
+
+def createStaticLibBuilder(env):
+    """This is a utility function that creates the StaticLibrary
+    Builder in an Environment if it is not there already.
+
+    If it is already there, we return the existing one.
+    """
+
+    try:
+        static_lib = env['BUILDERS']['StaticLibrary']
+    except KeyError:
+        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
+        if env.Detect('ranlib'):
+            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
+            action_list.append(ranlib_action)
+
+        static_lib = SCons.Builder.Builder(action = action_list,
+                                           emitter = '$LIBEMITTER',
+                                           prefix = '$LIBPREFIX',
+                                           suffix = '$LIBSUFFIX',
+                                           src_suffix = '$OBJSUFFIX',
+                                           src_builder = 'StaticObject')
+        env['BUILDERS']['StaticLibrary'] = static_lib
+        env['BUILDERS']['Library'] = static_lib
+
+    return static_lib
+
+def createSharedLibBuilder(env):
+    """This is a utility function that creates the SharedLibrary
+    Builder in an Environment if it is not there already.
+
+    If it is already there, we return the existing one.
+    """
+
+    try:
+        shared_lib = env['BUILDERS']['SharedLibrary']
+    except KeyError:
+        import SCons.Defaults
+        action_list = [ SCons.Defaults.SharedCheck,
+                        SCons.Defaults.ShLinkAction ]
+        shared_lib = SCons.Builder.Builder(action = action_list,
+                                           emitter = "$SHLIBEMITTER",
+                                           prefix = '$SHLIBPREFIX',
+                                           suffix = '$SHLIBSUFFIX',
+                                           target_scanner = ProgramScanner,
+                                           src_suffix = '$SHOBJSUFFIX',
+                                           src_builder = 'SharedObject')
+        env['BUILDERS']['SharedLibrary'] = shared_lib
+
+    return shared_lib
+
+def createLoadableModuleBuilder(env):
+    """This is a utility function that creates the LoadableModule
+    Builder in an Environment if it is not there already.
+
+    If it is already there, we return the existing one.
+    """
+
+    try:
+        ld_module = env['BUILDERS']['LoadableModule']
+    except KeyError:
+        import SCons.Defaults
+        action_list = [ SCons.Defaults.SharedCheck,
+                        SCons.Defaults.LdModuleLinkAction ]
+        ld_module = SCons.Builder.Builder(action = action_list,
+                                          emitter = "$SHLIBEMITTER",
+                                          prefix = '$LDMODULEPREFIX',
+                                          suffix = '$LDMODULESUFFIX',
+                                          target_scanner = ProgramScanner,
+                                          src_suffix = '$SHOBJSUFFIX',
+                                          src_builder = 'SharedObject')
+        env['BUILDERS']['LoadableModule'] = ld_module
+
+    return ld_module
+
+def createObjBuilders(env):
+    """This is a utility function that creates the StaticObject
+    and SharedObject Builders in an Environment if they
+    are not there already.
+
+    If they are there already, we return the existing ones.
+
+    This is a separate function because soooo many Tools
+    use this functionality.
+
+    The return is a 2-tuple of (StaticObject, SharedObject)
+    """
+
+
+    try:
+        static_obj = env['BUILDERS']['StaticObject']
+    except KeyError:
+        static_obj = SCons.Builder.Builder(action = {},
+                                           emitter = {},
+                                           prefix = '$OBJPREFIX',
+                                           suffix = '$OBJSUFFIX',
+                                           src_builder = ['CFile', 'CXXFile'],
+                                           source_scanner = SourceFileScanner,
+                                           single_source = 1)
+        env['BUILDERS']['StaticObject'] = static_obj
+        env['BUILDERS']['Object'] = static_obj
+
+    try:
+        shared_obj = env['BUILDERS']['SharedObject']
+    except KeyError:
+        shared_obj = SCons.Builder.Builder(action = {},
+                                           emitter = {},
+                                           prefix = '$SHOBJPREFIX',
+                                           suffix = '$SHOBJSUFFIX',
+                                           src_builder = ['CFile', 'CXXFile'],
+                                           source_scanner = SourceFileScanner,
+                                           single_source = 1)
+        env['BUILDERS']['SharedObject'] = shared_obj
+
+    return (static_obj, shared_obj)
+
+def createCFileBuilders(env):
+    """This is a utility function that creates the CFile/CXXFile
+    Builders in an Environment if they
+    are not there already.
+
+    If they are there already, we return the existing ones.
+
+    This is a separate function because soooo many Tools
+    use this functionality.
+
+    The return is a 2-tuple of (CFile, CXXFile)
+    """
+
+    try:
+        c_file = env['BUILDERS']['CFile']
+    except KeyError:
+        c_file = SCons.Builder.Builder(action = {},
+                                       emitter = {},
+                                       suffix = {None:'$CFILESUFFIX'})
+        env['BUILDERS']['CFile'] = c_file
+        env['CFILESUFFIX'] = '.c'
+
+    try:
+        cxx_file = env['BUILDERS']['CXXFile']
+    except KeyError:
+        cxx_file = SCons.Builder.Builder(action = {},
+                                         emitter = {},
+                                         suffix = {None:'$CXXFILESUFFIX'})
+        env['BUILDERS']['CXXFile'] = cxx_file
+        env['CXXFILESUFFIX'] = '.cc'
+
+    return (c_file, cxx_file)
+
+def FindTool(tools, env):
+    for tool in tools:
+        t = Tool(tool)
+        if t.exists(env):
+            return tool
+    return None
+
+def FindAllTools(tools, env):
+    def ToolExists(tool, env=env):
+        return Tool(tool).exists(env)
+    return filter (ToolExists, tools)
+             
+def tool_list(platform, env):
+
+    # XXX this logic about what tool to prefer on which platform
+    #     should be moved into either the platform files or
+    #     the tool files themselves.
+    # The search orders here are described in the man page.  If you
+    # change these search orders, update the man page as well.
+    if str(platform) == 'win32':
+        "prefer Microsoft tools on Windows"
+        linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
+        c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ]
+        cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'c++', 'bcc32' ]
+        assemblers = ['masm', 'nasm', 'gas', '386asm' ]
+        fortran_compilers = ['g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
+        ars = ['mslib', 'ar', 'tlib']
+    elif str(platform) == 'os2':
+        "prefer IBM tools on OS/2"
+        linkers = ['ilink', 'gnulink', 'mslink']
+        c_compilers = ['icc', 'gcc', 'msvc', 'cc']
+        cxx_compilers = ['icc', 'g++', 'msvc', 'c++']
+        assemblers = ['nasm', 'masm', 'gas']
+        fortran_compilers = ['ifl', 'g77']
+        ars = ['ar', 'mslib']
+    elif str(platform) == 'irix':
+        "prefer MIPSPro on IRIX"
+        linkers = ['sgilink', 'gnulink']
+        c_compilers = ['sgicc', 'gcc', 'cc']
+        cxx_compilers = ['sgic++', 'g++', 'c++']
+        assemblers = ['as', 'gas']
+        fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
+        ars = ['sgiar']
+    elif str(platform) == 'sunos':
+        "prefer Forte tools on SunOS"
+        linkers = ['sunlink', 'gnulink']
+        c_compilers = ['suncc', 'gcc', 'cc']
+        cxx_compilers = ['sunc++', 'g++', 'c++']
+        assemblers = ['as', 'gas']
+        fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
+        ars = ['sunar']
+    elif str(platform) == 'hpux':
+        "prefer aCC tools on HP-UX"
+        linkers = ['hplink', 'gnulink']
+        c_compilers = ['hpcc', 'gcc', 'cc']
+        cxx_compilers = ['hpc++', 'g++', 'c++']
+        assemblers = ['as', 'gas']
+        fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
+        ars = ['ar']
+    elif str(platform) == 'aix':
+        "prefer AIX Visual Age tools on AIX"
+        linkers = ['aixlink', 'gnulink']
+        c_compilers = ['aixcc', 'gcc', 'cc']
+        cxx_compilers = ['aixc++', 'g++', 'c++']
+        assemblers = ['as', 'gas']
+        fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran']
+        ars = ['ar']
+    elif str(platform) == 'darwin':
+        "prefer GNU tools on Mac OS X, except for some linkers and IBM tools"
+        linkers = ['applelink', 'gnulink']
+        c_compilers = ['gcc', 'cc']
+        cxx_compilers = ['g++', 'c++']
+        assemblers = ['as']
+        fortran_compilers = ['f95', 'f90', 'g77']
+        ars = ['ar']
+    else:
+        "prefer GNU tools on all other platforms"
+        linkers = ['gnulink', 'mslink', 'ilink']
+        c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
+        cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++']
+        assemblers = ['gas', 'nasm', 'masm']
+        fortran_compilers = ['f95', 'f90', 'g77', 'ifort', 'ifl', 'fortran']
+        ars = ['ar', 'mslib']
+
+    c_compiler = FindTool(c_compilers, env) or c_compilers[0]
+ 
+    # XXX this logic about what tool provides what should somehow be
+    #     moved into the tool files themselves.
+    if c_compiler and c_compiler == 'mingw':
+        # MinGW contains a linker, C compiler, C++ compiler, 
+        # Fortran compiler, archiver and assembler:
+        cxx_compiler = None
+        linker = None
+        assembler = None
+        fortran_compiler = None
+        ar = None
+    else:
+        # Don't use g++ if the C compiler has built-in C++ support:
+        if c_compiler in ('msvc', 'intelc', 'icc'):
+            cxx_compiler = None
+        else:
+            cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
+        linker = FindTool(linkers, env) or linkers[0]
+        assembler = FindTool(assemblers, env) or assemblers[0]
+        fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
+        ar = FindTool(ars, env) or ars[0]
+
+    other_tools = FindAllTools(['BitKeeper', 'CVS',
+                                'dmd',
+                                'dvipdf', 'dvips', 'gs',
+                                'jar', 'javac', 'javah',
+                                'latex', 'lex',
+                                'm4', 'midl', 'msvs',
+                                'pdflatex', 'pdftex', 'Perforce',
+                                'RCS', 'rmic', 'rpcgen',
+                                'SCCS',
+                                # 'Subversion',
+                                'swig',
+                                'tar', 'tex',
+                                'yacc', 'zip'],
+                               env)
+
+    tools = ([linker, c_compiler, cxx_compiler,
+              fortran_compiler, assembler, ar]
+             + other_tools)
+    
+    return filter(lambda x: x, tools)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/aixc++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/aixc++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/aixc++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,76 @@
+"""SCons.Tool.aixc++
+
+Tool-specific initialization for IBM xlC / Visual Age C++ compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/aixc++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Platform.aix
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+packages = ['vacpp.cmp.core', 'vacpp.cmp.batch', 'vacpp.cmp.C', 'ibmcxx.cmp']
+
+def get_xlc(env):
+    xlc = env.get('CXX', 'xlC')
+    xlc_r = env.get('SHCXX', 'xlC_r')
+    return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages)
+
+def smart_cxxflags(source, target, env, for_signature):
+    build_dir = env.GetBuildPath()
+    if build_dir:
+        return '-qtempinc=' + os.path.join(build_dir, 'tempinc')
+    return ''
+
+def generate(env):
+    """Add Builders and construction variables for xlC / Visual Age
+    suite to an Environment."""
+    path, _cxx, _shcxx, version = get_xlc(env)
+    if path:
+        _cxx = os.path.join(path, _cxx)
+        _shcxx = os.path.join(path, _shcxx)
+
+    cplusplus.generate(env)
+
+    env['CXX'] = _cxx
+    env['SHCXX'] = _shcxx
+    env['CXXVERSION'] = version
+    env['SHOBJSUFFIX'] = '.pic.o'
+    
+def exists(env):
+    path, _cxx, _shcxx, version = get_xlc(env)
+    if path and _cxx:
+        xlc = os.path.join(path, _cxx)
+        if os.path.exists(xlc):
+            return xlc
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/aixcc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/aixcc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/aixcc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,68 @@
+"""SCons.Tool.aixcc
+
+Tool-specific initialization for IBM xlc / Visual Age C compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixcc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Platform.aix
+
+import cc
+
+packages = ['vac.C', 'ibmcxx.cmp']
+
+def get_xlc(env):
+    xlc = env.get('CC', 'xlc')
+    xlc_r = env.get('SHCC', 'xlc_r')
+    return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages)
+
+def generate(env):
+    """Add Builders and construction variables for xlc / Visual Age
+    suite to an Environment."""
+    path, _cc, _shcc, version = get_xlc(env)
+    if path:
+        _cc = os.path.join(path, _cc)
+        _shcc = os.path.join(path, _shcc)
+
+    cc.generate(env)
+
+    env['CC'] = _cc
+    env['SHCC'] = _shcc
+    env['CCVERSION'] = version
+
+def exists(env):
+    path, _cc, _shcc, version = get_xlc(env)
+    if path and _cc:
+        xlc = os.path.join(path, _cc)
+        if os.path.exists(xlc):
+            return xlc
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/aixf77.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/aixf77.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/aixf77.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,74 @@
+"""engine.SCons.Tool.aixf77
+
+Tool-specific initialization for IBM Visual Age f77 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixf77.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+#import SCons.Platform.aix
+
+import f77
+
+# It would be good to look for the AIX F77 package the same way we're now
+# looking for the C and C++ packages.  This should be as easy as supplying
+# the correct package names in the following list and uncommenting the
+# SCons.Platform.aix_get_xlc() call the in the function below.
+packages = []
+
+def get_xlf77(env):
+    xlf77 = env.get('F77', 'xlf77')
+    xlf77_r = env.get('SHF77', 'xlf77_r')
+    #return SCons.Platform.aix.get_xlc(env, xlf77, xlf77_r, packages)
+    return (None, xlf77, xlf77_r, None)
+
+def generate(env):
+    """
+    Add Builders and construction variables for the Visual Age FORTRAN
+    compiler to an Environment.
+    """
+    path, _f77, _shf77, version = get_xlf77(env)
+    if path:
+        _f77 = os.path.join(path, _f77)
+        _shf77 = os.path.join(path, _shf77)
+
+    f77.generate(env)
+
+    env['F77'] = _f77
+    env['SHF77'] = _shf77
+
+def exists(env):
+    path, _f77, _shf77, version = get_xlf77(env)
+    if path and _f77:
+        xlf77 = os.path.join(path, _f77)
+        if os.path.exists(xlf77):
+            return xlf77
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/aixlink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/aixlink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/aixlink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,70 @@
+"""SCons.Tool.aixlink
+
+Tool-specific initialization for the IBM Visual Age linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/aixlink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+
+import SCons.Util
+
+import aixcc
+import link
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+def smart_linkflags(source, target, env, for_signature):
+    if cplusplus.iscplusplus(source):
+        build_dir = env.subst('$BUILDDIR')
+        if build_dir:
+            return '-qtempinc=' + os.path.join(build_dir, 'tempinc')
+    return ''
+
+def generate(env):
+    """
+    Add Builders and construction variables for Visual Age linker to
+    an Environment.
+    """
+    link.generate(env)
+
+    env['SMARTLINKFLAGS'] = smart_linkflags
+    env['LINKFLAGS']      = SCons.Util.CLVar('$SMARTLINKFLAGS')
+    env['SHLINKFLAGS']    = SCons.Util.CLVar('$LINKFLAGS -qmkshrobj -qsuppress=1501-218')
+    env['SHLIBSUFFIX']    = '.a'
+
+def exists(env):
+    path, _cc, _shcc, version = aixcc.get_xlc(env)
+    if path and _cc:
+        xlc = os.path.join(path, _cc)
+        if os.path.exists(xlc):
+            return xlc
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/applelink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/applelink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/applelink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,64 @@
+"""SCons.Tool.applelink
+
+Tool-specific initialization for the Apple gnu-like linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/applelink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import gnulink
+
+def generate(env):
+    """Add Builders and construction variables for applelink to an
+    Environment."""
+    gnulink.generate(env)
+
+    env['FRAMEWORKPATHPREFIX'] = '-F'
+    env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}'
+    env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}'
+    env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib')
+    env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS'
+
+    # override the default for loadable modules, which are different
+    # on OS X than dynamic shared libs.  echoing what XCode does for
+    # pre/suffixes:
+    env['LDMODULEPREFIX'] = '' 
+    env['LDMODULESUFFIX'] = '' 
+    env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle')
+    env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
+
+
+
+def exists(env):
+    import sys
+    return sys.platform == 'darwin'

Added: cs/scons/scons-local-0.96.92/SCons/Tool/ar.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/ar.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/ar.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,57 @@
+"""SCons.Tool.ar
+
+Tool-specific initialization for ar (library archive).
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/ar.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+
+    env['AR']          = 'ar'
+    env['ARFLAGS']     = SCons.Util.CLVar('rc')
+    env['ARCOM']       = '$AR $ARFLAGS $TARGET $SOURCES'
+    env['LIBPREFIX']   = 'lib'
+    env['LIBSUFFIX']   = '.a'
+
+    if env.Detect('ranlib'):
+        env['RANLIB']      = 'ranlib'
+        env['RANLIBFLAGS'] = SCons.Util.CLVar('')
+        env['RANLIBCOM']   = '$RANLIB $RANLIBFLAGS $TARGET'
+
+def exists(env):
+    return env.Detect('ar')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/as.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/as.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/as.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,68 @@
+"""SCons.Tool.as
+
+Tool-specific initialization for as, the generic Posix assembler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/as.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+assemblers = ['as']
+
+ASSuffixes = ['.s', '.asm', '.ASM']
+ASPPSuffixes = ['.spp', '.SPP']
+if SCons.Util.case_sensitive_suffixes('.s', '.S'):
+    ASPPSuffixes.extend(['.S'])
+else:
+    ASSuffixes.extend(['.S'])
+
+def generate(env):
+    """Add Builders and construction variables for as to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in ASSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+
+    for suffix in ASPPSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASPPAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+
+    env['AS']        = env.Detect(assemblers) or 'as'
+    env['ASFLAGS']   = SCons.Util.CLVar('')
+    env['ASCOM']     = '$AS $ASFLAGS -o $TARGET $SOURCES'
+    env['ASPPFLAGS'] = '$ASFLAGS'
+    env['ASPPCOM']   = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+
+def exists(env):
+    return env.Detect(assemblers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/bcc32.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/bcc32.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/bcc32.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,79 @@
+"""SCons.Tool.bcc32
+
+XXX
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/bcc32.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import string
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+def findIt(program, env):
+    # First search in the SCons path and then the OS path:
+    borwin = env.WhereIs(program) or SCons.Util.WhereIs(program)
+    if borwin:
+        dir = os.path.dirname(borwin)
+        path = env['ENV'].get('PATH', [])
+        if not path:
+            path = []
+        if SCons.Util.is_String(path):
+            path = string.split(path, os.pathsep)
+        env['ENV']['PATH'] = string.join([dir]+path, os.pathsep)
+    return borwin
+
+def generate(env):
+    findIt('bcc32', env)
+    """Add Builders and construction variables for bcc to an
+    Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+    for suffix in ['.c', '.cpp']:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+        shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
+
+    env['CC']        = 'bcc32'
+    env['CCFLAGS']   = SCons.Util.CLVar('')
+    env['CCCOM']     = '$CC -q $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
+    env['SHCC']      = '$CC'
+    env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
+    env['SHCCCOM']   = '$SHCC -WD $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
+    env['CPPDEFPREFIX']  = '-D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+    env['SHOBJSUFFIX'] = '.dll'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
+    env['CFILESUFFIX'] = '.cpp'
+
+def exists(env):
+    return findIt('bcc32', env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/c++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/c++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/c++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,89 @@
+"""SCons.Tool.c++
+
+Tool-specific initialization for generic Posix C++ compilers.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/c++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Tool
+import SCons.Defaults
+import SCons.Util
+
+compilers = ['CC', 'c++']
+
+CXXSuffixes = ['.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm']
+if SCons.Util.case_sensitive_suffixes('.c', '.C'):
+    CXXSuffixes.append('.C')
+
+def iscplusplus(source):
+    if not source:
+        # Source might be None for unusual cases like SConf.
+        return 0
+    for s in source:
+        if s.sources:
+            ext = os.path.splitext(str(s.sources[0]))[1]
+            if ext in CXXSuffixes:
+                return 1
+    return 0
+
+def generate(env):
+    """
+    Add Builders and construction variables for Visual Age C++ compilers
+    to an Environment.
+    """
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CXXSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CXXAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+        shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
+        
+    env['CXX']        = 'c++'
+    env['CXXFLAGS']   = SCons.Util.CLVar('$CCFLAGS')
+    env['CXXCOM']     = '$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES'
+    env['SHCXX']      = '$CXX'
+    env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
+    env['SHCXXCOM']   = '$SHCXX -o $TARGET -c $SHCXXFLAGS $_CCCOMCOM $SOURCES'
+
+    env['CPPDEFPREFIX']  = '-D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+    env['SHOBJSUFFIX'] = '.os'
+    env['OBJSUFFIX'] = '.o'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
+
+    env['CXXFILESUFFIX'] = '.cc'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/cc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/cc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/cc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,81 @@
+"""SCons.Tool.cc
+
+Tool-specific initialization for generic Posix C compilers.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/cc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool
+import SCons.Defaults
+import SCons.Util
+
+CSuffixes = ['.c', '.m']
+if not SCons.Util.case_sensitive_suffixes('.c', '.C'):
+    CSuffixes.append('.C')
+
+def generate(env):
+    """
+    Add Builders and construction variables for C compilers to an Environment.
+    """
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+        shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
+        
+    env['_CCCOMCOM'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS'
+    # It's a hack to test for darwin here, but the alternative of creating
+    # an applecc.py to contain this seems overkill.  Maybe someday the Apple
+    # platform will require more setup and this logic will be moved.
+    env['FRAMEWORKS'] = SCons.Util.CLVar('')
+    env['FRAMEWORKPATH'] = SCons.Util.CLVar('')
+    if env['PLATFORM'] == 'darwin':
+        env['_CCCOMCOM'] = env['_CCCOMCOM'] + ' $_FRAMEWORKPATH'
+
+    env['CC']        = 'cc'
+    env['CCFLAGS']   = SCons.Util.CLVar('')
+    env['CCCOM']     = '$CC -o $TARGET -c $CCFLAGS $_CCCOMCOM $SOURCES'
+    env['SHCC']      = '$CC'
+    env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
+    env['SHCCCOM']   = '$SHCC -o $TARGET -c $SHCCFLAGS $_CCCOMCOM $SOURCES'
+
+    env['CPPDEFPREFIX']  = '-D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+    env['SHOBJSUFFIX'] = '.os'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 0
+
+    env['CFILESUFFIX'] = '.c'
+
+def exists(env):
+    return env.Detect('cc')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/cvf.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/cvf.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/cvf.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,53 @@
+"""engine.SCons.Tool.cvf
+
+Tool-specific initialization for the Compaq Visual Fortran compiler.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/cvf.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+import fortran
+
+compilers = ['f90']
+
+def generate(env):
+    """Add Builders and construction variables for compaq visual fortran to an Environment."""
+
+    fortran.generate(env)
+
+    env['FORTRAN']        = 'f90'
+    env['FORTRANCOM']     = '$FORTRAN $FORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
+    env['FORTRANPPCOM']   = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
+    env['SHFORTRANCOM']   = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
+    env['SHFORTRANPPCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANMODFLAG $_FORTRANINCFLAGS /compile_only ${SOURCES.windows} /object:${TARGET.windows}'
+    env['OBJSUFFIX']      = '.obj'
+    env['FORTRANMODDIR'] = '${TARGET.dir}'
+    env['FORTRANMODDIRPREFIX'] = '/module:'
+    env['FORTRANMODDIRSUFFIX'] = ''
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/default.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/default.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/default.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,44 @@
+"""SCons.Tool.default
+
+Initialization with a default tool list.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/default.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool
+
+def generate(env):
+    """Add default tools."""
+    for t in SCons.Tool.tool_list(env['PLATFORM'], env):
+        SCons.Tool.Tool(t)(env)
+
+def exists(env):
+    return 1

Added: cs/scons/scons-local-0.96.92/SCons/Tool/dmd.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/dmd.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/dmd.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,210 @@
+"""SCons.Tool.dmd
+
+Tool-specific initialization for the Digital Mars D compiler.
+(http://digitalmars.com/d)
+
+Coded by Andy Friesen (andy at ikagames.com)
+15 November 2003
+
+There are a number of problems with this script at this point in time.
+The one that irritates me the most is the Windows linker setup.  The D
+linker doesn't have a way to add lib paths on the commandline, as far
+as I can see.  You have to specify paths relative to the SConscript or
+use absolute paths.  To hack around it, add '#/blah'.  This will link
+blah.lib from the directory where SConstruct resides.
+
+Compiler variables:
+    DC - The name of the D compiler to use.  Defaults to dmd.
+    DPATH - List of paths to search for import modules.
+    DVERSIONS - List of version tags to enable when compiling.
+    DDEBUG - List of debug tags to enable when compiling.
+
+Linker related variables:
+    LIBS - List of library files to link in.
+    DLINK - Name of the linker to use.  Defaults to dmd.
+    DLINKFLAGS - List of linker flags.
+
+Lib tool variables:
+    DLIB - Name of the lib tool to use.  Defaults to lib.
+    DLIBFLAGS - List of flags to pass to the lib tool.
+    LIBS - Same as for the linker. (libraries to pull into the .lib)
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/dmd.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import string
+
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Scanner.D
+import SCons.Tool
+
+# Adapted from c++.py
+def isD(source):
+    if not source:
+        return 0
+
+    for s in source:
+        if s.sources:
+            ext = os.path.splitext(str(s.sources[0]))[1]
+            if ext == '.d':
+                return 1
+    return 0
+
+smart_link = {}
+
+smart_lib = {}
+
+def generate(env):
+    global smart_link
+    global smart_lib
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    DAction = SCons.Action.Action('$DCOM', '$DCOMSTR')
+
+    static_obj.add_action('.d', DAction)
+    shared_obj.add_action('.d', DAction)
+    static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter)
+    shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter)
+
+    env['DC'] = 'dmd'
+    env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES'
+    env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}  $)'
+    env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)}  $)'
+    env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)'
+    env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)'
+
+    env['DPATH'] = ['#/']
+    env['DFLAGS'] = []
+    env['DVERSIONS'] = []
+    env['DDEBUG'] = []
+
+    # Add the path to the standard library.
+    # This is merely for the convenience of the dependency scanner.
+    dmd_path = env.WhereIs('dmd')
+    if dmd_path:
+        x = string.rindex(dmd_path, 'dmd')
+        phobosDir = dmd_path[:x] + '/../src/phobos'
+        if os.path.isdir(phobosDir):
+            env.Append(DPATH = [phobosDir])
+
+    env['DINCPREFIX'] = '-I'
+    env['DINCSUFFIX'] = ''
+    env['DVERPREFIX'] = '-version='
+    env['DVERSUFFIX'] = ''
+    env['DDEBUGPREFIX'] = '-debug='
+    env['DDEBUGSUFFIX'] = ''
+    env['DFLAGPREFIX'] = '-'
+    env['DFLAGSUFFIX'] = ''
+    env['DFILESUFFIX'] = '.d'
+
+    # Need to use the Digital Mars linker/lib on windows.
+    # *nix can just use GNU link.
+    if env['PLATFORM'] == 'win32':
+        env['DLINK'] = '$DC'
+        env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS $_DLINKLIBFLAGS'
+        env['DLIB'] = 'lib'
+        env['DLIBCOM'] = '$DLIB $_DLIBFLAGS -c $TARGET $SOURCES $_DLINKLIBFLAGS'
+
+        env['_DLINKLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+        env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)'
+        env['DLINKFLAGS'] = []
+        env['DLIBLINKPREFIX'] = ''
+        env['DLIBLINKSUFFIX'] = '.lib'
+        env['DLIBFLAGPREFIX'] = '-'
+        env['DLIBFLAGSUFFIX'] = ''
+        env['DLINKFLAGPREFIX'] = '-'
+        env['DLINKFLAGSUFFIX'] = ''
+
+        SCons.Tool.createStaticLibBuilder(env)
+
+        # Basically, we hijack the link and ar builders with our own.
+        # these builders check for the presence of D source, and swap out
+        # the system's defaults for the Digital Mars tools.  If there's no D
+        # source, then we silently return the previous settings.
+        linkcom = env.get('LINKCOM')
+        try:
+            env['SMART_LINKCOM'] = smart_link[linkcom]
+        except KeyError:
+            def _smartLink(source, target, env, for_signature,
+                           defaultLinker=linkcom):
+                if isD(source):
+                    # XXX I'm not sure how to add a $DLINKCOMSTR variable
+                    # so that it works with this _smartLink() logic,
+                    # and I don't have a D compiler/linker to try it out,
+                    # so we'll leave it alone for now.
+                    return '$DLINKCOM'
+                else:
+                    return defaultLinker
+            env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink
+
+        arcom = env.get('ARCOM')
+        try:
+            env['SMART_ARCOM'] = smart_lib[arcom]
+        except KeyError:
+            def _smartLib(source, target, env, for_signature,
+                         defaultLib=arcom):
+                if isD(source):
+                    # XXX I'm not sure how to add a $DLIBCOMSTR variable
+                    # so that it works with this _smartLib() logic, and
+                    # I don't have a D compiler/archiver to try it out,
+                    # so we'll leave it alone for now.
+                    return '$DLIBCOM'
+                else:
+                    return defaultLib
+            env['SMART_ARCOM'] = smart_lib[arcom] = _smartLib
+
+        # It is worth noting that the final space in these strings is
+        # absolutely pivotal.  SCons sees these as actions and not generators
+        # if it is not there. (very bad)
+        env['ARCOM'] = '$SMART_ARCOM '
+        env['LINKCOM'] = '$SMART_LINKCOM '
+    else: # assuming linux
+        linkcom = env.get('LINKCOM')
+        try:
+            env['SMART_LINKCOM'] = smart_link[linkcom]
+        except KeyError:
+            def _smartLink(source, target, env, for_signature,
+                           defaultLinker=linkcom):
+                if isD(source):
+                    try:
+                        libs = env['LIBS']
+                    except KeyError:
+                        libs = []
+                    if 'phobos' not in libs:
+                        env.Append(LIBS = ['phobos'])
+                    if 'pthread' not in libs:
+                        env.Append(LIBS = ['pthread'])
+                return defaultLinker
+            env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink
+
+        env['LINKCOM'] = '$SMART_LINKCOM '
+
+def exists(env):
+    return env.Detect('dmd')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/dvi.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/dvi.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/dvi.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,57 @@
+"""SCons.Tool.dvi
+
+Common DVI Builder definition for various other Tool modules that use it.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/dvi.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Builder
+import SCons.Tool
+
+DVIBuilder = None
+
+def generate(env):
+    try:
+        bld = env['BUILDERS']['DVI']
+    except KeyError:
+        global DVIBuilder
+
+        if DVIBuilder is None:
+            # The suffix is hard-coded to '.dvi', not configurable via a
+            # construction variable like $DVISUFFIX, because the output
+            # file name is hard-coded within TeX.
+            DVIBuilder = SCons.Builder.Builder(action = {},
+                                               source_scanner = SCons.Tool.LaTeXScanner,
+                                               suffix = '.dvi',
+                                               emitter = {})
+
+        env['BUILDERS']['DVI'] = DVIBuilder
+
+def exists(env):
+    # This only puts a skeleton Builder in place, so if someone
+    # references this Tool directly, it's always "available."
+    return 1

Added: cs/scons/scons-local-0.96.92/SCons/Tool/dvipdf.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/dvipdf.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/dvipdf.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,75 @@
+"""SCons.Tool.dvipdf
+
+Tool-specific initialization for dvipdf.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/dvipdf.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Tool.pdf
+import SCons.Util
+
+PDFAction = None
+
+def PDFEmitter(target, source, env):
+    """Strips any .aux or .log files from the input source list.
+    These are created by the TeX Builder that in all likelihood was
+    used to generate the .dvi file we're using as input, and we only
+    care about the .dvi file.
+    """
+    def strip_suffixes(n):
+        return not SCons.Util.splitext(str(n))[1] in ['.aux', '.log']
+    source = filter(strip_suffixes, source)
+    return (target, source)
+
+def generate(env):
+    """Add Builders and construction variables for dvipdf to an Environment."""
+    global PDFAction
+    if PDFAction is None:
+        PDFAction = SCons.Action.Action('$DVIPDFCOM', '$DVIPDFCOMSTR')
+
+    import pdf
+    pdf.generate(env)
+
+    bld = env['BUILDERS']['PDF']
+    bld.add_action('.dvi', PDFAction)
+    bld.add_emitter('.dvi', PDFEmitter)
+
+    env['DVIPDF']      = 'dvipdf'
+    env['DVIPDFFLAGS'] = SCons.Util.CLVar('')
+    env['DVIPDFCOM']   = '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET'
+
+    # Deprecated synonym.
+    env['PDFCOM']      = ['$DVIPDFCOM']
+
+def exists(env):
+    return env.Detect('dvipdf')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/dvips.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/dvips.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/dvips.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,66 @@
+"""SCons.Tool.dvips
+
+Tool-specific initialization for dvips.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/dvips.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+PSAction = None
+PSBuilder = None
+
+def generate(env):
+    """Add Builders and construction variables for dvips to an Environment."""
+    global PSAction
+    if PSAction is None:
+        PSAction = SCons.Action.Action('$PSCOM', '$PSCOMSTR')
+
+    global PSBuilder
+    if PSBuilder is None:
+        PSBuilder = SCons.Builder.Builder(action = PSAction,
+                                          prefix = '$PSPREFIX',
+                                          suffix = '$PSSUFFIX',
+                                          src_suffix = '.dvi',
+                                          src_builder = 'DVI')
+
+    env['BUILDERS']['PostScript'] = PSBuilder
+    
+    env['DVIPS']      = 'dvips'
+    env['DVIPSFLAGS'] = SCons.Util.CLVar('')
+    env['PSCOM']      = '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCE'
+    env['PSPREFIX'] = ''
+    env['PSSUFFIX'] = '.ps'
+
+def exists(env):
+    return env.Detect('dvips')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/f77.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/f77.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/f77.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,134 @@
+"""engine.SCons.Tool.f77
+
+Tool-specific initialization for the generic Posix f77 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/f77.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Scanner.Fortran
+import SCons.Tool
+import SCons.Util
+import fortran
+
+compilers = ['f77']
+
+#
+F77Suffixes = ['.f77']
+F77PPSuffixes = []
+if SCons.Util.case_sensitive_suffixes('.f77', '.F77'):
+    F77PPSuffixes.append('.F77')
+else:
+    F77Suffixes.append('.F77')
+
+#
+F77Scan = SCons.Scanner.Fortran.FortranScan("F77PATH")
+
+for suffix in F77Suffixes + F77PPSuffixes:
+    SCons.Tool.SourceFileScanner.add_scanner(suffix, F77Scan)
+
+#
+fVLG = fortran.VariableListGenerator
+
+F77Generator = fVLG('F77', 'FORTRAN', '_FORTRAND')
+F77FlagsGenerator = fVLG('F77FLAGS', 'FORTRANFLAGS')
+F77CommandGenerator = fVLG('F77COM', 'FORTRANCOM', '_F77COMD')
+F77CommandStrGenerator = fVLG('F77COMSTR', 'FORTRANCOMSTR', '_F77COMSTRD')
+F77PPCommandGenerator = fVLG('F77PPCOM', 'FORTRANPPCOM', '_F77PPCOMD')
+F77PPCommandStrGenerator = fVLG('F77PPCOMSTR', 'FORTRANPPCOMSTR', '_F77PPCOMSTRD')
+ShF77Generator = fVLG('SHF77', 'SHFORTRAN', 'F77', 'FORTRAN', '_FORTRAND')
+ShF77FlagsGenerator = fVLG('SHF77FLAGS', 'SHFORTRANFLAGS')
+ShF77CommandGenerator = fVLG('SHF77COM', 'SHFORTRANCOM', '_SHF77COMD')
+ShF77CommandStrGenerator = fVLG('SHF77COMSTR', 'SHFORTRANCOMSTR', '_SHF77COMSTRD')
+ShF77PPCommandGenerator = fVLG('SHF77PPCOM', 'SHFORTRANPPCOM', '_SHF77PPCOMD')
+ShF77PPCommandStrGenerator = fVLG('SHF77PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF77PPCOMSTRD')
+
+del fVLG
+
+#
+F77Action = SCons.Action.Action('$_F77COMG ', '$_F77COMSTRG')
+F77PPAction = SCons.Action.Action('$_F77PPCOMG ', '$_F77PPCOMSTRG')
+ShF77Action = SCons.Action.Action('$_SHF77COMG ', '$_SHF77COMSTRG')
+ShF77PPAction = SCons.Action.Action('$_SHF77PPCOMG ', '$_SHF77PPCOMSTRG')
+
+def add_to_env(env):
+    """Add Builders and construction variables for f77 to an Environment."""
+    env.AppendUnique(FORTRANSUFFIXES = F77Suffixes + F77PPSuffixes)
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in F77Suffixes:
+        static_obj.add_action(suffix, F77Action)
+        shared_obj.add_action(suffix, ShF77Action)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+
+    for suffix in F77PPSuffixes:
+        static_obj.add_action(suffix, F77PPAction)
+        shared_obj.add_action(suffix, ShF77PPAction)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+
+    env['_F77G']            = F77Generator
+    env['_F77FLAGSG']       = F77FlagsGenerator
+    env['_F77COMG']         = F77CommandGenerator
+    env['_F77PPCOMG']       = F77PPCommandGenerator
+    env['_F77COMSTRG']      = F77CommandStrGenerator
+    env['_F77PPCOMSTRG']    = F77PPCommandStrGenerator
+
+    env['_SHF77G']          = ShF77Generator
+    env['_SHF77FLAGSG']     = ShF77FlagsGenerator
+    env['_SHF77COMG']       = ShF77CommandGenerator
+    env['_SHF77PPCOMG']     = ShF77PPCommandGenerator
+    env['_SHF77COMSTRG']    = ShF77CommandStrGenerator
+    env['_SHF77PPCOMSTRG']  = ShF77PPCommandStrGenerator
+
+    env['_F77INCFLAGS'] = '$( ${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+
+    env['_F77COMD']     = '$_F77G -o $TARGET -c $_F77FLAGSG $_F77INCFLAGS $SOURCES'
+    env['_F77PPCOMD']   = '$_F77G -o $TARGET -c $_F77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES'
+    env['_SHF77COMD']   = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $_F77INCFLAGS $SOURCES'
+    env['_SHF77PPCOMD'] = '$_SHF77G -o $TARGET -c $_SHF77FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F77INCFLAGS $SOURCES'
+
+def generate(env):
+    fortran.add_to_env(env)
+
+    import f90
+    import f95
+    f90.add_to_env(env)
+    f95.add_to_env(env)
+
+    add_to_env(env)
+
+    env['_FORTRAND']        = env.Detect(compilers) or 'f77'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/f90.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/f90.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/f90.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,127 @@
+"""engine.SCons.Tool.f90
+
+Tool-specific initialization for the generic Posix f90 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/f90.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Scanner.Fortran
+import SCons.Tool
+import SCons.Util
+import fortran
+
+compilers = ['f90']
+
+#
+F90Suffixes = ['.f90']
+F90PPSuffixes = []
+if SCons.Util.case_sensitive_suffixes('.f90', '.F90'):
+    F90PPSuffixes.append('.F90')
+else:
+    F90Suffixes.append('.F90')
+
+#
+F90Scan = SCons.Scanner.Fortran.FortranScan("F90PATH")
+
+for suffix in F90Suffixes + F90PPSuffixes:
+    SCons.Tool.SourceFileScanner.add_scanner(suffix, F90Scan)
+
+#
+fVLG = fortran.VariableListGenerator
+
+F90Generator = fVLG('F90', 'FORTRAN', '_FORTRAND')
+F90FlagsGenerator = fVLG('F90FLAGS', 'FORTRANFLAGS')
+F90CommandGenerator = fVLG('F90COM', 'FORTRANCOM', '_F90COMD')
+F90CommandStrGenerator = fVLG('F90COMSTR', 'FORTRANCOMSTR', '_F90COMSTRD')
+F90PPCommandGenerator = fVLG('F90PPCOM', 'FORTRANPPCOM', '_F90PPCOMD')
+F90PPCommandStrGenerator = fVLG('F90PPCOMSTR', 'FORTRANPPCOMSTR', '_F90PPCOMSTRD')
+ShF90Generator = fVLG('SHF90', 'SHFORTRAN', 'F90', 'FORTRAN', '_FORTRAND')
+ShF90FlagsGenerator = fVLG('SHF90FLAGS', 'SHFORTRANFLAGS')
+ShF90CommandGenerator = fVLG('SHF90COM', 'SHFORTRANCOM', '_SHF90COMD')
+ShF90CommandStrGenerator = fVLG('SHF90COMSTR', 'SHFORTRANCOMSTR', '_SHF90COMSTRD')
+ShF90PPCommandGenerator = fVLG('SHF90PPCOM', 'SHFORTRANPPCOM', '_SHF90PPCOMD')
+ShF90PPCommandStrGenerator = fVLG('SHF90PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF90PPCOMSTRD')
+
+del fVLG
+
+#
+F90Action = SCons.Action.Action('$_F90COMG ', '$_F90COMSTRG')
+F90PPAction = SCons.Action.Action('$_F90PPCOMG ', '$_F90PPCOMSTRG')
+ShF90Action = SCons.Action.Action('$_SHF90COMG ', '$_SHF90COMSTRG')
+ShF90PPAction = SCons.Action.Action('$_SHF90PPCOMG ', '$_SHF90PPCOMSTRG')
+
+def add_to_env(env):
+    """Add Builders and construction variables for f90 to an Environment."""
+    env.AppendUnique(FORTRANSUFFIXES = F90Suffixes + F90PPSuffixes)
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in F90Suffixes:
+        static_obj.add_action(suffix, F90Action)
+        shared_obj.add_action(suffix, ShF90Action)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+
+    for suffix in F90PPSuffixes:
+        static_obj.add_action(suffix, F90PPAction)
+        shared_obj.add_action(suffix, ShF90PPAction)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+  
+    env['_F90G']            = F90Generator
+    env['_F90FLAGSG']       = F90FlagsGenerator
+    env['_F90COMG']         = F90CommandGenerator
+    env['_F90COMSTRG']      = F90CommandStrGenerator
+    env['_F90PPCOMG']       = F90PPCommandGenerator
+    env['_F90PPCOMSTRG']    = F90PPCommandStrGenerator
+
+    env['_SHF90G']          = ShF90Generator
+    env['_SHF90FLAGSG']     = ShF90FlagsGenerator
+    env['_SHF90COMG']       = ShF90CommandGenerator
+    env['_SHF90COMSTRG']    = ShF90CommandStrGenerator
+    env['_SHF90PPCOMG']     = ShF90PPCommandGenerator
+    env['_SHF90PPCOMSTRG']  = ShF90PPCommandStrGenerator
+
+    env['_F90INCFLAGS'] = '$( ${_concat(INCPREFIX, F90PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+    env['_F90COMD']     = '$_F90G -o $TARGET -c $_F90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_F90PPCOMD']   = '$_F90G -o $TARGET -c $_F90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHF90COMD']   = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHF90PPCOMD'] = '$_SHF90G -o $TARGET -c $_SHF90FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F90INCFLAGS $_FORTRANMODFLAG $SOURCES'
+
+def generate(env):
+    fortran.add_to_env(env)
+    add_to_env(env)
+
+    env['_FORTRAND']        = env.Detect(compilers) or 'f90'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/f95.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/f95.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/f95.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,127 @@
+"""engine.SCons.Tool.f95
+
+Tool-specific initialization for the generic Posix f95 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/f95.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+import fortran
+
+compilers = ['f95']
+
+#
+F95Suffixes = ['.f95']
+F95PPSuffixes = []
+if SCons.Util.case_sensitive_suffixes('.f95', '.F95'):
+    F95PPSuffixes.append('.F95')
+else:
+    F95Suffixes.append('.F95')
+
+#
+F95Scan = SCons.Scanner.Fortran.FortranScan("F95PATH")
+
+for suffix in F95Suffixes + F95PPSuffixes:
+    SCons.Tool.SourceFileScanner.add_scanner(suffix, F95Scan)
+
+#
+fVLG = fortran.VariableListGenerator
+
+F95Generator = fVLG('F95', 'FORTRAN', '_FORTRAND')
+F95FlagsGenerator = fVLG('F95FLAGS', 'FORTRANFLAGS')
+F95CommandGenerator = fVLG('F95COM', 'FORTRANCOM', '_F95COMD')
+F95CommandStrGenerator = fVLG('F95COMSTR', 'FORTRANCOMSTR', '_F95COMSTRD')
+F95PPCommandGenerator = fVLG('F95PPCOM', 'FORTRANPPCOM', '_F95PPCOMD')
+F95PPCommandStrGenerator = fVLG('F95PPCOMSTR', 'FORTRANPPCOMSTR', '_F95PPCOMSTRD')
+ShF95Generator = fVLG('SHF95', 'SHFORTRAN', 'F95', 'FORTRAN', '_FORTRAND')
+ShF95FlagsGenerator = fVLG('SHF95FLAGS', 'SHFORTRANFLAGS')
+ShF95CommandGenerator = fVLG('SHF95COM', 'SHFORTRANCOM', '_SHF95COMD')
+ShF95CommandStrGenerator = fVLG('SHF95COMSTR', 'SHFORTRANCOMSTR', '_SHF95COMSTRD')
+ShF95PPCommandGenerator = fVLG('SHF95PPCOM', 'SHFORTRANPPCOM', '_SHF95PPCOMD')
+ShF95PPCommandStrGenerator = fVLG('SHF95PPCOMSTR', 'SHFORTRANPPCOMSTR', '_SHF95PPCOMSTRD')
+
+del fVLG
+
+#
+F95Action = SCons.Action.Action('$_F95COMG ', '$_F95COMSTRG')
+F95PPAction = SCons.Action.Action('$_F95PPCOMG ', '$_F95PPCOMSTRG')
+ShF95Action = SCons.Action.Action('$_SHF95COMG ', '$_SHF95COMSTRG')
+ShF95PPAction = SCons.Action.Action('$_SHF95PPCOMG ', '$_SHF95PPCOMSTRG')
+
+def add_to_env(env):
+    """Add Builders and construction variables for f95 to an Environment."""
+    env.AppendUnique(FORTRANSUFFIXES = F95Suffixes + F95PPSuffixes)
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in F95Suffixes:
+        static_obj.add_action(suffix, F95Action)
+        shared_obj.add_action(suffix, ShF95Action)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+
+    for suffix in F95PPSuffixes:
+        static_obj.add_action(suffix, F95PPAction)
+        shared_obj.add_action(suffix, ShF95PPAction)
+        static_obj.add_emitter(suffix, fortran.FortranEmitter)
+        shared_obj.add_emitter(suffix, fortran.ShFortranEmitter)
+
+    env['_F95G']           = F95Generator
+    env['_F95FLAGSG']      = F95FlagsGenerator
+    env['_F95COMG']        = F95CommandGenerator
+    env['_F95COMSTRG']     = F95CommandStrGenerator
+    env['_F95PPCOMG']      = F95PPCommandGenerator
+    env['_F95PPCOMSTRG']   = F95PPCommandStrGenerator
+
+    env['_SHF95G']         = ShF95Generator
+    env['_SHF95FLAGSG']    = ShF95FlagsGenerator
+    env['_SHF95COMG']      = ShF95CommandGenerator
+    env['_SHF95COMSTRG']   = ShF95CommandStrGenerator
+    env['_SHF95PPCOMG']    = ShF95PPCommandGenerator
+    env['_SHF95PPCOMSTRG'] = ShF95PPCommandStrGenerator
+
+    env['_F95INCFLAGS'] = '$( ${_concat(INCPREFIX, F95PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+
+    env['_F95COMD']     = '$_F95G -o $TARGET -c $_F95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_F95PPCOMD']   = '$_F95G -o $TARGET -c $_F95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHF95COMD']   = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHF95PPCOMD'] = '$_SHF95G -o $TARGET -c $_SHF95FLAGSG $CPPFLAGS $_CPPDEFFLAGS $_F95INCFLAGS $_FORTRANMODFLAG $SOURCES'
+
+def generate(env):
+    fortran.add_to_env(env)
+    add_to_env(env)
+
+    env['_FORTRAND']        = env.Detect(compilers) or 'f95'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/fortran.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/fortran.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/fortran.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,185 @@
+"""SCons.Tool.fortran
+
+Tool-specific initialization for a generic Posix f77/f90 Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/fortran.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import re
+import string
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Scanner.Fortran
+import SCons.Tool
+import SCons.Util
+
+compilers = ['f95', 'f90', 'f77']
+
+#
+#  Not yet sure how to deal with fortran pre-processor functions.
+#  Different compilers do this differently in modern fortran.  Some still
+#  rely on the c pre-processor, some (like cvf, ivf) have their own
+#  pre-processor technology and use intermediary suffixes (.i90)
+#
+FortranSuffixes = [".f", ".for", ".ftn", ]
+FortranPPSuffixes = ['.fpp', '.FPP']
+upper_case = [".F", ".FOR", ".FTN"]
+if SCons.Util.case_sensitive_suffixes('.f', '.F'):
+    FortranPPSuffixes.extend(upper_case)
+else:
+    FortranSuffixes.extend(upper_case)
+
+#
+FortranScan = SCons.Scanner.Fortran.FortranScan("FORTRANPATH")
+
+for suffix in FortranSuffixes + FortranPPSuffixes:
+    SCons.Tool.SourceFileScanner.add_scanner(suffix, FortranScan)
+
+#
+def _fortranEmitter(target, source, env):
+    node = source[0].rfile()
+    if not node.exists() and not node.is_derived():
+       print "Could not locate " + str(node.name)
+       return ([], [])
+    mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)"""
+    cre = re.compile(mod_regex,re.M)
+    # Retrieve all USE'd module names
+    modules = cre.findall(node.get_contents())
+    # Remove unique items from the list
+    modules = SCons.Util.unique(modules)
+    # Convert module name to a .mod filename
+    suffix = env.subst('$FORTRANMODSUFFIX')
+    moddir = env.subst('$FORTRANMODDIR')
+    modules = map(lambda x, s=suffix: string.lower(x) + s, modules)
+    for m in modules:
+       target.append(env.fs.File(m, moddir))
+    return (target, source)
+
+def FortranEmitter(target, source, env):
+    target, source = _fortranEmitter(target, source, env)
+    return SCons.Defaults.StaticObjectEmitter(target, source, env)
+
+def ShFortranEmitter(target, source, env):
+    target, source = _fortranEmitter(target, source, env)
+    return SCons.Defaults.SharedObjectEmitter(target, source, env)
+
+class VariableListGenerator:
+    def __init__(self, *variablelist):
+        self.variablelist = variablelist
+    def __call__(self, env, target, source, for_signature=0):
+        for v in self.variablelist:
+            try: return env[v]
+            except KeyError: pass
+        return ''
+
+#
+FortranGenerator = VariableListGenerator('FORTRAN', 'F77', '_FORTRAND')
+FortranFlagsGenerator = VariableListGenerator('FORTRANFLAGS', 'F77FLAGS')
+FortranCommandGenerator = VariableListGenerator('FORTRANCOM', 'F77COM', '_FORTRANCOMD')
+FortranCommandStrGenerator = VariableListGenerator('FORTRANCOMSTR', 'F77COMSTR', '_FORTRANCOMSTRD')
+FortranPPCommandGenerator = VariableListGenerator('FORTRANPPCOM', 'F77PPCOM', '_FORTRANPPCOMD')
+FortranPPCommandStrGenerator = VariableListGenerator('FORTRANPPCOMSTR', 'F77PPCOMSTR', '_FORTRANPPCOMSTRD')
+ShFortranGenerator = VariableListGenerator('SHFORTRAN', 'SHF77', 'FORTRAN', 'F77', '_FORTRAND')
+ShFortranFlagsGenerator = VariableListGenerator('SHFORTRANFLAGS', 'SHF77FLAGS')
+ShFortranCommandGenerator = VariableListGenerator('SHFORTRANCOM', 'SHF77COM', '_SHFORTRANCOMD')
+ShFortranCommandStrGenerator = VariableListGenerator('SHFORTRANCOMSTR', 'SHF77COMSTR', '_SHFORTRANCOMSTRD')
+ShFortranPPCommandGenerator = VariableListGenerator('SHFORTRANPPCOM', 'SHF77PPCOM', '_SHFORTRANPPCOMD')
+ShFortranPPCommandStrGenerator = VariableListGenerator('SHFORTRANPPCOMSTR', 'SHF77PPCOMSTR', '_SHFORTRANPPCOMSTRD')
+
+#
+FortranAction = SCons.Action.Action('$_FORTRANCOMG ', '$_FORTRANCOMSTRG')
+FortranPPAction = SCons.Action.Action('$_FORTRANPPCOMG ', '$_FORTRANPPCOMSTRG')
+ShFortranAction = SCons.Action.Action('$_SHFORTRANCOMG ', '$_SHFORTRANCOMSTRG')
+ShFortranPPAction = SCons.Action.Action('$_SHFORTRANPPCOMG ', '$_SHFORTRANPPCOMSTRG')
+
+def add_to_env(env):
+    """Add Builders and construction variables for Fortran to an Environment."""
+
+    env['_FORTRANG']            = FortranGenerator
+    env['_FORTRANFLAGSG']       = FortranFlagsGenerator
+    env['_FORTRANCOMG']         = FortranCommandGenerator
+    env['_FORTRANCOMSTRG']      = FortranCommandStrGenerator
+    env['_FORTRANPPCOMG']       = FortranPPCommandGenerator
+    env['_FORTRANPPCOMSTRG']    = FortranPPCommandStrGenerator
+
+    env['_SHFORTRANG']          = ShFortranGenerator
+    env['_SHFORTRANFLAGSG']     = ShFortranFlagsGenerator
+    env['_SHFORTRANCOMG']       = ShFortranCommandGenerator
+    env['_SHFORTRANCOMSTRG']    = ShFortranCommandStrGenerator
+    env['_SHFORTRANPPCOMG']     = ShFortranPPCommandGenerator
+    env['_SHFORTRANPPCOMSTRG']  = ShFortranPPCommandStrGenerator
+
+    env['_FORTRANINCFLAGS'] = '$( ${_concat(INCPREFIX, FORTRANPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+
+    env['FORTRANMODPREFIX'] = ''     # like $LIBPREFIX
+    env['FORTRANMODSUFFIX'] = '.mod' # like $LIBSUFFIX
+
+    env['FORTRANMODDIR'] = ''          # where the compiler should place .mod files
+    env['FORTRANMODDIRPREFIX'] = ''    # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
+    env['FORTRANMODDIRSUFFIX'] = ''    # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
+    env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__)} $)'
+
+    env.AppendUnique(FORTRANSUFFIXES = FortranSuffixes + FortranPPSuffixes)
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in FortranSuffixes:
+        static_obj.add_action(suffix, FortranAction)
+        shared_obj.add_action(suffix, ShFortranAction)
+        static_obj.add_emitter(suffix, FortranEmitter)
+        shared_obj.add_emitter(suffix, ShFortranEmitter)
+
+    for suffix in FortranPPSuffixes:
+        static_obj.add_action(suffix, FortranPPAction)
+        shared_obj.add_action(suffix, ShFortranPPAction)
+        static_obj.add_emitter(suffix, FortranEmitter)
+        shared_obj.add_emitter(suffix, ShFortranEmitter)
+
+    env['_FORTRANCOMD']     = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_FORTRANPPCOMD']   = '$_FORTRANG -o $TARGET -c $_FORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHFORTRANCOMD']   = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
+    env['_SHFORTRANPPCOMD'] = '$_SHFORTRANG -o $TARGET -c $_SHFORTRANFLAGSG $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS $_FORTRANMODFLAG $SOURCES'
+
+def generate(env):
+    import f77
+    import f90
+    import f95
+    f77.add_to_env(env)
+    f90.add_to_env(env)
+    f95.add_to_env(env)
+
+    add_to_env(env)
+
+    env['_FORTRAND'] = env.Detect(compilers) or 'f77'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/g++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/g++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/g++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,87 @@
+"""SCons.Tool.g++
+
+Tool-specific initialization for g++.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+compilers = ['g++']
+
+def generate(env):
+    """Add Builders and construction variables for g++ to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    cplusplus.generate(env)
+
+    env['CXX']        = env.Detect(compilers)
+
+    # platform specific settings
+    if env['PLATFORM'] == 'cygwin':
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
+    elif env['PLATFORM'] == 'aix':
+        # Original line from Christian Engel added -DPIC:
+        #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC -mminimal-toc')
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc')
+        env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+        env['SHOBJSUFFIX'] = '$OBJSUFFIX'
+    elif env['PLATFORM'] == 'hpux':
+        # Original line from Christian Engel added -DPIC:
+        #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC')
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC')
+        env['SHOBJSUFFIX'] = '.pic.o'
+    elif env['PLATFORM'] == 'sunos':
+        # Original line from Christian Engel added -DPIC:
+        #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC')
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC')
+        env['SHOBJSUFFIX'] = '.pic.o'
+    else:
+        # Original line from Christian Engel added -DPIC:
+        #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC -DPIC')
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -fPIC')
+    # determine compiler version
+    if env['CXX']:
+        line = os.popen(env['CXX'] + ' --version').readline()
+        match = re.search(r'[0-9]+(\.[0-9]+)+', line)
+        if match:
+            env['CXXVERSION'] = match.group(0)
+
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/g77.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/g77.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/g77.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,47 @@
+"""engine.SCons.Tool.g77
+
+Tool-specific initialization for g77.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/g77.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import f77
+
+compilers = ['g77', 'f77']
+
+def generate(env):
+    """Add Builders and construction variables for g77 to an Environment."""
+    f77.generate(env)
+
+    env['_FORTRAND'] = env.Detect(compilers) or 'g77'
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/gas.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/gas.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/gas.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,47 @@
+"""SCons.Tool.gas
+
+Tool-specific initialization for as, the Gnu assembler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/gas.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import as
+
+assemblers = ['as', 'gas']
+
+def generate(env):
+    """Add Builders and construction variables for as to an Environment."""
+    as.generate(env)
+
+    env['AS']        = env.Detect(assemblers) or 'as'
+
+def exists(env):
+    return env.Detect(assemblers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/gcc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/gcc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/gcc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,61 @@
+"""SCons.Tool.gcc
+
+Tool-specific initialization for gcc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/gcc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import cc
+import os
+import re
+
+compilers = ['gcc', 'cc']
+
+def generate(env):
+    """Add Builders and construction variables for gcc to an Environment."""
+    cc.generate(env)
+
+    env['CC'] = env.Detect(compilers) or 'gcc'
+    if env['PLATFORM'] == 'cygwin':
+        env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
+    else:
+        env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC')
+    # determine compiler version
+    if env['CC']:
+        line = os.popen(env['CC'] + ' --version').readline()
+        match = re.search(r'[0-9]+(\.[0-9]+)+', line)
+        if match:
+            env['CCVERSION'] = match.group(0)
+
+def exists(env):
+    return env.Detect(compilers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/gnulink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/gnulink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/gnulink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,57 @@
+"""SCons.Tool.gnulink
+
+Tool-specific initialization for the gnu linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/gnulink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import link
+
+linkers = ['g++', 'gcc']
+
+def generate(env):
+    """Add Builders and construction variables for gnulink to an Environment."""
+    link.generate(env)
+
+    if env['PLATFORM'] == 'hpux':
+        env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared -fPIC')
+
+    # __RPATH is set to $_RPATH in the platform specification if that
+    # platform supports it.
+    env.Append(LINKFLAGS=['$__RPATH'])
+    env['RPATHPREFIX'] = '-Wl,-rpath='
+    env['RPATHSUFFIX'] = ''
+    env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}'
+    
+def exists(env):
+    return env.Detect(linkers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/gs.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/gs.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/gs.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,75 @@
+"""SCons.Tool.gs
+
+Tool-specific initialization for Ghostscript.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/gs.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Platform
+import SCons.Util
+
+# Ghostscript goes by different names on different platforms...
+platform = SCons.Platform.platform_default()
+
+if platform == 'os2':
+    gs = 'gsos2'
+elif platform == 'win32':
+    gs = 'gswin32c'
+else:
+    gs = 'gs'
+
+GhostscriptAction = None
+
+def generate(env):
+    """Add Builders and construction variables for Ghostscript to an
+    Environment."""
+
+    global GhostscriptAction
+    if GhostscriptAction is None:
+        GhostscriptAction = SCons.Action.Action('$GSCOM', '$GSCOMSTR')
+
+    import pdf
+    pdf.generate(env)
+
+    bld = env['BUILDERS']['PDF']
+    bld.add_action('.ps', GhostscriptAction)
+
+    env['GS']      = gs
+    env['GSFLAGS'] = SCons.Util.CLVar('-dNOPAUSE -dBATCH -sDEVICE=pdfwrite')
+    env['GSCOM']   = '$GS $GSFLAGS -sOutputFile=$TARGET $SOURCES'
+
+
+def exists(env):
+    if env.has_key('PS2PDF'):
+        return env.Detect(env['PS2PDF'])
+    else:
+        return env.Detect(gs) or SCons.Util.WhereIs(gs)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/hpc++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/hpc++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/hpc++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,79 @@
+"""SCons.Tool.hpc++
+
+Tool-specific initialization for c++ on HP/UX.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/hpc++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import string
+
+import SCons.Util
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+acc = None
+
+# search for the acc compiler and linker front end
+
+try:
+    dirs = os.listdir('/opt')
+except (IOError, OSError):
+    # Not being able to read the directory because it doesn't exist
+    # (IOError) or isn't readable (OSError) is okay.
+    dirs = []
+
+for dir in dirs:
+    cc = '/opt/' + dir + '/bin/aCC'
+    if os.path.exists(cc):
+        acc = cc
+        break
+
+        
+def generate(env):
+    """Add Builders and construction variables for g++ to an Environment."""
+    cplusplus.generate(env)
+
+    if acc:
+        env['CXX']        = acc or 'aCC'
+        env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS +Z')
+        # determine version of aCC
+        line = os.popen(acc + ' -V 2>&1').readline().rstrip()
+        if string.find(line, 'aCC: HP ANSI C++') == 0:
+            env['CXXVERSION'] = string.split(line)[-1]
+
+        if env['PLATFORM'] == 'cygwin':
+            env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
+        else:
+            env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS +Z')
+
+def exists(env):
+    return acc

Added: cs/scons/scons-local-0.96.92/SCons/Tool/hpcc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/hpcc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/hpcc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,47 @@
+"""SCons.Tool.hpcc
+
+Tool-specific initialization for HP aCC and cc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/hpcc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import cc
+
+def generate(env):
+    """Add Builders and construction variables for aCC & cc to an Environment."""
+    cc.generate(env)
+
+    env['CXX']        = 'aCC'
+    env['SHCCFLAGS']  = SCons.Util.CLVar('$CCFLAGS +Z')
+
+def exists(env):
+    return env.Detect('aCC')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/hplink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/hplink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/hplink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,71 @@
+"""SCons.Tool.hplink
+
+Tool-specific initialization for the HP linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/hplink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+
+import SCons.Util
+
+import link
+
+ccLinker = None
+
+# search for the acc compiler and linker front end
+
+try:
+    dirs = os.listdir('/opt')
+except (IOError, OSError):
+    # Not being able to read the directory because it doesn't exist
+    # (IOError) or isn't readable (OSError) is okay.
+    dirs = []
+
+for dir in dirs:
+    linker = '/opt/' + dir + '/bin/aCC'
+    if os.path.exists(linker):
+        ccLinker = linker
+        break
+
+def generate(env):
+    """
+    Add Builders and construction variables for Visual Age linker to
+    an Environment.
+    """
+    link.generate(env)
+    
+    env['LINKFLAGS']   = SCons.Util.CLVar('-Wl,+s -Wl,+vnocompatwarnings')
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -b')
+    env['SHLIBSUFFIX'] = '.sl'
+
+def exists(env):
+    return ccLinker

Added: cs/scons/scons-local-0.96.92/SCons/Tool/icc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/icc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/icc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,53 @@
+"""engine.SCons.Tool.icc
+
+Tool-specific initialization for the OS/2 icc compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/icc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import cc
+
+def generate(env):
+    """Add Builders and construction variables for the OS/2 to an Environment."""
+    cc.generate(env)
+
+    env['CC']         = 'icc'
+    env['CCCOM']      = '$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['CXXCOM']     = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['CPPDEFPREFIX']  = '/D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '/I'
+    env['INCSUFFIX']  = ''
+    env['CFILESUFFIX'] = '.c'
+    env['CXXFILESUFFIX'] = '.cc'
+
+def exists(env):
+    return env.Detect('icc')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/icl.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/icl.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/icl.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,46 @@
+"""engine.SCons.Tool.icl
+
+Tool-specific initialization for the Intel C/C++ compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/icl.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool.intelc
+
+# This has been completely superceded by intelc.py, which can
+# handle both Windows and Linux versions.
+
+def generate(*args, **kw):
+    """Add Builders and construction variables for icl to an Environment."""
+    return apply(SCons.Tool.intelc.generate, args, kw)
+
+def exists(*args, **kw):
+    return apply(SCons.Tool.intelc.exists, args, kw)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/ifl.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/ifl.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/ifl.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,53 @@
+"""SCons.Tool.ifl
+
+Tool-specific initialization for the Intel Fortran compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/ifl.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+
+import fortran
+
+def generate(env):
+    """Add Builders and construction variables for ifl to an Environment."""
+    SCons.Tool.SourceFileScanner.add_scanner('.i90', fortran.FortranScan)
+    fortran.FortranSuffixes.extend(['.i90'])
+    fortran.generate(env)
+
+    env['FORTRAN']        = 'ifl'
+    env['FORTRANCOM']     = '$FORTRAN $FORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['FORTRANPPCOM']   = '$FORTRAN $FORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['SHFORTRANCOM']   = '$SHFORTRAN $SHFORTRANFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
+    env['SHFORTRANPPCOM'] = '$SHFORTRAN $SHFORTRANFLAGS $CPPFLAGS $_CPPDEFFLAGS $_FORTRANINCFLAGS /c $SOURCES /Fo$TARGET'
+
+def exists(env):
+    return env.Detect('ifl')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/ifort.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/ifort.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/ifort.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,73 @@
+"""SCons.Tool.ifort
+
+Tool-specific initialization for newer versions of the Intel Fortran Compiler
+for Linux. 
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/ifort.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import string
+
+import SCons.Defaults
+
+import fortran
+
+def generate(env):
+    """Add Builders and construction variables for ifort to an Environment."""
+    # ifort supports Fortran 90 and Fortran 95
+    # Additionally, ifort recognizes more file extensions.
+    SCons.Tool.SourceFileScanner.add_scanner('.i', fortran.FortranScan)
+    SCons.Tool.SourceFileScanner.add_scanner('.i90', fortran.FortranScan)
+    fortran.FortranSuffixes.extend(['.i', '.i90'])
+    fortran.generate(env)
+
+    env['_FORTRAND'] = 'ifort'
+
+    # If files are compiled into objects, the Intel Fortran Compiler must use
+    # ld to link shared libraries.
+    env['SHLINK'] = 'ld'
+
+    # Additionally, no symbols can be defined in an archive file; to use
+    # Intel Fortran to create shared libraries, all external symbols must
+    # be in shared libraries.
+    env['SHLINKFLAGS'] = '-shared -no_archive'
+
+    #
+    if env['PLATFORM'] == 'win32':
+        # On Windows, the ifort compiler specifies the object on the
+        # command line with -object:, not -o.  Massage the necessary
+        # command-line construction variables.
+        for var in ['_FORTRANCOMD', '_FORTRANPPCOMD',
+                    '_SHFORTRANCOMD', '_SHFORTRANPPCOMD']:
+            env[var] = string.replace(env[var], '-o $TARGET', '-object:$TARGET')
+
+def exists(env):
+    return env.Detect('ifort')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/ilink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/ilink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/ilink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,53 @@
+"""SCons.Tool.ilink
+
+Tool-specific initialization for the OS/2 ilink linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/ilink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for ilink to an Environment."""
+    SCons.Tool.createProgBuilder(env)
+    
+    env['LINK']        = 'ilink'
+    env['LINKFLAGS']   = SCons.Util.CLVar('')
+    env['LINKCOM']     = '$LINK $LINKFLAGS /O:$TARGET $SOURCES $( $_LIBDIRFLAGS $) $_LIBFLAGS'
+    env['LIBDIRPREFIX']='/LIBPATH:'
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']=''
+    env['LIBLINKSUFFIX']='$LIBSUFFIX'
+
+def exists(env):
+    return env.Detect('ilink')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/ilink32.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/ilink32.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/ilink32.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,52 @@
+"""SCons.Tool.ilink32
+
+XXX
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/ilink32.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool
+import SCons.Tool.bcc32
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for ilink to an
+    Environment."""
+    SCons.Tool.createProgBuilder(env)
+
+    env['LINK']        = '$CC'
+    env['LINKFLAGS']   = SCons.Util.CLVar('')
+    env['LINKCOM']     = '$LINK -q $LINKFLAGS $SOURCES $LIBS'
+    env['LIBDIRPREFIX']=''
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']=''
+    env['LIBLINKSUFFIX']='$LIBSUFFIX'
+
+def exists(env):
+    # Uses bcc32 to do linking as it generally knows where the standard
+    # LIBS are and set up the linking correctly
+    return SCons.Tool.bcc32.findIt('bcc32', env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/intelc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/intelc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/intelc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,409 @@
+"""SCons.Tool.icl
+
+Tool-specific initialization for the Intel C/C++ compiler.
+Supports Linux and Windows compilers, v7 and up.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/intelc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import math, sys, os.path, glob, string, re
+
+is_windows = sys.platform == 'win32'
+is_linux = sys.platform == 'linux2'
+
+if is_windows:
+    import SCons.Tool.msvc
+elif is_linux:
+    import SCons.Tool.gcc
+import SCons.Util
+import SCons.Warnings
+
+# Exceptions for this tool
+class IntelCError(SCons.Errors.InternalError):
+    pass
+class MissingRegistryError(IntelCError): # missing registry entry
+    pass
+class MissingDirError(IntelCError):     # dir not found
+    pass
+class NoRegistryModuleError(IntelCError): # can't read registry at all
+    pass
+
+def uniquify(s):
+    """Return a sequence containing only one copy of each unique element from input sequence s.
+    Does not preserve order.
+    Input sequence must be hashable (i.e. must be usable as a dictionary key)."""
+    u = {}
+    for x in s:
+        u[x] = 1
+    return u.keys()
+
+def linux_ver_normalize(vstr):
+    """Normalize a Linux compiler version number.
+    Intel changed from "80" to "9.0" in 2005, so we assume if the number
+    is greater than 60 it's an old-style number and otherwise new-style.
+    Always returns an old-style float like 80 or 90 for compatibility with Windows.
+    Shades of Y2K!"""
+    f = float(vstr)
+    if is_windows:
+        return f
+    else:
+        if f < 60: return f * 10.0
+        else: return f
+
+def check_abi(abi):
+    """Check for valid ABI (application binary interface) name,
+    and map into canonical one"""
+    if not abi:
+        return None
+    abi = abi.lower()
+    # valid_abis maps input name to canonical name
+    if is_windows:
+        valid_abis = {'ia32'  : 'ia32',
+                      'x86'   : 'ia32',
+                      'ia64'  : 'ia64',
+                      'em64t' : 'ia32e',
+                      'amd64' : 'ia32e'}
+    if is_linux:
+        valid_abis = {'ia32'   : 'ia32',
+                      'x86'    : 'ia32',
+                      'x86_64' : 'x86_64',
+                      'em64t'  : 'x86_64',
+                      'amd64'  : 'x86_64'}
+    try:
+        abi = valid_abis[abi]
+    except KeyError:
+        raise SCons.Errors.UserError, \
+              "Intel compiler: Invalid ABI %s, valid values are %s"% \
+              (abi, valid_abis.keys())
+    return abi
+
+def vercmp(a, b):
+    """Compare strings as floats,
+    but Intel changed Linux naming convention at 9.0"""
+    return cmp(linux_ver_normalize(b), linux_ver_normalize(a))
+
+def get_version_from_list(v, vlist):
+    """See if we can match v (string) in vlist (list of strings)
+    Linux has to match in a fuzzy way."""
+    if is_windows:
+        # Simple case, just find it in the list
+        if v in vlist: return v
+        else: return None
+    else:
+        # Fuzzy match: normalize version number first, but still return
+        # original non-normalized form.
+        fuzz = 0.001
+        for vi in vlist:
+            if math.fabs(linux_ver_normalize(vi) - linux_ver_normalize(v)) < fuzz:
+                return vi
+        # Not found
+        return None
+
+def get_intel_registry_value(valuename, version=None, abi=None):
+    """
+    Return a value from the Intel compiler registry tree. (Windows only)
+    """
+    # Open the key:
+    K = 'Software\\Intel\\Compilers\\C++\\' + version + '\\'+abi.upper()
+    try:
+        k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
+    except SCons.Util.RegError:
+        raise MissingRegistryError, \
+              "%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)
+
+    # Get the value:
+    try:
+        v = SCons.Util.RegQueryValueEx(k, valuename)[0]
+        return v  # or v.encode('iso-8859-1', 'replace') to remove unicode?
+    except SCons.Util.RegError:
+        raise MissingRegistryError, \
+              "%s\\%s was not found in the registry."%(K, value)
+
+
+def get_all_compiler_versions():
+    """Returns a sorted list of strings, like "70" or "80" or "9.0"
+    with most recent compiler version first.
+    """
+    versions=[]
+    if is_windows:
+        keyname = 'Software\\Intel\\Compilers\\C++'
+        try:
+            k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+                                        keyname)
+        except WindowsError:
+            return []
+        i = 0
+        versions = []
+        try:
+            while i < 100:
+                subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError
+                # Check that this refers to an existing dir.
+                # This is not 100% perfect but should catch common
+                # installation issues like when the compiler was installed
+                # and then the install directory deleted or moved (rather
+                # than uninstalling properly), so the registry values
+                # are still there.
+                ok = False
+                for try_abi in ('IA32', 'IA32e',  'IA64'):
+                    try:
+                        d = get_intel_registry_value('ProductDir', subkey, try_abi)
+                    except MissingRegistryError:
+                        continue  # not found in reg, keep going
+                    if os.path.exists(d): ok = True
+                if ok:
+                    versions.append(subkey)
+                else:
+                    # Registry points to nonexistent dir.  Ignore this version.
+                    print "Ignoring "+str(get_intel_registry_value('ProductDir', subkey, 'IA32'))
+                i = i + 1
+        except EnvironmentError:
+            # no more subkeys
+            pass
+    elif is_linux:
+        for d in glob.glob('/opt/intel_cc_*'):
+            # Typical dir here is /opt/intel_cc_80.
+            versions.append(re.search(r'cc_(.*)$', d).group(1))
+        for d in glob.glob('/opt/intel/cc*/*'):
+            # Typical dir here is /opt/intel/cc/9.0 for IA32,
+            # /opt/intel/cce/9.0 for EMT64 (AMD64)
+            versions.append(re.search(r'([0-9.]+)$', d).group(1))
+    versions = uniquify(versions)       # remove dups
+    versions.sort(vercmp)
+    return versions
+
+def get_intel_compiler_top(version, abi):
+    """
+    Return the main path to the top-level dir of the Intel compiler,
+    using the given version.
+    The compiler will be in <top>/bin/icl.exe (icc on linux),
+    the include dir is <top>/include, etc.
+    """
+    if is_windows:
+        if not SCons.Util.can_read_reg:
+            raise NoRegistryModuleError, "No Windows registry module was found"
+        top = get_intel_registry_value('ProductDir', version, abi)
+        if not os.path.exists(os.path.join(top, "Bin", "icl.exe")):
+            raise MissingDirError, \
+                  "Can't find Intel compiler in %s"%(top)
+    elif is_linux:
+        # first dir is new (>=9.0) style, second is old (8.0) style.
+        dirs=('/opt/intel/cc/%s', '/opt/intel_cc_%s')
+        if abi == 'x86_64':
+            dirs=('/opt/intel/cce/%s',)  # 'e' stands for 'em64t', aka x86_64 aka amd64
+        top=None
+        for d in dirs:
+            if os.path.exists(os.path.join(d%version, "bin", "icc")):
+                top = d%version
+                break
+        if not top:
+            raise MissingDirError, \
+                  "Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi)
+    return top
+
+
+def generate(env, version=None, abi=None, topdir=None, verbose=0):
+    """Add Builders and construction variables for Intel C/C++ compiler
+    to an Environment.
+    args:
+      version: (string) compiler version to use, like "80"
+      abi:     (string) 'win32' or whatever Itanium version wants
+      topdir:  (string) compiler top dir, like
+                         "c:\Program Files\Intel\Compiler70"
+                        If topdir is used, version and abi are ignored.
+      verbose: (int)    if >0, prints compiler version used.
+    """
+    if not (is_linux or is_windows):
+        # can't handle this platform
+        return
+
+    if is_windows:
+        SCons.Tool.msvc.generate(env)
+    elif is_linux:
+        SCons.Tool.gcc.generate(env)
+
+    # if version is unspecified, use latest
+    vlist = get_all_compiler_versions()
+    if not version:
+        if vlist:
+            version = vlist[0]
+    else:
+        # User may have specified '90' but we need to get actual dirname '9.0'.
+        # get_version_from_list does that mapping.
+        v = get_version_from_list(version, vlist)
+        if not v:
+            raise SCons.Errors.UserError, \
+                  "Invalid Intel compiler version %s: "%version + \
+                  "installed versions are %s"%(', '.join(vlist))
+        version = v
+
+    # if abi is unspecified, use ia32
+    # alternatives are ia64 for Itanium, or amd64 or em64t or x86_64 (all synonyms here)
+    abi = check_abi(abi)
+    if abi is None:
+        if is_linux:
+            # Check if we are on 64-bit linux, default to 64 then.
+            uname_m = os.uname()[4]
+            if uname_m == 'x86_64':
+                abi = 'x86_64'
+            else:
+                abi = 'ia32'
+        else:
+            # XXX: how would we do the same test on Windows?
+            abi = "ia32"
+
+    if version and not topdir:
+        try:
+            topdir = get_intel_compiler_top(version, abi)
+        except (SCons.Util.RegError, IntelCError):
+            topdir = None
+
+    if not topdir:
+        # Normally this is an error, but it might not be if the compiler is
+        # on $PATH and the user is importing their env.
+        class ICLTopDirWarning(SCons.Warnings.Warning):
+            pass
+        if is_linux and not env.Detect('icc') or \
+           is_windows and not env.Detect('icl'):
+
+            SCons.Warnings.enableWarningClass(ICLTopDirWarning)
+            SCons.Warnings.warn(ICLTopDirWarning,
+                                "Failed to find Intel compiler for version='%s', abi='%s'"%
+                                (str(version), str(abi)))
+        else:
+            # should be cleaned up to say what this other version is
+            # since in this case we have some other Intel compiler installed
+            SCons.Warnings.enableWarningClass(ICLTopDirWarning)
+            SCons.Warnings.warn(ICLTopDirWarning,
+                                "Can't find Intel compiler top dir for version='%s', abi='%s'"%
+                                    (str(version), str(abi)))
+
+    if topdir:
+        if verbose:
+            print "Intel C compiler: using version '%s' (%g), abi %s, in '%s'"%\
+                  (version, linux_ver_normalize(version),abi,topdir)
+            if is_linux:
+                # Show the actual compiler version by running the compiler.
+                os.system('%s/bin/icc --version'%topdir)
+
+        env['INTEL_C_COMPILER_TOP'] = topdir
+        if is_linux:
+            paths={'INCLUDE'         : 'include',
+                   'LIB'             : 'lib',
+                   'PATH'            : 'bin',
+                   'LD_LIBRARY_PATH' : 'lib'}
+            for p in paths:
+                env.PrependENVPath(p, os.path.join(topdir, paths[p]))
+        if is_windows:
+            #       env key    reg valname   default subdir of top
+            paths=(('INCLUDE', 'IncludeDir', 'Include'),
+                   ('LIB'    , 'LibDir',     'Lib'),
+                   ('PATH'   , 'BinDir',     'Bin'))
+            # Each path has a registry entry, use that or default to subdir
+            for p in paths:
+                try:
+                    path=get_intel_registry_value(p[1], version, abi)
+                    # These paths may have $(ICInstallDir)
+                    # which needs to be substituted with the topdir.
+                    path=path.replace('$(ICInstallDir)', topdir + os.sep)
+                except IntelCError:
+                    # Couldn't get it from registry: use default subdir of topdir
+                    env.PrependENVPath(p[0], os.path.join(topdir, p[2]))
+                else:
+                    env.PrependENVPath(p[0], string.split(path, os.pathsep))
+                    # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
+
+    if is_windows:
+        env['CC']        = 'icl'
+        env['CXX']       = 'icl'
+        env['LINK']      = 'xilink'
+    else:
+        env['CC']        = 'icc'
+        env['CXX']       = 'icpc'
+        env['LINK']      = '$CC'
+        env['AR']        = 'xiar'
+        env['LD']        = 'xild' # not used by default
+
+    # This is not the exact (detailed) compiler version,
+    # just the major version as determined above or specified
+    # by the user.  It is a float like 80 or 90, in normalized form for Linux
+    # (i.e. even for Linux 9.0 compiler, still returns 90 rather than 9.0)
+    if version:
+        env['INTEL_C_COMPILER_VERSION']=linux_ver_normalize(version)
+
+    if is_windows:
+        # Look for license file dir
+        # in system environment, registry, and default location.
+        envlicdir = os.environ.get("INTEL_LICENSE_FILE", '')
+        K = ('SOFTWARE\Intel\Licenses')
+        try:
+            k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
+            reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0]
+        except (AttributeError, SCons.Util.RegError):
+            reglicdir = ""
+        defaultlicdir = r'C:\Program Files\Common Files\Intel\Licenses'
+
+        licdir = None
+        for ld in [envlicdir, reglicdir]:
+            if ld and os.path.exists(ld):
+                licdir = ld
+                break
+        if not licdir:
+            licdir = defaultlicdir
+            if not os.path.exists(licdir):
+                class ICLLicenseDirWarning(SCons.Warnings.Warning):
+                    pass
+                SCons.Warnings.enableWarningClass(ICLLicenseDirWarning)
+                SCons.Warnings.warn(ICLLicenseDirWarning,
+                                    "Intel license dir was not found."
+                                    "  Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)."
+                                    "  Using the default path as a last resort."
+                                        % (envlicdir, reglicdir, defaultlicdir))
+        env['ENV']['INTEL_LICENSE_FILE'] = licdir
+
+def exists(env):
+    if not (is_linux or is_windows):
+        # can't handle this platform
+        return 0
+
+    try:
+        versions = get_all_compiler_versions()
+    except (SCons.Util.RegError, IntelCError):
+        versions = None
+    detected = versions is not None and len(versions) > 0
+    if not detected:
+        # try env.Detect, maybe that will work
+        if is_windows:
+            return env.Detect('icl')
+        elif is_linux:
+            return env.Detect('icc')
+    return detected
+
+# end of file

Added: cs/scons/scons-local-0.96.92/SCons/Tool/jar.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/jar.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/jar.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,98 @@
+"""SCons.Tool.jar
+
+Tool-specific initialization for jar.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/jar.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def jarSources(target, source, env, for_signature):
+    """Only include sources that are not a manifest file."""
+    jarchdir = env.subst('$JARCHDIR')
+    result = []
+    for src in source:
+        contents = src.get_contents()
+        if contents[:16] != "Manifest-Version":
+            if jarchdir:
+                # If we are changing the dir with -C, then sources should
+                # be relative to that directory.
+                src = src.get_path(src.fs.Dir(jarchdir))
+                result.append('-C')
+                result.append(jarchdir)
+            result.append(src)
+    return result
+
+def jarManifest(target, source, env, for_signature):
+    """Look in sources for a manifest file, if any."""
+    for src in source:
+        contents = src.get_contents()
+        if contents[:16] == "Manifest-Version":
+            return src
+    return ''
+
+def jarFlags(target, source, env, for_signature):
+    """If we have a manifest, make sure that the 'm'
+    flag is specified."""
+    jarflags = env.subst('$JARFLAGS')
+    for src in source:
+        contents = src.get_contents()
+        if contents[:16] == "Manifest-Version":
+            if not 'm' in jarflags:
+                return jarflags + 'm'
+            break
+    return jarflags
+
+JarAction = SCons.Action.Action('$JARCOM', '$JARCOMSTR')
+
+JarBuilder = SCons.Builder.Builder(action = JarAction,
+                                   source_factory = SCons.Node.FS.Entry,
+                                   suffix = '$JARSUFFIX')
+
+def generate(env):
+    """Add Builders and construction variables for jar to an Environment."""
+    try:
+        env['BUILDERS']['Jar']
+    except KeyError:
+        env['BUILDERS']['Jar'] = JarBuilder
+
+    env['JAR']        = 'jar'
+    env['JARFLAGS']   = SCons.Util.CLVar('cf')
+    env['_JARFLAGS']  = jarFlags
+    env['_JARMANIFEST'] = jarManifest
+    env['_JARSOURCES'] = jarSources
+    env['JARCOM']     = '$JAR $_JARFLAGS $TARGET $_JARMANIFEST $_JARSOURCES'
+    env['JARSUFFIX']  = '.jar'
+
+def exists(env):
+    return env.Detect('jar')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/javac.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/javac.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/javac.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,116 @@
+"""SCons.Tool.javac
+
+Tool-specific initialization for javac.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/javac.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import string
+
+import SCons.Action
+import SCons.Builder
+from SCons.Node.FS import _my_normcase
+from SCons.Tool.JavaCommon import parse_java_file
+import SCons.Util
+
+def classname(path):
+    """Turn a string (path name) into a Java class name."""
+    return string.replace(os.path.normpath(path), os.sep, '.')
+
+def emit_java_classes(target, source, env):
+    """Create and return lists of source java files
+    and their corresponding target class files.
+    """
+    java_suffix = env.get('JAVASUFFIX', '.java')
+    class_suffix = env.get('JAVACLASSSUFFIX', '.class')
+
+    slist = []
+    js = _my_normcase(java_suffix)
+    for sdir in source:
+        def visit(arg, dirname, names, js=js, dirnode=sdir.rdir()):
+            java_files = filter(lambda n, js=js:
+                                _my_normcase(n[-len(js):]) == js,
+                                names)
+            # The on-disk entries come back in arbitrary order.  Sort them
+            # so our target and source lists are determinate.
+            java_files.sort()
+            mydir = dirnode.Dir(dirname)
+            java_paths = map(lambda f, d=mydir: d.File(f), java_files)
+            arg.extend(java_paths)
+        os.path.walk(sdir.rdir().get_abspath(), visit, slist)
+
+    tlist = []
+    for f in slist:
+        pkg_dir, classes = parse_java_file(f.get_abspath())
+        if pkg_dir:
+            for c in classes:
+                t = target[0].Dir(pkg_dir).File(c+class_suffix)
+                t.attributes.java_classdir = target[0]
+                t.attributes.java_classname = classname(pkg_dir + os.sep + c)
+                tlist.append(t)
+        elif classes:
+            for c in classes:
+                t = target[0].File(c+class_suffix)
+                t.attributes.java_classdir = target[0]
+                t.attributes.java_classname = classname(c)
+                tlist.append(t)
+        else:
+            # This is an odd end case:  no package and no classes.
+            # Just do our best based on the source file name.
+            base = str(f)[:-len(java_suffix)]
+            t = target[0].File(base + class_suffix)
+            t.attributes.java_classdir = target[0]
+            t.attributes.java_classname = classname(base)
+            tlist.append(t)
+
+    return tlist, slist
+
+JavaAction = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
+
+JavaBuilder = SCons.Builder.Builder(action = JavaAction,
+                    emitter = emit_java_classes,
+                    target_factory = SCons.Node.FS.Dir,
+                    source_factory = SCons.Node.FS.Dir)
+
+def generate(env):
+    """Add Builders and construction variables for javac to an Environment."""
+    env['BUILDERS']['Java'] = JavaBuilder
+
+    env['JAVAC']            = 'javac'
+    env['JAVACFLAGS']       = SCons.Util.CLVar('')
+    env['JAVACCOM']         = '$JAVAC $JAVACFLAGS -d ${TARGET.attributes.java_classdir} -sourcepath ${SOURCE.dir.rdir()} $SOURCES'
+    env['JAVACLASSSUFFIX']  = '.class'
+    env['JAVASUFFIX']       = '.java'
+
+def exists(env):
+    return env.Detect('javac')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/javah.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/javah.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/javah.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,128 @@
+"""SCons.Tool.javah
+
+Tool-specific initialization for javah.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/javah.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import string
+
+import SCons.Action
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Tool.javac
+import SCons.Util
+
+def emit_java_headers(target, source, env):
+    """Create and return lists of Java stub header files that will
+    be created from a set of class files.
+    """
+    class_suffix = env.get('JAVACLASSSUFFIX', '.class')
+    classdir = env.get('JAVACLASSDIR')
+
+    if not classdir:
+        try:
+            s = source[0]
+        except IndexError:
+            classdir = '.'
+        else:
+            try:
+                classdir = s.attributes.java_classdir
+            except AttributeError:
+                classdir = '.'
+    classdir = env.Dir(classdir).rdir()
+    if str(classdir) == '.':
+        c_ = None
+    else:
+        c_ = str(classdir) + os.sep
+
+    slist = []
+    for src in source:
+        try:
+            classname = src.attributes.java_classname
+        except AttributeError:
+            classname = str(src)
+            if c_ and classname[:len(c_)] == c_:
+                classname = classname[len(c_):]
+            if class_suffix and classname[-len(class_suffix):] == class_suffix:
+                classname = classname[:-len(class_suffix)]
+            classname = SCons.Tool.javac.classname(classname)
+        s = src.rfile()
+        s.attributes.java_classdir = classdir
+        s.attributes.java_classname = classname
+        slist.append(s)
+
+    if target[0].__class__ is SCons.Node.FS.File:
+        tlist = target
+    else:
+        if not isinstance(target[0], SCons.Node.FS.Dir):
+            target[0].__class__ = SCons.Node.FS.Dir
+            target[0]._morph()
+        tlist = []
+        for s in source:
+            fname = string.replace(s.attributes.java_classname, '.', '_') + '.h'
+            t = target[0].File(fname)
+            t.attributes.java_lookupdir = target[0]
+            tlist.append(t)
+
+    return tlist, source
+
+def JavaHOutFlagGenerator(target, source, env, for_signature):
+    try:
+        t = target[0]
+    except (AttributeError, TypeError):
+        t = target
+    try:
+        return '-d ' + str(t.attributes.java_lookupdir)
+    except AttributeError:
+        return '-o ' + str(t)
+
+JavaHAction = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR')
+
+JavaHBuilder = SCons.Builder.Builder(action = JavaHAction,
+                     emitter = emit_java_headers,
+                     src_suffix = '$JAVACLASSSUFFIX',
+                     target_factory = SCons.Node.FS.Entry,
+                     source_factory = SCons.Node.FS.File)
+
+def generate(env):
+    """Add Builders and construction variables for javah to an Environment."""
+    env['BUILDERS']['JavaH'] = JavaHBuilder
+
+    env['_JAVAHOUTFLAG']    = JavaHOutFlagGenerator
+    env['JAVAH']            = 'javah'
+    env['JAVAHFLAGS']       = SCons.Util.CLVar('')
+    env['JAVAHCOM']         = '$JAVAH $JAVAHFLAGS $_JAVAHOUTFLAG -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}'
+    env['JAVACLASSSUFFIX']  = '.class'
+
+def exists(env):
+    return env.Detect('javah')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/latex.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/latex.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/latex.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,71 @@
+"""SCons.Tool.latex
+
+Tool-specific initialization for LaTeX.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/latex.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Scanner.LaTeX
+import SCons.Util
+import SCons.Tool
+import SCons.Tool.tex
+
+LaTeXAction = None
+
+def LaTeXAuxFunction(target = None, source= None, env=None):
+    SCons.Tool.tex.InternalLaTeXAuxAction( LaTeXAction, target, source, env )
+
+LaTeXAuxAction = SCons.Action.Action(LaTeXAuxFunction, strfunction=None)
+
+def generate(env):
+    """Add Builders and construction variables for LaTeX to an Environment."""
+    global LaTeXAction
+    if LaTeXAction is None:
+        LaTeXAction = SCons.Action.Action('$LATEXCOM', '$LATEXCOMSTR')
+
+    import dvi
+    dvi.generate(env)
+
+    bld = env['BUILDERS']['DVI']
+    bld.add_action('.ltx', LaTeXAuxAction)
+    bld.add_action('.latex', LaTeXAuxAction)
+    bld.add_emitter('.ltx', SCons.Tool.tex.tex_emitter)
+    bld.add_emitter('.latex', SCons.Tool.tex.tex_emitter)
+
+    env['LATEX']        = 'latex'
+    env['LATEXFLAGS']   = SCons.Util.CLVar('')
+    env['LATEXCOM']     = '$LATEX $LATEXFLAGS $SOURCES'
+    env['LATEXRETRIES'] = 3
+
+def exists(env):
+    return env.Detect('latex')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/lex.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/lex.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/lex.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,55 @@
+"""SCons.Tool.lex
+
+Tool-specific initialization for lex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/lex.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Tool
+import SCons.Util
+
+LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR")
+
+def generate(env):
+    """Add Builders and construction variables for lex to an Environment."""
+    c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
+
+    c_file.add_action('.l', LexAction)
+    c_file.add_action('.lex', LexAction)
+    cxx_file.add_action('.ll', LexAction)
+
+    env['LEX']      = env.Detect('flex') or 'lex'
+    env['LEXFLAGS'] = SCons.Util.CLVar('')
+    env['LEXCOM']   = '$LEX $LEXFLAGS -t $SOURCES > $TARGET'
+    
+def exists(env):
+    return env.Detect(['flex', 'lex'])

Added: cs/scons/scons-local-0.96.92/SCons/Tool/link.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/link.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/link.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,88 @@
+"""SCons.Tool.link
+
+Tool-specific initialization for the generic Posix linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/link.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+def smart_link(source, target, env, for_signature):
+    if cplusplus.iscplusplus(source):
+        return '$CXX'
+    return '$CC'
+
+def generate(env):
+    """Add Builders and construction variables for gnulink to an Environment."""
+    SCons.Tool.createSharedLibBuilder(env)
+    SCons.Tool.createProgBuilder(env)
+    
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared')
+    env['SHLINKCOM']   = '$SHLINK -o $TARGET $SHLINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    # don't set up the emitter, cause AppendUnique will generate a list
+    # starting with None :-(
+    #env['SHLIBEMITTER']= None
+    env['SMARTLINK']   = smart_link
+    env['LINK']        = "$SMARTLINK"
+    env['LINKFLAGS']   = SCons.Util.CLVar('')
+    env['LINKCOM']     = '$LINK -o $TARGET $LINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    env['LIBDIRPREFIX']='-L'
+    env['LIBDIRSUFFIX']=''
+    env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIX, LIBSUFFIX, __env__)}'
+    env['LIBLINKPREFIX']='-l'
+    env['LIBLINKSUFFIX']=''
+
+    if env['PLATFORM'] == 'hpux':
+        env['SHLIBSUFFIX'] = '.sl'
+    elif env['PLATFORM'] == 'aix':
+        env['SHLIBSUFFIX'] = '.a'
+
+    # For most platforms, a loadable module is the same as a shared
+    # library.  Platforms which are different can override these, but
+    # setting them the same means that LoadableModule works everywhere.
+    SCons.Tool.createLoadableModuleBuilder(env)
+    env['LDMODULE'] = '$SHLINK'
+    env['LDMODULEPREFIX'] = '$SHLIBPREFIX' 
+    env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' 
+    env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
+    env['LDMODULECOM'] = '$SHLINKCOM'
+
+
+
+def exists(env):
+    # This module isn't really a Tool on its own, it's common logic for
+    # other linkers.
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/linkloc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/linkloc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/linkloc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,105 @@
+"""SCons.Tool.linkloc
+
+Tool specification for the LinkLoc linker for the Phar Lap ETS embedded
+operating system.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/linkloc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Errors
+import SCons.Tool
+import SCons.Util
+
+from SCons.Tool.msvc import get_msvc_paths
+from SCons.Tool.PharLapCommon import addPharLapPaths
+
+_re_linker_command = re.compile(r'(\s)@\s*([^\s]+)')
+
+def repl_linker_command(m):
+    # Replaces any linker command file directives (e.g. "@foo.lnk") with
+    # the actual contents of the file.
+    try:
+        f=open(m.group(2), "r")
+        return m.group(1) + f.read()
+    except IOError:
+        # the linker should return an error if it can't
+        # find the linker command file so we will remain quiet.
+        # However, we will replace the @ with a # so we will not continue
+        # to find it with recursive substitution
+        return m.group(1) + '#' + m.group(2)
+
+class LinklocGenerator:
+    def __init__(self, cmdline):
+        self.cmdline = cmdline
+
+    def __call__(self, env, target, source, for_signature):
+        if for_signature:
+            # Expand the contents of any linker command files recursively
+            subs = 1
+            strsub = env.subst(self.cmdline, target=target, source=source)
+            while subs:
+                strsub, subs = _re_linker_command.subn(repl_linker_command, strsub)
+            return strsub
+        else:
+            return "${TEMPFILE('" + self.cmdline + "')}"
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createSharedLibBuilder(env)
+    SCons.Tool.createProgBuilder(env)
+
+    env['SUBST_CMD_FILE'] = LinklocGenerator
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS')
+    env['SHLINKCOM']   = '${SUBST_CMD_FILE("$SHLINK $SHLINKFLAGS $( $_LIBDIRFLAGS $) $_LIBFLAGS -dll $TARGET $SOURCES")}'
+    env['SHLIBEMITTER']= None
+    env['LINK']        = "linkloc"
+    env['LINKFLAGS']   = SCons.Util.CLVar('')
+    env['LINKCOM']     = '${SUBST_CMD_FILE("$LINK $LINKFLAGS $( $_LIBDIRFLAGS $) $_LIBFLAGS -exe $TARGET $SOURCES")}'
+    env['LIBDIRPREFIX']='-libpath '
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']='-lib '
+    env['LIBLINKSUFFIX']='$LIBSUFFIX'
+
+    msvs_version = env.get('MSVS_VERSION')
+    include_path, lib_path, exe_path = get_msvc_paths(env, version = msvs_version)
+    env['ENV']['LIB']            = lib_path
+    env['ENV']['PATH']           = exe_path
+
+    addPharLapPaths(env)
+
+def exists(env):
+    return env.Detect('linkloc')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/m4.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/m4.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/m4.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,57 @@
+"""SCons.Tool.m4
+
+Tool-specific initialization for m4.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/m4.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for m4 to an Environment."""
+    M4Action = SCons.Action.Action('$M4COM', '$M4COMSTR')
+    bld = SCons.Builder.Builder(action = M4Action, src_suffix = '.m4')
+
+    env['BUILDERS']['M4'] = bld
+
+    # .m4 files might include other files, and it would be pretty hard
+    # to write a scanner for it, so let's just cd to the dir of the m4
+    # file and run from there.
+    # The src_suffix setup is like so: file.c.m4 -> file.c,
+    # file.cpp.m4 -> file.cpp etc.
+    env['M4']      = 'm4'
+    env['M4FLAGS'] = SCons.Util.CLVar('-E')
+    env['M4COM']   = 'cd ${SOURCE.rsrcdir} && $M4 $M4FLAGS < ${SOURCE.file} > ${TARGET.abspath}'
+
+def exists(env):
+    return env.Detect('m4')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/masm.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/masm.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/masm.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,71 @@
+"""SCons.Tool.masm
+
+Tool-specific initialization for the Microsoft Assembler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/masm.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+ASSuffixes = ['.s', '.asm', '.ASM']
+ASPPSuffixes = ['.spp', '.SPP']
+if SCons.Util.case_sensitive_suffixes('.s', '.S'):
+    ASPPSuffixes.extend(['.S'])
+else:
+    ASSuffixes.extend(['.S'])
+
+def generate(env):
+    """Add Builders and construction variables for masm to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in ASSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ASAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+        shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
+
+    for suffix in ASPPSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASPPAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ASPPAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+        shared_obj.add_emitter(suffix, SCons.Defaults.SharedObjectEmitter)
+
+    env['AS']        = 'ml'
+    env['ASFLAGS']   = SCons.Util.CLVar('/nologo')
+    env['ASPPFLAGS'] = '$ASFLAGS'
+    env['ASCOM']     = '$AS $ASFLAGS /c /Fo$TARGET $SOURCES'
+    env['ASPPCOM']   = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c /Fo$TARGET $SOURCES'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+
+def exists(env):
+    return env.Detect('ml')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/midl.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/midl.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/midl.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,79 @@
+"""SCons.Tool.midl
+
+Tool-specific initialization for midl (Microsoft IDL compiler).
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/midl.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Scanner.IDL
+import SCons.Util
+import SCons.Tool.msvs
+
+def midl_emitter(target, source, env):
+    """Produces a list of outputs from the MIDL compiler"""
+    base, ext = SCons.Util.splitext(str(target[0]))
+    tlb = target[0]
+    incl = base + '.h'
+    interface = base + '_i.c'
+    proxy = base + '_p.c'
+    dlldata = base + '_data.c'
+
+    t = [tlb, incl, interface, proxy, dlldata]
+
+    return (t,source)
+
+idl_scanner = SCons.Scanner.IDL.IDLScan()
+
+midl_action = SCons.Action.Action('$MIDLCOM', '$MIDLCOMSTR')
+
+midl_builder = SCons.Builder.Builder(action = midl_action,
+                                     src_suffix = '.idl',
+                                     suffix='.tlb',
+                                     emitter = midl_emitter,
+                                     source_scanner = idl_scanner)
+
+def generate(env):
+    """Add Builders and construction variables for midl to an Environment."""
+
+    env['MIDL']          = 'MIDL.EXE'
+    env['MIDLFLAGS']     = SCons.Util.CLVar('/nologo')
+    env['MIDLCOM']       = '$MIDL $MIDLFLAGS /tlb ${TARGETS[0]} /h ${TARGETS[1]} /iid ${TARGETS[2]} /proxy ${TARGETS[3]} /dlldata ${TARGETS[4]} $SOURCE 2> NUL'
+    env['BUILDERS']['TypeLibrary'] = midl_builder
+
+def exists(env):
+    if SCons.Tool.msvs.is_msvs_installed():
+        # there's at least one version of MSVS installed, which comes with midl:
+        return 1
+    else:
+        return env.Detect('midl')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/mingw.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/mingw.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/mingw.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,158 @@
+"""SCons.Tool.gcc
+
+Tool-specific initialization for MinGW (http://www.mingw.org/)
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/mingw.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+import string
+
+import SCons.Action
+import SCons.Builder
+import SCons.Tool
+import SCons.Util
+
+# This is what we search for to find mingw:
+key_program = 'mingw32-gcc'
+
+def find(env):
+    # First search in the SCons path and then the OS path:
+    return env.WhereIs(key_program) or SCons.Util.WhereIs(key_program)
+
+def shlib_generator(target, source, env, for_signature):
+    cmd = SCons.Util.CLVar(['$SHLINK', '$SHLINKFLAGS']) 
+
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    if dll: cmd.extend(['-o', dll])
+
+    cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS'])
+
+    implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
+    if implib: cmd.append('-Wl,--out-implib,'+implib.get_string(for_signature))
+
+    def_target = env.FindIxes(target, 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX')
+    if def_target: cmd.append('-Wl,--output-def,'+def_target.get_string(for_signature))
+
+    return [cmd]
+
+def shlib_emitter(target, source, env):
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    no_import_lib = env.get('no_import_lib', 0)
+
+    if not dll:
+        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
+    
+    if not no_import_lib and \
+       not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'):
+
+        # Append an import library to the list of targets.
+        target.append(env.ReplaceIxes(dll,  
+                                      'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                      'LIBPREFIX', 'LIBSUFFIX'))
+
+    # Append a def file target if there isn't already a def file target
+    # or a def file source. There is no option to disable def file
+    # target emitting, because I can't figure out why someone would ever
+    # want to turn it off.
+    def_source = env.FindIxes(source, 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX')
+    def_target = env.FindIxes(target, 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX')
+    if not def_source and not def_target:
+        target.append(env.ReplaceIxes(dll,  
+                                      'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                      'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX'))
+    
+    return (target, source)
+                         
+
+shlib_action = SCons.Action.Action(shlib_generator, generator=1)
+
+res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
+
+res_builder = SCons.Builder.Builder(action=res_action, suffix='.o',
+                                    source_scanner=SCons.Tool.SourceFileScanner)
+SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
+
+def generate(env):
+    mingw = find(env)
+    if mingw:
+        dir = os.path.dirname(mingw)
+
+        # The mingw bin directory must be added to the path:
+        path = env['ENV'].get('PATH', [])
+        if not path: 
+            path = []
+        if SCons.Util.is_String(path):
+            path = string.split(path, os.pathsep)
+
+        env['ENV']['PATH'] = string.join([dir] + path, os.pathsep)
+        
+
+    # Most of mingw is the same as gcc and friends...
+    gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas']
+    for tool in gnu_tools:
+        SCons.Tool.Tool(tool)(env)
+
+    #... but a few things differ:
+    env['CC'] = 'gcc'
+    env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
+    env['CXX'] = 'g++'
+    env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared')
+    env['SHLINKCOM']   = shlib_action
+    env.Append(SHLIBEMITTER = [shlib_emitter])
+    env['LINK'] = 'g++'
+    env['AS'] = 'as'
+
+    env['WIN32DEFPREFIX']        = ''
+    env['WIN32DEFSUFFIX']        = '.def'
+    env['WINDOWSDEFPREFIX']      = '${WIN32DEFPREFIX}'
+    env['WINDOWSDEFSUFFIX']      = '${WIN32DEFSUFFIX}'
+
+    env['SHOBJSUFFIX'] = '.o'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+
+    env['RC'] = 'windres'
+    env['RCFLAGS'] = SCons.Util.CLVar('')
+    env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, RCINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
+    env['RCINCPREFIX'] = '--include-dir '
+    env['RCINCSUFFIX'] = ''
+    env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX}${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
+    env['BUILDERS']['RES'] = res_builder
+    
+    # Some setting from the platform also have to be overridden:
+    env['OBJSUFFIX'] = '.o'
+    env['LIBPREFIX'] = 'lib'
+    env['LIBSUFFIX'] = '.a'
+
+def exists(env):
+    return find(env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/mslib.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/mslib.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/mslib.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,76 @@
+"""SCons.Tool.mslib
+
+Tool-specific initialization for lib (MicroSoft library archiver).
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/mslib.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Tool.msvs
+import SCons.Tool.msvc
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for lib to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+
+    try:
+        version = SCons.Tool.msvs.get_default_visualstudio_version(env)
+
+        if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']:
+            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version)
+        else:
+            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version)
+
+        # since other tools can set this, we just make sure that the
+        # relevant stuff from MSVS is in there somewhere.
+        env.PrependENVPath('PATH', exe_path)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        pass
+
+    env['AR']          = 'lib'
+    env['ARFLAGS']     = SCons.Util.CLVar('/nologo')
+    env['ARCOM']       = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
+    env['LIBPREFIX']   = ''
+    env['LIBSUFFIX']   = '.lib'
+
+def exists(env):
+    try:
+        v = SCons.Tool.msvs.get_visualstudio_versions()
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        pass
+
+    if not v:
+        return env.Detect('lib')
+    else:
+        # there's at least one version of MSVS installed.
+        return 1

Added: cs/scons/scons-local-0.96.92/SCons/Tool/mslink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/mslink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/mslink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,229 @@
+"""SCons.Tool.mslink
+
+Tool-specific initialization for the Microsoft linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/mslink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Errors
+import SCons.Platform.win32
+import SCons.Tool
+import SCons.Tool.msvc
+import SCons.Tool.msvs
+import SCons.Util
+
+def pdbGenerator(env, target, source, for_signature):
+    if target and env.has_key('PDB') and env['PDB']:
+        return ['/PDB:%s'%target[0].File(env['PDB']).get_string(for_signature),
+                '/DEBUG']
+    return None
+
+def windowsShlinkTargets(target, source, env, for_signature):
+    listCmd = []
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    if dll: listCmd.append("/out:%s"%dll.get_string(for_signature))
+
+    implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
+    if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature))
+
+    return listCmd
+
+def windowsShlinkSources(target, source, env, for_signature):
+    listCmd = []
+
+    deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")
+    for src in source:
+        if src == deffile:
+            # Treat this source as a .def file.
+            listCmd.append("/def:%s" % src.get_string(for_signature))
+        else:
+            # Just treat it as a generic source file.
+            listCmd.append(src)
+    return listCmd
+
+def windowsLibEmitter(target, source, env):
+    SCons.Tool.msvc.validate_vars(env)
+
+    dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX")
+    no_import_lib = env.get('no_import_lib', 0)
+
+    if not dll:
+        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
+
+    insert_def = env.subst("$WINDOWS_INSERT_DEF")
+    if not insert_def in ['', '0', 0] and \
+       not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"):
+
+        # append a def file to the list of sources
+        source.append(env.ReplaceIxes(dll,
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"))
+
+    version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0'))
+    if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0):
+        # MSVC 8 automatically generates .manifest files that must be installed
+        target.append(env.ReplaceIxes(dll,
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "WINDOWSSHLIBMANIFESTPREFIX", "WINDOWSSHLIBMANIFESTSUFFIX"))
+
+    if env.has_key('PDB') and env['PDB']:
+        target.append(env['PDB'])
+
+    if not no_import_lib and \
+       not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
+        # Append an import library to the list of targets.
+        target.append(env.ReplaceIxes(dll,
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "LIBPREFIX", "LIBSUFFIX"))
+        # and .exp file is created if there are exports from a DLL
+        target.append(env.ReplaceIxes(dll,
+                                      "SHLIBPREFIX", "SHLIBSUFFIX",
+                                      "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX"))
+
+    return (target, source)
+
+def prog_emitter(target, source, env):
+    SCons.Tool.msvc.validate_vars(env)
+
+    exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX")
+    if not exe:
+        raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX")
+
+    version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0'))
+    if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0):
+        # MSVC 8 automatically generates .manifest files that have to be installed
+        target.append(env.ReplaceIxes(exe,
+                                      "PROGPREFIX", "PROGSUFFIX",
+                                      "WINDOWSPROGMANIFESTPREFIX", "WINDOWSPROGMANIFESTSUFFIX"))
+
+    if env.has_key('PDB') and env['PDB']:
+        target.append(env['PDB'])
+
+    return (target,source)
+
+def RegServerFunc(target, source, env):
+    if env.has_key('register') and env['register']:
+        ret = regServerAction([target[0]], [source[0]], env)
+        if ret:
+            raise SCons.Errors.UserError, "Unable to register %s" % target[0]
+        else:
+            print "Registered %s sucessfully" % target[0]
+        return ret
+    return 0
+
+regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR")
+regServerCheck = SCons.Action.Action(RegServerFunc, None)
+shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}')
+compositeLinkAction = shlibLinkAction + regServerCheck
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createSharedLibBuilder(env)
+    SCons.Tool.createProgBuilder(env)
+
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
+    env['_SHLINK_TARGETS'] = windowsShlinkTargets
+    env['_SHLINK_SOURCES'] = windowsShlinkSources
+    env['SHLINKCOM']   =  compositeLinkAction
+    env.Append(SHLIBEMITTER = [windowsLibEmitter])
+    env['LINK']        = 'link'
+    env['LINKFLAGS']   = SCons.Util.CLVar('/nologo')
+    env['_PDB'] = pdbGenerator
+    env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $SOURCES.windows")}'
+    env.Append(PROGEMITTER = [prog_emitter])
+    env['LIBDIRPREFIX']='/LIBPATH:'
+    env['LIBDIRSUFFIX']=''
+    env['LIBLINKPREFIX']=''
+    env['LIBLINKSUFFIX']='$LIBSUFFIX'
+
+    env['WIN32DEFPREFIX']        = ''
+    env['WIN32DEFSUFFIX']        = '.def'
+    env['WIN32_INSERT_DEF']      = 0
+    env['WINDOWSDEFPREFIX']      = '${WIN32DEFPREFIX}'
+    env['WINDOWSDEFSUFFIX']      = '${WIN32DEFSUFFIX}'
+    env['WINDOWS_INSERT_DEF']    = '${WIN32_INSERT_DEF}'
+
+    env['WIN32EXPPREFIX']        = ''
+    env['WIN32EXPSUFFIX']        = '.exp'
+    env['WINDOWSEXPPREFIX']      = '${WIN32EXPPREFIX}'
+    env['WINDOWSEXPSUFFIX']      = '${WIN32EXPSUFFIX}'
+
+    env['WINDOWSSHLIBMANIFESTPREFIX'] = ''
+    env['WINDOWSSHLIBMANIFESTSUFFIX'] = env['SHLIBSUFFIX'] + '.manifest'
+    env['WINDOWSPROGMANIFESTPREFIX']  = ''
+    env['WINDOWSPROGMANIFESTSUFFIX']  = env['PROGSUFFIX'] + '.manifest'
+
+    env['REGSVRACTION'] = regServerCheck
+    env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32')
+    env['REGSVRFLAGS'] = '/s '
+    env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}'
+
+    try:
+        version = SCons.Tool.msvs.get_default_visualstudio_version(env)
+
+        if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']:
+            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version)
+        else:
+            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version)
+
+        # since other tools can set these, we just make sure that the
+        # relevant stuff from MSVS is in there somewhere.
+        env.PrependENVPath('INCLUDE', include_path)
+        env.PrependENVPath('LIB', lib_path)
+        env.PrependENVPath('PATH', exe_path)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        pass
+
+    # For most platforms, a loadable module is the same as a shared
+    # library.  Platforms which are different can override these, but
+    # setting them the same means that LoadableModule works everywhere.
+    SCons.Tool.createLoadableModuleBuilder(env)
+    env['LDMODULE'] = '$SHLINK'
+    env['LDMODULEPREFIX'] = '$SHLIBPREFIX'
+    env['LDMODULESUFFIX'] = '$SHLIBSUFFIX'
+    env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
+    # We can't use '$SHLINKCOM' here because that will stringify the
+    # action list on expansion, and will then try to execute expanded
+    # strings, with the upshot that it would try to execute RegServerFunc
+    # as a command.
+    env['LDMODULECOM'] = compositeLinkAction
+
+def exists(env):
+    if SCons.Tool.msvs.is_msvs_installed():
+        # there's at least one version of MSVS installed.
+        return 1
+    else:
+        return env.Detect('link')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/msvc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/msvc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/msvc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,752 @@
+"""engine.SCons.Tool.msvc
+
+Tool-specific initialization for Microsoft Visual C/C++.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/msvc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+import string
+
+import SCons.Action
+import SCons.Builder
+import SCons.Errors
+import SCons.Platform.win32
+import SCons.Tool
+import SCons.Tool.msvs
+import SCons.Util
+import SCons.Warnings
+
+CSuffixes = ['.c', '.C']
+CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
+
+def _parse_msvc7_overrides(version,platform):
+    """ Parse any overridden defaults for MSVS directory locations
+    in MSVS .NET. """
+
+    # First, we get the shell folder for this user:
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+
+    comps = ""
+    try:
+        (comps, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
+                                            r'Software\Microsoft\Windows\CurrentVersion' +\
+                                            r'\Explorer\Shell Folders\Local AppData')
+    except SCons.Util.RegError:
+        raise SCons.Errors.InternalError, \
+              "The Local AppData directory was not found in the registry."
+
+    comps = comps + '\\Microsoft\\VisualStudio\\' + version + '\\VCComponents.dat'
+    dirs = {}
+
+    if os.path.exists(comps):
+        # now we parse the directories from this file, if it exists.
+        # We only look for entries after:
+        # [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories],
+        # since this file could contain a number of things...
+        lines = None
+        try:
+            import codecs
+        except ImportError:
+            pass
+        else:
+            try:
+                f = codecs.open(comps, 'r', 'utf16')
+                encoder = codecs.getencoder('ascii')
+                lines = map(lambda l, e=encoder: e(l)[0], f.readlines())
+            except (LookupError, UnicodeError):
+                lines = codecs.open(comps, 'r', 'utf8').readlines()
+        if lines is None:
+            lines = open(comps, 'r').readlines()
+        if 'x86' == platform: platform = 'Win32'
+
+        found = 0
+        for line in lines:
+            line.strip()
+            if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories]'%platform) >= 0:
+                found = 1
+            elif line == '' or line[:1] == '[':
+                found = 0
+            elif found == 1:
+                kv = line.split('=', 1)
+                if len(kv) == 2:
+                    (key, val) = kv
+                key = key.replace(' Dirs','')
+                dirs[key.upper()] = val
+        f.close()
+    else:
+        # since the file didn't exist, we have only the defaults in
+        # the registry to work with.
+
+        if 'x86' == platform: platform = 'Win32'
+
+        try:
+            K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version
+            K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories'%platform
+            k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K)
+            i = 0
+            while 1:
+                try:
+                    (key,val,t) = SCons.Util.RegEnumValue(k,i)
+                    key = key.replace(' Dirs','')
+                    dirs[key.upper()] = val
+                    i = i + 1
+                except SCons.Util.RegError:
+                    break
+        except SCons.Util.RegError:
+            # if we got here, then we didn't find the registry entries:
+            raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
+    return dirs
+
+def _parse_msvc8_overrides(version,platform,suite):
+    """ Parse any overridden defaults for MSVC directory locations
+    in MSVC 2005. """
+
+    # In VS8 the user can change the location of the settings file that
+    # contains the include, lib and binary paths. Try to get the location
+    # from registry
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+
+    s = ''
+    if suite == 'EXPRESS':
+        s = '\\VCExpress\\'
+
+    # ToDo: add registry key strings for the other versions of visual
+    # studio 2005.
+    settings_path = ""
+    try:
+        (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
+                                                    r'Software\Microsoft' + s + version +\
+                                                    r'\Profile\AutoSaveFile')
+        settings_path = settings_path.upper()
+    except SCons.Util.RegError:
+        raise SCons.Errors.InternalError, \
+              "The VS8 settings file location was not found in the registry."
+
+    # Look for potential environment variables in the settings path
+    if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0:
+        # First replace a special variable named %vsspv_visualstudio_dir%
+        # that is not found in the OSs environment variables...
+        try:
+            (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
+                                                r'Software\Microsoft' + s + version +\
+                                                r'\VisualStudioLocation')
+            settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value)
+        except SCons.Util.RegError:
+            raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry."
+
+    if settings_path.find('%') >= 0:
+        # Collect global environment variables
+        env_vars = {}
+
+        # Read all the global environment variables of the current user
+        k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment')
+        i = 0
+        while 1:
+            try:
+                (key,val,t) = SCons.Util.RegEnumValue(k,i)
+                env_vars[key.upper()] = val.upper()
+                i = i + 1
+            except SCons.Util.RegError:
+                break
+
+        # And some more variables that are not found in the registry
+        env_vars['USERPROFILE'] = os.getenv('USERPROFILE')
+        env_vars['SystemDrive'] = os.getenv('SystemDrive')
+
+        found_var = 1
+        while found_var:
+            found_var = 0
+            for env_var in env_vars:
+                if settings_path.find(r'%' + env_var + r'%') >= 0:
+                    settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var])
+                    found_var = 1
+
+    dirs = {}
+
+    if os.path.exists(settings_path):
+        # now we parse the directories from this file, if it exists.
+        import xml.dom.minidom
+        doc = xml.dom.minidom.parse(settings_path)
+        user_settings = doc.getElementsByTagName('UserSettings')[0]
+        tool_options = user_settings.getElementsByTagName('ToolsOptions')[0]
+        tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory')
+        for category in tool_options_categories:
+            category_name = category.attributes.get('name')
+            if category_name is not None and category_name.value == 'Projects':
+                subcategories = category.getElementsByTagName('ToolsOptionsSubCategory')
+                for subcategory in subcategories:
+                    subcategory_name = subcategory.attributes.get('name')
+                    if subcategory_name is not None and subcategory_name.value == 'VCDirectories':
+                        properties = subcategory.getElementsByTagName('PropertyValue')
+                        for property in properties:
+                            property_name = property.attributes.get('name')
+                            if property_name is None:
+                                continue
+                            elif property_name.value == 'IncludeDirectories':
+                                include_dirs = property.childNodes[0].data
+                                # ToDo: Support for other destinations than Win32
+                                include_dirs = include_dirs.replace('Win32|', '')
+                                dirs['INCLUDE'] = include_dirs
+                            elif property_name.value == 'LibraryDirectories':
+                                lib_dirs = property.childNodes[0].data.replace('Win32|', '')
+                                # ToDo: Support for other destinations than Win32
+                                lib_dirs = lib_dirs.replace('Win32|', '')
+                                dirs['LIBRARY'] = lib_dirs
+                            elif property_name.value == 'ExecutableDirectories':
+                                path_dirs = property.childNodes[0].data.replace('Win32|', '')
+                                # ToDo: Support for other destinations than Win32
+                                path_dirs = path_dirs.replace('Win32|', '')
+                                dirs['PATH'] = path_dirs
+    else:
+        # There are no default directories in the registry for VS8 Express :(
+        raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
+    return dirs
+
+def _get_msvc7_path(path, version, platform):
+    """
+    Get Visual Studio directories from version 7 (MSVS .NET)
+    (it has a different registry structure than versions before it)
+    """
+    # first, look for a customization of the default values in the
+    # registry: These are sometimes stored in the Local Settings area
+    # for Visual Studio, in a file, so we have to parse it.
+    dirs = _parse_msvc7_overrides(version,platform)
+
+    if dirs.has_key(path):
+        p = dirs[path]
+    else:
+        raise SCons.Errors.InternalError, \
+              "Unable to retrieve the %s path from MS VC++."%path
+
+    # collect some useful information for later expansions...
+    paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+
+    # expand the directory path variables that we support.  If there
+    # is a variable we don't support, then replace that entry with
+    # "---Unknown Location VSInstallDir---" or something similar, to clue
+    # people in that we didn't find something, and so env expansion doesn't
+    # do weird things with the $(xxx)'s
+    s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
+
+    def repl(match, paths=paths):
+        key = string.upper(match.group(1))
+        if paths.has_key(key):
+            return paths[key]
+        else:
+            # Now look in the global environment variables
+            envresult = os.getenv(key)
+            if not envresult is None:
+                return envresult + '\\'
+            else:
+                return '---Unknown Location %s---' % match.group()
+
+    rv = []
+    for entry in p.split(os.pathsep):
+        entry = s.sub(repl,entry).rstrip('\n\r')
+        rv.append(entry)
+
+    return string.join(rv,os.pathsep)
+
+def _get_msvc8_path(path, version, platform, suite):
+    """
+    Get Visual Studio directories from version 8 (MSVS 2005)
+    (it has a different registry structure than versions before it)
+    """
+    # first, look for a customization of the default values in the
+    # registry: These are sometimes stored in the Local Settings area
+    # for Visual Studio, in a file, so we have to parse it.
+    dirs = _parse_msvc8_overrides(version, platform, suite)
+
+    if dirs.has_key(path):
+        p = dirs[path]
+    else:
+        raise SCons.Errors.InternalError, \
+              "Unable to retrieve the %s path from MS VC++."%path
+
+    # collect some useful information for later expansions...
+    paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+
+    # expand the directory path variables that we support.  If there
+    # is a variable we don't support, then replace that entry with
+    # "---Unknown Location VSInstallDir---" or something similar, to clue
+    # people in that we didn't find something, and so env expansion doesn't
+    # do weird things with the $(xxx)'s
+    s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
+
+    def repl(match, paths=paths):
+        key = string.upper(match.group(1))
+        if paths.has_key(key):
+            return paths[key]
+        else:
+            return '---Unknown Location %s---' % match.group()
+
+    rv = []
+    for entry in p.split(os.pathsep):
+        entry = s.sub(repl,entry).rstrip('\n\r')
+        rv.append(entry)
+
+    return string.join(rv,os.pathsep)
+
+def get_msvc_path(env, path, version):
+    """
+    Get a list of visualstudio directories (include, lib or path).
+    Return a string delimited by the os.pathsep separator (';'). An
+    exception will be raised if unable to access the registry or
+    appropriate registry keys not found.
+    """
+
+    if not SCons.Util.can_read_reg:
+        raise SCons.Errors.InternalError, "No Windows registry module was found"
+
+    # normalize the case for comparisons (since the registry is case
+    # insensitive)
+    path = string.upper(path)
+
+    if path=='LIB':
+        path= 'LIBRARY'
+
+    version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
+    if version_num >= 8.0:
+        platform = env.get('MSVS8_PLATFORM', 'x86')
+        suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
+    else:
+        platform = 'x86'
+
+    if version_num >= 8.0:
+        return _get_msvc8_path(path, str(version_num), platform, suite)
+    elif version_num >= 7.0:
+        return _get_msvc7_path(path, str(version_num), platform)
+
+    path = string.upper(path + ' Dirs')
+    K = ('Software\\Microsoft\\Devstudio\\%s\\' +
+         'Build System\\Components\\Platforms\\Win32 (x86)\\Directories') % \
+        (version)
+    for base in (SCons.Util.HKEY_CURRENT_USER,
+                 SCons.Util.HKEY_LOCAL_MACHINE):
+        try:
+            k = SCons.Util.RegOpenKeyEx(base,K)
+            i = 0
+            while 1:
+                try:
+                    (p,v,t) = SCons.Util.RegEnumValue(k,i)
+                    if string.upper(p) == path:
+                        return v
+                    i = i + 1
+                except SCons.Util.RegError:
+                    break
+        except SCons.Util.RegError:
+            pass
+
+    # if we got here, then we didn't find the registry entries:
+    raise SCons.Errors.InternalError, "The %s path was not found in the registry."%path
+
+def _get_msvc6_default_paths(version, use_mfc_dirs):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+    three environment variables that should be set in order to execute
+    the MSVC 6.0 tools properly, if the information wasn't available
+    from the registry."""
+    MVSdir = None
+    paths = {}
+    exe_path = ''
+    lib_path = ''
+    include_path = ''
+    try:
+        paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+        MVSdir = paths['VSINSTALLDIR']
+    except (SCons.Util.RegError, SCons.Errors.InternalError, KeyError):
+        if os.environ.has_key('MSDEVDIR'):
+            MVSdir = os.path.normpath(os.path.join(os.environ['MSDEVDIR'],'..','..'))
+        else:
+            MVSdir = r'C:\Program Files\Microsoft Visual Studio'
+    if MVSdir:
+        if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
+            MVSVCdir = paths['VCINSTALLDIR']
+        else:
+            MVSVCdir = os.path.join(MVSdir,'VC98')
+
+        MVSCommondir = r'%s\Common' % MVSdir
+        if use_mfc_dirs:
+            mfc_include_ = r'%s\ATL\include;%s\MFC\include;' % (MVSVCdir, MVSVCdir)
+            mfc_lib_ = r'%s\MFC\lib;' % MVSVCdir
+        else:
+            mfc_include_ = ''
+            mfc_lib_ = ''
+        include_path = r'%s%s\include' % (mfc_include_, MVSVCdir)
+        lib_path = r'%s%s\lib' % (mfc_lib_, MVSVCdir)
+
+        if os.environ.has_key('OS') and os.environ['OS'] == "Windows_NT":
+            osdir = 'WINNT'
+        else:
+            osdir = 'WIN95'
+
+        exe_path = r'%s\tools\%s;%s\MSDev98\bin;%s\tools;%s\bin' % (MVSCommondir, osdir, MVSCommondir,  MVSCommondir, MVSVCdir)
+    return (include_path, lib_path, exe_path)
+
+def _get_msvc7_default_paths(env, version, use_mfc_dirs):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+    three environment variables that should be set in order to execute
+    the MSVC .NET tools properly, if the information wasn't available
+    from the registry."""
+
+    MVSdir = None
+    paths = {}
+    exe_path = ''
+    lib_path = ''
+    include_path = ''
+    try:
+        paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+        MVSdir = paths['VSINSTALLDIR']
+    except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
+        if os.environ.has_key('VSCOMNTOOLS'):
+            MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
+        else:
+            # last resort -- default install location
+            MVSdir = r'C:\Program Files\Microsoft Visual Studio .NET'
+
+    if MVSdir:
+        if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
+            MVSVCdir = paths['VCINSTALLDIR']
+        else:
+            MVSVCdir = os.path.join(MVSdir,'Vc7')
+
+        MVSCommondir = r'%s\Common7' % MVSdir
+        if use_mfc_dirs:
+            mfc_include_ = r'%s\atlmfc\include;' % MVSVCdir
+            mfc_lib_ = r'%s\atlmfc\lib;' % MVSVCdir
+        else:
+            mfc_include_ = ''
+            mfc_lib_ = ''
+        include_path = r'%s%s\include;%s\PlatformSDK\include' % (mfc_include_, MVSVCdir, MVSVCdir)
+        lib_path = r'%s%s\lib;%s\PlatformSDK\lib' % (mfc_lib_, MVSVCdir, MVSVCdir)
+        exe_path = r'%s\IDE;%s\bin;%s\Tools;%s\Tools\bin' % (MVSCommondir,MVSVCdir, MVSCommondir, MVSCommondir )
+
+        if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
+            include_path = include_path + r';%s\include'%paths['FRAMEWORKSDKDIR']
+            lib_path = lib_path + r';%s\lib'%paths['FRAMEWORKSDKDIR']
+            exe_path = exe_path + r';%s\bin'%paths['FRAMEWORKSDKDIR']
+
+        if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
+            exe_path = exe_path + r';%s\%s'%(paths['FRAMEWORKDIR'],paths['FRAMEWORKVERSION'])
+
+    return (include_path, lib_path, exe_path)
+
+def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+    three environment variables that should be set in order to execute
+    the MSVC 8 tools properly, if the information wasn't available
+    from the registry."""
+
+    MVSdir = None
+    paths = {}
+    exe_paths = []
+    lib_paths = []
+    include_paths = []
+    try:
+        paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
+        MVSdir = paths['VSINSTALLDIR']
+    except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
+        if os.environ.has_key('VSCOMNTOOLS'):
+            MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
+        else:
+            # last resort -- default install location
+            MVSdir = os.getenv('ProgramFiles') + r'\Microsoft Visual Studio 8'
+
+    if MVSdir:
+        if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
+            MVSVCdir = paths['VCINSTALLDIR']
+        else:
+            MVSVCdir = os.path.join(MVSdir,'VC')
+
+        MVSCommondir = os.path.join(MVSdir, 'Common7')
+        include_paths.append( os.path.join(MVSVCdir, 'include') )
+        lib_paths.append( os.path.join(MVSVCdir, 'lib') )
+        for base, subdir in [(MVSCommondir,'IDE'), (MVSVCdir,'bin'),
+                             (MVSCommondir,'Tools'), (MVSCommondir,r'Tools\bin')]:
+            exe_paths.append( os.path.join( base, subdir) )
+
+        if paths.has_key('PLATFORMSDKDIR'):
+            PlatformSdkDir = paths['PLATFORMSDKDIR']
+        else:
+            PlatformSdkDir = os.path.join(MVSVCdir,'PlatformSDK')
+        platform_include_path = os.path.join( PlatformSdkDir, 'Include' )
+        include_paths.append( platform_include_path )
+        lib_paths.append( os.path.join( PlatformSdkDir, 'Lib' ) )
+        if use_mfc_dirs:
+            if paths.has_key('PLATFORMSDKDIR'):
+                include_paths.append( os.path.join( platform_include_path, 'mfc' ) )
+                include_paths.append( os.path.join( platform_include_path, 'atl' ) )
+            else:
+                atlmfc_path = os.path.join( MVSVCdir, 'atlmfc' )
+                include_paths.append( os.path.join( atlmfc_path, 'include' ) )
+                lib_paths.append( os.path.join( atlmfc_path, 'lib' ) )
+
+        env_include_path = SCons.Util.get_environment_var('INCLUDE')
+        if env_include_path:
+            include_paths.append( env_include_path )
+
+        if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
+            include_paths.append( os.path.join( paths['FRAMEWORKSDKDIR'], 'include' ) )
+            lib_paths.append( os.path.join( paths['FRAMEWORKSDKDIR'], 'lib' ) )
+            exe_paths.append( paths['FRAMEWORKSDKDIR'], 'bin' )
+
+        if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
+            exe_paths.append( os.path.join( paths['FRAMEWORKDIR'], paths['FRAMEWORKVERSION'] ) )
+
+    include_path = string.join( include_paths, os.pathsep )
+    lib_path = string.join(lib_paths, os.pathsep )
+    exe_path = string.join(exe_paths, os.pathsep )
+    return (include_path, lib_path, exe_path)
+
+def get_msvc_paths(env, version=None, use_mfc_dirs=0):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
+    of those three environment variables that should be set
+    in order to execute the MSVC tools properly."""
+    exe_path = ''
+    lib_path = ''
+    include_path = ''
+
+    if not version:
+        versions = SCons.Tool.msvs.get_visualstudio_versions()
+        if versions:
+            version = versions[0] #use highest version by default
+        else:
+            version = '6.0'
+
+    # Some of the configured directories only
+    # appear if the user changes them from the default.
+    # Therefore, we'll see if we can get the path to the MSDev
+    # base installation from the registry and deduce the default
+    # directories.
+    version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
+    if version_num >= 8.0:
+        suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
+        defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
+    elif version_num >= 7.0:
+        defpaths = _get_msvc7_default_paths(env, version, use_mfc_dirs)
+    else:
+        defpaths = _get_msvc6_default_paths(version, use_mfc_dirs)
+
+    try:
+        include_path = get_msvc_path(env, "include", version)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        include_path = defpaths[0]
+
+    try:
+        lib_path = get_msvc_path(env, "lib", version)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        lib_path = defpaths[1]
+
+    try:
+        exe_path = get_msvc_path(env, "path", version)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        exe_path = defpaths[2]
+
+    return (include_path, lib_path, exe_path)
+
+def get_msvc_default_paths(env, version=None, use_mfc_dirs=0):
+    """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
+    three environment variables that should be set in order to execute
+    the MSVC tools properly.  This will only return the default
+    locations for the tools, not the values used by MSVS in their
+    directory setup area.  This can help avoid problems with different
+    developers having different settings, and should allow the tools
+    to run in most cases."""
+
+    if not version and not SCons.Util.can_read_reg:
+        version = '6.0'
+
+    try:
+        if not version:
+            version = SCons.Tool.msvs.get_visualstudio_versions()[0] #use highest version
+    except KeyboardInterrupt:
+        raise
+    except:
+        pass
+
+    version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
+    if version_num >= 8.0:
+        suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
+        defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
+    elif version_num >= 7.0:
+        return _get_msvc7_default_paths(env, version, use_mfc_dirs)
+    else:
+        return _get_msvc6_default_paths(version, use_mfc_dirs)
+
+def validate_vars(env):
+    """Validate the PCH and PCHSTOP construction variables."""
+    if env.has_key('PCH') and env['PCH']:
+        if not env.has_key('PCHSTOP'):
+            raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
+        if not SCons.Util.is_String(env['PCHSTOP']):
+            raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
+
+def pch_emitter(target, source, env):
+    """Adds the object file target."""
+
+    validate_vars(env)
+
+    pch = None
+    obj = None
+
+    for t in target:
+        if SCons.Util.splitext(str(t))[1] == '.pch':
+            pch = t
+        if SCons.Util.splitext(str(t))[1] == '.obj':
+            obj = t
+
+    if not obj:
+        obj = SCons.Util.splitext(str(pch))[0]+'.obj'
+
+    target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
+
+    return (target, source)
+
+def object_emitter(target, source, env, parent_emitter):
+    """Sets up the PCH dependencies for an object file."""
+
+    validate_vars(env)
+
+    parent_emitter(target, source, env)
+
+    if env.has_key('PCH') and env['PCH']:
+        env.Depends(target, env['PCH'])
+
+    return (target, source)
+
+def static_object_emitter(target, source, env):
+    return object_emitter(target, source, env,
+                          SCons.Defaults.StaticObjectEmitter)
+
+def shared_object_emitter(target, source, env):
+    return object_emitter(target, source, env,
+                          SCons.Defaults.SharedObjectEmitter)
+
+pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
+pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
+                                    emitter=pch_emitter,
+                                    source_scanner=SCons.Tool.SourceFileScanner)
+res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
+res_builder = SCons.Builder.Builder(action=res_action, suffix='.res',
+                                    source_scanner=SCons.Tool.SourceFileScanner)
+SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
+
+def generate(env):
+    """Add Builders and construction variables for MSVC++ to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+        static_obj.add_emitter(suffix, static_object_emitter)
+        shared_obj.add_emitter(suffix, shared_object_emitter)
+
+    for suffix in CXXSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CXXAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
+        static_obj.add_emitter(suffix, static_object_emitter)
+        shared_obj.add_emitter(suffix, shared_object_emitter)
+
+    env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
+    env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
+    env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
+    env['CC']         = 'cl'
+    env['CCFLAGS']    = SCons.Util.CLVar('/nologo')
+    env['CCCOM']      = '$CC $CCFLAGS $CCCOMFLAGS'
+    env['SHCC']       = '$CC'
+    env['SHCCFLAGS']  = SCons.Util.CLVar('$CCFLAGS')
+    env['SHCCCOM']    = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
+    env['CXX']        = '$CC'
+    env['CXXFLAGS']   = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
+    env['CXXCOM']     = '$CXX $CXXFLAGS $CCCOMFLAGS'
+    env['SHCXX']      = '$CXX'
+    env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
+    env['SHCXXCOM']   = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
+    env['CPPDEFPREFIX']  = '/D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '/I'
+    env['INCSUFFIX']  = ''
+#    env.Append(OBJEMITTER = [static_object_emitter])
+#    env.Append(SHOBJEMITTER = [shared_object_emitter])
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+
+    env['RC'] = 'rc'
+    env['RCFLAGS'] = SCons.Util.CLVar('')
+    env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
+    env['BUILDERS']['RES'] = res_builder
+    env['OBJPREFIX']      = ''
+    env['OBJSUFFIX']      = '.obj'
+    env['SHOBJPREFIX']    = '$OBJPREFIX'
+    env['SHOBJSUFFIX']    = '$OBJSUFFIX'
+
+    try:
+        version = SCons.Tool.msvs.get_default_visualstudio_version(env)
+        version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
+        if version_num == 8.0:
+            suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
+
+        use_mfc_dirs = env.get('MSVS_USE_MFC_DIRS', 0)
+        if env.get('MSVS_IGNORE_IDE_PATHS', 0):
+            _get_paths = get_msvc_default_paths
+        else:
+            _get_paths = get_msvc_paths
+        include_path, lib_path, exe_path = _get_paths(env, version, use_mfc_dirs)
+
+        # since other tools can set these, we just make sure that the
+        # relevant stuff from MSVS is in there somewhere.
+        env.PrependENVPath('INCLUDE', include_path)
+        env.PrependENVPath('LIB', lib_path)
+        env.PrependENVPath('PATH', exe_path)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        pass
+
+    env['CFILESUFFIX'] = '.c'
+    env['CXXFILESUFFIX'] = '.cc'
+
+    env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
+    env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
+    env['BUILDERS']['PCH'] = pch_builder
+
+    if not env.has_key('ENV'):
+        env['ENV'] = {}
+    if not env['ENV'].has_key('SystemRoot'):    # required for dlls in the winsxs folders
+        env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
+
+def exists(env):
+    if SCons.Tool.msvs.is_msvs_installed():
+        # there's at least one version of MSVS installed.
+        return 1
+    else:
+        return env.Detect('cl')
+

Added: cs/scons/scons-local-0.96.92/SCons/Tool/msvs.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/msvs.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/msvs.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,1752 @@
+"""SCons.Tool.msvs
+
+Tool-specific initialization for Microsoft Visual Studio project files.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/msvs.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import base64
+import md5
+import os.path
+import pickle
+import re
+import string
+import sys
+
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Platform.win32
+import SCons.Script.SConscript
+import SCons.Util
+import SCons.Warnings
+
+##############################################################################
+# Below here are the classes and functions for generation of
+# DSP/DSW/SLN/VCPROJ files.
+##############################################################################
+
+def _hexdigest(s):
+    """Return a string as a string of hex characters.
+    """
+    # NOTE:  This routine is a method in the Python 2.0 interface
+    # of the native md5 module, but we want SCons to operate all
+    # the way back to at least Python 1.5.2, which doesn't have it.
+    h = string.hexdigits
+    r = ''
+    for c in s:
+        i = ord(c)
+        r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+    return r
+
+def xmlify(s):
+    s = string.replace(s, "&", "&amp;") # do this first
+    s = string.replace(s, "'", "&apos;")
+    s = string.replace(s, '"', "&quot;")
+    return s
+
+external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}'
+
+def _generateGUID(slnfile, name):
+    """This generates a dummy GUID for the sln file to use.  It is
+    based on the MD5 signatures of the sln filename plus the name of
+    the project.  It basically just needs to be unique, and not
+    change with each invocation."""
+    solution = _hexdigest(md5.new(str(slnfile)+str(name)).digest()).upper()
+    # convert most of the signature to GUID form (discard the rest)
+    solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:20] + "-" + solution[20:32] + "}"
+    return solution
+
+version_re = re.compile(r'(\d+\.\d+)(.*)')
+
+def msvs_parse_version(s):
+    """
+    Split a Visual Studio version, which may in fact be something like
+    '7.0Exp', into is version number (returned as a float) and trailing
+    "suite" portion.
+    """
+    num, suite = version_re.match(s).groups()
+    return float(num), suite
+
+# This is how we re-invoke SCons from inside MSVS Project files.
+# The problem is that we might have been invoked as either scons.bat
+# or scons.py.  If we were invoked directly as scons.py, then we could
+# use sys.argv[0] to find the SCons "executable," but that doesn't work
+# if we were invoked as scons.bat, which uses "python -c" to execute
+# things and ends up with "-c" as sys.argv[0].  Consequently, we have
+# the MSVS Project file invoke SCons the same way that scons.bat does,
+# which works regardless of how we were invoked.
+def getExecScriptMain(env, xml=None):
+    scons_home = env.get('SCONS_HOME')
+    if not scons_home and os.environ.has_key('SCONS_LIB_DIR'):
+        scons_home = os.environ['SCONS_LIB_DIR']
+    if scons_home:
+        exec_script_main = "from os.path import join; import sys; sys.path = [ r'%s' ] + sys.path; import SCons.Script; SCons.Script.main()" % scons_home
+    else:
+        version = SCons.__version__
+        exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-%(version)s'), join(sys.prefix, 'scons-%(version)s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % locals()
+    if xml:
+        exec_script_main = xmlify(exec_script_main)
+    return exec_script_main
+
+# The string for the Python executable we tell the Project file to use
+# is either sys.executable or, if an external PYTHON_ROOT environment
+# variable exists, $(PYTHON)ROOT\\python.exe (generalized a little to
+# pluck the actual executable name from sys.executable).
+try:
+    python_root = os.environ['PYTHON_ROOT']
+except KeyError:
+    python_executable = sys.executable
+else:
+    python_executable = os.path.join('$$(PYTHON_ROOT)',
+                                     os.path.split(sys.executable)[1])
+
+class Config:
+    pass
+
+def splitFully(path):
+    dir, base = os.path.split(path)
+    if dir and dir != '' and dir != path:
+        return splitFully(dir)+[base]
+    if base == '':
+        return []
+    return [base]
+
+def makeHierarchy(sources):
+    '''Break a list of files into a hierarchy; for each value, if it is a string,
+       then it is a file.  If it is a dictionary, it is a folder.  The string is
+       the original path of the file.'''
+
+    hierarchy = {}
+    for file in sources:
+        path = splitFully(file)
+        if len(path):
+            dict = hierarchy
+            for part in path[:-1]:
+                if not dict.has_key(part):
+                    dict[part] = {}
+                dict = dict[part]
+            dict[path[-1]] = file
+        #else:
+        #    print 'Warning: failed to decompose path for '+str(file)
+    return hierarchy
+
+class _DSPGenerator:
+    """ Base class for DSP generators """
+
+    srcargs = [
+        'srcs',
+        'incs',
+        'localincs',
+        'resources',
+        'misc']
+
+    def __init__(self, dspfile, source, env):
+        self.dspfile = str(dspfile)
+        try:
+            get_abspath = dspfile.get_abspath
+        except AttributeError:
+            self.dspabs = os.path.abspath(dspfile)
+        else:
+            self.dspabs = get_abspath()
+
+        if not env.has_key('variant'):
+            raise SCons.Errors.InternalError, \
+                  "You must specify a 'variant' argument (i.e. 'Debug' or " +\
+                  "'Release') to create an MSVSProject."
+        elif SCons.Util.is_String(env['variant']):
+            variants = [env['variant']]
+        elif SCons.Util.is_List(env['variant']):
+            variants = env['variant']
+
+        if not env.has_key('buildtarget') or env['buildtarget'] == None:
+            buildtarget = ['']
+        elif SCons.Util.is_String(env['buildtarget']):
+            buildtarget = [env['buildtarget']]
+        elif SCons.Util.is_List(env['buildtarget']):
+            if len(env['buildtarget']) != len(variants):
+                raise SCons.Errors.InternalError, \
+                    "Sizes of 'buildtarget' and 'variant' lists must be the same."
+            buildtarget = []
+            for bt in env['buildtarget']:
+                if SCons.Util.is_String(bt):
+                    buildtarget.append(bt)
+                else:
+                    buildtarget.append(bt.get_abspath())
+        else:
+            buildtarget = [env['buildtarget'].get_abspath()]
+        if len(buildtarget) == 1:
+            bt = buildtarget[0]
+            buildtarget = []
+            for v in variants:
+                buildtarget.append(bt)
+
+        if not env.has_key('outdir') or env['outdir'] == None:
+            outdir = ['']
+        elif SCons.Util.is_String(env['outdir']):
+            outdir = [env['outdir']]
+        elif SCons.Util.is_List(env['outdir']):
+            if len(env['outdir']) != len(variants):
+                raise SCons.Errors.InternalError, \
+                    "Sizes of 'outdir' and 'variant' lists must be the same."
+            outdir = []
+            for s in env['outdir']:
+                if SCons.Util.is_String(s):
+                    outdir.append(s)
+                else:
+                    outdir.append(s.get_abspath())
+        else:
+            outdir = [env['outdir'].get_abspath()]
+        if len(outdir) == 1:
+            s = outdir[0]
+            outdir = []
+            for v in variants:
+                outdir.append(s)
+
+        if not env.has_key('runfile') or env['runfile'] == None:
+            runfile = buildtarget[-1:]
+        elif SCons.Util.is_String(env['runfile']):
+            runfile = [env['runfile']]
+        elif SCons.Util.is_List(env['runfile']):
+            if len(env['runfile']) != len(variants):
+                raise SCons.Errors.InternalError, \
+                    "Sizes of 'runfile' and 'variant' lists must be the same."
+            runfile = []
+            for s in env['runfile']:
+                if SCons.Util.is_String(s):
+                    runfile.append(s)
+                else:
+                    runfile.append(s.get_abspath())
+        else:
+            runfile = [env['runfile'].get_abspath()]
+        if len(runfile) == 1:
+            s = runfile[0]
+            runfile = []
+            for v in variants:
+                runfile.append(s)
+
+        self.sconscript = env['MSVSSCONSCRIPT']
+
+        cmdargs = env.get('cmdargs', '')
+
+        self.env = env
+
+        if self.env.has_key('name'):
+            self.name = self.env['name']
+        else:
+            self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0])
+        self.name = self.env.subst(self.name)
+
+        sourcenames = [
+            'Source Files',
+            'Header Files',
+            'Local Headers',
+            'Resource Files',
+            'Other Files']
+
+        self.sources = {}
+        for n in sourcenames:
+            self.sources[n] = []
+
+        self.configs = {}
+
+        self.nokeep = 0
+        if env.has_key('nokeep') and env['variant'] != 0:
+            self.nokeep = 1
+
+        if self.nokeep == 0 and os.path.exists(self.dspabs):
+            self.Parse()
+
+        for t in zip(sourcenames,self.srcargs):
+            if self.env.has_key(t[1]):
+                if SCons.Util.is_List(self.env[t[1]]):
+                    for i in self.env[t[1]]:
+                        if not i in self.sources[t[0]]:
+                            self.sources[t[0]].append(i)
+                else:
+                    if not self.env[t[1]] in self.sources[t[0]]:
+                        self.sources[t[0]].append(self.env[t[1]])
+
+        for n in sourcenames:
+            self.sources[n].sort(lambda a, b: cmp(a.lower(), b.lower()))
+
+        def AddConfig(variant, buildtarget, outdir, runfile, cmdargs):
+            config = Config()
+            config.buildtarget = buildtarget
+            config.outdir = outdir
+            config.cmdargs = cmdargs
+            config.runfile = runfile
+
+            match = re.match('(.*)\|(.*)', variant)
+            if match:
+                config.variant = match.group(1)
+                config.platform = match.group(2)
+            else:
+                config.variant = variant
+                config.platform = 'Win32'
+
+            self.configs[variant] = config
+            print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'"
+
+        for i in range(len(variants)):
+            AddConfig(variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs)
+
+        self.platforms = []
+        for key in self.configs.keys():
+            platform = self.configs[key].platform
+            if not platform in self.platforms:
+                self.platforms.append(platform)
+
+    def Build(self):
+        pass
+
+V6DSPHeader = """\
+# Microsoft Developer Studio Project File - Name="%(name)s" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=%(name)s - Win32 %(confkey)s
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "%(name)s.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+"""
+
+class _GenerateV6DSP(_DSPGenerator):
+    """Generates a Project file for MSVS 6.0"""
+
+    def PrintHeader(self):
+        # pick a default config
+        confkeys = self.configs.keys()
+        confkeys.sort()
+
+        name = self.name
+        confkey = confkeys[0]
+
+        self.file.write(V6DSPHeader % locals())
+
+        for kind in confkeys:
+            self.file.write('!MESSAGE "%s - Win32 %s" (based on "Win32 (x86) External Target")\n' % (name, kind))
+
+        self.file.write('!MESSAGE \n\n')
+
+    def PrintProject(self):
+        name = self.name
+        self.file.write('# Begin Project\n'
+                        '# PROP AllowPerConfigDependencies 0\n'
+                        '# PROP Scc_ProjName ""\n'
+                        '# PROP Scc_LocalPath ""\n\n')
+
+        first = 1
+        confkeys = self.configs.keys()
+        confkeys.sort()
+        for kind in confkeys:
+            outdir = self.configs[kind].outdir
+            buildtarget = self.configs[kind].buildtarget
+            if first == 1:
+                self.file.write('!IF  "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind))
+                first = 0
+            else:
+                self.file.write('\n!ELSEIF  "$(CFG)" == "%s - Win32 %s"\n\n' % (name, kind))
+
+            env_has_buildtarget = self.env.has_key('MSVSBUILDTARGET')
+            if not env_has_buildtarget:
+                self.env['MSVSBUILDTARGET'] = buildtarget
+
+            # have to write this twice, once with the BASE settings, and once without
+            for base in ("BASE ",""):
+                self.file.write('# PROP %sUse_MFC 0\n'
+                                '# PROP %sUse_Debug_Libraries ' % (base, base))
+                if kind.lower().find('debug') < 0:
+                    self.file.write('0\n')
+                else:
+                    self.file.write('1\n')
+                self.file.write('# PROP %sOutput_Dir "%s"\n'
+                                '# PROP %sIntermediate_Dir "%s"\n' % (base,outdir,base,outdir))
+                cmd = 'echo Starting SCons && ' + self.env.subst('$MSVSBUILDCOM', 1)
+                self.file.write('# PROP %sCmd_Line "%s"\n'
+                                '# PROP %sRebuild_Opt "-c && %s"\n'
+                                '# PROP %sTarget_File "%s"\n'
+                                '# PROP %sBsc_Name ""\n'
+                                '# PROP %sTarget_Dir ""\n'\
+                                %(base,cmd,base,cmd,base,buildtarget,base,base))
+
+            if not env_has_buildtarget:
+                del self.env['MSVSBUILDTARGET']
+
+        self.file.write('\n!ENDIF\n\n'
+                        '# Begin Target\n\n')
+        for kind in confkeys:
+            self.file.write('# Name "%s - Win32 %s"\n' % (name,kind))
+        self.file.write('\n')
+        first = 0
+        for kind in confkeys:
+            if first == 0:
+                self.file.write('!IF  "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind))
+                first = 1
+            else:
+                self.file.write('!ELSEIF  "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind))
+        self.file.write('!ENDIF \n\n')
+        self.PrintSourceFiles()
+        self.file.write('# End Target\n'
+                        '# End Project\n')
+
+        if self.nokeep == 0:
+            # now we pickle some data and add it to the file -- MSDEV will ignore it.
+            pdata = pickle.dumps(self.configs,1)
+            pdata = base64.encodestring(pdata)
+            self.file.write(pdata + '\n')
+            pdata = pickle.dumps(self.sources,1)
+            pdata = base64.encodestring(pdata)
+            self.file.write(pdata + '\n')
+
+    def PrintSourceFiles(self):
+        categories = {'Source Files': 'cpp|c|cxx|l|y|def|odl|idl|hpj|bat',
+                      'Header Files': 'h|hpp|hxx|hm|inl',
+                      'Local Headers': 'h|hpp|hxx|hm|inl',
+                      'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe',
+                      'Other Files': ''}
+
+        cats = categories.keys()
+        cats.sort(lambda a, b: cmp(a.lower(), b.lower()))
+        for kind in cats:
+            if not self.sources[kind]:
+                continue # skip empty groups
+
+            self.file.write('# Begin Group "' + kind + '"\n\n')
+            typelist = categories[kind].replace('|',';')
+            self.file.write('# PROP Default_Filter "' + typelist + '"\n')
+
+            for file in self.sources[kind]:
+                file = os.path.normpath(file)
+                self.file.write('# Begin Source File\n\n'
+                                'SOURCE="' + file + '"\n'
+                                '# End Source File\n')
+            self.file.write('# End Group\n')
+
+        # add the SConscript file outside of the groups
+        self.file.write('# Begin Source File\n\n'
+                        'SOURCE="' + str(self.sconscript) + '"\n'
+                        '# End Source File\n')
+
+    def Parse(self):
+        try:
+            dspfile = open(self.dspabs,'r')
+        except IOError:
+            return # doesn't exist yet, so can't add anything to configs.
+
+        line = dspfile.readline()
+        while line:
+            if line.find("# End Project") > -1:
+                break
+            line = dspfile.readline()
+
+        line = dspfile.readline()
+        datas = line
+        while line and line != '\n':
+            line = dspfile.readline()
+            datas = datas + line
+
+        # OK, we've found our little pickled cache of data.
+        try:
+            datas = base64.decodestring(datas)
+            data = pickle.loads(datas)
+        except KeyboardInterrupt:
+            raise
+        except:
+            return # unable to unpickle any data for some reason
+
+        self.configs.update(data)
+
+        data = None
+        line = dspfile.readline()
+        datas = line
+        while line and line != '\n':
+            line = dspfile.readline()
+            datas = datas + line
+
+        # OK, we've found our little pickled cache of data.
+        # it has a "# " in front of it, so we strip that.
+        try:
+            datas = base64.decodestring(datas)
+            data = pickle.loads(datas)
+        except KeyboardInterrupt:
+            raise
+        except:
+            return # unable to unpickle any data for some reason
+
+        self.sources.update(data)
+
+    def Build(self):
+        try:
+            self.file = open(self.dspabs,'w')
+        except IOError, detail:
+            raise SCons.Errors.InternalError, 'Unable to open "' + self.dspabs + '" for writing:' + str(detail)
+        else:
+            self.PrintHeader()
+            self.PrintProject()
+            self.file.close()
+
+V7DSPHeader = """\
+<?xml version="1.0" encoding = "%(encoding)s"?>
+<VisualStudioProject
+\tProjectType="Visual C++"
+\tVersion="%(versionstr)s"
+\tName="%(name)s"
+%(scc_attrs)s
+\tKeyword="MakeFileProj">
+"""
+
+V7DSPConfiguration = """\
+\t\t<Configuration
+\t\t\tName="%(variant)s|%(platform)s"
+\t\t\tOutputDirectory="%(outdir)s"
+\t\t\tIntermediateDirectory="%(outdir)s"
+\t\t\tConfigurationType="0"
+\t\t\tUseOfMFC="0"
+\t\t\tATLMinimizesCRunTimeLibraryUsage="FALSE">
+\t\t\t<Tool
+\t\t\t\tName="VCNMakeTool"
+\t\t\t\tBuildCommandLine="%(buildcmd)s"
+\t\t\t\tCleanCommandLine="%(cleancmd)s"
+\t\t\t\tRebuildCommandLine="%(rebuildcmd)s"
+\t\t\t\tOutput="%(runfile)s"/>
+\t\t</Configuration>
+"""
+
+V8DSPHeader = """\
+<?xml version="1.0" encoding="%(encoding)s"?>
+<VisualStudioProject
+\tProjectType="Visual C++"
+\tVersion="%(versionstr)s"
+\tName="%(name)s"
+%(scc_attrs)s
+\tRootNamespace="%(name)s"
+\tKeyword="MakeFileProj">
+"""
+
+V8DSPConfiguration = """\
+\t\t<Configuration
+\t\t\tName="%(variant)s|Win32"
+\t\t\tConfigurationType="0"
+\t\t\tUseOfMFC="0"
+\t\t\tATLMinimizesCRunTimeLibraryUsage="false"
+\t\t\t>
+\t\t\t<Tool
+\t\t\t\tName="VCNMakeTool"
+\t\t\t\tBuildCommandLine="%(buildcmd)s"
+\t\t\t\tReBuildCommandLine="%(rebuildcmd)s"
+\t\t\t\tCleanCommandLine="%(cleancmd)s"
+\t\t\t\tOutput="%(runfile)s"
+\t\t\t\tPreprocessorDefinitions=""
+\t\t\t\tIncludeSearchPath=""
+\t\t\t\tForcedIncludes=""
+\t\t\t\tAssemblySearchPath=""
+\t\t\t\tForcedUsingAssemblies=""
+\t\t\t\tCompileAsManaged=""
+\t\t\t/>
+\t\t</Configuration>
+"""
+class _GenerateV7DSP(_DSPGenerator):
+    """Generates a Project file for MSVS .NET"""
+
+    def __init__(self, dspfile, source, env):
+        _DSPGenerator.__init__(self, dspfile, source, env)
+        self.version = env['MSVS_VERSION']
+        self.version_num, self.suite = msvs_parse_version(self.version)
+        if self.version_num >= 8.0:
+            self.versionstr = '8.00'
+            self.dspheader = V8DSPHeader
+            self.dspconfiguration = V8DSPConfiguration
+        else:
+            if self.version_num >= 7.1:
+                self.versionstr = '7.10'
+            else:
+                self.versionstr = '7.00'
+            self.dspheader = V7DSPHeader
+            self.dspconfiguration = V7DSPConfiguration
+        self.file = None
+
+    def PrintHeader(self):
+        env = self.env
+        versionstr = self.versionstr
+        name = self.name
+        encoding = self.env.subst('$MSVSENCODING')
+        scc_provider = env.get('MSVS_SCC_PROVIDER', '')
+        scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
+        scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
+        scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '')
+        project_guid = env.get('MSVS_PROJECT_GUID', '')
+        if self.version_num >= 8.0 and not project_guid:
+            project_guid = _generateGUID(self.dspfile, '')
+        if scc_provider != '':
+            scc_attrs = ('\tProjectGUID="%s"\n'
+                         '\tSccProjectName="%s"\n'
+                         '\tSccAuxPath="%s"\n'
+                         '\tSccLocalPath="%s"\n'
+                         '\tSccProvider="%s"' % (project_guid, scc_project_name, scc_aux_path, scc_local_path, scc_provider))
+        else:
+            scc_attrs = ('\tProjectGUID="%s"\n'
+                         '\tSccProjectName="%s"\n'
+                         '\tSccLocalPath="%s"' % (project_guid, scc_project_name, scc_local_path))
+
+        self.file.write(self.dspheader % locals())
+
+        self.file.write('\t<Platforms>\n')
+        for platform in self.platforms:
+            self.file.write(
+                        '\t\t<Platform\n'
+                        '\t\t\tName="%s"/>\n' % platform)
+        self.file.write('\t</Platforms>\n')
+
+        if self.version_num >= 8.0:
+            self.file.write('\t<ToolFiles>\n'
+                            '\t</ToolFiles>\n')
+
+    def PrintProject(self):
+        self.file.write('\t<Configurations>\n')
+
+        confkeys = self.configs.keys()
+        confkeys.sort()
+        for kind in confkeys:
+            variant = self.configs[kind].variant
+            platform = self.configs[kind].platform
+            outdir = self.configs[kind].outdir
+            buildtarget = self.configs[kind].buildtarget
+            runfile     = self.configs[kind].runfile
+            cmdargs = self.configs[kind].cmdargs
+
+            env_has_buildtarget = self.env.has_key('MSVSBUILDTARGET')
+            if not env_has_buildtarget:
+                self.env['MSVSBUILDTARGET'] = buildtarget
+
+            starting = 'echo Starting SCons && '
+            if cmdargs:
+                cmdargs = ' ' + cmdargs
+            else:
+                cmdargs = ''
+            buildcmd    = xmlify(starting + self.env.subst('$MSVSBUILDCOM', 1) + cmdargs)
+            rebuildcmd  = xmlify(starting + self.env.subst('$MSVSREBUILDCOM', 1) + cmdargs)
+            cleancmd    = xmlify(starting + self.env.subst('$MSVSCLEANCOM', 1) + cmdargs)
+
+            if not env_has_buildtarget:
+                del self.env['MSVSBUILDTARGET']
+
+            self.file.write(self.dspconfiguration % locals())
+
+        self.file.write('\t</Configurations>\n')
+
+        if self.version_num >= 7.1:
+            self.file.write('\t<References>\n'
+                            '\t</References>\n')
+
+        self.PrintSourceFiles()
+
+        self.file.write('</VisualStudioProject>\n')
+
+        if self.nokeep == 0:
+            # now we pickle some data and add it to the file -- MSDEV will ignore it.
+            pdata = pickle.dumps(self.configs,1)
+            pdata = base64.encodestring(pdata)
+            self.file.write('<!-- SCons Data:\n' + pdata + '\n')
+            pdata = pickle.dumps(self.sources,1)
+            pdata = base64.encodestring(pdata)
+            self.file.write(pdata + '-->\n')
+
+    def PrintSourceFiles(self):
+        categories = {'Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat',
+                      'Header Files': 'h;hpp;hxx;hm;inl',
+                      'Local Headers': 'h;hpp;hxx;hm;inl',
+                      'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe',
+                      'Other Files': ''}
+
+        self.file.write('\t<Files>\n')
+
+        cats = categories.keys()
+        cats.sort(lambda a, b: cmp(a.lower(), b.lower()))
+        cats = filter(lambda k, s=self: s.sources[k], cats)
+        for kind in cats:
+            if len(cats) > 1:
+                self.file.write('\t\t<Filter\n'
+                                '\t\t\tName="%s"\n'
+                                '\t\t\tFilter="%s">\n' % (kind, categories[kind]))
+
+
+            def printSources(hierarchy, commonprefix):
+                sorteditems = hierarchy.items()
+                sorteditems.sort(lambda a, b: cmp(a[0].lower(), b[0].lower()))
+
+                # First folders, then files
+                for key, value in sorteditems:
+                    if SCons.Util.is_Dict(value):
+                        self.file.write('\t\t\t<Filter\n'
+                                        '\t\t\t\tName="%s"\n'
+                                        '\t\t\t\tFilter="">\n' % (key))
+                        printSources(value, commonprefix)
+                        self.file.write('\t\t\t</Filter>\n')
+
+                for key, value in sorteditems:
+                    if SCons.Util.is_String(value):
+                        file = value
+                        if commonprefix:
+                            file = os.path.join(commonprefix, value)
+                        file = os.path.normpath(file)
+                        self.file.write('\t\t\t<File\n'
+                                        '\t\t\t\tRelativePath="%s">\n'
+                                        '\t\t\t</File>\n' % (file))
+
+            sources = self.sources[kind]
+
+            # First remove any common prefix
+            commonprefix = None
+            if len(sources) > 1:
+                s = map(os.path.normpath, sources)
+                cp = os.path.commonprefix(s)
+                if cp and s[0][len(cp)] == os.sep:
+                    sources = map(lambda s, l=len(cp): s[l:], sources)
+                    commonprefix = cp
+
+            hierarchy = makeHierarchy(sources)
+            printSources(hierarchy, commonprefix=commonprefix)
+
+            if len(cats)>1:
+                self.file.write('\t\t</Filter>\n')
+
+        # add the SConscript file outside of the groups
+        self.file.write('\t\t<File\n'
+                        '\t\t\tRelativePath="%s">\n'
+                        '\t\t</File>\n' % str(self.sconscript))
+
+        self.file.write('\t</Files>\n'
+                        '\t<Globals>\n'
+                        '\t</Globals>\n')
+
+    def Parse(self):
+        try:
+            dspfile = open(self.dspabs,'r')
+        except IOError:
+            return # doesn't exist yet, so can't add anything to configs.
+
+        line = dspfile.readline()
+        while line:
+            if line.find('<!-- SCons Data:') > -1:
+                break
+            line = dspfile.readline()
+
+        line = dspfile.readline()
+        datas = line
+        while line and line != '\n':
+            line = dspfile.readline()
+            datas = datas + line
+
+        # OK, we've found our little pickled cache of data.
+        try:
+            datas = base64.decodestring(datas)
+            data = pickle.loads(datas)
+        except KeyboardInterrupt:
+            raise
+        except:
+            return # unable to unpickle any data for some reason
+
+        self.configs.update(data)
+
+        data = None
+        line = dspfile.readline()
+        datas = line
+        while line and line != '\n':
+            line = dspfile.readline()
+            datas = datas + line
+
+        # OK, we've found our little pickled cache of data.
+        try:
+            datas = base64.decodestring(datas)
+            data = pickle.loads(datas)
+        except KeyboardInterrupt:
+            raise
+        except:
+            return # unable to unpickle any data for some reason
+
+        self.sources.update(data)
+
+    def Build(self):
+        try:
+            self.file = open(self.dspabs,'w')
+        except IOError, detail:
+            raise SCons.Errors.InternalError, 'Unable to open "' + self.dspabs + '" for writing:' + str(detail)
+        else:
+            self.PrintHeader()
+            self.PrintProject()
+            self.file.close()
+
+class _DSWGenerator:
+    """ Base class for DSW generators """
+    def __init__(self, dswfile, source, env):
+        self.dswfile = os.path.normpath(str(dswfile))
+        self.env = env
+
+        if not env.has_key('projects'):
+            raise SCons.Errors.UserError, \
+                "You must specify a 'projects' argument to create an MSVSSolution."
+        projects = env['projects']
+        if not SCons.Util.is_List(projects):
+            raise SCons.Errors.InternalError, \
+                "The 'projects' argument must be a list of nodes."
+        projects = SCons.Util.flatten(projects)
+        if len(projects) < 1:
+            raise SCons.Errors.UserError, \
+                "You must specify at least one project to create an MSVSSolution."
+        self.dspfiles = map(str, projects)
+
+        if self.env.has_key('name'):
+            self.name = self.env['name']
+        else:
+            self.name = os.path.basename(SCons.Util.splitext(self.dswfile)[0])
+        self.name = self.env.subst(self.name)
+
+    def Build(self):
+        pass
+
+class _GenerateV7DSW(_DSWGenerator):
+    """Generates a Solution file for MSVS .NET"""
+    def __init__(self, dswfile, source, env):
+        _DSWGenerator.__init__(self, dswfile, source, env)
+
+        self.file = None
+        self.version = self.env['MSVS_VERSION']
+        self.version_num, self.suite = msvs_parse_version(self.version)
+        self.versionstr = '7.00'
+        if self.version_num >= 8.0:
+            self.versionstr = '9.00'
+        elif self.version_num >= 7.1:
+            self.versionstr = '8.00'
+        if self.version_num >= 8.0:
+            self.versionstr = '9.00'
+
+        if env.has_key('slnguid') and env['slnguid']:
+            self.slnguid = env['slnguid']
+        else:
+            self.slnguid = _generateGUID(dswfile, self.name)
+
+        self.configs = {}
+
+        self.nokeep = 0
+        if env.has_key('nokeep') and env['variant'] != 0:
+            self.nokeep = 1
+
+        if self.nokeep == 0 and os.path.exists(self.dswfile):
+            self.Parse()
+
+        def AddConfig(variant):
+            config = Config()
+
+            match = re.match('(.*)\|(.*)', variant)
+            if match:
+                config.variant = match.group(1)
+                config.platform = match.group(2)
+            else:
+                config.variant = variant
+                config.platform = 'Win32'
+
+            self.configs[variant] = config
+            print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'"
+
+        if not env.has_key('variant'):
+            raise SCons.Errors.InternalError, \
+                  "You must specify a 'variant' argument (i.e. 'Debug' or " +\
+                  "'Release') to create an MSVS Solution File."
+        elif SCons.Util.is_String(env['variant']):
+            AddConfig(env['variant'])
+        elif SCons.Util.is_List(env['variant']):
+            for variant in env['variant']:
+                AddConfig(variant)
+
+        self.platforms = []
+        for key in self.configs.keys():
+            platform = self.configs[key].platform
+            if not platform in self.platforms:
+                self.platforms.append(platform)
+
+    def Parse(self):
+        try:
+            dswfile = open(self.dswfile,'r')
+        except IOError:
+            return # doesn't exist yet, so can't add anything to configs.
+
+        line = dswfile.readline()
+        while line:
+            if line[:9] == "EndGlobal":
+                break
+            line = dswfile.readline()
+
+        line = dswfile.readline()
+        datas = line
+        while line:
+            line = dswfile.readline()
+            datas = datas + line
+
+        # OK, we've found our little pickled cache of data.
+        try:
+            datas = base64.decodestring(datas)
+            data = pickle.loads(datas)
+        except KeyboardInterrupt:
+            raise
+        except:
+            return # unable to unpickle any data for some reason
+
+        self.configs.update(data)
+
+    def PrintSolution(self):
+        """Writes a solution file"""
+        self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr )
+        if self.version_num >= 8.0:
+            self.file.write('# Visual Studio 2005\n')
+        for p in self.dspfiles:
+            name = os.path.basename(p)
+            base, suffix = SCons.Util.splitext(name)
+            if suffix == '.vcproj':
+                name = base
+            guid = _generateGUID(p, '')
+            self.file.write('Project("%s") = "%s", "%s", "%s"\n'
+                            % ( external_makefile_guid, name, p, guid ) )
+            if self.version_num >= 7.1 and self.version_num < 8.0:
+                self.file.write('\tProjectSection(ProjectDependencies) = postProject\n'
+                                '\tEndProjectSection\n')
+            self.file.write('EndProject\n')
+
+        self.file.write('Global\n')
+
+        env = self.env
+        if env.has_key('MSVS_SCC_PROVIDER'):
+            dspfile_base = os.path.basename(self.dspfile)
+            slnguid = self.slnguid
+            scc_provider = env.get('MSVS_SCC_PROVIDER', '')
+            scc_provider = string.replace(scc_provider, ' ', r'\u0020')
+            scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
+            # scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
+            scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '')
+            scc_project_base_path = env.get('MSVS_SCC_PROJECT_BASE_PATH', '')
+            # project_guid = env.get('MSVS_PROJECT_GUID', '')
+
+            self.file.write('\tGlobalSection(SourceCodeControl) = preSolution\n'
+                            '\t\tSccNumberOfProjects = 2\n'
+                            '\t\tSccProjectUniqueName0 = %(dspfile_base)s\n'
+                            '\t\tSccLocalPath0 = %(scc_local_path)s\n'
+                            '\t\tCanCheckoutShared = true\n'
+                            '\t\tSccProjectFilePathRelativizedFromConnection0 = %(scc_project_base_path)s\n'
+                            '\t\tSccProjectName1 = %(scc_project_name)s\n'
+                            '\t\tSccLocalPath1 = %(scc_local_path)s\n'
+                            '\t\tSccProvider1 = %(scc_provider)s\n'
+                            '\t\tCanCheckoutShared = true\n'
+                            '\t\tSccProjectFilePathRelativizedFromConnection1 = %(scc_project_base_path)s\n'
+                            '\t\tSolutionUniqueID = %(slnguid)s\n'
+                            '\tEndGlobalSection\n' % locals())
+
+        if self.version_num >= 8.0:
+            self.file.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
+        else:
+            self.file.write('\tGlobalSection(SolutionConfiguration) = preSolution\n')
+
+        confkeys = self.configs.keys()
+        confkeys.sort()
+        cnt = 0
+        for name in confkeys:
+            variant = self.configs[name].variant
+            platform = self.configs[name].platform
+            if self.version_num >= 8.0:
+                self.file.write('\t\t%s|%s = %s|%s\n' % (variant, platform, variant, platform))
+            else:
+                self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant))
+            cnt = cnt + 1
+        self.file.write('\tEndGlobalSection\n')
+        if self.version_num < 7.1:
+            self.file.write('\tGlobalSection(ProjectDependencies) = postSolution\n'
+                            '\tEndGlobalSection\n')
+        if self.version_num >= 8.0:
+            self.file.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
+        else:
+            self.file.write('\tGlobalSection(ProjectConfiguration) = postSolution\n')
+
+        for name in confkeys:
+            name = name
+            variant = self.configs[name].variant
+            platform = self.configs[name].platform
+            if self.version_num >= 8.0:
+                for p in self.dspfiles:
+                    guid = _generateGUID(p, '')
+                    self.file.write('\t\t%s.%s|%s.ActiveCfg = %s|%s\n'
+                                    '\t\t%s.%s|%s.Build.0 = %s|%s\n'  % (guid,variant,platform,variant,platform,guid,variant,platform,variant,platform))
+            else:
+                self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n'
+                                '\t\t%s.%s.Build.0 = %s|%s\n'  %(self.slnguid,variant,variant,platform,self.slnguid,variant,variant,platform))
+
+        self.file.write('\tEndGlobalSection\n')
+
+        if self.version_num >= 8.0:
+            self.file.write('\tGlobalSection(SolutionProperties) = preSolution\n'
+                            '\t\tHideSolutionNode = FALSE\n'
+                            '\tEndGlobalSection\n')
+        else:
+            self.file.write('\tGlobalSection(ExtensibilityGlobals) = postSolution\n'
+                            '\tEndGlobalSection\n'
+                            '\tGlobalSection(ExtensibilityAddIns) = postSolution\n'
+                            '\tEndGlobalSection\n')
+        self.file.write('EndGlobal\n')
+        if self.nokeep == 0:
+            pdata = pickle.dumps(self.configs,1)
+            pdata = base64.encodestring(pdata)
+            self.file.write(pdata + '\n')
+
+    def Build(self):
+        try:
+            self.file = open(self.dswfile,'w')
+        except IOError, detail:
+            raise SCons.Errors.InternalError, 'Unable to open "' + self.dswfile + '" for writing:' + str(detail)
+        else:
+            self.PrintSolution()
+            self.file.close()
+
+V6DSWHeader = """\
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "%(name)s"="%(dspfile)s" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+"""
+
+class _GenerateV6DSW(_DSWGenerator):
+    """Generates a Workspace file for MSVS 6.0"""
+
+    def PrintWorkspace(self):
+        """ writes a DSW file """
+        name = self.name
+        dspfile = self.dspfiles[0]
+        self.file.write(V6DSWHeader % locals())
+
+    def Build(self):
+        try:
+            self.file = open(self.dswfile,'w')
+        except IOError, detail:
+            raise SCons.Errors.InternalError, 'Unable to open "' + self.dswfile + '" for writing:' + str(detail)
+        else:
+            self.PrintWorkspace()
+            self.file.close()
+
+
+def GenerateDSP(dspfile, source, env):
+    """Generates a Project file based on the version of MSVS that is being used"""
+
+    version_num = 6.0
+    if env.has_key('MSVS_VERSION'):
+        version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
+    if version_num >= 7.0:
+        g = _GenerateV7DSP(dspfile, source, env)
+        g.Build()
+    else:
+        g = _GenerateV6DSP(dspfile, source, env)
+        g.Build()
+
+def GenerateDSW(dswfile, source, env):
+    """Generates a Solution/Workspace file based on the version of MSVS that is being used"""
+
+    version_num = 6.0
+    if env.has_key('MSVS_VERSION'):
+        version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
+    if version_num >= 7.0:
+        g = _GenerateV7DSW(dswfile, source, env)
+        g.Build()
+    else:
+        g = _GenerateV6DSW(dswfile, source, env)
+        g.Build()
+
+
+##############################################################################
+# Above here are the classes and functions for generation of
+# DSP/DSW/SLN/VCPROJ files.
+##############################################################################
+
+def get_default_visualstudio_version(env):
+    """Returns the version set in the env, or the latest version
+    installed, if it can find it, or '6.0' if all else fails.  Also
+    updated the environment with what it found."""
+
+    version = '6.0'
+    versions = [version]
+
+    if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']):
+        env['MSVS'] = {}    
+
+        if env['MSVS'].has_key('VERSIONS'):
+            versions = env['MSVS']['VERSIONS']
+        elif SCons.Util.can_read_reg:
+            v = get_visualstudio_versions()
+            if v:
+                versions = v
+        if env.has_key('MSVS_VERSION'):
+            version = env['MSVS_VERSION']
+        else:
+            version = versions[0] #use highest version by default
+
+        env['MSVS_VERSION'] = version
+        env['MSVS']['VERSIONS'] = versions
+        env['MSVS']['VERSION'] = version
+    else:
+        version = env['MSVS']['VERSION']
+
+    return version
+
+def get_visualstudio_versions():
+    """
+    Get list of visualstudio versions from the Windows registry.
+    Returns a list of strings containing version numbers.  An empty list
+    is returned if we were unable to accees the register (for example,
+    we couldn't import the registry-access module) or the appropriate
+    registry keys weren't found.
+    """
+
+    if not SCons.Util.can_read_reg:
+        return []
+
+    HLM = SCons.Util.HKEY_LOCAL_MACHINE
+    KEYS = {
+        r'Software\Microsoft\VisualStudio'      : '',
+        r'Software\Microsoft\VCExpress'         : 'Exp',
+    }
+    L = []
+    for K, suite_suffix in KEYS.items():
+        try:
+            k = SCons.Util.RegOpenKeyEx(HLM, K)
+            i = 0
+            while 1:
+                try:
+                    p = SCons.Util.RegEnumKey(k,i)
+                except SCons.Util.RegError:
+                    break
+                i = i + 1
+                if not p[0] in '123456789' or p in L:
+                    continue
+                # Only add this version number if there is a valid
+                # registry structure (includes the "Setup" key),
+                # and at least some of the correct directories
+                # exist.  Sometimes VS uninstall leaves around
+                # some registry/filesystem turds that we don't
+                # want to trip over.  Also, some valid registry
+                # entries are MSDN entries, not MSVS ('7.1',
+                # notably), and we want to skip those too.
+                try:
+                    SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p + '\\Setup')
+                except SCons.Util.RegError:
+                    continue
+
+                id = []
+                idk = SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p)
+                # This is not always here -- it only exists if the
+                # user installed into a non-standard location (at
+                # least in VS6 it works that way -- VS7 seems to
+                # always write it)
+                try:
+                    id = SCons.Util.RegQueryValueEx(idk, 'InstallDir')
+                except SCons.Util.RegError:
+                    pass
+
+                # If the InstallDir key doesn't exist,
+                # then we check the default locations.
+                # Note: The IDE's executable is not devenv.exe for VS8 Express.
+                if not id or not id[0]:
+                    files_dir = SCons.Platform.win32.get_program_files_dir()
+                    version_num, suite = msvs_parse_version(p)
+                    if version_num < 7.0:
+                        vs = r'Microsoft Visual Studio\Common\MSDev98'
+                    elif version_num < 8.0:
+                        vs = r'Microsoft Visual Studio .NET\Common7\IDE'
+                    else:
+                        vs = r'Microsoft Visual Studio 8\Common7\IDE'
+                    id = [ os.path.join(files_dir, vs) ]
+                if os.path.exists(id[0]):
+                    L.append(p + suite_suffix)
+        except SCons.Util.RegError:
+            pass
+
+    if not L:
+        return []
+
+    # This is a hack to get around the fact that certain Visual Studio
+    # patches place a "6.1" version in the registry, which does not have
+    # any of the keys we need to find include paths, install directories,
+    # etc.  Therefore we ignore it if it is there, since it throws all
+    # other logic off.
+    try:
+        L.remove("6.1")
+    except ValueError:
+        pass
+
+    L.sort()
+    L.reverse()
+
+    return L
+
+def get_default_visualstudio8_suite(env):
+    """
+    Returns the Visual Studio 2005 suite identifier set in the env, or the
+    highest suite installed.
+    """
+    if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']):
+        env['MSVS'] = {}
+
+    if env.has_key('MSVS_SUITE'):
+        suite = env['MSVS_SUITE'].upper()
+        suites = [suite]
+    else:
+        suite = 'EXPRESS'
+        suites = [suite]
+        if SCons.Util.can_read_reg:
+            suites = get_visualstudio8_suites()
+            if suites:
+                suite = suites[0] #use best suite by default
+
+    env['MSVS_SUITE'] = suite
+    env['MSVS']['SUITES'] = suites
+    env['MSVS']['SUITE'] = suite
+
+    return suite
+
+def get_visualstudio8_suites():
+    """
+    Returns a sorted list of all installed Visual Studio 2005 suites found
+    in the registry. The highest version should be the first entry in the list.
+    """
+
+    suites = []
+
+    # Detect Standard, Professional and Team edition
+    try:
+        idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+            r'Software\Microsoft\VisualStudio\8.0')
+        id = SCons.Util.RegQueryValueEx(idk, 'InstallDir')
+        editions = { 'PRO': r'Setup\VS\Pro' }       # ToDo: add standard and team editions
+        edition_name = 'STD'
+        for name, key_suffix in editions.items():
+            try:
+                idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+                    r'Software\Microsoft\VisualStudio\8.0' + '\\' + key_suffix )
+                edition_name = name
+            except SCons.Util.RegError:
+                pass
+            suites.append(edition_name)
+    except SCons.Util.RegError:
+        pass
+
+    # Detect Expression edition
+    try:
+        idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+            r'Software\Microsoft\VCExpress\8.0')
+        id = SCons.Util.RegQueryValueEx(idk, 'InstallDir')
+        suites.append('EXPRESS')
+    except SCons.Util.RegError:
+        pass
+
+    return suites
+
+def is_msvs_installed():
+    """
+    Check the registry for an installed visual studio.
+    """
+    try:
+        v = SCons.Tool.msvs.get_visualstudio_versions()
+        return v
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        return 0
+
+def get_msvs_install_dirs(version = None):
+    """
+    Get installed locations for various msvc-related products, like the .NET SDK
+    and the Platform SDK.
+    """
+
+    if not SCons.Util.can_read_reg:
+        return {}
+
+    if not version:
+        versions = get_visualstudio_versions()
+        if versions:
+            version = versions[0] #use highest version by default
+        else:
+            return {}
+
+    version_num, suite = msvs_parse_version(version)
+
+    K = 'Software\\Microsoft\\VisualStudio\\' + str(version_num)
+    if (version_num >= 8.0):
+        try:
+            SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K )
+        except SCons.Util.RegError:
+            K = 'Software\\Microsoft\\VCExpress\\' + str(version_num)
+
+    # vc++ install dir
+    rv = {}
+    if (version_num < 7.0):
+        key = K + r'\Setup\Microsoft Visual C++\ProductDir'
+    else:
+        key = K + r'\Setup\VC\ProductDir'
+    try:
+        (rv['VCINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, key)
+    except SCons.Util.RegError:
+        pass
+
+    # visual studio install dir
+    if (version_num < 7.0):
+        try:
+            (rv['VSINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
+                                                             K + r'\Setup\Microsoft Visual Studio\ProductDir')
+        except SCons.Util.RegError:
+            pass
+
+        if not rv.has_key('VSINSTALLDIR') or not rv['VSINSTALLDIR']:
+            if rv.has_key('VCINSTALLDIR') and rv['VCINSTALLDIR']:
+                rv['VSINSTALLDIR'] = os.path.dirname(rv['VCINSTALLDIR'])
+            else:
+                rv['VSINSTALLDIR'] = os.path.join(SCons.Platform.win32.get_program_files_dir(),'Microsoft Visual Studio')
+    else:
+        try:
+            (rv['VSINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
+                                                             K + r'\Setup\VS\ProductDir')
+        except SCons.Util.RegError:
+            pass
+
+    # .NET framework install dir
+    try:
+        (rv['FRAMEWORKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
+            r'Software\Microsoft\.NETFramework\InstallRoot')
+    except SCons.Util.RegError:
+        pass
+
+    if rv.has_key('FRAMEWORKDIR'):
+        # try and enumerate the installed versions of the .NET framework.
+        contents = os.listdir(rv['FRAMEWORKDIR'])
+        l = re.compile('v[0-9]+.*')
+        versions = []
+        for entry in contents:
+            if l.match(entry):
+                versions.append(entry)
+
+        def versrt(a,b):
+            # since version numbers aren't really floats...
+            aa = a[1:]
+            bb = b[1:]
+            aal = aa.split('.')
+            bbl = bb.split('.')
+            c = int(bbl[0]) - int(aal[0])
+            if c == 0:
+                c = int(bbl[1]) - int(aal[1])
+                if c == 0:
+                    c = int(bbl[2]) - int(aal[2])
+            return c
+
+        versions.sort(versrt)
+
+        rv['FRAMEWORKVERSIONS'] = versions
+        # assume that the highest version is the latest version installed
+        rv['FRAMEWORKVERSION'] = versions[0]
+
+    # .NET framework SDK install dir
+    try:
+        if rv.has_key('FRAMEWORKVERSION') and rv['FRAMEWORKVERSION'][:4] == 'v1.1':
+            key = r'Software\Microsoft\.NETFramework\sdkInstallRootv1.1'
+        else:
+            key = r'Software\Microsoft\.NETFramework\sdkInstallRoot'
+
+        (rv['FRAMEWORKSDKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,key)
+
+    except SCons.Util.RegError:
+        pass
+
+    # MS Platform SDK dir
+    try:
+        (rv['PLATFORMSDKDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
+            r'Software\Microsoft\MicrosoftSDK\Directories\Install Dir')
+    except SCons.Util.RegError:
+        pass
+
+    if rv.has_key('PLATFORMSDKDIR'):
+        # if we have a platform SDK, try and get some info on it.
+        vers = {}
+        try:
+            loc = r'Software\Microsoft\MicrosoftSDK\InstalledSDKs'
+            k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,loc)
+            i = 0
+            while 1:
+                try:
+                    key = SCons.Util.RegEnumKey(k,i)
+                    sdk = SCons.Util.RegOpenKeyEx(k,key)
+                    j = 0
+                    name = ''
+                    date = ''
+                    version = ''
+                    while 1:
+                        try:
+                            (vk,vv,t) = SCons.Util.RegEnumValue(sdk,j)
+                            if vk.lower() == 'keyword':
+                                name = vv
+                            if vk.lower() == 'propagation_date':
+                                date = vv
+                            if vk.lower() == 'version':
+                                version = vv
+                            j = j + 1
+                        except SCons.Util.RegError:
+                            break
+                    if name:
+                        vers[name] = (date, version)
+                    i = i + 1
+                except SCons.Util.RegError:
+                    break
+            rv['PLATFORMSDK_MODULES'] = vers
+        except SCons.Util.RegError:
+            pass
+
+    return rv
+
+def GetMSVSProjectSuffix(target, source, env, for_signature):
+     return env['MSVS']['PROJECTSUFFIX']
+
+def GetMSVSSolutionSuffix(target, source, env, for_signature):
+     return env['MSVS']['SOLUTIONSUFFIX']
+
+def GenerateProject(target, source, env):
+    # generate the dsp file, according to the version of MSVS.
+    builddspfile = target[0]
+    dspfile = builddspfile.srcnode()
+
+    # this detects whether or not we're using a BuildDir
+    if not dspfile is builddspfile:
+        try:
+            bdsp = open(str(builddspfile), "w+")
+        except IOError, detail:
+            print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n'
+            raise
+
+        bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath())
+
+    GenerateDSP(dspfile, source, env)
+
+    if env.get('auto_build_solution', 1):
+        builddswfile = target[1]
+        dswfile = builddswfile.srcnode()
+
+        if not dswfile is builddswfile:
+
+            try:
+                bdsw = open(str(builddswfile), "w+")
+            except IOError, detail:
+                print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n'
+                raise
+
+            bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath())
+
+        GenerateDSW(dswfile, source, env)
+
+def GenerateSolution(target, source, env):
+    GenerateDSW(target[0], source, env)
+
+def projectEmitter(target, source, env):
+    """Sets up the DSP dependencies."""
+
+    # todo: Not sure what sets source to what user has passed as target,
+    # but this is what happens. When that is fixed, we also won't have
+    # to make the user always append env['MSVSPROJECTSUFFIX'] to target.
+    if source[0] == target[0]:
+        source = []
+
+    # make sure the suffix is correct for the version of MSVS we're running.
+    (base, suff) = SCons.Util.splitext(str(target[0]))
+    suff = env.subst('$MSVSPROJECTSUFFIX')
+    target[0] = base + suff
+
+    if not source:
+        source = 'prj_inputs:'
+        source = source + env.subst('$MSVSSCONSCOM', 1)
+        source = source + env.subst('$MSVSENCODING', 1)
+
+        if env.has_key('buildtarget') and env['buildtarget'] != None:
+            if SCons.Util.is_String(env['buildtarget']):
+                source = source + ' "%s"' % env['buildtarget']
+            elif SCons.Util.is_List(env['buildtarget']):
+                for bt in env['buildtarget']:
+                    if SCons.Util.is_String(bt):
+                        source = source + ' "%s"' % bt
+                    else:
+                        try: source = source + ' "%s"' % bt.get_abspath()
+                        except AttributeError: raise SCons.Errors.InternalError, \
+                            "buildtarget can be a string, a node, a list of strings or nodes, or None"
+            else:
+                try: source = source + ' "%s"' % env['buildtarget'].get_abspath()
+                except AttributeError: raise SCons.Errors.InternalError, \
+                    "buildtarget can be a string, a node, a list of strings or nodes, or None"
+
+        if env.has_key('outdir') and env['outdir'] != None:
+            if SCons.Util.is_String(env['outdir']):
+                source = source + ' "%s"' % env['outdir']
+            elif SCons.Util.is_List(env['outdir']):
+                for s in env['outdir']:
+                    if SCons.Util.is_String(s):
+                        source = source + ' "%s"' % s
+                    else:
+                        try: source = source + ' "%s"' % s.get_abspath()
+                        except AttributeError: raise SCons.Errors.InternalError, \
+                            "outdir can be a string, a node, a list of strings or nodes, or None"
+            else:
+                try: source = source + ' "%s"' % env['outdir'].get_abspath()
+                except AttributeError: raise SCons.Errors.InternalError, \
+                    "outdir can be a string, a node, a list of strings or nodes, or None"
+
+        if env.has_key('name'):
+            if SCons.Util.is_String(env['name']):
+                source = source + ' "%s"' % env['name']
+            else:
+                raise SCons.Errors.InternalError, "name must be a string"
+
+        if env.has_key('variant'):
+            if SCons.Util.is_String(env['variant']):
+                source = source + ' "%s"' % env['variant']
+            elif SCons.Util.is_List(env['variant']):
+                for variant in env['variant']:
+                    if SCons.Util.is_String(variant):
+                        source = source + ' "%s"' % variant
+                    else:
+                        raise SCons.Errors.InternalError, "name must be a string or a list of strings"
+            else:
+                raise SCons.Errors.InternalError, "variant must be a string or a list of strings"
+        else:
+            raise SCons.Errors.InternalError, "variant must be specified"
+
+        for s in _DSPGenerator.srcargs:
+            if env.has_key(s):
+                if SCons.Util.is_String(env[s]):
+                    source = source + ' "%s' % env[s]
+                elif SCons.Util.is_List(env[s]):
+                    for t in env[s]:
+                        if SCons.Util.is_String(t):
+                            source = source + ' "%s"' % t
+                        else:
+                            raise SCons.Errors.InternalError, s + " must be a string or a list of strings"
+                else:
+                    raise SCons.Errors.InternalError, s + " must be a string or a list of strings"
+
+        source = source + ' "%s"' % str(target[0])
+        source = [SCons.Node.Python.Value(source)]
+
+    targetlist = [target[0]]
+    sourcelist = source
+
+    if env.get('auto_build_solution', 1):
+        env['projects'] = targetlist
+        t, s = solutionEmitter(target, target, env)
+        targetlist = targetlist + t
+
+    return (targetlist, sourcelist)
+
+def solutionEmitter(target, source, env):
+    """Sets up the DSW dependencies."""
+
+    # todo: Not sure what sets source to what user has passed as target,
+    # but this is what happens. When that is fixed, we also won't have
+    # to make the user always append env['MSVSSOLUTIONSUFFIX'] to target.
+    if source[0] == target[0]:
+        source = []
+
+    # make sure the suffix is correct for the version of MSVS we're running.
+    (base, suff) = SCons.Util.splitext(str(target[0]))
+    suff = env.subst('$MSVSSOLUTIONSUFFIX')
+    target[0] = base + suff
+
+    if not source:
+        source = 'sln_inputs:'
+
+        if env.has_key('name'):
+            if SCons.Util.is_String(env['name']):
+                source = source + ' "%s"' % env['name']
+            else:
+                raise SCons.Errors.InternalError, "name must be a string"
+
+        if env.has_key('variant'):
+            if SCons.Util.is_String(env['variant']):
+                source = source + ' "%s"' % env['variant']
+            elif SCons.Util.is_List(env['variant']):
+                for variant in env['variant']:
+                    if SCons.Util.is_String(variant):
+                        source = source + ' "%s"' % variant
+                    else:
+                        raise SCons.Errors.InternalError, "name must be a string or a list of strings"
+            else:
+                raise SCons.Errors.InternalError, "variant must be a string or a list of strings"
+        else:
+            raise SCons.Errors.InternalError, "variant must be specified"
+
+        if env.has_key('slnguid'):
+            if SCons.Util.is_String(env['slnguid']):
+                source = source + ' "%s"' % env['slnguid']
+            else:
+                raise SCons.Errors.InternalError, "slnguid must be a string"
+
+        if env.has_key('projects'):
+            if SCons.Util.is_String(env['projects']):
+                source = source + ' "%s"' % env['projects']
+            elif SCons.Util.is_List(env['projects']):
+                for t in env['projects']:
+                    if SCons.Util.is_String(t):
+                        source = source + ' "%s"' % t
+
+        source = source + ' "%s"' % str(target[0])
+        source = [SCons.Node.Python.Value(source)]
+
+    return ([target[0]], source)
+
+projectAction = SCons.Action.Action(GenerateProject, None)
+
+solutionAction = SCons.Action.Action(GenerateSolution, None)
+
+projectBuilder = SCons.Builder.Builder(action = '$MSVSPROJECTCOM',
+                                       suffix = '$MSVSPROJECTSUFFIX',
+                                       emitter = projectEmitter)
+
+solutionBuilder = SCons.Builder.Builder(action = '$MSVSSOLUTIONCOM',
+                                        suffix = '$MSVSSOLUTIONSUFFIX',
+                                        emitter = solutionEmitter)
+
+default_MSVS_SConscript = None
+
+def generate(env):
+    """Add Builders and construction variables for Microsoft Visual
+    Studio project files to an Environment."""
+    try:
+        env['BUILDERS']['MSVSProject']
+    except KeyError:
+        env['BUILDERS']['MSVSProject'] = projectBuilder
+
+    try:
+        env['BUILDERS']['MSVSSolution']
+    except KeyError:
+        env['BUILDERS']['MSVSSolution'] = solutionBuilder
+
+    env['MSVSPROJECTCOM'] = projectAction
+    env['MSVSSOLUTIONCOM'] = solutionAction
+
+    if SCons.Script.call_stack:
+        # XXX Need to find a way to abstract this; the build engine
+        # shouldn't depend on anything in SCons.Script.
+        env['MSVSSCONSCRIPT'] = SCons.Script.call_stack[0].sconscript
+    else:
+        global default_MSVS_SConscript
+        if default_MSVS_SConscript is None:
+            default_MSVS_SConscript = env.File('SConstruct')
+        env['MSVSSCONSCRIPT'] = default_MSVS_SConscript
+
+    env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env))
+    env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.abspath}" -f ${MSVSSCONSCRIPT.name}'
+    env['MSVSSCONSCOM'] = '$MSVSSCONS $MSVSSCONSFLAGS'
+    env['MSVSBUILDCOM'] = '$MSVSSCONSCOM $MSVSBUILDTARGET'
+    env['MSVSREBUILDCOM'] = '$MSVSSCONSCOM $MSVSBUILDTARGET'
+    env['MSVSCLEANCOM'] = '$MSVSSCONSCOM -c $MSVSBUILDTARGET'
+    env['MSVSENCODING'] = 'Windows-1252'
+
+    try:
+        version = get_default_visualstudio_version(env)
+        # keep a record of some of the MSVS info so the user can use it.
+        dirs = get_msvs_install_dirs(version)
+        env['MSVS'].update(dirs)
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        # we don't care if we can't do this -- if we can't, it's
+        # because we don't have access to the registry, or because the
+        # tools aren't installed.  In either case, the user will have to
+        # find them on their own.
+        pass
+
+    version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
+    if (version_num < 7.0):
+        env['MSVS']['PROJECTSUFFIX']  = '.dsp'
+        env['MSVS']['SOLUTIONSUFFIX'] = '.dsw'
+    else:
+        env['MSVS']['PROJECTSUFFIX']  = '.vcproj'
+        env['MSVS']['SOLUTIONSUFFIX'] = '.sln'
+
+    env['GET_MSVSPROJECTSUFFIX']  = GetMSVSProjectSuffix
+    env['GET_MSVSSOLUTIONSUFFIX']  = GetMSVSSolutionSuffix
+    env['MSVSPROJECTSUFFIX']  = '${GET_MSVSPROJECTSUFFIX}'
+    env['MSVSSOLUTIONSUFFIX']  = '${GET_MSVSSOLUTIONSUFFIX}'
+    env['SCONS_HOME'] = os.environ.get('SCONS_HOME')
+
+def exists(env):
+    try:
+        v = SCons.Tool.msvs.get_visualstudio_versions()
+    except (SCons.Util.RegError, SCons.Errors.InternalError):
+        pass
+
+    if not v:
+        version_num = 6.0
+        if env.has_key('MSVS_VERSION'):
+            version_num, suite = msvs_parse_version(env['MSVS_VERSION'])
+        if version_num >= 7.0:
+            return env.Detect('devenv')
+        else:
+            return env.Detect('msdev')
+    else:
+        # there's at least one version of MSVS installed.
+        return 1

Added: cs/scons/scons-local-0.96.92/SCons/Tool/mwcc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/mwcc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/mwcc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,199 @@
+"""SCons.Tool.mwcc
+
+Tool-specific initialization for the Metrowerks CodeWarrior compiler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/mwcc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+import os
+import os.path
+import string
+
+
+def set_vars(env):
+    """Set MWCW_VERSION, MWCW_VERSIONS, and some codewarrior environment vars
+
+    MWCW_VERSIONS is set to a list of objects representing installed versions
+
+    MWCW_VERSION  is set to the version object that will be used for building.
+                  MWCW_VERSION can be set to a string during Environment
+                  construction to influence which version is chosen, otherwise
+                  the latest one from MWCW_VERSIONS is used.
+
+    Returns true if at least one version is found, false otherwise
+    """
+    desired = env.get('MWCW_VERSION', '')
+
+    # return right away if the variables are already set
+    if isinstance(desired, MWVersion):
+        return 1
+    elif desired is None:
+        return 0
+
+    versions = find_versions()
+    version = None
+
+    if desired:
+        for v in versions:
+            if str(v) == desired:
+                version = v
+    elif versions:
+        version = versions[-1]
+
+    env['MWCW_VERSIONS'] = versions
+    env['MWCW_VERSION'] = version
+
+    if version is None:
+      return 0
+
+    env.PrependENVPath('PATH', version.clpath)
+    env.PrependENVPath('PATH', version.dllpath)
+    ENV = env['ENV']
+    ENV['CWFolder'] = version.path
+    ENV['LM_LICENSE_FILE'] = version.license
+    plus = lambda x: '+%s' % x
+    ENV['MWCIncludes'] = string.join(map(plus, version.includes), os.pathsep)
+    ENV['MWLibraries'] = string.join(map(plus, version.libs), os.pathsep)
+    return 1
+
+
+def find_versions():
+    """Return a list of MWVersion objects representing installed versions"""
+    versions = []
+
+    ### This function finds CodeWarrior by reading from the registry on
+    ### Windows. Some other method needs to be implemented for other
+    ### platforms, maybe something that calls env.WhereIs('mwcc')
+
+    if SCons.Util.can_read_reg:
+        try:
+            HLM = SCons.Util.HKEY_LOCAL_MACHINE
+            product = 'SOFTWARE\\Metrowerks\\CodeWarrior\\Product Versions'
+            product_key = SCons.Util.RegOpenKeyEx(HLM, product)
+
+            i = 0
+            while 1:
+                name = product + '\\' + SCons.Util.RegEnumKey(product_key, i)
+                name_key = SCons.Util.RegOpenKeyEx(HLM, name)
+
+                try:
+                    version = SCons.Util.RegQueryValueEx(name_key, 'VERSION')
+                    path = SCons.Util.RegQueryValueEx(name_key, 'PATH')
+                    mwv = MWVersion(version[0], path[0], 'Win32-X86')
+                    versions.append(mwv)
+                except SCons.Util.RegError:
+                    pass
+
+                i = i + 1
+
+        except SCons.Util.RegError:
+            pass
+
+    return versions
+
+
+class MWVersion:
+    def __init__(self, version, path, platform):
+        self.version = version
+        self.path = path
+        self.platform = platform
+        self.clpath = os.path.join(path, 'Other Metrowerks Tools',
+                                   'Command Line Tools')
+        self.dllpath = os.path.join(path, 'Bin')
+
+        # The Metrowerks tools don't store any configuration data so they
+        # are totally dumb when it comes to locating standard headers,
+        # libraries, and other files, expecting all the information
+        # to be handed to them in environment variables. The members set
+        # below control what information scons injects into the environment
+
+        ### The paths below give a normal build environment in CodeWarrior for
+        ### Windows, other versions of CodeWarrior might need different paths.
+
+        msl = os.path.join(path, 'MSL')
+        support = os.path.join(path, '%s Support' % platform)
+
+        self.license = os.path.join(path, 'license.dat')
+        self.includes = [msl, support]
+        self.libs = [msl, support]
+
+    def __str__(self):
+        return self.version
+
+
+CSuffixes = ['.c', '.C']
+CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
+
+
+def generate(env):
+    """Add Builders and construction variables for the mwcc to an Environment."""
+
+    set_vars(env)
+
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in CSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
+
+    for suffix in CXXSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.CXXAction)
+        shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
+
+    env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -nolink -o $TARGET $SOURCES'
+
+    env['CC']         = 'mwcc'
+    env['CCCOM']      = '$CC $CCFLAGS $CCCOMFLAGS'
+
+    env['CXX']        = 'mwcc'
+    env['CXXCOM']     = '$CXX $CXXFLAGS $CCCOMFLAGS'
+
+    env['SHCC']       = '$CC'
+    env['SHCCFLAGS']  = '$CCFLAGS'
+    env['SHCCCOM']    = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
+
+    env['SHCXX']       = '$CXX'
+    env['SHCXXFLAGS']  = '$CXXFLAGS'
+    env['SHCXXCOM']    = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
+
+    env['CFILESUFFIX'] = '.c'
+    env['CXXFILESUFFIX'] = '.cpp'
+    env['CPPDEFPREFIX']  = '-D'
+    env['CPPDEFSUFFIX']  = ''
+    env['INCPREFIX']  = '-I'
+    env['INCSUFFIX']  = ''
+
+    #env['PCH'] = ?
+    #env['PCHSTOP'] = ?
+
+
+def exists(env):
+    return set_vars(env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/mwld.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/mwld.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/mwld.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,101 @@
+"""SCons.Tool.mwld
+
+Tool-specific initialization for the Metrowerks CodeWarrior linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/mwld.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool
+import SCons.Tool.mwcc
+
+
+def generate(env):
+    """Add Builders and construction variables for lib to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+    SCons.Tool.createSharedLibBuilder(env)
+    SCons.Tool.createProgBuilder(env)
+
+    env['AR'] = 'mwld'
+    env['ARCOM'] = '$AR $ARFLAGS -library -o $TARGET $SOURCES'
+
+    env['LIBDIRPREFIX'] = '-L'
+    env['LIBDIRSUFFIX'] = ''
+    env['LIBLINKPREFIX'] = '-l'
+    env['LIBLINKSUFFIX'] = '.lib'
+
+    env['LINK'] = 'mwld'
+    env['LINKCOM'] = '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+
+    env['SHLINK'] = '$LINK'
+    env['SHLINKFLAGS'] = '$LINKFLAGS'
+    env['SHLINKCOM']   = shlib_action
+    env['SHLIBEMITTER']= shlib_emitter
+
+
+def exists(env):
+    return mwcc.set_versions(env)
+
+
+def shlib_generator(target, source, env, for_signature):
+    cmd = ['$SHLINK', '$SHLINKFLAGS', '-shared']
+
+    no_import_lib = env.get('no_import_lib', 0)
+    if no_import_lib: cmd.extend('-noimplib')
+
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    if dll: cmd.extend(['-o', dll])
+
+    implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
+    if implib: cmd.extend(['-implib', implib.get_string(for_signature)])
+
+    cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS'])
+
+    return [cmd]
+
+
+def shlib_emitter(target, source, env):
+    dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+    no_import_lib = env.get('no_import_lib', 0)
+
+    if not dll:
+        raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
+
+    if not no_import_lib and \
+       not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'):
+
+        # Append an import library to the list of targets.
+        target.append(env.ReplaceIxes(dll,
+                                      'SHLIBPREFIX', 'SHLIBSUFFIX',
+                                      'LIBPREFIX', 'LIBSUFFIX'))
+
+    return target, source
+
+
+shlib_action = SCons.Action.Action(shlib_generator, generator=1)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/nasm.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/nasm.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/nasm.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,66 @@
+"""SCons.Tool.nasm
+
+Tool-specific initialization for nasm, the famous Netwide Assembler.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/nasm.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+ASSuffixes = ['.s', '.asm', '.ASM']
+ASPPSuffixes = ['.spp', '.SPP']
+if SCons.Util.case_sensitive_suffixes('.s', '.S'):
+    ASPPSuffixes.extend(['.S'])
+else:
+    ASSuffixes.extend(['.S'])
+
+def generate(env):
+    """Add Builders and construction variables for nasm to an Environment."""
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+
+    for suffix in ASSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+
+    for suffix in ASPPSuffixes:
+        static_obj.add_action(suffix, SCons.Defaults.ASPPAction)
+        static_obj.add_emitter(suffix, SCons.Defaults.StaticObjectEmitter)
+
+    env['AS']        = 'nasm'
+    env['ASFLAGS']   = SCons.Util.CLVar('')
+    env['ASPPFLAGS'] = '$ASFLAGS'
+    env['ASCOM']     = '$AS $ASFLAGS -o $TARGET $SOURCES'
+    env['ASPPCOM']   = '$CC $ASPPFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES'
+
+def exists(env):
+    return env.Detect('nasm')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/pdf.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/pdf.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/pdf.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,56 @@
+"""SCons.Tool.pdf
+
+Common PDF Builder definition for various other Tool modules that use it.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/pdf.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Builder
+import SCons.Tool
+
+PDFBuilder = None
+
+def generate(env):
+    try:
+        bld = env['BUILDERS']['PDF']
+    except KeyError:
+        global PDFBuilder
+        if PDFBuilder is None:
+            PDFBuilder = SCons.Builder.Builder(action = {},
+                                               source_scanner = SCons.Tool.LaTeXScanner,
+                                               prefix = '$PDFPREFIX',
+                                               suffix = '$PDFSUFFIX',
+                                               emitter = {})
+        env['BUILDERS']['PDF'] = PDFBuilder
+
+    env['PDFPREFIX'] = ''
+    env['PDFSUFFIX'] = '.pdf'
+
+def exists(env):
+    # This only puts a skeleton Builder in place, so if someone
+    # references this Tool directly, it's always "available."
+    return 1

Added: cs/scons/scons-local-0.96.92/SCons/Tool/pdflatex.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/pdflatex.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/pdflatex.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,74 @@
+"""SCons.Tool.pdflatex
+
+Tool-specific initialization for pdflatex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/pdflatex.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Util
+import SCons.Tool.pdf
+import SCons.Tool.tex
+
+PDFLaTeXAction = None
+
+def PDFLaTeXAuxFunction(target = None, source= None, env=None):
+    SCons.Tool.tex.InternalLaTeXAuxAction( PDFLaTeXAction, target, source, env )
+
+PDFLaTeXAuxAction = None
+
+def generate(env):
+    """Add Builders and construction variables for pdflatex to an Environment."""
+    global PDFLaTeXAction
+    if PDFLaTeXAction is None:
+        PDFLaTeXAction = SCons.Action.Action('$PDFLATEXCOM', '$PDFLATEXCOMSTR')
+
+    global PDFLaTeXAuxAction
+    if PDFLaTeXAuxAction is None:
+        PDFLaTeXAuxAction = SCons.Action.Action(PDFLaTeXAuxFunction,
+                                                strfunction=None)
+
+    import pdf
+    pdf.generate(env)
+
+    bld = env['BUILDERS']['PDF']
+    bld.add_action('.ltx', PDFLaTeXAuxAction)
+    bld.add_action('.latex', PDFLaTeXAuxAction)
+    bld.add_emitter('.ltx', SCons.Tool.tex.tex_emitter)
+    bld.add_emitter('.latex', SCons.Tool.tex.tex_emitter)
+
+    env['PDFLATEX']      = 'pdflatex'
+    env['PDFLATEXFLAGS'] = SCons.Util.CLVar('')
+    env['PDFLATEXCOM']   = '$PDFLATEX $PDFLATEXFLAGS $SOURCE'
+    env['LATEXRETRIES']  = 3
+
+def exists(env):
+    return env.Detect('pdflatex')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/pdftex.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/pdftex.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/pdftex.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,98 @@
+"""SCons.Tool.pdftex
+
+Tool-specific initialization for pdftex.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/pdftex.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Util
+import SCons.Tool.tex
+
+PDFTeXAction = None
+
+# This action might be needed more than once if we are dealing with
+# labels and bibtex.
+PDFLaTeXAction = None
+
+def PDFLaTeXAuxAction(target = None, source= None, env=None):
+    SCons.Tool.tex.InternalLaTeXAuxAction( PDFLaTeXAction, target, source, env )
+
+def PDFTeXLaTeXFunction(target = None, source= None, env=None):
+    """A builder for TeX and LaTeX that scans the source file to
+    decide the "flavor" of the source and then executes the appropriate
+    program."""
+    if SCons.Tool.tex.is_LaTeX(source):
+        PDFLaTeXAuxAction(target,source,env)
+    else:
+        PDFTeXAction(target,source,env)
+    return 0
+
+PDFTeXLaTeXAction = None
+
+def generate(env):
+    """Add Builders and construction variables for pdftex to an Environment."""
+    global PDFTeXAction
+    if PDFTeXAction is None:
+        PDFTeXAction = SCons.Action.Action('$PDFTEXCOM', '$PDFTEXCOMSTR')
+
+    global PDFLaTeXAction
+    if PDFLaTeXAction is None:
+        PDFLaTeXAction = SCons.Action.Action("$PDFLATEXCOM", "$PDFLATEXCOMSTR")
+
+    global PDFTeXLaTeXAction
+    if PDFTeXLaTeXAction is None:
+        PDFTeXLaTeXAction = SCons.Action.Action(PDFTeXLaTeXFunction,
+                                                strfunction=None)
+
+    import pdf
+    pdf.generate(env)
+
+    bld = env['BUILDERS']['PDF']
+    bld.add_action('.tex', PDFTeXLaTeXAction)
+    bld.add_emitter('.tex', SCons.Tool.tex.tex_emitter)
+
+    env['PDFTEX']      = 'pdftex'
+    env['PDFTEXFLAGS'] = SCons.Util.CLVar('')
+    env['PDFTEXCOM']   = '$PDFTEX $PDFTEXFLAGS $SOURCE'
+
+    # Duplicate from latex.py.  If latex.py goes away, then this is still OK.
+    env['PDFLATEX']      = 'pdflatex'
+    env['PDFLATEXFLAGS'] = SCons.Util.CLVar('')
+    env['PDFLATEXCOM']   = '$PDFLATEX $PDFLATEXFLAGS $SOURCES'
+    env['LATEXRETRIES']  = 3
+
+    env['BIBTEX']      = 'bibtex'
+    env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
+    env['BIBTEXCOM']   = '$BIBTEX $BIBTEXFLAGS $SOURCES'
+
+def exists(env):
+    return env.Detect('pdftex')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/qt.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/qt.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/qt.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,333 @@
+
+"""SCons.Tool.qt
+
+Tool-specific initialization for Qt.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/qt.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Scanner
+import SCons.Tool
+import SCons.Util
+
+class ToolQtWarning(SCons.Warnings.Warning):
+    pass
+
+class GeneratedMocFileNotIncluded(ToolQtWarning):
+    pass
+
+class QtdirNotFound(ToolQtWarning):
+    pass
+
+SCons.Warnings.enableWarningClass(ToolQtWarning)
+
+header_extensions = [".h", ".hxx", ".hpp", ".hh"]
+if SCons.Util.case_sensitive_suffixes('.h', '.H'):
+    header_extensions.append('.H')
+cplusplus = __import__('c++', globals(), locals(), [])
+cxx_suffixes = cplusplus.CXXSuffixes
+
+def checkMocIncluded(target, source, env):
+    moc = target[0]
+    cpp = source[0]
+    # looks like cpp.includes is cleared before the build stage :-(
+    # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/
+    path = SCons.Defaults.CScan.path_function(env, moc.cwd)
+    includes = SCons.Defaults.CScan(cpp, env, path)
+    if not moc in includes:
+        SCons.Warnings.warn(
+            GeneratedMocFileNotIncluded,
+            "Generated moc file '%s' is not included by '%s'" %
+            (str(moc), str(cpp)))
+
+def find_file(filename, paths, node_factory):
+    retval = None
+    for dir in paths:
+        node = node_factory(filename, dir)
+        if node.rexists():
+            return node
+    return None
+
+class _Automoc:
+    """
+    Callable class, which works as an emitter for Programs, SharedLibraries and
+    StaticLibraries.
+    """
+
+    def __init__(self, objBuilderName):
+        self.objBuilderName = objBuilderName
+        
+    def __call__(self, target, source, env):
+        """
+        Smart autoscan function. Gets the list of objects for the Program
+        or Lib. Adds objects and builders for the special qt files.
+        """
+        try:
+            if int(env.subst('$QT_AUTOSCAN')) == 0:
+                return target, source
+        except ValueError:
+            pass
+        try:
+            debug = int(env.subst('$QT_DEBUG'))
+        except ValueError:
+            debug = 0
+        
+        # some shortcuts used in the scanner
+        splitext = SCons.Util.splitext
+        objBuilder = getattr(env, self.objBuilderName)
+  
+        # some regular expressions:
+        # Q_OBJECT detection
+        q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') 
+        # cxx and c comment 'eater'
+        #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)')
+        # CW: something must be wrong with the regexp. See also bug #998222
+        #     CURRENTLY THERE IS NO TEST CASE FOR THAT
+        
+        # The following is kind of hacky to get builders working properly (FIXME)
+        objBuilderEnv = objBuilder.env
+        objBuilder.env = env
+        mocBuilderEnv = env.Moc.env
+        env.Moc.env = env
+        
+        # make a deep copy for the result; MocH objects will be appended
+        out_sources = source[:]
+
+        for obj in source:
+            if not obj.has_builder():
+                # binary obj file provided
+                if debug:
+                    print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj)
+                continue
+            cpp = obj.sources[0]
+            if not splitext(str(cpp))[1] in cxx_suffixes:
+                if debug:
+                    print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) 
+                # c or fortran source
+                continue
+            #cpp_contents = comment.sub('', cpp.get_contents())
+            cpp_contents = cpp.get_contents()
+            h=None
+            for h_ext in header_extensions:
+                # try to find the header file in the corresponding source
+                # directory
+                hname = splitext(cpp.name)[0] + h_ext
+                h = find_file(hname, (cpp.get_dir(),), env.File)
+                if h:
+                    if debug:
+                        print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
+                    #h_contents = comment.sub('', h.get_contents())
+                    h_contents = h.get_contents()
+                    break
+            if not h and debug:
+                print "scons: qt: no header for '%s'." % (str(cpp))
+            if h and q_object_search.search(h_contents):
+                # h file with the Q_OBJECT macro found -> add moc_cpp
+                moc_cpp = env.Moc(h)
+                moc_o = objBuilder(moc_cpp)
+                out_sources.append(moc_o)
+                #moc_cpp.target_scanner = SCons.Defaults.CScan
+                if debug:
+                    print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))
+            if cpp and q_object_search.search(cpp_contents):
+                # cpp file with Q_OBJECT macro found -> add moc
+                # (to be included in cpp)
+                moc = env.Moc(cpp)
+                env.Ignore(moc, moc)
+                if debug:
+                    print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
+                #moc.source_scanner = SCons.Defaults.CScan
+        # restore the original env attributes (FIXME)
+        objBuilder.env = objBuilderEnv
+        env.Moc.env = mocBuilderEnv
+
+        return (target, out_sources)
+
+AutomocShared = _Automoc('SharedObject')
+AutomocStatic = _Automoc('StaticObject')
+
+def _detect(env):
+    """Not really safe, but fast method to detect the QT library"""
+    QTDIR = None
+    if not QTDIR:
+        QTDIR = env.get('QTDIR',None)
+    if not QTDIR:
+        QTDIR = os.environ.get('QTDIR',None)
+    if not QTDIR:
+        moc = env.WhereIs('moc')
+        if moc:
+            QTDIR = os.path.dirname(os.path.dirname(moc))
+            SCons.Warnings.warn(
+                QtdirNotFound,
+                "Could not detect qt, using moc executable as a hint (QTDIR=%s)" % QTDIR)
+        else:
+            QTDIR = None
+            SCons.Warnings.warn(
+                QtdirNotFound,
+                "Could not detect qt, using empty QTDIR")
+    return QTDIR
+
+def uicEmitter(target, source, env):
+    adjustixes = SCons.Util.adjustixes
+    bs = SCons.Util.splitext(str(source[0].name))[0]
+    bs = os.path.join(str(target[0].get_dir()),bs)
+    # first target (header) is automatically added by builder
+    if len(target) < 2:
+        # second target is implementation
+        target.append(adjustixes(bs,
+                                 env.subst('$QT_UICIMPLPREFIX'),
+                                 env.subst('$QT_UICIMPLSUFFIX')))
+    if len(target) < 3:
+        # third target is moc file
+        target.append(adjustixes(bs,
+                                 env.subst('$QT_MOCHPREFIX'),
+                                 env.subst('$QT_MOCHSUFFIX')))
+    return target, source
+
+def uicScannerFunc(node, env, path):
+    dir = node.dir
+    lookout = []
+    lookout.extend(env['CPPPATH'])
+    lookout.append(str(node.rfile().dir))
+    includes = re.findall("<include.*?>(.*?)</include>", node.get_contents())
+    result = []
+    for incFile in includes:
+        dep = env.FindFile(incFile,lookout)
+        if dep:
+            result.append(dep)
+    return result
+
+uicScanner = SCons.Scanner.Scanner(uicScannerFunc,
+                                   name = "UicScanner", 
+                                   node_class = SCons.Node.FS.File,
+                                   node_factory = SCons.Node.FS.File,
+                                   recursive = 0)
+
+def generate(env):
+    """Add Builders and construction variables for qt to an Environment."""
+    CLVar = SCons.Util.CLVar
+    Action = SCons.Action.Action
+    Builder = SCons.Builder.Builder
+    splitext = SCons.Util.splitext
+
+    env.SetDefault(QTDIR  = _detect(env),
+                   QT_BINPATH = os.path.join('$QTDIR', 'bin'),
+                   QT_CPPPATH = os.path.join('$QTDIR', 'include'),
+                   QT_LIBPATH = os.path.join('$QTDIR', 'lib'),
+                   QT_MOC = os.path.join('$QT_BINPATH','moc'),
+                   QT_UIC = os.path.join('$QT_BINPATH','uic'),
+                   QT_LIB = 'qt', # may be set to qt-mt
+
+                   QT_AUTOSCAN = 1, # scan for moc'able sources
+
+                   # Some QT specific flags. I don't expect someone wants to
+                   # manipulate those ...
+                   QT_UICIMPLFLAGS = CLVar(''),
+                   QT_UICDECLFLAGS = CLVar(''),
+                   QT_MOCFROMHFLAGS = CLVar(''),
+                   QT_MOCFROMCXXFLAGS = CLVar('-i'),
+
+                   # suffixes/prefixes for the headers / sources to generate
+                   QT_UICDECLPREFIX = '',
+                   QT_UICDECLSUFFIX = '.h',
+                   QT_UICIMPLPREFIX = 'uic_',
+                   QT_UICIMPLSUFFIX = '$CXXFILESUFFIX',
+                   QT_MOCHPREFIX = 'moc_',
+                   QT_MOCHSUFFIX = '$CXXFILESUFFIX',
+                   QT_MOCCXXPREFIX = '',
+                   QT_MOCCXXSUFFIX = '.moc',
+                   QT_UISUFFIX = '.ui',
+
+                   # Commands for the qt support ...
+                   # command to generate header, implementation and moc-file
+                   # from a .ui file
+                   QT_UICCOM = [
+                    CLVar('$QT_UIC $QT_UICDECLFLAGS -o ${TARGETS[0]} $SOURCE'),
+                    CLVar('$QT_UIC $QT_UICIMPLFLAGS -impl ${TARGETS[0].file} '
+                          '-o ${TARGETS[1]} $SOURCE'),
+                    CLVar('$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[2]} ${TARGETS[0]}')],
+                   # command to generate meta object information for a class
+                   # declarated in a header
+                   QT_MOCFROMHCOM = (
+                          '$QT_MOC $QT_MOCFROMHFLAGS -o ${TARGETS[0]} $SOURCE'),
+                   # command to generate meta object information for a class
+                   # declarated in a cpp file
+                   QT_MOCFROMCXXCOM = [
+                    CLVar('$QT_MOC $QT_MOCFROMCXXFLAGS -o ${TARGETS[0]} $SOURCE'),
+                    Action(checkMocIncluded,None)])
+
+    # ... and the corresponding builders
+    uicBld = Builder(action=SCons.Action.Action('$QT_UICCOM', '$QT_UICCOMSTR'),
+                     emitter=uicEmitter,
+                     src_suffix='$QT_UISUFFIX',
+                     suffix='$QT_UICDECLSUFFIX',
+                     prefix='$QT_UICDECLPREFIX',
+                     source_scanner=uicScanner)
+    mocBld = Builder(action={}, prefix={}, suffix={})
+    for h in header_extensions:
+        act = SCons.Action.Action('$QT_MOCFROMHCOM', '$QT_MOCFROMHCOMSTR')
+        mocBld.add_action(h, act)
+        mocBld.prefix[h] = '$QT_MOCHPREFIX'
+        mocBld.suffix[h] = '$QT_MOCHSUFFIX'
+    for cxx in cxx_suffixes:
+        act = SCons.Action.Action('$QT_MOCFROMCXXCOM', '$QT_MOCFROMCXXCOMSTR')
+        mocBld.add_action(cxx, act)
+        mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX'
+        mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX'
+
+    # register the builders 
+    env['BUILDERS']['Uic'] = uicBld
+    env['BUILDERS']['Moc'] = mocBld
+    static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
+    static_obj.src_builder.append('Uic')
+    shared_obj.src_builder.append('Uic')
+
+    # We use the emitters of Program / StaticLibrary / SharedLibrary
+    # to scan for moc'able files
+    # We can't refer to the builders directly, we have to fetch them
+    # as Environment attributes because that sets them up to be called
+    # correctly later by our emitter.
+    env.AppendUnique(PROGEMITTER =[AutomocStatic],
+                     SHLIBEMITTER=[AutomocShared],
+                     LIBEMITTER  =[AutomocStatic],
+                     # Of course, we need to link against the qt libraries
+                     CPPPATH=["$QT_CPPPATH"],
+                     LIBPATH=["$QT_LIBPATH"],
+                     LIBS=['$QT_LIB'])
+
+def exists(env):
+    return _detect(env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/rmic.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/rmic.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/rmic.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,111 @@
+"""SCons.Tool.rmic
+
+Tool-specific initialization for rmic.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/rmic.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import string
+
+import SCons.Action
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Util
+
+def emit_rmic_classes(target, source, env):
+    """Create and return lists of Java RMI stub and skeleton
+    class files to be created from a set of class files.
+    """
+    class_suffix = env.get('JAVACLASSSUFFIX', '.class')
+    classdir = env.get('JAVACLASSDIR')
+
+    if not classdir:
+        try:
+            s = source[0]
+        except IndexError:
+            classdir = '.'
+        else:
+            try:
+                classdir = s.attributes.java_classdir
+            except AttributeError:
+                classdir = '.'
+    classdir = env.Dir(classdir).rdir()
+    if str(classdir) == '.':
+        c_ = None
+    else:
+        c_ = str(classdir) + os.sep
+
+    slist = []
+    for src in source:
+        try:
+            classname = src.attributes.java_classname
+        except AttributeError:
+            classname = str(src)
+            if c_ and classname[:len(c_)] == c_:
+                classname = classname[len(c_):]
+            if class_suffix and classname[:-len(class_suffix)] == class_suffix:
+                classname = classname[-len(class_suffix):]
+        s = src.rfile()
+        s.attributes.java_classdir = classdir
+        s.attributes.java_classname = classname
+        slist.append(s)
+
+    tlist = []
+    for s in source:
+        for suff in ['_Skel', '_Stub']:
+            fname = string.replace(s.attributes.java_classname, '.', os.sep) + \
+                    suff + class_suffix
+            t = target[0].File(fname)
+            t.attributes.java_lookupdir = target[0]
+            tlist.append(t)
+
+    return tlist, source
+
+RMICAction = SCons.Action.Action('$RMICCOM', '$RMICCOMSTR')
+
+RMICBuilder = SCons.Builder.Builder(action = RMICAction,
+                     emitter = emit_rmic_classes,
+                     src_suffix = '$JAVACLASSSUFFIX',
+                     target_factory = SCons.Node.FS.Dir,
+                     source_factory = SCons.Node.FS.File)
+
+def generate(env):
+    """Add Builders and construction variables for rmic to an Environment."""
+    env['BUILDERS']['RMIC'] = RMICBuilder
+
+    env['RMIC']            = 'rmic'
+    env['RMICFLAGS']       = SCons.Util.CLVar('')
+    env['RMICCOM']         = '$RMIC $RMICFLAGS -d ${TARGET.attributes.java_lookupdir} -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}'
+    env['JAVACLASSSUFFIX']  = '.class'
+
+def exists(env):
+    return env.Detect('rmic')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/rpcgen.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/rpcgen.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/rpcgen.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,64 @@
+"""SCons.Tool.rpcgen
+
+Tool-specific initialization for RPCGEN tools.
+
+Three normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/rpcgen.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+from SCons.Builder import Builder
+import SCons.Util
+
+cmd = "cd ${SOURCE.dir} && $RPCGEN -%s $RPCGENFLAGS %s -o ${TARGET.abspath} ${SOURCE.file}"
+
+rpcgen_client   = cmd % ('l', '$RPCGENCLIENTFLAGS')
+rpcgen_header   = cmd % ('h', '$RPCGENHEADERFLAGS')
+rpcgen_service  = cmd % ('m', '$RPCGENSERVICEFLAGS')
+rpcgen_xdr      = cmd % ('c', '$RPCGENXDRFLAGS')
+
+def generate(env):
+    "Add RPCGEN Builders and construction variables for an Environment."
+    
+    client  = Builder(action=rpcgen_client,  suffix='_clnt.c', src_suffix='.x')
+    header  = Builder(action=rpcgen_header,  suffix='.h',      src_suffix='.x')
+    service = Builder(action=rpcgen_service, suffix='_svc.c',  src_suffix='.x')
+    xdr     = Builder(action=rpcgen_xdr,     suffix='_xdr.c',  src_suffix='.x')
+    env.Append(BUILDERS={'RPCGenClient'  : client,
+                         'RPCGenHeader'  : header,
+                         'RPCGenService' : service,
+                         'RPCGenXDR'     : xdr})
+    env['RPCGEN'] = 'rpcgen'
+    env['RPCGENFLAGS'] = SCons.Util.CLVar('')
+    env['RPCGENCLIENTFLAGS'] = SCons.Util.CLVar('')
+    env['RPCGENHEADERFLAGS'] = SCons.Util.CLVar('')
+    env['RPCGENSERVICEFLAGS'] = SCons.Util.CLVar('')
+    env['RPCGENXDRFLAGS'] = SCons.Util.CLVar('')
+
+def exists(env):
+    return env.Detect('rpcgen')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sgiar.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sgiar.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sgiar.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,62 @@
+"""SCons.Tool.sgiar
+
+Tool-specific initialization for SGI ar (library archive).  If CC
+exists, static libraries should be built with it, so the prelinker has
+a chance to resolve C++ template instantiations.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/sgiar.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+    
+    if env.Detect('CC'):
+        env['AR']          = 'CC'
+        env['ARFLAGS']     = SCons.Util.CLVar('-ar')
+        env['ARCOM']       = '$AR $ARFLAGS -o $TARGET $SOURCES'
+    else:
+        env['AR']          = 'ar'
+        env['ARFLAGS']     = SCons.Util.CLVar('r')
+        env['ARCOM']       = '$AR $ARFLAGS $TARGET $SOURCES'
+        
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared')
+    env['SHLINKCOM']   = '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    env['LIBPREFIX']   = 'lib'
+    env['LIBSUFFIX']   = '.a'
+
+def exists(env):
+    return env.Detect('CC') or env.Detect('ar')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sgic++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sgic++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sgic++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,52 @@
+"""SCons.Tool.sgic++
+
+Tool-specific initialization for MIPSpro C++ on SGI.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/sgic++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+def generate(env):
+    """Add Builders and construction variables for SGI MIPS C++ to an Environment."""
+
+    cplusplus.generate(env)
+
+    env['CXX']         = 'CC'
+    env['CXXFLAGS']    = SCons.Util.CLVar('$CCFLAGS -LANG:std')
+    env['SHCXX']       = 'CC'
+    env['SHOBJSUFFIX'] = '.o'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+    
+def exists(env):
+    return env.Detect('CC')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sgicc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sgicc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sgicc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,47 @@
+"""SCons.Tool.sgicc
+
+Tool-specific initialization for MIPSPro cc on SGI.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/sgicc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import cc
+
+def generate(env):
+    """Add Builders and construction variables for gcc to an Environment."""
+    cc.generate(env)
+
+    env['CXX']        = 'CC'
+    env['SHOBJSUFFIX'] = '.o'
+    env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
+
+def exists(env):
+    return env.Detect('cc')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sgilink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sgilink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sgilink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,57 @@
+"""SCons.Tool.sgilink
+
+Tool-specific initialization for the SGI MIPSPro linker on SGI.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/sgilink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import link
+
+linkers = ['CC', 'cc']
+
+def generate(env):
+    """Add Builders and construction variables for MIPSPro to an Environment."""
+    link.generate(env)
+    
+    env['LINK'] = env.Detect(linkers) or 'cc'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared')
+
+    # __RPATH is set to $_RPATH in the platform specification if that
+    # platform supports it.
+    env.Append(LINKFLAGS=['$__RPATH'])
+    env['RPATHPREFIX'] = '-rpath '
+    env['RPATHSUFFIX'] = ''
+    env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}'
+
+def exists(env):
+    return env.Detect(linkers)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sunar.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sunar.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sunar.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,61 @@
+"""engine.SCons.Tool.sunar
+
+Tool-specific initialization for Solaris (Forte) ar (library archive). If CC
+exists, static libraries should be built with it, so that template
+instantians can be resolved.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/sunar.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+def generate(env):
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+    
+    if env.Detect('CC'):
+        env['AR']          = 'CC'
+        env['ARFLAGS']     = SCons.Util.CLVar('-xar')
+        env['ARCOM']       = '$AR $ARFLAGS -o $TARGET $SOURCES'
+    else:
+        env['AR']          = 'ar'
+        env['ARFLAGS']     = SCons.Util.CLVar('r')
+        env['ARCOM']       = '$AR $ARFLAGS $TARGET $SOURCES'
+
+    env['SHLINK']      = '$LINK'
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -G')
+    env['SHLINKCOM']   = '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'
+    env['LIBPREFIX']   = 'lib'
+    env['LIBSUFFIX']   = '.a'
+
+def exists(env):
+    return env.Detect('CC') or env.Detect('ar')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sunc++.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sunc++.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sunc++.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,84 @@
+"""SCons.Tool.sunc++
+
+Tool-specific initialization for C++ on SunOS / Solaris.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/sunc++.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import os.path
+
+cplusplus = __import__('c++', globals(), locals(), [])
+
+# use the package installer tool lslpp to figure out where cppc and what
+# version of it is installed
+def get_cppc(env):
+    cppcPath = env.get('CXX', None)
+    cppcVersion = None
+
+    pkginfo = env.subst('$PKGINFO')
+    pkgchk = env.subst('$PKGCHK')
+
+    for package in ['SPROcpl']:
+        cmd = "%s -l %s 2>/dev/null | grep '^ *VERSION:'" % (pkginfo, package)
+        line = os.popen(cmd).readline()
+        if line:
+            cppcVersion = line.split()[-1]
+            cmd = "%s -l %s 2>/dev/null | grep '^Pathname:.*/bin/CC$' | grep -v '/SC[0-9]*\.[0-9]*/'" % (pkgchk, package)
+            line = os.popen(cmd).readline()
+            cppcPath = os.path.dirname(line.split()[-1])
+            break
+    return (cppcPath, 'CC', 'CC', cppcVersion)
+
+def generate(env):
+    """Add Builders and construction variables for SunPRO C++."""
+    path, cxx, shcxx, version = get_cppc(env)
+    if path:
+        cxx = os.path.join(path, cxx)
+        shcxx = os.path.join(path, shcxx)
+
+    cplusplus.generate(env)
+
+    env['CXX'] = cxx
+    env['SHCXX'] = shcxx
+    env['CXXVERSION'] = version
+    env['SHCXXFLAGS']   = SCons.Util.CLVar('$CXXFLAGS -KPIC')
+    env['SHOBJPREFIX']  = 'so_'
+    env['SHOBJSUFFIX']  = '.o'
+    
+def exists(env):
+    path, cxx, shcxx, version = get_cppc(env)
+    if path and cxx:
+        cppc = os.path.join(path, cxx)
+        if os.path.exists(cppc):
+            return cppc
+    return None

Added: cs/scons/scons-local-0.96.92/SCons/Tool/suncc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/suncc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/suncc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,52 @@
+"""SCons.Tool.suncc
+
+Tool-specific initialization for Sun Solaris (Forte) CC and cc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/suncc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Util
+
+import cc
+
+def generate(env):
+    """
+    Add Builders and construction variables for Forte C and C++ compilers
+    to an Environment.
+    """
+    cc.generate(env)
+
+    env['CXX']          = 'CC'
+    env['SHCCFLAGS']    = SCons.Util.CLVar('$CCFLAGS -KPIC')
+    env['SHOBJPREFIX']  = 'so_'
+    env['SHOBJSUFFIX']  = '.o'
+
+def exists(env):
+    return env.Detect('CC')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/sunlink.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/sunlink.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/sunlink.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,71 @@
+"""SCons.Tool.sunlink
+
+Tool-specific initialization for the Sun Solaris (Forte) linker.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/sunlink.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os
+import os.path
+
+import SCons.Util
+
+import link
+
+ccLinker = None
+
+# search for the acc compiler and linker front end
+
+try:
+    dirs = os.listdir('/opt')
+except (IOError, OSError):
+    # Not being able to read the directory because it doesn't exist
+    # (IOError) or isn't readable (OSError) is okay.
+    dirs = []
+
+for d in dirs:
+    linker = '/opt/' + d + '/bin/CC'
+    if os.path.exists(linker):
+        ccLinker = linker
+        break
+
+def generate(env):
+    """Add Builders and construction variables for Forte to an Environment."""
+    link.generate(env)
+    
+    env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -G')
+
+    env.Append(LINKFLAGS=['$__RPATH'])
+    env['RPATHPREFIX'] = '-R'
+    env['RPATHSUFFIX'] = ''
+    env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}'
+
+def exists(env):
+    return ccLinker

Added: cs/scons/scons-local-0.96.92/SCons/Tool/swig.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/swig.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/swig.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,66 @@
+"""SCons.Tool.swig
+
+Tool-specific initialization for swig.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/swig.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR')
+
+def swigSuffixEmitter(env, source):
+    if '-c++' in SCons.Util.CLVar(env.subst("$SWIGFLAGS")):
+        return '$SWIGCXXFILESUFFIX'
+    else:
+        return '$SWIGCFILESUFFIX'
+
+def generate(env):
+    """Add Builders and construction variables for swig to an Environment."""
+    c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
+
+    c_file.suffix['.i'] = swigSuffixEmitter
+    cxx_file.suffix['.i'] = swigSuffixEmitter
+
+    c_file.add_action('.i', SwigAction)
+    cxx_file.add_action('.i', SwigAction)
+
+    env['SWIG']              = 'swig'
+    env['SWIGFLAGS']         = SCons.Util.CLVar('')
+    env['SWIGCFILESUFFIX']   = '_wrap$CFILESUFFIX'
+    env['SWIGCXXFILESUFFIX'] = '_wrap$CXXFILESUFFIX'
+    env['SWIGCOM']           = '$SWIG $SWIGFLAGS -o $TARGET $SOURCES'
+
+def exists(env):
+    return env.Detect(['swig'])

Added: cs/scons/scons-local-0.96.92/SCons/Tool/tar.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/tar.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/tar.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,67 @@
+"""SCons.Tool.tar
+
+Tool-specific initialization for tar.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/tar.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Action
+import SCons.Builder
+import SCons.Defaults
+import SCons.Node.FS
+import SCons.Util
+
+tars = ['tar', 'gtar']
+
+TarAction = SCons.Action.Action('$TARCOM', '$TARCOMSTR')
+
+TarBuilder = SCons.Builder.Builder(action = TarAction,
+                                   source_factory = SCons.Node.FS.Entry,
+                                   source_scanner = SCons.Defaults.DirScanner,
+                                   suffix = '$TARSUFFIX',
+                                   multi = 1)
+
+
+def generate(env):
+    """Add Builders and construction variables for tar to an Environment."""
+    try:
+        bld = env['BUILDERS']['Tar']
+    except KeyError:
+        bld = TarBuilder
+        env['BUILDERS']['Tar'] = bld
+
+    env['TAR']        = env.Detect(tars) or 'gtar'
+    env['TARFLAGS']   = SCons.Util.CLVar('-c')
+    env['TARCOM']     = '$TAR $TARFLAGS -f $TARGET $SOURCES'
+    env['TARSUFFIX']  = '.tar'
+
+def exists(env):
+    return env.Detect(tars)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/tex.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/tex.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/tex.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,184 @@
+"""SCons.Tool.tex
+
+Tool-specific initialization for TeX.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/tex.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+import re
+import string
+
+import SCons.Action
+import SCons.Node
+import SCons.Node.FS
+import SCons.Util
+
+# An Action sufficient to build any generic tex file.
+TeXAction = None
+
+# An action to build a latex file.  This action might be needed more
+# than once if we are dealing with labels and bibtex.
+LaTeXAction = None
+
+# An action to run BibTeX on a file.
+BibTeXAction = None
+
+# An action to run MakeIndex on a file.
+MakeIndexAction = None
+
+def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None):
+    """A builder for LaTeX files that checks the output in the aux file
+    and decides how many times to use LaTeXAction, and BibTeXAction."""
+
+    basename, ext = SCons.Util.splitext(str(target[0]))
+
+    # Run LaTeX once to generate a new aux file.
+    XXXLaTeXAction(target,source,env)
+
+    # Decide if various things need to be run, or run again.  We check
+    # for the existence of files before opening them--even ones like the
+    # aux file that TeX always creates--to make it possible to write tests
+    # with stubs that don't necessarily generate all of the same files.
+
+    # Now decide if bibtex will need to be run.
+    auxfilename = basename + '.aux'
+    if os.path.exists(auxfilename):
+        content = open(auxfilename, "rb").read()
+        if string.find(content, "bibdata") != -1:
+            bibfile = env.fs.File(basename)
+            BibTeXAction(None,bibfile,env)
+
+    # Now decide if makeindex will need to be run.
+    idxfilename = basename + '.idx'
+    if os.path.exists(idxfilename):
+        idxfile = env.fs.File(basename)
+        # TODO: if ( idxfile has changed) ...
+        MakeIndexAction(None,idxfile,env)
+        LaTeXAction(target,source,env)
+
+    # Now decide if latex needs to be run yet again.
+    logfilename = basename + '.log'
+    for trial in range(int(env.subst('$LATEXRETRIES'))):
+        if not os.path.exists(logfilename):
+            break
+        content = open(logfilename, "rb").read()
+        if not re.search("^LaTeX Warning:.*Rerun",content,re.MULTILINE) and not re.search("^LaTeX Warning:.*undefined references",content,re.MULTILINE):
+            break
+        XXXLaTeXAction(target,source,env)
+    return 0
+
+def LaTeXAuxAction(target = None, source= None, env=None):
+    InternalLaTeXAuxAction( LaTeXAction, target, source, env )
+
+LaTeX_re = re.compile("\\\\document(style|class)")
+
+def is_LaTeX(flist):
+    # Scan a file list to decide if it's TeX- or LaTeX-flavored.
+    for f in flist:
+        content = f.get_contents()
+        if LaTeX_re.search(content):
+            return 1
+    return 0
+
+def TeXLaTeXFunction(target = None, source= None, env=None):
+    """A builder for TeX and LaTeX that scans the source file to
+    decide the "flavor" of the source and then executes the appropriate
+    program."""
+    if is_LaTeX(source):
+        LaTeXAuxAction(target,source,env)
+    else:
+        TeXAction(target,source,env)
+    return 0
+
+def tex_emitter(target, source, env):
+    base = SCons.Util.splitext(str(source[0]))[0]
+    target.append(base + '.aux')
+    target.append(base + '.log')
+    return (target, source)
+
+TeXLaTeXAction = None
+
+def generate(env):
+    """Add Builders and construction variables for TeX to an Environment."""
+
+    # A generic tex file Action, sufficient for all tex files.
+    global TeXAction
+    if TeXAction is None:
+        TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR")
+
+    # An Action to build a latex file.  This might be needed more
+    # than once if we are dealing with labels and bibtex.
+    global LaTeXAction
+    if LaTeXAction is None:
+        LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR")
+
+    # Define an action to run BibTeX on a file.
+    global BibTeXAction
+    if BibTeXAction is None:
+        BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR")
+
+    # Define an action to run MakeIndex on a file.
+    global MakeIndexAction
+    if MakeIndexAction is None:
+        MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXOMSTR")
+
+    global TeXLaTeXAction
+    if TeXLaTeXAction is None:
+        TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction, strfunction=None)
+
+    import dvi
+    dvi.generate(env)
+
+    bld = env['BUILDERS']['DVI']
+    bld.add_action('.tex', TeXLaTeXAction)
+    bld.add_emitter('.tex', tex_emitter)
+
+    env['TEX']      = 'tex'
+    env['TEXFLAGS'] = SCons.Util.CLVar('')
+    env['TEXCOM']   = '$TEX $TEXFLAGS $SOURCE'
+
+    # Duplicate from latex.py.  If latex.py goes away, then this is still OK.
+    env['LATEX']        = 'latex'
+    env['LATEXFLAGS']   = SCons.Util.CLVar('')
+    env['LATEXCOM']     = '$LATEX $LATEXFLAGS $SOURCE'
+    env['LATEXRETRIES'] = 3
+
+    env['BIBTEX']      = 'bibtex'
+    env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
+    env['BIBTEXCOM']   = '$BIBTEX $BIBTEXFLAGS $SOURCE'
+
+    env['MAKEINDEX']      = 'makeindex'
+    env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('')
+    env['MAKEINDEXCOM']   = '$MAKEINDEX $MAKEINDEXFLAGS $SOURCES'
+
+def exists(env):
+    return env.Detect('tex')

Added: cs/scons/scons-local-0.96.92/SCons/Tool/tlib.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/tlib.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/tlib.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,47 @@
+"""SCons.Tool.tlib
+
+XXX
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Tool/tlib.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Tool
+import SCons.Tool.bcc32
+import SCons.Util
+
+def generate(env):
+    SCons.Tool.bcc32.findIt('tlib', env)
+    """Add Builders and construction variables for ar to an Environment."""
+    SCons.Tool.createStaticLibBuilder(env)
+    env['AR']          = 'tlib'
+    env['ARFLAGS']     = SCons.Util.CLVar('')
+    env['ARCOM']       = '$AR $TARGET $ARFLAGS /a $SOURCES'
+    env['LIBPREFIX']   = ''
+    env['LIBSUFFIX']   = '.lib'
+
+def exists(env):
+    return SCons.Tool.bcc32.findIt('tlib', env)

Added: cs/scons/scons-local-0.96.92/SCons/Tool/yacc.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/yacc.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/yacc.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,79 @@
+"""SCons.Tool.yacc
+
+Tool-specific initialization for yacc.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/yacc.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Defaults
+import SCons.Tool
+import SCons.Util
+
+YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR")
+
+def _yaccEmitter(target, source, env, ysuf, hsuf):
+    # If -d is specified on the command line, yacc will emit a .h
+    # or .hpp file as well as a .c or .cpp file, depending on whether
+    # the input file is a .y or .yy, respectively.
+    if len(source) and '-d' in SCons.Util.CLVar(env.subst("$YACCFLAGS")):
+        base, ext = os.path.splitext(SCons.Util.to_String(source[0]))
+        if ext in ysuf:
+            base, ext = os.path.splitext(SCons.Util.to_String(target[0]))
+            target.append(base + env.subst(hsuf))
+    return (target, source)
+
+def yEmitter(target, source, env):
+    return _yaccEmitter(target, source, env, ['.y', '.yacc'], '$YACCHFILESUFFIX')
+
+def yyEmitter(target, source, env):
+    return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX')
+
+def generate(env):
+    """Add Builders and construction variables for yacc to an Environment."""
+    c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
+    
+    c_file.add_action('.y', YaccAction)
+    c_file.add_action('.yacc', YaccAction)
+    cxx_file.add_action('.yy', YaccAction)
+    c_file.add_emitter('.y', yEmitter)
+    c_file.add_emitter('.yacc', yEmitter)
+    cxx_file.add_emitter('.yy', yyEmitter)
+
+    env['YACC']      = env.Detect('bison') or 'yacc'
+    env['YACCFLAGS'] = SCons.Util.CLVar('')
+    env['YACCCOM']   = '$YACC $YACCFLAGS -o $TARGET $SOURCES'
+    env['YACCHFILESUFFIX'] = '.h'
+    env['YACCHXXFILESUFFIX'] = '.hpp'
+
+def exists(env):
+    return env.Detect(['bison', 'yacc'])

Added: cs/scons/scons-local-0.96.92/SCons/Tool/zip.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Tool/zip.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Tool/zip.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,93 @@
+"""SCons.Tool.zip
+
+Tool-specific initialization for zip.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Tool/zip.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import os.path
+
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Util
+
+try:
+    import zipfile
+    internal_zip = 1
+except ImportError:
+    internal_zip = 0
+
+if internal_zip:
+    zipcompression = zipfile.ZIP_DEFLATED
+    def zip(target, source, env):
+        def visit(arg, dirname, names):
+            for name in names:
+                path = os.path.join(dirname, name)
+                if os.path.isfile(path):
+                    arg.write(path)
+        compression = env.get('ZIPCOMPRESSION', 0)
+        zf = zipfile.ZipFile(str(target[0]), 'w', compression)
+        for s in source:
+            if s.isdir():
+                os.path.walk(str(s), visit, zf)
+            else:
+                zf.write(str(s))
+        zf.close()
+else:
+    zipcompression = 0
+    zip = "$ZIP $ZIPFLAGS ${TARGET.abspath} $SOURCES"
+
+
+zipAction = SCons.Action.Action(zip, varlist=['ZIPCOMPRESSION'])
+
+ZipBuilder = SCons.Builder.Builder(action = SCons.Action.Action('$ZIPCOM', '$ZIPCOMSTR'),
+                                   source_factory = SCons.Node.FS.Entry,
+                                   source_scanner = SCons.Defaults.DirScanner,
+                                   suffix = '$ZIPSUFFIX',
+                                   multi = 1)
+
+
+def generate(env):
+    """Add Builders and construction variables for zip to an Environment."""
+    try:
+        bld = env['BUILDERS']['Zip']
+    except KeyError:
+        bld = ZipBuilder
+        env['BUILDERS']['Zip'] = bld
+
+    env['ZIP']        = 'zip'
+    env['ZIPFLAGS']   = SCons.Util.CLVar('')
+    env['ZIPCOM']     = zipAction
+    env['ZIPCOMPRESSION'] =  zipcompression
+    env['ZIPSUFFIX']  = '.zip'
+
+def exists(env):
+    return internal_zip or env.Detect('zip')

Added: cs/scons/scons-local-0.96.92/SCons/Util.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Util.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Util.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,983 @@
+"""SCons.Util
+
+Various utility functions go here.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/Util.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import __builtin__
+import copy
+import os
+import os.path
+import re
+import string
+import sys
+import stat
+import types
+
+from UserDict import UserDict
+from UserList import UserList
+
+# Don't "from types import ..." these because we need to get at the
+# types module later to look for UnicodeType.
+DictType        = types.DictType
+InstanceType    = types.InstanceType
+ListType        = types.ListType
+StringType      = types.StringType
+
+try:
+    from UserString import UserString
+except ImportError:
+    # "Borrowed" from the Python 2.2 UserString module
+    # and modified slightly for use with SCons.
+    class UserString:
+        def __init__(self, seq):
+            if is_String(seq):
+                self.data = seq
+            elif isinstance(seq, UserString):
+                self.data = seq.data[:]
+            else:
+                self.data = str(seq)
+        def __str__(self): return str(self.data)
+        def __repr__(self): return repr(self.data)
+        def __int__(self): return int(self.data)
+        def __long__(self): return long(self.data)
+        def __float__(self): return float(self.data)
+        def __complex__(self): return complex(self.data)
+        def __hash__(self): return hash(self.data)
+
+        def __cmp__(self, string):
+            if isinstance(string, UserString):
+                return cmp(self.data, string.data)
+            else:
+                return cmp(self.data, string)
+        def __contains__(self, char):
+            return char in self.data
+
+        def __len__(self): return len(self.data)
+        def __getitem__(self, index): return self.__class__(self.data[index])
+        def __getslice__(self, start, end):
+            start = max(start, 0); end = max(end, 0)
+            return self.__class__(self.data[start:end])
+
+        def __add__(self, other):
+            if isinstance(other, UserString):
+                return self.__class__(self.data + other.data)
+            elif is_String(other):
+                return self.__class__(self.data + other)
+            else:
+                return self.__class__(self.data + str(other))
+        def __radd__(self, other):
+            if is_String(other):
+                return self.__class__(other + self.data)
+            else:
+                return self.__class__(str(other) + self.data)
+        def __mul__(self, n):
+            return self.__class__(self.data*n)
+        __rmul__ = __mul__
+
+#
+try:
+    __builtin__.zip
+except AttributeError:
+    def zip(*lists):
+        result = []
+        for i in xrange(len(lists[0])):
+            result.append(tuple(map(lambda l, i=i: l[i], lists)))
+        return result
+    __builtin__.zip = zip
+
+_altsep = os.altsep
+if _altsep is None and sys.platform == 'win32':
+    # My ActivePython 2.0.1 doesn't set os.altsep!  What gives?
+    _altsep = '/'
+if _altsep:
+    def rightmost_separator(path, sep, _altsep=_altsep):
+        rfind = string.rfind
+        return max(rfind(path, sep), rfind(path, _altsep))
+else:
+    rightmost_separator = string.rfind
+
+# First two from the Python Cookbook, just for completeness.
+# (Yeah, yeah, YAGNI...)
+def containsAny(str, set):
+    """Check whether sequence str contains ANY of the items in set."""
+    for c in set:
+        if c in str: return 1
+    return 0
+
+def containsAll(str, set):
+    """Check whether sequence str contains ALL of the items in set."""
+    for c in set:
+        if c not in str: return 0
+    return 1
+
+def containsOnly(str, set):
+    """Check whether sequence str contains ONLY items in set."""
+    for c in str:
+        if c not in set: return 0
+    return 1
+
+def splitext(path):
+    "Same as os.path.splitext() but faster."
+    sep = rightmost_separator(path, os.sep)
+    dot = string.rfind(path, '.')
+    # An ext is only real if it has at least one non-digit char
+    if dot > sep and not containsOnly(path[dot:], "0123456789."):
+        return path[:dot],path[dot:]
+    else:
+        return path,""
+
+def updrive(path):
+    """
+    Make the drive letter (if any) upper case.
+    This is useful because Windows is inconsitent on the case
+    of the drive letter, which can cause inconsistencies when
+    calculating command signatures.
+    """
+    drive, rest = os.path.splitdrive(path)
+    if drive:
+        path = string.upper(drive) + rest
+    return path
+
+#
+# Generic convert-to-string functions that abstract away whether or
+# not the Python we're executing has Unicode support.  The wrapper
+# to_String_for_signature() will use a for_signature() method if the
+# specified object has one.
+#
+if hasattr(types, 'UnicodeType'):
+    UnicodeType = types.UnicodeType
+    def to_String(s):
+        if isinstance(s, UserString):
+            t = type(s.data)
+        else:
+            t = type(s)
+        if t is UnicodeType:
+            return unicode(s)
+        else:
+            return str(s)
+else:
+    to_String = str
+
+def to_String_for_signature(obj):
+    try:
+        f = obj.for_signature
+    except AttributeError:
+        return to_String(obj)
+    else:
+        return f()
+
+class CallableComposite(UserList):
+    """A simple composite callable class that, when called, will invoke all
+    of its contained callables with the same arguments."""
+    def __call__(self, *args, **kwargs):
+        retvals = map(lambda x, args=args, kwargs=kwargs: apply(x,
+                                                                args,
+                                                                kwargs),
+                      self.data)
+        if self.data and (len(self.data) == len(filter(callable, retvals))):
+            return self.__class__(retvals)
+        return NodeList(retvals)
+
+class NodeList(UserList):
+    """This class is almost exactly like a regular list of Nodes
+    (actually it can hold any object), with one important difference.
+    If you try to get an attribute from this list, it will return that
+    attribute from every item in the list.  For example:
+
+    >>> someList = NodeList([ '  foo  ', '  bar  ' ])
+    >>> someList.strip()
+    [ 'foo', 'bar' ]
+    """
+    def __nonzero__(self):
+        return len(self.data) != 0
+
+    def __str__(self):
+        return string.join(map(str, self.data))
+
+    def __getattr__(self, name):
+        if not self.data:
+            # If there is nothing in the list, then we have no attributes to
+            # pass through, so raise AttributeError for everything.
+            raise AttributeError, "NodeList has no attribute: %s" % name
+
+        # Return a list of the attribute, gotten from every element
+        # in the list
+        attrList = map(lambda x, n=name: getattr(x, n), self.data)
+
+        # Special case.  If the attribute is callable, we do not want
+        # to return a list of callables.  Rather, we want to return a
+        # single callable that, when called, will invoke the function on
+        # all elements of this list.
+        if self.data and (len(self.data) == len(filter(callable, attrList))):
+            return CallableComposite(attrList)
+        return self.__class__(attrList)
+
+_valid_var = re.compile(r'[_a-zA-Z]\w*$')
+_get_env_var = re.compile(r'^\$([_a-zA-Z]\w*|{[_a-zA-Z]\w*})$')
+
+def is_valid_construction_var(varstr):
+    """Return if the specified string is a legitimate construction
+    variable.
+    """
+    return _valid_var.match(varstr)
+
+def get_environment_var(varstr):
+    """Given a string, first determine if it looks like a reference
+    to a single environment variable, like "$FOO" or "${FOO}".
+    If so, return that variable with no decorations ("FOO").
+    If not, return None."""
+    mo=_get_env_var.match(to_String(varstr))
+    if mo:
+        var = mo.group(1)
+        if var[0] == '{':
+            return var[1:-1]
+        else:
+            return var
+    else:
+        return None
+
+class DisplayEngine:
+    def __init__(self):
+        self.__call__ = self.print_it
+
+    def print_it(self, text, append_newline=1):
+        if append_newline: text = text + '\n'
+        sys.stdout.write(text)
+
+    def dont_print(self, text, append_newline=1):
+        pass
+
+    def set_mode(self, mode):
+        if mode:
+            self.__call__ = self.print_it
+        else:
+            self.__call__ = self.dont_print
+
+def render_tree(root, child_func, prune=0, margin=[0], visited={}):
+    """
+    Render a tree of nodes into an ASCII tree view.
+    root - the root node of the tree
+    child_func - the function called to get the children of a node
+    prune - don't visit the same node twice
+    margin - the format of the left margin to use for children of root.
+       1 results in a pipe, and 0 results in no pipe.
+    visited - a dictionary of visited nodes in the current branch if not prune,
+       or in the whole tree if prune.
+    """
+
+    rname = str(root)
+
+    if visited.has_key(rname):
+        return ""
+
+    children = child_func(root)
+    retval = ""
+    for pipe in margin[:-1]:
+        if pipe:
+            retval = retval + "| "
+        else:
+            retval = retval + "  "
+
+    retval = retval + "+-" + rname + "\n"
+    if not prune:
+        visited = copy.copy(visited)
+    visited[rname] = 1
+
+    for i in range(len(children)):
+        margin.append(i<len(children)-1)
+        retval = retval + render_tree(children[i], child_func, prune, margin, visited
+)
+        margin.pop()
+
+    return retval
+
+IDX = lambda N: N and 1 or 0
+
+def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):
+    """
+    Print a tree of nodes.  This is like render_tree, except it prints
+    lines directly instead of creating a string representation in memory,
+    so that huge trees can be printed.
+
+    root - the root node of the tree
+    child_func - the function called to get the children of a node
+    prune - don't visit the same node twice
+    showtags - print status information to the left of each node line
+    margin - the format of the left margin to use for children of root.
+       1 results in a pipe, and 0 results in no pipe.
+    visited - a dictionary of visited nodes in the current branch if not prune,
+       or in the whole tree if prune.
+    """
+
+    rname = str(root)
+
+    if visited.has_key(rname):
+        return
+
+    if showtags:
+
+        if showtags == 2:
+            print ' E        = exists'
+            print '  R       = exists in repository only'
+            print '   b      = implicit builder'
+            print '   B      = explicit builder'
+            print '    S     = side effect'
+            print '     P    = precious'
+            print '      A   = always build'
+            print '       C  = current'
+            print '        N = no clean'
+            print ''
+
+        tags = ['[']
+        tags.append(' E'[IDX(root.exists())])
+        tags.append(' R'[IDX(root.rexists() and not root.exists())])
+        tags.append(' BbB'[[0,1][IDX(root.has_explicit_builder())] +
+                           [0,2][IDX(root.has_builder())]])
+        tags.append(' S'[IDX(root.side_effect)])
+        tags.append(' P'[IDX(root.precious)])
+        tags.append(' A'[IDX(root.always_build)])
+        tags.append(' C'[IDX(root.current())])
+        tags.append(' N'[IDX(root.noclean)])
+        tags.append(']')
+
+    else:
+        tags = []
+
+    def MMM(m):
+        return ["  ","| "][m]
+    margins = map(MMM, margin[:-1])
+
+    print string.join(tags + margins + ['+-', rname], '')
+
+    if prune:
+        visited[rname] = 1
+
+    children = child_func(root)
+    if children:
+        margin.append(1)
+        map(lambda C, cf=child_func, p=prune, i=IDX(showtags), m=margin, v=visited:
+                   print_tree(C, cf, p, i, m, v),
+            children[:-1])
+        margin[-1] = 0
+        print_tree(children[-1], child_func, prune, IDX(showtags), margin, visited)
+        margin.pop()
+
+
+
+# Functions for deciding if things are like various types, mainly to
+# handle UserDict, UserList and UserString like their underlying types.
+#
+# Yes, all of this manual testing breaks polymorphism, and the real
+# Pythonic way to do all of this would be to just try it and handle the
+# exception, but handling the exception when it's not the right type is
+# too slow.
+#
+# The actual implementations here have been selected after timings
+# coded up in in bench/is_types.py (from the SCons source tree, see the
+# scons-src distribution).  Key results from those timings:
+#
+#   --  Storing the type of the object in a variable (t = type(obj))
+#       slows down the case where it's a native type and the first
+#       comparison will match, but nicely speeds up the case where
+#       it's a different native type.  Since that's going to be common,
+#       it's a good tradeoff.
+#
+#   --  The data show that calling isinstance() on an object that's
+#       a native type (dict, list or string) is expensive enough that
+#       checking up front for whether the object is of type InstanceType
+#       is a pretty big win, even though it does slow down the case
+#       where it really *is* an object instance a little bit.
+
+def is_Dict(obj):
+    t = type(obj)
+    return t is DictType or \
+           (t is InstanceType and isinstance(obj, UserDict))
+
+def is_List(obj):
+    t = type(obj)
+    return t is ListType \
+        or (t is InstanceType and isinstance(obj, UserList))
+
+if hasattr(types, 'UnicodeType'):
+    def is_String(obj):
+        t = type(obj)
+        return t is StringType \
+            or t is UnicodeType \
+            or (t is InstanceType and isinstance(obj, UserString))
+else:
+    def is_String(obj):
+        t = type(obj)
+        return t is StringType \
+            or (t is InstanceType and isinstance(obj, UserString))
+
+
+
+def is_Scalar(e):
+    return is_String(e) or not is_List(e)
+
+def flatten(sequence, scalarp=is_Scalar, result=None):
+    if result is None:
+        result = []
+    for item in sequence:
+        if scalarp(item):
+            result.append(item)
+        else:
+            flatten(item, scalarp, result)
+    return result
+
+class Proxy:
+    """A simple generic Proxy class, forwarding all calls to
+    subject.  So, for the benefit of the python newbie, what does
+    this really mean?  Well, it means that you can take an object, let's
+    call it 'objA', and wrap it in this Proxy class, with a statement
+    like this
+
+                 proxyObj = Proxy(objA),
+
+    Then, if in the future, you do something like this
+
+                 x = proxyObj.var1,
+
+    since Proxy does not have a 'var1' attribute (but presumably objA does),
+    the request actually is equivalent to saying
+
+                 x = objA.var1
+
+    Inherit from this class to create a Proxy."""
+
+    def __init__(self, subject):
+        """Wrap an object as a Proxy object"""
+        self.__subject = subject
+
+    def __getattr__(self, name):
+        """Retrieve an attribute from the wrapped object.  If the named
+           attribute doesn't exist, AttributeError is raised"""
+        return getattr(self.__subject, name)
+
+    def get(self):
+        """Retrieve the entire wrapped object"""
+        return self.__subject
+
+    def __cmp__(self, other):
+        if issubclass(other.__class__, self.__subject.__class__):
+            return cmp(self.__subject, other)
+        return cmp(self.__dict__, other.__dict__)
+
+# attempt to load the windows registry module:
+can_read_reg = 0
+try:
+    import _winreg
+
+    can_read_reg = 1
+    hkey_mod = _winreg
+
+    RegOpenKeyEx = _winreg.OpenKeyEx
+    RegEnumKey = _winreg.EnumKey
+    RegEnumValue = _winreg.EnumValue
+    RegQueryValueEx = _winreg.QueryValueEx
+    RegError = _winreg.error
+
+except ImportError:
+    try:
+        import win32api
+        import win32con
+        can_read_reg = 1
+        hkey_mod = win32con
+
+        RegOpenKeyEx = win32api.RegOpenKeyEx
+        RegEnumKey = win32api.RegEnumKey
+        RegEnumValue = win32api.RegEnumValue
+        RegQueryValueEx = win32api.RegQueryValueEx
+        RegError = win32api.error
+
+    except ImportError:
+        class _NoError(Exception):
+            pass
+        RegError = _NoError
+
+if can_read_reg:
+    HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT
+    HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
+    HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
+    HKEY_USERS = hkey_mod.HKEY_USERS
+
+    def RegGetValue(root, key):
+        """This utility function returns a value in the registry
+        without having to open the key first.  Only available on
+        Windows platforms with a version of Python that can read the
+        registry.  Returns the same thing as
+        SCons.Util.RegQueryValueEx, except you just specify the entire
+        path to the value, and don't have to bother opening the key
+        first.  So:
+
+        Instead of:
+          k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
+                r'SOFTWARE\Microsoft\Windows\CurrentVersion')
+          out = SCons.Util.RegQueryValueEx(k,
+                'ProgramFilesDir')
+
+        You can write:
+          out = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE,
+                r'SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir')
+        """
+        # I would use os.path.split here, but it's not a filesystem
+        # path...
+        p = key.rfind('\\') + 1
+        keyp = key[:p]
+        val = key[p:]
+        k = RegOpenKeyEx(root, keyp)
+        return RegQueryValueEx(k,val)
+
+if sys.platform == 'win32':
+
+    def WhereIs(file, path=None, pathext=None, reject=[]):
+        if path is None:
+            try:
+                path = os.environ['PATH']
+            except KeyError:
+                return None
+        if is_String(path):
+            path = string.split(path, os.pathsep)
+        if pathext is None:
+            try:
+                pathext = os.environ['PATHEXT']
+            except KeyError:
+                pathext = '.COM;.EXE;.BAT;.CMD'
+        if is_String(pathext):
+            pathext = string.split(pathext, os.pathsep)
+        for ext in pathext:
+            if string.lower(ext) == string.lower(file[-len(ext):]):
+                pathext = ['']
+                break
+        if not is_List(reject):
+            reject = [reject]
+        for dir in path:
+            f = os.path.join(dir, file)
+            for ext in pathext:
+                fext = f + ext
+                if os.path.isfile(fext):
+                    try:
+                        reject.index(fext)
+                    except ValueError:
+                        return os.path.normpath(fext)
+                    continue
+        return None
+
+elif os.name == 'os2':
+
+    def WhereIs(file, path=None, pathext=None, reject=[]):
+        if path is None:
+            try:
+                path = os.environ['PATH']
+            except KeyError:
+                return None
+        if is_String(path):
+            path = string.split(path, os.pathsep)
+        if pathext is None:
+            pathext = ['.exe', '.cmd']
+        for ext in pathext:
+            if string.lower(ext) == string.lower(file[-len(ext):]):
+                pathext = ['']
+                break
+        if not is_List(reject):
+            reject = [reject]
+        for dir in path:
+            f = os.path.join(dir, file)
+            for ext in pathext:
+                fext = f + ext
+                if os.path.isfile(fext):
+                    try:
+                        reject.index(fext)
+                    except ValueError:
+                        return os.path.normpath(fext)
+                    continue
+        return None
+
+else:
+
+    def WhereIs(file, path=None, pathext=None, reject=[]):
+        if path is None:
+            try:
+                path = os.environ['PATH']
+            except KeyError:
+                return None
+        if is_String(path):
+            path = string.split(path, os.pathsep)
+        if not is_List(reject):
+            reject = [reject]
+        for d in path:
+            f = os.path.join(d, file)
+            if os.path.isfile(f):
+                try:
+                    st = os.stat(f)
+                except OSError:
+                    # os.stat() raises OSError, not IOError if the file
+                    # doesn't exist, so in this case we let IOError get
+                    # raised so as to not mask possibly serious disk or
+                    # network issues.
+                    continue
+                if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
+                    try:
+                        reject.index(f)
+                    except ValueError:
+                        return os.path.normpath(f)
+                    continue
+        return None
+
+def PrependPath(oldpath, newpath, sep = os.pathsep):
+    """This prepends newpath elements to the given oldpath.  Will only
+    add any particular path once (leaving the first one it encounters
+    and ignoring the rest, to preserve path order), and will
+    os.path.normpath and os.path.normcase all paths to help assure
+    this.  This can also handle the case where the given old path
+    variable is a list instead of a string, in which case a list will
+    be returned instead of a string.
+
+    Example:
+      Old Path: "/foo/bar:/foo"
+      New Path: "/biz/boom:/foo"
+      Result:   "/biz/boom:/foo:/foo/bar"
+    """
+
+    orig = oldpath
+    is_list = 1
+    paths = orig
+    if not is_List(orig):
+        paths = string.split(paths, sep)
+        is_list = 0
+
+    if is_List(newpath):
+        newpaths = newpath
+    else:
+        newpaths = string.split(newpath, sep)
+
+    newpaths = newpaths + paths # prepend new paths
+
+    normpaths = []
+    paths = []
+    # now we add them only if they are unique
+    for path in newpaths:
+        normpath = os.path.normpath(os.path.normcase(path))
+        if path and not normpath in normpaths:
+            paths.append(path)
+            normpaths.append(normpath)
+
+    if is_list:
+        return paths
+    else:
+        return string.join(paths, sep)
+
+def AppendPath(oldpath, newpath, sep = os.pathsep):
+    """This appends new path elements to the given old path.  Will
+    only add any particular path once (leaving the last one it
+    encounters and ignoring the rest, to preserve path order), and
+    will os.path.normpath and os.path.normcase all paths to help
+    assure this.  This can also handle the case where the given old
+    path variable is a list instead of a string, in which case a list
+    will be returned instead of a string.
+
+    Example:
+      Old Path: "/foo/bar:/foo"
+      New Path: "/biz/boom:/foo"
+      Result:   "/foo/bar:/biz/boom:/foo"
+    """
+
+    orig = oldpath
+    is_list = 1
+    paths = orig
+    if not is_List(orig):
+        paths = string.split(paths, sep)
+        is_list = 0
+
+    if is_List(newpath):
+        newpaths = newpath
+    else:
+        newpaths = string.split(newpath, sep)
+
+    newpaths = paths + newpaths # append new paths
+    newpaths.reverse()
+
+    normpaths = []
+    paths = []
+    # now we add them only of they are unique
+    for path in newpaths:
+        normpath = os.path.normpath(os.path.normcase(path))
+        if path and not normpath in normpaths:
+            paths.append(path)
+            normpaths.append(normpath)
+
+    paths.reverse()
+
+    if is_list:
+        return paths
+    else:
+        return string.join(paths, sep)
+
+if sys.platform == 'cygwin':
+    def get_native_path(path):
+        """Transforms an absolute path into a native path for the system.  In
+        Cygwin, this converts from a Cygwin path to a Windows one."""
+        return string.replace(os.popen('cygpath -w ' + path).read(), '\n', '')
+else:
+    def get_native_path(path):
+        """Transforms an absolute path into a native path for the system.
+        Non-Cygwin version, just leave the path alone."""
+        return path
+
+display = DisplayEngine()
+
+def Split(arg):
+    if is_List(arg):
+        return arg
+    elif is_String(arg):
+        return string.split(arg)
+    else:
+        return [arg]
+
+class CLVar(UserList):
+    """A class for command-line construction variables.
+
+    This is a list that uses Split() to split an initial string along
+    white-space arguments, and similarly to split any strings that get
+    added.  This allows us to Do the Right Thing with Append() and
+    Prepend() (as well as straight Python foo = env['VAR'] + 'arg1
+    arg2') regardless of whether a user adds a list or a string to a
+    command-line construction variable.
+    """
+    def __init__(self, seq = []):
+        UserList.__init__(self, Split(seq))
+    def __coerce__(self, other):
+        return (self, CLVar(other))
+    def __str__(self):
+        return string.join(self.data)
+
+# A dictionary that preserves the order in which items are added.
+# Submitted by David Benjamin to ActiveState's Python Cookbook web site:
+#     http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
+# Including fixes/enhancements from the follow-on discussions.
+class OrderedDict(UserDict):
+    def __init__(self, dict = None):
+        self._keys = []
+        UserDict.__init__(self, dict)
+
+    def __delitem__(self, key):
+        UserDict.__delitem__(self, key)
+        self._keys.remove(key)
+
+    def __setitem__(self, key, item):
+        UserDict.__setitem__(self, key, item)
+        if key not in self._keys: self._keys.append(key)
+
+    def clear(self):
+        UserDict.clear(self)
+        self._keys = []
+
+    def copy(self):
+        dict = OrderedDict()
+        dict.update(self)
+        return dict
+
+    def items(self):
+        return zip(self._keys, self.values())
+
+    def keys(self):
+        return self._keys[:]
+
+    def popitem(self):
+        try:
+            key = self._keys[-1]
+        except IndexError:
+            raise KeyError('dictionary is empty')
+
+        val = self[key]
+        del self[key]
+
+        return (key, val)
+
+    def setdefault(self, key, failobj = None):
+        UserDict.setdefault(self, key, failobj)
+        if key not in self._keys: self._keys.append(key)
+
+    def update(self, dict):
+        for (key, val) in dict.items():
+            self.__setitem__(key, val)
+
+    def values(self):
+        return map(self.get, self._keys)
+
+class Selector(OrderedDict):
+    """A callable ordered dictionary that maps file suffixes to
+    dictionary values.  We preserve the order in which items are added
+    so that get_suffix() calls always return the first suffix added."""
+    def __call__(self, env, source):
+        try:
+            ext = splitext(str(source[0]))[1]
+        except IndexError:
+            ext = ""
+        try:
+            return self[ext]
+        except KeyError:
+            # Try to perform Environment substitution on the keys of
+            # the dictionary before giving up.
+            s_dict = {}
+            for (k,v) in self.items():
+                if not k is None:
+                    s_k = env.subst(k)
+                    if s_dict.has_key(s_k):
+                        # We only raise an error when variables point
+                        # to the same suffix.  If one suffix is literal
+                        # and a variable suffix contains this literal,
+                        # the literal wins and we don't raise an error.
+                        raise KeyError, (s_dict[s_k][0], k, s_k)
+                    s_dict[s_k] = (k,v)
+            try:
+                return s_dict[ext][1]
+            except KeyError:
+                try:
+                    return self[None]
+                except KeyError:
+                    return None
+
+
+if sys.platform == 'cygwin':
+    # On Cygwin, os.path.normcase() lies, so just report back the
+    # fact that the underlying Windows OS is case-insensitive.
+    def case_sensitive_suffixes(s1, s2):
+        return 0
+else:
+    def case_sensitive_suffixes(s1, s2):
+        return (os.path.normcase(s1) != os.path.normcase(s2))
+
+def adjustixes(fname, pre, suf):
+    if pre:
+        path, fn = os.path.split(os.path.normpath(fname))
+        if fn[:len(pre)] != pre:
+            fname = os.path.join(path, pre + fn)
+    # Only append a suffix if the file does not have one.
+    if suf and not splitext(fname)[1] and fname[-len(suf):] != suf:
+            fname = fname + suf
+    return fname
+
+
+def unique(s):
+    """Return a list of the elements in s, but without duplicates.
+
+    For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
+    unique("abcabc") some permutation of ["a", "b", "c"], and
+    unique(([1, 2], [2, 3], [1, 2])) some permutation of
+    [[2, 3], [1, 2]].
+
+    For best speed, all sequence elements should be hashable.  Then
+    unique() will usually work in linear time.
+
+    If not possible, the sequence elements should enjoy a total
+    ordering, and if list(s).sort() doesn't raise TypeError it's
+    assumed that they do enjoy a total ordering.  Then unique() will
+    usually work in O(N*log2(N)) time.
+
+    If that's not possible either, the sequence elements must support
+    equality-testing.  Then unique() will usually work in quadratic
+    time.
+    """
+
+    n = len(s)
+    if n == 0:
+        return []
+
+    # Try using a dict first, as that's the fastest and will usually
+    # work.  If it doesn't work, it will usually fail quickly, so it
+    # usually doesn't cost much to *try* it.  It requires that all the
+    # sequence elements be hashable, and support equality comparison.
+    u = {}
+    try:
+        for x in s:
+            u[x] = 1
+    except TypeError:
+        del u  # move on to the next method
+    else:
+        return u.keys()
+
+    # We can't hash all the elements.  Second fastest is to sort,
+    # which brings the equal elements together; then duplicates are
+    # easy to weed out in a single pass.
+    # NOTE:  Python's list.sort() was designed to be efficient in the
+    # presence of many duplicate elements.  This isn't true of all
+    # sort functions in all languages or libraries, so this approach
+    # is more effective in Python than it may be elsewhere.
+    try:
+        t = list(s)
+        t.sort()
+    except TypeError:
+        del t  # move on to the next method
+    else:
+        assert n > 0
+        last = t[0]
+        lasti = i = 1
+        while i < n:
+            if t[i] != last:
+                t[lasti] = last = t[i]
+                lasti = lasti + 1
+            i = i + 1
+        return t[:lasti]
+
+    # Brute force is all that's left.
+    u = []
+    for x in s:
+        if x not in u:
+            u.append(x)
+    return u
+
+# Much of the logic here was originally based on recipe 4.9 from the
+# Python CookBook, but we had to dumb it way down for Python 1.5.2.
+class LogicalLines:
+
+    def __init__(self, fileobj):
+        self.fileobj = fileobj
+
+    def readline(self):
+        result = []
+        while 1:
+            line = self.fileobj.readline()
+            if not line:
+                break
+            if line[-2:] == '\\\n':
+                result.append(line[:-2])
+            else:
+                result.append(line)
+                break
+        return string.join(result, '')
+
+    def readlines(self):
+        result = []
+        while 1:
+            line = self.readline()
+            if not line:
+                break
+            result.append(line)
+        return result

Added: cs/scons/scons-local-0.96.92/SCons/Warnings.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/Warnings.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/Warnings.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+"""SCons.Warnings
+
+This file implements the warnings framework for SCons.
+
+"""
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Warnings.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+import SCons.Errors
+
+class Warning(SCons.Errors.UserError):
+    pass
+
+
+
+class CacheWriteErrorWarning(Warning):
+    pass
+
+class CorruptSConsignWarning(Warning):
+    pass
+
+class DependencyWarning(Warning):
+    pass
+
+class DeprecatedWarning(Warning):
+    pass
+
+class DuplicateEnvironmentWarning(Warning):
+    pass
+
+class MissingSConscriptWarning(Warning):
+    pass
+
+class NoParallelSupportWarning(Warning):
+    pass
+
+class ReservedVariableWarning(Warning):
+    pass
+
+class MisleadingKeywordsWarning(Warning):
+    pass
+
+_warningAsException = 0
+
+# The below is a list of 2-tuples.  The first element is a class object.
+# The second element is true if that class is enabled, false if it is disabled.
+_enabled = []
+
+_warningOut = None
+
+def suppressWarningClass(clazz):
+    """Suppresses all warnings that are of type clazz or
+    derived from clazz."""
+    _enabled.insert(0, (clazz, 0))
+    
+def enableWarningClass(clazz):
+    """Suppresses all warnings that are of type clazz or
+    derived from clazz."""
+    _enabled.insert(0, (clazz, 1))
+
+def warningAsException(flag=1):
+    """Turn warnings into exceptions.  Returns the old value of the flag."""
+    global _warningAsException
+    old = _warningAsException
+    _warningAsException = flag
+    return old
+
+def warn(clazz, *args):
+    global _enabled, _warningAsException, _warningOut
+
+    warning = clazz(args)
+    for clazz, flag in _enabled:
+        if isinstance(warning, clazz):
+            if flag:
+                if _warningAsException:
+                    raise warning
+            
+                if _warningOut:
+                    _warningOut(warning)
+            break

Added: cs/scons/scons-local-0.96.92/SCons/__init__.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/__init__.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/__init__.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,42 @@
+"""SCons
+
+The main package for the SCons software construction utility.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/engine/SCons/__init__.py 0.96.92.D002 2006/04/11 07:39:43 knight"
+
+__version__ = "0.96.92"
+
+__build__ = "D002"
+
+__buildsys__ = "roxbury"
+
+__date__ = "2006/04/11 07:39:43"
+
+__developer__ = "knight"
+
+import SCons.Memoize

Added: cs/scons/scons-local-0.96.92/SCons/dblite.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/dblite.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/dblite.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,204 @@
+# dblite.py module contributed by Ralf W. Grosse-Kunstleve.
+# Extended for Unicode by Steven Knight.
+
+import cPickle
+import time
+import shutil
+import os
+import os.path
+import types
+import __builtin__
+
+_open = __builtin__.open # avoid name clash
+
+keep_all_files = 00000
+ignore_corrupt_dbfiles = 0
+
+def corruption_warning(filename):
+    print "Warning: Discarding corrupt database:", filename
+
+if hasattr(types, 'UnicodeType'):
+    def is_string(s):
+        t = type(s)
+        return t is types.StringType or t is types.UnicodeType
+else:
+    def is_string(s):
+        return type(s) is types.StringType
+
+try:
+    unicode('a')
+except NameError:
+    def unicode(s): return s
+
+dblite_suffix = '.dblite'
+tmp_suffix = '.tmp'
+
+class dblite:
+
+  def __init__(self, file_base_name, flag, mode):
+    assert flag in (None, "r", "w", "c", "n")
+    if (flag is None): flag = "r"
+    base, ext = os.path.splitext(file_base_name)
+    if ext == dblite_suffix:
+      # There's already a suffix on the file name, don't add one.
+      self._file_name = file_base_name
+      self._tmp_name = base + tmp_suffix
+    else:
+      self._file_name = file_base_name + dblite_suffix
+      self._tmp_name = file_base_name + tmp_suffix
+    self._flag = flag
+    self._mode = mode
+    self._dict = {}
+    self._needs_sync = 00000
+    if (self._flag == "n"):
+      _open(self._file_name, "wb", self._mode)
+    else:
+      try:
+        f = _open(self._file_name, "rb")
+      except IOError, e:
+        if (self._flag != "c"):
+          raise e
+        _open(self._file_name, "wb", self._mode)
+      else:
+        p = f.read()
+        if (len(p) > 0):
+          try:
+            self._dict = cPickle.loads(p)
+          except (cPickle.UnpicklingError, EOFError):
+            if (ignore_corrupt_dbfiles == 0): raise
+            if (ignore_corrupt_dbfiles == 1):
+              corruption_warning(self._file_name)
+
+  def __del__(self):
+    if (self._needs_sync):
+      self.sync()
+
+  def sync(self):
+    self._check_writable()
+    f = _open(self._tmp_name, "wb", self._mode)
+    cPickle.dump(self._dict, f, 1)
+    f.close()
+    # Windows doesn't allow renaming if the file exists, so unlink
+    # it first, chmod'ing it to make sure we can do so.  On UNIX, we
+    # may not be able to chmod the file if it's owned by someone else
+    # (e.g. from a previous run as root).  We should still be able to
+    # unlink() the file if the directory's writable, though, so ignore
+    # any OSError exception  thrown by the chmod() call.
+    try: os.chmod(self._file_name, 0777)
+    except OSError: pass
+    os.unlink(self._file_name)
+    os.rename(self._tmp_name, self._file_name)
+    self._needs_sync = 00000
+    if (keep_all_files):
+      shutil.copyfile(
+        self._file_name,
+        self._file_name + "_" + str(int(time.time())))
+
+  def _check_writable(self):
+    if (self._flag == "r"):
+      raise IOError("Read-only database: %s" % self._file_name)
+
+  def __getitem__(self, key):
+    return self._dict[key]
+
+  def __setitem__(self, key, value):
+    self._check_writable()
+    if (not is_string(key)):
+      raise TypeError, "key `%s' must be a string but is %s" % (key, type(key))
+    if (not is_string(value)):
+      raise TypeError, "value `%s' must be a string but is %s" % (value, type(value))
+    self._dict[key] = value
+    self._needs_sync = 0001
+
+  def keys(self):
+    return self._dict.keys()
+
+  def has_key(self, key):
+    return key in self._dict
+
+  def __contains__(self, key):
+    return key in self._dict
+
+  def iterkeys(self):
+    return self._dict.iterkeys()
+
+  __iter__ = iterkeys
+
+  def __len__(self):
+    return len(self._dict)
+
+def open(file, flag=None, mode=0666):
+  return dblite(file, flag, mode)
+
+def _exercise():
+  db = open("tmp", "n")
+  assert len(db) == 0
+  db["foo"] = "bar"
+  assert db["foo"] == "bar"
+  db[unicode("ufoo")] = unicode("ubar")
+  assert db[unicode("ufoo")] == unicode("ubar")
+  db.sync()
+  db = open("tmp", "c")
+  assert len(db) == 2, len(db)
+  assert db["foo"] == "bar"
+  db["bar"] = "foo"
+  assert db["bar"] == "foo"
+  db[unicode("ubar")] = unicode("ufoo")
+  assert db[unicode("ubar")] == unicode("ufoo")
+  db.sync()
+  db = open("tmp", "r")
+  assert len(db) == 4, len(db)
+  assert db["foo"] == "bar"
+  assert db["bar"] == "foo"
+  assert db[unicode("ufoo")] == unicode("ubar")
+  assert db[unicode("ubar")] == unicode("ufoo")
+  try:
+    db.sync()
+  except IOError, e:
+    assert str(e) == "Read-only database: tmp.dblite"
+  else:
+    raise RuntimeError, "IOError expected."
+  db = open("tmp", "w")
+  assert len(db) == 4
+  db["ping"] = "pong"
+  db.sync()
+  try:
+    db[(1,2)] = "tuple"
+  except TypeError, e:
+    assert str(e) == "key `(1, 2)' must be a string but is <type 'tuple'>", str(e)
+  else:
+    raise RuntimeError, "TypeError exception expected"
+  try:
+    db["list"] = [1,2]
+  except TypeError, e:
+    assert str(e) == "value `[1, 2]' must be a string but is <type 'list'>", str(e)
+  else:
+    raise RuntimeError, "TypeError exception expected"
+  db = open("tmp", "r")
+  assert len(db) == 5
+  db = open("tmp", "n")
+  assert len(db) == 0
+  _open("tmp.dblite", "w")
+  db = open("tmp", "r")
+  _open("tmp.dblite", "w").write("x")
+  try:
+    db = open("tmp", "r")
+  except cPickle.UnpicklingError:
+    pass
+  else:
+    raise RuntimeError, "cPickle exception expected."
+  global ignore_corrupt_dbfiles
+  ignore_corrupt_dbfiles = 2
+  db = open("tmp", "r")
+  assert len(db) == 0
+  os.unlink("tmp.dblite")
+  try:
+    db = open("tmp", "w")
+  except IOError, e:
+    assert str(e) == "[Errno 2] No such file or directory: 'tmp.dblite'", str(e)
+  else:
+    raise RuntimeError, "IOError expected."
+  print "OK"
+
+if (__name__ == "__main__"):
+  _exercise()

Added: cs/scons/scons-local-0.96.92/SCons/exitfuncs.py
===================================================================
--- cs/scons/scons-local-0.96.92/SCons/exitfuncs.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons-local-0.96.92/SCons/exitfuncs.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -0,0 +1,71 @@
+"""SCons.exitfuncs
+
+Register functions which are executed when SCons exits for any reason.
+
+"""
+
+#
+# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/exitfuncs.py 0.96.92.D001 2006/04/10 23:13:27 knight"
+
+
+
+_exithandlers = []
+def _run_exitfuncs():
+    """run any registered exit functions
+
+    _exithandlers is traversed in reverse order so functions are executed
+    last in, first out.
+    """
+
+    while _exithandlers:
+        func, targs, kargs =  _exithandlers.pop()
+        apply(func, targs, kargs)
+
+def register(func, *targs, **kargs):
+    """register a function to be executed upon normal program termination
+
+    func - function to be called at exit
+    targs - optional arguments to pass to func
+    kargs - optional keyword arguments to pass to func
+    """
+    _exithandlers.append((func, targs, kargs))
+
+import sys
+
+try:
+    x = sys.exitfunc
+
+    # if x isn't our own exit func executive, assume it's another
+    # registered exit function - append it to our list...
+    if x != _run_exitfuncs:
+        register(x)
+
+except AttributeError:
+    pass
+
+# make our exit function get run by python when it exits:    
+sys.exitfunc = _run_exitfuncs
+
+del sys

Modified: cs/scons/scons.py
===================================================================
--- cs/scons/scons.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/scons.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -24,15 +24,15 @@
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #
 
-__revision__ = "/home/scons/scons/branch.0/baseline/src/script/scons.py 0.96.1.D001 2004/08/23 09:55:29 knight"
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/script/scons.py 0.96.92.D002 2006/04/11 07:39:43 knight"
 
-__version__ = "0.96.1"
+__version__ = "0.96.92"
 
-__build__ = "D001"
+__build__ = "D002"
 
-__buildsys__ = "casablanca"
+__buildsys__ = "roxbury"
 
-__date__ = "2004/08/23 09:55:29"
+__date__ = "2006/04/11 07:39:43"
 
 __developer__ = "knight"
 
@@ -129,6 +129,23 @@
                            prefs))
     prefs = temp
 
+    # Add the parent directory of the current python's library to the
+    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64,
+    # not /usr/lib.
+    try:
+        libpath = os.__file__
+    except AttributeError:
+        pass
+    else:
+        while libpath:
+            libpath, tail = os.path.split(libpath)
+            if tail[:6] == "python":
+                break
+        if libpath:
+            # Python library is in /usr/libfoo/python*;
+            # check /usr/libfoo/scons*.
+            prefs.append(libpath)
+
 # Look first for 'scons-__version__' in all of our preference libs,
 # then for 'scons'.
 libs.extend(map(lambda x: os.path.join(x, scons_version), prefs))

Modified: cs/scons/sconsign.py
===================================================================
--- cs/scons/sconsign.py	2006-08-05 00:26:33 UTC (rev 4234)
+++ cs/scons/sconsign.py	2006-08-05 06:49:51 UTC (rev 4235)
@@ -24,15 +24,15 @@
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #
 
-__revision__ = "/home/scons/scons/branch.0/baseline/src/script/sconsign.py 0.96.1.D001 2004/08/23 09:55:29 knight"
+__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/script/sconsign.py 0.96.92.D002 2006/04/11 07:39:43 knight"
 
-__version__ = "0.96.1"
+__version__ = "0.96.92"
 
-__build__ = "D001"
+__build__ = "D002"
 
-__buildsys__ = "casablanca"
+__buildsys__ = "roxbury"
 
-__date__ = "2004/08/23 09:55:29"
+__date__ = "2006/04/11 07:39:43"
 
 __developer__ = "knight"
 
@@ -130,6 +130,23 @@
                            prefs))
     prefs = temp
 
+    # Add the parent directory of the current python's library to the
+    # preferences.  On SuSE-91/AMD64, for example, this is /usr/lib64,
+    # not /usr/lib.
+    try:
+        libpath = os.__file__
+    except AttributeError:
+        pass
+    else:
+        while libpath:
+            libpath, tail = os.path.split(libpath)
+            if tail[:6] == "python":
+                break
+        if libpath:
+            # Python library is in /usr/libfoo/python*;
+            # check /usr/libfoo/scons*.
+            prefs.append(libpath)
+
 # Look first for 'scons-__version__' in all of our preference libs,
 # then for 'scons'.
 libs.extend(map(lambda x: os.path.join(x, scons_version), prefs))
@@ -184,6 +201,7 @@
 Print_Flags = Flagger()
 Verbose = 0
 Readable = 0
+Raw = 0
 
 def default_mapper(entry, name):
     try:
@@ -224,23 +242,44 @@
     'implicit'  : 'bkids',
 }
 
-def printfield(name, entry):
-    def field(name, verbose=Verbose, entry=entry):
-        if not Print_Flags[name]:
-            return None
-        fieldname = map_name.get(name, name)
-        mapper = map_field.get(fieldname, default_mapper)
-        val = mapper(entry, name)
-        if verbose:
-            val = name + ": " + val
-        return val
+def field(name, entry, verbose=Verbose):
+    if not Print_Flags[name]:
+        return None
+    fieldname = map_name.get(name, name)
+    mapper = map_field.get(fieldname, default_mapper)
+    val = mapper(entry, name)
+    if verbose:
+        val = name + ": " + val
+    return val
 
-    fieldlist = ["timestamp", "bsig", "csig"]
-    outlist = [name+":"] + filter(None, map(field, fieldlist))
-    sep = Verbose and "\n    " or " "
-    print string.join(outlist, sep)
+def nodeinfo_raw(name, ninfo, prefix=""):
+    # This does essentially what the pprint module does,
+    # except that it sorts the keys for deterministic output.
+    d = ninfo.__dict__
+    keys = d.keys()
+    keys.sort()
+    l = []
+    for k in keys:
+        l.append('%s: %s' % (repr(k), repr(d[k])))
+    return name + ': {' + string.join(l, ', ') + '}'
 
-    outlist = field("implicit", 0)
+def nodeinfo_string(name, ninfo, prefix=""):
+    fieldlist = ["bsig", "csig", "timestamp", "size"]
+    f = lambda x, ni=ninfo, v=Verbose: field(x, ni, v)
+    outlist = [name+":"] + filter(None, map(f, fieldlist))
+    if Verbose:
+        sep = "\n    " + prefix
+    else:
+        sep = " "
+    return string.join(outlist, sep)
+
+def printfield(name, entry, prefix=""):
+    if Raw:
+        print nodeinfo_raw(name, entry.ninfo, prefix)
+    else:
+        print nodeinfo_string(name, entry.ninfo, prefix)
+
+    outlist = field("implicit", entry, 0)
     if outlist:
         if Verbose:
             print "    implicit:"
@@ -256,8 +295,10 @@
             else:
                 printfield(name, entry)
     else:
-        for name, e in entries.items():
-            printfield(name, e)
+        names = entries.keys()
+        names.sort()
+        for name in names:
+            printfield(name, entries[name])
 
 class Do_SConsignDB:
     def __init__(self, dbm_name, dbm):
@@ -345,14 +386,17 @@
   -h, --help                  Print this message and exit.
   -i, --implicit              Print implicit dependency information.
   -r, --readable              Print timestamps in human-readable form.
+  --raw                       Print raw Python object representations.
+  -s, --size                  Print file sizes.
   -t, --timestamp             Print timestamp information.
   -v, --verbose               Verbose, describe each field.
 """
 
-opts, args = getopt.getopt(sys.argv[1:], "bcd:e:f:hirtv",
+opts, args = getopt.getopt(sys.argv[1:], "bcd:e:f:hirstv",
                             ['bsig', 'csig', 'dir=', 'entry=',
                              'format=', 'help', 'implicit',
-                             'readable', 'timestamp', 'verbose'])
+                             'raw', 'readable',
+                             'size', 'timestamp', 'verbose'])
 
 
 for o, a in opts:
@@ -383,8 +427,12 @@
         sys.exit(0)
     elif o in ('-i', '--implicit'):
         Print_Flags['implicit'] = 1
+    elif o in ('--raw',):
+        Raw = 1
     elif o in ('-r', '--readable'):
         Readable = 1
+    elif o in ('-s', '--size'):
+        Print_Flags['size'] = 1
     elif o in ('-t', '--timestamp'):
         Print_Flags['timestamp'] = 1
     elif o in ('-v', '--verbose'):



More information about the cig-commits mailing list