Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78204 - in branches/release: . tools tools/boostbook tools/boostbook/xsl tools/build/v2 tools/build/v2/build tools/build/v2/doc/src tools/build/v2/engine tools/build/v2/engine/modules tools/build/v2/test tools/build/v2/test/core-language tools/build/v2/test/direct-request-test tools/build/v2/test/engine tools/build/v2/test/prebuilt/ext tools/build/v2/test/project-test1 tools/build/v2/test/subdir1 tools/build/v2/test/test2 tools/build/v2/test/testing-primitives tools/build/v2/test/unused tools/build/v2/test/v1-testing tools/build/v2/test/v1_testing tools/build/v2/tools tools/build/v2/tools/types tools/build/v2/util
From: steven_at_[hidden]
Date: 2012-04-25 23:36:13


Author: steven_watanabe
Date: 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
New Revision: 78204
URL: http://svn.boost.org/trac/boost/changeset/78204

Log:
Merge Boost.Build from the trunk.
Added:
   branches/release/tools/build/v2/doc/src/abstract-target.xml
      - copied, changed from r77757, /trunk/tools/build/v2/doc/src/abstract-target.xml
   branches/release/tools/build/v2/doc/src/basic-target.xml
      - copied, changed from r77757, /trunk/tools/build/v2/doc/src/basic-target.xml
   branches/release/tools/build/v2/doc/src/main-target.xml
      - copied, changed from r77757, /trunk/tools/build/v2/doc/src/main-target.xml
   branches/release/tools/build/v2/doc/src/path.xml
      - copied unchanged from r77683, /trunk/tools/build/v2/doc/src/path.xml
   branches/release/tools/build/v2/doc/src/project-target.xml
      - copied, changed from r77757, /trunk/tools/build/v2/doc/src/project-target.xml
   branches/release/tools/build/v2/doc/src/property-set.xml
      - copied unchanged from r77818, /trunk/tools/build/v2/doc/src/property-set.xml
   branches/release/tools/build/v2/doc/src/type.xml
      - copied unchanged from r77715, /trunk/tools/build/v2/doc/src/type.xml
   branches/release/tools/build/v2/doc/src/typed-target.xml
      - copied unchanged from r77822, /trunk/tools/build/v2/doc/src/typed-target.xml
   branches/release/tools/build/v2/engine/constants.c
      - copied, changed from r75609, /trunk/tools/build/v2/engine/constants.c
   branches/release/tools/build/v2/engine/constants.h
      - copied, changed from r75609, /trunk/tools/build/v2/engine/constants.h
   branches/release/tools/build/v2/engine/function.c
      - copied, changed from r75738, /trunk/tools/build/v2/engine/function.c
   branches/release/tools/build/v2/engine/function.h
      - copied, changed from r75738, /trunk/tools/build/v2/engine/function.h
   branches/release/tools/build/v2/engine/object.c
      - copied, changed from r75609, /trunk/tools/build/v2/engine/object.c
   branches/release/tools/build/v2/engine/object.h
      - copied, changed from r75609, /trunk/tools/build/v2/engine/object.h
   branches/release/tools/build/v2/test/builtin_echo.py
      - copied unchanged from r77648, /trunk/tools/build/v2/test/builtin_echo.py
   branches/release/tools/build/v2/test/builtin_exit.py
      - copied unchanged from r77648, /trunk/tools/build/v2/test/builtin_exit.py
   branches/release/tools/build/v2/test/core-language/
      - copied from r75855, /trunk/tools/build/v2/test/core-language/
   branches/release/tools/build/v2/test/core_action_status.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_action_status.py
   branches/release/tools/build/v2/test/core_actions_quietly.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_actions_quietly.py
   branches/release/tools/build/v2/test/core_arguments.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_arguments.py
   branches/release/tools/build/v2/test/core_at_file.py
      - copied unchanged from r75873, /trunk/tools/build/v2/test/core_at_file.py
   branches/release/tools/build/v2/test/core_bindrule.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_bindrule.py
   branches/release/tools/build/v2/test/core_language.py
      - copied, changed from r75738, /trunk/tools/build/v2/test/core_language.py
   branches/release/tools/build/v2/test/core_nt_line_length.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_nt_line_length.py
   branches/release/tools/build/v2/test/core_option_d2.py
      - copied unchanged from r75836, /trunk/tools/build/v2/test/core_option_d2.py
   branches/release/tools/build/v2/test/core_option_l.py
      - copied, changed from r75836, /trunk/tools/build/v2/test/core_option_l.py
   branches/release/tools/build/v2/test/core_option_n.py
      - copied, changed from r75836, /trunk/tools/build/v2/test/core_option_n.py
   branches/release/tools/build/v2/test/core_parallel_actions.py
      - copied, changed from r75836, /trunk/tools/build/v2/test/core_parallel_actions.py
   branches/release/tools/build/v2/test/core_parallel_multifile_actions_1.py
      - copied, changed from r75836, /trunk/tools/build/v2/test/core_parallel_multifile_actions_1.py
   branches/release/tools/build/v2/test/core_parallel_multifile_actions_2.py
      - copied, changed from r75836, /trunk/tools/build/v2/test/core_parallel_multifile_actions_2.py
   branches/release/tools/build/v2/test/core_update_now.py
      - copied unchanged from r76045, /trunk/tools/build/v2/test/core_update_now.py
   branches/release/tools/build/v2/test/test2/jamroot.jam
      - copied unchanged from r75855, /trunk/tools/build/v2/test/test2/jamroot.jam
   branches/release/tools/build/v2/tools/cray.jam
      - copied unchanged from r74390, /trunk/tools/build/v2/tools/cray.jam
   branches/release/tools/build/v2/tools/mc.py
      - copied unchanged from r75722, /trunk/tools/build/v2/tools/mc.py
   branches/release/tools/build/v2/tools/midl.py
      - copied unchanged from r75722, /trunk/tools/build/v2/tools/midl.py
   branches/release/tools/build/v2/tools/msvc.py
      - copied, changed from r75722, /trunk/tools/build/v2/tools/msvc.py
   branches/release/tools/build/v2/tools/types/preprocessed.py
      - copied, changed from r75722, /trunk/tools/build/v2/tools/types/preprocessed.py
Removed:
   branches/release/tools/build/v2/doc/src/catalog.xml
   branches/release/tools/build/v2/engine/build_vms.com
   branches/release/tools/build/v2/engine/execmac.c
   branches/release/tools/build/v2/engine/execvms.c
   branches/release/tools/build/v2/engine/expand.c
   branches/release/tools/build/v2/engine/expand.h
   branches/release/tools/build/v2/engine/filemac.c
   branches/release/tools/build/v2/engine/fileos2.c
   branches/release/tools/build/v2/engine/filevms.c
   branches/release/tools/build/v2/engine/newstr.c
   branches/release/tools/build/v2/engine/newstr.h
   branches/release/tools/build/v2/engine/pathmac.c
   branches/release/tools/build/v2/engine/pathvms.c
   branches/release/tools/build/v2/test/Jamrules
   branches/release/tools/build/v2/test/assert-equal.jam
   branches/release/tools/build/v2/test/check-arguments.jam
   branches/release/tools/build/v2/test/check-bindrule.jam
   branches/release/tools/build/v2/test/check-jam-patches.jam
   branches/release/tools/build/v2/test/check-test-tools.jam
   branches/release/tools/build/v2/test/direct-request-test/
   branches/release/tools/build/v2/test/echo_args.jam
   branches/release/tools/build/v2/test/empty.jam
   branches/release/tools/build/v2/test/engine/
   branches/release/tools/build/v2/test/file_name_handling.py
   branches/release/tools/build/v2/test/jamfile.jam
   branches/release/tools/build/v2/test/m1-01.py
   branches/release/tools/build/v2/test/m1-02.py
   branches/release/tools/build/v2/test/m1-03.py
   branches/release/tools/build/v2/test/project-test1/
   branches/release/tools/build/v2/test/project-test1.jam
   branches/release/tools/build/v2/test/project_test1.py
   branches/release/tools/build/v2/test/recursive.jam
   branches/release/tools/build/v2/test/startup_v1.py
   branches/release/tools/build/v2/test/subdir1/
   branches/release/tools/build/v2/test/test2/Jamrules
   branches/release/tools/build/v2/test/test2/jamfile.jam
   branches/release/tools/build/v2/test/test_nt_line_length.jam
   branches/release/tools/build/v2/test/testing-primitives/
   branches/release/tools/build/v2/test/testing_primitives.py
   branches/release/tools/build/v2/test/unit-tests.jam
   branches/release/tools/build/v2/test/v1-testing/
   branches/release/tools/build/v2/test/v1_testing/
   branches/release/tools/build/v2/test/v1_testing.py
Properties modified:
   branches/release/ (props changed)
   branches/release/tools/ (props changed)
   branches/release/tools/boostbook/ (props changed)
   branches/release/tools/build/v2/ (props changed)
   branches/release/tools/build/v2/engine/ (props changed)
Text files modified:
   branches/release/tools/boostbook/xsl/annotation.xsl | 6
   branches/release/tools/boostbook/xsl/docbook.xsl | 12
   branches/release/tools/boostbook/xsl/source-highlight.xsl | 96 +
   branches/release/tools/build/v2/Jamroot.jam | 2
   branches/release/tools/build/v2/bootstrap.bat | 2
   branches/release/tools/build/v2/build/engine.py | 11
   branches/release/tools/build/v2/build/feature.py | 4
   branches/release/tools/build/v2/build/generators.jam | 76 -
   branches/release/tools/build/v2/build/generators.py | 36
   branches/release/tools/build/v2/build/project.jam | 201 ++-
   branches/release/tools/build/v2/build/property-set.jam | 184 +-
   branches/release/tools/build/v2/build/property.py | 4
   branches/release/tools/build/v2/build/targets.jam | 2
   branches/release/tools/build/v2/build/targets.py | 3
   branches/release/tools/build/v2/build/toolset.jam | 75 +
   branches/release/tools/build/v2/build/toolset.py | 11
   branches/release/tools/build/v2/build/type.py | 2
   branches/release/tools/build/v2/build/version.jam | 2
   branches/release/tools/build/v2/build_system.py | 37
   branches/release/tools/build/v2/doc/src/abstract-target.xml | 27
   branches/release/tools/build/v2/doc/src/basic-target.xml | 69
   branches/release/tools/build/v2/doc/src/extending.xml | 71
   branches/release/tools/build/v2/doc/src/faq.xml | 18
   branches/release/tools/build/v2/doc/src/howto.xml | 2
   branches/release/tools/build/v2/doc/src/install.xml | 8
   branches/release/tools/build/v2/doc/src/main-target.xml | 46
   branches/release/tools/build/v2/doc/src/overview.xml | 176 +-
   branches/release/tools/build/v2/doc/src/project-target.xml | 75 -
   branches/release/tools/build/v2/doc/src/reference.xml | 286 ++++
   branches/release/tools/build/v2/doc/src/tasks.xml | 176 +-
   branches/release/tools/build/v2/doc/src/tutorial.xml | 119 +-
   branches/release/tools/build/v2/engine/build.bat | 42
   branches/release/tools/build/v2/engine/build.jam | 109 -
   branches/release/tools/build/v2/engine/build.sh | 6
   branches/release/tools/build/v2/engine/builtins.c | 930 +++++++++--------
   branches/release/tools/build/v2/engine/builtins.h | 81
   branches/release/tools/build/v2/engine/class.c | 96 +
   branches/release/tools/build/v2/engine/class.h | 3
   branches/release/tools/build/v2/engine/command.c | 34
   branches/release/tools/build/v2/engine/command.h | 11
   branches/release/tools/build/v2/engine/compile.c | 1163 ---------------------
   branches/release/tools/build/v2/engine/compile.h | 27
   branches/release/tools/build/v2/engine/constants.c | 105 ++
   branches/release/tools/build/v2/engine/constants.h | 35
   branches/release/tools/build/v2/engine/debug.c | 35
   branches/release/tools/build/v2/engine/debug.h | 9
   branches/release/tools/build/v2/engine/execcmd.h | 10
   branches/release/tools/build/v2/engine/execnt.c | 65
   branches/release/tools/build/v2/engine/execunix.c | 242 ++-
   branches/release/tools/build/v2/engine/filent.c | 96 +
   branches/release/tools/build/v2/engine/filesys.c | 52
   branches/release/tools/build/v2/engine/filesys.h | 21
   branches/release/tools/build/v2/engine/fileunix.c | 84
   branches/release/tools/build/v2/engine/frames.c | 3
   branches/release/tools/build/v2/engine/frames.h | 14
   branches/release/tools/build/v2/engine/function.c | 2068 ++++++++++++++++++++++++++++++++++-----
   branches/release/tools/build/v2/engine/function.h | 15
   branches/release/tools/build/v2/engine/glob.c | 10
   branches/release/tools/build/v2/engine/hash.c | 335 ++---
   branches/release/tools/build/v2/engine/hash.h | 65 +
   branches/release/tools/build/v2/engine/hcache.c | 338 +++--
   branches/release/tools/build/v2/engine/hcache.h | 6
   branches/release/tools/build/v2/engine/hdrmacro.c | 49
   branches/release/tools/build/v2/engine/hdrmacro.h | 7
   branches/release/tools/build/v2/engine/headers.c | 61
   branches/release/tools/build/v2/engine/headers.h | 13
   branches/release/tools/build/v2/engine/jam.c | 239 +++-
   branches/release/tools/build/v2/engine/jam.h | 104 -
   branches/release/tools/build/v2/engine/jamgram.c | 1695 +++++++++++++++++++++-----------
   branches/release/tools/build/v2/engine/jamgram.h | 49
   branches/release/tools/build/v2/engine/jamgram.y | 50
   branches/release/tools/build/v2/engine/jamgram.yy | 48
   branches/release/tools/build/v2/engine/lists.c | 397 +++++--
   branches/release/tools/build/v2/engine/lists.h | 50
   branches/release/tools/build/v2/engine/make.c | 95
   branches/release/tools/build/v2/engine/make.h | 14
   branches/release/tools/build/v2/engine/make1.c | 249 ++--
   branches/release/tools/build/v2/engine/modules.c | 390 ++++++-
   branches/release/tools/build/v2/engine/modules.h | 42
   branches/release/tools/build/v2/engine/modules/order.c | 41
   branches/release/tools/build/v2/engine/modules/path.c | 10
   branches/release/tools/build/v2/engine/modules/property-set.c | 39
   branches/release/tools/build/v2/engine/modules/regex.c | 24
   branches/release/tools/build/v2/engine/modules/sequence.c | 23
   branches/release/tools/build/v2/engine/modules/set.c | 14
   branches/release/tools/build/v2/engine/native.c | 47
   branches/release/tools/build/v2/engine/native.h | 13
   branches/release/tools/build/v2/engine/object.c | 8
   branches/release/tools/build/v2/engine/object.h | 23
   branches/release/tools/build/v2/engine/output.c | 14
   branches/release/tools/build/v2/engine/output.h | 7
   branches/release/tools/build/v2/engine/parse.c | 44
   branches/release/tools/build/v2/engine/parse.h | 47
   branches/release/tools/build/v2/engine/patchlevel.h | 8
   branches/release/tools/build/v2/engine/pathsys.h | 34
   branches/release/tools/build/v2/engine/pathunix.c | 340 ++++--
   branches/release/tools/build/v2/engine/pwd.c | 20
   branches/release/tools/build/v2/engine/pwd.h | 3
   branches/release/tools/build/v2/engine/regexp.c | 32
   branches/release/tools/build/v2/engine/regexp.h | 10
   branches/release/tools/build/v2/engine/rules.c | 350 ++----
   branches/release/tools/build/v2/engine/rules.h | 67
   branches/release/tools/build/v2/engine/scan.c | 41
   branches/release/tools/build/v2/engine/scan.h | 21
   branches/release/tools/build/v2/engine/search.c | 145 +-
   branches/release/tools/build/v2/engine/search.h | 11
   branches/release/tools/build/v2/engine/subst.c | 57
   branches/release/tools/build/v2/engine/timestamp.c | 143 +-
   branches/release/tools/build/v2/engine/timestamp.h | 10
   branches/release/tools/build/v2/engine/variable.c | 460 +-------
   branches/release/tools/build/v2/engine/variable.h | 25
   branches/release/tools/build/v2/engine/w32_getreg.c | 34
   branches/release/tools/build/v2/test/BoostBuild.py | 58
   branches/release/tools/build/v2/test/absolute_sources.py | 1
   branches/release/tools/build/v2/test/conditionals_multiple.py | 19
   branches/release/tools/build/v2/test/configuration.py | 8
   branches/release/tools/build/v2/test/core-language/test.jam | 89 +
   branches/release/tools/build/v2/test/core_import_module.py | 17
   branches/release/tools/build/v2/test/core_language.py | 4
   branches/release/tools/build/v2/test/core_option_l.py | 31
   branches/release/tools/build/v2/test/core_option_n.py | 3
   branches/release/tools/build/v2/test/core_parallel_actions.py | 12
   branches/release/tools/build/v2/test/core_parallel_multifile_actions_1.py | 20
   branches/release/tools/build/v2/test/core_parallel_multifile_actions_2.py | 18
   branches/release/tools/build/v2/test/direct_request_test.py | 47
   branches/release/tools/build/v2/test/load_order.py | 24
   branches/release/tools/build/v2/test/prebuilt/ext/jamfile2.jam | 4
   branches/release/tools/build/v2/test/prebuilt/ext/jamfile3.jam | 4
   branches/release/tools/build/v2/test/test.jam | 30
   branches/release/tools/build/v2/test/test1.py | 4
   branches/release/tools/build/v2/test/test2.py | 4
   branches/release/tools/build/v2/test/test_all.py | 21
   branches/release/tools/build/v2/test/unused.py | 6
   branches/release/tools/build/v2/test/unused/jamroot.jam | 15
   branches/release/tools/build/v2/tools/auto-index.jam | 4
   branches/release/tools/build/v2/tools/boostbook.jam | 3
   branches/release/tools/build/v2/tools/builtin.py | 131 +-
   branches/release/tools/build/v2/tools/cast.jam | 2
   branches/release/tools/build/v2/tools/common.jam | 13
   branches/release/tools/build/v2/tools/common.py | 16
   branches/release/tools/build/v2/tools/darwin.jam | 27
   branches/release/tools/build/v2/tools/docutils.jam | 1
   branches/release/tools/build/v2/tools/gcc.jam | 21
   branches/release/tools/build/v2/tools/gcc.py | 14
   branches/release/tools/build/v2/tools/intel-win.jam | 4
   branches/release/tools/build/v2/tools/msvc.jam | 10
   branches/release/tools/build/v2/tools/msvc.py | 1191 ----------------------
   branches/release/tools/build/v2/tools/pch.py | 14
   branches/release/tools/build/v2/tools/python.jam | 2
   branches/release/tools/build/v2/tools/stage.jam | 2
   branches/release/tools/build/v2/tools/stage.py | 2
   branches/release/tools/build/v2/tools/types/__init__.py | 1
   branches/release/tools/build/v2/tools/types/cpp.py | 5
   branches/release/tools/build/v2/tools/types/preprocessed.py | 11
   branches/release/tools/build/v2/tools/unix.py | 8
   branches/release/tools/build/v2/util/doc.jam | 2
   156 files changed, 8436 insertions(+), 7153 deletions(-)

Modified: branches/release/tools/boostbook/xsl/annotation.xsl
==============================================================================
--- branches/release/tools/boostbook/xsl/annotation.xsl (original)
+++ branches/release/tools/boostbook/xsl/annotation.xsl 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -388,6 +388,12 @@
     </computeroutput>
   </xsl:template>
 
+ <xsl:template match="code[@language='jam']" mode="annotation">
+ <computeroutput>
+ <xsl:apply-templates mode="annotation"/>
+ </computeroutput>
+ </xsl:template>
+
   <xsl:template match="bold" mode="annotation">
     <emphasis role="bold">
       <xsl:apply-templates mode="annotation"/>

Modified: branches/release/tools/boostbook/xsl/docbook.xsl
==============================================================================
--- branches/release/tools/boostbook/xsl/docbook.xsl (original)
+++ branches/release/tools/boostbook/xsl/docbook.xsl 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -392,6 +392,12 @@
     </computeroutput>
   </xsl:template>
 
+ <xsl:template match="code[@language='jam']">
+ <computeroutput>
+ <xsl:apply-templates mode="highlight-jam"/>
+ </computeroutput>
+ </xsl:template>
+
   <xsl:template match="bold">
     <emphasis role="bold">
       <xsl:apply-templates mode="annotation"/>
@@ -447,6 +453,12 @@
     <programlisting><xsl:apply-templates/></programlisting>
   </xsl:template>
 
+ <xsl:template match="programlisting[@language='jam']">
+ <programlisting>
+ <xsl:apply-templates mode="highlight-jam"/>
+ </programlisting>
+ </xsl:template>
+
   <!-- These DocBook elements have special meaning. Use the annotation mode -->
   <xsl:template match="classname|methodname|functionname|enumname|
                        macroname|headername|globalname">

Modified: branches/release/tools/boostbook/xsl/source-highlight.xsl
==============================================================================
--- branches/release/tools/boostbook/xsl/source-highlight.xsl (original)
+++ branches/release/tools/boostbook/xsl/source-highlight.xsl 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -435,6 +435,92 @@
     </xsl:choose>
   </xsl:template>
 
+ <!-- Jam syntax highlighting -->
+
+ <xsl:variable name="jam-keywords" select="' actions bind case class default else for if ignore in include local module on piecemeal quietly return rule switch together updated while '"/>
+ <xsl:variable name="jam-operators" select="' ! != &amp; &amp;&amp; ( ) += : ; &lt; &lt;= = &gt; &gt;= ?= [ ] { | || } '"/>
+
+ <xsl:template name="highlight-jam-word">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="contains($jam-keywords, concat(' ', $text, ' '))">
+ <xsl:call-template name="highlight-keyword">
+ <xsl:with-param name="keyword" select="$text"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($jam-operators, concat(' ', $text, ' '))">
+ <xsl:call-template name="highlight-special">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="jam-word-length">
+ <xsl:param name="text"/>
+ <xsl:param name="pos" select="1"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) + 1= $pos">
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:when>
+ <xsl:when test="contains(' &#xA;&#xD;&#x9;', substring($text, $pos, 1))">
+ <xsl:value-of select="$pos - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="jam-word-length">
+ <xsl:with-param name="text" select="$text"/>
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="highlight-jam-text">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="string-length($text) = 0"/>
+ <xsl:when test="contains(' &#xA;&#xD;&#x9;', substring($text, 1, 1))">
+ <xsl:value-of select="substring($text, 1, 1)"/>
+ <xsl:call-template name="highlight-jam-text">
+ <xsl:with-param name="text" select="substring($text, 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="substring($text, 1, 1) = '#'">
+ <xsl:choose>
+ <xsl:when test="contains($text, '&#xA;')">
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="substring-before($text, '&#xA;')"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-jam-text">
+ <xsl:with-param name="text" select="concat('&#xA;', substring-after($text, '&#xA;'))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="highlight-comment">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="length">
+ <xsl:call-template name="jam-word-length">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="highlight-jam-word">
+ <xsl:with-param name="text" select="substring($text, 1, $length)"/>
+ </xsl:call-template>
+ <xsl:call-template name="highlight-jam-text">
+ <xsl:with-param name="text" select="substring($text, $length + 1)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
   <!-- Perform C++ syntax highlighting on the given text -->
   <xsl:template name="highlight-text">
     <xsl:param name="text" select="."/>
@@ -481,4 +567,14 @@
     <xsl:apply-templates mode="highlight"/>
   </xsl:template>
 
+ <xsl:template match="*" mode="highlight-jam">
+ <xsl:apply-templates select="." mode="annotation"/>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="highlight-jam">
+ <xsl:call-template name="highlight-jam-text">
+ <xsl:with-param name="text" select="."/>
+ </xsl:call-template>
+ </xsl:template>
+
 </xsl:stylesheet>

Modified: branches/release/tools/build/v2/Jamroot.jam
==============================================================================
--- branches/release/tools/build/v2/Jamroot.jam (original)
+++ branches/release/tools/build/v2/Jamroot.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -38,7 +38,7 @@
     [ path.glob-tree $(SELF)/build : *.jam *.py ]
     [ path.glob-tree $(SELF)/kernel : *.jam *.py ]
     [ path.glob-tree $(SELF)/util : *.jam *.py ]
- [ path.glob-tree $(SELF)/tools : *.jam *.py ]
+ [ path.glob-tree $(SELF)/tools : *.jam *.py *.xml *.xsl *.doxyfile *.hpp ]
     $(e2)
   : # What is the root of the directory
     <install-source-root>.

Modified: branches/release/tools/build/v2/bootstrap.bat
==============================================================================
--- branches/release/tools/build/v2/bootstrap.bat (original)
+++ branches/release/tools/build/v2/bootstrap.bat 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -10,7 +10,7 @@
 if exist ".\engine\bin.ntx86_64\bjam.exe" del engine\bin.ntx86_64\bjam.exe
 cd engine
 
-call .\build.bat %* > ..\..\bootstrap.log
+call .\build.bat %* > ..\bootstrap.log
 @ECHO OFF
 cd ..
 

Modified: branches/release/tools/build/v2/build/engine.py
==============================================================================
--- branches/release/tools/build/v2/build/engine.py (original)
+++ branches/release/tools/build/v2/build/engine.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -20,14 +20,14 @@
         self.function = function
             
     def __call__(self, targets, sources, property_set):
- if self.function:
- self.function(targets, sources, property_set)
 
         # Bjam actions defined from Python have only the command
         # to execute, and no associated jam procedural code. So
         # passing 'property_set' to it is not necessary.
         bjam_interface.call("set-update-action", self.action_name,
                             targets, sources, [])
+ if self.function:
+ self.function(targets, sources, property_set)
 
 class BjamNativeAction:
     """Class representing bjam action defined by Jam code.
@@ -132,7 +132,12 @@
         bjam_flags = reduce(operator.or_,
                             (action_modifiers[flag] for flag in flags), 0)
 
- bjam_interface.define_action(action_name, command, bound_list, bjam_flags)
+ # We allow command to be empty so that we can define 'action' as pure
+ # python function that would do some conditional logic and then relay
+ # to other actions.
+ assert command or function
+ if command:
+ bjam_interface.define_action(action_name, command, bound_list, bjam_flags)
 
         self.actions[action_name] = BjamAction(action_name, function)
 

Modified: branches/release/tools/build/v2/build/feature.py
==============================================================================
--- branches/release/tools/build/v2/build/feature.py (original)
+++ branches/release/tools/build/v2/build/feature.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -557,10 +557,12 @@
             result.extend(expand_composite(p))
     return result
 
-
+@bjam_signature((['feature'], ['properties', '*']))
 def get_values (feature, properties):
     """ Returns all values of the given feature specified by the given property set.
     """
+ if feature[0] != '<':
+ feature = '<' + feature + '>'
     result = []
     for p in properties:
         if get_grist (p) == feature:

Modified: branches/release/tools/build/v2/build/generators.jam
==============================================================================
--- branches/release/tools/build/v2/build/generators.jam (original)
+++ branches/release/tools/build/v2/build/generators.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -400,13 +400,13 @@
 
         if $(self.composing)
         {
- convert-multiple-sources-to-consumable-types $(project)
- : $(property-set) : $(sources) : consumed bypassed ;
+ consumed = [ convert-multiple-sources-to-consumable-types $(project)
+ : $(property-set) : $(sources) ] ;
         }
         else
         {
- convert-to-consumable-types $(project) $(name) : $(property-set)
- : $(sources) : : consumed bypassed ;
+ consumed = [ convert-to-consumable-types $(project) $(name)
+ : $(property-set) : $(sources) ] ;
         }
 
         local result ;
@@ -579,16 +579,9 @@
         : sources +
         : only-one ? # Convert 'source' to only one of the source types. If
                         # there is more that one possibility, report an error.
- : consumed-var # Name of the variable which receives all targets which
- # can be consumed.
- bypassed-var # Name of the variable which receives all targets which
- # can not be consumed.
     )
     {
- # We are likely to be passed 'consumed' and 'bypassed' var names. Use
- # '_' to avoid name conflicts.
         local _consumed ;
- local _bypassed ;
         local missing-types ;
 
         if $(sources[2])
@@ -599,7 +592,12 @@
         }
         else
         {
- consume-directly $(sources) : _consumed : missing-types ;
+ local temp = [ consume-directly $(sources) ] ;
+ if $(temp[1])
+ {
+ _consumed = $(temp[1]) ;
+ }
+ missing-types = $(temp[2-]) ;
         }
 
         # No need to search for transformation if some source type has consumed
@@ -611,8 +609,6 @@
 
         # TODO: we should check that only one source type if create of
         # 'only-one' is true.
- # TODO: consider if consumed/bypassed separation should be done by
- # 'construct-types'.
 
         if $(missing-types)
         {
@@ -631,61 +627,35 @@
                 {
                     _consumed += $(t) ;
                 }
- else
- {
- _bypassed += $(t) ;
- }
             }
         }
 
- _consumed = [ sequence.unique $(_consumed) ] ;
- _bypassed = [ sequence.unique $(_bypassed) ] ;
-
- # Remove elements of '_bypassed' that are in '_consumed'.
-
- # Suppose the target type of current generator, X is produced from X_1
- # and X_2, which are produced from Y by one generator. When creating X_1
- # from Y, X_2 will be added to 'bypassed'. Likewise, when creating X_2
- # from Y, X_1 will be added to 'bypassed', but they are also in
- # 'consumed'. We have to remove them from bypassed, so that generators
- # up the call stack do not try to convert them.
-
- # In this particular case, X_1 instance in 'consumed' and X_1 instance
- # in 'bypassed' will be the same: because they have the same source and
- # action name, and 'virtual-target.register' will not allow two
- # different instances. Therefore, it is OK to use 'set.difference'.
-
- _bypassed = [ set.difference $(_bypassed) : $(_consumed) ] ;
-
- $(consumed-var) += $(_consumed) ;
- $(bypassed-var) += $(_bypassed) ;
+ return [ sequence.unique $(_consumed) ] ;
     }
 
     # Converts several files to consumable types. Called for composing
     # generators only.
     #
     rule convert-multiple-sources-to-consumable-types ( project : property-set :
- sources * : consumed-var bypassed-var )
+ sources * )
     {
+ local result ;
         # We process each source one-by-one, trying to convert it to a usable
         # type.
         for local source in $(sources)
         {
- local _c ;
- local _b ;
- # TODO: need to check for failure on each source.
- convert-to-consumable-types $(project) : $(property-set) : $(source)
- : true : _c _b ;
+ local _c = [ convert-to-consumable-types $(project) : $(property-set)
+ : $(source) : true ] ;
             if ! $(_c)
             {
                 generators.dout [ indent ] " failed to convert " $(source) ;
             }
- $(consumed-var) += $(_c) ;
- $(bypassed-var) += $(_b) ;
+ result += $(_c) ;
         }
+ return $(result) ;
     }
 
- rule consume-directly ( source : consumed-var : missing-types-var )
+ rule consume-directly ( source )
     {
         local real-source-type = [ $(source).type ] ;
 
@@ -693,19 +663,23 @@
         local source-types = $(self.source-types) ;
         source-types ?= $(real-source-type) ;
 
+ local result = "" ;
+ local missing-types ;
+
         for local st in $(source-types)
         {
             # The 'source' if of the right type already.
             if $(real-source-type) = $(st) || [ type.is-derived
                 $(real-source-type) $(st) ]
             {
- $(consumed-var) += $(source) ;
+ result = $(source) ;
             }
             else
             {
- $(missing-types-var) += $(st) ;
+ missing-types += $(st) ;
             }
         }
+ return $(result) $(missing-types) ;
     }
 
     # Returns the class to be used to actions. Default implementation returns
@@ -1072,7 +1046,6 @@
     : sources + )
 {
     local result ;
- local matched-types ;
     local usage-requirements = [ property-set.empty ] ;
     for local t in $(target-types)
     {
@@ -1082,7 +1055,6 @@
         {
             usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
             result += $(r[2-]) ;
- matched-types += $(t) ;
         }
     }
     # TODO: have to introduce parameter controlling if several types can be

Modified: branches/release/tools/build/v2/build/generators.py
==============================================================================
--- branches/release/tools/build/v2/build/generators.py (original)
+++ branches/release/tools/build/v2/build/generators.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -400,6 +400,9 @@
 
         dir = os.path.dirname(fullname)
         name = os.path.basename(fullname)
+ idx = name.find(".")
+ if idx != -1:
+ name = name[:idx]
 
         if dir and not ".." in dir and not os.path.isabs(dir):
             # Relative path is always relative to the source
@@ -470,9 +473,6 @@
         post = self.name_postfix_
         for t in self.target_types_:
             basename = os.path.basename(name)
- idx = basename.find(".")
- if idx != -1:
- basename = basename[:idx]
             generated_name = pre[0] + basename + post[0]
             generated_name = os.path.join(os.path.dirname(name), generated_name)
             pre = pre[1:]
@@ -692,7 +692,7 @@
     after computing the list of viable generators, before
     running any of them."""
     
- __overrides.get(overrider_id, []).append(overridee_id)
+ __overrides.setdefault(overrider_id, []).append(overridee_id)
 
 def __viable_source_types_real (target_type):
     """ Returns a list of source type which can possibly be converted
@@ -974,7 +974,7 @@
     
     # Generators which are overriden
     overriden_ids = []
-
+
     for g in viable_generators:
         id = g.id ()
         
@@ -988,13 +988,7 @@
     if all_overrides:
         viable_generators = all_overrides
 
- result = []
- for g in viable_generators:
- if not g.id () in overriden_ids:
- result.append (g)
-
-
- return result
+ return [g for g in viable_generators if not g.id() in overriden_ids]
     
 def __construct_really (project, name, target_type, prop_set, sources):
     """ Attempts to construct target by finding viable generators, running them
@@ -1004,7 +998,7 @@
                     
     result = []
 
- project.manager ().logger ().log (__name__, "*** %d viable generators" % len (viable_generators))
+ dout(" *** %d viable generators" % len (viable_generators))
 
     generators_that_succeeded = []
     
@@ -1086,4 +1080,18 @@
         __active_generators = saved_active
 
     return result
-
+
+def add_usage_requirements (result, raw_properties):
+ if result:
+ if isinstance (result[0], property_set.PropertySet):
+ return (result[0].add_raw(raw_properties), result[1])
+ else:
+ return (propery_set.create(raw-properties), result)
+ #if [ class.is-a $(result[1]) : property-set ]
+ #{
+ # return [ $(result[1]).add-raw $(raw-properties) ] $(result[2-]) ;
+ #}
+ #else
+ #{
+ # return [ property-set.create $(raw-properties) ] $(result) ;
+ #}

Modified: branches/release/tools/build/v2/build/project.jam
==============================================================================
--- branches/release/tools/build/v2/build/project.jam (original)
+++ branches/release/tools/build/v2/build/project.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -263,7 +263,7 @@
     {
         errors.error Unable to load Jamfile.
             : Could not find a Jamfile in directory '$(dir)'.
- : Attempted to find it with pattern '"$(JAMFILE:J=" ")"'.
+ : Attempted to find it with pattern '"$(JAMFILE:J= )"'.
             : Please consult the documentation at 'http://www.boost.org'. ;
     }
 
@@ -301,56 +301,60 @@
     # prevents that second attempt from messing up.
     if ! $(jamfile-module) in $(.jamfile-modules)
     {
- .jamfile-modules += $(jamfile-module) ;
 
         # Initialize the Jamfile module before loading.
         #
         initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ]
             : $(jamfile-to-load:BS) ;
 
- local saved-project = $(.current-project) ;
-
- mark-as-user $(jamfile-module) ;
- modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ;
- if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ]
+ if ! $(jamfile-module) in $(.jamfile-modules)
         {
- jamfile = [ find-jamfile $(dir) : no-errors ] ;
- if $(jamfile)
+ .jamfile-modules += $(jamfile-module) ;
+
+ local saved-project = $(.current-project) ;
+
+ mark-as-user $(jamfile-module) ;
+ modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ;
+ if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ]
             {
- load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
+ jamfile = [ find-jamfile $(dir) : no-errors ] ;
+ if $(jamfile)
+ {
+ load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
+ }
             }
- }
-
- # Now do some checks.
- if $(.current-project) != $(saved-project)
- {
- errors.error "The value of the .current-project variable has magically"
- : "changed after loading a Jamfile. This means some of the targets"
- : "might be defined in the wrong project."
- : "after loading" $(jamfile-module)
- : "expected value" $(saved-project)
- : "actual value" $(.current-project) ;
- }
 
- if $(.global-build-dir)
- {
- local id = [ attribute $(jamfile-module) id ] ;
- local project-root = [ attribute $(jamfile-module) project-root ] ;
- local location = [ attribute $(jamfile-module) location ] ;
+ # Now do some checks.
+ if $(.current-project) != $(saved-project)
+ {
+ errors.error "The value of the .current-project variable has magically"
+ : "changed after loading a Jamfile. This means some of the targets"
+ : "might be defined in the wrong project."
+ : "after loading" $(jamfile-module)
+ : "expected value" $(saved-project)
+ : "actual value" $(.current-project) ;
+ }
 
- if $(location) && $(project-root) = $(dir)
- {
- # This is Jamroot.
- if ! $(id)
+ if $(.global-build-dir)
             {
- ECHO "warning: the --build-dir option was specified" ;
- ECHO "warning: but Jamroot at '$(dir)'" ;
- ECHO "warning: specified no project id" ;
- ECHO "warning: the --build-dir option will be ignored" ;
+ local id = [ attribute $(jamfile-module) id ] ;
+ local project-root = [ attribute $(jamfile-module) project-root ] ;
+ local location = [ attribute $(jamfile-module) location ] ;
+
+ if $(location) && $(project-root) = $(dir)
+ {
+ # This is Jamroot.
+ if ! $(id)
+ {
+ ECHO "warning: the --build-dir option was specified" ;
+ ECHO "warning: but Jamroot at '$(dir)'" ;
+ ECHO "warning: specified no project id" ;
+ ECHO "warning: the --build-dir option will be ignored" ;
+ }
+ }
             }
         }
     }
- }
 }
 
 
@@ -398,44 +402,6 @@
         ECHO "Initializing project '$(module-name)'" ;
     }
 
- # TODO: need to consider if standalone projects can do anything but define
- # prebuilt targets. If so, we need to give it a more sensible "location", so
- # that source paths are correct.
- location ?= "" ;
- # Create the module for the Jamfile first.
- module $(module-name)
- {
- }
- $(module-name).attributes = [ new project-attributes $(location)
- $(module-name) ] ;
- local attributes = $($(module-name).attributes) ;
-
- if $(location)
- {
- $(attributes).set source-location : [ path.make $(location) ] : exact ;
- }
- else if ! $(module-name) in test-config site-config user-config project-config
- {
- # This is a standalone project with known location. Set source location
- # so that it can declare targets. This is intended so that you can put
- # a .jam file in your sources and use it via 'using'. Standard modules
- # (in 'tools' subdir) may not assume source dir is set.
- local s = [ modules.binding $(module-name) ] ;
- if ! $(s)
- {
- errors.error "Could not determine project location $(module-name)" ;
- }
- $(attributes).set source-location : $(s:D) : exact ;
- }
-
- $(attributes).set requirements : [ property-set.empty ] : exact ;
- $(attributes).set usage-requirements : [ property-set.empty ] : exact ;
-
- # Import rules common to all project modules from project-rules module,
- # defined at the end of this file.
- local rules = [ RULENAMES project-rules ] ;
- IMPORT project-rules : $(rules) : $(module-name) : $(rules) ;
-
     local jamroot ;
 
     local parent-module ;
@@ -483,33 +449,77 @@
         }
     }
 
- if $(parent-module)
+ # TODO: need to consider if standalone projects can do anything but define
+ # prebuilt targets. If so, we need to give it a more sensible "location", so
+ # that source paths are correct.
+ location ?= "" ;
+ # Create the module for the Jamfile first.
+ module $(module-name)
     {
- inherit-attributes $(module-name) : $(parent-module) ;
- $(attributes).set parent-module : $(parent-module) : exact ;
     }
 
- if $(jamroot)
- {
- $(attributes).set project-root : $(location) : exact ;
- }
+ # load-parent can end up loading this module again.
+ # Make sure this isn't duplicated.
+ if ! $($(module-name).attributes) {
 
- local parent ;
- if $(parent-module)
- {
- parent = [ target $(parent-module) ] ;
- }
+ $(module-name).attributes = [ new project-attributes $(location)
+ $(module-name) ] ;
+ local attributes = $($(module-name).attributes) ;
 
- if ! $(.target.$(module-name))
- {
- .target.$(module-name) = [ new project-target $(module-name)
- : $(module-name) $(parent)
- : [ attribute $(module-name) requirements ] ] ;
+ if $(location)
+ {
+ $(attributes).set source-location : [ path.make $(location) ] : exact ;
+ }
+ else if ! $(module-name) in test-config site-config user-config project-config
+ {
+ # This is a standalone project with known location. Set source location
+ # so that it can declare targets. This is intended so that you can put
+ # a .jam file in your sources and use it via 'using'. Standard modules
+ # (in 'tools' subdir) may not assume source dir is set.
+ local s = [ modules.binding $(module-name) ] ;
+ if ! $(s)
+ {
+ errors.error "Could not determine project location $(module-name)" ;
+ }
+ $(attributes).set source-location : $(s:D) : exact ;
+ }
+
+ $(attributes).set requirements : [ property-set.empty ] : exact ;
+ $(attributes).set usage-requirements : [ property-set.empty ] : exact ;
+
+ # Import rules common to all project modules from project-rules module,
+ # defined at the end of this file.
+ local rules = [ RULENAMES project-rules ] ;
+ IMPORT project-rules : $(rules) : $(module-name) : $(rules) ;
+
+ if $(parent-module)
+ {
+ inherit-attributes $(module-name) : $(parent-module) ;
+ $(attributes).set parent-module : $(parent-module) : exact ;
+ }
+
+ if $(jamroot)
+ {
+ $(attributes).set project-root : $(location) : exact ;
+ }
+
+ local parent ;
+ if $(parent-module)
+ {
+ parent = [ target $(parent-module) ] ;
+ }
 
- if --debug-loading in [ modules.peek : ARGV ]
+ if ! $(.target.$(module-name))
         {
- ECHO "Assigned project target" $(.target.$(module-name))
- "to '$(module-name)'" ;
+ .target.$(module-name) = [ new project-target $(module-name)
+ : $(module-name) $(parent)
+ : [ attribute $(module-name) requirements ] ] ;
+
+ if --debug-loading in [ modules.peek : ARGV ]
+ {
+ ECHO "Assigned project target" $(.target.$(module-name))
+ "to '$(module-name)'" ;
+ }
         }
     }
 
@@ -1099,7 +1109,8 @@
     
     rule option ( name : value )
     {
- if $(__name__) != site-config && $(__name__) != user-config && $(__name__) != project-config
+ local m = [ CALLER_MODULE ] ;
+ if $(m) != site-config && $(m) != user-config && $(m) != project-config
         {
             import errors ;
             errors.error "The 'option' rule may be used only in site-config or user-config" ;

Modified: branches/release/tools/build/v2/build/property-set.jam
==============================================================================
--- branches/release/tools/build/v2/build/property-set.jam (original)
+++ branches/release/tools/build/v2/build/property-set.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -48,49 +48,6 @@
             {
                 errors.error "Invalid property: '$(p)'" ;
             }
-
- local att = [ feature.attributes $(p:G) ] ;
- # A feature can be both incidental and free, in which case we add it
- # to incidental.
- if incidental in $(att)
- {
- self.incidental += $(p) ;
- }
- else if free in $(att)
- {
- self.free += $(p) ;
- }
- else
- {
- self.base += $(p) ;
- }
-
- if dependency in $(att)
- {
- self.dependency += $(p) ;
- }
- else
- {
- self.non-dependency += $(p) ;
- }
-
- if [ MATCH (:) : $(p:G=) ]
- {
- self.conditional += $(p) ;
- }
- else
- {
- self.non-conditional += $(p) ;
- }
-
- if propagated in $(att)
- {
- self.propagated += $(p) ;
- }
- if link-incompatible in $(att)
- {
- self.link-incompatible += $(p) ;
- }
         }
     }
 
@@ -110,6 +67,10 @@
     #
     rule base ( )
     {
+ if ! $(self.base-initialized)
+ {
+ init-base ;
+ }
         return $(self.base) ;
     }
 
@@ -117,6 +78,10 @@
     #
     rule free ( )
     {
+ if ! $(self.base-initialized)
+ {
+ init-base ;
+ }
         return $(self.free) ;
     }
 
@@ -124,21 +89,37 @@
     #
     rule dependency ( )
     {
+ if ! $(self.dependency-initialized)
+ {
+ init-dependency ;
+ }
         return $(self.dependency) ;
     }
 
     rule non-dependency ( )
     {
+ if ! $(self.dependency-initialized)
+ {
+ init-dependency ;
+ }
         return $(self.non-dependency) ;
     }
 
     rule conditional ( )
     {
+ if ! $(self.conditional-initialized)
+ {
+ init-conditional ;
+ }
         return $(self.conditional) ;
     }
 
     rule non-conditional ( )
     {
+ if ! $(self.conditional-initialized)
+ {
+ init-conditional ;
+ }
         return $(self.non-conditional) ;
     }
 
@@ -146,6 +127,10 @@
     #
     rule incidental ( )
     {
+ if ! $(self.base-initialized)
+ {
+ init-base ;
+ }
         return $(self.incidental) ;
     }
 
@@ -200,30 +185,19 @@
     {
         if ! $(self.propagated-ps)
         {
- self.propagated-ps = [ property-set.create $(self.propagated) ] ;
+ local result ;
+ for local p in $(self.raw)
+ {
+ if propagated in [ feature.attributes $(p:G) ]
+ {
+ result += $(p) ;
+ }
+ }
+ self.propagated-ps = [ property-set.create $(result) ] ;
         }
         return $(self.propagated-ps) ;
     }
 
- rule link-incompatible ( )
- {
- if ! $(self.link-incompatible-ps)
- {
- self.link-incompatible-ps =
- [ property-set.create $(self.link-incompatible) ] ;
- }
- return $(self.link-incompatible-ps) ;
- }
-
- rule run-actions ( )
- {
- if ! $(self.run)
- {
- self.run = [ property-set.create [ feature.run-actions $(self.raw) ] ] ;
- }
- return $(self.run) ;
- }
-
     rule add-defaults ( )
     {
         if ! $(self.defaults)
@@ -238,7 +212,7 @@
     {
         if ! $(self.as-path)
         {
- self.as-path = [ property.as-path $(self.base) ] ;
+ self.as-path = [ property.as-path [ base ] ] ;
         }
         return $(self.as-path) ;
     }
@@ -303,47 +277,81 @@
         return [ add [ property-set.create $(properties) ] ] ;
     }
 
- rule link-incompatible-with ( ps )
+ # Returns all values of 'feature'.
+ #
+ rule get ( feature )
+ {
+ if ! $(self.map-built)
+ {
+ # For each feature, create a member var and assign all values to it.
+ # Since all regular member vars start with 'self', there will be no
+ # conflicts between names.
+ self.map-built = true ;
+ for local v in $(self.raw)
+ {
+ $(v:G) += $(v:G=) ;
+ }
+ }
+ return $($(feature)) ;
+ }
+
+ # private
+
+ rule init-base ( )
     {
- if ! $(.li.$(ps))
+ for local p in $(self.raw)
         {
- local li1 = [ $(__name__).link-incompatible ] ;
- local li2 = [ $(ps).link-incompatible ] ;
- if [ set.equal $(li1) : $(li2) ]
+ local att = [ feature.attributes $(p:G) ] ;
+ # A feature can be both incidental and free, in which case we add it
+ # to incidental.
+ if incidental in $(att)
+ {
+ self.incidental += $(p) ;
+ }
+ else if free in $(att)
             {
- .li.$(ps) = false ;
+ self.free += $(p) ;
             }
             else
             {
- .li.$(ps) = true ;
+ self.base += $(p) ;
             }
         }
- if $(.li.$(ps)) = true
- {
- return true ;
- }
- else
+ self.base-initialized = true ;
+ }
+
+ rule init-dependency ( )
+ {
+ for local p in $(self.raw)
         {
- return ;
+ local att = [ feature.attributes $(p:G) ] ;
+
+ if dependency in $(att)
+ {
+ self.dependency += $(p) ;
+ }
+ else
+ {
+ self.non-dependency += $(p) ;
+ }
         }
+ self.dependency-initialized = true ;
     }
 
- # Returns all values of 'feature'.
- #
- rule get ( feature )
+ rule init-conditional ( )
     {
- if ! $(self.map-built)
+ for local p in $(self.raw)
         {
- # For each feature, create a member var and assign all values to it.
- # Since all regular member vars start with 'self', there will be no
- # conflicts between names.
- self.map-built = true ;
- for local v in $(self.raw)
+ if [ MATCH (:) : $(p:G=) ]
             {
- $(v:G) += $(v:G=) ;
+ self.conditional += $(p) ;
+ }
+ else
+ {
+ self.non-conditional += $(p) ;
             }
         }
- return $($(feature)) ;
+ self.conditional-initialized = true ;
     }
 }
 

Modified: branches/release/tools/build/v2/build/property.py
==============================================================================
--- branches/release/tools/build/v2/build/property.py (original)
+++ branches/release/tools/build/v2/build/property.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -63,7 +63,7 @@
                    (other._feature, other._value, other._condition))
                            
 
-def create_from_string(s, allow_condition=False):
+def create_from_string(s, allow_condition=False,allow_missing_value=False):
 
     condition = []
     import types
@@ -92,7 +92,7 @@
         f = feature.get(feature_name)
 
         value = get_value(s)
- if not value:
+ if not value and not allow_missing_value:
             get_manager().errors()("Invalid property '%s' -- no value specified" % s)
 
 

Modified: branches/release/tools/build/v2/build/targets.jam
==============================================================================
--- branches/release/tools/build/v2/build/targets.jam (original)
+++ branches/release/tools/build/v2/build/targets.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -936,7 +936,7 @@
     {
         $(key) = [ common-properties2 $(build-request) $(non-free) ] ;
     }
- result = [ $($(key)).add-raw $(free) ] ;
+ return [ $($(key)).add-raw $(free) ] ;
 }
 
 

Modified: branches/release/tools/build/v2/build/targets.py
==============================================================================
--- branches/release/tools/build/v2/build/targets.py (original)
+++ branches/release/tools/build/v2/build/targets.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1290,7 +1290,8 @@
             
     def construct (self, name, source_targets, prop_set):
 
- r = generators.construct (self.project_, name, self.type_,
+ r = generators.construct (self.project_, os.path.splitext(name)[0],
+ self.type_,
                                   prop_set.add_raw(['<main-target-type>' + self.type_]),
                                   source_targets, True)
 

Modified: branches/release/tools/build/v2/build/toolset.jam
==============================================================================
--- branches/release/tools/build/v2/build/toolset.jam (original)
+++ branches/release/tools/build/v2/build/toolset.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -15,6 +15,7 @@
 import regex ;
 import sequence ;
 import set ;
+import property-set ;
 
 
 .flag-no = 1 ;
@@ -320,10 +321,82 @@
     return $(result) ;
 }
 
+rule relevant-features ( rule-or-module )
+{
+ local result ;
+ if ! $(.relevant-features.$(rule-or-module))
+ {
+ for local f in $(.$(rule-or-module).flags)
+ {
+ local condition = $(.$(rule-or-module).condition.$(f)) ;
+ local values = $(.$(rule-or-module).values.$(f)) ;
+
+ for local c in $(condition)
+ {
+ for local p in [ feature.split $(c) ]
+ {
+ if $(p:G)
+ {
+ result += $(p:G) ;
+ }
+ else
+ {
+ local temp = [ feature.expand-subfeatures $(p) ] ;
+ result += $(temp:G) ;
+ }
+ }
+ }
+
+ for local v in $(values)
+ {
+ if $(v:G)
+ {
+ result += $(v:G) ;
+ }
+ }
+ }
+
+ # Strip away last dot separated part and recurse.
+ local next = [ MATCH ^(.+)\\.([^\\.])* : $(rule-or-module) ] ;
+ if $(next)
+ {
+ result += [ relevant-features $(next[1]) ] ;
+ }
+ result = [ sequence.unique $(result) ] ;
+ if $(result[1]) = ""
+ {
+ result = $(result) ;
+ }
+ .relevant-features.$(rule-or-module) = $(result) ;
+ return $(result) ;
+ }
+ else
+ {
+ return $(.relevant-features.$(rule-or-module)) ;
+ }
+}
+
+rule filter-property-set ( rule-or-module : property-set )
+{
+ if ! $(.filtered.property-set.$(rule-or-module).$(property-set))
+ {
+ local relevant = [ relevant-features $(rule-or-module) ] ;
+ local result ;
+ for local p in [ $(property-set).raw ]
+ {
+ if $(p:G) in $(relevant)
+ {
+ result += $(p) ;
+ }
+ }
+ .filtered.property-set.$(rule-or-module).$(property-set) = [ property-set.create $(result) ] ;
+ }
+ return $(.filtered.property-set.$(rule-or-module).$(property-set)) ;
+}
 
 rule set-target-variables ( rule-or-module targets + : property-set )
 {
- properties = [ $(property-set).raw ] ;
+ property-set = [ filter-property-set $(rule-or-module) : $(property-set) ] ;
     local key = $(rule-or-module).$(property-set) ;
     local settings = $(.stv.$(key)) ;
     if ! $(settings)

Modified: branches/release/tools/build/v2/build/toolset.py
==============================================================================
--- branches/release/tools/build/v2/build/toolset.py (original)
+++ branches/release/tools/build/v2/build/toolset.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -68,7 +68,9 @@
 reset ()
 
 # FIXME: --ignore-toolset-requirements
-# FIXME: using
+def using(toolset_module, *args):
+ loaded_toolset_module= get_manager().projects().load_module(toolset_module, [os.getcwd()]);
+ loaded_toolset_module.init(*args)
     
 # FIXME push-checking-for-flags-module ....
 # FIXME: investigate existing uses of 'hack-hack' parameter
@@ -115,8 +117,8 @@
                           is specified, then the value of 'feature'
                           will be added.
     """
- caller = bjam.caller()[:-1]
- if not '.' in rule_or_module and caller.startswith("Jamfile"):
+ caller = bjam.caller()
+ if not '.' in rule_or_module and caller and caller[:-1].startswith("Jamfile"):
         # Unqualified rule name, used inside Jamfile. Most likely used with
         # 'make' or 'notfile' rules. This prevents setting flags on the entire
         # Jamfile module (this will be considered as rule), but who cares?
@@ -142,7 +144,7 @@
         transformed = []
         for c in condition:
             # FIXME: 'split' might be a too raw tool here.
- pl = [property.create_from_string(s) for s in c.split('/')]
+ pl = [property.create_from_string(s,False,True) for s in c.split('/')]
             pl = feature.expand_subfeatures(pl);
             transformed.append(property_set.create(pl))
         condition = transformed
@@ -378,7 +380,6 @@
     
     #if ! $(.ignore-requirements)
     #{
- print "XXXX", requirements
     __requirements.extend(requirements)
     #}
          

Modified: branches/release/tools/build/v2/build/type.py
==============================================================================
--- branches/release/tools/build/v2/build/type.py (original)
+++ branches/release/tools/build/v2/build/type.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -81,7 +81,7 @@
     __types [type] = entry
     
     if base_type:
- __types [base_type]['derived'].append (type)
+ __types.setdefault(base_type, {}).setdefault('derived', []).append(type)
 
     if len (suffixes) > 0:
         # Generated targets of 'type' will use the first of 'suffixes'

Modified: branches/release/tools/build/v2/build/version.jam
==============================================================================
--- branches/release/tools/build/v2/build/version.jam (original)
+++ branches/release/tools/build/v2/build/version.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -7,7 +7,7 @@
 import numbers ;
 
 major = "2011" ;
-minor = "04" ;
+minor = "12" ;
 
 rule boost-build ( )
 {

Modified: branches/release/tools/build/v2/build_system.py
==============================================================================
--- branches/release/tools/build/v2/build_system.py (original)
+++ branches/release/tools/build/v2/build_system.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -20,6 +20,7 @@
 import b2.build.build_request
 from b2.build.errors import ExceptionWithUserContext
 import b2.tools.common
+from b2.build.toolset import using
 
 import b2.build.project as project
 import b2.build.virtual_target as virtual_target
@@ -290,6 +291,9 @@
     initialize_config_module('user-config')
     if not test_config and not legacy_ignore_config:
 
+ # Here, user_config has value of None if nothing is explicitly
+ # specified, and value of '' if user explicitly does not want
+ # to load any user config.
         user_config = None
         for a in sys.argv:
             m = re.match("--user-config=(.*)$", a)
@@ -297,30 +301,32 @@
                 user_config = m.group(1)
                 break
 
- if not user_config:
+ if user_config is None:
             user_config = os.getenv("BOOST_BUILD_USER_CONFIG")
             
         # Special handling for the case when the OS does not strip the quotes
         # around the file name, as is the case when using Cygwin bash.
         user_config = b2.util.unquote(user_config)
         explicitly_requested = user_config
- if not user_config:
+
+ if user_config is None:
             user_config = "user-config.jam"
 
- if explicitly_requested:
+ if user_config:
+ if explicitly_requested:
 
- user_config = os.path.abspath(user_config)
+ user_config = os.path.abspath(user_config)
             
- if debug_config:
- print "notice: Loading explicitly specified user configuration file:"
- print " " + user_config
+ if debug_config:
+ print "notice: Loading explicitly specified user configuration file:"
+ print " " + user_config
             
- load_config('user-config', os.path.basename(user_config), [os.path.dirname(user_config)], True)
+ load_config('user-config', os.path.basename(user_config), [os.path.dirname(user_config)], True)
+ else:
+ load_config('user-config', os.path.basename(user_config), user_path)
         else:
- load_config('user-config', os.path.basename(user_config), user_path)
-
- elif debug_config:
- print "notice: User configuration file loading explicitly disabled." ;
+ if debug_config:
+ print "notice: User configuration file loading explicitly disabled."
         
     # We look for project-config.jam from "." upward.
     # I am not sure this is 100% right decision, we might as well check for
@@ -381,7 +387,10 @@
 
             if debug_config:
                 print "notice: [cmdline-cfg] toolset '%s' not previously configured; attempting to auto-configure now" % toolset_version
- toolset.using(toolset, version)
+ if version is not None:
+ using(toolset, version)
+ else:
+ using(toolset)
 
         else:
 
@@ -515,7 +524,7 @@
         print "warning: For more configuration options, please consult"
         print "warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html"
 
- toolset.using(dt, dtv)
+ using(dt, dtv)
 
     # Parse command line for targets and properties. Note that this requires
     # that all project files already be loaded.

Copied: branches/release/tools/build/v2/doc/src/abstract-target.xml (from r77757, /trunk/tools/build/v2/doc/src/abstract-target.xml)
==============================================================================
--- /trunk/tools/build/v2/doc/src/abstract-target.xml (original)
+++ branches/release/tools/build/v2/doc/src/abstract-target.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -13,6 +13,17 @@
     Base class for all abstract targets.
   </para>
 
+<programlisting language="jam">
+class abstract-target {
+ rule <link linkend="bbv2.reference.class.abstract-target.__init__">__init__</link> ( name : project )
+ rule <link linkend="bbv2.reference.class.abstract-target.name">name</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.project">project</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.location">location</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.full-name">full-name</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.__init__">generate</link> ( property-set )
+}
+</programlisting>
+
   <para>
     Classes derived from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>:
     <itemizedlist>
@@ -31,19 +42,19 @@
   <orderedlist>
     
     <listitem id="bbv2.reference.class.abstract-target.__init__">
- <code language="jam">rule __init__ ( name : project-target )</code>
+ <code language="jam">rule __init__ ( name : project )</code>
       <para>
         <variablelist>
           <varlistentry>
- <literal>name</literal>
+ <term><literal>name</literal></term>
             <listitem>
- <para>Name of the target in Jamfile.</para>
+ <para>The name of the target in the Jamfile.</para>
             </listitem>
- </varlistentry>
+ </varlistentry>
           <varlistentry>
- <literal>project-target</literal>
+ <term><literal>project</literal></term>
             <listitem>
- <para>The project target to which this one belongs.</para>
+ <para>The <link linkend="bbv2.reference.class.project-target">project</link> to which this target belongs.</para>
             </listitem>
           </varlistentry>
         </variablelist>
@@ -65,7 +76,7 @@
         <secondary>Abstract Target</secondary>
       </indexterm>
       <code language="jam">rule project ( )</code>
- <para>Returns the project for this target.</para>
+ <para>Returns the <link linkend="bbv2.reference.class.project-target">project</link> for this target.</para>
     </listitem>
 
     <listitem id="bbv2.reference.class.abstract-target.location">
@@ -74,7 +85,7 @@
         <secondary>Abstract Target</secondary>
       </indexterm>
       <code language="jam">rule location ( )</code>
- <para>Return the location where the target was declared.</para>
+ <para>Returns the location where the target was declared.</para>
     </listitem>
 
     <listitem id="bbv2.reference.class.abstract-target.full-name">

Copied: branches/release/tools/build/v2/doc/src/basic-target.xml (from r77757, /trunk/tools/build/v2/doc/src/basic-target.xml)
==============================================================================
--- /trunk/tools/build/v2/doc/src/basic-target.xml (original)
+++ branches/release/tools/build/v2/doc/src/basic-target.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,9 +9,19 @@
     <primary>basic-target</primary>
   </indexterm>
 
- <para>
- Derived from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
+<programlisting language="jam">
+class basic-target : <link linkend="bbv2.reference.class.abstract-target">abstract-target</link> {
+ rule <link linkend="bbv2.reference.class.basic-target.__init__">__init__</link> ( name : project : sources * : requirements * : default-build * : usage-requirements * )
+ rule <link linkend="bbv2.reference.class.basic-target.generate">generate</link> ( property-set )
+ rule <link linkend="bbv2.reference.class.basic-target.construct">construct</link> ( name : source-targets * : property-set )
+
+ # Methods inherited from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>
+ rule <link linkend="bbv2.reference.class.abstract-target.name">name</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.project">project</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.location">location</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.full-name">full-name</link> ( )
+}
+</programlisting>
 
   <para>
     Implements the most standard way of constructing main target alternative from
@@ -23,39 +33,24 @@
 
   <orderedlist>
 
- <listitem>
+ <listitem id="bbv2.reference.class.basic-target.__init__">
       <code language="jam">rule __init__ ( name : project : sources * : requirements * : default-build * : usage-requirements * )</code>
- </listitem>
-
- <listitem id="bbv2.reference.class.basic-target.name">
- <code language="jam">rule name ( )</code>
- <para>
- Returns the name of this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.basic-target.project">
- <code language="jam">rule project ( )</code>
- <para>
- Returns the project for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.basic-target.location">
- <code language="jam">rule location ( )</code>
- <para>
- Return the location where the target was declared. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.basic-target.full-name">
- <code language="jam">rule full-name ( )</code>
       <para>
- Returns a user-readable name for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
+ <variablelist>
+ <varlistentry>
+ <term><literal>name</literal></term>
+ <listitem><para>The name of the target</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>project</literal></term>
+ <listitem>
+ <para>
+ The <link linkend="bbv2.reference.class.project-target">project</link>
+ in which the target is declared.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
       </para>
     </listitem>
 
@@ -88,10 +83,10 @@
         <primary>construct</primary>
         <secondary>Basic Target Method</secondary>
       </indexterm>
- <code language="jam">rule construct ( name : source-targets * : properties * )</code>
+ <code language="jam">rule construct ( name : source-targets * : property-set )</code>
       <para>
- Constructs virtual targets for this abstract target and the dependency
- graph. Returns a usage-requirements property-set and a list of virtual
+ Constructs virtual targets for this abstract target. Returns a
+ usage-requirements property-set and a list of virtual
         targets. Should be overriden in derived classes.
       </para>
     </listitem>

Deleted: branches/release/tools/build/v2/doc/src/catalog.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/catalog.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,9 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE catalog
- PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
- "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
-<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
- <rewriteURI uriStartString="http://www.boost.org/tools/boostbook/dtd/" rewritePrefix="file:///home/ccurrie/src/boost/tools/boostbook/dtd//"/>
- <rewriteURI uriStartString="http://docbook.sourceforge.net/release/xsl/current/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-xsl-1.64.1/"/>
- <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2/" rewritePrefix="file:///shared/ccurrie/share/sgml/docbook/docbook-dtd-4.2/"/>
-</catalog>

Modified: branches/release/tools/build/v2/doc/src/extending.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/extending.xml (original)
+++ branches/release/tools/build/v2/doc/src/extending.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -76,17 +76,20 @@
         in Jamfile, such as metatarget kind, name, sources and properties,
         and can be called with specific properties to generate concrete
         targets. At the code level it is represented by an instance of
- class derived from <classname>abstract-target</classname>.
+ class derived from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
         <footnote><para>This name is historic, and will be eventuall changed to
         <code>metatarget</code></para></footnote>
         </para>
         
- <para>The <methodname>generate</methodname> method takes the build properties
- (as an instance of the <classname>property-set</classname> class) and returns
+ <para>The <link linkend="bbv2.reference.class.abstract-target.generate">generate</link>
+ method takes the build properties
+ (as an instance of the <link linkend="bbv2.reference.class.property-set">
+ property-set</link> class) and returns
         a list containing:</para>
         <itemizedlist>
           <listitem><para>As front element&mdash;Usage-requirements from this invocation
- (an instance of <classname>property-set</classname>)</para></listitem>
+ (an instance of <link linkend="bbv2.reference.class.property-set">
+ property-set</link>)</para></listitem>
           <listitem><para>As subsequent elements&mdash;created concrete targets (
           instances of the <classname>virtual-target</classname> class.)</para></listitem>
         </itemizedlist>
@@ -96,47 +99,52 @@
         <code>targets.generate-from-reference</code> function can both
         lookup and generate a metatarget.</para>
         
- <para>The <classname>abstract-target</classname> class has three immediate
- derived classes:</para>
+ <para>The <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>
+ class has three immediate derived classes:</para>
         <itemizedlist>
           
- <listitem><para><classname>project-target</classname> that
+ <listitem><para><link linkend="bbv2.reference.class.project-target">project-target</link> that
           corresponds to a project and is not intended for further
- subclassing. The <methodname>generate</methodname> method of this
+ subclassing. The <link linkend="bbv2.reference.class.project-target.generate">
+ generate</link> method of this
           class builds all targets in the project that are not marked as
           explicit.</para></listitem>
           
- <listitem><para><classname>main-target</classname> corresponds to a target in a project
+ <listitem><para><link linkend="bbv2.reference.class.main-target">main-target</link>
+ corresponds to a target in a project
           and contains one or more target alternatives. This class also should not be
- subclassed. The <methodname>generate</methodname> method of this class selects
- an alternative to build, and calls the <methodname>generate</methodname> method of that
- alternative.</para></listitem>
+ subclassed. The <link linkend="bbv2.reference.class.main-target.generate">generate</link>
+ method of this class selects an alternative to build, and calls the
+ <link linkend="bbv2.reference.class.basic-target.generate">generate</link>
+ method of that alternative.</para></listitem>
           
- <listitem><para><classname>basic-target</classname> corresponds to a
- specific target alternative. This is base class, with a number of
- derived classes. The <methodname>generate</methodname> method
+ <listitem><para><link linkend="bbv2.reference.class.basic-target">basic-target</link>
+ corresponds to a specific target alternative. This is base class,
+ with a number of derived classes. The
+ <link linkend="bbv2.reference.class.basic-target.generate">generate</link> method
           processes the target requirements and requested build properties to
           determine final properties for the target, builds all sources, and
- finally calls the abstract <classname>construct</classname> method with the list
- of source virtual targets, and the final properties.
+ finally calls the abstract
+ <link linkend="bbv2.reference.class.basic-target.construct">construct</link>
+ method with the list of source virtual targets, and the final properties.
           </para></listitem>
           
         </itemizedlist>
         
- <para>The instances of the <classname>project-target</classname> and
- <classname>main-target</classname> classes are created
+ <para>The instances of the <link linkend="bbv2.reference.class.project-target">project-target</link> and
+ <link linkend="bbv2.reference.class.main-target">main-target</link> classes are created
         implicitly&mdash;when loading a new Jamfiles, or when a new target
         alternative with as-yet unknown name is created. The instances of the
- classes derived from <classname>basic-target</classname> are typically
- created when Jamfile calls a <firstterm>metatarget rule</firstterm>,
+ classes derived from <link linkend="bbv2.reference.class.basic-target">basic-target</link>
+ are typically created when Jamfile calls a <firstterm>metatarget rule</firstterm>,
         such as such as <code>exe</code>.
         </para>
         
         <para>It it permissible to create a custom class derived from
- <classname>basic-target</classname> and create new metatarget rule
+ <link linkend="bbv2.reference.class.basic-target">basic-target</link> and create new metatarget rule
         that creates instance of such target. However, in the majority
- of cases, a specific subclass of <classname>basic-target</classname>&mdash;
- <classname>typed-target</classname> is used. That class is associated
+ of cases, a specific subclass of <link linkend="bbv2.reference.class.basic-target">basic-target</link>&mdash;
+ <link linkend="bbv2.reference.class.typed-target">typed-target</link> is used. That class is associated
         with a <firstterm>type</firstterm> and relays to <firstterm>generators</firstterm>
         to construct concrete targets of that type. This process will be explained below.
         When a new type is declared, a new metatarget rule is automatically defined.
@@ -153,8 +161,8 @@
         subclass is <classname>file-target</classname>. A file target is associated
         with an action that creates it&mdash; an instance of the <classname>action</classname>
         class. The action, in turn, hold a list of source targets. It also holds the
- <classname>property-set</classname> instance with the build properties that
- should be used for the action.</para>
+ <link linkend="bbv2.reference.class.property-set">property-set</link>
+ instance with the build properties that should be used for the action.</para>
 
         <para>Here's an example of creating a target from another target, <code>source</code></para>
 <programlisting>
@@ -200,11 +208,12 @@
         fact, Boost.Build defines concept of target type and
         <indexterm><primary>generators</primary></indexterm>
         <firstterm>generators</firstterm>, and has special metatarget class
- <classname>typed-target</classname>. Target type is merely an
+ <link linkend="bbv2.reference.class.typed-target">typed-target</link>. Target type is merely an
         identifier. It is associated with a set of file extensions that
         correspond to that type. Generator is an abstraction of a tool. It advertises
         the types it produces and, if called with a set of input target, tries to construct
- output targets of the advertised types. Finally, <classname>typed-target</classname>
+ output targets of the advertised types. Finally,
+ <link linkend="bbv2.reference.class.typed-target">typed-target</link>
         is associated with specific target type, and relays the generator (or generators)
         for that type.
         </para>
@@ -393,7 +402,7 @@
 type.register VERBATIM : verbatim ;
 </programlisting>
 
- <para>The first parameter to <functionname>type.register</functionname> gives
+ <para>The first parameter to <link linkend="bbv2.reference.modules.type.register">type.register</link> gives
       the name of the declared type. By convention, it's uppercase. The second
       parameter is the suffix for files of this type. So, if Boost.Build sees
       <filename>code.verbatim</filename> in a list of sources, it knows that it's of
@@ -1031,8 +1040,8 @@
   <section id="bbv2.extending.rules">
     <title>Main target rules</title>
     <para>
- A main target rule (e.g “<functionname>exe</functionname>”
- Or “<functionname>lib</functionname>”) creates a top-level target. It's quite likely that you'll want to declare your own and
+ A main target rule (e.g “<link linkend="bbv2.tasks.programs">exe</link>”
+ Or “<link linkend="bbv2.tasks.libraries">lib</link>”) creates a top-level target. It's quite likely that you'll want to declare your own and
       there are two ways to do that.
       <!-- Why did "that" get changed to "this" above? -->
     </para>

Modified: branches/release/tools/build/v2/doc/src/faq.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/faq.xml (original)
+++ branches/release/tools/build/v2/doc/src/faq.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1,11 +1,11 @@
-<?xml version="1.0" standalone="yes"?>
-<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
      "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
 
 <chapter id="bbv2.faq">
   <title>Frequently Asked Questions</title>
 
- <section>
+ <section id="bbv2.faq.featurevalue">
     <title>
       How do I get the current value of feature in Jamfile?
     </title>
@@ -13,7 +13,7 @@
     <para>
       This is not possible, since Jamfile does not have "current" value of any
       feature, be it toolset, build variant or anything else. For a single
- invocation of <filename>bjam</filename>, any given main target can be
+ run of Boost.Build, any given main target can be
       built with several property sets. For example, user can request two build
       variants on the command line. Or one library is built as shared when used
       from one application, and as static when used from another. Each Jamfile
@@ -41,7 +41,7 @@
     </itemizedlist>
   </section>
 
- <section>
+ <section id="bbv2.faq.duplicate">
     <title>
       I am getting a "Duplicate name of actual target" error. What does that
       mean?
@@ -174,7 +174,7 @@
     </para>
   </section>
 
- <section>
+ <section id="bbv2.faq.proporder">
     <title>
       How to control properties order?
     </title>
@@ -203,7 +203,7 @@
     </para>
   </section>
 
- <section>
+ <section id="bbv2.faq.liborder">
     <title>
       How to control the library linking order on Unix?
     </title>
@@ -257,7 +257,7 @@
     </para>
   </section>
 
- <section>
+ <section id="bbv2.faq.projectroot">
     <title>
       How to get the project root (a.k.a. Jamroot) location?
     </title>
@@ -272,7 +272,7 @@
     </para>
   </section>
 
- <section>
+ <section id="bbv2.faq.flags">
     <title>
       How to change compilation flags for one file?
     </title>

Modified: branches/release/tools/build/v2/doc/src/howto.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/howto.xml (original)
+++ branches/release/tools/build/v2/doc/src/howto.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -28,7 +28,7 @@
     <para>
       If you have questions, please post them to our mailing list (<ulink
       url="http://boost.org/more/mailing_lists.htm#jamboost"/>). The mailing list is
- also mirrowed to newsgroup <ulink url="news://news.gmane.org/gmane.comp.lib.boost.build"/>.
+ also mirrored to the newsgroup <ulink url="news://news.gmane.org/gmane.comp.lib.boost.build"/>.
     </para>
 
   </chapter>

Modified: branches/release/tools/build/v2/doc/src/install.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/install.xml (original)
+++ branches/release/tools/build/v2/doc/src/install.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -29,7 +29,7 @@
       <listitem>
         <simpara>
           Run
- <screen>./bjam install --prefix=<replaceable>PREFIX</replaceable></screen>
+ <screen>./b2 install --prefix=<replaceable>PREFIX</replaceable></screen>
           where <replaceable>PREFIX</replaceable> is a directory where you
           want Boost.Build to be installed.
         </simpara>
@@ -43,15 +43,15 @@
       </listitem>
     </orderedlist>
 
- <para>If you are not using Boost.Build package, but rather the version
+ <para>If you are not using a Boost.Build package, but rather the version
     bundled with the Boost C++ Libraries, the above commands should be run
     in the <filename>tools/build/v2</filename> directory.</para>
 
     <para>
- Now that Boost.Build is installed, you can try some of examples. Copy
+ Now that Boost.Build is installed, you can try some of the examples. Copy
       <filename><replaceable>PREFIX</replaceable>/share/boost-build/examples/hello</filename>
       to a different directory, then change to that directory and run:
-<screen><filename><replaceable>PREFIX</replaceable>/bin/bjam</filename></screen>
+<screen><filename><replaceable>PREFIX</replaceable>/bin/b2</filename></screen>
       A simple executable should be built.
     </para>
 

Copied: branches/release/tools/build/v2/doc/src/main-target.xml (from r77757, /trunk/tools/build/v2/doc/src/main-target.xml)
==============================================================================
--- /trunk/tools/build/v2/doc/src/main-target.xml (original)
+++ branches/release/tools/build/v2/doc/src/main-target.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,9 +9,17 @@
     <primary>main-target</primary>
   </indexterm>
 
- <para>
- Derived from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
+<programlisting language="jam">
+class main-target : <link linkend="bbv2.reference.class.abstract-target">abstract-target</link> {
+ rule <link linkend="bbv2.reference.class.main-target.generate">generate</link> ( property-set )
+
+ # Methods inherited from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>
+ rule <link linkend="bbv2.reference.class.abstract-target.name">name</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.project">project</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.location">location</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.full-name">full-name</link> ( )
+}
+</programlisting>
 
   <para>
     A <link linkend="bbv2.reference.class.main-target">main-target</link>
@@ -20,38 +28,6 @@
 
   <orderedlist>
 
- <listitem id="bbv2.reference.class.main-target.name">
- <code language="jam">rule name ( )</code>
- <para>
- Returns the name of this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.main-target.project">
- <code language="jam">rule project ( )</code>
- <para>
- Returns the project for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.main-target.location">
- <code language="jam">rule location ( )</code>
- <para>
- Return the location where the target was declared. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.main-target.full-name">
- <code language="jam">rule full-name ( )</code>
- <para>
- Returns a user-readable name for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
     <listitem id="bbv2.reference.class.main-target.generate">
       <indexterm zone="bbv2.reference.class.main-target.generate">
         <primary>generate</primary>

Modified: branches/release/tools/build/v2/doc/src/overview.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/overview.xml (original)
+++ branches/release/tools/build/v2/doc/src/overview.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -17,20 +17,20 @@
       Boost.Build actually consists of two parts - Boost.Jam, a build engine
       with its own interpreted language, and Boost.Build itself, implemented in
       Boost.Jam's language. The chain of events when you type
- <command>bjam</command> on the command line is as follows:
+ <command>b2</command> on the command line is as follows:
       <orderedlist>
         <listitem>
           <para>
- Boost.Jam tries to find Boost.Build and loads the top-level module.
- The exact process is described in <xref linkend=
+ The Boost.Build executable tries to find Boost.Build modules and
+ loads the top-level module. The exact process is described in <xref linkend=
             "bbv2.reference.init"/>
           </para>
         </listitem>
         <listitem>
           <para>
             The top-level module loads user-defined configuration files,
- <filename>user-config.jam</filename> and <filename>site-config.jam
- </filename>, which define available toolsets.
+ <filename>user-config.jam</filename> and
+ <filename>site-config.jam</filename>, which define available toolsets.
           </para>
         </listitem>
         <listitem>
@@ -97,8 +97,8 @@
 a.o: a.c
     g++ -o a.o -g a.c
 </programlisting>
- This is rather low-level description mechanism and it's hard to adjust commands, options,
- and sets of created targets depending on the used compiler and operating system.
+ This is a rather low-level description mechanism and it's hard to adjust commands, options,
+ and sets of created targets depending on the compiler and operating system used.
       </para>
 
       <para>
@@ -107,20 +107,20 @@
 <programlisting>
 add_program ("a", "a.c")
 </programlisting>
- This is a function call that creates targets necessary to create executable file
- from source file <filename>a.c</filename>. Depending on configured properties,
- different commands line may be used. However, <code>add_program</code> is higher-level,
- but rather thin level. All targets are created immediately when build description
+ This is a function call that creates the targets necessary to create a executable file
+ from the source file <filename>a.c</filename>. Depending on configured properties,
+ different command lines may be used. However, <code>add_program</code> is higher-level,
+ but rather thin level. All targets are created immediately when the build description
         is parsed, which makes it impossible to perform multi-variant builds. Often, change
- in any build property requires complete reconfiguration of the build tree.
+ in any build property requires a complete reconfiguration of the build tree.
       </para>
 
       <para>
- In order to support true multivariant builds, Boost.Build introduces the concept of
+ In order to support true multivariant builds, Boost.Build introduces the concept of a
         <indexterm> <primary>metatarget</primary> <secondary>definition</secondary></indexterm>
         <indexterm> <primary>main target</primary> <see>metataget</see> </indexterm>
- <firstterm>metatarget</firstterm>&mdash;object that is created when build description
- is parsed and can be later called with specific build properties to generate
+ <firstterm>metatarget</firstterm>&mdash;an object that is created when the build description
+ is parsed and can be called later with specific build properties to generate
         actual targets.
       </para>
 
@@ -130,11 +130,11 @@
 exe a : a.cpp ;
 </programlisting>
         When this declaration is parsed, Boost.Build creates a metatarget, but does not
- yet decides what files must be created, or what commands must be used. After
- all build files are parsed, Boost.Build considers properties requested on the
+ yet decide what files must be created, or what commands must be used. After
+ all build files are parsed, Boost.Build considers the properties requested on the
         command line. Supposed you have invoked Boost.Build with:
 <screen>
-bjam toolset=gcc toolset=msvc
+b2 toolset=gcc toolset=msvc
 </screen>
         In that case, the metatarget will be called twice, once with <code>toolset=gcc</code>
         and once with <code>toolset=msvc</code>. Both invocations will produce concrete
@@ -142,9 +142,9 @@
       </para>
 
       <para>
- Another key concept is
+ Another key concept is
         <indexterm><primary>property</primary><secondary>definition</secondary></indexterm>
- <firstterm>build property</firstterm>. Build property is a variable
+ <firstterm>build property</firstterm>. A build property is a variable
         that affects the build process. It can be specified on the command line, and is
         passed when calling a metatarget. While all build tools have a similar mechanism,
         Boost.Build differs by requiring that all build properties are declared in advance,
@@ -158,12 +158,12 @@
         "top-level" metatargets are called with the properties specified on the command line.
         Each metatarget can elect to augment or override some properties (in particular,
         using the requirements mechanism, see <xref linkend="bbv2.overview.targets.requirements"/>).
- Then, the dependency metatargets are called with modified properties and produce
- concrete targets that are then used in build process. Of course, dependency metatargets
+ Then, the dependency metatargets are called with the modified properties and produce
+ concrete targets that are then used in the build process. Of course, dependency metatargets
         maybe in turn modify build properties and have dependencies of their own.
       </para>
 
- <para>For more in-depth treatment of the requirements and concepts, you may refer
+ <para>For a more in-depth treatment of the requirements and concepts, you may refer
       to <ulink url="http://syrcose.ispras.ru/2009/files/04_paper.pdf">SYRCoSE 2009 Boost.Build article</ulink>.
       </para>
            
@@ -173,8 +173,8 @@
       <title>Boost.Jam Language</title>
 
       <para>
- This section will describe the basics of the Boost.Jam language&#x2014;
- just enough for writing Jamfiles. For more information, please see the
+ This section will describe the basics of the Boost.Jam language&#x2014;just
+ enough for writing Jamfiles. For more information, please see the
         <link linkend="bbv2.jam">Boost.Jam</link> documentation.
       </para>
 
@@ -182,8 +182,8 @@
         <link linkend="bbv2.jam">Boost.Jam</link> has an interpreted, procedural
         language. On the lowest level, a <link linkend="bbv2.jam">Boost.Jam
         </link> program consists of variables and <indexterm><primary>rule
- </primary></indexterm> <firstterm>rules</firstterm> (Jam term for
- function). They are grouped into modules&#x2014;there is one global
+ </primary></indexterm> <firstterm>rules</firstterm> (the Jam term for
+ functions). They are grouped into modules&#x2014;there is one global
         module and a number of named modules. Besides that, a <link linkend=
         "bbv2.jam">Boost.Jam</link> program contains classes and class
         instances.
@@ -325,7 +325,7 @@
 import <replaceable>module</replaceable> ;
 import <replaceable>module</replaceable> : <replaceable>rule</replaceable> ;
 </programlisting>
- The first form imports the specified bjam module. All rules from that
+ The first form imports the specified module. All rules from that
         module are made available using the qualified name: <code><replaceable>
         module</replaceable>.<replaceable>rule</replaceable></code>. The second
         form imports the specified rules only, and they can be called using
@@ -333,8 +333,8 @@
       </para>
 
       <para id="bbv2.overview.jam_language.actions">
- Sometimes, you'd need to specify the actual command lines to be used
- when creating targets. In jam language, you use named actions to do
+ Sometimes, you need to specify the actual command lines to be used
+ when creating targets. In the jam language, you use named actions to do
         this. For example:
 <programlisting>
 actions create-file-from-another
@@ -350,8 +350,8 @@
       </para>
 
       <para>
- To flexibly adjust the command line, you can define a rule with the same
- name as the action and taking three parameters -- targets, sources and
+ To adjust the command line flexibly, you can define a rule with the same
+ name as the action and taking three parameters&mdash;targets, sources and
         properties. For example:
 <programlisting>
 rule create-file-from-another ( targets * : sources * : properties * )
@@ -366,8 +366,8 @@
     create-file-from-another $(OPTIONS) $(&lt;) $(&gt;)
 }
 </programlisting>
- In this example, the rule checks if certain build property is specified.
- If so, it sets variable <varname>OPIONS</varname> that is then used
+ In this example, the rule checks if a certain build property is specified.
+ If so, it sets the variable <varname>OPIONS</varname> that is then used
         inside the action. Note that the variables set "on a target" will be
         visible only inside actions building that target, not globally. Were
         they set globally, using variable named <varname>OPTIONS</varname> in
@@ -375,7 +375,7 @@
       </para>
 
       <para>
- More details can be found in Jam reference, <xref
+ More details can be found in the Jam reference, <xref
         linkend="jam.language.rules"/>.
       </para>
     </section>
@@ -386,9 +386,9 @@
     <para>
       On startup, Boost.Build searches and reads two configuration files:
       <filename>site-config.jam</filename> and <filename>user-config.jam</filename>.
- The first one is usually installed and maintained by system administrator, and
- the second is for user to modify. You can edit the one in the top-level
- directory of Boost.Build installation or create a copy in your home
+ The first one is usually installed and maintained by a system administrator, and
+ the second is for the user to modify. You can edit the one in the top-level
+ directory of your Boost.Build installation or create a copy in your home
       directory and edit the copy. The following table explains where both files
       are searched.
     </para>
@@ -453,7 +453,7 @@
     </tip>
 
     <para>
- Usually, <filename>user-config.jam</filename> just defines available compilers
+ Usually, <filename>user-config.jam</filename> just defines the available compilers
       and other tools (see <xref linkend="bbv2.recipies.site-config"/> for more advanced
       usage). A tool is configured using the following syntax:
     </para>
@@ -462,7 +462,7 @@
 using <replaceable>tool-name</replaceable> : ... ;
 </programlisting>
 <para>
- The <functionname>using</functionname> rule is given a name of tool, and
+ The <code language="jam">using</code> rule is given the name of tool, and
       will make that tool available to Boost.Build. For example,
 <programlisting>
 using gcc ;
@@ -476,9 +476,9 @@
     </para>
 
     <para>
- For all the C++ compiler toolsets Boost.Build supports
+ For all the C++ compiler toolsets that Boost.Build supports
       out-of-the-box, the list of parameters to
- <functionname>using</functionname> is the same: <parameter
+ <code language="jam">using</code> is the same: <parameter
       class="function">toolset-name</parameter>, <parameter
       class="function">version</parameter>, <parameter
       class="function">invocation-command</parameter>, and <parameter
@@ -509,8 +509,8 @@
     <para>
       Some Boost.Build toolsets will use that path to take additional actions
       required before invoking the compiler, such as calling vendor-supplied
- scripts to set up its required environment variables. When compiler
- executables for C and C++ are different, path to the C++ compiler
+ scripts to set up its required environment variables. When the compiler
+ executables for C and C++ are different, the path to the C++ compiler
       executable must be specified. The command can
       be any command allowed by the operating system. For example:
 <programlisting>
@@ -521,13 +521,13 @@
 
     <para>
       To configure several versions of a toolset, simply invoke the
- <functionname>using</functionname> rule multiple times:
+ <code language="jam">using</code> rule multiple times:
 <programlisting>
 using gcc : 3.3 ;
 using gcc : 3.4 : g++-3.4 ;
 using gcc : 3.2 : g++-3.2 ;
 </programlisting>
- Note that in the first call to <functionname>using</functionname>, the
+ Note that in the first call to <code language="jam">using</code>, the
       compiler found in the <envar>PATH</envar> will be used, and there is no
       need to explicitly specify the command.
     </para>
@@ -581,13 +581,13 @@
     <section id="bbv2.overview.invocation">
       <title>Invocation</title>
 
- <para>To invoke Boost.Build, type <command>bjam</command> on the command line. Three kinds
+ <para>To invoke Boost.Build, type <command>b2</command> on the command line. Three kinds
       of command-line tokens are accepted, in any order:</para>
       <variablelist>
         <varlistentry>
           <term>options</term>
 
- <listitem><para>Options start with either dash, or two dashes. The standard options
+ <listitem><para>Options start with either one or two dashes. The standard options
           are listed below, and each project may add additional options</para></listitem>
         </varlistentry>
 
@@ -595,8 +595,8 @@
           <term>properties</term>
 
           <listitem><para>Properties specify details of what you want to build (e.g. debug
- or release variant). Syntactically, all command line tokens with equal sign in them
- are considered to specify properties. In the simplest form, property looks like
+ or release variant). Syntactically, all command line tokens with an equal sign in them
+ are considered to specify properties. In the simplest form, a property looks like
           <command><replaceable>feature</replaceable>=<replaceable>value</replaceable></command>
           </para></listitem>
         </varlistentry>
@@ -613,22 +613,22 @@
       <section id="bbv2.overview.invocation.examples">
         <title>Examples</title>
        
- <para>To build all targets defined in Jamfile in the current directory with default properties, run:
+ <para>To build all targets defined in the Jamfile in the current directory with the default properties, run:
 <screen>
-bjam
+b2
 </screen>
         </para>
 
         <para>To build specific targets, specify them on the command line:
 <screen>
-bjam lib1 subproject//lib2
+b2 lib1 subproject//lib2
 </screen>
         </para>
 
         <para>To request a certain value for some property, add <literal>
         <replaceable>property</replaceable>=<replaceable>value</replaceable></literal> to the command line:
 <screen>
-bjam toolset=gcc variant=debug optimization=space
+b2 toolset=gcc variant=debug optimization=space
 </screen>
         </para>
       </section>
@@ -673,8 +673,8 @@
           <varlistentry>
             <term><option>--build-dir</option></term>
             <listitem>
- <para>Changes build directories for all project roots being built. When
- this option is specified, all Jamroot files should declare project name.
+ <para>Changes the build directories for all project roots being built. When
+ this option is specified, all Jamroot files must declare a project name.
               The build directory for the project root will be computed by concatanating
               the value of the <option>--build-dir</option> option, the project name
               specified in Jamroot, and the build dir specified in Jamroot
@@ -690,7 +690,7 @@
           <varlistentry>
             <term><option>--version</option></term>
             <listitem>
- <para>Prints information on Boost.Build and Boost.Jam
+ <para>Prints information on the Boost.Build and Boost.Jam
               versions.
               </para>
             </listitem>
@@ -713,7 +713,7 @@
           <varlistentry>
             <term><option>-q</option></term>
             <listitem>
- <para>Stop at first error, as opposed to continuing to build targets
+ <para>Stop at the first error, as opposed to continuing to build targets
               that don't depend on the failed ones.</para>
             </listitem>
           </varlistentry>
@@ -728,7 +728,7 @@
           <varlistentry>
             <term><option>--debug-configuration</option></term>
             <listitem>
- <para>Produces debug information about loading of Boost.Build
+ <para>Produces debug information about the loading of Boost.Build
               and toolset files.</para>
             </listitem>
           </varlistentry>
@@ -744,7 +744,7 @@
           <varlistentry>
             <term><option>--debug-generators</option></term>
             <listitem>
- <para>Produces debug output from generator search process.
+ <para>Produces debug output from the generator search process.
               Useful for debugging custom generators.
               </para>
             </listitem>
@@ -753,8 +753,8 @@
           <varlistentry>
             <term><option>--ignore-config</option></term>
             <listitem>
- <para>Do not load <literal>site-config.jam</literal> and
- <literal>user-config.jam</literal> configuration files.
+ <para>Do not load <literal>site-config.jam</literal> or
+ <literal>user-config.jam</literal>.
               </para>
             </listitem>
           </varlistentry>
@@ -937,11 +937,12 @@
           </tgroup>
         </table>
 
- If you have more than one version of a given C++ toolset (e.g. configured in
+ <para>If you have more than one version of a given C++ toolset (e.g. configured in
         <filename>user-config.jam</filename>, or autodetected, as happens with msvc), you can
         request the specific version by passing
         <code><replaceable>toolset</replaceable>-<replaceable>version</replaceable></code> as
         the value of the <code>toolset</code> feature, for example <code>toolset=msvc-8.0</code>.
+ </para>
 
 
         <para>
@@ -951,21 +952,21 @@
           once for each specified value of a feature. For example, if you use
         </para>
 <screen>
-bjam link=static link=shared threading=single threading=multi
+b2 link=static link=shared threading=single threading=multi
 </screen>
         <para>
           Then a total of 4 builds will be performed. For convenience,
           instead of specifying all requested values of a feature in separate command line elements,
- you can separate the values with commands, for example:
+ you can separate the values with commas, for example:
         </para>
 <screen>
-bjam link=static,shared threading=single,multi
+b2 link=static,shared threading=single,multi
 </screen>
         <para>
- The comma has special meaning only if the feature has a fixed set of values, so
+ The comma has this special meaning only if the feature has a fixed set of values, so
         </para>
 <screen>
-bjam include=static,shared
+b2 include=static,shared
 </screen>
         <para>is not treated specially.</para>
                 
@@ -1068,7 +1069,7 @@
       </para>
 
       <para>The actual requirements for a target are obtained by refining
- requirements of the project where a target is declared with the
+ the requirements of the project where the target is declared with the
       explicitly specified requirements. The same is true for
       usage-requirements. More details can be found in
       <xref linkend="bbv2.reference.variants.proprefine"/>
@@ -1108,7 +1109,8 @@
         files. Sometimes, you'll want to automatically construct the
         list of source files rather than having to spell it out
         manually, in which case you can use the
- <functionname>glob</functionname> rule. Here are two examples:</para>
+ <link linkend="bbv2.reference.rules.glob">glob</link> rule.
+ Here are two examples:</para>
 <programlisting>
 exe a : a.cpp ; # a.cpp is the only source file
 exe b : [ glob *.cpp ] ; # all .cpp files in this directory are sources
@@ -1158,7 +1160,7 @@
 <programlisting>
 exe hello : hello.cpp : &lt;include&gt;/opt/boost &lt;define&gt;MY_DEBUG ;
 </programlisting>
- There is a number of other features, listed in
+ There are a number of other features, listed in
         <xref linkend="bbv2.overview.builtins.features"/>. For example if
         a library can only be built statically, or a file can't be compiled
         with optimization due to a compiler bug, one can use
@@ -1221,13 +1223,13 @@
 
         <para>Requirements explicitly specified for a target are usually
         combined with the requirements specified for the containing project. You
- can cause a target to completely ignore specific project's requirement
- using the syntax by adding a minus sign before a property, for example:
+ can cause a target to completely ignore a specific project requirement
+ using the syntax by adding a minus sign before the property, for example:
 <programlisting>
 exe main : main.cpp : <emphasis role="bold">-&lt;define&gt;UNNECESSARY_DEFINE</emphasis> ;
 </programlisting>
- This syntax is the only way to ignore free properties from a parent,
- such as defines. It can be also useful for ordinary properties. Consider
+ This syntax is the only way to ignore free properties, such as defines,
+ from a parent. It can be also useful for ordinary properties. Consider
         this example:
 <programlisting>
 project test : requirements &lt;threading&gt;multi ;
@@ -1235,12 +1237,12 @@
 exe test2 : test2.cpp : &lt;threading&gt;single ;
 exe test3 : test3.cpp : -&lt;threading&gt;multi ;
 </programlisting>
- Here, <code>test1</code> inherits project requirements and will always
+ Here, <code>test1</code> inherits the project requirements and will always
         be built in multi-threaded mode. The <code>test2</code> target
- <emphasis>overrides</emphasis> project's requirements and will
+ <emphasis>overrides</emphasis> the project's requirements and will
         always be built in single-threaded mode. In contrast, the
         <code>test3</code> target <emphasis>removes</emphasis> a property
- from project requirements and will be built either in single-threaded or
+ from the project requirements and will be built either in single-threaded or
         multi-threaded mode depending on which variant is requested by the
         user.</para>
 
@@ -1260,7 +1262,7 @@
 </programlisting>
         would build a multi-threaded target unless the user
         explicitly requests a single-threaded version. The difference between
- requirements and default-build is that requirements cannot be
+ the requirements and the default-build is that the requirements cannot be
         overridden in any way.
         </para>
       </section>
@@ -1276,7 +1278,7 @@
           it. We can express this situation using <firstterm>target
           alternatives</firstterm>:
 <programlisting>
-lib demangler : dummy_demangler.cpp ; # alternative 1
+lib demangler : dummy_demangler.cpp ; # alternative 1
 lib demangler : demangler_gcc.cpp : &lt;toolset&gt;gcc ; # alternative 2
 lib demangler : demangler_msvc.cpp : &lt;toolset&gt;msvc ; # alternative 3
 </programlisting>
@@ -1299,13 +1301,13 @@
            optimization. When referring to an inline main target, its declared
            name must be prefixed by its parent target's name and two dots. In
            the example above, to build only helpers, one should run
- <code>bjam hello..helpers</code>.
+ <code>b2 hello..helpers</code>.
          </para>
 
          <para>When no target is requested on the command line, all targets in the
          current project will be built. If a target should be built only by
          explicit request, this can be expressed by the
- <functionname>explicit</functionname> rule:
+ <link linkend="bbv2.reference.rules.explicit">explicit</link> rule:
          <programlisting>
 explicit install_programs ;</programlisting>
          </para>
@@ -1325,7 +1327,7 @@
       </para>
 
       <para>Projects are named using the
- <functionname>project</functionname> rule, which has the
+ <code language="jam">project</code> rule, which has the
       following syntax:
 <programlisting>
 project <replaceable>id</replaceable> : <replaceable>attributes</replaceable> ;
@@ -1388,7 +1390,7 @@
 
                 <entry>Default value</entry>
 
- <entry>Handling by the <functionname>project</functionname>
+ <entry>Handling by the <code language="jam">project</code>
                 rule</entry>
 
               </row>
@@ -1541,7 +1543,7 @@
         The command line specifies which targets to build and with which
         properties. For example:
 <programlisting>
-bjam app1 lib1//lib1 toolset=gcc variant=debug optimization=full
+b2 app1 lib1//lib1 toolset=gcc variant=debug optimization=full
 </programlisting>
         would build two targets, "app1" and "lib1//lib1" with the specified
         properties. You can refer to any targets, using
@@ -1549,7 +1551,7 @@
         properties. Some of the properties are very common, and for them the name
         of the property can be omitted. For example, the above can be written as:
 <programlisting>
-bjam app1 lib1//lib1 gcc debug optimization=full
+b2 app1 lib1//lib1 gcc debug optimization=full
 </programlisting>
         The complete syntax, which has some additional shortcuts, is
         described in <xref linkend="bbv2.overview.invocation"/>.
@@ -1640,7 +1642,7 @@
     <section><title>Building a Project</title>
 
       <para>Often, a user builds a complete project, not just one main
- target. In fact, invoking <command>bjam</command> without
+ target. In fact, invoking <command>b2</command> without
       arguments
       <!-- do you know the difference between parameters and
            arguments? I only learned this year -->

Copied: branches/release/tools/build/v2/doc/src/project-target.xml (from r77757, /trunk/tools/build/v2/doc/src/project-target.xml)
==============================================================================
--- /trunk/tools/build/v2/doc/src/project-target.xml (original)
+++ branches/release/tools/build/v2/doc/src/project-target.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,10 +8,22 @@
   <indexterm>
     <primary>project-target</primary>
   </indexterm>
-
- <para>
- Derived from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
+
+<programlisting language="jam">
+class project-target : <link linkend="bbv2.reference.class.abstract-target">abstract-target</link> {
+ rule <link linkend="bbv2.reference.class.project-target.generate">generate</link> ( property-set )
+ rule <link linkend="bbv2.reference.class.project-target.build-dir">build-dir</link> ( )
+ rule <link linkend="bbv2.reference.class.project-target.main-target">main-target</link> ( name )
+ rule <link linkend="bbv2.reference.class.project-target.has-main-target">has-main-target</link> ( name )
+ rule <link linkend="bbv2.reference.class.project-target.find">find</link> ( id : no-error ? )
+
+ # Methods inherited from <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>
+ rule <link linkend="bbv2.reference.class.abstract-target.name">name</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.project">project</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.location">location</link> ( )
+ rule <link linkend="bbv2.reference.class.abstract-target.full-name">full-name</link> ( )
+}
+</programlisting>
 
   <para>
     This class has the following responsibilities:
@@ -23,59 +35,9 @@
       </listitem>
     </itemizedlist>
   </para>
-
- <para>
- Main targets are constructed in two stages:
- <itemizedlist>
- <listitem>
- <para>
- When Jamfile is read, a number of calls to 'add-alternative' are made. At
- that time, alternatives can also be renamed to account for inline targets.
- </para>
- </listitem>
- <listitem>
- <para>
- The first time 'main-target' or 'has-main-target' rule is called, all
- alternatives are enumerated and main targets are created.
- </para>
- </listitem>
- </itemizedlist>
- </para>
 
   <orderedlist>
 
- <listitem id="bbv2.reference.class.project-target.name">
- <code language="jam">rule name ( )</code>
- <para>
- Returns the name of this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.project-target.project">
- <code language="jam">rule project ( )</code>
- <para>
- Returns the project for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.project-target.location">
- <code language="jam">rule location ( )</code>
- <para>
- Return the location of the project. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
- <listitem id="bbv2.reference.class.project-target.full-name">
- <code language="jam">rule full-name ( )</code>
- <para>
- Returns a user-readable name for this target. Inherited from
- <link linkend="bbv2.reference.class.abstract-target">abstract-target</link>.
- </para>
- </listitem>
-
     <listitem id="bbv2.reference.class.project-target.generate">
       <indexterm zone="bbv2.reference.class.project-target.generate">
         <primary>generate</primary>
@@ -117,7 +79,9 @@
       <code language="jam">rule main-target ( name )</code>
       <para>
         Returns a <link linkend="bbv2.reference.class.main-target">main-target</link>
- class instance corresponding to <literal>name</literal>.</para>
+ class instance corresponding to <literal>name</literal>.
+ Can only be called after the project has been fully loaded.
+ </para>
     </listitem>
 
     <listitem id="bbv2.reference.class.project-target.has-main-target">
@@ -129,6 +93,7 @@
       <para>
         Returns whether a <link linkend="bbv2.reference.class.main-target">main-target</link>
         with the specified name exists.
+ Can only be called after the project has been fully loaded.
       </para>
     </listitem>
 

Modified: branches/release/tools/build/v2/doc/src/reference.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/reference.xml (original)
+++ branches/release/tools/build/v2/doc/src/reference.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -45,7 +45,7 @@
 boost-build build-system ;
 </programlisting>
 
- In this case, running bjam anywhere in the project tree will
+ In this case, running <command>b2</command> anywhere in the project tree will
         automatically find the build system.</para>
 
       <para>The default <filename>bootstrap.jam</filename>, after loading some standard
@@ -126,7 +126,7 @@
         <link linkend="bbv2.main-target-rule-syntax">common syntax</link>.</para></listitem>
       </varlistentry>
 
- <varlistentry>
+ <varlistentry id="bbv2.reference.rules.glob">
         <term><literal>glob</literal></term>
 
         <listitem><para>The <code>glob</code> rule takes a list shell pattern
@@ -178,7 +178,7 @@
         </para></listitem>
       </varlistentry>
 
- <varlistentry>
+ <varlistentry id="bbv2.reference.rules.explicit">
         <term><literal>explicit</literal></term>
 
         <listitem><para>The <literal>explicit</literal> rule takes a single
@@ -227,13 +227,13 @@
 
         <listitem><para>Same as <literal>constant</literal> except that
         the value is treated as path relative to Jamfile location. For example,
- if <command>bjam</command> is invoked in the current directory,
+ if <command>b2</command> is invoked in the current directory,
         and Jamfile in <filename>helper</filename> subdirectory has:
         <programlisting>
 path-constant DATA : data/a.txt ;
         </programlisting>
         then the variable <varname>DATA</varname> will be set to
- <literal>helper/data/a.txt</literal>, and if <command>bjam</command>
+ <literal>helper/data/a.txt</literal>, and if <command>b2</command>
         is invoked from the <filename>helper</filename> directory, then
         the variable <varname>DATA</varname> will be set to
         <literal>data/a.txt</literal>.
@@ -411,7 +411,7 @@
             feature, except that it takes effect only for linking. When you want
             to link all targets in a Jamfile to certain library, the
             <code>&lt;library&gt;</code> feature is preferred over
- <code>&lt;source&gt;X</code> -- the latter will add the library to
+ <code>&lt;source&gt;X</code>&mdash;the latter will add the library to
             all targets, even those that have nothing to do with libraries.
           </simpara>
         </listitem>
@@ -455,6 +455,20 @@
         </listitem>
       </varlistentry>
 
+ <varlistentry><term><anchor id="bbv2.builtin.features.implicit-dependency"/>
+ <literal>implicit-dependency</literal></term>
+ <indexterm><primary>implicit-dependency</primary></indexterm>
+
+ <listitem>
+ <simpara>
+ Indicates that the target named by the value of this feature
+ may produce files that are included by the sources of the
+ target being declared. See <xref linkend="bbv2.reference.generated_headers"/>
+ for more information.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
 
       <varlistentry><term><anchor id="bbv2.builtin.features.use"/>
           <literal>use</literal></term>
@@ -1761,6 +1775,194 @@
 
     </section>
 
+ <section id="bbv2.reference.modules">
+ <title>Builtin modules</title>
+
+ <para>
+ This section describes the modules that are provided
+ by Boost.Build. The import rule allows rules from
+ one module to be used in another module or Jamfile.
+ </para>
+
+ <section id="bbv2.reference.modules.modules">
+ <title>modules</title>
+ <indexterm><primary>modules</primary></indexterm>
+
+ <para>
+ The <code>modules</code> module defines basic functionality
+ for handling modules.
+ </para>
+
+ <para>
+ A module defines a number of rules that can be used in other
+ modules. Modules can contain code at the top level to initialize
+ the module. This code is executed the first time the
+ module is loaded.
+ <note>
+ <para>
+ A Jamfile is a special kind of module which is managed by
+ the build system. Although they cannot be loaded directly
+ by users, the other features of modules are still useful
+ for Jamfiles.
+ </para>
+ </note>
+ </para>
+
+ <para>
+ Each module has its own namespaces for variables and rules. If two
+ modules A and B both use a variable named X, each one gets its own
+ copy of X. They won't interfere with each other in any way.
+ Similarly, importing rules into one module has no effect on any other
+ module.
+ </para>
+
+ <para>
+ Every module has two special variables.
+ <code>$(__file__)</code> contains the name of the file that
+ the module was loaded from and <code>$(__name__)</code>
+ contains the name of the module.
+ <note><para><code>$(__file__)</code> does not contain
+ the full path to the file. If you need this, use
+ <code>modules.binding</code>.</para></note>
+ </para>
+
+ <orderedlist>
+
+ <listitem id="bbv2.reference.modules.modules.binding">
+ <indexterm zone="bbv2.reference.modules.modules.binding"><primary>binding</primary></indexterm>
+ <code language="jam">rule binding ( module-name )</code>
+ <para>Returns the filesystem binding of the given module.</para>
+ <para>For example, a module can get its own location with:
+ <programlisting language="jam">me = [ modules.binding $(__name__) ] ;</programlisting>
+ </para>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.poke">
+ <indexterm zone="bbv2.reference.modules.modules.poke"><primary>poke</primary></indexterm>
+ <code language="jam">rule poke ( module-name ? : variables + : value * )</code>
+ <para>Sets the module-local value of a variable.</para>
+ <para>For example, to set a variable in the global module:
+ <programlisting language="jam">modules.poke : ZLIB_INCLUDE : /usr/local/include ;</programlisting>
+ </para>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.peek">
+ <indexterm zone="bbv2.reference.modules.modules.peek"><primary>peek</primary></indexterm>
+ <code language="jam">rule peek ( module-name ? : variables + )</code>
+ <para>Returns the module-local value of a variable.</para>
+ <para>
+ For example, to read a variable from the global module:
+ <programlisting language="jam">local ZLIB_INCLUDE = [ modules.peek : ZLIB_INCLUDE ] ;</programlisting>
+ </para>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.call-in">
+ <indexterm zone="bbv2.reference.modules.modules.call-in"><primary>call-in</primary></indexterm>
+ <code language="jam">rule call-in ( module-name ? : rule-name args * : * ) </code>
+ <para>Call the given rule locally in the given module. Use
+ this for rules accepting rule names as arguments, so that
+ the passed rule may be invoked in the context of the rule's
+ caller (for example, if the rule accesses module globals or
+ is a local rule).
+ <note><para>rules called this way may accept at most
+ 8 parameters.</para></note></para>
+ <para>Example:
+<programlisting language="jam">
+rule filter ( f : values * )
+{
+ local m = [ CALLER_MODULE ] ;
+ local result ;
+ for v in $(values)
+ {
+ if [ modules.call-in $(m) : $(f) $(v) ]
+ {
+ result += $(v) ;
+ }
+ }
+ return result ;
+}
+</programlisting>
+ </para>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.load">
+ <indexterm zone="bbv2.reference.modules.modules.load"><primary>load</primary></indexterm>
+ <code language="jam">rule load ( module-name : filename ? : search * )</code>
+ <para>Load the indicated module if it is not already loaded.</para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>module-name</literal></term>
+ <listitem><para>Name of module to load.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ <variablelist>
+ <varlistentry>
+ <term><literal>filename</literal></term>
+ <listitem><para>(partial) path to file; Defaults to <code>$(module-name).jam</code></para></listitem>
+ </varlistentry>
+ </variablelist>
+ <variablelist>
+ <varlistentry>
+ <term><literal>search</literal></term>
+ <listitem><para>Directories in which to search for filename.
+ Defaults to <code>$(BOOST_BUILD_PATH)</code>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.import">
+ <indexterm zone="bbv2.reference.modules.modules.import"><primary>import</primary></indexterm>
+ <code language="jam">rule import ( module-names + : rules-opt * : rename-opt * )</code>
+ <para>Load the indicated module and import rule names into the
+ current module. Any members of <code>rules-opt</code> will be
+ available without qualification in the caller's module. Any
+ members of <code>rename-opt</code> will be taken as the names
+ of the rules in the caller's module, in place of the names they
+ have in the imported module. If <code>rules-opt = '*'</code>,
+ all rules from the indicated module are imported into the
+ caller's module. If <code>rename-opt</code> is supplied, it must have the
+ same number of elements as <code>rules-opt</code>.</para>
+ <note><para>The <literal>import</literal> rule is available
+ without qualification in all modules.</para></note>
+ <para>Examples:
+<programlisting language="jam">
+import path ;
+import path : * ;
+import path : join ;
+import path : native make : native-path make-path ;
+</programlisting>
+ </para>
+ </listitem>
+
+ <listitem id="bbv2.reference.modules.modules.clone-rules">
+ <indexterm zone="bbv2.reference.modules.modules.clone-rules"><primary>clone-rules</primary></indexterm>
+ <code language="jam">rule clone-rules ( source-module target-module )</code>
+ <para>Define exported copies in <code>$(target-module)</code>
+ of all rules exported from <code>$(source-module)</code>. Also
+ make them available in the global module with qualification,
+ so that it is just as though the rules were defined originally
+ in <code>$(target-module)</code>.</para>
+ </listitem>
+
+ </orderedlist>
+
+ </section>
+
+ <xi:include href="path.xml"/>
+ <xi:include href="type.xml"/>
+
+ </section>
+
+ <section id="bbv2.reference.class">
+ <title>Builtin classes</title>
+ <xi:include href="abstract-target.xml"/>
+ <xi:include href="project-target.xml"/>
+ <xi:include href="main-target.xml"/>
+ <xi:include href="basic-target.xml"/>
+ <xi:include href="typed-target.xml"/>
+ <xi:include href="property-set.xml"/>
+ </section>
+
   <section id="bbv2.reference.buildprocess">
     <title>Build process</title>
 
@@ -1883,7 +2085,46 @@
 </programlisting>
       </para>
 
- </section>
+ </section>
+
+ <section id="bbv2.reference.buildprocess.targetpath">
+ <title>Target Paths</title>
+
+ <para>Several factors determine the location of a concrete
+ file target. All files in a project are built under
+ the directory bin unless this is overriden by the build-dir project
+ attribute. Under bin is a path that depends on the properties
+ used to build each target. This path is uniquely determined by
+ all non-free, non-incidental properties. For example,
+ given a property set containing:
+ <code>&lt;toolset&gt;gcc &lt;toolset-gcc:version&gt;4.6.1 &lt;variant&gt;debug
+ &lt;warnings&gt;all &lt;define&gt;_DEBUG &lt;include&gt;/usr/local/include
+ &lt;link&gt;static</code>,
+ the path will be gcc-4.6.1/debug/link-static. &lt;warnings&gt; is an
+ incidental feature and &lt;define&gt; and &lt;include&gt; are
+ free features, so they do not affect the path.</para>
+
+ <para>Sometimes the paths produced by Boost.Build can become excessively
+ long. There are a couple of command line options that can help with this.
+ --abbreviate-paths reduces each element to no more than five characters.
+ For example, link-static becomes lnk-sttc. The --hash option reduces the
+ path to a single directory using an MD5 hash.</para>
+
+ <para>There are two features that affect the build
+ directory. The &lt;location&gt; feature completely
+ overrides the default build directory. For example,
+ <programlisting>exe a : a.cpp : &lt;location&gt;. ;</programlisting>
+ builds all the files produced by <code>a</code>
+ in the directory of the Jamfile. This is generally
+ discouraged, as it precludes variant builds.</para>
+
+ <para>The &lt;location-prefix&gt; feature adds a
+ prefix to the path, under the project's build
+ directory. For example,
+ <programlisting>exe a : a.cpp : &lt;location-prefix&gt;subdir ;</programlisting>
+ will create the files for <code>a</code> in bin/subdir/gcc-4.6.1/debug</para>
+
+ </section>
 
   </section>
 
@@ -1985,7 +2226,7 @@
             <para>Non-incidental features are assumed to affect build
               products, so the files for targets whose build specification
               differs in non-incidental features are placed in different
- directories as described in "target paths" below. [ where? ]
+ directories as described in <xref linkend="bbv2.reference.buildprocess.targetpath"/>.
             </para>
           </listitem>
 
@@ -2041,14 +2282,11 @@
           <listitem>
             <para><emphasis>symmetric</emphasis></para>
 
- <para>A symmetric feature's default value is not automatically
- included in <link linkend=
- "bbv2.reference.variants">build variants</link>. Normally
- a feature only generates a subvariant directory when its
- value differs from the value specified by the build variant,
+ <para>Normally a feature only generates a subvariant directory
+ when its value differs from its default value,
               leading to an assymmetric subvariant directory structure for
- certain values of the feature. A symmetric feature, when
- relevant to the toolset, always generates a corresponding
+ certain values of the feature. A symmetric feature
+ always generates a corresponding
               subvariant directory.</para>
           </listitem>
 
@@ -2124,24 +2362,6 @@
       </section>
     </section>
 
- <section id="bbv2.reference.variants">
- <title>Build Variants</title>
-
- <para>
- A build variant, or (simply variant) is a special kind of composite
- feature that automatically incorporates the default values of
- features that . Typically you'll want at least two separate
- variants: one for debugging, and one for your release code. [
- Volodya says: "Yea, we'd need to mention that it's a composite
- feature and describe how they are declared, in pacticular that
- default values of non-optional features are incorporated into
- build variant automagically. Also, do we wan't some variant
- inheritance/extension/templates. I don't remember how it works in
- V1, so can't document this for V2.". Will clean up soon -DWA ]
- </para>
-
- </section>
-
     <section id="bbv2.reference.variants.proprefine">
       <title>Property refinement</title>
 

Modified: branches/release/tools/build/v2/doc/src/tasks.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/tasks.xml (original)
+++ branches/release/tools/build/v2/doc/src/tasks.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -28,7 +28,7 @@
           : &lt;threading&gt;multi
           ;
 </programlisting>
- This will create an executable file from the sources -- in this case, one
+ This will create an executable file from the sources&mdash;in this case, one
       C++ file, one library file present in the same directory, and another
       library that is created by Boost.Build. Generally, sources can include C
       and C++ files, object files and libraries. Boost.Build will automatically
@@ -54,6 +54,11 @@
   <section id="bbv2.tasks.libraries">
     <title>Libraries</title>
 
+ <indexterm>
+ <primary>library</primary>
+ <secondary>target</secondary>
+ </indexterm>
+
     <para>
       Library targets are created using the <code>lib</code> rule, which
       follows the <link linkend="bbv2.main-target-rule-syntax">common syntax
@@ -63,66 +68,71 @@
 </programlisting>
       This will define a library target named <code>helpers</code> built from
       the <code>helpers.cpp</code> source file.
+ It can be either a static library or a shared library,
+ depending on the value of the <link linkend="bbv2.overview.builtins.features.link">&lt;link&gt;</link> feature.
     </para>
     <para>
- Depending on the given &lt;link&gt; feature value the library will be
- either static or shared.
- </para>
- <para>
- Library targets may be used to represent:
+ Library targets can represent:
       <itemizedlist>
         <listitem>
           <para>
- <code>Built libraries</code> that get built from specified sources,
- as is the one in the example above. <!-- add link -->
+ Libraries that should be built from source,
+ as in the example above.
           </para>
         </listitem>
         <listitem>
           <para>
- <code>Prebuilt libraries</code> which already exist on the system
- and are just supposed to be used by the build system. Such
- libraries may be searched for by the tools using them (typically
- linkers referencing the library using the <option>-l</option>
- option) or their path may be known in advance by the build system.
- <!-- We need examples for this. -->
+ Prebuilt libraries which already exist on the system.
+ Such libraries can be searched for by the tools using them (typically
+ with the linker's <option>-l</option> option) or their paths can be
+ known in advance by the build system.
           </para>
         </listitem>
       </itemizedlist>
     </para>
 
     <para>
- The syntax for these case is given below:
+ The syntax for prebuilt libraries is given below:
 <programlisting>
 lib z : : &lt;name&gt;z &lt;search&gt;/home/ghost ;
 lib compress : : &lt;file&gt;/opt/libs/compress.a ;
 </programlisting>
- The <code>name</code> property specifies the name that should be passed to
- the <option>-l</option> option, and the <code>file</code> property
- specifies the file location. The <varname>search</varname> feature
- specifies paths in which to search for the library. That feature can be
- specified several times or it can be omitted, in which case only the
- default compiler paths will be searched.
+ The <code>name</code> property specifies the name of the library
+ without the standard prefixes and suffixes. For example, depending
+ on the system, <code>z</code> could refer to a file called
+ z.so, libz.a, or z.lib, etc. The <code>search</code> feature
+ specifies paths in which to search for the library in addition
+ to the default compiler paths. <code>search</code> can be specified
+ several times or it can be omitted, in which case only the default
+ compiler paths will be searched. The <code>file</code> property
+ specifies the file location.
     </para>
 
     <para>
- The difference between using the <varname>file</varname> feature as
- opposed to the <varname>name</varname> feature together with the <varname>
- search</varname> feature is that <varname>file</varname> is more precise.
- A specific file will be used as opposed to the <varname>search</varname>
- feature only adding a library path, or the <varname>name</varname> feature
- giving only the basic name of the library. The search rules are specific
- to the linker used. For example, given these definition:
-<programlisting>
-lib a : : &lt;variant&gt;release &lt;file&gt;/pool/release/a.so ;
-lib a : : &lt;variant&gt;debug &lt;file&gt;/pool/debug/a.so ;
-lib b : : &lt;variant&gt;release &lt;file&gt;/pool/release/b.so ;
-lib b : : &lt;variant&gt;debug &lt;file&gt;/pool/debug/b.so ;
-</programlisting>
- It is possible to use a release version of <code>a</code> and debug
- version of <code>b</code>. Had we used the <varname>name</varname> and
- <varname>search</varname> features, the linker would have always picked
- either the release or the debug versions.
- <!-- explain -->
+ The difference between using the <code>file</code> feature and
+ using a combination of the <code>name</code> and <code>search</code>
+ features is that <code>file</code> is more precise.
+
+ <warning>
+ <para>
+ The value of the <code>search</code> feature is just added to the
+ linker search path. When linking to multiple libraries,
+ the paths specified by <code>search</code> are combined without
+ regard to which <code>lib</code> target each path came from.
+ Thus, given
+<programlisting>
+lib a : : &lt;name&gt;a &lt;search&gt;/pool/release ;
+lib b : : &lt;name&gt;b &lt;search&gt;/pool/debug ;
+</programlisting>
+ If /pool/release/a.so, /pool/release/b.so, /pool/debug/a.so,
+ and /pool/release/b.so all exist, the linker will probably
+ take both <code>a</code> and <code>b</code> from the same
+ directory, instead of finding <code>a</code> in /pool/release
+ and <code>b</code> in /pool/debug. If you need to distinguish
+ between multiple libraries with the same name, it's safer
+ to use <code>file</code>.
+ </para>
+ </warning>
     </para>
 
     <para>
@@ -154,18 +164,18 @@
 
     <note>
       <para>
- When a library has a shared library defined as its source, or a static
- library has another static library defined as its source then any target
+ When a library has a shared library as a source, or a static
+ library has another static library as a source then any target
         linking to the first library with automatically link to its source
         library as well.
       </para>
       <para>
- On the other hand, when a shared library has a static library defined as
- its source then the first library will be built so that it completely
+ On the other hand, when a shared library has a static library as
+ a source then the first library will be built so that it completely
         includes the second one.
       </para>
       <para>
- If you do not want shared libraries to include all libraries specified
+ If you do not want a shared library to include all the libraries specified
         in its sources (especially statically linked ones), you would need to
         use the following:
 <programlisting>
@@ -173,18 +183,16 @@
 lib a : a.cpp : &lt;use&gt;b : : &lt;library&gt;b ;
 </programlisting>
         This specifies that library <code>a</code> uses library <code>b</code>,
- and causes all executables that link to <code>a</code> also link to
- <code>b</code>. In this case, even for shared linking, the
- <code>a</code> library will not even refer to <code>b</code>.
+ and causes all executables that link to <code>a</code> to link to
+ <code>b</code> also. In this case, even for shared linking, the
+ <code>a</code> library will not refer to <code>b</code>.
       </para>
     </note>
 
     <para>
- One Boost.Build feature that is often very useful for defining library
- targets are usage requirements. <!-- Rephrase that. But then, it is much
- too late for an introduction of usage requirements - you have already
- discussed them many times. Also, add references to the sections describing
- requirements and usage-requirements here. --> For example, imagine that
+ <!-- FIXME: After adding a full subsection on usage requirements, link to it -->
+ <link linkend="bbv2.overview.targets">Usage requirements</link> are often
+ very useful for defining library targets. For example, imagine that
       you want you build a <code>helpers</code> library and its interface is
       described in its <code>helpers.hpp</code> header file located in the same
       directory as the <code>helpers.cpp</code> source file. Then you could add
@@ -203,7 +211,7 @@
     <title>Alias</title>
 
     <para>
- The <functionname>alias</functionname> rule gives an alternative name to a
+ The <code language="jam">alias</code> rule gives an alternative name to a
       group of targets. For example, to give the name <filename>core</filename>
       to a group of three other targets with the following code:
 <programlisting>
@@ -384,8 +392,8 @@
     </para>
 
     <para>
- The <functionname>unit-test</functionname> rule behaves like the
- <functionname>exe</functionname> rule, but after the executable is created
+ The <code language="jam">unit-test</code> rule behaves like the
+ <link linkend="bbv2.tasks.programs">exe</link> rule, but after the executable is created
       it is also run. If the executable returns an error code, the build system
       will also return an error and will try running the executable on the next
       invocation until it runs successfully. This behaviour ensures that you can
@@ -476,8 +484,8 @@
     </para>
 
     <para>
- It is possible to process the list of tests, the output of bjam during
- command run, and the presense/absense of the <filename>*.test</filename>
+ It is possible to process the list of tests, Boost.Build output
+ and the presense/absense of the <filename>*.test</filename>
       files created when test passes into human-readable status table of tests.
       Such processing utilities are not included in Boost.Build.
     </para>
@@ -487,33 +495,33 @@
     <title>Custom commands</title>
 
     <para>
- When you use most of main target rules, Boost.Build automatically figures
- what commands to run and it what order. As soon as you want to use new
+ For most main target rules, Boost.Build automatically figures out
+ the commands to run. When you want to use new
       file types or support new tools, one approach is to extend Boost.Build to
- smoothly support them, as documented in <xref linkend="bbv2.extender"/>.
- However, if there is only a single place where the new tool is used, it
- might be easier to just explicitly specify the commands to run.
+ support them smoothly, as documented in <xref linkend="bbv2.extender"/>.
+ However, if the new tool is only used in a single place, it
+ might be easier just to specify the commands to run explicitly.
     </para>
 
     <para>
       <!-- This paragraph requires links to where the terms 'virtual target' &
       'target' are defined. -->
- Three main target rules can be used for that. The <functionname>make
- </functionname> rule allows you to construct a single file from any number
- of source file, by running a command you specify. The <functionname>
- notfile</functionname> rule allows you to run an arbitrary command,
- without creating any files. And finaly, the <functionname>generate
- </functionname> rule allows you to describe transformation using
- Boost.Build's virtual targets. This is higher-level than file names that
- the <functionname>make</functionname> rule operates with and allows you to
+ Three main target rules can be used for that. The <code language="jam">make
+ </code> rule allows you to construct a single file from any number
+ of source file, by running a command you specify. The <code language="jam">
+ notfile</code> rule allows you to run an arbitrary command,
+ without creating any files. And finaly, the <code language="jam">generate
+ </code> rule allows you to describe a transformation using
+ Boost.Build's virtual targets. This is higher-level than the file names that
+ the <code language="jam">make</code> rule operates with and allows you to
       create more than one target, create differently named targets depending on
       properties or use more than one tool.
     </para>
 
     <para>
- The <functionname>make</functionname> rule is used when you want to create
+ The <code language="jam">make</code> rule is used when you want to create
       one file from a number of sources using some specific command. The
- <functionname>notfile</functionname> is used to unconditionally run a
+ <code language="jam">notfile</code> is used to unconditionally run a
       command.
     </para>
 
@@ -524,8 +532,8 @@
     them to become accessible. -->
 
     <para>
- Suppose you want to create file <filename>file.out</filename> from file
- <filename>file.in</filename> by running command <command>
+ Suppose you want to create the file <filename>file.out</filename> from
+ the file <filename>file.in</filename> by running the command <command>
       in2out</command>. Here is how you would do this in Boost.Build:
 <programlisting>
 make file.out : file.in : @in2out ;
@@ -534,7 +542,7 @@
     in2out $(&lt;) $(&gt;)
 }
 </programlisting>
- If you run <command>bjam</command> and <filename>file.out</filename> does
+ If you run <command>b2</command> and <filename>file.out</filename> does
       not exist, Boost.Build will run the <command>in2out</command> command to
       create that file. For more details on specifying actions, see <xref
       linkend="bbv2.overview.jam_language.actions"/>.
@@ -543,7 +551,7 @@
     <para>
       It could be that you just want to run some command unconditionally, and
       that command does not create any specific files. For that you can use the
- <functionname>notfile</functionname> rule. For example:
+ <code language="jam">notfile</code> rule. For example:
 <programlisting>
 notfile echo_something : @echo ;
 actions echo
@@ -551,7 +559,7 @@
     echo "something"
 }
 </programlisting>
- The only difference from the <functionname>make</functionname> rule is
+ The only difference from the <code language="jam">make</code> rule is
       that the name of the target is not considered a name of a file, so
       Boost.Build will unconditionally run the action.
     </para>
@@ -559,9 +567,9 @@
     <para>
       <!-- This paragraph requires links to where terms like 'virtual target',
       'target', 'project-target' & 'property-set' are defined. -->
- The <functionname>generate</functionname> rule is used when you want to
+ The <code language="jam">generate</code> rule is used when you want to
       express transformations using Boost.Build's virtual targets, as opposed to
- just filenames. The <functionname>generate</functionname> rule has the
+ just filenames. The <code language="jam">generate</code> rule has the
       standard main target rule signature, but you are required to specify the
       <literal>generating-rule</literal> property. The value of the property
       should be in the form <literal>
@@ -620,7 +628,7 @@
 cpp-pch pch : pch.hpp ;
 exe main : main.cpp pch ;
 </programlisting>
- You can use the <functionname>c-pch</functionname> rule if you want to
+ You can use the <code language="jam">c-pch</code> rule if you want to
           use the precompiled header in C programs.
         </para></listitem>
     </orderedlist>
@@ -704,7 +712,7 @@
       Making this mechanism work across main target boundaries is possible, but
       imposes certain overhead. For that reason, if there is implicit dependency
       on files from other main targets, the <literal>&lt;implicit-dependency&gt;
- </literal> [ link ] feature must be used, for example:
+ </literal> feature must be used, for example:
 <programlisting>
 lib parser : parser.y ;
 exe app : app.cpp : &lt;implicit-dependency&gt;parser ;
@@ -735,7 +743,7 @@
       just request that this compiler version to be used:
     </para>
 <screen>
-bjam toolset=gcc-arm
+b2 toolset=gcc-arm
 </screen>
 
     <para>
@@ -745,9 +753,9 @@
     </para>
 <screen>
 # On windows box
-bjam toolset=gcc-arm <emphasis role="bold">target-os=linux</emphasis>
+b2 toolset=gcc-arm <emphasis role="bold">target-os=linux</emphasis>
 # On Linux box
-bjam toolset=gcc-mingw <emphasis role="bold">target-os=windows</emphasis>
+b2 toolset=gcc-mingw <emphasis role="bold">target-os=windows</emphasis>
 </screen>
     <para>
       For the complete list of allowed opeating system names, please see the documentation for

Modified: branches/release/tools/build/v2/doc/src/tutorial.xml
==============================================================================
--- branches/release/tools/build/v2/doc/src/tutorial.xml (original)
+++ branches/release/tools/build/v2/doc/src/tutorial.xml 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -30,33 +30,33 @@
       <filename>example/hello/</filename> directory. The project is described by
       a file called <filename>Jamroot</filename> that contains:
 
-<programlisting>
+<programlisting language="jam">
 exe hello : hello.cpp ;
 </programlisting>
 
       Even with this simple setup, you can do some interesting things. First of
- all, just invoking <command>bjam</command> will build the <filename>hello
+ all, just invoking <command>b2</command> will build the <filename>hello
       </filename> executable by compiling and linking <filename>hello.cpp
- </filename>. By default, debug variant is built. Now, to build the release
+ </filename>. By default, the debug variant is built. Now, to build the release
       variant of <filename>hello</filename>, invoke
 
 <screen>
-bjam release
+b2 release
 </screen>
 
- Note that debug and release variants are created in different directories,
+ Note that the debug and release variants are created in different directories,
       so you can switch between variants or even build multiple variants at
       once, without any unnecessary recompilation. Let us extend the example by
       adding another line to our project's <filename>Jamroot</filename>:
 
-<programlisting>
+<programlisting language="jam">
 exe hello2 : hello.cpp ;
 </programlisting>
 
       Now let us build both the debug and release variants of our project again:
 
 <screen>
-bjam debug release
+b2 debug release
 </screen>
 
       Note that two variants of <filename>hello2</filename> are linked. Since we
@@ -66,7 +66,7 @@
       let us remove all the built products:
 
 <screen>
-bjam --clean debug release
+b2 --clean debug release
 </screen>
 
       It is also possible to build or clean specific targets. The following two
@@ -74,8 +74,8 @@
       <filename>hello2</filename>.
 
 <screen>
-bjam hello2
-bjam --clean hello2
+b2 hello2
+b2 --clean hello2
 </screen>
     </para>
   </section>
@@ -84,9 +84,9 @@
     <title>Properties</title>
 
     <para>
- To portably represent aspects of target configuration such as
+ To represent aspects of target configuration such as
       debug and release variants, or single- and multi-threaded
- builds, Boost.Build uses <firstterm>features</firstterm> with
+ builds portably, Boost.Build uses <firstterm>features</firstterm> with
       associated <firstterm>values</firstterm>. For
       example, the <code>debug-symbols</code> feature can have a value of <code>on</code> or
       <code>off</code>. A <firstterm>property</firstterm> is just a (feature,
@@ -102,7 +102,7 @@
       builds the project's <code>release</code> variant with inlining
       disabled and debug symbols enabled:
 <screen>
-bjam release inlining=off debug-symbols=on
+b2 release inlining=off debug-symbols=on
 </screen>
     </para>
 
@@ -116,19 +116,19 @@
 
     <para>
       The <option>release</option> and <option>debug</option> that we have seen
- in <command>bjam</command> invocations are just a shorthand way to specify
+ in <command>b2</command> invocations are just a shorthand way to specify
       values of the <varname>variant</varname> feature. For example, the
       command above could also have been written this way:
 
       <screen>
-bjam variant=release inlining=off debug-symbols=on
+b2 variant=release inlining=off debug-symbols=on
       </screen>
     </para>
 
     <para>
       <varname>variant</varname> is so commonly-used that it has been given
       special status as an <firstterm>implicit</firstterm> feature&#x2014;
- Boost.Build will deduce the its identity just from the name of one of its
+ Boost.Build will deduce its identity just from the name of one of its
       values.
     </para>
 
@@ -140,7 +140,7 @@
       <title>Build Requests and Target Requirements</title>
 
       <para>
- The set of properties specified on the command line constitute
+ The set of properties specified on the command line constitutes
         a <firstterm>build request</firstterm>&#x2014;a description of
         the desired properties for building the requested targets (or,
         if no targets were explicitly requested, the project in the
@@ -160,7 +160,7 @@
         illustrates how these requirements might be specified.
       </para>
 
-<programlisting>
+<programlisting language="jam">
 exe hello
     : hello.cpp
     : &lt;include&gt;boost &lt;threading&gt;multi
@@ -170,7 +170,7 @@
       <para>
         When <filename>hello</filename> is built, the two requirements specified
         above will always be present. If the build request given on the
- <command>bjam</command> command-line explictly contradicts a target's
+ <command>b2</command> command-line explictly contradicts a target's
         requirements, the target requirements usually override (or, in the case
         of &#x201C;free&rdquo;&#x201D; features like
         <varname>&lt;include&gt;</varname>,
@@ -195,14 +195,15 @@
       <title>Project Attributes</title>
 
       <para>
- If we want the same requirements for our other target, <filename>hello2
- </filename>, we could simply duplicate them. However, as projects grow,
- that approach leads to a great deal of repeated boilerplate in Jamfiles.
+ If we want the same requirements for our other target,
+ <filename>hello2</filename>, we could simply duplicate them. However,
+ as projects grow, that approach leads to a great deal of repeated
+ boilerplate in Jamfiles.
 
         Fortunately, there's a better way. Each project can specify a set of
         <firstterm>attributes</firstterm>, including requirements:
 
-<programlisting>
+<programlisting language="jam">
 project
     : requirements &lt;include&gt;/home/ghost/Work/boost &lt;threading&gt;multi
     ;
@@ -220,8 +221,8 @@
     <title>Project Hierarchies</title>
 
     <para>
- So far we have only considered examples with one project &#x2014;a. with
- one user-written Boost.Jam file, <filename>Jamroot</filename>). A typical
+ So far we have only considered examples with one project, with
+ one user-written Boost.Jam file, <filename>Jamroot</filename>. A typical
       large codebase would be composed of many projects organized into a tree.
       The top of the tree is called the <firstterm>project root</firstterm>.
       Every subproject is defined by a file called <filename>Jamfile</filename>
@@ -271,7 +272,7 @@
       any requirements specified by the subproject.
       For example, if <filename>top/Jamroot</filename> has
 
-<programlisting>
+<programlisting language="jam">
 &lt;include&gt;/home/ghost/local
 </programlisting>
 
@@ -289,14 +290,14 @@
     </para>
 
     <para>
- Invoking <command>bjam</command> without explicitly specifying
+ Invoking <command>b2</command> without explicitly specifying
       any targets on the command line builds the project rooted in the
       current directory. Building a project does not automatically
       cause its subprojects to be built unless the parent project's
       Jamfile explicitly requests it. In our example,
       <filename>top/Jamroot</filename> might contain:
 
-<programlisting>
+<programlisting language="jam">
 build-project app ;
 </programlisting>
 
@@ -312,7 +313,7 @@
     <title>Dependent Targets</title>
 
     <para>
- When a building a target <filename>X</filename> depends on first
+ When building a target <filename>X</filename> that depends on first
       building another target <filename>Y</filename> (such as a
       library that must be linked with <firstterm>X</firstterm>),
       <filename>Y</filename> is called a
@@ -326,14 +327,14 @@
       use libraries from <filename>top/util/foo</filename>. If
       <filename>top/util/foo/Jamfile</filename> contains
 
-<programlisting>
+<programlisting language="jam">
 lib bar : bar.cpp ;
 </programlisting>
 
       then to use this library in <filename>top/app/Jamfile</filename>, we can
       write:
 
-<programlisting>
+<programlisting language="jam">
 exe app : app.cpp ../util/foo//bar ;
 </programlisting>
 
@@ -352,7 +353,7 @@
 
     <para>Suppose we build <filename>app</filename> with:
     <screen>
-bjam app optimization=full define=USE_ASM
+b2 app optimization=full define=USE_ASM
     </screen>
     Which properties will be used to build <code>foo</code>? The answer is
     that some features are
@@ -369,13 +370,13 @@
     <para>
       Let's improve this project further. The library probably has some headers
       that must be used when compiling <filename>app.cpp</filename>. We could
- manually add the necessary <code>#include</code> paths to <filename>app
- </filename>'s requirements as values of the <varname>&lt;include&gt;
- </varname> feature, but then this work will be repeated for all programs
- that use <filename>foo</filename>. A better solution is to modify
- <filename>util/foo/Jamfile</filename> in this way:
+ manually add the necessary <code>#include</code> paths to
+ <filename>app</filename>'s requirements as values of the
+ <varname>&lt;include&gt; </varname> feature, but then this work will be
+ repeated for all programs that use <filename>foo</filename>. A better
+ solution is to modify <filename>util/foo/Jamfile</filename> in this way:
 
- <programlisting>
+ <programlisting language="jam">
 project
     : usage-requirements &lt;include&gt;.
     ;
@@ -397,7 +398,7 @@
       code to <filename>Jamroot</filename>:
     </para>
 
- <programlisting>
+ <programlisting language="jam">
 use-project /library-example/foo : util/foo ;</programlisting>
 
     <para>
@@ -424,7 +425,7 @@
         requirements, like this:
       </para>
 
- <programlisting>
+ <programlisting language="jam">
 project
    : requirements &lt;library&gt;/boost/filesystem//fs
    ;</programlisting>
@@ -448,9 +449,9 @@
       <literal>shared</literal>, and to build a static library, the value should
       be <literal>static</literal>. You can request a static build either on the
       command line:
- <programlisting>bjam link=static</programlisting>
+ <programlisting>b2 link=static</programlisting>
       or in the library's requirements:
- <programlisting>lib l : l.cpp : &lt;link&gt;static ;</programlisting>
+ <programlisting language="jam">lib l : l.cpp : &lt;link&gt;static ;</programlisting>
     </para>
 
     <para>
@@ -469,10 +470,10 @@
      VP: to be addressed when this section is moved. See comment below.
 -->
 
- <programlisting>
+ <programlisting language="jam">
 exe important : main.cpp helpers/&lt;link&gt;static ;</programlisting>
 
- No matter what arguments are specified on the <command>bjam</command>
+ No matter what arguments are specified on the <command>b2</command>
       command line, <filename>important</filename> will only be linked with the
       static version of <filename>helpers</filename>.
     </para>
@@ -484,7 +485,7 @@
       that library is used by many targets, you <emphasis>could</emphasis> use
       target references everywhere:
 
- <programlisting>
+ <programlisting language="jam">
 exe e1 : e1.cpp /other_project//bar/&lt;link&gt;static ;
 exe e10 : e10.cpp /other_project//bar/&lt;link&gt;static ;</programlisting>
 
@@ -497,9 +498,9 @@
 exe e1 : e1.cpp foo ;
 exe e10 : e10.cpp foo ;</programlisting>
 
- The <link linkend="bbv2.tasks.alias"><functionname>alias</functionname>
- </link> rule is specifically used to rename a reference to a target and
- possibly change the properties.
+ The <link linkend="bbv2.tasks.alias">alias</link> rule is specifically
+ used to rename a reference to a target and possibly change the
+ properties.
 
       <!-- You should introduce the alias rule in an earlier section, before
            describing how it applies to this specific use-case, and the
@@ -514,7 +515,7 @@
       <para>
         When one library uses another, you put the second library in the source
         list of the first. For example:
- <programlisting>
+ <programlisting language="jam">
 lib utils : utils.cpp /boost/filesystem//fs ;
 lib core : core.cpp utils ;
 exe app : app.cpp core ;</programlisting>
@@ -553,14 +554,14 @@
       <code>release</code> variant is built. This can be achieved using
       <firstterm>conditional requirements</firstterm>.
 
- <programlisting>
+ <programlisting language="jam">
 lib network : network.cpp
     : <emphasis role="bold">&lt;link&gt;shared:&lt;define&gt;NEWORK_LIB_SHARED</emphasis>
      &lt;variant&gt;release:&lt;define&gt;EXTRA_FAST
     ;</programlisting>
 
       In the example above, whenever <filename>network</filename> is built with
- <code>&lt;link&gt;shared</code>, <code>&lt;define&gt;NEWORK_LIB_SHARED
+ <code language="jam">&lt;link&gt;shared</code>, <code language="jam">&lt;define&gt;NEWORK_LIB_SHARED
       </code> will be in its properties, too. Also, whenever its release variant
       is built, <code>&lt;define&gt;EXTRA_FAST</code> will appear in its
       properties.
@@ -572,15 +573,15 @@
       library actually uses different source files depending on the toolset used
       to build it. We can express this situation using <firstterm>target
       alternatives</firstterm>:
- <programlisting>
+ <programlisting language="jam">
 lib demangler : dummy_demangler.cpp ; # alternative 1
 lib demangler : demangler_gcc.cpp : &lt;toolset&gt;gcc ; # alternative 2
 lib demangler : demangler_msvc.cpp : &lt;toolset&gt;msvc ; # alternative 3</programlisting>
       When building <filename>demangler</filename>, Boost.Build will compare
       requirements for each alternative with build properties to find the best
- match. For example, when building with <code>&lt;toolset&gt;gcc</code>
+ match. For example, when building with <code language="jam">&lt;toolset&gt;gcc</code>
       alternative 2, will be selected, and when building with
- <code>&lt;toolset&gt;msvc</code> alternative 3 will be selected. In all
+ <code language="jam">&lt;toolset&gt;msvc</code> alternative 3 will be selected. In all
       other cases, the most generic alternative 1 will be built.
     </para>
   </section>
@@ -594,7 +595,7 @@
       <varname>file</varname> property. Target alternatives can be used to
       associate multiple library files with a single conceptual target. For
       example:
- <programlisting>
+ <programlisting language="jam">
 # util/lib2/Jamfile
 lib lib2
     :
@@ -616,7 +617,7 @@
       Once a prebuilt target has been declared, it can be used just like any
       other target:
 
- <programlisting>
+ <programlisting language="jam">
 exe app : app.cpp ../util/lib2//lib2 ;</programlisting>
 
       As with any target, the alternative selected depends on the properties
@@ -631,7 +632,7 @@
       by searching through some set of predetermined paths&#x2014;should be
       declared almost like regular ones:
 
- <programlisting>
+ <programlisting language="jam">
 lib pythonlib : : &lt;name&gt;python22 ;</programlisting>
 
       We again don't specify any sources, but give a <varname>name</varname>
@@ -644,12 +645,12 @@
     <para>
       We can also specify where the toolset should look for the library:
 
- <programlisting>
+ <programlisting language="jam">
 lib pythonlib : : &lt;name&gt;python22 &lt;search&gt;/opt/lib ;</programlisting>
 
       And, of course, target alternatives can be used in the usual way:
 
- <programlisting>
+ <programlisting language="jam">
 lib pythonlib : : &lt;name&gt;python22 &lt;variant&gt;release ;
 lib pythonlib : : &lt;name&gt;python22_d &lt;variant&gt;debug ;</programlisting>
     </para>

Modified: branches/release/tools/build/v2/engine/build.bat
==============================================================================
--- branches/release/tools/build/v2/engine/build.bat (original)
+++ branches/release/tools/build/v2/engine/build.bat 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -28,7 +28,7 @@
 ECHO ### .\build.bat msvc
 ECHO ###
 ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin,
-ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10
+ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10, vc11
 ECHO ###
 call :Set_Error
 endlocal
@@ -101,6 +101,16 @@
 if not errorlevel 1 set ProgramFiles=C:\Program Files
 
 call :Clear_Error
+if NOT "_%VS110COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET=vc11"
+ set "BOOST_JAM_TOOLSET_ROOT=%VS110COMNTOOLS%..\..\VC\"
+ goto :eof)
+call :Clear_Error
+if EXIST "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\VCVARSALL.BAT" (
+ set "BOOST_JAM_TOOLSET=vc11"
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 11.0\VC\"
+ goto :eof)
+call :Clear_Error
 if NOT "_%VS100COMNTOOLS%_" == "__" (
     set "BOOST_JAM_TOOLSET=vc10"
     set "BOOST_JAM_TOOLSET_ROOT=%VS100COMNTOOLS%..\..\VC\"
@@ -371,6 +381,21 @@
 set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
 set "_known_=1"
 :Skip_VC10
+if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc11_" goto Skip_VC11
+if NOT "_%VS110COMNTOOLS%_" == "__" (
+ set "BOOST_JAM_TOOLSET_ROOT=%VS110COMNTOOLS%..\..\VC\"
+ )
+if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
+if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
+ if "_%VCINSTALLDIR%_" == "__" (
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
+ ) )
+set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
+set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
+set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
+set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
+set "_known_=1"
+:Skip_VC11
 if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto Skip_BORLAND
 if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
     call :Test_Path bcc32.exe )
@@ -438,9 +463,9 @@
 set YYACC_SOURCES=yyacc.c
 set MKJAMBASE_SOURCES=mkjambase.c
 set BJAM_SOURCES=
-set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c debug.c execnt.c expand.c filent.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c constants.c debug.c execnt.c filent.c function.c glob.c hash.c
 set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
-set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c output.c parse.c pathunix.c regexp.c
+set BJAM_SOURCES=%BJAM_SOURCES% object.c option.c output.c parse.c pathunix.c regexp.c
 set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
 set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c md5.c pwd.c class.c w32_getreg.c native.c
 set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c
@@ -457,10 +482,13 @@
 set test=%test:"###=%
 set test=%test:###"=%
 set test=%test:###=%
-if "%test%" == "--update" set BJAM_UPDATE=update
+if "%test%" == "--update" goto Found_Update
 endlocal
 shift
 if not "_%BJAM_UPDATE%_" == "_update_" goto Check_Update
+:Found_Update
+endlocal
+set BJAM_UPDATE=update
 :Check_Update_End
 if "_%BJAM_UPDATE%_" == "_update_" (
     if not exist ".\bootstrap\jam0.exe" (
@@ -506,9 +534,6 @@
 %BOOST_JAM_CC% %BOOST_JAM_OPT_JAM% %BJAM_SOURCES%
 :Skip_Bootstrap
 @if not exist ".\bootstrap\jam0.exe" goto Skip_Jam
-_at_if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Clean
-.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " clean
-:Skip_Clean
 @set args=%*
 @echo OFF
 :Set_Args
@@ -526,6 +551,9 @@
 goto Set_Args
 :Set_Args_End
 @echo ON
+@if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Clean
+.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args% clean
+:Skip_Clean
 .\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args%
 :Skip_Jam
 

Modified: branches/release/tools/build/v2/engine/build.jam
==============================================================================
--- branches/release/tools/build/v2/engine/build.jam (original)
+++ branches/release/tools/build/v2/engine/build.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -18,12 +18,9 @@
 
 # Platform related specifics.
 if $(OS) = NT { rule .path { return "$(<:J=\\)" ; } ./ = "/" ; }
-else if $(OS) = OS2 { rule .path { return "$(<:J=\\)" ; } ./ = "/" ; }
-else if $(OS) = VMS { rule .path { return "[.$(<:J=/)]" ; } }
-else if $(OS) = MAC { rule .path { return ":$(<:J=\:)" ; } }
 else { rule .path { return "$(<:J=/)" ; } }
-if $(OS) = VMS { . = "_" ; }
-else { . = "." ; }
+
+. = "." ;
 ./ ?= "" ;
 
 # Info about what we are building.
@@ -71,7 +68,7 @@
     {
         --python-include = [ .path $(python-location) include ] ;
         --python-lib = ;
- for local v in 26 25 24 23 22
+ for local v in 27 26 25 24 23 22
         {
             --python-lib ?=
                 [ GLOB [ .path $(python-location) libs ] : "python$(v).lib" ]
@@ -94,7 +91,7 @@
     {
         --python-include = ;
         --python-lib = ;
- for local v in 2.6 2.5 2.4 2.3 2.2
+ for local v in 2.7 2.6 2.5 2.4 2.3 2.2
         {
             local inc = [ GLOB [ .path $(python-location) include ] : python$(v) ] ;
             local lib = [ GLOB [ .path $(python-location) lib ] : libpython$(v)* ] ;
@@ -214,6 +211,7 @@
     : -pedantic -fno-strict-aliasing
     [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
     [ opt --debug : -g -O0 -fno-inline ]
+ [ opt --profile : -O3 -g -pg ]
     -I$(--python-include) -I$(--extra-include) -Wno-long-long
     : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
 ## GCC 2.x, 3.x on CYGWIN but without cygwin1.dll
@@ -319,14 +317,14 @@
 ## Sun Workshop 6 C++
 toolset sun cc : "-o " : -D
     :
- [ opt --release : -s -fast -xO4 ]
+ [ opt --release : -s -xO3 ]
     [ opt --debug : -g ]
     -I$(--python-include) -I$(--extra-include)
     : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
 ## Sun Workshop 6 C++ (old alias)
 toolset sunpro cc : "-o " : -D
     :
- [ opt --release : -s -fast -xO4 ]
+ [ opt --release : -s -xO3 ]
     [ opt --debug : -g ]
     -I$(--python-include) -I$(--extra-include)
     : -L$(--python-lib[1]) -l$(--python-lib[2]) ;
@@ -372,18 +370,13 @@
     [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
     -I$(--python-include) -I$(--extra-include)
     : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
-## VMS/OpenVMS DEC C
-toolset vmsdecc cc : /OBJECT= : "/DEFINES=(" "," ")"
- : /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES
- [ opt --release : /OPTIMIZE /NODEBUG ]
- [ opt --debug : /NOOPTIMIZE /DEBUG ]
- ;
-toolset vmsdecc link .link : /EXECUTABLE= :
- : /NOMAP
- [ opt --release : /NODEBUG ]
- [ opt --debug : /DEBUG ]
- ;
-
+toolset vc11 cl : /Fe /Fe /Fd /Fo : -D
+ : /nologo
+ [ opt --release : /MT /O2 /Ob2 /Gy /GF /GA /wd4996 ]
+ [ opt --debug : /MTd /DEBUG /Z7 /Od /Ob0 /wd4996 ]
+ -I$(--python-include) -I$(--extra-include)
+ : kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
+
 # First set the build commands and options according to the
 # preset toolset.
 toolset = [ MATCH --toolset=(.*) : $(ARGV) ] ;
@@ -454,17 +447,7 @@
 
 # Put executables in platform-specific subdirectory.
 locate-target = $(LOCATE_TARGET) ;
-if $(OS) = VMS
-{
- locate-target ?= bin$(.)vms ;
- platform = vms ;
-}
-else if $(OS) = MAC
-{
- locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
- platform = $(OS:L)$(OSPLAT:L) ;
-}
-else if $(OSPLAT)
+if $(OSPLAT)
 {
     locate-target ?= bin$(.)$(OS:L)$(OSPLAT:L) ;
     platform = $(OS:L)$(OSPLAT:L) ;
@@ -492,12 +475,12 @@
   ECHO $(locate-target) ;
 }
 
-# We have some different files for UNIX, VMS, and NT.
+# We have some different files for UNIX, and NT.
 jam.source =
- command.c compile.c debug.c expand.c glob.c
+ command.c compile.c constants.c debug.c function.c glob.c
     hash.c hcache.c headers.c hdrmacro.c
     jam.c jambase.c jamgram.c
- lists.c make.c make1.c mem.c newstr.c
+ lists.c make.c make1.c mem.c object.c
     option.c output.c parse.c regexp.c rules.c
     scan.c search.c subst.c w32_getreg.c
     timestamp.c variable.c modules.c strings.c filesys.c
@@ -509,18 +492,6 @@
 {
     jam.source += execnt.c filent.c pathunix.c ;
 }
-else if $(OS) = OS2
-{
- jam.source += execunix.c fileos2.c pathunix.c ;
-}
-else if $(OS) = VMS
-{
- jam.source += execvms.c filevms.c pathvms.c ;
-}
-else if $(OS) = MAC
-{
- jam.source += execmac.c filemac.c pathmac.c ;
-}
 else
 {
     jam.source += execunix.c fileunix.c pathunix.c ;
@@ -565,10 +536,6 @@
 {
     --defs += NT ;
 }
-if $(OS) = VMS
-{
- --defs += VMS ;
-}
 --defs += YYSTACKSIZE=5000 ;
 
 if $(with-python)
@@ -597,18 +564,12 @@
 if $(UNIX) = true { actions piecemeal together existing [DELETE] {
     rm -f "$(>)"
 } }
-if $(OS) = VMS { actions piecemeal together existing [DELETE] {
- DELETE $(>[--2]:J=";*, ") $(>[-1]);*
-} }
 if $(OS) = NT {
     --chmod+w = "attrib -r " ;
 }
 if $(UNIX) = true {
     --chmod+w = "chmod +w " ;
 }
-if $(OS) = VMS {
- --chmod+w = "SET FILE/PROT=(S:RWED) " ;
-}
 
 rule .mkdir
 {
@@ -622,14 +583,11 @@
 if $(UNIX) = true { actions [MKDIR] {
     mkdir "$(<)"
 } }
-if $(OS) = VMS { actions [MKDIR] {
- CREATE/DIR $(<J=", ")
-} }
 
 rule .exe
 {
     local exe = $(<) ;
- if $(OS) = NT || ( $(UNIX) = true && $(OS) = CYGWIN ) || $(OS) = VMS { exe = $(exe:S=.exe) ; }
+ if $(OS) = NT || ( $(UNIX) = true && $(OS) = CYGWIN ) { exe = $(exe:S=.exe) ; }
     LOCATE on $(exe) = $(locate-target) ;
     DEPENDS all : $(exe) ;
     .mkdir $(locate-target) ;
@@ -665,18 +623,16 @@
     return $(exe) ;
 }
 if ! $(--def[2]) { actions [COMPILE] {
- "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def)$(--defs)" "$(--flags)" "$(--libs)" "$(>)"
+ "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def)$(--defs)" "$(--flags)" "$(>)" "$(--libs)"
 } }
 else { actions [COMPILE] {
- "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def[1])$(--defs:J=$(--def[2]))$(--def[3])" "$(--flags)" "$(--libs)" "$(>)"
-} }
-if $(OS) = VMS { actions [COMPILE.LINK] {
- "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D)$(./) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>J=", ")
-} }
-else { actions [COMPILE.LINK] {
- "$(--link)" "$(--link-bin)$(<:D=)" "$(--link-dir)$(<:D)$(./)" "$(--link-out)$(<)" "$(--link-def)$(--link-defs)" "$(--link-flags)" "$(--link-libs)" "$(>)"
+ "$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def[1])$(--defs:J=$(--def[2]))$(--def[3])" "$(--flags)" "$(>)" "$(--libs)"
 } }
 
+actions [COMPILE.LINK] {
+ "$(--link)" "$(--link-bin)$(<:D=)" "$(--link-dir)$(<:D)$(./)" "$(--link-out)$(<)" "$(--link-def)$(--link-defs)" "$(--link-flags)" "$(>)" "$(--link-libs)"
+}
+
 rule .link
 {
     DEPENDS all : $(<) ;
@@ -690,9 +646,6 @@
 if $(UNIX) = true { actions [LINK] {
     ln -fs "$(>)" "$(<)"
 } }
-if $(OS) = VMS { actions [LINK] {
- COPY/REPLACE $(>) $(<)
-} }
 
 rule .copy
 {
@@ -720,9 +673,6 @@
 if $(UNIX) = true { actions [MOVE] {
     mv -f "$(>)" "$(<)"
 } }
-if $(OS) = VMS { actions [MOVE] {
- RENAME "$(>)" "$(<)"
-} }
 
 # Generate the grammar tokens table, and the real yacc grammar.
 rule .yyacc
@@ -796,13 +746,6 @@
         exit 1
     fi
 } }
-if $(OS) = VMS { actions [YACC] {
- IF "$(yacc)" $(>)
- THEN
- RENAME y_tab$(<[1]:S) $(<[1])
- RENAME y_tab$(<[2]:S) $(<[2])
- ENDIF
-} }
 if $(grammar) && ! $(yacc)
 {
     EXIT "Could not find the 'yacc' tool, and therefore can not build the grammar." ;
@@ -888,7 +831,7 @@
 dist.source = $(dist.source:D=)
     $(dist.license[1])
     $(dist.docs)
- build.jam build.bat build.sh build_vms.com
+ build.jam build.bat build.sh
     Jambase
     jamgram.y jamgram.yy
     [ .path modules set.c ]

Modified: branches/release/tools/build/v2/engine/build.sh
==============================================================================
--- branches/release/tools/build/v2/engine/build.sh (original)
+++ branches/release/tools/build/v2/engine/build.sh 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -245,9 +245,9 @@
 YYACC_SOURCES="yyacc.c"
 MKJAMBASE_SOURCES="mkjambase.c"
 BJAM_SOURCES="\
- command.c compile.c debug.c expand.c glob.c hash.c\
+ command.c compile.c constants.c debug.c function.c glob.c hash.c\
  hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
- newstr.c option.c output.c parse.c pathunix.c pathvms.c regexp.c\
+ object.c option.c output.c parse.c pathunix.c regexp.c\
  rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
  strings.c filesys.c builtins.c pwd.c class.c native.c md5.c w32_getreg.c\
  modules/set.c modules/path.c modules/regex.c modules/property-set.c\
@@ -297,7 +297,7 @@
 fi
 if test -x "./bootstrap/jam0" ; then
     if test "${BJAM_UPDATE}" != "update" ; then
- echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" clean
+ echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@" clean
     fi
     echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@"
 fi

Deleted: branches/release/tools/build/v2/engine/build_vms.com
==============================================================================
--- branches/release/tools/build/v2/engine/build_vms.com 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,105 +0,0 @@
-$ ! Copyright 2002-2003 Rene Rivera, Johan Nilsson.
-$ ! Distributed under the Boost Software License, Version 1.0.
-$ ! (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-$ !
-$ ! bootstrap build script for Jam
-$ !
-$ SAY :== WRITE SYS$OUTPUT
-$ !
-$ ON WARNING THEN CONTINUE
-$ !
-$ IF "" .NES. F$SEARCH("[.bootstrap_vms]*.*")
-$ THEN
-$ SAY "Cleaning previous boostrap files..."
-$ !
-$ SET FILE/PROTECTION=(S:RWED) [.bootstrap_vms]*.*;*
-$ DELETE [.bootstrap_vms]*.*;*
-$ ENDIF
-$ !
-$ IF "" .NES. F$SEARCH("bootstrap_vms.dir")
-$ THEN
-$ SAY "Removing previous boostrap directory..."
-$ !
-$ SET FILE/PROT=(S:RWED) bootstrap_vms.dir
-$ DELETE bootstrap_vms.dir;
-$ ENDIF
-$ !
-$ SAY "Creating boostrap directory..."
-$ !
-$ CREATE/DIR [.bootstrap_vms]
-$ !
-$ SAY "Building bootstrap jam..."
-$ !
-$ CC_FLAGS = "/DEFINE=VMS /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES "
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]builtins.obj builtins.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]command.obj command.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]compile.obj compile.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]execvms.obj execvms.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]expand.obj expand.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filesys.obj filesys.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filevms.obj filevms.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]glob.obj glob.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hash.obj hash.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]hdrmacro.obj hdrmacro.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]headers.obj headers.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jam.obj jam.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jambase.obj jambase.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]jamgram.obj jamgram.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]lists.obj lists.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make.obj make.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make1.obj make1.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]modules.obj modules.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]newstr.obj newstr.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]option.obj option.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]parse.obj parse.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pathvms.obj pathvms.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pwd.obj pwd.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]regexp.obj regexp.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]rules.obj rules.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]scan.obj scan.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]search.obj search.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]strings.obj strings.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]subst.obj subst.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]timestamp.obj timestamp.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]variable.obj variable.c
-$ link -
- /EXECUTABLE=[.bootstrap_vms]jam0.exe -
- [.bootstrap_vms]builtins.obj, -
- [.bootstrap_vms]command.obj, -
- [.bootstrap_vms]compile.obj, -
- [.bootstrap_vms]execvms.obj, -
- [.bootstrap_vms]expand.obj, -
- [.bootstrap_vms]filesys.obj, -
- [.bootstrap_vms]filevms.obj, -
- [.bootstrap_vms]glob.obj, -
- [.bootstrap_vms]hash.obj, -
- [.bootstrap_vms]hdrmacro.obj, -
- [.bootstrap_vms]headers.obj, -
- [.bootstrap_vms]jam.obj, -
- [.bootstrap_vms]jambase.obj, -
- [.bootstrap_vms]jamgram.obj, -
- [.bootstrap_vms]lists.obj, -
- [.bootstrap_vms]make.obj, -
- [.bootstrap_vms]make1.obj, -
- [.bootstrap_vms]modules.obj, -
- [.bootstrap_vms]newstr.obj, -
- [.bootstrap_vms]option.obj, -
- [.bootstrap_vms]parse.obj, -
- [.bootstrap_vms]pathvms.obj, -
- [.bootstrap_vms]pwd.obj, -
- [.bootstrap_vms]regexp.obj, -
- [.bootstrap_vms]rules.obj, -
- [.bootstrap_vms]scan.obj, -
- [.bootstrap_vms]search.obj, -
- [.bootstrap_vms]strings.obj, -
- [.bootstrap_vms]subst.obj, -
- [.bootstrap_vms]timestamp.obj, -
- [.bootstrap_vms]variable.obj
-$ !
-$ SAY "Cleaning any previous build..."
-$ !
-$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc clean
-$ !
-$ SAY "Building Boost.Jam..."
-$ !
-$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc

Modified: branches/release/tools/build/v2/engine/builtins.c
==============================================================================
--- branches/release/tools/build/v2/engine/builtins.c (original)
+++ branches/release/tools/build/v2/engine/builtins.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,7 +11,7 @@
 #include "builtins.h"
 #include "rules.h"
 #include "filesys.h"
-#include "newstr.h"
+#include "object.h"
 #include "regexp.h"
 #include "frames.h"
 #include "hash.h"
@@ -25,6 +25,7 @@
 #include "variable.h"
 #include "timestamp.h"
 #include "md5.h"
+#include "constants.h"
 #include <ctype.h>
 
 #if defined(USE_EXECUNIX)
@@ -65,38 +66,44 @@
  */
 
 #define P0 (PARSE *)0
-#define C0 (char *)0
+#define C0 (OBJECT *)0
 
 #if defined( OS_NT ) || defined( OS_CYGWIN )
- LIST * builtin_system_registry ( PARSE *, FRAME * );
- LIST * builtin_system_registry_names( PARSE *, FRAME * );
+ LIST * builtin_system_registry ( FRAME *, int );
+ LIST * builtin_system_registry_names( FRAME *, int );
 #endif
 
-int glob( char * s, char * c );
+int glob( const char * s, const char * c );
 
 void backtrace ( FRAME * );
 void backtrace_line ( FRAME * );
-void print_source_line( PARSE * );
+void print_source_line( FRAME * );
 
 
-RULE * bind_builtin( char * name, LIST * (* f)( PARSE *, FRAME * ), int flags, char * * args )
+RULE * bind_builtin( const char * name_, LIST * (* f)( FRAME *, int flags ), int flags, const char * * args )
 {
- argument_list* arg_list = 0;
+ FUNCTION * func;
+ RULE * result;
+ OBJECT * name = object_new( name_ );
 
- if ( args )
- {
- arg_list = args_new();
- lol_build( arg_list->data, args );
- }
+ func = function_builtin( f, flags, args );
+
+ result = new_rule_body( root_module(), name, func, 1 );
+
+ function_free( func );
+
+ object_free( name );
 
- return new_rule_body( root_module(), name, arg_list,
- parse_make( f, P0, P0, P0, C0, C0, flags ), 1 );
+ return result;
 }
 
 
-RULE * duplicate_rule( char * name, RULE * other )
+RULE * duplicate_rule( const char * name_, RULE * other )
 {
- return import_rule( other, root_module(), name );
+ OBJECT * name = object_new( name_ );
+ RULE * result = import_rule( other, root_module(), name );
+ object_free( name );
+ return result;
 }
 
 
@@ -116,7 +123,7 @@
                     builtin_echo, 0, 0 ) ) );
 
     {
- char * args[] = { "message", "*", ":", "result-value", "?", 0 };
+ const char * args[] = { "message", "*", ":", "result-value", "?", 0 };
         duplicate_rule( "exit",
         duplicate_rule( "Exit",
           bind_builtin( "EXIT",
@@ -124,13 +131,13 @@
     }
 
     {
- char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
+ const char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
         duplicate_rule( "Glob",
                         bind_builtin( "GLOB", builtin_glob, 0, args ) );
     }
 
     {
- char * args[] = { "patterns", "*", 0 };
+ const char * args[] = { "patterns", "*", 0 };
         bind_builtin( "GLOB-RECURSIVELY",
                       builtin_glob_recursive, 0, args );
     }
@@ -140,7 +147,7 @@
                     builtin_depends, 1, 0 ) );
 
     {
- char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
+ const char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
         bind_builtin( "REBUILDS",
                       builtin_rebuilds, 0, args );
     }
@@ -154,7 +161,7 @@
                     builtin_match, 0, 0 ) );
 
     {
- char * args[] = { "string", ":", "delimiters" };
+ const char * args[] = { "string", ":", "delimiters" };
         bind_builtin( "SPLIT_BY_CHARACTERS",
                       builtin_split_by_characters, 0, 0 );
     }
@@ -194,13 +201,13 @@
                     builtin_flags, T_FLAG_RMOLD, 0 );
 
       {
- char * args[] = { "targets", "*", 0 };
+ const char * args[] = { "targets", "*", 0 };
           bind_builtin( "UPDATE",
                         builtin_update, 0, args );
       }
 
       {
- char * args[] = { "targets", "*",
+ const char * args[] = { "targets", "*",
                             ":", "log", "?",
                             ":", "ignore-minus-n", "?",
                             ":", "ignore-minus-q", "?", 0 };
@@ -209,33 +216,33 @@
       }
 
       {
- char * args[] = { "string", "pattern", "replacements", "+", 0 };
+ const char * args[] = { "string", "pattern", "replacements", "+", 0 };
           duplicate_rule( "subst",
             bind_builtin( "SUBST",
                           builtin_subst, 0, args ) );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "RULENAMES",
                          builtin_rulenames, 0, args );
       }
 
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "VARNAMES",
                          builtin_varnames, 0, args );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "DELETE_MODULE",
                          builtin_delete_module, 0, args );
       }
 
       {
- char * args[] = { "source_module", "?",
+ const char * args[] = { "source_module", "?",
                             ":", "source_rules", "*",
                             ":", "target_module", "?",
                             ":", "target_rules", "*",
@@ -245,104 +252,98 @@
       }
 
       {
- char * args[] = { "module", "?", ":", "rules", "*", 0 };
+ const char * args[] = { "module", "?", ":", "rules", "*", 0 };
           bind_builtin( "EXPORT",
                         builtin_export, 0, args );
       }
 
       {
- char * args[] = { "levels", "?", 0 };
+ const char * args[] = { "levels", "?", 0 };
           bind_builtin( "CALLER_MODULE",
                          builtin_caller_module, 0, args );
       }
 
       {
- char * args[] = { "levels", "?", 0 };
+ const char * args[] = { "levels", "?", 0 };
           bind_builtin( "BACKTRACE",
                         builtin_backtrace, 0, args );
       }
 
       {
- char * args[] = { 0 };
+ const char * args[] = { 0 };
           bind_builtin( "PWD",
                         builtin_pwd, 0, args );
       }
 
       {
- char * args[] = { "target", "*", ":", "path", "*", 0 };
- bind_builtin( "SEARCH_FOR_TARGET",
- builtin_search_for_target, 0, args );
- }
-
- {
- char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
+ const char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
           bind_builtin( "IMPORT_MODULE",
                         builtin_import_module, 0, args );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "IMPORTED_MODULES",
                         builtin_imported_modules, 0, args );
       }
 
       {
- char * args[] = { "instance_module", ":", "class_module", 0 };
+ const char * args[] = { "instance_module", ":", "class_module", 0 };
           bind_builtin( "INSTANCE",
                         builtin_instance, 0, args );
       }
 
       {
- char * args[] = { "sequence", "*", 0 };
+ const char * args[] = { "sequence", "*", 0 };
           bind_builtin( "SORT",
                         builtin_sort, 0, args );
       }
 
       {
- char * args[] = { "path_parts", "*", 0 };
+ const char * args[] = { "path_parts", "*", 0 };
           bind_builtin( "NORMALIZE_PATH",
                         builtin_normalize_path, 0, args );
       }
 
       {
- char * args[] = { "args", "*", 0 };
+ const char * args[] = { "args", "*", 0 };
           bind_builtin( "CALC",
                         builtin_calc, 0, args );
       }
 
       {
- char * args[] = { "module", ":", "rule", 0 };
+ const char * args[] = { "module", ":", "rule", 0 };
           bind_builtin( "NATIVE_RULE",
                         builtin_native_rule, 0, args );
       }
 
       {
- char * args[] = { "module", ":", "rule", ":", "version", 0 };
+ const char * args[] = { "module", ":", "rule", ":", "version", 0 };
           bind_builtin( "HAS_NATIVE_RULE",
                         builtin_has_native_rule, 0, args );
       }
 
       {
- char * args[] = { "module", "*", 0 };
+ const char * args[] = { "module", "*", 0 };
           bind_builtin( "USER_MODULE",
                         builtin_user_module, 0, args );
       }
 
       {
- char * args[] = { 0 };
+ const char * args[] = { 0 };
           bind_builtin( "NEAREST_USER_LOCATION",
                         builtin_nearest_user_location, 0, args );
       }
 
       {
- char * args[] = { "file", 0 };
+ const char * args[] = { "file", 0 };
           bind_builtin( "CHECK_IF_FILE",
                         builtin_check_if_file, 0, args );
       }
 
 #ifdef HAVE_PYTHON
       {
- char * args[] = { "python-module", ":", "function", ":",
+ const char * args[] = { "python-module", ":", "function", ":",
                             "jam-module", ":", "rule-name", 0 };
           bind_builtin( "PYTHON_IMPORT_RULE",
                         builtin_python_import_rule, 0, args );
@@ -351,56 +352,56 @@
 
 # if defined( OS_NT ) || defined( OS_CYGWIN )
       {
- char * args[] = { "key_path", ":", "data", "?", 0 };
+ const char * args[] = { "key_path", ":", "data", "?", 0 };
           bind_builtin( "W32_GETREG",
                         builtin_system_registry, 0, args );
       }
 
       {
- char * args[] = { "key_path", ":", "result-type", 0 };
+ const char * args[] = { "key_path", ":", "result-type", 0 };
           bind_builtin( "W32_GETREGNAMES",
                         builtin_system_registry_names, 0, args );
       }
 # endif
 
       {
- char * args[] = { "command", ":", "*", 0 };
+ const char * args[] = { "command", ":", "*", 0 };
           duplicate_rule( "SHELL",
             bind_builtin( "COMMAND",
                           builtin_shell, 0, args ) );
       }
 
       {
- char * args[] = { "string", 0 };
+ const char * args[] = { "string", 0 };
           bind_builtin( "MD5",
                         builtin_md5, 0, args ) ;
       }
 
       {
- char * args[] = { "name", ":", "mode", 0 };
+ const char * args[] = { "name", ":", "mode", 0 };
           bind_builtin( "FILE_OPEN",
                         builtin_file_open, 0, args );
       }
 
       {
- char * args[] = { "string", ":", "width", 0 };
+ const char * args[] = { "string", ":", "width", 0 };
           bind_builtin( "PAD",
                         builtin_pad, 0, args );
       }
 
       {
- char * args[] = { "targets", "*", 0 };
+ const char * args[] = { "targets", "*", 0 };
           bind_builtin( "PRECIOUS",
                         builtin_precious, 0, args );
       }
 
       {
- char * args [] = { 0 };
+ const char * args [] = { 0 };
           bind_builtin( "SELF_PATH", builtin_self_path, 0, args );
       }
 
       {
- char * args [] = { "path", 0 };
+ const char * args [] = { "path", 0 };
           bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
       }
 
@@ -420,11 +421,11 @@
  * The CALC rule performs simple mathematical operations on two arguments.
  */
 
-LIST * builtin_calc( PARSE * parse, FRAME * frame )
+LIST * builtin_calc( FRAME * frame, int flags )
 {
     LIST * arg = lol_get( frame->args, 0 );
 
- LIST * result = 0;
+ LIST * result = L0;
     long lhs_value;
     long rhs_value;
     long result_value;
@@ -432,17 +433,18 @@
     char const * lhs;
     char const * op;
     char const * rhs;
+ LISTITER iter = list_begin( arg ), end = list_end( arg );
 
- if ( arg == 0 ) return L0;
- lhs = arg->string;
+ if ( iter == end ) return L0;
+ lhs = object_str( list_item( iter ) );
 
- arg = list_next( arg );
- if ( arg == 0 ) return L0;
- op = arg->string;
-
- arg = list_next( arg );
- if ( arg == 0 ) return L0;
- rhs = arg->string;
+ iter = list_next( iter );
+ if ( iter == end ) return L0;
+ op = object_str( list_item( iter ) );
+
+ iter = list_next( iter );
+ if ( iter == end ) return L0;
+ rhs = object_str( list_item( iter ) );
 
     lhs_value = atoi( lhs );
     rhs_value = atoi( rhs );
@@ -461,7 +463,7 @@
     }
 
     sprintf( buffer, "%ld", result_value );
- result = list_new( result, newstr( buffer ) );
+ result = list_push_back( result, object_new( buffer ) );
     return result;
 }
 
@@ -474,21 +476,22 @@
  * targets and sources as TARGETs.
  */
 
-LIST * builtin_depends( PARSE * parse, FRAME * frame )
+LIST * builtin_depends( FRAME * frame, int flags )
 {
     LIST * targets = lol_get( frame->args, 0 );
     LIST * sources = lol_get( frame->args, 1 );
- LIST * l;
-
- for ( l = targets; l; l = list_next( l ) )
+ LISTITER iter, end;
+
+ iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( list_item( iter ) );
 
         /* If doing INCLUDES, switch to the TARGET's include */
         /* TARGET, creating it if needed. The internal include */
         /* TARGET shares the name of its parent. */
 
- if ( parse->num )
+ if ( flags )
         {
             if ( !t->includes )
             {
@@ -502,9 +505,10 @@
     }
 
     /* Enter reverse links */
- for ( l = sources; l; l = list_next( l ) )
+ iter = list_begin( sources ), end = list_end( sources );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- TARGET * s = bindtarget( l->string );
+ TARGET * s = bindtarget( list_item( iter ) );
         s->dependants = targetlist( s->dependants, targets );
     }
 
@@ -520,15 +524,15 @@
  * argument.
  */
 
-LIST * builtin_rebuilds( PARSE * parse, FRAME * frame )
+LIST * builtin_rebuilds( FRAME * frame, int flags )
 {
     LIST * targets = lol_get( frame->args, 0 );
     LIST * rebuilds = lol_get( frame->args, 1 );
- LIST * l;
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
 
- for ( l = targets; l; l = list_next( l ) )
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( list_item( iter ) );
         t->rebuilds = targetlist( t->rebuilds, rebuilds );
     }
 
@@ -543,7 +547,7 @@
  * taken.
  */
 
-LIST * builtin_echo( PARSE * parse, FRAME * frame )
+LIST * builtin_echo( FRAME * frame, int flags )
 {
     list_print( lol_get( frame->args, 0 ) );
     printf( "\n" );
@@ -559,13 +563,14 @@
  * with a failure status.
  */
 
-LIST * builtin_exit( PARSE * parse, FRAME * frame )
+LIST * builtin_exit( FRAME * frame, int flags )
 {
+ LIST * code = lol_get( frame->args, 1 );
     list_print( lol_get( frame->args, 0 ) );
     printf( "\n" );
- if ( lol_get( frame->args, 1 ) )
+ if ( !list_empty( code ) )
     {
- exit( atoi( lol_get( frame->args, 1 )->string ) );
+ exit( atoi( object_str( list_front( code ) ) ) );
     }
     else
     {
@@ -582,11 +587,12 @@
  * It binds each target as a TARGET.
  */
 
-LIST * builtin_flags( PARSE * parse, FRAME * frame )
+LIST * builtin_flags( FRAME * frame, int flags )
 {
     LIST * l = lol_get( frame->args, 0 );
- for ( ; l; l = list_next( l ) )
- bindtarget( l->string )->flags |= parse->num;
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ for ( ; iter != end; iter = list_next( iter ) )
+ bindtarget( list_item( iter ) )->flags |= flags;
     return L0;
 }
 
@@ -612,10 +618,10 @@
 
 static void builtin_glob_back
 (
- void * closure,
- char * file,
- int status,
- time_t time
+ void * closure,
+ OBJECT * file,
+ int status,
+ time_t time
 )
 {
     PROFILE_ENTER( BUILTIN_GLOB_BACK );
@@ -624,15 +630,16 @@
     LIST * l;
     PATHNAME f;
     string buf[ 1 ];
+ LISTITER iter, end;
 
     /* Null out directory for matching. We wish we had file_dirscan() pass up a
      * PATHNAME.
      */
- path_parse( file, &f );
+ path_parse( object_str( file ), &f );
     f.f_dir.len = 0;
 
     /* For globbing, we unconditionally ignore current and parent directory
- * items. Since they items always exist, there is no reason why caller of
+ * items. Since these items always exist, there is no reason why caller of
      * GLOB would want to see them. We could also change file_dirscan(), but
      * then paths with embedded "." and ".." would not work anywhere.
     */
@@ -648,11 +655,12 @@
     if ( globbing->case_insensitive )
         downcase_inplace( buf->value );
 
- for ( l = globbing->patterns; l; l = l->next )
+ iter = list_begin( globbing->patterns ), end = list_end( globbing->patterns );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- if ( !glob( l->string, buf->value ) )
+ if ( !glob( object_str( list_item( iter ) ), buf->value ) )
         {
- globbing->results = list_new( globbing->results, newstr( file ) );
+ globbing->results = list_push_back( globbing->results, object_copy( file ) );
             break;
         }
     }
@@ -665,17 +673,18 @@
 
 static LIST * downcase_list( LIST * in )
 {
- LIST * result = 0;
+ LIST * result = L0;
+ LISTITER iter = list_begin( in ), end = list_end( in );
 
     string s[ 1 ];
     string_new( s );
 
- while ( in )
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- string_copy( s, in->string );
+ string_append( s, object_str( list_item( iter ) ) );
         downcase_inplace( s->value );
- result = list_append( result, list_new( 0, newstr( s->value ) ) );
- in = in->next;
+ result = list_push_back( result, object_new( s->value ) );
+ string_truncate( s, 0 );
     }
 
     string_free( s );
@@ -683,11 +692,12 @@
 }
 
 
-LIST * builtin_glob( PARSE * parse, FRAME * frame )
+LIST * builtin_glob( FRAME * frame, int flags )
 {
     LIST * l = lol_get( frame->args, 0 );
     LIST * r = lol_get( frame->args, 1 );
 
+ LISTITER iter, end;
     struct globbing globbing;
 
     globbing.results = L0;
@@ -703,8 +713,9 @@
     if ( globbing.case_insensitive )
         globbing.patterns = downcase_list( r );
 
- for ( ; l; l = list_next( l ) )
- file_dirscan( l->string, builtin_glob_back, &globbing );
+ iter = list_begin( l ), end = list_end( l );
+ for ( ; iter != end; iter = list_next( iter ) )
+ file_dirscan( list_item( iter ), builtin_glob_back, &globbing );
 
     if ( globbing.case_insensitive )
         list_free( globbing.patterns );
@@ -724,19 +735,19 @@
  * If 'file' exists, append 'file' to 'list'. Returns 'list'.
  */
 
-static LIST * append_if_exists( LIST * list, char * file )
+static LIST * append_if_exists( LIST * list, OBJECT * file )
 {
     time_t time;
     timestamp( file, &time );
     return time > 0
- ? list_new( list, newstr( file ) )
+ ? list_push_back( list, object_copy( file ) )
         : list;
 }
 
 
-LIST * glob1( char * dirname, char * pattern )
+LIST * glob1( OBJECT * dirname, OBJECT * pattern )
 {
- LIST * plist = list_new( L0, pattern );
+ LIST * plist = list_new( object_copy(pattern) );
     struct globbing globbing;
 
     globbing.results = L0;
@@ -763,7 +774,7 @@
 }
 
 
-LIST * glob_recursive( char * pattern )
+LIST * glob_recursive( const char * pattern )
 {
     LIST * result = L0;
 
@@ -771,7 +782,9 @@
     if ( !has_wildcards( pattern ) )
     {
         /* No metacharacters. Check if the path exists. */
- result = append_if_exists(result, pattern);
+ OBJECT * p = object_new( pattern );
+ result = append_if_exists( result, p );
+ object_free( p );
     }
     else
     {
@@ -798,27 +811,35 @@
 
             dirs = has_wildcards( dirname->value )
                 ? glob_recursive( dirname->value )
- : list_new( dirs, dirname->value );
+ : list_push_back( dirs, object_new( dirname->value ) );
 
             if ( has_wildcards( basename->value ) )
             {
- for ( ; dirs; dirs = dirs->next )
- result = list_append( result, glob1( dirs->string,
- basename->value ) );
+ OBJECT * b = object_new( basename->value );
+ LISTITER iter = list_begin( dirs ), end = list_end( dirs );
+ for ( ; iter != end; iter = list_next( iter ) )
+ result = list_append( result, glob1( list_item( iter ), b ) );
+ object_free( b );
             }
             else
             {
+ LISTITER iter = list_begin( dirs ), end = list_end( dirs );
                 string file_string[ 1 ];
                 string_new( file_string );
 
                 /* No wildcard in basename. */
- for ( ; dirs; dirs = dirs->next )
+ for ( ; iter != end; iter = list_next( iter ) )
                 {
- path->f_dir.ptr = dirs->string;
- path->f_dir.len = strlen( dirs->string );
+ OBJECT * p;
+ path->f_dir.ptr = object_str( list_item( iter ) );
+ path->f_dir.len = strlen( object_str( list_item( iter ) ) );
                     path_build( path, file_string, 0 );
 
- result = append_if_exists( result, file_string->value );
+ p = object_new( file_string->value );
+
+ result = append_if_exists( result, p );
+
+ object_free( p );
 
                     string_truncate( file_string, 0 );
                 }
@@ -828,11 +849,15 @@
 
             string_free( dirname );
             string_free( basename );
+
+ list_free( dirs );
         }
         else
         {
             /** No directory, just a pattern. */
- result = list_append( result, glob1( ".", pattern ) );
+ OBJECT * p = object_new( pattern );
+ result = list_append( result, glob1( constant_dot, p ) );
+ object_free( p );
         }
     }
 
@@ -840,12 +865,13 @@
 }
 
 
-LIST * builtin_glob_recursive( PARSE * parse, FRAME * frame )
+LIST * builtin_glob_recursive( FRAME * frame, int flags )
 {
     LIST * result = L0;
     LIST * l = lol_get( frame->args, 0 );
- for ( ; l; l = l->next )
- result = list_append( result, glob_recursive( l->string ) );
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ for ( ; iter != end; iter = list_next( iter ) )
+ result = list_append( result, glob_recursive( object_str( list_item( iter ) ) ) );
     return result;
 }
 
@@ -854,26 +880,31 @@
  * builtin_match() - MATCH rule, regexp matching.
  */
 
-LIST * builtin_match( PARSE * parse, FRAME * frame )
+LIST * builtin_match( FRAME * frame, int flags )
 {
     LIST * l;
     LIST * r;
- LIST * result = 0;
+ LIST * result = L0;
+ LISTITER l_iter, l_end, r_iter, r_end;
 
     string buf[ 1 ];
     string_new( buf );
 
     /* For each pattern */
 
- for ( l = lol_get( frame->args, 0 ); l; l = l->next )
+ l = lol_get( frame->args, 0 );
+ l_iter = list_begin( l ), l_end = list_end( l );
+ for (; l_iter != l_end; l_iter = list_next( l_iter ) )
     {
         /* Result is cached and intentionally never freed. */
- regexp * re = regex_compile( l->string );
+ regexp * re = regex_compile( list_item( l_iter ) );
 
         /* For each string to match against. */
- for ( r = lol_get( frame->args, 1 ); r; r = r->next )
+ r = lol_get( frame->args, 1 );
+ r_iter = list_begin( r ), r_end = list_end( r );
+ for ( ; r_iter != r_end; r_iter = list_next( r_iter ) )
         {
- if ( regexec( re, r->string ) )
+ if ( regexec( re, object_str( list_item( r_iter ) ) ) )
             {
                 int i;
                 int top;
@@ -889,7 +920,7 @@
                 for ( i = 1; i <= top; ++i )
                 {
                     string_append_range( buf, re->startp[ i ], re->endp[ i ] );
- result = list_new( result, newstr( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
                     string_truncate( buf, 0 );
                 }
             }
@@ -900,41 +931,45 @@
     return result;
 }
 
-LIST * builtin_split_by_characters( PARSE * parse, FRAME * frame )
+LIST * builtin_split_by_characters( FRAME * frame, int flags )
 {
     LIST * l1 = lol_get( frame->args, 0 );
     LIST * l2 = lol_get( frame->args, 1 );
 
- LIST * result = 0;
+ LIST * result = L0;
+
+ string buf[ 1 ];
 
- char* s = strdup (l1->string);
- char* delimiters = l2->string;
- char* t;
+ const char * delimiters = object_str( list_front( l2 ) );
+ char * t;
 
- t = strtok (s, delimiters);
- while (t)
+ string_copy( buf, object_str( list_front( l1 ) ) );
+
+ t = strtok( buf->value, delimiters) ;
+ while ( t )
     {
- result = list_new(result, newstr(t));
- t = strtok (NULL, delimiters);
+ result = list_push_back( result, object_new( t ) );
+ t = strtok( NULL, delimiters );
     }
 
- free (s);
+ string_free( buf );
 
     return result;
 }
 
-LIST * builtin_hdrmacro( PARSE * parse, FRAME * frame )
+LIST * builtin_hdrmacro( FRAME * frame, int flags )
 {
   LIST * l = lol_get( frame->args, 0 );
+ LISTITER iter = list_begin( l ), end = list_end( l );
 
- for ( ; l; l = list_next( l ) )
+ for ( ; iter != end; iter = list_next( iter ) )
   {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( list_item( iter ) );
 
     /* Scan file for header filename macro definitions. */
     if ( DEBUG_HEADER )
         printf( "scanning '%s' for header file macro definitions\n",
- l->string );
+ object_str( list_item( iter ) ) );
 
     macro_headers( t );
   }
@@ -955,15 +990,15 @@
     RULE * r = (RULE *)r_;
     LIST * * result = (LIST * *)result_;
     if ( r->exported )
- *result = list_new( *result, copystr( r->name ) );
+ *result = list_push_back( *result, object_copy( r->name ) );
 }
 
 
-LIST * builtin_rulenames( PARSE * parse, FRAME * frame )
+LIST * builtin_rulenames( FRAME * frame, int flags )
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( !list_empty( arg0 ) ? list_front( arg0 ) : 0 );
 
     if ( source_module->rules )
         hashenumerate( source_module->rules, add_rule_name, &result );
@@ -984,36 +1019,17 @@
 static void add_hash_key( void * np, void * result_ )
 {
     LIST * * result = (LIST * *)result_;
- *result = list_new( *result, copystr( *(char * *)np ) );
-}
-
-
-static struct hash * get_running_module_vars()
-{
- struct hash * dummy;
- struct hash * vars = NULL;
- /* Get the global variables pointer (that of the currently running module).
- */
- var_hash_swap( &vars );
- dummy = vars;
- /* Put the global variables pointer in its right place. */
- var_hash_swap( &dummy );
- return vars;
+ *result = list_push_back( *result, object_copy( *(OBJECT * *)np ) );
 }
 
 
-LIST * builtin_varnames( PARSE * parse, FRAME * frame )
+LIST * builtin_varnames( FRAME * frame, int flags )
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( !list_empty(arg0) ? list_front(arg0) : 0 );
 
- /* The running module _always_ has its 'variables' member set to NULL due to
- * the way enter_module() and var_hash_swap() work.
- */
- struct hash * vars = source_module == frame->module
- ? get_running_module_vars()
- : source_module->variables;
+ struct hash * vars = source_module->variables;
 
     if ( vars )
         hashenumerate( vars, add_hash_key, &result );
@@ -1027,20 +1043,28 @@
  * Clears all rules and variables from the given module.
  */
 
-LIST * builtin_delete_module( PARSE * parse, FRAME * frame )
+LIST * builtin_delete_module( FRAME * frame, int flags )
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( !list_empty(arg0) ? list_front(arg0) : 0 );
     delete_module( source_module );
     return result;
 }
 
 
-static void unknown_rule( FRAME * frame, char * key, char * module_name, char * rule_name )
+static void unknown_rule( FRAME * frame, const char * key, module_t * module, OBJECT * rule_name )
 {
+ const char * module_name = module->name ? object_str( module->name ) : "";
     backtrace_line( frame->prev );
- printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
+ if ( module->name )
+ {
+ printf( "%s error: rule \"%s\" unknown in module \"%s.\"\n", key, object_str( rule_name ), object_str( module->name ) );
+ }
+ else
+ {
+ printf( "%s error: rule \"%s\" unknown in module \"\"\n", key, object_str( rule_name ) );
+ }
     backtrace( frame->prev );
     exit( 1 );
 }
@@ -1067,7 +1091,7 @@
  * variables.
  */
 
-LIST * builtin_import( PARSE * parse, FRAME * frame )
+LIST * builtin_import( FRAME * frame, int flags )
 {
     LIST * source_module_list = lol_get( frame->args, 0 );
     LIST * source_rules = lol_get( frame->args, 1 );
@@ -1076,37 +1100,35 @@
     LIST * localize = lol_get( frame->args, 4 );
 
     module_t * target_module =
- bindmodule( target_module_list ? target_module_list->string : 0 );
+ bindmodule( !list_empty( target_module_list ) ? list_front( target_module_list ) : 0 );
     module_t * source_module =
- bindmodule( source_module_list ? source_module_list->string : 0 );
+ bindmodule( !list_empty( source_module_list ) ? list_front( source_module_list ) : 0 );
 
- LIST * source_name;
- LIST * target_name;
+ LISTITER source_iter = list_begin( source_rules ), source_end = list_end( source_rules );
+ LISTITER target_iter = list_begin( target_rules ), target_end = list_end( target_rules );
 
- for ( source_name = source_rules, target_name = target_rules;
- source_name && target_name;
- source_name = list_next( source_name ),
- target_name = list_next( target_name ) )
+ for ( ;
+ source_iter != source_end && target_iter != target_end;
+ source_iter = list_next( source_iter ),
+ target_iter = list_next( target_iter ) )
     {
- RULE r_;
- RULE * r = &r_;
+ RULE * r;
         RULE * imported;
- r_.name = source_name->string;
 
         if ( !source_module->rules ||
- !hashcheck( source_module->rules, (HASHDATA * *)&r ) )
- unknown_rule( frame, "IMPORT", source_module->name, r_.name );
+ !(r = (RULE *)hash_find( source_module->rules, list_item( source_iter ) ) ) )
+ unknown_rule( frame, "IMPORT", source_module, list_item( source_iter ) );
 
- imported = import_rule( r, target_module, target_name->string );
- if ( localize )
- imported->module = target_module;
+ imported = import_rule( r, target_module, list_item( target_iter ) );
+ if ( !list_empty( localize ) )
+ rule_localize( imported, target_module );
         /* This rule is really part of some other module. Just refer to it here,
          * but do not let it out.
          */
         imported->exported = 0;
     }
 
- if ( source_name || target_name )
+ if ( source_iter != source_end || target_iter != target_end )
     {
         backtrace_line( frame->prev );
         printf( "import error: length of source and target rule name lists don't match!\n" );
@@ -1131,20 +1153,19 @@
  * is issued.
  */
 
-LIST * builtin_export( PARSE * parse, FRAME * frame )
+LIST * builtin_export( FRAME * frame, int flags )
 {
     LIST * module_list = lol_get( frame->args, 0 );
     LIST * rules = lol_get( frame->args, 1 );
- module_t * m = bindmodule( module_list ? module_list->string : 0 );
+ module_t * m = bindmodule( !list_empty( module_list ) ? list_front( module_list ) : 0 );
 
- for ( ; rules; rules = list_next( rules ) )
+ LISTITER iter = list_begin( rules ), end = list_end( rules );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- RULE r_;
- RULE * r = &r_;
- r_.name = rules->string;
+ RULE * r;
 
- if ( !m->rules || !hashcheck( m->rules, (HASHDATA * *)&r ) )
- unknown_rule( frame, "EXPORT", m->name, r_.name );
+ if ( !m->rules || !(r = (RULE *)hash_find( m->rules, list_item( iter ) ) ) )
+ unknown_rule( frame, "EXPORT", m, list_item( iter ) );
 
         r->exported = 1;
     }
@@ -1157,12 +1178,12 @@
  * indicated for a given procedure in debug output or an error backtrace.
  */
 
-static void get_source_line( PARSE * procedure, char * * file, int * line )
+static void get_source_line( FRAME * frame, const char * * file, int * line )
 {
- if ( procedure )
+ if ( frame->file )
     {
- char * f = procedure->file;
- int l = procedure->line;
+ const char * f = object_str( frame->file );
+ int l = frame->line;
         if ( !strcmp( f, "+" ) )
         {
             f = "jambase.c";
@@ -1179,12 +1200,12 @@
 }
 
 
-void print_source_line( PARSE * p )
+void print_source_line( FRAME * frame )
 {
- char * file;
+ const char * file;
     int line;
 
- get_source_line( p, &file, &line );
+ get_source_line( frame, &file, &line );
     if ( line < 0 )
         printf( "(builtin):" );
     else
@@ -1205,7 +1226,7 @@
     }
     else
     {
- print_source_line( frame->procedure );
+ print_source_line( frame );
         printf( " in %s\n", frame->rulename );
     }
 }
@@ -1231,23 +1252,31 @@
  * period.
  */
 
-LIST * builtin_backtrace( PARSE * parse, FRAME * frame )
+LIST * builtin_backtrace( FRAME * frame, int flags )
 {
     LIST * levels_arg = lol_get( frame->args, 0 );
- int levels = levels_arg ? atoi( levels_arg->string ) : ( (unsigned int)(-1) >> 1 ) ;
+ int levels = !list_empty( levels_arg ) ? atoi( object_str( list_front( levels_arg ) ) ) : (int)( (unsigned int)(-1) >> 1 ) ;
 
     LIST * result = L0;
     for ( ; ( frame = frame->prev ) && levels ; --levels )
     {
- char * file;
+ const char * file;
         int line;
         char buf[32];
- get_source_line( frame->procedure, &file, &line );
+ string module_name[1];
+ get_source_line( frame, &file, &line );
         sprintf( buf, "%d", line );
- result = list_new( result, newstr( file ) );
- result = list_new( result, newstr( buf ) );
- result = list_new( result, newstr( frame->module->name ) );
- result = list_new( result, newstr( frame->rulename ) );
+ string_new( module_name );
+ if ( frame->module->name )
+ {
+ string_append( module_name, object_str( frame->module->name ) );
+ string_append( module_name, "." );
+ }
+ result = list_push_back( result, object_new( file ) );
+ result = list_push_back( result, object_new( buf ) );
+ result = list_push_back( result, object_new( module_name->value ) );
+ result = list_push_back( result, object_new( frame->rulename ) );
+ string_free( module_name );
     }
     return result;
 }
@@ -1265,10 +1294,10 @@
  * behavior.
  */
 
-LIST * builtin_caller_module( PARSE * parse, FRAME * frame )
+LIST * builtin_caller_module( FRAME * frame, int flags )
 {
     LIST * levels_arg = lol_get( frame->args, 0 );
- int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
+ int levels = !list_empty( levels_arg ) ? atoi( object_str( list_front( levels_arg ) ) ) : 0 ;
 
     int i;
     for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i )
@@ -1276,16 +1305,8 @@
 
     if ( frame->module == root_module() )
         return L0;
-
- {
- LIST * result;
- string name;
- string_copy( &name, frame->module->name );
- string_pop_back( &name );
- result = list_new( L0, newstr(name.value) );
- string_free( &name );
- return result;
- }
+ else
+ return list_new( object_copy( frame->module->name ) );
 }
 
 
@@ -1295,7 +1316,7 @@
  * Usage: pwd = [ PWD ] ;
  */
 
-LIST * builtin_pwd( PARSE * parse, FRAME * frame )
+LIST * builtin_pwd( FRAME * frame, int flags )
 {
     return pwd();
 }
@@ -1305,13 +1326,14 @@
  * Adds targets to the list of target that jam will attempt to update.
  */
 
-LIST * builtin_update( PARSE * parse, FRAME * frame )
+LIST * builtin_update( FRAME * frame, int flags )
 {
- LIST * result = list_copy( L0, targets_to_update() );
+ LIST * result = list_copy( targets_to_update() );
     LIST * arg1 = lol_get( frame->args, 0 );
+ LISTITER iter = list_begin( arg1 ), end = list_end( arg1 );
     clear_targets_to_update();
- for ( ; arg1; arg1 = list_next( arg1 ) )
- mark_target_for_updating( newstr( arg1->string ) );
+ for ( ; iter != end; iter = list_next( iter ) )
+ mark_target_for_updating( object_copy( list_item( iter ) ) );
     return result;
 }
 
@@ -1325,34 +1347,30 @@
    Third parameter, if non-empty, specifies that the -n option should have
    no effect -- that is, all out-of-date targets should be rebuild.
 */
-LIST * builtin_update_now( PARSE * parse, FRAME * frame )
+LIST * builtin_update_now( FRAME * frame, int flags )
 {
     LIST * targets = lol_get( frame->args, 0 );
     LIST * log = lol_get( frame->args, 1 );
- LIST * force = lol_get (frame->args, 2);
- LIST * continue_ = lol_get(frame->args, 3);
- int status = 0;
- int original_stdout;
- int original_stderr;
- int n;
- int targets_count;
- const char** targets2;
- int i;
- int original_noexec;
- int original_quitquick;
+ LIST * force = lol_get( frame->args, 2 );
+ LIST * continue_ = lol_get( frame->args, 3 );
+ int status;
+ int original_stdout = 0;
+ int original_stderr = 0;
+ int original_noexec = 0;
+ int original_quitquick = 0;
         
 
- if (log)
+ if ( !list_empty( log ) )
     {
- int fd = atoi(log->string);
+ int fd = atoi( object_str( list_front( log ) ) );
         /* Redirect stdout and stderr, temporary, to the log file. */
- original_stdout = dup (0);
- original_stderr = dup (1);
- dup2 (fd, 0);
- dup2 (fd, 1);
+ original_stdout = dup( 0 );
+ original_stderr = dup( 1 );
+ dup2 ( fd, 0 );
+ dup2 ( fd, 1 );
     }
 
- if (force)
+ if ( !list_empty( force ) )
     {
         original_noexec = globs.noexec;
         globs.noexec = 0;
@@ -1360,95 +1378,83 @@
         globs.quitquick = 0;
     }
 
- if (continue_)
+ if ( !list_empty( continue_ ) )
     {
         original_quitquick = globs.quitquick;
         globs.quitquick = 0;
     }
 
- targets_count = list_length( targets );
- targets2 = (const char * *)BJAM_MALLOC( targets_count * sizeof( char * ) );
- for (i = 0 ; targets; targets = list_next( targets ) )
- targets2[ i++ ] = targets->string;
- status |= make( targets_count, targets2, anyhow);
- free( targets );
+ status = make( targets, anyhow );
 
- if (force)
+ if ( !list_empty( force ) )
     {
         globs.noexec = original_noexec;
         globs.quitquick = original_quitquick;
     }
 
- if (continue_)
+ if ( !list_empty( continue_ ) )
     {
         globs.quitquick = original_quitquick;
     }
 
- if (log)
+ if ( !list_empty( log ) )
     {
         /* Flush whatever stdio might have buffered, while descriptions
            0 and 1 still refer to the log file. */
- fflush (stdout);
- fflush (stderr);
- dup2 (original_stdout, 0);
- dup2 (original_stderr, 1);
- close (original_stdout);
- close (original_stderr);
+ fflush( stdout );
+ fflush( stderr );
+ dup2( original_stdout, 0 );
+ dup2( original_stderr, 1 );
+ close( original_stdout );
+ close( original_stderr );
     }
 
     last_update_now_status = status;
         
- if (status == 0)
- return list_new (L0, newstr ("ok"));
+ if ( status == 0 )
+ return list_new( object_copy( constant_ok ) );
     else
         return L0;
 }
 
-LIST * builtin_search_for_target( PARSE * parse, FRAME * frame )
-{
- LIST * arg1 = lol_get( frame->args, 0 );
- LIST * arg2 = lol_get( frame->args, 1 );
- TARGET * t = search_for_target( arg1->string, arg2 );
- return list_new( L0, t->name );
-}
-
 
-LIST * builtin_import_module( PARSE * parse, FRAME * frame )
+LIST * builtin_import_module( FRAME * frame, int flags )
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     LIST * arg2 = lol_get( frame->args, 1 );
- module_t * m = arg2 ? bindmodule( arg2->string ) : root_module();
+ module_t * m = !list_empty( arg2 ) ? bindmodule( list_front( arg2 ) ) : root_module();
     import_module( arg1, m );
     return L0;
 }
 
 
-LIST * builtin_imported_modules( PARSE * parse, FRAME * frame )
+LIST * builtin_imported_modules( FRAME * frame, int flags )
 {
     LIST * arg0 = lol_get( frame->args, 0 );
- return imported_modules( bindmodule( arg0 ? arg0->string : 0 ) );
+ return imported_modules( bindmodule( !list_empty( arg0 ) ? list_front( arg0 ) : 0 ) );
 }
 
 
-LIST * builtin_instance( PARSE * parse, FRAME * frame )
+LIST * builtin_instance( FRAME * frame, int flags )
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     LIST * arg2 = lol_get( frame->args, 1 );
- module_t * const instance = bindmodule( arg1->string );
- module_t * const class_module = bindmodule( arg2->string );
+ module_t * const instance = bindmodule( list_front( arg1 ) );
+ module_t * const class_module = bindmodule( list_front( arg2 ) );
     instance->class_module = class_module;
+ module_set_fixed_variables( instance, class_module->num_fixed_variables );
     return L0;
 }
 
 
-LIST * builtin_sort( PARSE * parse, FRAME * frame )
+LIST * builtin_sort( FRAME * frame, int flags )
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     return list_sort( arg1 );
 }
 
 
-LIST * builtin_normalize_path( PARSE * parse, FRAME * frame )
+LIST * builtin_normalize_path( FRAME * frame, int flags )
 {
     LIST * arg = lol_get( frame->args, 0 );
 
@@ -1468,7 +1474,8 @@
         /* Number of '..' elements seen and not processed yet. */
     int dotdots = 0;
     int rooted = 0;
- char * result = 0;
+ OBJECT * result = 0;
+ LISTITER arg_iter = list_begin( arg ), arg_end = list_end( arg );
 
     /* Make a copy of input: we should not change it. Prepend a '/' before it as
      * a guard for the algorithm later on and remember whether it was originally
@@ -1476,16 +1483,16 @@
      */
     string_new( in );
     string_push_back( in, '/' );
- for ( ; arg; arg = list_next( arg ) )
+ for ( ; arg_iter != arg_end; arg_iter = list_next( arg_iter ) )
     {
- if ( arg->string[ 0 ] != '\0' )
+ if ( object_str( list_item( arg_iter ) )[ 0 ] != '\0' )
         {
             if ( in->size == 1 )
- rooted = ( ( arg->string[ 0 ] == '/' ) ||
- ( arg->string[ 0 ] == '\\' ) );
+ rooted = ( ( object_str( list_item( arg_iter ) )[ 0 ] == '/' ) ||
+ ( object_str( list_item( arg_iter ) )[ 0 ] == '\\' ) );
             else
                 string_append( in, "/" );
- string_append( in, arg->string );
+ string_append( in, object_str( list_item( arg_iter ) ) );
         }
     }
 
@@ -1544,7 +1551,12 @@
      */
     if ( dotdots )
     {
- if ( rooted ) return L0;
+ if ( rooted )
+ {
+ string_free( out );
+ string_free( in );
+ return L0;
+ }
         do
             string_append( out, "/.." );
         while ( --dotdots );
@@ -1561,34 +1573,32 @@
      * the original path was rooted and we have an empty path we need to add
      * back the '/'.
      */
- result = newstr( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
+ result = object_new( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
 
     string_free( out );
     string_free( in );
 
- return list_new( 0, result );
+ return list_new( result );
 }
 
 
-LIST * builtin_native_rule( PARSE * parse, FRAME * frame )
+LIST * builtin_native_rule( FRAME * frame, int flags )
 {
     LIST * module_name = lol_get( frame->args, 0 );
     LIST * rule_name = lol_get( frame->args, 1 );
 
- module_t * module = bindmodule( module_name->string );
+ module_t * module = bindmodule( list_front( module_name ) );
 
- native_rule_t n;
- native_rule_t * np = &n;
- n.name = rule_name->string;
- if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
+ native_rule_t * np;
+ if ( module->native_rules && (np = (native_rule_t *)hash_find( module->native_rules, list_front( rule_name ) ) ) )
     {
- new_rule_body( module, np->name, np->arguments, np->procedure, 1 );
+ new_rule_body( module, np->name, np->procedure, 1 );
     }
     else
     {
         backtrace_line( frame->prev );
- printf( "error: no native rule \"%s\" defined in module \"%s\"\n",
- n.name, module->name );
+ printf( "error: no native rule \"%s\" defined in module \"%s.\"\n",
+ object_str( list_front( rule_name ) ), object_str( module->name ) );
         backtrace( frame->prev );
         exit( 1 );
     }
@@ -1596,40 +1606,39 @@
 }
 
 
-LIST * builtin_has_native_rule( PARSE * parse, FRAME * frame )
+LIST * builtin_has_native_rule( FRAME * frame, int flags )
 {
     LIST * module_name = lol_get( frame->args, 0 );
     LIST * rule_name = lol_get( frame->args, 1 );
     LIST * version = lol_get( frame->args, 2 );
 
- module_t * module = bindmodule( module_name->string );
+ module_t * module = bindmodule( list_front( module_name ) );
 
- native_rule_t n;
- native_rule_t * np = &n;
- n.name = rule_name->string;
- if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
+ native_rule_t * np;
+ if ( module->native_rules && (np = (native_rule_t *)hash_find( module->native_rules, list_front( rule_name ) ) ) )
     {
- int expected_version = atoi( version->string );
+ int expected_version = atoi( object_str( list_front( version ) ) );
         if ( np->version == expected_version )
- return list_new( 0, newstr( "true" ) );
+ return list_new( object_copy( constant_true ) );
     }
     return L0;
 }
 
 
-LIST * builtin_user_module( PARSE * parse, FRAME * frame )
+LIST * builtin_user_module( FRAME * frame, int flags )
 {
     LIST * module_name = lol_get( frame->args, 0 );
- for ( ; module_name; module_name = module_name->next )
+ LISTITER iter = list_begin( module_name ), end = list_end( module_name );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- module_t * m = bindmodule( module_name->string );
+ module_t * m = bindmodule( list_item( iter ) );
         m->user_module = 1;
     }
     return L0;
 }
 
 
-LIST * builtin_nearest_user_location( PARSE * parse, FRAME * frame )
+LIST * builtin_nearest_user_location( FRAME * frame, int flags )
 {
     FRAME * nearest_user_frame =
         frame->module->user_module ? frame : frame->prev_user;
@@ -1637,33 +1646,33 @@
         return L0;
 
     {
- LIST * result = 0;
- char * file;
+ LIST * result = L0;
+ const char * file;
         int line;
         char buf[32];
 
- get_source_line( nearest_user_frame->procedure, &file, &line );
+ get_source_line( nearest_user_frame, &file, &line );
         sprintf( buf, "%d", line );
- result = list_new( result, newstr( file ) );
- result = list_new( result, newstr( buf ) );
+ result = list_push_back( result, object_new( file ) );
+ result = list_push_back( result, object_new( buf ) );
         return result;
     }
 }
 
 
-LIST * builtin_check_if_file( PARSE * parse, FRAME * frame )
+LIST * builtin_check_if_file( FRAME * frame, int flags )
 {
     LIST * name = lol_get( frame->args, 0 );
- return file_is_file( name->string ) == 1
- ? list_new( 0, newstr( "true" ) )
+ return file_is_file( list_front( name ) ) == 1
+ ? list_new( object_copy( constant_true ) )
         : L0 ;
 }
 
 
-LIST * builtin_md5( PARSE * parse, FRAME * frame )
+LIST * builtin_md5( FRAME * frame, int flags )
 {
     LIST * l = lol_get( frame->args, 0 );
- char* s = l->string;
+ const char* s = object_str( list_front( l ) );
 
     md5_state_t state;
     md5_byte_t digest[16];
@@ -1671,36 +1680,36 @@
 
     int di;
 
- md5_init(&state);
- md5_append(&state, (const md5_byte_t *)s, strlen(s));
- md5_finish(&state, digest);
+ md5_init( &state );
+ md5_append( &state, (const md5_byte_t *)s, strlen(s) );
+ md5_finish( &state, digest );
 
     for (di = 0; di < 16; ++di)
- sprintf(hex_output + di * 2, "%02x", digest[di]);
+ sprintf( hex_output + di * 2, "%02x", digest[di] );
 
- return list_new (0, newstr(hex_output));
+ return list_new( object_new( hex_output ) );
 }
 
-LIST *builtin_file_open( PARSE *parse, FRAME *frame )
+LIST *builtin_file_open( FRAME * frame, int flags )
 {
- char* name = lol_get(frame->args, 0)->string;
- char* mode = lol_get(frame->args, 1)->string;
+ const char * name = object_str( list_front( lol_get( frame->args, 0 ) ) );
+ const char * mode = object_str( list_front( lol_get( frame->args, 1 ) ) );
     int fd;
     char buffer[sizeof("4294967295")];
 
- if (strcmp(mode, "w") == 0)
+ if ( strcmp(mode, "w") == 0 )
     {
- fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ fd = open( name, O_WRONLY|O_CREAT|O_TRUNC, 0666 );
     }
     else
     {
- fd = open(name, O_RDONLY);
+ fd = open( name, O_RDONLY );
     }
 
     if (fd != -1)
     {
- sprintf(buffer, "%d", fd);
- return list_new(L0, newstr(buffer));
+ sprintf( buffer, "%d", fd );
+ return list_new( object_new( buffer ) );
     }
     else
     {
@@ -1708,52 +1717,53 @@
     }
 }
 
-LIST *builtin_pad( PARSE *parse, FRAME *frame )
+LIST *builtin_pad( FRAME * frame, int flags )
 {
- char *string = lol_get(frame->args, 0)->string;
- char *width_s = lol_get(frame->args, 1)->string;
+ OBJECT * string = list_front( lol_get( frame->args, 0 ) );
+ const char * width_s = object_str( list_front( lol_get( frame->args, 1 ) ) );
 
- int current = strlen (string);
- int desired = atoi(width_s);
+ int current = strlen( object_str( string ) );
+ int desired = atoi( width_s );
     if (current >= desired)
- return list_new (L0, string);
+ return list_new( object_copy( string ) );
     else
     {
- char *buffer = malloc (desired + 1);
+ char * buffer = BJAM_MALLOC( desired + 1 );
         int i;
- LIST *result;
+ LIST * result;
 
- strcpy (buffer, string);
- for (i = current; i < desired; ++i)
+ strcpy( buffer, object_str( string ) );
+ for ( i = current; i < desired; ++i )
             buffer[i] = ' ';
         buffer[desired] = '\0';
- result = list_new (L0, newstr (buffer));
- free (buffer);
+ result = list_new( object_new( buffer ) );
+ BJAM_FREE( buffer );
         return result;
     }
 }
 
-LIST *builtin_precious( PARSE *parse, FRAME *frame )
+LIST *builtin_precious( FRAME * frame, int flags )
 {
- LIST* targets = lol_get(frame->args, 0);
+ LIST * targets = lol_get(frame->args, 0);
 
- for ( ; targets; targets = list_next( targets ) )
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- TARGET* t = bindtarget (targets->string);
+ TARGET* t = bindtarget( list_item( iter ) );
         t->flags |= T_FLAG_PRECIOUS;
     }
 
     return L0;
 }
 
-LIST *builtin_self_path( PARSE *parse, FRAME *frame )
+LIST *builtin_self_path( FRAME * frame, int flags )
 {
- extern char *saved_argv0;
- char *p = executable_path (saved_argv0);
- if (p)
+ extern const char * saved_argv0;
+ char * p = executable_path( saved_argv0 );
+ if ( p )
     {
- LIST* result = list_new (0, newstr (p));
- free(p);
+ LIST* result = list_new( object_new( p ) );
+ free( p );
         return result;
     }
     else
@@ -1762,13 +1772,13 @@
     }
 }
 
-LIST *builtin_makedir( PARSE *parse, FRAME *frame )
+LIST *builtin_makedir( FRAME * frame, int flags )
 {
- LIST *path = lol_get(frame->args, 0);
+ LIST * path = lol_get( frame->args, 0 );
 
- if (file_mkdir(path->string) == 0)
+ if ( file_mkdir( object_str( list_front( path ) ) ) == 0 )
     {
- LIST *result = list_new (0, newstr(path->string));
+ LIST * result = list_new( object_copy( list_front( path ) ) );
         return result;
     }
     else
@@ -1779,13 +1789,13 @@
 
 #ifdef HAVE_PYTHON
 
-LIST * builtin_python_import_rule( PARSE * parse, FRAME * frame )
+LIST * builtin_python_import_rule( FRAME * frame, int flags )
 {
     static int first_time = 1;
- char * python_module = lol_get( frame->args, 0 )->string;
- char * python_function = lol_get( frame->args, 1 )->string;
- char * jam_module = lol_get( frame->args, 2 )->string;
- char * jam_rule = lol_get( frame->args, 3 )->string;
+ const char * python_module = object_str( list_front( lol_get( frame->args, 0 ) ) );
+ const char * python_function = object_str( list_front( lol_get( frame->args, 1 ) ) );
+ OBJECT * jam_module = list_front( lol_get( frame->args, 2 ) );
+ OBJECT * jam_rule = list_front( lol_get( frame->args, 3 ) );
 
     PyObject * pName;
     PyObject * pModule;
@@ -1799,29 +1809,19 @@
          */
         LIST * extra = 0;
         module_t * outer_module = frame->module;
+ LISTITER iter, end;
 
         first_time = 0;
 
- if ( outer_module != root_module() )
- {
- exit_module( outer_module );
- enter_module( root_module() );
- }
-
- extra = var_get( "EXTRA_PYTHONPATH" );
+ extra = var_get( root_module(), constant_extra_pythonpath );
 
- if ( outer_module != root_module() )
- {
- exit_module( root_module() );
- enter_module( outer_module );
- }
-
- for ( ; extra; extra = extra->next )
+ iter = list_begin( extra ), end = list_end( extra );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
             string buf[ 1 ];
             string_new( buf );
             string_append( buf, "import sys\nsys.path.append(\"" );
- string_append( buf, extra->string );
+ string_append( buf, object_str( list_item( iter ) ) );
             string_append( buf, "\")\n" );
             PyRun_SimpleString( buf->value );
             string_free( buf );
@@ -1840,12 +1840,7 @@
         if ( pFunc && PyCallable_Check( pFunc ) )
         {
             module_t * m = bindmodule( jam_module );
- RULE * r = bindrule( jam_rule, m );
-
- /* Make pFunc owned. */
- Py_INCREF( pFunc );
-
- r->python_function = pFunc;
+ new_rule_body( m, jam_rule, function_python( pFunc, 0 ), 0 );
         }
         else
         {
@@ -1866,7 +1861,7 @@
 
 #endif
 
-void lol_build( LOL * lol, char * * elements )
+void lol_build( LOL * lol, const char * * elements )
 {
     LIST * l = L0;
     lol_init( lol );
@@ -1880,7 +1875,7 @@
         }
         else
         {
- l = list_new( l, newstr( *elements ) );
+ l = list_push_back( l, object_new( *elements ) );
         }
         ++elements;
     }
@@ -1900,22 +1895,21 @@
 
 PyObject* bjam_call( PyObject * self, PyObject * args )
 {
- FRAME inner[ 1 ];
- LIST * result;
- PARSE * p;
- char * rulename;
+ FRAME inner[ 1 ];
+ LIST * result;
+ PARSE * p;
+ OBJECT * rulename;
 
     /* Build up the list of arg lists. */
     frame_init( inner );
     inner->prev = 0;
     inner->prev_user = 0;
- inner->module = bindmodule( "python_interface" );
- inner->procedure = 0;
+ inner->module = bindmodule( constant_python_interface );
 
     /* Extract the rule name and arguments from 'args'. */
 
     /* PyTuple_GetItem returns borrowed reference. */
- rulename = PyString_AsString( PyTuple_GetItem( args, 0 ) );
+ rulename = object_new( PyString_AsString( PyTuple_GetItem( args, 0 ) ) );
     {
         int i = 1;
         int size = PyTuple_Size( args );
@@ -1924,7 +1918,7 @@
             PyObject * a = PyTuple_GetItem( args, i );
             if ( PyString_Check( a ) )
             {
- lol_add( inner->args, list_new( 0, newstr(
+ lol_add( inner->args, list_new( object_new(
                     PyString_AsString( a ) ) ) );
             }
             else if ( PySequence_Check( a ) )
@@ -1942,7 +1936,7 @@
                         printf( "Invalid parameter type passed from Python\n" );
                         exit( 1 );
                     }
- l = list_new( l, newstr( s ) );
+ l = list_push_back( l, object_new( s ) );
                     Py_DECREF( e );
                 }
                 lol_add( inner->args, l );
@@ -1951,6 +1945,7 @@
     }
 
     result = evaluate_rule( rulename, inner );
+ object_free( rulename );
 
     frame_free( inner );
 
@@ -1958,10 +1953,10 @@
     {
         PyObject * pyResult = PyList_New( list_length( result ) );
         int i = 0;
- while ( result )
+ LISTITER iter = list_begin( result ), end = list_end( result );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- PyList_SetItem( pyResult, i, PyString_FromString( result->string ) );
- result = list_next( result );
+ PyList_SetItem( pyResult, i, PyString_FromString( object_str( list_item( iter ) ) ) );
             i += 1;
         }
         list_free( result );
@@ -1988,6 +1983,8 @@
     PyObject * bjam_signature = NULL;
     module_t * m;
     RULE * r;
+ OBJECT * module_name;
+ OBJECT * rule_name;
 
     if ( !PyArg_ParseTuple( args, "ssO|O:import_rule",
                             &module, &rule, &func, &bjam_signature ) )
@@ -2000,29 +1997,15 @@
         return NULL;
     }
 
- m = bindmodule( *module ? module : 0 );
- r = bindrule( rule, m );
-
- /* Make pFunc owned. */
- Py_INCREF( func );
-
- r->python_function = func;
- r->arguments = 0;
-
- if (bjam_signature)
- {
- argument_list * arg_list = args_new();
- Py_ssize_t i;
-
- Py_ssize_t s = PySequence_Size (bjam_signature);
- for (i = 0; i < s; ++i)
- {
- PyObject* v = PySequence_GetItem (bjam_signature, i);
- lol_add(arg_list->data, list_from_python (v));
- Py_DECREF(v);
- }
- r->arguments = arg_list;
- }
+ module_name = *module ? object_new( module ) : 0;
+ m = bindmodule( module_name );
+ if( module_name )
+ {
+ object_free( module_name );
+ }
+ rule_name = object_new( rule );
+ new_rule_body( m, rule_name, function_python( func, bjam_signature ), 0 );
+ object_free( rule_name );
 
     Py_INCREF( Py_None );
     return Py_None;
@@ -2048,6 +2031,8 @@
     LIST * bindlist = L0;
     int n;
     int i;
+ OBJECT * name_str;
+ FUNCTION * body_func;
 
     if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
                           &PyList_Type, &bindlist_python, &flags ) )
@@ -2063,10 +2048,14 @@
                             "bind list has non-string type" );
             return NULL;
         }
- bindlist = list_new( bindlist, PyString_AsString( next ) );
+ bindlist = list_push_back( bindlist, object_new( PyString_AsString( next ) ) );
     }
 
- new_rule_actions( root_module(), name, newstr( body ), bindlist, flags );
+ name_str = object_new( name );
+ body_func = function_compile_actions( body, constant_builtin, -1 );
+ new_rule_actions( root_module(), name_str, body_func, bindlist, flags );
+ function_free( body_func );
+ object_free( name_str );
 
     Py_INCREF( Py_None );
     return Py_None;
@@ -2083,17 +2072,20 @@
     LIST * value;
     PyObject * result;
     int i;
+ OBJECT * varname;
+ LISTITER iter, end;
 
     if ( !PyArg_ParseTuple( args, "s", &name ) )
         return NULL;
 
- enter_module( root_module() );
- value = var_get( name );
- exit_module( root_module() );
+ varname = object_new( name );
+ value = var_get( root_module(), varname );
+ object_free( varname );
+ iter = list_begin( value ), end = list_end( value );
 
     result = PyList_New( list_length( value ) );
- for ( i = 0; value; value = list_next( value ), ++i )
- PyList_SetItem( result, i, PyString_FromString( value->string ) );
+ for ( i = 0; iter != end; iter = list_next( iter ), ++i )
+ PyList_SetItem( result, i, PyString_FromString( object_str( list_item( iter ) ) ) );
 
     return result;
 }
@@ -2106,19 +2098,28 @@
 
     for ( ; f = f->prev; )
     {
- PyObject * tuple = PyTuple_New( 4 );
- char * file;
- int line;
- char buf[ 32 ];
+ PyObject * tuple = PyTuple_New( 4 );
+ const char * file;
+ int line;
+ char buf[ 32 ];
+ string module_name[1];
 
- get_source_line( f->procedure, &file, &line );
+ get_source_line( f, &file, &line );
         sprintf( buf, "%d", line );
+ string_new( module_name );
+ if ( f->module->name )
+ {
+ string_append( module_name, object_str( f->module->name ) );
+ string_append( module_name, "." );
+ }
 
         /* PyTuple_SetItem steals reference. */
         PyTuple_SetItem( tuple, 0, PyString_FromString( file ) );
         PyTuple_SetItem( tuple, 1, PyString_FromString( buf ) );
- PyTuple_SetItem( tuple, 2, PyString_FromString( f->module->name ) );
- PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
+ PyTuple_SetItem( tuple, 2, PyString_FromString( module_name->value ) );
+ PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
+
+ string_free( module_name );
 
         PyList_Append( result, tuple );
         Py_DECREF( tuple );
@@ -2128,9 +2129,10 @@
 
 PyObject * bjam_caller( PyObject * self, PyObject * args )
 {
- PyObject *result = PyString_FromString(
- frame_before_python_call->prev->module->name);
- return result;
+ const char * s = frame_before_python_call->prev->module->name ?
+ object_str( frame_before_python_call->prev->module->name ) :
+ "";
+ return PyString_FromString( s );
 }
 
 #endif /* #ifdef HAVE_PYTHON */
@@ -2189,7 +2191,7 @@
      * should Windows ever 'fix' this feature.
      * (03.06.2008.) (Jurko)
      */
- static FILE * windows_popen_wrapper( char * command, char * mode )
+ static FILE * windows_popen_wrapper( const char * command, const char * mode )
     {
         int extra_command_quotes_needed = ( strchr( command, '"' ) != 0 );
         string quoted_command;
@@ -2214,18 +2216,18 @@
 #endif
 
 
-static char * rtrim(char *s)
+static char * rtrim( char * s )
 {
- char *p = s;
- while(*p) ++p;
- for(--p; p >= s && isspace(*p); *p-- = 0);
+ char * p = s;
+ while ( *p ) ++p;
+ for ( --p; p >= s && isspace( *p ); *p-- = 0 );
     return s;
 }
 
-LIST * builtin_shell( PARSE * parse, FRAME * frame )
+LIST * builtin_shell( FRAME * frame, int flags )
 {
     LIST * command = lol_get( frame->args, 0 );
- LIST * result = 0;
+ LIST * result = L0;
     string s;
     int ret;
     char buffer[ 1024 ];
@@ -2239,17 +2241,17 @@
     {
         int a = 1;
         LIST * arg = lol_get( frame->args, a );
- while ( arg )
+ while ( !list_empty( arg ) )
         {
- if ( strcmp( "exit-status", arg->string ) == 0 )
+ if ( strcmp( "exit-status", object_str( list_front( arg ) ) ) == 0 )
             {
                 exit_status_opt = 1;
             }
- else if ( strcmp( "no-output", arg->string ) == 0 )
+ else if ( strcmp( "no-output", object_str( list_front( arg ) ) ) == 0 )
             {
                 no_output_opt = 1;
             }
- else if ( strcmp("strip-eol", arg->string) == 0 )
+ else if ( strcmp("strip-eol", object_str( list_front( arg ) ) ) == 0 )
             {
                 strip_eol_opt = 1;
             }
@@ -2263,7 +2265,7 @@
      */
     fflush( NULL );
 
- p = popen( command->string, "r" );
+ p = popen( object_str( list_front( command ) ), "r" );
     if ( p == NULL )
         return L0;
 
@@ -2283,7 +2285,7 @@
     exit_status = pclose( p );
 
     /* The command output is returned first. */
- result = list_new( L0, newstr( s.value ) );
+ result = list_new( object_new( s.value ) );
     string_free( &s );
 
     /* The command exit result next. */
@@ -2294,7 +2296,7 @@
         else
             exit_status = -1;
         sprintf( buffer, "%d", exit_status );
- result = list_new( result, newstr( buffer ) );
+ result = list_push_back( result, object_new( buffer ) );
     }
 
     return result;
@@ -2302,7 +2304,7 @@
 
 #else /* #ifdef HAVE_POPEN */
 
-LIST * builtin_shell( PARSE * parse, FRAME * frame )
+LIST * builtin_shell( FRAME * frame, int flags )
 {
     return L0;
 }

Modified: branches/release/tools/build/v2/engine/builtins.h
==============================================================================
--- branches/release/tools/build/v2/engine/builtins.h (original)
+++ branches/release/tools/build/v2/engine/builtins.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -21,47 +21,46 @@
 void init_sequence();
 void init_order();
 
-LIST *builtin_calc( PARSE *parse, FRAME *args );
-LIST *builtin_depends( PARSE *parse, FRAME *args );
-LIST *builtin_rebuilds( PARSE *parse, FRAME *args );
-LIST *builtin_echo( PARSE *parse, FRAME *args );
-LIST *builtin_exit( PARSE *parse, FRAME *args );
-LIST *builtin_flags( PARSE *parse, FRAME *args );
-LIST *builtin_glob( PARSE *parse, FRAME *args );
-LIST *builtin_glob_recursive( PARSE *parse, FRAME *frame );
-LIST *builtin_subst( PARSE *parse, FRAME *args );
-LIST *builtin_match( PARSE *parse, FRAME *args );
-LIST *builtin_split_by_characters( PARSE *parse, FRAME *args );
-LIST *builtin_hdrmacro( PARSE *parse, FRAME *args );
-LIST *builtin_rulenames( PARSE *parse, FRAME *args );
-LIST *builtin_varnames( PARSE *parse, FRAME *args );
-LIST *builtin_delete_module( PARSE *parse, FRAME *args );
-LIST *builtin_import( PARSE *parse, FRAME *args );
-LIST *builtin_export( PARSE *parse, FRAME *args );
-LIST *builtin_caller_module( PARSE *parse, FRAME *args );
-LIST *builtin_backtrace( PARSE *parse, FRAME *args );
-LIST *builtin_pwd( PARSE *parse, FRAME *args );
-LIST *builtin_update( PARSE *parse, FRAME *args );
-LIST *builtin_update_now( PARSE *parse, FRAME *args );
-LIST *builtin_search_for_target( PARSE *parse, FRAME *args );
-LIST *builtin_import_module( PARSE *parse, FRAME *args );
-LIST *builtin_imported_modules( PARSE *parse, FRAME *frame );
-LIST *builtin_instance( PARSE *parse, FRAME *frame );
-LIST *builtin_sort( PARSE *parse, FRAME *frame );
-LIST *builtin_normalize_path( PARSE *parse, FRAME *frame );
-LIST *builtin_native_rule( PARSE *parse, FRAME *frame );
-LIST *builtin_has_native_rule( PARSE *parse, FRAME *frame );
-LIST *builtin_user_module( PARSE *parse, FRAME *frame );
-LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame );
-LIST *builtin_check_if_file( PARSE *parse, FRAME *frame );
-LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame );
-LIST *builtin_shell( PARSE *parse, FRAME *frame );
-LIST *builtin_md5( PARSE *parse, FRAME *frame );
-LIST *builtin_file_open( PARSE *parse, FRAME *frame );
-LIST *builtin_pad( PARSE *parse, FRAME *frame );
-LIST *builtin_precious( PARSE *parse, FRAME *frame );
-LIST *builtin_self_path( PARSE *parse, FRAME *frame );
-LIST *builtin_makedir( PARSE *parse, FRAME *frame );
+LIST *builtin_calc( FRAME * frame, int flags );
+LIST *builtin_depends( FRAME * frame, int flags );
+LIST *builtin_rebuilds( FRAME * frame, int flags );
+LIST *builtin_echo( FRAME * frame, int flags );
+LIST *builtin_exit( FRAME * frame, int flags );
+LIST *builtin_flags( FRAME * frame, int flags );
+LIST *builtin_glob( FRAME * frame, int flags );
+LIST *builtin_glob_recursive( FRAME * frame, int flags );
+LIST *builtin_subst( FRAME * frame, int flags );
+LIST *builtin_match( FRAME * frame, int flags );
+LIST *builtin_split_by_characters( FRAME * frame, int flags );
+LIST *builtin_hdrmacro( FRAME * frame, int flags );
+LIST *builtin_rulenames( FRAME * frame, int flags );
+LIST *builtin_varnames( FRAME * frame, int flags );
+LIST *builtin_delete_module( FRAME * frame, int flags );
+LIST *builtin_import( FRAME * frame, int flags );
+LIST *builtin_export( FRAME * frame, int flags );
+LIST *builtin_caller_module( FRAME * frame, int flags );
+LIST *builtin_backtrace( FRAME * frame, int flags );
+LIST *builtin_pwd( FRAME * frame, int flags );
+LIST *builtin_update( FRAME * frame, int flags );
+LIST *builtin_update_now( FRAME * frame, int flags );
+LIST *builtin_import_module( FRAME * frame, int flags );
+LIST *builtin_imported_modules( FRAME * frame, int flags );
+LIST *builtin_instance( FRAME * frame, int flags );
+LIST *builtin_sort( FRAME * frame, int flags );
+LIST *builtin_normalize_path( FRAME * frame, int flags );
+LIST *builtin_native_rule( FRAME * frame, int flags );
+LIST *builtin_has_native_rule( FRAME * frame, int flags );
+LIST *builtin_user_module( FRAME * frame, int flags );
+LIST *builtin_nearest_user_location( FRAME * frame, int flags );
+LIST *builtin_check_if_file( FRAME * frame, int flags );
+LIST *builtin_python_import_rule( FRAME * frame, int flags );
+LIST *builtin_shell( FRAME * frame, int flags );
+LIST *builtin_md5( FRAME * frame, int flags );
+LIST *builtin_file_open( FRAME * frame, int flags );
+LIST *builtin_pad( FRAME * frame, int flags );
+LIST *builtin_precious( FRAME * frame, int flags );
+LIST *builtin_self_path( FRAME * frame, int flags );
+LIST *builtin_makedir( FRAME * frame, int flags );
 
 void backtrace( FRAME *frame );
 extern int last_update_now_status;

Modified: branches/release/tools/build/v2/engine/class.c
==============================================================================
--- branches/release/tools/build/v2/engine/class.c (original)
+++ branches/release/tools/build/v2/engine/class.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -7,7 +7,7 @@
 #include "variable.h"
 #include "frames.h"
 #include "rules.h"
-#include "newstr.h"
+#include "object.h"
 
 #include "hash.h"
 
@@ -17,28 +17,28 @@
 
 static void check_defined( LIST * class_names )
 {
- for ( ; class_names; class_names = class_names->next )
+ LISTITER iter = list_begin( class_names ), end = list_end( class_names );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- char * * p = &class_names->string;
- if ( !hashcheck( classes, (HASHDATA * *)&p ) )
+ if ( !hash_find( classes, list_item( iter ) ) )
         {
- printf( "Class %s is not defined\n", class_names->string );
+ printf( "Class %s is not defined\n", object_str( list_item( iter ) ) );
             abort();
         }
     }
 }
 
 
-static char * class_module_name( char * declared_name )
+static OBJECT * class_module_name( OBJECT * declared_name )
 {
     string name[ 1 ];
- char * result;
+ OBJECT * result;
 
     string_new( name );
     string_append( name, "class@" );
- string_append( name, declared_name );
+ string_append( name, object_str( declared_name ) );
 
- result = newstr( name->value );
+ result = object_new( name->value );
     string_free( name );
 
     return result;
@@ -47,7 +47,7 @@
 
 struct import_base_data
 {
- char * base_name;
+ OBJECT * base_name;
     module_t * base_module;
     module_t * class_module;
 };
@@ -60,14 +60,19 @@
     RULE * ir2;
     struct import_base_data * d = (struct import_base_data *)d_;
     string qualified_name[ 1 ];
+ OBJECT * qname;
 
     string_new ( qualified_name );
- string_append ( qualified_name, d->base_name );
+ string_append ( qualified_name, object_str( d->base_name ) );
     string_push_back( qualified_name, '.' );
- string_append ( qualified_name, r->name );
+ string_append ( qualified_name, object_str( r->name ) );
+
+ qname = object_new( qualified_name->value );
 
     ir1 = import_rule( r, d->class_module, r->name );
- ir2 = import_rule( r, d->class_module, qualified_name->value );
+ ir2 = import_rule( r, d->class_module, qname );
+
+ object_free( qname );
 
     /* Copy 'exported' flag. */
     ir1->exported = ir2->exported = r->exported;
@@ -75,7 +80,10 @@
     /* If we are importing a class method, localize it. */
     if ( ( r->module == d->base_module ) || ( r->module->class_module &&
         ( r->module->class_module == d->base_module ) ) )
- ir1->module = ir2->module = d->class_module;
+ {
+ rule_localize( ir1, d->class_module );
+ rule_localize( ir2, d->class_module );
+ }
 
     string_free( qualified_name );
 }
@@ -87,55 +95,73 @@
  * marked as exported.
  */
 
-static void import_base_rules( module_t * class, char * base )
+static void import_base_rules( module_t * class_, OBJECT * base )
 {
- module_t * base_module = bindmodule( class_module_name( base ) );
+ OBJECT * module_name = class_module_name( base );
+ module_t * base_module = bindmodule( module_name );
+ LIST * imported;
     struct import_base_data d;
     d.base_name = base;
     d.base_module = base_module;
- d.class_module = class;
+ d.class_module = class_;
+ object_free( module_name );
 
     if ( base_module->rules )
         hashenumerate( base_module->rules, import_base_rule, &d );
 
- import_module( imported_modules( base_module ), class );
+ imported = imported_modules( base_module );
+ import_module( imported, class_ );
+ list_free( imported );
 }
 
 
-char * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
+OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
 {
- char * name = class_module_name( xname->string );
- char * * pp = &xname->string;
+ OBJECT * name = class_module_name( list_front( xname ) );
+ OBJECT * * pp;
     module_t * class_module = 0;
     module_t * outer_module = frame->module;
+ int found;
+ LISTITER iter, end;
 
     if ( !classes )
- classes = hashinit( sizeof( char * ), "classes" );
+ classes = hashinit( sizeof( OBJECT * ), "classes" );
 
- if ( hashcheck( classes, (HASHDATA * *)&pp ) )
+ pp = (OBJECT * *)hash_insert( classes, list_front( xname ), &found );
+ if ( !found )
     {
- printf( "Class %s already defined\n", xname->string );
- abort();
+ *pp = object_copy( list_front( xname ) );
     }
     else
     {
- hashenter( classes, (HASHDATA * *)&pp );
+ printf( "Class %s already defined\n", object_str( list_front( xname ) ) );
+ abort();
     }
     check_defined( bases );
 
     class_module = bindmodule( name );
 
- exit_module( outer_module );
- enter_module( class_module );
+ var_set( class_module, constant_name, xname, VAR_SET );
+ var_set( class_module, constant_bases, bases, VAR_SET );
 
- var_set( "__name__", xname, VAR_SET );
- var_set( "__bases__", bases, VAR_SET );
+ iter = list_begin( bases ), end = list_end( bases );
+ for ( ; iter != end; iter = list_next( iter ) )
+ import_base_rules( class_module, list_item( iter ) );
 
- exit_module( class_module );
- enter_module( outer_module );
+ return name;
+}
 
- for ( ; bases; bases = bases->next )
- import_base_rules( class_module, bases->string );
+static void free_class( void * xclass, void * data )
+{
+ object_free( *(OBJECT * *)xclass );
+}
 
- return name;
+void class_done( void )
+{
+ if( classes )
+ {
+ hashenumerate( classes, free_class, (void *)0 );
+ hashdone( classes );
+ classes = 0;
+ }
 }

Modified: branches/release/tools/build/v2/engine/class.h
==============================================================================
--- branches/release/tools/build/v2/engine/class.h (original)
+++ branches/release/tools/build/v2/engine/class.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,6 +8,7 @@
 #include "lists.h"
 #include "frames.h"
 
-char* make_class_module(LIST* xname, LIST* bases, FRAME* frame);
+OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame );
+void class_done( void );
 
 #endif

Modified: branches/release/tools/build/v2/engine/command.c
==============================================================================
--- branches/release/tools/build/v2/engine/command.c (original)
+++ branches/release/tools/build/v2/engine/command.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -33,10 +33,11 @@
 CMD * cmd_new( RULE * rule, LIST * targets, LIST * sources, LIST * shell )
 {
     CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
+ LISTITER iter = list_begin( shell ), end = list_end( shell );
     /* Lift line-length limitation entirely when JAMSHELL is just "%". */
- int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
+ int no_limit = ( iter != end && !strcmp( object_str( list_item( iter ) ), "%") && list_next( iter ) == end );
     int max_line = MAXLINE;
- int allocated = -1;
+ FRAME frame[1];
 
     cmd->rule = rule;
     cmd->shell = shell;
@@ -45,27 +46,20 @@
     lol_init( &cmd->args );
     lol_add( &cmd->args, targets );
     lol_add( &cmd->args, sources );
- cmd->buf = 0;
+ string_new( cmd->buf );
 
- do
- {
- BJAM_FREE( cmd->buf ); /* free any buffer from previous iteration */
-
- cmd->buf = (char*)BJAM_MALLOC_ATOMIC( max_line + 1 );
-
- if ( cmd->buf == 0 )
- break;
-
- allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
-
- max_line = max_line * 2;
- }
- while ( ( allocated < 0 ) && ( max_line < INT_MAX / 2 ) );
+ frame_init( frame );
+ frame->module = rule->module;
+ lol_init( frame->args );
+ lol_add( frame->args, list_copy( targets ) );
+ lol_add( frame->args, list_copy( sources ) );
+ function_run_actions( rule->actions->command, frame, stack_global(), cmd->buf );
+ frame_free( frame );
 
     if ( !no_limit )
     {
         /* Bail if the result will not fit in MAXLINE. */
- char * s = cmd->buf;
+ char * s = cmd->buf->value;
         while ( *s )
         {
             size_t l = strcspn( s, "\n" );
@@ -95,6 +89,6 @@
 {
     lol_free( &cmd->args );
     list_free( cmd->shell );
- BJAM_FREE( cmd->buf );
- BJAM_FREE( (char *)cmd );
+ string_free( cmd->buf );
+ BJAM_FREE( (void *)cmd );
 }

Modified: branches/release/tools/build/v2/engine/command.h
==============================================================================
--- branches/release/tools/build/v2/engine/command.h (original)
+++ branches/release/tools/build/v2/engine/command.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -36,6 +36,13 @@
  * CMD - an action, ready to be formatted into a buffer and executed.
  */
 
+#ifndef COMMAND_SW20111118_H
+#define COMMAND_SW20111118_H
+
+#include "lists.h"
+#include "rules.h"
+#include "strings.h"
+
 typedef struct _cmd CMD;
 
 struct _cmd
@@ -45,7 +52,7 @@
     RULE * rule; /* rule->actions contains shell script */
     LIST * shell; /* $(SHELL) value */
     LOL args; /* LISTs for $(<), $(>) */
- char * buf; /* actual commands */
+ string buf[1]; /* actual commands */
 };
 
 CMD * cmd_new
@@ -59,3 +66,5 @@
 void cmd_free( CMD * );
 
 #define cmd_next( c ) ( ( c )->next )
+
+#endif

Modified: branches/release/tools/build/v2/engine/compile.c
==============================================================================
--- branches/release/tools/build/v2/engine/compile.c (original)
+++ branches/release/tools/build/v2/engine/compile.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,9 +16,8 @@
 # include "parse.h"
 # include "compile.h"
 # include "variable.h"
-# include "expand.h"
 # include "rules.h"
-# include "newstr.h"
+# include "object.h"
 # include "make.h"
 # include "search.h"
 # include "hdrmacro.h"
@@ -27,6 +26,7 @@
 # include "strings.h"
 # include "builtins.h"
 # include "class.h"
+# include "constants.h"
 
 # include <assert.h>
 # include <string.h>
@@ -86,15 +86,17 @@
  * 01/10/00 (seiwald) - built-ins split out to builtin.c.
  */
 
-static void debug_compile( int which, char *s, FRAME* frame );
-int glob( char *s, char *c );
+static void debug_compile( int which, const char * s, FRAME * frame );
+int glob( const char * s, const char * c );
 /* Internal functions from builtins.c */
-void backtrace( FRAME *frame );
-void backtrace_line( FRAME *frame );
-void print_source_line( PARSE* p );
+void backtrace( FRAME * frame );
+void backtrace_line( FRAME * frame );
+void print_source_line( FRAME * frame );
 
 struct frame * frame_before_python_call;
 
+static OBJECT * module_scope;
+
 void frame_init( FRAME* frame )
 {
     frame->prev = 0;
@@ -102,7 +104,8 @@
     lol_init(frame->args);
     frame->module = root_module();
     frame->rulename = "module scope";
- frame->procedure = 0;
+ frame->file = 0;
+ frame->line = -1;
 }
 
 
@@ -113,907 +116,39 @@
 
 
 /*
- * compile_append() - append list results of two statements
- *
- * parse->left more compile_append() by left-recursion
- * parse->right single rule
- */
-
-LIST * compile_append( PARSE * parse, FRAME * frame )
-{
- /* Append right to left. */
- return list_append(
- parse_evaluate( parse->left, frame ),
- parse_evaluate( parse->right, frame ) );
-}
-
-
-/*
- * compile_eval() - evaluate if to determine which leg to compile
- *
- * Returns:
- * list if expression true - compile 'then' clause
- * L0 if expression false - compile 'else' clause
- */
-
-static int lcmp( LIST * t, LIST * s )
-{
- int status = 0;
-
- while ( !status && ( t || s ) )
- {
- char *st = t ? t->string : "";
- char *ss = s ? s->string : "";
-
- status = strcmp( st, ss );
-
- t = t ? list_next( t ) : t;
- s = s ? list_next( s ) : s;
- }
-
- return status;
-}
-
-LIST * compile_eval( PARSE * parse, FRAME * frame )
-{
- LIST * ll;
- LIST * lr;
- LIST * s;
- LIST * t;
- int status = 0;
-
- /* Short circuit lr eval for &&, ||, and 'in'. */
-
- ll = parse_evaluate( parse->left, frame );
- lr = 0;
-
- switch ( parse->num )
- {
- case EXPR_AND:
- case EXPR_IN : if ( ll ) goto eval; break;
- case EXPR_OR : if ( !ll ) goto eval; break;
- default: eval: lr = parse_evaluate( parse->right, frame );
- }
-
- /* Now eval. */
- switch ( parse->num )
- {
- case EXPR_NOT: if ( !ll ) status = 1; break;
- case EXPR_AND: if ( ll && lr ) status = 1; break;
- case EXPR_OR : if ( ll || lr ) status = 1; break;
-
- case EXPR_IN:
- /* "a in b": make sure each of ll is equal to something in lr. */
- for ( t = ll; t; t = list_next( t ) )
- {
- for ( s = lr; s; s = list_next( s ) )
- if ( !strcmp( t->string, s->string ) )
- break;
- if ( !s ) break;
- }
- /* No more ll? Success. */
- if ( !t ) status = 1;
- break;
-
- case EXPR_EXISTS: if ( lcmp( ll, L0 ) != 0 ) status = 1; break;
- case EXPR_EQUALS: if ( lcmp( ll, lr ) == 0 ) status = 1; break;
- case EXPR_NOTEQ : if ( lcmp( ll, lr ) != 0 ) status = 1; break;
- case EXPR_LESS : if ( lcmp( ll, lr ) < 0 ) status = 1; break;
- case EXPR_LESSEQ: if ( lcmp( ll, lr ) <= 0 ) status = 1; break;
- case EXPR_MORE : if ( lcmp( ll, lr ) > 0 ) status = 1; break;
- case EXPR_MOREEQ: if ( lcmp( ll, lr ) >= 0 ) status = 1; break;
- }
-
- if ( DEBUG_IF )
- {
- debug_compile( 0, "if", frame );
- list_print( ll );
- printf( "(%d) ", status );
- list_print( lr );
- printf( "\n" );
- }
-
- /* Find something to return. */
- /* In odd circumstances (like "" = "") */
- /* we'll have to return a new string. */
-
- if ( !status ) t = 0;
- else if ( ll ) t = ll, ll = 0;
- else if ( lr ) t = lr, lr = 0;
- else t = list_new( L0, newstr( "1" ) );
-
- if ( ll ) list_free( ll );
- if ( lr ) list_free( lr );
- return t;
-}
-
-
-/*
- * compile_foreach() - compile the "for x in y" statement
- *
- * Compile_foreach() resets the given variable name to each specified
- * value, executing the commands enclosed in braces for each iteration.
- *
- * parse->string index variable
- * parse->left variable values
- * parse->right rule to compile
- */
-
-LIST * compile_foreach( PARSE * parse, FRAME * frame )
-{
- LIST * nv = parse_evaluate( parse->left, frame );
- LIST * l;
- SETTINGS * s = 0;
-
- if ( parse->num )
- {
- s = addsettings( s, VAR_SET, parse->string, L0 );
- pushsettings( s );
- }
-
- /* Call var_set to reset $(parse->string) for each val. */
-
- for ( l = nv; l; l = list_next( l ) )
- {
- LIST * val = list_new( L0, copystr( l->string ) );
- var_set( parse->string, val, VAR_SET );
- list_free( parse_evaluate( parse->right, frame ) );
- }
-
- if ( parse->num )
- {
- popsettings( s );
- freesettings( s );
- }
-
- list_free( nv );
-
- return L0;
-}
-
-/*
- * compile_if() - compile 'if' rule
- *
- * parse->left condition tree
- * parse->right then tree
- * parse->third else tree
- */
-
-LIST * compile_if( PARSE * p, FRAME * frame )
-{
- LIST * l = parse_evaluate( p->left, frame );
- if ( l )
- {
- list_free( l );
- return parse_evaluate( p->right, frame );
- }
- return parse_evaluate( p->third, frame );
-}
-
-
-LIST * compile_while( PARSE * p, FRAME * frame )
-{
- LIST * r = 0;
- LIST * l;
- while ( ( l = parse_evaluate( p->left, frame ) ) )
- {
- list_free( l );
- if ( r ) list_free( r );
- r = parse_evaluate( p->right, frame );
- }
- return r;
-}
-
-
-/*
- * compile_include() - support for 'include' - call include() on file
- *
- * parse->left list of files to include (can only do 1)
- */
-
-LIST * compile_include( PARSE * parse, FRAME * frame )
-{
- LIST * nt = parse_evaluate( parse->left, frame );
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "include", frame);
- list_print( nt );
- printf( "\n" );
- }
-
- if ( nt )
- {
- TARGET * t = bindtarget( nt->string );
-
- /* DWA 2001/10/22 - Perforce Jam cleared the arguments here, which
- * prevents an included file from being treated as part of the body of a
- * rule. I did not see any reason to do that, so I lifted the
- * restriction.
- */
-
- /* Bind the include file under the influence of */
- /* "on-target" variables. Though they are targets, */
- /* include files are not built with make(). */
-
- pushsettings( t->settings );
- /* We don't expect that file to be included is generated by some
- action. Therefore, pass 0 as third argument.
- If the name resolves to directory, let it error out. */
- t->boundname = search( t->name, &t->time, 0, 0 );
- popsettings( t->settings );
-
- parse_file( t->boundname, frame );
- }
-
- list_free( nt );
-
- return L0;
-}
-
-static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame)
-{
- LIST* result;
-
- module_t* outer_module = frame->module;
- frame->module = module_name ? bindmodule( module_name ) : root_module();
-
- if ( outer_module != frame->module )
- {
- exit_module( outer_module );
- enter_module( frame->module );
- }
-
- result = parse_evaluate( p, frame );
-
- if ( outer_module != frame->module )
- {
- exit_module( frame->module );
- enter_module( outer_module );
- frame->module = outer_module;
- }
-
- return result;
-}
-
-
-LIST * compile_module( PARSE * p, FRAME * frame )
-{
- /* Here we are entering a module declaration block. */
- LIST * module_name = parse_evaluate( p->left, frame );
- LIST * result = evaluate_in_module( module_name ? module_name->string : 0,
- p->right, frame );
- list_free( module_name );
- return result;
-}
-
-
-LIST * compile_class( PARSE * p, FRAME * frame )
-{
- /** Todo: check for empty class name.
- Check for class redeclaration. */
-
- char * class_module = 0;
-
- LIST * name = parse_evaluate( p->left->right, frame );
- LIST * bases = 0;
-
- if ( p->left->left )
- bases = parse_evaluate( p->left->left->right, frame );
-
- class_module = make_class_module( name, bases, frame );
- evaluate_in_module( class_module, p->right, frame );
-
- return L0;
-}
-
-
-/*
- * compile_list() - expand and return a list.
- *
- * parse->string - character string to expand.
- */
-
-LIST * compile_list( PARSE * parse, FRAME * frame )
-{
- /* s is a copyable string */
- char * s = parse->string;
- return var_expand( L0, s, s + strlen( s ), frame->args, 1 );
-}
-
-
-/*
- * compile_local() - declare (and set) local variables.
- *
- * parse->left list of variables
- * parse->right list of values
- * parse->third rules to execute
- */
-
-LIST * compile_local( PARSE * parse, FRAME * frame )
-{
- LIST * l;
- SETTINGS * s = 0;
- LIST * nt = parse_evaluate( parse->left, frame );
- LIST * ns = parse_evaluate( parse->right, frame );
- LIST * result;
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "local", frame );
- list_print( nt );
- printf( " = " );
- list_print( ns );
- printf( "\n" );
- }
-
- /* Initial value is ns. */
- for ( l = nt; l; l = list_next( l ) )
- s = addsettings( s, VAR_SET, l->string, list_copy( (LIST *)0, ns ) );
-
- list_free( ns );
- list_free( nt );
-
- /* Note that callees of the current context get this "local" variable,
- * making it not so much local as layered.
- */
-
- pushsettings( s );
- result = parse_evaluate( parse->third, frame );
- popsettings( s );
-
- freesettings( s );
-
- return result;
-}
-
-
-/*
- * compile_null() - do nothing -- a stub for parsing.
- */
-
-LIST * compile_null( PARSE * parse, FRAME * frame )
-{
- return L0;
-}
-
-
-/*
- * compile_on() - run rule under influence of on-target variables
- *
- * parse->left list of files to include (can only do 1).
- * parse->right rule to run.
- *
- * EXPERIMENTAL!
- */
-
-LIST * compile_on( PARSE * parse, FRAME * frame )
-{
- LIST * nt = parse_evaluate( parse->left, frame );
- LIST * result = 0;
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "on", frame );
- list_print( nt );
- printf( "\n" );
- }
-
- if ( nt )
- {
- TARGET * t = bindtarget( nt->string );
- pushsettings( t->settings );
- result = parse_evaluate( parse->right, frame );
- popsettings( t->settings );
- }
-
- list_free( nt );
-
- return result;
-}
-
-
-/*
- * compile_rule() - compile a single user defined rule.
- *
- * parse->string name of user defined rule.
- * parse->left parameters (list of lists) to rule, recursing left.
- *
- * Wrapped around evaluate_rule() so that headers() can share it.
- */
-
-LIST * compile_rule( PARSE * parse, FRAME * frame )
-{
- FRAME inner[ 1 ];
- LIST * result;
- PARSE * p;
-
- /* Build up the list of arg lists. */
- frame_init( inner );
- inner->prev = frame;
- inner->prev_user = frame->module->user_module ? frame : frame->prev_user;
- inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below. */
- inner->procedure = parse;
- /* Special-case LOL of length 1 where the first list is totally empty.
- This is created when calling functions with no parameters, due to
- the way jam grammar is written. This is OK when one jam function
- calls another, but really not good when Jam function calls Python. */
- if ( parse->left->left == NULL && parse->left->right->func == compile_null)
- ;
- else
- for ( p = parse->left; p; p = p->left )
- lol_add( inner->args, parse_evaluate( p->right, frame ) );
-
- /* And invoke the rule. */
- result = evaluate_rule( parse->string, inner );
- frame_free( inner );
- return result;
-}
-
-
-static void argument_error( char * message, RULE * rule, FRAME * frame, LIST* arg )
-{
- LOL * actual = frame->args;
- assert( frame->procedure != 0 );
- backtrace_line( frame->prev );
- printf( "*** argument error\n* rule %s ( ", frame->rulename );
- lol_print( rule->arguments->data );
- printf( " )\n* called with: ( " );
- lol_print( actual );
- printf( " )\n* %s %s\n", message, arg ? arg->string : "" );
- print_source_line( rule->procedure );
- printf( "see definition of rule '%s' being called\n", rule->name );
- backtrace( frame->prev );
- exit( 1 );
-}
-
-
-/* Define delimiters for type check elements in argument lists (and return type
- * specifications, eventually).
- */
-# define TYPE_OPEN_DELIM '['
-# define TYPE_CLOSE_DELIM ']'
-
-/*
- * is_type_name() - true iff the given string represents a type check
- * specification.
- */
-
-static int is_type_name( char * s )
-{
- return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
- ( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
-}
-
-
-/*
- * arg_modifier - if the next element of formal is a single character, return
- * that; return 0 otherwise. Used to extract "*+?" modifiers * from argument
- * lists.
- */
-
-static char arg_modifier( LIST * formal )
-{
- if ( formal->next )
- {
- char * next = formal->next->string;
- if ( next && ( next[ 0 ] != 0 ) && ( next[ 1 ] == 0 ) )
- return next[ 0 ];
- }
- return 0;
-}
-
-
-/*
- * type_check() - checks that each element of values satisfies the requirements
- * of type_name.
- *
- * caller - the frame of the rule calling the rule whose arguments are
- * being checked
- *
- * called - the rule being called
- *
- * arg_name - a list element containing the name of the argument being
- * checked
- */
-
-static void type_check
-(
- char * type_name,
- LIST * values,
- FRAME * caller,
- RULE * called,
- LIST * arg_name
-)
-{
- static module_t * typecheck = 0;
-
- /* If nothing to check, bail now. */
- if ( !values || !type_name )
- return;
-
- if ( !typecheck )
- typecheck = bindmodule( ".typecheck" );
-
- /* If the checking rule can not be found, also bail. */
- {
- RULE checker_, *checker = &checker_;
-
- checker->name = type_name;
- if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA * *)&checker ) )
- return;
- }
-
- exit_module( caller->module );
-
- while ( values != 0 )
- {
- LIST *error;
- FRAME frame[1];
- frame_init( frame );
- frame->module = typecheck;
- frame->prev = caller;
- frame->prev_user = caller->module->user_module ? caller : caller->prev_user;
-
- enter_module( typecheck );
- /* Prepare the argument list */
- lol_add( frame->args, list_new( L0, values->string ) );
- error = evaluate_rule( type_name, frame );
-
- exit_module( typecheck );
-
- if ( error )
- argument_error( error->string, called, caller, arg_name );
-
- frame_free( frame );
- values = values->next;
- }
-
- enter_module( caller->module );
-}
-
-/*
- * collect_arguments() - local argument checking and collection
- */
-static SETTINGS *
-collect_arguments( RULE* rule, FRAME* frame )
-{
- SETTINGS *locals = 0;
-
- LOL * all_actual = frame->args;
- LOL * all_formal = rule->arguments ? rule->arguments->data : 0;
- if ( all_formal ) /* Nothing to set; nothing to check */
- {
- int max = all_formal->count > all_actual->count
- ? all_formal->count
- : all_actual->count;
-
- int n;
- for ( n = 0; n < max ; ++n )
- {
- LIST *actual = lol_get( all_actual, n );
- char *type_name = 0;
-
- LIST *formal;
- for ( formal = lol_get( all_formal, n ); formal; formal = formal->next )
- {
- char* name = formal->string;
-
- if ( is_type_name(name) )
- {
- if ( type_name )
- argument_error( "missing argument name before type name:", rule, frame, formal );
-
- if ( !formal->next )
- argument_error( "missing argument name after type name:", rule, frame, formal );
-
- type_name = formal->string;
- }
- else
- {
- LIST* value = 0;
- char modifier;
- LIST* arg_name = formal; /* hold the argument name for type checking */
- int multiple = 0;
-
- /* Stop now if a variable number of arguments are specified */
- if ( name[0] == '*' && name[1] == 0 )
- return locals;
-
- modifier = arg_modifier( formal );
-
- if ( !actual && modifier != '?' && modifier != '*' )
- argument_error( "missing argument", rule, frame, formal );
-
- switch ( modifier )
- {
- case '+':
- case '*':
- value = list_copy( 0, actual );
- multiple = 1;
- actual = 0;
- /* skip an extra element for the modifier */
- formal = formal->next;
- break;
- case '?':
- /* skip an extra element for the modifier */
- formal = formal->next;
- /* fall through */
- default:
- if ( actual ) /* in case actual is missing */
- {
- value = list_new( 0, actual->string );
- actual = actual->next;
- }
- }
-
- locals = addsettings(locals, VAR_SET, name, value);
- locals->multiple = multiple;
- type_check( type_name, value, frame, rule, arg_name );
- type_name = 0;
- }
- }
-
- if ( actual )
- {
- argument_error( "extra argument", rule, frame, actual );
- }
- }
- }
- return locals;
-}
-
-RULE *
-enter_rule( char *rulename, module_t *target_module );
-
-#ifdef HAVE_PYTHON
-
-static int python_instance_number = 0;
-
-
-/* Given a Python object, return a string to use in Jam
- code instead of said object.
- If the object is string, use the string value
- If the object implemenets __jam_repr__ method, use that.
- Otherwise return 0.
-
- The result value is newstr-ed. */
-char *python_to_string(PyObject* value)
-{
- if (PyString_Check(value))
- {
- return newstr(PyString_AsString(value));
- }
- else
- {
- /* See if this is an instance that defines special __jam_repr__
- method. */
- if (PyInstance_Check(value)
- && PyObject_HasAttrString(value, "__jam_repr__"))
- {
- PyObject* repr = PyObject_GetAttrString(value, "__jam_repr__");
- if (repr)
- {
- PyObject* arguments2 = PyTuple_New(0);
- PyObject* value2 = PyObject_Call(repr, arguments2, 0);
- Py_DECREF(repr);
- Py_DECREF(arguments2);
- if (PyString_Check(value2))
- {
- return newstr(PyString_AsString(value2));
- }
- Py_DECREF(value2);
- }
- }
- return 0;
- }
-}
-
-static LIST*
-call_python_function(RULE* r, FRAME* frame)
-{
- LIST * result = 0;
- PyObject * arguments = 0;
- PyObject * kw = NULL;
- int i ;
- PyObject * py_result;
-
- if (r->arguments)
- {
- SETTINGS * args;
-
- arguments = PyTuple_New(0);
- kw = PyDict_New();
-
- for (args = collect_arguments(r, frame); args; args = args->next)
- {
- PyObject *key = PyString_FromString(args->symbol);
- PyObject *value = 0;
- if (args->multiple)
- value = list_to_python(args->value);
- else {
- if (args->value)
- value = PyString_FromString(args->value->string);
- }
-
- if (value)
- PyDict_SetItem(kw, key, value);
- Py_DECREF(key);
- Py_XDECREF(value);
- }
- }
- else
- {
- arguments = PyTuple_New( frame->args->count );
- for ( i = 0; i < frame->args->count; ++i )
- {
- PyObject * arg = PyList_New(0);
- LIST* l = lol_get( frame->args, i);
-
- for ( ; l; l = l->next )
- {
- PyObject * v = PyString_FromString(l->string);
- PyList_Append( arg, v );
- Py_DECREF(v);
- }
- /* Steals reference to 'arg' */
- PyTuple_SetItem( arguments, i, arg );
- }
- }
-
- frame_before_python_call = frame;
- py_result = PyObject_Call( r->python_function, arguments, kw );
- Py_DECREF(arguments);
- Py_XDECREF(kw);
- if ( py_result != NULL )
- {
- if ( PyList_Check( py_result ) )
- {
- int size = PyList_Size( py_result );
- int i;
- for ( i = 0; i < size; ++i )
- {
- PyObject * item = PyList_GetItem( py_result, i );
- char *s = python_to_string (item);
- if (!s) {
- fprintf( stderr, "Non-string object returned by Python call.\n" );
- } else {
- result = list_new (result, s);
- }
- }
- }
- else if ( py_result == Py_None )
- {
- result = L0;
- }
- else
- {
- char *s = python_to_string(py_result);
- if (s)
- result = list_new(0, s);
- else
- /* We have tried all we could. Return empty list. There are
- cases, e.g. feature.feature function that should return
- value for the benefit of Python code and which also can be
- called by Jam code, where no sensible value can be
- returned. We cannot even emit a warning, since there will
- be a pile of them. */
- result = L0;
- }
-
- Py_DECREF( py_result );
- }
- else
- {
- PyErr_Print();
- fprintf(stderr,"Call failed\n");
- }
-
- return result;
-}
-
-
-module_t * python_module()
-{
- static module_t * python = 0;
- if ( !python )
- python = bindmodule("__python__");
- return python;
-}
-
-#endif
-
-
-/*
  * evaluate_rule() - execute a rule invocation.
  */
 
 LIST *
 evaluate_rule(
- char * rulename,
- FRAME * frame )
+ OBJECT * rulename,
+ FRAME * frame )
 {
     LIST * result = L0;
     RULE * rule;
     profile_frame prof[1];
     module_t * prev_module = frame->module;
 
- LIST * l;
- {
- LOL arg_context_, * arg_context = &arg_context_;
- if ( !frame->prev )
- lol_init(arg_context);
- else
- arg_context = frame->prev->args;
- l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
- }
-
- if ( !l )
- {
- backtrace_line( frame->prev );
- printf( "warning: rulename %s expands to empty string\n", rulename );
- backtrace( frame->prev );
- return result;
- }
-
- rulename = l->string;
- rule = bindrule( l->string, frame->module );
-
-#ifdef HAVE_PYTHON
- if ( rule->python_function )
- {
- /* The below messing with modules is due to the way modules are
- * implemented in Jam. Suppose we are in module M1 now. The global
- * variable map actually holds 'M1' variables, and M1->variables hold
- * global variables.
- *
- * If we call Python right away, Python calls back Jam and then Jam
- * does 'module M1 { }' then Jam will try to swap the current global
- * variables with M1->variables. The result will be that global
- * variables map will hold global variables, and any variable settings
- * we do will go to the global module, not M1.
- *
- * By restoring basic state, where the global variable map holds global
- * variable, we make sure any future 'module M1' entry will work OK.
- */
-
- LIST * result;
- module_t * m = python_module();
-
- frame->module = m;
-
- exit_module( prev_module );
- enter_module( m );
-
- result = call_python_function( rule, frame );
-
- exit_module( m );
- enter_module ( prev_module );
-
- return result;
- }
-#endif
-
- /* Drop the rule name. */
- l = list_pop_front( l );
-
- /* Tack the rest of the expansion onto the front of the first argument. */
- frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) );
+ rule = bindrule( rulename, frame->module );
 
     if ( DEBUG_COMPILE )
     {
         /* Try hard to indicate in which module the rule is going to execute. */
         if ( rule->module != frame->module
- && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) )
+ && rule->procedure != 0 && !object_equal( rulename, function_rulename( rule->procedure ) ) )
         {
             char buf[256] = "";
- strncat( buf, rule->module->name, sizeof( buf ) - 1 );
- strncat( buf, rule->name, sizeof( buf ) - 1 );
+ if ( rule->module->name )
+ {
+ strncat( buf, object_str( rule->module->name ), sizeof( buf ) - 1 );
+ strncat( buf, ".", sizeof( buf ) - 1 );
+ }
+ strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 );
             debug_compile( 1, buf, frame );
         }
         else
         {
- debug_compile( 1, rulename, frame );
+ debug_compile( 1, object_str( rulename ), frame );
         }
 
         lol_print( frame->args );
@@ -1024,26 +159,29 @@
     {
         /* Propagate current module to nested rule invocations. */
         frame->module = rule->module;
-
- /* Swap variables. */
- exit_module( prev_module );
- enter_module( rule->module );
     }
 
     /* Record current rule name in frame. */
     if ( rule->procedure )
     {
- frame->rulename = rulename;
+ frame->rulename = object_str( rulename );
         /* And enter record profile info. */
         if ( DEBUG_PROFILE )
- profile_enter( rule->procedure->rulename, prof );
+ profile_enter( function_rulename( rule->procedure ), prof );
     }
 
     /* Check traditional targets $(<) and sources $(>). */
     if ( !rule->actions && !rule->procedure )
     {
         backtrace_line( frame->prev );
- printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
+ if ( frame->module->name )
+ {
+ printf( "rule %s unknown in module %s\n", object_str( rule->name ), object_str( frame->module->name ) );
+ }
+ else
+ {
+ printf( "rule %s unknown in module \n", object_str( rule->name ) );
+ }
         backtrace( frame->prev );
         exit( 1 );
     }
@@ -1063,6 +201,7 @@
         action->rule = rule;
         action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
         action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );
+ action->refs = 1;
 
         /* If we have a group of targets all being built using the same action
          * then we must not allow any of them to be used as sources unless they
@@ -1109,30 +248,21 @@
         /* Append this action to the actions of each target. */
         for ( t = action->targets; t; t = t->next )
             t->target->actions = actionlist( t->target->actions, action );
+
+ action_free( action );
     }
 
     /* Now recursively compile any parse tree associated with this rule.
- * parse_refer()/parse_free() call pair added to ensure rule not freed
+ * function_refer()/function_free() call pair added to ensure rule not freed
      * during use.
      */
     if ( rule->procedure )
     {
- SETTINGS * local_args = collect_arguments( rule, frame );
- PARSE * parse = rule->procedure;
- parse_refer( parse );
-
- pushsettings( local_args );
- result = parse_evaluate( parse, frame );
- popsettings( local_args );
- freesettings( local_args );
-
- parse_free( parse );
- }
+ FUNCTION * function = rule->procedure;
 
- if ( frame->module != prev_module )
- {
- exit_module( frame->module );
- enter_module( prev_module );
+ function_refer( function );
+ result = function_run( function, frame, stack_global() );
+ function_free( function );
     }
 
     if ( DEBUG_PROFILE && rule->procedure )
@@ -1154,7 +284,7 @@
  * which might be implemented in Jam.
  */
 
-LIST * call_rule( char * rulename, FRAME * caller_frame, ... )
+LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... )
 {
     va_list va;
     LIST * result;
@@ -1165,7 +295,6 @@
     inner->prev_user = caller_frame->module->user_module ?
         caller_frame : caller_frame->prev_user;
     inner->module = caller_frame->module;
- inner->procedure = 0;
 
     va_start( va, caller_frame );
     for ( ; ; )
@@ -1185,218 +314,12 @@
 }
 
 
-/*
- * compile_rules() - compile a chain of rules
- *
- * parse->left single rule
- * parse->right more compile_rules() by right-recursion
- */
-
-LIST * compile_rules( PARSE * parse, FRAME * frame )
-{
- /* Ignore result from first statement; return the 2nd. */
- /* Optimize recursion on the right by looping. */
- do list_free( parse_evaluate( parse->left, frame ) );
- while ( ( parse = parse->right )->func == compile_rules );
- return parse_evaluate( parse, frame );
-}
-
-
-/*
- * assign_var_mode() - convert ASSIGN_XXX compilation flag into corresponding
- * VAR_XXX variable set flag.
- */
-
-static int assign_var_mode( int parsenum, char const * * tracetext )
-{
- char const * trace;
- int setflag;
- switch ( parsenum )
- {
- case ASSIGN_SET : setflag = VAR_SET ; trace = "=" ; break;
- case ASSIGN_APPEND : setflag = VAR_APPEND ; trace = "+="; break;
- case ASSIGN_DEFAULT: setflag = VAR_DEFAULT; trace = "?="; break;
- default: setflag = VAR_SET ; trace = "" ; break;
- }
- if ( tracetext )
- *tracetext = trace ;
- return setflag;
-}
-
-/*
- * compile_set() - compile the "set variable" statement
- *
- * parse->left variable names
- * parse->right variable values
- * parse->num ASSIGN_SET/APPEND/DEFAULT
- */
-
-LIST * compile_set( PARSE * parse, FRAME * frame )
-{
- LIST * nt = parse_evaluate( parse->left, frame );
- LIST * ns = parse_evaluate( parse->right, frame );
- LIST * l;
- char const * trace;
- int setflag = assign_var_mode( parse->num, &trace );
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "set", frame );
- list_print( nt );
- printf( " %s ", trace );
- list_print( ns );
- printf( "\n" );
- }
-
- /* Call var_set to set variable. var_set keeps ns, so need to copy it. */
- for ( l = nt; l; l = list_next( l ) )
- var_set( l->string, list_copy( L0, ns ), setflag );
- list_free( nt );
- return ns;
-}
-
-
-/*
- * compile_setcomp() - support for `rule` - save parse tree.
- *
- * parse->string rule name
- * parse->left rules for rule
- * parse->right optional list-of-lists describing arguments
- */
-
-LIST * compile_setcomp( PARSE * parse, FRAME * frame )
-{
- argument_list * arg_list = 0;
-
- /* Create new LOL describing argument requirements if supplied. */
- if ( parse->right )
- {
- PARSE * p;
- arg_list = args_new();
- for ( p = parse->right; p; p = p->left )
- lol_add( arg_list->data, parse_evaluate( p->right, frame ) );
- }
-
- new_rule_body( frame->module, parse->string, arg_list, parse->left, !parse->num );
- return L0;
-}
-
-
-/*
- * compile_setexec() - support for `actions` - save execution string.
- *
- * parse->string rule name
- * parse->string1 OS command string
- * parse->num flags
- * parse->left `bind` variables
- *
- * Note that the parse flags (as defined in compile.h) are transferred directly
- * to the rule flags (as defined in rules.h).
- */
-
-LIST * compile_setexec( PARSE * parse, FRAME * frame )
-{
- LIST * bindlist = parse_evaluate( parse->left, frame );
- new_rule_actions( frame->module, parse->string, parse->string1, bindlist, parse->num );
- return L0;
-}
-
-
-/*
- * compile_settings() - compile the "on =" (set variable on exec) statement.
- *
- * parse->left variable names
- * parse->right target name
- * parse->third variable value
- * parse->num ASSIGN_SET/APPEND
- */
-
-LIST * compile_settings( PARSE * parse, FRAME * frame )
-{
- LIST * nt = parse_evaluate( parse->left, frame );
- LIST * ns = parse_evaluate( parse->third, frame );
- LIST * targets = parse_evaluate( parse->right, frame );
- LIST * ts;
- char const * trace;
- int setflag = assign_var_mode( parse->num, &trace );
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "set", frame );
- list_print( nt );
- printf( " on " );
- list_print( targets );
- printf( " %s ", trace );
- list_print( ns );
- printf( "\n" );
- }
-
- /* Call addsettings() to save variable setting. addsettings() keeps ns, so
- * need to copy it. Pass append flag to addsettings().
- */
- for ( ts = targets; ts; ts = list_next( ts ) )
- {
- TARGET * t = bindtarget( ts->string );
- LIST * l;
-
- for ( l = nt; l; l = list_next( l ) )
- t->settings = addsettings( t->settings, setflag, l->string,
- list_copy( (LIST *)0, ns ) );
- }
-
- list_free( nt );
- list_free( targets );
- return ns;
-}
-
-
-/*
- * compile_switch() - compile 'switch' rule.
- *
- * parse->left switch value (only 1st used)
- * parse->right cases
- *
- * cases->left 1st case
- * cases->right next cases
- *
- * case->string argument to match
- * case->left parse tree to execute
- */
-
-LIST * compile_switch( PARSE * parse, FRAME * frame )
-{
- LIST * nt = parse_evaluate( parse->left, frame );
- LIST * result = 0;
-
- if ( DEBUG_COMPILE )
- {
- debug_compile( 0, "switch", frame );
- list_print( nt );
- printf( "\n" );
- }
-
- /* Step through cases. */
- for ( parse = parse->right; parse; parse = parse->right )
- {
- if ( !glob( parse->left->string, nt ? nt->string : "" ) )
- {
- /* Get & exec parse tree for this case. */
- parse = parse->left->left;
- result = parse_evaluate( parse, frame );
- break;
- }
- }
-
- list_free( nt );
- return result;
-}
-
 
 /*
  * debug_compile() - printf with indent to show rule expansion.
  */
 
-static void debug_compile( int which, char * s, FRAME * frame )
+static void debug_compile( int which, const char * s, FRAME * frame )
 {
     static int level = 0;
     static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";
@@ -1405,7 +328,7 @@
     {
         int i;
 
- print_source_line( frame->procedure );
+ print_source_line( frame );
 
         i = ( level + 1 ) * 2;
         while ( i > 35 )

Modified: branches/release/tools/build/v2/engine/compile.h
==============================================================================
--- branches/release/tools/build/v2/engine/compile.h (original)
+++ branches/release/tools/build/v2/engine/compile.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,6 +16,7 @@
 # include "frames.h"
 # include "parse.h"
 # include "regexp.h"
+# include "object.h"
 
 /*
  * compile.h - compile parsed jam statements
@@ -23,30 +24,10 @@
 
 void compile_builtins();
 
-LIST *compile_append( PARSE *parse, FRAME *frame );
-LIST *compile_foreach( PARSE *parse, FRAME *frame );
-LIST *compile_if( PARSE *parse, FRAME *frame );
-LIST *compile_eval( PARSE *parse, FRAME *args );
-LIST *compile_include( PARSE *parse, FRAME *frame );
-LIST *compile_list( PARSE *parse, FRAME *frame );
-LIST *compile_local( PARSE *parse, FRAME *frame );
-LIST *compile_module( PARSE *parse, FRAME *frame );
-LIST *compile_class( PARSE *parse, FRAME *frame );
-LIST *compile_null( PARSE *parse, FRAME *frame );
-LIST *compile_on( PARSE *parse, FRAME *frame );
-LIST *compile_rule( PARSE *parse, FRAME *frame );
-LIST *compile_rules( PARSE *parse, FRAME *frame );
-LIST *compile_set( PARSE *parse, FRAME *frame );
-LIST *compile_setcomp( PARSE *parse, FRAME *frame );
-LIST *compile_setexec( PARSE *parse, FRAME *frame );
-LIST *compile_settings( PARSE *parse, FRAME *frame );
-LIST *compile_switch( PARSE *parse, FRAME *frame );
-LIST *compile_while( PARSE *parse, FRAME *frame );
+LIST *evaluate_rule( OBJECT * rulename, FRAME * frame );
+LIST *call_rule( OBJECT * rulename, FRAME * caller_frame, ...);
 
-LIST *evaluate_rule( char *rulename, FRAME *frame );
-LIST *call_rule( char *rulename, FRAME* caller_frame, ...);
-
-regexp* regex_compile( const char* pattern );
+regexp* regex_compile( OBJECT * pattern );
 
 /* Flags for compile_set(), etc */
 

Copied: branches/release/tools/build/v2/engine/constants.c (from r75609, /trunk/tools/build/v2/engine/constants.c)
==============================================================================
--- /trunk/tools/build/v2/engine/constants.c (original)
+++ branches/release/tools/build/v2/engine/constants.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -19,7 +19,42 @@
 
 void constants_init( void )
 {
+ constant_empty = object_new( "" );
+ constant_dot = object_new( "." );
+ constant_percent = object_new( "%" );
+ constant_plus = object_new( "+" );
+ constant_star = object_new( "*" );
+ constant_question_mark = object_new( "?" );
+ constant_ok = object_new( "ok" );
+ constant_true = object_new( "true" );
+ constant_name = object_new( "__name__" );
+ constant_bases = object_new( "__bases__" );
+ constant_typecheck = object_new( ".typecheck" );
     constant_builtin = object_new( "(builtin)" );
+ constant_HCACHEFILE = object_new( "HCACHEFILE" );
+ constant_HCACHEMAXAGE = object_new( "HCACHEMAXAGE" );
+ constant_HDRSCAN = object_new( "HDRSCAN" );
+ constant_HDRRULE = object_new( "HDRRULE" );
+ constant_BINDRULE = object_new( "BINDRULE" );
+ constant_LOCATE = object_new( "LOCATE" );
+ constant_SEARCH = object_new( "SEARCH" );
+ constant_JAM_SEMAPHORE = object_new( "JAM_SEMAPHORE" );
+ constant_TIMING_RULE = object_new( "__TIMING_RULE__" );
+ constant_ACTION_RULE = object_new( "__ACTION_RULE__" );
+ constant_JAMSHELL = object_new( "JAMSHELL" );
+ constant_TMPDIR = object_new( "TMPDIR" );
+ constant_TMPNAME = object_new( "TMPNAME" );
+ constant_TMPFILE = object_new( "TMPFILE" );
+ constant_STDOUT = object_new( "STDOUT" );
+ constant_STDERR = object_new( "STDERR" );
+ constant_JAMDATE = object_new( "JAMDATE" );
+ constant_JAM_VERSION = object_new( "JAM_VERSION" );
+ constant_JAMUNAME = object_new( "JAMUNAME" );
+ constant_ENVIRON = object_new( ".ENVIRON" );
+ constant_ARGV = object_new( "ARGV" );
+ constant_all = object_new( "all" );
+ constant_PARALLELISM = object_new( "PARALLELISM" );
+ constant_KEEP_GOING = object_new( "KEEP_GOING" );
     constant_other = object_new( "[OTHER]" );
     constant_total = object_new( "[TOTAL]" );
     constant_FILE_DIRSCAN = object_new( "FILE_DIRSCAN" );
@@ -40,7 +75,42 @@
 
 void constants_done( void )
 {
+ object_free( constant_empty );
+ object_free( constant_dot );
+ object_free( constant_percent );
+ object_free( constant_plus );
+ object_free( constant_star );
+ object_free( constant_question_mark );
+ object_free( constant_ok );
+ object_free( constant_true );
+ object_free( constant_name );
+ object_free( constant_bases );
+ object_free( constant_typecheck );
     object_free( constant_builtin );
+ object_free( constant_HCACHEFILE );
+ object_free( constant_HCACHEMAXAGE );
+ object_free( constant_HDRSCAN );
+ object_free( constant_HDRRULE );
+ object_free( constant_BINDRULE );
+ object_free( constant_LOCATE );
+ object_free( constant_SEARCH );
+ object_free( constant_JAM_SEMAPHORE );
+ object_free( constant_TIMING_RULE );
+ object_free( constant_ACTION_RULE );
+ object_free( constant_JAMSHELL );
+ object_free( constant_TMPDIR );
+ object_free( constant_TMPNAME );
+ object_free( constant_TMPFILE );
+ object_free( constant_STDOUT );
+ object_free( constant_STDERR );
+ object_free( constant_JAMDATE );
+ object_free( constant_JAM_VERSION );
+ object_free( constant_JAMUNAME );
+ object_free( constant_ENVIRON );
+ object_free( constant_ARGV );
+ object_free( constant_all );
+ object_free( constant_PARALLELISM );
+ object_free( constant_KEEP_GOING );
     object_free( constant_other );
     object_free( constant_total );
     object_free( constant_FILE_DIRSCAN );
@@ -59,7 +129,42 @@
     object_free( constant_MAIN_PYTHON );
 }
 
+OBJECT * constant_empty;
+OBJECT * constant_dot;
+OBJECT * constant_percent;
+OBJECT * constant_plus;
+OBJECT * constant_star;
+OBJECT * constant_question_mark;
+OBJECT * constant_ok;
+OBJECT * constant_true;
+OBJECT * constant_name;
+OBJECT * constant_bases;
+OBJECT * constant_typecheck;
 OBJECT * constant_builtin;
+OBJECT * constant_HCACHEFILE;
+OBJECT * constant_HCACHEMAXAGE;
+OBJECT * constant_HDRSCAN;
+OBJECT * constant_HDRRULE;
+OBJECT * constant_BINDRULE;
+OBJECT * constant_LOCATE;
+OBJECT * constant_SEARCH;
+OBJECT * constant_JAM_SEMAPHORE;
+OBJECT * constant_TIMING_RULE;
+OBJECT * constant_ACTION_RULE;
+OBJECT * constant_JAMSHELL;
+OBJECT * constant_TMPDIR;
+OBJECT * constant_TMPNAME;
+OBJECT * constant_TMPFILE;
+OBJECT * constant_STDOUT;
+OBJECT * constant_STDERR;
+OBJECT * constant_JAMDATE;
+OBJECT * constant_JAM_VERSION;
+OBJECT * constant_JAMUNAME;
+OBJECT * constant_ENVIRON;
+OBJECT * constant_ARGV;
+OBJECT * constant_all;
+OBJECT * constant_PARALLELISM;
+OBJECT * constant_KEEP_GOING;
 OBJECT * constant_other;
 OBJECT * constant_total;
 OBJECT * constant_FILE_DIRSCAN;

Copied: branches/release/tools/build/v2/engine/constants.h (from r75609, /trunk/tools/build/v2/engine/constants.h)
==============================================================================
--- /trunk/tools/build/v2/engine/constants.h (original)
+++ branches/release/tools/build/v2/engine/constants.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,7 +16,42 @@
 void constants_init( void );
 void constants_done( void );
 
+extern OBJECT * constant_empty; /* "" */
+extern OBJECT * constant_dot; /* "." */
+extern OBJECT * constant_percent; /* "%" */
+extern OBJECT * constant_plus; /* "+" */
+extern OBJECT * constant_star; /* "*" */
+extern OBJECT * constant_question_mark; /* "?" */
+extern OBJECT * constant_ok; /* "ok" */
+extern OBJECT * constant_true; /* "true" */
+extern OBJECT * constant_name; /* "__name__" */
+extern OBJECT * constant_bases; /* "__bases__" */
+extern OBJECT * constant_typecheck; /* ".typecheck" */
 extern OBJECT * constant_builtin; /* "(builtin)" */
+extern OBJECT * constant_HCACHEFILE; /* "HCACHEFILE" */
+extern OBJECT * constant_HCACHEMAXAGE; /* "HCACHEMAXAGE" */
+extern OBJECT * constant_HDRSCAN; /* "HDRSCAN" */
+extern OBJECT * constant_HDRRULE; /* "HDRRULE" */
+extern OBJECT * constant_BINDRULE; /* "BINDRULE" */
+extern OBJECT * constant_LOCATE; /* "LOCATE" */
+extern OBJECT * constant_SEARCH; /* "SEARCH" */
+extern OBJECT * constant_JAM_SEMAPHORE; /* "JAM_SEMAPHORE" */
+extern OBJECT * constant_TIMING_RULE; /* "__TIMING_RULE__" */
+extern OBJECT * constant_ACTION_RULE; /* "__ACTION_RULE__" */
+extern OBJECT * constant_JAMSHELL; /* "JAMSHELL" */
+extern OBJECT * constant_TMPDIR; /* "TMPDIR" */
+extern OBJECT * constant_TMPNAME; /* "TMPNAME" */
+extern OBJECT * constant_TMPFILE; /* "TMPFILE" */
+extern OBJECT * constant_STDOUT; /* "STDOUT" */
+extern OBJECT * constant_STDERR; /* "STDERR" */
+extern OBJECT * constant_JAMDATE; /* "JAMDATE" */
+extern OBJECT * constant_JAM_VERSION; /* "JAM_VERSION" */
+extern OBJECT * constant_JAMUNAME; /* "JAMUNAME" */
+extern OBJECT * constant_ENVIRON; /* ".ENVIRON" */
+extern OBJECT * constant_ARGV; /* "ARGV" */
+extern OBJECT * constant_all; /* "all" */
+extern OBJECT * constant_PARALLELISM; /* "PARALLELISM" */
+extern OBJECT * constant_KEEP_GOING; /* "KEEP_GOING" */
 extern OBJECT * constant_other; /* "[OTHER]" */
 extern OBJECT * constant_total; /* "[TOTAL]" */
 extern OBJECT * constant_FILE_DIRSCAN; /* "FILE_DIRSCAN" */

Modified: branches/release/tools/build/v2/engine/debug.c
==============================================================================
--- branches/release/tools/build/v2/engine/debug.c (original)
+++ branches/release/tools/build/v2/engine/debug.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -14,34 +14,41 @@
 
 static profile_frame * profile_stack = 0;
 static struct hash * profile_hash = 0;
-static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
-static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
+static profile_info profile_other = { 0, 0, 0, 0, 0, 0 };
+static profile_info profile_total = { 0, 0, 0, 0, 0, 0 };
 
 
-profile_frame * profile_init( char * rulename, profile_frame * frame )
+profile_frame * profile_init( OBJECT * rulename, profile_frame * frame )
 {
     if ( DEBUG_PROFILE ) profile_enter( rulename, frame );
     return frame;
 }
 
 
-void profile_enter( char * rulename, profile_frame * frame )
+void profile_enter( OBJECT * rulename, profile_frame * frame )
 {
     if ( DEBUG_PROFILE )
     {
         clock_t start = clock();
- profile_info info;
- profile_info * p = &info;
-
- if ( !rulename ) p = &profile_other;
+ profile_info * p;
 
         if ( !profile_hash && rulename )
             profile_hash = hashinit( sizeof( profile_info ), "profile" );
 
- info.name = rulename;
-
- if ( rulename && hashenter( profile_hash, (HASHDATA * *)&p ) )
- p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
+ if ( rulename )
+ {
+ int found;
+ p = (profile_info *)hash_insert( profile_hash, rulename, &found );
+ if ( !found )
+ {
+ p->name = rulename;
+ p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
+ }
+ }
+ else
+ {
+ p = &profile_other;
+ }
 
         ++p->num_entries;
         ++p->stack_count;
@@ -115,7 +122,7 @@
         profile_total.memory += p->memory;
     }
     printf( "%10ld %12.6f %12.6f %12.8f %10ld %10ld %s\n", p->num_entries,
- cumulative, net, q, p->memory, mem_each, p->name );
+ cumulative, net, q, p->memory, mem_each, object_str( p->name ) );
 }
 
 
@@ -126,7 +133,9 @@
         printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--",
             "--net--", "--each--", "--mem--", "--each--", "--name--" );
         hashenumerate( profile_hash, dump_profile_entry, 0 );
+ profile_other.name = constant_other;
         dump_profile_entry( &profile_other, 0 );
+ profile_total.name = constant_total;
         dump_profile_entry( &profile_total, (void *)1 );
     }
 }

Modified: branches/release/tools/build/v2/engine/debug.h
==============================================================================
--- branches/release/tools/build/v2/engine/debug.h (original)
+++ branches/release/tools/build/v2/engine/debug.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -6,6 +6,7 @@
 #ifndef BJAM_DEBUG_H
 #define BJAM_DEBUG_H
 
+#include "constants.h"
 #include "jam.h"
 #include <time.h>
 
@@ -13,7 +14,7 @@
 struct profile_info
 {
     /* name of rule being called */
- char* name;
+ OBJECT * name;
     /* cumulative time spent in rule */
     clock_t cumulative;
     /* time spent in rule proper */
@@ -42,13 +43,13 @@
 };
 typedef struct profile_frame profile_frame;
 
-profile_frame * profile_init( char * rulename, profile_frame * frame );
-void profile_enter( char* rulename, profile_frame * frame );
+profile_frame * profile_init( OBJECT * rulename, profile_frame * frame );
+void profile_enter( OBJECT * rulename, profile_frame * frame );
 void profile_memory( long mem );
 void profile_exit( profile_frame * frame );
 void profile_dump();
 
-#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( #scope, &PROF_ ## scope )
+#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( constant_ ## scope, &PROF_ ## scope )
 #define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
 
 #endif

Modified: branches/release/tools/build/v2/engine/execcmd.h
==============================================================================
--- branches/release/tools/build/v2/engine/execcmd.h (original)
+++ branches/release/tools/build/v2/engine/execcmd.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -28,16 +28,18 @@
 
 void exec_cmd
 (
- char * string,
- void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ const char * string,
+ void (* func)( void * closure, int status, timing_info *, const char *, const char * ),
     void * closure,
     LIST * shell,
- char * action,
- char * target
+ const char * action,
+ const char * target
 );
 
 int exec_wait();
 
+void exec_done( void );
+
 #define EXEC_CMD_OK 0
 #define EXEC_CMD_FAIL 1
 #define EXEC_CMD_INTR 2

Deleted: branches/release/tools/build/v2/engine/execmac.c
==============================================================================
--- branches/release/tools/build/v2/engine/execmac.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,69 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-#include "jam.h"
-#include "lists.h"
-#include "execcmd.h"
-#include <errno.h>
-
-#ifdef OS_MAC
-
-/*
- * execunix.c - execute a shell script on UNIX
- *
- * If $(JAMSHELL) is defined, uses that to formulate execvp().
- * The default is:
- *
- * /bin/sh -c %
- *
- * Each word must be an individual element in a jam variable value.
- *
- * In $(JAMSHELL), % expands to the command string and ! expands to
- * the slot number (starting at 1) for multiprocess (-j) invocations.
- * If $(JAMSHELL) doesn't include a %, it is tacked on as the last
- * argument.
- *
- * Don't just set JAMSHELL to /bin/sh - it won't work!
- *
- * External routines:
- * exec_cmd() - launch an async command execution.
- * exec_wait() - wait and drive at most one execution completion.
- *
- * Internal routines:
- * onintr() - bump intr to note command interruption.
- *
- * 04/08/94 (seiwald) - Coherent/386 support added.
- * 05/04/94 (seiwald) - async multiprocess interface
- * 01/22/95 (seiwald) - $(JAMSHELL) support
- */
-
-
-/*
- * exec_cmd() - launch an async command execution.
- */
-
-void exec_cmd
-(
- char * string,
- void (* func)( void * closure, int status, timing_info *, char *, char * ),
- void * closure,
- LIST * shell
-)
-{
- printf( "%s", string );
- (*func)( closure, EXEC_CMD_OK );
-}
-
-/*
- * exec_wait() - wait and drive at most one execution completion.
- */
-
-int exec_wait()
-{
- return 0;
-}
-
-#endif /* OS_MAC */

Modified: branches/release/tools/build/v2/engine/execnt.c
==============================================================================
--- branches/release/tools/build/v2/engine/execnt.c (original)
+++ branches/release/tools/build/v2/engine/execnt.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -65,13 +65,13 @@
 int maxline();
 
 /* delete and argv list */
-static void free_argv(char**);
+static void free_argv(const char * *);
 /* Convert a command string into arguments for spawnvp. */
-static char** string_to_args(const char*);
+static const char** string_to_args(const char*);
 /* bump intr to note command interruption */
 static void onintr(int);
 /* If the command is suitable for execution via spawnvp */
-long can_spawn(char*);
+long can_spawn(const char*);
 /* Add two 64-bit unsigned numbers, h1l1 and h2l2 */
 static FILETIME add_64(
     unsigned long h1, unsigned long l1,
@@ -135,7 +135,7 @@
     int exit_reason; /* reason why a command completed */
 
     /* Function called when the command completes. */
- void (* func)( void * closure, int status, timing_info *, char *, char * );
+ void (* func)( void * closure, int status, timing_info *, const char *, const char * );
 
     /* Opaque data passed back to the 'func' callback called when the command
      * completes.
@@ -184,7 +184,7 @@
         /* Work around vc6 bug; it doesn't like escaped string
          * literals inside assert
          */
- char * * argv = string_to_args(" \"g++\" -c -I\"Foobar\"" );
+ const char * * argv = string_to_args(" \"g++\" -c -I\"Foobar\"" );
         char const expected[] = "-c -I\"Foobar\"";
 
         assert( !strcmp( argv[ 0 ], "g++" ) );
@@ -201,26 +201,26 @@
 
 void exec_cmd
 (
- char * command,
- void (* func)( void * closure, int status, timing_info *, char * invoked_command, char * command_output ),
- void * closure,
- LIST * shell,
- char * action,
- char * target
+ const char * command,
+ void (* func)( void * closure, int status, timing_info *, const char * invoked_command, const char * command_output ),
+ void * closure,
+ LIST * shell,
+ const char * action,
+ const char * target
 )
 {
     int slot;
     int raw_cmd = 0 ;
- char * argv_static[ MAXARGC + 1 ]; /* +1 for NULL */
- char * * argv = argv_static;
+ const char * argv_static[ MAXARGC + 1 ]; /* +1 for NULL */
+ const char * * argv = argv_static;
     char * p;
- char * command_orig = command;
+ const char * command_orig = command;
 
     /* Check to see if we need to hack around the line-length limitation. Look
      * for a JAMSHELL setting of "%", indicating that the command should be
      * invoked directly.
      */
- if ( shell && !strcmp( shell->string, "%" ) && !list_next( shell ) )
+ if ( !list_empty( shell ) && !strcmp( object_str( list_front( shell ) ), "%" ) && list_next( list_begin( shell ) ) == list_end( shell ) )
     {
         raw_cmd = 1;
         shell = 0;
@@ -290,8 +290,8 @@
 
         if ( DEBUG_EXECCMD )
         {
- if ( shell )
- printf( "using user-specified shell: %s", shell->string );
+ if ( !list_empty( shell ) )
+ printf( "using user-specified shell: %s", object_str( list_front( shell ) ) );
             else
                 printf( "Executing through .bat file\n" );
         }
@@ -305,16 +305,17 @@
         int i;
         char jobno[ 4 ];
         int gotpercent = 0;
+ LISTITER shell_iter = list_begin( shell ), shell_end = list_end( shell );
 
         sprintf( jobno, "%d", slot + 1 );
 
- for ( i = 0; shell && ( i < MAXARGC ); ++i, shell = list_next( shell ) )
+ for ( i = 0; shell_iter != shell_end && ( i < MAXARGC ); ++i, shell_iter = list_next( shell_iter ) )
         {
- switch ( shell->string[ 0 ] )
+ switch ( object_str( list_item( shell_iter ) )[ 0 ] )
             {
                 case '%': argv[ i ] = command; ++gotpercent; break;
                 case '!': argv[ i ] = jobno; break;
- default : argv[ i ] = shell->string;
+ default : argv[ i ] = object_str( list_item( shell_iter ) );
             }
             if ( DEBUG_EXECCMD )
                 printf( "argv[%d] = '%s'\n", i, argv[ i ] );
@@ -425,7 +426,7 @@
 
         /* Put together the command we run. */
         {
- char * * argp = argv;
+ const char * * argp = argv;
             string_new( &cmd );
             string_copy( &cmd, *(argp++) );
             while ( *argp )
@@ -577,10 +578,10 @@
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 
-static void free_argv( char * * args )
+static void free_argv( const char * * args )
 {
- BJAM_FREE( args[ 0 ] );
- BJAM_FREE( args );
+ BJAM_FREE( (void *)args[ 0 ] );
+ BJAM_FREE( (void *)args );
 }
 
 
@@ -613,14 +614,14 @@
  * New strategy: break the string in at most one place.
  */
 
-static char * * string_to_args( char const * string )
+static const char * * string_to_args( char const * string )
 {
     int src_len;
     int in_quote;
     char * line;
     char const * src;
     char * dst;
- char * * argv;
+ const char * * argv;
 
     /* Drop leading and trailing whitespace if any. */
     while ( isspace( *string ) )
@@ -640,7 +641,7 @@
      * element 1: stores the command-line arguments to the executable
      * element 2: NULL terminator
      */
- argv = (char * *)BJAM_MALLOC( 3 * sizeof( char * ) );
+ argv = (const char * *)BJAM_MALLOC( 3 * sizeof( const char * ) );
     if ( !argv )
     {
         BJAM_FREE( line );
@@ -697,9 +698,9 @@
  * Otherwise, return zero.
  */
 
-long can_spawn( char * command )
+long can_spawn( const char * command )
 {
- char * p;
+ const char * p;
     char inquote = 0;
 
     /* Move to the first non-whitespace. */
@@ -1293,4 +1294,10 @@
     }
 }
 
+
+void exec_done( void )
+{
+}
+
+
 #endif /* USE_EXECNT */

Modified: branches/release/tools/build/v2/engine/execunix.c
==============================================================================
--- branches/release/tools/build/v2/engine/execunix.c (original)
+++ branches/release/tools/build/v2/engine/execunix.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -66,7 +66,7 @@
  */
 
 static clock_t tps = 0;
-static struct timeval tv;
+static struct timespec tv;
 static int select_timeout = 0;
 static int intr = 0;
 static int cmdsrunning = 0;
@@ -88,9 +88,10 @@
     char *target; /* buffer to hold action and target invoked */
     char *command; /* buffer to hold command being invoked */
     char *buffer[2]; /* buffer to hold stdout and stderr, if any */
- void (*func)( void *closure, int status, timing_info*, char *, char * );
+ void (*func)( void *closure, int status, timing_info*, const char *, const char * );
     void *closure;
     time_t start_dt; /* start of command timestamp */
+ long msgsize[2];
 } cmdtab[ MAXJOBS ] = {{0}};
 
 /*
@@ -110,12 +111,12 @@
 
 void exec_cmd
 (
- char * string,
- void (*func)( void *closure, int status, timing_info*, char *, char * ),
+ const char * string,
+ void (*func)( void *closure, int status, timing_info*, const char *, const char * ),
     void * closure,
     LIST * shell,
- char * action,
- char * target
+ const char * action,
+ const char * target
 )
 {
     static int initialized = 0;
@@ -123,7 +124,7 @@
     int err[2];
     int slot;
     int len;
- char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
+ const char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
 
     /* Find a slot in the running commands table for this one. */
     for ( slot = 0; slot < MAXJOBS; ++slot )
@@ -139,21 +140,22 @@
     /* Forumulate argv. If shell was defined, be prepared for % and ! subs.
      * Otherwise, use stock /bin/sh on unix or cmd.exe on NT.
      */
- if ( shell )
+ if ( !list_empty( shell ) )
     {
         int i;
         char jobno[4];
         int gotpercent = 0;
+ LISTITER iter = list_begin( shell ), end = list_end( shell );
 
         sprintf( jobno, "%d", slot + 1 );
 
- for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
+ for ( i = 0; iter != end && i < MAXARGC; ++i, iter = list_next( iter ) )
         {
- switch ( shell->string[0] )
+ switch ( object_str( list_item( iter ) )[0] )
             {
                 case '%': argv[ i ] = string; ++gotpercent; break;
                 case '!': argv[ i ] = jobno; break;
- default : argv[ i ] = shell->string;
+ default : argv[ i ] = object_str( list_item( iter ) );
             }
             if ( DEBUG_EXECCMD )
                 printf( "argv[%d] = '%s'\n", i, argv[ i ] );
@@ -242,7 +244,7 @@
             setrlimit( RLIMIT_CPU, &r_limit );
         }
         setpgid( pid,pid );
- execvp( argv[0], argv );
+ execvp( argv[0], (char * *)argv );
         perror( "execvp" );
         _exit( 127 );
     }
@@ -342,28 +344,36 @@
 
 int read_descriptor( int i, int s )
 {
- int ret;
- int len;
+ int ret = 1, len, err;
     char buffer[BUFSIZ];
 
- while ( 0 < ( ret = fread( buffer, sizeof(char), BUFSIZ-1, cmdtab[ i ].stream[ s ] ) ) )
- {
- buffer[ret] = 0;
- if ( !cmdtab[ i ].buffer[ s ] )
- {
- /* Never been allocated. */
- cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( ret + 1 );
- memcpy( cmdtab[ i ].buffer[ s ], buffer, ret + 1 );
- }
- else
- {
- /* Previously allocated. */
- char * tmp = cmdtab[ i ].buffer[ s ];
- len = strlen( tmp );
- cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( len + ret + 1 );
- memcpy( cmdtab[ i ].buffer[ s ], tmp, len );
- memcpy( cmdtab[ i ].buffer[ s ] + len, buffer, ret + 1 );
- BJAM_FREE( tmp );
+ while ( 0 < ( ret = fread( buffer, sizeof(char), BUFSIZ-1, cmdtab[ i ].stream[ s ] ) ) ) {
+
+ /* only copy action data until hit buffer limit, then ignore rest of data */
+ if (cmdtab[i].msgsize[s] < globs.maxbuf) {
+ cmdtab[i].msgsize[s] += ret;
+ buffer[ret] = 0;
+ if ( !cmdtab[ i ].buffer[ s ] )
+ {
+ /* Never been allocated. */
+ cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( ret + 1 );
+ memcpy( cmdtab[ i ].buffer[ s ], buffer, ret + 1 );
+ }
+ else
+ {
+ /* Previously allocated. */
+ char * tmp = cmdtab[ i ].buffer[ s ];
+ len = strlen( tmp );
+ cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( len + ret + 1 );
+ memcpy( cmdtab[ i ].buffer[ s ], tmp, len );
+ memcpy( cmdtab[ i ].buffer[ s ] + len, buffer, ret + 1 );
+ BJAM_FREE( tmp );
+ }
+
+ /* buffer was truncated, append newline to ensure pjl can find line end */
+ if (globs.maxbuf <= cmdtab[i].msgsize[s]) {
+ cmdtab[i].buffer[s][cmdtab[i].msgsize[s]-1] = '\n';
+ }
         }
     }
 
@@ -379,6 +389,8 @@
 
     close(cmdtab[ i ].fd[ s ]);
     cmdtab[ i ].fd[ s ] = 0;
+
+ cmdtab[i].msgsize[s] = 0;
 }
 
 
@@ -423,6 +435,61 @@
     *fmax = fd_max;
 }
 
+void cleanup_child(int i, int status)
+{
+ int rstat;
+ struct tms new_time;
+ timing_info time_info;
+
+ cmdtab[ i ].pid = 0;
+
+ /* Set reason for exit if not timed out. */
+ if ( WIFEXITED( status ) ) {
+ cmdtab[ i ].exit_reason = 0 == WEXITSTATUS( status )
+ ? EXIT_OK : EXIT_FAIL;
+ }
+
+ /* Print out the rule and target name. */
+ out_action( cmdtab[ i ].action, cmdtab[ i ].target,
+ cmdtab[ i ].command, cmdtab[ i ].buffer[ OUT ],
+ cmdtab[ i ].buffer[ ERR ], cmdtab[ i ].exit_reason
+ );
+
+ times( &new_time );
+
+ time_info.system = (double)( new_time.tms_cstime - old_time.tms_cstime ) / CLOCKS_PER_SEC;
+ time_info.user = (double)( new_time.tms_cutime - old_time.tms_cutime ) / CLOCKS_PER_SEC;
+ time_info.start = cmdtab[ i ].start_dt;
+ time_info.end = time( 0 );
+
+ old_time = new_time;
+
+ if ( intr )
+ rstat = EXEC_CMD_INTR;
+ else if ( status != 0 )
+ rstat = EXEC_CMD_FAIL;
+ else
+ rstat = EXEC_CMD_OK;
+
+ /* Assume -p0 in effect so only pass buffer[ 0 ]
+ * containing merged output.
+ */
+ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time_info, cmdtab[ i ].command, cmdtab[ i ].buffer[ 0 ] );
+
+ BJAM_FREE( cmdtab[ i ].buffer[ OUT ] );
+ cmdtab[ i ].buffer[ OUT ] = 0;
+
+ BJAM_FREE( cmdtab[ i ].buffer[ ERR ] );
+ cmdtab[ i ].buffer[ ERR ] = 0;
+
+ BJAM_FREE( cmdtab[ i ].command );
+ cmdtab[ i ].command = 0;
+
+ cmdtab[ i ].func = 0;
+ cmdtab[ i ].closure = 0;
+ cmdtab[ i ].start_time = 0;
+}
+
 
 /*
  * exec_wait() - wait and drive at most one execution completion.
@@ -430,16 +497,13 @@
 
 int exec_wait()
 {
- int i;
+ int i, j;
     int ret;
     int fd_max;
     int pid;
     int status;
     int finished;
- int rstat;
- timing_info time_info;
     fd_set fds;
- struct tms new_time;
 
     /* Handle naive make1() which does not know if commands are running. */
     if ( !cmdsrunning )
@@ -457,17 +521,47 @@
             /* Force select() to timeout so we can terminate expired processes.
              */
             tv.tv_sec = select_timeout;
- tv.tv_usec = 0;
+ tv.tv_nsec = 0;
 
             /* select() will wait until: i/o on a descriptor, a signal, or we
              * time out.
              */
- ret = select( fd_max + 1, &fds, 0, 0, &tv );
+ ret = pselect( fd_max + 1, &fds, 0, 0, &tv, &empty_sigmask );
         }
         else
         {
- /* select() will wait until i/o on a descriptor or a signal. */
- ret = select( fd_max + 1, &fds, 0, 0, 0 );
+ /* pselect() will wait until i/o on a descriptor or a signal. */
+ ret = pselect( fd_max + 1, &fds, 0, 0, 0, &empty_sigmask );
+ }
+
+ if (-1 == ret && errno != EINTR) {
+ perror("pselect()");
+ exit(-1);
+ }
+
+ if (0 < child_events) {
+ /* child terminated via SIGCHLD */
+ for (i=0; i<MAXJOBS; ++i) {
+ if (0 < terminated_children[i].pid) {
+ pid_t pid = terminated_children[i].pid;
+ /* get index of terminated pid */
+ for (j=0; j<globs.jobs; ++j) {
+ if (pid == cmdtab[j].pid) {
+ /* cleanup loose ends for terminated process */
+ close_streams(j, OUT);
+ if ( globs.pipe_action != 0 ) close_streams(j, ERR);
+ cleanup_child(j, terminated_children[i].status);
+ --cmdsrunning;
+ finished = 1;
+ break;
+ }
+ }
+ /* clear entry from list */
+ terminated_children[i].status = 0;
+ terminated_children[i].pid = 0;
+ --child_events;
+ }
+ }
         }
 
         if ( 0 < ret )
@@ -496,62 +590,10 @@
 
                     if ( pid == cmdtab[ i ].pid )
                     {
+ /* move into function so signal handler can also use */
                         finished = 1;
- pid = 0;
- cmdtab[ i ].pid = 0;
-
- /* Set reason for exit if not timed out. */
- if ( WIFEXITED( status ) )
- {
- cmdtab[ i ].exit_reason = 0 == WEXITSTATUS( status )
- ? EXIT_OK
- : EXIT_FAIL;
- }
-
- /* Print out the rule and target name. */
- out_action( cmdtab[ i ].action, cmdtab[ i ].target,
- cmdtab[ i ].command, cmdtab[ i ].buffer[ OUT ],
- cmdtab[ i ].buffer[ ERR ], cmdtab[ i ].exit_reason
- );
-
- times( &new_time );
-
- time_info.system = (double)( new_time.tms_cstime - old_time.tms_cstime ) / CLOCKS_PER_SEC;
- time_info.user = (double)( new_time.tms_cutime - old_time.tms_cutime ) / CLOCKS_PER_SEC;
- time_info.start = cmdtab[ i ].start_dt;
- time_info.end = time( 0 );
-
- old_time = new_time;
-
- /* Drive the completion. */
+ cleanup_child(i, status);
                         --cmdsrunning;
-
- if ( intr )
- rstat = EXEC_CMD_INTR;
- else if ( status != 0 )
- rstat = EXEC_CMD_FAIL;
- else
- rstat = EXEC_CMD_OK;
-
- /* Assume -p0 in effect so only pass buffer[ 0 ]
- * containing merged output.
- */
- (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat,
- &time_info, cmdtab[ i ].command,
- cmdtab[ i ].buffer[ 0 ] );
-
- BJAM_FREE( cmdtab[ i ].buffer[ OUT ] );
- cmdtab[ i ].buffer[ OUT ] = 0;
-
- BJAM_FREE( cmdtab[ i ].buffer[ ERR ] );
- cmdtab[ i ].buffer[ ERR ] = 0;
-
- BJAM_FREE( cmdtab[ i ].command );
- cmdtab[ i ].command = 0;
-
- cmdtab[ i ].func = 0;
- cmdtab[ i ].closure = 0;
- cmdtab[ i ].start_time = 0;
                     }
                     else
                     {
@@ -562,8 +604,18 @@
             }
         }
     }
-
     return 1;
 }
 
+void exec_done( void )
+{
+ int i;
+ for( i = 0; i < MAXJOBS; ++i )
+ {
+ if( ! cmdtab[i].action ) break;
+ BJAM_FREE( cmdtab[i].action );
+ BJAM_FREE( cmdtab[i].target );
+ }
+}
+
 # endif /* USE_EXECUNIX */

Deleted: branches/release/tools/build/v2/engine/execvms.c
==============================================================================
--- branches/release/tools/build/v2/engine/execvms.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,161 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-#include "jam.h"
-#include "lists.h"
-#include "execcmd.h"
-
-#ifdef OS_VMS
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <iodef.h>
-#include <ssdef.h>
-#include <descrip.h>
-#include <dvidef.h>
-#include <clidef.h>
-
-/*
- * execvms.c - execute a shell script, ala VMS.
- *
- * The approach is this:
- *
- * If the command is a single line, and shorter than WRTLEN (what we believe to
- * be the maximum line length), we just system() it.
- *
- * If the command is multi-line, or longer than WRTLEN, we write the command
- * block to a temp file, splitting long lines (using "-" at the end of the line
- * to indicate contiuation), and then source that temp file. We use special
- * logic to make sure we do not continue in the middle of a quoted string.
- *
- * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
- * 12/20/96 (seiwald) - rewritten to handle multi-line commands well
- * 01/14/96 (seiwald) - do not put -'s between "'s
- */
-
-#define WRTLEN 240
-
-#define MIN( a, b ) ((a) < (b) ? (a) : (b))
-
-/* 1 for the @ and 4 for the .com */
-
-char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
-
-
-void exec_cmd
-(
- char * string,
- void (* func)( void * closure, int status, timing_info *, char *, char * ),
- void * closure,
- LIST * shell,
- char * rule_name,
- char * target
-)
-{
- char * s;
- char * e;
- cahr * p;
- int rstat = EXEC_CMD_OK;
- int status;
-
- /* See if string is more than one line discounting leading/trailing white
- * space.
- */
- for ( s = string; *s && isspace( *s ); ++s );
-
- e = p = strchr( s, '\n' );
-
- while ( p && isspace( *p ) )
- ++p;
-
- /* If multi line or long, write to com file. Otherwise, exec directly. */
- if ( ( p && *p ) || ( e - s > WRTLEN ) )
- {
- FILE * f;
-
- /* Create temp file invocation "@sys$scratch:tempfile.com". */
- if ( !*tempnambuf )
- {
- tempnambuf[0] = '@';
- (void)tmpnam( tempnambuf + 1 );
- strcat( tempnambuf, ".com" );
- }
-
- /* Open tempfile. */
- if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
- {
- printf( "can't open command file\n" );
- (*func)( closure, EXEC_CMD_FAIL );
- return;
- }
-
- /* For each line of the string. */
- while ( *string )
- {
- char * s = strchr( string, '\n' );
- int len = s ? s + 1 - string : strlen( string );
-
- fputc( '$', f );
-
- /* For each chunk of a line that needs to be split. */
- while ( len > 0 )
- {
- char * q = string;
- char * qe = string + MIN( len, WRTLEN );
- char * qq = q;
- int quote = 0;
-
- /* Look for matching "s. */
- for ( ; q < qe; ++q )
- if ( ( *q == '"' ) && ( quote = !quote ) )
- qq = q;
-
- /* Back up to opening quote, if in one. */
- if ( quote )
- q = qq;
-
- fwrite( string, ( q - string ), 1, f );
-
- len -= ( q - string );
- string = q;
-
- if ( len )
- {
- fputc( '-', f );
- fputc( '\n', f );
- }
- }
- }
-
- fclose( f );
-
- status = system( tempnambuf ) & 0x07;
-
- unlink( tempnambuf + 1 );
- }
- else
- {
- /* Execute single line command. Strip trailing newline before execing.
- */
- if ( e ) *e = 0;
- status = system( s ) & 0x07;
- }
-
- /* Fail for error or fatal error. OK on OK, warning or info exit. */
- if ( ( status == 2 ) || ( status == 4 ) )
- rstat = EXEC_CMD_FAIL;
-
- (*func)( closure, rstat );
-}
-
-
-int exec_wait()
-{
- return 0;
-}
-
-# endif /* VMS */

Deleted: branches/release/tools/build/v2/engine/expand.c
==============================================================================
--- branches/release/tools/build/v2/engine/expand.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,733 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-# include "jam.h"
-# include "lists.h"
-# include "variable.h"
-# include "expand.h"
-# include "pathsys.h"
-# include "newstr.h"
-# include <assert.h>
-# include <stdlib.h>
-# include <limits.h>
-
-# ifdef OS_CYGWIN
-# include <sys/cygwin.h>
-# include <windows.h>
-# endif
-
-/*
- * expand.c - expand a buffer, given variable values
- *
- * External routines:
- *
- * var_expand() - variable-expand input string into list of strings
- *
- * Internal routines:
- *
- * var_edit_parse() - parse : modifiers into PATHNAME structure.
- * var_edit_file() - copy input target name to output, modifying filename.
- * var_edit_shift() - do upshift/downshift mods.
- *
- * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
- * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
- * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
- */
-
-typedef struct
-{
- PATHNAME f; /* :GDBSMR -- pieces */
- char parent; /* :P -- go to parent directory */
- char filemods; /* one of the above applied */
- char downshift; /* :L -- downshift result */
- char upshift; /* :U -- upshift result */
- char to_slashes; /* :T -- convert "\" to "/" */
- char to_windows; /* :W -- convert cygwin to native paths */
- PATHPART empty; /* :E -- default for empties */
- PATHPART join; /* :J -- join list with char */
-} VAR_EDITS ;
-
-static void var_edit_parse( char * mods, VAR_EDITS * edits );
-static void var_edit_file ( char * in, string * out, VAR_EDITS * edits );
-static void var_edit_shift( string * out, VAR_EDITS * edits );
-
-#define MAGIC_COLON '\001'
-#define MAGIC_LEFT '\002'
-#define MAGIC_RIGHT '\003'
-
-
-/*
- * var_expand() - variable-expand input string into list of strings.
- *
- * Would just copy input to output, performing variable expansion, except that
- * since variables can contain multiple values the result of variable expansion
- * may contain multiple values (a list). Properly performs "product" operations
- * that occur in "$(var1)xxx$(var2)" or even "$($(var2))".
- *
- * Returns a newly created list.
- */
-
-LIST * var_expand( LIST * l, char * in, char * end, LOL * lol, int cancopyin )
-{
- char out_buf[ MAXSYM ];
- string buf[ 1 ];
- string out1[ 1 ]; /* temporary buffer */
- size_t prefix_length;
- char * out;
- char * inp = in;
- char * ov; /* for temp copy of variable in outbuf */
- int depth;
-
- if ( DEBUG_VAREXP )
- printf( "expand '%.*s'\n", end - in, in );
-
- /* This gets a lot of cases: $(<) and $(>). */
- if
- (
- ( in[ 0 ] == '$' ) &&
- ( in[ 1 ] == '(' ) &&
- ( in[ 3 ] == ')' ) &&
- ( in[ 4 ] == '\0' )
- )
- {
- switch ( in[ 2 ] )
- {
- case '<': return list_copy( l, lol_get( lol, 0 ) );
- case '>': return list_copy( l, lol_get( lol, 1 ) );
-
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return list_copy( l, lol_get( lol, in[ 2 ] - '1' ) );
- }
- }
- else if ( in[0] == '$' && in[1] == '(' && in[2] == '1' && in[4] == ')' &&
- in[5] == '\0') {
-
- switch( in[3] )
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return list_copy( l, lol_get( lol, in[3]-'0'+10-1 ) );
- }
- }
-
- /* Expand @() files, to single item plus accompanying file. */
- if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) && ( *( end - 1 ) == ')' ) )
- {
- /* We try the expansion until it fits within the propective output
- * buffer.
- */
- char * at_buf = 0;
- int at_size = MAXJPATH;
- int at_len = 0;
- do
- {
- BJAM_FREE( at_buf );
- at_buf = (char *)BJAM_MALLOC_ATOMIC( at_size + 1 );
- at_len = var_string( in, at_buf, at_size, lol );
- at_size *= 2;
- }
- while ( ( at_len < 0 ) && ( at_size < INT_MAX / 2 ) );
- /* Return the result as a single item list. */
- if ( at_len > 0 )
- {
- LIST * r;
- string_copy( buf, at_buf );
- r = list_new( l, newstr( buf->value ) );
- string_free( buf );
- BJAM_FREE( at_buf );
- return r;
- }
- BJAM_FREE( at_buf );
- }
-
- /* Just try simple copy of in to out. */
- while ( in < end )
- if ( ( *in++ == '$' ) && ( *in == '(' ) )
- goto expand;
-
- /* No variables expanded - just add copy of input string to list. */
-
- /* 'cancopyin' is an optimization: if the input was already a list item, we
- * can use copystr() to put it on the new list. Otherwise, we use the slower
- * newstr().
- */
- if ( cancopyin )
- return list_new( l, copystr( inp ) );
-
- {
- LIST * r;
- string_new( buf );
- string_append_range( buf, inp, end );
- r = list_new( l, newstr( buf->value ) );
- string_free( buf );
- return r;
- }
-
-expand:
- string_new( buf );
- string_append_range( buf, inp, in - 1 ); /* Copy the part before '$'. */
- /*
- * Input so far (ignore blanks):
- *
- * stuff-in-outbuf $(variable) remainder
- * ^ ^
- * in end
- * Output so far:
- *
- * stuff-in-outbuf $
- * ^ ^
- * out_buf out
- *
- *
- * We just copied the $ of $(...), so back up one on the output. We now find
- * the matching close paren, copying the variable and modifiers between the
- * $( and ) temporarily into out_buf, so that we can replace :'s with
- * MAGIC_COLON. This is necessary to avoid being confused by modifier values
- * that are variables containing :'s. Ugly.
- */
-
- depth = 1;
- inp = ++in; /* Skip over the '('. */
-
- while ( ( in < end ) && depth )
- {
- switch ( *in++ )
- {
- case '(': ++depth; break;
- case ')': --depth; break;
- }
- }
-
- /*
- * Input so far (ignore blanks):
- *
- * stuff-in-outbuf $(variable) remainder
- * ^ ^ ^
- * inp in end
- */
- prefix_length = buf->size;
- string_append_range( buf, inp, in - 1 );
-
- out = buf->value + prefix_length;
- for ( ov = out; ov < buf->value + buf->size; ++ov )
- {
- switch ( *ov )
- {
- case ':': *ov = MAGIC_COLON; break;
- case '[': *ov = MAGIC_LEFT ; break;
- case ']': *ov = MAGIC_RIGHT; break;
- }
- }
-
- /*
- * Input so far (ignore blanks):
- *
- * stuff-in-outbuf $(variable) remainder
- * ^ ^
- * in end
- * Output so far:
- *
- * stuff-in-outbuf variable
- * ^ ^ ^
- * out_buf out ov
- *
- * Later we will overwrite 'variable' in out_buf, but we will be done with
- * it by then. 'variable' may be a multi-element list, so may each value for
- * '$(variable element)', and so may 'remainder'. Thus we produce a product
- * of three lists.
- */
- {
- LIST * variables = 0;
- LIST * remainder = 0;
- LIST * vars;
-
- /* Recursively expand variable name & rest of input. */
- if ( out < ov ) variables = var_expand( L0, out, ov, lol, 0 );
- if ( in < end ) remainder = var_expand( L0, in, end, lol, 0 );
-
- /* Now produce the result chain. */
-
- /* For each variable name. */
- for ( vars = variables; vars; vars = list_next( vars ) )
- {
- LIST * value = 0;
- LIST * evalue = 0;
- char * colon;
- char * bracket;
- string variable[1];
- char * varname;
- int sub1 = 0;
- int sub2 = -1;
- VAR_EDITS edits;
-
- /* Look for a : modifier in the variable name. Must copy into
- * varname so we can modify it.
- */
- string_copy( variable, vars->string );
- varname = variable->value;
-
- if ( ( colon = strchr( varname, MAGIC_COLON ) ) )
- {
- string_truncate( variable, colon - varname );
- var_edit_parse( colon + 1, &edits );
- }
-
- /* Look for [x-y] subscripting. sub1 and sub2 are x and y. */
- if ( ( bracket = strchr( varname, MAGIC_LEFT ) ) )
- {
- /* Make all syntax errors in [] subscripting result in the same
- * behavior: silenty return an empty expansion (by setting sub2
- * = 0). Brute force parsing; May get moved into yacc someday.
- */
-
- char * s = bracket + 1;
-
- string_truncate( variable, bracket - varname );
-
- do /* so we can use "break" */
- {
- /* Allow negative indexes. */
- if ( !isdigit( *s ) && ( *s != '-' ) )
- {
- sub2 = 0;
- break;
- }
- sub1 = atoi( s );
-
- /* Skip over the first symbol, which is either a digit or dash. */
- ++s;
- while ( isdigit( *s ) ) ++s;
-
- if ( *s == MAGIC_RIGHT )
- {
- sub2 = sub1;
- break;
- }
-
- if ( *s != '-' )
- {
- sub2 = 0;
- break;
- }
-
- ++s;
-
- if ( *s == MAGIC_RIGHT )
- {
- sub2 = -1;
- break;
- }
-
- if ( !isdigit( *s ) && ( *s != '-' ) )
- {
- sub2 = 0;
- break;
- }
-
- /* First, compute the index of the last element. */
- sub2 = atoi( s );
- while ( isdigit( *++s ) );
-
- if ( *s != MAGIC_RIGHT )
- sub2 = 0;
-
- } while ( 0 );
-
- /* Anything but the end of the string, or the colon introducing
- * a modifier is a syntax error.
- */
- ++s;
- if ( *s && ( *s != MAGIC_COLON ) )
- sub2 = 0;
-
- *bracket = '\0';
- }
-
- /* Get variable value, with special handling for $(<), $(>), $(n).
- */
- if ( !varname[1] )
- {
- if ( varname[0] == '<' )
- value = lol_get( lol, 0 );
- else if ( varname[0] == '>' )
- value = lol_get( lol, 1 );
- else if ( ( varname[0] >= '1' ) && ( varname[0] <= '9' ) )
- value = lol_get( lol, varname[0] - '1' );
- else if( varname[0] == '1' && varname[1] >= '0' &&
- varname[1] <= '9' && !varname[2] )
- value = lol_get( lol, varname[1] - '0' + 10 - 1 );
- }
-
- if ( !value )
- value = var_get( varname );
-
- /* Handle negitive indexes: part two. */
- {
- int length = list_length( value );
-
- if ( sub1 < 0 )
- sub1 = length + sub1;
- else
- sub1 -= 1;
-
- if ( sub2 < 0 )
- sub2 = length + 1 + sub2 - sub1;
- else
- sub2 -= sub1;
- /* The "sub2 < 0" test handles the semantic error of sub2 <
- * sub1.
- */
- if ( sub2 < 0 )
- sub2 = 0;
- }
-
- /* The fast path: $(x) - just copy the variable value. This is only
- * an optimization.
- */
- if ( ( out == out_buf ) && !bracket && !colon && ( in == end ) )
- {
- string_free( variable );
- l = list_copy( l, value );
- continue;
- }
-
- /* Handle start subscript. */
- while ( ( sub1 > 0 ) && value )
- --sub1, value = list_next( value );
-
- /* Empty w/ :E=default?. */
- if ( !value && colon && edits.empty.ptr )
- evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
-
- /* For each variable value. */
- string_new( out1 );
- for ( ; value; value = list_next( value ) )
- {
- LIST * rem;
- size_t postfix_start;
-
- /* Handle end subscript (length actually). */
-
- if ( sub2 >= 0 && --sub2 < 0 )
- break;
-
- string_truncate( buf, prefix_length );
-
- /* Apply : mods, if present */
-
- if ( colon && edits.filemods )
- var_edit_file( value->string, out1, &edits );
- else
- string_append( out1, value->string );
-
- if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
- var_edit_shift( out1, &edits );
-
- /* Handle :J=joinval */
- /* If we have more values for this var, just keep appending them
- * (using the join value) rather than creating separate LIST
- * elements.
- */
- if ( colon && edits.join.ptr &&
- ( list_next( value ) || list_next( vars ) ) )
- {
- string_append( out1, edits.join.ptr );
- continue;
- }
-
- string_append( buf, out1->value );
- string_free( out1 );
- string_new( out1 );
-
- /* If no remainder, append result to output chain. */
- if ( in == end )
- {
- l = list_new( l, newstr( buf->value ) );
- continue;
- }
-
- /* For each remainder, append the complete string to the output
- * chain. Remember the end of the variable expansion so we can
- * just tack on each instance of 'remainder'.
- */
- postfix_start = buf->size;
- for ( rem = remainder; rem; rem = list_next( rem ) )
- {
- string_truncate( buf, postfix_start );
- string_append( buf, rem->string );
- l = list_new( l, newstr( buf->value ) );
- }
- }
- string_free( out1 );
-
- /* Toss used empty. */
- if ( evalue )
- list_free( evalue );
-
- string_free( variable );
- }
-
- /* variables & remainder were gifts from var_expand and must be freed. */
- if ( variables ) list_free( variables );
- if ( remainder ) list_free( remainder );
-
- if ( DEBUG_VAREXP )
- {
- printf( "expanded to " );
- list_print( l );
- printf( "\n" );
- }
-
- string_free( buf );
- return l;
- }
-}
-
-
-/*
- * var_edit_parse() - parse : modifiers into PATHNAME structure
- *
- * The : modifiers in a $(varname:modifier) currently support replacing or
- * omitting elements of a filename, and so they are parsed into a PATHNAME
- * structure (which contains pointers into the original string).
- *
- * Modifiers of the form "X=value" replace the component X with the given value.
- * Modifiers without the "=value" cause everything but the component X to be
- * omitted. X is one of:
- *
- * G <grist>
- * D directory name
- * B base name
- * S .suffix
- * M (member)
- * R root directory - prepended to whole path
- *
- * This routine sets:
- *
- * f->f_xxx.ptr = 0
- * f->f_xxx.len = 0
- * -> leave the original component xxx
- *
- * f->f_xxx.ptr = string
- * f->f_xxx.len = strlen( string )
- * -> replace component xxx with string
- *
- * f->f_xxx.ptr = ""
- * f->f_xxx.len = 0
- * -> omit component xxx
- *
- * var_edit_file() below and path_build() obligingly follow this convention.
- */
-
-static void var_edit_parse( char * mods, VAR_EDITS * edits )
-{
- int havezeroed = 0;
- memset( (char *)edits, 0, sizeof( *edits ) );
-
- while ( *mods )
- {
- char * p;
- PATHPART * fp;
-
- switch ( *mods++ )
- {
- case 'L': edits->downshift = 1; continue;
- case 'U': edits->upshift = 1; continue;
- case 'P': edits->parent = edits->filemods = 1; continue;
- case 'E': fp = &edits->empty; goto strval;
- case 'J': fp = &edits->join; goto strval;
- case 'G': fp = &edits->f.f_grist; goto fileval;
- case 'R': fp = &edits->f.f_root; goto fileval;
- case 'D': fp = &edits->f.f_dir; goto fileval;
- case 'B': fp = &edits->f.f_base; goto fileval;
- case 'S': fp = &edits->f.f_suffix; goto fileval;
- case 'M': fp = &edits->f.f_member; goto fileval;
- case 'T': edits->to_slashes = 1; continue;
- case 'W': edits->to_windows = 1; continue;
- default:
- return; /* Should complain, but so what... */
- }
-
- fileval:
- /* Handle :CHARS, where each char (without a following =) selects a
- * particular file path element. On the first such char, we deselect all
- * others (by setting ptr = "", len = 0) and for each char we select
- * that element (by setting ptr = 0).
- */
- edits->filemods = 1;
-
- if ( *mods != '=' )
- {
- if ( !havezeroed++ )
- {
- int i;
- for ( i = 0; i < 6; ++i )
- {
- edits->f.part[ i ].len = 0;
- edits->f.part[ i ].ptr = "";
- }
- }
-
- fp->ptr = 0;
- continue;
- }
-
- strval:
- /* Handle :X=value, or :X */
- if ( *mods != '=' )
- {
- fp->ptr = "";
- fp->len = 0;
- }
- else if ( ( p = strchr( mods, MAGIC_COLON ) ) )
- {
- *p = 0;
- fp->ptr = ++mods;
- fp->len = p - mods;
- mods = p + 1;
- }
- else
- {
- fp->ptr = ++mods;
- fp->len = strlen( mods );
- mods += fp->len;
- }
- }
-}
-
-
-/*
- * var_edit_file() - copy input target name to output, modifying filename.
- */
-
-static void var_edit_file( char * in, string * out, VAR_EDITS * edits )
-{
- PATHNAME pathname;
-
- /* Parse apart original filename, putting parts into "pathname". */
- path_parse( in, &pathname );
-
- /* Replace any pathname with edits->f */
- if ( edits->f.f_grist .ptr ) pathname.f_grist = edits->f.f_grist;
- if ( edits->f.f_root .ptr ) pathname.f_root = edits->f.f_root;
- if ( edits->f.f_dir .ptr ) pathname.f_dir = edits->f.f_dir;
- if ( edits->f.f_base .ptr ) pathname.f_base = edits->f.f_base;
- if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix;
- if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member;
-
- /* If requested, modify pathname to point to parent. */
- if ( edits->parent )
- path_parent( &pathname );
-
- /* Put filename back together. */
- path_build( &pathname, out, 0 );
-}
-
-
-/*
- * var_edit_shift() - do upshift/downshift mods.
- */
-
-static void var_edit_shift( string * out, VAR_EDITS * edits )
-{
- /* Handle upshifting, downshifting and slash translation now. */
- char * p;
- for ( p = out->value; *p; ++p)
- {
- if ( edits->upshift )
- *p = toupper( *p );
- else if ( edits->downshift )
- *p = tolower( *p );
- if ( edits->to_slashes && ( *p == '\\' ) )
- *p = '/';
-# ifdef OS_CYGWIN
- if ( edits->to_windows )
- {
- char result[ MAX_PATH + 1 ];
- cygwin_conv_to_win32_path( out->value, result );
- assert( strlen( result ) <= MAX_PATH );
- string_free( out );
- string_copy( out, result );
- }
-# endif
- }
- out->size = p - out->value;
-}
-
-
-#ifndef NDEBUG
-void var_expand_unit_test()
-{
- LOL lol[ 1 ];
- LIST * l;
- LIST * l2;
- LIST * expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
- LIST * e2;
- char axyb[] = "a$(xy)b";
- char azb[] = "a$($(z))b";
- char path[] = "$(p:W)";
-
-# ifdef OS_CYGWIN
- char cygpath[ 256 ];
- cygwin_conv_to_posix_path( "c:\\foo\\bar", cygpath );
-# else
- char cygpath[] = "/cygdrive/c/foo/bar";
-# endif
-
- lol_init(lol);
- var_set( "xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
- var_set( "z", list_new( L0, newstr( "xy" ) ), VAR_SET );
- var_set( "p", list_new( L0, newstr( cygpath ) ), VAR_SET );
-
- l = var_expand( 0, axyb, axyb + sizeof( axyb ) - 1, lol, 0 );
- for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
- assert( !strcmp( e2->string, l2->string ) );
- assert( l2 == 0 );
- assert( e2 == 0 );
- list_free( l );
-
- l = var_expand( 0, azb, azb + sizeof( azb ) - 1, lol, 0 );
- for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
- assert( !strcmp( e2->string, l2->string ) );
- assert( l2 == 0 );
- assert( e2 == 0 );
- list_free( l );
-
- l = var_expand( 0, path, path + sizeof( path ) - 1, lol, 0 );
- assert( l != 0 );
- assert( list_next( l ) == 0 );
-# ifdef OS_CYGWIN
- /* On some installations of cygwin the drive letter is expanded to other
- * case. This has been reported to be the case if cygwin has been installed
- * to C:\ as opposed to C:\cygwin. Since case of the drive letter will not
- * matter, we allow for both.
- */
- assert( !strcmp( l->string, "c:\\foo\\bar" ) ||
- !strcmp( l->string, "C:\\foo\\bar" ) );
-# else
- assert( !strcmp( l->string, cygpath ) );
-# endif
- list_free( l );
- list_free( expected );
- lol_free( lol );
-}
-#endif

Deleted: branches/release/tools/build/v2/engine/expand.h
==============================================================================
--- branches/release/tools/build/v2/engine/expand.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,14 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/*
- * expand.h - expand a buffer, given variable values
- */
-
-#include "lists.h"
-
-LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
-void var_expand_unit_test();

Deleted: branches/release/tools/build/v2/engine/filemac.c
==============================================================================
--- branches/release/tools/build/v2/engine/filemac.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,175 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/* This file is ALSO:
- * Copyright 2001-2004 David Abrahams.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- */
-
-# include "jam.h"
-# include "filesys.h"
-# include "pathsys.h"
-
-# ifdef OS_MAC
-
-#include <Files.h>
-#include <Folders.h>
-
-# include <:sys:stat.h>
-
-/*
- * filemac.c - manipulate file names and scan directories on macintosh
- *
- * External routines:
- *
- * file_dirscan() - scan a directory for files
- * file_time() - get timestamp of file, if not done by file_dirscan()
- * file_archscan() - scan an archive for files
- *
- * File_dirscan() and file_archscan() call back a caller provided function
- * for each file found. A flag to this callback function lets file_dirscan()
- * and file_archscan() indicate that a timestamp is being provided with the
- * file. If file_dirscan() or file_archscan() do not provide the file's
- * timestamp, interested parties may later call file_time().
- *
- * 04/08/94 (seiwald) - Coherent/386 support added.
- * 12/19/94 (mikem) - solaris string table insanity support
- * 02/14/95 (seiwald) - parse and build /xxx properly
- * 05/03/96 (seiwald) - split into pathunix.c
- * 11/21/96 (peterk) - BEOS does not have Unix-style archives
- */
-
-
-void CopyC2PStr( char const * cstr, StringPtr pstr )
-{
- int len;
- for ( len = 0; *cstr && ( len < 255 ); pstr[ ++len ] = *cstr++ );
- pstr[ 0 ] = len;
-}
-
-
-/*
- * file_dirscan() - scan a directory for files.
- */
-
-void file_dirscan( char * dir, scanback func, void * closure )
-{
- PATHNAME f;
- string filename[ 1 ];
- unsigned char fullPath[ 512 ];
-
- FSSpec spec;
- WDPBRec vol;
- Str63 volName;
- CInfoPBRec lastInfo;
- int index = 1;
-
- /* First enter directory itself. */
-
- memset( (char *)&f, '\0', sizeof( f ) );
-
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
-
- if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
-
- /* Special case ":" - enter it */
-
- if ( ( f.f_dir.len == 1 ) && ( f.f_dir.ptr[0] == ':' ) )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
-
- /* Now enter contents of directory */
-
- vol.ioNamePtr = volName;
-
- if ( PBHGetVolSync( &vol ) )
- return;
-
- CopyC2PStr( dir, fullPath );
-
- if ( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
- return;
-
- lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
- lastInfo.dirInfo.ioDrDirID = spec.parID;
- lastInfo.dirInfo.ioNamePtr = spec.name;
- lastInfo.dirInfo.ioFDirIndex = 0;
- lastInfo.dirInfo.ioACUser = 0;
-
- if ( PBGetCatInfoSync( &lastInfo ) )
- return;
-
- if ( !( lastInfo.dirInfo.ioFlAttrib & 0x10 ) )
- return;
-
- /* ioDrDirID must be reset each time. */
- spec.parID = lastInfo.dirInfo.ioDrDirID;
-
- string_new( filename );
- for ( ; ; )
- {
- lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
- lastInfo.dirInfo.ioDrDirID = spec.parID;
- lastInfo.dirInfo.ioNamePtr = fullPath;
- lastInfo.dirInfo.ioFDirIndex = index++;
-
- if ( PBGetCatInfoSync( &lastInfo ) )
- return;
-
- f.f_base.ptr = (char *)fullPath + 1;
- f.f_base.len = *fullPath;
-
- string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
- (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
- }
- string_free( filename );
-}
-
-
-/*
- * file_time() - get timestamp of file, if not done by file_dirscan().
- */
-
-int file_time( char * filename, time_t * time )
-{
- struct stat statbuf;
-
- if ( stat( filename, &statbuf ) < 0 )
- return -1;
-
- *time = statbuf.st_mtime;
-
- return 0;
-}
-
-
-int file_is_file( char * filename )
-{
- struct stat statbuf;
- if ( stat( filename, &statbuf ) < 0 )
- return -1;
- return S_ISREG( statbuf.st_mode ) ? 1 : 0;
-}
-
-int file_mkdir(char *pathname)
-{
- return mkdir(pathname, 0766);
-}
-
-
-/*
- * file_archscan() - scan an archive for files.
- */
-
-void file_archscan( char * archive, scanback func, void * closure )
-{
-}
-
-
-# endif /* macintosh */

Modified: branches/release/tools/build/v2/engine/filent.c
==============================================================================
--- branches/release/tools/build/v2/engine/filent.c (original)
+++ branches/release/tools/build/v2/engine/filent.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,7 +16,7 @@
 # include "filesys.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 
 # ifdef OS_NT
 
@@ -57,20 +57,19 @@
  * file_dirscan() - scan a directory for files
  */
 
-void file_dirscan( char * dir, scanback func, void * closure )
+void file_dirscan( OBJECT * dir, scanback func, void * closure )
 {
     PROFILE_ENTER( FILE_DIRSCAN );
 
     file_info_t * d = 0;
 
- dir = short_path_to_long_path( dir );
-
     /* First enter directory itself */
 
     d = file_query( dir );
 
     if ( !d || !d->is_dir )
     {
+ object_free( dir );
         PROFILE_EXIT( FILE_DIRSCAN );
         return;
     }
@@ -84,11 +83,15 @@
         int ret;
         struct _finddata_t finfo[ 1 ];
         LIST * files = L0;
- int d_length = strlen( d->name );
+ int d_length;
+
+ dir = short_path_to_long_path( dir );
+
+ d_length = strlen( object_str( dir ) );
 
         memset( (char *)&f, '\0', sizeof( f ) );
 
- f.f_dir.ptr = d->name;
+ f.f_dir.ptr = object_str( dir );
         f.f_dir.len = d_length;
 
         /* Now enter contents of directory */
@@ -103,8 +106,8 @@
              * its trailing path separator or otherwise we would not support the
              * Windows root folder specified without its drive letter, i.e. '\'.
              */
- char trailingChar = d->name[ d_length - 1 ] ;
- string_copy( filespec, d->name );
+ char trailingChar = object_str( dir )[ d_length - 1 ] ;
+ string_copy( filespec, object_str( dir ) );
             if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
                 string_append( filespec, "\\" );
             string_append( filespec, "*" );
@@ -117,6 +120,7 @@
         if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
         {
             string_free( filespec );
+ object_free( dir );
             PROFILE_EXIT( FILE_DIRSCAN );
             return;
         }
@@ -132,7 +136,7 @@
             string_truncate( filename, 0 );
             path_build( &f, filename );
 
- files = list_new( files, newstr(filename->value) );
+ files = list_push_back( files, object_new(filename->value) );
             ff = file_info( filename->value );
             ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
             ff->is_dir = finfo->ff_attrib & FA_DIREC ? 1 : 0;
@@ -147,6 +151,7 @@
         if ( ret = ( handle < 0L ) )
         {
             string_free( filespec );
+ object_free( dir );
             PROFILE_EXIT( FILE_DIRSCAN );
             return;
         }
@@ -154,6 +159,7 @@
         string_new( filename );
         while ( !ret )
         {
+ OBJECT * filename_obj;
             file_info_t * ff = 0;
 
             f.f_base.ptr = finfo->name;
@@ -162,8 +168,10 @@
             string_truncate( filename, 0 );
             path_build( &f, filename, 0 );
 
- files = list_new( files, newstr( filename->value ) );
- ff = file_info( filename->value );
+ filename_obj = object_new( filename->value );
+ path_add_key( filename_obj );
+ files = list_push_back( files, filename_obj );
+ ff = file_info( filename_obj );
             ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
             ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
             ff->size = finfo->size;
@@ -176,17 +184,26 @@
         # endif
         string_free( filename );
         string_free( filespec );
+ object_free( dir );
 
         d->files = files;
     }
 
     /* Special case \ or d:\ : enter it */
     {
- unsigned long len = strlen(d->name);
- if ( len == 1 && d->name[0] == '\\' )
- (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
- else if ( len == 3 && d->name[1] == ':' ) {
- (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ unsigned long len = strlen( object_str( d->name ) );
+ if ( len == 1 && object_str( d->name )[0] == '\\' )
+ {
+ OBJECT * dir = short_path_to_long_path( d->name );
+ (*func)( closure, dir, 1 /* stat()'ed */, d->time );
+ object_free( dir );
+ }
+ else if ( len == 3 && object_str( d->name )[1] == ':' )
+ {
+ char buf[4];
+ OBJECT * dir1 = short_path_to_long_path( d->name );
+ OBJECT * dir2;
+ (*func)( closure, dir1, 1 /* stat()'ed */, d->time );
             /* We've just entered 3-letter drive name spelling (with trailing
                slash), into the hash table. Now enter two-letter variant,
                without trailing slash, so that if we try to check whether
@@ -199,34 +216,38 @@
                There will be no trailing slash in $(p), but there will be one
                in $(p2). But, that seems rather fragile.
             */
- d->name[2] = 0;
- (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ strcpy( buf, object_str( dir1 ) );
+ buf[2] = 0;
+ dir2 = object_new( buf );
+ (*func)( closure, dir2, 1 /* stat()'ed */, d->time );
+ object_free( dir2 );
+ object_free( dir1 );
         }
     }
 
     /* Now enter contents of directory */
- if ( d->files )
+ if ( !list_empty( d->files ) )
     {
         LIST * files = d->files;
- while ( files )
+ LISTITER iter = list_begin( files ), end = list_end( files );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- file_info_t * ff = file_info( files->string );
- (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
- files = list_next( files );
+ file_info_t * ff = file_info( list_item( iter ) );
+ (*func)( closure, list_item( iter ), 1 /* stat()'ed */, ff->time );
         }
     }
 
     PROFILE_EXIT( FILE_DIRSCAN );
 }
 
-file_info_t * file_query( char * filename )
+file_info_t * file_query( OBJECT * filename )
 {
     file_info_t * ff = file_info( filename );
     if ( ! ff->time )
     {
         struct stat statbuf;
 
- if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ if ( stat( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
             return 0;
 
         ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -243,8 +264,8 @@
 
 int
 file_time(
- char *filename,
- time_t *time )
+ OBJECT * filename,
+ time_t * time )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
@@ -252,14 +273,14 @@
     return 0;
 }
 
-int file_is_file(char* filename)
+int file_is_file( OBJECT * filename )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
     return ff->is_file;
 }
 
-int file_mkdir(char *pathname)
+int file_mkdir( const char * pathname )
 {
     return _mkdir(pathname);
 }
@@ -290,9 +311,9 @@
 
 void
 file_archscan(
- char *archive,
- scanback func,
- void *closure )
+ const char * archive,
+ scanback func,
+ void * closure )
 {
     struct ar_hdr ar_hdr;
     char *string_table = 0;
@@ -320,9 +341,10 @@
     {
         long lar_date;
         long lar_size;
- char *name = 0;
- char *endname;
- char *c;
+ char * name = 0;
+ char * endname;
+ char * c;
+ OBJECT * member;
 
         sscanf( ar_hdr.ar_date, "%ld", &lar_date );
         sscanf( ar_hdr.ar_size, "%ld", &lar_size );
@@ -375,7 +397,9 @@
         name = c + 1;
 
         sprintf( buf, "%s(%.*s)", archive, endname - name, name );
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
 
         offset += SARHDR + lar_size;
         lseek( fd, offset, 0 );

Deleted: branches/release/tools/build/v2/engine/fileos2.c
==============================================================================
--- branches/release/tools/build/v2/engine/fileos2.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,138 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/* This file is ALSO:
- * Copyright 2001-2004 David Abrahams.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- */
-
-# include "jam.h"
-# include "filesys.h"
-# include "pathsys.h"
-
-/* note that we use "fileunix.c" when compiling with EMX on OS/2 */
-# if defined(OS_OS2) && !defined(__EMX__)
-
-# include <io.h>
-# include <dos.h>
-
-/*
- * fileos2.c - scan directories and archives on NT
- *
- * External routines:
- *
- * file_dirscan() - scan a directory for files
- * file_time() - get timestamp of file, if not done by file_dirscan()
- * file_archscan() - scan an archive for files
- *
- * File_dirscan() and file_archscan() call back a caller provided function
- * for each file found. A flag to this callback function lets file_dirscan()
- * and file_archscan() indicate that a timestamp is being provided with the
- * file. If file_dirscan() or file_archscan() do not provide the file's
- * timestamp, interested parties may later call file_time().
- *
- * 07/10/95 (taylor) Findfirst() returns the first file on NT.
- * 05/03/96 (seiwald) split apart into pathnt.c
- * 09/22/00 (seiwald) handle \ and c:\ specially: don't add extra /
- */
-
-/*
- * file_dirscan() - scan a directory for files
- */
-
-void
-file_dirscan(
- char *dir,
- scanback func,
- void *closure )
-{
- PATHNAME f;
- string filespec[1];
- long handle;
- int ret;
- struct _find_t finfo[1];
-
- /* First enter directory itself */
-
- memset( (char *)&f, '\0', sizeof( f ) );
-
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
-
- dir = *dir ? dir : ".";
-
- /* Special case \ or d:\ : enter it */
- string_copy( filespec, dir );
-
- if ( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
- else if ( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
- else
- string_push_back( filespec, '/' );
-
- string_push_back( filespec, '*' );
-
- /* Now enter contents of directory */
-
- if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", filespec->value );
-
- /* Time info in dos find_t is not very useful. It consists */
- /* of a separate date and time, and putting them together is */
- /* not easy. So we leave that to a later stat() call. */
-
- if ( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
- {
- string filename[1];
- string_new( filename );
- do
- {
- f.f_base.ptr = finfo->name;
- f.f_base.len = strlen( finfo->name );
-
- string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
- (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
- }
- while ( !_dos_findnext( finfo ) );
- string_free( filename );
- }
-}
-
-/*
- * file_time() - get timestamp of file, if not done by file_dirscan()
- */
-
-int
-file_time(
- char *filename,
- time_t *time )
-{
- /* This is called on OS2, not NT. */
- /* NT fills in the time in the dirscan. */
-
- struct stat statbuf;
-
- if ( stat( filename, &statbuf ) < 0 )
- return -1;
-
- *time = statbuf.st_mtime;
-
- return 0;
-}
-
-void
-file_archscan(
- char *archive,
- scanback func,
- void *closure )
-{
-}
-
-# endif /* OS2 && !__EMX__ */
-

Modified: branches/release/tools/build/v2/engine/filesys.c
==============================================================================
--- branches/release/tools/build/v2/engine/filesys.c (original)
+++ branches/release/tools/build/v2/engine/filesys.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1,7 +1,7 @@
 # include "jam.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 # include "filesys.h"
 # include "lists.h"
 
@@ -36,25 +36,30 @@
 static struct hash * filecache_hash = 0;
 static file_info_t filecache_finfo;
 
-file_info_t * file_info(char * filename)
+file_info_t * file_info( OBJECT * filename )
 {
     file_info_t *finfo = &filecache_finfo;
+ int found;
 
     if ( !filecache_hash )
         filecache_hash = hashinit( sizeof( file_info_t ), "file_info" );
 
- finfo->name = filename;
- finfo->is_file = 0;
- finfo->is_dir = 0;
- finfo->size = 0;
- finfo->time = 0;
- finfo->files = 0;
- if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) )
+ filename = path_as_key( filename );
+
+ finfo = (file_info_t *)hash_insert( filecache_hash, filename, &found );
+ if ( !found )
     {
         /* printf( "file_info: %s\n", filename ); */
- finfo->name = newstr( finfo->name );
+ finfo->name = object_copy( filename );
+ finfo->is_file = 0;
+ finfo->is_dir = 0;
+ finfo->size = 0;
+ finfo->time = 0;
+ finfo->files = L0;
     }
 
+ object_free( filename );
+
     return finfo;
 }
 
@@ -62,22 +67,33 @@
 
 static void remove_files_atexit(void)
 {
- /* we do pop front in case this exit function is called
- more than once */
- while ( files_to_remove )
+ LISTITER iter = list_begin( files_to_remove ), end = list_end( files_to_remove );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- remove( files_to_remove->string );
- files_to_remove = list_pop_front( files_to_remove );
+ remove( object_str( list_item( iter ) ) );
     }
+ list_free( files_to_remove );
+ files_to_remove = L0;
+}
+
+static void free_file_info ( void * xfile, void * data )
+{
+ file_info_t * file = (file_info_t *)xfile;
+ object_free( file->name );
+ list_free( file->files );
 }
 
 void file_done()
 {
     remove_files_atexit();
- hashdone( filecache_hash );
+ if ( filecache_hash )
+ {
+ hashenumerate( filecache_hash, free_file_info, (void *)0 );
+ hashdone( filecache_hash );
+ }
 }
 
-void file_remove_atexit( const char * path )
+void file_remove_atexit( OBJECT * path )
 {
- files_to_remove = list_new( files_to_remove, newstr((char*)path) );
+ files_to_remove = list_push_back( files_to_remove, object_copy( path ) );
 }

Modified: branches/release/tools/build/v2/engine/filesys.h
==============================================================================
--- branches/release/tools/build/v2/engine/filesys.h (original)
+++ branches/release/tools/build/v2/engine/filesys.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -20,22 +20,23 @@
 # include "pathsys.h"
 #include "hash.h"
 #include "lists.h"
+#include "object.h"
 
-typedef void (*scanback)( void *closure, char *file, int found, time_t t );
+typedef void (*scanback)( void *closure, OBJECT * file, int found, time_t t );
 
-void file_dirscan( char *dir, scanback func, void *closure );
-void file_archscan( char *arch, scanback func, void *closure );
+void file_dirscan( OBJECT * dir, scanback func, void * closure );
+void file_archscan( const char * arch, scanback func, void * closure );
 
-int file_time( char *filename, time_t *time );
+int file_time( OBJECT * filename, time_t * time );
 
 void file_build1(PATHNAME *f, string* file) ;
-int file_is_file(char* filename);
-int file_mkdir(char *pathname);
+int file_is_file( OBJECT * filename );
+int file_mkdir( const char * pathname );
 
 typedef struct file_info_t file_info_t ;
 struct file_info_t
 {
- char * name;
+ OBJECT * name;
     short is_file;
     short is_dir;
     unsigned long size;
@@ -47,14 +48,14 @@
 /* Creates a pointer to information about file 'filename', creating it as
  * necessary. If created, the structure will be default initialized.
  */
-file_info_t * file_info( char * filename );
+file_info_t * file_info( OBJECT * filename );
 
 /* Returns information about a file, queries the OS if needed. */
-file_info_t * file_query( char * filename );
+file_info_t * file_query( OBJECT * filename );
 
 void file_done();
 
 /* Marks a path/file to be removed when jam exits. */
-void file_remove_atexit( const char * path );
+void file_remove_atexit( OBJECT * path );
 
 #endif

Modified: branches/release/tools/build/v2/engine/fileunix.c
==============================================================================
--- branches/release/tools/build/v2/engine/fileunix.c (original)
+++ branches/release/tools/build/v2/engine/fileunix.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -15,7 +15,7 @@
 # include "filesys.h"
 # include "strings.h"
 # include "pathsys.h"
-# include "newstr.h"
+# include "object.h"
 # include <stdio.h>
 # include <sys/stat.h>
 
@@ -125,7 +125,7 @@
  * file_dirscan() - scan a directory for files.
  */
 
-void file_dirscan( char * dir, scanback func, void * closure )
+void file_dirscan( OBJECT * dir, scanback func, void * closure )
 {
     PROFILE_ENTER( FILE_DIRSCAN );
 
@@ -139,37 +139,39 @@
         return;
     }
 
- if ( ! d->files )
+ if ( list_empty( d->files ) )
     {
         LIST* files = L0;
         PATHNAME f;
         DIR *dd;
         STRUCT_DIRENT *dirent;
         string filename[1];
+ const char * dirstr = object_str( dir );
 
         /* First enter directory itself */
 
         memset( (char *)&f, '\0', sizeof( f ) );
 
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
+ f.f_dir.ptr = dirstr;
+ f.f_dir.len = strlen( dirstr );
 
- dir = *dir ? dir : ".";
+ dirstr = *dirstr ? dirstr : ".";
 
         /* Now enter contents of directory. */
 
- if ( !( dd = opendir( dir ) ) )
+ if ( !( dd = opendir( dirstr ) ) )
         {
             PROFILE_EXIT( FILE_DIRSCAN );
             return;
         }
 
         if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
+ printf( "scan directory %s\n", dirstr );
 
         string_new( filename );
         while ( ( dirent = readdir( dd ) ) )
         {
+ OBJECT * filename_obj;
             # ifdef old_sinix
             /* Broken structure definition on sinix. */
             f.f_base.ptr = dirent->d_name - 2;
@@ -181,8 +183,9 @@
             string_truncate( filename, 0 );
             path_build( &f, filename, 0 );
 
- files = list_new( files, newstr(filename->value) );
- file_query( filename->value );
+ filename_obj = object_new( filename->value );
+ files = list_push_back( files, filename_obj );
+ file_query( filename_obj );
         }
         string_free( filename );
 
@@ -193,18 +196,18 @@
 
     /* Special case / : enter it */
     {
- unsigned long len = strlen(d->name);
- if ( ( len == 1 ) && ( d->name[0] == '/' ) )
+ if ( strcmp( object_str( d->name ), "/" ) == 0 )
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
     }
 
     /* Now enter contents of directory */
- if ( d->files )
+ if ( !list_empty( d->files ) )
     {
         LIST * files = d->files;
- while ( files )
+ LISTITER iter = list_begin( files ), end = list_end( files );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- file_info_t * ff = file_info( files->string );
+ file_info_t * ff = file_info( list_item( iter ) );
             (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
             files = list_next( files );
         }
@@ -214,14 +217,14 @@
 }
 
 
-file_info_t * file_query( char * filename )
+file_info_t * file_query( OBJECT * filename )
 {
     file_info_t * ff = file_info( filename );
     if ( ! ff->time )
     {
         struct stat statbuf;
 
- if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ if ( stat( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
             return 0;
 
         ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -238,8 +241,8 @@
 
 int
 file_time(
- char *filename,
- time_t *time )
+ OBJECT * filename,
+ time_t * time )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
@@ -247,16 +250,16 @@
     return 0;
 }
 
-int file_is_file(char* filename)
+int file_is_file( OBJECT * filename )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
     return ff->is_file;
 }
 
-int file_mkdir(char* pathname)
+int file_mkdir( const char * pathname )
 {
- return mkdir(pathname, 0766);
+ return mkdir( pathname, 0766 );
 }
 
 /*
@@ -270,9 +273,9 @@
 
 void
 file_archscan(
- char *archive,
+ const char * archive,
     scanback func,
- void *closure )
+ void * closure )
 {
 # ifndef NO_AR
     struct ar_hdr ar_hdr;
@@ -312,6 +315,7 @@
         char * c;
         char * src;
         char * dest;
+ OBJECT * member;
 
         strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
 
@@ -356,14 +360,16 @@
 
         sprintf( buf, "%s(%s)", archive, lar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
 
         offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
         lseek( fd, offset, 0 );
     }
 
- if (string_table)
- BJAM_FREE(string_table);
+ if ( string_table )
+ BJAM_FREE( string_table );
 
     close( fd );
 
@@ -396,10 +402,11 @@
 
     while ( ( offset > 0 )
            && ( lseek( fd, offset, 0 ) >= 0 )
- && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
+ && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) ) )
     {
         long lar_date;
         int lar_namlen;
+ OBJECT * member;
 
         sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
         sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
@@ -412,7 +419,9 @@
 
         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
     }
 }
 
@@ -446,6 +455,7 @@
     {
         long lar_date;
         int lar_namlen;
+ OBJECT * member;
 
         sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
         sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
@@ -458,19 +468,21 @@
 
         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
     }
 
 }
 
 #endif /* AR_HSZ_BIG */
 
-void file_archscan(char *archive, scanback func, void *closure)
+void file_archscan( const char * archive, scanback func, void *closure)
 {
     int fd;
     char fl_magic[SAIAMAG];
 
- if (( fd = open(archive, O_RDONLY, 0)) < 0)
+ if (( fd = open( archive, O_RDONLY, 0)) < 0)
         return;
 
     if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
@@ -480,16 +492,16 @@
         return;
     }
 
- if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
+ if ( strncmp( AIAMAG, fl_magic, SAIAMAG ) == 0 )
     {
         /* read small variant */
- file_archscan_small(fd, archive, func, closure);
+ file_archscan_small( fd, archive, func, closure );
     }
 #ifdef AR_HSZ_BIG
- else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
+ else if ( strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) == 0 )
     {
         /* read big variant */
- file_archscan_big(fd, archive, func, closure);
+ file_archscan_big( fd, archive, func, closure );
     }
 #endif
 

Deleted: branches/release/tools/build/v2/engine/filevms.c
==============================================================================
--- branches/release/tools/build/v2/engine/filevms.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,327 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/* This file is ALSO:
- * Copyright 2001-2004 David Abrahams.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- */
-
-# include "jam.h"
-# include "filesys.h"
-# include "pathsys.h"
-
-# ifdef OS_VMS
-
-/*
- * filevms.c - scan directories and libaries on VMS
- *
- * External routines:
- *
- * file_dirscan() - scan a directory for files
- * file_time() - get timestamp of file, if not done by file_dirscan()
- * file_archscan() - scan an archive for files
- *
- * File_dirscan() and file_archscan() call back a caller provided function
- * for each file found. A flag to this callback function lets file_dirscan()
- * and file_archscan() indicate that a timestamp is being provided with the
- * file. If file_dirscan() or file_archscan() do not provide the file's
- * timestamp, interested parties may later call file_time().
- *
- * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
- * 05/03/96 (seiwald) - split into pathvms.c
- */
-
-# include <rms.h>
-# include <iodef.h>
-# include <ssdef.h>
-# include <string.h>
-# include <stdlib.h>
-# include <stdio.h>
-# include <descrip.h>
-
-#include <lbrdef.h>
-#include <credef.h>
-#include <mhddef.h>
-#include <lhidef.h>
-#include <lib$routines.h>
-#include <starlet.h>
-
-/* Supply missing prototypes for lbr$-routines*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-int lbr$set_module(
- void **,
- unsigned long *,
- struct dsc$descriptor_s *,
- unsigned short *,
- void * );
-
-int lbr$open( void **,
- struct dsc$descriptor_s *,
- void *,
- void *,
- void *,
- void *,
- void * );
-
-int lbr$ini_control(
- void **,
- unsigned long *,
- unsigned long *,
- void * );
-
-int lbr$get_index(
- void **,
- unsigned long *,
- int (*func)( struct dsc$descriptor_s *, unsigned long *),
- void * );
-
-int lbr$close(
- void ** );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-static void
-file_cvttime(
- unsigned int *curtime,
- time_t *unixtime )
-{
- static const size_t divisor = 10000000;
- static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
- int delta[2], remainder;
-
- lib$subx( curtime, bastim, delta );
- lib$ediv( &divisor, delta, unixtime, &remainder );
-}
-
-# define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
-
-# define min( a,b ) ((a)<(b)?(a):(b))
-
-void
-file_dirscan(
- char *dir,
- scanback func,
- void *closure )
-{
-
- struct FAB xfab;
- struct NAM xnam;
- struct XABDAT xab;
- char esa[256];
- char filename[256];
- string filename2[1];
- char dirname[256];
- register int status;
- PATHNAME f;
-
- memset( (char *)&f, '\0', sizeof( f ) );
-
- f.f_root.ptr = dir;
- f.f_root.len = strlen( dir );
-
- /* get the input file specification
- */
- xnam = cc$rms_nam;
- xnam.nam$l_esa = esa;
- xnam.nam$b_ess = sizeof( esa ) - 1;
- xnam.nam$l_rsa = filename;
- xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
-
- xab = cc$rms_xabdat; /* initialize extended attributes */
- xab.xab$b_cod = XAB$C_DAT; /* ask for date */
- xab.xab$l_nxt = NULL; /* terminate XAB chain */
-
- xfab = cc$rms_fab;
- xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
- xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
- xfab.fab$l_fop = FAB$M_NAM;
- xfab.fab$l_fna = dir; /* address of file name */
- xfab.fab$b_fns = strlen( dir ); /* length of file name */
- xfab.fab$l_nam = &xnam; /* address of NAB block */
- xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
-
-
- status = sys$parse( &xfab );
-
- if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
-
- if ( !( status & 1 ) )
- return;
-
-
-
- /* Add bogus directory for [000000] */
-
- if ( !strcmp( dir, "[000000]" ) )
- {
- (*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
- }
-
- /* Add bogus directory for [] */
-
- if ( !strcmp( dir, "[]" ) )
- {
- (*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
- (*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
- }
-
- string_new( filename2 );
- while ( (status = sys$search( &xfab )) & 1 )
- {
- char *s;
- time_t time;
-
- /* "I think that might work" - eml */
-
- sys$open( &xfab );
- sys$close( &xfab );
-
- file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
-
- filename[xnam.nam$b_rsl] = '\0';
-
- /* What we do with the name depends on the suffix: */
- /* .dir is a directory */
- /* .xxx is a file with a suffix */
- /* . is no suffix at all */
-
- if ( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
- {
- /* directory */
- sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
- f.f_dir.ptr = dirname;
- f.f_dir.len = strlen( dirname );
- f.f_base.ptr = 0;
- f.f_base.len = 0;
- f.f_suffix.ptr = 0;
- f.f_suffix.len = 0;
- }
- else
- {
- /* normal file with a suffix */
- f.f_dir.ptr = 0;
- f.f_dir.len = 0;
- f.f_base.ptr = xnam.nam$l_name;
- f.f_base.len = xnam.nam$b_name;
- f.f_suffix.ptr = xnam.nam$l_type;
- f.f_suffix.len = xnam.nam$b_type;
- }
-
- string_truncate( filename2, 0 );
- path_build( &f, filename2, 0 );
-
- /*
- if ( DEBUG_SEARCH )
- printf("root '%s' base %.*s suf %.*s = %s\n",
- dir,
- xnam.nam$b_name, xnam.nam$l_name,
- xnam.nam$b_type, xnam.nam$l_type,
- filename2 );
- */
-
- (*func)( closure, filename2->value, 1 /* time valid */, time );
- }
- string_free( filename2 );
-}
-
-int
-file_time(
- char *filename,
- time_t *time )
-{
- /* This should never be called, as all files are */
- /* timestampped in file_dirscan() and file_archscan() */
- return -1;
-}
-
-static char *VMS_archive = 0;
-static scanback VMS_func;
-static void *VMS_closure;
-static void *context;
-
-static int
-file_archmember(
- struct dsc$descriptor_s *module,
- unsigned long *rfa )
-{
- static struct dsc$descriptor_s bufdsc =
- {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
-
- struct mhddef *mhd;
- char filename[128];
- char buf[ MAXJPATH ];
-
- int status;
- time_t library_date;
-
- register int i;
- register char *p;
-
- bufdsc.dsc$a_pointer = filename;
- bufdsc.dsc$w_length = sizeof( filename );
- status = lbr$set_module( &context, rfa, &bufdsc,
- &bufdsc.dsc$w_length, NULL );
-
- if ( !(status & 1) )
- return ( 1 );
-
- mhd = (struct mhddef *)filename;
-
- file_cvttime( &mhd->mhd$l_datim, &library_date );
-
- for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; ++i, ++p )
- filename[ i ] = *p;
-
- filename[ i ] = '\0';
-
- sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
-
- (*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
-
- return ( 1 );
-}
-
-
-void file_archscan( char * archive, scanback func, void * closure )
-{
- static struct dsc$descriptor_s library =
- {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
-
- unsigned long lfunc = LBR$C_READ;
- unsigned long typ = LBR$C_TYP_UNK;
- unsigned long index = 1;
-
- register int status;
-
- VMS_archive = archive;
- VMS_func = func;
- VMS_closure = closure;
-
- status = lbr$ini_control( &context, &lfunc, &typ, NULL );
- if ( !( status & 1 ) )
- return;
-
- library.dsc$a_pointer = archive;
- library.dsc$w_length = strlen( archive );
-
- status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
- if ( !( status & 1 ) )
- return;
-
- (void) lbr$get_index( &context, &index, file_archmember, NULL );
-
- (void) lbr$close( &context );
-}
-
-# endif /* VMS */

Modified: branches/release/tools/build/v2/engine/frames.c
==============================================================================
--- branches/release/tools/build/v2/engine/frames.c (original)
+++ branches/release/tools/build/v2/engine/frames.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -13,7 +13,8 @@
     lol_init(frame->args);
     frame->module = root_module();
     frame->rulename = "module scope";
- frame->procedure = 0;
+ frame->file = 0;
+ frame->line = -1;
 }
 
 void frame_free( FRAME* frame )

Modified: branches/release/tools/build/v2/engine/frames.h
==============================================================================
--- branches/release/tools/build/v2/engine/frames.h (original)
+++ branches/release/tools/build/v2/engine/frames.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -7,6 +7,7 @@
 #define FRAMES_DWA20011021_H
 
 #include "lists.h"
+#include "object.h"
 #include "modules.h"
 
 typedef struct _PARSE PARSE;
@@ -14,13 +15,14 @@
 
 struct frame
 {
- FRAME * prev;
+ FRAME * prev;
     /* The nearest enclosing frame for which module->user_module is true. */
- FRAME * prev_user;
- LOL args[ 1 ];
- module_t * module;
- PARSE * procedure;
- char * rulename;
+ FRAME * prev_user;
+ LOL args[ 1 ];
+ module_t * module;
+ OBJECT * file;
+ int line;
+ const char * rulename;
 };
 
 

Copied: branches/release/tools/build/v2/engine/function.c (from r75738, /trunk/tools/build/v2/engine/function.c)
==============================================================================
--- /trunk/tools/build/v2/engine/function.c (original)
+++ branches/release/tools/build/v2/engine/function.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,8 +16,11 @@
 #include "compile.h"
 #include "search.h"
 #include "class.h"
+#include "pathsys.h"
+#include "filesys.h"
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <assert.h>
 
 # ifdef OS_CYGWIN
@@ -25,10 +28,15 @@
 # include <windows.h>
 # endif
 
+int glob( const char * s, const char * c );
+void backtrace( FRAME * frame );
+void backtrace_line( FRAME * frame );
+
 #define INSTR_PUSH_EMPTY 0
 #define INSTR_PUSH_CONSTANT 1
 #define INSTR_PUSH_ARG 2
 #define INSTR_PUSH_VAR 3
+#define INSTR_PUSH_VAR_FIXED 57
 #define INSTR_PUSH_GROUP 4
 #define INSTR_PUSH_RESULT 5
 #define INSTR_PUSH_APPEND 6
@@ -49,7 +57,8 @@
 
 #define INSTR_JUMP_NOT_GLOB 19
 
-#define INSTR_TRY_POP_FRONT 20
+#define INSTR_FOR_INIT 56
+#define INSTR_FOR_LOOP 20
 
 #define INSTR_SET_RESULT 21
 #define INSTR_RETURN 22
@@ -61,6 +70,12 @@
 #define INSTR_APPEND 27
 #define INSTR_DEFAULT 28
 
+#define INSTR_PUSH_LOCAL_FIXED 58
+#define INSTR_POP_LOCAL_FIXED 59
+#define INSTR_SET_FIXED 60
+#define INSTR_APPEND_FIXED 61
+#define INSTR_DEFAULT_FIXED 62
+
 #define INSTR_PUSH_LOCAL_GROUP 29
 #define INSTR_POP_LOCAL_GROUP 30
 #define INSTR_SET_GROUP 31
@@ -89,6 +104,11 @@
 #define INSTR_PUSH_MODULE 50
 #define INSTR_POP_MODULE 51
 #define INSTR_CLASS 52
+#define INSTR_BIND_MODULE_VARIABLES 63
+
+#define INSTR_APPEND_STRINGS 53
+#define INSTR_WRITE_FILE 54
+#define INSTR_OUTPUT_STRINGS 55
 
 typedef struct instruction
 {
@@ -100,41 +120,56 @@
 {
     OBJECT * name;
     FUNCTION * code;
- int arguments;
     int local;
 } SUBFUNCTION;
 
 typedef struct _subaction
 {
- OBJECT * name;
- OBJECT * command;
- int flags;
+ OBJECT * name;
+ FUNCTION * command;
+ int flags;
 } SUBACTION;
 
 #define FUNCTION_BUILTIN 0
 #define FUNCTION_JAM 1
 
+struct argument {
+ int flags;
+#define ARG_ONE 0
+#define ARG_OPTIONAL 1
+#define ARG_PLUS 2
+#define ARG_STAR 3
+#define ARG_VARIADIC 4
+ OBJECT * type_name;
+ OBJECT * arg_name;
+ int index;
+};
+
+struct arg_list {
+ int size;
+ struct argument * args;
+};
+
 struct _function
 {
     int type;
     int reference_count;
     OBJECT * rulename;
+ struct arg_list * formal_arguments;
+ int num_formal_arguments;
 };
 
 typedef struct _builtin_function
 {
- int type;
- int reference_count;
- OBJECT * rulename;
+ FUNCTION base;
     LIST * ( * func )( FRAME *, int flags );
     int flags;
 } BUILTIN_FUNCTION;
 
 typedef struct _jam_function
 {
- int type;
- int reference_count;
- OBJECT * rulename;
+ FUNCTION base;
+ int code_size;
     instruction * code;
     int num_constants;
     OBJECT * * constants;
@@ -142,11 +177,27 @@
     SUBFUNCTION * functions;
     int num_subactions;
     SUBACTION * actions;
+ FUNCTION * generic;
     OBJECT * file;
     int line;
 } JAM_FUNCTION;
 
 
+#ifdef HAVE_PYTHON
+
+#define FUNCTION_PYTHON 2
+
+typedef struct _python_function
+{
+ FUNCTION base;
+ PyObject * python_function;
+} PYTHON_FUNCTION;
+
+static LIST * call_python_function( PYTHON_FUNCTION * function, FRAME * frame );
+
+#endif
+
+
 struct _stack
 {
     void * data;
@@ -166,51 +217,66 @@
     return &result;
 }
 
+static void check_alignment( STACK * s )
+{
+ assert( (unsigned long)s->data % sizeof( LIST * ) == 0 );
+}
+
+void * stack_allocate( STACK * s, int size )
+{
+ check_alignment( s );
+ s->data = (char *)s->data - size;
+ check_alignment( s );
+ return s->data;
+}
+
+void stack_deallocate( STACK * s, int size )
+{
+ check_alignment( s );
+ s->data = (char *)s->data + size;
+ check_alignment( s );
+}
+
 void stack_push( STACK * s, LIST * l )
 {
- *--(*(LIST * * *)&s->data) = l;
+ *(LIST * *)stack_allocate( s, sizeof( LIST * ) ) = l;
 }
 
 LIST * stack_pop( STACK * s )
 {
- return *(*(LIST * * *)&s->data)++;
+ LIST * result = *(LIST * *)s->data;
+ stack_deallocate( s, sizeof( LIST * ) );
+ return result;
 }
 
 LIST * stack_top(STACK * s)
 {
+ check_alignment( s );
     return *(LIST * *)s->data;
 }
 
 LIST * stack_at( STACK * s, int n )
 {
+ check_alignment( s );
     return *((LIST * *)s->data + n);
 }
 
 void stack_set( STACK * s, int n, LIST * value )
 {
+ check_alignment( s );
     *((LIST * *)s->data + n) = value;
 }
 
 void * stack_get( STACK * s )
 {
+ check_alignment( s );
     return (LIST * *)s->data;
 }
 
-void * stack_allocate( STACK * s, int size )
-{
- *(char * *)&s->data -= size;
- return s->data;
-}
-
-void stack_deallocate( STACK * s, int size )
-{
- *(char * *)&s->data += size;
-}
-
 LIST * frame_get_local( FRAME * frame, int idx )
 {
     /* The only local variables are the arguments */
- return list_copy( L0, lol_get( frame->args, idx ) );
+ return list_copy( lol_get( frame->args, idx ) );
 }
 
 static OBJECT * function_get_constant( JAM_FUNCTION * function, int idx )
@@ -220,50 +286,33 @@
 
 static LIST * function_get_variable( JAM_FUNCTION * function, FRAME * frame, int idx )
 {
- return list_copy( L0, var_get( function->constants[idx] ) );
+ return list_copy( var_get( frame->module, function->constants[idx] ) );
 }
 
 static void function_set_variable( JAM_FUNCTION * function, FRAME * frame, int idx, LIST * value )
 {
- var_set( function->constants[idx], value, VAR_SET );
+ var_set( frame->module, function->constants[idx], value, VAR_SET );
 }
 
 static LIST * function_swap_variable( JAM_FUNCTION * function, FRAME * frame, int idx, LIST * value )
 {
- return var_swap( function->constants[idx], value );
+ return var_swap( frame->module, function->constants[idx], value );
 }
 
 static void function_append_variable( JAM_FUNCTION * function, FRAME * frame, int idx, LIST * value )
 {
- var_set( function->constants[idx], value, VAR_APPEND );
+ var_set( frame->module, function->constants[idx], value, VAR_APPEND );
 }
 
 static void function_default_variable( JAM_FUNCTION * function, FRAME * frame, int idx, LIST * value )
 {
- var_set( function->constants[idx], value, VAR_DEFAULT );
+ var_set( frame->module, function->constants[idx], value, VAR_DEFAULT );
 }
 
 static void function_set_rule( JAM_FUNCTION * function, FRAME * frame, STACK * s, int idx )
 {
     SUBFUNCTION * sub = function->functions + idx;
- argument_list * args = 0;
-
- if ( sub->arguments )
- {
- int i;
- args = args_new();
- for ( i = sub->arguments; i > 0; --i )
- {
- lol_add( args->data, stack_at( s, i - 1 ) );
- }
-
- for ( i = 0; i < sub->arguments; ++i )
- {
- stack_pop( s );
- }
- }
-
- new_rule_body( frame->module, sub->name, args, sub->code, !sub->local );
+ new_rule_body( frame->module, sub->name, sub->code, !sub->local );
 }
 
 static void function_set_actions( JAM_FUNCTION * function, FRAME * frame, STACK * s, int idx )
@@ -328,32 +377,32 @@
     int idx = get_argument_index( object_str( name ) );
     if( idx != -1 )
     {
- return list_copy( L0, lol_get( frame->args, idx ) );
+ return list_copy( lol_get( frame->args, idx ) );
     }
     else
     {
- return list_copy( L0, var_get( name ) );
+ return list_copy( var_get( frame->module, name ) );
     }
 }
 
 static void function_set_named_variable( JAM_FUNCTION * function, FRAME * frame, OBJECT * name, LIST * value)
 {
- var_set( name, value, VAR_SET );
+ var_set( frame->module, name, value, VAR_SET );
 }
 
 static LIST * function_swap_named_variable( JAM_FUNCTION * function, FRAME * frame, OBJECT * name, LIST * value )
 {
- return var_swap( name, value );
+ return var_swap( frame->module, name, value );
 }
 
 static void function_append_named_variable( JAM_FUNCTION * function, FRAME * frame, OBJECT * name, LIST * value)
 {
- var_set( name, value, VAR_APPEND );
+ var_set( frame->module, name, value, VAR_APPEND );
 }
 
 static void function_default_named_variable( JAM_FUNCTION * function, FRAME * frame, OBJECT * name, LIST * value )
 {
- var_set( name, value, VAR_DEFAULT );
+ var_set( frame->module, name, value, VAR_DEFAULT );
 }
 
 static LIST * function_call_rule( JAM_FUNCTION * function, FRAME * frame, STACK * s, int n_args, const char * unexpanded, OBJECT * file, int line )
@@ -363,19 +412,28 @@
     LIST * first = stack_pop( s );
     LIST * result = L0;
     OBJECT * rulename;
+ LIST * trailing;
 
     frame->file = file;
     frame->line = line;
     
- if ( !first )
+ if ( list_empty( first ) )
     {
         backtrace_line( frame );
         printf( "warning: rulename %s expands to empty string\n", unexpanded );
         backtrace( frame );
+
+ list_free( first );
+
+ for( i = 0; i < n_args; ++i )
+ {
+ list_free( stack_pop( s ) );
+ }
+
         return result;
     }
 
- rulename = object_copy( first->value );
+ rulename = object_copy( list_front( first ) );
 
     frame_init( inner );
 
@@ -393,14 +451,18 @@
         stack_pop( s );
     }
 
- if ( inner->args->count == 0 )
+ trailing = list_pop_front( first );
+ if ( trailing )
     {
- lol_add( inner->args, list_pop_front( first ) );
- }
- else
- {
- LIST * * l = &inner->args->list[0];
- *l = list_append( list_pop_front( first ), *l );
+ if ( inner->args->count == 0 )
+ {
+ lol_add( inner->args, trailing );
+ }
+ else
+ {
+ LIST * * l = &inner->args->list[0];
+ *l = list_append( trailing, *l );
+ }
     }
 
     result = evaluate_rule( rulename, inner );
@@ -430,8 +492,8 @@
     PATHPART join; /* :J -- join list with char */
 } VAR_EDITS;
 
-static LIST * apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int n, LIST * iter, LIST * end );
-static void get_iters( subscript_t subscript, LIST * * first, LIST * * last, int length );
+static LIST * apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int n, LISTITER iter, LISTITER end );
+static void get_iters( subscript_t subscript, LISTITER * first, LISTITER * last, int length );
 static void var_edit_file( const char * in, string * out, VAR_EDITS * edits );
 static void var_edit_shift( string * out, size_t pos, VAR_EDITS * edits );
 static int var_edit_parse( const char * mods, VAR_EDITS * edits, int havezeroed );
@@ -494,7 +556,7 @@
             case 'T': edits->to_slashes = 1; continue;
             case 'W': edits->to_windows = 1; continue;
             default:
- break; /* Should complain, but so what... */
+ continue; /* Should complain, but so what... */
         }
 
     fileval:
@@ -626,10 +688,10 @@
     if ( total != 0 )
     {
         VAR_EDITS * out = stack_allocate( s, total * sizeof(VAR_EDITS) );
- LIST * * iter = stack_allocate( s, n * sizeof(LIST *) );
+ LISTITER * iter = stack_allocate( s, n * sizeof(LIST *) );
         for (i = 0; i < n; ++i )
         {
- iter[i] = args[i];
+ iter[i] = list_begin( args[i] );
         }
         i = 0;
         {
@@ -639,19 +701,19 @@
             havezeroed = 0;
             for (i = 0; i < n; ++i )
             {
- havezeroed = var_edit_parse( object_str( iter[i]->value ), out, havezeroed );
+ havezeroed = var_edit_parse( object_str( list_item( iter[i] ) ), out, havezeroed );
             }
             ++out;
             while ( --i >= 0 )
             {
- if ( iter[i]->next )
+ if ( list_next( iter[i] ) != list_end( args[i] ) )
                 {
- iter[i] = iter[i]->next;
+ iter[i] = list_next( iter[i] );
                     goto loop;
                 }
                 else
                 {
- iter[i] = args[i];
+ iter[i] = list_begin( args[i] );
                 }
             }
         }
@@ -667,7 +729,7 @@
     VAR_EDITS * edits = (VAR_EDITS *)( (LIST * *)stack_get( s ) + 1 );
     string buf[1];
     string_new( buf );
- result = apply_modifiers_impl( result, buf, edits, n, value, L0 );
+ result = apply_modifiers_impl( result, buf, edits, n, list_begin( value ), list_end( value ) );
     string_free( buf );
     return result;
 }
@@ -740,16 +802,17 @@
     LIST * result = L0;
     int length = list_length( value );
     string buf[1];
+ LISTITER indices_iter = list_begin( indices ), indices_end = list_end( indices );
     string_new( buf );
- for ( ; indices; indices = list_next( indices ) )
+ for ( ; indices_iter != indices_end; indices_iter = list_next( indices_iter ) )
     {
- LIST * iter = value;
- LIST * end;
- subscript_t subscript = parse_subscript( object_str( indices->value ) );
+ LISTITER iter = list_begin( value );
+ LISTITER end = list_end( value );
+ subscript_t subscript = parse_subscript( object_str( list_item( indices_iter ) ) );
         get_iters( subscript, &iter, &end, length );
         for ( ; iter != end; iter = list_next( iter ) )
         {
- result = list_new( result, object_copy( iter->value ) );
+ result = list_push_back( result, object_copy( list_item( iter ) ) );
         }
     }
     string_free( buf );
@@ -761,12 +824,12 @@
  * The results are written to *first and *last.
  */
 
-static void get_iters( subscript_t subscript, LIST * * first, LIST * * last, int length )
+static void get_iters( subscript_t subscript, LISTITER * first, LISTITER * last, int length )
 {
     int start;
     int size;
- LIST * iter;
- LIST * end;
+ LISTITER iter;
+ LISTITER end;
     {
 
         if ( subscript.sub1 < 0 )
@@ -822,41 +885,41 @@
             /** FIXME: is empty.ptr always null-terminated? */
             var_edit_file( edits[i].empty.ptr, buf, edits + i );
             var_edit_shift( buf, 0, edits + i );
- result = list_new( result, object_new( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
             string_truncate( buf, 0 );
         }
     }
     return result;
 }
 
-static LIST * apply_modifiers_non_empty( LIST * result, string * buf, VAR_EDITS * edits, int n, LIST * begin, LIST * end )
+static LIST * apply_modifiers_non_empty( LIST * result, string * buf, VAR_EDITS * edits, int n, LISTITER begin, LISTITER end )
 {
     int i;
- LIST * iter;
+ LISTITER iter;
     for ( i = 0; i < n; ++i )
     {
         if ( edits[i].join.ptr )
         {
- var_edit_file( object_str( begin->value ), buf, edits + i );
+ var_edit_file( object_str( list_item( begin ) ), buf, edits + i );
             var_edit_shift( buf, 0, edits + i );
             for ( iter = list_next( begin ); iter != end; iter = list_next( iter ) )
             {
                 size_t size;
                 string_append( buf, edits[i].join.ptr );
                 size = buf->size;
- var_edit_file( object_str( iter->value ), buf, edits + i );
+ var_edit_file( object_str( list_item( iter ) ), buf, edits + i );
                 var_edit_shift( buf, size, edits + i );
             }
- result = list_new( result, object_new( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
             string_truncate( buf, 0 );
         }
         else
         {
- for ( iter = begin; iter != end; iter = iter->next )
+ for ( iter = begin; iter != end; iter = list_next( iter ) )
             {
- var_edit_file( object_str( iter->value ), buf, edits + i );
+ var_edit_file( object_str( list_item( iter ) ), buf, edits + i );
                 var_edit_shift( buf, 0, edits + i );
- result = list_new( result, object_new( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
                 string_truncate( buf, 0 );
             }
         }
@@ -864,7 +927,7 @@
     return result;
 }
 
-static LIST * apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int n, LIST * iter, LIST * end )
+static LIST * apply_modifiers_impl( LIST * result, string * buf, VAR_EDITS * edits, int n, LISTITER iter, LISTITER end )
 {
     if ( iter != end )
     {
@@ -884,12 +947,13 @@
     VAR_EDITS * edits = (VAR_EDITS *)((LIST * *)stack_get( s ) + 2);
     int length = list_length( value );
     string buf[1];
+ LISTITER indices_iter = list_begin( indices ), indices_end = list_end( indices );
     string_new( buf );
- for ( ; indices; indices = list_next( indices ) )
+ for ( ; indices_iter != indices_end; indices_iter = list_next( indices_iter ) )
     {
- LIST * iter = value;
- LIST * end;
- subscript_t sub = parse_subscript( object_str( indices->value ) );
+ LISTITER iter = list_begin( value );
+ LISTITER end = list_end( value );
+ subscript_t sub = parse_subscript( object_str( list_item( indices_iter ) ) );
         get_iters( sub, &iter, &end, length );
         result = apply_modifiers_impl( result, buf, edits, n, iter, end );
     }
@@ -899,7 +963,7 @@
 
 typedef struct expansion_item
 {
- LIST * elem;
+ LISTITER elem;
     LIST * saved;
     int size;
 } expansion_item;
@@ -914,11 +978,11 @@
     for ( i = 0; i < length; ++i )
     {
         int max = 0;
- LIST * l;
- if ( !elem[i].elem ) return result;
- for ( l = elem[i].elem; l; l = l->next )
+ LISTITER iter = elem[i].elem, end = list_end( elem[i].saved );
+ if ( iter == end ) return result;
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- int len = strlen( object_str( l->value ) );
+ int len = strlen( object_str( list_item( iter ) ) );
             if ( len > max ) max = len;
         }
         size += max;
@@ -931,20 +995,20 @@
         for ( ; i < length; ++i )
         {
             elem[i].size = buf->size;
- string_append( buf, object_str( elem[i].elem->value ) );
+ string_append( buf, object_str( list_item( elem[i].elem ) ) );
         }
- result = list_new( result, object_new( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
         while ( --i >= 0 )
         {
- if(elem[i].elem->next)
+ if( list_next( elem[i].elem ) != list_end( elem[i].saved ) )
             {
- elem[i].elem = elem[i].elem->next;
+ elem[i].elem = list_next( elem[i].elem );
                 string_truncate( buf, elem[i].size );
                 goto loop;
             }
             else
             {
- elem[i].elem = elem[i].saved;
+ elem[i].elem = list_begin( elem[i].saved );
             }
         }
     }
@@ -952,6 +1016,26 @@
     return result;
 }
 
+static void combine_strings( STACK * s, int n, string * out )
+{
+ int i;
+ for ( i = 0; i < n; ++i )
+ {
+ LIST * values = stack_pop( s );
+ LISTITER iter = list_begin( values ), end = list_end( values );
+ if ( iter != end )
+ {
+ string_append( out, object_str( list_item( iter ) ) );
+ for ( iter = list_next( iter ); iter != end; iter = list_next( iter ) )
+ {
+ string_push_back( out, ' ' );
+ string_append( out, object_str( list_item( iter ) ) );
+ }
+ list_free( values );
+ }
+ }
+}
+
 struct dynamic_array
 {
     int size;
@@ -1008,7 +1092,8 @@
 {
     OBJECT * name;
     PARSE * parse;
- int arguments;
+ int num_arguments;
+ struct arg_list * arguments;
     int local;
 };
 
@@ -1107,23 +1192,24 @@
     return c->constants->size - 1;
 }
 
-static int compile_emit_rule( compiler * c, OBJECT * name, PARSE * parse, int arguments, int local )
+static int compile_emit_rule( compiler * c, OBJECT * name, PARSE * parse, int num_arguments, struct arg_list * arguments, int local )
 {
     struct stored_rule rule;
     rule.name = object_copy( name );
     rule.parse = parse;
+ rule.num_arguments = num_arguments;
     rule.arguments = arguments;
     rule.local = local;
     dynamic_array_push( c->rules, rule );
     return (int)( c->rules->size - 1 );
 }
 
-static int compile_emit_actions( compiler * c, OBJECT * name, OBJECT * command, int flags )
+static int compile_emit_actions( compiler * c, PARSE * parse )
 {
     SUBACTION a;
- a.name = object_copy( name );
- a.command = object_copy( command );
- a.flags = flags;
+ a.name = object_copy( parse->string );
+ a.command = function_compile_actions( object_str( parse->string1 ), parse->file, parse->line );
+ a.flags = parse->num;
     dynamic_array_push( c->actions, a );
     return (int)( c->actions->size - 1 );
 }
@@ -1132,11 +1218,14 @@
 {
     JAM_FUNCTION * result = BJAM_MALLOC( sizeof(JAM_FUNCTION) );
     int i;
- result->type = FUNCTION_JAM;
- result->reference_count = 1;
+ result->base.type = FUNCTION_JAM;
+ result->base.reference_count = 1;
+ result->base.formal_arguments = 0;
+ result->base.num_formal_arguments = 0;
 
- result->rulename = 0;
+ result->base.rulename = 0;
 
+ result->code_size = c->code->size;
     result->code = BJAM_MALLOC( c->code->size * sizeof(instruction) );
     memcpy( result->code, c->code->data, c->code->size * sizeof(instruction) );
 
@@ -1151,7 +1240,8 @@
         struct stored_rule * rule = &dynamic_array_at( struct stored_rule, c->rules, i );
         result->functions[i].name = rule->name;
         result->functions[i].code = function_compile( rule->parse );
- result->functions[i].arguments = rule->arguments;
+ result->functions[i].code->num_formal_arguments = rule->num_arguments;
+ result->functions[i].code->formal_arguments = rule->arguments;
         result->functions[i].local = rule->local;
     }
 
@@ -1159,6 +1249,8 @@
     memcpy( result->actions, c->actions->data, c->actions->size * sizeof(SUBACTION) );
     result->num_subactions = c->actions->size;
 
+ result->generic = 0;
+
     result->file = 0;
     result->line = -1;
 
@@ -1174,8 +1266,14 @@
     struct dynamic_array elems[1];
 } VAR_PARSE_GROUP;
 
+typedef struct VAR_PARSE_ACTIONS
+{
+ struct dynamic_array elems[1];
+} VAR_PARSE_ACTIONS;
+
 #define VAR_PARSE_TYPE_VAR 0
 #define VAR_PARSE_TYPE_STRING 1
+#define VAR_PARSE_TYPE_FILE 2
 
 typedef struct _var_parse
 {
@@ -1184,7 +1282,7 @@
 
 typedef struct
 {
- int type;
+ VAR_PARSE base;
     VAR_PARSE_GROUP * name;
     VAR_PARSE_GROUP * subscript;
     struct dynamic_array modifiers[1];
@@ -1192,10 +1290,17 @@
 
 typedef struct
 {
- int type;
+ VAR_PARSE base;
     OBJECT * s;
 } VAR_PARSE_STRING;
 
+typedef struct
+{
+ VAR_PARSE base;
+ struct dynamic_array filename[1];
+ struct dynamic_array contents[1];
+} VAR_PARSE_FILE;
+
 static void var_parse_free( VAR_PARSE * );
 
 /*
@@ -1231,7 +1336,7 @@
     {
         string buf[1];
         VAR_PARSE_STRING * value = (VAR_PARSE_STRING *)BJAM_MALLOC( sizeof(VAR_PARSE_STRING) );
- value->type = VAR_PARSE_TYPE_STRING;
+ value->base.type = VAR_PARSE_TYPE_STRING;
         string_new( buf );
         string_append_range( buf, start, end );
         value->s = object_new( buf->value );
@@ -1240,6 +1345,41 @@
     }
 }
 
+VAR_PARSE_STRING * var_parse_group_as_literal( VAR_PARSE_GROUP * group )
+{
+ if ( group->elems->size == 1 )
+ {
+ VAR_PARSE * result = dynamic_array_at( VAR_PARSE *, group->elems, 0 );
+ if ( result->type == VAR_PARSE_TYPE_STRING )
+ {
+ return (VAR_PARSE_STRING *)result;
+ }
+ }
+ return 0;
+}
+
+/*
+ * VAR_PARSE_ACTIONS
+ */
+
+static VAR_PARSE_ACTIONS * var_parse_actions_new()
+{
+ VAR_PARSE_ACTIONS * result = (VAR_PARSE_ACTIONS *)BJAM_MALLOC( sizeof(VAR_PARSE_ACTIONS) );
+ dynamic_array_init( result->elems );
+ return result;
+}
+
+static void var_parse_actions_free( VAR_PARSE_ACTIONS * actions )
+{
+ int i;
+ for ( i = 0; i < actions->elems->size; ++i )
+ {
+ var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, actions->elems, i ) );
+ }
+ dynamic_array_free( actions->elems );
+ BJAM_FREE( actions );
+}
+
 /*
  * VAR_PARSE_VAR
  */
@@ -1247,7 +1387,7 @@
 static VAR_PARSE_VAR * var_parse_var_new()
 {
     VAR_PARSE_VAR * result = BJAM_MALLOC( sizeof( VAR_PARSE_VAR ) );
- result->type = VAR_PARSE_TYPE_VAR;
+ result->base.type = VAR_PARSE_TYPE_VAR;
     result->name = var_parse_group_new();
     result->subscript = 0;
     dynamic_array_init( result->modifiers );
@@ -1284,6 +1424,31 @@
 }
 
 /*
+ * VAR_PARSE_FILE
+ */
+
+static VAR_PARSE_FILE * var_parse_file_new( void )
+{
+ VAR_PARSE_FILE * result = (VAR_PARSE_FILE *)BJAM_MALLOC( sizeof( VAR_PARSE_FILE ) );
+ result->base.type = VAR_PARSE_TYPE_FILE;
+ dynamic_array_init( result->filename );
+ dynamic_array_init( result->contents );
+ return result;
+}
+
+static void var_parse_file_free( VAR_PARSE_FILE * file )
+{
+ int i;
+ for( i = 0; i < file->filename->size; ++i )
+ var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, file->filename, i ) );
+ dynamic_array_free( file->filename );
+ for( i = 0; i < file->contents->size; ++i )
+ var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, file->contents, i ) );
+ dynamic_array_free( file->contents );
+ BJAM_FREE( file );
+}
+
+/*
  * VAR_PARSE
  */
 
@@ -1297,6 +1462,10 @@
     {
         var_parse_string_free( (VAR_PARSE_STRING *)parse );
     }
+ else if ( parse->type == VAR_PARSE_TYPE_FILE )
+ {
+ var_parse_file_free( (VAR_PARSE_FILE *)parse );
+ }
     else
     {
         assert(!"Invalid type");
@@ -1395,6 +1564,21 @@
     compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c, parse->s ) );
 }
 
+static void var_parse_file_compile( const VAR_PARSE_FILE * parse, compiler * c )
+{
+ int i;
+ for ( i = 0; i < parse->filename->size; ++i )
+ {
+ var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, parse->filename, parse->filename->size - i - 1 ), c );
+ }
+ compile_emit( c, INSTR_APPEND_STRINGS, parse->filename->size );
+ for ( i = 0; i < parse->contents->size; ++i )
+ {
+ var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, parse->contents, parse->contents->size - i - 1 ), c );
+ }
+ compile_emit( c, INSTR_WRITE_FILE, parse->contents->size );
+}
+
 static void var_parse_compile( const VAR_PARSE * parse, compiler * c )
 {
     if( parse->type == VAR_PARSE_TYPE_VAR )
@@ -1405,6 +1589,14 @@
     {
         var_parse_string_compile( (const VAR_PARSE_STRING *)parse, c );
     }
+ else if( parse->type == VAR_PARSE_TYPE_FILE )
+ {
+ var_parse_file_compile( (const VAR_PARSE_FILE *)parse, c );
+ }
+ else
+ {
+ assert( !"Unknown var parse type." );
+ }
 }
 
 static void var_parse_group_compile( const VAR_PARSE_GROUP * parse, compiler * c )
@@ -1427,13 +1619,25 @@
     }
 }
 
+static void var_parse_actions_compile( const VAR_PARSE_ACTIONS * actions, compiler * c )
+{
+ int i;
+ for ( i = 0; i < actions->elems->size; ++i )
+ {
+ var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, actions->elems, actions->elems->size - i - 1 ), c );
+ }
+ compile_emit( c, INSTR_OUTPUT_STRINGS, actions->elems->size );
+}
+
 /*
  * Parse VAR_PARSE_VAR
  */
 
+static VAR_PARSE * parse_at_file( const char * start, const char * mid, const char * end );
 static VAR_PARSE * parse_variable( const char * * string );
 static int try_parse_variable( const char * * s_, const char * * string, VAR_PARSE_GROUP * out);
 static void balance_parentheses( const char * * s_, const char * * string, VAR_PARSE_GROUP * out);
+static void parse_var_string( const char * first, const char * last, struct dynamic_array * out );
 
 /*
  * Parses a string that can contain variables to expand.
@@ -1458,6 +1662,13 @@
     }
 }
 
+static VAR_PARSE_ACTIONS * parse_actions( const char * string )
+{
+ VAR_PARSE_ACTIONS * result = var_parse_actions_new();
+ parse_var_string( string, string + strlen( string ), result->elems );
+ return result;
+}
+
 /*
  * Checks whether the string a *s_ starts with
  * a variable expansion "$(". *string should point
@@ -1480,6 +1691,41 @@
         *s_ = s;
         return 1;
     }
+ else if(s[0] == '@' && s[1] == '(')
+ {
+ int depth = 1;
+ const char * ine;
+ const char * split = 0;
+ var_parse_group_maybe_add_constant( out, *string, s );
+ s += 2;
+ ine = s;
+
+ /* Scan the content of the response file @() section. */
+ while ( *ine && ( depth > 0 ) )
+ {
+ switch ( *ine )
+ {
+ case '(': ++depth; break;
+ case ')': --depth; break;
+ case ':':
+ if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
+ split = ine;
+ break;
+ }
+ ++ine;
+ }
+
+ if ( !split || depth != 0 )
+ {
+ return 0;
+ }
+
+ var_parse_group_add( out, parse_at_file( s, split, ine - 1 ) );
+ *string = ine;
+ *s_ = ine;
+
+ return 1;
+ }
     else
     {
         return 0;
@@ -1492,7 +1738,6 @@
 static void parse_error( const char * message )
 {
     printf( "%s:%d: %s\n", current_file, current_line, message );
- exit(1);
 }
 
 /*
@@ -1542,10 +1787,14 @@
                 else if ( s[0] == '[' )
                 {
                     parse_error("unexpected subscript");
+ ++s;
                 }
                 else if ( s[0] == '\0' )
                 {
                     parse_error( "unbalanced parentheses" );
+ var_parse_group_maybe_add_constant( mod, *string, s );
+ *string = s;
+ return (VAR_PARSE *)result;
                 }
                 else
                 {
@@ -1568,26 +1817,29 @@
                     var_parse_group_maybe_add_constant( subscript, *string, s );
                     ++s;
                     *string = s;
- if ( s[0] == '\0' )
- {
- parse_error( "unbalanced parentheses" );
- }
- else if ( s[0] == ')' || s[0] == ':' )
+ if ( s[0] == ')' || s[0] == ':' || s[0] == '\0')
                     {
                         break;
                     }
                     else
                     {
                         parse_error( "unexpected text following []" );
+ break;
                     }
                 }
                 else if ( isdigit( s[0] ) || s[0] == '-' )
                 {
                     ++s;
                 }
+ else if( s[0] == '\0' )
+ {
+ parse_error( "malformed subscript" );
+ break;
+ }
                 else
                 {
                     parse_error( "malformed subscript" );
+ ++s;
                 }
             }
         }
@@ -1606,6 +1858,9 @@
         else if ( s[0] == '\0' )
         {
             parse_error( "unbalanced parentheses" );
+ var_parse_group_maybe_add_constant( name, *string, s );
+ *string = s;
+ return (VAR_PARSE *)result;
         }
         else
         {
@@ -1614,6 +1869,65 @@
     }
 }
 
+static void parse_var_string( const char * first, const char * last, struct dynamic_array * out )
+{
+ const char * saved = first;
+ for ( ; ; )
+ {
+ /* Handle whitespace */
+ for ( ; first != last; ++first ) if ( !isspace(*first) ) break;
+ if ( saved != first )
+ {
+ VAR_PARSE_GROUP * group = var_parse_group_new();
+ var_parse_group_maybe_add_constant( group, saved, first );
+ saved = first;
+ dynamic_array_push( out, group );
+ }
+
+ if ( first == last ) break;
+
+ /* Handle non-whitespace */
+
+ {
+ VAR_PARSE_GROUP * group = var_parse_group_new();
+ for ( ; ; )
+ {
+
+ if( first == last || isspace( *first ) )
+ {
+ var_parse_group_maybe_add_constant( group, saved, first );
+ saved = first;
+ break;
+ }
+ else if ( try_parse_variable( &first, &saved, group ) )
+ {
+ assert( first <= last );
+ }
+ else
+ {
+ ++first;
+ }
+ }
+ dynamic_array_push( out, group );
+ }
+ if ( first == last ) break;
+ }
+}
+
+/*
+ * start should point to the character immediately following the
+ * opening "@(", mid should point to the ":E=", and end should
+ * point to the closing ")".
+ */
+
+static VAR_PARSE * parse_at_file( const char * start, const char * mid, const char * end )
+{
+ VAR_PARSE_FILE * result = var_parse_file_new();
+ parse_var_string( start, mid, result->filename );
+ parse_var_string( mid + 3, end, result->contents );
+ return (VAR_PARSE *)result;
+}
+
 /*
  * Given that *s_ points to the character after a "(",
  * parses up to the matching ")". *string should
@@ -1633,9 +1947,15 @@
     for ( ; ; )
     {
         if ( try_parse_variable( &s, string, out ) ) { }
- else if(s[0] == ':' || s[0] == '[' || s[0] == '\0')
+ else if(s[0] == ':' || s[0] == '[')
+ {
+ parse_error( "unbalanced parentheses" );
+ ++s;
+ }
+ else if(s[0] == '\0')
         {
             parse_error( "unbalanced parentheses" );
+ break;
         }
         else if(s[0] == ')')
         {
@@ -1664,6 +1984,7 @@
 #define RESULT_NONE 2
 
 static void compile_parse( PARSE * parse, compiler * c, int result_location );
+static struct arg_list * arg_list_compile( PARSE * parse, int * num_arguments );
 
 static void compile_condition( PARSE * parse, compiler * c, int branch_true, int label )
 {
@@ -1825,23 +2146,29 @@
     }
 }
 
-static void compile_parse( PARSE * parse, compiler * c, int result_location )
+static void compile_append_chain( PARSE * parse, compiler * c )
 {
- if ( parse->type == PARSE_APPEND )
+ assert( parse->type == PARSE_APPEND );
+ if ( parse->left->type == PARSE_NULL )
     {
- /*
- * append is associative, so flip the parse tree of chained
- * appends around to keep the stack from getting too deep.
- */
         compile_parse( parse->right, c, RESULT_STACK );
- while ( parse->left->type == PARSE_APPEND )
- {
- compile_parse( parse->left->right, c, RESULT_STACK );
- compile_emit( c, INSTR_PUSH_APPEND, 0 );
- parse = parse->left;
- }
- compile_parse( parse->left, c, RESULT_STACK );
+ }
+ else
+ {
+ if ( parse->left->type == PARSE_APPEND )
+ compile_append_chain( parse->left, c );
+ else
+ compile_parse( parse->left, c, RESULT_STACK );
+ compile_parse( parse->right, c, RESULT_STACK );
         compile_emit( c, INSTR_PUSH_APPEND, 0 );
+ }
+}
+
+static void compile_parse( PARSE * parse, compiler * c, int result_location )
+{
+ if ( parse->type == PARSE_APPEND )
+ {
+ compile_append_chain( parse, c );
         adjust_result( c, RESULT_STACK, result_location );
     }
     else if ( parse->type == PARSE_EVAL )
@@ -1853,8 +2180,19 @@
         }
         else
         {
- printf( "%s:%d: Conditional used as list (check operator precedence).\n", object_str(parse->file), parse->line, parse->num );
- exit( 1 );
+ int f = compile_new_label( c );
+ int end = compile_new_label( c );
+
+ printf( "%s:%d: Conditional used as list (check operator precedence).\n", object_str(parse->file), parse->line );
+
+ /* Emit the condition */
+ compile_condition( parse, c, 0, f );
+ compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c, constant_true ) );
+ compile_emit_branch( c, INSTR_JUMP, end );
+ compile_set_label( c, f );
+ compile_emit( c, INSTR_PUSH_EMPTY, 0 );
+ compile_set_label( c, end );
+ adjust_result( c, RESULT_STACK, result_location );
         }
     }
     else if ( parse->type == PARSE_FOREACH )
@@ -1876,8 +2214,9 @@
             compile_emit( c, INSTR_SWAP, 1 );
         }
 
+ compile_emit( c, INSTR_FOR_INIT, 0 );
         compile_set_label( c, top );
- compile_emit_branch( c, INSTR_TRY_POP_FRONT, end );
+ compile_emit_branch( c, INSTR_FOR_LOOP, end );
         compile_emit( c, INSTR_SET, var );
         compile_emit( c, INSTR_POP, 0 );
 
@@ -1896,19 +2235,18 @@
     }
     else if( parse->type == PARSE_IF )
     {
- int nested_result = result_location == RESULT_NONE? RESULT_NONE : RESULT_RETURN;
         int f = compile_new_label( c );
         /* Emit the condition */
         compile_condition( parse->left, c, 0, f );
         /* Emit the if block */
- compile_parse( parse->right, c, nested_result );
- if ( parse->third->type != PARSE_NULL )
+ compile_parse( parse->right, c, result_location );
+ if ( parse->third->type != PARSE_NULL || result_location != RESULT_NONE )
         {
             /* Emit the else block */
             int end = compile_new_label( c );
             compile_emit_branch( c, INSTR_JUMP, end );
             compile_set_label( c, f );
- compile_parse( parse->third, c, nested_result );
+ compile_parse( parse->third, c, result_location );
             compile_set_label( c, end );
         }
         else
@@ -1916,13 +2254,14 @@
             compile_set_label( c, f );
         }
 
- adjust_result( c, nested_result, result_location);
     }
     else if( parse->type == PARSE_WHILE )
     {
         int nested_result = result_location == RESULT_NONE? RESULT_NONE : RESULT_RETURN;
         int test = compile_new_label( c );
         int top = compile_new_label( c );
+ /* Make sure that we return an empty list if the loop runs zero times. */
+ adjust_result( c, RESULT_NONE, nested_result );
         /* Jump to the loop test */
         compile_emit_branch( c, INSTR_JUMP, test );
         compile_set_label( c, top );
@@ -1938,6 +2277,7 @@
     {
         compile_parse( parse->left, c, RESULT_STACK );
         compile_emit( c, INSTR_INCLUDE, 0 );
+ compile_emit( c, INSTR_BIND_MODULE_VARIABLES, 0 );
         adjust_result( c, RESULT_NONE, result_location );
     }
     else if ( parse->type == PARSE_MODULE )
@@ -1964,6 +2304,7 @@
         }
         compile_emit( c, INSTR_CLASS, 0 );
         compile_parse( parse->right, c, RESULT_NONE );
+ compile_emit( c, INSTR_BIND_MODULE_VARIABLES, 0 );
         compile_emit( c, INSTR_POP_MODULE, 0 );
 
         adjust_result( c, RESULT_NONE, result_location );
@@ -2128,26 +2469,17 @@
     }
     else if ( parse->type == PARSE_SETCOMP )
     {
- int n_args = 0;
- int rule_id;
- if ( parse->right )
- {
- PARSE * p;
- for ( p = parse->right; p; p = p->left )
- {
- compile_parse( p->right, c, RESULT_STACK );
- ++n_args;
- }
- }
+ int n_args;
+ struct arg_list * args = arg_list_compile( parse->right, &n_args );
 
- rule_id = compile_emit_rule( c, parse->string, parse->left, n_args, parse->num );
+ int rule_id = compile_emit_rule( c, parse->string, parse->left, n_args, args, parse->num );
 
         compile_emit( c, INSTR_RULE, rule_id );
         adjust_result( c, RESULT_NONE, result_location );
     }
     else if ( parse->type == PARSE_SETEXEC )
     {
- int actions_id = compile_emit_actions( c, parse->string, parse->string1, parse->num );
+ int actions_id = compile_emit_actions( c, parse );
 
         compile_parse( parse->left, c, RESULT_STACK );
 
@@ -2215,20 +2547,31 @@
         *file = constant_builtin;
         *line = -1;
     }
+#ifdef HAVE_PYTHON
+ if ( function_->type == FUNCTION_PYTHON )
+ {
+ *file = constant_builtin;
+ *line = -1;
+ }
+#endif
     else
     {
         JAM_FUNCTION * function = (JAM_FUNCTION *)function_;
+ assert( function_->type == FUNCTION_JAM );
         *file = function->file;
         *line = function->line;
     }
 }
 
-FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ), int flags )
+static struct arg_list * arg_list_compile_builtin( const char * * args, int * num_arguments );
+
+FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ), int flags, const char * * args )
 {
     BUILTIN_FUNCTION * result = BJAM_MALLOC( sizeof( BUILTIN_FUNCTION ) );
- result->type = FUNCTION_BUILTIN;
- result->reference_count = 1;
- result->rulename = 0;
+ result->base.type = FUNCTION_BUILTIN;
+ result->base.reference_count = 1;
+ result->base.rulename = 0;
+ result->base.formal_arguments = arg_list_compile_builtin( args, &result->base.num_formal_arguments );
     result->func = func;
     result->flags = flags;
     return (FUNCTION *)result;
@@ -2248,50 +2591,782 @@
     return (FUNCTION *)result;
 }
 
-void function_refer( FUNCTION * func )
+FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int line )
 {
- ++func->reference_count;
-}
-
-void function_free( FUNCTION * function_ )
+ compiler c[1];
+ JAM_FUNCTION * result;
+ VAR_PARSE_ACTIONS * parse;
+ current_file = object_str( file );
+ current_line = line;
+ parse = parse_actions( actions );
+ compiler_init( c );
+ var_parse_actions_compile( parse, c );
+ var_parse_actions_free( parse );
+ compile_emit( c, INSTR_RETURN, 0 );
+ result = compile_to_function( c );
+ compiler_free( c );
+ result->file = object_copy( file );
+ result->line = line;
+ return (FUNCTION *)result;
+}
+
+static void argument_list_print( struct arg_list * args, int num_args );
+
+
+/* Define delimiters for type check elements in argument lists (and return type
+ * specifications, eventually).
+ */
+# define TYPE_OPEN_DELIM '['
+# define TYPE_CLOSE_DELIM ']'
+
+/*
+ * is_type_name() - true iff the given string represents a type check
+ * specification.
+ */
+
+int is_type_name( const char * s )
 {
- int i;
+ return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
+ ( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
+}
 
- if ( --function_->reference_count != 0 ) return;
+static void argument_error( const char * message, FUNCTION * procedure, FRAME * frame, OBJECT * arg )
+{ extern void print_source_line( FRAME * );
+ LOL * actual = frame->args;
+ backtrace_line( frame->prev );
+ printf( "*** argument error\n* rule %s ( ", frame->rulename );
+ argument_list_print( procedure->formal_arguments, procedure->num_formal_arguments );
+ printf( " )\n* called with: ( " );
+ lol_print( actual );
+ printf( " )\n* %s %s\n", message, arg ? object_str ( arg ) : "" );
+ function_location( procedure, &frame->file, &frame->line );
+ print_source_line( frame );
+ printf( "see definition of rule '%s' being called\n", frame->rulename );
+ backtrace( frame->prev );
+ exit( 1 );
+}
 
- if ( function_->rulename ) object_free( function_->rulename );
+static void type_check_range
+(
+ OBJECT * type_name,
+ LISTITER iter,
+ LISTITER end,
+ FRAME * caller,
+ FUNCTION * called,
+ OBJECT * arg_name
+)
+{
+ static module_t * typecheck = 0;
 
- if ( function_->type == FUNCTION_JAM )
+ /* If nothing to check, bail now. */
+ if ( iter == end || !type_name )
+ return;
+
+ if ( !typecheck )
     {
- JAM_FUNCTION * func = (JAM_FUNCTION *)function_;
+ typecheck = bindmodule( constant_typecheck );
+ }
 
- BJAM_FREE( func->code );
- for ( i = 0; i < func->num_constants; ++i )
+ /* If the checking rule can not be found, also bail. */
+ if ( !typecheck->rules || !hash_find( typecheck->rules, type_name ) )
+ return;
+
+ for ( ; iter != end; iter = list_next( iter ) )
+ {
+ LIST *error;
+ FRAME frame[1];
+ frame_init( frame );
+ frame->module = typecheck;
+ frame->prev = caller;
+ frame->prev_user = caller->module->user_module ? caller : caller->prev_user;
+
+ /* Prepare the argument list */
+ lol_add( frame->args, list_new( object_copy( list_item( iter ) ) ) );
+ error = evaluate_rule( type_name, frame );
+
+ if ( !list_empty( error ) )
+ argument_error( object_str( list_front( error ) ), called, caller, arg_name );
+
+ frame_free( frame );
+ }
+}
+
+static void type_check
+(
+ OBJECT * type_name,
+ LIST * values,
+ FRAME * caller,
+ FUNCTION * called,
+ OBJECT * arg_name
+)
+{
+ type_check_range( type_name, list_begin( values ), list_end( values ), caller, called, arg_name );
+}
+
+void argument_list_check( struct arg_list * formal, int formal_count, FUNCTION * function, FRAME * frame )
+{
+ LOL * all_actual = frame->args;
+ int i, j;
+
+ for ( i = 0; i < formal_count; ++i )
+ {
+ LIST *actual = lol_get( all_actual, i );
+ LISTITER actual_iter = list_begin( actual ), actual_end = list_end( actual );
+ for ( j = 0; j < formal[i].size; ++j )
         {
- object_free( func->constants[i] );
+ struct argument * formal_arg = &formal[i].args[j];
+ LIST * value;
+
+ switch ( formal_arg->flags )
+ {
+ case ARG_ONE:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
+ actual_iter = list_next( actual_iter );
+ break;
+ case ARG_OPTIONAL:
+ if ( actual_iter == actual_end )
+ value = L0;
+ else
+ {
+ type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
+ actual_iter = list_next( actual_iter );
+ }
+ break;
+ case ARG_PLUS:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ /* fallthrough */
+ case ARG_STAR:
+ type_check_range( formal_arg->type_name, actual_iter, actual_end, frame, function, formal_arg->arg_name );
+ actual_iter = actual_end;
+ break;
+ case ARG_VARIADIC:
+ return;
+ }
         }
- BJAM_FREE( func->constants );
 
- for ( i = 0; i < func->num_subfunctions; ++i )
+ if ( actual_iter != actual_end )
         {
- object_free( func->functions[i].name );
- function_free( func->functions[i].code );
+ argument_error( "extra argument", function, frame, list_item( actual_iter ) );
         }
- BJAM_FREE( func->functions );
+ }
 
- for ( i = 0; i < func->num_subactions; ++i )
+ for ( ; i < all_actual->count; ++i )
+ {
+ LIST * actual = lol_get( all_actual, i );
+ if ( !list_empty( actual ) )
+ {
+ argument_error( "extra argument", function, frame, list_front( actual ) );
+ }
+ }
+}
+
+void argument_list_push( struct arg_list * formal, int formal_count, FUNCTION * function, FRAME * frame, STACK * s )
+{
+ LOL * all_actual = frame->args;
+ int i, j;
+
+ for ( i = 0; i < formal_count; ++i )
+ {
+ LIST *actual = lol_get( all_actual, i );
+ LISTITER actual_iter = list_begin( actual ), actual_end = list_end( actual );
+ for ( j = 0; j < formal[i].size; ++j )
+ {
+ struct argument * formal_arg = &formal[i].args[j];
+ LIST * value;
+
+ switch ( formal_arg->flags )
+ {
+ case ARG_ONE:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ value = list_new( object_copy( list_item( actual_iter ) ) );
+ actual_iter = list_next( actual_iter );
+ break;
+ case ARG_OPTIONAL:
+ if ( actual_iter == actual_end )
+ value = L0;
+ else
+ {
+ value = list_new( object_copy( list_item( actual_iter ) ) );
+ actual_iter = list_next( actual_iter );
+ }
+ break;
+ case ARG_PLUS:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ /* fallthrough */
+ case ARG_STAR:
+ value = list_copy_range( actual, actual_iter, actual_end );
+ actual_iter = actual_end;
+ break;
+ case ARG_VARIADIC:
+ return;
+ }
+
+ type_check( formal_arg->type_name, value, frame, function, formal_arg->arg_name );
+
+ if ( formal_arg->index != -1 )
+ {
+ LIST * * old = &frame->module->fixed_variables[ formal_arg->index ];
+ stack_push( s, *old );
+ *old = value;
+ }
+ else
+ {
+ stack_push( s, var_swap( frame->module, formal_arg->arg_name, value ) );
+ }
+ }
+
+ if ( actual_iter != actual_end )
+ {
+ argument_error( "extra argument", function, frame, list_item( actual_iter ) );
+ }
+ }
+
+ for ( ; i < all_actual->count; ++i )
+ {
+ LIST * actual = lol_get( all_actual, i );
+ if ( !list_empty( actual ) )
+ {
+ argument_error( "extra argument", function, frame, list_front( actual ) );
+ }
+ }
+}
+
+void argument_list_pop( struct arg_list * formal, int formal_count, FRAME * frame, STACK * s )
+{
+ int i, j;
+
+ for ( i = formal_count - 1; i >= 0; --i )
+ {
+ for ( j = formal[i].size - 1; j >= 0 ; --j )
+ {
+ struct argument * formal_arg = &formal[i].args[j];
+
+ if ( formal_arg->flags == ARG_VARIADIC )
+ {
+ continue;
+ }
+ else if ( formal_arg->index != -1 )
+ {
+ LIST * old = stack_pop( s );
+ LIST * * pos = &frame->module->fixed_variables[ formal_arg->index ];
+ list_free( *pos );
+ *pos = old;
+ }
+ else
+ {
+ var_set( frame->module, formal_arg->arg_name, stack_pop( s ), VAR_SET );
+ }
+ }
+ }
+}
+
+
+struct argument_compiler
+{
+ struct dynamic_array args[ 1 ];
+ struct argument arg;
+ int state;
+#define ARGUMENT_COMPILER_START 0
+#define ARGUMENT_COMPILER_FOUND_TYPE 1
+#define ARGUMENT_COMPILER_FOUND_OBJECT 2
+#define ARGUMENT_COMPILER_DONE 3
+};
+
+
+static void argument_compiler_init( struct argument_compiler * c )
+{
+ dynamic_array_init( c->args );
+ c->state = ARGUMENT_COMPILER_START;
+}
+
+static void argument_compiler_free( struct argument_compiler * c )
+{
+ dynamic_array_free( c->args );
+}
+
+static void argument_compiler_add( struct argument_compiler * c, OBJECT * arg, OBJECT * file, int line )
+{
+ switch ( c->state )
+ {
+ case ARGUMENT_COMPILER_FOUND_OBJECT:
+
+ if ( object_equal( arg, constant_question_mark ) )
+ {
+ c->arg.flags = ARG_OPTIONAL;
+ }
+ else if ( object_equal( arg, constant_plus ) )
+ {
+ c->arg.flags = ARG_PLUS;
+ }
+ else if ( object_equal( arg, constant_star ) )
+ {
+ c->arg.flags = ARG_STAR;
+ }
+
+ dynamic_array_push( c->args, c->arg );
+ c->state = ARGUMENT_COMPILER_START;
+
+ if ( c->arg.flags != ARG_ONE )
+ break;
+ /* fall-through */
+
+ case ARGUMENT_COMPILER_START:
+
+ c->arg.type_name = 0;
+ c->arg.index = -1;
+ c->arg.flags = ARG_ONE;
+
+ if ( is_type_name( object_str( arg ) ) )
+ {
+ c->arg.type_name = object_copy( arg );
+ c->state = ARGUMENT_COMPILER_FOUND_TYPE;
+ break;
+ }
+ /* fall-through */
+
+ case ARGUMENT_COMPILER_FOUND_TYPE:
+
+ if ( is_type_name( object_str( arg ) ) )
         {
- object_free( func->actions[i].name );
- object_free( func->actions[i].command );
+ printf( "%s:%d: missing argument name before type name: %s\n", object_str( file ), line, object_str( arg ) );
+ exit( 1 );
+ }
+
+ c->arg.arg_name = object_copy( arg );
+ if ( object_equal( arg, constant_star ) )
+ {
+ c->arg.flags = ARG_VARIADIC;
+ dynamic_array_push( c->args, c->arg );
+ c->state = ARGUMENT_COMPILER_DONE;
+ }
+ else
+ {
+ c->state = ARGUMENT_COMPILER_FOUND_OBJECT;
+ }
+ break;
+
+ case ARGUMENT_COMPILER_DONE:
+ break;
+ }
+}
+
+static void argument_compiler_recurse( struct argument_compiler * c, PARSE * parse )
+{
+ if ( parse->type == PARSE_APPEND )
+ {
+ argument_compiler_recurse( c, parse->left );
+ argument_compiler_recurse( c, parse->right );
+ }
+ else if ( parse->type != PARSE_NULL )
+ {
+ assert( parse->type == PARSE_LIST );
+ argument_compiler_add( c, parse->string, parse->file, parse->line );
+ }
+}
+
+static struct arg_list arg_compile_impl( struct argument_compiler * c, OBJECT * file, int line )
+{
+ struct arg_list result;
+ switch ( c->state )
+ {
+ case ARGUMENT_COMPILER_START:
+ case ARGUMENT_COMPILER_DONE:
+ break;
+ case ARGUMENT_COMPILER_FOUND_TYPE:
+ printf( "%s:%d: missing argument name after type name: %s\n", object_str( file ), line, object_str( c->arg.type_name ) );
+ exit( 1 );
+ case ARGUMENT_COMPILER_FOUND_OBJECT:
+ dynamic_array_push( c->args, c->arg );
+ break;
+ }
+ result.size = c->args->size;
+ result.args = BJAM_MALLOC( c->args->size * sizeof( struct argument ) );
+ memcpy( result.args, c->args->data, c->args->size * sizeof( struct argument ) );
+ return result;
+}
+
+static struct arg_list arg_compile( PARSE * parse )
+{
+ struct argument_compiler c[ 1 ];
+ struct arg_list result;
+ argument_compiler_init( c );
+ argument_compiler_recurse( c, parse );
+ result = arg_compile_impl( c, parse->file, parse->line );
+ argument_compiler_free( c );
+ return result;
+}
+
+struct argument_list_compiler
+{
+ struct dynamic_array args[ 1 ];
+};
+
+static void argument_list_compiler_init( struct argument_list_compiler * c )
+{
+ dynamic_array_init( c->args );
+}
+
+static void argument_list_compiler_free( struct argument_list_compiler * c )
+{
+ dynamic_array_free( c->args );
+}
+
+static void argument_list_compiler_add( struct argument_list_compiler * c, PARSE * parse )
+{
+ struct arg_list args = arg_compile( parse );
+ dynamic_array_push( c->args, args );
+}
+
+static void argument_list_compiler_recurse( struct argument_list_compiler * c, PARSE * parse )
+{
+ if ( parse )
+ {
+ argument_list_compiler_add( c, parse->right );
+ argument_list_compiler_recurse( c, parse->left );
+ }
+}
+
+static struct arg_list * arg_list_compile( PARSE * parse, int * num_arguments )
+{
+ if ( parse )
+ {
+ struct argument_list_compiler c[ 1 ];
+ struct arg_list * result;
+ argument_list_compiler_init( c );
+ argument_list_compiler_recurse( c, parse );
+ *num_arguments = c->args->size;
+ result = BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
+ memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list ) );
+ argument_list_compiler_free( c );
+ return result;
+ }
+ else
+ {
+ *num_arguments = 0;
+ return 0;
+ }
+}
+
+static struct arg_list * arg_list_compile_builtin( const char * * args, int * num_arguments )
+{
+ if ( args )
+ {
+ struct argument_list_compiler c[ 1 ];
+ struct arg_list * result;
+ argument_list_compiler_init( c );
+ while ( *args )
+ {
+ struct argument_compiler arg_comp[ 1 ];
+ struct arg_list arg;
+ argument_compiler_init( arg_comp );
+ for ( ; *args; ++args )
+ {
+ OBJECT * token;
+ if ( strcmp( *args, ":" ) == 0 )
+ {
+ ++args;
+ break;
+ }
+ token = object_new( *args );
+ argument_compiler_add( arg_comp, token, constant_builtin, -1 );
+ object_free( token );
+ }
+ arg = arg_compile_impl( arg_comp, constant_builtin, -1 );
+ dynamic_array_push( c->args, arg );
+ argument_compiler_free( arg_comp );
+ }
+ *num_arguments = c->args->size;
+ result = BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
+ memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list ) );
+ argument_list_compiler_free( c );
+ return result;
+ }
+ else
+ {
+ *num_arguments = 0;
+ return 0;
+ }
+}
+
+static void argument_list_print( struct arg_list * args, int num_args )
+{
+ if ( args )
+ {
+ int i, j;
+ for ( i = 0; i < num_args; ++i )
+ {
+ if ( i ) printf(" : ");
+ for ( j = 0; j < args[ i ].size; ++j )
+ {
+ struct argument * formal_arg = &args[ i ].args[ j ];
+ if ( j ) printf( " " );
+ if ( formal_arg->type_name ) printf( "%s ", object_str( formal_arg->type_name ) );
+ printf( "%s", formal_arg->arg_name );
+ switch( formal_arg->flags )
+ {
+ case ARG_OPTIONAL: printf( " ?" ); break;
+ case ARG_PLUS: printf( " +" ); break;
+ case ARG_STAR: printf( " *" ); break;
+ }
+ }
+ }
+ }
+}
+
+
+struct arg_list * argument_list_bind_variables( struct arg_list * formal, int formal_count, module_t * module, int * counter )
+{
+ if ( formal )
+ {
+ struct arg_list * result = (struct arg_list *)BJAM_MALLOC( sizeof( struct arg_list ) * formal_count );
+ int i, j;
+
+ for ( i = 0; i < formal_count; ++i )
+ {
+ struct argument * args = (struct argument *)BJAM_MALLOC( sizeof( struct argument ) * formal[ i ].size );
+ for ( j = 0; j < formal[ i ].size; ++j )
+ {
+ args[ j ] = formal[ i ].args[ j ];
+ if ( args[ j ].type_name )
+ args[ j ].type_name = object_copy( args[ j ].type_name );
+ args[ j ].arg_name = object_copy( args[ j ].arg_name );
+ if ( args[ j ].flags != ARG_VARIADIC )
+ {
+ args[ j ].index = module_add_fixed_var( module, args[ j ].arg_name, counter );
+ }
+ }
+ result[ i ].args = args;
+ result[ i ].size = formal[ i ].size;
+ }
+
+ return result;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+void argument_list_free( struct arg_list * args, int args_count )
+{
+ int i, j;
+ for ( i = 0; i < args_count; ++i )
+ {
+ for ( j = 0; j < args[ i ].size; ++j )
+ {
+ if ( args[ i ].args[ j ].type_name )
+ object_free( args[ i ].args[ j ].type_name );
+ object_free( args[ i ].args[ j ].arg_name );
+ }
+ BJAM_FREE( args[ i ].args );
+ }
+ BJAM_FREE( args );
+}
+
+
+FUNCTION * function_unbind_variables( FUNCTION * f )
+{
+ if ( f->type == FUNCTION_JAM )
+ {
+ JAM_FUNCTION * func = (JAM_FUNCTION *)f;
+ if ( func->generic )
+ return func->generic;
+ else
+ return (FUNCTION *)func;
+ }
+#ifdef HAVE_PYTHON
+ else if ( f->type == FUNCTION_PYTHON )
+ {
+ return f;
+ }
+#endif
+ else
+ {
+ assert( f->type == FUNCTION_BUILTIN );
+ return f;
+ }
+}
+
+FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter )
+{
+ if ( f->type == FUNCTION_BUILTIN )
+ {
+ return f;
+ }
+#ifdef HAVE_PYTHON
+ else if ( f->type == FUNCTION_PYTHON )
+ {
+ return f;
+ }
+#endif
+ else
+ {
+ JAM_FUNCTION * func = (JAM_FUNCTION *)f;
+ JAM_FUNCTION * new_func = BJAM_MALLOC( sizeof( JAM_FUNCTION ) );
+ instruction * code;
+ int i;
+ assert( f->type == FUNCTION_JAM );
+ memcpy( new_func, func, sizeof( JAM_FUNCTION ) );
+ new_func->base.reference_count = 1;
+ new_func->base.formal_arguments = argument_list_bind_variables( f->formal_arguments, f->num_formal_arguments, module, counter );
+ new_func->code = BJAM_MALLOC( func->code_size * sizeof( instruction ) );
+ memcpy( new_func->code, func->code, func->code_size * sizeof( instruction ) );
+ new_func->generic = (FUNCTION *)func;
+ func = new_func;
+ for ( i = 0; ; ++i )
+ {
+ OBJECT * key;
+ int op_code;
+ code = func->code + i;
+ switch ( code->op_code )
+ {
+ case INSTR_PUSH_VAR: op_code = INSTR_PUSH_VAR_FIXED; break;
+ case INSTR_PUSH_LOCAL: op_code = INSTR_PUSH_LOCAL_FIXED; break;
+ case INSTR_POP_LOCAL: op_code = INSTR_POP_LOCAL_FIXED; break;
+ case INSTR_SET: op_code = INSTR_SET_FIXED; break;
+ case INSTR_APPEND: op_code = INSTR_APPEND_FIXED; break;
+ case INSTR_DEFAULT: op_code = INSTR_DEFAULT_FIXED; break;
+ case INSTR_RETURN: return (FUNCTION *)new_func;
+ case INSTR_CALL_RULE: ++i; continue;
+ case INSTR_PUSH_MODULE:
+ {
+ int depth = 1;
+ ++i;
+ while ( depth > 0 )
+ {
+ code = func->code + i;
+ switch ( code->op_code )
+ {
+ case INSTR_PUSH_MODULE:
+ case INSTR_CLASS:
+ ++depth;
+ break;
+ case INSTR_POP_MODULE:
+ --depth;
+ break;
+ case INSTR_CALL_RULE:
+ ++i;
+ break;
+ }
+ ++i;
+ }
+ --i;
+ }
+ default: continue;
+ }
+ key = func->constants[ code->arg ];
+ if ( !( object_equal( key, constant_TMPDIR ) ||
+ object_equal( key, constant_TMPNAME ) ||
+ object_equal( key, constant_TMPFILE ) ||
+ object_equal( key, constant_STDOUT ) ||
+ object_equal( key, constant_STDERR ) ) )
+ {
+ code->op_code = op_code;
+ code->arg = module_add_fixed_var( module, key, counter );
+ }
         }
- BJAM_FREE( func->actions );
+ }
+}
+
+void function_refer( FUNCTION * func )
+{
+ ++func->reference_count;
+}
+
+void function_free( FUNCTION * function_ )
+{
+ int i;
+
+ if ( --function_->reference_count != 0 ) return;
+
+ if ( function_->formal_arguments ) argument_list_free( function_->formal_arguments, function_->num_formal_arguments );
+
+ if ( function_->type == FUNCTION_JAM )
+ {
+ JAM_FUNCTION * func = (JAM_FUNCTION *)function_;
+
+ BJAM_FREE( func->code );
 
- object_free( func->file );
+ if ( func->generic )
+ function_free( func->generic );
+ else
+ {
+ if ( function_->rulename ) object_free( function_->rulename );
+
+ for ( i = 0; i < func->num_constants; ++i )
+ {
+ object_free( func->constants[i] );
+ }
+ BJAM_FREE( func->constants );
+
+ for ( i = 0; i < func->num_subfunctions; ++i )
+ {
+ object_free( func->functions[i].name );
+ function_free( func->functions[i].code );
+ }
+ BJAM_FREE( func->functions );
+
+ for ( i = 0; i < func->num_subactions; ++i )
+ {
+ object_free( func->actions[i].name );
+ function_free( func->actions[i].command );
+ }
+ BJAM_FREE( func->actions );
+
+ object_free( func->file );
+ }
+ }
+#ifdef HAVE_PYTHON
+ else if ( function_->type == FUNCTION_PYTHON )
+ {
+ PYTHON_FUNCTION * func = (PYTHON_FUNCTION *)function_;
+ Py_DECREF( func->python_function );
+ if ( function_->rulename ) object_free( function_->rulename );
+ }
+#endif
+ else
+ {
+ assert( function_->type == FUNCTION_BUILTIN );
+ if ( function_->rulename ) object_free( function_->rulename );
     }
 
     BJAM_FREE( function_ );
 }
 
+
+/* Alignment check for stack */
+
+struct align_var_edits
+{
+ char ch;
+ VAR_EDITS e;
+};
+
+struct align_expansion_item
+{
+ char ch;
+ expansion_item e;
+};
+
+static char check_align_var_edits[ sizeof(struct align_var_edits) <= sizeof(VAR_EDITS) + sizeof(void *) ? 1 : -1 ];
+static char check_align_expansion_item[ sizeof(struct align_expansion_item) <= sizeof(expansion_item) + sizeof(void *) ? 1 : -1 ];
+
+static char check_ptr_size1[ sizeof(LIST *) <= sizeof(void *) ? 1 : -1 ];
+static char check_ptr_size2[ sizeof(char *) <= sizeof(void *) ? 1 : -1 ];
+
+void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string * out )
+{
+ *(string * *)stack_allocate( s, sizeof( string * ) ) = out;
+ list_free( function_run( function, frame, s ) );
+ stack_deallocate( s, sizeof( string * ) );
+}
+
 /*
  * WARNING: The instruction set is tuned for Jam and
  * is not really generic. Be especially careful about
@@ -2310,9 +3385,26 @@
     if ( function_->type == FUNCTION_BUILTIN )
     {
         BUILTIN_FUNCTION * f = (BUILTIN_FUNCTION *)function_;
+ if ( function_->formal_arguments )
+ argument_list_check( function_->formal_arguments, function_->num_formal_arguments, function_, frame );
         return f->func( frame, f->flags );
     }
 
+#ifdef HAVE_PYTHON
+
+ else if ( function_->type == FUNCTION_PYTHON )
+ {
+ PYTHON_FUNCTION * f = (PYTHON_FUNCTION *)function_;
+ return call_python_function( f, frame );
+ }
+
+#endif
+
+ assert( function_->type == FUNCTION_JAM );
+
+ if ( function_->formal_arguments )
+ argument_list_push( function_->formal_arguments, function_->num_formal_arguments, function_, frame, s );
+
     function = (JAM_FUNCTION *)function_;
     code = function->code;
     for ( ; ; )
@@ -2333,7 +3425,7 @@
         case INSTR_PUSH_CONSTANT:
         {
             OBJECT * value = function_get_constant( function, code->arg );
- stack_push( s, list_new( L0, object_copy( value ) ) );
+ stack_push( s, list_new( object_copy( value ) ) );
             break;
         }
 
@@ -2349,13 +3441,20 @@
             break;
         }
 
+ case INSTR_PUSH_VAR_FIXED:
+ {
+ stack_push( s, list_copy( frame->module->fixed_variables[ code->arg ] ) );
+ break;
+ }
+
         case INSTR_PUSH_GROUP:
         {
             LIST * value = L0;
+ LISTITER iter, end;
             l = stack_pop( s );
- for ( r = l; r; r = list_next( r ) )
+ for ( iter = list_begin( l ), end = list_end( l ); iter != end; iter = list_next( iter ) )
             {
- LIST * one = function_get_named_variable( function, frame, r->value );
+ LIST * one = function_get_named_variable( function, frame, list_item( iter ) );
                 value = list_append( value, one );
             }
             list_free( l );
@@ -2367,7 +3466,7 @@
         {
             r = stack_pop( s );
             l = stack_pop( s );
- stack_push( s, list_append( r, l ) );
+ stack_push( s, list_append( l, r ) );
             break;
         }
 
@@ -2495,18 +3594,29 @@
          * For
          */
         
- case INSTR_TRY_POP_FRONT:
+ case INSTR_FOR_INIT:
         {
- l = stack_pop( s );
- if( !l )
+ l = stack_top( s );
+ *(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) =
+ list_begin( l );
+ break;
+ }
+
+ case INSTR_FOR_LOOP:
+ {
+ LISTITER iter = *(LISTITER *)stack_get( s );
+ stack_deallocate( s, sizeof( LISTITER ) );
+ l = stack_top( s );
+ if( iter == list_end( l ) )
             {
+ list_free( stack_pop( s ) );
                 code += code->arg;
             }
             else
             {
- r = list_new( L0, object_copy( l->value ) );
- l = list_pop_front( l );
- stack_push( s, l );
+ r = list_new( object_copy( list_item( iter ) ) );
+ iter = list_next( iter );
+ *(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) = iter;
                 stack_push( s, r );
             }
             break;
@@ -2522,8 +3632,8 @@
             const char * match;
             l = stack_pop( s );
             r = stack_top( s );
- pattern = l ? object_str( l->value ) : "";
- match = r ? object_str( r->value ) : "";
+ pattern = !list_empty( l ) ? object_str( list_front( l ) ) : "";
+ match = !list_empty( r ) ? object_str( list_front( r ) ) : "";
             if( glob( pattern, match ) )
             {
                 code += code->arg;
@@ -2556,6 +3666,20 @@
 
         case INSTR_RETURN:
         {
+ if ( function_->formal_arguments )
+ argument_list_pop( function_->formal_arguments, function_->num_formal_arguments, frame, s );
+#ifndef NDEBUG
+
+ if ( !( saved_stack == s->data ) )
+ {
+ frame->file = function->file;
+ frame->line = function->line;
+ backtrace_line( frame );
+ printf( "error: stack check failed.\n" );
+ backtrace( frame );
+ assert( saved_stack == s->data );
+ }
+#endif
             assert( saved_stack == s->data );
             return result;
         }
@@ -2577,13 +3701,34 @@
             break;
         }
 
+ case INSTR_PUSH_LOCAL_FIXED:
+ {
+ LIST * value = stack_pop( s );
+ LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
+ assert( code->arg < frame->module->num_fixed_variables );
+ stack_push( s, *ptr );
+ *ptr = value;
+ break;
+ }
+
+ case INSTR_POP_LOCAL_FIXED:
+ {
+ LIST * value = stack_pop( s );
+ LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
+ assert( code->arg < frame->module->num_fixed_variables );
+ list_free( *ptr );
+ *ptr = value;
+ break;
+ }
+
         case INSTR_PUSH_LOCAL_GROUP:
         {
             LIST * value = stack_pop( s );
+ LISTITER iter, end;
             l = stack_pop( s );
- for( r = l; r; r = list_next( r ) )
+ for( iter = list_begin( l ), end = list_end( l ); iter != end; iter = list_next( iter ) )
             {
- LIST * saved = function_swap_named_variable( function, frame, r->value, list_copy( L0, value ) );
+ LIST * saved = function_swap_named_variable( function, frame, list_item( iter ), list_copy( value ) );
                 stack_push( s, saved );
             }
             list_free( value );
@@ -2593,12 +3738,13 @@
 
         case INSTR_POP_LOCAL_GROUP:
         {
+ LISTITER iter, end;
             r = stack_pop( s );
             l = list_reverse( r );
             list_free( r );
- for( r = l; r; r = list_next( r ) )
+ for( iter = list_begin( l ), end = list_end( l ); iter != end; iter = list_next( iter ) )
             {
- function_set_named_variable( function, frame, r->value, stack_pop( s ) );
+ function_set_named_variable( function, frame, list_item( iter ), stack_pop( s ) );
             }
             list_free( l );
             break;
@@ -2611,14 +3757,14 @@
         case INSTR_PUSH_ON:
         {
             LIST * targets = stack_top( s );
- if ( targets )
+ if ( !list_empty( targets ) )
             {
                 /*
                  * FIXME: push the state onto the stack instead of
                  * using pushsettings.
                  */
- TARGET * t = bindtarget( targets->value );
- pushsettings( t->settings );
+ TARGET * t = bindtarget( list_front( targets ) );
+ pushsettings( frame->module, t->settings );
             }
             else
             {
@@ -2636,10 +3782,10 @@
         {
             LIST * result = stack_pop( s );
             LIST * targets = stack_pop( s );
- if ( targets )
+ if ( !list_empty( targets ) )
             {
- TARGET * t = bindtarget( targets->value );
- popsettings( t->settings );
+ TARGET * t = bindtarget( list_front( targets ) );
+ popsettings( frame->module, t->settings );
             }
             list_free( targets );
             stack_push( s, result );
@@ -2651,15 +3797,15 @@
             LIST * targets = stack_pop( s );
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- LIST * ts;
- for ( ts = targets; ts; ts = list_next( ts ) )
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
             {
- TARGET * t = bindtarget( ts->value );
- LIST * l;
+ TARGET * t = bindtarget( list_item( iter ) );
+ LISTITER vars_iter = list_begin( vars ), vars_end = list_end( vars );
 
- for ( l = vars; l; l = list_next( l ) )
- t->settings = addsettings( t->settings, VAR_SET, l->value,
- list_copy( L0, value ) );
+ for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) )
+ t->settings = addsettings( t->settings, VAR_SET, list_item( vars_iter ),
+ list_copy( value ) );
             }
             list_free( vars );
             list_free( targets );
@@ -2672,15 +3818,15 @@
             LIST * targets = stack_pop( s );
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- LIST * ts;
- for ( ts = targets; ts; ts = list_next( ts ) )
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
             {
- TARGET * t = bindtarget( ts->value );
- LIST * l;
+ TARGET * t = bindtarget( list_item( iter ) );
+ LISTITER vars_iter = list_begin( vars ), vars_end = list_end( vars );
 
- for ( l = vars; l; l = list_next( l ) )
- t->settings = addsettings( t->settings, VAR_APPEND, l->value,
- list_copy( L0, value ) );
+ for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) )
+ t->settings = addsettings( t->settings, VAR_APPEND, list_item( vars_iter ),
+ list_copy( value ) );
             }
             list_free( vars );
             list_free( targets );
@@ -2693,15 +3839,15 @@
             LIST * targets = stack_pop( s );
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- LIST * ts;
- for ( ts = targets; ts; ts = list_next( ts ) )
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
             {
- TARGET * t = bindtarget( ts->value );
- LIST * l;
+ TARGET * t = bindtarget( list_item( iter ) );
+ LISTITER vars_iter = list_begin( vars ), vars_end = list_end( vars );
 
- for ( l = vars; l; l = list_next( l ) )
- t->settings = addsettings( t->settings, VAR_DEFAULT, l->value,
- list_copy( L0, value ) );
+ for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) )
+ t->settings = addsettings( t->settings, VAR_DEFAULT, list_item( vars_iter ),
+ list_copy( value ) );
             }
             list_free( vars );
             list_free( targets );
@@ -2715,18 +3861,45 @@
 
         case INSTR_SET:
         {
- function_set_variable( function, frame, code->arg, list_copy( L0, stack_top( s ) ) );
+ function_set_variable( function, frame, code->arg, list_copy( stack_top( s ) ) );
             break;
         }
 
         case INSTR_APPEND:
         {
- function_append_variable( function, frame, code->arg, list_copy( L0, stack_top( s ) ) );
+ function_append_variable( function, frame, code->arg, list_copy( stack_top( s ) ) );
             break;
         }
+
         case INSTR_DEFAULT:
         {
- function_default_variable( function, frame, code->arg, list_copy( L0, stack_top( s ) ) );
+ function_default_variable( function, frame, code->arg, list_copy( stack_top( s ) ) );
+ break;
+ }
+
+ case INSTR_SET_FIXED:
+ {
+ LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
+ assert( code->arg < frame->module->num_fixed_variables );
+ list_free( *ptr );
+ *ptr = list_copy( stack_top( s ) );
+ break;
+ }
+
+ case INSTR_APPEND_FIXED:
+ {
+ LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
+ assert( code->arg < frame->module->num_fixed_variables );
+ *ptr = list_append( *ptr, list_copy( stack_top( s ) ) );
+ break;
+ }
+
+ case INSTR_DEFAULT_FIXED:
+ {
+ LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
+ assert( code->arg < frame->module->num_fixed_variables );
+ if ( list_empty( *ptr ) )
+ *ptr = list_copy( stack_top( s ) );
             break;
         }
 
@@ -2734,8 +3907,9 @@
         {
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- for( r = vars; r; r = list_next( r ) )
- function_set_named_variable( function, frame, r->value, list_copy( L0, value ) );
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
+ for( ; iter != end; iter = list_next( iter ) )
+ function_set_named_variable( function, frame, list_item( iter ), list_copy( value ) );
             list_free( vars );
             stack_push( s, value );
             break;
@@ -2745,8 +3919,9 @@
         {
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- for( r = vars; r; r = list_next( r ) )
- function_append_named_variable( function, frame, r->value, list_copy( L0, value ) );
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
+ for( ; iter != end; iter = list_next( iter ) )
+ function_append_named_variable( function, frame, list_item( iter ), list_copy( value ) );
             list_free( vars );
             stack_push( s, value );
             break;
@@ -2756,8 +3931,9 @@
         {
             LIST * value = stack_pop( s );
             LIST * vars = stack_pop( s );
- for( r = vars; r; r = list_next( r ) )
- function_default_named_variable( function, frame, r->value, list_copy( L0, value ) );
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
+ for( ; iter != end; iter = list_next( iter ) )
+ function_default_named_variable( function, frame, list_item( iter ), list_copy( value ) );
             list_free( vars );
             stack_push( s, value );
             break;
@@ -2843,9 +4019,10 @@
             LIST * vars = stack_pop( s );
             int n = expand_modifiers( s, code->arg );
             LIST * result = L0;
- for( l = vars; l; l = list_next( l ) )
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
+ for( ; iter != end; iter = list_next( iter ) )
             {
- stack_push( s, function_get_named_variable( function, frame, l->value ) );
+ stack_push( s, function_get_named_variable( function, frame, list_item( iter ) ) );
                 result = list_append( result, apply_modifiers( s, n ) );
                 list_free( stack_pop( s ) );
             }
@@ -2861,9 +4038,10 @@
         {
             LIST * vars = stack_pop( s );
             LIST * result = L0;
- for( l = vars; l; l = list_next( l ) )
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
+ for( ; iter != end; iter = list_next( iter ) )
             {
- stack_push( s, function_get_named_variable( function, frame, l->value ) );
+ stack_push( s, function_get_named_variable( function, frame, list_item( iter ) ) );
                 result = list_append( result, apply_subscript( s ) );
                 list_free( stack_pop( s ) );
             }
@@ -2880,10 +4058,11 @@
             LIST * r = stack_pop( s );
             int n = expand_modifiers( s, code->arg );
             LIST * result = L0;
+ LISTITER iter = list_begin( vars ), end = list_end( vars );
             stack_push( s, r );
- for( l = vars; l; l = list_next( l ) )
+ for( ; iter != end; iter = list_next( iter ) )
             {
- stack_push( s, function_get_named_variable( function, frame, l->value ) );
+ stack_push( s, function_get_named_variable( function, frame, list_item( iter ) ) );
                 result = list_append( result, apply_subscript_and_modifiers( s, n ) );
                 list_free( stack_pop( s ) );
             }
@@ -2905,7 +4084,8 @@
             int i;
             for( i = 0; i < code->arg; ++i )
             {
- items[i].elem = items[i].saved = stack_pos[i];
+ items[i].saved = stack_pos[i];
+ items[i].elem = list_begin( items[i].saved );
             }
             result = expand( items, code->arg );
             stack_deallocate( s, buffer_size );
@@ -2921,9 +4101,9 @@
         {
             LIST * nt = stack_pop( s );
 
- if ( nt )
+ if ( !list_empty( nt ) )
             {
- TARGET * t = bindtarget( nt->value );
+ TARGET * t = bindtarget( list_front( nt ) );
                 list_free( nt );
 
                 /* DWA 2001/10/22 - Perforce Jam cleared the arguments here, which
@@ -2936,13 +4116,13 @@
                 /* "on-target" variables. Though they are targets, */
                 /* include files are not built with make(). */
 
- pushsettings( t->settings );
+ pushsettings( root_module(), t->settings );
                 /* We don't expect that file to be included is generated by some
                    action. Therefore, pass 0 as third argument.
                    If the name resolves to directory, let it error out. */
                 object_free( t->boundname );
                 t->boundname = search( t->name, &t->time, 0, 0 );
- popsettings( t->settings );
+ popsettings( root_module(), t->settings );
 
                 parse_file( t->boundname, frame );
             }
@@ -2959,16 +4139,10 @@
             LIST * module_name = stack_pop( s );
 
             module_t * outer_module = frame->module;
- frame->module = module_name ? bindmodule( module_name->value ) : root_module();
+ frame->module = !list_empty( module_name ) ? bindmodule( list_front( module_name ) ) : root_module();
 
             list_free( module_name );
 
- if ( outer_module != frame->module )
- {
- exit_module( outer_module );
- enter_module( frame->module );
- }
-
             *(module_t * *)stack_allocate( s, sizeof( module_t * ) ) = outer_module;
 
             break;
@@ -2978,12 +4152,7 @@
         {
             module_t * outer_module = *(module_t * *)stack_get( s );
             stack_deallocate( s, sizeof( module_t * ) );
- if ( outer_module != frame->module )
- {
- exit_module( frame->module );
- enter_module( outer_module );
- frame->module = outer_module;
- }
+ frame->module = outer_module;
             break;
         }
 
@@ -2996,23 +4165,388 @@
             module_t * outer_module = frame->module;
             frame->module = bindmodule( class_module );
             object_free( class_module );
+
+ *(module_t * *)stack_allocate( s, sizeof( module_t * ) ) = outer_module;
 
- if ( outer_module != frame->module )
+ break;
+ }
+
+ case INSTR_BIND_MODULE_VARIABLES:
+ {
+ module_bind_variables( frame->module );
+ break;
+ }
+
+ case INSTR_APPEND_STRINGS:
+ {
+ string buf[1];
+ string_new( buf );
+ combine_strings( s, code->arg, buf );
+ stack_push( s, list_new( object_new( buf->value ) ) );
+ string_free( buf );
+ break;
+ }
+
+ case INSTR_WRITE_FILE:
+ {
+ string buf[1];
+ const char * out;
+ OBJECT * tmp_filename = 0;
+ int out_debug = DEBUG_EXEC ? 1 : 0;
+ FILE * out_file = 0;
+ string_new( buf );
+ combine_strings( s, code->arg, buf );
+ out = object_str( list_front( stack_top( s ) ) );
+
+ /* For stdout/stderr we will create a temp file and generate
+ * a command that outputs the content as needed.
+ */
+ if ( ( strcmp( "STDOUT", out ) == 0 ) ||
+ ( strcmp( "STDERR", out ) == 0 ) )
+ {
+ int err_redir = strcmp( "STDERR", out ) == 0;
+ string result[1];
+ tmp_filename = path_tmpfile();
+ string_new( result );
+
+ #ifdef OS_NT
+ string_append( result, "type \"" );
+ #else
+ string_append( result, "cat \"" );
+ #endif
+ string_append( result, object_str( tmp_filename ) );
+ string_push_back( result, '\"' );
+ if ( err_redir )
+ string_append( result, " 1>&2" );
+
+ /* Replace STDXXX with the temporary file. */
+ list_free( stack_pop( s ) );
+ stack_push( s, list_new( object_new( result->value ) ) );
+ out = object_str( tmp_filename );
+
+ string_free( result );
+
+ /* We also make sure that the temp files created by this
+ * get nuked eventually.
+ */
+ file_remove_atexit( tmp_filename );
+ }
+
+ if ( !globs.noexec )
             {
- exit_module( outer_module );
- enter_module( frame->module );
+ string out_name[1];
+ /* Handle "path to file" filenames. */
+ if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
+ {
+ string_copy( out_name, out + 1 );
+ string_truncate( out_name, out_name->size - 1 );
+ }
+ else
+ {
+ string_copy( out_name, out );
+ }
+ out_file = fopen( out_name->value, "w" );
+
+ if ( !out_file )
+ {
+ printf( "failed to write output file '%s'!\n", out_name->value );
+ exit( EXITBAD );
+ }
+ string_free( out_name );
             }
+
+ if ( out_debug ) printf( "\nfile %s\n", out );
+
+ if ( out_file ) fputs( buf->value, out_file );
+ if ( out_debug ) fputs( buf->value, stdout );
             
- *(module_t * *)stack_allocate( s, sizeof( module_t * ) ) = outer_module;
+ if ( out_file )
+ {
+ fflush( out_file );
+ fclose( out_file );
+ }
+ string_free( buf );
+ if ( tmp_filename )
+ object_free( tmp_filename );
+
+ if ( out_debug ) fputc( '\n', stdout );
 
             break;
         }
 
+ case INSTR_OUTPUT_STRINGS:
+ {
+ string * buf = *(string * *)( (char *)stack_get( s ) + ( code->arg * sizeof( LIST * ) ) );
+ combine_strings( s, code->arg, buf );
+ break;
+ }
+
         }
         ++code;
     }
 }
 
+
+#ifdef HAVE_PYTHON
+
+static struct arg_list * arg_list_compile_python( PyObject * bjam_signature, int * num_arguments )
+{
+ if ( bjam_signature )
+ {
+ struct argument_list_compiler c[ 1 ];
+ struct arg_list * result;
+ Py_ssize_t s, i, j, inner;
+ argument_list_compiler_init( c );
+
+ s = PySequence_Size( bjam_signature );
+ for ( i = 0; i < s; ++i )
+ {
+ struct argument_compiler arg_comp[ 1 ];
+ struct arg_list arg;
+ PyObject * v = PySequence_GetItem( bjam_signature, i );
+ argument_compiler_init( arg_comp );
+
+ inner = PySequence_Size( v );
+ for ( j = 0; j < inner; ++j )
+ {
+ PyObject * x = PySequence_GetItem( v, j );
+ argument_compiler_add( arg_comp, object_new( PyString_AsString( x ) ), constant_builtin, -1 );
+ }
+
+ arg = arg_compile_impl( arg_comp, constant_builtin, -1 );
+ dynamic_array_push( c->args, arg );
+ argument_compiler_free( arg_comp );
+ Py_DECREF( v );
+ }
+
+ *num_arguments = c->args->size;
+ result = BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
+ memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list ) );
+ argument_list_compiler_free( c );
+ return result;
+ }
+ else
+ {
+ *num_arguments = 0;
+ return 0;
+ }
+}
+
+FUNCTION * function_python( PyObject * function, PyObject * bjam_signature )
+{
+ PYTHON_FUNCTION * result = BJAM_MALLOC( sizeof( PYTHON_FUNCTION ) );
+
+ result->base.type = FUNCTION_PYTHON;
+ result->base.reference_count = 1;
+ result->base.rulename = 0;
+ result->base.formal_arguments = arg_list_compile_python( bjam_signature, &result->base.num_formal_arguments );
+ Py_INCREF( function );
+ result->python_function = function;
+
+ return (FUNCTION *)result;
+}
+
+static void argument_list_to_python( struct arg_list * formal, int formal_count, FUNCTION * function, FRAME * frame, PyObject * kw )
+{
+ LOL * all_actual = frame->args;
+ int i, j;
+
+ for ( i = 0; i < formal_count; ++i )
+ {
+ LIST *actual = lol_get( all_actual, i );
+ LISTITER actual_iter = list_begin( actual ), actual_end = list_end( actual );
+ for ( j = 0; j < formal[i].size; ++j )
+ {
+ struct argument * formal_arg = &formal[i].args[j];
+ PyObject * value;
+ LIST * l;
+
+ switch ( formal_arg->flags )
+ {
+ case ARG_ONE:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
+ value = PyString_FromString( object_str( list_item( actual_iter) ) );
+ actual_iter = list_next( actual_iter );
+ break;
+ case ARG_OPTIONAL:
+ if ( actual_iter == actual_end )
+ value = 0;
+ else
+ {
+ type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
+ value = PyString_FromString( object_str( list_item( actual_iter) ) );
+ actual_iter = list_next( actual_iter );
+ }
+ break;
+ case ARG_PLUS:
+ if ( actual_iter == actual_end )
+ argument_error( "missing argument", function, frame, formal_arg->arg_name );
+ /* fallthrough */
+ case ARG_STAR:
+ type_check_range( formal_arg->type_name, actual_iter, actual_end, frame, function, formal_arg->arg_name );
+ l = list_copy_range( actual, actual_iter, actual_end );
+ value = list_to_python( l );
+ list_free( l );
+ actual_iter = actual_end;
+ break;
+ case ARG_VARIADIC:
+ return;
+ }
+
+ if (value)
+ {
+ PyObject * key = PyString_FromString( object_str( formal_arg->arg_name ) );
+ PyDict_SetItem( kw, key, value );
+ Py_DECREF( key );
+ Py_DECREF( value );
+ }
+ }
+
+ if ( actual_iter != actual_end )
+ {
+ argument_error( "extra argument", function, frame, list_item( actual_iter ) );
+ }
+ }
+
+ for ( ; i < all_actual->count; ++i )
+ {
+ LIST * actual = lol_get( all_actual, i );
+ if ( !list_empty( actual ) )
+ {
+ argument_error( "extra argument", function, frame, list_front( actual ) );
+ }
+ }
+}
+
+/* Given a Python object, return a string to use in Jam
+ code instead of said object.
+ If the object is string, use the string value
+ If the object implemenets __jam_repr__ method, use that.
+ Otherwise return 0. */
+OBJECT * python_to_string( PyObject * value )
+{
+ if ( PyString_Check( value ) )
+ {
+ return object_new( PyString_AsString( value ) );
+ }
+ else
+ {
+ /* See if this is an instance that defines special __jam_repr__
+ method. */
+ if ( PyInstance_Check( value )
+ && PyObject_HasAttrString( value, "__jam_repr__" ) )
+ {
+ PyObject* repr = PyObject_GetAttrString( value, "__jam_repr__" );
+ if ( repr )
+ {
+ PyObject * arguments2 = PyTuple_New( 0 );
+ PyObject * value2 = PyObject_Call( repr, arguments2, 0 );
+ Py_DECREF( repr );
+ Py_DECREF( arguments2 );
+ if ( PyString_Check( value2 ) )
+ {
+ return object_new( PyString_AsString( value2 ) );
+ }
+ Py_DECREF( value2 );
+ }
+ }
+ return 0;
+ }
+}
+
+static module_t * python_module()
+{
+ static module_t * python = 0;
+ if ( !python )
+ python = bindmodule(constant_python);
+ return python;
+}
+
+static LIST * call_python_function( PYTHON_FUNCTION * function, FRAME * frame )
+{
+ LIST * result = 0;
+ PyObject * arguments = 0;
+ PyObject * kw = NULL;
+ int i ;
+ PyObject * py_result;
+ FRAME * prev_frame_before_python_call;
+
+ if ( function->base.formal_arguments )
+ {
+ arguments = PyTuple_New(0);
+ kw = PyDict_New();
+
+ argument_list_to_python( function->base.formal_arguments, function->base.num_formal_arguments, &function->base, frame, kw );
+ }
+ else
+ {
+ arguments = PyTuple_New( frame->args->count );
+ for ( i = 0; i < frame->args->count; ++i )
+ {
+ PyTuple_SetItem( arguments, i, list_to_python( lol_get( frame->args, i ) ) );
+ }
+ }
+
+ frame->module = python_module();
+
+ prev_frame_before_python_call = frame_before_python_call;
+ frame_before_python_call = frame;
+ py_result = PyObject_Call( function->python_function, arguments, kw );
+ frame_before_python_call = prev_frame_before_python_call;
+ Py_DECREF( arguments );
+ Py_XDECREF( kw );
+ if ( py_result != NULL )
+ {
+ if ( PyList_Check( py_result ) )
+ {
+ int size = PyList_Size( py_result );
+ int i;
+ for ( i = 0; i < size; ++i )
+ {
+ PyObject * item = PyList_GetItem( py_result, i );
+ OBJECT *s = python_to_string( item );
+ if ( !s ) {
+ fprintf( stderr, "Non-string object returned by Python call.\n" );
+ } else {
+ result = list_push_back( result, s );
+ }
+ }
+ }
+ else if ( py_result == Py_None )
+ {
+ result = L0;
+ }
+ else
+ {
+ OBJECT *s = python_to_string( py_result );
+ if (s)
+ result = list_new( s );
+ else
+ /* We have tried all we could. Return empty list. There are
+ cases, e.g. feature.feature function that should return
+ value for the benefit of Python code and which also can be
+ called by Jam code, where no sensible value can be
+ returned. We cannot even emit a warning, since there will
+ be a pile of them. */
+ result = L0;
+ }
+
+ Py_DECREF( py_result );
+ }
+ else
+ {
+ PyErr_Print();
+ fprintf( stderr,"Call failed\n" );
+ }
+
+ return result;
+}
+
+#endif
+
+
 void function_done( void )
 {
     BJAM_FREE( stack );

Copied: branches/release/tools/build/v2/engine/function.h (from r75738, /trunk/tools/build/v2/engine/function.h)
==============================================================================
--- /trunk/tools/build/v2/engine/function.h (original)
+++ branches/release/tools/build/v2/engine/function.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,6 +11,7 @@
 #include "frames.h"
 #include "lists.h"
 #include "parse.h"
+#include "strings.h"
 
 typedef struct _function FUNCTION;
 typedef struct _stack STACK;
@@ -20,7 +21,7 @@
 LIST * stack_pop( STACK * s );
 
 FUNCTION * function_compile( PARSE * parse );
-FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ), int flags );
+FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ), int flags, const char * * args );
 void function_refer( FUNCTION * );
 void function_free( FUNCTION * );
 OBJECT * function_rulename( FUNCTION * );
@@ -28,6 +29,18 @@
 void function_location( FUNCTION *, OBJECT * *, int * );
 LIST * function_run( FUNCTION * function, FRAME * frame, STACK * s );
 
+FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int line );
+void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string * out );
+
+FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter );
+FUNCTION * function_unbind_variables( FUNCTION * f );
+
 void function_done( void );
 
+#ifdef HAVE_PYTHON
+
+FUNCTION * function_python( PyObject * function, PyObject * bjam_signature );
+
+#endif
+
 #endif

Modified: branches/release/tools/build/v2/engine/glob.c
==============================================================================
--- branches/release/tools/build/v2/engine/glob.c (original)
+++ branches/release/tools/build/v2/engine/glob.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -29,17 +29,17 @@
 # define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
 # define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
 
-static void globchars( char * s, char * e, char * b );
+static void globchars( const char * s, const char * e, char * b );
 
 
 /*
  * glob() - match a string against a simple pattern.
  */
 
-int glob( char * c, char * s )
+int glob( const char * c, const char * s )
 {
     char bitlist[ BITLISTSIZE ];
- char * here;
+ const char * here;
 
     for ( ; ; )
     switch ( *c++ )
@@ -64,7 +64,7 @@
 
         globchars( here, c, bitlist );
 
- if ( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
+ if ( !CHECK_BIT( bitlist, *(const unsigned char *)s ) )
             return 1;
         ++s;
         break;
@@ -111,7 +111,7 @@
  * globchars() - build a bitlist to check for character group match.
  */
 
-static void globchars( char * s, char * e, char * b )
+static void globchars( const char * s, const char * e, char * b )
 {
     int neg = 0;
 

Modified: branches/release/tools/build/v2/engine/hash.c
==============================================================================
--- branches/release/tools/build/v2/engine/hash.c (original)
+++ branches/release/tools/build/v2/engine/hash.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -7,6 +7,7 @@
 # include "jam.h"
 # include "hash.h"
 # include "compile.h"
+# include "object.h"
 # include <assert.h>
 
 /*
@@ -29,30 +30,16 @@
 #define HASH_DEBUG_PROFILE 1
 /* */
 
-char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
-
 /* Header attached to all data items entered into a hash table. */
 
 struct hashhdr
 {
     struct item * next;
- unsigned int keyval; /* for quick comparisons */
-};
-
-/* This structure overlays the one handed to hashenter(). Its actual size is
- * given to hashinit().
- */
-
-struct hashdata
-{
- char * key;
- /* rest of user data */
 };
 
 typedef struct item
 {
     struct hashhdr hdr;
- struct hashdata data;
 } ITEM ;
 
 # define MAX_LISTS 32
@@ -78,7 +65,6 @@
         int more; /* how many more ITEMs fit in lists[ list ] */
         ITEM *free; /* free list of items */
         char *next; /* where to put more ITEMs in lists[ list ] */
- int datalen; /* length of records in this hash table */
         int size; /* sizeof( ITEM ) + aligned datalen */
         int nel; /* total ITEMs held by all lists[] */
         int list; /* index into lists[] */
@@ -89,54 +75,23 @@
         } lists[ MAX_LISTS ];
     } items;
 
- char * name; /* just for hashstats() */
+ const char * name; /* just for hashstats() */
 };
 
 static void hashrehash( struct hash *hp );
 static void hashstat( struct hash *hp );
-static void * hash_mem_alloc(size_t datalen, size_t size);
-static void hash_mem_free(size_t datalen, void * data);
-#ifdef OPT_BOEHM_GC
-static void hash_mem_finalizer(char * key, struct hash * hp);
-#endif
-
-static unsigned int jenkins_one_at_a_time_hash(const unsigned char *key)
-{
- unsigned int hash = 0;
-
- while ( *key )
- {
- hash += *key++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash;
-}
-
-/*
-static unsigned int knuth_hash(const unsigned char *key)
-{
- unsigned int keyval = *key;
- while ( *key )
- keyval = keyval * 2147059363 + *key++;
- return keyval;
-}
-*/
 
-static unsigned int hash_keyval( const char * key_ )
+static unsigned int hash_keyval( OBJECT * key )
 {
- /*
- return knuth_hash((const unsigned char *)key_);
- */
- return jenkins_one_at_a_time_hash((const unsigned char *)key_);
+ return object_hash( key );
 }
 
 #define hash_bucket(hp,keyval) ((hp)->tab.base + ( (keyval) % (hp)->tab.nel ))
 
+#define hash_data_key(data) (*(OBJECT * *)(data))
+#define hash_item_data(item) ((HASHDATA *)((char *)item + sizeof(struct hashhdr)))
+#define hash_item_key(item) (hash_data_key(hash_item_data(item)))
+
 /* Find the hash item for the given data. Returns pointer to the
     item and if given a pointer to the item before the found item.
     If it's the first item in a bucket, there is no previous item,
@@ -145,7 +100,7 @@
 static ITEM * hash_search(
     struct hash *hp,
     unsigned int keyval,
- const char * keydata,
+ OBJECT * keydata,
     ITEM * * previous )
 {
     ITEM * i = *hash_bucket(hp,keyval);
@@ -153,8 +108,7 @@
 
     for ( ; i; i = i->hdr.next )
     {
- if ( ( keyval == i->hdr.keyval ) &&
- !strcmp( i->data.key, keydata ) )
+ if ( object_equal( hash_item_key( i ), keydata ) )
         {
             if (previous)
             {
@@ -169,52 +123,13 @@
 }
 
 /*
- * hash_free() - remove the given item from the table if it's there.
- * Returns 1 if found, 0 otherwise.
- *
- * NOTE: 2nd argument is HASHDATA*, not HASHDATA** as elsewhere.
- */
-int
-hash_free(
- register struct hash *hp,
- HASHDATA *data)
-{
- ITEM * i = 0;
- ITEM * prev = 0;
- unsigned int keyval = hash_keyval(data->key);
-
- i = hash_search( hp, keyval, data->key, &prev );
- if (i)
- {
- /* mark it free so we skip it during enumeration */
- i->data.key = 0;
- /* unlink the record from the hash chain */
- if (prev) prev->hdr.next = i->hdr.next;
- else *hash_bucket(hp,keyval) = i->hdr.next;
- /* link it into the freelist */
- i->hdr.next = hp->items.free;
- hp->items.free = i;
- /* we have another item */
- hp->items.more++;
-
- return 1;
- }
- return 0;
-}
-
-/*
- * hashitem() - find a record in the table, and optionally enter a new one
+ * hash_insert() - insert a record in the table or return the existing one
  */
 
-int
-hashitem(
- register struct hash *hp,
- HASHDATA **data,
- int enter )
-{
- register ITEM *i;
- char *b = (*data)->key;
- unsigned int keyval = hash_keyval(b);
+HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
+{
+ ITEM * i;
+ unsigned int keyval = hash_keyval( key );
 
     #ifdef HASH_DEBUG_PROFILE
     profile_frame prof[1];
@@ -222,38 +137,24 @@
         profile_enter( 0, prof );
     #endif
 
- if ( enter && !hp->items.more )
+ if ( !hp->items.more )
         hashrehash( hp );
 
- if ( !enter && !hp->items.nel )
+ i = hash_search( hp, keyval, key, 0 );
+ if ( i )
     {
- #ifdef HASH_DEBUG_PROFILE
- if ( DEBUG_PROFILE )
- profile_exit( prof );
- #endif
- return 0;
+ *found = 1;
     }
-
- i = hash_search( hp, keyval, (*data)->key, 0 );
- if (i)
- {
- *data = &i->data;
- #ifdef HASH_DEBUG_PROFILE
- if ( DEBUG_PROFILE ) profile_exit( prof );
- #endif
- return !0;
- }
-
- if ( enter )
+ else
     {
- ITEM * * base = hash_bucket(hp,keyval);
+ ITEM * * base = hash_bucket( hp, keyval );
 
         /* try to grab one from the free list */
         if ( hp->items.free )
         {
             i = hp->items.free;
             hp->items.free = i->hdr.next;
- assert( i->data.key == 0 );
+ assert( hash_item_key( i ) == 0 );
         }
         else
         {
@@ -261,24 +162,58 @@
             hp->items.next += hp->items.size;
         }
         hp->items.more--;
- memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
- i->hdr.keyval = keyval;
         i->hdr.next = *base;
         *base = i;
- *data = &i->data;
- #ifdef OPT_BOEHM_GC
- if (sizeof(HASHDATA) == hp->items.datalen)
- {
- GC_REGISTER_FINALIZER(i->data.key,&hash_mem_finalizer,hp,0,0);
- }
+ *found = 0;
+ }
+
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
+
+ return hash_item_data( i );
+}
+
+/*
+ * hash_find() - find a record in the table or NULL if none exists
+ */
+
+HASHDATA * hash_find( struct hash *hp, OBJECT *key )
+{
+ ITEM *i;
+ unsigned int keyval = hash_keyval(key);
+
+ #ifdef HASH_DEBUG_PROFILE
+ profile_frame prof[1];
+ if ( DEBUG_PROFILE )
+ profile_enter( 0, prof );
+ #endif
+
+ if ( !hp->items.nel )
+ {
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
         #endif
+ return 0;
     }
 
+ i = hash_search( hp, keyval, key, 0 );
+
     #ifdef HASH_DEBUG_PROFILE
     if ( DEBUG_PROFILE )
         profile_exit( prof );
     #endif
- return 0;
+
+ if (i)
+ {
+ return hash_item_data( i );
+ }
+ else
+ {
+ return 0;
+ }
 }
 
 /*
@@ -289,7 +224,7 @@
 {
     int i = ++hp->items.list;
     hp->items.more = i ? 2 * hp->items.nel : hp->inel;
- hp->items.next = (char *)hash_mem_alloc( hp->items.datalen, hp->items.more * hp->items.size );
+ hp->items.next = (char *)BJAM_MALLOC( hp->items.more * hp->items.size );
     hp->items.free = 0;
 
     hp->items.lists[i].nel = hp->items.more;
@@ -297,10 +232,10 @@
     hp->items.nel += hp->items.more;
 
     if ( hp->tab.base )
- hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
+ BJAM_FREE( (char *)hp->tab.base );
 
     hp->tab.nel = hp->items.nel * hp->bloat;
- hp->tab.base = (ITEM **)hash_mem_alloc( hp->items.datalen, hp->tab.nel * sizeof(ITEM **) );
+ hp->tab.base = (ITEM **)BJAM_MALLOC( hp->tab.nel * sizeof(ITEM **) );
 
     memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
 
@@ -312,9 +247,9 @@
         for ( ; nel--; next += hp->items.size )
         {
             register ITEM *i = (ITEM *)next;
- ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
+ ITEM **ip = hp->tab.base + object_hash( hash_item_key( i ) ) % hp->tab.nel;
             /* code currently assumes rehashing only when there are no free items */
- assert( i->data.key != 0 );
+ assert( hash_item_key( i ) != 0 );
 
             i->hdr.next = *ip;
             *ip = i;
@@ -335,8 +270,8 @@
         for ( ; nel--; next += hp->items.size )
         {
             ITEM * i = (ITEM *)next;
- if ( i->data.key != 0 ) /* DO not enumerate freed items. */
- f( &i->data, data );
+ if ( hash_item_key( i ) != 0 ) /* DO not enumerate freed items. */
+ f( hash_item_data( i ), data );
         }
     }
 }
@@ -352,16 +287,15 @@
 struct hash *
 hashinit(
     int datalen,
- char *name )
+ const char *name )
 {
- struct hash *hp = (struct hash *)hash_mem_alloc( datalen, sizeof( *hp ) );
+ struct hash *hp = (struct hash *)BJAM_MALLOC( sizeof( *hp ) );
 
     hp->bloat = 3;
     hp->tab.nel = 0;
     hp->tab.base = (ITEM **)0;
     hp->items.more = 0;
     hp->items.free = 0;
- hp->items.datalen = datalen;
     hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
     hp->items.list = -1;
     hp->items.nel = 0;
@@ -371,89 +305,92 @@
     return hp;
 }
 
+void hashdone( struct hash * hp )
+{
+ if ( !hp )
+ return;
+ if ( DEBUG_MEM || DEBUG_PROFILE )
+ hashstat( hp );
+ hash_free( hp );
+}
+
 /*
- * hashdone() - free a hash table, given its handle
+ * hash_free() - free a hash table, given its handle
  */
 
 void
-hashdone( struct hash *hp )
+hash_free( struct hash * hp )
 {
     int i;
 
     if ( !hp )
         return;
 
- if ( DEBUG_MEM || DEBUG_PROFILE )
- hashstat( hp );
-
     if ( hp->tab.base )
- hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
+ BJAM_FREE( (char *)hp->tab.base );
     for ( i = 0; i <= hp->items.list; ++i )
- hash_mem_free( hp->items.datalen, hp->items.lists[i].base );
- hash_mem_free( hp->items.datalen, (char *)hp );
+ BJAM_FREE( hp->items.lists[i].base );
+ BJAM_FREE( (char *)hp );
 }
 
-static void * hash_mem_alloc(size_t datalen, size_t size)
-{
- if (sizeof(HASHDATA) == datalen)
- {
- return BJAM_MALLOC_RAW(size);
- }
- else
- {
- return BJAM_MALLOC(size);
- }
-}
 
-static void hash_mem_free(size_t datalen, void * data)
+/* ---- */
+
+static void hashstat( struct hash * hp )
 {
- if (sizeof(HASHDATA) == datalen)
- {
- BJAM_FREE_RAW(data);
- }
- else
- {
- BJAM_FREE(data);
- }
+ struct hashstats stats[ 1 ];
+ hashstats_init( stats );
+ hashstats_add( stats, hp );
+ hashstats_print( stats, hp->name );
 }
 
-#ifdef OPT_BOEHM_GC
-static void hash_mem_finalizer(char * key, struct hash * hp)
+void hashstats_init( struct hashstats * stats )
 {
- HASHDATA d;
- d.key = key;
- hash_free(hp,&d);
+ stats->count = 0;
+ stats->num_items = 0;
+ stats->tab_size = 0;
+ stats->item_size = 0;
+ stats->sets = 0;
 }
-#endif
 
-
-/* ---- */
-
-static void hashstat( struct hash * hp )
+void hashstats_add( struct hashstats * stats, struct hash * hp )
 {
- ITEM * * tab = hp->tab.base;
- int nel = hp->tab.nel;
- int count = 0;
- int sets = 0;
- int run = ( tab[ nel - 1 ] != (ITEM *)0 );
- int i;
- int here;
-
- for ( i = nel; i > 0; --i )
+ if ( hp )
     {
- if ( ( here = ( *tab++ != (ITEM *)0 ) ) )
- count++;
- if ( here && !run )
- sets++;
- run = here;
+ ITEM * * tab = hp->tab.base;
+ int nel = hp->tab.nel;
+ int count = 0;
+ int sets = 0;
+ int i;
+
+ for ( i = 0; i < nel; ++i )
+ {
+ ITEM * item;
+ int here = 0;
+ for ( item = tab[ i ]; item != 0; item = item->hdr.next )
+ ++here;
+
+ count += here;
+ if ( here > 0 )
+ ++sets;
+ }
+
+ stats->count += count;
+ stats->sets += sets;
+ stats->num_items += hp->items.nel;
+ stats->tab_size += hp->tab.nel;
+ stats->item_size = hp->items.size;
     }
+}
 
+void hashstats_print( struct hashstats * stats, const char * name )
+{
     printf( "%s table: %d+%d+%d (%dK+%luK) items+table+hash, %f density\n",
- hp->name,
- count,
- hp->items.nel,
- hp->tab.nel,
- hp->items.nel * hp->items.size / 1024,
- (long unsigned)hp->tab.nel * sizeof( ITEM ** ) / 1024,
- (float)count / (float)sets );
+ name,
+ stats->count,
+ stats->num_items,
+ stats->tab_size,
+ stats->num_items * stats->item_size / 1024,
+ (long unsigned)stats->tab_size * sizeof( ITEM ** ) / 1024,
+ (float)stats->count / (float)stats->sets );
 }

Modified: branches/release/tools/build/v2/engine/hash.h
==============================================================================
--- branches/release/tools/build/v2/engine/hash.h (original)
+++ branches/release/tools/build/v2/engine/hash.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,15 +11,68 @@
 #ifndef BOOST_JAM_HASH_H
 #define BOOST_JAM_HASH_H
 
+/*
+ * An opaque struct representing an item in the
+ * hash table. The first element of every struct
+ * stored in the table must be an OBJECT * which
+ * is treated as the key.
+ */
 typedef struct hashdata HASHDATA;
 
-struct hash * hashinit ( int datalen, char * name );
-int hashitem ( struct hash * hp, HASHDATA * * data, int enter );
-void hashdone ( struct hash * hp );
+/*
+ * hashinit() - initialize a hash table, returning a handle.
+ * datalen is the size of the items. name is used for debugging.
+ */
+struct hash * hashinit ( int datalen, const char * name );
+
+/*
+ * hash_free() - free a hash table, given its handle
+ */
+void hash_free( struct hash * hp );
+void hashdone( struct hash * hp );
+
+/*
+ * hashenumerate() - call f(i, data) on each item, i in the hash
+ * table. The order of the items is unspecified.
+ */
 void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data );
-int hash_free ( struct hash * hp, HASHDATA * data);
 
-#define hashenter( hp, data ) ( !hashitem( hp, data, !0 ) )
-#define hashcheck( hp, data ) hashitem( hp, data, 0 )
+/*
+ * hash_insert() - insert a new item in a hash table, or return an
+ * existing one.
+ *
+ * Preconditions:
+ * - hp must be a hash table created by hashinit
+ * - key must be an object created by object_new
+ *
+ * Postconditions:
+ * - if the key does not already exist in the hash
+ * table, *found == 0 and the result will be a
+ * pointer to an uninitialized item. The key
+ * of the new item must be set to a value equal to
+ * key before any further operations on the
+ * hash table except hashdone.
+ * - if the key is present then *found == 1 and
+ * the result is a pointer to the existing
+ * record.
+ */
+HASHDATA * hash_insert ( struct hash * hp, OBJECT * key, int * found );
+
+/*
+ * hash_find() - find a record in the table or NULL if none exists
+ */
+HASHDATA * hash_find ( struct hash * hp, OBJECT * key );
+
+struct hashstats {
+ int count;
+ int num_items;
+ int tab_size;
+ int item_size;
+ int sets;
+};
+
+void hashstats_init( struct hashstats * stats );
+void hashstats_add( struct hashstats * stats, struct hash * hp );
+void hashstats_print( struct hashstats * stats, const char * name );
 
 #endif

Modified: branches/release/tools/build/v2/engine/hcache.c
==============================================================================
--- branches/release/tools/build/v2/engine/hcache.c (original)
+++ branches/release/tools/build/v2/engine/hcache.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,11 +8,12 @@
 # include "rules.h"
 # include "regexp.h"
 # include "headers.h"
-# include "newstr.h"
+# include "object.h"
 # include "hash.h"
 # include "hcache.h"
 # include "variable.h"
 # include "search.h"
+# include "modules.h"
 
 #ifdef OPT_HEADER_CACHE_EXT
 
@@ -43,7 +44,7 @@
 
 struct hcachedata
 {
- char * boundname;
+ OBJECT * boundname;
     time_t time;
     LIST * includes;
     LIST * hdrscan; /* the HDRSCAN value for this target */
@@ -70,30 +71,30 @@
  * the result so the user can not change the cache file during header scanning.
  */
 
-static char * cache_name( void )
+static const char * cache_name( void )
 {
- static char * name = 0;
+ static OBJECT * name = 0;
     if ( !name )
     {
- LIST * hcachevar = var_get( "HCACHEFILE" );
+ LIST * hcachevar = var_get( root_module(), constant_HCACHEFILE );
 
- if ( hcachevar )
+ if ( !list_empty( hcachevar ) )
         {
- TARGET * t = bindtarget( hcachevar->string );
+ TARGET * t = bindtarget( list_front( hcachevar ) );
 
- pushsettings( t->settings );
+ pushsettings( root_module(), t->settings );
             /* Do not expect the cache file to be generated, so pass 0 as the
              * third argument to search. Expect the location to be specified via
              * LOCATE, so pass 0 as the fourth arugment.
              */
+ object_free( t->boundname );
             t->boundname = search( t->name, &t->time, 0, 0 );
- popsettings( t->settings );
+ popsettings( root_module(), t->settings );
 
- if ( hcachevar )
- name = copystr( t->boundname );
+ name = object_copy( t->boundname );
         }
     }
- return name;
+ return name ? object_str( name ) : 0;
 }
 
 
@@ -105,10 +106,10 @@
 static int cache_maxage( void )
 {
     int age = 100;
- LIST * var = var_get( "HCACHEMAXAGE" );
- if ( var )
+ LIST * var = var_get( root_module(), constant_HCACHEMAXAGE );
+ if ( !list_empty( var ) )
     {
- age = atoi( var->string );
+ age = atoi( object_str( list_front( var ) ) );
         if ( age < 0 )
             age = 0;
     }
@@ -118,10 +119,10 @@
 
 /*
  * Read a netstring. The caveat is that the string can not contain ASCII 0. The
- * returned value is as returned by newstr(), so it need not be freed.
+ * returned value is as returned by object_new().
  */
 
-char * read_netstring( FILE * f )
+OBJECT * read_netstring( FILE * f )
 {
     unsigned long len;
     static char * buf = NULL;
@@ -154,7 +155,7 @@
         return NULL;
 
     buf[ len ] = 0;
- return newstr( buf );
+ return object_new( buf );
 }
 
 
@@ -172,12 +173,13 @@
 
 void hcache_init()
 {
- HCACHEDATA cachedata;
- HCACHEDATA * c;
     FILE * f;
- char * version;
+ OBJECT * version = 0;
     int header_count = 0;
- char * hcachename;
+ const char * hcachename;
+
+ if ( hcachehash )
+ return;
 
     hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" );
 
@@ -188,105 +190,144 @@
         return;
 
     version = read_netstring( f );
- if ( !version || strcmp( version, CACHE_FILE_VERSION ) )
- {
- fclose( f );
- return;
- }
+
+ if ( !version || strcmp( object_str( version ), CACHE_FILE_VERSION ) )
+ goto bail;
 
     while ( 1 )
     {
- char * record_type;
- char * time_str;
- char * age_str;
- char * includes_count_str;
- char * hdrscan_count_str;
- int i;
- int count;
- LIST * l;
+ HCACHEDATA cachedata;
+ HCACHEDATA * c;
+ OBJECT * record_type = 0;
+ OBJECT * time_str = 0;
+ OBJECT * age_str = 0;
+ OBJECT * includes_count_str = 0;
+ OBJECT * hdrscan_count_str = 0;
+ int i;
+ int count;
+ LIST * l;
+ int found;
+
+ cachedata.boundname = 0;
+ cachedata.includes = 0;
+ cachedata.hdrscan = 0;
 
         record_type = read_netstring( f );
         if ( !record_type )
         {
             fprintf( stderr, "invalid %s\n", hcachename );
- goto bail;
+ goto cleanup;
         }
- if ( !strcmp( record_type, CACHE_RECORD_END ) )
+ if ( !strcmp( object_str( record_type ), CACHE_RECORD_END ) )
+ {
+ object_free( record_type );
             break;
- if ( strcmp( record_type, CACHE_RECORD_HEADER ) )
+ }
+ if ( strcmp( object_str( record_type ), CACHE_RECORD_HEADER ) )
         {
             fprintf( stderr, "invalid %s with record separator <%s>\n",
- hcachename, record_type ? record_type : "<null>" );
- goto bail;
+ hcachename, record_type ? object_str( record_type ) : "<null>" );
+ goto cleanup;
         }
 
- c = &cachedata;
-
- c->boundname = read_netstring( f );
- time_str = read_netstring( f );
- age_str = read_netstring( f );
- includes_count_str = read_netstring( f );
+ cachedata.boundname = read_netstring( f );
+ time_str = read_netstring( f );
+ age_str = read_netstring( f );
+ includes_count_str = read_netstring( f );
 
- if ( !c->boundname || !time_str || !age_str || !includes_count_str )
+ if ( !cachedata.boundname || !time_str || !age_str || !includes_count_str )
         {
             fprintf( stderr, "invalid %s\n", hcachename );
- goto bail;
+ goto cleanup;
         }
 
- c->time = atoi( time_str );
- c->age = atoi( age_str ) + 1;
+ cachedata.time = atoi( object_str( time_str ) );
+ cachedata.age = atoi( object_str( age_str ) ) + 1;
 
- count = atoi( includes_count_str );
- for ( l = 0, i = 0; i < count; ++i )
+ count = atoi( object_str( includes_count_str ) );
+ for ( l = L0, i = 0; i < count; ++i )
         {
- char * s = read_netstring( f );
+ OBJECT * s = read_netstring( f );
             if ( !s )
             {
                 fprintf( stderr, "invalid %s\n", hcachename );
- goto bail;
+ list_free( l );
+ goto cleanup;
             }
- l = list_new( l, s );
+ l = list_push_back( l, s );
         }
- c->includes = l;
+ cachedata.includes = l;
 
         hdrscan_count_str = read_netstring( f );
- if ( !includes_count_str )
+ if ( !hdrscan_count_str )
         {
- list_free( c->includes );
             fprintf( stderr, "invalid %s\n", hcachename );
- goto bail;
+ goto cleanup;
         }
 
- count = atoi( hdrscan_count_str );
- for ( l = 0, i = 0; i < count; ++i )
+ count = atoi( object_str( hdrscan_count_str ) );
+ for ( l = L0, i = 0; i < count; ++i )
         {
- char * s = read_netstring( f );
+ OBJECT * s = read_netstring( f );
             if ( !s )
             {
                 fprintf( stderr, "invalid %s\n", hcachename );
- goto bail;
+ list_free( l );
+ goto cleanup;
             }
- l = list_new( l, s );
+ l = list_push_back( l, s );
         }
- c->hdrscan = l;
+ cachedata.hdrscan = l;
 
- if ( !hashenter( hcachehash, (HASHDATA * *)&c ) )
+ c = (HCACHEDATA *)hash_insert( hcachehash, cachedata.boundname, &found );
+ if ( !found )
+ {
+ c->boundname = cachedata.boundname;
+ c->time = cachedata.time;
+ c->includes = cachedata.includes;
+ c->hdrscan = cachedata.hdrscan;
+ c->age = cachedata.age;
+ }
+ else
         {
             fprintf( stderr, "can't insert header cache item, bailing on %s\n",
                 hcachename );
- goto bail;
+ goto cleanup;
         }
 
         c->next = hcachelist;
         hcachelist = c;
 
         ++header_count;
+
+ object_free( record_type );
+ object_free( time_str );
+ object_free( age_str );
+ object_free( includes_count_str );
+ object_free( hdrscan_count_str );
+ continue;
+
+cleanup:
+
+ if ( record_type ) object_free( record_type );
+ if ( time_str ) object_free( time_str );
+ if ( age_str ) object_free( age_str );
+ if ( includes_count_str ) object_free( includes_count_str );
+ if ( hdrscan_count_str ) object_free( hdrscan_count_str );
+
+ if ( cachedata.boundname ) object_free( cachedata.boundname );
+ if ( cachedata.includes ) list_free( cachedata.includes );
+ if ( cachedata.hdrscan ) list_free( cachedata.hdrscan );
+
+ goto bail;
     }
 
     if ( DEBUG_HEADER )
         printf( "hcache read from file %s\n", hcachename );
 
- bail:
+bail:
+ if ( version )
+ object_free( version );
     fclose( f );
 }
 
@@ -296,17 +337,17 @@
     FILE * f;
     HCACHEDATA * c;
     int header_count = 0;
- char * hcachename;
+ const char * hcachename;
     int maxage;
 
     if ( !hcachehash )
         return;
 
     if ( !( hcachename = cache_name() ) )
- return;
+ goto cleanup;
 
     if ( !( f = fopen( hcachename, "wb" ) ) )
- return;
+ goto cleanup;
 
     maxage = cache_maxage();
 
@@ -316,7 +357,7 @@
     c = hcachelist;
     for ( c = hcachelist; c; c = c->next )
     {
- LIST * l;
+ LISTITER iter, end;
         char time_str[ 30 ];
         char age_str[ 30 ];
         char includes_count_str[ 30 ];
@@ -333,15 +374,17 @@
         sprintf( age_str, "%lu", (long unsigned) c->age );
 
         write_netstring( f, CACHE_RECORD_HEADER );
- write_netstring( f, c->boundname );
+ write_netstring( f, object_str( c->boundname ) );
         write_netstring( f, time_str );
         write_netstring( f, age_str );
         write_netstring( f, includes_count_str );
- for ( l = c->includes; l; l = list_next( l ) )
- write_netstring( f, l->string );
+ for ( iter = list_begin( c->includes ), end = list_end( c->includes );
+ iter != end; iter = list_next( iter ) )
+ write_netstring( f, object_str( list_item( iter ) ) );
         write_netstring( f, hdrscan_count_str );
- for ( l = c->hdrscan; l; l = list_next( l ) )
- write_netstring( f, l->string );
+ for ( iter = list_begin( c->hdrscan ), end = list_end( c->hdrscan );
+ iter != end; iter = list_next( iter ) )
+ write_netstring( f, object_str( list_item( iter ) ) );
         fputs( "\n", f );
         ++header_count;
     }
@@ -352,81 +395,110 @@
             hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
 
     fclose ( f );
+
+cleanup:
+ for ( c = hcachelist; c; c = c->next )
+ {
+ list_free( c->includes );
+ list_free( c->hdrscan );
+ object_free( c->boundname );
+ }
+
+ hcachelist = 0;
+ if ( hcachehash )
+ hashdone( hcachehash );
+ hcachehash = 0;
 }
 
 
 LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
 {
- HCACHEDATA cachedata;
- HCACHEDATA * c = &cachedata;
+ HCACHEDATA * c;
 
     LIST * l = 0;
 
     ++queries;
 
- c->boundname = t->boundname;
-
- if (hashcheck (hcachehash, (HASHDATA **) &c))
- {
- if (c->time == t->time)
+ if ( ( c = (HCACHEDATA *)hash_find( hcachehash, t->boundname ) ) )
     {
- LIST *l1 = hdrscan, *l2 = c->hdrscan;
- while (l1 && l2) {
- if (l1->string != l2->string) {
- l1 = NULL;
- } else {
- l1 = list_next(l1);
- l2 = list_next(l2);
- }
- }
- if (l1 || l2) {
- if (DEBUG_HEADER)
- printf("HDRSCAN out of date in cache for %s\n",
- t->boundname);
-
- printf("HDRSCAN out of date for %s\n", t->boundname);
- printf(" real : ");
- list_print(hdrscan);
- printf("\n cached: ");
- list_print(c->hdrscan);
- printf("\n");
-
- list_free(c->includes);
- list_free(c->hdrscan);
- c->includes = 0;
- c->hdrscan = 0;
- } else {
- if (DEBUG_HEADER)
- printf ("using header cache for %s\n", t->boundname);
- c->age = 0;
- ++hits;
- l = list_copy (0, c->includes);
- return l;
- }
- } else {
- if (DEBUG_HEADER)
- printf ("header cache out of date for %s\n", t->boundname);
- list_free (c->includes);
- list_free(c->hdrscan);
- c->includes = 0;
- c->hdrscan = 0;
- }
- } else {
- if (hashenter (hcachehash, (HASHDATA **)&c)) {
- c->boundname = newstr (c->boundname);
- c->next = hcachelist;
- hcachelist = c;
+ if ( c->time == t->time )
+ {
+ LIST *l1 = hdrscan, *l2 = c->hdrscan;
+ LISTITER iter1 = list_begin( l1 ), end1 = list_end( l1 ),
+ iter2 = list_begin( l2 ), end2 = list_end( l2 );
+ while ( iter1 != end1 && iter2 != end2 )
+ {
+ if ( !object_equal( list_item( iter1 ), list_item( iter2 ) ) )
+ {
+ iter1 = end1;
+ }
+ else
+ {
+ iter1 = list_next( iter1 );
+ iter2 = list_next( iter2 );
+ }
+ }
+ if ( iter1 != end1 || iter2 != end2 )
+ {
+ if (DEBUG_HEADER)
+ printf( "HDRSCAN out of date in cache for %s\n",
+ object_str( t->boundname ) );
+
+ printf( "HDRSCAN out of date for %s\n",
+ object_str( t->boundname ) );
+ printf(" real : ");
+ list_print( hdrscan );
+ printf( "\n cached: " );
+ list_print( c->hdrscan );
+ printf( "\n" );
+
+ list_free( c->includes );
+ list_free( c->hdrscan );
+ c->includes = L0;
+ c->hdrscan = L0;
+ }
+ else
+ {
+ if (DEBUG_HEADER)
+ printf( "using header cache for %s\n",
+ object_str( t->boundname ) );
+ c->age = 0;
+ ++hits;
+ l = list_copy( c->includes );
+ return l;
+ }
+ }
+ else
+ {
+ if (DEBUG_HEADER)
+ printf ("header cache out of date for %s\n",
+ object_str( t->boundname ) );
+ list_free( c->includes );
+ list_free( c->hdrscan );
+ c->includes = L0;
+ c->hdrscan = L0;
+ }
     }
+ else
+ {
+ int found;
+ c = (HCACHEDATA *)hash_insert( hcachehash, t->boundname, &found );
+ if ( !found )
+ {
+ c->boundname = object_copy( t->boundname );
+ c->next = hcachelist;
+ hcachelist = c;
+ }
     }
 
     /* 'c' points at the cache entry. Its out of date. */
 
- l = headers1 (0, t->boundname, rec, re);
+ l = headers1( L0, t->boundname, rec, re );
 
     c->time = t->time;
     c->age = 0;
- c->includes = list_copy (0, l);
- c->hdrscan = list_copy(0, hdrscan);
+ c->includes = list_copy( l );
+ c->hdrscan = list_copy( hdrscan );
 
     return l;
 }

Modified: branches/release/tools/build/v2/engine/hcache.h
==============================================================================
--- branches/release/tools/build/v2/engine/hcache.h (original)
+++ branches/release/tools/build/v2/engine/hcache.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,8 +11,8 @@
 # include "regexp.h"
 # include "lists.h"
 
-void hcache_init(void);
-void hcache_done(void);
-LIST *hcache(TARGET *t, int rec, regexp *re[], LIST *hdrscan);
+void hcache_init( void );
+void hcache_done( void );
+LIST * hcache( TARGET *t, int rec, regexp * re[], LIST * hdrscan );
 
 #endif

Modified: branches/release/tools/build/v2/engine/hdrmacro.c
==============================================================================
--- branches/release/tools/build/v2/engine/hdrmacro.c (original)
+++ branches/release/tools/build/v2/engine/hdrmacro.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -19,7 +19,7 @@
 # include "regexp.h"
 # include "hdrmacro.h"
 # include "hash.h"
-# include "newstr.h"
+# include "object.h"
 # include "strings.h"
 
 /*
@@ -49,8 +49,8 @@
 /* this type is used to store a dictionary of file header macros */
 typedef struct header_macro
 {
- char * symbol;
- char * filename; /* we could maybe use a LIST here ?? */
+ OBJECT * symbol;
+ OBJECT * filename; /* we could maybe use a LIST here ?? */
 } HEADER_MACRO;
 
 static struct hash * header_macros_hash = 0;
@@ -63,26 +63,28 @@
 # define MAXINC 10
 
 void
-macro_headers( TARGET *t )
+macro_headers( TARGET * t )
 {
     static regexp *re = 0;
     FILE *f;
     char buf[ 1024 ];
 
     if ( DEBUG_HEADER )
- printf( "macro header scan for %s\n", t->name );
+ printf( "macro header scan for %s\n", object_str( t->name ) );
 
     /* this regexp is used to detect lines of the form */
     /* "#define MACRO <....>" or "#define MACRO "....." */
     /* in the header macro files.. */
     if ( re == 0 )
     {
- re = regex_compile(
+ OBJECT * re_str = object_new(
             "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
             "[<\"]([^\">]*)[\">].*$" );
+ re = regex_compile( re_str );
+ object_free( re_str );
     }
 
- if ( !( f = fopen( t->boundname, "r" ) ) )
+ if ( !( f = fopen( object_str( t->boundname ), "r" ) ) )
         return;
 
     while ( fgets( buf, sizeof( buf ), f ) )
@@ -92,24 +94,30 @@
 
         if ( regexec( re, buf ) && re->startp[1] )
         {
+ OBJECT * symbol;
+ int found;
             /* we detected a line that looks like "#define MACRO filename */
- re->endp[1][0] = '\0';
- re->endp[2][0] = '\0';
+ ((char *)re->endp[1])[0] = '\0';
+ ((char *)re->endp[2])[0] = '\0';
 
             if ( DEBUG_HEADER )
                 printf( "macro '%s' used to define filename '%s' in '%s'\n",
- re->startp[1], re->startp[2], t->boundname );
+ re->startp[1], re->startp[2], object_str( t->boundname ) );
 
             /* add macro definition to hash table */
             if ( !header_macros_hash )
                 header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" );
 
- v->symbol = re->startp[1];
- v->filename = 0;
- if ( hashenter( header_macros_hash, (HASHDATA **)&v ) )
+ symbol = object_new( re->startp[1] );
+ v = (HEADER_MACRO *)hash_insert( header_macros_hash, symbol, &found );
+ if ( !found )
             {
- v->symbol = newstr( re->startp[1] ); /* never freed */
- v->filename = newstr( re->startp[2] ); /* never freed */
+ v->symbol = symbol;
+ v->filename = object_new( re->startp[2] ); /* never freed */
+ }
+ else
+ {
+ object_free( symbol );
             }
             /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */
             /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */
@@ -120,17 +128,14 @@
 }
 
 
-char * macro_header_get( const char * macro_name )
+OBJECT * macro_header_get( OBJECT * macro_name )
 {
- HEADER_MACRO var;
- HEADER_MACRO * v = &var;
-
- v->symbol = (char* )macro_name;
+ HEADER_MACRO * v;
 
- if ( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
+ if ( header_macros_hash && ( v = (HEADER_MACRO *)hash_find( header_macros_hash, macro_name ) ) )
     {
         if ( DEBUG_HEADER )
- printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
+ printf( "### macro '%s' evaluated to '%s'\n", object_str( macro_name ), object_str( v->filename ) );
         return v->filename;
     }
     return 0;

Modified: branches/release/tools/build/v2/engine/hdrmacro.h
==============================================================================
--- branches/release/tools/build/v2/engine/hdrmacro.h (original)
+++ branches/release/tools/build/v2/engine/hdrmacro.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,6 +9,11 @@
  * #define MACRO "filename" definitions
  */
 
+#ifndef HDRMACRO_SW20111118_H
+#define HDRMACRO_SW20111118_H
+
 void macro_headers( TARGET *t );
 
-char* macro_header_get( const char* macro_name );
+OBJECT * macro_header_get( OBJECT * macro_name );
+
+#endif

Modified: branches/release/tools/build/v2/engine/headers.c
==============================================================================
--- branches/release/tools/build/v2/engine/headers.c (original)
+++ branches/release/tools/build/v2/engine/headers.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -14,11 +14,12 @@
 # include "parse.h"
 # include "compile.h"
 # include "rules.h"
+# include "modules.h"
 # include "variable.h"
 # include "regexp.h"
 # include "headers.h"
 # include "hdrmacro.h"
-# include "newstr.h"
+# include "object.h"
 
 #ifdef OPT_HEADER_CACHE_EXT
 # include "hcache.h"
@@ -46,7 +47,7 @@
  */
 
 #ifndef OPT_HEADER_CACHE_EXT
-static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
+static LIST * headers1( LIST * l, OBJECT * file, int rec, regexp * re[]);
 #endif
 
 /*
@@ -56,28 +57,33 @@
 # define MAXINC 10
 
 void
-headers( TARGET *t )
+headers( TARGET * t )
 {
     LIST * hdrscan;
     LIST * hdrrule;
         #ifndef OPT_HEADER_CACHE_EXT
- LIST * headlist = 0;
+ LIST * headlist = L0;
         #endif
     regexp * re[ MAXINC ];
     int rec = 0;
+ LISTITER iter, end;
 
- if ( !( hdrscan = var_get( "HDRSCAN" ) ) ||
- !( hdrrule = var_get( "HDRRULE" ) ) )
+ hdrscan = var_get( root_module(), constant_HDRSCAN );
+ if ( list_empty( hdrscan ) )
+ return;
+
+ hdrrule = var_get( root_module(), constant_HDRRULE );
+ if ( list_empty( hdrrule ) )
         return;
 
     if ( DEBUG_HEADER )
- printf( "header scan %s\n", t->name );
+ printf( "header scan %s\n", object_str( t->name ) );
 
     /* Compile all regular expressions in HDRSCAN */
- while ( ( rec < MAXINC ) && hdrscan )
+ iter = list_begin( hdrscan ), end = list_end( hdrscan );
+ for ( ; ( rec < MAXINC ) && iter != end; iter = list_next( iter ) )
     {
- re[ rec++ ] = regex_compile( hdrscan->string );
- hdrscan = list_next( hdrscan );
+ re[ rec++ ] = regex_compile( list_item( iter ) );
     }
 
     /* Doctor up call to HDRRULE rule */
@@ -85,7 +91,7 @@
     {
         FRAME frame[1];
         frame_init( frame );
- lol_add( frame->args, list_new( L0, t->name ) );
+ lol_add( frame->args, list_new( object_copy( t->name ) ) );
 #ifdef OPT_HEADER_CACHE_EXT
         lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
 #else
@@ -96,9 +102,9 @@
         {
             /* The third argument to HDRRULE is the bound name of
              * $(<) */
- lol_add( frame->args, list_new( L0, t->boundname ) );
+ lol_add( frame->args, list_new( object_copy( t->boundname ) ) );
 
- list_free( evaluate_rule( hdrrule->string, frame ) );
+ list_free( evaluate_rule( list_front( hdrrule ), frame ) );
         }
 
         /* Clean up. */
@@ -118,7 +124,7 @@
 #endif
 headers1(
     LIST * l,
- char * file,
+ OBJECT * file,
     int rec,
     regexp * re[] )
 {
@@ -137,10 +143,14 @@
     /* the following regexp is used to detect cases where a */
     /* file is included through a line line "#include MACRO" */
     if ( re_macros == 0 )
- re_macros = regex_compile(
+ {
+ OBJECT * re_str = object_new(
             "^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
+ re_macros = regex_compile( re_str );
+ object_free( re_str );
+ }
 
- if ( !( f = fopen( file, "r" ) ) )
+ if ( !( f = fopen( object_str( file ), "r" ) ) )
         return l;
 
     while ( fgets( buf, sizeof( buf ), f ) )
@@ -158,30 +168,33 @@
         for ( i = 0; i < rec; ++i )
             if ( regexec( re[i], buf ) && re[i]->startp[1] )
             {
- re[i]->endp[1][0] = '\0';
+ ((char *)re[i]->endp[1])[0] = '\0';
 
                 if ( DEBUG_HEADER )
                     printf( "header found: %s\n", re[i]->startp[1] );
 
- l = list_new( l, newstr( re[i]->startp[1] ) );
+ l = list_push_back( l, object_new( re[i]->startp[1] ) );
             }
 
         /* special treatment for #include MACRO */
         if ( regexec( re_macros, buf ) && re_macros->startp[1] )
         {
- char* header_filename;
+ OBJECT * header_filename;
+ OBJECT * macro_name;
 
- re_macros->endp[1][0] = '\0';
+ ((char *)re_macros->endp[1])[0] = '\0';
 
             if ( DEBUG_HEADER )
                 printf( "macro header found: %s", re_macros->startp[1] );
 
- header_filename = macro_header_get( re_macros->startp[1] );
+ macro_name = object_new( re_macros->startp[1] );
+ header_filename = macro_header_get( macro_name );
+ object_free( macro_name );
             if ( header_filename )
             {
                 if ( DEBUG_HEADER )
- printf( " resolved to '%s'\n", header_filename );
- l = list_new( l, newstr( header_filename ) );
+ printf( " resolved to '%s'\n", object_str( header_filename ) );
+ l = list_push_back( l, object_copy( header_filename ) );
             }
             else
             {
@@ -197,7 +210,7 @@
 }
 
 
-void regerror( char * s )
+void regerror( const char * s )
 {
     printf( "re error %s\n", s );
 }

Modified: branches/release/tools/build/v2/engine/headers.h
==============================================================================
--- branches/release/tools/build/v2/engine/headers.h (original)
+++ branches/release/tools/build/v2/engine/headers.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,9 +8,18 @@
  * headers.h - handle #includes in source files
  */
 
-void headers( TARGET *t );
+#ifndef HEADERS_SW20111118_H
+#define HEADERS_SW20111118_H
+
+#include "object.h"
+#include "rules.h"
+#include "regexp.h"
+
+void headers( TARGET * t );
 
 #ifdef OPT_HEADER_CACHE_EXT
 struct regexp;
-LIST *headers1( LIST *l, char *file, int rec, struct regexp *re[] );
+LIST * headers1( LIST *l, OBJECT * file, int rec, struct regexp *re[] );
+#endif
+
 #endif

Modified: branches/release/tools/build/v2/engine/jam.c
==============================================================================
--- branches/release/tools/build/v2/engine/jam.c (original)
+++ branches/release/tools/build/v2/engine/jam.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -54,18 +54,18 @@
  * are layered thus:
  *
  * variable|expand
- * / | | |
- * / | | |
- * / | | |
- * lists | | pathsys
- * \ | |
- * \ | |
- * \ | |
- * newstr |
+ * / | |
+ * / | |
+ * / | |
+ * lists | pathsys
+ * \ |
+ * \ hash
+ * \ |
+ * \ |
  * \ |
  * \ |
  * \ |
- * hash
+ * object
  *
  * Roughly, the modules are:
  *
@@ -73,8 +73,6 @@
  * command.c - maintain lists of commands
  * compile.c - compile parsed jam statements
  * execunix.c - execute a shell script on UNIX
- * execvms.c - execute a shell script, ala VMS
- * expand.c - expand a buffer, given variable values
  * file*.c - scan directories and archives on *
  * hash.c - simple in-memory hashing routines
  * hdrmacro.c - handle header file parsing for filename macro definitions
@@ -84,7 +82,7 @@
  * lists.c - maintain lists of strings
  * make.c - bring a target up to date, once rules are in place
  * make1.c - execute command to bring targets up to date
- * newstr.c - string manipulation routines
+ * object.c - string manipulation routines
  * option.c - command line option processing
  * parse.c - make and destroy parse trees as driven by the parser
  * path*.c - manipulate file names on *
@@ -104,6 +102,8 @@
  */
 
 
+#include "limits.h"
+
 #include "jam.h"
 #include "option.h"
 #include "patchlevel.h"
@@ -115,14 +115,20 @@
 #include "compile.h"
 #include "builtins.h"
 #include "rules.h"
-#include "newstr.h"
+#include "object.h"
 #include "scan.h"
 #include "timestamp.h"
 #include "make.h"
 #include "strings.h"
-#include "expand.h"
 #include "filesys.h"
 #include "output.h"
+#include "search.h"
+#include "class.h"
+#include "execcmd.h"
+#include "constants.h"
+#include "function.h"
+#include "pwd.h"
+#include "hcache.h"
 
 /* Macintosh is "special" */
 #ifdef OS_MAC
@@ -130,9 +136,36 @@
 #endif
 
 /* And UNIX for this. */
-#ifdef unix
+#if defined(unix) || defined(__unix)
     #include <sys/utsname.h>
+ #include <sys/wait.h>
     #include <signal.h>
+
+ #include <sys/utsname.h>
+ #include <signal.h>
+
+ sigset_t empty_sigmask;
+ volatile sig_atomic_t child_events = 0;
+ struct terminated_child terminated_children[MAXJOBS] = {{ 0 }};
+
+ void child_sig_handler(int x) {
+ pid_t pid;
+ int i, status;
+ pid = waitpid(-1, &status, WNOHANG);
+ if (0 < pid) {
+ /* save terminated child pid and status */
+ for (i=0; i<MAXJOBS; ++i) {
+ /* find first available slot */
+ if (terminated_children[i].pid == 0) {
+ terminated_children[i].pid = pid;
+ terminated_children[i].status = status;
+ break;
+ }
+ }
+ }
+ ++child_events;
+ signal(SIGCHLD, child_sig_handler);
+ }
 #endif
 
 struct globs globs =
@@ -148,7 +181,9 @@
     { 0, 1 }, /* debug ... */
 #endif
     0, /* output commands, not run them */
- 0 /* action timeout */
+ 0, /* action timeout */
+ 0,
+ INT_MAX /* default is to accept all action output */
 };
 
 /* Symbols to be defined as true for use in Jambase. */
@@ -196,7 +231,6 @@
     execnt_unit_test();
 #endif
     string_unit_test();
- var_expand_unit_test();
 }
 #endif
 
@@ -211,7 +245,9 @@
     extern PyObject * bjam_caller ( PyObject * self, PyObject * args );
 #endif
 
-char *saved_argv0;
+void regex_done();
+
+const char *saved_argv0;
 
 int main( int argc, char * * argv, char * * arg_environ )
 {
@@ -223,6 +259,21 @@
     int arg_c = argc;
     char * * arg_v = argv;
     char const * progname = argv[0];
+ module_t * environ_module;
+
+#if defined(unix) || defined(__unix)
+ sigset_t sigmask;
+ struct sigaction sa;
+
+ sigemptyset(&sigmask);
+ sigaddset(&sigmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sigmask, NULL);
+ sa.sa_flags = 0;
+ sa.sa_handler = child_sig_handler;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGCHLD, &sa, NULL);
+ sigemptyset(&empty_sigmask);
+#endif
 
     saved_argv0 = argv[0];
 
@@ -235,7 +286,7 @@
     --argc;
     ++argv;
 
- if ( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
+ if ( getoptions( argc, argv, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
     {
         printf( "\nusage: %s [ options ] targets...\n\n", progname );
 
@@ -245,6 +296,7 @@
         /* printf( "-g Build from newest sources first.\n" ); */
         printf( "-jx Run up to x shell commands concurrently.\n" );
         printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" );
+ printf( "-mx Limit action output buffer to x kb's of data, after which action output is read and ignored.\n" );
         printf( "-n Don't actually execute the updating actions.\n" );
         printf( "-ox Write the updating actions to file x.\n" );
         printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" );
@@ -312,6 +364,9 @@
     if ( ( s = getoptval( optv, 'l', 0 ) ) )
         globs.timeout = atoi( s );
 
+ if ( ( s = getoptval( optv, 'm', 0 ) ) )
+ globs.maxbuf = atoi( s ) * 1024;
+
     /* Turn on/off debugging */
     for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n )
     {
@@ -338,6 +393,8 @@
             globs.debug[i--] = 1;
     }
 
+ constants_init();
+
     {
         PROFILE_ENTER( MAIN );
 
@@ -377,34 +434,34 @@
 #endif
 
         /* Set JAMDATE. */
- var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
+ var_set( root_module(), constant_JAMDATE, list_new( outf_time(time(0)) ), VAR_SET );
 
         /* Set JAM_VERSION. */
- var_set( "JAM_VERSION",
- list_new( list_new( list_new( L0,
- newstr( VERSION_MAJOR_SYM ) ),
- newstr( VERSION_MINOR_SYM ) ),
- newstr( VERSION_PATCH_SYM ) ),
+ var_set( root_module(), constant_JAM_VERSION,
+ list_push_back( list_push_back( list_new(
+ object_new( VERSION_MAJOR_SYM ) ),
+ object_new( VERSION_MINOR_SYM ) ),
+ object_new( VERSION_PATCH_SYM ) ),
                    VAR_SET );
 
         /* Set JAMUNAME. */
-#ifdef unix
+#if defined(unix) || defined(__unix)
         {
             struct utsname u;
 
             if ( uname( &u ) >= 0 )
             {
- var_set( "JAMUNAME",
- list_new(
- list_new(
- list_new(
- list_new(
- list_new( L0,
- newstr( u.sysname ) ),
- newstr( u.nodename ) ),
- newstr( u.release ) ),
- newstr( u.version ) ),
- newstr( u.machine ) ), VAR_SET );
+ var_set( root_module(), constant_JAMUNAME,
+ list_push_back(
+ list_push_back(
+ list_push_back(
+ list_push_back(
+ list_new(
+ object_new( u.sysname ) ),
+ object_new( u.nodename ) ),
+ object_new( u.release ) ),
+ object_new( u.version ) ),
+ object_new( u.machine ) ), VAR_SET );
             }
         }
 #endif /* unix */
@@ -414,19 +471,18 @@
         /* First into the global module, with splitting, for backward
          * compatibility.
          */
- var_defines( use_environ, 1 );
+ var_defines( root_module(), use_environ, 1 );
 
+ environ_module = bindmodule( constant_ENVIRON );
         /* Then into .ENVIRON, without splitting. */
- enter_module( bindmodule(".ENVIRON") );
- var_defines( use_environ, 0 );
- exit_module( bindmodule(".ENVIRON") );
+ var_defines( environ_module, use_environ, 0 );
 
         /*
          * Jam defined variables OS & OSPLAT. We load them after environment, so
          * that setting OS in environment does not change Jam's notion of the
          * current platform.
          */
- var_defines( othersyms, 1 );
+ var_defines( root_module(), othersyms, 1 );
 
         /* Load up variables set on command line. */
         for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n )
@@ -434,16 +490,16 @@
             char *symv[2];
             symv[ 0 ] = s;
             symv[ 1 ] = 0;
- var_defines( symv, 1 );
- enter_module( bindmodule(".ENVIRON") );
- var_defines( symv, 0 );
- exit_module( bindmodule(".ENVIRON") );
+ var_defines( root_module(), symv, 1 );
+ var_defines( environ_module, symv, 0 );
         }
 
         /* Set the ARGV to reflect the complete list of arguments of invocation.
          */
         for ( n = 0; n < arg_c; ++n )
- var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
+ {
+ var_set( root_module(), constant_ARGV, list_new( object_new( arg_v[n] ) ), VAR_APPEND );
+ }
 
         /* Initialize built-in rules. */
         load_builtins();
@@ -459,29 +515,43 @@
             }
             else
             {
- mark_target_for_updating( arg_v[ n ] );
+ OBJECT * target = object_new( arg_v[ n ] );
+ mark_target_for_updating( target );
+ object_free( target );
             }
         }
 
- if (!targets_to_update())
- mark_target_for_updating("all");
+ if ( list_empty( targets_to_update() ) )
+ {
+ mark_target_for_updating( constant_all );
+ }
 
         /* Parse ruleset. */
         {
             FRAME frame[ 1 ];
             frame_init( frame );
             for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
- parse_file( s, frame );
+ {
+ OBJECT * filename = object_new( s );
+ parse_file( filename, frame );
+ object_free( filename );
+ }
 
             if ( !n )
- parse_file( "+", frame );
+ {
+ parse_file( constant_plus, frame );
+ }
         }
 
         status = yyanyerrors();
 
         /* Manually touch -t targets. */
         for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
- touch_target( s );
+ {
+ OBJECT * target = object_new( s );
+ touch_target( target );
+ object_free( target );
+ }
 
         /* If an output file is specified, set globs.cmdout to that. */
         if ( ( s = getoptval( optv, 'o', 0 ) ) )
@@ -498,13 +568,13 @@
            options. */
         {
             LIST *p = L0;
- p = var_get ("PARALLELISM");
- if (p)
+ p = var_get ( root_module(), constant_PARALLELISM );
+ if ( !list_empty( p ) )
             {
- int j = atoi (p->string);
- if (j == -1)
+ int j = atoi( object_str( list_front( p ) ) );
+ if ( j == -1 )
                 {
- printf( "Invalid value of PARALLELISM: %s\n", p->string);
+ printf( "Invalid value of PARALLELISM: %s\n", object_str( list_front( p ) ) );
                 }
                 else
                 {
@@ -516,11 +586,11 @@
         /* KEEP_GOING overrides -q option. */
         {
             LIST *p = L0;
- p = var_get ("KEEP_GOING");
- if (p)
+ p = var_get( root_module(), constant_KEEP_GOING );
+ if ( !list_empty( p ) )
             {
- int v = atoi (p->string);
- if (v == 0)
+ int v = atoi( object_str( list_front( p ) ) );
+ if ( v == 0 )
                     globs.quitquick = 1;
                 else
                     globs.quitquick = 0;
@@ -532,16 +602,9 @@
             PROFILE_ENTER( MAIN_MAKE );
 
             LIST * targets = targets_to_update();
- if (targets)
+ if ( !list_empty( targets ) )
             {
- int targets_count = list_length( targets );
- const char * * targets2 = (const char * *)
- BJAM_MALLOC( targets_count * sizeof( char * ) );
- int n = 0;
- for ( ; targets; targets = list_next( targets ) )
- targets2[ n++ ] = targets->string;
- status |= make( targets_count, targets2, anyhow );
- free( targets );
+ status |= make( targets, anyhow );
             }
             else
             {
@@ -557,12 +620,28 @@
     if ( DEBUG_PROFILE )
         profile_dump();
 
+
+#ifdef OPT_HEADER_CACHE_EXT
+ hcache_done();
+#endif
+
+ clear_targets_to_update();
+
     /* Widely scattered cleanup. */
- var_done();
     file_done();
     rules_done();
     stamps_done();
- str_done();
+ search_done();
+ class_done();
+ modules_done();
+ regex_done();
+ exec_done();
+ pwd_done();
+ path_done();
+ function_done();
+ list_done();
+ constants_done();
+ object_done();
 
     /* Close cmdout. */
     if ( globs.cmdout )
@@ -579,7 +658,7 @@
 
 #if defined(_WIN32)
 #include <windows.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     DWORD ret = GetModuleFileName(NULL, buf, sizeof(buf));
     if (ret == 0 || ret == sizeof(buf)) return NULL;
@@ -587,7 +666,7 @@
 }
 #elif defined(__APPLE__) /* Not tested */
 #include <mach-o/dyld.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     uint32_t size = sizeof(buf);
     int ret = _NSGetExecutablePath(buf, &size);
@@ -597,12 +676,12 @@
 #elif defined(sun) || defined(__sun) /* Not tested */
 #include <stdlib.h>
 
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     return strdup(getexecname());
 }
 #elif defined(__FreeBSD__)
 #include <sys/sysctl.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     int mib[4];
     mib[0] = CTL_KERN;
     mib[1] = KERN_PROC;
@@ -616,16 +695,16 @@
 }
 #elif defined(__linux__)
 #include <unistd.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf));
     if (ret == 0 || ret == sizeof(buf)) return NULL;
     return strndup(buf, ret);
 }
 #else
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     /* If argv0 is absolute path, assume it's the right absolute path. */
- if (argv0[0] == "/")
+ if (argv0[0] == '/')
         return strdup(argv0);
     return NULL;
 }

Modified: branches/release/tools/build/v2/engine/jam.h
==============================================================================
--- branches/release/tools/build/v2/engine/jam.h (original)
+++ branches/release/tools/build/v2/engine/jam.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -46,40 +46,6 @@
 #define HAVE_POPEN 1
 
 /*
- * VMS, OPENVMS
- */
-
-#ifdef VMS
-
-#include <types.h>
-#include <file.h>
-#include <stat.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <unixlib.h>
-
-#define OSMINOR "OS=VMS"
-#define OSMAJOR "VMS=true"
-#define OS_VMS
-#define MAXLINE 1024 /* longest 'together' actions */
-#define SPLITPATH ','
-#define EXITOK 1
-#define EXITBAD 0
-#define DOWNSHIFT_PATHS
-
-/* This may be inaccurate. */
-#ifndef __DECC
-#define OSPLAT "OSPLAT=VAX"
-#endif
-
-#endif
-
-/*
  * Windows NT
  */
 
@@ -157,55 +123,6 @@
 #endif
 
 /*
- * OS2
- */
-
-#ifdef __OS2__
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <malloc.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-
-#define OSMAJOR "OS2=true"
-#define OSMINOR "OS=OS2"
-#define OS_OS2
-#define SPLITPATH ';'
-#define MAXLINE 996 /* longest 'together' actions */
-#define USE_EXECUNIX
-#define USE_PATHUNIX
-#define PATH_DELIM '\\'
-#define DOWNSHIFT_PATHS
-
-#ifdef __EMX__
- #define USE_FILEUNIX
-#endif
-
-#endif
-
-/*
- * Macintosh MPW
- */
-
-#ifdef macintosh
-
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#define OSMAJOR "MAC=true"
-#define OSMINOR "OS=MAC"
-#define OS_MAC
-#define SPLITPATH ','
-
-#endif
-
-/*
  * God fearing UNIX.
  */
 
@@ -539,10 +456,23 @@
                                  * default 0 for no limit.
                                  */
     int dart; /* output build and test results formatted for Dart */
+ int maxbuf; /* limit action output buffer to maxbuf kb's of data */
 };
 
 extern struct globs globs;
 
+#if defined(unix) || defined(__unix)
+
+struct terminated_child
+{
+ pid_t pid;
+ int status;
+};
+
+extern struct terminated_child terminated_children[MAXJOBS];
+
+#endif
+
 #define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
 #define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
 #define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
@@ -576,4 +506,12 @@
 /* They also get the profile functions. */
 #include "debug.h"
 
+/* Handle child process termination */
+#if defined(unix) || defined(__unix)
+#include <signal.h>
+extern sigset_t empty_sigmask;
+extern volatile sig_atomic_t child_events;
+void child_sig_handler(int x);
+#endif
+
 #endif

Modified: branches/release/tools/build/v2/engine/jamgram.c
==============================================================================
--- branches/release/tools/build/v2/engine/jamgram.c (original)
+++ branches/release/tools/build/v2/engine/jamgram.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1,30 +1,38 @@
-/* A Bison parser, made by GNU Bison 1.875. */
+/* A Bison parser, made by GNU Bison 2.4.3. */
 
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
-
+
    You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
 
-/* Written by Richard Stallman by simplifying the original so called
- ``semantic'' parser. */
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
 
 /* All symbols defined below should begin with yy or YY, to avoid
    infringing on user name space. This should be done even for local
@@ -36,17 +44,93 @@
 /* Identify Bison output. */
 #define YYBISON 1
 
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
 /* Skeleton name. */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Pure parsers. */
 #define YYPURE 0
 
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
 /* Using locations. */
 #define YYLSP_NEEDED 0
 
 
 
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 96 "jamgram.y"
+
+#include "jam.h"
+
+#include "lists.h"
+#include "parse.h"
+#include "scan.h"
+#include "compile.h"
+#include "object.h"
+#include "rules.h"
+
+# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
+
+# define F0 -1
+# define P0 (PARSE *)0
+# define S0 (OBJECT *)0
+
+# define pappend( l,r ) parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( PARSE_EVAL,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( PARSE_FOREACH,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( PARSE_IF,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( PARSE_ON,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( PARSE_RULE,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( PARSE_RULES,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( PARSE_SET,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 )
+
+# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
+# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+
+
+
+/* Line 189 of yacc.c */
+#line 114 "y.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
 /* Tokens. */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -101,6 +185,7 @@
      STRING = 303
    };
 #endif
+/* Tokens. */
 #define _BANG_t 258
 #define _BANG_EQUALS_t 259
 #define _AMPER_t 260
@@ -151,119 +236,184 @@
 
 
 
-/* Copy the first part of user declarations. */
-#line 96 "jamgram.y"
-
-#include "jam.h"
-
-#include "lists.h"
-#include "parse.h"
-#include "scan.h"
-#include "compile.h"
-#include "newstr.h"
-#include "rules.h"
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
 
-# define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
-# define F0 (LIST *(*)(PARSE *, FRAME *))0
-# define P0 (PARSE *)0
-# define S0 (char *)0
+/* Copy the second part of user declarations. */
 
-# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
-# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
-# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
-# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
-# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
-# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
-# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
-# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
-# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
-# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
-# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
-# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
-# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
-# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
-# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
-# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
-# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
-# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
-# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
 
-# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
-# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
+/* Line 264 of yacc.c */
+#line 252 "y.tab.c"
 
+#ifdef short
+# undef short
+#endif
 
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
 
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
 #endif
 
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
 #else
-# define YYERROR_VERBOSE 0
+typedef unsigned short int yytype_uint16;
 #endif
 
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
 #endif
 
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
 
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
-/* Copy the second part of user declarations. */
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
 
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
 
-/* Line 214 of yacc.c. */
-#line 223 "y.tab.c"
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
 
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
+#if ! defined yyoverflow || YYERROR_VERBOSE
 
 /* The parser invokes alloca or malloc; define the necessary symbols. */
 
-# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
-# else
-# ifndef YYSTACK_USE_ALLOCA
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
 # else
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
 # endif
 # endif
 # endif
 # endif
 
 # ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
 # else
-# if defined (__STDC__) || defined (__cplusplus)
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
 # endif
-# define YYSTACK_ALLOC malloc
-# define YYSTACK_FREE free
 # endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
 
 
-#if (! defined (yyoverflow) \
- && (! defined (__cplusplus) \
- || (YYSTYPE_IS_TRIVIAL)))
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member. */
 union yyalloc
 {
- short yyss;
- YYSTYPE yyvs;
- };
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
 
 /* The size of the maximum gap between one aligned stack and the next. */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -271,24 +421,24 @@
 /* The size of an array large to enough to hold all stacks, each with
    N elements. */
 # define YYSTACK_BYTES(N) \
- ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
 /* Copy COUNT objects from FROM to TO. The source and destination do
    not overlap. */
 # ifndef YYCOPY
-# if 1 < __GNUC__
+# if defined __GNUC__ && 1 < __GNUC__
 # define YYCOPY(To, From, Count) \
       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
 # else
 # define YYCOPY(To, From, Count) \
       do \
         { \
- register YYSIZE_T yyi; \
+ YYSIZE_T yyi; \
           for (yyi = 0; yyi < (Count); yyi++) \
             (To)[yyi] = (From)[yyi]; \
         } \
- while (0)
+ while (YYID (0))
 # endif
 # endif
 
@@ -297,48 +447,42 @@
    elements in the stack, and YYPTR gives the new location of the
    stack. Advance YYPTR to a properly aligned location for the next
    stack. */
-# define YYSTACK_RELOCATE(Stack) \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
     do \
       { \
         YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
         yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
         yyptr += yynewbytes / sizeof (*yyptr); \
       } \
- while (0)
-
-#endif
+ while (YYID (0))
 
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short yysigned_char;
 #endif
 
-/* YYFINAL -- State number of the termination state. */
+/* YYFINAL -- State number of the termination state. */
 #define YYFINAL 43
 /* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 261
+#define YYLAST 243
 
-/* YYNTOKENS -- Number of terminals. */
+/* YYNTOKENS -- Number of terminals. */
 #define YYNTOKENS 49
-/* YYNNTS -- Number of nonterminals. */
+/* YYNNTS -- Number of nonterminals. */
 #define YYNNTS 24
-/* YYNRULES -- Number of rules. */
+/* YYNRULES -- Number of rules. */
 #define YYNRULES 75
-/* YYNRULES -- Number of states. */
+/* YYNRULES -- Number of states. */
 #define YYNSTATES 159
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
 #define YYUNDEFTOK 2
 #define YYMAXUTOK 303
 
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char yytranslate[] =
+static const yytype_uint8 yytranslate[] =
 {
        0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -376,7 +520,7 @@
 #if YYDEBUG
 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
    YYRHS. */
-static const unsigned char yyprhs[] =
+static const yytype_uint8 yyprhs[] =
 {
        0, 0, 3, 4, 6, 8, 10, 12, 15, 21,
       22, 25, 27, 31, 32, 34, 35, 39, 43, 47,
@@ -388,8 +532,8 @@
      244, 246, 248, 250, 252, 253
 };
 
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
 {
       50, 0, -1, -1, 52, -1, 53, -1, 52, -1,
       57, -1, 57, 52, -1, 32, 65, 54, 11, 51,
@@ -413,14 +557,14 @@
        7, 61, 8, -1, -1, 63, 62, -1, 22, 47,
       10, 51, -1, 65, -1, 65, 10, 64, -1, 66,
       -1, -1, 66, 67, -1, 47, -1, -1, 18, 68,
- 69, 19, -1, 67, 64, -1, 34, 67, 67, 64,
+ 69, 19, -1, 47, 64, -1, 34, 67, 47, 64,
       -1, 34, 67, 37, 65, -1, -1, 70, 71, -1,
       41, -1, 40, -1, 29, -1, 36, -1, 35, -1,
       26, -1, -1, 21, 65, -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short yyrline[] =
+static const yytype_uint16 yyrline[] =
 {
        0, 139, 139, 141, 152, 154, 158, 160, 162, 167,
      170, 172, 176, 179, 182, 185, 188, 190, 192, 194,
@@ -433,9 +577,9 @@
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "_BANG_t", "_BANG_EQUALS_t", "_AMPER_t",
@@ -448,15 +592,15 @@
   "RULE_t", "SWITCH_t", "TOGETHER_t", "UPDATED_t", "WHILE_t", "_LBRACE_t",
   "_BAR_t", "_BARBAR_t", "_RBRACE_t", "ARG", "STRING", "$accept", "run",
   "block", "rules", "null", "assign_list_opt", "arglist_opt", "local_opt",
- "rule", "@1", "@2", "assign", "expr", "cases", "case", "lol", "list",
- "listp", "arg", "@3", "func", "eflags", "eflag", "bindlist", 0
+ "rule", "$@1", "$@2", "assign", "expr", "cases", "case", "lol", "list",
+ "listp", "arg", "$@3", "func", "eflags", "eflag", "bindlist", 0
 };
 #endif
 
 # ifdef YYPRINT
 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
    token YYLEX-NUM. */
-static const unsigned short yytoknum[] =
+static const yytype_uint16 yytoknum[] =
 {
        0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
      265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
@@ -467,7 +611,7 @@
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
+static const yytype_uint8 yyr1[] =
 {
        0, 49, 50, 50, 51, 51, 52, 52, 52, 53,
       54, 54, 55, 55, 56, 56, 57, 57, 57, 57,
@@ -480,7 +624,7 @@
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
+static const yytype_uint8 yyr2[] =
 {
        0, 2, 0, 1, 1, 1, 1, 2, 5, 0,
        2, 1, 3, 0, 1, 0, 3, 3, 3, 4,
@@ -495,7 +639,7 @@
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
    STATE-NUM when YYTABLE doesn't specify something else to do. Zero
    means the default is an error. */
-static const unsigned char yydefact[] =
+static const yytype_uint8 yydefact[] =
 {
        2, 61, 66, 58, 15, 0, 58, 58, 58, 0,
       58, 58, 0, 9, 60, 0, 3, 0, 6, 0,
@@ -515,8 +659,8 @@
       12, 20, 32, 0, 28, 54, 0, 22, 33
 };
 
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short yydefgoto[] =
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
 {
       -1, 15, 39, 40, 41, 84, 125, 17, 18, 146,
      156, 51, 30, 121, 122, 22, 23, 24, 31, 20,
@@ -526,31 +670,31 @@
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM. */
 #define YYPACT_NINF -48
-static const short yypact[] =
+static const yytype_int16 yypact[] =
 {
- 179, -48, -48, -48, -15, 7, -48, -16, -48, 3,
- -48, -48, 7, 179, 1, 27, -48, -9, 179, 19,
- -3, 33, -11, 24, 3, -48, -10, 7, 7, -48,
- 138, 9, 30, 35, 13, 205, 53, 22, 151, 20,
- -48, -48, 56, -48, 23, -48, -48, -48, -48, 61,
- -48, -48, 3, -48, 62, -48, -48, -48, -48, -48,
- -48, 58, -48, 179, -48, -48, 52, -48, 164, 7,
- 7, 7, 7, 7, 7, 7, 7, 179, 7, 7,
- -48, -48, -48, -48, 72, 179, -48, -48, 68, 179,
- -48, -48, 85, -48, 77, 73, 8, -48, -48, -48,
- 50, 57, -48, -48, -48, 45, 93, 93, -48, -48,
- 45, -48, -48, 64, 245, 245, -48, -48, 179, 66,
- 67, 69, 68, 71, -48, 205, -48, -48, -48, -48,
- -48, -48, -48, 70, 79, -48, -48, 109, -48, -48,
- -48, 112, -48, 115, -48, -48, 75, 179, 205, 179,
- -48, -48, -48, 81, -48, -48, 82, -48, -48
+ 170, -48, -48, -48, -12, 7, -48, -17, -48, -3,
+ -48, -48, 7, 170, 1, 22, -48, -9, 170, 19,
+ -2, 79, -6, 29, -3, -48, 2, 7, 7, -48,
+ 138, 20, 44, 45, 18, 196, 51, 26, 151, 24,
+ -48, -48, 62, -48, 27, -48, -48, -48, -48, 61,
+ -48, -48, -3, -48, 67, -48, -48, -48, -48, -48,
+ -48, 58, -48, 170, -48, -48, 50, -48, 52, 7,
+ 7, 7, 7, 7, 7, 7, 7, 170, 7, 7,
+ -48, -48, -48, -48, 70, 170, -48, -48, 87, 170,
+ -48, -48, 94, -48, 17, 99, -20, -48, -48, -48,
+ 69, 71, -48, -48, -48, 91, 156, 156, -48, -48,
+ 91, -48, -48, 77, 78, 78, -48, -48, 170, 81,
+ 66, 82, 87, 95, -48, 196, -48, -48, -48, -48,
+ -48, -48, -48, 97, 112, -48, -48, 135, -48, -48,
+ -48, 150, -48, 148, -48, -48, 98, 170, 196, 170,
+ -48, -48, -48, 115, -48, -48, 116, -48, -48
 };
 
 /* YYPGOTO[NTERM-NUM]. */
-static const short yypgoto[] =
+static const yytype_int16 yypgoto[] =
 {
- -48, -48, -47, 5, 104, -48, -48, 136, -27, -48,
- -48, 47, 60, 36, -48, -13, -4, -48, 0, -48,
+ -48, -48, -47, 5, 140, -48, -48, 171, -27, -48,
+ -48, 80, 60, 54, -48, -13, -4, -48, 0, -48,
      -48, -48, -48, -48
 };
 
@@ -559,106 +703,86 @@
    number is the opposite. If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error. */
 #define YYTABLE_NINF -59
-static const short yytable[] =
+static const yytype_int16 yytable[] =
 {
       19, 42, 32, 33, 34, 16, 36, 37, 86, 35,
- 27, -58, -58, 19, 28, 1, 101, 25, 19, -58,
- 53, 1, -14, 45, 65, 1, 1, 43, 46, 44,
- 113, 52, 63, 47, 64, 19, 48, 66, 119, 80,
- 97, 81, 123, 49, 29, 128, 94, 95, -58, 82,
- 29, 102, 96, 50, 29, 29, 85, 72, 73, 55,
- 75, 76, 56, 19, 87, 88, 90, 91, 57, 58,
- 92, 135, 38, 59, 60, 93, 116, 19, 117, 99,
- 61, 98, 103, 118, 127, 19, 46, 67, 68, 19,
- 120, 47, 124, 131, 48, 130, 129, 69, 142, 133,
- 153, 49, 155, 132, 148, 72, 73, 74, 75, 76,
- 134, 141, 136, 147, 137, 138, 145, 140, 19, 149,
- 150, 154, 143, 152, 144, 19, 151, 157, 158, 105,
- 106, 107, 108, 109, 110, 111, 112, 83, 114, 115,
- 26, 126, 69, 70, 71, 0, 0, 19, 19, 19,
- 72, 73, 74, 75, 76, 69, 70, 71, 139, 0,
- 0, 0, 0, 72, 73, 74, 75, 76, 69, 70,
- 71, 0, 104, 0, 0, 0, 72, 73, 74, 75,
- 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 89, 78, 79, 1, 0, 2,
- 0, 0, 3, 0, 0, 0, 4, 5, 78, 79,
- 6, 7, 8, 9, 0, 0, 10, -15, 11, 0,
- 0, 12, 13, 1, 0, 2, 14, 0, 3, 0,
- 0, 0, 4, 5, 0, 0, 6, 25, 8, 9,
- 0, 0, 10, 0, 11, 0, 0, 12, 13, 69,
- 70, 71, 14, 0, 0, 0, 0, 72, 73, 74,
- 75, 76
+ 27, -58, -58, 19, 28, 1, 101, 128, 19, -58,
+ 25, -14, 43, 45, 65, 1, 46, 129, 46, 44,
+ 113, 47, 52, 47, 48, 19, 48, 63, 119, 64,
+ 97, 49, 123, 49, 29, 53, 94, 95, -58, 66,
+ 80, 102, 96, 50, 29, 81, 69, 70, 71, 82,
+ 104, 85, 87, 19, 72, 73, 74, 75, 76, 88,
+ 90, 135, 38, 91, 92, 93, 116, 19, 117, 99,
+ 103, 118, 69, 70, 71, 19, 98, 67, 68, 19,
+ 72, 73, 74, 75, 76, 130, 78, 79, 142, 133,
+ 153, 124, 155, 72, 73, 55, 75, 76, 56, 120,
+ 127, 141, 131, 137, 57, 58, 145, 132, 19, 59,
+ 60, 154, 143, 134, 144, 19, 61, 136, 138, 105,
+ 106, 107, 108, 109, 110, 111, 112, 148, 114, 115,
+ 147, 140, 69, 70, 71, 149, 152, 19, 19, 19,
+ 72, 73, 74, 75, 76, 69, 70, 71, 150, 151,
+ 69, 157, 158, 72, 73, 74, 75, 76, 72, 73,
+ 74, 75, 76, 83, 126, 26, 139, 0, 0, 0,
+ 0, 77, 78, 79, 0, 0, 0, 0, 1, 0,
+ 2, 0, 0, 3, 89, 78, 79, 4, 5, 0,
+ 0, 6, 7, 8, 9, 0, 0, 10, -15, 11,
+ 0, 0, 12, 13, 1, 0, 2, 14, 0, 3,
+ 0, 0, 0, 4, 5, 0, 0, 6, 25, 8,
+ 9, 0, 0, 10, 0, 11, 0, 0, 12, 13,
+ 0, 0, 0, 14
 };
 
-static const short yycheck[] =
+static const yytype_int16 yycheck[] =
 {
        0, 14, 6, 7, 8, 0, 10, 11, 35, 9,
- 3, 10, 11, 13, 7, 18, 63, 32, 18, 18,
- 20, 18, 38, 18, 24, 18, 18, 0, 9, 38,
- 77, 34, 43, 14, 10, 35, 17, 47, 85, 30,
- 53, 11, 89, 24, 47, 37, 50, 51, 47, 14,
- 47, 64, 52, 34, 47, 47, 43, 12, 13, 26,
- 15, 16, 29, 63, 11, 43, 46, 11, 35, 36,
- 47, 118, 12, 40, 41, 14, 80, 77, 82, 21,
- 47, 19, 30, 11, 11, 85, 9, 27, 28, 89,
- 22, 14, 7, 43, 17, 99, 96, 4, 125, 103,
- 147, 24, 149, 46, 25, 12, 13, 14, 15, 16,
- 46, 124, 46, 43, 47, 46, 129, 46, 118, 10,
- 8, 148, 126, 48, 128, 125, 11, 46, 46, 69,
- 70, 71, 72, 73, 74, 75, 76, 33, 78, 79,
- 4, 94, 4, 5, 6, -1, -1, 147, 148, 149,
- 12, 13, 14, 15, 16, 4, 5, 6, 122, -1,
- -1, -1, -1, 12, 13, 14, 15, 16, 4, 5,
- 6, -1, 8, -1, -1, -1, 12, 13, 14, 15,
- 16, 43, 44, 45, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 43, 44, 45, 18, -1, 20,
- -1, -1, 23, -1, -1, -1, 27, 28, 44, 45,
- 31, 32, 33, 34, -1, -1, 37, 38, 39, -1,
- -1, 42, 43, 18, -1, 20, 47, -1, 23, -1,
- -1, -1, 27, 28, -1, -1, 31, 32, 33, 34,
- -1, -1, 37, -1, 39, -1, -1, 42, 43, 4,
- 5, 6, 47, -1, -1, -1, -1, 12, 13, 14,
- 15, 16
+ 3, 10, 11, 13, 7, 18, 63, 37, 18, 18,
+ 32, 38, 0, 18, 24, 18, 9, 47, 9, 38,
+ 77, 14, 34, 14, 17, 35, 17, 43, 85, 10,
+ 53, 24, 89, 24, 47, 47, 50, 51, 47, 47,
+ 30, 64, 52, 34, 47, 11, 4, 5, 6, 14,
+ 8, 43, 11, 63, 12, 13, 14, 15, 16, 43,
+ 46, 118, 12, 11, 47, 14, 80, 77, 82, 21,
+ 30, 11, 4, 5, 6, 85, 19, 27, 28, 89,
+ 12, 13, 14, 15, 16, 99, 44, 45, 125, 103,
+ 147, 7, 149, 12, 13, 26, 15, 16, 29, 22,
+ 11, 124, 43, 47, 35, 36, 129, 46, 118, 40,
+ 41, 148, 126, 46, 128, 125, 47, 46, 46, 69,
+ 70, 71, 72, 73, 74, 75, 76, 25, 78, 79,
+ 43, 46, 4, 5, 6, 10, 48, 147, 148, 149,
+ 12, 13, 14, 15, 16, 4, 5, 6, 8, 11,
+ 4, 46, 46, 12, 13, 14, 15, 16, 12, 13,
+ 14, 15, 16, 33, 94, 4, 122, -1, -1, -1,
+ -1, 43, 44, 45, -1, -1, -1, -1, 18, -1,
+ 20, -1, -1, 23, 43, 44, 45, 27, 28, -1,
+ -1, 31, 32, 33, 34, -1, -1, 37, 38, 39,
+ -1, -1, 42, 43, 18, -1, 20, 47, -1, 23,
+ -1, -1, -1, 27, 28, -1, -1, 31, 32, 33,
+ 34, -1, -1, 37, -1, 39, -1, -1, 42, 43,
+ -1, -1, -1, 47
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
+static const yytype_uint8 yystos[] =
 {
        0, 18, 20, 23, 27, 28, 31, 32, 33, 34,
       37, 39, 42, 43, 47, 50, 52, 56, 57, 67,
       68, 70, 64, 65, 66, 32, 56, 3, 7, 47,
       61, 67, 65, 65, 65, 67, 65, 65, 61, 51,
       52, 53, 64, 0, 38, 52, 9, 14, 17, 24,
- 34, 60, 34, 67, 69, 26, 29, 35, 36, 40,
+ 34, 60, 34, 47, 69, 26, 29, 35, 36, 40,
       41, 47, 71, 43, 10, 67, 47, 61, 61, 4,
        5, 6, 12, 13, 14, 15, 16, 43, 44, 45,
       30, 11, 14, 53, 54, 43, 57, 11, 43, 43,
       46, 11, 47, 14, 65, 65, 67, 64, 19, 21,
       72, 51, 64, 30, 8, 61, 61, 61, 61, 61,
       61, 61, 61, 51, 61, 61, 65, 65, 11, 51,
- 22, 62, 63, 51, 7, 55, 60, 11, 37, 67,
+ 22, 62, 63, 51, 7, 55, 60, 11, 37, 47,
       65, 43, 46, 65, 46, 51, 46, 47, 46, 62,
       46, 64, 57, 65, 65, 64, 58, 43, 25, 10,
        8, 11, 48, 51, 57, 51, 59, 46, 46
 };
 
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
 #define yyerrok (yyerrstatus = 0)
 #define yyclearin (yychar = YYEMPTY)
 #define YYEMPTY (-2)
@@ -666,13 +790,23 @@
 
 #define YYACCEPT goto yyacceptlab
 #define YYABORT goto yyabortlab
-#define YYERROR goto yyerrlab1
+#define YYERROR goto yyerrorlab
+
 
 /* Like YYERROR except do call yyerror. This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
 
 #define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
 
 #define YYRECOVERING() (!!yyerrstatus)
 
@@ -683,30 +817,63 @@
       yychar = (Token); \
       yylval = (Value); \
       yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
+ YYPOPSTACK (1); \
       goto yybackup; \
     } \
   else \
- { \
- yyerror ("syntax error: cannot back up");\
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
       YYERROR; \
     } \
-while (0)
+while (YYID (0))
+
 
 #define YYTERROR 1
 #define YYERRCODE 256
 
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
- are run). */
 
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
 #ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- Current.first_line = Rhs[1].first_line; \
- Current.first_column = Rhs[1].first_column; \
- Current.last_line = Rhs[N].last_line; \
- Current.last_column = Rhs[N].last_column;
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
 #endif
 
+
 /* YYLEX -- calling `yylex' with the right arguments. */
 
 #ifdef YYLEX_PARAM
@@ -727,43 +894,100 @@
 do { \
   if (yydebug) \
     YYFPRINTF Args; \
-} while (0)
+} while (YYID (0))
 
-# define YYDSYMPRINT(Args) \
-do { \
- if (yydebug) \
- yysymprint Args; \
-} while (0)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
 
-# define YYDSYMPRINTF(Title, Token, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Token, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
 
 /*------------------------------------------------------------------.
 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (cinluded). |
+| TOP (included). |
 `------------------------------------------------------------------*/
 
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (short *bottom, short *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 #else
 static void
-yy_stack_print (bottom, top)
- short *bottom;
- short *top;
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -771,45 +995,52 @@
 do { \
   if (yydebug) \
     yy_stack_print ((Bottom), (Top)); \
-} while (0)
+} while (YYID (0))
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced. |
 `------------------------------------------------*/
 
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (int yyrule)
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
 #else
 static void
-yy_reduce_print (yyrule)
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
     int yyrule;
 #endif
 {
+ int yynrhs = yyr2[yyrule];
   int yyi;
- unsigned int yylineno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
- yyrule - 1, yylineno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
 }
 
 # define YY_REDUCE_PRINT(Rule) \
 do { \
   if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
 
 /* Nonzero means print parse trace. It is left uninitialized so that
    multiple parsers can coexist. */
 int yydebug;
 #else /* !YYDEBUG */
 # define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
 # define YY_STACK_PRINT(Bottom, Top)
 # define YY_REDUCE_PRINT(Rule)
 #endif /* !YYDEBUG */
@@ -824,13 +1055,9 @@
    if the built-in stack extension method is used).
 
    Do not make this value too large; the results are undefined if
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
    evaluated with infinite-precision integer arithmetic. */
 
-#if YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
 #ifndef YYMAXDEPTH
 # define YYMAXDEPTH 10000
 #endif
@@ -840,45 +1067,47 @@
 #if YYERROR_VERBOSE
 
 # ifndef yystrlen
-# if defined (__GLIBC__) && defined (_STRING_H)
+# if defined __GLIBC__ && defined _STRING_H
 # define yystrlen strlen
 # else
 /* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
 yystrlen (const char *yystr)
-# else
+#else
+static YYSIZE_T
 yystrlen (yystr)
- const char *yystr;
-# endif
+ const char *yystr;
+#endif
 {
- register const char *yys = yystr;
-
- while (*yys++ != '\0')
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
     continue;
-
- return yys - yystr - 1;
+ return yylen;
 }
 # endif
 # endif
 
 # ifndef yystpcpy
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
 # define yystpcpy stpcpy
 # else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 static char *
-# if defined (__STDC__) || defined (__cplusplus)
 yystpcpy (char *yydest, const char *yysrc)
-# else
+#else
+static char *
 yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
+ char *yydest;
+ const char *yysrc;
+#endif
 {
- register char *yyd = yydest;
- register const char *yys = yysrc;
+ char *yyd = yydest;
+ const char *yys = yysrc;
 
   while ((*yyd++ = *yys++) != '\0')
     continue;
@@ -888,84 +1117,204 @@
 # endif
 # endif
 
-#endif /* !YYERROR_VERBOSE */
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
 
-
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
 
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+ if (! yyres)
+ return yystrlen (yystr);
 
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
 {
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ int yyn = yypact[yystate];
 
- if (yytype < YYNTOKENS)
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
     {
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
 # endif
- }
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
 
- switch (yytype)
- {
- default:
- break;
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
     }
- YYFPRINTF (yyoutput, ")");
 }
+#endif /* YYERROR_VERBOSE */
+
 
-#endif /* ! YYDEBUG */
 /*-----------------------------------------------.
 | Release the memory associated to this symbol. |
 `-----------------------------------------------*/
 
-#if defined (__STDC__) || defined (__cplusplus)
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
 #else
 static void
-yydestruct (yytype, yyvaluep)
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
     int yytype;
     YYSTYPE *yyvaluep;
 #endif
 {
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
   switch (yytype)
     {
 
       default:
- break;
+ break;
     }
 }
-
 
 /* Prevent warnings from -Wmissing-prototypes. */
-
 #ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
-# else
+#else
 int yyparse ();
-# endif
+#endif
 #else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if defined __STDC__ || defined __cplusplus
 int yyparse (void);
 #else
 int yyparse ();
@@ -973,7 +1322,6 @@
 #endif /* ! YYPARSE_PARAM */
 
 
-
 /* The lookahead symbol. */
 int yychar;
 
@@ -985,19 +1333,23 @@
 
 
 
-/*----------.
-| yyparse. |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
 #else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (void)
 #else
@@ -1008,59 +1360,67 @@
 #endif
 {
 
- register int yystate;
- register int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- short yyssa[YYINITDEPTH];
- short *yyss = yyssa;
- register short *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
-
 
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
 
-#define YYPOPSTACK (yyvsp--, yyssp--)
-
- YYSIZE_T yystacksize = YYINITDEPTH;
+ YYSIZE_T yystacksize;
 
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
   /* The variables used to return semantic value and location from the
      action routines. */
   YYSTYPE yyval;
 
-
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ yychar = YYEMPTY; /* Cause a token to be read. */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized. */
-
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1071,8 +1431,7 @@
 `------------------------------------------------------------*/
  yynewstate:
   /* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks.
- */
+ have just been pushed. So pushing a state here evens the stacks. */
   yyssp++;
 
  yysetstate:
@@ -1085,21 +1444,19 @@
 
 #ifdef yyoverflow
       {
- /* Give user a chance to reallocate the stack. Use copies of
+ /* Give user a chance to reallocate the stack. Use copies of
            these so that the &'s don't force the real ones into
            memory. */
         YYSTYPE *yyvs1 = yyvs;
- short *yyss1 = yyss;
-
+ yytype_int16 *yyss1 = yyss;
 
         /* Each stack pointer address is followed by the size of the
            data in use in that stack, in bytes. This used to be a
            conditional around just the two extra args, but that might
            be undefined if yyoverflow is a macro. */
- yyoverflow ("parser stack overflow",
+ yyoverflow (YY_("memory exhausted"),
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
-
                     &yystacksize);
 
         yyss = yyss1;
@@ -1107,24 +1464,23 @@
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
+ goto yyexhaustedlab;
 # else
       /* Extend the stack our own way. */
       if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
+ goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
         yystacksize = YYMAXDEPTH;
 
       {
- short *yyss1 = yyss;
+ yytype_int16 *yyss1 = yyss;
         union yyalloc *yyptr =
           (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
         if (! yyptr)
- goto yyoverflowlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 # undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
@@ -1135,7 +1491,6 @@
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                   (unsigned long int) yystacksize));
 
@@ -1145,6 +1500,9 @@
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1152,12 +1510,10 @@
 `-----------*/
 yybackup:
 
-/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
-/* yyresume: */
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
 
   /* First try to decide what to do without reference to lookahead token. */
-
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
     goto yydefault;
@@ -1179,7 +1535,7 @@
   else
     {
       yytoken = YYTRANSLATE (yychar);
- YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
     }
 
   /* If the proper action on seeing token YYTOKEN is to reduce or to
@@ -1196,25 +1552,20 @@
       goto yyreduce;
     }
 
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-
-
   /* Count tokens shifted since error; after three, turn off error
      status. */
   if (yyerrstatus)
     yyerrstatus--;
 
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
   yystate = yyn;
+ *++yyvsp = yylval;
+
   goto yynewstate;
 
 
@@ -1250,385 +1601,530 @@
   switch (yyn)
     {
         case 3:
+
+/* Line 1464 of yacc.c */
 #line 142 "jamgram.y"
- { parse_save( yyvsp[0].parse ); }
+ { parse_save( (yyvsp[(1) - (1)]).parse ); }
     break;
 
   case 4:
+
+/* Line 1464 of yacc.c */
 #line 153 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; }
+ { (yyval).parse = (yyvsp[(1) - (1)]).parse; }
     break;
 
   case 5:
+
+/* Line 1464 of yacc.c */
 #line 155 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; }
+ { (yyval).parse = (yyvsp[(1) - (1)]).parse; }
     break;
 
   case 6:
+
+/* Line 1464 of yacc.c */
 #line 159 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; }
+ { (yyval).parse = (yyvsp[(1) - (1)]).parse; }
     break;
 
   case 7:
+
+/* Line 1464 of yacc.c */
 #line 161 "jamgram.y"
- { yyval.parse = prules( yyvsp[-1].parse, yyvsp[0].parse ); }
+ { (yyval).parse = prules( (yyvsp[(1) - (2)]).parse, (yyvsp[(2) - (2)]).parse ); }
     break;
 
   case 8:
+
+/* Line 1464 of yacc.c */
 #line 163 "jamgram.y"
- { yyval.parse = plocal( yyvsp[-3].parse, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = plocal( (yyvsp[(2) - (5)]).parse, (yyvsp[(3) - (5)]).parse, (yyvsp[(5) - (5)]).parse ); }
     break;
 
   case 9:
+
+/* Line 1464 of yacc.c */
 #line 167 "jamgram.y"
- { yyval.parse = pnull(); }
+ { (yyval).parse = pnull(); }
     break;
 
   case 10:
+
+/* Line 1464 of yacc.c */
 #line 171 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_SET; }
+ { (yyval).parse = (yyvsp[(2) - (2)]).parse; (yyval).number = ASSIGN_SET; }
     break;
 
   case 11:
+
+/* Line 1464 of yacc.c */
 #line 173 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_APPEND; }
+ { (yyval).parse = (yyvsp[(1) - (1)]).parse; (yyval).number = ASSIGN_APPEND; }
     break;
 
   case 12:
+
+/* Line 1464 of yacc.c */
 #line 177 "jamgram.y"
- { yyval.parse = yyvsp[-1].parse; }
+ { (yyval).parse = (yyvsp[(2) - (3)]).parse; }
     break;
 
   case 13:
+
+/* Line 1464 of yacc.c */
 #line 179 "jamgram.y"
- { yyval.parse = P0; }
+ { (yyval).parse = P0; }
     break;
 
   case 14:
+
+/* Line 1464 of yacc.c */
 #line 183 "jamgram.y"
- { yyval.number = 1; }
+ { (yyval).number = 1; }
     break;
 
   case 15:
+
+/* Line 1464 of yacc.c */
 #line 185 "jamgram.y"
- { yyval.number = 0; }
+ { (yyval).number = 0; }
     break;
 
   case 16:
+
+/* Line 1464 of yacc.c */
 #line 189 "jamgram.y"
- { yyval.parse = yyvsp[-1].parse; }
+ { (yyval).parse = (yyvsp[(2) - (3)]).parse; }
     break;
 
   case 17:
+
+/* Line 1464 of yacc.c */
 #line 191 "jamgram.y"
- { yyval.parse = pincl( yyvsp[-1].parse ); }
+ { (yyval).parse = pincl( (yyvsp[(2) - (3)]).parse ); }
     break;
 
   case 18:
+
+/* Line 1464 of yacc.c */
 #line 193 "jamgram.y"
- { yyval.parse = prule( yyvsp[-2].string, yyvsp[-1].parse ); }
+ { (yyval).parse = prule( (yyvsp[(1) - (3)]).string, (yyvsp[(2) - (3)]).parse ); }
     break;
 
   case 19:
+
+/* Line 1464 of yacc.c */
 #line 195 "jamgram.y"
- { yyval.parse = pset( yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ { (yyval).parse = pset( (yyvsp[(1) - (4)]).parse, (yyvsp[(3) - (4)]).parse, (yyvsp[(2) - (4)]).number ); }
     break;
 
   case 20:
+
+/* Line 1464 of yacc.c */
 #line 197 "jamgram.y"
- { yyval.parse = pset1( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
+ { (yyval).parse = pset1( (yyvsp[(1) - (6)]).parse, (yyvsp[(3) - (6)]).parse, (yyvsp[(5) - (6)]).parse, (yyvsp[(4) - (6)]).number ); }
     break;
 
   case 21:
+
+/* Line 1464 of yacc.c */
 #line 199 "jamgram.y"
- { yyval.parse = yyvsp[-1].parse; }
+ { (yyval).parse = (yyvsp[(2) - (3)]).parse; }
     break;
 
   case 22:
+
+/* Line 1464 of yacc.c */
 #line 201 "jamgram.y"
- { yyval.parse = pfor( yyvsp[-5].string, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-6].number ); }
+ { (yyval).parse = pfor( (yyvsp[(3) - (8)]).string, (yyvsp[(5) - (8)]).parse, (yyvsp[(7) - (8)]).parse, (yyvsp[(2) - (8)]).number ); }
     break;
 
   case 23:
+
+/* Line 1464 of yacc.c */
 #line 203 "jamgram.y"
- { yyval.parse = pswitch( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ { (yyval).parse = pswitch( (yyvsp[(2) - (5)]).parse, (yyvsp[(4) - (5)]).parse ); }
     break;
 
   case 24:
+
+/* Line 1464 of yacc.c */
 #line 205 "jamgram.y"
- { yyval.parse = pif( yyvsp[-3].parse, yyvsp[-1].parse, pnull() ); }
+ { (yyval).parse = pif( (yyvsp[(2) - (5)]).parse, (yyvsp[(4) - (5)]).parse, pnull() ); }
     break;
 
   case 25:
+
+/* Line 1464 of yacc.c */
 #line 207 "jamgram.y"
- { yyval.parse = pmodule( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ { (yyval).parse = pmodule( (yyvsp[(2) - (5)]).parse, (yyvsp[(4) - (5)]).parse ); }
     break;
 
   case 26:
+
+/* Line 1464 of yacc.c */
 #line 209 "jamgram.y"
- { yyval.parse = pclass( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ { (yyval).parse = pclass( (yyvsp[(2) - (5)]).parse, (yyvsp[(4) - (5)]).parse ); }
     break;
 
   case 27:
+
+/* Line 1464 of yacc.c */
 #line 211 "jamgram.y"
- { yyval.parse = pwhile( yyvsp[-3].parse, yyvsp[-1].parse ); }
+ { (yyval).parse = pwhile( (yyvsp[(2) - (5)]).parse, (yyvsp[(4) - (5)]).parse ); }
     break;
 
   case 28:
+
+/* Line 1464 of yacc.c */
 #line 213 "jamgram.y"
- { yyval.parse = pif( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[0].parse ); }
+ { (yyval).parse = pif( (yyvsp[(2) - (7)]).parse, (yyvsp[(4) - (7)]).parse, (yyvsp[(7) - (7)]).parse ); }
     break;
 
   case 29:
+
+/* Line 1464 of yacc.c */
 #line 215 "jamgram.y"
- { yyval.parse = psetc( yyvsp[-2].string, yyvsp[0].parse, yyvsp[-1].parse, yyvsp[-4].number ); }
+ { (yyval).parse = psetc( (yyvsp[(3) - (5)]).string, (yyvsp[(5) - (5)]).parse, (yyvsp[(4) - (5)]).parse, (yyvsp[(1) - (5)]).number ); }
     break;
 
   case 30:
+
+/* Line 1464 of yacc.c */
 #line 217 "jamgram.y"
- { yyval.parse = pon( yyvsp[-1].parse, yyvsp[0].parse ); }
+ { (yyval).parse = pon( (yyvsp[(2) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 31:
+
+/* Line 1464 of yacc.c */
 #line 219 "jamgram.y"
     { yymode( SCAN_STRING ); }
     break;
 
   case 32:
+
+/* Line 1464 of yacc.c */
 #line 221 "jamgram.y"
     { yymode( SCAN_NORMAL ); }
     break;
 
   case 33:
+
+/* Line 1464 of yacc.c */
 #line 223 "jamgram.y"
- { yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); }
+ { (yyval).parse = psete( (yyvsp[(3) - (9)]).string,(yyvsp[(4) - (9)]).parse,(yyvsp[(7) - (9)]).string,(yyvsp[(2) - (9)]).number ); }
     break;
 
   case 34:
+
+/* Line 1464 of yacc.c */
 #line 231 "jamgram.y"
- { yyval.number = ASSIGN_SET; }
+ { (yyval).number = ASSIGN_SET; }
     break;
 
   case 35:
+
+/* Line 1464 of yacc.c */
 #line 233 "jamgram.y"
- { yyval.number = ASSIGN_APPEND; }
+ { (yyval).number = ASSIGN_APPEND; }
     break;
 
   case 36:
+
+/* Line 1464 of yacc.c */
 #line 235 "jamgram.y"
- { yyval.number = ASSIGN_DEFAULT; }
+ { (yyval).number = ASSIGN_DEFAULT; }
     break;
 
   case 37:
+
+/* Line 1464 of yacc.c */
 #line 237 "jamgram.y"
- { yyval.number = ASSIGN_DEFAULT; }
+ { (yyval).number = ASSIGN_DEFAULT; }
     break;
 
   case 38:
+
+/* Line 1464 of yacc.c */
 #line 244 "jamgram.y"
- { yyval.parse = peval( EXPR_EXISTS, yyvsp[0].parse, pnull() ); }
+ { (yyval).parse = peval( EXPR_EXISTS, (yyvsp[(1) - (1)]).parse, pnull() ); }
     break;
 
   case 39:
+
+/* Line 1464 of yacc.c */
 #line 246 "jamgram.y"
- { yyval.parse = peval( EXPR_EQUALS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_EQUALS, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 40:
+
+/* Line 1464 of yacc.c */
 #line 248 "jamgram.y"
- { yyval.parse = peval( EXPR_NOTEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_NOTEQ, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 41:
+
+/* Line 1464 of yacc.c */
 #line 250 "jamgram.y"
- { yyval.parse = peval( EXPR_LESS, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_LESS, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 42:
+
+/* Line 1464 of yacc.c */
 #line 252 "jamgram.y"
- { yyval.parse = peval( EXPR_LESSEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_LESSEQ, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 43:
+
+/* Line 1464 of yacc.c */
 #line 254 "jamgram.y"
- { yyval.parse = peval( EXPR_MORE, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_MORE, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 44:
+
+/* Line 1464 of yacc.c */
 #line 256 "jamgram.y"
- { yyval.parse = peval( EXPR_MOREEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_MOREEQ, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 45:
+
+/* Line 1464 of yacc.c */
 #line 258 "jamgram.y"
- { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_AND, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 46:
+
+/* Line 1464 of yacc.c */
 #line 260 "jamgram.y"
- { yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_AND, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 47:
+
+/* Line 1464 of yacc.c */
 #line 262 "jamgram.y"
- { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_OR, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 48:
+
+/* Line 1464 of yacc.c */
 #line 264 "jamgram.y"
- { yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_OR, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 49:
+
+/* Line 1464 of yacc.c */
 #line 266 "jamgram.y"
- { yyval.parse = peval( EXPR_IN, yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = peval( EXPR_IN, (yyvsp[(1) - (3)]).parse, (yyvsp[(3) - (3)]).parse ); }
     break;
 
   case 50:
+
+/* Line 1464 of yacc.c */
 #line 268 "jamgram.y"
- { yyval.parse = peval( EXPR_NOT, yyvsp[0].parse, pnull() ); }
+ { (yyval).parse = peval( EXPR_NOT, (yyvsp[(2) - (2)]).parse, pnull() ); }
     break;
 
   case 51:
+
+/* Line 1464 of yacc.c */
 #line 270 "jamgram.y"
- { yyval.parse = yyvsp[-1].parse; }
+ { (yyval).parse = (yyvsp[(2) - (3)]).parse; }
     break;
 
   case 52:
+
+/* Line 1464 of yacc.c */
 #line 281 "jamgram.y"
- { yyval.parse = P0; }
+ { (yyval).parse = P0; }
     break;
 
   case 53:
+
+/* Line 1464 of yacc.c */
 #line 283 "jamgram.y"
- { yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); }
+ { (yyval).parse = pnode( (yyvsp[(1) - (2)]).parse, (yyvsp[(2) - (2)]).parse ); }
     break;
 
   case 54:
+
+/* Line 1464 of yacc.c */
 #line 287 "jamgram.y"
- { yyval.parse = psnode( yyvsp[-2].string, yyvsp[0].parse ); }
+ { (yyval).parse = psnode( (yyvsp[(2) - (4)]).string, (yyvsp[(4) - (4)]).parse ); }
     break;
 
   case 55:
+
+/* Line 1464 of yacc.c */
 #line 296 "jamgram.y"
- { yyval.parse = pnode( P0, yyvsp[0].parse ); }
+ { (yyval).parse = pnode( P0, (yyvsp[(1) - (1)]).parse ); }
     break;
 
   case 56:
+
+/* Line 1464 of yacc.c */
 #line 298 "jamgram.y"
- { yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); }
+ { (yyval).parse = pnode( (yyvsp[(3) - (3)]).parse, (yyvsp[(1) - (3)]).parse ); }
     break;
 
   case 57:
+
+/* Line 1464 of yacc.c */
 #line 308 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; yymode( SCAN_NORMAL ); }
+ { (yyval).parse = (yyvsp[(1) - (1)]).parse; yymode( SCAN_NORMAL ); }
     break;
 
   case 58:
+
+/* Line 1464 of yacc.c */
 #line 312 "jamgram.y"
- { yyval.parse = pnull(); yymode( SCAN_PUNCT ); }
+ { (yyval).parse = pnull(); yymode( SCAN_PUNCT ); }
     break;
 
   case 59:
+
+/* Line 1464 of yacc.c */
 #line 314 "jamgram.y"
- { yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); }
+ { (yyval).parse = pappend( (yyvsp[(1) - (2)]).parse, (yyvsp[(2) - (2)]).parse ); }
     break;
 
   case 60:
+
+/* Line 1464 of yacc.c */
 #line 318 "jamgram.y"
- { yyval.parse = plist( yyvsp[0].string ); }
+ { (yyval).parse = plist( (yyvsp[(1) - (1)]).string ); }
     break;
 
   case 61:
+
+/* Line 1464 of yacc.c */
 #line 319 "jamgram.y"
     { yymode( SCAN_NORMAL ); }
     break;
 
   case 62:
+
+/* Line 1464 of yacc.c */
 #line 320 "jamgram.y"
- { yyval.parse = yyvsp[-1].parse; }
+ { (yyval).parse = (yyvsp[(3) - (4)]).parse; }
     break;
 
   case 63:
+
+/* Line 1464 of yacc.c */
 #line 329 "jamgram.y"
- { yyval.parse = prule( yyvsp[-1].string, yyvsp[0].parse ); }
+ { (yyval).parse = prule( (yyvsp[(1) - (2)]).string, (yyvsp[(2) - (2)]).parse ); }
     break;
 
   case 64:
+
+/* Line 1464 of yacc.c */
 #line 331 "jamgram.y"
- { yyval.parse = pon( yyvsp[-2].parse, prule( yyvsp[-1].string, yyvsp[0].parse ) ); }
+ { (yyval).parse = pon( (yyvsp[(2) - (4)]).parse, prule( (yyvsp[(3) - (4)]).string, (yyvsp[(4) - (4)]).parse ) ); }
     break;
 
   case 65:
+
+/* Line 1464 of yacc.c */
 #line 333 "jamgram.y"
- { yyval.parse = pon( yyvsp[-2].parse, yyvsp[0].parse ); }
+ { (yyval).parse = pon( (yyvsp[(2) - (4)]).parse, (yyvsp[(4) - (4)]).parse ); }
     break;
 
   case 66:
+
+/* Line 1464 of yacc.c */
 #line 343 "jamgram.y"
- { yyval.number = 0; }
+ { (yyval).number = 0; }
     break;
 
   case 67:
+
+/* Line 1464 of yacc.c */
 #line 345 "jamgram.y"
- { yyval.number = yyvsp[-1].number | yyvsp[0].number; }
+ { (yyval).number = (yyvsp[(1) - (2)]).number | (yyvsp[(2) - (2)]).number; }
     break;
 
   case 68:
+
+/* Line 1464 of yacc.c */
 #line 349 "jamgram.y"
- { yyval.number = EXEC_UPDATED; }
+ { (yyval).number = EXEC_UPDATED; }
     break;
 
   case 69:
+
+/* Line 1464 of yacc.c */
 #line 351 "jamgram.y"
- { yyval.number = EXEC_TOGETHER; }
+ { (yyval).number = EXEC_TOGETHER; }
     break;
 
   case 70:
+
+/* Line 1464 of yacc.c */
 #line 353 "jamgram.y"
- { yyval.number = EXEC_IGNORE; }
+ { (yyval).number = EXEC_IGNORE; }
     break;
 
   case 71:
+
+/* Line 1464 of yacc.c */
 #line 355 "jamgram.y"
- { yyval.number = EXEC_QUIETLY; }
+ { (yyval).number = EXEC_QUIETLY; }
     break;
 
   case 72:
+
+/* Line 1464 of yacc.c */
 #line 357 "jamgram.y"
- { yyval.number = EXEC_PIECEMEAL; }
+ { (yyval).number = EXEC_PIECEMEAL; }
     break;
 
   case 73:
+
+/* Line 1464 of yacc.c */
 #line 359 "jamgram.y"
- { yyval.number = EXEC_EXISTING; }
+ { (yyval).number = EXEC_EXISTING; }
     break;
 
   case 74:
+
+/* Line 1464 of yacc.c */
 #line 368 "jamgram.y"
- { yyval.parse = pnull(); }
+ { (yyval).parse = pnull(); }
     break;
 
   case 75:
+
+/* Line 1464 of yacc.c */
 #line 370 "jamgram.y"
- { yyval.parse = yyvsp[0].parse; }
+ { (yyval).parse = (yyvsp[(2) - (2)]).parse; }
     break;
 
 
- }
-
-/* Line 991 of yacc.c. */
-#line 1621 "y.tab.c"
-
- yyvsp -= yylen;
- yyssp -= yylen;
 
+/* Line 1464 of yacc.c */
+#line 2118 "y.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
+ YYPOPSTACK (yylen);
+ yylen = 0;
   YY_STACK_PRINT (yyss, yyssp);
 
   *++yyvsp = yyval;
 
-
   /* Now `shift' the result of the reduction. Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by. */
@@ -1652,54 +2148,41 @@
   if (!yyerrstatus)
     {
       ++yynerrs;
-#if YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- char *yymsg;
- int yyx, yycount;
-
- yycount = 0;
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- for (yyx = yyn < 0 ? -yyn : 0;
- yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- yysize += yystrlen (yytname[yyx]) + 15, yycount++;
- yysize += yystrlen ("syntax error, unexpected ") + 1;
- yysize += yystrlen (yytname[yytype]);
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
- {
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yycount = 0;
- for (yyx = yyn < 0 ? -yyn : 0;
- yyx < (int) (sizeof (yytname) / sizeof (char *));
- yyx++)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- const char *yyq = ! yycount ? ", expecting " : " or ";
- yyp = yystpcpy (yyp, yyq);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yycount++;
- }
- }
- yyerror (yymsg);
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
               YYSTACK_FREE (yymsg);
- }
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
     }
 
 
@@ -1709,51 +2192,49 @@
       /* If just tried and failed to reuse lookahead token after an
          error, discard it. */
 
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- {
- /* Pop the error token. */
- YYPOPSTACK;
- /* Pop the rest of the stack. */
- while (yyss < yyssp)
- {
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[*yyssp], yyvsp);
- YYPOPSTACK;
- }
- YYABORT;
- }
-
- YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
- yydestruct (yytoken, &yylval);
- yychar = YYEMPTY;
-
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
      token. */
- goto yyerrlab2;
-
-
-/*----------------------------------------------------.
-| yyerrlab1 -- error raised explicitly by an action. |
-`----------------------------------------------------*/
-yyerrlab1:
-
- /* Suppress GCC warning that yyerrlab1 is unused when no action
- invokes YYERROR. */
-#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__)
- __attribute__ ((__unused__))
-#endif
+ goto yyerrlab1;
 
 
- goto yyerrlab2;
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
 
 
-/*---------------------------------------------------------------.
-| yyerrlab2 -- pop states until the error token can be shifted. |
-`---------------------------------------------------------------*/
-yyerrlab2:
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
   yyerrstatus = 3; /* Each real token shifted decrements this. */
 
   for (;;)
@@ -1774,22 +2255,20 @@
       if (yyssp == yyss)
         YYABORT;
 
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[yystate], yyvsp);
- yyvsp--;
- yystate = *--yyssp;
 
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
- if (yyn == YYFINAL)
- YYACCEPT;
-
- YYDPRINTF ((stderr, "Shifting error token, "));
-
   *++yyvsp = yylval;
 
 
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
   yystate = yyn;
   goto yynewstate;
 
@@ -1808,22 +2287,40 @@
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through. */
 #endif
 
 yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
 #ifndef yyoverflow
   if (yyss != yyssa)
     YYSTACK_FREE (yyss);
 #endif
- return yyresult;
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
 }
 
 

Modified: branches/release/tools/build/v2/engine/jamgram.h
==============================================================================
--- branches/release/tools/build/v2/engine/jamgram.h (original)
+++ branches/release/tools/build/v2/engine/jamgram.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1,27 +1,36 @@
-/* A Bison parser, made by GNU Bison 1.875. */
+/* A Bison parser, made by GNU Bison 2.4.3. */
 
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
-
+
    You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
 
 /* Tokens. */
 #ifndef YYTOKENTYPE
@@ -77,6 +86,7 @@
      STRING = 303
    };
 #endif
+/* Tokens. */
 #define _BANG_t 258
 #define _BANG_EQUALS_t 259
 #define _AMPER_t 260
@@ -127,14 +137,13 @@
 
 
 
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
 
-

Modified: branches/release/tools/build/v2/engine/jamgram.y
==============================================================================
--- branches/release/tools/build/v2/engine/jamgram.y (original)
+++ branches/release/tools/build/v2/engine/jamgram.y 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -100,34 +100,34 @@
 #include "parse.h"
 #include "scan.h"
 #include "compile.h"
-#include "newstr.h"
+#include "object.h"
 #include "rules.h"
 
 # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
-# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define F0 -1
 # define P0 (PARSE *)0
-# define S0 (char *)0
+# define S0 (OBJECT *)0
 
-# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
-# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
-# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
-# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
-# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
-# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
-# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
-# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
-# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
-# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
-# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
-# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
-# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
-# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
-# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
-# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
-# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
-# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
-# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+# define pappend( l,r ) parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( PARSE_EVAL,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( PARSE_FOREACH,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( PARSE_IF,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( PARSE_ON,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( PARSE_RULE,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( PARSE_RULES,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( PARSE_SET,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 )
 
 # define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
 # define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
@@ -325,9 +325,9 @@
  * This needs to be split cleanly out of 'rule'
  */
 
-func : arg lol
+func : ARG lol
                 { $$.parse = prule( $1.string, $2.parse ); }
- | ON_t arg arg lol
+ | ON_t arg ARG lol
                 { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
         | ON_t arg RETURN_t list
                 { $$.parse = pon( $2.parse, $4.parse ); }
@@ -369,3 +369,5 @@
         | BIND_t list
                 { $$.parse = $2.parse; }
         ;
+
+

Modified: branches/release/tools/build/v2/engine/jamgram.yy
==============================================================================
--- branches/release/tools/build/v2/engine/jamgram.yy (original)
+++ branches/release/tools/build/v2/engine/jamgram.yy 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -56,34 +56,34 @@
 #include "parse.h"
 #include "scan.h"
 #include "compile.h"
-#include "newstr.h"
+#include "object.h"
 #include "rules.h"
 
 # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
-# define F0 (LIST *(*)(PARSE *, FRAME *))0
+# define F0 -1
 # define P0 (PARSE *)0
-# define S0 (char *)0
+# define S0 (OBJECT *)0
 
-# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
-# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
-# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
-# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
-# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
-# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
-# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
-# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
-# define pclass( l,r ) parse_make( compile_class,l,r,P0,S0,S0,0 )
-# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
-# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
-# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
-# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
-# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
-# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
-# define psetc( s,p,a,l ) parse_make( compile_setcomp,p,a,P0,s,S0,l )
-# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
-# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
-# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
+# define pappend( l,r ) parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 )
+# define peval( c,l,r ) parse_make( PARSE_EVAL,l,r,P0,S0,S0,c )
+# define pfor( s,l,r,x ) parse_make( PARSE_FOREACH,l,r,P0,s,S0,x )
+# define pif( l,r,t ) parse_make( PARSE_IF,l,r,t,S0,S0,0 )
+# define pincl( l ) parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 )
+# define plist( s ) parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 )
+# define plocal( l,r,t ) parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 )
+# define pmodule( l,r ) parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 )
+# define pclass( l,r ) parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 )
+# define pnull() parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 )
+# define pon( l,r ) parse_make( PARSE_ON,l,r,P0,S0,S0,0 )
+# define prule( s,p ) parse_make( PARSE_RULE,p,P0,P0,s,S0,0 )
+# define prules( l,r ) parse_make( PARSE_RULES,l,r,P0,S0,S0,0 )
+# define pset( l,r,a ) parse_make( PARSE_SET,l,r,P0,S0,S0,a )
+# define pset1( l,r,t,a ) parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a )
+# define psetc( s,p,a,l ) parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l )
+# define psete( s,l,s1,f ) parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f )
+# define pswitch( l,r ) parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 )
+# define pwhile( l,r ) parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 )
 
 # define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
 # define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
@@ -281,9 +281,9 @@
  * This needs to be split cleanly out of 'rule'
  */
 
-func : arg lol
+func : ARG lol
                 { $$.parse = prule( $1.string, $2.parse ); }
- | `on` arg arg lol
+ | `on` arg ARG lol
                 { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
         | `on` arg `return` list
                 { $$.parse = pon( $2.parse, $4.parse ); }

Modified: branches/release/tools/build/v2/engine/lists.c
==============================================================================
--- branches/release/tools/build/v2/engine/lists.c (original)
+++ branches/release/tools/build/v2/engine/lists.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,27 +5,65 @@
  */
 
 # include "jam.h"
-# include "newstr.h"
+# include "object.h"
 # include "lists.h"
+# include "assert.h"
 
 /*
- * lists.c - maintain lists of strings
- *
- * This implementation essentially uses a singly linked list, but
- * guarantees that the head element of every list has a valid pointer
- * to the tail of the list, so the new elements can efficiently and
- * properly be appended to the end of a list.
- *
- * To avoid massive allocation, list_free() just tacks the whole freed
- * chain onto freelist and list_new() looks on freelist first for an
- * available list struct. list_free() does not free the strings in the
- * chain: it lazily lets list_new() do so.
+ * lists.c - maintain lists of objects
  *
  * 08/23/94 (seiwald) - new list_append()
  * 09/07/00 (seiwald) - documented lol_*() functions
  */
 
-static LIST *freelist = 0; /* junkpile for list_free() */
+struct freelist_node { struct freelist_node *next; };
+
+static struct freelist_node *freelist[32]; /* junkpile for list_free() */
+
+static unsigned get_bucket( unsigned size )
+{
+ unsigned bucket = 0;
+ while ( size > ( 1u << bucket ) ) ++bucket;
+ return bucket;
+}
+
+static LIST * list_alloc( unsigned size )
+{
+ unsigned bucket = get_bucket( size );
+ if ( freelist[ bucket ] )
+ {
+ struct freelist_node * result = freelist[ bucket ];
+ freelist[ bucket ] = result->next;
+ return (LIST *)result;
+ }
+ else
+ {
+ return (LIST *)BJAM_MALLOC( sizeof( LIST ) + ( 1u << bucket ) * sizeof( OBJECT * ) );
+ }
+}
+
+static void list_dealloc( LIST * l )
+{
+ unsigned size = list_length( l );
+ unsigned bucket;
+ struct freelist_node * node = (struct freelist_node *)l;
+
+ if ( size == 0 ) return;
+
+ bucket = get_bucket( size );;
+
+#ifdef BJAM_NO_MEM_CACHE
+
+ BJAM_FREE( node );
+
+#else
+
+ node->next = freelist[ bucket ];
+ freelist[ bucket ] = node;
+
+#endif
+
+}
 
 /*
  * list_append() - append a list onto another one, returning total
@@ -33,60 +71,104 @@
 
 LIST * list_append( LIST * l, LIST * nl )
 {
- if ( !nl )
+ if ( list_empty( nl ) )
     {
         /* Just return l */
     }
- else if ( !l )
+ else if ( list_empty( l ) )
     {
         l = nl;
     }
     else
     {
- /* Graft two non-empty lists. */
- l->tail->next = nl;
- l->tail = nl->tail;
+ int l_size = list_length( l );
+ int nl_size = list_length( nl );
+ int size = l_size + nl_size;
+ unsigned bucket;
+ int i;
+
+ bucket = get_bucket( size );
+ /* Do we need to reallocate? */
+ if ( l_size <= ( 1u << (bucket - 1) ) )
+ {
+ LIST * result = list_alloc( size );
+ memcpy( list_begin( result ), list_begin( l ), l_size * sizeof( OBJECT * ) );
+ list_dealloc( l );
+ l = result;
+ }
+
+ l->impl.size = size;
+ memcpy( list_begin( l ) + l_size, list_begin( nl ), nl_size * sizeof( OBJECT * ) );
+ list_dealloc( nl );
+ return l;
     }
 
     return l;
 }
 
+LISTITER list_begin( LIST * l )
+{
+ if ( l )
+ return (LISTITER)( (char *)l + sizeof(LIST) );
+ else
+ return 0;
+}
+
+LISTITER list_end( LIST * l )
+{
+ if ( l )
+ return list_begin( l ) + l->impl.size;
+ else
+ return 0;
+}
+
+LIST * list_new( OBJECT * value )
+{
+ LIST * head;
+ if ( freelist[ 0 ] )
+ {
+ struct freelist_node * result = freelist[ 0 ];
+ freelist[ 0 ] = result->next;
+ head = (LIST *)result;
+ }
+ else
+ {
+ head = BJAM_MALLOC( sizeof( LIST * ) + sizeof( OBJECT * ) );
+ }
+
+ head->impl.size = 1;
+ list_begin( head )[ 0 ] = value;
+
+ return head;
+}
+
 /*
- * list_new() - tack a string onto the end of a list of strings
+ * list_push_back() - tack a string onto the end of a list of strings
  */
 
-LIST * list_new( LIST * head, char * string )
+LIST * list_push_back( LIST * head, OBJECT * value )
 {
- LIST * l;
+ unsigned int size = list_length( head );
+ unsigned int i;
 
     if ( DEBUG_LISTS )
- printf( "list > %s <\n", string );
+ printf( "list > %s <\n", object_str( value ) );
 
- /* Get list struct from freelist, if one available. */
- /* Otherwise allocate. */
- /* If from freelist, must free string first */
-
- if ( freelist )
+ /* If the size is a power of 2, reallocate. */
+ if ( size == 0 )
     {
- l = freelist;
- freestr( l->string );
- freelist = freelist->next;
+ head = list_alloc( 1 );
     }
- else
+ else if ( ( ( size - 1 ) & size ) == 0 )
     {
- l = (LIST *)BJAM_MALLOC( sizeof( LIST ) );
+ LIST * l = list_alloc( size + 1 );
+ memcpy( l, head, sizeof( LIST ) + size * sizeof( OBJECT * ) );
+ list_dealloc( head );
+ head = l;
     }
 
- /* If first on chain, head points here. */
- /* If adding to chain, tack us on. */
- /* Tail must point to this new, last element. */
-
- if ( !head ) head = l;
- else head->tail->next = l;
- head->tail = l;
- l->next = 0;
-
- l->string = string;
+ list_begin( head )[ size ] = value;
+ head->impl.size = size + 1;
 
     return head;
 }
@@ -96,11 +178,42 @@
  * list_copy() - copy a whole list of strings (nl) onto end of another (l).
  */
 
-LIST * list_copy( LIST * l, LIST * nl )
+LIST * list_copy( LIST * l )
 {
- for ( ; nl; nl = list_next( nl ) )
- l = list_new( l, copystr( nl->string ) );
- return l;
+ int size = list_length( l );
+ int i;
+ LIST * result;
+
+ if ( size == 0 ) return L0;
+
+ result = list_alloc( size );
+ result->impl.size = size;
+ for ( i = 0; i < size; ++i )
+ {
+ list_begin( result )[ i ] = object_copy( list_begin( l )[ i ] );
+ }
+ return result;
+}
+
+
+LIST * list_copy_range( LIST *l, LISTITER first, LISTITER last )
+{
+ if ( first == last )
+ {
+ return L0;
+ }
+ else
+ {
+ int size = last - first;
+ LIST * result = list_alloc( size );
+ LISTITER dest = list_begin( result );
+ result->impl.size = size;
+ for ( ; first != last; ++first, ++dest )
+ {
+ *dest = object_copy( *first );
+ }
+ return result;
+ }
 }
 
 
@@ -110,19 +223,19 @@
 
 LIST * list_sublist( LIST * l, int start, int count )
 {
- LIST * nl = 0;
- for ( ; l && start--; l = list_next( l ) );
- for ( ; l && count--; l = list_next( l ) )
- nl = list_new( nl, copystr( l->string ) );
- return nl;
+ int end = start + count;
+ int size = list_length( l );
+ if ( start >= size ) return L0;
+ if ( end > size ) end = size;
+ return list_copy_range( l, list_begin( l ) + start, list_begin( l ) + end );
 }
 
 
 static int str_ptr_compare( void const * va, void const * vb )
 {
- char * a = *( (char * *)va );
- char * b = *( (char * *)vb );
- return strcmp(a, b);
+ OBJECT * a = *( (OBJECT * *)va );
+ OBJECT * b = *( (OBJECT * *)vb );
+ return strcmp(object_str(a), object_str(b));
 }
 
 
@@ -130,29 +243,15 @@
 {
     int len;
     int ii;
- char * * strings;
- LIST * listp;
- LIST * result = 0;
+ LIST * result;
 
     if ( !l )
         return L0;
 
     len = list_length( l );
- strings = (char * *)BJAM_MALLOC( len * sizeof(char*) );
-
- listp = l;
- for ( ii = 0; ii < len; ++ii )
- {
- strings[ ii ] = listp->string;
- listp = listp->next;
- }
-
- qsort( strings, len, sizeof( char * ), str_ptr_compare );
+ result = list_copy( l );
 
- for ( ii = 0; ii < len; ++ii )
- result = list_append( result, list_new( 0, strings[ ii ] ) );
-
- BJAM_FREE( strings );
+ qsort( list_begin( result ), len, sizeof( OBJECT * ), str_ptr_compare );
 
     return result;
 }
@@ -164,11 +263,14 @@
 
 void list_free( LIST * head )
 {
- /* Just tack onto freelist. */
- if ( head )
+ if ( !list_empty( head ) )
     {
- head->tail->next = freelist;
- freelist = head;
+ LISTITER iter = list_begin( head ), end = list_end( head );
+ for ( ; iter != end; iter = list_next( iter ) )
+ {
+ object_free( list_item( iter ) );
+ }
+ list_dealloc( head );
     }
 }
 
@@ -179,17 +281,79 @@
 
 LIST * list_pop_front( LIST * l )
 {
- LIST * result = l->next;
- if ( result )
+ unsigned size = list_length( l );
+ assert( size != 0 );
+ --size;
+ object_free( list_front( l ) );
+
+ if ( size == 0 )
     {
- result->tail = l->tail;
- l->next = L0;
- l->tail = l;
+ list_dealloc( l );
+ return L0;
+ }
+ else if ( ( ( size - 1 ) & size ) == 0 )
+ {
+ LIST * nl = list_alloc( size );
+ nl->impl.size = size;
+ memcpy( list_begin( nl ), list_begin( l ) + 1, size * sizeof( OBJECT * ) );
+ list_dealloc( l );
+ return nl;
+ }
+ else
+ {
+ l->impl.size = size;
+ memmove( list_begin( l ), list_begin( l ) + 1, size * sizeof( OBJECT * ) );
+ return l;
+ }
+}
+
+LIST * list_reverse( LIST * l )
+{
+ int size = list_length( l );
+ if ( size == 0 ) return L0;
+ else
+ {
+ LIST * result = list_alloc( size );
+ int i;
+ result->impl.size = size;
+ for ( i = 0; i < size; ++i )
+ {
+ list_begin( result )[ i ] = object_copy( list_begin( l )[ size - i - 1 ] );
+ }
+ return result;
     }
- list_free( l );
- return result;
 }
 
+int list_cmp( LIST * t, LIST * s )
+{
+ int status = 0;
+ LISTITER t_it = list_begin( t ), t_end = list_end( t );
+ LISTITER s_it = list_begin( s ), s_end = list_end( s );
+
+ while ( !status && ( t_it != t_end || s_it != s_end ) )
+ {
+ const char *st = t_it != t_end ? object_str( list_item( t_it ) ) : "";
+ const char *ss = s_it != s_end ? object_str( list_item( s_it ) ) : "";
+
+ status = strcmp( st, ss );
+
+ t_it = t_it != t_end ? list_next( t_it ) : t_it;
+ s_it = s_it != s_end ? list_next( s_it ) : s_it;
+ }
+
+ return status;
+}
+
+int list_is_sublist( LIST * sub, LIST * l )
+{
+ LISTITER iter = list_begin( sub ), end = list_end( sub );
+ for ( ; iter != end; iter = list_next( iter ) )
+ {
+ if ( !list_in( l, list_item( iter ) ) )
+ return 0;
+ }
+ return 1;
+}
 
 /*
  * list_print() - print a list of strings to stdout
@@ -197,12 +361,14 @@
 
 void list_print( LIST * l )
 {
- LIST * p = 0;
- for ( ; l; p = l, l = list_next( l ) )
- if ( p )
- printf( "%s ", p->string );
- if ( p )
- printf( "%s", p->string );
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ if ( iter != end )
+ {
+ printf( "%s", object_str( list_item( iter ) ) );
+ iter = list_next( iter );
+ for ( ; iter != end; iter = list_next( iter ) )
+ printf( " %s", object_str( list_item( iter ) ) );
+ }
 }
 
 
@@ -212,16 +378,18 @@
 
 int list_length( LIST * l )
 {
- int n = 0;
- for ( ; l; l = list_next( l ), ++n );
- return n;
+ if ( l )
+ return l->impl.size;
+ else
+ return 0;
 }
 
 
-int list_in( LIST * l, char * value )
+int list_in( LIST * l, OBJECT * value )
 {
- for ( ; l; l = l->next )
- if ( strcmp( l->string, value ) == 0 )
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ for ( ; iter != end; iter = list_next( iter ) )
+ if ( object_equal( list_item( iter ), value ) )
             return 1;
     return 0;
 }
@@ -229,20 +397,38 @@
 
 LIST * list_unique( LIST * sorted_list )
 {
- LIST * result = 0;
- LIST * last_added = 0;
+ LIST * result = L0;
+ OBJECT * last_added = 0;
 
- for ( ; sorted_list; sorted_list = sorted_list->next )
+ LISTITER iter = list_begin( sorted_list ), end = list_end( sorted_list );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- if ( !last_added || strcmp( sorted_list->string, last_added->string ) != 0 )
+ if ( !last_added || !object_equal( list_item( iter ), last_added ) )
         {
- result = list_new( result, sorted_list->string );
- last_added = sorted_list;
+ result = list_push_back( result, object_copy( list_item( iter ) ) );
+ last_added = list_item( iter );
         }
     }
     return result;
 }
 
+void list_done()
+{
+ int i;
+ int total = 0;
+ for ( i = 0; i < sizeof( freelist ) / sizeof( freelist[ 0 ] ); ++i )
+ {
+ struct freelist_node *l, *tmp;
+ int bytes;
+ for( l = freelist[ i ]; l; )
+ {
+ tmp = l;
+ l = l->next;
+ BJAM_FREE( tmp );
+ }
+ }
+}
+
 
 /*
  * lol_init() - initialize a LOL (list of lists).
@@ -284,7 +470,7 @@
 
 LIST * lol_get( LOL * lol, int i )
 {
- return i < lol->count ? lol->list[ i ] : 0;
+ return i < lol->count ? lol->list[ i ] : L0;
 }
 
 
@@ -309,10 +495,11 @@
 PyObject *list_to_python(LIST *l)
 {
     PyObject *result = PyList_New(0);
+ LISTITER iter = list_begin( l ), end = list_end( l );
 
- for (; l; l = l->next)
+ for (; iter != end; iter = list_next( iter ) )
     {
- PyObject* s = PyString_FromString(l->string);
+ PyObject* s = PyString_FromString(object_str(list_item(iter)));
         PyList_Append(result, s);
         Py_DECREF(s);
     }
@@ -322,14 +509,14 @@
 
 LIST *list_from_python(PyObject *l)
 {
- LIST * result = 0;
+ LIST * result = L0;
 
     Py_ssize_t i, n;
     n = PySequence_Size(l);
     for (i = 0; i < n; ++i)
     {
         PyObject *v = PySequence_GetItem(l, i);
- result = list_new (result, newstr (PyString_AsString(v)));
+ result = list_push_back(result, object_new (PyString_AsString(v)));
         Py_DECREF(v);
     }
 

Modified: branches/release/tools/build/v2/engine/lists.h
==============================================================================
--- branches/release/tools/build/v2/engine/lists.h (original)
+++ branches/release/tools/build/v2/engine/lists.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -13,23 +13,23 @@
 /*
  * lists.h - the LIST structure and routines to manipulate them
  *
- * The whole of jam relies on lists of strings as a datatype. This
- * module, in conjunction with newstr.c, handles these relatively
+ * The whole of jam relies on lists of objects as a datatype. This
+ * module, in conjunction with object.c, handles these relatively
  * efficiently.
  *
  * Structures defined:
  *
- * LIST - list of strings
+ * LIST - list of OBJECTs
  * LOL - list of LISTs
  *
  * External routines:
  *
  * list_append() - append a list onto another one, returning total
- * list_new() - tack a string onto the end of a list of strings
- * list_copy() - copy a whole list of strings
- * list_sublist() - copy a subset of a list of strings
- * list_free() - free a list of strings
- * list_print() - print a list of strings to stdout
+ * list_new() - tack an object onto the end of a list of objects
+ * list_copy() - copy a whole list of objects
+ * list_sublist() - copy a subset of a list of objects
+ * list_free() - free a list of objects
+ * list_print() - print a list of objects to stdout
  * list_length() - return the number of items in the list
  *
  * lol_init() - initialize a LOL (list of lists)
@@ -45,6 +45,8 @@
 #ifndef LISTS_DWA20011022_H
 # define LISTS_DWA20011022_H
 
+#include "object.h"
+
 #ifdef HAVE_PYTHON
 #include <Python.h>
 #endif
@@ -56,11 +58,14 @@
 typedef struct _list LIST;
 
 struct _list {
- LIST *next;
- LIST *tail; /* only valid in head node */
- char *string; /* private copy */
+ union {
+ int size;
+ OBJECT *align;
+ } impl;
 };
 
+typedef OBJECT * * LISTITER;
+
 /*
  * LOL - list of LISTs
  */
@@ -74,19 +79,30 @@
     LIST *list[ LOL_MAX ];
 };
 
+LIST * list_new( OBJECT * value );
 LIST * list_append( LIST *l, LIST *nl );
-LIST * list_copy( LIST *l, LIST *nl );
+LIST * list_copy( LIST *l );
+LIST * list_copy_range( LIST *l, LISTITER first, LISTITER last );
 void list_free( LIST *head );
-LIST * list_new( LIST *head, char *string );
+LIST * list_push_back( LIST *head, OBJECT *string );
 void list_print( LIST *l );
 int list_length( LIST *l );
 LIST * list_sublist( LIST *l, int start, int count );
 LIST * list_pop_front( LIST *l );
 LIST * list_sort( LIST *l);
 LIST * list_unique( LIST *sorted_list);
-int list_in(LIST* l, char* value);
-
-# define list_next( l ) ((l)->next)
+int list_in(LIST* l, OBJECT* value);
+LIST * list_reverse( LIST * );
+int list_cmp( LIST * lhs, LIST * rhs );
+int list_is_sublist( LIST * sub, LIST * l );
+void list_done();
+
+LISTITER list_begin( LIST * );
+LISTITER list_end( LIST * );
+# define list_next( it ) ((it) + 1)
+# define list_item( it ) (*(it))
+# define list_empty( l ) ( (l) == L0 )
+# define list_front( l ) list_item( list_begin( l ) )
 
 # define L0 ((LIST *)0)
 
@@ -95,7 +111,7 @@
 void lol_free( LOL *lol );
 LIST * lol_get( LOL *lol, int i );
 void lol_print( LOL *lol );
-void lol_build( LOL* lol, char** elements );
+void lol_build( LOL* lol, const char** elements );
 
 #ifdef HAVE_PYTHON
 

Modified: branches/release/tools/build/v2/engine/make.c
==============================================================================
--- branches/release/tools/build/v2/engine/make.c (original)
+++ branches/release/tools/build/v2/engine/make.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -58,7 +58,7 @@
 #endif
 
 #include "search.h"
-#include "newstr.h"
+#include "object.h"
 #include "make.h"
 #include "headers.h"
 #include "command.h"
@@ -106,9 +106,8 @@
  * make() - make a target, given its name.
  */
 
-int make( int n_targets, char const * * targets, int anyhow )
+int make( LIST * targets, int anyhow )
 {
- int i;
     COUNTS counts[ 1 ];
     int status = 0; /* 1 if anything fails */
 
@@ -124,16 +123,24 @@
     bind_explicitly_located_targets();
 
     {
+ LISTITER iter, end;
         PROFILE_ENTER( MAKE_MAKE0 );
- for ( i = 0; i < n_targets; ++i )
- make0( bindtarget( targets[ i ] ), 0, 0, counts, anyhow );
+ for ( iter = list_begin( targets ), end = list_end( targets ); iter != end; iter = list_next( iter ) )
+ {
+ TARGET * t = bindtarget( list_item( iter ) );
+ if ( t->fate == T_FATE_INIT )
+ make0( t, 0, 0, counts, anyhow );
+ }
         PROFILE_EXIT( MAKE_MAKE0 );
     }
 
 #ifdef OPT_GRAPH_DEBUG_EXT
     if ( DEBUG_GRAPH )
- for ( i = 0; i < n_targets; ++i )
- dependGraphOutput( bindtarget( targets[ i ] ), 0 );
+ {
+ LISTITER iter, end;
+ for ( iter = list_begin( targets ), end = list_end( targets ); iter != end; iter = list_next( iter ) )
+ dependGraphOutput( bindtarget( list_item( iter ) ), 0 );
+ }
 #endif
 
     if ( DEBUG_MAKE )
@@ -155,16 +162,13 @@
                 counts->cantmake > 1 ? "s" : "" );
     }
 
-#ifdef OPT_HEADER_CACHE_EXT
- hcache_done();
-#endif
-
     status = counts->cantfind || counts->cantmake;
 
     {
+ LISTITER iter, end;
         PROFILE_ENTER( MAKE_MAKE1 );
- for ( i = 0; i < n_targets; ++i )
- status |= make1( bindtarget( targets[ i ] ) );
+ for ( iter = list_begin( targets ), end = list_end( targets ); iter != end; iter = list_next( iter ) )
+ status |= make1( bindtarget( list_item( iter ) ) );
         PROFILE_EXIT( MAKE_MAKE1 );
     }
 
@@ -195,7 +199,7 @@
             if ( DEBUG_FATE )
             {
                 printf( "fate change %s from %s to %s (as dependant of %s)\n",
- p->name, target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], t->name );
+ object_str( p->name ), target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], object_str( t->name ) );
             }
 
             /* If we are done visiting it, go back and make sure its dependants
@@ -224,7 +228,7 @@
         {
             if ( DEBUG_FATE )
                 printf( "fate change %s from %s to %s (by rebuild)\n",
- r->name, target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] );
+ object_str( r->name ), target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] );
 
             /* Force rebuild it. */
             r->fate = T_FATE_REBUILD;
@@ -266,14 +270,14 @@
 #endif
 
     if ( DEBUG_MAKEPROG )
- printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+ printf( "make\t--\t%s%s\n", spaces( depth ), object_str( t->name ) );
 
     /*
      * Step 1: initialize
      */
 
     if ( DEBUG_MAKEPROG )
- printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+ printf( "make\t--\t%s%s\n", spaces( depth ), object_str( t->name ) );
 
     t->fate = T_FATE_MAKING;
 
@@ -284,12 +288,13 @@
 
     /* Step 2a: set "on target" variables. */
     s = copysettings( t->settings );
- pushsettings( s );
+ pushsettings( root_module(), s );
 
     /* Step 2b: find and timestamp the target file (if it is a file). */
     if ( ( t->binding == T_BIND_UNBOUND ) && !( t->flags & T_FLAG_NOTFILE ) )
     {
- char * another_target;
+ OBJECT * another_target;
+ object_free( t->boundname );
         t->boundname = search( t->name, &t->time, &another_target,
                                t->flags & T_FLAG_ISFILE );
         /* If it was detected that this target refers to an already existing and
@@ -317,10 +322,10 @@
 
 #ifdef OPT_SEMAPHORE
     {
- LIST * var = var_get( "JAM_SEMAPHORE" );
- if ( var )
+ LIST * var = var_get( root_module(), constant_JAM_SEMAPHORE );
+ if ( !list_empty( var ) )
         {
- TARGET * semaphore = bindtarget( var->string );
+ TARGET * semaphore = bindtarget( list_front( var ) );
             semaphore->progress = T_MAKE_SEMAPHORE;
             t->semaphore = semaphore;
         }
@@ -332,7 +337,7 @@
         headers( t );
 
     /* Step 2d: reset "on target" variables. */
- popsettings( s );
+ popsettings( root_module(), s );
     freesettings( s );
 
     /*
@@ -341,9 +346,9 @@
 
     if ( DEBUG_BIND )
     {
- if ( strcmp( t->name, t->boundname ) )
+ if ( ! object_equal( t->name, t->boundname ) )
             printf( "bind\t--\t%s%s: %s\n",
- spaces( depth ), t->name, t->boundname );
+ spaces( depth ), object_str( t->name ), object_str( t->boundname ) );
 
         switch ( t->binding )
         {
@@ -351,12 +356,12 @@
         case T_BIND_MISSING:
         case T_BIND_PARENTS:
             printf( "time\t--\t%s%s: %s\n",
- spaces( depth ), t->name, target_bind[ (int) t->binding ] );
+ spaces( depth ), object_str( t->name ), target_bind[ (int) t->binding ] );
             break;
 
         case T_BIND_EXISTS:
             printf( "time\t--\t%s%s: %s",
- spaces( depth ), t->name, ctime( &t->time ) );
+ spaces( depth ), object_str( t->name ), ctime( &t->time ) );
             break;
         }
     }
@@ -376,7 +381,7 @@
         if ( c->target->fate == T_FATE_INIT )
             make0( c->target, ptime, depth + 1, counts, anyhow );
         else if ( c->target->fate == T_FATE_MAKING && !internal )
- printf( "warning: %s depends on itself\n", c->target->name );
+ printf( "warning: %s depends on itself\n", object_str( c->target->name ) );
     }
 
     /* Step 3b: recursively make0() internal includes node. */
@@ -420,8 +425,8 @@
         if ( DEBUG_FATE )
             if ( fate < c->target->fate )
                 printf( "fate change %s from %s to %s by dependency %s\n",
- t->name, target_fate[(int) fate], target_fate[(int) c->target->fate],
- c->target->name );
+ object_str( t->name ), target_fate[(int) fate], target_fate[(int) c->target->fate],
+ object_str( c->target->name ) );
 #endif
     }
 
@@ -445,8 +450,8 @@
 #ifdef OPT_GRAPH_DEBUG_EXT
         if ( DEBUG_FATE )
             if ( fate != T_FATE_STABLE )
- printf( "fate change %s back to stable, NOUPDATE.\n", t->name
- );
+ printf( "fate change %s back to stable, NOUPDATE.\n",
+ object_str( t->name ) );
 #endif
 
         last = 0;
@@ -541,10 +546,10 @@
     if ( DEBUG_FATE && ( fate != savedFate ) )
         {
         if ( savedFate == T_FATE_STABLE )
- printf( "fate change %s set to %s%s\n", t->name,
+ printf( "fate change %s set to %s%s\n", object_str( t->name ),
                 target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" );
         else
- printf( "fate change %s from %s to %s%s\n", t->name,
+ printf( "fate change %s from %s to %s%s\n", object_str( t->name ),
                 target_fate[ savedFate ], target_fate[ fate ],
                 oldTimeStamp ? " (by timestamp)" : "" );
         }
@@ -564,13 +569,13 @@
             if ( DEBUG_FATE )
                 printf( "fate change %s to STABLE from %s, "
                     "no actions, no dependencies and do not care\n",
- t->name, target_fate[ fate ] );
+ object_str( t->name ), target_fate[ fate ] );
 #endif
             fate = T_FATE_STABLE;
         }
         else
         {
- printf( "don't know how to make %s\n", t->name );
+ printf( "don't know how to make %s\n", object_str( t->name ) );
             fate = T_FATE_CANTFIND;
         }
     }
@@ -637,7 +642,7 @@
 
     if ( DEBUG_MAKEPROG )
         printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int) t->fate ],
- spaces( depth ), t->name );
+ spaces( depth ), object_str( t->name ) );
 }
 
 
@@ -648,10 +653,10 @@
     static char buf[ 1000 ];
     if ( t->flags & T_FLAG_INTERNAL )
     {
- sprintf( buf, "%s (internal node)", t->name );
+ sprintf( buf, "%s (internal node)", object_str( t->name ) );
         return buf;
     }
- return t->name;
+ return object_str( t->name );
 }
 
 
@@ -681,8 +686,8 @@
         break;
     }
 
- if ( strcmp( t->name, t->boundname ) )
- printf( " %s Loc: %s\n", spaces( depth ), t->boundname );
+ if ( ! object_equal( t->name, t->boundname ) )
+ printf( " %s Loc: %s\n", spaces( depth ), object_str( t->boundname ) );
 
     switch ( t->fate )
     {
@@ -792,12 +797,12 @@
 }
 
 
-static LIST * targets_to_update_ = 0;
+static LIST * targets_to_update_ = L0;
 
 
-void mark_target_for_updating( char * target )
+void mark_target_for_updating( OBJECT * target )
 {
- targets_to_update_ = list_new( targets_to_update_, target );
+ targets_to_update_ = list_push_back( targets_to_update_, object_copy( target ) );
 }
 
 
@@ -810,5 +815,5 @@
 void clear_targets_to_update()
 {
     list_free( targets_to_update_ );
- targets_to_update_ = 0;
+ targets_to_update_ = L0;
 }

Modified: branches/release/tools/build/v2/engine/make.h
==============================================================================
--- branches/release/tools/build/v2/engine/make.h (original)
+++ branches/release/tools/build/v2/engine/make.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,10 +8,14 @@
  * make.h - bring a target up to date, once rules are in place
  */
 
+#ifndef MAKE_SW20111118_H
+#define MAKE_SW20111118_H
+
 #include "lists.h"
+#include "object.h"
 
-int make( int n_targets, const char **targets, int anyhow );
-int make1( TARGET *t );
+int make( LIST * targets, int anyhow );
+int make1( TARGET * t );
 
 typedef struct {
     int temp;
@@ -30,12 +34,14 @@
 /*
  * Specifies that the target should be updated.
  */
-void mark_target_for_updating(char *target);
+void mark_target_for_updating( OBJECT * target );
 /*
  * Returns the list of all the target previously passed to 'mark_target_for_updating'.
  */
-LIST *targets_to_update();
+LIST * targets_to_update();
 /*
  * Cleasr/unmarks all targets that are currently marked for update.
  */
 void clear_targets_to_update();
+
+#endif

Modified: branches/release/tools/build/v2/engine/make1.c
==============================================================================
--- branches/release/tools/build/v2/engine/make1.c (original)
+++ branches/release/tools/build/v2/engine/make1.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -57,7 +57,7 @@
 #include "headers.h"
 
 #include "search.h"
-#include "newstr.h"
+#include "object.h"
 #include "make.h"
 #include "command.h"
 #include "execcmd.h"
@@ -72,7 +72,7 @@
 
 static CMD * make1cmds ( TARGET * );
 static LIST * make1list ( LIST *, TARGETS *, int flags );
-static SETTINGS * make1settings( LIST * vars );
+static SETTINGS * make1settings( struct module_t * module, LIST * vars );
 static void make1bind ( TARGET * );
 
 /* Ugly static - it is too hard to carry it through the callbacks. */
@@ -107,7 +107,7 @@
 static void make1b ( state * );
 static void make1c ( state * );
 static void make1d ( state * );
-static void make_closure( void * closure, int status, timing_info *, char *, char * );
+static void make_closure( void * closure, int status, timing_info *, const char *, const char * );
 
 typedef struct _stack
 {
@@ -281,6 +281,15 @@
                 ++pState->parent->asynccnt;
         }
 
+ /*
+ * If the target has been previously updated with -n in
+ * effect, and we're ignoring -n, update it for real.
+ */
+ if ( !globs.noexec && pState->t->progress == T_MAKE_NOEXEC_DONE )
+ {
+ pState->t->progress = T_MAKE_INIT;
+ }
+
     /* If this target is already being processed then do nothing. There is no
      * need to start processing the same target all over again.
      */
@@ -350,10 +359,10 @@
 
 static void make1b( state * pState )
 {
- TARGET * t = pState->t;
- TARGETS * c;
- TARGET * failed = 0;
- char * failed_name = "dependencies";
+ TARGET * t = pState->t;
+ TARGETS * c;
+ TARGET * failed = 0;
+ const char * failed_name = "dependencies";
 
     /* If any dependencies are still outstanding, wait until they call make1b()
      * to signal their completion.
@@ -376,7 +385,7 @@
 
         if ( DEBUG_EXECCMD )
             printf( "SEM: %s is busy, delaying launch of %s\n",
- t->semaphore->name, t->name );
+ object_str( t->semaphore->name ), object_str( t->name ) );
         pop_state( &state_stack );
         return;
     }
@@ -384,13 +393,21 @@
 
     /* Now ready to build target 't', if dependencies built OK. */
 
- /* Collect status from dependencies. */
- for ( c = t->depends; c; c = c->next )
- if ( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ) )
- {
- failed = c->target;
- pState->t->status = c->target->status;
- }
+ /* Collect status from dependencies. If -n was passed then
+ * act as though all dependencies built correctly. The only
+ * way they can fail is if UPDATE_NOW was called. If
+ * the dependencies can't be found or we got an interrupt,
+ * we can't get here.
+ */
+ if ( !globs.noexec )
+ {
+ for ( c = t->depends; c; c = c->next )
+ if ( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ) )
+ {
+ failed = c->target;
+ pState->t->status = c->target->status;
+ }
+ }
     /* If an internal header node failed to build, we want to output the target
      * that it failed on.
      */
@@ -398,7 +415,7 @@
     {
         failed_name = failed->flags & T_FLAG_INTERNAL
             ? failed->failed
- : failed->name;
+ : object_str( failed->name );
     }
     t->failed = failed_name;
 
@@ -410,11 +427,11 @@
         ++counts->skipped;
         if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
         {
- if ( !unlink( pState->t->boundname ) )
- printf( "...removing outdated %s\n", pState->t->boundname );
+ if ( !unlink( object_str( pState->t->boundname ) ) )
+ printf( "...removing outdated %s\n", object_str( pState->t->boundname ) );
         }
         else
- printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name );
+ printf( "...skipped %s for lack of %s...\n", object_str( pState->t->name ), failed_name );
     }
 
     if ( pState->t->status == EXEC_CMD_OK )
@@ -436,7 +453,7 @@
 
         case T_FATE_ISTMP:
             if ( DEBUG_MAKE )
- printf( "...using %s...\n", pState->t->name );
+ printf( "...using %s...\n", object_str( pState->t->name ) );
             break;
 
         case T_FATE_TOUCHED:
@@ -467,7 +484,7 @@
 
             /* All possible fates should have been accounted for by now. */
         default:
- printf( "ERROR: %s has bad fate %d", pState->t->name,
+ printf( "ERROR: %s has bad fate %d", object_str( pState->t->name ),
                 pState->t->fate );
             abort();
         }
@@ -484,8 +501,8 @@
     {
         ++pState->t->semaphore->asynccnt;
         if ( DEBUG_EXECCMD )
- printf( "SEM: %s now used by %s\n", pState->t->semaphore->name,
- pState->t->name );
+ printf( "SEM: %s now used by %s\n", object_str( pState->t->semaphore->name ),
+ object_str( pState->t->name ) );
     }
 #endif
 
@@ -508,16 +525,16 @@
 
     if ( cmd && ( pState->t->status == EXEC_CMD_OK ) )
     {
- char * rule_name = 0;
- char * target = 0;
+ const char * rule_name = 0;
+ const char * target = 0;
 
         if ( DEBUG_MAKEQ ||
             ( !( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE ) )
         {
- rule_name = cmd->rule->name;
- target = lol_get( &cmd->args, 0 )->string;
+ rule_name = object_str( cmd->rule->name );
+ target = object_str( list_front( lol_get( &cmd->args, 0 ) ) );
             if ( globs.noexec )
- out_action( rule_name, target, cmd->buf, "", "", EXIT_OK );
+ out_action( rule_name, target, cmd->buf->value, "", "", EXIT_OK );
         }
 
         if ( globs.noexec )
@@ -529,7 +546,7 @@
         {
             /* Pop state first because exec_cmd() could push state. */
             pop_state( &state_stack );
- exec_cmd( cmd->buf, make_closure, pState->t, cmd->shell, rule_name,
+ exec_cmd( cmd->buf->value, make_closure, pState->t, cmd->shell, rule_name,
                 target );
         }
     }
@@ -560,13 +577,17 @@
             TARGET * t = pState->t;
             TARGET * additional_includes = NULL;
 
- t->progress = T_MAKE_DONE;
+ if ( globs.noexec )
+ t->progress = T_MAKE_NOEXEC_DONE;
+ else
+ t->progress = T_MAKE_DONE;
 
             /* Target has been updated so rescan it for dependencies. */
             if ( ( t->fate >= T_FATE_MISSING ) &&
                 ( t->status == EXEC_CMD_OK ) &&
                 !t->rescanned )
             {
+ TARGET * saved_includes;
                 TARGET * target_to_rescan = t;
                 SETTINGS * s;
 
@@ -576,16 +597,21 @@
                     target_to_rescan = t->original_target;
 
                 /* Clean current includes. */
+ saved_includes = target_to_rescan->includes;
                 target_to_rescan->includes = 0;
 
                 s = copysettings( target_to_rescan->settings );
- pushsettings( s );
+ pushsettings( root_module(), s );
                 headers( target_to_rescan );
- popsettings( s );
+ popsettings( root_module(), s );
                 freesettings( s );
 
                 if ( target_to_rescan->includes )
                 {
+ /* Link the old includes on to make sure that it gets
+ * cleaned up correctly.
+ */
+ target_to_rescan->includes->includes = saved_includes;
                     target_to_rescan->includes->rescanned = 1;
                     /* Tricky. The parents have already been processed, but they
                      * have not seen the internal node, because it was just
@@ -604,6 +630,10 @@
                     /* Will be processed below. */
                     additional_includes = target_to_rescan->includes;
                 }
+ else
+ {
+ target_to_rescan->includes = saved_includes;
+ }
             }
 
             if ( additional_includes )
@@ -621,7 +651,7 @@
                 --t->semaphore->asynccnt;
 
                 if ( DEBUG_EXECCMD )
- printf( "SEM: %s is now free\n", t->semaphore->name );
+ printf( "SEM: %s is now free\n", object_str( t->semaphore->name ) );
 
                 /* If anything is waiting, notify the next target. There is no
                  * point in notifying waiting targets, since they will be
@@ -635,7 +665,7 @@
                     t->semaphore->parents = first->next;
 
                     if ( DEBUG_EXECCMD )
- printf( "SEM: placing %s on stack\n", first->target->name );
+ printf( "SEM: placing %s on stack\n", object_str( first->target->name ) );
                     push_state( &temp_stack, first->target, NULL, T_STATE_MAKE1B );
                     BJAM_FREE( first );
                 }
@@ -662,11 +692,11 @@
 {
     LIST * timing_rule;
 
- pushsettings( target->settings );
- timing_rule = var_get( "__TIMING_RULE__" );
- popsettings( target->settings );
+ pushsettings( root_module(), target->settings );
+ timing_rule = var_get( root_module(), constant_TIMING_RULE );
+ popsettings( root_module(), target->settings );
 
- if ( timing_rule )
+ if ( !list_empty( timing_rule ) )
     {
         /* rule timing-rule ( args * : target : start end user system ) */
 
@@ -675,20 +705,20 @@
         frame_init( frame );
 
         /* args * :: $(__TIMING_RULE__[2-]) */
- lol_add( frame->args, list_copy( L0, timing_rule->next ) );
+ lol_add( frame->args, list_copy_range( timing_rule, list_next( list_begin( timing_rule ) ), list_end( timing_rule ) ) );
 
         /* target :: the name of the target */
- lol_add( frame->args, list_new( L0, target->name ) );
+ lol_add( frame->args, list_new( object_copy( target->name ) ) );
 
         /* start end user system :: info about the action command */
- lol_add( frame->args, list_new( list_new( list_new( list_new( L0,
+ lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_new(
             outf_time ( time->start ) ),
             outf_time ( time->end ) ),
             outf_double( time->user ) ),
             outf_double( time->system ) ) );
 
         /* Call the rule. */
- evaluate_rule( timing_rule->string, frame );
+ evaluate_rule( list_front( timing_rule ), frame );
 
         /* Clean up. */
         frame_free( frame );
@@ -707,17 +737,17 @@
     TARGET * target,
     int status,
     timing_info * time,
- char * executed_command,
- char * command_output
+ const char * executed_command,
+ const char * command_output
 )
 {
- LIST * action_rule;
+ LIST * action_rule;
 
- pushsettings( target->settings );
- action_rule = var_get( "__ACTION_RULE__" );
- popsettings( target->settings );
+ pushsettings( root_module(), target->settings );
+ action_rule = var_get( root_module(), constant_ACTION_RULE );
+ popsettings( root_module(), target->settings );
 
- if ( action_rule )
+ if ( !list_empty( action_rule ) )
     {
         /* rule action-rule (
             args * :
@@ -730,15 +760,15 @@
         frame_init( frame );
 
         /* args * :: $(__ACTION_RULE__[2-]) */
- lol_add( frame->args, list_copy( L0, action_rule->next ) );
+ lol_add( frame->args, list_copy_range( action_rule, list_next( list_begin( action_rule ) ), list_end( action_rule ) ) );
 
         /* target :: the name of the target */
- lol_add( frame->args, list_new( L0, target->name ) );
+ lol_add( frame->args, list_new( object_copy( target->name ) ) );
 
         /* command status start end user system :: info about the action command */
         lol_add( frame->args,
- list_new( list_new( list_new( list_new( list_new( list_new( L0,
- newstr( executed_command ) ),
+ list_push_back( list_push_back( list_push_back( list_push_back( list_push_back( list_new(
+ object_new( executed_command ) ),
                 outf_int( status ) ),
                 outf_time( time->start ) ),
                 outf_time( time->end ) ),
@@ -747,12 +777,12 @@
 
         /* output ? :: the output of the action command */
         if ( command_output )
- lol_add( frame->args, list_new( L0, newstr( command_output ) ) );
+ lol_add( frame->args, list_new( object_new( command_output ) ) );
         else
             lol_add( frame->args, L0 );
 
         /* Call the rule. */
- evaluate_rule( action_rule->string, frame );
+ evaluate_rule( list_front( action_rule ), frame );
 
         /* Clean up. */
         frame_free( frame );
@@ -770,8 +800,8 @@
     void * closure,
     int status,
     timing_info * time,
- char * executed_command,
- char * command_output
+ const char * executed_command,
+ const char * command_output
 )
 {
     TARGET * built = (TARGET *)closure;
@@ -801,7 +831,7 @@
     CMD * cmd = (CMD *)t->cmds;
     int status = pState->status;
 
- if ( t->flags & T_FLAG_FAIL_EXPECTED )
+ if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec )
     {
         /* Invert execution result when FAIL_EXPECTED has been applied. */
         switch ( status )
@@ -823,9 +853,9 @@
     if ( ( status == EXEC_CMD_FAIL ) && DEBUG_MAKE )
     {
         if ( !DEBUG_EXEC )
- printf( "%s\n", cmd->buf );
+ printf( "%s\n", cmd->buf->value );
 
- printf( "...failed %s ", cmd->rule->name );
+ printf( "...failed %s ", object_str( cmd->rule->name ) );
         list_print( lol_get( &cmd->args, 0 ) );
         printf( "...\n" );
     }
@@ -842,16 +872,17 @@
     if (status != EXEC_CMD_OK)
     {
         LIST * targets = lol_get( &cmd->args, 0 );
- for ( ; targets; targets = list_next( targets ) )
+ LISTITER iter = list_begin( targets ), end = list_end( targets );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
             int need_unlink = 1;
- TARGET* t = bindtarget ( targets->string );
+ TARGET* t = bindtarget ( list_item( iter ) );
             if (t->flags & T_FLAG_PRECIOUS)
             {
                 need_unlink = 0;
             }
- if (need_unlink && !unlink( targets->string ) )
- printf( "...removing %s\n", targets->string );
+ if (need_unlink && !unlink( object_str( list_item( iter ) ) ) )
+ printf( "...removing %s\n", object_str( list_item( iter ) ) );
         }
     }
 
@@ -878,29 +909,17 @@
     TARGET * new_target
 )
 {
- if ( new_module == root_module() )
- new_module = 0;
-
     if ( ( new_target == *current_target ) && ( new_module == *current_module ) )
         return;
 
     if ( *current_target )
- popsettings( (*current_target)->settings );
-
- if ( new_module != *current_module )
- {
- if ( *current_module )
- exit_module( *current_module );
+ popsettings( *current_module, (*current_target)->settings );
 
- *current_module = new_module;
-
- if ( new_module )
- enter_module( new_module );
- }
+ if ( new_target )
+ pushsettings( new_module, new_target->settings );
 
+ *current_module = new_module;
     *current_target = new_target;
- if ( new_target )
- pushsettings( new_target->settings );
 }
 
 
@@ -916,10 +935,11 @@
 static CMD * make1cmds( TARGET * t )
 {
     CMD * cmds = 0;
- LIST * shell = 0;
+ LIST * shell = L0;
     module_t * settings_module = 0;
     TARGET * settings_target = 0;
     ACTIONS * a0;
+ int running_flag = globs.noexec ? A_RUNNING_NOEXEC : A_RUNNING;
 
     /* Step through actions. Actions may be shared with other targets or grouped
      * using RULE_TOGETHER, so actions already seen are skipped.
@@ -939,10 +959,10 @@
         /* Only do rules with commands to execute. If this action has already
          * been executed, use saved status.
          */
- if ( !actions || a0->action->running )
+ if ( !actions || a0->action->running >= running_flag )
             continue;
 
- a0->action->running = 1;
+ a0->action->running = running_flag;
 
         /* Make LISTS of targets and sources. If `execute together` has been
          * specified for this rule, tack on sources from each instance of this
@@ -952,28 +972,30 @@
         ns = make1list( L0, a0->action->sources, actions->flags );
         if ( actions->flags & RULE_TOGETHER )
             for ( a1 = a0->next; a1; a1 = a1->next )
- if ( a1->action->rule == rule && !a1->action->running )
+ if ( a1->action->rule == rule && a1->action->running < running_flag )
                 {
                     ns = make1list( ns, a1->action->sources, actions->flags );
- a1->action->running = 1;
+ a1->action->running = running_flag;
                 }
 
         /* If doing only updated (or existing) sources, but none have been
          * updated (or exist), skip this action.
          */
- if ( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
+ if ( list_empty( ns ) && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
         {
             list_free( nt );
             continue;
         }
 
         swap_settings( &settings_module, &settings_target, rule->module, t );
- if ( !shell )
- shell = var_get( "JAMSHELL" ); /* shell is per-target */
+ if ( list_empty( shell ) )
+ {
+ shell = var_get( rule->module, constant_JAMSHELL ); /* shell is per-target */
+ }
 
         /* If we had 'actions xxx bind vars' we bind the vars now. */
- boundvars = make1settings( actions->bindlist );
- pushsettings( boundvars );
+ boundvars = make1settings( rule->module, actions->bindlist );
+ pushsettings( rule->module, boundvars );
 
         /*
          * Build command, starting with all source args.
@@ -998,9 +1020,9 @@
         {
             /* Build cmd: cmd_new consumes its lists. */
             CMD * cmd = cmd_new( rule,
- list_copy( L0, nt ),
+ list_copy( nt ),
                 list_sublist( ns, start, chunk ),
- list_copy( L0, shell ) );
+ list_copy( shell ) );
 
             if ( cmd )
             {
@@ -1018,14 +1040,14 @@
             else
             {
                 /* Too long and not splittable. */
- printf( "%s actions too long (max %d):\n", rule->name, MAXLINE
+ printf( "%s actions too long (max %d):\n", object_str( rule->name ), MAXLINE
                     );
 
                 /* Tell the user what didn't fit. */
- cmd = cmd_new( rule, list_copy( L0, nt ),
+ cmd = cmd_new( rule, list_copy( nt ),
                     list_sublist( ns, start, chunk ),
- list_new( L0, newstr( "%" ) ) );
- fputs( cmd->buf, stdout );
+ list_new( object_copy( constant_percent ) ) );
+ fputs( cmd->buf->value, stdout );
                 exit( EXITBAD );
             }
         }
@@ -1038,7 +1060,7 @@
         /* Free the variables whose values were bound by 'actions xxx bind
          * vars'.
          */
- popsettings( boundvars );
+ popsettings( rule->module, boundvars );
         freesettings( boundvars );
     }
 
@@ -1077,16 +1099,16 @@
         /* Prohibit duplicates for RULE_TOGETHER. */
         if ( flags & RULE_TOGETHER )
         {
- LIST * m;
- for ( m = l; m; m = m->next )
- if ( !strcmp( m->string, t->boundname ) )
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ for ( ; iter != end; iter = list_next( iter ) )
+ if ( object_equal( list_item( iter ), t->boundname ) )
                     break;
- if ( m )
+ if ( iter != end )
                 continue;
         }
 
         /* Build new list. */
- l = list_new( l, copystr( t->boundname ) );
+ l = list_push_back( l, object_copy( t->boundname ) );
     }
 
     return l;
@@ -1097,29 +1119,31 @@
  * make1settings() - for vars that get bound values, build up replacement lists.
  */
 
-static SETTINGS * make1settings( LIST * vars )
+static SETTINGS * make1settings( struct module_t * module, LIST * vars )
 {
     SETTINGS * settings = 0;
 
- for ( ; vars; vars = list_next( vars ) )
+ LISTITER vars_iter = list_begin( vars ), vars_end = list_end( vars );
+ for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) )
     {
- LIST * l = var_get( vars->string );
- LIST * nl = 0;
+ LIST * l = var_get( module, list_item( vars_iter ) );
+ LIST * nl = L0;
+ LISTITER iter = list_begin( l ), end = list_end( l );
 
- for ( ; l; l = list_next( l ) )
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( list_item( iter ) );
 
             /* Make sure the target is bound. */
             if ( t->binding == T_BIND_UNBOUND )
                 make1bind( t );
 
             /* Build a new list. */
- nl = list_new( nl, copystr( t->boundname ) );
+ nl = list_push_back( nl, object_copy( t->boundname ) );
         }
 
         /* Add to settings chain. */
- settings = addsettings( settings, VAR_SET, vars->string, nl );
+ settings = addsettings( settings, VAR_SET, list_item( vars_iter ), nl );
     }
 
     return settings;
@@ -1138,8 +1162,9 @@
     if ( t->flags & T_FLAG_NOTFILE )
         return;
 
- pushsettings( t->settings );
+ pushsettings( root_module(), t->settings );
+ object_free( t->boundname );
     t->boundname = search( t->name, &t->time, 0, ( t->flags & T_FLAG_ISFILE ) );
     t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
- popsettings( t->settings );
+ popsettings( root_module(), t->settings );
 }

Modified: branches/release/tools/build/v2/engine/modules.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules.c (original)
+++ branches/release/tools/build/v2/engine/modules.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,64 +8,54 @@
 #include "modules.h"
 #include "string.h"
 #include "hash.h"
-#include "newstr.h"
+#include "object.h"
 #include "lists.h"
 #include "parse.h"
 #include "rules.h"
 #include "variable.h"
 #include "strings.h"
+#include "native.h"
 #include <assert.h>
 
 static struct hash * module_hash = 0;
+static module_t root;
 
-
-static char * new_module_str( module_t * m, char * suffix )
-{
- char * result;
- string s;
- string_copy( &s, m->name );
- string_append( &s, suffix );
- result = newstr( s.value );
- string_free( &s );
- return result;
-}
-
-
-module_t * bindmodule( char * name )
+module_t * bindmodule( OBJECT * name )
 {
- PROFILE_ENTER( BINDMODULE );
-
- string s;
- module_t m_;
- module_t * m = &m_;
-
- if ( !module_hash )
- module_hash = hashinit( sizeof( module_t ), "modules" );
 
- string_new( &s );
- if ( name )
+ if ( !name )
     {
- string_append( &s, name );
- string_push_back( &s, '.' );
+ return &root;
     }
+ else
+ {
+ PROFILE_ENTER( BINDMODULE );
 
- m->name = s.value;
+ module_t * m;
+ int found;
 
- if ( hashenter( module_hash, (HASHDATA * *)&m ) )
- {
- m->name = newstr( m->name );
- m->variables = 0;
- m->rules = 0;
- m->imported_modules = 0;
- m->class_module = 0;
- m->native_rules = 0;
- m->user_module = 0;
- }
- string_free( &s );
+ if ( !module_hash )
+ module_hash = hashinit( sizeof( module_t ), "modules" );
+
+ m = (module_t *)hash_insert( module_hash, name, &found );
+ if ( !found )
+ {
+ m->name = object_copy( name );
+ m->variables = 0;
+ m->variable_indices = 0;
+ m->num_fixed_variables = 0;
+ m->fixed_variables = 0;
+ m->rules = 0;
+ m->imported_modules = 0;
+ m->class_module = 0;
+ m->native_rules = 0;
+ m->user_module = 0;
+ }
 
- PROFILE_EXIT( BINDMODULE );
+ PROFILE_EXIT( BINDMODULE );
 
- return m;
+ return m;
+ }
 }
 
 /*
@@ -74,7 +64,7 @@
 struct hash * demand_rules( module_t * m )
 {
     if ( !m->rules )
- m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
+ m->rules = hashinit( sizeof( RULE ), "rules" );
     return m->rules;
 }
 
@@ -89,43 +79,194 @@
 }
 
 
+static void delete_native_rule( void * xrule, void * data )
+{
+ native_rule_t * rule = (native_rule_t *)xrule;
+ object_free( rule->name );
+ if ( rule->procedure )
+ function_free( rule->procedure );
+}
+
+
+static void delete_imported_modules( void * xmodule_name, void * data )
+{
+ object_free( *(OBJECT * *)xmodule_name );
+}
+
+static void free_fixed_variable( void * xvar, void * data );
+
 void delete_module( module_t * m )
 {
     /* Clear out all the rules. */
     if ( m->rules )
     {
         hashenumerate( m->rules, delete_rule_, (void *)0 );
- hashdone( m->rules );
+ hash_free( m->rules );
         m->rules = 0;
     }
 
+ if ( m->native_rules )
+ {
+ hashenumerate( m->native_rules, delete_native_rule, (void *)0 );
+ hash_free( m->native_rules );
+ m->native_rules = 0;
+ }
+
     if ( m->variables )
     {
- var_hash_swap( &m->variables );
- var_done();
- var_hash_swap( &m->variables );
+ var_done( m );
         m->variables = 0;
     }
+
+ if ( m->fixed_variables )
+ {
+ int i;
+ for ( i = 0; i < m->num_fixed_variables; ++i )
+ {
+ list_free( m->fixed_variables[ i ] );
+ }
+ BJAM_FREE( m->fixed_variables );
+ m->fixed_variables = 0;
+ }
+
+ if ( m->variable_indices )
+ {
+ hashenumerate( m->variable_indices, &free_fixed_variable, (void *)0 );
+ hash_free( m->variable_indices );
+ m->variable_indices = 0;
+ }
+
+ if ( m->imported_modules )
+ {
+ hashenumerate( m->imported_modules, delete_imported_modules, (void *)0 );
+ hash_free( m->imported_modules );
+ m->imported_modules = 0;
+ }
 }
 
 
-module_t * root_module()
+struct module_stats
+{
+ OBJECT * module_name;
+ struct hashstats rules_stats[ 1 ];
+ struct hashstats variables_stats[ 1 ];
+ struct hashstats variable_indices_stats[ 1 ];
+ struct hashstats imported_modules_stats[ 1 ];
+};
+
+
+static void module_stat( struct hash * hp, OBJECT * module, const char * name )
+{
+ if ( hp )
+ {
+ struct hashstats stats[ 1 ];
+ string id[ 1 ];
+ hashstats_init( stats );
+ string_new( id );
+ string_append( id, object_str( module ) );
+ string_push_back( id, ' ' );
+ string_append( id, name );
+
+ hashstats_add( stats, hp );
+ hashstats_print( stats, id->value );
+
+ string_free( id );
+ }
+}
+
+
+static void class_module_stat( struct hashstats * stats, OBJECT * module, const char * name )
+{
+ if ( stats->item_size )
+ {
+ string id[ 1 ];
+ string_new( id );
+ string_append( id, object_str( module ) );
+ string_append( id, " object " );
+ string_append( id, name );
+
+ hashstats_print( stats, id->value );
+
+ string_free( id );
+ }
+}
+
+
+static void stat_module( void * xmodule, void * data )
 {
- static module_t * root = 0;
- if ( !root )
- root = bindmodule( 0 );
- return root;
+ module_t *m = (module_t *)xmodule;
+
+ if ( DEBUG_MEM || DEBUG_PROFILE )
+ {
+ struct hash * class_info = (struct hash *)data;
+ if ( m->class_module )
+ {
+ int found;
+ struct module_stats * ms = (struct module_stats *)hash_insert( class_info, m->class_module->name, &found );
+ if ( !found )
+ {
+ ms->module_name = m->class_module->name;
+ hashstats_init( ms->rules_stats );
+ hashstats_init( ms->variables_stats );
+ hashstats_init( ms->variable_indices_stats );
+ hashstats_init( ms->imported_modules_stats );
+ }
+
+ hashstats_add( ms->rules_stats, m->rules );
+ hashstats_add( ms->variables_stats, m->variables );
+ hashstats_add( ms->variable_indices_stats, m->variable_indices );
+ hashstats_add( ms->imported_modules_stats, m->imported_modules );
+ }
+ else
+ {
+ module_stat( m->rules, m->name, "rules" );
+ module_stat( m->variables, m->name, "variables" );
+ module_stat( m->variable_indices, m->name, "fixed variables" );
+ module_stat( m->imported_modules, m->name, "imported modules" );
+ }
+ }
+
+ delete_module( m );
+ object_free( m->name );
 }
 
-void enter_module( module_t * m )
+static void print_class_stats( void * xstats, void * data )
 {
- var_hash_swap( &m->variables );
+ struct module_stats * stats = (struct module_stats *)xstats;
+ class_module_stat( stats->rules_stats, stats->module_name, "rules" );
+ class_module_stat( stats->variables_stats, stats->module_name, "variables" );
+ class_module_stat( stats->variable_indices_stats, stats->module_name, "fixed variables" );
+ class_module_stat( stats->imported_modules_stats, stats->module_name, "imported modules" );
 }
 
 
-void exit_module( module_t * m )
+static void delete_module_( void * xmodule, void * data )
 {
- var_hash_swap( &m->variables );
+ module_t *m = (module_t *)xmodule;
+
+ delete_module( m );
+ object_free( m->name );
+}
+
+
+void modules_done()
+{
+ if ( DEBUG_MEM || DEBUG_PROFILE )
+ {
+ struct hash * class_hash = hashinit( sizeof( struct module_stats ), "object info" );
+ hashenumerate( module_hash, stat_module, (void *)class_hash );
+ hashenumerate( class_hash, print_class_stats, (void *)0 );
+ hash_free( class_hash );
+ }
+ hashenumerate( module_hash, delete_module_, (void *)0 );
+ hashdone( module_hash );
+ module_hash = 0;
+ delete_module( &root );
+}
+
+module_t * root_module()
+{
+ return &root;
 }
 
 
@@ -134,16 +275,22 @@
     PROFILE_ENTER( IMPORT_MODULE );
 
     struct hash * h;
+ LISTITER iter, end;
 
     if ( !target_module->imported_modules )
         target_module->imported_modules = hashinit( sizeof( char * ), "imported" );
     h = target_module->imported_modules;
 
- for ( ; module_names; module_names = module_names->next )
+ iter = list_begin( module_names ), end = list_end( module_names );
+ for ( ; iter != end; iter = list_next( iter ) )
     {
- char * s = module_names->string;
- char * * ss = &s;
- hashenter( h, (HASHDATA * *)&ss );
+ int found;
+ OBJECT * s = list_item( iter );
+ OBJECT * * ss = (OBJECT * *)hash_insert( h, s, &found );
+ if( !found )
+ {
+ *ss = object_copy( s );
+ }
     }
 
     PROFILE_EXIT( IMPORT_MODULE );
@@ -152,10 +299,10 @@
 
 static void add_module_name( void * r_, void * result_ )
 {
- char * * r = (char * *)r_;
+ OBJECT * * r = (OBJECT * *)r_;
     LIST * * result = (LIST * *)result_;
 
- *result = list_new( *result, copystr( *r ) );
+ *result = list_push_back( *result, object_copy( *r ) );
 }
 
 
@@ -166,3 +313,124 @@
         hashenumerate( module->imported_modules, add_module_name, &result );
     return result;
 }
+
+
+FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter );
+FUNCTION * function_unbind_variables( FUNCTION * f );
+
+struct fixed_variable
+{
+ OBJECT * key;
+ int n;
+};
+
+struct bind_vars_t
+{
+ module_t * module;
+ int counter;
+};
+
+static void free_fixed_variable( void * xvar, void * data )
+{
+ object_free( ( (struct fixed_variable *)xvar )->key );
+}
+
+static void bind_variables_for_rule( void * xrule, void * xdata )
+{
+ RULE * rule = (RULE *)xrule;
+ struct bind_vars_t * data = (struct bind_vars_t *)xdata;
+ if ( rule->procedure && rule->module == data->module )
+ rule->procedure = function_bind_variables( rule->procedure, data->module, &data->counter );
+}
+
+void module_bind_variables( struct module_t * m )
+{
+ if ( m != root_module() && m->rules )
+ {
+ struct bind_vars_t data;
+ data.module = m;
+ data.counter = m->num_fixed_variables;
+ hashenumerate( m->rules, &bind_variables_for_rule, &data );
+ module_set_fixed_variables( m, data.counter );
+ }
+}
+
+int module_add_fixed_var( struct module_t * m, OBJECT * name, int * counter )
+{
+ struct fixed_variable * v;
+ int found;
+
+ assert( !m->class_module );
+
+ if ( !m->variable_indices )
+ m->variable_indices = hashinit( sizeof( struct fixed_variable ), "variable index table" );
+
+ v = (struct fixed_variable *)hash_insert( m->variable_indices, name, &found );
+ if ( !found )
+ {
+ v->key = object_copy( name );
+ v->n = (*counter)++;
+ }
+
+ return v->n;
+}
+
+LIST * var_get_and_clear_raw( module_t * m, OBJECT * name );
+
+static void load_fixed_variable( void * xvar, void * data )
+{
+ struct fixed_variable * var = (struct fixed_variable *)xvar;
+ struct module_t * m = (struct module_t *)data;
+ if ( var->n >= m->num_fixed_variables )
+ {
+ m->fixed_variables[ var->n ] = var_get_and_clear_raw( m, var->key );
+ }
+}
+
+void module_set_fixed_variables( struct module_t * m, int n_variables )
+{
+ /* Reallocate */
+ struct hash * variable_indices;
+ LIST * * fixed_variables = BJAM_MALLOC( n_variables * sizeof( LIST * ) );
+ if ( m->fixed_variables )
+ {
+ memcpy( fixed_variables, m->fixed_variables, n_variables * sizeof( LIST * ) );
+ BJAM_FREE( m->fixed_variables );
+ }
+ m->fixed_variables = fixed_variables;
+ if ( m->class_module )
+ {
+ variable_indices = m->class_module->variable_indices;
+ }
+ else
+ {
+ variable_indices = m->variable_indices;
+ }
+ if ( variable_indices )
+ hashenumerate( variable_indices, &load_fixed_variable, m );
+ m->num_fixed_variables = n_variables;
+}
+
+int module_get_fixed_var( struct module_t * m_, OBJECT * name )
+{
+ struct fixed_variable * v;
+ struct module_t * m = m_;
+
+ if ( m->class_module )
+ {
+ m = m->class_module;
+ }
+
+ if ( !m->variable_indices )
+ return -1;
+
+ v = (struct fixed_variable *)hash_find( m->variable_indices, name );
+ if ( v && v->n < m_->num_fixed_variables )
+ {
+ return v->n;
+ }
+ else
+ {
+ return -1;
+ }
+}

Modified: branches/release/tools/build/v2/engine/modules.h
==============================================================================
--- branches/release/tools/build/v2/engine/modules.h (original)
+++ branches/release/tools/build/v2/engine/modules.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -10,28 +10,44 @@
 
 struct module_t
 {
- char* name;
- struct hash* rules;
- struct hash* variables;
- struct hash* imported_modules;
- struct module_t* class_module;
- struct hash* native_rules;
+ OBJECT * name;
+ struct hash * rules;
+ struct hash * variables;
+ struct hash * variable_indices;
+ int num_fixed_variables;
+ LIST * * fixed_variables;
+ struct hash * imported_modules;
+ struct module_t * class_module;
+ struct hash * native_rules;
     int user_module;
 };
 
 typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */
 
-module_t* bindmodule( char* name );
-module_t* root_module();
-void enter_module( module_t* );
-void exit_module( module_t* );
-void delete_module( module_t* );
+module_t * bindmodule( OBJECT * name );
+module_t * root_module();
+void delete_module( module_t * );
 
-void import_module(LIST* module_names, module_t* target_module);
+void import_module( LIST * module_names, module_t * target_module );
 LIST* imported_modules(module_t* module);
 
-struct hash* demand_rules( module_t* );
+struct hash * demand_rules( module_t * );
 
+void module_bind_variables( struct module_t * m );
+
+/*
+ * After calling module_add_fixed_var, module_set_fixed_variables
+ * must be called before accessing any variables in the module.
+ */
+int module_add_fixed_var( struct module_t * m, OBJECT * name, int * n );
+void module_set_fixed_variables( struct module_t * m, int n );
+
+/*
+ * Returns the index of the variable or -1 if none exists.
+ */
+int module_get_fixed_var( struct module_t * m, OBJECT * name );
+
+void modules_done();
 
 #endif
 

Modified: branches/release/tools/build/v2/engine/modules/order.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/order.c (original)
+++ branches/release/tools/build/v2/engine/modules/order.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,18 +5,19 @@
 #include "../native.h"
 #include "../lists.h"
 #include "../strings.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../variable.h"
 
 
 /* Use quite klugy approach: when we add order dependency from 'a' to 'b',
    just append 'b' to of value of variable 'a'.
 */
-LIST *add_pair( PARSE *parse, FRAME *frame )
+LIST *add_pair( FRAME *frame, int flags )
 {
     LIST* arg = lol_get( frame->args, 0 );
+ LISTITER iter = list_begin( arg ), end = list_end( arg );
 
- var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
+ var_set( frame->module, list_item( iter ), list_copy_range( arg, list_next( iter ), end ), VAR_APPEND );
 
     return L0;
 }
@@ -24,11 +25,12 @@
 /** Given a list and a value, returns position of that value in
     the list, or -1 if not found.
 */
-int list_index(LIST* list, const char* value)
+int list_index(LIST* list, OBJECT* value)
 {
     int result = 0;
- for(; list; list = list->next, ++result) {
- if (strcmp(list->string, value) == 0)
+ LISTITER iter = list_begin(list), end = list_end(list);
+ for(; iter != end; iter = list_next(iter), ++result) {
+ if (object_equal(list_item(iter), value))
             return result;
     }
     return -1;
@@ -74,12 +76,12 @@
     BJAM_FREE(colors);
 }
 
-LIST *order( PARSE *parse, FRAME *frame )
+LIST *order( FRAME *frame, int flags )
 {
- LIST* arg = lol_get( frame->args, 0 );
- LIST* tmp;
- LIST* result = 0;
+ LIST* arg = lol_get( frame->args, 0 );
+ LIST* result = L0;
     int src;
+ LISTITER iter = list_begin(arg), end = list_end(arg);
 
     /* We need to create a graph of order dependencies between
        the passed objects. We assume that there are no duplicates
@@ -89,15 +91,16 @@
     int** graph = (int**)BJAM_CALLOC(length, sizeof(int*));
     int* order = (int*)BJAM_MALLOC((length+1)*sizeof(int));
    
- for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
+ for(src = 0; iter != end; iter = list_next(iter), ++src) {
         /* For all object this one depend upon, add elements
            to 'graph' */
- LIST* dependencies = var_get(tmp->string);
+ LIST* dependencies = var_get(frame->module, list_item(iter));
         int index = 0;
+ LISTITER dep_iter = list_begin(dependencies), dep_end = list_end(dependencies);
 
         graph[src] = (int*)BJAM_CALLOC(list_length(dependencies)+1, sizeof(int));
- for(; dependencies; dependencies = dependencies->next) {
- int dst = list_index(arg, dependencies->string);
+ for(; dep_iter != dep_end; dep_iter = list_next(dep_iter)) {
+ int dst = list_index(arg, list_item(dep_iter));
             if (dst != -1)
                 graph[src][index++] = dst;
         }
@@ -110,9 +113,9 @@
         int index = length-1;
         for(; index >= 0; --index) {
             int i;
- tmp = arg;
- for (i = 0; i < order[index]; ++i, tmp = tmp->next);
- result = list_new(result, tmp->string);
+ iter = list_begin(arg), end = list_end(arg);
+ for (i = 0; i < order[index]; ++i, iter = list_next(iter));
+ result = list_push_back(result, object_copy(list_item(iter)));
         }
     }
 
@@ -131,12 +134,12 @@
 void init_order()
 {
     {
- char* args[] = { "first", "second", 0 };
+ const char* args[] = { "first", "second", 0 };
         declare_native_rule("class_at_order", "add-pair", args, add_pair, 1);
     }
 
     {
- char* args[] = { "objects", "*", 0 };
+ const char* args[] = { "objects", "*", 0 };
         declare_native_rule("class_at_order", "order", args, order, 1);
     }
 

Modified: branches/release/tools/build/v2/engine/modules/path.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/path.c (original)
+++ branches/release/tools/build/v2/engine/modules/path.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,17 +4,17 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 
-LIST *path_exists( PARSE *parse, FRAME *frame )
+LIST *path_exists( FRAME *frame, int flags )
 {
     LIST* l = lol_get( frame->args, 0 );
 
     time_t time;
- timestamp(l->string, &time);
+ timestamp(list_front(l), &time);
     if (time != 0)
     {
- return list_new(0, newstr("true"));
+ return list_new(object_new("true"));
     }
     else
     {
@@ -25,7 +25,7 @@
 void init_path()
 {
     {
- char* args[] = { "location", 0 };
+ const char* args[] = { "location", 0 };
         declare_native_rule("path", "exists", args, path_exists, 1);
     }
 

Modified: branches/release/tools/build/v2/engine/modules/property-set.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/property-set.c (original)
+++ branches/release/tools/build/v2/engine/modules/property-set.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,7 +4,7 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../strings.h"
 #include "../lists.h"
 #include "../variable.h"
@@ -19,7 +19,7 @@
     string_new(s);
 
     string_append_range(s, f, end+1);
- result = list_new(0, newstr(s->value));
+ result = list_new(object_new(s->value));
 
     string_free(s);
     return result;
@@ -41,17 +41,18 @@
 }
 */
 
-LIST *property_set_create( PARSE *parse, FRAME *frame )
+LIST *property_set_create( FRAME *frame, int flags )
 {
     LIST* properties = lol_get( frame->args, 0 );
- LIST* sorted = 0;
+ LIST* sorted = L0;
 #if 0
     LIST* order_sensitive = 0;
 #endif
     LIST* unique;
- LIST* tmp;
     LIST* val;
     string var[1];
+ OBJECT* name;
+ LISTITER iter, end;
 
 #if 0
     /* Sort all properties which are not order sensitive */
@@ -59,9 +60,9 @@
         LIST* g = get_grist(tmp->string);
         LIST* att = call_rule("feature.attributes", frame, g, 0);
         if (list_in(att, "order-sensitive")) {
- order_sensitive = list_new( order_sensitive, tmp->string);
+ order_sensitive = list_new( order_sensitive, copystr(tmp->string));
         } else {
- sorted = list_new( sorted, tmp->string);
+ sorted = list_new( sorted, copystr(tmp->string));
         }
         list_free(att);
     }
@@ -76,22 +77,28 @@
     string_new(var);
     string_append(var, ".ps.");
 
- for(tmp = unique; tmp; tmp = tmp->next) {
- string_append(var, tmp->string);
+ iter = list_begin( unique ), end = list_end( unique );
+ for( ; iter != end; iter = list_next( iter ) ) {
+ string_append(var, object_str( list_item( iter ) ));
         string_push_back(var, '-');
     }
- val = var_get(var->value);
- if (val == 0)
+ name = object_new(var->value);
+ val = var_get(frame->module, name);
+ if (list_empty(val))
     {
- val = call_rule("new", frame,
- list_append(list_new(0, "property-set"), unique), 0);
+ OBJECT* rulename = object_new("new");
+ val = call_rule(rulename, frame,
+ list_append(list_new(object_new("property-set")), unique), 0);
+ object_free(rulename);
 
- var_set(newstr(var->value), list_copy(0, val), VAR_SET);
+ var_set(frame->module, name, list_copy(val), VAR_SET);
     }
     else
     {
- val = list_copy(0, val);
+ list_free(unique);
+ val = list_copy(val);
     }
+ object_free(name);
 
     string_free(var);
     /* The 'unique' variable is freed in 'call_rule'. */
@@ -104,7 +111,7 @@
 void init_property_set()
 {
     {
- char* args[] = { "raw-properties", "*", 0 };
+ const char* args[] = { "raw-properties", "*", 0 };
         declare_native_rule("property-set", "create", args, property_set_create, 1);
     }
 }

Modified: branches/release/tools/build/v2/engine/modules/regex.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/regex.c (original)
+++ branches/release/tools/build/v2/engine/modules/regex.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,7 +4,7 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../strings.h"
 #include "../regexp.h"
 #include "../compile.h"
@@ -25,7 +25,7 @@
     return $(result) ;
 }
 */
-LIST *regex_transform( PARSE *parse, FRAME *frame )
+LIST *regex_transform( FRAME *frame, int flags )
 {
     LIST* l = lol_get( frame->args, 0 );
     LIST* pattern = lol_get( frame->args, 1 );
@@ -33,18 +33,19 @@
     int* indices = 0;
     int size;
     int* p;
- LIST* result = 0;
+ LIST* result = L0;
 
     string buf[1];
     string_new(buf);
 
- if (indices_list)
+ if (!list_empty(indices_list))
     {
+ LISTITER iter = list_begin(indices_list), end = list_end(indices_list);
         size = list_length(indices_list);
         indices = (int*)BJAM_MALLOC(size*sizeof(int));
- for(p = indices; indices_list; indices_list = indices_list->next)
+ for(p = indices; iter != end; iter = list_next(iter))
         {
- *p++ = atoi(indices_list->string);
+ *p++ = atoi(object_str(list_item(iter)));
         }
     }
     else
@@ -56,11 +57,12 @@
 
     {
         /* Result is cached and intentionally never freed */
- regexp *re = regex_compile( pattern->string );
+ regexp *re = regex_compile( list_front( pattern ) );
 
- for(; l; l = l->next)
+ LISTITER iter = list_begin( l ), end = list_end( l );
+ for( ; iter != end; iter = list_next( iter ) )
         {
- if( regexec( re, l->string ) )
+ if( regexec( re, object_str( list_item( iter ) ) ) )
             {
                 int i = 0;
                 for(; i < size; ++i)
@@ -73,7 +75,7 @@
                     if (re->startp[index] != re->endp[index])
                     {
                         string_append_range( buf, re->startp[index], re->endp[index] );
- result = list_new( result, newstr( buf->value ) );
+ result = list_push_back( result, object_new( buf->value ) );
                         string_truncate( buf, 0 );
                     }
                 }
@@ -90,7 +92,7 @@
 void init_regex()
 {
     {
- char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
+ const char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
         declare_native_rule("regex", "transform", args, regex_transform, 2);
     }
 }

Modified: branches/release/tools/build/v2/engine/modules/sequence.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/sequence.c (original)
+++ branches/release/tools/build/v2/engine/modules/sequence.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -3,30 +3,35 @@
 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
+#include "../object.h"
 
 # ifndef max
 # define max( a,b ) ((a)>(b)?(a):(b))
 # endif
 
 
-LIST *sequence_select_highest_ranked( PARSE *parse, FRAME *frame )
+LIST *sequence_select_highest_ranked( FRAME *frame, int flags )
 {
    /* Returns all of 'elements' for which corresponding element in parallel */
    /* list 'rank' is equal to the maximum value in 'rank'. */
 
     LIST* elements = lol_get( frame->args, 0 );
     LIST* rank = lol_get( frame->args, 1 );
+ LISTITER iter, end, elements_iter, elements_end;
     
- LIST* result = 0;
+ LIST* result = L0;
     LIST* tmp;
     int highest_rank = -1;
 
- for (tmp = rank; tmp; tmp = tmp->next)
- highest_rank = max(highest_rank, atoi(tmp->string));
-
- for (; rank; rank = rank->next, elements = elements->next)
- if (atoi(rank->string) == highest_rank)
- result = list_new(result, elements->string);
+ iter = list_begin(rank), end = list_end(rank);
+ for (; iter != end; iter = list_next(iter))
+ highest_rank = max(highest_rank, atoi(object_str(list_item(iter))));
+
+ iter = list_begin(rank), end = list_end(rank);
+ elements_iter = list_begin(elements), elements_end = list_end(elements);
+ for (; iter != end; iter = list_next(iter), elements_iter = list_next(elements_iter))
+ if (atoi(object_str(list_item(iter))) == highest_rank)
+ result = list_push_back(result, object_copy(list_item(elements_iter)));
 
     return result;
 }
@@ -34,7 +39,7 @@
 void init_sequence()
 {
     {
- char* args[] = { "elements", "*", ":", "rank", "*", 0 };
+ const char* args[] = { "elements", "*", ":", "rank", "*", 0 };
         declare_native_rule("sequence", "select-highest-ranked", args,
                             sequence_select_highest_ranked, 1);
     }

Modified: branches/release/tools/build/v2/engine/modules/set.c
==============================================================================
--- branches/release/tools/build/v2/engine/modules/set.c (original)
+++ branches/release/tools/build/v2/engine/modules/set.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -3,6 +3,7 @@
 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
+#include "../object.h"
 
 /*
     local result = ;
@@ -16,17 +17,18 @@
     }
     return $(result) ;
 */
-LIST *set_difference( PARSE *parse, FRAME *frame )
+LIST *set_difference( FRAME *frame, int flags )
 {
 
     LIST* b = lol_get( frame->args, 0 );
     LIST* a = lol_get( frame->args, 1 );
 
- LIST* result = 0;
- for(; b; b = b->next)
+ LIST* result = L0;
+ LISTITER iter = list_begin( b ), end = list_end( b );
+ for( ; iter != end; iter = list_next( iter ) )
     {
- if (!list_in(a, b->string))
- result = list_new(result, b->string);
+ if (!list_in(a, list_item(iter)))
+ result = list_push_back(result, object_copy(list_item(iter)));
     }
     return result;
 }
@@ -34,7 +36,7 @@
 void init_set()
 {
     {
- char* args[] = { "B", "*", ":", "A", "*", 0 };
+ const char* args[] = { "B", "*", ":", "A", "*", 0 };
         declare_native_rule("set", "difference", args, set_difference, 1);
     }
 

Modified: branches/release/tools/build/v2/engine/native.c
==============================================================================
--- branches/release/tools/build/v2/engine/native.c (original)
+++ branches/release/tools/build/v2/engine/native.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,33 +4,36 @@
 
 #include "native.h"
 #include "hash.h"
+#include "object.h"
+#include "assert.h"
 
-# define P0 (PARSE *)0
-# define C0 (char *)0
-
-
-void declare_native_rule(char* module, char* rule, char** args,
- LIST*(*f)(PARSE*, FRAME*), int version)
+void declare_native_rule( const char * module, const char * rule, const char * * args,
+ LIST * (*f)( FRAME *, int ), int version )
 {
- module_t* m = bindmodule(module);
- if (m->native_rules == 0) {
+ OBJECT * module_obj = 0;
+ module_t * m;
+ if ( module )
+ {
+ module_obj = object_new( module );
+ }
+ m = bindmodule( module_obj );
+ if ( module_obj )
+ {
+ object_free( module_obj );
+ }
+ if (m->native_rules == 0)
+ {
         m->native_rules = hashinit( sizeof( native_rule_t ), "native rules");
     }
 
     {
- native_rule_t n, *np = &n;
- n.name = rule;
- if (args)
- {
- n.arguments = args_new();
- lol_build( n.arguments->data, args );
- }
- else
- {
- n.arguments = 0;
- }
- n.procedure = parse_make( f, P0, P0, P0, C0, C0, 0 );
- n.version = version;
- hashenter(m->native_rules, (HASHDATA**)&np);
+ native_rule_t *np;
+ OBJECT * name = object_new( rule );
+ int found;
+ np = (native_rule_t *)hash_insert( m->native_rules, name, &found );
+ np->name = name;
+ assert( !found );
+ np->procedure = function_builtin( f, 0, args );
+ np->version = version;
     }
 }

Modified: branches/release/tools/build/v2/engine/native.h
==============================================================================
--- branches/release/tools/build/v2/engine/native.h (original)
+++ branches/release/tools/build/v2/engine/native.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,13 +5,16 @@
 #ifndef NATIVE_H_VP_2003_12_09
 #define NATIVE_H_VP_2003_12_09
 
+#include "lists.h"
+#include "object.h"
+#include "frames.h"
+#include "function.h"
 #include "rules.h"
 
 struct native_rule_t
 {
- char* name;
- argument_list* arguments;
- PARSE* procedure;
+ OBJECT * name;
+ FUNCTION * procedure;
     /* Version of the interface that the native rule provides.
        It's possible that we want to change the set parameter
        for existing native rule. In that case, version number
@@ -26,8 +29,8 @@
 /* MSVC debugger gets confused unless this is provided */
 typedef struct native_rule_t native_rule_t ;
 
-void declare_native_rule(char* module, char* rule, char** args,
- LIST*(*f)(PARSE*, FRAME*), int version);
+void declare_native_rule( const char * module, const char * rule, const char * * args,
+ LIST * (*f)( FRAME *, int ), int version );
 
 
 

Deleted: branches/release/tools/build/v2/engine/newstr.c
==============================================================================
--- branches/release/tools/build/v2/engine/newstr.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,174 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-# include "jam.h"
-# include "newstr.h"
-# include "hash.h"
-# include "compile.h"
-# include <stddef.h>
-# include <stdlib.h>
-
-/*
- * newstr.c - string manipulation routines
- *
- * To minimize string copying, string creation, copying, and freeing
- * is done through newstr.
- *
- * External functions:
- *
- * newstr() - return a dynamically allocated copy of a string
- * copystr() - return a copy of a string previously returned by newstr()
- * freestr() - free a string returned by newstr() or copystr()
- * str_done() - free string tables
- *
- * Once a string is passed to newstr(), the returned string is readonly.
- *
- * This implementation builds a hash table of all strings, so that multiple
- * calls of newstr() on the same string allocate memory for the string once.
- * Strings are never actually freed.
- */
-
-typedef char * STRING;
-
-static struct hash * strhash = 0;
-static int strtotal = 0;
-static int strcount_in = 0;
-static int strcount_out = 0;
-
-
-/*
- * Immortal string allocator implementation speeds string allocation and cuts
- * down on internal fragmentation.
- */
-
-# define STRING_BLOCK 4096
-typedef struct strblock
-{
- struct strblock * next;
- char data[STRING_BLOCK];
-} strblock;
-
-static strblock * strblock_chain = 0;
-
-/* Storage remaining in the current strblock */
-static char * storage_start = 0;
-static char * storage_finish = 0;
-
-
-/*
- * allocate() - Allocate n bytes of immortal string storage.
- */
-
-static char * allocate( size_t const n )
-{
-#ifdef BJAM_NEWSTR_NO_ALLOCATE
- return (char*)BJAM_MALLOC_ATOMIC(n);
-#else
- /* See if we can grab storage from an existing block. */
- size_t remaining = storage_finish - storage_start;
- if ( remaining >= n )
- {
- char * result = storage_start;
- storage_start += n;
- return result;
- }
- else /* Must allocate a new block. */
- {
- strblock * new_block;
- size_t nalloc = n;
- if ( nalloc < STRING_BLOCK )
- nalloc = STRING_BLOCK;
-
- /* Allocate a new block and link into the chain. */
- new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof( new_block->data[0] ) );
- if ( new_block == 0 )
- return 0;
- new_block->next = strblock_chain;
- strblock_chain = new_block;
-
- /* Take future allocations out of the larger remaining space. */
- if ( remaining < nalloc - n )
- {
- storage_start = new_block->data + n;
- storage_finish = new_block->data + nalloc;
- }
- return new_block->data;
- }
-#endif
-}
-
-
-/*
- * newstr() - return a dynamically allocated copy of a string.
- */
-
-char * newstr( char * string )
-{
- STRING str;
- STRING * s = &str;
-
- if ( !strhash )
- strhash = hashinit( sizeof( STRING ), "strings" );
-
- *s = string;
-
- if ( hashenter( strhash, (HASHDATA **)&s ) )
- {
- int l = strlen( string );
- char * m = (char *)allocate( l + 1 );
-
- strtotal += l + 1;
- memcpy( m, string, l + 1 );
- *s = m;
- }
-
- strcount_in += 1;
- return *s;
-}
-
-
-/*
- * copystr() - return a copy of a string previously returned by newstr()
- */
-
-char * copystr( char * s )
-{
- strcount_in += 1;
- return s;
-}
-
-
-/*
- * freestr() - free a string returned by newstr() or copystr()
- */
-
-void freestr( char * s )
-{
- strcount_out += 1;
-}
-
-
-/*
- * str_done() - free string tables.
- */
-
-void str_done()
-{
- /* Reclaim string blocks. */
- while ( strblock_chain != 0 )
- {
- strblock * n = strblock_chain->next;
- BJAM_FREE(strblock_chain);
- strblock_chain = n;
- }
-
- hashdone( strhash );
-
- if ( DEBUG_MEM )
- printf( "%dK in strings\n", strtotal / 1024 );
-
- /* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
-}

Deleted: branches/release/tools/build/v2/engine/newstr.h
==============================================================================
--- branches/release/tools/build/v2/engine/newstr.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,14 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/*
- * newstr.h - string manipulation routines
- */
-
-char * copystr ( char * );
-void freestr ( char * );
-char * newstr ( char * );
-void str_done();

Copied: branches/release/tools/build/v2/engine/object.c (from r75609, /trunk/tools/build/v2/engine/object.c)
==============================================================================
--- /trunk/tools/build/v2/engine/object.c (original)
+++ branches/release/tools/build/v2/engine/object.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -29,6 +29,8 @@
 
 #define OBJECT_MAGIC 0xa762e0e3u
 
+#ifndef object_copy
+
 struct hash_header
 {
 #ifndef NDEBUG
@@ -38,6 +40,8 @@
     struct hash_item * next;
 };
 
+#endif
+
 struct hash_item
 {
     struct hash_header header;
@@ -212,6 +216,7 @@
     result->header.magic = OBJECT_MAGIC;
 #endif
     memcpy( result->data, string, l + 1 );
+ assert( hash_keyval( result->data ) == result->header.hash );
     set->data[pos] = result;
     strtotal += l + 1;
     ++set->size;
@@ -256,6 +261,7 @@
 #endif
 }
 
+#ifndef object_copy
 
 /*
  * object_copy() - return a copy of an object
@@ -329,6 +335,8 @@
 #endif
 }
 
+#endif
+
 /*
  * object_done() - free string tables.
  */

Copied: branches/release/tools/build/v2/engine/object.h (from r75609, /trunk/tools/build/v2/engine/object.h)
==============================================================================
--- /trunk/tools/build/v2/engine/object.h (original)
+++ branches/release/tools/build/v2/engine/object.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -14,11 +14,30 @@
 typedef struct _object OBJECT;
 
 OBJECT * object_new ( const char * );
+void object_done ( void );
+
+#if defined(NDEBUG) && !defined(BJAM_NO_MEM_CACHE)
+
+struct hash_header
+{
+ unsigned int hash;
+ struct hash_item * next;
+};
+
+#define object_str( obj ) ( (const char *)( obj ) )
+#define object_copy( obj ) ( obj )
+#define object_free( obj ) ( (void)0 )
+#define object_equal( lhs, rhs ) ( ( lhs ) == ( rhs ) )
+#define object_hash( obj ) ( ((struct hash_header *)( (char *)( obj ) - sizeof(struct hash_header) ))->hash )
+
+#else
+
+const char * object_str ( OBJECT * );
 OBJECT * object_copy ( OBJECT * );
 void object_free ( OBJECT * );
-const char * object_str ( OBJECT * );
-void object_done ( void );
 int object_equal ( OBJECT *, OBJECT * );
 unsigned int object_hash ( OBJECT * );
 
 #endif
+
+#endif

Modified: branches/release/tools/build/v2/engine/output.c
==============================================================================
--- branches/release/tools/build/v2/engine/output.c (original)
+++ branches/release/tools/build/v2/engine/output.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -6,7 +6,7 @@
 
 #include "jam.h"
 #include "output.h"
-#include "newstr.h"
+#include "object.h"
 #include <stdio.h>
 
 #define bjam_out (stdout)
@@ -101,25 +101,25 @@
 }
 
 
-char * outf_int( int value )
+OBJECT * outf_int( int value )
 {
     char buffer[50];
     sprintf( buffer, "%i", value );
- return newstr( buffer );
+ return object_new( buffer );
 }
 
 
-char * outf_double( double value )
+OBJECT * outf_double( double value )
 {
     char buffer[50];
     sprintf( buffer, "%f", value );
- return newstr( buffer );
+ return object_new( buffer );
 }
 
 
-char * outf_time( time_t value )
+OBJECT * outf_time( time_t value )
 {
     char buffer[50];
     strftime( buffer, 49, "%Y-%m-%d %H:%M:%SZ", gmtime( &value ) );
- return newstr( buffer );
+ return object_new( buffer );
 }

Modified: branches/release/tools/build/v2/engine/output.h
==============================================================================
--- branches/release/tools/build/v2/engine/output.h (original)
+++ branches/release/tools/build/v2/engine/output.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -7,6 +7,7 @@
 #ifndef BJAM_OUTPUT_H
 #define BJAM_OUTPUT_H
 
+#include "object.h"
 #include <time.h>
 
 #define EXIT_OK 0
@@ -22,8 +23,8 @@
     int exit_reason
     );
 
-char * outf_int( int value );
-char * outf_double( double value );
-char * outf_time( time_t value );
+OBJECT * outf_int( int value );
+OBJECT * outf_double( double value );
+OBJECT * outf_time( time_t value );
 
 #endif

Modified: branches/release/tools/build/v2/engine/parse.c
==============================================================================
--- branches/release/tools/build/v2/engine/parse.c (original)
+++ branches/release/tools/build/v2/engine/parse.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -14,9 +14,10 @@
 #include "lists.h"
 #include "parse.h"
 #include "scan.h"
-#include "newstr.h"
+#include "object.h"
 #include "modules.h"
 #include "frames.h"
+#include "function.h"
 
 /*
  * parse.c - make and destroy parse trees as driven by the parser
@@ -29,7 +30,7 @@
 
 static PARSE * yypsave;
 
-void parse_file( char * f, FRAME * frame )
+void parse_file( OBJECT * f, FRAME * frame )
 {
     /* Suspend scan of current file and push this new file in the stream. */
     yyfparse( f );
@@ -41,6 +42,7 @@
     for ( ; ; )
     {
         PARSE * p;
+ FUNCTION * func;
 
         /* Filled by yyparse() calling parse_save(). */
         yypsave = 0;
@@ -50,8 +52,10 @@
             break;
 
         /* Run the parse tree. */
- parse_evaluate( p, frame );
+ func = function_compile( p );
         parse_free( p );
+ list_free( function_run( func, frame, stack_global() ) );
+ function_free( func );
     }
 }
 
@@ -63,17 +67,17 @@
 
 
 PARSE * parse_make(
- LIST * (* func)( PARSE *, FRAME * ),
- PARSE * left,
- PARSE * right,
- PARSE * third,
- char * string,
- char * string1,
- int num )
+ int type,
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ OBJECT * string,
+ OBJECT * string1,
+ int num )
 {
     PARSE * p = (PARSE *)BJAM_MALLOC( sizeof( PARSE ) );
 
- p->func = func;
+ p->type = type;
     p->left = left;
     p->right = right;
     p->third = third;
@@ -85,12 +89,13 @@
 
     if ( left )
     {
- p->file = left->file;
+ p->file = object_copy( left->file );
         p->line = left->line;
     }
     else
     {
         yyinput_stream( &p->file, &p->line );
+ p->file = object_copy( p->file );
     }
 
     return p;
@@ -109,9 +114,9 @@
         return;
 
     if ( p->string )
- freestr( p->string );
+ object_free( p->string );
     if ( p->string1 )
- freestr( p->string1 );
+ object_free( p->string1 );
     if ( p->left )
         parse_free( p->left );
     if ( p->right )
@@ -119,14 +124,9 @@
     if ( p->third )
         parse_free( p->third );
     if ( p->rulename )
- freestr( p->rulename );
+ object_free( p->rulename );
+ if ( p->file )
+ object_free( p->file );
 
     BJAM_FREE( (char *)p );
 }
-
-
-LIST * parse_evaluate( PARSE * p, FRAME * frame )
-{
- frame->procedure = p;
- return (*p->func)( p, frame );
-}

Modified: branches/release/tools/build/v2/engine/parse.h
==============================================================================
--- branches/release/tools/build/v2/engine/parse.h (original)
+++ branches/release/tools/build/v2/engine/parse.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -21,36 +21,55 @@
  * parse.h - make and destroy parse trees as driven by the parser.
  */
 
+#define PARSE_APPEND 0
+#define PARSE_FOREACH 1
+#define PARSE_IF 2
+#define PARSE_EVAL 3
+#define PARSE_INCLUDE 4
+#define PARSE_LIST 5
+#define PARSE_LOCAL 6
+#define PARSE_MODULE 7
+#define PARSE_CLASS 8
+#define PARSE_NULL 9
+#define PARSE_ON 10
+#define PARSE_RULE 11
+#define PARSE_RULES 12
+#define PARSE_SET 13
+#define PARSE_SETCOMP 14
+#define PARSE_SETEXEC 15
+#define PARSE_SETTINGS 16
+#define PARSE_SWITCH 17
+#define PARSE_WHILE 18
+
 /*
  * Parse tree node.
  */
 
 struct _PARSE {
- LIST * (* func)( PARSE *, FRAME * );
+ int type;
     PARSE * left;
     PARSE * right;
     PARSE * third;
- char * string;
- char * string1;
+ OBJECT * string;
+ OBJECT * string1;
     int num;
     int refs;
-/* module * module; */
- char * rulename;
- char * file;
+ OBJECT * rulename;
+ OBJECT * file;
     int line;
 };
 
-void parse_file( char *, FRAME * );
+void parse_file( OBJECT *, FRAME * );
 void parse_save( PARSE * );
 
 PARSE * parse_make(
- LIST * (* func)( PARSE *, FRAME * ),
- PARSE * left,
- PARSE * right,
- PARSE * third,
- char * string,
- char * string1,
- int num );
+ int type,
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ OBJECT * string,
+ OBJECT * string1,
+ int num );
 
 void parse_refer ( PARSE * );
 void parse_free ( PARSE * );

Modified: branches/release/tools/build/v2/engine/patchlevel.h
==============================================================================
--- branches/release/tools/build/v2/engine/patchlevel.h (original)
+++ branches/release/tools/build/v2/engine/patchlevel.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,10 +8,10 @@
 /* It can be accessed as $(JAMVERSION) in the Jamfile. */
 
 #define VERSION_MAJOR 2011
-#define VERSION_MINOR 04
+#define VERSION_MINOR 12
 #define VERSION_PATCH 0
 #define VERSION_MAJOR_SYM "2011"
-#define VERSION_MINOR_SYM "04"
+#define VERSION_MINOR_SYM "12"
 #define VERSION_PATCH_SYM "00"
-#define VERSION "2011.4"
-#define JAMVERSYM "JAMVERSION=2011.4"
+#define VERSION "2011.12"
+#define JAMVERSYM "JAMVERSION=2011.12"

Deleted: branches/release/tools/build/v2/engine/pathmac.c
==============================================================================
--- branches/release/tools/build/v2/engine/pathmac.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,252 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/* This file is ALSO:
- * Copyright 2001-2004 David Abrahams.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- */
-
-# include "jam.h"
-# include "pathsys.h"
-
-# ifdef OS_MAC
-
-# define DELIM ':'
-
-/*
- * pathunix.c - manipulate file names on UNIX, NT, OS2
- *
- * External routines:
- *
- * path_parse() - split a file name into dir/base/suffix/member
- * path_build() - build a filename given dir/base/suffix/member
- * path_parent() - make a PATHNAME point to its parent dir
- *
- * File_parse() and path_build() just manipuate a string and a structure;
- * they do not make system calls.
- *
- * 04/08/94 (seiwald) - Coherent/386 support added.
- * 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
- * 12/19/94 (mikem) - solaris string table insanity support
- * 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
- * 02/14/95 (seiwald) - parse and build /xxx properly
- * 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
- * should expect hdr searches to come up with strings
- * like "thing/thing.h". So we need to test for "/" as
- * well as "\" when parsing pathnames.
- * 03/16/95 (seiwald) - fixed accursed typo on line 69.
- * 05/03/96 (seiwald) - split from filent.c, fileunix.c
- * 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
- * don't include the archive member name.
- * 01/10/01 (seiwald) - path_parse now strips the trailing : from the
- * directory name, unless the directory name is all
- * :'s, so that $(d:P) works.
- */
-
-/*
- * path_parse() - split a file name into dir/base/suffix/member
- */
-
-void
-path_parse(
- char *file,
- PATHNAME *f )
-{
- char *p, *q;
- char *end;
-
- memset( (char *)f, 0, sizeof( *f ) );
-
- /* Look for <grist> */
-
- if ( file[0] == '<' && ( p = strchr( file, '>' ) ) )
- {
- f->f_grist.ptr = file;
- f->f_grist.len = p - file;
- file = p + 1;
- }
-
- /* Look for dir: */
-
- if ( p = strrchr( file, DELIM ) )
- {
- f->f_dir.ptr = file;
- f->f_dir.len = p - file;
- file = p + 1;
-
- /* All :'s? Include last : as part of directory name */
-
- while ( ( p > f->f_dir.ptr ) && ( *--p == DELIM ) );
-
- if ( p == f->f_dir.ptr )
- ++f->f_dir.len;
- }
-
- end = file + strlen( file );
-
- /* Look for (member). */
-
- if ( ( p = strchr( file, '(' ) ) && ( end[-1] == ')' ) )
- {
- f->f_member.ptr = p + 1;
- f->f_member.len = end - p - 2;
- end = p;
- }
-
- /* Look for .suffix */
- /* This would be memrchr() */
-
- p = 0;
- q = file;
-
- while ( q = memchr( q, '.', end - q ) )
- p = q++;
-
- if ( p )
- {
- f->f_suffix.ptr = p;
- f->f_suffix.len = end - p;
- end = p;
- }
-
- /* Leaves base */
-
- f->f_base.ptr = file;
- f->f_base.len = end - file;
-}
-
-/*
- * path_build() - build a filename given dir/base/suffix/member.
- */
-
-# define DIR_EMPTY 0 /* "" */
-# define DIR_DOT 1 /* : */
-# define DIR_DOTDOT 2 /* :: */
-# define DIR_ABS 3 /* dira:dirb: */
-# define DIR_REL 4 /* :dira:dirb: */
-
-# define G_DIR 0 /* take dir */
-# define G_ROOT 1 /* take root */
-# define G_CAT 2 /* prepend root to dir */
-# define G_DTDR 3 /* :: of rel dir */
-# define G_DDDD 4 /* make it ::: (../..) */
-# define G_MT 5 /* leave it empty */
-
-char grid[5][5] = {
-/* EMPTY DOT DOTDOT ABS REL */
-/* EMPTY */ { G_MT, G_DIR, G_DIR, G_DIR, G_DIR },
-/* DOT */ { G_ROOT, G_DIR, G_DIR, G_DIR, G_DIR },
-/* DOTDOT */ { G_ROOT, G_ROOT, G_DDDD, G_DIR, G_DTDR },
-/* ABS */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT },
-/* REL */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT }
-};
-
-static int file_flags( char * ptr, int len )
-{
- if ( !len )
- return DIR_EMPTY;
- if ( ( len == 1 ) && ( ptr[0] == DELIM ) )
- return DIR_DOT;
- if ( ( len == 2 ) && ( ptr[0] == DELIM ) && ( ptr[1] == DELIM ) )
- return DIR_DOTDOT;
- if ( ptr[0] == DELIM )
- return DIR_REL;
- return DIR_ABS;
-}
-
-
-void path_build( PATHNAME * f, string * file, int binding )
-{
- int dflag;
- int rflag;
- int act;
-
- file_build1( f, file );
-
- /* Combine root & directory, according to the grid. */
-
- dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
- rflag = file_flags( f->f_root.ptr, f->f_root.len );
-
- switch ( act = grid[ rflag ][ dflag ] )
- {
- case G_DTDR:
- {
- /* :: of rel dir */
- string_push_back( file, DELIM );
- }
- /* fall through */
-
- case G_DIR:
- /* take dir */
- string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
- break;
-
- case G_ROOT:
- /* take root */
- string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
- break;
-
- case G_CAT:
- /* prepend root to dir */
- string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
- if ( file->value[ file->size - 1 ] == DELIM )
- string_pop_back( file );
- string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
- break;
-
- case G_DDDD:
- /* make it ::: (../..) */
- string_append( file, ":::" );
- break;
- }
-
- /* Put : between dir and file (if none already). */
-
- if ( ( act != G_MT ) &&
- ( file->value[ file->size - 1 ] != DELIM ) &&
- ( f->f_base.len || f->f_suffix.len ) )
- {
- string_push_back( file, DELIM );
- }
-
- if ( f->f_base.len )
- string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
-
- if ( f->f_suffix.len )
- string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
-
- if ( f->f_member.len )
- {
- string_push_back( file, '(' );
- string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
- string_push_back( file, ')' );
- }
-
- if ( DEBUG_SEARCH )
- printf( " -> '%s'\n", file->value );
-}
-
-
-/*
- * path_parent() - make a PATHNAME point to its parent dir
- */
-
-void path_parent( PATHNAME * f )
-{
- /* Just set everything else to nothing. */
-
- f->f_base.ptr =
- f->f_suffix.ptr =
- f->f_member.ptr = "";
-
- f->f_base.len =
- f->f_suffix.len =
- f->f_member.len = 0;
-}
-
-# endif /* OS_MAC */

Modified: branches/release/tools/build/v2/engine/pathsys.h
==============================================================================
--- branches/release/tools/build/v2/engine/pathsys.h (original)
+++ branches/release/tools/build/v2/engine/pathsys.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -15,31 +15,27 @@
  * have the same name: it never appears in the bound name of a target.
  * (member) is an archive member name: the syntax is arbitrary, but must
  * agree in path_parse(), path_build() and the Jambase.
- *
- * On VMS, we keep track of whether the original path was a directory
- * (without a file), so that $(VAR:D) can climb to the parent.
  */
 
 #ifndef PATHSYS_VP_20020211_H
 # define PATHSYS_VP_20020211_H
 
+#include "jam.h"
 #include "strings.h"
+#include "object.h"
 
 typedef struct _pathname PATHNAME;
 typedef struct _pathpart PATHPART;
 
 struct _pathpart
 {
- char * ptr;
- int len;
+ const char * ptr;
+ int len;
 };
 
 struct _pathname
 {
     PATHPART part[6];
-#ifdef OS_VMS
- int parent;
-#endif
 
 #define f_grist part[0]
 #define f_root part[1]
@@ -52,18 +48,26 @@
 void path_build( PATHNAME * f, string * file, int binding );
 void path_build1( PATHNAME * f, string * file );
 
-void path_parse( char * file, PATHNAME * f );
+void path_parse( const char * file, PATHNAME * f );
 void path_parent( PATHNAME * f );
 
 #ifdef NT
 
-/** Returns newstr-allocated string with long equivivalent of 'short_name'.
+/** Returns object_new-allocated string with long equivivalent of 'short_name'.
     If none exists -- i.e. 'short_path' is already long path, it's returned
     unaltered. */
-char * short_path_to_long_path( char * short_path );
+OBJECT * short_path_to_long_path( OBJECT * short_path );
 
 #endif
 
+/** Given a path, returns an object that can be
+ used as a unique key for that path. Equivalent
+ paths such as a/b, A\B, and a\B on NT all yield the
+ same key.
+ */
+OBJECT * path_as_key( OBJECT * path );
+void path_add_key( OBJECT * path );
+
 #ifdef USE_PATHUNIX
 /** Returns a static pointer to the system dependent path to the temporary
     directory. NOTE: *without* a trailing path separator.
@@ -72,11 +76,11 @@
 
 /** Returns a new temporary name.
 */
-const char * path_tmpnam( void );
+OBJECT * path_tmpnam( void );
 
 /** Returns a new temporary path.
 */
-const char * path_tmpfile( void );
+OBJECT * path_tmpfile( void );
 #endif
 
 /** Give the first argument to 'main', return a full path to
@@ -86,6 +90,8 @@
 
     Implemented in jam.c
 */
-char * executable_path (char *argv0);
+char * executable_path (const char *argv0);
+
+void path_done( void );
 
 #endif

Modified: branches/release/tools/build/v2/engine/pathunix.c
==============================================================================
--- branches/release/tools/build/v2/engine/pathunix.c (original)
+++ branches/release/tools/build/v2/engine/pathunix.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -14,10 +14,11 @@
 # include "jam.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 # include "filesys.h"
 # include <time.h>
 # include <stdlib.h>
+# include <assert.h>
 # ifndef OS_NT
 # include <unistd.h>
 # endif
@@ -56,11 +57,11 @@
  * path_parse() - split a file name into dir/base/suffix/member
  */
 
-void path_parse( char * file, PATHNAME * f )
+void path_parse( const char * file, PATHNAME * f )
 {
- char * p;
- char * q;
- char * end;
+ const char * p;
+ const char * q;
+ const char * end;
 
     memset( (char *)f, 0, sizeof( *f ) );
 
@@ -273,124 +274,250 @@
 
 #ifdef NT
 #include <windows.h>
-#include <tchar.h>
 
 /* The definition of this in winnt.h is not ANSI-C compatible. */
 #undef INVALID_FILE_ATTRIBUTES
 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
 
+OBJECT * path_as_key( OBJECT * path );
+static void path_write_key( char * path_, string * out );
+
+void ShortPathToLongPath( char * short_path, string * out )
+{
+ const char * new_element;
+ unsigned long saved_size;
+ char * p;
+
+ if ( short_path[0] == '\0' )
+ {
+ return;
+ }
+
+ if ( short_path[0] == '\\' && short_path[1] == '\0')
+ {
+ string_push_back( out, '\\' );
+ return;
+ }
+
+ if ( short_path[1] == ':' &&
+ ( short_path[2] == '\0' ||
+ ( short_path[2] == '\\' && short_path[3] == '\0' ) ) )
+ {
+ string_push_back( out, toupper( short_path[0] ) );
+ string_push_back( out, ':' );
+ string_push_back( out, '\\' );
+ return;
+ }
+
+ /* '/' already handled. */
+ if ( ( p = strrchr( short_path, '\\' ) ) )
+ {
+ char saved;
+ new_element = p + 1;
+
+ /* special case \ */
+ if ( p == short_path )
+ ++p;
+
+ /* special case D:\ */
+ if ( p == short_path + 2 && short_path[1] == ':' )
+ ++p;
+
+ saved = *p;
+ *p = '\0';
+ path_write_key( short_path, out );
+ *p = saved;
+ }
+ else
+ {
+ new_element = short_path;
+ }
+
+ if ( out->size && out->value[ out->size - 1 ] != '\\' )
+ {
+ string_push_back( out, '\\' );
+ }
+
+ saved_size = out->size;
+ string_append( out, new_element );
+
+ if ( ! ( new_element[0] == '.' && new_element[1] == '\0' ||
+ new_element[0] == '.' && new_element[1] == '.'
+ && new_element[2] == '\0' ) )
+ {
+ WIN32_FIND_DATA fd;
+ HANDLE hf = 0;
+ hf = FindFirstFile( out->value, &fd );
 
-DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
- cchBuffer)
+ /* If the file exists, replace the name. */
+ if ( hf != INVALID_HANDLE_VALUE )
+ {
+ string_truncate( out, saved_size );
+ string_append( out, fd.cFileName );
+ FindClose( hf );
+ }
+ }
+}
+
+OBJECT * short_path_to_long_path( OBJECT * short_path )
 {
- LONG i=0;
- TCHAR path[_MAX_PATH]={0};
- TCHAR ret[_MAX_PATH]={0};
- LONG pos=0, prev_pos=0;
- LONG len=_tcslen(lpszShortPath);
-
- /* Is the string valid? */
- if (!lpszShortPath) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- /* Is the path valid? */
- if (GetFileAttributes(lpszShortPath)==INVALID_FILE_ATTRIBUTES)
- return 0;
-
- /* Convert "/" to "\" */
- for (i=0;i<len;++i) {
- if (lpszShortPath[i]==_T('/'))
- path[i]=_T('\\');
+ return path_as_key( short_path );
+}
+
+struct path_key_entry
+{
+ OBJECT * path;
+ OBJECT * key;
+};
+
+static struct hash * path_key_cache;
+
+static void path_write_key( char * path_, string * out )
+{
+ struct path_key_entry * result;
+ OBJECT * path = object_new( path_ );
+ int found;
+
+ /* This is only called by path_as_key, which initializes the cache. */
+ assert( path_key_cache );
+
+ result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
+ if ( !found )
+ {
+ /* path_ is already normalized. */
+ result->path = path;
+ ShortPathToLongPath( path_, out );
+ result->key = object_new( out->value );
+ }
+ else
+ {
+ object_free( path );
+ string_append( out, object_str( result->key ) );
+ }
+
+}
+
+static void normalize_path( string * path )
+{
+ char * s;
+ for ( s = path->value; s < path->value + path->size; ++s )
+ {
+ if ( *s == '/' )
+ *s = '\\';
         else
- path[i]=lpszShortPath[i];
+ *s = tolower( *s );
+ }
+ /* Strip trailing "/" */
+ if ( path->size != 0 && path->size != 3 && path->value[ path->size - 1 ] == '\\' )
+ {
+ string_pop_back( path );
     }
+}
+
+void path_add_key( OBJECT * path )
+{
+ struct path_key_entry * result;
+ int found;
 
- /* UNC path? */
- if (path[0]==_T('\\') && path[1]==_T('\\')) {
- pos=2;
- for (i=0;i<2;++i) {
- while (path[pos]!=_T('\\') && path[pos]!=_T('\0'))
- ++pos;
- ++pos;
+ if ( ! path_key_cache )
+ path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" );
+
+ result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
+ if ( !found )
+ {
+ string buf[1];
+ OBJECT * normalized;
+ struct path_key_entry * nresult;
+ result->path = path;
+ string_copy( buf, object_str( path ) );
+ normalize_path( buf );
+ normalized = object_new( buf->value );
+ string_free( buf );
+ nresult = (struct path_key_entry *)hash_insert( path_key_cache, normalized, &found );
+ if ( !found || nresult == result )
+ {
+ nresult->path = object_copy( normalized );
+ nresult->key = object_copy( path );
         }
- _tcsncpy(ret,path,pos-1);
- } /* Drive letter? */
- else if (path[1]==_T(':')) {
- if (path[2]==_T('\\'))
- pos=3;
- if (len==3) {
- if (cchBuffer>3)
- _tcscpy(lpszLongPath,lpszShortPath);
- return len;
+ object_free( normalized );
+ if ( nresult != result )
+ {
+ result->path = object_copy( path );
+ result->key = object_copy( nresult->key );
         }
- _tcsncpy(ret,path,2);
     }
+}
 
- /* Expand the path for each subpath, and strip trailing backslashes */
- for (prev_pos = pos-1;pos<=len;++pos) {
- if (path[pos]==_T('\\') || (path[pos]==_T('\0') &&
- path[pos-1]!=_T('\\'))) {
- WIN32_FIND_DATA fd;
- HANDLE hf=0;
- TCHAR c=path[pos];
- char* new_element;
- path[pos]=_T('\0');
-
- /* the path[prev_pos+1]... path[pos] range is the part of
- path we're handling right now. We need to find long
- name for that element and add it. */
- new_element = path + prev_pos + 1;
-
- /* First add separator, but only if there's something in result already. */
- if (ret[0] != _T('\0'))
- {
- _tcscat(ret,_T("\\"));
- }
-
- /* If it's ".." element, we need to append it, not
- the name in parent that FindFirstFile will return.
- Same goes for "." */
-
- if (new_element[0] == _T('.') && new_element[1] == _T('\0') ||
- new_element[0] == _T('.') && new_element[1] == _T('.')
- && new_element[2] == _T('\0'))
- {
- _tcscat(ret, new_element);
- }
- else
- {
- hf=FindFirstFile(path, &fd);
- if (hf==INVALID_HANDLE_VALUE)
- return 0;
-
- _tcscat(ret,fd.cFileName);
- FindClose(hf);
- }
+OBJECT * path_as_key( OBJECT * path )
+{
+ struct path_key_entry * result;
+ int found;
 
- path[pos]=c;
+ if ( ! path_key_cache )
+ path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" );
 
- prev_pos = pos;
+ result = (struct path_key_entry *)hash_insert( path_key_cache, path, &found );
+ if ( !found )
+ {
+ string buf[1];
+ OBJECT * normalized;
+ struct path_key_entry * nresult;
+ result->path = path;
+ string_copy( buf, object_str( path ) );
+ normalize_path( buf );
+ normalized = object_new( buf->value );
+ nresult = (struct path_key_entry *)hash_insert( path_key_cache, normalized, &found );
+ if ( !found || nresult == result )
+ {
+ string long_path[1];
+ nresult->path = normalized;
+ string_new( long_path );
+ ShortPathToLongPath( buf->value, long_path );
+ nresult->path = object_copy( normalized );
+ nresult->key = object_new( long_path->value );
+ string_free( long_path );
         }
+ string_free( buf );
+ object_free( normalized );
+ if ( nresult != result )
+ {
+ result->path = object_copy( path );
+ result->key = object_copy( nresult->key );
+ }
+ }
+
+ return object_copy( result->key );
+}
+
+static void free_path_key_entry( void * xentry, void * data )
+{
+ struct path_key_entry * entry = (struct path_key_entry *)xentry;
+ object_free( entry->path );
+ object_free( entry->key );
+}
+
+void path_done( void )
+{
+ if ( path_key_cache )
+ {
+ hashenumerate( path_key_cache, &free_path_key_entry, (void *)0 );
+ hashdone( path_key_cache );
     }
+}
 
- len=_tcslen(ret)+1;
- if (cchBuffer>=len)
- _tcscpy(lpszLongPath,ret);
+#else
 
- return len;
+void path_add_key( OBJECT * path )
+{
 }
 
-char* short_path_to_long_path(char* short_path)
+OBJECT * path_as_key( OBJECT * path )
 {
- char buffer2[_MAX_PATH];
- int ret = ShortPathToLongPath(short_path, buffer2, _MAX_PATH);
+ return object_copy( path );
+}
 
- if (ret)
- return newstr(buffer2);
- else
- return newstr(short_path);
+void path_done( void )
+{
 }
 
 #endif
@@ -424,7 +551,7 @@
     return path_tmpdir_result;
 }
 
-const char * path_tmpnam(void)
+OBJECT * path_tmpnam(void)
 {
     char name_buffer[64];
     # ifdef OS_NT
@@ -436,18 +563,21 @@
     if (0 == c1) c1 = time(0)&0xffff;
     c1 += 1;
     sprintf(name_buffer,"jam%lx%lx.000",c0,c1);
- return newstr(name_buffer);
+ return object_new(name_buffer);
 }
 
-const char * path_tmpfile(void)
+OBJECT * path_tmpfile(void)
 {
- const char * result = 0;
+ OBJECT * result = 0;
+ OBJECT * tmpnam;
 
     string file_path;
     string_copy(&file_path,path_tmpdir());
     string_push_back(&file_path,PATH_DELIM);
- string_append(&file_path,path_tmpnam());
- result = newstr(file_path.value);
+ tmpnam = path_tmpnam();
+ string_append(&file_path,object_str(tmpnam));
+ object_free(tmpnam);
+ result = object_new(file_path.value);
     string_free(&file_path);
 
     return result;

Deleted: branches/release/tools/build/v2/engine/pathvms.c
==============================================================================
--- branches/release/tools/build/v2/engine/pathvms.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,406 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/* This file is ALSO:
- * Copyright 2001-2004 David Abrahams.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
- */
-
-# include "jam.h"
-# include "pathsys.h"
-
-# ifdef OS_VMS
-
-# define DEBUG
-
-/*
- * pathvms.c - manipulate file names on VMS
- *
- * External routines:
- *
- * path_parse() - split a file name into dir/base/suffix/member
- * path_build() - build a filename given dir/base/suffix/member
- * path_parent() - make a PATHNAME point to its parent dir
- *
- * File_parse() and path_build() just manipuate a string and a structure;
- * they do not make system calls.
- *
- * WARNING! This file contains voodoo logic, as black magic is
- * necessary for wrangling with VMS file name. Woe be to people
- * who mess with this code.
- *
- * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
- * 05/03/96 (seiwald) - split from filevms.c
- */
-
-/*
- * path_parse() - split a file name into dir/base/suffix/member.
- */
-
-void path_parse( char * file, PATHNAME * f )
-{
- char * p;
- char * q;
- char * end;
-
- memset( (char *)f, 0, sizeof( *f ) );
-
- /* Look for <grist> */
-
- if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
- {
- f->f_grist.ptr = file;
- f->f_grist.len = p - file;
- file = p + 1;
- }
-
- /* Look for dev:[dir] or dev: */
-
- if ( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
- {
- f->f_dir.ptr = file;
- f->f_dir.len = p + 1 - file;
- file = p + 1;
- }
-
- end = file + strlen( file );
-
- /* Look for (member). */
-
- if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
- {
- f->f_member.ptr = p + 1;
- f->f_member.len = end - p - 2;
- end = p;
- }
-
- /* Look for .suffix */
- /* This would be memrchr(). */
-
- p = 0;
- q = file;
-
- while ( q = (char *)memchr( q, '.', end - q ) )
- p = q++;
-
- if ( p )
- {
- f->f_suffix.ptr = p;
- f->f_suffix.len = end - p;
- end = p;
- }
-
- /* Leaves base. */
- f->f_base.ptr = file;
- f->f_base.len = end - file;
-
- /* Is this a directory without a file spec? */
- f->parent = 0;
-}
-
-/*
- * dir mods result
- * --- --- ------
- * Rerooting:
- *
- * (none) :R=dev: dev:
- * devd: :R=dev: devd:
- * devd:[dir] :R=dev: devd:[dir]
- * [.dir] :R=dev: dev:[dir] questionable
- * [dir] :R=dev: dev:[dir]
- *
- * (none) :R=[rdir] [rdir] questionable
- * devd: :R=[rdir] devd:
- * devd:[dir] :R=[rdir] devd:[dir]
- * [.dir] :R=[rdir] [rdir.dir] questionable
- * [dir] :R=[rdir] [rdir]
- *
- * (none) :R=dev:[root] dev:[root]
- * devd: :R=dev:[root] devd:
- * devd:[dir] :R=dev:[root] devd:[dir]
- * [.dir] :R=dev:[root] dev:[root.dir]
- * [dir] :R=dev:[root] [dir]
- *
- * Climbing to parent:
- *
- */
-
-# define DIR_EMPTY 0 /* empty string */
-# define DIR_DEV 1 /* dev: */
-# define DIR_DEVDIR 2 /* dev:[dir] */
-# define DIR_DOTDIR 3 /* [.dir] */
-# define DIR_DASHDIR 4 /* [-] or [-.dir] */
-# define DIR_ABSDIR 5 /* [dir] */
-# define DIR_ROOT 6 /* [000000] or dev:[000000] */
-
-# define G_DIR 0 /* take just dir */
-# define G_ROOT 1 /* take just root */
-# define G_VAD 2 /* root's dev: + [abs] */
-# define G_DRD 3 /* root's dev:[dir] + [.rel] */
-# define G_VRD 4 /* root's dev: + [.rel] made [abs] */
-# define G_DDD 5 /* root's dev:[dir] + . + [dir] */
-
-static int grid[7][7] = {
-
-/* root/dir EMPTY DEV DEVDIR DOTDIR DASH, ABSDIR ROOT */
-/* EMPTY */ G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR,
-/* DEV */ G_ROOT, G_DIR, G_DIR, G_VRD, G_VAD, G_VAD, G_VAD,
-/* DEVDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_VAD, G_VAD, G_VAD,
-/* DOTDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
-/* DASHDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DDD, G_DIR, G_DIR,
-/* ABSDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
-/* ROOT */ G_ROOT, G_DIR, G_DIR, G_VRD, G_DIR, G_DIR, G_DIR,
-
-};
-
-struct dirinf
-{
- int flags;
-
- struct
- {
- char * ptr;
- int len;
- } dev, dir;
-};
-
-static char * strnchr( char * buf, int c, int len )
-{
- while ( len-- )
- if ( *buf && ( *buf++ == c ) )
- return buf - 1;
- return 0;
-}
-
-
-static void dir_flags( char * buf, int len, struct dirinf * i )
-{
- char * p;
-
- if ( !buf || !len )
- {
- i->flags = DIR_EMPTY;
- i->dev.ptr =
- i->dir.ptr = 0;
- i->dev.len =
- i->dir.len = 0;
- }
- else if ( p = strnchr( buf, ':', len ) )
- {
- i->dev.ptr = buf;
- i->dev.len = p + 1 - buf;
- i->dir.ptr = buf + i->dev.len;
- i->dir.len = len - i->dev.len;
- i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
- }
- else
- {
- i->dev.ptr = buf;
- i->dev.len = 0;
- i->dir.ptr = buf;
- i->dir.len = len;
-
- if ( ( *buf == '[' ) && ( buf[1] == ']' ) )
- i->flags = DIR_EMPTY;
- else if ( ( *buf == '[' ) && ( buf[1] == '.' ) )
- i->flags = DIR_DOTDIR;
- else if ( ( *buf == '[' ) && ( buf[1] == '-' ) )
- i->flags = DIR_DASHDIR;
- else
- i->flags = DIR_ABSDIR;
- }
-
- /* But if its rooted in any way. */
-
- if ( ( i->dir.len == 8 ) && !strncmp( i->dir.ptr, "[000000]", 8 ) )
- i->flags = DIR_ROOT;
-}
-
-
-/*
- * path_build() - build a filename given dir/base/suffix/member
- */
-
-void path_build( PATHNAME * f, string * file, int binding )
-{
- struct dirinf root;
- struct dirinf dir;
- int g;
-
- file_build1( f, file );
-
- /* Get info on root and dir for combining. */
- dir_flags( f->f_root.ptr, f->f_root.len, &root );
- dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
-
- /* Combine. */
- switch ( g = grid[ root.flags ][ dir.flags ] )
- {
- case G_DIR:
- /* take dir */
- string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
- break;
-
- case G_ROOT:
- /* take root */
- string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
- break;
-
- case G_VAD:
- /* root's dev + abs directory */
- string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
- string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len );
- break;
-
- case G_DRD:
- case G_DDD:
- /* root's dev:[dir] + rel directory */
- string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
-
- /* sanity checks: root ends with ] */
-
- if ( file->value[file->size - 1] == ']' )
- string_pop_back( file );
-
- /* Add . if separating two -'s */
-
- if ( g == G_DDD )
- string_push_back( file, '.' );
-
- /* skip [ of dir */
- string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 );
- break;
-
- case G_VRD:
- /* root's dev + rel directory made abs */
- string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
- string_push_back( file, '[' );
- /* skip [. of rel dir */
- string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 );
- break;
- }
-
-# ifdef DEBUG
- if ( DEBUG_SEARCH && ( root.flags || dir.flags ) )
- printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
- grid[ root.flags ][ dir.flags ], file->value );
-# endif
-
- /*
- * Now do the special :P modifier when no file was present.
- * (none) (none)
- * [dir1.dir2] [dir1]
- * [dir] [000000]
- * [.dir] (none)
- * [] []
- */
-
- if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent )
- {
- char * p = file->value + file->size;
- while ( p-- > file->value )
- {
- if ( *p == '.' )
- {
- /* If we've truncated everything and left with '[',
- return empty string. */
- if ( p == file->value + 1 )
- string_truncate( file, 0 );
- else
- {
- string_truncate( file, p - file->value );
- string_push_back( file, ']' );
- }
- break;
- }
-
- if ( *p == '-' )
- {
- /* handle .- or - */
- if ( ( p > file->value ) && ( p[ -1 ] == '.' ) )
- --p;
-
- *p++ = ']';
- break;
- }
-
- if ( *p == '[' )
- {
- if ( p[ 1 ] == ']' )
- {
- /* CONSIDER: I don't see any use of this code. We immediately
- break, and 'p' is a local variable. */
- p += 2;
- }
- else
- {
- string_truncate( file, p - file->value );
- string_append( file, "[000000]" );
- }
- break;
- }
- }
- }
-
- /* Now copy the file pieces. */
- if ( f->f_base.len )
- {
- string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
- }
-
- /* If there is no suffix, we append a "." onto all generated names. This
- * keeps VMS from appending its own (wrong) idea of what the suffix should
- * be.
- */
- if ( f->f_suffix.len )
- string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
- else if ( binding && f->f_base.len )
- string_push_back( file, '.' );
-
- if ( f->f_member.len )
- {
- string_push_back( file, '(' );
- string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
- string_push_back( file, ')' );
- }
-
-# ifdef DEBUG
- if ( DEBUG_SEARCH )
- printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
- f->f_root.len, f->f_root.ptr,
- f->f_dir.len, f->f_dir.ptr,
- f->f_base.len, f->f_base.ptr,
- f->f_suffix.len, f->f_suffix.ptr,
- f->f_member.len, f->f_member.ptr,
- file->value );
-# endif
-}
-
-
-/*
- * path_parent() - make a PATHNAME point to its parent dir
- */
-
-void path_parent( PATHNAME * f )
-{
- if ( f->f_base.len )
- {
- f->f_base.ptr =
- f->f_suffix.ptr =
- f->f_member.ptr = "";
-
- f->f_base.len =
- f->f_suffix.len =
- f->f_member.len = 0;
- }
- else
- {
- f->parent = 1;
- }
-}
-
-# endif /* VMS */

Modified: branches/release/tools/build/v2/engine/pwd.c
==============================================================================
--- branches/release/tools/build/v2/engine/pwd.c (original)
+++ branches/release/tools/build/v2/engine/pwd.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,7 +4,7 @@
 
 #include "jam.h"
 #include "lists.h"
-#include "newstr.h"
+#include "object.h"
 #include "pathsys.h"
 #include "mem.h"
 
@@ -29,7 +29,7 @@
 /* The current directory can't change in bjam, so optimize this to cache
 ** the result.
 */
-static char * pwd_result = NULL;
+static OBJECT * pwd_result = NULL;
 
 
 LIST*
@@ -46,9 +46,11 @@
                         if (result_buffer)
                         {
                                 #ifdef NT
- pwd_result = short_path_to_long_path(result_buffer);
+ OBJECT * result = object_new(result_buffer);
+ pwd_result = short_path_to_long_path(result);
+ object_free( result );
                                 #else
- pwd_result = newstr(result_buffer);
+ pwd_result = object_new(result_buffer);
                                 #endif
                         }
                         buffer_size *= 2;
@@ -62,5 +64,13 @@
             return L0;
         }
     }
- return list_new(L0, pwd_result);
+ return list_new( object_copy( pwd_result ) );
+}
+
+void pwd_done( void )
+{
+ if( pwd_result )
+ {
+ object_free( pwd_result );
+ }
 }

Modified: branches/release/tools/build/v2/engine/pwd.h
==============================================================================
--- branches/release/tools/build/v2/engine/pwd.h (original)
+++ branches/release/tools/build/v2/engine/pwd.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,6 +5,7 @@
 #ifndef PWD_H
 #define PWD_H
 
-LIST* pwd(void);
+LIST * pwd( void );
+void pwd_done( void );
 
 #endif

Modified: branches/release/tools/build/v2/engine/regexp.c
==============================================================================
--- branches/release/tools/build/v2/engine/regexp.c (original)
+++ branches/release/tools/build/v2/engine/regexp.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -152,7 +152,7 @@
  * Utility definitions.
  */
 #ifndef CHARBITS
-#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#define UCHARAT(p) ((int)*(const unsigned char *)(p))
 #else
 #define UCHARAT(p) ((int)*(p)&CHARBITS)
 #endif
@@ -213,7 +213,7 @@
  * of the structure of the compiled regexp.
  */
 regexp *
-regcomp( char *exp )
+regcomp( const char *exp )
 {
     register regexp *r;
     register char *scan;
@@ -770,15 +770,15 @@
 /*
  * Global work variables for regexec().
  */
-static char *reginput; /* String-input pointer. */
-static char *regbol; /* Beginning of input, for ^ check. */
-static char **regstartp; /* Pointer to startp array. */
-static char **regendp; /* Ditto for endp. */
+static const char *reginput; /* String-input pointer. */
+static const char *regbol; /* Beginning of input, for ^ check. */
+static const char **regstartp; /* Pointer to startp array. */
+static const char **regendp; /* Ditto for endp. */
 
 /*
  * Forwards.
  */
-STATIC int regtry( regexp *prog, char *string );
+STATIC int regtry( regexp *prog, const char *string );
 STATIC int regmatch( char *prog );
 STATIC int regrepeat( char *p );
 
@@ -794,7 +794,7 @@
 int
 regexec(
     register regexp *prog,
- register char *string )
+ register const char *string )
 {
     register char *s;
 
@@ -859,11 +859,11 @@
 static int /* 0 failure, 1 success */
 regtry(
     regexp *prog,
- char *string )
+ const char *string )
 {
     register int i;
- register char * * sp;
- register char * * ep;
+ register const char * * sp;
+ register const char * * ep;
 
     reginput = string;
     regstartp = prog->startp;
@@ -982,7 +982,7 @@
         case OPEN+8:
         case OPEN+9: {
                 register int no;
- register char *save;
+ register const char *save;
 
                 no = OP(scan) - OPEN;
                 save = reginput;
@@ -1010,7 +1010,7 @@
         case CLOSE+8:
         case CLOSE+9: {
                 register int no;
- register char *save;
+ register const char *save;
 
                 no = OP(scan) - CLOSE;
                 save = reginput;
@@ -1029,7 +1029,7 @@
             }
             break;
         case BRANCH: {
- register char *save;
+ register const char *save;
 
                 if (OP(next) != BRANCH) /* No choice. */
                     next = OPERAND(scan); /* Avoid recursion. */
@@ -1050,7 +1050,7 @@
         case PLUS: {
                 register char nextch;
                 register int no;
- register char *save;
+ register const char *save;
                 register int min;
 
                 /*
@@ -1102,7 +1102,7 @@
 regrepeat( char *p )
 {
     register int count = 0;
- register char *scan;
+ register const char *scan;
     register char *opnd;
 
     scan = reginput;

Modified: branches/release/tools/build/v2/engine/regexp.h
==============================================================================
--- branches/release/tools/build/v2/engine/regexp.h (original)
+++ branches/release/tools/build/v2/engine/regexp.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,8 +9,8 @@
 
 #define NSUBEXP 10
 typedef struct regexp {
- char *startp[NSUBEXP];
- char *endp[NSUBEXP];
+ const char *startp[NSUBEXP];
+ const char *endp[NSUBEXP];
     char regstart; /* Internal use only. */
     char reganch; /* Internal use only. */
     char *regmust; /* Internal use only. */
@@ -18,9 +18,9 @@
     char program[1]; /* Unwarranted chumminess with compiler. */
 } regexp;
 
-regexp *regcomp( char *exp );
-int regexec( regexp *prog, char *string );
-void regerror( char *s );
+regexp *regcomp( const char *exp );
+int regexec( regexp *prog, const char *string );
+void regerror( const char *s );
 
 /*
  * The first byte of the regexp internal "program" is actually this magic

Modified: branches/release/tools/build/v2/engine/rules.c
==============================================================================
--- branches/release/tools/build/v2/engine/rules.c (original)
+++ branches/release/tools/build/v2/engine/rules.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,7 +9,7 @@
 # include "parse.h"
 # include "variable.h"
 # include "rules.h"
-# include "newstr.h"
+# include "object.h"
 # include "hash.h"
 # include "modules.h"
 # include "search.h"
@@ -45,19 +45,10 @@
  */
 
 static void set_rule_actions( RULE *, rule_actions * );
-static void set_rule_body ( RULE *, argument_list *, PARSE * procedure );
+static void set_rule_body ( RULE *, FUNCTION * procedure );
 
 static struct hash * targethash = 0;
 
-struct _located_target
-{
- char * file_name;
- TARGET * target;
-};
-typedef struct _located_target LOCATED_TARGET ;
-
-static struct hash * located_targets = 0;
-
 
 /*
  * target_include() - adds the 'included' TARGET to the list of targets included
@@ -83,25 +74,20 @@
  * target_module.
  */
 
-static RULE * enter_rule( char * rulename, module_t * target_module )
+static RULE * enter_rule( OBJECT * rulename, module_t * target_module )
 {
- RULE rule;
- RULE * r = &rule;
+ int found;
+ RULE * r;
 
- r->name = rulename;
-
- if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) )
+ r = (RULE *)hash_insert( demand_rules(target_module), rulename, &found );
+ if ( !found )
     {
- r->name = newstr( rulename ); /* never freed */
- r->procedure = (PARSE *)0;
+ r->name = object_copy( rulename );
+ r->procedure = 0;
         r->module = 0;
         r->actions = 0;
- r->arguments = 0;
         r->exported = 0;
         r->module = target_module;
-#ifdef HAVE_PYTHON
- r->python_function = 0;
-#endif
     }
     return r;
 }
@@ -116,14 +102,14 @@
 static RULE * define_rule
 (
     module_t * src_module,
- char * rulename,
+ OBJECT * rulename,
     module_t * target_module
 )
 {
     RULE * r = enter_rule( rulename, target_module );
     if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
     {
- set_rule_body( r, 0, 0 );
+ set_rule_body( r, 0 );
         set_rule_actions( r, 0 );
         r->module = src_module; /* r will be executed in the source module */
     }
@@ -133,13 +119,11 @@
 
 void rule_free( RULE * r )
 {
- freestr( r->name );
- r->name = "";
- parse_free( r->procedure );
+ object_free( r->name );
+ r->name = 0;
+ if ( r->procedure )
+ function_free( r->procedure );
     r->procedure = 0;
- if ( r->arguments )
- args_free( r->arguments );
- r->arguments = 0;
     if ( r->actions )
         actions_free( r->actions );
     r->actions = 0;
@@ -150,25 +134,20 @@
  * bindtarget() - return pointer to TARGET, creating it if necessary.
  */
 
-TARGET * bindtarget( char const * target_name )
+TARGET * bindtarget( OBJECT * target_name )
 {
- TARGET target;
- TARGET * t = &target;
+ int found;
+ TARGET * t;
 
     if ( !targethash )
         targethash = hashinit( sizeof( TARGET ), "targets" );
 
- /* Perforce added const everywhere. No time to merge that change. */
-#ifdef NT
- target_name = short_path_to_long_path( (char *)target_name );
-#endif
- t->name = (char *)target_name;
-
- if ( hashenter( targethash, (HASHDATA * *)&t ) )
+ t = (TARGET *)hash_insert( targethash, target_name, &found );
+ if ( !found )
     {
         memset( (char *)t, '\0', sizeof( *t ) );
- t->name = newstr( (char *)target_name ); /* never freed */
- t->boundname = t->name; /* default for T_FLAG_NOTFILE */
+ t->name = object_copy( target_name );
+ t->boundname = object_copy( t->name ); /* default for T_FLAG_NOTFILE */
     }
 
     return t;
@@ -184,14 +163,15 @@
         SETTINGS * s = t->settings;
         for ( ; s ; s = s->next )
         {
- if ( strcmp( s->symbol, "LOCATE" ) == 0 )
+ if ( strcmp( object_str( s->symbol ), "LOCATE" ) == 0 )
             {
- pushsettings( t->settings );
+ pushsettings( root_module(), t->settings );
                 /* We are binding a target with explicit LOCATE. So third
                  * argument is of no use: nothing will be returned through it.
                  */
+ object_free( t->boundname );
                 t->boundname = search( t->name, &t->time, 0, 0 );
- popsettings( t->settings );
+ popsettings( root_module(), t->settings );
                 break;
             }
         }
@@ -206,81 +186,6 @@
 }
 
 
-/* TODO: It is probably not a good idea to use functions in other modules like
- this. */
-void call_bind_rule( char * target, char * boundname );
-
-
-TARGET * search_for_target ( char * name, LIST * search_path )
-{
- PATHNAME f[1];
- string buf[1];
- LOCATED_TARGET lt;
- LOCATED_TARGET * lta = &lt;
- time_t time;
- int found = 0;
- TARGET * result;
-
- string_new( buf );
-
- path_parse( name, f );
-
- f->f_grist.ptr = 0;
- f->f_grist.len = 0;
-
- while ( search_path )
- {
- f->f_root.ptr = search_path->string;
- f->f_root.len = strlen( search_path->string );
-
- string_truncate( buf, 0 );
- path_build( f, buf, 1 );
-
- lt.file_name = buf->value ;
-
- if ( !located_targets )
- located_targets = hashinit( sizeof(LOCATED_TARGET),
- "located targets" );
-
- if ( hashcheck( located_targets, (HASHDATA * *)&lta ) )
- {
- return lta->target;
- }
-
- timestamp( buf->value, &time );
- if ( time )
- {
- found = 1;
- break;
- }
-
- search_path = list_next( search_path );
- }
-
- if ( !found )
- {
- f->f_root.ptr = 0;
- f->f_root.len = 0;
-
- string_truncate( buf, 0 );
- path_build( f, buf, 1 );
-
- timestamp( buf->value, &time );
- }
-
- result = bindtarget( name );
- result->boundname = newstr( buf->value );
- result->time = time;
- result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;
-
- call_bind_rule( result->name, result->boundname );
-
- string_free( buf );
-
- return result;
-}
-
-
 /*
  * copytarget() - make a new target with the old target's name.
  *
@@ -291,8 +196,8 @@
 {
     TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
     memset( (char *)t, '\0', sizeof( *t ) );
- t->name = copystr( ot->name );
- t->boundname = t->name;
+ t->name = object_copy( ot->name );
+ t->boundname = object_copy( t->name );
 
     t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
 
@@ -304,7 +209,7 @@
  * touch_target() - mark a target to simulate being new.
  */
 
-void touch_target( char * t )
+void touch_target( OBJECT * t )
 {
     bindtarget( t )->flags |= T_FLAG_TOUCHED;
 }
@@ -320,8 +225,9 @@
 
 TARGETS * targetlist( TARGETS * chain, LIST * target_names )
 {
- for ( ; target_names; target_names = list_next( target_names ) )
- chain = targetentry( chain, bindtarget( target_names->string ) );
+ LISTITER iter = list_begin( target_names ), end = list_end( target_names );
+ for ( ; iter != end; iter = list_next( iter ) )
+ chain = targetentry( chain, bindtarget( list_item( iter ) ) );
     return chain;
 }
 
@@ -368,6 +274,21 @@
 }
 
 /*
+ * action_free - decrement the ACTIONs refrence count
+ * and (maybe) free it.
+ */
+
+void action_free ( ACTION * action )
+{
+ if ( --action->refs == 0 )
+ {
+ freetargets( action->targets );
+ freetargets( action->sources );
+ BJAM_FREE( action );
+ }
+}
+
+/*
  * actionlist() - append to an ACTION chain.
  */
 
@@ -377,6 +298,7 @@
 
     actions->action = action;
 
+ ++action->refs;
     if ( !chain ) chain = actions;
     else chain->tail->next = actions;
     chain->tail = actions;
@@ -397,13 +319,13 @@
  * the head of the settings chain.
  */
 
-SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
+SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol, LIST * value )
 {
     SETTINGS * v;
 
     /* Look for previous settings. */
     for ( v = head; v; v = v->next )
- if ( !strcmp( v->symbol, symbol ) )
+ if ( object_equal( v->symbol, symbol ) )
             break;
 
     /* If not previously set, alloc a new. */
@@ -418,10 +340,9 @@
         else
             v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
 
- v->symbol = newstr( symbol );
+ v->symbol = object_copy( symbol );
         v->value = value;
         v->next = head;
- v->multiple = 0;
         head = v;
     }
     else if ( flag == VAR_APPEND )
@@ -445,10 +366,10 @@
  * pushsettings() - set all target specific variables.
  */
 
-void pushsettings( SETTINGS * v )
+void pushsettings( struct module_t * module, SETTINGS * v )
 {
     for ( ; v; v = v->next )
- v->value = var_swap( v->symbol, v->value );
+ v->value = var_swap( module, v->symbol, v->value );
 }
 
 
@@ -456,9 +377,9 @@
  * popsettings() - reset target specific variables to their pre-push values.
  */
 
-void popsettings( SETTINGS * v )
+void popsettings( struct module_t * module, SETTINGS * v )
 {
- pushsettings( v ); /* just swap again */
+ pushsettings( module, v ); /* just swap again */
 }
 
 
@@ -471,7 +392,7 @@
     SETTINGS * copy = 0;
     SETTINGS * v;
     for ( v = head; v; v = v->next )
- copy = addsettings( copy, VAR_SET, v->symbol, list_copy( 0, v->value ) );
+ copy = addsettings( copy, VAR_SET, v->symbol, list_copy( v->value ) );
     return copy;
 }
 
@@ -500,6 +421,7 @@
     while ( chain )
     {
         ACTIONS * n = chain->next;
+ action_free( chain->action );
         BJAM_FREE( chain );
         chain = n;
     }
@@ -515,7 +437,7 @@
     while ( v )
     {
         SETTINGS * n = v->next;
- freestr( v->symbol );
+ object_free( v->symbol );
         list_free( v->value );
         v->next = settings_freelist;
         settings_freelist = v;
@@ -527,10 +449,19 @@
 static void freetarget( void * xt, void * data )
 {
     TARGET * t = (TARGET *)xt;
- if ( t->settings ) freesettings( t->settings );
- if ( t->depends ) freetargets ( t->depends );
- if ( t->includes ) freetarget ( t->includes, (void *)0 );
- if ( t->actions ) freeactions ( t->actions );
+ if ( t->name ) object_free ( t->name );
+ if ( t->boundname ) object_free ( t->boundname );
+ if ( t->settings ) freesettings( t->settings );
+ if ( t->depends ) freetargets ( t->depends );
+ if ( t->dependants ) freetargets ( t->dependants );
+ if ( t->parents ) freetargets ( t->parents );
+ if ( t->actions ) freeactions ( t->actions );
+
+ if ( t->includes )
+ {
+ freetarget( t->includes, (void *)0 );
+ BJAM_FREE( t->includes );
+ }
 }
 
 
@@ -540,8 +471,11 @@
 
 void rules_done()
 {
- hashenumerate( targethash, freetarget, 0 );
- hashdone( targethash );
+ if ( targethash )
+ {
+ hashenumerate( targethash, freetarget, 0 );
+ hashdone( targethash );
+ }
     while ( settings_freelist )
     {
         SETTINGS * n = settings_freelist->next;
@@ -552,43 +486,6 @@
 
 
 /*
- * args_new() - make a new reference-counted argument list.
- */
-
-argument_list * args_new()
-{
- argument_list * r = (argument_list *)BJAM_MALLOC( sizeof(argument_list) );
- r->reference_count = 0;
- lol_init( r->data );
- return r;
-}
-
-
-/*
- * args_refer() - add a new reference to the given argument list.
- */
-
-void args_refer( argument_list * a )
-{
- ++a->reference_count;
-}
-
-
-/*
- * args_free() - release a reference to the given argument list.
- */
-
-void args_free( argument_list * a )
-{
- if ( --a->reference_count <= 0 )
- {
- lol_free( a->data );
- BJAM_FREE( a );
- }
-}
-
-
-/*
  * actions_refer() - add a new reference to the given actions.
  */
 
@@ -606,29 +503,22 @@
 {
     if ( --a->reference_count <= 0 )
     {
- freestr( a->command );
+ function_free( a->command );
         list_free( a->bindlist );
         BJAM_FREE( a );
     }
 }
 
-
 /*
  * set_rule_body() - set the argument list and procedure of the given rule.
  */
 
-static void set_rule_body( RULE * rule, argument_list * args, PARSE * procedure )
+static void set_rule_body( RULE * rule, FUNCTION * procedure )
 {
- if ( args )
- args_refer( args );
- if ( rule->arguments )
- args_free( rule->arguments );
- rule->arguments = args;
-
     if ( procedure )
- parse_refer( procedure );
+ function_refer( procedure );
     if ( rule->procedure )
- parse_free( rule->procedure );
+ function_free( rule->procedure );
     rule->procedure = procedure;
 }
 
@@ -638,16 +528,20 @@
  * global module.
  */
 
-static char * global_rule_name( RULE * r )
+static OBJECT * global_rule_name( RULE * r )
 {
     if ( r->module == root_module() )
- return r->name;
+ return object_copy( r->name );
 
     {
         char name[4096] = "";
- strncat( name, r->module->name, sizeof( name ) - 1 );
- strncat( name, r->name, sizeof( name ) - 1 );
- return newstr( name);
+ if ( r->module->name )
+ {
+ strncat( name, object_str( r->module->name ), sizeof( name ) - 1 );
+ strncat( name, ".", sizeof( name ) - 1 );
+ }
+ strncat( name, object_str( r->name ), sizeof( name ) - 1 );
+ return object_new( name );
     }
 }
 
@@ -663,9 +557,9 @@
         return r;
 
     {
- char * name = global_rule_name( r );
+ OBJECT * name = global_rule_name( r );
         RULE * result = define_rule( r->module, name, root_module() );
- freestr( name );
+ object_free( name );
         return result;
     }
 }
@@ -677,19 +571,19 @@
  * exported to the global module as modulename.rulename.
  */
 
-RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported )
+RULE * new_rule_body( module_t * m, OBJECT * rulename, FUNCTION * procedure, int exported )
 {
     RULE * local = define_rule( m, rulename, m );
     local->exported = exported;
- set_rule_body( local, args, procedure );
+ set_rule_body( local, procedure );
 
     /* Mark the procedure with the global rule name, regardless of whether the
      * rule is exported. That gives us something reasonably identifiable that we
      * can use, e.g. in profiling output. Only do this once, since this could be
      * called multiple times with the same procedure.
      */
- if ( procedure->rulename == 0 )
- procedure->rulename = global_rule_name( local );
+ if ( function_rulename( procedure ) == 0 )
+ function_set_rulename( procedure, global_rule_name( local ) );
 
     return local;
 }
@@ -705,10 +599,11 @@
 }
 
 
-static rule_actions * actions_new( char * command, LIST * bindlist, int flags )
+static rule_actions * actions_new( FUNCTION * command, LIST * bindlist, int flags )
 {
     rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
- result->command = copystr( command );
+ function_refer( command );
+ result->command = command;
     result->bindlist = bindlist;
     result->flags = flags;
     result->reference_count = 0;
@@ -716,7 +611,7 @@
 }
 
 
-RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags )
+RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags )
 {
     RULE * local = define_rule( m, rulename, m );
     RULE * global = global_rule( local );
@@ -733,32 +628,37 @@
  * modules, look in module 'name1' for rule 'name2'.
  */
 
-RULE * lookup_rule( char * rulename, module_t * m, int local_only )
+RULE * lookup_rule( OBJECT * rulename, module_t * m, int local_only )
 {
- RULE rule;
- RULE * r = &rule;
+ RULE * r;
     RULE * result = 0;
     module_t * original_module = m;
 
- r->name = rulename;
-
     if ( m->class_module )
         m = m->class_module;
 
- if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) )
+ if ( m->rules && ( r = (RULE *)hash_find( m->rules, rulename ) ) )
         result = r;
     else if ( !local_only && m->imported_modules )
     {
         /* Try splitting the name into module and rule. */
- char *p = strchr( r->name, '.' ) ;
+ char *p = strchr( object_str( rulename ), '.' ) ;
         if ( p )
         {
- *p = '\0';
+ string buf[1];
+ OBJECT * module_part;
+ OBJECT * rule_part;
+ string_new( buf );
+ string_append_range( buf, object_str( rulename ), p );
+ module_part = object_new( buf->value );
+ rule_part = object_new( p + 1 );
             /* Now, r->name keeps the module name, and p+1 keeps the rule name.
              */
- if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
- result = lookup_rule( p + 1, bindmodule( rulename ), 1 );
- *p = '.';
+ if ( hash_find( m->imported_modules, module_part ) )
+ result = lookup_rule( rule_part, bindmodule( module_part ), 1 );
+ object_free( rule_part );
+ object_free( module_part );
+ string_free( buf );
         }
     }
 
@@ -786,7 +686,7 @@
 }
 
 
-RULE * bindrule( char * rulename, module_t * m )
+RULE * bindrule( OBJECT * rulename, module_t * m )
 {
     RULE * result = lookup_rule( rulename, m, 0 );
     if ( !result )
@@ -801,10 +701,24 @@
 }
 
 
-RULE * import_rule( RULE * source, module_t * m, char * name )
+RULE * import_rule( RULE * source, module_t * m, OBJECT * name )
 {
     RULE * dest = define_rule( source->module, name, m );
- set_rule_body( dest, source->arguments, source->procedure );
+ set_rule_body( dest, source->procedure );
     set_rule_actions( dest, source->actions );
     return dest;
 }
+
+
+void rule_localize( RULE * rule, module_t * m )
+{
+ rule->module = m;
+ if ( rule->procedure )
+ {
+ FUNCTION * procedure = function_unbind_variables( rule->procedure );
+ function_refer( procedure );
+ function_free( rule->procedure );
+ rule->procedure = procedure;
+ }
+}
+

Modified: branches/release/tools/build/v2/engine/rules.h
==============================================================================
--- branches/release/tools/build/v2/engine/rules.h (original)
+++ branches/release/tools/build/v2/engine/rules.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -15,7 +15,7 @@
 
 #include "modules.h"
 #include "jam.h"
-#include "parse.h"
+#include "function.h"
 
 
 /*
@@ -52,20 +52,13 @@
 
 /* RULE - a generic jam rule, the product of RULE and ACTIONS. */
 
-/* A rule's argument list. */
-struct argument_list
-{
- int reference_count;
- LOL data[1];
-};
-
 /* Build actions corresponding to a rule. */
 struct rule_actions
 {
- int reference_count;
- char * command; /* command string from ACTIONS */
- LIST * bindlist;
- int flags; /* modifiers on ACTIONS */
+ int reference_count;
+ FUNCTION * command; /* command string from ACTIONS */
+ LIST * bindlist;
+ int flags; /* modifiers on ACTIONS */
 
 #define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
 #define RULE_TOGETHER 0x02 /* combine actions on single target */
@@ -80,19 +73,14 @@
 
 struct _rule
 {
- char * name;
- PARSE * procedure; /* parse tree from RULE */
- argument_list * arguments; /* argument checking info, or NULL for unchecked
- */
+ OBJECT * name;
+ FUNCTION * procedure;
     rule_actions * actions; /* build actions, or NULL for no actions */
     module_t * module; /* module in which this rule is executed */
     int exported; /* nonzero if this rule is supposed to appear in
                                  * the global module and be automatically
                                  * imported into other modules
                                  */
-#ifdef HAVE_PYTHON
- PyObject * python_function;
-#endif
 };
 
 /* ACTIONS - a chain of ACTIONs. */
@@ -110,16 +98,19 @@
     TARGETS * targets;
     TARGETS * sources; /* aka $(>) */
     char running; /* has been started */
+#define A_INIT 0
+#define A_RUNNING_NOEXEC 1
+#define A_RUNNING 2
     char status; /* see TARGET status */
+ int refs;
 };
 
 /* SETTINGS - variables to set when executing a TARGET's ACTIONS. */
 struct _settings
 {
     SETTINGS * next;
- char * symbol; /* symbol name for var_set() */
+ OBJECT * symbol; /* symbol name for var_set() */
     LIST * value; /* symbol value for var_set() */
- int multiple;
 };
 
 /* TARGETS - a chain of TARGETs. */
@@ -133,8 +124,8 @@
 /* TARGET - an entity (e.g. a file) that can be built. */
 struct _target
 {
- char * name;
- char * boundname; /* if search() relocates target */
+ OBJECT * name;
+ OBJECT * boundname; /* if search() relocates target */
     ACTIONS * actions; /* rules to execute, if any */
     SETTINGS * settings; /* variables to define */
 
@@ -220,6 +211,7 @@
 #define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
 #define T_MAKE_RUNNING 3 /* make1(target) running commands */
 #define T_MAKE_DONE 4 /* make1(target) done */
+#define T_MAKE_NOEXEC_DONE 5 /* make1(target) done with -n in effect */
 
 #ifdef OPT_SEMAPHORE
     #define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
@@ -235,44 +227,41 @@
     TARGETS * parents; /* used by make1() for completion */
     char * cmds; /* type-punned command list */
 
- char * failed;
+ const char * failed;
 };
 
 
 /* Action related functions. */
+void action_free ( ACTION * );
 ACTIONS * actionlist ( ACTIONS *, ACTION * );
 void freeactions ( ACTIONS * );
-SETTINGS * addsettings ( SETTINGS *, int flag, char * symbol, LIST * value );
-void pushsettings ( SETTINGS * );
-void popsettings ( SETTINGS * );
+SETTINGS * addsettings ( SETTINGS *, int flag, OBJECT * symbol, LIST * value );
+void pushsettings ( struct module_t * module, SETTINGS * );
+void popsettings ( struct module_t * module, SETTINGS * );
 SETTINGS * copysettings ( SETTINGS * );
 void freesettings ( SETTINGS * );
 void actions_refer( rule_actions * );
 void actions_free ( rule_actions * );
 
-/* Argument list related functions. */
-void args_free ( argument_list * );
-argument_list * args_new ();
-void args_refer( argument_list * );
-
 /* Rule related functions. */
-RULE * bindrule ( char * rulename, module_t * );
-RULE * import_rule ( RULE * source, module_t *, char * name );
-RULE * new_rule_body ( module_t *, char * rulename, argument_list *, PARSE * procedure, int exprt );
-RULE * new_rule_actions( module_t *, char * rulename, char * command, LIST * bindlist, int flags );
+RULE * bindrule ( OBJECT * rulename, module_t * );
+RULE * import_rule ( RULE * source, module_t *, OBJECT * name );
+void rule_localize ( RULE * rule, module_t * module );
+RULE * new_rule_body ( module_t *, OBJECT * rulename, FUNCTION * func, int exprt );
+RULE * new_rule_actions( module_t *, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags );
 void rule_free ( RULE * );
 
 /* Target related functions. */
 void bind_explicitly_located_targets();
-TARGET * bindtarget ( char const * target_name );
+TARGET * bindtarget ( OBJECT * target_name );
 TARGET * copytarget ( TARGET const * t );
 void freetargets ( TARGETS * );
-TARGET * search_for_target ( char * name, LIST * search_path );
 TARGETS * targetchain ( TARGETS * chain, TARGETS * );
 TARGETS * targetentry ( TARGETS * chain, TARGET * );
 void target_include ( TARGET * including, TARGET * included );
 TARGETS * targetlist ( TARGETS * chain, LIST * target_names );
-void touch_target ( char * t );
+void touch_target ( OBJECT * t );
+void clear_includes ( TARGET * );
 
 /* Final module cleanup. */
 void rules_done();

Modified: branches/release/tools/build/v2/engine/scan.c
==============================================================================
--- branches/release/tools/build/v2/engine/scan.c (original)
+++ branches/release/tools/build/v2/engine/scan.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -10,7 +10,8 @@
 #include "scan.h"
 #include "jamgram.h"
 #include "jambase.h"
-#include "newstr.h"
+#include "object.h"
+#include "constants.h"
 
 /*
  * scan.c - the jam yacc scanner
@@ -41,7 +42,7 @@
     char * string; /* pointer into current line */
     char * * strings; /* for yyfparse() -- text to parse */
     FILE * file; /* for yyfparse() -- file being read */
- char * fname; /* for yyfparse() -- file name */
+ OBJECT * fname; /* for yyfparse() -- file name */
     int line; /* line counter for error messages */
     char buf[ 512 ]; /* for yyfparse() -- line buffer */
 };
@@ -67,7 +68,7 @@
 }
 
 
-void yyerror( char * s )
+void yyerror( const char * s )
 {
     /* We use yylval instead of incp to access the error location information as
      * the incp pointer will already be reset to 0 in case the error occurred at
@@ -82,7 +83,7 @@
      * TODO: Test the theory about when yylval and incp location information are
      * the same and when they differ.
      */
- printf( "%s:%d: %s at %s\n", yylval.file, yylval.line, s, symdump( &yylval ) );
+ printf( "%s:%d: %s at %s\n", object_str( yylval.file ), yylval.line, s, symdump( &yylval ) );
     ++anyerrors;
 }
 
@@ -93,7 +94,7 @@
 }
 
 
-void yyfparse( char * s )
+void yyfparse( OBJECT * s )
 {
     struct include * i = (struct include *)BJAM_MALLOC( sizeof( *i ) );
 
@@ -101,13 +102,13 @@
     i->string = "";
     i->strings = 0;
     i->file = 0;
- i->fname = copystr( s );
+ i->fname = object_copy( s );
     i->line = 0;
     i->next = incp;
     incp = i;
 
     /* If the filename is "+", it means use the internal jambase. */
- if ( !strcmp( s, "+" ) )
+ if ( !strcmp( object_str( s ), "+" ) )
         i->strings = jambase;
 }
 
@@ -151,8 +152,8 @@
         if ( !i->file )
         {
             FILE * f = stdin;
- if ( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
- perror( i->fname );
+ if ( strcmp( object_str( i->fname ), "-" ) && !( f = fopen( object_str( i->fname ), "r" ) ) )
+ perror( object_str( i->fname ) );
             i->file = f;
         }
 
@@ -174,7 +175,7 @@
     /* Close file, free name. */
     if ( i->file && ( i->file != stdin ) )
         fclose( i->file );
- freestr( i->fname );
+ object_free( i->fname );
     BJAM_FREE( (char *)i );
 
     return EOF;
@@ -252,7 +253,7 @@
 
         *b = 0;
         yylval.type = STRING;
- yylval.string = newstr( buf );
+ yylval.string = object_new( buf );
         yylval.file = incp->fname;
         yylval.line = incp->line;
     }
@@ -361,12 +362,12 @@
                 if ( ( *buf == *k->word ) && !strcmp( k->word, buf ) )
                 {
                     yylval.type = k->type;
- yylval.string = k->word; /* used by symdump */
+ yylval.keyword = k->word; /* used by symdump */
                     break;
                 }
 
         if ( yylval.type == ARG )
- yylval.string = newstr( buf );
+ yylval.string = object_new( buf );
     }
 
     if ( DEBUG_SCAN )
@@ -388,11 +389,11 @@
     static char buf[ BIGGEST_TOKEN + 20 ];
     switch ( s->type )
     {
- case EOF : sprintf( buf, "EOF" ); break;
- case 0 : sprintf( buf, "unknown symbol %s", s->string ); break;
- case ARG : sprintf( buf, "argument %s" , s->string ); break;
- case STRING: sprintf( buf, "string \"%s\"" , s->string ); break;
- default : sprintf( buf, "keyword %s" , s->string ); break;
+ case EOF : sprintf( buf, "EOF" ); break;
+ case 0 : sprintf( buf, "unknown symbol %s", object_str( s->string ) ); break;
+ case ARG : sprintf( buf, "argument %s" , object_str( s->string ) ); break;
+ case STRING: sprintf( buf, "string \"%s\"" , object_str( s->string ) ); break;
+ default : sprintf( buf, "keyword %s" , s->keyword ); break;
     }
     return buf;
 }
@@ -403,7 +404,7 @@
  * transitions that produce a parse.
  */
 
-void yyinput_stream( char * * name, int * line )
+void yyinput_stream( OBJECT * * name, int * line )
 {
     if ( incp )
     {
@@ -412,7 +413,7 @@
     }
     else
     {
- *name = "(builtin)";
+ *name = constant_builtin;
         *line = -1;
     }
 }

Modified: branches/release/tools/build/v2/engine/scan.h
==============================================================================
--- branches/release/tools/build/v2/engine/scan.h (original)
+++ branches/release/tools/build/v2/engine/scan.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -31,25 +31,26 @@
 
 typedef struct _YYSTYPE
 {
- int type;
- char * string;
- PARSE * parse;
- LIST * list;
- int number;
- char * file;
- int line;
+ int type;
+ OBJECT * string;
+ PARSE * parse;
+ LIST * list;
+ int number;
+ OBJECT * file;
+ int line;
+ const char * keyword;
 } YYSTYPE;
 
 extern YYSTYPE yylval;
 
 void yymode( int n );
-void yyerror( char * s );
+void yyerror( const char * s );
 int yyanyerrors();
-void yyfparse( char * s );
+void yyfparse( OBJECT * s );
 int yyline();
 int yylex();
 int yyparse();
-void yyinput_stream( char * * name, int * line );
+void yyinput_stream( OBJECT * * name, int * line );
 
 # define SCAN_NORMAL 0 /* normal parsing */
 # define SCAN_STRING 1 /* look only for matching } */

Modified: branches/release/tools/build/v2/engine/search.c
==============================================================================
--- branches/release/tools/build/v2/engine/search.c (original)
+++ branches/release/tools/build/v2/engine/search.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,7 +16,7 @@
 #include "timestamp.h"
 #include "pathsys.h"
 #include "variable.h"
-#include "newstr.h"
+#include "object.h"
 #include "compile.h"
 #include "strings.h"
 #include "hash.h"
@@ -26,8 +26,8 @@
 
 typedef struct _binding
 {
- char * binding;
- char * target;
+ OBJECT * binding;
+ OBJECT * target;
 } BINDING;
 
 static struct hash *explicit_bindings = 0;
@@ -35,22 +35,15 @@
 
 void call_bind_rule
 (
- char * target_,
- char * boundname_
+ OBJECT * target_,
+ OBJECT * boundname_
 )
 {
- LIST * bind_rule = var_get( "BINDRULE" );
- if ( bind_rule )
+ LIST * bind_rule = var_get( root_module(), constant_BINDRULE );
+ if ( !list_empty( bind_rule ) )
     {
- /* No guarantee that the target is an allocated string, so be on the
- * safe side.
- */
- char * target = copystr( target_ );
-
- /* Likewise, do not rely on implementation details of newstr.c: allocate
- * a copy of boundname.
- */
- char * boundname = copystr( boundname_ );
+ OBJECT * target = object_copy( target_ );
+ OBJECT * boundname = object_copy( boundname_ );
         if ( boundname && target )
         {
             /* Prepare the argument list. */
@@ -58,11 +51,11 @@
             frame_init( frame );
 
             /* First argument is the target name. */
- lol_add( frame->args, list_new( L0, target ) );
+ lol_add( frame->args, list_new( target ) );
 
- lol_add( frame->args, list_new( L0, boundname ) );
+ lol_add( frame->args, list_new( boundname ) );
             if ( lol_get( frame->args, 1 ) )
- evaluate_rule( bind_rule->string, frame );
+ list_free( evaluate_rule( list_front( bind_rule ), frame ) );
 
             /* Clean up */
             frame_free( frame );
@@ -70,9 +63,9 @@
         else
         {
             if ( boundname )
- freestr( boundname );
+ object_free( boundname );
             if ( target )
- freestr( target );
+ object_free( target );
         }
     }
 }
@@ -93,21 +86,21 @@
  * the third argument.
  */
 
-char *
+OBJECT *
 search(
- char *target,
+ OBJECT * target,
     time_t *time,
- char **another_target,
+ OBJECT * * another_target,
     int file
 )
 {
     PATHNAME f[1];
- LIST *varlist;
- string buf[1];
- int found = 0;
+ LIST * varlist;
+ string buf[1];
+ int found = 0;
     /* Will be set to 1 if target location is specified via LOCATE. */
- int explicitly_located = 0;
- char *boundname = 0;
+ int explicitly_located = 0;
+ OBJECT * boundname = 0;
 
     if ( another_target )
         *another_target = 0;
@@ -119,55 +112,64 @@
     string_new( buf );
     /* Parse the filename */
 
- path_parse( target, f );
+ path_parse( object_str( target ), f );
 
     f->f_grist.ptr = 0;
     f->f_grist.len = 0;
 
- if ( ( varlist = var_get( "LOCATE" ) ) )
- {
- f->f_root.ptr = varlist->string;
- f->f_root.len = strlen( varlist->string );
+ varlist = var_get( root_module(), constant_LOCATE );
+ if ( !list_empty( varlist ) )
+ {
+ OBJECT * key;
+ f->f_root.ptr = object_str( list_front( varlist ) );
+ f->f_root.len = strlen( object_str( list_front( varlist ) ) );
 
         path_build( f, buf, 1 );
 
         if ( DEBUG_SEARCH )
- printf( "locate %s: %s\n", target, buf->value );
+ printf( "locate %s: %s\n", object_str( target ), buf->value );
 
         explicitly_located = 1;
 
- timestamp( buf->value, time );
+ key = object_new( buf->value );
+ timestamp( key, time );
+ object_free( key );
         found = 1;
     }
- else if ( ( varlist = var_get( "SEARCH" ) ) )
+ else if ( varlist = var_get( root_module(), constant_SEARCH ), !list_empty( varlist ) )
     {
- while ( varlist )
+ LISTITER iter = list_begin( varlist ), end = list_end( varlist );
+ for ( ; iter != end; iter = list_next( iter ) )
         {
- BINDING b, *ba = &b;
+ BINDING * ba;
             file_info_t *ff;
+ OBJECT * key;
+ OBJECT * test_path;
 
- f->f_root.ptr = varlist->string;
- f->f_root.len = strlen( varlist->string );
+ f->f_root.ptr = object_str( list_item( iter ) );
+ f->f_root.len = strlen( object_str( list_item( iter ) ) );
 
             string_truncate( buf, 0 );
             path_build( f, buf, 1 );
 
             if ( DEBUG_SEARCH )
- printf( "search %s: %s\n", target, buf->value );
-
- ff = file_query(buf->value);
- timestamp( buf->value, time );
+ printf( "search %s: %s\n", object_str( target ), buf->value );
 
- b.binding = buf->value;
+ test_path = object_new( buf->value );
+ key = path_as_key( test_path );
+ object_free( test_path );
+ ff = file_query( key );
+ timestamp( key, time );
 
- if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
+ if ( ( ba = (BINDING *)hash_find( explicit_bindings, key ) ) )
             {
                 if ( DEBUG_SEARCH )
                     printf(" search %s: found explicitly located target %s\n",
- target, ba->target);
+ object_str( target ), object_str( ba->target ) );
                 if ( another_target )
                     *another_target = ba->target;
                 found = 1;
+ object_free( key );
                 break;
             }
             else if ( ff && ff->time )
@@ -175,11 +177,11 @@
                 if ( !file || ff->is_file )
                 {
                     found = 1;
+ object_free( key );
                     break;
                 }
             }
-
- varlist = list_next( varlist );
+ object_free( key );
         }
     }
 
@@ -188,6 +190,7 @@
         /* Look for the obvious */
         /* This is a questionable move. Should we look in the */
         /* obvious place if SEARCH is set? */
+ OBJECT * key;
 
         f->f_root.ptr = 0;
         f->f_root.len = 0;
@@ -196,24 +199,34 @@
         path_build( f, buf, 1 );
 
         if ( DEBUG_SEARCH )
- printf( "search %s: %s\n", target, buf->value );
+ printf( "search %s: %s\n", object_str( target ), buf->value );
 
- timestamp( buf->value, time );
+ key = object_new( buf->value );
+ timestamp( key, time );
+ object_free( key );
     }
 
- boundname = newstr( buf->value );
+ boundname = object_new( buf->value );
     string_free( buf );
 
     if ( explicitly_located )
     {
- BINDING b;
- BINDING * ba = &b;
- b.binding = boundname;
- b.target = target;
+ int found;
+ BINDING * ba;
+ OBJECT * key = path_as_key( boundname );
         /* CONSIDER: we probably should issue a warning is another file
            is explicitly bound to the same location. This might break
            compatibility, though. */
- hashenter( explicit_bindings, (HASHDATA * *)&ba );
+ ba = (BINDING *)hash_insert( explicit_bindings, key, &found );
+ if ( !found )
+ {
+ ba->binding = key;
+ ba->target = target;
+ }
+ else
+ {
+ object_free( key );
+ }
     }
 
     /* prepare a call to BINDRULE if the variable is set */
@@ -221,3 +234,19 @@
 
     return boundname;
 }
+
+
+static void free_binding( void * xbinding, void * data )
+{
+ BINDING * binding = (BINDING *)xbinding;
+ object_free( binding->binding );
+}
+
+void search_done( void )
+{
+ if ( explicit_bindings )
+ {
+ hashenumerate( explicit_bindings, free_binding, (void *)0 );
+ hashdone( explicit_bindings );
+ }
+}

Modified: branches/release/tools/build/v2/engine/search.h
==============================================================================
--- branches/release/tools/build/v2/engine/search.h (original)
+++ branches/release/tools/build/v2/engine/search.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,4 +8,13 @@
  * search.h - find a target along $(SEARCH) or $(LOCATE)
  */
 
-char *search( char *target, time_t *time, char **another_target, int file );
+#ifndef SEARCH_SW20111118_H
+#define SEARCH_SW20111118_H
+
+#include "object.h"
+#include <time.h>
+
+OBJECT * search( OBJECT * target, time_t * time, OBJECT * * another_target, int file );
+void search_done( void );
+
+#endif

Modified: branches/release/tools/build/v2/engine/subst.c
==============================================================================
--- branches/release/tools/build/v2/engine/subst.c (original)
+++ branches/release/tools/build/v2/engine/subst.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -3,62 +3,64 @@
 #include "regexp.h"
 #include "hash.h"
 
-#include "newstr.h"
+#include "object.h"
 #include "lists.h"
-#include "parse.h"
 #include "compile.h"
 #include "frames.h"
+#include "builtins.h"
 
 struct regex_entry
 {
- const char* pattern;
+ OBJECT* pattern;
     regexp* regex;
 };
 typedef struct regex_entry regex_entry;
 
 static struct hash* regex_hash;
 
-regexp* regex_compile( const char* pattern )
+regexp* regex_compile( OBJECT* pattern )
 {
- regex_entry entry, *e = &entry;
- entry.pattern = pattern;
+ int found;
+ regex_entry * e ;
 
     if ( !regex_hash )
         regex_hash = hashinit(sizeof(regex_entry), "regex");
 
- if ( hashenter( regex_hash, (HASHDATA **)&e ) )
+ e = (regex_entry *)hash_insert( regex_hash, pattern, &found );
+ if ( !found )
+ {
+ e->pattern = object_copy( pattern );
         e->regex = regcomp( (char*)pattern );
+ }
 
     return e->regex;
 }
 
-LIST*
-builtin_subst(
- PARSE *parse,
- FRAME *frame )
+LIST * builtin_subst( FRAME * frame, int flags )
 {
   LIST* result = L0;
   LIST* arg1 = lol_get( frame->args, 0 );
+ LISTITER iter = list_begin( arg1 ), end = list_end( arg1 );
 
- if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) )
+ if ( iter != end && list_next( iter ) != end && list_next( list_next( iter ) ) != end )
   {
 
- const char* source = arg1->string;
- const char* pattern = list_next(arg1)->string;
+ const char* source = object_str( list_item( iter ) );
+ OBJECT * pattern = list_item( list_next( iter ) );
       regexp* repat = regex_compile( pattern );
 
       if ( regexec( repat, (char*)source) )
       {
- LIST* subst = list_next(arg1);
+ LISTITER subst = list_next( iter );
 
- while ((subst = list_next(subst)) != L0)
+ while ( ( subst = list_next( subst ) ) != end )
           {
 # define BUFLEN 4096
               char buf[BUFLEN + 1];
- const char* in = subst->string;
+ const char* in = object_str( list_item( subst ) );
               char* out = buf;
 
- for ( in = subst->string; *in && out < buf + BUFLEN; ++in )
+ for ( ; *in && out < buf + BUFLEN; ++in )
               {
                   if ( *in == '\\' || *in == '$' )
                   {
@@ -83,7 +85,7 @@
               }
               *out = 0;
 
- result = list_new( result, newstr( buf ) );
+ result = list_push_back( result, object_new( buf ) );
 #undef BUFLEN
           }
       }
@@ -92,3 +94,20 @@
   return result;
 }
 
+
+static void free_regex( void * xregex, void * data )
+{
+ regex_entry * regex = (regex_entry *)xregex;
+ object_free( regex->pattern );
+ BJAM_FREE( regex->regex );
+}
+
+
+void regex_done()
+{
+ if ( regex_hash )
+ {
+ hashenumerate( regex_hash, free_regex, (void *)0 );
+ hashdone( regex_hash );
+ }
+}

Modified: branches/release/tools/build/v2/engine/timestamp.c
==============================================================================
--- branches/release/tools/build/v2/engine/timestamp.c (original)
+++ branches/release/tools/build/v2/engine/timestamp.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,7 +16,7 @@
 # include "filesys.h"
 # include "pathsys.h"
 # include "timestamp.h"
-# include "newstr.h"
+# include "object.h"
 # include "strings.h"
 
 /*
@@ -32,12 +32,12 @@
 typedef struct _binding BINDING;
 
 struct _binding {
- char *name;
- short flags;
+ OBJECT * name;
+ short flags;
 
 # define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
 
- short progress;
+ short progress;
 
 # define BIND_INIT 0 /* never seen */
 # define BIND_NOENTRY 1 /* timestamp requested but file never found */
@@ -45,11 +45,11 @@
 # define BIND_MISSING 3 /* file found but can't get timestamp */
 # define BIND_FOUND 4 /* file found and time stamped */
 
- time_t time; /* update time - 0 if not exist */
+ time_t time; /* update time - 0 if not exist */
 };
 
 static struct hash * bindhash = 0;
-static void time_enter( void *, char *, int, time_t );
+static void time_enter( void *, OBJECT *, int, time_t );
 
 static char * time_progress[] =
 {
@@ -65,49 +65,32 @@
  * timestamp() - return timestamp on a file, if present.
  */
 
-void timestamp( char * target, time_t * time )
+void timestamp( OBJECT * target, time_t * time )
 {
     PROFILE_ENTER( timestamp );
 
     PATHNAME f1;
     PATHNAME f2;
- BINDING binding;
- BINDING * b = &binding;
+ int found;
+ BINDING * b;
     string buf[ 1 ];
-#ifdef DOWNSHIFT_PATHS
- string path;
- char * p;
-#endif
-
-#ifdef DOWNSHIFT_PATHS
- string_copy( &path, target );
- p = path.value;
-
- do
- {
- *p = tolower( *p );
-#ifdef NT
- /* On NT, we must use backslashes or the file will not be found. */
- if ( *p == '/' )
- *p = PATH_DELIM;
-#endif
- }
- while ( *p++ );
 
- target = path.value;
-#endif /* #ifdef DOWNSHIFT_PATHS */
+ target = path_as_key( target );
+
     string_new( buf );
 
     if ( !bindhash )
         bindhash = hashinit( sizeof( BINDING ), "bindings" );
 
     /* Quick path - is it there? */
- b->name = target;
- b->time = b->flags = 0;
- b->progress = BIND_INIT;
 
- if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( target ); /* never freed */
+ b = (BINDING *)hash_insert( bindhash, target, &found );
+ if ( !found )
+ {
+ b->name = object_copy( target ); /* never freed */
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+ }
 
     if ( b->progress != BIND_INIT )
         goto afterscanning;
@@ -115,37 +98,44 @@
     b->progress = BIND_NOENTRY;
 
     /* Not found - have to scan for it. */
- path_parse( target, &f1 );
+ path_parse( object_str( target ), &f1 );
 
     /* Scan directory if not already done so. */
     {
- BINDING binding;
- BINDING * b = &binding;
+ int found;
+ BINDING * b;
+ OBJECT * name;
 
         f2 = f1;
         f2.f_grist.len = 0;
         path_parent( &f2 );
         path_build( &f2, buf, 0 );
 
- b->name = buf->value;
- b->time = b->flags = 0;
- b->progress = BIND_INIT;
+ name = object_new( buf->value );
 
- if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( buf->value ); /* never freed */
+ b = (BINDING *)hash_insert( bindhash, name, &found );
+ if ( !found )
+ {
+ b->name = object_copy( name );
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+ }
 
         if ( !( b->flags & BIND_SCANNED ) )
         {
- file_dirscan( buf->value, time_enter, bindhash );
+ file_dirscan( name, time_enter, bindhash );
             b->flags |= BIND_SCANNED;
         }
+
+ object_free( name );
     }
 
     /* Scan archive if not already done so. */
     if ( f1.f_member.len )
     {
- BINDING binding;
- BINDING * b = &binding;
+ int found;
+ BINDING * b;
+ OBJECT * name;
 
         f2 = f1;
         f2.f_grist.len = 0;
@@ -153,18 +143,23 @@
         string_truncate( buf, 0 );
         path_build( &f2, buf, 0 );
 
- b->name = buf->value;
- b->time = b->flags = 0;
- b->progress = BIND_INIT;
+ name = object_new( buf->value );
 
- if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( buf->value ); /* never freed */
+ b = (BINDING *)hash_insert( bindhash, name, &found );
+ if ( !found )
+ {
+ b->name = object_copy( name );
+ b->time = b->flags = 0;
+ b->progress = BIND_INIT;
+ }
 
         if ( !( b->flags & BIND_SCANNED ) )
         {
             file_archscan( buf->value, time_enter, bindhash );
             b->flags |= BIND_SCANNED;
         }
+
+ object_free( name );
     }
 
     afterscanning:
@@ -178,43 +173,41 @@
 
     *time = b->progress == BIND_FOUND ? b->time : 0;
         string_free( buf );
-#ifdef DOWNSHIFT_PATHS
- string_free( &path );
-#endif
+
+ object_free( target );
 
     PROFILE_EXIT( timestamp );
 }
 
 
-static void time_enter( void * closure, char * target, int found, time_t time )
+static void time_enter( void * closure, OBJECT * target, int found, time_t time )
 {
- BINDING binding;
- BINDING * b = &binding;
+ int item_found;
+ BINDING * b;
     struct hash * bindhash = (struct hash *)closure;
 
-#ifdef DOWNSHIFT_PATHS
- char path[ MAXJPATH ];
- char * p = path;
-
- do *p++ = tolower( *target );
- while ( *target++ );
+ target = path_as_key( target );
 
- target = path;
-#endif
-
- b->name = target;
- b->flags = 0;
-
- if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( target ); /* never freed */
+ b = (BINDING *)hash_insert( bindhash, target, &item_found );
+ if ( !item_found )
+ {
+ b->name = object_copy( target );
+ b->flags = 0;
+ }
 
     b->time = time;
     b->progress = found ? BIND_FOUND : BIND_SPOTTED;
 
     if ( DEBUG_BINDSCAN )
- printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] );
+ printf( "time ( %s ) : %s\n", object_str( target ), time_progress[ b->progress ] );
+
+ object_free( target );
 }
 
+static void free_timestamps ( void * xbinding, void * data )
+{
+ object_free( ((BINDING *)xbinding)->name );
+}
 
 /*
  * stamps_done() - free timestamp tables.
@@ -222,5 +215,9 @@
 
 void stamps_done()
 {
- hashdone( bindhash );
+ if ( bindhash )
+ {
+ hashenumerate( bindhash, free_timestamps, (void *)0 );
+ hashdone( bindhash );
+ }
 }

Modified: branches/release/tools/build/v2/engine/timestamp.h
==============================================================================
--- branches/release/tools/build/v2/engine/timestamp.h (original)
+++ branches/release/tools/build/v2/engine/timestamp.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,5 +8,13 @@
  * timestamp.h - get the timestamp of a file or archive member
  */
 
-void timestamp( char * target, time_t * time );
+#ifndef TIMESTAMP_H_SW_2011_11_18
+#define TIMESTAMP_H_SW_2011_11_18
+
+#include "object.h"
+#include "time.h"
+
+void timestamp( OBJECT * target, time_t * time );
 void stamps_done();
+
+#endif

Modified: branches/release/tools/build/v2/engine/variable.c
==============================================================================
--- branches/release/tools/build/v2/engine/variable.c (original)
+++ branches/release/tools/build/v2/engine/variable.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -16,12 +16,12 @@
 #include "lists.h"
 #include "parse.h"
 #include "variable.h"
-#include "expand.h"
 #include "hash.h"
 #include "filesys.h"
-#include "newstr.h"
+#include "object.h"
 #include "strings.h"
 #include "pathsys.h"
+#include "modules.h"
 #include <stdlib.h>
 #include <stdio.h>
 
@@ -49,8 +49,6 @@
  * 09/11/00 (seiwald) - defunct var_list() removed
  */
 
-static struct hash *varhash = 0;
-
 /*
  * VARIABLE - a user defined multi-value variable
  */
@@ -59,26 +57,12 @@
 
 struct _variable
 {
- char * symbol;
- LIST * value;
+ OBJECT * symbol;
+ LIST * value;
 };
 
-static VARIABLE * var_enter( char * symbol );
-static void var_dump( char * symbol, LIST * value, char * what );
-
-
-/*
- * var_hash_swap() - swap all variable settings with those passed
- *
- * Used to implement separate settings spaces for modules
- */
-
-void var_hash_swap( struct hash * * new_vars )
-{
- struct hash * old = varhash;
- varhash = *new_vars;
- *new_vars = old;
-}
+static LIST * * var_enter( struct module_t * module, OBJECT * symbol );
+static void var_dump( OBJECT * symbol, LIST * value, char * what );
 
 
 /*
@@ -94,7 +78,7 @@
  * Otherwise, split the value at blanks.
  */
 
-void var_defines( char * const * e, int preprocess )
+void var_defines( struct module_t * module, char * const * e, int preprocess )
 {
     string buf[1];
 
@@ -103,6 +87,7 @@
     for ( ; *e; ++e )
     {
         char * val;
+ OBJECT * varname;
 
 # ifdef OS_MAC
         /* On the mac (MPW), the var=val is actually var\0val */
@@ -133,7 +118,7 @@
             if ( quoted && preprocess )
             {
                 string_append_range( buf, val + 2, val + len );
- l = list_new( l, newstr( buf->value ) );
+ l = list_push_back( l, object_new( buf->value ) );
                 string_truncate( buf, 0 );
             }
             else
@@ -156,16 +141,18 @@
                 )
                 {
                     string_append_range( buf, pp, p );
- l = list_new( l, newstr( buf->value ) );
+ l = list_push_back( l, object_new( buf->value ) );
                     string_truncate( buf, 0 );
                 }
 
- l = list_new( l, newstr( pp ) );
+ l = list_push_back( l, object_new( pp ) );
             }
 
             /* Get name. */
             string_append_range( buf, *e, val );
- var_set( buf->value, l, VAR_SET );
+ varname = object_new( buf->value );
+ var_set( module, varname, l, VAR_SET );
+ object_free( varname );
             string_truncate( buf, 0 );
         }
     }
@@ -173,304 +160,7 @@
 }
 
 
-/*
- * var_string() - expand a string with variables in it
- *
- * Copies in to out; doesn't modify targets & sources.
- */
-
-int var_string( char * in, char * out, int outsize, LOL * lol )
-{
- char * out0 = out;
- char * oute = out + outsize - 1;
-
- while ( *in )
- {
- char * lastword;
- int dollar = 0;
-
- /* Copy white space. */
- while ( isspace( *in ) )
- {
- if ( out >= oute )
- return -1;
- *out++ = *in++;
- }
-
- lastword = out;
-
- /* Copy non-white space, watching for variables. */
- while ( *in && !isspace( *in ) )
- {
- if ( out >= oute )
- return -1;
-
- if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) )
- {
- ++dollar;
- *out++ = *in++;
- }
- #ifdef OPT_AT_FILES
- else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
- {
- int depth = 1;
- char * ine = in + 2;
- char * split = 0;
-
- /* Scan the content of the response file @() section. */
- while ( *ine && ( depth > 0 ) )
- {
- switch ( *ine )
- {
- case '(': ++depth; break;
- case ')': --depth; break;
- case ':':
- if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
- split = ine;
- break;
- }
- ++ine;
- }
-
- if ( !split )
- {
- /* the @() reference doesn't match the @(foo:E=bar) format.
- hence we leave it alone by copying directly to output. */
- int l = 0;
- if ( out + 2 >= oute ) return -1;
- *( out++ ) = '@';
- *( out++ ) = '(';
- l = var_string( in + 2, out, oute - out, lol );
- if ( l < 0 ) return -1;
- out += l;
- if ( out + 1 >= oute ) return -1;
- *( out++ ) = ')';
- }
- else if ( depth == 0 )
- {
- string file_name_v;
- int file_name_l = 0;
- const char * file_name_s = 0;
-
- /* Expand the temporary file name var inline. */
- #if 0
- string_copy( &file_name_v, "$(" );
- string_append_range( &file_name_v, in + 2, split );
- string_push_back( &file_name_v, ')' );
- #else
- string_new( &file_name_v );
- string_append_range( &file_name_v, in + 2, split );
- #endif
- file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol );
- string_free( &file_name_v );
- if ( file_name_l < 0 ) return -1;
- file_name_s = out;
-
- /* For stdout/stderr we will create a temp file and generate
- * a command that outputs the content as needed.
- */
- if ( ( strcmp( "STDOUT", out ) == 0 ) ||
- ( strcmp( "STDERR", out ) == 0 ) )
- {
- int err_redir = strcmp( "STDERR", out ) == 0;
- out[ 0 ] = '\0';
- file_name_s = path_tmpfile();
- file_name_l = strlen(file_name_s);
- #ifdef OS_NT
- if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
- return -1;
- sprintf( out,"type \"%s\"%s", file_name_s,
- err_redir ? " 1>&2" : "" );
- #else
- if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
- return -1;
- sprintf( out,"cat \"%s\"%s", file_name_s,
- err_redir ? " 1>&2" : "" );
- #endif
- /* We also make sure that the temp files created by this
- * get nuked eventually.
- */
- file_remove_atexit( file_name_s );
- }
-
- /* Expand the file value into the file reference. */
- var_string_to_file( split + 3, ine - split - 4, file_name_s,
- lol );
-
- /* Continue on with the expansion. */
- out += strlen( out );
- }
-
- /* And continue with the parsing just past the @() reference. */
- in = ine;
- }
- #endif
- else
- {
- *out++ = *in++;
- }
- }
-
- /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
- if ( out >= oute )
- return -1;
- /* Do not increment, intentionally. */
- *out = '\0';
-
- /* If a variable encountered, expand it and and embed the
- * space-separated members of the list in the output.
- */
- if ( dollar )
- {
- LIST * l = var_expand( L0, lastword, out, lol, 0 );
-
- out = lastword;
-
- while ( l )
- {
- int so = strlen( l->string );
-
- if ( out + so >= oute )
- return -1;
-
- strcpy( out, l->string );
- out += so;
- l = list_next( l );
- if ( l ) *out++ = ' ';
- }
-
- list_free( l );
- }
- }
-
- if ( out >= oute )
- return -1;
-
- *out++ = '\0';
-
- return out - out0;
-}
-
-
-void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )
-{
- char const * ine = in + insize;
- FILE * out_file = 0;
- int out_debug = DEBUG_EXEC ? 1 : 0;
- if ( globs.noexec )
- {
- /* out_debug = 1; */
- }
- else if ( strcmp( out, "STDOUT" ) == 0 )
- {
- out_file = stdout;
- }
- else if ( strcmp( out, "STDERR" ) == 0 )
- {
- out_file = stderr;
- }
- else
- {
- /* Handle "path to file" filenames. */
- string out_name;
- if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
- {
- string_copy( &out_name, out + 1 );
- string_truncate( &out_name, out_name.size - 1 );
- }
- else
- {
- string_copy( &out_name,out );
- }
- out_file = fopen( out_name.value, "w" );
- if ( !out_file )
- {
- printf( "failed to write output file '%s'!\n", out_name.value );
- exit( EXITBAD );
- }
- string_free( &out_name );
- }
-
- if ( out_debug ) printf( "\nfile %s\n", out );
-
- while ( *in && ( in < ine ) )
- {
- int dollar = 0;
- const char * output_0 = in;
- const char * output_1 = in;
-
- /* Copy white space. */
- while ( ( output_1 < ine ) && isspace( *output_1 ) )
- ++output_1;
-
- if ( output_0 < output_1 )
- {
- if ( out_file ) fwrite( output_0, output_1 - output_0, 1, out_file );
- if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout );
- }
- output_0 = output_1;
-
- /* Copy non-white space, watching for variables. */
- while ( ( output_1 < ine ) && *output_1 && !isspace( *output_1 ) )
- {
- if ( ( output_1[ 0 ] == '$' ) && ( output_1[ 1 ] == '(' ) )
- ++dollar;
- ++output_1;
- }
-
- /* If a variable encountered, expand it and embed the space-separated
- * members of the list in the output.
- */
- if ( dollar )
- {
- LIST * l = var_expand( L0, (char *)output_0, (char *)output_1, lol, 0 );
-
- while ( l )
- {
- if ( out_file ) fputs( l->string, out_file );
- if ( out_debug ) puts( l->string );
- l = list_next( l );
- if ( l )
- {
- if ( out_file ) fputc( ' ', out_file );
- if ( out_debug ) fputc( ' ', stdout );
- }
- }
-
- list_free( l );
- }
- else if ( output_0 < output_1 )
- {
- if ( out_file )
- {
- const char * output_n = output_0;
- while ( output_n < output_1 )
- {
- output_n += fwrite( output_n, 1, output_1-output_n, out_file );
- }
- }
- if ( out_debug )
- {
- const char * output_n = output_0;
- while ( output_n < output_1 )
- {
- output_n += fwrite( output_n, 1, output_1-output_n, stdout );
- }
- }
- }
-
- in = output_1;
- }
-
- if ( out_file && ( out_file != stdout ) && ( out_file != stderr ) )
- {
- fflush( out_file );
- fclose( out_file );
- }
-
- if ( out_debug ) fputc( '\n', stdout );
-}
-
+static LIST * saved_var = L0;
 
 /*
  * var_get() - get value of a user defined symbol.
@@ -478,40 +168,49 @@
  * Returns NULL if symbol unset.
  */
 
-LIST * var_get( char * symbol )
+LIST * var_get( struct module_t * module, OBJECT * symbol )
 {
- LIST * result = 0;
+ LIST * result = L0;
 #ifdef OPT_AT_FILES
     /* Some "fixed" variables... */
- if ( strcmp( "TMPDIR", symbol ) == 0 )
+ if ( object_equal( symbol, constant_TMPDIR ) )
     {
- result = list_new( L0, newstr( (char *)path_tmpdir() ) );
+ list_free( saved_var );
+ result = saved_var = list_new( object_new( path_tmpdir() ) );
     }
- else if ( strcmp( "TMPNAME", symbol ) == 0 )
+ else if ( object_equal( symbol, constant_TMPNAME ) )
     {
- result = list_new( L0, newstr( (char *)path_tmpnam() ) );
+ list_free( saved_var );
+ result = saved_var = list_new( path_tmpnam() );
     }
- else if ( strcmp( "TMPFILE", symbol ) == 0 )
+ else if ( object_equal( symbol, constant_TMPFILE ) )
     {
- result = list_new( L0, newstr( (char *)path_tmpfile() ) );
+ list_free( saved_var );
+ result = saved_var = list_new( path_tmpfile() );
     }
- else if ( strcmp( "STDOUT", symbol ) == 0 )
+ else if ( object_equal( symbol, constant_STDOUT ) )
     {
- result = list_new( L0, newstr( "STDOUT" ) );
+ list_free( saved_var );
+ result = saved_var = list_new( object_copy( constant_STDOUT ) );
     }
- else if ( strcmp( "STDERR", symbol ) == 0 )
+ else if ( object_equal( symbol, constant_STDERR ) )
     {
- result = list_new( L0, newstr( "STDERR" ) );
+ list_free( saved_var );
+ result = saved_var = list_new( object_copy( constant_STDERR ) );
     }
     else
 #endif
     {
- VARIABLE var;
- VARIABLE * v = &var;
+ VARIABLE * v;
+ int n;
 
- v->symbol = symbol;
-
- if ( varhash && hashcheck( varhash, (HASHDATA * *)&v ) )
+ if ( ( n = module_get_fixed_var( module, symbol ) ) != -1 )
+ {
+ if ( DEBUG_VARGET )
+ var_dump( symbol, module->fixed_variables[ n ], "get" );
+ result = module->fixed_variables[ n ];
+ }
+ else if ( module->variables && ( v = (VARIABLE *)hash_find( module->variables, symbol ) ) )
         {
             if ( DEBUG_VARGET )
                 var_dump( v->symbol, v->value, "get" );
@@ -522,6 +221,20 @@
 }
 
 
+LIST * var_get_and_clear_raw( module_t * module, OBJECT * symbol )
+{
+ LIST * result = L0;
+ VARIABLE * v;
+
+ if ( module->variables && ( v = (VARIABLE *)hash_find( module->variables, symbol ) ) )
+ {
+ result = v->value;
+ v->value = L0;
+ }
+
+ return result;
+}
+
 /*
  * var_set() - set a variable in Jam's user defined symbol table.
  *
@@ -532,9 +245,9 @@
  * Copies symbol. Takes ownership of value.
  */
 
-void var_set( char * symbol, LIST * value, int flag )
+void var_set( struct module_t * module, OBJECT * symbol, LIST * value, int flag )
 {
- VARIABLE * v = var_enter( symbol );
+ LIST * * v = var_enter( module, symbol );
 
     if ( DEBUG_VARSET )
         var_dump( symbol, value, "set" );
@@ -543,19 +256,19 @@
     {
     case VAR_SET:
         /* Replace value */
- list_free( v->value );
- v->value = value;
+ list_free( *v );
+ *v = value;
         break;
 
     case VAR_APPEND:
         /* Append value */
- v->value = list_append( v->value, value );
+ *v = list_append( *v, value );
         break;
 
     case VAR_DEFAULT:
         /* Set only if unset */
- if ( !v->value )
- v->value = value;
+ if ( list_empty( *v ) )
+ *v = value;
         else
             list_free( value );
         break;
@@ -567,13 +280,13 @@
  * var_swap() - swap a variable's value with the given one.
  */
 
-LIST * var_swap( char * symbol, LIST * value )
+LIST * var_swap( struct module_t * module, OBJECT * symbol, LIST * value )
 {
- VARIABLE * v = var_enter( symbol );
- LIST * oldvalue = v->value;
+ LIST * * v = var_enter( module, symbol );
+ LIST * oldvalue = *v;
     if ( DEBUG_VARSET )
         var_dump( symbol, value, "set" );
- v->value = value;
+ *v = value;
     return oldvalue;
 }
 
@@ -582,21 +295,28 @@
  * var_enter() - make new var symbol table entry, returning var ptr.
  */
 
-static VARIABLE * var_enter( char * symbol )
+static LIST * * var_enter( struct module_t * module, OBJECT * symbol )
 {
- VARIABLE var;
- VARIABLE * v = &var;
+ int found;
+ VARIABLE * v;
+ int n;
 
- if ( !varhash )
- varhash = hashinit( sizeof( VARIABLE ), "variables" );
+ if ( ( n = module_get_fixed_var( module, symbol ) ) != -1 )
+ {
+ return &module->fixed_variables[ n ];
+ }
 
- v->symbol = symbol;
- v->value = 0;
+ if ( !module->variables )
+ module->variables = hashinit( sizeof( VARIABLE ), "variables" );
 
- if ( hashenter( varhash, (HASHDATA * *)&v ) )
- v->symbol = newstr( symbol ); /* never freed */
+ v = (VARIABLE *)hash_insert( module->variables, symbol, &found );
+ if ( !found )
+ {
+ v->symbol = object_copy( symbol );
+ v->value = L0;
+ }
 
- return v;
+ return &v->value;
 }
 
 
@@ -604,9 +324,9 @@
  * var_dump() - dump a variable to stdout.
  */
 
-static void var_dump( char * symbol, LIST * value, char * what )
+static void var_dump( OBJECT * symbol, LIST * value, char * what )
 {
- printf( "%s %s = ", what, symbol );
+ printf( "%s %s = ", what, object_str( symbol ) );
     list_print( value );
     printf( "\n" );
 }
@@ -619,13 +339,15 @@
 static void delete_var_( void * xvar, void * data )
 {
     VARIABLE * v = (VARIABLE *)xvar;
- freestr( v->symbol );
+ object_free( v->symbol );
     list_free( v-> value );
 }
 
 
-void var_done()
+void var_done( struct module_t * module )
 {
- hashenumerate( varhash, delete_var_, (void *)0 );
- hashdone( varhash );
+ list_free( saved_var );
+ saved_var = L0;
+ hashenumerate( module->variables, delete_var_, (void *)0 );
+ hash_free( module->variables );
 }

Modified: branches/release/tools/build/v2/engine/variable.h
==============================================================================
--- branches/release/tools/build/v2/engine/variable.h (original)
+++ branches/release/tools/build/v2/engine/variable.h 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,22 +8,16 @@
  * variable.h - handle jam multi-element variables
  */
 
-struct hash;
+#ifndef VARIABLE_SW20111119_H
+#define VARIABLE_SW20111119_H
 
-void var_defines( char* const *e, int preprocess );
-int var_string( char *in, char *out, int outsize, LOL *lol );
-LIST * var_get( char *symbol );
-void var_set( char *symbol, LIST *value, int flag );
-LIST * var_swap( char *symbol, LIST *value );
-void var_done();
-void var_hash_swap( struct hash** );
-
-/** Expands the "in" expression directly into the "out" file.
- The file can be one of: a path, STDOUT, or STDERR to send
- the output to a file overwriting previous content, to
- the console, or to the error output respectively.
-*/
-void var_string_to_file( const char * in, int insize, const char * out, LOL * lol );
+struct module_t;
+
+void var_defines( struct module_t * module, char * const * e, int preprocess );
+LIST * var_get( struct module_t * module, OBJECT * symbol );
+void var_set( struct module_t * module, OBJECT * symbol, LIST * value, int flag );
+LIST * var_swap( struct module_t * module, OBJECT * symbol, LIST * value );
+void var_done( struct module_t * module );
 
 /*
  * Defines for var_set().
@@ -33,3 +27,4 @@
 # define VAR_APPEND 1 /* append to previous value */
 # define VAR_DEFAULT 2 /* set only if no previous value */
 
+#endif

Modified: branches/release/tools/build/v2/engine/w32_getreg.c
==============================================================================
--- branches/release/tools/build/v2/engine/w32_getreg.c (original)
+++ branches/release/tools/build/v2/engine/w32_getreg.c 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,7 +9,7 @@
 # if defined( OS_NT ) || defined( OS_CYGWIN )
 
 # include "lists.h"
-# include "newstr.h"
+# include "object.h"
 # include "parse.h"
 # include "frames.h"
 # include "strings.h"
@@ -57,12 +57,9 @@
     return p->value;
 }
 
-LIST*
-builtin_system_registry(
- PARSE *parse,
- FRAME *frame )
+LIST * builtin_system_registry( FRAME * frame, int flags )
 {
- char const* path = lol_get(frame->args, 0)->string;
+ char const* path = object_str( list_front( lol_get(frame->args, 0) ) );
     LIST* result = L0;
     HKEY key = get_key(&path);
 
@@ -74,10 +71,10 @@
         DWORD type;
         BYTE data[MAX_REGISTRY_DATA_LENGTH];
         DWORD len = sizeof(data);
- LIST const* const field = lol_get(frame->args, 1);
+ LIST * const field = lol_get(frame->args, 1);
 
         if ( ERROR_SUCCESS ==
- RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
+ RegQueryValueEx(key, field ? object_str( list_front( field ) ) : 0, 0, &type, data, &len) )
         {
             switch (type)
             {
@@ -97,7 +94,7 @@
 
                      expanded->size = len - 1;
 
- result = list_new( result, newstr(expanded->value) );
+ result = list_push_back( result, object_new(expanded->value) );
                      string_free( expanded );
                  }
                  break;
@@ -107,7 +104,7 @@
                      char* s;
 
                      for (s = (char*)data; *s; s += strlen(s) + 1)
- result = list_new( result, newstr(s) );
+ result = list_push_back( result, object_new(s) );
 
                  }
                  break;
@@ -116,12 +113,12 @@
                  {
                      char buf[100];
                      sprintf( buf, "%u", *(PDWORD)data );
- result = list_new( result, newstr(buf) );
+ result = list_push_back( result, object_new(buf) );
                  }
                  break;
 
              case REG_SZ:
- result = list_new( result, newstr((char*)data) );
+ result = list_push_back( result, object_new( (const char *)data ) );
                  break;
             }
         }
@@ -151,7 +148,7 @@
         )
         {
             name[name_size] = 0;
- result = list_append(result, list_new(0, newstr(name)));
+ result = list_append(result, list_new(object_new(name)));
         }
 
         RegCloseKey(key);
@@ -178,7 +175,7 @@
         )
         {
             name[name_size] = 0;
- result = list_append(result, list_new(0, newstr(name)));
+ result = list_append(result, list_new(object_new(name)));
         }
 
         RegCloseKey(key);
@@ -187,13 +184,10 @@
     return result;
 }
 
-LIST*
-builtin_system_registry_names(
- PARSE *parse,
- FRAME *frame )
+LIST * builtin_system_registry_names( FRAME * frame, int flags )
 {
- char const* path = lol_get(frame->args, 0)->string;
- char const* result_type = lol_get(frame->args, 1)->string;
+ char const* path = object_str( list_front( lol_get(frame->args, 0) ) );
+ char const* result_type = object_str( list_front( lol_get(frame->args, 1) ) );
 
     HKEY key = get_key(&path);
 

Modified: branches/release/tools/build/v2/test/BoostBuild.py
==============================================================================
--- branches/release/tools/build/v2/test/BoostBuild.py (original)
+++ branches/release/tools/build/v2/test/BoostBuild.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -76,19 +76,30 @@
 
 # Detect the host OS.
 windows = False
-if os.environ.get('OS', '').lower().startswith('windows') or \
- os.__dict__.has_key('uname') and \
- os.uname()[0].lower().startswith('cygwin'):
+cygwin = False
+if os.environ.get('OS', '').lower().startswith('windows'):
     windows = True
 
+if os.__dict__.has_key('uname') and \
+ os.uname()[0].lower().startswith('cygwin'):
+ windows = True
+ cygwin = True
 
 suffixes = {}
 
 
+# Configuration stating whether Boost Build is expected to automatically prepend
+# prefixes to built library targets.
+lib_prefix = "lib"
+dll_prefix = "lib"
+
 # Prepare the map of suffixes
 def prepare_suffix_map(toolset):
     global windows
     global suffixes
+ global cygwin
+ global lib_prefix
+ global dll_prefix
     suffixes = {'.exe': '', '.dll': '.so', '.lib': '.a', '.obj': '.o'}
     suffixes['.implib'] = '.no_implib_files_on_this_platform'
     if windows:
@@ -96,9 +107,19 @@
         if toolset in ["gcc"]:
             suffixes['.lib'] = '.a' # static libs have '.a' suffix with mingw...
             suffixes['.obj'] = '.o'
- suffixes['.implib'] = '.lib'
+ if cygwin:
+ suffixes['.implib'] = '.lib.a'
+ else:
+ suffixes['.implib'] = '.lib'
     if os.__dict__.has_key('uname') and (os.uname()[0] == 'Darwin'):
         suffixes['.dll'] = '.dylib'
+
+ lib_prefix = "lib"
+ dll_prefix = "lib"
+ if cygwin:
+ dll_prefix = "cyg"
+ elif windows and not toolset in ["gcc"]:
+ dll_prefix = None
 
 
 def re_remove(sequence, regex):
@@ -118,13 +139,6 @@
         sequence.remove(r)
 
 
-# Configuration stating whether Boost Build is expected to automatically prepend
-# prefixes to built library targets.
-lib_prefix = True
-dll_prefix = True
-if windows:
- dll_prefix = False
-
 
 #
 # FIXME: this is copy-pasted from TestSCons.py
@@ -192,7 +206,7 @@
     def __init__(self, arguments="", executable="bjam",
         match=TestCmd.match_exact, boost_build_path=None,
         translate_suffixes=True, pass_toolset=True, use_test_config=True,
- ignore_toolset_requirements=True, workdir="", **keywords):
+ ignore_toolset_requirements=True, workdir="", pass_d0=True, **keywords):
 
         self.original_workdir = os.getcwd()
         if workdir != '' and not os.path.isabs(workdir):
@@ -259,6 +273,8 @@
                 sys.exit(1)
 
         verbosity = ['-d0', '--quiet']
+ if not pass_d0:
+ verbosity = []
         if '--verbose' in sys.argv:
             keywords['verbose'] = True
             verbosity = ['-d+2']
@@ -365,9 +381,16 @@
             os.utime(self.native_file_name(name), None)
 
     def rm(self, names):
- self.wait_for_time_change_since_last_build()
         if not type(names) == types.ListType:
             names = [names]
+
+ if names == ["."]:
+ # If we're deleting the entire workspace, there's no
+ # need to wait for a clock tick.
+ self.last_build_time_start = 0
+ self.last_build_time_finish = 0
+
+ self.wait_for_time_change_since_last_build()
 
         # Avoid attempts to remove the current directory.
         os.chdir(self.original_workdir)
@@ -495,6 +518,10 @@
 
         self.tree = tree.build_tree(self.workdir)
         self.difference = tree.trees_difference(self.previous_tree, self.tree)
+ if self.difference.empty():
+ # If nothing was changed, there's no need to wait
+ self.last_build_time_start = 0
+ self.last_build_time_finish = 0
         self.difference.ignore_directories()
         self.unexpected_difference = copy.deepcopy(self.difference)
 
@@ -795,6 +822,7 @@
 
     def adjust_lib_name(self, name):
         global lib_prefix
+ global dll_prefix
         result = name
 
         pos = string.rfind(name, ".")
@@ -803,12 +831,12 @@
             if suffix == ".lib":
                 (head, tail) = os.path.split(name)
                 if lib_prefix:
- tail = "lib" + tail
+ tail = lib_prefix + tail
                     result = os.path.join(head, tail)
             elif suffix == ".dll":
                 (head, tail) = os.path.split(name)
                 if dll_prefix:
- tail = "lib" + tail
+ tail = dll_prefix + tail
                     result = os.path.join(head, tail)
         # If we want to use this name in a Jamfile, we better convert \ to /, as
         # otherwise we would have to quote \.

Deleted: branches/release/tools/build/v2/test/Jamrules
==============================================================================
--- branches/release/tools/build/v2/test/Jamrules 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,4 +0,0 @@
-# This simple Jamrules file is used for the Boost.Build test project.
-
-# The testing framework itself gets no boost-Jambase
-BOOST_JAMBASE = empty.jam ;

Modified: branches/release/tools/build/v2/test/absolute_sources.py
==============================================================================
--- branches/release/tools/build/v2/test/absolute_sources.py (original)
+++ branches/release/tools/build/v2/test/absolute_sources.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -26,6 +26,7 @@
 
 t.run_build_system()
 t.expect_addition("bin/$toolset/debug/hello.exe")
+t.rm(".")
 
 # Test a contrived case. There, absolute name is used in a standalone project
 # (not Jamfile). Moreover, the target with an absolute name is returned by

Deleted: branches/release/tools/build/v2/test/assert-equal.jam
==============================================================================
--- branches/release/tools/build/v2/test/assert-equal.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,33 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Evaluates [ rulename arg1... : arg2... : ... : argN... ] and compares the
-# result to expected-results. If there is a mismatch, prints an error message
-# and exits.
-rule assert-equal ( expected-results *
- : rulename a1 * : a2 * : a3 * : a4 * : a5 * : a6 * : a7 * : a8 * : a9 * )
-{
-
- local results = [ $(rulename) $(a1) : $(a2) : $(a3)
- : $(a4) : $(a5) : $(a6) : $(a7) : $(a8) ] ;
-
- if $(results) != $(expected-results)
- {
- EXIT ******ASSERTION FAILURE******* "
- [ $(rulename) " $(a1)
- ": "$(a2[1]) $(a2[2-])
- ": "$(a3[1]) $(a3[2-])
- ": "$(a4[1]) $(a4[2-])
- ": "$(a5[1]) $(a5[2-])
- ": "$(a6[1]) $(a6[2-])
- ": "$(a7[1]) $(a7[2-])
- ": "$(a8[1]) $(a8[2-]) "]
-expected:
- (" $(expected-results) ")
-result was:
- (" $(results) ")"
- ;
-
- }
-}

Deleted: branches/release/tools/build/v2/test/check-arguments.jam
==============================================================================
--- branches/release/tools/build/v2/test/check-arguments.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,71 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-#
-# Jam code for testing the named-argument patch.
-#
-
-include recursive.jam ;
-
-# Prefixes for all of the jam code we're going to test
-local ECHO_ARGS = "include echo_args.jam ; echo_args "
- ;
-
-local ECHO_VARARGS = "include echo_args.jam ; echo_varargs "
- ;
-
-# Check that it will find missing arguments
-Jam-fail $(ECHO_ARGS)";"
- : "missing argument a"
- ;
-
-# Check that it will find if too many arguments are passed
-Jam-fail $(ECHO_ARGS)"1 2 : 3 : 4 : 5 ;"
- : "extra argument 5"
- ;
-
-# Check that it will find when an argument has too many elements
-Jam-fail $(ECHO_ARGS)"a b c1 c2 : d ;"
- : "extra argument c2"
- ;
-
-# Check modifier '?'
-Jam $(ECHO_ARGS)"1 2 3 : 4 ;"
- : "a= 1 b= 2 c= 3 : d= 4 : e=" ;
-Jam $(ECHO_ARGS)"1 2 : 3 ;"
- : "a= 1 b= 2 c= : d= 3 : e=" ;
-Jam $(ECHO_ARGS)"1 : 2 ;"
- : "a= 1 b= c= : d= 2 : e=" ;
-
-# Check modifier '+'
-Jam-fail $(ECHO_ARGS)"1 ;"
- : "missing argument d" ;
-Jam $(ECHO_ARGS)"1 : 2 3 ;"
- : "a= 1 b= c= : d= 2 3 : e=" ;
-Jam $(ECHO_ARGS)"1 : 2 3 4 ;"
- : "a= 1 b= c= : d= 2 3 4 : e=" ;
-
-# Check modifier '*'
-Jam $(ECHO_ARGS)"1 : 2 : 3 ;"
- : "a= 1 b= c= : d= 2 : e= 3" ;
-Jam $(ECHO_ARGS)"1 : 2 : 3 4 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4" ;
-Jam $(ECHO_ARGS)"1 : 2 : 3 4 5 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
-
-#
-# Check varargs
-#
-Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5" ;
-Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6" ;
-Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7" ;
-Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8" ;
-Jam $(ECHO_VARARGS)"1 : 2 : 3 4 5 : 6 7 : 8 : 9 ;"
- : "a= 1 b= c= : d= 2 : e= 3 4 5 : rest= 6 7 : 8 : 9" ;
-
-

Deleted: branches/release/tools/build/v2/test/check-bindrule.jam
==============================================================================
--- branches/release/tools/build/v2/test/check-bindrule.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,29 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# This rule establishes a dependency, with no special build actions
-rule do-nothing ( target : source )
-{
- DEPENDS $(target) : $(source) ;
-}
-actions quietly do-nothing
-{
-}
-
-# Make a non-file target which depends on a file that exists
-NOTFILE fake-target ;
-SEARCH on file-to-bind = subdir1 ;
-
-do-nothing fake-target
- : file-to-bind ;
-
-# Set jam up to call our bind-rule
-BINDRULE = bind-rule ;
-
-rule bind-rule ( target : path )
-{
- ECHO found: $(target) at $(path) ;
-}
-
-DEPENDS all : fake-target ;

Deleted: branches/release/tools/build/v2/test/check-jam-patches.jam
==============================================================================
--- branches/release/tools/build/v2/test/check-jam-patches.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,293 +0,0 @@
-# Copyright 2001, 2002 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Get the recursive Jam invocation code
-include recursive.jam ;
-include assert-equal.jam ;
-
-Jam "include check-bindrule.jam ;"
- : "found: file-to-bind at subdir1$(SLASH)file-to-bind"
- ;
-
-include check-arguments.jam ;
-
-if $(NT)
-{
- # if this one fails, you don't have the line length patch
- Jam "include test_nt_line_length.jam ;" ;
-}
-
-# a little utility for assertions
-rule identity ( list * )
-{
- return $(list) ;
-}
-
-#
-# test rule indirection
-#
-rule select ( n list * )
-{
- return $(list[$(n)]) ;
-}
-
-rule indirect1 ( rule + : args * )
-{
- return [ $(rule) $(args) ] ;
-}
-
-assert-equal a : indirect1 select 1 : a b c d e ;
-assert-equal b : indirect1 select 2 : a b c d e ;
-
-x = reset ;
-rule reset-x ( new-value )
-{
- x = $(new-value) ;
-}
-$(x)-x bar ; # invokes reset-x...
-assert-equal bar : identity $(x) ; # which changes x
-
-# Check that unmatched subst returns an empty list
-assert-equal # nothing
- : SUBST "abc" "d+" x ;
-
-# Check that a matched subst works
-assert-equal x
- : SUBST "ddd" "d+" x ;
-
-# Check that we can get multiple substitutions from a single invocation
-assert-equal x y x-y
- : SUBST "x/y/z" "([^/]*)/([^/]*).*" "\\1" $2 "\\1-\\2" ;
-
-#
-# test local foreach modification
-#
-{
- local x = 0 ;
- local entered = ;
- for local x in a b c # x declared local to for loop.
- {
- entered = 1 ;
- if ! ( $(x) in a b c )
- {
- EXIT "local foreach: expected one of a, b, c; got" $(x) ;
- }
- }
-
- if $(x) != 0 # if x was modified, it failed to be a local variable
- {
- EXIT "local foreach failed" ;
- }
-}
-
-#
-# test while loops
-#
-{
- local x = a b c ;
- local y = $(x) ;
- local z = ;
-
- while $(y)
- {
- z += $(y[1]) ;
- y = $(y[2-]) ;
- }
-
- if $(z) != $(x)
- {
- EXIT "while loops failed" ;
- }
-}
-
-#
-# test negative list indices and slices
-#
-{
- local x = a b c d e ;
-
- rule assert-index ( index : list * )
- {
- if $(x[$(index)]) != $(list)
- {
- ECHO with x= $(x) ;
- ECHO x[$(index)] == $(x[$(index)]) ;
- EXIT expected $(list) ;
- }
- }
-
- assert-index 1 : a ;
- assert-index 3 : c ;
- assert-index 1-2 : a b ;
- assert-index -1 : e ;
- assert-index -2 : d ;
- assert-index 2--2 : b c d ;
- assert-index -3--2 : c d ;
- assert-index 1--2 : a b c d ;
- assert-index 1--2 : a b c d ;
- assert-index 1--10 : ;
- x = a ;
- assert-index 1--2 : ;
- assert-index 1--2 : ;
-}
-
-#
-# test module primitives
-#
-{
- local x = a b c d e f g h i j ;
- local y = $(x[3-]) ;
-
- rule shift1 ( dummy ) { }
-
- rule my_module.not_really ( ) { return something ; }
-
- # import the identity rule into my_module as "id"
- IMPORT : identity : my_module : id ;
- module my_module
- {
- # assert-equal operates in its own module, so call id in here and use
- # identity later.
- local f = [ id x y z ] ;
- assert-equal x y z : identity $(f) ;
-
- w = ;
- y = ;
- x2 = 1 2 3 ;
- x3 = $(x2) ;
- z = $(x2) ;
-
- x3 = ; # should reset x3
-
- # drops one element from the head of x
- # moves the first element of z from the head of z to the head of y
- rule shift1 ( )
- {
- x = $(x[2-]) ;
- y = $(z[1]) $(y) ;
- z = $(z[2-]) ;
- }
-
- rule shift2 ( )
- {
- shift1 ;
- }
-
- shift1 ;
- shift2 ;
-
- rule get ( symbol )
- {
- return $($(symbol)) ;
- }
- local rule not_really ( ) { return nothing ; }
- }
-
- local expected = shift1 shift2 get ;
- if ! ( $(expected) in [ RULENAMES my_module ] )
- || ! ( [ RULENAMES my_module ] in $(expected) )
- {
- EXIT "[ RULENAMES my_module ] =" [ RULENAMES my_module ] "!=" shift1 shift2 get ;
- }
-
-
- # show that not_really was actually a local definition
- assert-equal something : my_module.not_really ;
-
- if not_really in [ RULENAMES my_module ]
- {
- EXIT unexpectedly found local rule "not_really" in "my_module" ;
- }
- EXPORT my_module : not_really ;
-
- if ! ( not_really in [ RULENAMES my_module ] )
- {
- EXIT unexpectedly failed to find exported rule "not_really" in "my_module" ;
- }
-
- # show that my_module doesn't have access to our variables
- my_module.shift1 ;
- assert-equal $(x[3-]) : identity $(y) ;
-
- # check module locals
- assert-equal : my_module.get w ;
- assert-equal 3 2 1 : my_module.get y ;
- assert-equal 1 2 3 : my_module.get x2 ;
- assert-equal : my_module.get x3 ;
- assert-equal : my_module.get z ;
-
- my_module.shift2 ;
- x = $(x[3-]) ;
- assert-equal $(x) : identity $(y) ;
-
- # Prove that the module's rule is not exposed to the world at large without
- # qualification
- shift1 nothing ;
- assert-equal $(x) : identity $(y) ;
-
- # import my_module.shift1 into the global module as "shifty", and
- # my_module.shift2 into the global module as "shift2".
- IMPORT my_module : shift1 shift2 : : shifty shift2 ;
-
- shifty ;
- assert-equal $(x) : identity $(y) ;
-
- shift2 ;
- assert-equal $(x) : identity $(y) ;
-
- # Now do the same with localization
- IMPORT my_module : shift1 : : shifty : LOCALIZE ;
-
- shifty ;
- y = $(y[3-]) ;
- assert-equal $(x) : identity $(y) ;
-
- # import everything from my_module into the global module using
- # the same names.
- IMPORT my_module : [ RULENAMES my_module ] : : [ RULENAMES my_module ] : LOCALIZE ;
-
- shift1 ;
- y = $(y[2-]) ;
- assert-equal $(x) : identity $(y) ;
-
- shift2 ;
- y = $(y[2-]) ;
- assert-equal $(x) : identity $(y) ;
-}
-
-#
-# test CALLER_MODULE and backtrace
-#
-{
- rule backtrace ( )
- {
- local bt = [ BACKTRACE ] ;
- bt = $(bt[5-]) ;
- while $(bt)
- {
- ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) ;
- bt = $(bt[5-]) ;
- }
- }
- module module1
- {
- rule f ( )
- {
- local m = [ CALLER_MODULE ] ;
- assert-equal : identity $(m) ;
- module2.f ;
- }
-
- }
- module module2
- {
- rule f ( )
- {
- local m = [ CALLER_MODULE ] ;
- assert-equal module1 : identity $(m) ;
- backtrace ;
- }
- }
- module1.f ;
-}

Deleted: branches/release/tools/build/v2/test/check-test-tools.jam
==============================================================================
--- branches/release/tools/build/v2/test/check-test-tools.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,26 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-include recursive.jam ;
-include assert-equal.jam ;
-
-#####################################
-# Test the testing tools right here #
-#####################################
-
-# This command always exits with a failure.
-Jam-fail "EXIT error ;" ;
-
-# This should fail to fail
-Jam-fail
- "include recursive.jam ; Jam-fail \"# this innocuous Jamfile should fail to fail\" ;"
- ;
-
-# the ECHO rule always has an empty result.
-Jam-fail "include assert-equal.jam ; assert-equal fubar : ECHO checking that assertions fail ;"
- : "ASSERTION FAILURE"
- ;
-
-local NOTHING = ;
-assert-equal $(NOTHING) : ECHO checking that assertions succeed ;

Modified: branches/release/tools/build/v2/test/conditionals_multiple.py
==============================================================================
--- branches/release/tools/build/v2/test/conditionals_multiple.py (original)
+++ branches/release/tools/build/v2/test/conditionals_multiple.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -21,7 +21,7 @@
     """Basic tests for properties conditioned on multiple other properties.
     """
 
- t = BoostBuild.Tester("--ignore-regular-config toolset=testToolset",
+ t = BoostBuild.Tester("--user-config= --ignore-site-config toolset=testToolset",
         pass_toolset=False, use_test_config=False)
 
     t.write("testToolset.jam", """
@@ -30,6 +30,13 @@
 rule init ( ) { }
 """)
 
+ t.write("testToolset.py", """
+from b2.build import feature
+feature.extend('toolset', ["testToolset"])
+def init ( ):
+ pass
+""")
+
     t.write("jamroot.jam", """
 import feature ;
 import notfile ;
@@ -126,7 +133,7 @@
 
     toolset = "testToolset" ;
 
- t = BoostBuild.Tester("--ignore-regular-config", pass_toolset=False, use_test_config=False)
+ t = BoostBuild.Tester("--user-config= --ignore-site-config", pass_toolset=False, use_test_config=False)
 
     t.write( toolset + ".jam", """
 import feature ;
@@ -135,6 +142,14 @@
 rule init ( version ? ) { }
 """ % {"toolset": toolset})
 
+ t.write( "testToolset.py", """
+from b2.build import feature
+feature.extend('toolset', ["testToolset"])
+feature.subfeature('toolset',"testToolset","version",['0','1'])
+def init ( version ):
+ pass
+ """)
+
     t.write("jamroot.jam", """
 import feature ;
 import notfile ;

Modified: branches/release/tools/build/v2/test/configuration.py
==============================================================================
--- branches/release/tools/build/v2/test/configuration.py (original)
+++ branches/release/tools/build/v2/test/configuration.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -47,6 +47,14 @@
 feature.extend toolset : %s ;
 rule init ( ) { }
 """ % toolsetName )
+
+ # Python version of same dummy toolset.
+ t.write(toolsetName + ".py", """
+from b2.build import feature
+feature.extend('toolset', ['%s'])
+def init(): pass
+""" % toolsetName )
+
     t.write("jamroot.jam", "using %s ;" % toolsetName)
 
     t.run_build_system()

Modified: branches/release/tools/build/v2/test/core-language/test.jam
==============================================================================
--- /trunk/tools/build/v2/test/core-language/test.jam (original)
+++ branches/release/tools/build/v2/test/core-language/test.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -63,6 +63,7 @@
 local p0 = name ;
 local p1 = dir/name ;
 local p2 = dir/sub/name ;
+local j1 = , - ;
 
 check-equal var-product : $(v1)$(v2) : 14 15 16 24 25 26 34 35 36 ;
 
@@ -80,6 +81,16 @@
 check-equal var-member : $(v6:M) : (member.txt) ;
 check-equal var-multi : $(v6:$(select1)) : <GRIST> path generic/path.txt ;
 
+check-equal var-join-0 : $(:J=,) : ;
+check-equal var-join-1 : $(p0:J=,) : name ;
+check-equal var-join-3 : $(v1:J=,) : 1,2,3 ;
+check-equal var-set-grist-join : $(v1:G=grist:J=,) : <grist>1,<grist>2,<grist>3 ;
+# behavior change. In the past, a J= modifier would
+# cause only the last element of the other modifiers
+# to take effect.
+check-equal var-set-grist-multi-join : $(v1:G=$(g):J=,) : <g1>1,<g1>2,<g1>3 <g2>1,<g2>2,<g2>3 ;
+check-equal var-set-grist-multi-join-multi : $(v1:G=$(g):J=$(j1)) : <g1>1,<g1>2,<g1>3 <g1>1-<g1>2-<g1>3 <g2>1,<g2>2,<g2>3 <g2>1-<g2>2-<g2>3 ;
+
 check-equal var-D=-0 : name : $(p0:D=) ;
 check-equal var-D=-1 : name : $(p1:D=) ;
 check-equal var-D=-2 : name : $(p2:D=) ;
@@ -246,7 +257,7 @@
 
 local value = [ mark-order r1 : v1 v2 ] [ mark-order r2 : v3 v4 ] ;
 check-equal append : $(value) : v1 v2 v3 v4 ;
-check-order append-order : r2 r1 ;
+check-order append-order : r1 r2 ;
 
 }
 
@@ -348,6 +359,61 @@
 
 check-order if-else-false : r2 ;
 
+rule test-rule
+{
+ if true
+ {
+ return result ;
+ }
+}
+
+check-equal if-true-result : [ test-rule ] : result ;
+
+rule test-rule
+{
+ local idx = 1 2 ;
+ local values = true ;
+ while $(idx)
+ {
+ local v = $(values[$(idx[1])]) ;
+ idx = $(idx[2-]) ;
+ if $(v)
+ {
+ return result ;
+ }
+ }
+}
+
+check-equal if-false-result : [ test-rule ] : ;
+
+rule test-rule
+{
+ if true
+ {
+ return r1 ;
+ }
+ else
+ {
+ return r2 ;
+ }
+}
+
+check-equal if-else-true-result : [ test-rule ] : r1 ;
+
+rule test-rule
+{
+ if $(false)
+ {
+ return r1 ;
+ }
+ else
+ {
+ return r2 ;
+ }
+}
+
+check-equal if-else-false-result : [ test-rule ] : r2 ;
+
 }
 
 # Check the evaluation of conditions
@@ -1100,6 +1166,23 @@
 
 check-equal while-result : [ test-rule ] : x ;
 
+rule test-rule
+{
+ local value = 1 2 ;
+ while $(value)
+ {
+ value = $(value[2-]) ;
+ local inner = $(value) ;
+ while $(inner)
+ {
+ inner = $(inner[2-]) ;
+ return x ;
+ }
+ }
+}
+
+check-equal while-result-2 : [ test-rule ] : ;
+
 }
 
 #
@@ -1114,8 +1197,8 @@
         local bt = [ BACKTRACE ] ;
         check-equal backtrace-1-file : $(bt) :
             test.jam [ CALC $(base) + 4 ] "" backtrace
- test.jam [ CALC $(base) + 28 ] module2. f
- test.jam [ CALC $(base) + 19 ] module1. f
+ test.jam [ CALC $(base) + 28 ] module2. module2.f
+ test.jam [ CALC $(base) + 19 ] module1. module1.f
             test.jam [ CALC $(base) + 32 ] "" "module scope"
         ;
     }

Modified: branches/release/tools/build/v2/test/core_import_module.py
==============================================================================
--- branches/release/tools/build/v2/test/core_import_module.py (original)
+++ branches/release/tools/build/v2/test/core_import_module.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -15,6 +15,11 @@
     {
         ECHO R1 ;
     }
+
+ local rule l1 ( )
+ {
+ ECHO A.L1 ;
+ }
 }
 module a2
 {
@@ -25,6 +30,11 @@
 }
 IMPORT a2 : r2 : : a2.r2 ;
 
+rule a.l1 ( )
+{
+ ECHO L1 ;
+}
+
 module b
 {
     IMPORT_MODULE a : b ;
@@ -34,6 +44,11 @@
         a.r1 ;
         # Call rule in global scope
         a2.r2 ;
+ # Call rule in global scope. Doesn't find local rule
+ a.l1 ;
+ # Make l1 visible
+ EXPORT a : l1 ;
+ a.l1 ;
     }
 }
 
@@ -57,6 +72,8 @@
 
 t.run_build_system("-fcode", stdout="""R1
 R2
+L1
+A.L1
 CTEST
 """)
 

Copied: branches/release/tools/build/v2/test/core_language.py (from r75738, /trunk/tools/build/v2/test/core_language.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_language.py (original)
+++ branches/release/tools/build/v2/test/core_language.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -8,7 +8,7 @@
 
 t = BoostBuild.Tester(pass_toolset=0)
 
-t.set_tree(".")
-t.run_build_system(extra_args="-fcore_language.jam")
+t.set_tree("core-language")
+t.run_build_system(extra_args="-ftest.jam")
 
 t.cleanup()

Copied: branches/release/tools/build/v2/test/core_option_l.py (from r75836, /trunk/tools/build/v2/test/core_option_l.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_option_l.py (original)
+++ branches/release/tools/build/v2/test/core_option_l.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,14 +11,27 @@
 
 t.write("sleep.bat","""@setlocal
 @echo off
-timeout /T %1 /NOBREAK >nul
+@REM timeout /T %1 /NOBREAK >nul
+ping 127.0.0.1 -n 2 -w 1000 >nul
+ping 127.0.0.1 -n %1 -w 1000 >nul
+@endlocal
+@exit /B 0
 """)
 
 t.write("file.jam", """
 
+if $(NT)
+{
+ SLEEP = @call sleep.bat ;
+}
+else
+{
+ SLEEP = sleep ;
+}
+
 actions .a. {
 echo 001
-sleep 4
+$(SLEEP) 4
 echo 002
 }
 
@@ -27,18 +40,8 @@
 DEPENDS all : sleeper ;
 """)
 
-t.run_build_system("-ffile.jam -d1 -l2", status=1, stdout="""...found 2 targets...
-...updating 1 target...
-.a. sleeper
-2 second time limit exceeded
-001
+t.run_build_system("-ffile.jam -d1 -l2", status=1)
 
-echo 001
-sleep 4
-echo 002
-
-...failed .a. sleeper...
-...failed updating 1 target...
-""")
+t.expect_output_line("2 second time limit exceeded")
 
 t.cleanup()

Copied: branches/release/tools/build/v2/test/core_option_n.py (from r75836, /trunk/tools/build/v2/test/core_option_n.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_option_n.py (original)
+++ branches/release/tools/build/v2/test/core_option_n.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -25,6 +25,7 @@
     NOTFILE subtest ;
     .a. subtest_a : subtest ;
     .a. subtest_b : subtest ;
+ FAIL_EXPECTED subtest_b ;
     DEPENDS all : subtest_a subtest_b ;
 """)
 
@@ -45,4 +46,6 @@
 ...updated 2 targets...
 """)
 
+t.expect_nothing_more()
+
 t.cleanup()

Copied: branches/release/tools/build/v2/test/core_parallel_actions.py (from r75836, /trunk/tools/build/v2/test/core_parallel_actions.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_parallel_actions.py (original)
+++ branches/release/tools/build/v2/test/core_parallel_actions.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,7 +11,11 @@
 
 t.write("sleep.bat","""@setlocal
 @echo off
-timeout /T %1 /NOBREAK >nul
+@REM timeout /T %1 /NOBREAK >nul
+ping 127.0.0.1 -n 2 -w 1000 >nul
+ping 127.0.0.1 -n %1 -w 1000 >nul
+@endlocal
+@exit /B 0
 """)
 
 t.write("file.jam", """
@@ -20,11 +24,11 @@
         actions sleeper
         {
 echo [$(<:S)] 0
-sleep 1
+@call sleep.bat 1
 echo [$(<:S)] 1
-sleep 1
+@call sleep.bat 1
 echo [$(<:S)] 2
-sleep $(<:B)
+@call sleep.bat $(<:B)
         }
     }
     else

Copied: branches/release/tools/build/v2/test/core_parallel_multifile_actions_1.py (from r75836, /trunk/tools/build/v2/test/core_parallel_multifile_actions_1.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_parallel_multifile_actions_1.py (original)
+++ branches/release/tools/build/v2/test/core_parallel_multifile_actions_1.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,13 +11,27 @@
 
 t.write("sleep.bat","""@setlocal
 @echo off
-timeout /T %1 /NOBREAK >nul
+@REM timeout /T %1 /NOBREAK >nul
+ping 127.0.0.1 -n 2 -w 1000 >nul
+ping 127.0.0.1 -n %1 -w 1000 >nul
+@endlocal
+@exit /B 0
 """)
 
 t.write("file.jam", """
+
+ if $(NT)
+ {
+ SLEEP = @call sleep.bat ;
+ }
+ else
+ {
+ SLEEP = sleep ;
+ }
+
     actions .gen. {
 echo 001
-sleep 4
+$(SLEEP) 4
 echo 002
 }
     rule .use.1 { DEPENDS $(<) : $(>) ; }
@@ -26,7 +40,7 @@
 }
     rule .use.2 { DEPENDS $(<) : $(>) ; }
     actions .use.2 {
-sleep 1
+$(SLEEP) 1
 echo 004
 }
 

Copied: branches/release/tools/build/v2/test/core_parallel_multifile_actions_2.py (from r75836, /trunk/tools/build/v2/test/core_parallel_multifile_actions_2.py)
==============================================================================
--- /trunk/tools/build/v2/test/core_parallel_multifile_actions_2.py (original)
+++ branches/release/tools/build/v2/test/core_parallel_multifile_actions_2.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -23,13 +23,27 @@
 
 t.write("sleep.bat","""@setlocal
 @echo off
-timeout /T %1 /NOBREAK >nul
+@REM timeout /T %1 /NOBREAK >nul
+ping 127.0.0.1 -n 2 -w 1000 >nul
+ping 127.0.0.1 -n %1 -w 1000 >nul
+@endlocal
+@exit /B 0
 """)
 
 t.write("file.jam", """
+
+ if $(NT)
+ {
+ SLEEP = @call sleep.bat ;
+ }
+ else
+ {
+ SLEEP = sleep ;
+ }
+
     actions link
     {
- sleep 1
+ $(SLEEP) 1
         echo 001 - linked
     }
 

Modified: branches/release/tools/build/v2/test/direct_request_test.py
==============================================================================
--- branches/release/tools/build/v2/test/direct_request_test.py (original)
+++ branches/release/tools/build/v2/test/direct_request_test.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,9 +4,42 @@
 
 t = BoostBuild.Tester()
 
-
 # First check some startup.
-t.set_tree("direct-request-test")
+
+t.write("jamroot.jam", "")
+
+t.write("jamfile.jam", """
+exe a : a.cpp b ;
+lib b : b.cpp ;
+""")
+
+t.write("a.cpp", """
+void
+# ifdef _WIN32
+__declspec(dllimport)
+# endif
+foo();
+
+int main()
+{
+ foo();
+}
+""")
+
+t.write("b.cpp", """
+#ifdef MACROS
+void
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+foo() {}
+#endif
+
+# ifdef _WIN32
+int __declspec(dllexport) force_implib_creation;
+# endif
+""")
+
 t.run_build_system(extra_args="define=MACROS")
 t.expect_addition("bin/$toolset/debug/"
                   * (BoostBuild.List("a.obj b.obj b.dll a.exe")))
@@ -19,11 +52,11 @@
                   * (BoostBuild.List("a.obj b.obj b.dll a.exe")))
 
 
-# When building release version, the 'define' should not apply: we will have
-# direct build request 'release <define>MACROS' and a real build property
-# 'debug'.
-t.copy("jamfile2.jam", "jamfile.jam")
-t.copy("b_inverse.cpp", "b.cpp")
+# When building release version, the 'define' still applies.
+t.write("jamfile.jam", """
+exe a : a.cpp b : <variant>debug ;
+lib b : b.cpp ;
+""")
 t.rm("bin")
 t.run_build_system(extra_args="release define=MACROS")
 

Deleted: branches/release/tools/build/v2/test/echo_args.jam
==============================================================================
--- branches/release/tools/build/v2/test/echo_args.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,20 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-rule echo_args ( a b ? c ? : d + : e * )
-{
- ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e) ;
-}
-
-rule echo_varargs ( a b ? c ? : d + : e * : * )
-{
- ECHO a= $(a) b= $(b) c= $(c) ":" d= $(d) ":" e= $(e)
- ": rest= "$(4[1]) $(4[2])
- ": "$(5[1]) $(5[2])
- ": "$(6[1]) $(6[2])
- ": "$(7[1]) $(7[2])
- ": "$(8[1]) $(8[2])
- ": "$(9[1]) $(9[2]) ;
-}
-

Deleted: branches/release/tools/build/v2/test/empty.jam
==============================================================================
--- branches/release/tools/build/v2/test/empty.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,5 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# This file is empty; it just suppresses warnings

Deleted: branches/release/tools/build/v2/test/file_name_handling.py
==============================================================================
--- branches/release/tools/build/v2/test/file_name_handling.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,255 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2008 Jurko Gospodnetic
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Tests Boost Jam & Boost Build's source & target file name handling. Originally
-# added as a regression test for a bug causing versions included in the Boost
-# library 1.35 release (and earlier) not handling Windows short file names
-# correctly. Also tests handling target file names containing spaces.
-
-# Implementation notes:
-#
-# We expect Boost Jam to automatically update the 'all' target when no target
-# has been explicitly specified on the command line.
-#
-# Windows short & long file names can not be matched until the file in
-# question actually exists so we need to create the file before running Boost
-# Jam.
-#
-# Currently Windows short file names are hardcoded but in case this proves
-# insufficient we should use the GetShortPathName() Windows API to get the
-# correct short file for a given long file name.
-# (30.04.2008.) (Jurko)
-
-import BoostBuild
-import os
-import time
-
-
-################################################################################
-#
-# prepare_file()
-# --------------
-#
-################################################################################
-
-def prepare_file(tester, target_name, age_in_seconds=0):
- """Prepares a new file with the given name, optionally setting its last
- access and modification timestamps to the given number of seconds in the
- history.
- """
- tester.write( target_name, "Original file content." )
- if ( ( not age_in_seconds is None ) and ( age_in_seconds != 0 ) ):
- t = time.time() - age_in_seconds
- os.utime( tester.native_file_name( target_name ), ( t, t ) )
-
-
-################################################################################
-#
-# test_simple_file_names()
-# ------------------------
-#
-################################################################################
-
-def test_simple_file_names():
- """Runs simple file name handling that is not expected to fail anywhere. Not
- really needed for regular testing but the test is really fast and its
- content may be used for comparing to other more complex test functions in
- this module which test the same system but with some potentially more
- problematic file names.
- """
- t = BoostBuild.Tester(pass_toolset=0)
-
- prepare_file(t, "source.txt" )
- prepare_file(t, "target.txt" , 120)
- prepare_file(t, "target_noupdate.txt", 240)
-
- t.write("testScript.jam", """
-actions create-file
-{
- echo "Modified file content ($(1:E=""))."> "$(1:E="")"
-}
-
-DEPENDS all : standaloneTarget.txt ;
-create-file standaloneTarget.txt : all ;
-
-DEPENDS all : target.txt ;
-DEPENDS target.txt : source.txt ;
-create-file target.txt ;
-
-NOUPDATE target_noupdate.txt ;
-DEPENDS all : target_noupdate.txt ;
-DEPENDS target_noupdate.txt : source.txt ;
-create-file target_noupdate.txt ;
-
-create-file shouldNotBeCreated1 ;
-create-file shouldNotBeCreated2 ;
-create-file shouldNotBeCreated3 ;
-""")
-
- t.run_build_system("-ftestScript.jam")
- t.expect_addition("standaloneTarget.txt")
- t.expect_modification("target.txt")
- t.expect_nothing_more()
-
- t.cleanup()
-
-
-################################################################################
-#
-# test_short_file_name_with_action()
-# ----------------------------------
-#
-################################################################################
-
-def test_short_file_name_with_action():
- """Tests how Boost Jam handles the case when a Windows short file name is
- passed to a Boost Jam action.
- """
- if ( not BoostBuild.windows ):
- return
-
- t = BoostBuild.Tester(pass_toolset=0)
-
- long_file_name1 = "1__target that should be rebuilt.txt"
- long_file_name2 = "2__target that should be rebuilt.txt"
- short_file_name2 = "2__tar~1.txt"
-
- prepare_file(t, long_file_name1)
- prepare_file(t, long_file_name2)
-
- t.write("testScript.jam", """
-actions create-file
-{
- echo Modified file content ($(1:E="")).> "$(1:E="")"
-}
-
-ALWAYS "%(long_file_name1)s" ;
-DEPENDS all : "%(long_file_name1)s" ;
-create-file "%(long_file_name1)s" ;
-
-ALWAYS "%(long_file_name2)s" ;
-DEPENDS all : "%(long_file_name2)s" ;
-create-file "%(short_file_name2)s" ;
-""" % {'long_file_name1': long_file_name1,
- 'long_file_name2' : long_file_name2,
- 'short_file_name2' : short_file_name2})
-
- t.run_build_system("-ftestScript.jam")
- t.expect_modification(long_file_name1)
- t.expect_modification(long_file_name2)
- t.expect_nothing_more()
-
- t.cleanup()
-
-
-################################################################################
-#
-# test_short_file_name_with_ALWAYS()
-# ----------------------------------
-#
-################################################################################
-
-def test_short_file_name_with_ALWAYS():
- """Tests how Boost Jam handles the case when a Windows short file name is
- passed to the builtin ALWAYS rule.
- """
- if ( not BoostBuild.windows ):
- return
-
- t = BoostBuild.Tester(pass_toolset=0)
-
- long_file_name1 = "1__target that should be rebuilt.txt"
- long_file_name2 = "2__target that should be rebuilt.txt"
- short_file_name2 = "2__tar~1.txt"
-
- prepare_file(t, long_file_name1)
- prepare_file(t, long_file_name2)
-
- t.write("testScript.jam", """
-actions create-file
-{
- echo Modified file content ($(1:E="")).> "$(1:E="")"
-}
-
-ALWAYS "%(long_file_name1)s" ;
-DEPENDS all : "%(long_file_name1)s" ;
-create-file "%(long_file_name1)s" ;
-
-ALWAYS "%(short_file_name2)s" ;
-DEPENDS all : "%(long_file_name2)s" ;
-create-file "%(long_file_name2)s" ;
-""" % {'long_file_name1': long_file_name1,
- 'long_file_name2' : long_file_name2,
- 'short_file_name2' : short_file_name2})
-
- t.run_build_system("-ftestScript.jam")
- t.expect_modification(long_file_name1)
- t.expect_modification(long_file_name2)
- t.expect_nothing_more()
-
- t.cleanup()
-
-
-################################################################################
-#
-# test_short_file_name_with_NOUPDATE()
-# ------------------------------------
-#
-################################################################################
-
-def test_short_file_name_with_NOUPDATE():
- """Tests how Boost Jam handles the case when a Windows short file name is
- passed to the builtin NOUPDATE rule.
- """
- if ( not BoostBuild.windows ):
- return
-
- t = BoostBuild.Tester(pass_toolset=0)
-
- long_file_name1 = "1__target that should be rebuilt.txt"
- long_file_name2 = "2__target that should not be rebuilt.txt"
- short_file_name2 = "2__tar~1.txt"
-
- prepare_file(t, "source.txt" )
- prepare_file(t, long_file_name1, 120)
- prepare_file(t, long_file_name2, 120)
-
- t.write("testScript.jam", """
-actions create-file
-{
- echo Modified file content ($(1:E="")).> "$(1:E="")"
-}
-
-DEPENDS all : "%(long_file_name1)s" ;
-DEPENDS "%(long_file_name1)s" : source.txt ;
-create-file "%(long_file_name1)s" ;
-
-NOUPDATE "%(short_file_name2)s" ;
-DEPENDS all : "%(long_file_name2)s" ;
-DEPENDS "%(long_file_name2)s" : source.txt ;
-create-file "%(long_file_name2)s" ;
-""" % {'long_file_name1': long_file_name1,
- 'long_file_name2' : long_file_name2,
- 'short_file_name2' : short_file_name2})
-
- t.run_build_system("-ftestScript.jam")
- t.expect_modification(long_file_name1)
- t.expect_nothing_more()
-
- t.cleanup()
-
-
-################################################################################
-#
-# main()
-# ------
-#
-################################################################################
-
-test_simple_file_names()
-test_short_file_name_with_action()
-test_short_file_name_with_ALWAYS()
-test_short_file_name_with_NOUPDATE()

Deleted: branches/release/tools/build/v2/test/jamfile.jam
==============================================================================
--- branches/release/tools/build/v2/test/jamfile.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,11 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-
-# establish a project root right here in the test directory, so that we can test
-# things independently of the boost jambase, etc.
-project-root ;
-
-include check-test-tools.jam ;
-include check-jam-patches.jam ;

Modified: branches/release/tools/build/v2/test/load_order.py
==============================================================================
--- branches/release/tools/build/v2/test/load_order.py (original)
+++ branches/release/tools/build/v2/test/load_order.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -61,4 +61,28 @@
 t.run_build_system(subdir="src/app")
 t.expect_addition("src/app/bin/$toolset/debug/test.exe")
 
+# child/child2 used to be loaded before child
+t.rm(".")
+t.write("jamroot.jam", """
+use-project /child/child2 : child/child2 ;
+rule parent-rule ( )
+{
+ ECHO "Running parent-rule" ;
+}
+""")
+
+t.write("child/jamfile.jam", """
+""")
+
+t.write("child/child1/jamfile.jam", """
+""")
+
+t.write("child/child2/jamfile.jam", """
+parent-rule ;
+""")
+
+
+t.run_build_system(subdir="child/child1")
+t.expect_output_line("Running parent-rule")
+
 t.cleanup()

Deleted: branches/release/tools/build/v2/test/m1-01.py
==============================================================================
--- branches/release/tools/build/v2/test/m1-01.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Test the very basic 'make' functionality.
-
-import BoostBuild
-
-t = BoostBuild.Tester()
-
-t.set_tree("test1")
-
-# Check that we can build something.
-t.run_build_system("-sTOOLSET=yfc")
-
-t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
-t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
-t.expect_nothing_more()
-
-t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-""")
-
-t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-""")
-
-# Check that we have vanilla target names available.
-t.touch("a.cpp")
-t.run_build_system("-sTOOLSET a.obj")
-t.expect_touch("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
-t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
-
-
-# Check that if a build request cannot be completely matches, a warning is
-# issued and a subvariant with link-compatible properties is used.
-t.write("jamfile.jam", t.read("jamfile2.jam"))
-stdout="""Warning: cannot exactly satisfy request for ./a with properties
- <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-Using
- <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-instead.
-""")
-t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
-
-# Check that conflicting link-incompatible requirements prevent building.
-t.write("jamfile.jam", t.read("jamfile3.jam"))
-stdout="""Warning: cannot satisfy request for ./a with properties
- <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-Nothing will be built.
-""")
-t.run_build_system("-sTOOLSET=yfc", stdout=stdout, status=1)
-
-t.pass_test()

Deleted: branches/release/tools/build/v2/test/m1-02.py
==============================================================================
--- branches/release/tools/build/v2/test/m1-02.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,90 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Tests that 'make' accepts targets from other directories and that build
-# requests for those targets can be overriden.
-
-import BoostBuild
-
-t = BoostBuild.Tester()
-
-t.set_tree("test1")
-
-t.run_build_system("-sTOOLSET=yfc")
-
-t.expect_addition("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
-t.expect_addition("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
-t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
-t.expect_nothing_more()
-
-t.fail(t.read("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-""")
-
-t.fail(t.read("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
-"""
-<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-b.cpp
-""")
-
-t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-b.cpp
-""")
-
-# Check that we have vanilla target names available in subdirs.
-t.touch("auxillary/b.cpp")
-t.run_build_system("-sTOOLSET b.obj", subdir="auxillary")
-t.expect_touch("auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
-t.expect_no_modification("bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
-t.expect_no_modification("bin/a/yfc/debug/runtime-link-dynamic/a")
-
-
-# Check that we can not request link-incompatible property for source target.
-t.write('jamfile.jam', t.read('jamfile2.jam'))
-stdout="""Error: subvariant of target ./a with properties
- <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-requests link-incompatible property
- <rtti>off
-for source @auxillary/b.obj
-"""
-t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
-
-
-# Check that if we request link-compatible property then requirement for the
-# source target will override it, with a warning. This is similar to the way
-# build requests are satisfied (see the first test).
-#
-# CONSIDER: should be print the main target which requests this one (and
-# modifies requirements)?
-t.write('jamfile.jam', t.read('jamfile3.jam'))
-t.write('auxillary/jamfile.jam', t.read('auxillary/jamfile3.jam'))
-stdout="""Warning: cannot exactly satisfy request for auxillary/b.obj with properties
- <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-Using
- <optimization>speed <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-instead.
-"""
-t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
-
-
-# Check for link-incompatible properties.
-t.write('jamfile.jam', t.read('jamfile4.jam'))
-t.write('auxillary/jamfile.jam', t.read('auxillary/jamfile4.jam'))
-stdout="""Warning: cannot satisfy request for auxillary/b.obj with properties
- <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-Nothing will be built.
-"""
-t.run_build_system("-sTOOLSET=yfc", stdout=stdout)
-
-
-t.pass_test()

Deleted: branches/release/tools/build/v2/test/m1-03.py
==============================================================================
--- branches/release/tools/build/v2/test/m1-03.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Tests that we can use objects from other projects, i.e. with other project
-# root. Test also that we can refer to those target using project-id.
-
-import BoostBuild
-
-t = BoostBuild.Tester()
-
-t.set_tree("test1")
-
-t.run_build_system("-sTOOLSET=yfc", subdir="p1")
-
-t.expect_addition("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj")
-t.expect_addition("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/optimization-space/b.obj")
-t.expect_addition("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj")
-t.expect_addition("bin/a/yfc/debug/runtime-link-dynamic/a")
-t.expect_nothing_more()
-
-t.fail(t.read("p1/bin/a.obj/yfc/debug/runtime-link-dynamic/a.obj") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-""")
-
-t.fail(t.read("p1/auxillary/bin/b.obj/yfc/debug/runtime-link-dynamic/b.obj") !=\
-"""
-<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-b.cpp
-""")
-
-t.fail(t.read("p2/bin/c.obj/yfc/debug/runtime-link-dynamic/c.obj") !=\
-"""
-<include>everything <optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-""")
-
-t.fail(t.read("bin/a/yfc/debug/runtime-link-dynamic/a") !=\
-"""
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-<optimization>off <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-a.cpp
-<optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-b.cpp
-<include>everything <optimization>space <rtti>on <runtime-link>dynamic <toolset>yfc <variant>debug
-c.cpp
-""")
-
-t.expect_nothing_more()
-
-# TODO: need to write test cases for referring to targets using project-id.
-
-t.pass_test()

Modified: branches/release/tools/build/v2/test/prebuilt/ext/jamfile2.jam
==============================================================================
--- branches/release/tools/build/v2/test/prebuilt/ext/jamfile2.jam (original)
+++ branches/release/tools/build/v2/test/prebuilt/ext/jamfile2.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1,9 +1,9 @@
 
-import modules ;
+import os ;
 
 local dll-suffix = so ;
 local prefix = "" ;
-if [ modules.peek : OS ] in CYGWIN NT
+if [ os.name ] in CYGWIN NT
 {
    if [ MATCH ^(gcc) : $toolset ]
    {

Modified: branches/release/tools/build/v2/test/prebuilt/ext/jamfile3.jam
==============================================================================
--- branches/release/tools/build/v2/test/prebuilt/ext/jamfile3.jam (original)
+++ branches/release/tools/build/v2/test/prebuilt/ext/jamfile3.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -3,11 +3,11 @@
 # it tries to access prebuilt targets using absolute
 # paths. It used to be broken on Windows.
 
-import modules ;
+import os ;
 
 local dll-suffix = so ;
 local prefix = "" ;
-if [ modules.peek : OS ] in CYGWIN NT
+if [ os.name ] in CYGWIN NT
 {
    if [ MATCH ^(gcc) : $toolset ]
    {

Deleted: branches/release/tools/build/v2/test/project-test1.jam
==============================================================================
--- branches/release/tools/build/v2/test/project-test1.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,18 +0,0 @@
-# Copyright 2002, 2003 Dave Abrahams
-# Copyright 2002 Rene Rivera
-# Copyright 2002, 2003 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-import project ;
-import targets ;
-import assert ;
-
-project.load project-test1 ;
-import project-roots ;
-
-project-roots.print ;
-
-NOTFILE all ;
-
-

Deleted: branches/release/tools/build/v2/test/project_test1.py
==============================================================================
--- branches/release/tools/build/v2/test/project_test1.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Dave Abrahams
-# Copyright 2002, 2003, 2004 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-import BoostBuild
-import os
-
-t = BoostBuild.Tester("--build-system=project-test1", boost_build_path='',
- pass_toolset=0)
-
-# This test does no modifications, so run in in the invocation dir.
-os.chdir(t.original_workdir)
-
-expected_output1="""Project Roots:
-
-"""
-
-expected_output2="""'%(root-dir-prefix)sdir2':
-
- Module for project-root is 'project-root<%(root-dir-prefix)sdir2>'
-
-Projects:
-
-'/cool-library':
-
-* Parent project: (none)
-* Requirements: <include>/home/ghost/build/boost-cvs
-* Default build:
-* Source location: %(root-dir-prefix)sdir2
-* Projects to build:
-
-"""
-
-expected_output3="""'%(root-dir)s':
-
- Module for project-root is 'project-root<%(root-dir)s>'
-
-Projects:
-
-'/boost-build-test-project-1':
-
-* Parent project: (none)
-* Requirements: <include>/home/ghost/local/include <threading>multi
-* Default build:
-* Source location: %(root-dir)s
-* Projects to build: dir dir2
-
-'/boost-build-test-project-1/dir':
-
-* Parent project: %(root-dir)s
-* Requirements: <include>/home/ghost/local/include <threading>multi
-* Default build: <variant>release
-* Source location: %(root-dir-prefix)sdir/src
-* Projects to build:
-
-"""
-
-# Test that correct project structure is created when jam is invoked outside of
-# the source tree.
-expected = (expected_output1 + expected_output2 + expected_output3) % \
- {"root-dir": "project-test1",
- "root-dir-prefix": "project-test1/" }
-
-t.run_build_system(stdout=expected)
-
-# Test that correct project structure is created when jam is invoked at the top
-# of the source tree.
-expected = (expected_output1 + expected_output3 + expected_output2) % \
- {"root-dir": ".",
- "root-dir-prefix": "" }
-
-os.chdir("project-test1")
-t.run_build_system(stdout=expected)
-
-t.cleanup()

Deleted: branches/release/tools/build/v2/test/recursive.jam
==============================================================================
--- branches/release/tools/build/v2/test/recursive.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,117 +0,0 @@
-# Copyright 2001, 2002 Dave Abrahams
-# Copyright 2005 Rene Rivera
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-##############################################################
-# Rules and actions that test Jam by invoking it recursively #
-# #
-# This is necessary for testing anything that requires Jam #
-# to execute build actions whose results must be checked, #
-# and anything which exits Jam with a failure code (e.g. a #
-# failed assertion). #
-##############################################################
-
-# Creates a fake target, always built, which succeeds in building if Invoking a
-# Jamfile containing the given string succeeds. If optional-expected-output is
-# supplied, creates another fake target which succeeds in building if
-# optional-expected-output is in the Jam output.
-#
-# RETURNS: the target name of the Jam command.
-rule Jam ( command : expected-output ? )
-{
- local jam-cmd = "$(command:G=jam_command)" ;
-
- NOTFILE "$(jam-cmd)" ;
- ALWAYS "$(jam-cmd)" ;
- DEPENDS all : "$(jam-cmd)" ;
-
- if ($NT)
- {
- redirect on $(jam-cmd) = "nul" ;
- }
- else if $(UNIX)
- {
- redirect on $(jam-cmd) = "/dev/null" ;
- }
-
- if $(VERBOSE)
- {
- redirect on $(jam-cmd) = ;
- }
-
- invoke-Jam "$(jam-cmd)" ;
-
- if $(expected-output)
- {
- redirect on $(jam-cmd) = "scratch-output.txt" ;
- local output-target = "$(expected-output:G=$(command))" ;
- NOTFILE "$(output-target)" ;
- ALWAYS "$(output-target)" ;
- DEPENDS all : "$(output-target)" ;
- Expect-in-output "$(output-target)" ;
-
- if $(VERBOSE)
- {
- if $(NT) { VERBOSE on $(output-target) = "type " ; }
- else { VERBOSE on $(output-target) = "cat " ; }
- }
- }
- return $(jam-cmd) ;
-}
-
-# Just like the "Jam" rule, above, but only succeeds if the Jam command /fails/.
-rule Jam-fail ( command : expected-output ? )
-{
- local target = [ Jam $(command) : $(expected-output) ] ;
- FAIL_EXPECTED $(target) ;
- return $(target) ;
-}
-
-# The temporary jamfile we write is called "temp.jam". If the user has set
-# BOOST_BUILD_ROOT, it will be built there.
-gBOOST_TEST_JAMFILE = temp.jam ;
-LOCATE on gBOOST_TEST_JAMFILE ?= $(BOOST_BUILD_ROOT) ;
-
-# Runs Jam on a temporary Jamfile which contains the string in $(command:G=)
-# and redirects the results into a file whose name is given by $(redirect) on
-# command
-rule invoke-Jam ( command )
-{
- PREFIX on $(command) = "actions unbuilt { } unbuilt all ;" ;
- if $(NT)
- {
- REMOVE on $(command) = $(SystemRoot)\System32\find ;
- }
- REMOVE on $(command) ?= rm ;
-}
-actions invoke-Jam
-{
- echo $(PREFIX) $(<:G=) > $(gBOOST_TEST_JAMFILE)
- jam -sBOOST_ROOT=../../.. -sJAMFILE=$(gBOOST_TEST_JAMFILE) $(JAMARGS) >$(redirect)
-}
-# $(REMOVE) $(gBOOST_TEST_JAMFILE)
-
-
-# These actions expect to find the ungristed part of $(<) in scratch-output.txt
-# and return a nonzero exit code otherwise
-if $(NT)
-{
- # Explicitly get the NT find command in case someone has another find in their path.
- actions quietly Expect-in-output
- {
- $(VERBOSE)scratch-output.txt ;
- $(SystemRoot)\System32\find /C "$(<:G=)" scratch-output.txt >nul
- }
-}
-else
-{
- # Not really the right actions for Unix; the argument will be interpreted as
- # a regular expression. Is there a simpler find?
- actions quietly Expect-in-output
- {
- $(VERBOSE)scratch-output.txt;
- grep "$(<:G=)" scratch-output.txt
- }
-}
-

Deleted: branches/release/tools/build/v2/test/startup_v1.py
==============================================================================
--- branches/release/tools/build/v2/test/startup_v1.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,81 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Dave Abrahams
-# Copyright 2003, 2004, 2005 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-import BoostBuild
-import os
-import re
-
-def expect_substring(actual, expected):
- return actual.find(expected) != -1
-
-def match_re(actual, expected):
- return re.match(expected, actual, re.DOTALL) != None
-
-# Test the v1 startup behavior.
-t = BoostBuild.Tester(executable='bjam', match=match_re, boost_build_path='',
- pass_toolset=0)
-
-t.set_tree('startup')
-
-#if os.name == 'nt':
-# t.run_build_system(
-# status=1, stdout="You didn't set BOOST_ROOT", match = expect_substring)
-
-t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
- stdout=r'''Unable to load Boost\.Build: could not find ''' +
- r'''"boost-build\.jam".''')
-
-os.chdir('no-bootstrap1')
-
-t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
- stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
- + r'''.*attempted to load the build system by invoking'''
- + r'''.*'boost-build ;'.*'''
- + r'''but we were unable to find "bootstrap\.jam"''')
-
-# Descend to a subdirectory which /doesn't/ contain a boost-build.jam
-# file, and try again to test the crawl-up behavior.
-os.chdir('subdir')
-
-t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
- stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
- + r'''.*attempted to load the build system by invoking'''
- + r'''.*'boost-build ;'.*'''
- + r'''but we were unable to find "bootstrap\.jam"''')
-
-os.chdir('../../no-bootstrap2')
-
-t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
- stdout=r'''Unable to load Boost\.Build: could not find build system\.'''
- + r'''.*attempted to load the build system by invoking'''
- + r'''.*'boost-build \. ;'.*'''
- + r'''but we were unable to find "bootstrap\.jam"''')
-
-os.chdir('../no-bootstrap3')
-
-t.run_build_system(extra_args='-sBOOST_ROOT=.', status=1,
- stdout=r'''Unable to load Boost.Build
-.*boost-build.jam" was found.*
-However, it failed to call the "boost-build" rule''')
-
-# test bootstrapping based on BOOST_BUILD_PATH
-os.chdir('../bootstrap-env')
-t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root ' +
- '-sBOOST_BUILD_PATH=../boost-root/build',
- stdout='build system bootstrapped')
-
-# test bootstrapping based on an explicit path in boost-build.jam
-os.chdir('../bootstrap-explicit')
-t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root',
- stdout='build system bootstrapped')
-
-# test bootstrapping based on BOOST_ROOT
-os.chdir('../bootstrap-implicit')
-t.run_build_system(extra_args='-sBOOST_ROOT=../boost-root',
- stdout='build system bootstrapped')
-
-t.cleanup()

Modified: branches/release/tools/build/v2/test/test.jam
==============================================================================
--- branches/release/tools/build/v2/test/test.jam (original)
+++ branches/release/tools/build/v2/test/test.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -4,20 +4,36 @@
 # Distributed under the Boost Software License, Version 1.0.
 # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 
+# util
+import assert ;
+import container ;
 import indirect ;
-import string ;
 import numbers ;
-import sequence ;
-import "class" ;
+import order ;
 import os ;
 import path ;
+import print ;
+import regex ;
+import sequence ;
+import set ;
+import string ;
+import utility ;
+
+# kernel
+import "class" ;
+import errors ;
+import modules ;
+
+# build
+import build-request ;
 import feature ;
 import property ;
-import build-request ;
-import container ;
-import print ;
-import common ;
+import toolset ;
+import type ;
+import version ;
 
+# tools
+import common ;
 
 actions nothing { }
 nothing all ;

Modified: branches/release/tools/build/v2/test/test1.py
==============================================================================
--- branches/release/tools/build/v2/test/test1.py (original)
+++ branches/release/tools/build/v2/test/test1.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -6,7 +6,7 @@
 
 import BoostBuild
 
-t = BoostBuild.Tester()
+t = BoostBuild.Tester(pass_toolset=0)
 
 t.write("test.jam", """
 actions unbuilt { }
@@ -15,4 +15,4 @@
 """)
 
 t.run_build_system("-ftest.jam", stdout="Hi\n")
-t.pass_test()
+t.cleanup()

Modified: branches/release/tools/build/v2/test/test2.py
==============================================================================
--- branches/release/tools/build/v2/test/test2.py (original)
+++ branches/release/tools/build/v2/test/test2.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,7 +11,7 @@
 
 t.set_tree("test2")
 
-file_list = 'bin/foo/$toolset/debug/runtime-link-dynamic/' * \
+file_list = 'bin/$toolset/debug/' * \
     BoostBuild.List("foo foo.o")
 
 t.run_build_system("-sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
@@ -22,4 +22,4 @@
 t.run_build_system("-d2 -sBOOST_BUILD_PATH=" + t.original_workdir + "/..")
 t.expect_touch(file_list)
 
-t.pass_test()
+t.cleanup()

Deleted: branches/release/tools/build/v2/test/test2/Jamrules
==============================================================================

Deleted: branches/release/tools/build/v2/test/test2/jamfile.jam
==============================================================================
--- branches/release/tools/build/v2/test/test2/jamfile.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,8 +0,0 @@
-# Copyright 2002 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-
-project-root ;
-
-exe foo : foo.cpp ;

Modified: branches/release/tools/build/v2/test/test_all.py
==============================================================================
--- branches/release/tools/build/v2/test/test_all.py (original)
+++ branches/release/tools/build/v2/test/test_all.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -118,10 +118,10 @@
         return tests
 
 
-critical_tests = ["unit_tests", "module_actions", "startup_v1", "startup_v2"]
+critical_tests = ["unit_tests", "module_actions", "startup_v2"]
 
 critical_tests += ["core_d12", "core_typecheck", "core_delete_module",
- "core_varnames", "core_import_module"]
+ "core_language", "core_arguments", "core_varnames", "core_import_module"]
 
 tests = [ "absolute_sources",
           "alias",
@@ -130,6 +130,8 @@
           "build_dir",
           "build_file",
           "build_no",
+ "builtin_echo",
+ "builtin_exit",
           "c_file",
           "chain",
           "clean",
@@ -140,6 +142,18 @@
           "conditionals_multiple",
           "configuration",
           "copy_time",
+ "core_action_status",
+ "core_actions_quietly",
+ "core_at_file",
+ "core_bindrule",
+ "core_nt_line_length",
+ "core_option_d2",
+ "core_option_l",
+ "core_option_n",
+ "core_parallel_actions",
+ "core_parallel_multifile_actions_1",
+ "core_parallel_multifile_actions_2",
+ "core_update_now",
           "custom_generator",
           "default_build",
           "default_features",
@@ -147,6 +161,7 @@
 # "default_toolset",
           "dependency_property",
           "dependency_test",
+ "direct_request_test",
           "disambiguation",
           "dll_path",
           "double_loading",
@@ -155,7 +170,6 @@
           "example_make",
           "expansion",
           "explicit",
- "file_name_handling",
           "free_features_request",
           "generator_selection",
           "generators_test",
@@ -202,6 +216,7 @@
           "testing_support",
           "timedata",
           "unit_test",
+ "unused",
           "use_requirements",
           "using",
           "wrapper",

Deleted: branches/release/tools/build/v2/test/test_nt_line_length.jam
==============================================================================
--- branches/release/tools/build/v2/test/test_nt_line_length.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,39 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# Test that the patch which allows long command-lines in actions on NT is
-# working. For reasons of backward-compatibility, this patch requires that the
-# action fits on a single command-line, and that the JAMSHELL variable on the
-# target being built is set to "%".
-if $(NT)
-{
- #
- # Build a really long commandline. (> 10K characters).
- #
- ten = 0 1 2 3 4 5 6 7 8 9 ;
- 1x7chars = 0_____ ;
- # add a digit and multiply by 10
- 10x8chars = $(ten)$(1x7chars) ;
- # add a digit to each of 10 strings and multiply by 10
- 100x9chars = $(ten)$(10x8chars) ;
- # add a digit to each of 100 strings and multiply by 10
- 1000x10chars = $(ten)$(100x9chars) ;
-
- #
- # Cause line_length_test to be built
- #
- actions do_echo
- {
- echo $(text)
- }
-
- 400x10chars = $(ten[1-4])$(100x9chars) ;
-
- text on line_length_test = $(400x10chars) 40$(10x8chars[1-9]) 01234 ;
- text on line_length_test = $(1000x10chars) $(1000x10chars) ;
- JAMSHELL on line_length_test = % ;
- DEPENDS all : line_length_test ;
-
- do_echo line_length_test ;
-}

Deleted: branches/release/tools/build/v2/test/testing_primitives.py
==============================================================================
--- branches/release/tools/build/v2/test/testing_primitives.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-import BoostBuild
-import re
-
-def match_re(actual, expected):
- return re.match(expected, actual, re.DOTALL) != None
-
-t = BoostBuild.Tester(match=match_re)
-
-t.set_tree('testing-primitives')
-
-# We expect t5 and t7's output to be dumped to stdout.
-t.run_build_system(stdout=r'''.*failing t5.*failing t7''')
-
-t.expect_addition('t2.txt')
-t.expect_addition('t3.txt')
-t.expect_addition('t5.out')
-t.expect_addition('t6.out')
-t.expect_addition('t6.txt')
-t.expect_addition('t7.out')
-t.expect_addition('t7.txt')
-t.expect_addition('t8.out')
-t.expect_nothing_more()
-
-t.cleanup()

Deleted: branches/release/tools/build/v2/test/unit-tests.jam
==============================================================================
--- branches/release/tools/build/v2/test/unit-tests.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,262 +0,0 @@
-# Copyright 2001 Dave Abrahams
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-# assert_equal a : b
-#
-# exits with an assertion failure if a != b
-rule assert_equal
-{
- if $(<) != $(>)
- {
- EXIT "assertion failure: [" $(<) "] != [" $(>) "]" ;
- }
-}
-
-rule assert_equal_sets
-{
- if ! [ equal-sets $(<) : $(>) ]
- {
- EXIT "assertion failure: [" $(<) "] !=(set) [" $(>) "]" ;
- }
-}
-
-# FAppendSuffix
-assert_equal [ FAppendSuffix yacc lex foo.bat : ] : yacc lex foo.bat ;
-assert_equal [ FAppendSuffix yacc lex foo.bat : .exe ] : yacc.exe lex.exe foo.bat ;
-assert_equal [ FAppendSuffix yacc lex foo.bat : .dll .lib ] : yacc.dll yacc.lib lex.dll lex.lib foo.bat foo.lib ;
-
-# sort
-assert_equal [ sort 7 3 5 6 2 4 ] : 2 3 4 5 6 7 ;
-
-# min
-assert_equal [ min 7 3 5 6 2 4 ] : 2 ;
-
-# difference
-assert_equal [ difference 0 1 2 3 4 5 6 7 8 9 : 2 3 5 7 ] : 0 1 4 6 8 9 ;
-
-# replace
-assert_equal [ replace 1 3 5 7 7 9 2 5 4 3 1 : 7 x ] : 1 3 5 x x 9 2 5 4 3 1 ;
-
-# select-ungristed
-assert_equal [ select-ungristed <a>b c <d>e f ] : c f ;
-
-# split-qualified-property
-assert_equal [ split-qualified-property <feature>value ]
- : <*> <*> <feature>value ;
-
-assert_equal [ split-qualified-property <variant><feature>value ]
- : <*> <variant> <feature>value ;
-
-assert_equal [ split-qualified-property <toolset><variant><feature>value ]
- : <toolset> <variant> <feature>value ;
-
-# unique
-assert_equal [ unique 0 1 2 3 1 7 6 6 4 5 ] : 0 1 2 3 7 6 4 5 ;
-
-# get-properties
-assert_equal [ get-properties <foo> <bar> : <foo>bar <foo>baz <bar>fight <baz>niss ]
- : <foo>bar <foo>baz <bar>fight ;
-
-# get-values
-assert_equal [ get-values <foo> : <foo>bar <foo>baz <bar>fight <baz>niss ] : bar baz ;
-
-# normalize-properties
-assert_equal [ normalize-properties <a>b <c><d>e <f><g><h>i ] :
- <*><*><a>b <*><c><d>e <f><g><h>i ;
-
-# intersection
-assert_equal [ intersection 1 2 2 3 3 4 5 6 7 : 5 1 3 7 3 9 11 ] : 1 3 3 5 7 ;
-
-# is-subset
-assert_equal [ is-subset a b c : c a b d ] : true ;
-assert_equal [ is-subset a b z : c a b d ] : ;
-
-# split-path
-assert_equal [ split-path <a>b/c/<d>e ] : <a>b c <d>e ;
-assert_equal [ split-path <a>/<d>/<e> ] : <a> <d> <e> ;
-assert_equal [ split-path <a> ] : <a> ;
-assert_equal [ split-path x ] : x ;
-assert_equal [ split-path $(DOT) ] : $(DOT) ;
-assert_equal [ split-path a/b.c/d.e/f ] : a b.c d.e f ;
-if $(NT)
-{
- assert_equal [ split-path x:\\y\\z\\w ] : x: y z w ;
- assert_equal [ split-path x:\\y\\z ] : x: y z ;
- assert_equal [ split-path x:\\y ] : x: y ;
- assert_equal [ split-path x:\\ ] : x: ;
- assert_equal [ split-path x: ] : x: ;
-}
-
-# distribute-feature
-assert_equal [ distribute-feature <feature>value1 ] : <feature>value1 ;
-assert_equal [ distribute-feature <feature>value1/value2 ] : <feature>value1 <feature>value2 ;
-assert_equal [ distribute-feature <feature>value1/value2/value3 ] : <feature>value1 <feature>value2 <feature>value3 ;
-
-# segregate-free-properties
-{
- local gFREE_FEATURES = <a> <c> <e> ;
- local x = <a>b <b>c <d>e ;
- local y = <a>b <a>c <b>c <e>f ;
- local free = [ segregate-free-properties x y ] ;
- assert_equal $(free) : <a>b <a>c <e>f ;
- assert_equal $(x) : <b>c <d>e ;
- assert_equal $(y) : <b>c ;
-}
-
-# set-insert
-{
- local gTEST_SET = 1 2 3 ;
- set-insert gTEST_SET : 2 ;
- assert_equal $(gTEST_SET) : 1 2 3 ;
- set-insert gTEST_SET : 0 ;
- assert_equal $(gTEST_SET) : 1 2 3 0 ;
-}
-
-# equal-sets
-assert_equal [ equal-sets 1 2 3 : 3 2 2 1 ] : true ;
-assert_equal [ equal-sets 1 2 3 3 : 3 2 2 1 ] : true ;
-assert_equal [ equal-sets 1 2 3 3 4 : 3 2 2 1 ] : ;
-
-# segregate-overrides
-{
- local base = <a>b <c>d <e>f ;
- local overrides = <a>b <c>c <d>e <f>g ;
- segregate-overrides overrides : base ;
- assert_equal $(overrides) : <c>c <d>e <f>g ;
- assert_equal $(base) : <a>b <e>f ;
-}
-
-# select-properties
-{
- local TOOLS = gcc msvc ;
-
- local gRELEVANT_FEATURES(msvc) = <debug-symbols> <optimization> <inlining> <inline> <runtime-build> <runtime-link> <threading> <define> <undef> <include> <target-type> ;
- local gRELEVANT_FEATURES(gcc) = <runtime-link> <debug-symbols> <optimization> <inlining> <profiling> <define> <undef> <include> <shared-linkable> <target-type> ;
- local gFREE_FEATURES = <define> <undef> <include> ;
-
- local gBASE_PROPERTIES(msvc,debug) = <debug-symbols>on <inlining>off <optimization>off <runtime-build>debug <threading>single ;
- local gBASE_PROPERTIES(gcc,debug) = <debug-symbols>on <inlining>off <optimization>off <profiling>off <shared-linkable>false ;
- local gBASE_PROPERTIES(msvc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <runtime-build>release <threading>single ;
- local gBASE_PROPERTIES(gcc,release) = <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <profiling>off <shared-linkable>false ;
-
- local TEST_PROPERTIES = <inlining>off <define>FOO <*><release><inlining>on
- <debug><define>DEBUG <msvc><release><foo>bar
- <gcc><*><inlining>on
- <msvc><*><foo>baz
- <msvc><release><optimization>speed
- <msvc><*><optimization>off
- <*><debug><optimization>off
- ;
-
- assert_equal_sets [ select-properties gcc debug my-target : $(TEST_PROPERTIES) ]
- : <define>FOO <define>DEBUG <inlining>on <optimization>off ;
-
- assert_equal_sets [ select-properties gcc release my-target : $(TEST_PROPERTIES) ]
- : <define>FOO <inlining>on ;
-
- assert_equal_sets [ select-properties msvc debug my-target : $(TEST_PROPERTIES) ]
- : <define>FOO <define>DEBUG <inlining>off <optimization>off ;
-
- assert_equal_sets [ select-properties msvc release my-target : $(TEST_PROPERTIES) ]
- : <define>FOO <inlining>on <optimization>speed ;
-}
-
-
-# ungrist-properties
-feature TEST_FEATURE1 : a b ;
-feature TEST_FEATURE2 : c d ;
-assert_equal [ ungrist-properties <TEST_FEATURE1>a <TEST_FEATURE2>c ]
- : TEST_FEATURE1-a TEST_FEATURE2-c ;
-
-
-# fixup-path-properties
-{
- local RELATIVE_SUBDIR = foobar ;
- local gPATH_FEATURES = <include> ;
- assert_equal [ fixup-path-properties <a>b <include>.. <c>d ]
- : <include>foobar$(SLASH).. <a>b <c>d ;
-}
-# multiply-property-sets
-assert_equal [ multiply-property-sets <b>1 <a>2/3 <c>4/5 ]
- : <a>2/<b>1/<c>4 <a>2/<b>1/<c>5 <a>3/<b>1/<c>4 <a>3/<b>1/<c>5 ;
-
-# make-path-property-sets
-{
- local gUNGRISTED(<a>) = a ;
- local gUNGRISTED(<c>) = c ;
- local gUNGRISTED(<e>) = e ;
- local gUNGRISTED(<g>) = g ;
- local gUNGRISTED(<i>) = i ;
- assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : <e>f$(SLASH)<g>h <i>j ]
- : foo$(SLASH)bar$(SLASH)e-f$(SLASH)g-h$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<e>f$(SLASH)<g>h foo$(SLASH)bar$(SLASH)i-j$(SLASH)<a>b$(SLASH)<c>d$(SLASH)<i>j ;
- assert_equal [ make-path-property-sets foo$(SLASH)bar : <a>b <c>d : ]
- : foo$(SLASH)bar$(SLASH)<a>b$(SLASH)<c>d ;
-}
-
-
-# split-path-at-grist
-assert_equal
- [ split-path-at-grist <a>b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
- : <a>b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
-assert_equal
- [ split-path-at-grist b$(SLASH)c$(SLASH)<d>e$(SLASH)<f>g$(SLASH)h$(SLASH)i ]
- : b$(SLASH)c <d>e <f>g$(SLASH)h$(SLASH)i ;
-if $(NT)
-{
- assert_equal
- [ split-path-at-grist b\\c\\<include>e:\\f\\g\\<h>i ]
- : b\\c <include>e:\\f\\g <h>i ;
-}
-# directory-of
-assert_equal [ directory-of a$(SLASH)b c d$(SLASH)e$(SLASH)f ] : a . d$(SLASH)e ;
-
-# top-relative-tokens
-{
- local SUBDIR_TOKENS = a b c ;
- assert_equal [ top-relative-tokens ..$(SLASH)d$(SLASH)e ] : a b d e ;
-}
-
-# flags
-{
- local gBUILD_PROPERTIES = <a>b <c>d <e>f ;
- local FLAGS1 FLAGS2 FLAGS3 ;
- flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f <x>y <a>/<c> <e> : foobar ;
- assert_equal $(FLAGS1) : foobar b d f ;
- flags toolset FLAGS2 <a> : foobar ;
- assert_equal $(FLAGS2) : b ;
- flags toolset FLAGS1 <a>b/<c>d <a>b/<e>f : foobar ;
- assert_equal $(FLAGS1) : foobar b d f foobar ;
-}
-
-# get-BUILD
-{
- local DEFAULT_BUILD = a ;
- local BUILD = b ;
- assert_equal [ get-BUILD c <d>e ] : b ;
- BUILD = ;
- assert_equal [ get-BUILD c <d>e ] : c <d>e ;
- assert_equal [ get-BUILD ] : a ;
- assert_equal [ get-BUILD <d>e ] : <d>e a ;
- BUILD = <f>g ;
- assert_equal [ get-BUILD c <d>e ] : <f>g a ;
-}
-
-# strip-initial
-assert_equal [ strip-initial a b c : a b c d e f g ] : d e f g ;
-assert_equal [ strip-initial a b c : a b d e f g ] : a b d e f g ;
-assert_equal [ strip-initial a b c : b d e f g ] : b d e f g ;
-assert_equal [ strip-initial a b c : ] : ;
-
-# simplify-path-tokens
-{
- local $(gTOP)_TOKENS = .. .. .. ;
- local gINVOCATION_SUBDIR_TOKENS = d e ;
- assert_equal [ simplify-path-tokens a b . c .. .. d e ] : a d e ;
- assert_equal [ simplify-path-tokens a b .. .. .. d e ] : .. d e ;
- assert_equal [ simplify-path-tokens .. .. d e : xxx ] : .. .. d e ;
- assert_equal [ simplify-path-tokens a b .. .. : xxx ] : xxx ;
- $(gTOP)_TOKENS = .. .. ;
- assert_equal [ simplify-path-tokens .. .. d e : xxx ] : xxx ;
- assert_equal [ simplify-path-tokens .. .. d e f g : xxx ] : f g ;
-}

Modified: branches/release/tools/build/v2/test/unused.py
==============================================================================
--- branches/release/tools/build/v2/test/unused.py (original)
+++ branches/release/tools/build/v2/test/unused.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -17,11 +17,9 @@
 # The second invocation should do nothing, and produce no warning. The previous
 # invocation might have printed executed actions and other things, so it is not
 # easy to check if warning was issued or not.
-t.run_build_system()
-t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+t.run_build_system(stdout="")
 
-t.run_build_system("-sGENERATE_ONLY_UNUSABLE=1")
-t.fail_test(find(t.stdout(), "warning: Unused source { b.X } in main target ./a") == -1)
+t.run_build_system("-sGENERATE_ONLY_UNUSABLE=1", stdout="")
 
 # Now check that even if main target generates nothing, its usage requirements
 # are still propagated to dependants.

Modified: branches/release/tools/build/v2/test/unused/jamroot.jam
==============================================================================
--- branches/release/tools/build/v2/test/unused/jamroot.jam (original)
+++ branches/release/tools/build/v2/test/unused/jamroot.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -10,6 +10,7 @@
 import "class" : new ;
 import modules ;
 import targets ;
+import project ;
 
 
 type.register X : x ;
@@ -21,21 +22,23 @@
         basic-target.__init__ $(name) : $(project) ;
     }
         
- rule construct ( source-targets * : property-set )
+ rule construct ( name : source-targets * : property-set )
     {
         if [ modules.peek : GENERATE_NOTHING ]
         {
- return ;
+ return [ property-set.empty ] ;
         }
         else if [ modules.peek : GENERATE_ONLY_UNUSABLE ]
         {
- return [ virtual-target.from-file b.x : $(self.project) ]
+ return [ property-set.empty ]
+ [ virtual-target.from-file b.x : . : $(self.project) ]
               ;
         }
         else
         {
- return [ virtual-target.from-file b.x : $(self.project) ]
- [ virtual-target.from-file b.cpp : $(self.project) ]
+ return [ property-set.empty ]
+ [ virtual-target.from-file b.x : . : $(self.project) ]
+ [ virtual-target.from-file b.cpp : . : $(self.project) ]
                 ;
         }
     }
@@ -48,7 +51,7 @@
 
 rule make-b-main-target
 {
- local project = [ CALLER_MODULE ] ;
+ local project = [ project.current ] ;
     
     targets.main-target-alternative
       [ new test-target-class b : $(project) ] ;

Deleted: branches/release/tools/build/v2/test/v1_testing.py
==============================================================================
--- branches/release/tools/build/v2/test/v1_testing.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
+++ (empty file)
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2002 Dave Abrahams
-# Copyright 2004 Vladimir Prus
-# Distributed under the Boost Software License, Version 1.0.
-# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-
-import BoostBuild
-import os
-from string import strip
-import re
-import time
-
-def match_re(actual,expected):
- return re.match(expected,actual,re.DOTALL) != None
-
-t = BoostBuild.Tester(match = match_re, boost_build_path = os.path.join(os.getcwd(), ".."))
-t.set_tree('v1_testing')
-
-os.environ['TOOLS'] = 'gcc'
-os.environ['NOARSCAN'] = '1'
-
-# 1) No existing bin directories. Both build and test ran fine. As
-# expected, the residue files were a bit different: There was no
-# path_test.success, and path_test.test contained the word "passed"
-# instead of the path to the .cpp file. I've haven't looked yet to
-# see if the lack of the path is a problem for reporting, but
-# hopefully the information is trivially available somewhere else.
-t.run_build_system(arguments = 'test', status = 0)
-t.expect_addition(
- ['bin/compile.test/gcc/debug/runtime-link-dynamic/compile.test'
- , 'bin/nocompile.test/gcc/debug/runtime-link-dynamic/nocompile.test'
- , 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
- , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
- , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
-
-
-# 2) Missing source file for the library build. path_test.test was
-# deleted, so the reporting programs would know that failure
-# occurred. The stdout messages also indicated what had
-# happened. Excellent!
-t.rename('lib.cpp', 'lib.cpp.bak')
-t.run_build_system(arguments = 'test', status = 1)
-t.expect_removal(
- ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
- , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
- , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
-
-# 3) Missing file restored. Worked fine; path_test.test was recreated,
-# no other files were touched.
-t.rename('lib.cpp.bak', 'lib.cpp')
-t.run_build_system(arguments = 'test', status = 0)
-t.expect_addition(
- [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
- , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
- , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
- # I didn't add a test for 'no other files were touched', because
- # it's a little complicated. There is an expect_nothing_more()
- # function, but we actually need to spell out a lot more than
- # what we currently have to do that.
-
-# 4) Introduced error into one of the library files, causing a library build
-# compile to fail. path_test.test was deleted, so the reporting programs
-# would know that failure occurred. Excellent! This is the case that has
-# caused regression testing to report the wrong results in the past, so it
-# was good news to see it working correctly now. We probably should figure
-# out some other test cases just to be sure it is working for full coverage.
-t.rename('lib.cpp', 'lib.cpp.bak')
-t.rename('lib-err.cpp', 'lib.cpp')
-t.touch('lib.cpp')
-t.run_build_system(arguments = 'test', status=1)
-t.expect_removal(
- ['bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
- , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
- , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
-
-# 5) Fixed the error in the library file. The library build then worked, and
-# path_test.exe was relinked, without first recompiling path_test.obj. Test was
-# rerun. Exactly the right behavior!
-t.rename('lib.cpp.bak', 'lib.cpp')
-t.run_build_system(arguments = 'test', status = 0)
-t.expect_addition(
- [ 'bin/link.test/gcc/debug/runtime-link-dynamic/link.test'
- , 'bin/nolink.test/gcc/debug/runtime-link-dynamic/nolink.test'
- , 'bin/run.test/gcc/debug/runtime-link-dynamic/run.test'])
-
-t.cleanup()
-print 'testing complete'

Modified: branches/release/tools/build/v2/tools/auto-index.jam
==============================================================================
--- branches/release/tools/build/v2/tools/auto-index.jam (original)
+++ branches/release/tools/build/v2/tools/auto-index.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,8 +11,8 @@
 feature.feature auto-index-internal : off "on" ;
 feature.feature auto-index-verbose : off "on" ;
 feature.feature auto-index-no-duplicates : off "on" ;
-feature.feature auto-index-script : : free ;
-feature.feature auto-index-prefix : : free ;
+feature.feature auto-index-script : : free path ;
+feature.feature auto-index-prefix : : free path ;
 feature.feature auto-index-type : : free ;
 feature.feature auto-index-section-names : "on" off ;
 

Modified: branches/release/tools/build/v2/tools/boostbook.jam
==============================================================================
--- branches/release/tools/build/v2/tools/boostbook.jam (original)
+++ branches/release/tools/build/v2/tools/boostbook.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -336,6 +336,9 @@
     # Ubuntu Linux
     docbook-xsl-dir ?= [ path.glob /usr/share/xml/docbook/stylesheet : nwalsh ] ;
     docbook-dtd-dir ?= [ path.glob /usr/share/xml/docbook/schema/dtd : $(dtd-versions) ] ;
+
+ # SUSE
+ docbook-xsl-dir ?= [ path.glob /usr/share/xml/docbook/stylesheet/nwalsh : current ] ;
   }
 
   if $(docbook-xsl-dir)

Modified: branches/release/tools/build/v2/tools/builtin.py
==============================================================================
--- branches/release/tools/build/v2/tools/builtin.py (original)
+++ branches/release/tools/build/v2/tools/builtin.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -144,11 +144,20 @@
     feature.feature ('threading', ['single', 'multi'], ['propagated'])
     feature.feature ('rtti', ['on', 'off'], ['propagated'])
     feature.feature ('exception-handling', ['on', 'off'], ['propagated'])
+
+ # Whether there is support for asynchronous EH (e.g. catching SEGVs).
+ feature.feature ('asynch-exceptions', ['on', 'off'], ['propagated'])
+
+ # Whether all extern "C" functions are considered nothrow by default.
+ feature.feature ('extern-c-nothrow', ['off', 'on'], ['propagated'])
+
     feature.feature ('debug-symbols', ['on', 'off'], ['propagated'])
     feature.feature ('define', [], ['free'])
+ feature.feature ('undef', [], ['free'])
     feature.feature ('include', [], ['free', 'path']) #order-sensitive
     feature.feature ('cflags', [], ['free'])
     feature.feature ('cxxflags', [], ['free'])
+ feature.feature ('asmflags', [], ['free'])
     feature.feature ('linkflags', [], ['free'])
     feature.feature ('archiveflags', [], ['free'])
     feature.feature ('version', [], ['free'])
@@ -309,10 +318,6 @@
     variant ('release', ['<optimization>speed', '<debug-symbols>off', '<inlining>full',
                          '<runtime-debugging>off', '<define>NDEBUG'])
     variant ('profile', ['release'], ['<profiling>on', '<debug-symbols>on'])
-
- type.register ('H', ['h'])
- type.register ('HPP', ['hpp'], 'H')
- type.register ('C', ['c'])
     
 
 reset ()
@@ -348,8 +353,11 @@
 class CScanner (scanner.Scanner):
     def __init__ (self, includes):
         scanner.Scanner.__init__ (self)
-
- self.includes_ = includes
+
+ self.includes_ = []
+
+ for i in includes:
+ self.includes_.extend(i.split("&&"))
 
     def pattern (self):
         return r'#[ \t]*include[ ]*(<(.*)>|"(.*)")'
@@ -399,7 +407,7 @@
         SHARED_LIB.
     """
 
- def __init__(self, id = 'LibGenerator', composing = True, source_types = [], target_types_and_names = ['LIB'], requirements = []):
+ def __init__(self, id, composing = True, source_types = [], target_types_and_names = ['LIB'], requirements = []):
         generators.Generator.__init__(self, id, composing, source_types, target_types_and_names, requirements)
     
     def run(self, project, name, prop_set, sources):
@@ -432,7 +440,9 @@
     def viable_source_types(self):
         return ['*']
 
-generators.register(LibGenerator())
+generators.register(LibGenerator("builtin.lib-generator"))
+
+generators.override("builtin.prebuilt", "builtin.lib-generator")
 
 def lib(names, sources=[], requirements=[], default_build=[], usage_requirements=[]):
     """The implementation of the 'lib' rule. Beyond standard syntax that rule allows
@@ -508,22 +518,19 @@
 
 generators.register (SearchedLibGenerator ())
 
-### class prebuilt-lib-generator : generator
-### {
-### rule __init__ ( * : * )
-### {
-### generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
-### }
-###
-### rule run ( project name ? : prop_set : sources * : multiple ? )
-### {
-### local f = [ $(prop_set).get <file> ] ;
-### return $(f) $(sources) ;
-### }
-### }
-###
-### generators.register
-### [ new prebuilt-lib-generator builtin.prebuilt : : LIB : <file> ] ;
+class PrebuiltLibGenerator(generators.Generator):
+
+ def __init__(self, id, composing, source_types, target_types_and_names, requirements):
+ generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
+
+ def run(self, project, name, properties, sources):
+ f = properties.get("file")
+ return f + sources
+
+generators.register(PrebuiltLibGenerator("builtin.prebuilt", False, [],
+ ["LIB"], ["<file>"]))
+
+generators.override("builtin.prebuilt", "builtin.lib-generator")
 
 
 class CompileAction (virtual_target.Action):
@@ -565,9 +572,8 @@
         generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
         
     def run (self, project, name, prop_set, sources):
-
- lib_sources = prop_set.get('<library>')
- sources.extend(lib_sources)
+
+ sources.extend(prop_set.get('<library>'))
         
         # Add <library-path> properties for all searched libraries
         extra = []
@@ -576,38 +582,41 @@
                 search = s.search()
                 extra.extend(property.Property('<library-path>', sp) for sp in search)
 
- orig_xdll_path = []
-
- if prop_set.get('<hardcode-dll-paths>') == ['true'] \
- and type.is_derived(self.target_types_ [0], 'EXE'):
- xdll_path = prop_set.get('<xdll-path>')
- orig_xdll_path = [ replace_grist(x, '<dll-path>') for x in xdll_path ]
- # It's possible that we have libraries in sources which did not came
- # from 'lib' target. For example, libraries which are specified
- # just as filenames as sources. We don't have xdll-path properties
- # for such target, but still need to add proper dll-path properties.
- for s in sources:
+ # It's possible that we have libraries in sources which did not came
+ # from 'lib' target. For example, libraries which are specified
+ # just as filenames as sources. We don't have xdll-path properties
+ # for such target, but still need to add proper dll-path properties.
+ extra_xdll_path = []
+ for s in sources:
                 if type.is_derived (s.type (), 'SHARED_LIB') and not s.action ():
                     # Unfortunately, we don't have a good way to find the path
                     # to a file, so use this nasty approach.
                     p = s.project()
- location = path.root(s.name(), p.get('source-location'))
- xdll_path.append(path.parent(location))
-
- extra.extend(property.Property('<dll-path>', sp) for sp in xdll_path)
+ location = path.root(s.name(), p.get('source-location')[0])
+ extra_xdll_path.append(os.path.dirname(location))
+
+ # Hardcode DLL paths only when linking executables.
+ # Pros: do not need to relink libraries when installing.
+ # Cons: "standalone" libraries (plugins, python extensions) can not
+ # hardcode paths to dependent libraries.
+ if prop_set.get('<hardcode-dll-paths>') == ['true'] \
+ and type.is_derived(self.target_types_ [0], 'EXE'):
+ xdll_path = prop_set.get('<xdll-path>')
+ extra.extend(property.Property('<dll-path>', sp) \
+ for sp in extra_xdll_path)
+ extra.extend(property.Property('<dll-path>', sp) \
+ for sp in xdll_path)
         
         if extra:
- prop_set = prop_set.add_raw (extra)
-
+ prop_set = prop_set.add_raw (extra)
         result = generators.Generator.run(self, project, name, prop_set, sources)
-
+
         if result:
             ur = self.extra_usage_requirements(result, prop_set)
- ur = ur.add(property_set.create(orig_xdll_path))
+ ur = ur.add(property_set.create(['<xdll-path>' + p for p in extra_xdll_path]))
         else:
             return None
-
- return(ur, result)
+ return (ur, result)
     
     def extra_usage_requirements (self, created_targets, prop_set):
         
@@ -696,20 +705,18 @@
              
         return result
 
-### rule register-archiver ( id composing ? : source_types + : target_types + :
-### requirements * )
-### {
-### local g = [ new ArchiveGenerator $(id) $(composing) : $(source_types)
-### : $(target_types) : $(requirements) ] ;
-### generators.register $(g) ;
-### }
-###
-###
-### IMPORT $(__name__) : register-linker register-archiver
-### : : generators.register-linker generators.register-archiver ;
-###
-###
-###
+
+def register_archiver(id, source_types, target_types, requirements):
+ g = ArchiveGenerator(id, True, source_types, target_types, requirements)
+ generators.register(g)
+
+class DummyGenerator(generators.Generator):
+ """Generator that accepts everything and produces nothing. Useful as a general
+ fallback for toolset-specific actions like PCH generation.
+ """
+ def run (self, project, name, prop_set, sources):
+ return (property_set.empty(), [])
+
 
 get_manager().projects().add_rule("variant", variant)
 

Modified: branches/release/tools/build/v2/tools/cast.jam
==============================================================================
--- branches/release/tools/build/v2/tools/cast.jam (original)
+++ branches/release/tools/build/v2/tools/cast.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -11,7 +11,7 @@
 #
 # exe main : main.cpp [ cast _ moccable-cpp : widget.cpp ] ;
 #
-# Boost.Build will assing target type CPP to both main.cpp and widget.cpp. Then,
+# Boost.Build will assign target type CPP to both main.cpp and widget.cpp. Then,
 # the cast rule will change target type of widget.cpp to MOCCABLE-CPP, and Qt
 # support will run the MOC tool as part of the build process.
 #

Modified: branches/release/tools/build/v2/tools/common.jam
==============================================================================
--- branches/release/tools/build/v2/tools/common.jam (original)
+++ branches/release/tools/build/v2/tools/common.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -334,7 +334,7 @@
 # first path found. Otherwise, returns an empty string. If 'path-last' is
 # specified, PATH is searched after 'additional-paths'.
 #
-local rule find-tool ( name : additional-paths * : path-last ? )
+rule find-tool ( name : additional-paths * : path-last ? )
 {
     local path = [ path.programs-path ] ;
     local match = [ path.glob $(path) : $(name) $(name).exe ] ;
@@ -961,25 +961,22 @@
 {
     import assert ;
 
- local nl = "
-" ;
-
     local save-os = [ modules.peek os : .name ] ;
 
     modules.poke os : .name : LINUX ;
 
- assert.result "PATH=\"foo:bar:baz\"$(nl)export PATH$(nl)"
+ assert.result "PATH=\"foo:bar:baz\"\nexport PATH\n"
         : path-variable-setting-command PATH : foo bar baz ;
 
- assert.result "PATH=\"foo:bar:$PATH\"$(nl)export PATH$(nl)"
+ assert.result "PATH=\"foo:bar:$PATH\"\nexport PATH\n"
         : prepend-path-variable-command PATH : foo bar ;
 
     modules.poke os : .name : NT ;
 
- assert.result "set PATH=foo;bar;baz$(nl)"
+ assert.result "set PATH=foo;bar;baz\n"
         : path-variable-setting-command PATH : foo bar baz ;
 
- assert.result "set PATH=foo;bar;%PATH%$(nl)"
+ assert.result "set PATH=foo;bar;%PATH%\n"
         : prepend-path-variable-command PATH : foo bar ;
 
     modules.poke os : .name : $(save-os) ;

Modified: branches/release/tools/build/v2/tools/common.py
==============================================================================
--- branches/release/tools/build/v2/tools/common.py (original)
+++ branches/release/tools/build/v2/tools/common.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -53,7 +53,7 @@
     if OS == "NT":
         # On Windows the case and capitalization of PATH is not always predictable, so
         # let's find out what variable name was really set.
- for n in sys.environ:
+ for n in os.environ:
             if n.lower() == "path":
                 __executable_path_variable = n
                 break
@@ -99,7 +99,7 @@
     def __init__(self):
         self.used_ = set()
         self.all_ = set()
- self.params = {}
+ self.params_ = {}
 
     def register(self, id):
         """
@@ -113,7 +113,7 @@
             errors.error("common: the configuration '$(id)' is in use")
 
         if id not in self.all_:
- self.all_ += [id]
+ self.all_.add(id)
 
             # Indicate that a new configuration has been added.
             return True
@@ -133,7 +133,7 @@
             errors.error("common: the configuration '$(id)' is not known")
 
         if id not in self.used_:
- self.used_ += [id]
+ self.used_.add(id)
 
             # indicate that the configuration has been marked as 'used'
             return True
@@ -150,7 +150,7 @@
 
     def get(self, id, param):
         """ Returns the value of a configuration parameter. """
- self.params_.getdefault(param, {}).getdefault(id, None)
+ return self.params_.get(param, {}).get(id)
 
     def set (self, id, param, value):
         """ Sets the value of a configuration parameter. """
@@ -294,6 +294,8 @@
             #print "warning: initialized from" [ errors.nearest-user-location ] ;
     else:
         command = check_tool(user_provided_command)
+ assert(isinstance(command, list))
+ command=' '.join(command)
         if not command and __debug_configuration:
             print "warning: toolset", toolset, "initialization:"
             print "warning: can't find user-provided command", user_provided_command
@@ -347,7 +349,9 @@
         programs = path.programs_path()
         m = path.glob(programs, [command, command + '.exe' ])
         if not len(m):
- print "Could not find:", command, "in", programs
+ if __debug_configuration:
+ print "Could not find:", command, "in", programs
+ return None
         return os.path.dirname(m[0])
 
 # ported from trunk_at_47174

Modified: branches/release/tools/build/v2/tools/darwin.jam
==============================================================================
--- branches/release/tools/build/v2/tools/darwin.jam (original)
+++ branches/release/tools/build/v2/tools/darwin.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -231,7 +231,7 @@
     {
         if $(.debug-configuration)
         {
- ECHO notice: available sdk for $(condition)/<macosx-version>$(version-feature) at $(sdk) ;
+ ECHO notice: available sdk for $(condition)/<macosx-version>$(version-feature) at $(root) ;
         }
         
         # Add the version to the features for specifying them.
@@ -247,9 +247,9 @@
         # Set the flags the version needs to compile with, first
         # generic options.
         flags darwin.compile OPTIONS $(condition)/<macosx-version>$(version-feature)
- : -isysroot $(sdk) ;
+ : -isysroot $(root) ;
         flags darwin.link OPTIONS $(condition)/<macosx-version>$(version-feature)
- : -isysroot $(sdk) ;
+ : -isysroot $(root) ;
         
         # Then device variation options.
         switch $(version[1])
@@ -287,13 +287,28 @@
             }
         }
         
- return $(version-feature) ;
+ if $(version[3]) > 0
+ {
+ # We have a minor version of an SDK. We want to set up
+ # previous minor versions, plus the current minor version.
+ # So we recurse to set up the previous minor versions, up to
+ # the current version.
+ local minor-minus-1 = [ CALC $(version[3]) - 1 ] ;
+ return
+ [ init-sdk $(condition) : $(root)
+ : $(version[1-2]) $(minor-minus-1) : [ version-to-feature $(version[1-2]) $(minor-minus-1) ] ]
+ $(version-feature) ;
+ }
+ else
+ {
+ return $(version-feature) ;
+ }
     }
     else if $(version[4])
     {
         # We have a patch version of an SDK. We want to set up
         # both the specific patch version, and the minor version.
- # So we recurse to set up the minor version. Plus the minor version.
+ # So we recurse to set up the patch version. Plus the minor version.
         return
             [ init-sdk $(condition) : $(root)
                 : $(version[1-3]) : [ version-to-feature $(version[1-3]) ] ]
@@ -498,7 +513,7 @@
 flags darwin.compile OPTIONS <link>shared : -dynamic ;
 
 # Misc options.
-flags darwin.compile OPTIONS : -no-cpp-precomp -gdwarf-2 -fexceptions ;
+flags darwin.compile OPTIONS : -gdwarf-2 -fexceptions ;
 #~ flags darwin.link OPTIONS : -fexceptions ;
 
 # Add the framework names to use.

Modified: branches/release/tools/build/v2/tools/docutils.jam
==============================================================================
--- branches/release/tools/build/v2/tools/docutils.jam (original)
+++ branches/release/tools/build/v2/tools/docutils.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -56,6 +56,7 @@
         .setup = [
           common.prepend-path-variable-command PYTHONPATH
             : $(.docutils-dir) $(.docutils-dir)/extras ] ;
+ RST2XXX = [ common.find-tool rst2html ] ;
     }
 }
 

Modified: branches/release/tools/build/v2/tools/gcc.jam
==============================================================================
--- branches/release/tools/build/v2/tools/gcc.jam (original)
+++ branches/release/tools/build/v2/tools/gcc.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -446,13 +446,17 @@
         }
         else
         {
- if $(model) = 32
+ local arch = [ feature.get-values architecture : $(properties) ] ;
+ if $(arch) != arm
             {
- option = -m32 ;
- }
- else if $(model) = 64
- {
- option = -m64 ;
+ if $(model) = 32
+ {
+ option = -m32 ;
+ }
+ else if $(model) = 64
+ {
+ option = -m64 ;
+ }
             }
             # For darwin, the model can be 32_64. darwin.jam will handle that
             # on its own.
@@ -1097,9 +1101,10 @@
 #
 # x86 and compatible
 # The 'native' option appeared in gcc 4.2 so we cannot safely use it
-# as default. Use conservative i386 instead.
+# as default. Use conservative i386 instead for 32-bit.
+toolset.flags gcc OPTIONS <architecture>x86/<address-model>32/<instruction-set> : -march=i386 ;
 cpu-flags gcc OPTIONS : x86 : native : -march=native ;
-cpu-flags gcc OPTIONS : x86 : i386 : -march=i386 : default ;
+cpu-flags gcc OPTIONS : x86 : i386 : -march=i386 ;
 cpu-flags gcc OPTIONS : x86 : i486 : -march=i486 ;
 cpu-flags gcc OPTIONS : x86 : i586 : -march=i586 ;
 cpu-flags gcc OPTIONS : x86 : i686 : -march=i686 ;

Modified: branches/release/tools/build/v2/tools/gcc.py
==============================================================================
--- branches/release/tools/build/v2/tools/gcc.py (original)
+++ branches/release/tools/build/v2/tools/gcc.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -23,13 +23,16 @@
 import bjam
 
 from b2.tools import unix, common, rc, pch, builtin
-from b2.build import feature, type, toolset, generators
+from b2.build import feature, type, toolset, generators, property_set
+from b2.build.property import Property
 from b2.util.utility import os_name, on_windows
 from b2.manager import get_manager
 from b2.build.generators import Generator
 from b2.build.toolset import flags
 from b2.util.utility import to_seq
 
+
+
 __debug = None
 
 def debug():
@@ -222,12 +225,12 @@
         # Find the header in sources. Ignore any CPP sources.
         header = None
         for s in sources:
- if type.is_derived(s.type, 'H'):
+ if type.is_derived(s.type(), 'H'):
                 header = s
 
         # Error handling: Base header file name should be the same as the base
         # precompiled header name.
- header_name = header.name
+ header_name = header.name()
         header_basename = os.path.basename(header_name).rsplit('.', 1)[0]
         if header_basename != name:
             location = project.project_module
@@ -239,14 +242,15 @@
 
         # return result of base class and pch-file property as usage-requirements
         # FIXME: what about multiple results from generator.run?
- return (property_set.create('<pch-file>' + pch_file[0], '<cflags>-Winvalid-pch'),
+ return (property_set.create([Property('pch-file', pch_file[0]),
+ Property('cflags', '-Winvalid-pch')]),
                 pch_file)
 
     # Calls the base version specifying source's name as the name of the created
     # target. As result, the PCH will be named whatever.hpp.gch, and not
     # whatever.gch.
     def generated_targets(self, sources, prop_set, project, name = None):
- name = sources[0].name
+ name = sources[0].name()
         return Generator.generated_targets(self, sources,
             prop_set, project, name)
 

Modified: branches/release/tools/build/v2/tools/intel-win.jam
==============================================================================
--- branches/release/tools/build/v2/tools/intel-win.jam (original)
+++ branches/release/tools/build/v2/tools/intel-win.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -161,8 +161,8 @@
 
     if ! $(compatibility)
     {
- # If there's no backend version, assume 7.1.
- compatibility = vc7.1 ;
+ # If there's no backend version, assume 10.
+ compatibility = vc10 ;
     }
 
     local extract-version = [ MATCH ^vc(.*) : $(compatibility) ] ;

Modified: branches/release/tools/build/v2/tools/msvc.jam
==============================================================================
--- branches/release/tools/build/v2/tools/msvc.jam (original)
+++ branches/release/tools/build/v2/tools/msvc.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -736,7 +736,11 @@
             # version from the path.
             # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
             # 9.0express as 9.0 here.
- if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
+ if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ]
+ {
+ version = 11.0 ;
+ }
+ else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
             {
                 version = 10.0 ;
             }
@@ -1351,7 +1355,7 @@
 
 
 # Known toolset versions, in order of preference.
-.known-versions = 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;
+.known-versions = 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ;
 
 # Version aliases.
 .version-alias-6 = 6.0 ;
@@ -1360,6 +1364,7 @@
 .version-alias-8 = 8.0 ;
 .version-alias-9 = 9.0 ;
 .version-alias-10 = 10.0 ;
+.version-alias-11 = 11.0 ;
 
 # Names of registry keys containing the Visual C++ installation path (relative
 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
@@ -1372,6 +1377,7 @@
 .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
 .version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
 .version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
+.version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
 
 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
 # The environment variable 'VCToolkitInstallDir' and the default installation

Copied: branches/release/tools/build/v2/tools/msvc.py (from r75722, /trunk/tools/build/v2/tools/msvc.py)
==============================================================================
--- /trunk/tools/build/v2/tools/msvc.py (original)
+++ branches/release/tools/build/v2/tools/msvc.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -646,6 +646,8 @@
             # version from the path.
             # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
             # 9.0express as 9.0 here.
+ if re.search("Microsoft Visual Studio 11", command):
+ version = '11.0'
             if re.search("Microsoft Visual Studio 10", command):
                 version = '10.0'
             elif re.search("Microsoft Visual Studio 9", command):
@@ -1154,7 +1156,7 @@
 
 
 # Known toolset versions, in order of preference.
-_known_versions = ['10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
+_known_versions = ['11.0', '10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
 
 # Version aliases.
 __version_alias_6 = '6.0'
@@ -1163,6 +1165,7 @@
 __version_alias_8 = '8.0'
 __version_alias_9 = '9.0'
 __version_alias_10 = '10.0'
+__version_alias_11 = '11.0'
 
 # Names of registry keys containing the Visual C++ installation path (relative
 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
@@ -1175,6 +1178,7 @@
 __version_9_0express_reg = "VCExpress\\9.0\\Setup\\VC"
 __version_10_0_reg = "VisualStudio\\10.0\\Setup\\VC"
 __version_10_0express_reg = "VCExpress\\10.0\\Setup\\VC"
+__version_11_0_reg = "VisualStudio\\11.0\\Setup\\VC"
 
 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
 # The environment variable 'VCToolkitInstallDir' and the default installation
@@ -1192,1188 +1196,3 @@
 
 # And finally trigger the actual Boost Build toolset registration.
 register_toolset()
-# Copyright (c) 2003 David Abrahams.
-# Copyright (c) 2005 Vladimir Prus.
-# Copyright (c) 2005 Alexey Pakhunov.
-# Copyright (c) 2006 Bojan Resnik.
-# Copyright (c) 2006 Ilya Sokolov.
-# Copyright (c) 2007 Rene Rivera
-# Copyright (c) 2008 Jurko Gospodnetic
-#
-# Use, modification and distribution is subject to the Boost Software
-# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
-# http://www.boost.org/LICENSE_1_0.txt)
-
-################################################################################
-#
-# MSVC Boost Build toolset module.
-# --------------------------------
-#
-# All toolset versions need to have their location either auto-detected or
-# explicitly specified except for the special 'default' version that expects the
-# environment to find the needed tools or report an error.
-#
-################################################################################
-
-import os
-import os.path
-import re
-import _winreg
-
-import bjam
-
-from b2.tools import common, rc, pch, builtin
-from b2.build import feature, type, toolset, generators, property_set
-from b2.build.property import Property
-from b2.util import path
-from b2.util.utility import on_windows
-from b2.manager import get_manager
-from b2.build.generators import Generator
-from b2.build.toolset import flags
-from b2.util.utility import to_seq
-from b2.tools.common import Configurations
-
-__debug = None
-
-def debug():
- global __debug
- if __debug is None:
- __debug = "--debug-configuration" in bjam.variable("ARGV")
- return __debug
-
-
-type.register('MANIFEST', ['manifest'])
-feature.feature('embed-manifest',['on','off'], ['incidental', 'propagated']) ;
-
-type.register('PDB','pdb')
-
-################################################################################
-#
-# Public rules.
-#
-################################################################################
-
-# Initialize a specific toolset version configuration. As the result, path to
-# compiler and, possible, program names are set up, and will be used when that
-# version of compiler is requested. For example, you might have:
-#
-# using msvc : 6.5 : cl.exe ;
-# using msvc : 7.0 : Y:/foo/bar/cl.exe ;
-#
-# The version parameter may be ommited:
-#
-# using msvc : : Z:/foo/bar/cl.exe ;
-#
-# The following keywords have special meanings when specified as versions:
-# - all - all detected but not yet used versions will be marked as used
-# with their default options.
-# - default - this is an equivalent to an empty version.
-#
-# Depending on a supplied version, detected configurations and presence 'cl.exe'
-# in the path different results may be achieved. The following table describes
-# the possible scenarios:
-#
-# Nothing "x.y"
-# Passed Nothing "x.y" detected, detected,
-# version detected detected cl.exe in path cl.exe in path
-#
-# default Error Use "x.y" Create "default" Use "x.y"
-# all None Use all None Use all
-# x.y - Use "x.y" - Use "x.y"
-# a.b Error Error Create "a.b" Create "a.b"
-#
-# "x.y" - refers to a detected version;
-# "a.b" - refers to an undetected version.
-#
-# FIXME: Currently the command parameter and the <compiler> property parameter
-# seem to overlap in duties. Remove this duplication. This seems to be related
-# to why someone started preparing to replace init with configure rules.
-
-def init(version = None, command = None, options = None):
- # When initialized from
- # using msvc : x.0 ;
- # we get version as a single element list i.e. ['x.0'],
- # but when specified from the command line we get a string i.e. 'x.0'.
- # We want to work with a string, so unpack the list if needed.
- is_single_element_list = (isinstance(version,list) and len(version) == 1)
- assert(version==None or isinstance(version,str) or is_single_element_list)
- if is_single_element_list:
- version = version[0]
-
- options = to_seq(options)
- command = to_seq(command)
-
- if command:
- options.append("<command>"+command)
- configure(version,options)
-
-def configure(version=None, options=None):
- if version == "all":
- if options:
- raise RuntimeError("MSVC toolset configuration: options should be empty when '{}' is specified.".format(version))
-
- # Configure (i.e. mark as used) all registered versions.
- all_versions = _versions.all()
- if not all_versions:
- if debug():
- print "notice: [msvc-cfg] Asked to configure all registered" \
- "msvc toolset versions when there are none currently" \
- "registered." ;
- else:
- for v in all_versions:
- # Note that there is no need to skip already configured
- # versions here as this will request configure-really rule
- # to configure the version using default options which will
- # in turn cause it to simply do nothing in case the version
- # has already been configured.
- configure_really(v)
- elif version == "default":
- configure_really(None,options)
- else:
- configure_really(version, options)
-
-def extend_conditions(conditions,exts):
- return [ cond + '/' + ext for cond in conditions for ext in exts ]
-
-def configure_version_specific(toolset_arg, version, conditions):
- # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
- # /Zc:wchar_t options that improve C++ standard conformance, but those
- # options are off by default. If we are sure that the msvc version is at
- # 7.*, add those options explicitly. We can be sure either if user specified
- # version 7.* explicitly or if we auto-detected the version ourselves.
- if not re.match('^6\\.', version):
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',conditions, ['/Zc:forScope','/Zc:wchar_t'])
- toolset.flags('{}.compile.c++'.format(toolset_arg), 'C++FLAGS',conditions, ['/wd4675'])
-
- # Explicitly disable the 'function is deprecated' warning. Some msvc
- # versions have a bug, causing them to emit the deprecation warning even
- # with /W0.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',extend_conditions(conditions,['<warnings>off']), ['/wd4996'])
- if re.match('^[78]\\.', version):
- # 64-bit compatibility warning deprecated since 9.0, see
- # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',extend_conditions(conditions,['<warnings>all']), ['/Wp64'])
-
- #
- # Processor-specific optimization.
- #
- if re.match('^[67]', version ):
- # 8.0 deprecates some of the options.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>speed','<optimization>space']), ['/Ogiy', '/Gs'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>speed']), ['/Ot'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>space']), ['/Os'])
-
- global _cpu_arch_i386
- cpu_arch_i386_cond = extend_conditions(conditions, _cpu_arch_i386)
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>']),['/GB'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>i386']),['/G3'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>i486']),['/G4'])
-
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in _cpu_type_g5]), ['/G5'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in _cpu_type_g6]), ['/G6'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in _cpu_type_g7]), ['/G7'])
-
- # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
- # tests will fail.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', conditions, ['/Op'])
-
- # 7.1 and below have single-threaded static RTL.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>off/<runtime-link>static/<threading>single']), ['/ML'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>on/<runtime-link>static/<threading>single']), ['/MLd'])
- else:
- # 8.0 and above adds some more options.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' for a in _cpu_arch_amd64]), ['/favor:blend'])
-
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' + t for a in _cpu_arch_amd64 for t in _cpu_type_em64t]), ['/favor:EM64T'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' + t for a in _cpu_arch_amd64 for t in _cpu_type_amd64]), ['/favor:AMD64'])
-
- # 8.0 and above only has multi-threaded static RTL.
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>off/<runtime-link>static/<threading>single']), ['/MT'])
- toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>on/<runtime-link>static/<threading>single']), ['/MTd'])
-
- # Specify target machine type so the linker will not need to guess.
- toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions,_cpu_arch_amd64), ['/MACHINE:X64'])
- toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions,_cpu_arch_i386), ['/MACHINE:X86'])
- toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions,_cpu_arch_ia64), ['/MACHINE:IA64'])
-
- # Make sure that manifest will be generated even if there is no
- # dependencies to put there.
- toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions,["<embed-manifest>off"]), ['/MANIFEST'])
-
-
-# Registers this toolset including all of its flags, features & generators. Does
-# nothing on repeated calls.
-
-def register_toolset():
- if not 'msvc' in feature.values('toolset'):
- register_toolset_really()
-
-
-engine = get_manager().engine()
-
-# this rule sets up the pdb file that will be used when generating static
-# libraries and the debug-store option is database, so that the compiler
-# puts all debug info into a single .pdb file named after the library
-#
-# Poking at source targets this way is probably not clean, but it's the
-# easiest approach.
-def archive(targets, sources=None, properties=None):
- assert( len( targets ) == 1 )
- bjam.call('set-target-variable',targets,'PDB_NAME', os.path.splitext(targets[0])[0] + '.pdb')
-
-# Declare action for creating static libraries. If library exists, remove it
-# before adding files. See
-# http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
-if on_windows():
- engine.register_action(
- 'msvc.archive',
- '''if exist "$(<[1])" DEL "$(<[1])"
- $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
- function=archive)
-else:
- engine.register_action(
- 'msvc.archive',
- '''{rm} "$(<[1])"
- $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"'''.format(rm=common.rm_command()),
- function=archive)
-
-# For the assembler the following options are turned on by default:
-#
-# -Zp4 align structures to 4 bytes
-# -Cp preserve case of user identifiers
-# -Cx preserve case in publics, externs
-#
-engine.register_action(
- 'msvc.compile.asm',
- '$(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"' )
-
-
-# Equivalent to [ on $(target) return $(prefix)$(var)$(suffix) ]. Note that $(var) can be a list.
-def expand_target_variable(target,var,prefix=None,suffix=None):
- list = bjam.call( 'get-target-variable', target, var )
- return " ".join([ ("" if prefix is None else prefix) + elem + ("" if suffix is None else suffix) for elem in list ])
-
-
-def get_rspline(targets, lang_opt):
- result = lang_opt + ' ' + \
- expand_target_variable(targets, 'UNDEFS', '-U' ) + ' ' + \
- expand_target_variable(targets, 'CFLAGS' ) + ' ' + \
- expand_target_variable(targets, 'OPTIONS' ) + ' -c ' + \
- expand_target_variable(targets, 'DEFINES', '\n-D' ) + ' ' + \
- expand_target_variable(targets, 'INCLUDES:W', '\n"-I', '"' )
- bjam.call('set-target-variable', targets, 'CC_RSPLINE', result)
-
-def compile_c(targets, sources = [], properties = None):
- get_manager().engine().set_target_variable( targets[1], 'C++FLAGS', '' )
- get_rspline(targets, '-TC')
- sources += bjam.call('get-target-variable',targets,'PCH_FILE')
- sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
- compile_c_cpp(targets,sources)
-
-def compile_c_preprocess(targets, sources = [], properties = None):
- get_manager().engine().set_target_variable( target[1], 'C++FLAGS', '' )
- get_rspline(targets, '-TC')
- sources += bjam.call('get-target-variable',targets,'PCH_FILE')
- sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
- preprocess_c_cpp(targets,sources)
-
-def compile_c_pch(targets, sources = [], properties = []):
- get_manager().engine().set_target_variable( target[1], 'C++FLAGS', '' )
- get_rspline([targets[1]], '-TC')
- get_rspline([targets[2]], '-TC')
- pch_source = bjam.call('get-target-variable', targets, 'PCH_SOURCE')
- sources += pch_source
- if pch_source:
- get_manager().engine().add_dependency(targets,pch_source)
- compile_c_cpp_pch_s(targets,sources)
- else:
- compile_c_cpp_pch(targets,sources)
-
-toolset.flags( 'msvc', 'YLOPTION', None, ['-Yl'] )
-
-def compile_cpp(targets,sources=[],properties=None):
- get_rspline(targets,'-TP')
- sources += bjam.call('get-target-variable',targets,'PCH_FILE')
- sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
- compile_c_cpp(targets,sources)
-
-def compile_cpp_preprocess(targets,sources=[],properties=None):
- get_rspline(targets,'-TP')
- sources += bjam.call('get-target-variable',targets,'PCH_FILE')
- sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
- preprocess_c_cpp(targets,sources)
-
-def compile_cpp_pch(targets,sources=[],properties=None):
- get_rspline([targets[1]], '-TP')
- get_rspline([targets[2]], '-TP')
- pch_source = bjam.call('get-target-variable', targets, 'PCH_SOURCE')
- sources += pch_source
- if pch_source:
- get_manager().engine().add_dependency(targets,pch_source)
- compile_c_cpp_pch_s(targets,sources)
- else:
- compile_c_cpp_pch(targets,sources)
-
-
-# Action for running the C/C++ compiler without using precompiled headers.
-#
-# WARNING: Synchronize any changes this in action with intel-win
-#
-# Notes regarding PDB generation, for when we use <debug-symbols>on/<debug-store>database
-#
-# 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring that the /Fd flag is dropped if PDB_CFLAG is empty
-#
-# 2. When compiling executables's source files, PDB_NAME is set on a per-source file basis by rule compile-c-c++.
-# The linker will pull these into the executable's PDB
-#
-# 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb for each source file by rule archive,
-# as in this case the compiler must be used to create a single PDB for our library.
-#
-
-compile_action = '$(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)'
-engine.register_action(
- 'msvc.compile.c',
- compile_action,
- function=compile_c,
- bound_list=['PDB_NAME'])
-
-engine.register_action(
- 'msvc.compile.c++',
- compile_action,
- function=compile_cpp,
- bound_list=['PDB_NAME'])
-
-
-preprocess_action = '$(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"'
-
-engine.register_action(
- 'msvc.preprocess.c',
- preprocess_action,
- function=compile_c_preprocess,
- bound_list=['PDB_NAME'])
-
-engine.register_action(
- 'msvc.preprocess.c++',
- preprocess_action,
- function=compile_cpp_preprocess,
- bound_list=['PDB_NAME'])
-
-def compile_c_cpp(targets,sources=None):
- pch_header = bjam.call('get-target-variable',targets[0],'PCH_HEADER')
- pch_file = bjam.call('get-target-variable',targets[0],'PCH_FILE')
- if pch_header: get_manager().engine().add_dependency(targets[0],pch_header)
- if pch_file: get_manager().engine().add_dependency(targets[0],pch_file)
- # This used to be
- # PDB_NAME on $(<) = $(<:S=.pdb) ;
- # I believe this means that $(<) must contain a single target. Lets assert and see.
- assert( len( targets ) == 1 )
- bjam.call('set-target-variable',targets,'PDB_NAME', os.path.splitext(targets[0])[0] + '.pdb')
-
-def preprocess_c_cpp(targets,sources=None):
- #same as above
- return compile_c_cpp(targets,sources)
-
-# Action for running the C/C++ compiler using precompiled headers. In addition
-# to whatever else it needs to compile, this action also adds a temporary source
-# .cpp file used to compile the precompiled headers themselves.
-
-pch_action = '''$(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include \\"$(>[1]:D=)\\"\n)" $(.CC.FILTER)'''
-
-engine.register_action(
- 'msvc.compile.c.pch',
- pch_action,
- function=compile_c_pch)
-
-engine.register_action(
- 'msvc.compile.c++.pch',
- pch_action,
- function=compile_cpp_pch)
-
-
-# Action for running the C/C++ compiler using precompiled headers. An already
-# built source file for compiling the precompiled headers is expected to be
-# given as one of the source parameters.
-# TODO(JI): This is currently unused because I did not see any direct way to
-# implement this. In old BB the rule was first, and could change the action
-# that was to be executed. Now the action comes first and decides on the rule
-# i.e. function.
-engine.register_action(
- 'compile-c-c++-pch-s',
- '$(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER)')
-
-
-# See midl.py for details.
-#
-engine.register_action(
- 'msvc.compile.idl',
- '''$(.IDL) /nologo @"@($(<[1]:W).rsp:E=
-"$(>:W)"
--D$(DEFINES)
-"-I$(INCLUDES:W)"
--U$(UNDEFS)
-$(MIDLFLAGS)
-/tlb "$(<[1]:W)"
-/h "$(<[2]:W)"
-/iid "$(<[3]:W)"
-/proxy "$(<[4]:W)"
-/dlldata "$(<[5]:W)")"
- {touch} "$(<[4]:W)"
- {touch} "$(<[5]:W)"'''.format(touch=common.file_creation_command()))
-
-engine.register_action(
- 'msvc.compile.mc',
- '$(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"')
-
-engine.register_action(
- 'msvc.compile.rc',
- '$(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"')
-
-def link(targets,sources=None,properties=None):
- if '<embed-manifest>on' in properties:
- manifest(targets,sources,properties)
-
-def link_dll(targets,sources=None,properties=None):
- get_manager().engine().add_dependency(targets,bjam.call('get-target-variable',targets,'DEF_FILE'))
- if '<embed-manifest>on' in properties:
- manifest_dll(targets,sources,properties)
-
-
-# Incremental linking a DLL causes no end of problems: if the actual exports do
-# not change, the import .lib file is never updated. Therefore, the .lib is
-# always out-of-date and gets rebuilt every time. I am not sure that incremental
-# linking is such a great idea in general, but in this case I am sure we do not
-# want it.
-
-# Windows manifest is a new way to specify dependencies on managed DotNet
-# assemblies and Windows native DLLs. The manifests are embedded as resources
-# and are useful in any PE target (both DLL and EXE).
-
-if on_windows():
- engine.register_action(
- 'msvc.link',
- '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-$(LIBRARIES)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
- if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
- function=link,
- bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
-
- engine.register_action(
- 'msvc.manifest',
- '''if exist "$(<[1]).manifest" (
- $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
- )''')
-
- engine.register_action(
- 'msvc.link.dll',
- '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-$(LIBRARIES)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
- if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
- function=link_dll,
- bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
-
- engine.register_action(
- 'msvc.manifest.dll',
- '''if exist "$(<[1]).manifest" (
- $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
- )''')
-else:
- engine.register_action(
- 'msvc.link',
- '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-$(LIBRARIES)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
- function=link,
- bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
-
- engine.register_action(
- 'msvc.manifest',
- '''if test -e "$(<[1]).manifest"; then
- $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
- fi''')
-
- engine.register_action(
- 'msvc.link.dll',
- '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
-"$(>)"
-$(LIBRARIES_MENTIONED_BY_FILE)
-$(LIBRARIES)
-"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
-"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
- function=link_dll,
- bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
-
- engine.register_action(
- 'msvc.manifest.dll',
- '''if test -e "$(<[1]).manifest"; then
- $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
- fi''')
-
-
-################################################################################
-#
-# Classes.
-#
-################################################################################
-
-class MsvcPchGenerator(pch.PchGenerator):
-
- # Inherit the __init__ method
-
- def run_pch(self, project, name, prop_set, sources):
- # Find the header in sources. Ignore any CPP sources.
- pch_header = None
- pch_source = None
- for s in sources:
- if type.is_derived(s.type(), 'H'):
- pch_header = s
- elif type.is_derived(s.type(), 'CPP') or type.is_derived(s.type(), 'C'):
- pch_source = s
-
- if not pch-header:
- raise RuntimeError( "can not build pch without pch-header" )
-
- # If we do not have the PCH source - that is fine. We will just create a
- # temporary .cpp file in the action.
- temp_prop_set = property_set.create([Property('pch-source',pch_source)]+prop_set.all())
- generated = Generator.run(project,name,temp_prop_set,pch_header)
- pch_file = None
- for g in generated:
- if type.is_derived(g.type(), 'PCH'):
- pch_file = g
- return property_set.create([Property('pch-header',pch_header),Property('pch-file',pch_file)]+generated)
-
-
-################################################################################
-#
-# Local rules.
-#
-################################################################################
-
-# Detects versions listed as '_known_versions' by checking registry information,
-# environment variables & default paths. Supports both native Windows and
-# Cygwin.
-def auto_detect_toolset_versions():
- for version in _known_versions:
- versionVarName = '_version_{}_reg'.format(version.replace('.','_'))
- vc_path = None
- if versionVarName in globals():
- for x in [ '', 'Wow6432Node\\' ]:
- try:
- with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\{}{}'.format(x, globals()[versionVarName])) as reg_key:
- vc_path = _winreg.QueryValue( reg_key, "ProductDir" )
- except:
- pass
- if vc_path:
- vc_path = os.path.join(vc_path,'bin')
- register_configuration(version,os.path.normpath(vc_path))
-
- global _versions
- for i in _known_versions:
- if not i in _versions.all():
- register_configuration(i,default_path(i))
-
-
-# Worker rule for toolset version configuration. Takes an explicit version id or
-# nothing in case it should configure the default toolset version (the first
-# registered one or a new 'default' one in case no toolset versions have been
-# registered yet).
-#
-
-def configure_really(version=None,options=[]):
- global _versions
- v = version
- if not v:
- # Take the first registered (i.e. auto-detected) version.
- version = _versions.all()[0]
-
- # Note: 'version' can still be empty at this point if no versions have
- # been auto-detected.
- if not version:
- version = "default"
-
- # Version alias -> real version number.
- if "_version_alias_{}".format(version) in globals():
- version = globals()["_version_alias_{}".format(version)]
-
- # Check whether the selected configuration is already in use.
- if version in _versions.used():
- # Allow multiple 'toolset.using' calls for the same configuration if the
- # identical sets of options are used.
- if options and options != _versions.get(version,'options'):
- raise RuntimeError("MSVC toolset configuration: Toolset version '$(version)' already configured.".format(version))
- else:
- # Register a new configuration.
- _versions.register(version)
-
- # Add user-supplied to auto-detected options.
- version_opts = _versions.get(version,'options')
- if (version_opts):
- options = version_opts + options
-
- # Mark the configuration as 'used'.
- _versions.use(version)
- # Generate conditions and save them.
- conditions = common.check_init_parameters('msvc', None, ('version', v))
- _versions.set(version,'conditions',conditions)
- command = feature.get_values('<command>',options)
-
- # If version is specified, we try to search first in default paths, and
- # only then in PATH.
- command = common.get_invocation_command('msvc','cl.exe',command,default_paths(version))
- common.handle_options("msvc",conditions,command,options)
-
- if not version:
- # Even if version is not explicitly specified, try to detect the
- # version from the path.
- # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
- # 9.0express as 9.0 here.
- if re.search("Microsoft Visual Studio 10", command):
- version = '10.0'
- elif re.search("Microsoft Visual Studio 9", command):
- version = '9.0'
- elif re.search("Microsoft Visual Studio 8", command):
- version = '8.0'
- elif re.search("NET 2003[\/\\]VC7", command):
- version = '7.1'
- elif re.search("Microsoft Visual C\\+\\+ Toolkit 2003", command):
- version = '7.1toolkit'
- elif re.search(".NET[\/\\]VC7", command):
- version = '7.0'
- else:
- version = '6.0'
-
- # Generate and register setup command.
-
- below_8_0 = re.search("^[67]\\.",version) != None
-
- if below_8_0:
- cpu = ['i386']
- else:
- cpu = ['i386', 'amd64', 'ia64']
-
- setup_scripts = {}
-
- if command:
- # TODO: Note that if we specify a non-existant toolset version then
- # this rule may find and use a corresponding compiler executable
- # belonging to an incorrect toolset version. For example, if you
- # have only MSVC 7.1 installed, have its executable on the path and
- # specify you want Boost Build to use MSVC 9.0, then you want Boost
- # Build to report an error but this may cause it to silently use the
- # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
- # toolset version.
- command = common.get_absolute_tool_path(command)
-
- if command:
- parent = os.path.split(os.path.normpath(command))[0]
- # Setup will be used if the command name has been specified. If
- # setup is not specified explicitly then a default setup script will
- # be used instead. Setup scripts may be global or arhitecture/
- # /platform/cpu specific. Setup options are used only in case of
- # global setup scripts.
-
- # Default setup scripts provided with different VC distributions:
- #
- # VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
- # builds. It was located in the bin folder for the regular version
- # and in the root folder for the free VC 7.1 tools.
- #
- # Later 8.0 & 9.0 versions introduce separate platform specific
- # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
- # located in or under the bin folder. Most also include a global
- # vcvarsall.bat helper script located in the root folder which runs
- # one of the aforementioned vcvars*.bat scripts based on the options
- # passed to it. So far only the version coming with some PlatformSDK
- # distributions does not include this top level script but to
- # support those we need to fall back to using the worker scripts
- # directly in case the top level script can not be found.
-
- global_setup = feature.get_values('<setup>',options)
- if global_setup:
- global_setup = global_setup[0]
- else:
- global_setup = None
-
- if not below_8_0 and not global_setup:
- global_setup = locate_default_setup(command,parent,'vcvarsall.bat')
-
- default_setup_amd64 = 'vcvarsx86_amd64.bat'
- default_setup_i386 = 'vcvars32.bat'
- default_setup_ia64 = 'vcvarsx86_ia64.bat'
-
- # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
- # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
- # mention an x86_IPF option, that seems to be a documentation bug
- # and x86_ia64 is the correct option.
- default_global_setup_options_amd64 = 'x86_amd64'
- default_global_setup_options_i386 = 'x86'
- default_global_setup_options_ia64 = 'x86_ia64'
-
- somehow_detect_the_itanium_platform = None
- # When using 64-bit Windows, and targeting 64-bit, it is possible to
- # use a native 64-bit compiler, selected by the "amd64" & "ia64"
- # parameters to vcvarsall.bat. There are two variables we can use --
- # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
- # 'x86' when running 32-bit Windows, no matter which processor is
- # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
- # Windows.
- #
- if re.search( 'AMD64', os.environ[ "PROCESSOR_ARCHITECTURE" ] ) != None:
- default_global_setup_options_amd64 = 'amd64'
- # TODO: The same 'native compiler usage' should be implemented for
- # the Itanium platform by using the "ia64" parameter. For this
- # though we need someone with access to this platform who can find
- # out how to correctly detect this case.
- elif somehow_detect_the_itanium_platform:
- default_global_setup_options_ia64 = 'ia64'
-
- setup_prefix = "call "
- setup_suffix = """ >nul\n"""
- if not on_windows():
- setup_prefix = "cmd.exe /S /C call "
- setup_suffix = " \">nul\" \"&&\" "
-
- locals()[ 'setup_i386' ] = "Pero"
- for c in cpu:
- setup_options = None
- setup_cpu = feature.get_values('<setup-{}>'.format(c),options)
-
- if not setup_cpu:
- if global_setup:
- setup_cpu = global_setup
- # If needed we can easily add using configuration flags
- # here for overriding which options get passed to the
- # global setup command for which target platform:
- # setup_options = feature.get_values('<setup-options-{}>'.format(c),options)
- if not setup_options:
- setup_options = locals()[ 'default_global_setup_options_{}'.format(c) ]
- else:
- setup_cpu = locate_default_setup(command,parent,globals()['default_setup_{}'.format(c)])
-
- # Cygwin to Windows path translation.
- # setup-$(c) = "\""$(setup-$(c):W)"\"" ;
-
- # Append setup options to the setup name and add the final setup
- # prefix & suffix.
- setup_scripts['setup_' + c] = '{}"{}" {}{}'.format(setup_prefix, setup_cpu, setup_options, setup_suffix)
-
- # Get tool names (if any) and finish setup.
- compiler = feature.get_values("<compiler>", options)
- if not compiler:
- compiler = "cl"
-
- linker = feature.get_values("<linker>", options)
- if not linker:
- linker = "link"
-
- resource_compiler = feature.get_values("<resource-compiler>", options)
- if not resource_compiler:
- resource_compiler = "rc"
-
- # Turn on some options for i386 assembler
- # -coff generate COFF format object file (compatible with cl.exe output)
- default_assembler_amd64 = 'ml64'
- default_assembler_i386 = 'ml -coff'
- default_assembler_ia64 = 'ias'
-
- assembler = feature.get_values('<assembler>',options)
-
- idl_compiler = feature.get_values('<idl-compiler>',options)
- if not idl_compiler:
- idl_compiler = 'midl'
-
- mc_compiler = feature.get_values('<mc-compiler>',options)
- if not mc_compiler:
- mc_compiler = 'mc'
-
- manifest_tool = feature.get_values('<manifest-tool>',options)
- if not manifest_tool:
- manifest_tool = 'mt'
-
- cc_filter = feature.get_values('<compiler-filter>',options)
-
- for c in cpu:
- cpu_conditions = [ condition + '/' + arch for arch in globals()['_cpu_arch_{}'.format(c)] for condition in conditions ]
-
- setup_script = setup_scripts['setup_{}'.format(c)]
-
- if debug():
- for cpu_condition in cpu_conditions:
- print "notice: [msvc-cfg] condition: '{}', setup: '{}'".format(cpu_condition,setup_script)
-
- cpu_assembler = assembler
- if not cpu_assembler:
- cpu_assembler = locals()['default_assembler_{}'.format(c)]
-
- toolset.flags('msvc.compile', '.CC' , cpu_conditions, ['{}{} /Zm800 -nologo' .format(setup_script, compiler)])
- toolset.flags('msvc.compile', '.RC' , cpu_conditions, ['{}{} -nologo' .format(setup_script, resource_compiler)])
- toolset.flags('msvc.compile', '.ASM', cpu_conditions, ['{}{} ' .format(setup_script, cpu_assembler)])
- toolset.flags('msvc.link' , '.LD' , cpu_conditions, ['{}{} /NOLOGO /INCREMENTAL:NO'.format(setup_script, linker)])
- toolset.flags('msvc.archive', '.LD' , cpu_conditions, ['{}{} /lib /NOLOGO' .format(setup_script, linker)])
- toolset.flags('msvc.compile', '.IDL', cpu_conditions, ['{}{} ' .format(setup_script, idl_compiler)])
- toolset.flags('msvc.compile', '.MC' , cpu_conditions, ['{}{} ' .format(setup_script, mc_compiler)])
- toolset.flags('msvc.link' , '.MT' , cpu_conditions, ['{}{} -nologo' .format(setup_script, manifest_tool)])
-
- if cc_filter:
- toolset.flags('msvc', '.CC.FILTER', cpu_conditions, ['"|" {}'.format(cc_filter)])
-
- # Set version-specific flags.
- configure_version_specific('msvc', version, conditions)
-
-
-# Returns the default installation path for the given version.
-#
-def default_path(version):
- global _versions
- # Use auto-detected path if possible.
- options = _versions.get(version, 'options')
- tmp_path = None
- if options:
- tmp_path = feature.get_values('<command>', options)
-
- if tmp_path:
- tmp_path=os.path.split(path)[0]
- else:
- env_var_var_name = '_version_{}_env'.format(version.replace('.','_'))
- vc_path = None
- if env_var_var_name in globals():
- env_var_name = globals()[env_var_var_name]
- if env_var_name in os.environ:
- vc_path = os.environ[env_var_name]
- if vc_path:
- vc_path = os.path.join(vc_path,globals()['_version_{}_envpath'.format(version.replace('.','_'))])
- tmp_path = os.path.normpath(vc_path)
-
- var_name = '_version_{}_path'.format(version.replace('.','_'))
- if not tmp_path and var_name in globals():
- tmp_path = os.path.normpath(os.path.join('c:\\Program Files', globals()[var_name]))
- return tmp_path
-
-
-# Returns either the default installation path (if 'version' is not empty) or
-# list of all known default paths (if no version is given)
-#
-def default_paths(version = None):
- possible_paths = []
- if version:
- path = default_path(version)
- if path:
- possible_paths.append(path)
- else:
- for i in _known_versions:
- path = default_path(i)
- if path:
- possible_paths.append(path)
- return possible_paths
-
-
-class MsvcLinkingGenerator(builtin.LinkingGenerator):
- # Calls the base version. If necessary, also create a target for the
- # manifest file.specifying source's name as the name of the created
- # target. As result, the PCH will be named whatever.hpp.gch, and not
- # whatever.gch.
- def generated_targets(self, sources, prop_set, project, name):
- result = builtin.LinkingGenerator.generated_targets(self, sources, prop_set, project, name)
- if result:
- name_main = result[0].name()
- action = result[0].action()
-
- if prop_set.get('<debug-symbols>') == 'on':
- # We force exact name on PDB. The reason is tagging -- the tag rule may
- # reasonably special case some target types, like SHARED_LIB. The tag rule
- # will not catch PDB, and it cannot even easily figure if PDB is paired with
- # SHARED_LIB or EXE or something else. Because PDB always get the
- # same name as the main target, with .pdb as extension, just force it.
- target = FileTarget(name_main.split_ext()[0]+'.pdb','PDB',project,action,True)
- registered_target = virtual_target.register(target)
- if target != registered_target:
- action.replace_targets(target,registered_target)
- result.append(registered_target)
- if prop_set.get('<embed-manifest>') == 'off':
- # Manifest is evil target. It has .manifest appened to the name of
- # main target, including extension. E.g. a.exe.manifest. We use 'exact'
- # name because to achieve this effect.
- target = FileTarget(name_main+'.manifest', 'MANIFEST', project, action, True)
- registered_target = virtual_target.register(target)
- if target != registered_target:
- action.replace_targets(target,registered_target)
- result.append(registered_target)
- return result
-
-
-# Unsafe worker rule for the register-toolset() rule. Must not be called
-# multiple times.
-
-def register_toolset_really():
- feature.extend('toolset', ['msvc'])
-
- # Intel and msvc supposedly have link-compatible objects.
- feature.subfeature( 'toolset', 'msvc', 'vendor', 'intel', ['propagated', 'optional'])
-
- # Inherit MIDL flags.
- toolset.inherit_flags('msvc', 'midl')
-
- # Inherit MC flags.
- toolset.inherit_flags('msvc','mc')
-
- # Dynamic runtime comes only in MT flavour.
- toolset.add_requirements(['<toolset>msvc,<runtime-link>shared:<threading>multi'])
-
- # Declare msvc toolset specific features.
- feature.feature('debug-store', ['object', 'database'], ['propagated'])
- feature.feature('pch-source', [], ['dependency', 'free'])
-
- # Declare generators.
-
- # TODO: Is it possible to combine these? Make the generators
- # non-composing so that they do not convert each source into a separate
- # .rsp file.
- generators.register(MsvcLinkingGenerator('msvc.link', False, ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ['EXE'], ['<toolset>msvc']))
- generators.register(MsvcLinkingGenerator('msvc.link.dll', False, ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ['SHARED_LIB','IMPORT_LIB'], ['<toolset>msvc']))
-
- builtin.register_archiver('msvc.archive', ['OBJ'], ['STATIC_LIB'], ['<toolset>msvc'])
- builtin.register_c_compiler('msvc.compile.c++', ['CPP'], ['OBJ'], ['<toolset>msvc'])
- builtin.register_c_compiler('msvc.compile.c', ['C'], ['OBJ'], ['<toolset>msvc'])
- builtin.register_c_compiler('msvc.compile.c++.preprocess', ['CPP'], ['PREPROCESSED_CPP'], ['<toolset>msvc'])
- builtin.register_c_compiler('msvc.compile.c.preprocess', ['C'], ['PREPROCESSED_C'], ['<toolset>msvc'])
-
- # Using 'register-c-compiler' adds the build directory to INCLUDES.
- builtin.register_c_compiler('msvc.compile.rc', ['RC'], ['OBJ(%_res)'], ['<toolset>msvc'])
- generators.override('msvc.compile.rc', 'rc.compile.resource')
- generators.register_standard('msvc.compile.asm', ['ASM'], ['OBJ'], ['<toolset>msvc'])
-
- # TODO(JI): requires porting midl.jam
- #builtin.register_c_compiler('msvc.compile.idl', ['IDL'], ['MSTYPELIB', 'H', 'C(%_i)', 'C(%_proxy)', 'C(%_dlldata)'], ['<toolset>msvc'])
- #generators.override('msvc.compile.idl', 'midl.compile.idl')
-
- # TODO(JI): requires porting mc.jam
- #generators.register_standard('msvc.compile.mc', ['MC'], ['H','RC'], ['<toolset>msvc'])
- #generators.override('msvc.compile.mc', 'mc.compile')
-
- # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
- # the latter have their HPP type derived from H. The type of compilation
- # is determined entirely by the destination type.
- generators.register(MsvcPchGenerator('msvc.compile.c.pch', False, ['H'], ['C_PCH','OBJ'], ['<pch>on', '<toolset>msvc']))
- generators.register(MsvcPchGenerator('msvc.compile.c++.pch', False, ['H'], ['CPP_PCH','OBJ'], ['<pch>on', '<toolset>msvc']))
-
- generators.override('msvc.compile.c.pch', 'pch.default-c-pch-generator')
- generators.override('msvc.compile.c++.pch', 'pch.default-cpp-pch-generator')
-
- toolset.flags('msvc.compile', 'PCH_FILE' , ['<pch>on'], ['<pch-file>' ])
- toolset.flags('msvc.compile', 'PCH_SOURCE', ['<pch>on'], ['<pch-source>'])
- toolset.flags('msvc.compile', 'PCH_HEADER', ['<pch>on'], ['<pch-header>'])
-
- #
- # Declare flags for compilation.
- #
- toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>speed'], ['/O2'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>space'], ['/O1'])
-
- toolset.flags('msvc.compile', 'CFLAGS', [ a + '/<instruction-set>' + t for a in _cpu_arch_ia64 for t in _cpu_type_itanium ], ['/G1'])
- toolset.flags('msvc.compile', 'CFLAGS', [ a + '/<instruction-set>' + t for a in _cpu_arch_ia64 for t in _cpu_type_itanium2 ], ['/G2'])
-
- toolset.flags('msvc.compile', 'CFLAGS', ['<debug-symbols>on/<debug-store>object'], ['/Z7'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<debug-symbols>on/<debug-store>database'], ['/Zi'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>off'], ['/Od'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>off'], ['/Ob0'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>on'], ['/Ob1'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>full'], ['/Ob2'])
-
- toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>on'], ['/W3'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>off'], ['/W0'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>all'], ['/W4'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<warnings-as-errors>on'], ['/WX'])
-
- toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off'], ['/EHs'])
- toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on'], ['/EHsc'])
- toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off'], ['/EHa'])
- toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on'], ['/EHac'])
-
- # By default 8.0 enables rtti support while prior versions disabled it. We
- # simply enable or disable it explicitly so we do not have to depend on this
- # default behaviour.
- toolset.flags('msvc.compile', 'CFLAGS', ['<rtti>on'], ['/GR'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<rtti>off'], ['/GR-'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>off/<runtime-link>shared'], ['/MD'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>on/<runtime-link>shared'], ['/MDd'])
-
- toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>off/<runtime-link>static/<threading>multi'], ['/MT'])
- toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>on/<runtime-link>static/<threading>multi'], ['/MTd'])
-
- toolset.flags('msvc.compile', 'OPTIONS', ['<cflags>'])
- toolset.flags('msvc.compile.c++', 'OPTIONS', ['<cxxflags>'])
-
- toolset.flags('msvc.compile', 'PDB_CFLAG', ['<debug-symbols>on/<debug-store>database'],['/Fd'])
-
- toolset.flags('msvc.compile', 'DEFINES', ['<define>'])
- toolset.flags('msvc.compile', 'UNDEFS', ['<undef>'])
- toolset.flags('msvc.compile', 'INCLUDES', ['<include>'])
-
- # Declare flags for the assembler.
- toolset.flags('msvc.compile.asm', 'USER_ASMFLAGS', ['<asmflags>'])
-
- toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<debug-symbols>on'], ['/Zi', '/Zd'])
-
- toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>on'], ['/W3'])
- toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>off'], ['/W0'])
- toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>all'], ['/W4'])
- toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings-as-errors>on'], ['/WX'])
-
- toolset.flags('msvc.compile.asm', 'DEFINES', ['<define>'])
-
- # Declare flags for linking.
- toolset.flags('msvc.link', 'PDB_LINKFLAG', ['<debug-symbols>on/<debug-store>database'], ['/PDB']) # not used yet
- toolset.flags('msvc.link', 'LINKFLAGS', ['<debug-symbols>on'], ['/DEBUG'])
- toolset.flags('msvc.link', 'DEF_FILE', ['<def-file>'])
-
- # The linker disables the default optimizations when using /DEBUG so we
- # have to enable them manually for release builds with debug symbols.
- toolset.flags('msvc', 'LINKFLAGS', ['<debug-symbols>on/<runtime-debugging>off'], ['/OPT:REF,ICF'])
-
- toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>console'], ['/subsystem:console'])
- toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>gui'], ['/subsystem:windows'])
- toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>wince'], ['/subsystem:windowsce'])
- toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>native'], ['/subsystem:native'])
- toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>auto'], ['/subsystem:posix'])
-
- toolset.flags('msvc.link', 'OPTIONS', ['<linkflags>'])
- toolset.flags('msvc.link', 'LINKPATH', ['<library-path>'])
-
- toolset.flags('msvc.link', 'FINDLIBS_ST', ['<find-static-library>'])
- toolset.flags('msvc.link', 'FINDLIBS_SA', ['<find-shared-library>'])
- toolset.flags('msvc.link', 'LIBRARY_OPTION', ['<toolset>msvc'])
- toolset.flags('msvc.link', 'LIBRARIES_MENTIONED_BY_FILE', ['<library-file>'])
-
- toolset.flags('msvc.archive', 'AROPTIONS', ['<archiveflags>'])
-
-
-# Locates the requested setup script under the given folder and returns its full
-# path or nothing in case the script can not be found. In case multiple scripts
-# are found only the first one is returned.
-#
-# TODO: There used to exist a code comment for the msvc.init rule stating that
-# we do not correctly detect the location of the vcvars32.bat setup script for
-# the free VC7.1 tools in case user explicitly provides a path. This should be
-# tested or simply remove this whole comment in case this toolset version is no
-# longer important.
-#
-def locate_default_setup(command, parent, setup_name):
- for setup in [os.path.join(dir,setup_name) for dir in [command,parent]]:
- if os.path.exists(setup):
- return setup
- return None
-
-
-# Validates given path, registers found configuration and prints debug
-# information about it.
-#
-def register_configuration(version, path=None):
- if path:
- command = os.path.join(path, 'cl.exe')
- if os.path.exists(command):
- if debug():
- print "notice: [msvc-cfg] msvc-$(version) detected, command: ''".format(version,command)
- _versions.register(version)
- _versions.set(version,'options',['<command>{}'.format(command)])
-
-
-################################################################################
-#
-# Startup code executed when loading this module.
-#
-################################################################################
-
-# List of all registered configurations.
-_versions = Configurations()
-
-# Supported CPU architectures.
-_cpu_arch_i386 = [
- '<architecture>/<address-model>',
- '<architecture>/<address-model>32',
- '<architecture>x86/<address-model>',
- '<architecture>x86/<address-model>32']
-
-_cpu_arch_amd64 = [
- '<architecture>/<address-model>64',
- '<architecture>x86/<address-model>64']
-
-_cpu_arch_ia64 = [
- '<architecture>ia64/<address-model>',
- '<architecture>ia64/<address-model>64']
-
-
-# Supported CPU types (only Itanium optimization options are supported from
-# VC++ 2005 on). See
-# http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
-# detailed information.
-_cpu_type_g5 = ['i586', 'pentium', 'pentium-mmx' ]
-_cpu_type_g6 = ['i686', 'pentiumpro', 'pentium2', 'pentium3', 'pentium3m', 'pentium-m', 'k6',
- 'k6-2', 'k6-3', 'winchip-c6', 'winchip2', 'c3', 'c3-2' ]
-_cpu_type_em64t = ['prescott', 'nocona', 'conroe', 'conroe-xe', 'conroe-l', 'allendale', 'mermon',
- 'mermon-xe', 'kentsfield', 'kentsfield-xe', 'penryn', 'wolfdale',
- 'yorksfield', 'nehalem' ]
-_cpu_type_amd64 = ['k8', 'opteron', 'athlon64', 'athlon-fx']
-_cpu_type_g7 = ['pentium4', 'pentium4m', 'athlon', 'athlon-tbird', 'athlon-4', 'athlon-xp'
- 'athlon-mp'] + _cpu_type_em64t + _cpu_type_amd64
-_cpu_type_itanium = ['itanium', 'itanium1', 'merced']
-_cpu_type_itanium2 = ['itanium2', 'mckinley']
-
-
-# Known toolset versions, in order of preference.
-_known_versions = ['10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
-
-# Version aliases.
-_version_alias_6 = '6.0'
-_version_alias_6_5 = '6.0'
-_version_alias_7 = '7.0'
-_version_alias_8 = '8.0'
-_version_alias_9 = '9.0'
-_version_alias_10 = '10.0'
-
-# Names of registry keys containing the Visual C++ installation path (relative
-# to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
-_version_6_0_reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++"
-_version_7_0_reg = "VisualStudio\\7.0\\Setup\\VC"
-_version_7_1_reg = "VisualStudio\\7.1\\Setup\\VC"
-_version_8_0_reg = "VisualStudio\\8.0\\Setup\\VC"
-_version_8_0express_reg = "VCExpress\\8.0\\Setup\\VC"
-_version_9_0_reg = "VisualStudio\\9.0\\Setup\\VC"
-_version_9_0express_reg = "VCExpress\\9.0\\Setup\\VC"
-_version_10_0_reg = "VisualStudio\\10.0\\Setup\\VC"
-_version_10_0express_reg = "VCExpress\\10.0\\Setup\\VC"
-
-# Visual C++ Toolkit 2003 does not store its installation path in the registry.
-# The environment variable 'VCToolkitInstallDir' and the default installation
-# path will be checked instead.
-_version_7_1toolkit_path = 'Microsoft Visual C++ Toolkit 2003\\bin'
-_version_7_1toolkit_env = 'VCToolkitInstallDir'
-
-# Path to the folder containing "cl.exe" relative to the value of the
-# corresponding environment variable.
-_version_7_1toolkit_envpath = 'bin' ;
-#
-#
-# Auto-detect all the available msvc installations on the system.
-auto_detect_toolset_versions()
-
-# And finally trigger the actual Boost Build toolset registration.
-register_toolset()

Modified: branches/release/tools/build/v2/tools/pch.py
==============================================================================
--- branches/release/tools/build/v2/tools/pch.py (original)
+++ branches/release/tools/build/v2/tools/pch.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -29,6 +29,7 @@
 # ;
 
 from b2.build import type, feature, generators
+from b2.tools import builtin
 
 type.register('PCH', ['pch'])
 type.register('C_PCH', [], 'PCH')
@@ -48,7 +49,7 @@
         from being run unless it's being used for a top-level PCH target.
     """
     def action_class(self):
- return 'compile-action'
+ return builtin.CompileAction
 
     def run(self, project, name, prop_set, sources):
         if not name:
@@ -65,7 +66,7 @@
             pass
         else:
             r = self.run_pch(project, name,
- prop_set.add_raw('<define>BOOST_BUILD_PCH_ENABLED'),
+ prop_set.add_raw(['<define>BOOST_BUILD_PCH_ENABLED']),
                  sources)
             return generators.add_usage_requirements(
                 r, ['<define>BOOST_BUILD_PCH_ENABLED'])
@@ -74,10 +75,9 @@
     def run_pch(self, project, name, prop_set, sources):
         pass
 
-#FIXME: dummy-generator in builtins.jam needs to be ported.
 # NOTE: requirements are empty, default pch generator can be applied when
 # pch=off.
-###generators.register(
-### [ new dummy-generator pch.default-c-pch-generator : : C_PCH ] ;
-###generators.register
-### [ new dummy-generator pch.default-cpp-pch-generator : : CPP_PCH ] ;
+generators.register(builtin.DummyGenerator(
+ "pch.default-c-pch-generator", False, [], ['C_PCH'], []))
+generators.register(builtin.DummyGenerator(
+ "pch.default-cpp-pch-generator", False, [], ['CPP_PCH'], []))

Modified: branches/release/tools/build/v2/tools/python.jam
==============================================================================
--- branches/release/tools/build/v2/tools/python.jam (original)
+++ branches/release/tools/build/v2/tools/python.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -1178,7 +1178,7 @@
 
         property-set = [ $(property-set).add-raw <dependency>$(other-pythons) ] ;
 
- result = [ construct-result $(python) $(extensions) $(new-sources) :
+ return [ construct-result $(python) $(extensions) $(new-sources) :
             $(project) $(name) : $(property-set) ] ;
     }
 }

Modified: branches/release/tools/build/v2/tools/stage.jam
==============================================================================
--- branches/release/tools/build/v2/tools/stage.jam (original)
+++ branches/release/tools/build/v2/tools/stage.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -263,7 +263,7 @@
             }
         }
         DELETE_MODULE $(result) ;
- result = [ sequence.unique $(result2) ] ;
+ return [ sequence.unique $(result2) ] ;
     }
 
     # Returns true iff 'type' is subtype of some element of 'types-to-include'.

Modified: branches/release/tools/build/v2/tools/stage.py
==============================================================================
--- branches/release/tools/build/v2/tools/stage.py (original)
+++ branches/release/tools/build/v2/tools/stage.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -224,7 +224,7 @@
     return virtual_target.FileTarget(name, source.type(), project, a, exact=True)
 
 def relink_file(project, source, ps):
- action = source.action()
+ action = source[0].action()
     cloned_action = virtual_target.clone_action(action, project, "", ps)
     targets = cloned_action.targets()
     # We relink only on Unix, where exe or shared lib is always a single file.

Modified: branches/release/tools/build/v2/tools/types/__init__.py
==============================================================================
--- branches/release/tools/build/v2/tools/types/__init__.py (original)
+++ branches/release/tools/build/v2/tools/types/__init__.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,6 +5,7 @@
     'html',
     'lib',
     'obj',
+ 'preprocessed',
     'rsp',
 ]
 

Modified: branches/release/tools/build/v2/tools/types/cpp.py
==============================================================================
--- branches/release/tools/build/v2/tools/types/cpp.py (original)
+++ branches/release/tools/build/v2/tools/types/cpp.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -5,6 +5,9 @@
 from b2.build import type
 
 def register ():
- type.register_type ('CPP', ['cpp', 'cxx', 'cc'])
+ type.register_type('CPP', ['cpp', 'cxx', 'cc'])
+ type.register_type('H', ['h'])
+ type.register_type('HPP', ['hpp'], 'H')
+ type.register_type('C', ['c'])
 
 register ()

Copied: branches/release/tools/build/v2/tools/types/preprocessed.py (from r75722, /trunk/tools/build/v2/tools/types/preprocessed.py)
==============================================================================
--- /trunk/tools/build/v2/tools/types/preprocessed.py (original)
+++ branches/release/tools/build/v2/tools/types/preprocessed.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -9,14 +9,3 @@
     type.register_type('PREPROCESSED_CPP', ['ii'], 'CPP')
 
 register ()
-# Copyright David Abrahams 2004. Distributed under the Boost
-# Software License, Version 1.0. (See accompanying
-# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-from b2.build import type
-
-def register ():
- type.register_type ('PREPROCESSED_C', ['i'], 'C')
- type.register_type ('PREPROCESSED_CPP', ['ii'], 'CPP')
-
-register ()

Modified: branches/release/tools/build/v2/tools/unix.py
==============================================================================
--- branches/release/tools/build/v2/tools/unix.py (original)
+++ branches/release/tools/build/v2/tools/unix.py 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -58,8 +58,8 @@
     def optional_properties (self):
         return self.requirements ()
               
- def run (self, project, name, prop_set, sources, multiple):
- result = SearchedLibGenerator.run (project, name, prop_set, sources, multiple)
+ def run (self, project, name, prop_set, sources):
+ result = SearchedLibGenerator.run (project, name, prop_set, sources)
         
         set_library_order (sources, prop_set, result)
         
@@ -69,10 +69,10 @@
     def __init__ (self, id, composing, source_types, target_types_and_names, requirements):
         generators.Generator.__init__ (self, id, composing, source_types, target_types_and_names, requirements)
 
- def run (self, project, name, prop_set, sources, multiple):
+ def run (self, project, name, prop_set, sources):
         f = prop_set.get ('<file>')
         set_library_order_aux (f, sources)
- return (f, sources)
+ return f + sources
 
 ### # The derived toolset must specify their own rules and actions.
 # FIXME: restore?

Modified: branches/release/tools/build/v2/util/doc.jam
==============================================================================
--- branches/release/tools/build/v2/util/doc.jam (original)
+++ branches/release/tools/build/v2/util/doc.jam 2012-04-25 23:35:55 EDT (Wed, 25 Apr 2012)
@@ -670,7 +670,7 @@
     while ! $(syntax) && ! [ MATCH "^[$(ws)]*(#)" : $(line) ] && $($(var))
     {
         local m = [ MATCH "^[$(ws)]*(.*)$" : $(line) ] ;
- if $(m) && ! $(m) = ""
+ if $(m)
         {
             syntax = $(m) ;
         }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk