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 ( !