[pkg-boost-commits] r13928 - in boost-jam/trunk: . debian modules

Domenico Andreoli cavok at costa.debian.org
Thu Dec 22 12:04:39 UTC 2005


Author: cavok
Date: 2005-12-22 12:04:37 +0000 (Thu, 22 Dec 2005)
New Revision: 13928

Modified:
   boost-jam/trunk/Jambase
   boost-jam/trunk/boost-jam.spec
   boost-jam/trunk/build.bat
   boost-jam/trunk/build.jam
   boost-jam/trunk/build.sh
   boost-jam/trunk/builtins.c
   boost-jam/trunk/builtins.h
   boost-jam/trunk/class.c
   boost-jam/trunk/class.h
   boost-jam/trunk/compile.c
   boost-jam/trunk/debian/copyright
   boost-jam/trunk/execcmd.h
   boost-jam/trunk/execnt.c
   boost-jam/trunk/execunix.c
   boost-jam/trunk/expand.c
   boost-jam/trunk/filemac.c
   boost-jam/trunk/filent.c
   boost-jam/trunk/filesys.h
   boost-jam/trunk/fileunix.c
   boost-jam/trunk/frames.h
   boost-jam/trunk/index.html
   boost-jam/trunk/jam.c
   boost-jam/trunk/jam.h
   boost-jam/trunk/jambase.c
   boost-jam/trunk/make.c
   boost-jam/trunk/make1.c
   boost-jam/trunk/modules.c
   boost-jam/trunk/modules.h
   boost-jam/trunk/modules/order.c
   boost-jam/trunk/modules/path.c
   boost-jam/trunk/modules/property-set.c
   boost-jam/trunk/modules/regex.c
   boost-jam/trunk/modules/sequence.c
   boost-jam/trunk/modules/set.c
   boost-jam/trunk/native.c
   boost-jam/trunk/native.h
   boost-jam/trunk/option.c
   boost-jam/trunk/patchlevel.h
   boost-jam/trunk/pathunix.c
   boost-jam/trunk/pwd.c
   boost-jam/trunk/pwd.h
   boost-jam/trunk/rules.c
   boost-jam/trunk/rules.h
   boost-jam/trunk/strings.c
   boost-jam/trunk/strings.h
   boost-jam/trunk/variable.c
   boost-jam/trunk/variable.h
   boost-jam/trunk/w32_getreg.c
Log:
successfully merged with upstream 3.1.11

Modified: boost-jam/trunk/Jambase
===================================================================
--- boost-jam/trunk/Jambase	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/Jambase	2005-12-22 12:04:37 UTC (rev 13928)
@@ -51,8 +51,15 @@
     BOOST_BUILD_PATH = /usr/share/boost-build ;
 }
 
+    
+rule _poke ( module-name ? : variables + : value * )
+{
+    module $(<)
+    {
+        $(>) = $(3) ;
+    }
+}
 
-
 # This rule can be invoked from an optional user's boost-build.jam
 # file to both indicate where to find the build system files, and to
 # load them. The path indicated is relative to the location of the
@@ -74,6 +81,12 @@
     #
     BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;
     
+    # We might have just modified the *global* value of BOOST_BUILD_PATH.
+    # The code that loads the rest of Boost.Build, in particular the 
+    # site-config.jam and user-config.jam files uses os.environ, so we need to
+    # update the value there.    
+    _poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;
+            
     # Try to find the build system bootstrap file 'bootstrap.jam'.
     #
     local bootstrap-file =
@@ -101,8 +114,7 @@
         ECHO "notice: loading Boost.Build from" 
           [ NORMALIZE_PATH $(.bootstrap-file:D) ] ;
     }
-    
-    
+           
     # Load the build system, now that we know where to start from.
     #
     include $(.bootstrap-file) ;
@@ -126,13 +138,7 @@
         [ GLOB $(search-path) : boost-build.jam ] ;
     
     .boost-build-file = $(boost-build-files[1]) ;
-    
-    if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
-    {
-        ECHO "notice: found boost-build.jam at" 
-          [ NORMALIZE_PATH $(.boost-build-file) ] ;
-    }
-        
+            
     # There is no boost-build.jam we can find, exit with an error, and information.
     #
     if ! $(.boost-build-file)
@@ -153,6 +159,12 @@
         EXIT "Please consult the documentation at 'http://www.boost.org'." ;
     }
     
+    if [ MATCH .*(--debug-configuration).* : $(ARGV) ]      
+    {
+        ECHO "notice: found boost-build.jam at" 
+             [ NORMALIZE_PATH $(.boost-build-file) ] ;
+    }
+    
     # Now load the boost-build.jam to get the build system loaded. This
     # incidentaly loads the users jamfile and attempts to build targets.
     #

Modified: boost-jam/trunk/boost-jam.spec
===================================================================
--- boost-jam/trunk/boost-jam.spec	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/boost-jam.spec	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,5 +1,5 @@
 Name: boost-jam
-Version: 3.1.10
+Version: 3.1.11
 Summary: Build tool
 Release: 1
 Source: %{name}-%{version}.tgz
@@ -32,7 +32,7 @@
 
 Also:
     Copyright 2001-2004 David Abrahams.
-    Copyright 2002-2004 Rene Rivera.
+    Copyright 2002-2005 Rene Rivera.
     
     Distributed under the Boost Software License, Version 1.0.
     (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
@@ -49,7 +49,6 @@
 mkdir -p $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
 install -m 755 bin/bjam $RPM_BUILD_ROOT%{_bindir}/bjam-%{version}
 ln -sf bjam-%{version} $RPM_BUILD_ROOT%{_bindir}/bjam
-ln -sf bjam-%{version} $RPM_BUILD_ROOT%{_bindir}/jam
 install -m 644 *.html *.txt Porting $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
 
 find $RPM_BUILD_ROOT -name CVS -type d -depth -exec rm -r {} \;

Modified: boost-jam/trunk/build.bat
===================================================================
--- boost-jam/trunk/build.bat	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/build.bat	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,6 +1,6 @@
 @ECHO OFF
 
-REM ~ Copyright 2002-2003 Rene Rivera.
+REM ~ Copyright 2002-2005 Rene Rivera.
 REM ~ Distributed under the Boost Software License, Version 1.0.
 REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 
@@ -51,17 +51,6 @@
 REM May also set BOOST_JAM_TOOLSET_ROOT to the
 REM location of the found toolset.
 setlocal & endlocal
-if NOT "_%CWFolder%_" == "__" (
-    set BOOST_JAM_TOOLSET=metrowerks
-    set BOOST_JAM_TOOLSET_ROOT=%CWFolder%\
-    goto :eof )
-setlocal & endlocal
-call :Test_Path mwcc.exe
-if not errorlevel 1 (
-    set BOOST_JAM_TOOLSET=metrowerks
-    set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\
-    goto :eof)
-setlocal & endlocal
 if NOT "_%VS71COMNTOOLS%_" == "__" (
     set BOOST_JAM_TOOLSET=vc7
     set BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%\..\..\VC7\
@@ -152,6 +141,17 @@
     set BOOST_JAM_TOOLSET_ROOT=C:\MinGW\
     goto :eof)
 setlocal & endlocal
+if NOT "_%CWFolder%_" == "__" (
+    set BOOST_JAM_TOOLSET=metrowerks
+    set BOOST_JAM_TOOLSET_ROOT=%CWFolder%\
+    goto :eof )
+setlocal & endlocal
+call :Test_Path mwcc.exe
+if not errorlevel 1 (
+    set BOOST_JAM_TOOLSET=metrowerks
+    set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\
+    goto :eof)
+setlocal & endlocal
 call :Error_Print "Could not find a suitable toolset."
 goto :eof
 
@@ -182,7 +182,7 @@
 REM or if first argument is an option guess the toolset;
 REM otherwise the argument is the toolset to use.
 if "_%1_" == "__" (
-    call :Guess_Toolset
+    call :Guess_Toolset
     if not errorlevel 1 goto Setup_Toolset
 ) else (
     call :Test_Option %1
@@ -197,7 +197,7 @@
     )
 )
 if errorlevel 1 goto Finish
-
+
 :Setup_Toolset
 REM Setup the toolset command and options. This bit of code
 REM needs to be flexible enough to handle both when
@@ -214,9 +214,9 @@
     if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
         set PATH=%BOOST_JAM_TOOLSET_ROOT%Other Metrowerks Tools\Command Line Tools;%PATH%)
     set BOOST_JAM_CC=mwcc -runtime ss -cwd include -DNT -ladvapi32.lib
-    set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
-    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
-    set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+    set BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe
+    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe
+    set BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_msvc_" (
@@ -229,9 +229,9 @@
     if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
         set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
     set BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd -DNT -DYYDEBUG kernel32.lib advapi32.lib
-    set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
-    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
-    set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+    set BOOST_JAM_OPT_JAM=/Febootstrap\jam0
+    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0
+    set BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_vc7_" (
@@ -244,9 +244,9 @@
     if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
         set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
     set BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd -DNT -DYYDEBUG kernel32.lib advapi32.lib
-    set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
-    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
-    set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+    set BOOST_JAM_OPT_JAM=/Febootstrap\jam0
+    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0
+    set BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_borland_" (
@@ -258,7 +258,7 @@
             set BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\) ) )
 if "_%BOOST_JAM_TOOLSET%_" == "_borland_" (
     if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (set PATH=%BOOST_JAM_TOOLSET_ROOT%Bin;%PATH%)
-    set BOOST_JAM_CC=bcc32 -WC -w- -q "-I%BOOST_JAM_TOOLSET_ROOT%Include" "-L%BOOST_JAM_TOOLSET_ROOT%Lib" /DNT -nbootstrap.%BOOST_JAM_TOOLSET%
+    set BOOST_JAM_CC=bcc32 -WC -w- -q "-I%BOOST_JAM_TOOLSET_ROOT%Include" "-L%BOOST_JAM_TOOLSET_ROOT%Lib" /DNT -nbootstrap
     set BOOST_JAM_OPT_JAM=-ejam0
     set BOOST_JAM_OPT_MKJAMBASE=-emkjambasejam0
     set BOOST_JAM_OPT_YYACC=-eyyacc0
@@ -266,38 +266,38 @@
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_como_" (
     set BOOST_JAM_CC=como -DNT
-    set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
-    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
-    set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+    set BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe
+    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe
+    set BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_gcc_" (
     set BOOST_JAM_CC=gcc -DNT
-    set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
-    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
-    set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+    set BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe
+    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe
+    set BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" (
     set BOOST_JAM_CC=gcc -DNT -mno-cygwin
-    set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
-    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
-    set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+    set BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe
+    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe
+    set BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" (
     set BOOST_JAM_CC=icl -DNT /nologo
-    set BOOST_JAM_OPT_JAM=/Febootstrap.%BOOST_JAM_TOOLSET%\jam0
-    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap.%BOOST_JAM_TOOLSET%\mkjambase0
-    set BOOST_JAM_OPT_YYACC=/Febootstrap.%BOOST_JAM_TOOLSET%\yyacc0
+    set BOOST_JAM_OPT_JAM=/Febootstrap\jam0
+    set BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0
+    set BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0
     set _known_=1
 )
 if "_%BOOST_JAM_TOOLSET%_" == "_mingw_" (
     if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (set PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%)
     set BOOST_JAM_CC=gcc -DNT
-    set BOOST_JAM_OPT_JAM=-o bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe
-    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe
-    set BOOST_JAM_OPT_YYACC=-o bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe
+    set BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe
+    set BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe
+    set BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe
     set _known_=1
 )
 if "_%_known_%_" == "__" (
@@ -321,16 +321,37 @@
 set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c 
 set BJAM_SOURCES=%BJAM_SOURCES% modules/property-set.c modules/sequence.c modules/order.c
 
+set BJAM_UPDATE=
+if "_%1" == "_--update" (
+    set BJAM_UPDATE=update
+)
+if "_%2" == "_--update" (
+    set BJAM_UPDATE=update
+)
+if "_%3" == "_--update" (
+    set BJAM_UPDATE=update
+)
+if "_%4" == "_--update" (
+    set BJAM_UPDATE=update
+)
+if "_%BJAM_UPDATE%_" == "_update_" (
+    if not exist ".\bootstrap\jam0.exe" (
+        set BJAM_UPDATE=
+    )
+)
+
+
 @echo ON
-rd /S /Q bootstrap.%BOOST_JAM_TOOLSET%
-md bootstrap.%BOOST_JAM_TOOLSET%
+ at if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Bootstrap
+rd /S /Q bootstrap
+md bootstrap
 @if not exist jamgram.y goto Bootstrap_GrammarPrep
 @if not exist jamgramtab.h goto Bootstrap_GrammarPrep
 @goto Skip_GrammarPrep
 :Bootstrap_GrammarPrep
 %BOOST_JAM_CC% %BOOST_JAM_OPT_YYACC% %YYACC_SOURCES%
- at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\yyacc0.exe" goto Skip_GrammarPrep
-.\bootstrap.%BOOST_JAM_TOOLSET%\yyacc0 jamgram.y jamgramtab.h jamgram.yy
+ at if not exist ".\bootstrap\yyacc0.exe" goto Skip_GrammarPrep
+.\bootstrap\yyacc0 jamgram.y jamgramtab.h jamgram.yy
 :Skip_GrammarPrep
 @if not exist jamgram.c goto Bootstrap_GrammarBuild
 @if not exist jamgram.h goto Bootstrap_GrammarBuild
@@ -352,13 +373,16 @@
 @echo ON
 @if exist jambase.c goto Skip_Jambase
 %BOOST_JAM_CC% %BOOST_JAM_OPT_MKJAMBASE% %MKJAMBASE_SOURCES%
- at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0.exe" goto Skip_Jambase
-.\bootstrap.%BOOST_JAM_TOOLSET%\mkjambase0 jambase.c Jambase
+ at if not exist ".\bootstrap\mkjambase0.exe" goto Skip_Jambase
+.\bootstrap\mkjambase0 jambase.c Jambase
 :Skip_Jambase
 %BOOST_JAM_CC% %BOOST_JAM_OPT_JAM% %BJAM_SOURCES%
- at if not exist ".\bootstrap.%BOOST_JAM_TOOLSET%\jam0.exe" goto Skip_Jam
-.\bootstrap.%BOOST_JAM_TOOLSET%\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " clean
-.\bootstrap.%BOOST_JAM_TOOLSET%\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %1 %2 %3 %4 %5 %6 %7 %8 %9
+:Skip_Bootstrap
+ at 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
+.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %1 %2 %3 %4 %5 %6 %7 %8 %9
 :Skip_Jam
 
 :Finish

Modified: boost-jam/trunk/build.jam
===================================================================
--- boost-jam/trunk/build.jam	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/build.jam	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,4 +1,4 @@
-#~ Copyright 2002-2004 Rene Rivera.
+#~ Copyright 2002-2005 Rene Rivera.
 #~ Distributed under the Boost Software License, Version 1.0.
 #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 
@@ -13,10 +13,15 @@
 
 # Info about what we are building.
 NAME = boost-jam ;
-VERSION = 3$(.)1$(.)10 ;
+VERSION = 3$(.)1$(.)11 ;
 RELEASE = 1 ;
 LICENSE = 1_0 ;
 
+HAVE_PYTHON = 0 ;
+PYTHON_INCUDES = /usr/include/python2.3 ;
+PYTHON_LIB = -lpython2.3 ;
+
+
 # Generate development debug binaries?
 if --debug in $(ARGV)
 {
@@ -85,7 +90,7 @@
     : $(LIBS) ;
 ## Comeau C/C++ 4.x
 toolset como como : "-o " : -D
-    :
+    : --c
     [ opt --release : --inlining ]
     [ opt --debug : --no_inlining ] ;
 ## MacOSX Darwin, using GCC 2.9.x, 3.x
@@ -125,12 +130,17 @@
     [ opt --debug : -v -Od -vi- ] ;
 ## Metrowerks CodeWarrior 8.x
 {
+    # Even though CW can compile all files at once, it crashes if it tries in the bjam case.
     local mwcc = ; if $(NT) { mwcc = mwcc ; } else { mwcc = mwc$(OSPLAT:L) ; }
     mwcc ?= mwcc ;
     toolset metrowerks $(mwcc) : "-o " : -D
-        : -subsystem console -cwd include -ladvapi32.lib
-        [ opt --release : -runtime ss -opt full -inline auto -inline level=8 ]
-        [ opt --debug : -runtime ssd -O0 -inline off ] ;
+        : -c -lang c -subsystem console -cwd include
+        [ opt --release : -runtime ss -opt full -inline all ]
+        [ opt --debug : -runtime ssd -opt none -inline off ] ;
+    toolset metrowerks $(mwcc) .link : "-o " :
+        : -subsystem console -ladvapi32.lib
+        [ opt --release : -runtime ss ]
+        [ opt --debug : -runtime ssd ] ;
 }
 ## MINGW GCC
 toolset mingw gcc : "-o " : -D
@@ -312,6 +322,7 @@
 
 # Bug fixes
 --defs += OPT_FIX_TARGET_VARIABLES_EXT ;
+#~ --defs += OPT_NO_EXTERNAL_VARIABLE_SPLIT ;
 
 # Improvements
 --defs += OPT_IMPROVED_PATIENCE_EXT ;
@@ -326,6 +337,16 @@
 }
 --defs += YYSTACKSIZE=5000 ;
 
+if $(HAVE_PYTHON) = 1
+{
+    --defs += HAVE_PYTHON ;
+    --flags += -I$(PYTHON_INCUDES) ;
+    --flags += -Wno-long-long ;
+    --libs += $(PYTHON_LIB) ;
+}
+
+
+
 # The basic symbolic targets...
 NOTFILE all clean dist ;
 ALWAYS clean ;
@@ -333,15 +354,15 @@
 # Utility rules and actions...
 rule .clean
 {
-    .rm. clean : $(<) ;
+    [DELETE] clean : $(<) ;
 }
-if $(NT) { actions piecemeal together existing .rm. {
+if $(NT) { actions piecemeal together existing [DELETE] {
     del /F /Q $(>)
 } }
-if $(UNIX) { actions piecemeal together existing .rm. {
+if $(UNIX) { actions piecemeal together existing [DELETE] {
     rm -f $(>)
 } }
-if $(VMS) { actions piecemeal together existing .rm. {
+if $(VMS) { actions piecemeal together existing [DELETE] {
     DELETE $(>[--2]:J=";*, ") $(>[-1]);*
 } }
 if $(NT) {
@@ -358,15 +379,15 @@
 {
     NOUPDATE $(<) ;
     if $(<:P) { DEPENDS $(<) : $(<:P) ; .mkdir $(<:P) ; }
-    if ! $(md<$(<)>) { .mkdir. $(<) ; md<$(<)> = - ; }
+    if ! $(md<$(<)>) { [MKDIR] $(<) ; md<$(<)> = - ; }
 }
-if $(NT) { actions .mkdir. {
+if $(NT) { actions [MKDIR] {
     md $(<)
 } }
-if $(UNIX) { actions .mkdir. {
+if $(UNIX) { actions [MKDIR] {
     mkdir $(<)
 } }
-if $(VMS) { actions .mkdir. {
+if $(VMS) { actions [MKDIR] {
     CREATE/DIR $(<J=", ")
 } }
 
@@ -379,40 +400,45 @@
     .mkdir $(locate-target) ;
     if $(--link)
     {
+        local objs = ;
         for local s in $(>)
         {
-            local o = $(s:S=.o) ;
+            # Translate any subdir elements into a simple file name.
+            local o = [ MATCH "([^/]+)[/]?(.+)" : $(s) ] ;
+            o = $(o:J=_) ;
+            o = $(o:S=.o) ;
+            objs += $(o) ;
             LOCATE on $(o) = $(locate-target) ;
             DEPENDS $(exe) : $(o) ;
             DEPENDS $(o) : $(s) ;
             DEPENDS $(o) : $(locate-target) ;
-            .cc. $(o) : $(s) ;
+            [COMPILE] $(o) : $(s) ;
             .clean $(o) ;
         }
-        DEPENDS $(exe) : $(>:S=.o) ;
+        DEPENDS $(exe) : $(objs) ;
         DEPENDS $(exe) : $(locate-target) ;
-        .ld. $(exe) : $(>:S=.o) ;
+        [COMPILE.LINK] $(exe) : $(objs) ;
         .clean $(exe) ;
     }
     else
     {
         DEPENDS $(exe) : $(>) ;
         DEPENDS $(exe) : $(locate-target) ;
-        .cc. $(exe) : $(>) ;
+        [COMPILE] $(exe) : $(>) ;
         .clean $(exe) ;
     }
     return $(exe) ;
 }
-if ! $(--def[2]) { actions .cc. {
+if ! $(--def[2]) { actions [COMPILE] {
     "$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D) $(--out)$(<) $(--def)$(--defs) $(--flags) "$(--libs)" $(>)
 } }
-else { actions .cc. {
+else { actions [COMPILE] {
     "$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D) $(--out)$(<) $(--def[1])$(--defs:J=$(--def[2]))$(--def[3]) $(--flags) "$(--libs)" $(>)
 } }
-if $(VMS) { actions .ld. {
+if $(VMS) { actions [COMPILE.LINK] {
     "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>J=", ")
 } }
-else { actions .ld. {
+else { actions [COMPILE.LINK] {
     "$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>)
 } }
 
@@ -420,32 +446,32 @@
 {
     DEPENDS all : $(<) ;
     DEPENDS $(<) : $(>) ;
-    .link. $(<) : $(>) ;
+    [LINK] $(<) : $(>) ;
     .clean $(<) ;
 }
-if $(NT) { actions .link. {
+if $(NT) { actions [LINK] {
     copy $(>) $(<)
 } }
-if $(UNIX) { actions .link. {
-    ln -f $(>) $(<)
+if $(UNIX) { actions [LINK] {
+    ln -fs $(>) $(<)
 } }
-if $(VMS) { actions .link. {
+if $(VMS) { actions [LINK] {
     COPY/REPLACE $(>) $(<)
 } }
 
 rule .move
 {
     DEPENDS $(<) : $(>) ;
-    .move. $(<) : $(>) ;
+    [MOVE] $(<) : $(>) ;
 }
-if $(NT) { actions .move. {
+if $(NT) { actions [MOVE] {
     del /f $(<)
     rename $(>) $(<)
 } }
-if $(UNIX) { actions .move. {
+if $(UNIX) { actions [MOVE] {
     mv -f $(>) $(<)
 } }
-if $(VMS) { actions .move. {
+if $(VMS) { actions [MOVE] {
     RENAME $(>) $(<)
 } }
 
@@ -457,9 +483,9 @@
     DEPENDS $(<) : $(exe) $(>) ;
     LEAVES $(<) ;
     yyacc.exe on $(<) = $(exe:R=$(locate-target)) ;
-    .yyacc. $(<) : $(>) ;
+    [YYACC] $(<) : $(>) ;
 }
-actions .yyacc. {
+actions [YYACC] {
     $(--chmod+w)$(<[1])
     $(--chmod+w)$(<[2])
     "$(yyacc.exe)" $(<) $(>)
@@ -468,7 +494,7 @@
 {
     .yyacc jamgram.y jamgramtab.h : jamgram.yy ;
 }
-else
+else if $(debug)
 {
     .exe yyacc : yyacc.c ;
 }
@@ -502,9 +528,9 @@
 {
     DEPENDS $(<) : $(>) ;
     LEAVES $(<) ;
-    .yacc. $(<) : $(>) ;
+    [YACC] $(<) : $(>) ;
 }
-if $(NT) { actions .yacc. {
+if $(NT) { actions [YACC] {
     "$(yacc)" $(>)
     if not errorlevel 1 (
         del /f $(<[1])
@@ -513,7 +539,7 @@
         rename y.tab$(<[2]:S) $(<[2])
     ) else set _error_ =
 } }
-if $(UNIX) { actions .yacc. {
+if $(UNIX) { actions [YACC] {
     if ` "$(yacc)" $(>) ` ; then
         mv -f y.tab$(<[1]:S) $(<[1])
         mv -f y.tab$(<[2]:S) $(<[2])
@@ -521,7 +547,7 @@
         exit 1
     fi
 } }
-if $(VMS) { actions .yacc. {
+if $(VMS) { actions [YACC] {
     IF "$(yacc)" $(>)
     THEN
         RENAME y_tab$(<[1]:S) $(<[1])
@@ -544,38 +570,50 @@
     DEPENDS $(<) : $(exe) $(>) ;
     LEAVES $(<) ;
     mkjambase.exe on $(<) = $(exe:R=$(locate-target)) ;
-    .mkjambase. $(<) : $(>) ;
+    [MKJAMBASE] $(<) : $(>) ;
 }
-actions .mkjambase. {
+actions [MKJAMBASE] {
     $(--chmod+w)$(<)
     $(mkjambase.exe) $(<) $(>)
 }
-.mkjambase jambase.c : Jambase ;
+if $(debug)
+{
+    .mkjambase jambase.c : Jambase ;
+}
 
 # How to build Jam.
 rule .jam
 {
     $(>).exe = [ .exe $(>) : $(jam.source) ] ;
-    $(<).exe = $(<:S=$($(>).exe:S)) ;
-    LOCATE on $($(<).exe) = $(locate-target) ;
-    .link $($(<).exe) : $($(>).exe) ;
+    DEPENDS all : $($(>).exe) ;
     
-    DEPENDS all : $($(>).exe) $($(<).exe) ;
+    if $(debug)
+    {
+        $(<).exe = $(<:S=$($(>).exe:S)) ;
+        LOCATE on $($(<).exe) = $(locate-target) ;
+        .link $($(<).exe) : $($(>).exe) ;
+        DEPENDS all : $($(<).exe) ;
+    }
 }
-.jam bjam : jam ;
+.jam jam : bjam ;
 
 # Scan sources for header dependencies.
+#	WARNING: Yes those are *REAL TABS* below. DO NOT CHANGE,
+#	under any circumstances, to spaces!! And the tabs
+#	indenting this are so that if someone is in the mood to
+#	replace tabs they hit this comment, and hopefully notice
+#	their error.
 rule .scan
 {
     HDRRULE on $(<:D=) = .hdr.scan ;
-    HDRSCAN on $(<:D=) = "^[     ]*#[    ]*include[  ]*[<\"]([^\">]*)[\">].*$" ;
+    HDRSCAN on $(<:D=) = "^[ 	]*#[ 	]*include[ 	]*([<\"][^\">]*[\">]).*$" ;
 }
 rule .hdr.scan
 {
     local hdrs = [ GLOB . : $(>:D=) ] ;
     INCLUDES $(<:D=) : $(hdrs:D=) ;
     HDRRULE on $(>:D=) = .hdr.scan ;
-    HDRSCAN on $(>:D=) = "^[     ]*#[    ]*include[  ]*[<\"]([^\">]*)[\">].*$" ;
+    HDRSCAN on $(>:D=) = "^[ 	]*#[ 	]*include[ 	]*([<\"][^\">]*[\">]).*$" ;
 }
 .scan [ GLOB . : *.c ] ;
 
@@ -622,34 +660,34 @@
 
 if $(NT)
 {
-    zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7zn.exe" ] ;
+    zip ?= [ GLOB "$(ProgramFiles:J= )\\7-ZIP" "C:\\Program Files\\7-ZIP" : "7z.exe" "7zn.exe" ] ;
     zip ?= [ GLOB $(PATH) : zip.exe ] ;
     zip ?= zip ;
     zip = $(zip[1]) ;
     switch $(zip:D=:S=)
     {
-        case 7zn : zip += a -r -tzip ;
+        case 7z* : zip += a -r -tzip -mx=9 ;
         case zip  : zip += -9r ;
     }
-    actions piecemeal .pack. {
+    actions piecemeal [PACK] {
     "$(zip)" "$(<)" "$(>)"
     }
-    actions piecemeal .zip. {
+    actions piecemeal [ZIP] {
     "$(zip)" "$(<)" "$(>)"
     }
-    actions piecemeal .cp. {
-    copy /Y "$(>)" "$(<)"
+    actions piecemeal [COPY] {
+    copy /Y "$(>)" "$(<)" >NUL:
     }
 }
 if $(UNIX)
 {
-    actions .pack. {
+    actions [PACK] {
     tar zcf "$(<)" "$(>)"
     }
-    actions .zip. {
+    actions [ZIP] {
     gzip -c9 "$(>)" > "$(<)"
     }
-    actions .cp. {
+    actions [COPY] {
     cp -Rpf "$(>)" "$(<)"
     }
 }
@@ -664,8 +702,8 @@
     DEPENDS $(zip) : $($(<).exe) ;
     DEPENDS dist : $(zip) ;
     #~ LOCATE on $(zip) = $(locate-target) ;
-    if $(NT) { .zip. $(zip) : $($(<).exe) ; }
-    if $(UNIX) { .pack. $(zip) : $($(<).exe) ; }
+    if $(NT) { [ZIP] $(zip) : $($(<).exe) ; }
+    if $(UNIX) { [PACK] $(zip) : $($(<).exe) ; }
     .clean $(zip) ;
 }
 
@@ -700,11 +738,11 @@
         DEPENDS $(dst-file) : $(src-path) $(dst-file:D) ;
         .mkdir $(dst-file:D) ;
         
-        .cp. $(dst-file) : $(src-path) ;
+        [COPY] $(dst-file) : $(src-path) ;
         .clean $(dst-file) ;
     }
     
-    .pack. $(pack) : $(dst-files) ;
+    [PACK] $(pack) : $(dst-files) ;
     .clean $(pack) ;
 }
 
@@ -734,10 +772,10 @@
     arch on $(target) = $(rpm-arch) ;
     if $(rpm-arch) = ppc { target-opt on $(target) = --target= ; }
     else { target-opt on $(target) = "--target " ; }
-    .rpm. $(target) : $(source) ;
+    [RPM] $(target) : $(source) ;
     .clean $(name).$(rpm-arch).rpm $(name).src.rpm ;
 }
-actions .rpm. {
+actions [RPM] {
     export BOOST_JAM_TOOLSET="$(toolset)"
     $(rpm-tool[1]) -ta $(target-opt)$(arch) $(>) | tee rpm.out
     cp `grep -e '^Wrote:' rpm.out | sed 's/^Wrote: //'` .

Modified: boost-jam/trunk/build.sh
===================================================================
--- boost-jam/trunk/build.sh	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/build.sh	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-#~ Copyright 2002-2003 Rene Rivera.
+#~ Copyright 2002-2004 Rene Rivera.
 #~ Distributed under the Boost Software License, Version 1.0.
 #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 
@@ -12,7 +12,7 @@
 echo_run ()
 {
     echo "$@"
-    "$@"
+    $@
     r=$?
     if test $r -ne 0 ; then
         exit $r
@@ -43,8 +43,8 @@
 # Check that a command is in the PATH.
 test_path ()
 {
-    if `whence 1>/dev/null 2>/dev/null`; then
-        whence $1 1>/dev/null 2>/dev/null
+    if `command -v command 1>/dev/null 2>/dev/null`; then
+        command -v $1 1>/dev/null 2>/dev/null
     else
         hash $1 1>/dev/null 2>/dev/null
     fi
@@ -64,6 +64,7 @@
     if test_uname Darwin ; then BOOST_JAM_TOOLSET=darwin
     elif test_uname IRIX ; then BOOST_JAM_TOOLSET=mipspro
     elif test_uname IRIX64 ; then BOOST_JAM_TOOLSET=mipspro
+    elif test_uname OSF1 ; then BOOST_JAM_TOOLSET=tru64cxx
     elif test_path gcc ; then BOOST_JAM_TOOLSET=gcc
     elif test_path icc ; then BOOST_JAM_TOOLSET=intel-linux
     elif test -r /opt/intel/compiler70/ia32/bin/iccvars.sh ; then
@@ -103,9 +104,9 @@
     ?*) BOOST_JAM_TOOLSET=$1 ; shift ;;
     *) Guess_Toolset ;;
 esac
-BOOST_JAM_OPT_JAM="-o bootstrap.$BOOST_JAM_TOOLSET/jam0"
-BOOST_JAM_OPT_MKJAMBASE="-o bootstrap.$BOOST_JAM_TOOLSET/mkjambase0"
-BOOST_JAM_OPT_YYACC="-o bootstrap.$BOOST_JAM_TOOLSET/yyacc0"
+BOOST_JAM_OPT_JAM="-o bootstrap/jam0"
+BOOST_JAM_OPT_MKJAMBASE="-o bootstrap/mkjambase0"
+BOOST_JAM_OPT_YYACC="-o bootstrap/yyacc0"
 case $BOOST_JAM_TOOLSET in
     gcc)
     BOOST_JAM_CC=gcc
@@ -134,7 +135,7 @@
     ;;
     
     como)
-    BOOST_JAM_CC=como
+    BOOST_JAM_CC="como --c"
     ;;
     
     kcc)
@@ -196,30 +197,42 @@
  modules/path.c modules/regex.c modules/property-set.c\
  modules/sequence.c modules/order.c"
 
-echo_run rm -rf bootstrap.$BOOST_JAM_TOOLSET
-echo_run mkdir bootstrap.$BOOST_JAM_TOOLSET
-if test ! -r jamgram.y -o ! -r jamgramtab.h ; then
-    echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_YYACC} ${YYACC_SOURCES}
-    if test -x "./bootstrap.$BOOST_JAM_TOOLSET/yyacc0" ; then
-        echo_run ./bootstrap.$BOOST_JAM_TOOLSET/yyacc0 jamgram.y jamgramtab.h jamgram.yy
-    fi
+BJAM_UPDATE=
+if test "$1" = "--update" -o "$2" = "--update" -o "$3" = "--update" -o "$4" = "--update"  ; then
+    BJAM_UPDATE="update"
 fi
-if test ! -r jamgram.c -o ! -r jamgram.h ; then
-    if test_path yacc ; then YACC="yacc -d"
-    elif test_path bison ; then YACC="bison -y -d --yacc"
+if test "${BJAM_UPDATE}" = "update" -a ! -x "./bootstrap/jam0" ; then
+    BJAM_UPDATE=
+fi
+
+if test "${BJAM_UPDATE}" != "update" ; then
+    echo_run rm -rf bootstrap
+    echo_run mkdir bootstrap
+    if test ! -r jamgram.y -o ! -r jamgramtab.h ; then
+        echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_YYACC} ${YYACC_SOURCES}
+        if test -x "./bootstrap/yyacc0" ; then
+            echo_run ./bootstrap/yyacc0 jamgram.y jamgramtab.h jamgram.yy
+        fi
     fi
-    echo_run $YACC jamgram.y
-    mv -f y.tab.c jamgram.c
-    mv -f y.tab.h jamgram.h
+    if test ! -r jamgram.c -o ! -r jamgram.h ; then
+        if test_path yacc ; then YACC="yacc -d"
+        elif test_path bison ; then YACC="bison -y -d --yacc"
+        fi
+        echo_run $YACC jamgram.y
+        mv -f y.tab.c jamgram.c
+        mv -f y.tab.h jamgram.h
+    fi
+    if test ! -r jambase.c ; then
+        echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_MKJAMBASE} ${MKJAMBASE_SOURCES}
+        if test -x "./bootstrap/mkjambase0" ; then
+            echo_run ./bootstrap/mkjambase0 jambase.c Jambase
+        fi
+    fi
+    echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_JAM} ${BJAM_SOURCES}
 fi
-if test ! -r jambase.c ; then
-    echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_MKJAMBASE} ${MKJAMBASE_SOURCES}
-    if test -x "./bootstrap.$BOOST_JAM_TOOLSET/mkjambase0" ; then
-        echo_run ./bootstrap.$BOOST_JAM_TOOLSET/mkjambase0 jambase.c Jambase
+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
     fi
+    echo_run ./bootstrap/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@"
 fi
-echo_run ${BOOST_JAM_CC} ${BOOST_JAM_OPT_JAM} ${BJAM_SOURCES}
-if test -x "./bootstrap.$BOOST_JAM_TOOLSET/jam0" ; then
-    echo_run ./bootstrap.$BOOST_JAM_TOOLSET/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" clean
-    echo_run ./bootstrap.$BOOST_JAM_TOOLSET/jam0 -f build.jam --toolset=$BOOST_JAM_TOOLSET "--toolset-root=$BOOST_JAM_TOOLSET_ROOT" "$@"
-fi

Modified: boost-jam/trunk/builtins.c
===================================================================
--- boost-jam/trunk/builtins.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/builtins.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -22,6 +22,7 @@
 # include "hdrmacro.h"
 # include "compile.h"
 # include "native.h"
+# include "variable.h"
 # include <ctype.h>
 
 /*
@@ -109,10 +110,22 @@
             );
     }
 
+    {
+        char * args[] = { "patterns", "*", 0 };
+        bind_builtin( "GLOB-RECURSIVELY" , builtin_glob_recursive, 0, args );
+    }
+
+
     duplicate_rule( "Includes" ,
       bind_builtin( "INCLUDES" ,
                     builtin_depends, 1, 0 ) );
 
+    {
+        char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
+        bind_builtin( "REBUILDS" ,
+                      builtin_rebuilds, 0, args );
+    }
+    
     duplicate_rule( "Leaves" ,
       bind_builtin( "LEAVES" ,
                     builtin_flags, T_FLAG_LEAVES, 0 ) );
@@ -138,6 +151,13 @@
       bind_builtin( "TEMPORARY" ,
                     builtin_flags, T_FLAG_TEMP, 0 ) );
 
+    {
+        char * args[] = { "targets", "*", 0 };
+        bind_builtin(
+            "ISFILE",
+            builtin_flags, T_FLAG_ISFILE, 0 );
+    }
+
     duplicate_rule( "HdrMacro" ,
       bind_builtin( "HDRMACRO" ,
                     builtin_hdrmacro, 0, 0 ) );
@@ -263,6 +283,33 @@
               builtin_native_rule, 0, args );
       }
 
+      {
+          char * args[] = { "module", "*", 0 };
+          bind_builtin( "USER_MODULE",
+              builtin_user_module, 0, args );
+      }
+
+      {
+          char * args[] = { 0 };
+          bind_builtin( "NEAREST_USER_LOCATION",
+              builtin_nearest_user_location, 0, args );
+      }
+
+      {
+          char * args[] = { "file", 0 };
+          bind_builtin( "CHECK_IF_FILE",
+                        builtin_check_if_file, 0, args );
+      }
+
+#ifdef HAVE_PYTHON
+      {
+          char * args[] = { "python-module", ":", "function", ":", 
+                            "jam-module", ":", "rule-name", 0 };
+          bind_builtin( "PYTHON_IMPORT_RULE",
+              builtin_python_import_rule, 0, args );
+      }
+#endif
+
 # ifdef OS_NT
       {
           char * args[] = { "key_path", ":", "data", "?", 0 };
@@ -271,6 +318,12 @@
       }
 # endif
 
+      {
+          char * args[] = { "command", 0 };
+          bind_builtin( "SHELL",
+              builtin_shell, 0, args );
+      }
+
       /* Initialize builtin modules */
       init_set();
       init_path();
@@ -349,7 +402,6 @@
 {
 	LIST *targets = lol_get( frame->args, 0 );
 	LIST *sources = lol_get( frame->args, 1 );
-	int which = parse->num;
 	LIST *l;
 
 	for( l = targets; l; l = list_next( l ) )
@@ -372,10 +424,43 @@
 	    t->depends = targetlist( t->depends, sources );
 	}
 
+    /* Enter reverse links */
+	for( l = sources; l; l = list_next( l ) )
+	{
+	    TARGET *s = bindtarget( l->string );
+        s->dependents = targetlist( s->dependents, targets );
+    }
+
 	return L0;
 }
 
 /*
+ * builtin_rebuilds() - REBUILDS rule
+ *
+ * The REBUILDS builtin rule appends each of the listed
+ * rebuild-targets in its 2nd argument on the rebuilds list of each of
+ * the listed targets in its first argument.
+ */
+
+LIST *
+builtin_rebuilds(
+	PARSE	*parse,
+	FRAME *frame )
+{
+	LIST *targets = lol_get( frame->args, 0 );
+	LIST *rebuilds = lol_get( frame->args, 1 );
+	LIST *l;
+
+	for( l = targets; l; l = list_next( l ) )
+	{
+	    TARGET *t = bindtarget( l->string );
+	    t->rebuilds = targetlist( t->rebuilds, rebuilds );
+	}
+
+	return L0;
+}
+
+/*
  * builtin_echo() - ECHO rule
  *
  * The ECHO builtin rule echoes the targets to the user.  No other 
@@ -465,11 +550,22 @@
 
     path_parse( file, &f );
     f.f_dir.len = 0;
+
+    /* For globbing, we unconditionally ignore current and parent
+       directory items. Since they items always exist, there's not
+       reason why caller of GLOB would want to see them.
+       We could also change file_dirscan, but then paths with embedded
+       "." and ".." won't work anywhere.
+    */
+    if (strcmp(f.f_base.ptr, ".") == 0 || strcmp(f.f_base.ptr, "..") == 0)
+        return;
+
     string_new( buf );
     path_build( &f, buf, 0 );
 
-    if (globbing->case_insensitive)
+    if (globbing->case_insensitive) {
         downcase_inplace( buf->value );
+    }
 
     for( l = globbing->patterns; l; l = l->next )
     {
@@ -537,6 +633,160 @@
     return globbing.results;
 }
 
+static int has_wildcards(const char* str)
+{
+    size_t index = strcspn(str, "[]*?");
+    if (str[index] == '\0')
+        return 0;
+    else
+        return 1;
+}
+
+/** If 'file' exists, append 'file' to 'list'.
+    Returns 'list'.
+*/
+static LIST* append_if_exists(LIST* list, char* file)
+{
+    time_t time;
+    timestamp(file, &time);
+    if (time > 0)
+        return list_new(list, newstr(file));
+    else
+        return list;        
+}
+
+LIST* glob1(char* dirname, char* pattern)
+{
+    LIST* plist = list_new(L0, pattern);
+    struct globbing globbing;
+
+    globbing.results = L0;
+    globbing.patterns = plist;
+    
+    globbing.case_insensitive
+# if defined( OS_NT ) || defined( OS_CYGWIN )
+       = plist;  /* always case-insensitive if any files can be found */
+# else 
+       = L0;
+# endif
+
+    if ( globbing.case_insensitive )
+    {
+        globbing.patterns = downcase_list( plist );
+    }
+    
+    file_dirscan( dirname, builtin_glob_back, &globbing );
+
+    if ( globbing.case_insensitive )
+    {
+        list_free( globbing.patterns );
+    }
+
+    list_free(plist);
+
+    return globbing.results;
+}
+
+
+LIST* glob_recursive(char* pattern)
+{
+    LIST* result = L0;
+
+    /* Check if there's metacharacters in pattern */
+    if (!has_wildcards(pattern))
+    {
+        /* No metacharacters. Check if the path exists. */
+        result = append_if_exists(result, pattern);
+    }        
+    else
+    {
+        /* Have metacharacters in the pattern. Split into dir/name */
+        PATHNAME path[1];
+        path_parse(pattern, path);            
+        
+        if (path->f_dir.ptr)
+        {
+            LIST* dirs = L0;
+            string dirname[1];
+            string basename[1];
+            string_new(dirname);
+            string_new(basename);
+
+            string_append_range(dirname, path->f_dir.ptr, 
+                                path->f_dir.ptr + path->f_dir.len);
+
+            path->f_grist.ptr = 0;
+            path->f_grist.len = 0;
+            path->f_dir.ptr = 0;
+            path->f_dir.len = 0;
+            path_build(path, basename, 0);
+
+            if (has_wildcards(dirname->value))
+            {
+                dirs = glob_recursive(dirname->value);
+            }
+            else
+            {
+                dirs = list_new(dirs, dirname->value);
+            }
+            
+            if (has_wildcards(basename->value))
+            {
+                for(; dirs; dirs = dirs->next)
+                {
+                    result = list_append(result, 
+                                         glob1(dirs->string, basename->value));
+                }
+            }
+            else
+            {
+                string file_string[1];
+                string_new(file_string);
+
+                /** No wildcard in basename. */
+                for(; dirs; dirs = dirs->next)
+                {                                      
+                    path->f_dir.ptr = dirs->string;
+                    path->f_dir.len = strlen(dirs->string);                    
+                    path_build(path, file_string, 0);
+
+                    result = append_if_exists(result, file_string->value);
+
+                    string_truncate(file_string, 0);
+                }
+
+                string_free(file_string);
+            }
+
+            string_free(dirname);
+            string_free(basename);
+        }
+        else
+        {
+            /** No directory, just a pattern. */
+            result = list_append(result, glob1(".", pattern));
+        }
+    }
+
+    return result;
+}
+
+LIST *
+builtin_glob_recursive(
+    PARSE   *parse,
+    FRAME *frame )
+{
+    LIST* result = L0;
+    LIST* l = lol_get( frame->args, 0 );
+
+    for(; l; l = l->next)
+    {
+        result = list_append(result, glob_recursive(l->string));
+    }
+
+    return result;
+}
+
 /*
  * builtin_match() - MATCH rule, regexp matching
  */
@@ -1118,7 +1368,137 @@
     return L0;    
 }
 
+LIST *builtin_user_module( PARSE *parse, FRAME *frame )
+{
+    LIST* module_name = lol_get( frame->args, 0 );    
+    for(; module_name; module_name = module_name->next) 
+    {
+        module_t* m = bindmodule( module_name->string);
+        m->user_module = 1;
+    }
+    return L0;
+}
 
+LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame )
+{
+    LIST* result = 0;
+    FRAME* nearest_user_frame = 
+        frame->module->user_module ? frame : frame->prev_user;
+
+    if (nearest_user_frame)
+    {
+        char* file;
+        int line;
+        char buf[32];
+        get_source_line( nearest_user_frame->procedure, &file, &line );
+        sprintf( buf, "%d", line );
+        result = list_new( result, newstr( file ) );
+        result = list_new( result, newstr( buf ) );
+        return result;
+    }
+    else
+    {
+        return L0;
+    }
+}
+
+LIST *builtin_check_if_file( PARSE *parse, FRAME *frame )
+{
+    LIST* name = lol_get( frame->args, 0 );
+    if (file_is_file(name->string) == 1) {
+        return list_new(0, newstr("true"));
+    } else {
+        return L0;
+    }
+}
+
+
+#ifdef HAVE_PYTHON
+
+LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame )
+{
+    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;        
+
+   PyObject *pName, *pModule, *pDict, *pFunc;
+
+   if (first_time)
+   {
+       /* At the first invocation, we add the value of the
+          global EXTRA_PYTHONPATH to the sys.path Python
+          variable.
+       */
+       LIST* extra = 0;
+       module_t* outer_module = frame->module;
+
+       first_time = 0;
+
+       if ( outer_module != root_module())
+       {
+           exit_module( outer_module );
+           enter_module( root_module());
+       }
+    
+       extra = var_get("EXTRA_PYTHONPATH");
+    
+       if ( outer_module != root_module())
+       {
+            exit_module( root_module());
+            enter_module( outer_module );
+       }
+
+       for(; extra; extra = extra->next)
+       {
+           string buf[1];
+           string_new(buf);
+           string_append(buf, "import sys\nsys.path.append(\"");
+           string_append(buf, extra->string);
+           string_append(buf, "\")\n");
+           PyRun_SimpleString(buf->value);   
+           string_free(buf);               
+       }       
+   }
+
+
+   pName = PyString_FromString(python_module);
+   
+   pModule = PyImport_Import(pName);
+   Py_DECREF(pName);
+
+   if (pModule != NULL) {
+        pDict = PyModule_GetDict(pModule);
+        pFunc = PyDict_GetItemString(pDict, python_function);
+
+        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;
+        }
+        else {
+            if (PyErr_Occurred())
+                PyErr_Print();
+            fprintf(stderr, "Cannot find function \"%s\"\n", python_function);
+        }
+        Py_DECREF(pModule);
+    }
+    else {
+        PyErr_Print();
+        fprintf(stderr, "Failed to load \"%s\"\n", python_module);
+    }
+   return L0;
+
+}
+
+#endif
+
 void lol_build( LOL* lol, char** elements )
 {
     LIST* l = L0;
@@ -1142,3 +1522,137 @@
         lol_add( lol, l );
 }
 
+#ifdef HAVE_PYTHON
+
+/** Calls the bjam rule specified by name passed in 'args'.
+    The name is looked up in context of bjam's 'python_interface'
+    module. Returns the list of string retured by the rule.
+*/
+PyObject*
+bjam_call(PyObject* self, PyObject* args)
+{
+    FRAME       inner[1];
+    LIST    *result;
+    PARSE   *p;
+    char*  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;
+
+    /* Extract the rule name and arguments from 'args' */
+
+    /* PyTuple_GetItem returns borrowed reference */
+    rulename = PyString_AsString(PyTuple_GetItem(args, 0));
+    {
+        int i = 1;
+        int size = PyTuple_Size(args);
+        for( ; i < size; ++i) {
+            PyObject* a = PyTuple_GetItem(args, i);
+            if (PyString_Check(a))
+            {
+                lol_add(inner->args, 
+                        list_new(0, newstr(PyString_AsString(a))));
+            }
+            else if (PySequence_Check(a))
+            {
+                LIST* l = 0;
+                int s = PySequence_Size(a);
+                int i = 0;
+                for(; i < s; ++i)
+                {
+                    /* PySequence_GetItem returns new reference. */
+                    PyObject* e = PySequence_GetItem(a, i);
+                    l = list_new(l, newstr(PyString_AsString(e)));
+                    Py_DECREF(e);
+                }
+                lol_add(inner->args, l);
+            }                
+        }
+    }
+
+    result = evaluate_rule( rulename, inner );
+
+    frame_free( inner );
+}
+
+/** Accepts three arguments: module name, rule name and Python callable.
+
+    Creates bjam rule with the specified name in the specified module,
+    which will invoke the Python callable.
+*/
+PyObject*
+bjam_import_rule(PyObject* self, PyObject* args)
+{
+    char* module;
+    char* rule;
+    PyObject* func;
+    module_t* m;
+    RULE* r;
+
+    if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func))
+        return NULL;
+    
+    if (!PyCallable_Check(func))
+        return NULL;
+    
+    m = bindmodule(module);
+    r = bindrule(rule, m);
+
+    /* Make pFunc owned */
+    Py_INCREF(func);
+
+    r->python_function = func;
+    return Py_None;
+}
+
+#endif
+
+#ifdef HAVE_POPEN
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+    #define popen _popen
+    #define pclose _pclose
+#endif
+
+LIST *builtin_shell( PARSE *parse, FRAME *frame )
+{
+    LIST* arg = lol_get( frame->args, 0 );
+    LIST* result = 0; 
+    string s;
+    int ret;
+    char buffer[1024];
+    FILE *p = NULL;
+
+    string_new( &s );
+
+    fflush(NULL);
+
+    p = popen(arg->string, "r");
+    if ( p == NULL )
+        return L0;
+
+    while ( (ret = fread(buffer, sizeof(char), sizeof(buffer)-1, p)) > 0 )
+    {
+        buffer[ret+1] = 0;
+        string_append( &s, buffer );
+    }
+
+    pclose(p);
+
+    result = list_new( L0, newstr(s.value) );
+    string_free(&s);
+    return result;
+}
+
+#else
+
+LIST *builtin_shell( PARSE *parse, FRAME *frame )
+{
+    return L0;
+}
+
+#endif

Modified: boost-jam/trunk/builtins.h
===================================================================
--- boost-jam/trunk/builtins.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/builtins.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -17,10 +17,12 @@
 
 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_hdrmacro( PARSE *parse, FRAME *args );
@@ -40,6 +42,11 @@
 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_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 );
 
 void backtrace( FRAME *frame );
 

Modified: boost-jam/trunk/class.c
===================================================================
--- boost-jam/trunk/class.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/class.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladiir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "class.h"
 #include "strings.h"

Modified: boost-jam/trunk/class.h
===================================================================
--- boost-jam/trunk/class.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/class.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,7 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 #ifndef CLASS_H_VP_2003_08_01
 #define CLASS_H_VP_2003_08_01
 

Modified: boost-jam/trunk/compile.c
===================================================================
--- boost-jam/trunk/compile.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/compile.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -98,6 +98,7 @@
 void frame_init( FRAME* frame )
 {
     frame->prev = 0;
+    frame->prev_user = 0;
     lol_init(frame->args);
     frame->module = root_module();
     frame->rulename = "module scope";
@@ -584,6 +585,7 @@
 
     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;
 
@@ -690,6 +692,7 @@
         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 */
@@ -886,6 +889,106 @@
     }
 }
 
+static int python_instance_number = 0;
+
+RULE *
+enter_rule( char *rulename, module_t *target_module );
+
+#ifdef HAVE_PYTHON
+static LIST*
+call_python_function(RULE* r, FRAME* frame)
+{
+    LIST* result = 0;
+    PyObject* arguments = PyTuple_New(frame->args->count);
+    int i ;
+    PyObject* py_result;
+
+    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);
+            /* Steals reference to 'v' */
+            PyList_Append(arg, v);            
+        }
+        /* Steals reference to 'arg' */
+        PyTuple_SetItem(arguments, i, arg);
+    }
+
+    py_result = PyObject_CallObject(r->python_function, arguments);
+    Py_DECREF(arguments);
+    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);
+                if (PyString_Check(item))
+                {
+                    result = list_new(result, 
+                                      newstr(PyString_AsString(item)));
+                }
+                else
+                {
+                    fprintf(stderr, "Non-string object returned by Python call\n");
+                }
+            }
+        }
+        else if (PyInstance_Check(py_result))
+        {
+            static char instance_name[1000];
+            static char imported_method_name[1000];
+            module_t* m;
+            PyObject* method;
+            PyObject* method_name = PyString_FromString("foo");
+            RULE* r;
+
+            fprintf(stderr, "Got instance!\n");
+
+            snprintf(instance_name, 1000,
+                     "pyinstance%d", python_instance_number);
+            snprintf(imported_method_name, 1000,
+                     "pyinstance%d.foo", python_instance_number);
+            ++python_instance_number;
+            
+            m = bindmodule(instance_name);
+
+            /* This is expected to get bound method. */
+            method = PyObject_GetAttr(py_result, method_name);
+            
+            r = bindrule( imported_method_name, root_module() );
+
+            r->python_function = method;
+
+            result = list_new(0, newstr(instance_name));    
+
+            Py_DECREF(method_name);
+        }
+        else if (py_result == Py_None)
+        {
+            result = L0;
+        }
+        else
+        {
+            fprintf(stderr, "Non-list object returned by Python call\n");
+        }
+
+        Py_DECREF(py_result);
+    }
+    else {
+        PyErr_Print();
+        fprintf(stderr,"Call failed\n");
+    }
+    
+    return result;
+}
+#endif
+
 /*
  * evaluate_rule() - execute a rule invocation
  */
@@ -922,6 +1025,13 @@
     rulename = l->string;
     rule = bindrule( l->string, frame->module );
 
+#ifdef HAVE_PYTHON
+    if (rule->python_function)
+    {
+        return call_python_function(rule, frame);
+    }
+#endif
+
     /* drop the rule name */
     l = list_pop_front( l );
 
@@ -1049,7 +1159,9 @@
     FRAME       inner[1];
     frame_init( inner );
     inner->prev = caller_frame;
-    inner->module = caller_frame->module;
+    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);    

Modified: boost-jam/trunk/debian/copyright
===================================================================
--- boost-jam/trunk/debian/copyright	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/debian/copyright	2005-12-22 12:04:37 UTC (rev 13928)
@@ -21,7 +21,7 @@
 Some portions are also:
 
     Copyright 2001-2004 David Abrahams.
-    Copyright 2002-2004 Rene Rivera.
+    Copyright 2002-2005 Rene Rivera.
     
     Distributed under the Boost Software License, Version 1.0.
 

Modified: boost-jam/trunk/execcmd.h
===================================================================
--- boost-jam/trunk/execcmd.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/execcmd.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -10,9 +10,16 @@
  * 05/04/94 (seiwald) - async multiprocess interface
  */
 
+typedef struct timing_info
+{
+    /* double elapsed; */  /* We don't know how to get this number on Unix */
+    double system;
+    double user;
+} timing_info;
+
 void execcmd(
 	char *string,
-	void (*func)( void *closure, int status ),
+	void (*func)( void *closure, int status, timing_info* ),
 	void *closure,
 	LIST *shell );
 

Modified: boost-jam/trunk/execnt.c
===================================================================
--- boost-jam/trunk/execnt.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/execnt.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -16,6 +16,7 @@
 # include <errno.h>
 # include <assert.h>
 # include <ctype.h>
+# include <time.h>
 
 # ifdef USE_EXECNT
 
@@ -71,7 +72,7 @@
 static struct
 {
 	int	pid; /* on win32, a real process handle */
-	void	(*func)( void *closure, int status );
+	void	(*func)( void *closure, int status, timing_info* );
 	void 	*closure;
 	char	*tempfile;
 
@@ -107,93 +108,99 @@
         : 2047;
 }
 
+static void
+free_argv( char** args )
+{
+  free( args[0] );
+  free( args );
+}
+
+/* Convert a command string into arguments for spawnvp.  The original
+ * code, inherited from ftjam, tried to break up every argument on the
+ * command-line, dealing with quotes, but that's really a waste of
+ * time on Win32, at least.  It turns out that all you need to do is
+ * get the raw path to the executable in the first argument to
+ * spawnvp, and you can pass all the rest of the command-line
+ * arguments to spawnvp in one, un-processed string.
+ *
+ * New strategy: break the string in at most one place.
+ */
 static char**
-string_to_args( const char*  string, int*  pcount )
+string_to_args( const char*  string )
 {
-  int    total    = strlen( string );
-  int    in_quote = 0,
-      num_args = 0; /* was uninitialized -- dwa */
-  char*  line;
-  char*  p;
-  char** arg;
-  char** args;
+    int src_len;
+    int in_quote;
+    char* line;
+    char const* src;
+    char* dst;
+    char** argv;
 
-  *pcount = 0;  
+    /* drop leading and trailing whitespace if any */
+    while (isspace(*string))
+        ++string;
+  
+    src_len = strlen( string );
+    while ( src_len > 0 && isspace( string[src_len - 1] ) )
+        --src_len;
 
-  /* do not copy trailing newlines, if any */  
-  while ( total > 0 )
-  {
-      if ( !isspace( string[total - 1] ) )
-          break;
-      --total;
-  }
-  
-  /* first of all, copy the input string */
-  line    = (char*)malloc( total+2 );
-  if (!line)
-    return 0;
-    
-  memcpy( line+1, string, total );
-  line[0]       = 0;
-  line[total+1] = 0;
-  
-  in_quote = 0;
-  for ( p = line+1; p[0]; p++ )
-  {
-    switch (p[0])
+    /* Copy the input string into a buffer we can modify
+     */
+    line = (char*)malloc( src_len+1 );
+    if (!line)
+        return 0;
+
+    /* allocate the argv array.
+     *   element 0: stores the path to the executable
+     *   element 1: stores the command-line arguments to the executable
+     *   element 2: NULL terminator
+     */
+    argv = (char**)malloc( 3 * sizeof(char*) );
+    if (!argv)
     {
-      case '"':
-        in_quote = !in_quote;
-        break;
-        
-      case ' ':
-      case '\t':
-        if (!in_quote)
-          p[0]    = 0;
-        
-      default:
-        ;
+        free( line );
+        return 0;
     }
-  }
-  
-  /* now count the arguments.. */
-  for ( p = line; p < line+total+1; p++ )
-    if ( !p[0] && p[1] )
-      num_args++;
-      
-  /* allocate the args array */
-  /* dwa -- did you really mean to allocate only 2 additional bytes? */
-#if 0 /* was like this */
-  args = (char**)malloc( num_args*sizeof(char*)+2 );
-#endif
-  args = (char**)malloc( (num_args + 2) * sizeof(char*) );
-  if (!args)
-  {
-    free( line );
-    return 0;
-  }
-  
-  arg = args+1;
-  for ( p = line; p < line+total+1; p++ )
-    if ( !p[0] && p[1] )
+    
+    /* Strip quotes from the first command-line argument and find
+     * where it ends.  Quotes are illegal in Win32 pathnames, so we
+     * don't need to worry about preserving escaped quotes here.
+     * Spaces can't be escaped in Win32, only enclosed in quotes, so
+     * removing backslash escapes is also a non-issue.
+     */
+    in_quote = 0;
+    for ( src = string, dst = line ; *src; src++ )
     {
-      arg[0] = p+1;
-      arg++;
+        if (*src == '"')
+            in_quote = !in_quote;
+        else if (!in_quote && isspace(*src))
+            break;
+        else
+            *dst++ = *src;
     }
-  arg[0]  = 0;
-  *pcount = num_args;
-  args[0] = line;
-  return args+1;
-}
+    *dst++ = 0;
+    argv[0] = line;
 
-static void
-free_args( char** args )
-{
-  free( args[-1] );
-  free( args-1 );
+    /* skip whitespace in src */
+    while (isspace(*src))
+        ++src;
+
+    argv[1] = dst;
+
+	/* Copy the rest of the arguments verbatim */
+    
+    src_len -= src - string;
+
+    /* Use strncat because it appends a trailing nul */
+    *dst = 0;
+    strncat(dst, src, src_len);
+
+    argv[2] = 0;
+    
+    return argv;
 }
 
 
+
 /* process a "del" or "erase" command under Windows 95/98 */
 static int
 process_del( char*  command )
@@ -310,28 +317,22 @@
 	printf( "...interrupted\n" );
 }
 
-#if 0 // the shell is too different from direct invocation; let's
-      // always use the shell unless forced.
 /*
- * use_bat_file() - return true iff the command demands the use of a
- * .bat file to run it
+ * can_spawn() - If the command is suitable for execution via spawnvp,
+ * return a number >= the number of characters it would occupy on the
+ * command-line.  Otherwise, return zero.
  */
-int use_bat_file(char* command)
+long can_spawn(char* command)
 {
-    char *p = command;
+    char *p;
     
     char inquote = 0;
 
-    p += strspn( p, " \t" );
+    /* Move to the first non-whitespace */
+    command += strspn( command, " \t" );
 
-    /* spawnvp can't handle any paths with spaces or quoted filenames with no directory prefix */
-    if ( *p == '"' )
-    {
-        char* q = p + 1 + strcspn( p + 1, "\" /\\" );
-        if ( *q == '"' || *q == ' ' )
-            return 1;
-    }
-        
+    p = command;
+    
     /* Look for newlines and unquoted i/o redirection */
     do
     {
@@ -343,11 +344,11 @@
             /* skip over any following spaces */
             while( isspace( *p ) )
                 ++p;
-            /* return true iff there is anything significant following
-             * the newline
+            /* Must use a .bat file if there is anything significant
+             * following the newline
              */
             if (*p)
-                return 1;
+                return 0;
             break;
             
         case '"':
@@ -367,20 +368,21 @@
         case '>':
         case '|':
             if (!inquote)
-                return 1;
+                return 0;
             ++p;
             break;
         }
     }
     while (*p);
-    
-    return p - command >= MAXLINE;
+
+    /* Return the number of characters the command will occupy
+     */
+    return p - command;
 }
-#endif
 
 void execnt_unit_test()
 {
-#if 0 && !defined(NDEBUG)
+#if !defined(NDEBUG)        
     /* vc6 preprocessor is broken, so assert with these strings gets
      * confused. Use a table instead.
      */
@@ -390,10 +392,6 @@
         { "x\n ", 0 },
         { "x\ny", 1 },
         { "x\n\n y", 1 },
-        { "\"x\"", 1 },
-        { "\"x y\"", 1 },
-        { "\"x/y\"", 0 },
-        { "\"x\\y\"", 0 },
         { "echo x > foo.bar", 1 },
         { "echo x < foo.bar", 1 },
         { "echo x \">\" foo.bar", 0 },
@@ -404,7 +402,7 @@
     int i;
     for ( i = 0; i < sizeof(tests)/sizeof(*tests); ++i)
     {
-        assert( use_bat_file( tests[i].command ) == tests[i].result );
+        assert( !can_spawn( tests[i].command ) == tests[i].result );
     }
 
     {
@@ -412,13 +410,25 @@
         assert( long_command != 0 );
         memset( long_command, 'x', MAXLINE + 9 );
         long_command[MAXLINE + 9] = 0;
-        assert( use_bat_file( long_command ) );
+        assert( can_spawn( long_command ) == MAXLINE + 9);
         free( long_command );
     }
+
+    {
+        /* Work around vc6 bug; it doesn't like escaped string
+         * literals inside assert
+         */
+        char** argv = string_to_args("\"g++\" -c -I\"Foobar\"");
+        char const expected[] = "-c -I\"Foobar\""; 
+        
+        assert(!strcmp(argv[0], "g++"));
+        assert(!strcmp(argv[1], expected));
+        free_argv(argv);
+    }
 #endif 
 }
 
-// SVA - handle temp dirs with spaces in the path
+/* SVA - handle temp dirs with spaces in the path */
 static const char *getTempDir(void)
 {
     static char tempPath[_MAX_PATH];
@@ -446,6 +456,65 @@
     return pTempPath;
 }
 
+/* 64-bit arithmetic helpers */
+
+/* Compute the carry bit from the addition of two 32-bit unsigned numbers */
+#define add_carry_bit(a, b) ( (((a) | (b)) >> 31) & (~((a) + (b)) >> 31) & 0x1 )
+
+/* Compute the high 32 bits of the addition of two 64-bit unsigned numbers, h1l1 and h2l2 */
+#define add_64_hi(h1, l1, h2, l2) ((h1) + (h2) + add_carry_bit(l1, l2))
+
+/* Add two 64-bit unsigned numbers, h1l1 and h2l2 */
+static FILETIME add_64(
+    unsigned long h1, unsigned long l1,
+    unsigned long h2, unsigned long l2)
+{
+    FILETIME result;
+    result.dwLowDateTime = l1 + l2;
+    result.dwHighDateTime = add_64_hi(h1, l1, h2, l2);
+
+    return result;
+}
+
+static FILETIME add_FILETIME(FILETIME t1, FILETIME t2)
+{
+    return add_64(
+        t1.dwHighDateTime, t1.dwLowDateTime
+      , t2.dwHighDateTime, t2.dwLowDateTime);
+}
+static FILETIME negate_FILETIME(FILETIME t)
+{
+    /* 2s complement negation */
+    return add_64(~t.dwHighDateTime, ~t.dwLowDateTime, 0, 1);
+}
+
+/* COnvert a FILETIME to a number of seconds */
+static double filetime_seconds(FILETIME t)
+{
+    return t.dwHighDateTime * (double)(1UL << 31) * 2 + t.dwLowDateTime * 1.0e-7;
+}
+
+static void
+record_times(int pid, timing_info* time)
+{
+    FILETIME creation, exit, kernel, user;
+    if (GetProcessTimes((HANDLE)pid, &creation, &exit, &kernel, &user))
+    {
+        /* Compute the elapsed time */
+#if 0 /* We don't know how to get this number this on Unix */
+        time->elapsed = filetime_seconds(
+            add_FILETIME( exit, negate_FILETIME(creation) )
+        );
+#endif 
+
+        time->system = filetime_seconds(kernel);
+        time->user = filetime_seconds(user);            
+    }
+        
+    CloseHandle((HANDLE)pid);
+}
+    
+
 /*
  * execcmd() - launch an async command execution
  */
@@ -453,7 +522,7 @@
 void
 execcmd( 
 	char *string,
-	void (*func)( void *closure, int status ),
+	void (*func)( void *closure, int status, timing_info* ),
 	void *closure,
 	LIST *shell )
 {
@@ -501,7 +570,7 @@
 
         tempdir = getTempDir();
   
-        // SVA - allocate 64 other just to be safe
+        /* SVA - allocate 64 other just to be safe */
         cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 64 );
   
         procID = GetCurrentProcessId();
@@ -515,19 +584,26 @@
     while( isspace( *string ) )
         ++string;
 
-    /* If multi line, or too long, or JAMSHELL is set, write to bat file. */
-    /* Otherwise, exec directly. */
-    /* Frankly, if it is a single long line I don't think the */
-    /* command interpreter will do any better -- it will fail. */
-
-    if( shell || !raw_cmd // && use_bat_file( string )
-        )
+    /* Write to .BAT file unless the line would be too long and it
+     * meets the other spawnability criteria.
+     */
+    if( raw_cmd && can_spawn( string ) >= MAXLINE )
     {
+        if( DEBUG_EXECCMD )
+            printf("Executing raw command directly\n");        
+    }
+    else
+    {
         FILE *f;
-
+        raw_cmd = 0;
+        
         /* Write command to bat file. */
-
         f = fopen( cmdtab[ slot ].tempfile, "w" );
+        if (!f)
+        {
+            printf( "failed to write command file!\n" );
+            exit( EXITBAD );
+        }
         fputs( string, f );
         fclose( f );
 
@@ -541,10 +617,6 @@
                 printf("Executing through .bat file\n");
         }
     }
-    else if( DEBUG_EXECCMD )
-    {
-        printf("Executing raw command directly\n");
-    }
 
     /* Forumulate argv */
     /* If shell was defined, be prepared for % and ! subs. */
@@ -577,8 +649,7 @@
     }
     else if (raw_cmd)
     {
-        int ignored;
-        argv = string_to_args(string, &ignored);
+        argv = string_to_args(string);
     }
     else
     {
@@ -608,6 +679,7 @@
         const char**  keyword;
         int           len, spawn = 1;
         int           result;
+        timing_info time = {0,0};
           
         for ( keyword = hard_coded; keyword[0]; keyword++ )
         {
@@ -630,11 +702,10 @@
         if (spawn)
         {
             char**  args;
-            int     num_args;
             
             /* convert the string into an array of arguments */
             /* we need to take care of double quotes !!      */
-            args = string_to_args( string, &num_args );
+            args = string_to_args( string );
             if ( args )
             {
 #if 0
@@ -649,12 +720,13 @@
                 fprintf( stderr, "\n" );
 #endif              
                 result = spawnvp( P_WAIT, args[0], args );
-                free_args( args );
+                record_times(result, &time);
+                free_argv( args );
             }
             else
                 result = 1;
         }
-        func( closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK );
+        func( closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK, &time );
         return;
     }
 
@@ -672,12 +744,19 @@
     }
 
     /* the rest is for Windows NT only */
-    /* spawn doesn't like quotes aroudn the command name */
+    /* spawn doesn't like quotes around the command name */
     if ( argv[0][0] == '"')
     {
         int l = strlen(argv[0]);
-        if (argv[0][l-1] == '"') argv[0][l-1] = '\0';
-        strcpy(argv[0],argv[0]+1);
+
+        /* Clobber any closing quote, shortening the string by one
+         * element */
+        if (argv[0][l-1] == '"')
+            argv[0][l-1] = '\0';
+        
+        /* Move everything *including* the original terminating zero
+         * back one place in memory, covering up the opening quote */
+        memmove(argv[0],argv[0]+1,l);
     }
     if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
     {
@@ -699,7 +778,7 @@
     
     if (argv != argv_static)
     {
-        free_args(argv);
+        free_argv(argv);
     }
 }
 
@@ -713,19 +792,20 @@
 	int i;
 	int status, w;
 	int rstat;
+    timing_info time;
 
 	/* Handle naive make1() which doesn't know if cmds are running. */
 
 	if( !cmdsrunning )
 	    return 0;
 
-        if ( is_win95 )
-          return 0;
+    if ( is_win95 )
+        return 0;
           
 	/* Pick up process pid and status */
     
-	while( ( w = wait( &status ) ) == -1 && errno == EINTR )
-		;
+    while( ( w = wait( &status ) ) == -1 && errno == EINTR )
+        ;
 
 	if( w == -1 )
 	{
@@ -746,6 +826,12 @@
 	    exit( EXITBAD );
 	}
 
+    record_times(cmdtab[i].pid, &time);
+    
+	/* Clear the temp file */
+    if ( cmdtab[i].tempfile )
+        unlink( cmdtab[ i ].tempfile );
+
 	/* Drive the completion */
 
 	if( !--cmdsrunning )
@@ -759,68 +845,113 @@
 	    rstat = EXEC_CMD_OK;
 
 	cmdtab[ i ].pid = 0;
-	// SVA don't leak temp files
+	/* SVA don't leak temp files */
 	if(cmdtab[i].tempfile != NULL)
 	{
             free(cmdtab[i].tempfile);
             cmdtab[i].tempfile = NULL;
 	}
-	(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
+	(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time );
 
 	return 1;
 }
 
 # if !defined( __BORLANDC__ )
 
+/* The possible result codes from check_process_exit, below */
+typedef enum { process_error, process_active, process_finished } process_state;
+
+/* Helper for my_wait() below.  Checks to see whether the process has
+ * exited and if so, records timing information.
+ */
+static process_state
+check_process_exit(
+    HANDLE process         /* The process we're looking at */
+    
+  , int* status            /* Storage for the finished process' exit
+                            * code.  If the process is still active
+                            * this location is left untouched. */
+    
+  , HANDLE* active_handles /* Storage for the process handle if it is
+                            * found to be still active, or NULL.  The
+                            * process is treated as though it is
+                            * complete.  */
+    
+  , int* num_active        /* The current length of active_handles */
+)
+{
+    DWORD exitcode;
+    process_state result;
+
+    /* Try to get the process exit code */
+    if (!GetExitCodeProcess(process, &exitcode))
+    {
+        result = process_error; /* signal an error */
+    }
+    else if (
+        exitcode == STILL_ACTIVE     /* If the process is still active */
+        && active_handles != 0       /* and we've been passed a place to buffer it */
+    )
+    {
+        active_handles[(*num_active)++] = process; /* push it onto the active stack */
+        result = process_active;
+    }
+    else
+    {
+        *status = (int)((exitcode & 0xff) << 8);
+        result = process_finished;
+    }
+    
+    return result;
+}
+
 static int
 my_wait( int *status )
 {
 	int i, num_active = 0;
 	DWORD exitcode, waitcode;
-	static HANDLE *active_handles = 0;
+	HANDLE active_handles[MAXJOBS];
 
-	if (!active_handles)
-	    active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
-
 	/* first see if any non-waited-for processes are dead,
 	 * and return if so.
 	 */
-	for ( i = 0; i < globs.jobs; i++ ) {
-	    if ( cmdtab[i].pid ) {
-		if ( GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode) ) {
-		    if ( exitcode == STILL_ACTIVE )
-			active_handles[num_active++] = (HANDLE)cmdtab[i].pid;
-		    else {
-			CloseHandle((HANDLE)cmdtab[i].pid);
-			*status = (int)((exitcode & 0xff) << 8);
-			return cmdtab[i].pid;
-		    }
-		}
-		else
-		    goto FAILED;
+	for ( i = 0; i < globs.jobs; i++ )
+    {
+        int pid = cmdtab[i].pid;
+        
+	    if ( pid )
+        {
+            process_state state
+                = check_process_exit((HANDLE)pid, status, active_handles, &num_active);
+            
+            if ( state == process_error )
+                goto FAILED;
+            else if ( state == process_finished )
+                return pid;
 	    }
 	}
 
 	/* if a child exists, wait for it to die */
-	if ( !num_active ) {
+	if ( !num_active )
+    {
 	    errno = ECHILD;
 	    return -1;
 	}
+    
 	waitcode = WaitForMultipleObjects( num_active,
-					   active_handles,
-					   FALSE,
-					   INFINITE );
-	if ( waitcode != WAIT_FAILED ) {
+                                       active_handles,
+                                       FALSE,
+                                       INFINITE );
+	if ( waitcode != WAIT_FAILED )
+    {
 	    if ( waitcode >= WAIT_ABANDONED_0
-		&& waitcode < WAIT_ABANDONED_0 + num_active )
-		i = waitcode - WAIT_ABANDONED_0;
+             && waitcode < WAIT_ABANDONED_0 + num_active )
+            i = waitcode - WAIT_ABANDONED_0;
 	    else
-		i = waitcode - WAIT_OBJECT_0;
-	    if ( GetExitCodeProcess(active_handles[i], &exitcode) ) {
-		CloseHandle(active_handles[i]);
-		*status = (int)((exitcode & 0xff) << 8);
-		return (int)active_handles[i];
-	    }
+            i = waitcode - WAIT_OBJECT_0;
+        
+        if ( check_process_exit(active_handles[i], status, 0, 0) == process_finished )
+            return (int)active_handles[i];
 	}
 
 FAILED:

Modified: boost-jam/trunk/execunix.c
===================================================================
--- boost-jam/trunk/execunix.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/execunix.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -8,6 +8,7 @@
 # include "lists.h"
 # include "execcmd.h"
 # include <errno.h>
+# include <time.h>
 
 #if defined(sun) || defined(__sun)
 #include <unistd.h> /* need to include unistd.h on sun for the vfork prototype*/
@@ -15,24 +16,12 @@
 #endif
 
 # ifdef USE_EXECUNIX
+# include <sys/times.h>
 
 # ifdef NO_VFORK
 # define vfork() fork()
 # endif
 
-# if defined( OS_NT ) || defined( OS_OS2 )
-
-# define USE_EXECNT
-
-# include <process.h>
-
-# if !defined( __BORLANDC__ ) && !defined( OS_OS2 )
-# define wait my_wait
-static int my_wait( int *status );
-# endif
-
-# endif
-
 /*
  * execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
  *
@@ -71,13 +60,8 @@
 static struct
 {
 	int	pid; /* on win32, a real process handle */
-	void	(*func)( void *closure, int status );
+	void	(*func)( void *closure, int status, timing_info* );
 	void 	*closure;
-
-# ifdef USE_EXECNT
-	char	*tempfile;
-# endif
-
 } cmdtab[ MAXJOBS ] = {{0}};
 
 /*
@@ -98,7 +82,7 @@
 void
 execcmd( 
 	char *string,
-	void (*func)( void *closure, int status ),
+	void (*func)( void *closure, int status, timing_info* ),
 	void *closure,
 	LIST *shell )
 {
@@ -106,10 +90,6 @@
 	int slot;
 	char *argv[ MAXARGC + 1 ];	/* +1 for NULL */
 
-# ifdef USE_EXECNT
-	char *p;
-# endif
-
 	/* Find a slot in the running commands table for this one. */
 
 	for( slot = 0; slot < MAXJOBS; slot++ )
@@ -122,50 +102,7 @@
 	    exit( EXITBAD );
 	}
 
-# ifdef USE_EXECNT
-	if( !cmdtab[ slot ].tempfile )
-	{
-	    char *tempdir;
 
-	    if( !( tempdir = getenv( "TEMP" ) ) &&
-		!( tempdir = getenv( "TMP" ) ) )
-		    tempdir = "\\temp";
-
-	    cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 14 );
-
-	    sprintf( cmdtab[ slot ].tempfile, "%s\\jamtmp%02d.bat", 
-				tempdir, slot );
-	}
-
-	/* Trim leading, ending white space */
-
-	while( isspace( *string ) )
-		++string;
-
-	p = strchr( string, '\n' );
-
-	while( p && isspace( *p ) )
-		++p;
-
-	/* If multi line, or too long, or JAMSHELL is set, write to bat file. */
-	/* Otherwise, exec directly. */
-	/* Frankly, if it is a single long line I don't think the */
-	/* command interpreter will do any better -- it will fail. */
-
-	if( p && *p || strlen( string ) > MAXLINE || shell )
-	{
-	    FILE *f;
-
-	    /* Write command to bat file. */
-
-	    f = fopen( cmdtab[ slot ].tempfile, "w" );
-	    fputs( string, f );
-	    fclose( f );
-
-	    string = cmdtab[ slot ].tempfile;
-	}
-# endif
-
 	/* Forumulate argv */
 	/* If shell was defined, be prepared for % and ! subs. */
 	/* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
@@ -197,13 +134,8 @@
 	}
 	else
 	{
-# ifdef USE_EXECNT
-	    argv[0] = "cmd.exe";
-	    argv[1] = "/Q/C";		/* anything more is non-portable */
-# else
 	    argv[0] = "/bin/sh";
 	    argv[1] = "-c";
-# endif
 	    argv[2] = string;
 	    argv[3] = 0;
 	}
@@ -215,13 +147,6 @@
 
 	/* Start the command */
 
-# ifdef USE_EXECNT
-	if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
-	{
-	    perror( "spawn" );
-	    exit( EXITBAD );
-	}
-# else
 	if ((pid = vfork()) == 0) 
    	{
 		execvp( argv[0], argv );
@@ -233,7 +158,7 @@
 	    perror( "vfork" );
 	    exit( EXITBAD );
 	}
-# endif
+
 	/* Save the operation for execwait() to find. */
 
 	cmdtab[ slot ].pid = pid;
@@ -258,14 +183,17 @@
 	int i;
 	int status, w;
 	int rstat;
-
+    timing_info time;
+    struct tms old_time, new_time;
+    
 	/* Handle naive make1() which doesn't know if cmds are running. */
 
 	if( !cmdsrunning )
 	    return 0;
 
-	/* Pick up process pid and status */
+    times(&old_time);
     
+	/* Pick up process pid and status */
 	while( ( w = wait( &status ) ) == -1 && errno == EINTR )
 		;
 
@@ -276,6 +204,11 @@
 	    exit( EXITBAD );
 	}
 
+    times(&new_time);
+
+    time.system = (double)(new_time.tms_cstime - old_time.tms_cstime) / CLOCKS_PER_SEC;
+    time.user = (double)(new_time.tms_cutime - old_time.tms_cutime) / CLOCKS_PER_SEC;
+    
 	/* Find the process in the cmdtab. */
 
 	for( i = 0; i < MAXJOBS; i++ )
@@ -288,6 +221,7 @@
 	    exit( EXITBAD );
 	}
 
+    
 	/* Drive the completion */
 
 	if( !--cmdsrunning )
@@ -302,7 +236,7 @@
 
 	cmdtab[ i ].pid = 0;
 
-	(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
+	(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time );
 
 	return 1;
 }

Modified: boost-jam/trunk/expand.c
===================================================================
--- boost-jam/trunk/expand.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/expand.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,9 @@
+/*
+ * 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"
@@ -130,14 +136,14 @@
     /*
      * Input so far (ignore blanks):
      *
-     *	stuff-in-outbuf $(variable) remainder
-     *			 ^	             ^
-     *			 in		     end
+     *  stuff-in-outbuf $(variable) remainder
+     *                   ^                   ^
+     *                   in                  end
      * Output so far:
      *
-     *	stuff-in-outbuf $
-     *	^	         ^
-     *	out_buf          out
+     *  stuff-in-outbuf $
+     *  ^                ^
+     *  out_buf          out
      *
      *
      * We just copied the $ of $(...), so back up one on the output.
@@ -163,9 +169,9 @@
     /*
      * Input so far (ignore blanks):
      *
-     *	stuff-in-outbuf $(variable) remainder
-     *			  ^	   ^         ^
-     *			  inp      in        end
+     *  stuff-in-outbuf $(variable) remainder
+     *                    ^        ^         ^
+     *                    inp      in        end
      */
     prefix_length = buf->size;
     string_append_range( buf, inp, in - 1 );
@@ -184,14 +190,14 @@
     /*
      * Input so far (ignore blanks):
      *
-     *	stuff-in-outbuf $(variable) remainder
-     *			            ^        ^
-     *			            in       end
+     *  stuff-in-outbuf $(variable) remainder
+     *                              ^        ^
+     *                              in       end
      * Output so far:
      *
-     *	stuff-in-outbuf variable
-     *	^	        ^       ^
-     *	out_buf         out	ov
+     *  stuff-in-outbuf variable
+     *  ^               ^       ^
+     *  out_buf         out     ov
      *
      * Later we will overwrite 'variable' in out_buf, but we'll be
      * done with it by then.  'variable' may be a multi-element list, 
@@ -708,3 +714,9 @@
     lol_free(lol);
 }
 #endif
+
+/*
+     Local Variables:
+     tab-width: 8
+     End:
+ */

Modified: boost-jam/trunk/filemac.c
===================================================================
--- boost-jam/trunk/filemac.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/filemac.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -156,6 +156,20 @@
 	return 0;
 }
 
+int file_is_file(char* filename)
+{
+	struct stat statbuf;
+
+	if( stat( filename, &statbuf ) < 0 )
+	    return -1;
+
+    if (S_ISREG(statbuf.st_mode)) 
+        return 1;
+    else
+        return 0;    
+}
+
+
 /*
  * file_archscan() - scan an archive for files
  */

Modified: boost-jam/trunk/filent.c
===================================================================
--- boost-jam/trunk/filent.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/filent.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -54,7 +54,7 @@
  */
 
 void
-file_dirscan( 
+file_dirscan(
 	char *dir,
 	scanback func,
 	void *closure )
@@ -67,7 +67,7 @@
     struct _finddata_t finfo[1];
 
     dir = short_path_to_long_path( dir );
-	
+
     /* First enter directory itself */
 
     memset( (char *)&f, '\0', sizeof( f ) );
@@ -78,7 +78,7 @@
     dir = *dir ? dir : ".";
 
     /* Special case \ or d:\ : enter it */
- 
+
     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] == ':' )
@@ -123,7 +123,7 @@
         string_free( filespec );
         return;
     }
-        
+
     string_new( filename );
     while( !ret )
     {
@@ -134,7 +134,7 @@
         path_build( &f, filename, 0 );
 
         (*func)( closure, filename->value, 1 /* stat()'ed */, finfo->time_write );
- 
+
         ret = _findnext( handle, finfo );
     }
 
@@ -165,6 +165,20 @@
 	return 0;
 }
 
+int file_is_file(char* filename)
+{
+	struct stat statbuf;
+
+	if( stat( filename, &statbuf ) < 0 )
+	    return -1;
+
+    if (statbuf.st_mode & S_IFREG) 
+        return 1;
+    else
+        return 0;    
+}
+
+
 /*
  * file_archscan() - scan an archive for files
  */
@@ -237,9 +251,10 @@
 		** 15 characters (ie. don't fit into a ar_name
 		*/
 
-		string_table = malloc(lar_size);
+		string_table = malloc(lar_size+1);
 		if (read(fd, string_table, lar_size) != lar_size)
 		    printf("error reading string table\n");
+		string_table[lar_size] = '\0';
 		offset += SARHDR + lar_size;
 		continue;
 	    }
@@ -251,7 +266,7 @@
 		*/
 
 		name = string_table + atoi( ar_hdr.ar_name + 1 );
-		endname = name + strlen( name );
+		for ( endname = name; *endname && *endname != '\n'; ++endname) {}
 	    }
 	    else
 	    {
@@ -263,7 +278,7 @@
 	    /* strip trailing white-space, slashes, and backslashes */
 
 	    while( endname-- > name )
-		if( !isspace(*endname) && *endname != '\\' && *endname != '/' )
+	    	if( !isspace(*endname) && *endname != '\\' && *endname != '/' )
 		    break;
 	    *++endname = 0;
 

Modified: boost-jam/trunk/filesys.h
===================================================================
--- boost-jam/trunk/filesys.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/filesys.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -27,5 +27,6 @@
 int file_time( char *filename, time_t *time );
 
 void file_build1(PATHNAME *f, string* file) ;
+int file_is_file(char* filename);
 
 #endif

Modified: boost-jam/trunk/fileunix.c
===================================================================
--- boost-jam/trunk/fileunix.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/fileunix.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -199,6 +199,20 @@
 	return 0;
 }
 
+int file_is_file(char* filename)
+{
+	struct stat statbuf;
+
+	if( stat( filename, &statbuf ) < 0 )
+	    return -1;
+
+    if (S_ISREG(statbuf.st_mode)) 
+        return 1;
+    else
+        return 0;    
+}
+
+
 /*
  * file_archscan() - scan an archive for files
  */
@@ -236,8 +250,13 @@
 	if( DEBUG_BINDSCAN )
 	    printf( "scan archive %s\n", archive );
 
-	while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
-	       !memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
+	while( read( fd, &ar_hdr, SARHDR ) == SARHDR
+	       && ! ( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
+#ifdef ARFZMAG
+		      /* OSF also has a compressed format */
+		      && memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
+#endif
+	      ) )
 	{
 	    char    lar_name_[257];
             char*   lar_name = lar_name_ + 1;

Modified: boost-jam/trunk/frames.h
===================================================================
--- boost-jam/trunk/frames.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/frames.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -15,6 +15,9 @@
 struct frame
 {
     FRAME* prev;
+    /** The nearest enclosing frame for which module->user_module is
+        true. */
+    FRAME* prev_user;
     LOL args[1];
     module_t* module;
     PARSE* procedure;

Modified: boost-jam/trunk/index.html
===================================================================
--- boost-jam/trunk/index.html	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/index.html	2005-12-22 12:04:37 UTC (rev 13928)
@@ -20,7 +20,7 @@
       <tr>
         <td valign="top" width="300">
           <h3><a href="../../../index.htm"><img height="86" width="277" alt=
-          "C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
+          "C++ Boost" src="../../../boost.png" border="0"></a></h3>
         </td>
 
         <td valign="top">
@@ -120,21 +120,26 @@
 
         <dt><a href="#semaphores">Semaphores</a></dt>
 
-        <dt><a href="#semaphores">The W32_GETREG rule</a></dt>
+        <dt><a href="#w32_getreg">The W32_GETREG rule</a></dt>
+
+        <dt><a href="#ISFILE_rule">The <tt>ISFILE</tt> rule</a></dt>
+
+        <dt><a href="#SHELL_rule">The <tt>SHELL</tt> rule</a></dt>
       </dl>
     </dd>
 
     <dt><a href="#jam_fundamentals">Jam Fundamentals</a></dt>
   </dl>
 
-  <h2><a name="introduction"></a>Introduction</h2>
+  <h2><a name="introduction" id="introduction"></a>Introduction</h2>
 
   <p>Boost.Jam (BJam) &nbsp;is a build tool based on FTJam, which in turn is
   based on Perforce Jam. It contains significant improvements made to
   facilitate its use in the Boost Build System, but should be backward
   compatible with Perforce Jam.</p>
 
-  <p>This is version 3.1.10 of BJam and is based on version 2.4 of Jam/MR:</p>
+  <p>This is version 3.1.10 of BJam and is based on version 2.4 of
+  Jam/MR:</p>
   <pre>
 /+\
 +\  Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
@@ -146,7 +151,7 @@
 ALL WARRANTIES ARE HEREBY DISCLAIMED.
 </pre>
 
-  <h2><a name="features"></a>Features</h2>
+  <h2><a name="features" id="features"></a>Features</h2>
 
   <p>Jam is a make(1) replacement that makes building simple things simple
   and building complicated things manageable.</p>
@@ -176,7 +181,7 @@
   <p>Jam isn't under the blinkin GNU copyright, so you can incorporate it
   into commercial products.</p>
 
-  <h2><a name="contents"></a>Contents</h2>
+  <h2><a name="contents" id="contents"></a>Contents</h2>
 
   <table cellpadding="2" cellspacing="2" border="0" summary=
   "Contents of Jam documents.">
@@ -193,7 +198,7 @@
     </tr>
   </table>
 
-  <h2><a name="building_bjam"></a>Building Boost.Jam</h2>
+  <h2><a name="building_bjam" id="building_bjam"></a>Building Boost.Jam</h2>
 
   <p>Installing BJam after building it is simply a matter of copying the
   generated executables someplace in your <tt>PATH</tt>. For building the
@@ -421,11 +426,8 @@
 
   <p>The built executables are placed in a subdirectory specific to your
   platform. For example, in Linux running on an Intel x86 compatible chip,
-  the executables are placed in: <tt>"bin.linuxx86"</tt>. There are two
-  executables generated: <tt>jam[.exe]</tt>, and <tt>bjam[.exe]</tt>, both
-  are the same binary but with different names. The "jam" invocation is used
-  for compatability with the Perforce Jam/MR functionality, whereas "bjam" is
-  used for the extended Boost.Build functionality.</p>
+  the executables are placed in: <tt>"bin.linuxx86"</tt>. 
+  The <tt>bjam[.exe]</tt> executable can be used to invoke Boost.Build.</p>
 
   <p>The <tt>build</tt> scripts support additional invocation arguments for
   use by developers of Boost.Jam. The extra arguments come after the toolset,
@@ -446,14 +448,15 @@
   as appropriate for distribution in the platform, or remove all the built
   executables and objects.</p>
 
-  <h2><a name="core_extensions">Core Jam Extensions</a></h2>
+  <h2><a name="core_extensions" id="core_extensions">Core Jam
+  Extensions</a></h2>
 
   <p>A number of enhancements have been made to the core language of Classic
   Jam. These changes were aimed primarily at making it easier to manage the
   complexity of a large system such as Boost.Build.</p>
 
-  <h3><a name="variable_quoting"></a>Command-line and Environment Variable
-  Quoting</h3>
+  <h3><a name="variable_quoting" id="variable_quoting"></a>Command-line and
+  Environment Variable Quoting</h3>
 
   <p>Classic Jam had an <a href="#variable_splitting">odd behavior</a> with
   respect to command-line variable ( <tt>-s...</tt>) and environment variable
@@ -476,7 +479,8 @@
 set MSVCNT=""C:\Program Files\Microsoft Visual C++\VC98\""
 </pre>
 
-  <h3><a name="jambase_replacement">Startup Behavior</a></h3>
+  <h3><a name="jambase_replacement" id="jambase_replacement">Startup
+  Behavior</a></h3>
 
   <p>The Boost.Build v2 initialization behavior has been implemented. This
   behavior only applies when the executable being invoked is called
@@ -512,7 +516,8 @@
     message and exit.</li>
   </ol>
 
-  <h3><a name="rule_indirection">Rule Indirection</a></h3>
+  <h3><a name="rule_indirection" id="rule_indirection">Rule
+  Indirection</a></h3>
 
   <p>Boost Jam allows you to call a rule whose name is held in a variable or
   computed as the result of an expression:</p>
@@ -545,7 +550,7 @@
 ECHO [ filter 1 2 3 4 5 4 3 : equal 3 ] ; # prints "3 3"
 </pre>
 
-  <h3><a name="argument_lists">Argument lists</a></h3>
+  <h3><a name="argument_lists" id="argument_lists">Argument lists</a></h3>
 
   <p>You can now describe the arguments accepted by a rule, and refer to them
   by name within the rule. For example, the following prints ``I'm sorry,
@@ -612,7 +617,7 @@
   readability of your rules, however, and are <b>strongly recommended</b> for
   any new Jam code you write.</p>
 
-  <h3><a name="module_support">Module Support</a></h3>
+  <h3><a name="module_support" id="module_support">Module Support</a></h3>
 
   <p>Boost Jam introduces support for modules, which provide some rudimentary
   namespace protection for rules and variables. A new keyword,
@@ -621,7 +626,8 @@
   operations needed to write Jam rules which provide a more elegant module
   interface.</p>
 
-  <h4><a name="module_declaration">Declaration</a></h4>
+  <h4><a name="module_declaration" id=
+  "module_declaration">Declaration</a></h4>
   <pre>
 module <i>expression</i> { ... }
 </pre>
@@ -651,7 +657,7 @@
 }
 </pre>
 
-  <h4><a name="module_locals">Variable Scope</a></h4>
+  <h4><a name="module_locals" id="module_locals">Variable Scope</a></h4>
 
   <p>Each module has its own set of dynamically nested variable scopes. When
   execution passes from module A to module B, all the variable bindings from
@@ -696,7 +702,7 @@
 module scope is entered, argument bindings become unavailable. That explains
 the use of "<code>$(&gt;)</code>" in the <code>peek</code> rule above.
 
-  <h4><a name="local_rules">Local Rules</a></h4>
+  <h4><a name="local_rules" id="local_rules">Local Rules</a></h4>
   <pre>
 local rule <i>rulename...</i>
 </pre>
@@ -708,7 +714,8 @@
 [ RULENAMES <i>module-name</i> ]
 </pre>
 
-  <h4><a name="RULENAMES_rule">The <tt>RULENAMES</tt> Rule</a></h4>
+  <h4><a name="RULENAMES_rule" id="RULENAMES_rule">The <tt>RULENAMES</tt>
+  Rule</a></h4>
   <pre>
 rule RULENAMES ( module ? )
 </pre>
@@ -717,7 +724,8 @@
   If <tt>module</tt> is omitted, the names of all non-local rules in the
   global module are returned.</p>
 
-  <h4><a name="VARNAMES_rule">The <tt>VARNAMES</tt> Rule</a></h4>
+  <h4><a name="VARNAMES_rule" id="VARNAMES_rule">The <tt>VARNAMES</tt>
+  Rule</a></h4>
   <pre>
 rule VARNAMES ( module ? )
 </pre>
@@ -728,7 +736,8 @@
   variables in rules from the call stack which have not returned at the time
   of the <code>VARNAMES</code> invocation.</p>
 
-  <h4><a name="IMPORT_rule">The <tt>IMPORT</tt> Rule</a></h4>
+  <h4><a name="IMPORT_rule" id="IMPORT_rule">The <tt>IMPORT</tt>
+  Rule</a></h4>
 
   <p><tt>IMPORT</tt> allows rule name aliasing across modules:</p>
   <pre>
@@ -752,7 +761,8 @@
 IMPORT m1 : [ RULENAMES m1 ] : m2 : [ RULENAMES m1 ] ;
 </pre>
 
-  <h4><a name="EXPORT_rule">The <tt>EXPORT</tt> Rule</a></h4>
+  <h4><a name="EXPORT_rule" id="EXPORT_rule">The <tt>EXPORT</tt>
+  Rule</a></h4>
 
   <p><tt>EXPORT</tt> allows rule name aliasing across modules:</p>
   <pre>
@@ -772,7 +782,8 @@
 IMPORT X : r : : r ; # OK.
 </pre>
 
-  <h4><a name="CALLER_MODULE_rule">The <tt>CALLER_MODULE</tt> Rule</a></h4>
+  <h4><a name="CALLER_MODULE_rule" id="CALLER_MODULE_rule">The
+  <tt>CALLER_MODULE</tt> Rule</a></h4>
   <pre>
 rule CALLER_MODULE ( levels ? )
 </pre>
@@ -797,7 +808,8 @@
 ECHO {$(callers)} ;
 </pre>
 
-  <h4><a name="DELETE_MODULE_rule">The <tt>DELETE_MODULE</tt> Rule</a></h4>
+  <h4><a name="DELETE_MODULE_rule" id="DELETE_MODULE_rule">The
+  <tt>DELETE_MODULE</tt> Rule</a></h4>
   <pre>
 rule DELETE_MODULE ( module ? )
 </pre>
@@ -812,7 +824,8 @@
   variables which are shadowed by locals will not be destroyed, so the
   results can be really unpredictable.</p>
 
-  <h3><a name="local_foreach">Local For Loop Variables</a></h3>
+  <h3><a name="local_foreach" id="local_foreach">Local For Loop
+  Variables</a></h3>
 
   <p>Boost Jam allows you to declare a local <tt>for</tt> loop control
   variable right in the loop:</p>
@@ -826,7 +839,8 @@
 ECHO $(y) ;     # prints "4 5 6"
 </pre>
 
-  <h4><a name="negative_indexing">Negative Indexing</a></h4>
+  <h4><a name="negative_indexing" id="negative_indexing">Negative
+  Indexing</a></h4>
 
   <p>Classic Jam supplies 1-based list indexing, and slicing on a closed
   (inclusive) range:</p>
@@ -850,7 +864,8 @@
   use of ``<tt>-</tt>'' as the range separator make this feature a bit
   clumsier than it would otherwise need to be, but it does work.</p>
 
-  <h4><a name="cygwin_support">Support for Cygwin</a></h4>
+  <h4><a name="cygwin_support" id="cygwin_support">Support for
+  Cygwin</a></h4>
 
   <p>When invoking Windows-based tools from <a href=
   "www.cygwin.com">Cygwin</a> it can be important to pass them true
@@ -865,7 +880,7 @@
 ECHO $(x:W) ; # prints "c:\Program Files\Borland" on Cygwin
 </pre>
 
-  <h4><a name="BINDRULE">Target Binding Detection</a></h4>
+  <h4><a name="BINDRULE" id="BINDRULE">Target Binding Detection</a></h4>
 
   <p>Whenever a target is <a href="#binding">bound</a> to a location in the
   filesystem, Boost Jam will look for a variable called <tt>BINDRULE</tt>
@@ -882,7 +897,8 @@
   containing the file doing the <tt>#include</tt> directive.
   <tt>$(BINDRULE)</tt> can be used to make a record of that directory.</p>
 
-  <h4><a name="FAIL_EXPECTED">Return Code Inversion</a></h4>
+  <h4><a name="FAIL_EXPECTED" id="FAIL_EXPECTED">Return Code
+  Inversion</a></h4>
 
   <p>For handling targets whose build actions are expected to fail (e.g. when
   testing that assertions or compile-time type checkin work properly), Boost
@@ -892,7 +908,7 @@
   fails, building of dependent targets continues as though it succeeded. If
   it succeeds, dependent targets are skipped.</p>
 
-  <h4><a name="NOCARE">Ignoring Return Codes</a></h4>
+  <h4><a name="NOCARE" id="NOCARE">Ignoring Return Codes</a></h4>
 
   <p>Perforce Jam supplied a <tt>NOCARE</tt> rule which is typically used for
   header files to indicate that if they are not found, the dependent targets
@@ -900,7 +916,7 @@
   targets with build actions: if their build actions exit with a nonzero
   return code, dependent targets will still be built.</p>
 
-  <h4><a name="RMOLD">Removing Outdated Targets</a></h4>
+  <h4><a name="RMOLD" id="RMOLD">Removing Outdated Targets</a></h4>
   <pre>
 rule RMOLD ( targets * )
 </pre>
@@ -911,7 +927,7 @@
   causes its arguments to be removed if any of their dependencies fail to
   build.</p>
 
-  <h3><a name="SUBST_rule">The <tt>SUBST</tt> Rule</a></h3>
+  <h3><a name="SUBST_rule" id="SUBST_rule">The <tt>SUBST</tt> Rule</a></h3>
 
   <p><b>Note:</b> the <code>SUBST</code> rule is deprecated in favor of
   Perforce Jam's built-in <code>MATCH</code> rule, which has been rolled into
@@ -944,16 +960,19 @@
     string.</li>
   </ul>
 
-  <h3><a name="JAM_VERSION">The <tt>JAM_VERSION</tt> global variable</a></h3>
+  <h3><a name="JAM_VERSION" id="JAM_VERSION">The <tt>JAM_VERSION</tt> global
+  variable</a></h3>
 
   <p>A predefined global variable with two elements indicates the version
   number of Boost Jam. Boost Jam versions start at <tt>"03" "00"</tt>.
   Earlier versions of Jam do not automatically define
   <tt>JAM_VERSION</tt>.</p>
 
-  <h3><a name="debugging_support">Debugging Support</a></h3>
+  <h3><a name="debugging_support" id="debugging_support">Debugging
+  Support</a></h3>
 
-  <h4><a name="BACKTRACE_rule">The BACKTRACE rule</a></h4>
+  <h4><a name="BACKTRACE_rule" id="BACKTRACE_rule">The BACKTRACE
+  rule</a></h4>
   <pre>
 rule BACKTRACE ( )
 </pre>
@@ -965,23 +984,23 @@
   <p>The <tt>-d</tt> command-line option admits new arguments:</p>
 
   <ul>
-    <li><tt>-d+10</tt> - enables <a name="profiling"><b>profiling</b></a> of
-    rule invocations. When Jam exits, it dumps all rules invoked, their gross
-    and net times in platform-dependent units, and the number of times the
-    rule was invoked.</li>
+    <li><tt>-d+10</tt> - enables <a name="profiling" id=
+    "profiling"><b>profiling</b></a> of rule invocations. When Jam exits, it
+    dumps all rules invoked, their gross and net times in platform-dependent
+    units, and the number of times the rule was invoked.</li>
 
-    <li><tt>-d+11</tt> - enables <a name="parse_debugging"><b>parser
-    debugging</b></a>, if Jam has been compiled with the "--debug" option to
-    the parser generator named by $(YACC).</li>
+    <li><tt>-d+11</tt> - enables <a name="parse_debugging" id=
+    "parse_debugging"><b>parser debugging</b></a>, if Jam has been compiled
+    with the "--debug" option to the parser generator named by $(YACC).</li>
 
-    <li><tt>-d+12</tt> - enables <a name="dependency_graph"><b>dependency
-    graph output</b></a> . This feature was ``stolen'' from a version of Jam
-    modified by <a href="mailto:cmcpheeters at aw.sgi.com">Craig
-    McPheeters</a>.</li>
+    <li><tt>-d+12</tt> - enables <a name="dependency_graph" id=
+    "dependency_graph"><b>dependency graph output</b></a> . This feature was
+    ``stolen'' from a version of Jam modified by <a href=
+    "mailto:cmcpheeters at aw.sgi.com">Craig McPheeters</a>.</li>
   </ul>
 
-  <h3><a name="UPDATE">The <tt>UPDATE</tt> rule and changes to command line
-  handling</a></h3>
+  <h3><a name="UPDATE" id="UPDATE">The <tt>UPDATE</tt> rule and changes to
+  command line handling</a></h3>
 
   <p>Classic jam treats any non-option element of command line as a name of
   target to be updated. This prevented more sophisticated handling of command
@@ -1027,44 +1046,67 @@
   option.</p>
 
   <h3 id="w32_getreg">The W32_GETREG rule</h3>
-<pre>
+  <pre>
     rule W32_GETREG ( path : data ? )
 </pre>
 
-<p>    
-    Defined only for win32 platform. It reads the registry of Windows.
-    'path' is the location of the information, and 'data' is
-    the name of the value which we want to get. If 'data' is omitted,
-    the default value of 'path' will be returned. The 'path' value
-    must conform to MS key path format and must be prefixed with
-    one of the predefined root keys. As usual,
+  <p>Defined only for win32 platform. It reads the registry of Windows.
+  'path' is the location of the information, and 'data' is the name of the
+  value which we want to get. If 'data' is omitted, the default value of
+  'path' will be returned. The 'path' value must conform to MS key path
+  format and must be prefixed with one of the predefined root keys. As
+  usual,</p>
 
-<ul>    
-    <li>'HKLM' is equivalent to 'HKEY_LOCAL_MACHINE'.
-    <li>'HKCU' is equivalent to 'HKEY_CURRENT_USER'.
-    <li>'HKCR' is equivalent to 'HKEY_CLASSES_ROOT'.
-</ul>    
-    
-<p>    
-    Other predefined root keys are not supported.    
-<p>    
-    Currently supported data types : 'REG_DWORD', 'REG_SZ',
-    'REG_EXPAND_SZ', 'REG_MULTI_SZ'. The data with 'REG_DWORD' type
-    will be turned into a string, 'REG_MULTI_SZ' into a list of strings,
-    and for those with 'REG_EXPAND_SZ' type environment variables
-    in it will be replaced with their defined values.
-    The data with 'REG_SZ' type and other unsupported types
-    will be put into a string without modification. If it can't
-    receive the value of the data, it just return an empty list.
-    For example,
+  <ul>
+    <li>'HKLM' is equivalent to 'HKEY_LOCAL_MACHINE'.</li>
 
-<pre>
+    <li>'HKCU' is equivalent to 'HKEY_CURRENT_USER'.</li>
+
+    <li>'HKCR' is equivalent to 'HKEY_CLASSES_ROOT'.</li>
+  </ul>
+
+  <p>Other predefined root keys are not supported.</p>
+
+  <p>Currently supported data types : 'REG_DWORD', 'REG_SZ', 'REG_EXPAND_SZ',
+  'REG_MULTI_SZ'. The data with 'REG_DWORD' type will be turned into a
+  string, 'REG_MULTI_SZ' into a list of strings, and for those with
+  'REG_EXPAND_SZ' type environment variables in it will be replaced with
+  their defined values. The data with 'REG_SZ' type and other unsupported
+  types will be put into a string without modification. If it can't receive
+  the value of the data, it just return an empty list. For example,</p>
+  <pre>
     local PSDK-location =
     [ PROFILE HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MicrosoftSDK\\Directories : "Install Dir" ] ;
 </pre>
 
-  <h2><a name="jam_fundamentals">Jam Fundamentals</a></h2>
+  <h4><a name="ISFILE_rule" id="ISFILE_rule">The <tt>ISFILE</tt>
+  Rule</a></h4>
+  <pre>
+rule ISFILE ( targets * )
+</pre>
 
+  <p><tt>ISFILE</tt> marks targets as required to be files. This changes the
+  way <b>jam</b> searches for the target such that it ignores mathes for file
+  system items that are not file, like directories. This makes it possible to
+  avoid <code>#include "exception"</code> matching if one happens to have a
+  directory named <i>exception</i> in the header search path.</p>
+
+  <h4><a name="SHELL_rule" id="SHELL_rule">The <tt>SHELL</tt>
+  Rule</a></h4>
+  <pre>
+rule SHELL ( command )
+</pre>
+
+  <p><tt>SHELL</tt> executes <i>command</i>, and then returns the standard
+  output of <i>command</i>.  SHELL only works on platforms with a popen() function 
+  in the C library.  On platforms without a working popen() function,
+  SHELL is implemented as a no-op.  SHELL works on Unix, MacOS X,
+  and most Windows compilers.  SHELL is a no-op on Metrowerks compilers
+  under Windows.</p>.  
+
+  <h2><a name="jam_fundamentals" id="jam_fundamentals">Jam
+  Fundamentals</a></h2>
+
   <p>This section is derived from the official Jam documentation and from my
   experience using it and reading the Jambase rules. I repeat the information
   here mostly because it is essential to understanding and using Jam, but is
@@ -1094,17 +1136,18 @@
   argument. It is actually possible to invoke an undeclared rule if
   corresponding actions are declared: the rule is treated as empty.</p>
 
-  <p>&middot; <a name="binding">Targets</a> (other than <tt>NOTFILE</tt>
-  targets) are associated with paths in the file system through a process
-  called <a href="./Jam.html#binding">binding</a>. Binding is a process of
-  searching for a file with the same name as the target (sans grist), based
-  on the settings of the <a href="#target_specific">target-specific</a>
-  <tt>SEARCH</tt> and <tt>LOCATE</tt> variables.</p>
+  <p>&middot; <a name="binding" id="binding">Targets</a> (other than
+  <tt>NOTFILE</tt> targets) are associated with paths in the file system
+  through a process called <a href="./Jam.html#binding">binding</a>. Binding
+  is a process of searching for a file with the same name as the target (sans
+  grist), based on the settings of the <a href=
+  "#target_specific">target-specific</a> <tt>SEARCH</tt> and <tt>LOCATE</tt>
+  variables.</p>
 
-  <p>&middot; <a name="target_specific">In addition to</a> local and global
-  variables, jam allows you to set a variable <tt><b>on</b></tt> a target.
-  Target-specific variable values can usually not be read, and take effect
-  <i>only</i> in the following contexts:</p>
+  <p>&middot; <a name="target_specific" id="target_specific">In addition
+  to</a> local and global variables, jam allows you to set a variable
+  <tt><b>on</b></tt> a target. Target-specific variable values can usually
+  not be read, and take effect <i>only</i> in the following contexts:</p>
 
   <ul>
     <li>In updating <tt>actions</tt>, variable values are first looked up
@@ -1170,14 +1213,15 @@
   the form <tt>&lt;</tt><i>expr2</i><tt>&gt;</tt>;
   <tt>&lt;</tt><i>expr2</i><tt>&gt;</tt> is then prepended.</p>
 
-  <p>&middot; <a name="variable_splitting">When Jam</a> is invoked it imports
-  all environment variable settings into corresponding Jam variables,
-  followed by all command-line (<tt>-s...</tt>) variable settings. Variables
-  whose name ends in <tt>PATH</tt>, <tt>Path</tt>, or <tt>path</tt> are split
-  into string lists on OS-specific path-list separator boundaries (e.g.
-  "<tt>:</tt>" for UNIX and "<tt>;</tt>" for Windows). All other variables
-  are split on space (" ") boundaries. Boost Jam modifies that behavior by
-  allowing variables to be <a href="#variable_quoting">quoted</a>.</p>
+  <p>&middot; <a name="variable_splitting" id="variable_splitting">When
+  Jam</a> is invoked it imports all environment variable settings into
+  corresponding Jam variables, followed by all command-line (<tt>-s...</tt>)
+  variable settings. Variables whose name ends in <tt>PATH</tt>,
+  <tt>Path</tt>, or <tt>path</tt> are split into string lists on OS-specific
+  path-list separator boundaries (e.g. "<tt>:</tt>" for UNIX and "<tt>;</tt>"
+  for Windows). All other variables are split on space (" ") boundaries.
+  Boost Jam modifies that behavior by allowing variables to be <a href=
+  "#variable_quoting">quoted</a>.</p>
 
   <p>&middot; A variable whose value is an empty list <i>or</i> which
   consists entirely of empty strings has a negative logical value. Thus, for
@@ -1208,13 +1252,13 @@
 
   <p>Revised 
   <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
-   18 November, 2003 
+   18 November, 2004 
   <!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
 
   <p>Copyright 2003-2004 Rene Rivera, David Abrahams, Vladimir Prus.</p>
 
-  <p>Distributed under the Boost Software License, Version 1.0.
-  (See accompanying file LICENSE_1_0.txt or <a href="http://www.boost.org/LICENSE_1_0.txt">
-  http://www.boost.org/LICENSE_1_0.txt)</a></p>
+  <p>Distributed under the Boost Software License, Version 1.0. (See
+  accompanying file LICENSE_1_0.txt or <a href=
+  "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt)</a></p>
 </body>
 </html>

Modified: boost-jam/trunk/jam.c
===================================================================
--- boost-jam/trunk/jam.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/jam.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -196,6 +196,14 @@
 }
 #endif
 
+#ifdef HAVE_PYTHON
+    extern PyObject*
+    bjam_call(PyObject *self, PyObject *args);
+ 
+    extern PyObject*
+    bjam_import_rule(PyObject* self, PyObject* args);
+#endif
+
 int  main( int argc, char **argv, char **arg_environ )
 {
     int		n;
@@ -206,16 +214,34 @@
     int		status;
     int arg_c = argc;
     char ** arg_v = argv;
+    const char *progname = argv[0];
 
 # ifdef OS_MAC
     InitGraf(&qd.thePort);
 # endif
 
+#ifdef HAVE_PYTHON
+    Py_Initialize();
+
+    {
+        static PyMethodDef BjamMethods[] = {
+            {"call", bjam_call, METH_VARARGS,
+             "Call the specified bjam rule."},
+            {"import_rule", bjam_import_rule, METH_VARARGS,
+             "Imports Python callable to bjam."},
+            {NULL, NULL, 0, NULL}
+        };
+
+        Py_InitModule("bjam", BjamMethods);
+    }
+
+#endif
+
     argc--, argv++;
 
-	if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 )
+	if( getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) < 0 )
     {
-        printf( "\nusage: jam [ options ] targets...\n\n" );
+        printf( "\nusage: %s [ options ] targets...\n\n", progname );
 
         printf( "-a      Build all targets, even if they are current.\n" );
         printf( "-dx     Set the debug level to x (0-9).\n" );
@@ -233,8 +259,6 @@
         exit( EXITBAD );
     }
 
-    argc -= n, argv += n;
-
     /* Version info. */
 
     if( ( s = getoptval( optv, 'v', 0 ) ) )
@@ -244,7 +268,8 @@
 	   printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.  \n" );
         printf( "   Copyright 2001 David Turner.\n" );
         printf( "   Copyright 2001-2004 David Abrahams.\n" );
-        printf( "   Copyright 2002-2004 Rene Rivera.\n" );
+        printf( "   Copyright 2002-2005 Rene Rivera.\n" );
+        printf( "   Copyright 2003-2005 Vladimir Prus.\n" );
 
         return EXITOK;
     }
@@ -322,7 +347,7 @@
     {
    /* Pleace don't change the following line. The 'bump_version.py' script
        expect a specific format of it. */
-    char  *major_version = "03", *minor_version = "01", *changenum = "10";
+    char  *major_version = "03", *minor_version = "01", *changenum = "11";
     var_set( "JAM_VERSION",
              list_new( list_new( list_new( L0, newstr( major_version ) ), 
                                  newstr( minor_version ) ), 
@@ -352,16 +377,26 @@
     }
 # endif /* unix */
 
+    /* load up environment variables */
+
+    /* first into global module, with splitting, for backward compatibility */
+    var_defines( use_environ, 1 );
+    
+    /* then into .ENVIRON, without splitting */
+    enter_module( bindmodule(".ENVIRON") );
+    var_defines( use_environ, 0 );
+    exit_module( bindmodule(".ENVIRON") );
+
 	/*
 	 * Jam defined variables OS, OSPLAT
+     * We load them after environment, so that
+     * setting OS in environment does not 
+     * change Jam notion of the current platform.
 	 */
 
-    var_defines( othersyms );
+    var_defines( othersyms, 1 );
 
-    /* load up environment variables */
 
-    var_defines( use_environ );
-
     /* Load up variables set on command line. */
 
     for( n = 0; s = getoptval( optv, 's', n ); n++ )
@@ -369,7 +404,7 @@
         char *symv[2];
         symv[0] = s;
         symv[1] = 0;
-        var_defines( symv );
+        var_defines( symv, 1 );
     }
 
     /* Set the ARGV to reflect the complete list of arguments of invocation. */
@@ -385,9 +420,18 @@
 
     /* Add the targets in the command line to update list */
 
-    for ( n = 0; n < argc; ++n )
+    for ( n = 1; n < arg_c; ++n )
     {
-        mark_target_for_updating(argv[n]);
+        if ( arg_v[n][0] == '-' )
+        {
+            char *f = "-:d:j:f:gs:t:ano:qv";
+            for( ; *f; f++ ) if( *f == arg_v[n][1] ) break;
+            if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; }
+        }
+        else
+        {
+            mark_target_for_updating(arg_v[n]);
+        }
     }
 
     /* Parse ruleset */
@@ -459,5 +503,10 @@
     if( globs.cmdout )
         fclose( globs.cmdout );
 
+#ifdef HAVE_PYTHON
+    Py_Finalize();
+#endif
+
+
     return status ? EXITBAD : EXITOK;
 }

Modified: boost-jam/trunk/jam.h
===================================================================
--- boost-jam/trunk/jam.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/jam.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -37,6 +37,14 @@
 
 #ifndef JAM_H_VP_2003_08_01
 #define JAM_H_VP_2003_08_01
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+#endif
+
+/* Assume popen support is available unless known otherwise. */
+#define HAVE_POPEN 1
+
 /*
  * VMS, OPENVMS
  */
@@ -111,6 +119,12 @@
 # define OS_AS400
 # endif
 
+/* Metrowerks Standard Library on Windows. */
+
+# ifdef __MSL__
+#undef HAVE_POPEN
+#endif
+
 # endif
 
 /*
@@ -231,10 +245,14 @@
 # define OSMINOR "OS=CYGWIN"
 # define OS_CYGWIN
 # endif
-# ifdef __FreeBSD__
+# if defined(__FreeBSD__) && !defined(__DragonFly__)
 # define OSMINOR "OS=FREEBSD"
 # define OS_FREEBSD
 # endif
+# ifdef __DragonFly__
+# define OSMINOR "OS=DRAGONFLYBSD"
+# define OS_DRAGONFLYBSD
+# endif
 # ifdef __DGUX__
 # define OSMINOR "OS=DGUX"
 # define OS_DGUX
@@ -321,6 +339,9 @@
 # define OS_MACOSX
 # endif
 # ifdef __osf__
+# ifndef unix
+# define unix
+# endif
 # define OSMINOR "OS=OSF"
 # define OS_OSF
 # endif
@@ -394,6 +415,7 @@
 
 # if !defined(OS_BSDI) && \
      !defined(OS_FREEBSD) && \
+     !defined(OS_DRAGONFLYBSD) && \
      !defined(OS_NEXT) && \
      !defined(OS_MACHTEN) && \
      !defined(OS_MACOSX) && \
@@ -426,6 +448,7 @@
      defined( __i386__ ) || \
      defined( _M_IX86 )
 # if !defined( OS_FREEBSD ) && \
+     !defined( OS_DRAGONFLYBSD ) && \
      !defined( OS_OS2 ) && \
      !defined( OS_AS400 )
 # define OSPLAT "OSPLAT=X86"

Modified: boost-jam/trunk/jambase.c
===================================================================
--- boost-jam/trunk/jambase.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/jambase.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -23,6 +23,13 @@
 "{\n",
 "BOOST_BUILD_PATH = /usr/share/boost-build ;\n",
 "}\n",
+"rule _poke ( module-name ? : variables + : value * )\n",
+"{\n",
+"module $(<)\n",
+"{\n",
+"$(>) = $(3) ;\n",
+"}\n",
+"}\n",
 "rule boost-build ( dir ? )\n",
 "{\n",
 "if $(.bootstrap-file)\n",
@@ -34,6 +41,7 @@
 "EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
 "}\n",
 "BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;\n",
+"_poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;\n",
 "local bootstrap-file =\n",
 "[ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;\n",
 ".bootstrap-file = $(bootstrap-file[1]) ;\n",
@@ -65,11 +73,6 @@
 "[ find-to-root [ PWD ] : boost-build.jam ]\n",
 "[ GLOB $(search-path) : boost-build.jam ] ;\n",
 ".boost-build-file = $(boost-build-files[1]) ;\n",
-"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
-"{\n",
-"ECHO \"notice: found boost-build.jam at\" \n",
-"[ NORMALIZE_PATH $(.boost-build-file) ] ;\n",
-"}\n",
 "if ! $(.boost-build-file)\n",
 "{\n",
 "ECHO \"Unable to load Boost.Build: could not find \\\"boost-build.jam\\\"\" ;\n",
@@ -85,6 +88,11 @@
 "ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
 "EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
 "}\n",
+"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]      \n",
+"{\n",
+"ECHO \"notice: found boost-build.jam at\" \n",
+"[ NORMALIZE_PATH $(.boost-build-file) ] ;\n",
+"}\n",
 "include $(.boost-build-file) ;\n",
 "if ! $(.bootstrap-file)\n",
 "{\n",

Modified: boost-jam/trunk/make.c
===================================================================
--- boost-jam/trunk/make.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/make.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -82,6 +82,7 @@
 	"newer",	/* T_FATE_NEWER */
 	"temp", 	/* T_FATE_ISTMP */
 	"touched", 	/* T_FATE_TOUCHED */
+	"rebuild", 	/* T_FATE_REBUILD */
 	"missing", 	/* T_FATE_MISSING */
 	"needtmp", 	/* T_FATE_NEEDTMP */
 	"old", 		/* T_FATE_OUTDATED */
@@ -174,6 +175,63 @@
 	return status;
 }
 
+/* Force any dependents of t that have already at least begun being
+ * visited by make0 to be updated.
+ */
+static void update_dependents(TARGET* t)
+{
+    TARGETS *q;
+    
+    for (q = t->dependents; q; q = q->next)
+    {
+        TARGET* p = q->target;
+        char fate0 = p->fate;
+
+        /* If we've already at least begun visiting it and
+         * we're not already rebuilding it for other reasons
+         */
+        if (fate0 != T_FATE_INIT && fate0 < T_FATE_BUILD)
+        {
+            p->fate = T_FATE_UPDATE;
+            
+            if (DEBUG_FATE)
+            {
+                printf( "fate change  %s from %s to %s (as dependent of %s)\n",
+                        p->name, target_fate[fate0], target_fate[p->fate], t->name);
+            }
+    
+            /* If we're done visiting it, go back and make sure its
+             * dependents get rebuilt.
+             */
+            if (fate0 > T_FATE_MAKING)
+                update_dependents(p);
+        }
+    }
+}
+
+/* Make sure that all of t's rebuilds get rebuilt */
+static void force_rebuilds(TARGET* t)
+{
+    TARGETS* d;
+    for (d = t->rebuilds; d; d = d->next)
+    {
+        TARGET* r = d->target;
+
+        /* If it's not already being rebuilt for other reasons */
+        if (r->fate < T_FATE_BUILD)
+        {
+            if (DEBUG_FATE)
+                printf( "fate change  %s from %s to %s (by rebuild)\n",
+                        r->name, target_fate[r->fate], target_fate[T_FATE_REBUILD]);
+            
+            /* Force rebuild it */
+            r->fate = T_FATE_REBUILD;
+
+            /* And make sure its dependents are updated too */
+            update_dependents(r);
+        }
+    }
+}
 /*
  * make0() - bind and scan everything to make a TARGET
  *
@@ -362,7 +420,7 @@
 
 	last = 0;
 	leaf = 0;
-	fate = T_FATE_STABLE;
+    fate = T_FATE_STABLE;
 
 	for( c = t->depends; c; c = c->next )
 	{
@@ -515,7 +573,7 @@
 		       t->name, target_fate[fate],
 		       oldTimeStamp ? " (by timestamp)" : "" );
 	    else
-		printf( "fate change  %s adjusted from %s to %s%s\n",
+		printf( "fate change  %s from %s to %s%s\n",
 		       t->name, target_fate[savedFate], target_fate[fate],
 		       oldTimeStamp ? " (by timestamp)" : "" );
 #endif
@@ -551,8 +609,19 @@
 
 	t->time = max( t->time, last );
 	t->leaf = leaf ? leaf : t->time ;
-	t->fate = fate;
+    /* This target's fate may have been updated by virtue of following
+     * some target's rebuilds list, so only allow it to be increased
+     * to the fate we've calculated.  Otherwise, grab its new fate.
+     */
+    if (fate > t->fate)
+        t->fate = fate;
+    else
+        fate = t->fate;
 
+    /* Step 4g: if this target needs to be built, force rebuild
+     * everything in this target's rebuilds list */
+    if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN)
+        force_rebuilds(t);
 	/* 
 	 * Step 5: sort dependents by their update time. 
 	 */
@@ -674,6 +743,9 @@
       case T_FATE_OUTDATED:
 	printf( "  %s       : Outdated, updating it\n", spaces(depth) );
 	break;
+      case T_FATE_REBUILD:
+	printf( "  %s       : Rebuild, Updating it\n", spaces(depth) );
+	break;
       case T_FATE_UPDATE:
 	printf( "  %s       : Updating it\n", spaces(depth) );
 	break;

Modified: boost-jam/trunk/make1.c
===================================================================
--- boost-jam/trunk/make1.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/make1.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -61,6 +61,8 @@
 # include "command.h"
 # include "execcmd.h"
 
+# include <stdlib.h>
+
 #if defined(sun) || defined(__sun)
 #include <unistd.h> /* for unlink */
 #endif
@@ -68,7 +70,7 @@
 static CMD *make1cmds( TARGET *t );
 static LIST *make1list( LIST *l, TARGETS *targets, int flags );
 static SETTINGS *make1settings( LIST *vars );
-static void make1bind( TARGET *t, int warn );
+static void make1bind( TARGET *t );
 
 /* Ugly static - it's too hard to carry it through the callbacks. */
 
@@ -101,7 +103,7 @@
 static void make1b( state *pState );
 static void make1c( state *pState );
 static void make1d( state *pState );
-static void make_closure(void *closure, int status);
+static void make_closure(void *closure, int status, timing_info*);
 
 typedef struct _stack
 {
@@ -410,9 +412,10 @@
     if( pState->t->status == EXEC_CMD_OK )
         switch( pState->t->fate )
         {
+            /* These are handled by the default case below now
         case T_FATE_INIT:
         case T_FATE_MAKING:
-            /* shouldn't happen */
+            */
 
         case T_FATE_STABLE:
         case T_FATE_NEWER:
@@ -433,6 +436,7 @@
         case T_FATE_NEEDTMP:
         case T_FATE_OUTDATED:
         case T_FATE_UPDATE:
+        case T_FATE_REBUILD:
 
             /* Set "on target" vars, build actions, unset vars */
             /* Set "progress" so that make1c() counts this target among */
@@ -449,6 +453,11 @@
             }
 
             break;
+            
+            /* All possible fates should have been accounted for by now */
+        default:
+            printf("ERROR: %s has bad fate %d", pState->t->name, pState->t->fate);
+            abort();
         }
 
 		/* Call make1c() to begin the execution of the chain of commands */
@@ -655,11 +664,62 @@
 	}
 }
 
-static void make_closure(void *closure, int status)
+/* To l, append a 1-element list containing the string representation
+ * of x
+ */
+static void append_double_string( LOL *l, double x )
 {
-	push_state(&state_stack, (TARGET *)closure, NULL, T_STATE_MAKE1D)->status = status;
+    char buffer[50];
+    sprintf(buffer, "%f", x);
+    lol_add( l, list_new( L0, newstr( buffer ) ) );
 }
 
+/* Look up the __TIMING_RULE__ variable on the given target, and if
+ * non-empty, invoke the rule it names, passing the given
+ * timing_info
+ */
+static void call_timing_rule(TARGET* target, timing_info* time)
+{
+    LIST* timing_rule;
+    
+    pushsettings(target->settings);
+    timing_rule = var_get( "__TIMING_RULE__" );
+    popsettings(target->settings);
+
+    if (timing_rule)
+    {
+        /* We'll prepend $(__TIMING_RULE__[2-]) to the first argument */
+        LIST* initial_args = list_copy( L0, timing_rule->next );
+            
+        /* Prepare the argument list */
+        FRAME frame[1];
+        frame_init( frame );
+
+        /* First argument is the name of the timed target */
+        lol_add( frame->args, list_new( initial_args, target->name ) );
+        append_double_string(frame->args, time->user);
+        append_double_string(frame->args, time->system);
+
+        if( lol_get( frame->args, 2 ) )
+            evaluate_rule( timing_rule->string, frame );
+            
+        /* Clean up */
+        frame_free( frame );
+    }
+}
+
+static void make_closure(
+    void *closure, int status, timing_info* time)
+{
+    TARGET* built = (TARGET*)closure;
+
+    call_timing_rule(built, time);
+    if (DEBUG_EXECCMD)
+        printf("%f sec system; %f sec user\n", time->system, time->user);
+    
+    push_state(&state_stack, built, NULL, T_STATE_MAKE1D)->status = status;
+}
+
 /*
  * make1d() - handle command execution completion and call back make1c()
  */
@@ -935,13 +995,8 @@
     {
 	TARGET *t = targets->target;
 
-	/* Sources to 'actions existing' are never in the dependency */
-	/* graph (if they were, they'd get built and 'existing' would */
-	/* be superfluous, so throttle warning message about independent */
-	/* targets. */
-
 	if( t->binding == T_BIND_UNBOUND )
-	    make1bind( t, !( flags & RULE_EXISTING ) );
+	    make1bind( t );
 
     if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) )
     {
@@ -997,11 +1052,10 @@
 	    {
 		TARGET *t = bindtarget( l->string );
 
-		/* Make sure the target is bound, warning if it is not in the */
-		/* dependency graph. */
+		/* Make sure the target is bound */
 
 		if( t->binding == T_BIND_UNBOUND )
-		    make1bind( t, 1 );
+		    make1bind( t );
 
 		/* Build new list */
 
@@ -1025,20 +1079,11 @@
 
 static void
 make1bind( 
-	TARGET	*t,
-	int	warn )
+	TARGET	*t )
 {
 	if( t->flags & T_FLAG_NOTFILE )
 	    return;
 
-	/* Sources to 'actions existing' are never in the dependency */
-	/* graph (if they were, they'd get built and 'existing' would */
-	/* be superfluous, so throttle warning message about independent */
-	/* targets. */
-
-	if( warn )
-	    printf( "warning: using independent target %s\n", t->name );
-
 	pushsettings( t->settings );
 	t->boundname = search( t->name, &t->time, 0 );
 	t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;

Modified: boost-jam/trunk/modules/order.c
===================================================================
--- boost-jam/trunk/modules/order.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/order.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 #include "../lists.h"

Modified: boost-jam/trunk/modules/path.c
===================================================================
--- boost-jam/trunk/modules/path.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/path.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 #include "../timestamp.h"

Modified: boost-jam/trunk/modules/property-set.c
===================================================================
--- boost-jam/trunk/modules/property-set.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/property-set.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 #include "../timestamp.h"

Modified: boost-jam/trunk/modules/regex.c
===================================================================
--- boost-jam/trunk/modules/regex.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/regex.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 #include "../timestamp.h"

Modified: boost-jam/trunk/modules/sequence.c
===================================================================
--- boost-jam/trunk/modules/sequence.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/sequence.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 

Modified: boost-jam/trunk/modules/set.c
===================================================================
--- boost-jam/trunk/modules/set.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules/set.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
 

Modified: boost-jam/trunk/modules.c
===================================================================
--- boost-jam/trunk/modules.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -53,6 +53,7 @@
         m->imported_modules = 0;
         m->class_module = 0;
         m->native_rules = 0;
+        m->user_module = 0;
     }
     string_free( &s );
     return m;
@@ -147,4 +148,3 @@
 
     return result;
 }
-

Modified: boost-jam/trunk/modules.h
===================================================================
--- boost-jam/trunk/modules.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/modules.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -16,13 +16,13 @@
     struct hash* imported_modules;
     struct module_t* class_module;
     struct hash* native_rules;
+    int user_module;
 };
 
 typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */
 
 module_t* bindmodule( char* name );
 module_t* root_module();
-void bind_module_var( module_t*, char* name );
 void enter_module( module_t* );
 void exit_module( module_t* );
 void delete_module( module_t* );

Modified: boost-jam/trunk/native.c
===================================================================
--- boost-jam/trunk/native.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/native.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright Vladimir Prus 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "native.h"
 #include "hash.h"

Modified: boost-jam/trunk/native.h
===================================================================
--- boost-jam/trunk/native.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/native.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,6 @@
+/* Copyright David Abrahams 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #ifndef NATIVE_H_VP_2003_12_09
 #define NATIVE_H_VP_2003_12_09

Modified: boost-jam/trunk/option.c
===================================================================
--- boost-jam/trunk/option.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/option.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -34,7 +34,7 @@
 	char *arg;
 
 	if( argv[i][0] != '-' || ( argv[i][1] != '-' && !isalpha( argv[i][1] ) ) )
-	    break;
+	    continue;
 
 	if( !optc-- )
 	{

Modified: boost-jam/trunk/patchlevel.h
===================================================================
--- boost-jam/trunk/patchlevel.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/patchlevel.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,5 +1,11 @@
+/*
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
 /* Keep JAMVERSYM in sync with VERSION. */
 /* It can be accessed as $(JAMVERSION) in the Jamfile. */
 
-#define VERSION "3.1.10"
+#define VERSION "3.1.11"
 #define JAMVERSYM "JAMVERSION=3.1"

Modified: boost-jam/trunk/pathunix.c
===================================================================
--- boost-jam/trunk/pathunix.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/pathunix.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -207,7 +207,10 @@
 
     {
         string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
-        string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
+        /* If 'root' already ends with path delimeter, 
+           don't add yet another one. */
+        if( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
+            string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
     }
 
     if( f->f_dir.len )

Modified: boost-jam/trunk/pwd.c
===================================================================
--- boost-jam/trunk/pwd.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/pwd.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,7 @@
+/* Copyright Vladimir Prus 2002. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 #include "jam.h"
 #include "lists.h"
 #include "newstr.h"
@@ -10,8 +14,12 @@
 #include <direct.h>
 #define PATH_MAX _MAX_PATH
 #else
+#include <limits.h>
 #include <unistd.h>
+#if defined(__COMO__)
+     #include <linux/limits.h>
 #endif
+#endif
 
 
 

Modified: boost-jam/trunk/pwd.h
===================================================================
--- boost-jam/trunk/pwd.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/pwd.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,7 @@
+/* Copyright Vladimir Prus 2002. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 #ifndef PWD_H
 #define PWD_H
 

Modified: boost-jam/trunk/rules.c
===================================================================
--- boost-jam/trunk/rules.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/rules.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -82,6 +82,9 @@
         r->arguments = 0;
         r->exported = 0;
         r->module = target_module;
+#ifdef HAVE_PYTHON
+        r->python_function = 0;
+#endif
     }
     return r;
 }
@@ -768,7 +771,7 @@
        here, but we don't have necessary information, such as frame.
     */
     if (!result)
-        result = enter_rule( rulename, root_module() );
+        result = enter_rule( rulename, m );
 
     return result;
 }

Modified: boost-jam/trunk/rules.h
===================================================================
--- boost-jam/trunk/rules.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/rules.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -87,6 +87,9 @@
                                 * appear in the global module and be
                                 * automatically imported into other modules
                                 */
+#ifdef HAVE_PYTHON
+    PyObject* python_function;
+#endif    
 };
 
 /* ACTIONS - a chain of ACTIONs */
@@ -156,8 +159,12 @@
 
 # define T_FLAG_INTERNAL 0x0200    /* internal INCLUDES node */
 
+/*  Indicates that the target must be a file. This prevents matching non-files,
+    like directories, when a target is searched. */
+#define     T_FLAG_ISFILE   0x0400
 
 
+
 #ifdef OPT_SEMAPHORE
 # define 	T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
 #endif
@@ -174,6 +181,8 @@
 # define 	T_BIND_EXISTS	3	/* real file, timestamp valid */
 
 	TARGETS		*depends;	/* dependencies */
+	TARGETS		*dependents;/* the inverse of dependencies */
+    TARGETS     *rebuilds;  /* targets that should be force-rebuilt whenever this one is */
 	TARGET		*includes;	/* includes */
     TARGET        *original_target; /* original_target->includes = this */
     char rescanned;
@@ -194,14 +203,15 @@
 
 # define	T_FATE_BUILD	5	/* >= BUILD rebuilds target */
 # define	T_FATE_TOUCHED	5	/* manually touched with -t */
-# define	T_FATE_MISSING	6	/* is missing, needs updating */
-# define	T_FATE_NEEDTMP	7	/* missing temp that must be rebuild */
-# define 	T_FATE_OUTDATED	8	/* is out of date, needs updating */
-# define 	T_FATE_UPDATE	9	/* deps updated, needs updating */
+# define	T_FATE_REBUILD	6
+# define	T_FATE_MISSING	7	/* is missing, needs updating */
+# define	T_FATE_NEEDTMP	8	/* missing temp that must be rebuild */
+# define 	T_FATE_OUTDATED	9	/* is out of date, needs updating */
+# define 	T_FATE_UPDATE	10	/* deps updated, needs updating */
 
-# define 	T_FATE_BROKEN	10	/* >= BROKEN ruins parents */
-# define 	T_FATE_CANTFIND	10	/* no rules to make missing target */
-# define 	T_FATE_CANTMAKE	11	/* can't find dependents */
+# define 	T_FATE_BROKEN	11	/* >= BROKEN ruins parents */
+# define 	T_FATE_CANTFIND	11	/* no rules to make missing target */
+# define 	T_FATE_CANTMAKE	12	/* can't find dependents */
 
 	char	progress;		/* tracks make1() progress */
 

Modified: boost-jam/trunk/strings.c
===================================================================
--- boost-jam/trunk/strings.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/strings.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,7 @@
+/* Copyright David Abrahams 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 #include "strings.h"
 #include <stdlib.h>
 #include <string.h>
@@ -74,7 +78,7 @@
     assert_invariants( self );
 }
 
-static void extend_full( string* self, char* start, char *finish )
+static void extend_full( string* self, char const* start, char const* finish )
 {
     size_t new_size = self->capacity + ( finish - start );
     size_t new_capacity = self->capacity;
@@ -87,7 +91,7 @@
     self->size = new_size;
 }
 
-void string_append( string* self, char* rhs )
+void string_append( string* self, char const* rhs )
 {
     char* p = self->value + self->size;
     char* end = self->value + self->capacity;
@@ -108,7 +112,7 @@
     assert_invariants( self );
 }
 
-void string_append_range( string* self, char* start, char* finish )
+void string_append_range( string* self, char const* start, char const* finish )
 {
     char* p = self->value + self->size;
     char* end = self->value + self->capacity;
@@ -129,7 +133,7 @@
     assert_invariants( self );
 }
 
-void string_copy( string* s, char* rhs )
+void string_copy( string* s, char const* rhs )
 {
     string_new( s );
     string_append( s, rhs );

Modified: boost-jam/trunk/strings.h
===================================================================
--- boost-jam/trunk/strings.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/strings.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,6 +1,10 @@
 #ifndef STRINGS_DWA20011024_H
 # define STRINGS_DWA20011024_H
 
+/* Copyright David Abrahams 2004. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 # include <stddef.h>
 
 typedef struct string
@@ -15,10 +19,10 @@
 } string;
 
 void string_new( string* );
-void string_copy( string*, char* );
+void string_copy( string*, char const* );
 void string_free( string* );
-void string_append( string*, char* );
-void string_append_range( string*, char*, char* );
+void string_append( string*, char const* );
+void string_append_range( string*, char const*, char const* );
 void string_push_back( string* s, char x );
 void string_reserve( string*, size_t );
 void string_truncate( string*, size_t );

Modified: boost-jam/trunk/variable.c
===================================================================
--- boost-jam/trunk/variable.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/variable.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -78,12 +78,18 @@
 /*
  * var_defines() - load a bunch of variable=value settings
  *
- * If variable name ends in PATH, split value at :'s.  
- * Otherwise, split at blanks.
+ * If preprocess is false, take the value verbatim.
+ *
+ * Otherwise, if the variable value is enclosed in quotes, strip the
+ * quotes.
+ *
+ * Otherwise, if variable name ends in PATH, split value at :'s.
+ *
+ * Otherwise, split the value at blanks.
  */
 
 void
-var_defines( char **e )
+var_defines( char *const* e, int preprocess )
 {
     string buf[1];
 
@@ -93,12 +99,6 @@
 	{
 	    char *val;
 
-	    /* Just say "no": windows defines this in the env, */
-	    /* but we don't want it to override our notion of OS. */
-
-	    if( !strcmp( *e, "OS=Windows_NT" ) )
-		continue;
-
 # ifdef OS_MAC
 	    /* On the mac (MPW), the var=val is actually var\0val */
 	    /* Think different. */
@@ -110,13 +110,20 @@
 	    {
 		LIST *l = L0;
 		char *pp, *p;
+# ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT
+                char split = '\0';
+# else
 # ifdef OS_MAC
 		char split = ',';
 # else
 		char split = ' ';
 # endif
+# endif
                 size_t len = strlen(val + 1);
-                if ( val[1] == '"' && val[len] == '"')
+
+                int quoted = val[1] == '"' && val[len] == '"';
+                
+                if ( quoted && preprocess )
                 {
                     string_append_range( buf, val + 2, val + len );
                     l = list_new( l, newstr( buf->value ) );
@@ -136,7 +143,10 @@
 
                     /* Do the split */
 
-                    for( pp = val + 1; p = strchr( pp, split ); pp = p + 1 )
+                    for(
+                        pp = val + 1;
+                        preprocess && (p = strchr( pp, split )) != 0;
+                        pp = p + 1 )
                     {
                         string_append_range( buf, pp, p );
                         l = list_new( l, newstr( buf->value ) );

Modified: boost-jam/trunk/variable.h
===================================================================
--- boost-jam/trunk/variable.h	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/variable.h	2005-12-22 12:04:37 UTC (rev 13928)
@@ -10,7 +10,7 @@
 
 struct hash;
 
-void 	var_defines( char **e );
+void 	var_defines( char* const *e, int preprocess );
 int 	var_string( char *in, char *out, int outsize, LOL *lol );
 LIST * 	var_get( char *symbol );
 void 	var_set( char *symbol, LIST *value, int flag );

Modified: boost-jam/trunk/w32_getreg.c
===================================================================
--- boost-jam/trunk/w32_getreg.c	2005-12-22 12:00:45 UTC (rev 13927)
+++ boost-jam/trunk/w32_getreg.c	2005-12-22 12:04:37 UTC (rev 13928)
@@ -1,3 +1,7 @@
+/* Copyright Paul Lin 2003. Distributed under the Boost */
+/* Software License, Version 1.0. (See accompanying */
+/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
+
 # include "jam.h"
 # include "lists.h"
 # include "newstr.h"
@@ -59,8 +63,9 @@
         && ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) 
     )
     {
-        DWORD  type, len;
+        DWORD  type;
         BYTE   data[MAX_REGISTRY_DATA_LENGTH];
+        DWORD  len = sizeof(data);
         LIST const* const field = lol_get(frame->args, 1);
         
         if ( ERROR_SUCCESS ==
@@ -116,3 +121,4 @@
     }
     return  result;
 }
+




More information about the pkg-boost-commits mailing list