Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75609 - in trunk/tools/build/v2/engine: . modules
From: steven_at_[hidden]
Date: 2011-11-22 18:04:19


Author: steven_watanabe
Date: 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
New Revision: 75609
URL: http://svn.boost.org/trac/boost/changeset/75609

Log:
Replace newstr with object. Use OBJECT * instead of char *. Fix a few bugs uncovered by the better typechecking.
Added:
   trunk/tools/build/v2/engine/constants.c (contents, props changed)
   trunk/tools/build/v2/engine/constants.h (contents, props changed)
   trunk/tools/build/v2/engine/object.c
      - copied, changed from r75606, /trunk/tools/build/v2/engine/newstr.c
   trunk/tools/build/v2/engine/object.h
      - copied, changed from r75606, /trunk/tools/build/v2/engine/newstr.h
Removed:
   trunk/tools/build/v2/engine/newstr.c
   trunk/tools/build/v2/engine/newstr.h
Text files modified:
   trunk/tools/build/v2/engine/build.bat | 4
   trunk/tools/build/v2/engine/build.jam | 4
   trunk/tools/build/v2/engine/build.sh | 4
   trunk/tools/build/v2/engine/build_vms.com | 6
   trunk/tools/build/v2/engine/builtins.c | 534 +++++++++++++++++++++------------------
   trunk/tools/build/v2/engine/class.c | 62 ++-
   trunk/tools/build/v2/engine/class.h | 2
   trunk/tools/build/v2/engine/command.c | 4
   trunk/tools/build/v2/engine/command.h | 5
   trunk/tools/build/v2/engine/compile.c | 152 +++++-----
   trunk/tools/build/v2/engine/compile.h | 7
   trunk/tools/build/v2/engine/debug.c | 10
   trunk/tools/build/v2/engine/debug.h | 9
   trunk/tools/build/v2/engine/execcmd.h | 8
   trunk/tools/build/v2/engine/execnt.c | 54 ++--
   trunk/tools/build/v2/engine/execunix.c | 18
   trunk/tools/build/v2/engine/execvms.c | 46 ++-
   trunk/tools/build/v2/engine/expand.c | 68 ++--
   trunk/tools/build/v2/engine/expand.h | 8
   trunk/tools/build/v2/engine/filent.c | 66 ++--
   trunk/tools/build/v2/engine/filesys.c | 14
   trunk/tools/build/v2/engine/filesys.h | 21
   trunk/tools/build/v2/engine/fileunix.c | 77 +++--
   trunk/tools/build/v2/engine/filevms.c | 141 +++++----
   trunk/tools/build/v2/engine/frames.h | 13
   trunk/tools/build/v2/engine/glob.c | 10
   trunk/tools/build/v2/engine/hash.c | 62 +---
   trunk/tools/build/v2/engine/hash.h | 6
   trunk/tools/build/v2/engine/hcache.c | 98 +++---
   trunk/tools/build/v2/engine/hcache.h | 6
   trunk/tools/build/v2/engine/hdrmacro.c | 38 +-
   trunk/tools/build/v2/engine/hdrmacro.h | 7
   trunk/tools/build/v2/engine/headers.c | 57 ++-
   trunk/tools/build/v2/engine/headers.h | 13
   trunk/tools/build/v2/engine/jam.c | 151 +++++++---
   trunk/tools/build/v2/engine/jamgram.c | 4
   trunk/tools/build/v2/engine/jamgram.y | 4
   trunk/tools/build/v2/engine/jamgram.yy | 4
   trunk/tools/build/v2/engine/lists.c | 58 ++--
   trunk/tools/build/v2/engine/lists.h | 26 +
   trunk/tools/build/v2/engine/make.c | 62 ++--
   trunk/tools/build/v2/engine/make.h | 14
   trunk/tools/build/v2/engine/make1.c | 106 ++++---
   trunk/tools/build/v2/engine/modules.c | 48 +--
   trunk/tools/build/v2/engine/modules.h | 26
   trunk/tools/build/v2/engine/modules/order.c | 18
   trunk/tools/build/v2/engine/modules/path.c | 8
   trunk/tools/build/v2/engine/modules/property-set.c | 21
   trunk/tools/build/v2/engine/modules/regex.c | 12
   trunk/tools/build/v2/engine/modules/sequence.c | 10
   trunk/tools/build/v2/engine/modules/set.c | 8
   trunk/tools/build/v2/engine/native.c | 22 +
   trunk/tools/build/v2/engine/native.h | 10
   trunk/tools/build/v2/engine/object.c | 124 ++++++--
   trunk/tools/build/v2/engine/object.h | 22 +
   trunk/tools/build/v2/engine/output.c | 14
   trunk/tools/build/v2/engine/output.h | 7
   trunk/tools/build/v2/engine/parse.c | 30 +-
   trunk/tools/build/v2/engine/parse.h | 24
   trunk/tools/build/v2/engine/pathsys.h | 17
   trunk/tools/build/v2/engine/pathunix.c | 33 +-
   trunk/tools/build/v2/engine/pathvms.c | 16
   trunk/tools/build/v2/engine/pwd.c | 20 +
   trunk/tools/build/v2/engine/pwd.h | 3
   trunk/tools/build/v2/engine/regexp.c | 32 +-
   trunk/tools/build/v2/engine/regexp.h | 10
   trunk/tools/build/v2/engine/rules.c | 138 +++++----
   trunk/tools/build/v2/engine/rules.h | 34 +-
   trunk/tools/build/v2/engine/scan.c | 41 +-
   trunk/tools/build/v2/engine/scan.h | 21
   trunk/tools/build/v2/engine/search.c | 105 ++++---
   trunk/tools/build/v2/engine/search.h | 10
   trunk/tools/build/v2/engine/subst.c | 20
   trunk/tools/build/v2/engine/timestamp.c | 58 ++-
   trunk/tools/build/v2/engine/timestamp.h | 10
   trunk/tools/build/v2/engine/variable.c | 83 +++--
   trunk/tools/build/v2/engine/variable.h | 14
   trunk/tools/build/v2/engine/w32_getreg.c | 22
   78 files changed, 1764 insertions(+), 1390 deletions(-)

Modified: trunk/tools/build/v2/engine/build.bat
==============================================================================
--- trunk/tools/build/v2/engine/build.bat (original)
+++ trunk/tools/build/v2/engine/build.bat 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -438,9 +438,9 @@
 set YYACC_SOURCES=yyacc.c
 set MKJAMBASE_SOURCES=mkjambase.c
 set BJAM_SOURCES=
-set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c debug.c execnt.c expand.c filent.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c constants.c debug.c execnt.c expand.c filent.c glob.c hash.c
 set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
-set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c output.c parse.c pathunix.c regexp.c
+set BJAM_SOURCES=%BJAM_SOURCES% object.c option.c output.c parse.c pathunix.c regexp.c
 set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
 set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c md5.c pwd.c class.c w32_getreg.c native.c
 set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c

Modified: trunk/tools/build/v2/engine/build.jam
==============================================================================
--- trunk/tools/build/v2/engine/build.jam (original)
+++ trunk/tools/build/v2/engine/build.jam 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -495,10 +495,10 @@
 
 # We have some different files for UNIX, VMS, and NT.
 jam.source =
- command.c compile.c debug.c expand.c glob.c
+ command.c compile.c constants.c debug.c expand.c glob.c
     hash.c hcache.c headers.c hdrmacro.c
     jam.c jambase.c jamgram.c
- lists.c make.c make1.c mem.c newstr.c
+ lists.c make.c make1.c mem.c object.c
     option.c output.c parse.c regexp.c rules.c
     scan.c search.c subst.c w32_getreg.c
     timestamp.c variable.c modules.c strings.c filesys.c

Modified: trunk/tools/build/v2/engine/build.sh
==============================================================================
--- trunk/tools/build/v2/engine/build.sh (original)
+++ trunk/tools/build/v2/engine/build.sh 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -245,9 +245,9 @@
 YYACC_SOURCES="yyacc.c"
 MKJAMBASE_SOURCES="mkjambase.c"
 BJAM_SOURCES="\
- command.c compile.c debug.c expand.c glob.c hash.c\
+ command.c compile.c constants.c debug.c expand.c glob.c hash.c\
  hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
- newstr.c option.c output.c parse.c pathunix.c pathvms.c regexp.c\
+ object.c option.c output.c parse.c pathunix.c pathvms.c regexp.c\
  rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
  strings.c filesys.c builtins.c pwd.c class.c native.c md5.c w32_getreg.c\
  modules/set.c modules/path.c modules/regex.c modules/property-set.c\

Modified: trunk/tools/build/v2/engine/build_vms.com
==============================================================================
--- trunk/tools/build/v2/engine/build_vms.com (original)
+++ trunk/tools/build/v2/engine/build_vms.com 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -34,6 +34,7 @@
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]builtins.obj builtins.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]command.obj command.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]compile.obj compile.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]constants.obj constants.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]execvms.obj execvms.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]expand.obj expand.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]filesys.obj filesys.c
@@ -49,7 +50,7 @@
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make.obj make.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]make1.obj make1.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]modules.obj modules.c
-$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]newstr.obj newstr.c
+$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]object.obj object.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]option.obj option.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]parse.obj parse.c
 $ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]pathvms.obj pathvms.c
@@ -67,6 +68,7 @@
  [.bootstrap_vms]builtins.obj, -
  [.bootstrap_vms]command.obj, -
  [.bootstrap_vms]compile.obj, -
+ [.bootstrap_vms]constants.obj, -
  [.bootstrap_vms]execvms.obj, -
  [.bootstrap_vms]expand.obj, -
  [.bootstrap_vms]filesys.obj, -
@@ -82,7 +84,7 @@
  [.bootstrap_vms]make.obj, -
  [.bootstrap_vms]make1.obj, -
  [.bootstrap_vms]modules.obj, -
- [.bootstrap_vms]newstr.obj, -
+ [.bootstrap_vms]object.obj, -
  [.bootstrap_vms]option.obj, -
  [.bootstrap_vms]parse.obj, -
  [.bootstrap_vms]pathvms.obj, -

Modified: trunk/tools/build/v2/engine/builtins.c
==============================================================================
--- trunk/tools/build/v2/engine/builtins.c (original)
+++ trunk/tools/build/v2/engine/builtins.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -11,7 +11,7 @@
 #include "builtins.h"
 #include "rules.h"
 #include "filesys.h"
-#include "newstr.h"
+#include "object.h"
 #include "regexp.h"
 #include "frames.h"
 #include "hash.h"
@@ -25,6 +25,7 @@
 #include "variable.h"
 #include "timestamp.h"
 #include "md5.h"
+#include "constants.h"
 #include <ctype.h>
 
 #if defined(USE_EXECUNIX)
@@ -65,25 +66,26 @@
  */
 
 #define P0 (PARSE *)0
-#define C0 (char *)0
+#define C0 (OBJECT *)0
 
 #if defined( OS_NT ) || defined( OS_CYGWIN )
     LIST * builtin_system_registry ( PARSE *, FRAME * );
     LIST * builtin_system_registry_names( PARSE *, FRAME * );
 #endif
 
-int glob( char * s, char * c );
+int glob( const char * s, const char * c );
 
 void backtrace ( FRAME * );
 void backtrace_line ( FRAME * );
 void print_source_line( PARSE * );
 
 
-RULE * bind_builtin( char * name, LIST * (* f)( PARSE *, FRAME * ), int flags, char * * args )
+RULE * bind_builtin( const char * name_, LIST * (* f)( PARSE *, FRAME * ), int flags, const char * * args )
 {
     PARSE * p;
     RULE * result;
     argument_list* arg_list = 0;
+ OBJECT * name = object_new( name_ );
 
     if ( args )
     {
@@ -97,13 +99,18 @@
 
     parse_free( p );
 
+ object_free( name );
+
     return result;
 }
 
 
-RULE * duplicate_rule( char * name, RULE * other )
+RULE * duplicate_rule( const char * name_, RULE * other )
 {
- return import_rule( other, root_module(), name );
+ OBJECT * name = object_new( name_ );
+ RULE * result = import_rule( other, root_module(), name );
+ object_free( name );
+ return result;
 }
 
 
@@ -123,7 +130,7 @@
                     builtin_echo, 0, 0 ) ) );
 
     {
- char * args[] = { "message", "*", ":", "result-value", "?", 0 };
+ const char * args[] = { "message", "*", ":", "result-value", "?", 0 };
         duplicate_rule( "exit",
         duplicate_rule( "Exit",
           bind_builtin( "EXIT",
@@ -131,13 +138,13 @@
     }
 
     {
- char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
+ const char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
         duplicate_rule( "Glob",
                         bind_builtin( "GLOB", builtin_glob, 0, args ) );
     }
 
     {
- char * args[] = { "patterns", "*", 0 };
+ const char * args[] = { "patterns", "*", 0 };
         bind_builtin( "GLOB-RECURSIVELY",
                       builtin_glob_recursive, 0, args );
     }
@@ -147,7 +154,7 @@
                     builtin_depends, 1, 0 ) );
 
     {
- char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
+ const char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
         bind_builtin( "REBUILDS",
                       builtin_rebuilds, 0, args );
     }
@@ -161,7 +168,7 @@
                     builtin_match, 0, 0 ) );
 
     {
- char * args[] = { "string", ":", "delimiters" };
+ const char * args[] = { "string", ":", "delimiters" };
         bind_builtin( "SPLIT_BY_CHARACTERS",
                       builtin_split_by_characters, 0, 0 );
     }
@@ -201,13 +208,13 @@
                     builtin_flags, T_FLAG_RMOLD, 0 );
 
       {
- char * args[] = { "targets", "*", 0 };
+ const char * args[] = { "targets", "*", 0 };
           bind_builtin( "UPDATE",
                         builtin_update, 0, args );
       }
 
       {
- char * args[] = { "targets", "*",
+ const char * args[] = { "targets", "*",
                             ":", "log", "?",
                             ":", "ignore-minus-n", "?",
                             ":", "ignore-minus-q", "?", 0 };
@@ -216,33 +223,33 @@
       }
 
       {
- char * args[] = { "string", "pattern", "replacements", "+", 0 };
+ const char * args[] = { "string", "pattern", "replacements", "+", 0 };
           duplicate_rule( "subst",
             bind_builtin( "SUBST",
                           builtin_subst, 0, args ) );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "RULENAMES",
                          builtin_rulenames, 0, args );
       }
 
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "VARNAMES",
                          builtin_varnames, 0, args );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "DELETE_MODULE",
                          builtin_delete_module, 0, args );
       }
 
       {
- char * args[] = { "source_module", "?",
+ const char * args[] = { "source_module", "?",
                             ":", "source_rules", "*",
                             ":", "target_module", "?",
                             ":", "target_rules", "*",
@@ -252,104 +259,104 @@
       }
 
       {
- char * args[] = { "module", "?", ":", "rules", "*", 0 };
+ const char * args[] = { "module", "?", ":", "rules", "*", 0 };
           bind_builtin( "EXPORT",
                         builtin_export, 0, args );
       }
 
       {
- char * args[] = { "levels", "?", 0 };
+ const char * args[] = { "levels", "?", 0 };
           bind_builtin( "CALLER_MODULE",
                          builtin_caller_module, 0, args );
       }
 
       {
- char * args[] = { "levels", "?", 0 };
+ const char * args[] = { "levels", "?", 0 };
           bind_builtin( "BACKTRACE",
                         builtin_backtrace, 0, args );
       }
 
       {
- char * args[] = { 0 };
+ const char * args[] = { 0 };
           bind_builtin( "PWD",
                         builtin_pwd, 0, args );
       }
 
       {
- char * args[] = { "target", "*", ":", "path", "*", 0 };
+ const char * args[] = { "target", "*", ":", "path", "*", 0 };
           bind_builtin( "SEARCH_FOR_TARGET",
                         builtin_search_for_target, 0, args );
       }
 
       {
- char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
+ const char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
           bind_builtin( "IMPORT_MODULE",
                         builtin_import_module, 0, args );
       }
 
       {
- char * args[] = { "module", "?", 0 };
+ const char * args[] = { "module", "?", 0 };
           bind_builtin( "IMPORTED_MODULES",
                         builtin_imported_modules, 0, args );
       }
 
       {
- char * args[] = { "instance_module", ":", "class_module", 0 };
+ const char * args[] = { "instance_module", ":", "class_module", 0 };
           bind_builtin( "INSTANCE",
                         builtin_instance, 0, args );
       }
 
       {
- char * args[] = { "sequence", "*", 0 };
+ const char * args[] = { "sequence", "*", 0 };
           bind_builtin( "SORT",
                         builtin_sort, 0, args );
       }
 
       {
- char * args[] = { "path_parts", "*", 0 };
+ const char * args[] = { "path_parts", "*", 0 };
           bind_builtin( "NORMALIZE_PATH",
                         builtin_normalize_path, 0, args );
       }
 
       {
- char * args[] = { "args", "*", 0 };
+ const char * args[] = { "args", "*", 0 };
           bind_builtin( "CALC",
                         builtin_calc, 0, args );
       }
 
       {
- char * args[] = { "module", ":", "rule", 0 };
+ const char * args[] = { "module", ":", "rule", 0 };
           bind_builtin( "NATIVE_RULE",
                         builtin_native_rule, 0, args );
       }
 
       {
- char * args[] = { "module", ":", "rule", ":", "version", 0 };
+ const char * args[] = { "module", ":", "rule", ":", "version", 0 };
           bind_builtin( "HAS_NATIVE_RULE",
                         builtin_has_native_rule, 0, args );
       }
 
       {
- char * args[] = { "module", "*", 0 };
+ const char * args[] = { "module", "*", 0 };
           bind_builtin( "USER_MODULE",
                         builtin_user_module, 0, args );
       }
 
       {
- char * args[] = { 0 };
+ const char * args[] = { 0 };
           bind_builtin( "NEAREST_USER_LOCATION",
                         builtin_nearest_user_location, 0, args );
       }
 
       {
- char * args[] = { "file", 0 };
+ const char * args[] = { "file", 0 };
           bind_builtin( "CHECK_IF_FILE",
                         builtin_check_if_file, 0, args );
       }
 
 #ifdef HAVE_PYTHON
       {
- char * args[] = { "python-module", ":", "function", ":",
+ const char * args[] = { "python-module", ":", "function", ":",
                             "jam-module", ":", "rule-name", 0 };
           bind_builtin( "PYTHON_IMPORT_RULE",
                         builtin_python_import_rule, 0, args );
@@ -358,56 +365,56 @@
 
 # if defined( OS_NT ) || defined( OS_CYGWIN )
       {
- char * args[] = { "key_path", ":", "data", "?", 0 };
+ const char * args[] = { "key_path", ":", "data", "?", 0 };
           bind_builtin( "W32_GETREG",
                         builtin_system_registry, 0, args );
       }
 
       {
- char * args[] = { "key_path", ":", "result-type", 0 };
+ const char * args[] = { "key_path", ":", "result-type", 0 };
           bind_builtin( "W32_GETREGNAMES",
                         builtin_system_registry_names, 0, args );
       }
 # endif
 
       {
- char * args[] = { "command", ":", "*", 0 };
+ const char * args[] = { "command", ":", "*", 0 };
           duplicate_rule( "SHELL",
             bind_builtin( "COMMAND",
                           builtin_shell, 0, args ) );
       }
 
       {
- char * args[] = { "string", 0 };
+ const char * args[] = { "string", 0 };
           bind_builtin( "MD5",
                         builtin_md5, 0, args ) ;
       }
 
       {
- char * args[] = { "name", ":", "mode", 0 };
+ const char * args[] = { "name", ":", "mode", 0 };
           bind_builtin( "FILE_OPEN",
                         builtin_file_open, 0, args );
       }
 
       {
- char * args[] = { "string", ":", "width", 0 };
+ const char * args[] = { "string", ":", "width", 0 };
           bind_builtin( "PAD",
                         builtin_pad, 0, args );
       }
 
       {
- char * args[] = { "targets", "*", 0 };
+ const char * args[] = { "targets", "*", 0 };
           bind_builtin( "PRECIOUS",
                         builtin_precious, 0, args );
       }
 
       {
- char * args [] = { 0 };
+ const char * args [] = { 0 };
           bind_builtin( "SELF_PATH", builtin_self_path, 0, args );
       }
 
       {
- char * args [] = { "path", 0 };
+ const char * args [] = { "path", 0 };
           bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
       }
 
@@ -441,15 +448,15 @@
     char const * rhs;
 
     if ( arg == 0 ) return L0;
- lhs = arg->string;
+ lhs = object_str( arg->value );
 
     arg = list_next( arg );
     if ( arg == 0 ) return L0;
- op = arg->string;
+ op = object_str( arg->value );
 
     arg = list_next( arg );
     if ( arg == 0 ) return L0;
- rhs = arg->string;
+ rhs = object_str( arg->value );
 
     lhs_value = atoi( lhs );
     rhs_value = atoi( rhs );
@@ -468,7 +475,7 @@
     }
 
     sprintf( buffer, "%ld", result_value );
- result = list_new( result, newstr( buffer ) );
+ result = list_new( result, object_new( buffer ) );
     return result;
 }
 
@@ -489,7 +496,7 @@
 
     for ( l = targets; l; l = list_next( l ) )
     {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( l->value );
 
         /* If doing INCLUDES, switch to the TARGET's include */
         /* TARGET, creating it if needed. The internal include */
@@ -511,7 +518,7 @@
     /* Enter reverse links */
     for ( l = sources; l; l = list_next( l ) )
     {
- TARGET * s = bindtarget( l->string );
+ TARGET * s = bindtarget( l->value );
         s->dependants = targetlist( s->dependants, targets );
     }
 
@@ -535,7 +542,7 @@
 
     for ( l = targets; l; l = list_next( l ) )
     {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( l->value );
         t->rebuilds = targetlist( t->rebuilds, rebuilds );
     }
 
@@ -572,7 +579,7 @@
     printf( "\n" );
     if ( lol_get( frame->args, 1 ) )
     {
- exit( atoi( lol_get( frame->args, 1 )->string ) );
+ exit( atoi( object_str( lol_get( frame->args, 1 )->value ) ) );
     }
     else
     {
@@ -593,7 +600,7 @@
 {
     LIST * l = lol_get( frame->args, 0 );
     for ( ; l; l = list_next( l ) )
- bindtarget( l->string )->flags |= parse->num;
+ bindtarget( l->value )->flags |= parse->num;
     return L0;
 }
 
@@ -619,10 +626,10 @@
 
 static void builtin_glob_back
 (
- void * closure,
- char * file,
- int status,
- time_t time
+ void * closure,
+ OBJECT * file,
+ int status,
+ time_t time
 )
 {
     PROFILE_ENTER( BUILTIN_GLOB_BACK );
@@ -635,11 +642,11 @@
     /* Null out directory for matching. We wish we had file_dirscan() pass up a
      * PATHNAME.
      */
- path_parse( file, &f );
+ path_parse( object_str( file ), &f );
     f.f_dir.len = 0;
 
     /* For globbing, we unconditionally ignore current and parent directory
- * items. Since they items always exist, there is no reason why caller of
+ * items. Since these items always exist, there is no reason why caller of
      * GLOB would want to see them. We could also change file_dirscan(), but
      * then paths with embedded "." and ".." would not work anywhere.
     */
@@ -657,9 +664,9 @@
 
     for ( l = globbing->patterns; l; l = l->next )
     {
- if ( !glob( l->string, buf->value ) )
+ if ( !glob( object_str( l->value ), buf->value ) )
         {
- globbing->results = list_new( globbing->results, newstr( file ) );
+ globbing->results = list_new( globbing->results, object_copy( file ) );
             break;
         }
     }
@@ -679,9 +686,9 @@
 
     while ( in )
     {
- string_copy( s, in->string );
+ string_copy( s, object_str( in->value ) );
         downcase_inplace( s->value );
- result = list_append( result, list_new( 0, newstr( s->value ) ) );
+ result = list_append( result, list_new( 0, object_new( s->value ) ) );
         in = in->next;
     }
 
@@ -711,7 +718,7 @@
         globbing.patterns = downcase_list( r );
 
     for ( ; l; l = list_next( l ) )
- file_dirscan( l->string, builtin_glob_back, &globbing );
+ file_dirscan( l->value, builtin_glob_back, &globbing );
 
     if ( globbing.case_insensitive )
         list_free( globbing.patterns );
@@ -731,19 +738,19 @@
  * If 'file' exists, append 'file' to 'list'. Returns 'list'.
  */
 
-static LIST * append_if_exists( LIST * list, char * file )
+static LIST * append_if_exists( LIST * list, OBJECT * file )
 {
     time_t time;
     timestamp( file, &time );
     return time > 0
- ? list_new( list, newstr( file ) )
+ ? list_new( list, object_copy( file ) )
         : list;
 }
 
 
-LIST * glob1( char * dirname, char * pattern )
+LIST * glob1( OBJECT * dirname, OBJECT * pattern )
 {
- LIST * plist = list_new( L0, newstr(pattern) );
+ LIST * plist = list_new( L0, object_copy(pattern) );
     struct globbing globbing;
 
     globbing.results = L0;
@@ -770,7 +777,7 @@
 }
 
 
-LIST * glob_recursive( char * pattern )
+LIST * glob_recursive( const char * pattern )
 {
     LIST * result = L0;
 
@@ -778,7 +785,9 @@
     if ( !has_wildcards( pattern ) )
     {
         /* No metacharacters. Check if the path exists. */
- result = append_if_exists(result, pattern);
+ OBJECT * p = object_new( pattern );
+ result = append_if_exists( result, p );
+ object_free( p );
     }
     else
     {
@@ -805,14 +814,15 @@
 
             dirs = has_wildcards( dirname->value )
                 ? glob_recursive( dirname->value )
- : list_new( dirs, newstr( dirname->value ) );
+ : list_new( dirs, object_new( dirname->value ) );
 
             if ( has_wildcards( basename->value ) )
             {
                 LIST * d;
+ OBJECT * b = object_new( basename->value );
                 for ( d = dirs ; d; d = d->next )
- result = list_append( result, glob1( d->string,
- basename->value ) );
+ result = list_append( result, glob1( d->value, b ) );
+ object_free( b );
             }
             else
             {
@@ -823,11 +833,16 @@
                 /* No wildcard in basename. */
                 for ( d = dirs ; d; d = d->next )
                 {
- path->f_dir.ptr = d->string;
- path->f_dir.len = strlen( d->string );
+ OBJECT * p;
+ path->f_dir.ptr = object_str( d->value );
+ path->f_dir.len = strlen( object_str( d->value ) );
                     path_build( path, file_string, 0 );
 
- result = append_if_exists( result, file_string->value );
+ p = object_new( file_string->value );
+
+ result = append_if_exists( result, p );
+
+ object_free( p );
 
                     string_truncate( file_string, 0 );
                 }
@@ -843,7 +858,11 @@
         else
         {
             /** No directory, just a pattern. */
- result = list_append( result, glob1( ".", pattern ) );
+ OBJECT * d = object_new( "." );
+ OBJECT * p = object_new( pattern );
+ result = list_append( result, glob1( d, p ) );
+ object_free( p );
+ object_free( d );
         }
     }
 
@@ -856,7 +875,7 @@
     LIST * result = L0;
     LIST * l = lol_get( frame->args, 0 );
     for ( ; l; l = l->next )
- result = list_append( result, glob_recursive( l->string ) );
+ result = list_append( result, glob_recursive( object_str( l->value ) ) );
     return result;
 }
 
@@ -879,12 +898,12 @@
     for ( l = lol_get( frame->args, 0 ); l; l = l->next )
     {
         /* Result is cached and intentionally never freed. */
- regexp * re = regex_compile( l->string );
+ regexp * re = regex_compile( l->value );
 
         /* For each string to match against. */
         for ( r = lol_get( frame->args, 1 ); r; r = r->next )
         {
- if ( regexec( re, r->string ) )
+ if ( regexec( re, object_str( r->value ) ) )
             {
                 int i;
                 int top;
@@ -900,7 +919,7 @@
                 for ( i = 1; i <= top; ++i )
                 {
                     string_append_range( buf, re->startp[ i ], re->endp[ i ] );
- result = list_new( result, newstr( buf->value ) );
+ result = list_new( result, object_new( buf->value ) );
                     string_truncate( buf, 0 );
                 }
             }
@@ -916,20 +935,23 @@
     LIST * l1 = lol_get( frame->args, 0 );
     LIST * l2 = lol_get( frame->args, 1 );
 
- LIST * result = 0;
+ LIST * result = L0;
+
+ string buf[ 1 ];
+
+ const char * delimiters = object_str( l2->value );
+ char * t;
 
- char* s = strdup (l1->string);
- char* delimiters = l2->string;
- char* t;
+ string_copy( buf, object_str( l1->value ) );
 
- t = strtok (s, delimiters);
- while (t)
+ t = strtok( buf->value, delimiters) ;
+ while ( t )
     {
- result = list_new(result, newstr(t));
- t = strtok (NULL, delimiters);
+ result = list_new( result, object_new( t ) );
+ t = strtok( NULL, delimiters );
     }
 
- free (s);
+ string_free( buf );
 
     return result;
 }
@@ -940,12 +962,12 @@
 
   for ( ; l; l = list_next( l ) )
   {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( l->value );
 
     /* Scan file for header filename macro definitions. */
     if ( DEBUG_HEADER )
         printf( "scanning '%s' for header file macro definitions\n",
- l->string );
+ object_str( l->value ) );
 
     macro_headers( t );
   }
@@ -966,7 +988,7 @@
     RULE * r = (RULE *)r_;
     LIST * * result = (LIST * *)result_;
     if ( r->exported )
- *result = list_new( *result, copystr( r->name ) );
+ *result = list_new( *result, object_copy( r->name ) );
 }
 
 
@@ -974,7 +996,7 @@
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( arg0 ? arg0->value : 0 );
 
     if ( source_module->rules )
         hashenumerate( source_module->rules, add_rule_name, &result );
@@ -995,7 +1017,7 @@
 static void add_hash_key( void * np, void * result_ )
 {
     LIST * * result = (LIST * *)result_;
- *result = list_new( *result, copystr( *(char * *)np ) );
+ *result = list_new( *result, object_copy( *(OBJECT * *)np ) );
 }
 
 
@@ -1017,7 +1039,7 @@
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( arg0 ? arg0->value : 0 );
 
     /* The running module _always_ has its 'variables' member set to NULL due to
      * the way enter_module() and var_hash_swap() work.
@@ -1042,16 +1064,16 @@
 {
     LIST * arg0 = lol_get( frame->args, 0 );
     LIST * result = L0;
- module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
+ module_t * source_module = bindmodule( arg0 ? arg0->value : 0 );
     delete_module( source_module );
     return result;
 }
 
 
-static void unknown_rule( FRAME * frame, char * key, char * module_name, char * rule_name )
+static void unknown_rule( FRAME * frame, const char * key, OBJECT * module_name, OBJECT * rule_name )
 {
     backtrace_line( frame->prev );
- printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
+ printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, object_str( rule_name ), object_str( module_name ) );
     backtrace( frame->prev );
     exit( 1 );
 }
@@ -1087,9 +1109,9 @@
     LIST * localize = lol_get( frame->args, 4 );
 
     module_t * target_module =
- bindmodule( target_module_list ? target_module_list->string : 0 );
+ bindmodule( target_module_list ? target_module_list->value : 0 );
     module_t * source_module =
- bindmodule( source_module_list ? source_module_list->string : 0 );
+ bindmodule( source_module_list ? source_module_list->value : 0 );
 
     LIST * source_name;
     LIST * target_name;
@@ -1102,13 +1124,13 @@
         RULE r_;
         RULE * r = &r_;
         RULE * imported;
- r_.name = source_name->string;
+ r_.name = source_name->value;
 
         if ( !source_module->rules ||
             !hashcheck( source_module->rules, (HASHDATA * *)&r ) )
             unknown_rule( frame, "IMPORT", source_module->name, r_.name );
 
- imported = import_rule( r, target_module, target_name->string );
+ imported = import_rule( r, target_module, target_name->value );
         if ( localize )
             imported->module = target_module;
         /* This rule is really part of some other module. Just refer to it here,
@@ -1146,13 +1168,13 @@
 {
     LIST * module_list = lol_get( frame->args, 0 );
     LIST * rules = lol_get( frame->args, 1 );
- module_t * m = bindmodule( module_list ? module_list->string : 0 );
+ module_t * m = bindmodule( module_list ? module_list->value : 0 );
 
     for ( ; rules; rules = list_next( rules ) )
     {
         RULE r_;
         RULE * r = &r_;
- r_.name = rules->string;
+ r_.name = rules->value;
 
         if ( !m->rules || !hashcheck( m->rules, (HASHDATA * *)&r ) )
             unknown_rule( frame, "EXPORT", m->name, r_.name );
@@ -1168,11 +1190,11 @@
  * indicated for a given procedure in debug output or an error backtrace.
  */
 
-static void get_source_line( PARSE * procedure, char * * file, int * line )
+static void get_source_line( PARSE * procedure, const char * * file, int * line )
 {
     if ( procedure )
     {
- char * f = procedure->file;
+ const char * f = object_str( procedure->file );
         int l = procedure->line;
         if ( !strcmp( f, "+" ) )
         {
@@ -1192,7 +1214,7 @@
 
 void print_source_line( PARSE * p )
 {
- char * file;
+ const char * file;
     int line;
 
     get_source_line( p, &file, &line );
@@ -1245,20 +1267,20 @@
 LIST * builtin_backtrace( PARSE * parse, FRAME * frame )
 {
     LIST * levels_arg = lol_get( frame->args, 0 );
- int levels = levels_arg ? atoi( levels_arg->string ) : ( (unsigned int)(-1) >> 1 ) ;
+ int levels = levels_arg ? atoi( object_str( levels_arg->value ) ) : (int)( (unsigned int)(-1) >> 1 ) ;
 
     LIST * result = L0;
     for ( ; ( frame = frame->prev ) && levels ; --levels )
     {
- char * file;
+ const char * file;
         int line;
         char buf[32];
         get_source_line( frame->procedure, &file, &line );
         sprintf( buf, "%d", line );
- result = list_new( result, newstr( file ) );
- result = list_new( result, newstr( buf ) );
- result = list_new( result, newstr( frame->module->name ) );
- result = list_new( result, newstr( frame->rulename ) );
+ result = list_new( result, object_new( file ) );
+ result = list_new( result, object_new( buf ) );
+ result = list_new( result, object_copy( frame->module->name ) );
+ result = list_new( result, object_new( frame->rulename ) );
     }
     return result;
 }
@@ -1279,7 +1301,7 @@
 LIST * builtin_caller_module( PARSE * parse, FRAME * frame )
 {
     LIST * levels_arg = lol_get( frame->args, 0 );
- int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
+ int levels = levels_arg ? atoi( object_str( levels_arg->value ) ) : 0 ;
 
     int i;
     for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i )
@@ -1291,9 +1313,9 @@
     {
         LIST * result;
         string name;
- string_copy( &name, frame->module->name );
+ string_copy( &name, object_str( frame->module->name ) );
         string_pop_back( &name );
- result = list_new( L0, newstr(name.value) );
+ result = list_new( L0, object_new(name.value) );
         string_free( &name );
         return result;
     }
@@ -1322,7 +1344,7 @@
     LIST * arg1 = lol_get( frame->args, 0 );
     clear_targets_to_update();
     for ( ; arg1; arg1 = list_next( arg1 ) )
- mark_target_for_updating( copystr( arg1->string ) );
+ mark_target_for_updating( object_copy( arg1->value ) );
     return result;
 }
 
@@ -1340,30 +1362,30 @@
 {
     LIST * targets = lol_get( frame->args, 0 );
     LIST * log = lol_get( frame->args, 1 );
- LIST * force = lol_get (frame->args, 2);
- LIST * continue_ = lol_get(frame->args, 3);
+ LIST * force = lol_get( frame->args, 2 );
+ LIST * continue_ = lol_get( frame->args, 3 );
     int status = 0;
     int original_stdout;
     int original_stderr;
     int n;
     int targets_count;
- const char** targets2;
+ OBJECT * * targets2;
     int i;
     int original_noexec;
     int original_quitquick;
         
 
- if (log)
+ if ( log )
     {
- int fd = atoi(log->string);
+ int fd = atoi( object_str( log->value ) );
         /* Redirect stdout and stderr, temporary, to the log file. */
- original_stdout = dup (0);
- original_stderr = dup (1);
- dup2 (fd, 0);
- dup2 (fd, 1);
+ original_stdout = dup( 0 );
+ original_stderr = dup( 1 );
+ dup2 ( fd, 0 );
+ dup2 ( fd, 1 );
     }
 
- if (force)
+ if ( force )
     {
         original_noexec = globs.noexec;
         globs.noexec = 0;
@@ -1371,16 +1393,16 @@
         globs.quitquick = 0;
     }
 
- if (continue_)
+ if ( continue_ )
     {
         original_quitquick = globs.quitquick;
         globs.quitquick = 0;
     }
 
     targets_count = list_length( targets );
- targets2 = (const char * *)BJAM_MALLOC( targets_count * sizeof( char * ) );
+ targets2 = (OBJECT * *)BJAM_MALLOC( targets_count * sizeof( OBJECT * ) );
     for (i = 0 ; targets; targets = list_next( targets ) )
- targets2[ i++ ] = targets->string;
+ targets2[ i++ ] = targets->value;
     status |= make( targets_count, targets2, anyhow);
     BJAM_FREE( (void *)targets2 );
 
@@ -1390,27 +1412,27 @@
         globs.quitquick = original_quitquick;
     }
 
- if (continue_)
+ if ( continue_ )
     {
         globs.quitquick = original_quitquick;
     }
 
- if (log)
+ if ( log )
     {
         /* Flush whatever stdio might have buffered, while descriptions
            0 and 1 still refer to the log file. */
- fflush (stdout);
- fflush (stderr);
- dup2 (original_stdout, 0);
- dup2 (original_stderr, 1);
- close (original_stdout);
- close (original_stderr);
+ fflush( stdout );
+ fflush( stderr );
+ dup2( original_stdout, 0 );
+ dup2( original_stderr, 1 );
+ close( original_stdout );
+ close( original_stderr );
     }
 
     last_update_now_status = status;
         
- if (status == 0)
- return list_new (L0, newstr ("ok"));
+ if ( status == 0 )
+ return list_new( L0, object_new( "ok" ) );
     else
         return L0;
 }
@@ -1419,8 +1441,8 @@
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     LIST * arg2 = lol_get( frame->args, 1 );
- TARGET * t = search_for_target( arg1->string, arg2 );
- return list_new( L0, copystr( t->name ) );
+ TARGET * t = search_for_target( arg1->value, arg2 );
+ return list_new( L0, object_copy( t->name ) );
 }
 
 
@@ -1428,7 +1450,7 @@
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     LIST * arg2 = lol_get( frame->args, 1 );
- module_t * m = arg2 ? bindmodule( arg2->string ) : root_module();
+ module_t * m = arg2 ? bindmodule( arg2->value ) : root_module();
     import_module( arg1, m );
     return L0;
 }
@@ -1437,7 +1459,7 @@
 LIST * builtin_imported_modules( PARSE * parse, FRAME * frame )
 {
     LIST * arg0 = lol_get( frame->args, 0 );
- return imported_modules( bindmodule( arg0 ? arg0->string : 0 ) );
+ return imported_modules( bindmodule( arg0 ? arg0->value : 0 ) );
 }
 
 
@@ -1445,8 +1467,8 @@
 {
     LIST * arg1 = lol_get( frame->args, 0 );
     LIST * arg2 = lol_get( frame->args, 1 );
- module_t * const instance = bindmodule( arg1->string );
- module_t * const class_module = bindmodule( arg2->string );
+ module_t * const instance = bindmodule( arg1->value );
+ module_t * const class_module = bindmodule( arg2->value );
     instance->class_module = class_module;
     return L0;
 }
@@ -1479,7 +1501,7 @@
         /* Number of '..' elements seen and not processed yet. */
     int dotdots = 0;
     int rooted = 0;
- char * result = 0;
+ OBJECT * result = 0;
 
     /* Make a copy of input: we should not change it. Prepend a '/' before it as
      * a guard for the algorithm later on and remember whether it was originally
@@ -1489,14 +1511,14 @@
     string_push_back( in, '/' );
     for ( ; arg; arg = list_next( arg ) )
     {
- if ( arg->string[ 0 ] != '\0' )
+ if ( object_str( arg->value )[ 0 ] != '\0' )
         {
             if ( in->size == 1 )
- rooted = ( ( arg->string[ 0 ] == '/' ) ||
- ( arg->string[ 0 ] == '\\' ) );
+ rooted = ( ( object_str( arg->value )[ 0 ] == '/' ) ||
+ ( object_str( arg->value )[ 0 ] == '\\' ) );
             else
                 string_append( in, "/" );
- string_append( in, arg->string );
+ string_append( in, object_str( arg->value ) );
         }
     }
 
@@ -1572,7 +1594,7 @@
      * the original path was rooted and we have an empty path we need to add
      * back the '/'.
      */
- result = newstr( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
+ result = object_new( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
 
     string_free( out );
     string_free( in );
@@ -1586,11 +1608,11 @@
     LIST * module_name = lol_get( frame->args, 0 );
     LIST * rule_name = lol_get( frame->args, 1 );
 
- module_t * module = bindmodule( module_name->string );
+ module_t * module = bindmodule( module_name->value );
 
     native_rule_t n;
     native_rule_t * np = &n;
- n.name = rule_name->string;
+ n.name = rule_name->value;
     if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
     {
         args_refer( np->arguments );
@@ -1600,7 +1622,7 @@
     {
         backtrace_line( frame->prev );
         printf( "error: no native rule \"%s\" defined in module \"%s\"\n",
- n.name, module->name );
+ object_str( n.name ), object_str( module->name ) );
         backtrace( frame->prev );
         exit( 1 );
     }
@@ -1614,16 +1636,16 @@
     LIST * rule_name = lol_get( frame->args, 1 );
     LIST * version = lol_get( frame->args, 2 );
 
- module_t * module = bindmodule( module_name->string );
+ module_t * module = bindmodule( module_name->value );
 
     native_rule_t n;
     native_rule_t * np = &n;
- n.name = rule_name->string;
+ n.name = rule_name->value;
     if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
     {
- int expected_version = atoi( version->string );
+ int expected_version = atoi( object_str( version->value ) );
         if ( np->version == expected_version )
- return list_new( 0, newstr( "true" ) );
+ return list_new( 0, object_new( "true" ) );
     }
     return L0;
 }
@@ -1634,7 +1656,7 @@
     LIST * module_name = lol_get( frame->args, 0 );
     for ( ; module_name; module_name = module_name->next )
     {
- module_t * m = bindmodule( module_name->string );
+ module_t * m = bindmodule( module_name->value );
         m->user_module = 1;
     }
     return L0;
@@ -1650,14 +1672,14 @@
 
     {
         LIST * result = 0;
- char * file;
+ const 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 ) );
+ result = list_new( result, object_new( file ) );
+ result = list_new( result, object_new( buf ) );
         return result;
     }
 }
@@ -1666,8 +1688,8 @@
 LIST * builtin_check_if_file( PARSE * parse, FRAME * frame )
 {
     LIST * name = lol_get( frame->args, 0 );
- return file_is_file( name->string ) == 1
- ? list_new( 0, newstr( "true" ) )
+ return file_is_file( name->value ) == 1
+ ? list_new( 0, object_new( "true" ) )
         : L0 ;
 }
 
@@ -1675,7 +1697,7 @@
 LIST * builtin_md5( PARSE * parse, FRAME * frame )
 {
     LIST * l = lol_get( frame->args, 0 );
- char* s = l->string;
+ const char* s = object_str( l->value );
 
     md5_state_t state;
     md5_byte_t digest[16];
@@ -1683,36 +1705,36 @@
 
     int di;
 
- md5_init(&state);
- md5_append(&state, (const md5_byte_t *)s, strlen(s));
- md5_finish(&state, digest);
+ md5_init( &state );
+ md5_append( &state, (const md5_byte_t *)s, strlen(s) );
+ md5_finish( &state, digest );
 
     for (di = 0; di < 16; ++di)
- sprintf(hex_output + di * 2, "%02x", digest[di]);
+ sprintf( hex_output + di * 2, "%02x", digest[di] );
 
- return list_new (0, newstr(hex_output));
+ return list_new( L0, object_new( hex_output ) );
 }
 
-LIST *builtin_file_open( PARSE *parse, FRAME *frame )
+LIST *builtin_file_open( PARSE * parse, FRAME * frame )
 {
- char* name = lol_get(frame->args, 0)->string;
- char* mode = lol_get(frame->args, 1)->string;
+ const char * name = object_str( lol_get( frame->args, 0 )->value );
+ const char * mode = object_str( lol_get( frame->args, 1 )->value );
     int fd;
     char buffer[sizeof("4294967295")];
 
- if (strcmp(mode, "w") == 0)
+ if ( strcmp(mode, "w") == 0 )
     {
- fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ fd = open( name, O_WRONLY|O_CREAT|O_TRUNC, 0666 );
     }
     else
     {
- fd = open(name, O_RDONLY);
+ fd = open( name, O_RDONLY );
     }
 
     if (fd != -1)
     {
- sprintf(buffer, "%d", fd);
- return list_new(L0, newstr(buffer));
+ sprintf( buffer, "%d", fd );
+ return list_new( L0, object_new( buffer ) );
     }
     else
     {
@@ -1722,50 +1744,50 @@
 
 LIST *builtin_pad( PARSE *parse, FRAME *frame )
 {
- char *string = lol_get(frame->args, 0)->string;
- char *width_s = lol_get(frame->args, 1)->string;
+ OBJECT * string = lol_get( frame->args, 0 )->value;
+ const char * width_s = object_str( lol_get( frame->args, 1 )->value );
 
- int current = strlen (string);
- int desired = atoi(width_s);
+ int current = strlen( object_str( string ) );
+ int desired = atoi( width_s );
     if (current >= desired)
- return list_new (L0, copystr( string ) );
+ return list_new (L0, object_copy( string ) );
     else
     {
- char *buffer = malloc (desired + 1);
+ char * buffer = BJAM_MALLOC( desired + 1 );
         int i;
- LIST *result;
+ LIST * result;
 
- strcpy (buffer, string);
- for (i = current; i < desired; ++i)
+ strcpy( buffer, object_str( string ) );
+ for ( i = current; i < desired; ++i )
             buffer[i] = ' ';
         buffer[desired] = '\0';
- result = list_new (L0, newstr (buffer));
- free (buffer);
+ result = list_new( L0, object_new( buffer ) );
+ BJAM_FREE( buffer );
         return result;
     }
 }
 
-LIST *builtin_precious( PARSE *parse, FRAME *frame )
+LIST *builtin_precious( PARSE * parse, FRAME * frame )
 {
- LIST* targets = lol_get(frame->args, 0);
+ LIST * targets = lol_get(frame->args, 0);
 
     for ( ; targets; targets = list_next( targets ) )
     {
- TARGET* t = bindtarget (targets->string);
+ TARGET* t = bindtarget( targets->value );
         t->flags |= T_FLAG_PRECIOUS;
     }
 
     return L0;
 }
 
-LIST *builtin_self_path( PARSE *parse, FRAME *frame )
+LIST *builtin_self_path( PARSE * parse, FRAME * frame )
 {
- extern char *saved_argv0;
- char *p = executable_path (saved_argv0);
- if (p)
+ extern const char * saved_argv0;
+ char * p = executable_path( saved_argv0 );
+ if ( p )
     {
- LIST* result = list_new (0, newstr (p));
- free(p);
+ LIST* result = list_new( 0, object_new( p ) );
+ free( p );
         return result;
     }
     else
@@ -1774,13 +1796,13 @@
     }
 }
 
-LIST *builtin_makedir( PARSE *parse, FRAME *frame )
+LIST *builtin_makedir( PARSE * parse, FRAME * frame )
 {
- LIST *path = lol_get(frame->args, 0);
+ LIST * path = lol_get( frame->args, 0 );
 
- if (file_mkdir(path->string) == 0)
+ if ( file_mkdir( object_str( path->value ) ) == 0 )
     {
- LIST *result = list_new (0, newstr(path->string));
+ LIST * result = list_new ( L0, object_copy( path->value ) );
         return result;
     }
     else
@@ -1794,10 +1816,10 @@
 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;
+ const char * python_module = object_str( lol_get( frame->args, 0 )->value );
+ const char * python_function = object_str( lol_get( frame->args, 1 )->value );
+ OBJECT * jam_module = lol_get( frame->args, 2 )->value;
+ OBJECT * jam_rule = lol_get( frame->args, 3 )->value;
 
     PyObject * pName;
     PyObject * pModule;
@@ -1820,7 +1842,7 @@
             enter_module( root_module() );
         }
 
- extra = var_get( "EXTRA_PYTHONPATH" );
+ extra = var_get( constant_extra_pythonpath );
 
         if ( outer_module != root_module() )
         {
@@ -1833,7 +1855,7 @@
             string buf[ 1 ];
             string_new( buf );
             string_append( buf, "import sys\nsys.path.append(\"" );
- string_append( buf, extra->string );
+ string_append( buf, object_str( extra->value ) );
             string_append( buf, "\")\n" );
             PyRun_SimpleString( buf->value );
             string_free( buf );
@@ -1878,7 +1900,7 @@
 
 #endif
 
-void lol_build( LOL * lol, char * * elements )
+void lol_build( LOL * lol, const char * * elements )
 {
     LIST * l = L0;
     lol_init( lol );
@@ -1892,7 +1914,7 @@
         }
         else
         {
- l = list_new( l, newstr( *elements ) );
+ l = list_new( l, object_new( *elements ) );
         }
         ++elements;
     }
@@ -1912,22 +1934,22 @@
 
 PyObject* bjam_call( PyObject * self, PyObject * args )
 {
- FRAME inner[ 1 ];
- LIST * result;
- PARSE * p;
- char * rulename;
+ FRAME inner[ 1 ];
+ LIST * result;
+ PARSE * p;
+ OBJECT * rulename;
 
     /* Build up the list of arg lists. */
     frame_init( inner );
     inner->prev = 0;
     inner->prev_user = 0;
- inner->module = bindmodule( "python_interface" );
+ inner->module = bindmodule( constant_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 ) );
+ rulename = object_new( PyString_AsString( PyTuple_GetItem( args, 0 ) ) );
     {
         int i = 1;
         int size = PyTuple_Size( args );
@@ -1936,7 +1958,7 @@
             PyObject * a = PyTuple_GetItem( args, i );
             if ( PyString_Check( a ) )
             {
- lol_add( inner->args, list_new( 0, newstr(
+ lol_add( inner->args, list_new( 0, object_new(
                     PyString_AsString( a ) ) ) );
             }
             else if ( PySequence_Check( a ) )
@@ -1954,7 +1976,7 @@
                         printf( "Invalid parameter type passed from Python\n" );
                         exit( 1 );
                     }
- l = list_new( l, newstr( s ) );
+ l = list_new( l, object_new( s ) );
                     Py_DECREF( e );
                 }
                 lol_add( inner->args, l );
@@ -1963,6 +1985,7 @@
     }
 
     result = evaluate_rule( rulename, inner );
+ object_free( rulename );
 
     frame_free( inner );
 
@@ -1972,7 +1995,7 @@
         int i = 0;
         while ( result )
         {
- PyList_SetItem( pyResult, i, PyString_FromString( result->string ) );
+ PyList_SetItem( pyResult, i, PyString_FromString( object_str( result->value ) ) );
             result = list_next( result );
             i += 1;
         }
@@ -2000,6 +2023,8 @@
     PyObject * bjam_signature = NULL;
     module_t * m;
     RULE * r;
+ OBJECT * module_name;
+ OBJECT * rule_name;
 
     if ( !PyArg_ParseTuple( args, "ssO|O:import_rule",
                             &module, &rule, &func, &bjam_signature ) )
@@ -2012,8 +2037,15 @@
         return NULL;
     }
 
- m = bindmodule( *module ? module : 0 );
- r = bindrule( rule, m );
+ module_name = *module ? object_new( module ) : 0;
+ m = bindmodule( module_name );
+ if( module_name )
+ {
+ object_free( module_name );
+ }
+ rule_name = object_new( rule );
+ r = bindrule( rule_name, m );
+ object_free( rule_name );
 
     /* Make pFunc owned. */
     Py_INCREF( func );
@@ -2060,6 +2092,8 @@
     LIST * bindlist = L0;
     int n;
     int i;
+ OBJECT * name_str;
+ OBJECT * body_str;
 
     if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
                           &PyList_Type, &bindlist_python, &flags ) )
@@ -2075,10 +2109,14 @@
                             "bind list has non-string type" );
             return NULL;
         }
- bindlist = list_new( bindlist, newstr( PyString_AsString( next ) ) );
+ bindlist = list_new( bindlist, object_new( PyString_AsString( next ) ) );
     }
 
- new_rule_actions( root_module(), name, newstr( body ), bindlist, flags );
+ name_str = object_new( name );
+ body_str = object_new( body );
+ new_rule_actions( root_module(), name_str, body_str, bindlist, flags );
+ object_free( body_str );
+ object_free( name_str );
 
     Py_INCREF( Py_None );
     return Py_None;
@@ -2095,17 +2133,20 @@
     LIST * value;
     PyObject * result;
     int i;
+ OBJECT * varname;
 
     if ( !PyArg_ParseTuple( args, "s", &name ) )
         return NULL;
 
     enter_module( root_module() );
- value = var_get( name );
+ varname = object_new( name );
+ value = var_get( varname );
+ object_free( varname );
     exit_module( root_module() );
 
     result = PyList_New( list_length( value ) );
     for ( i = 0; value; value = list_next( value ), ++i )
- PyList_SetItem( result, i, PyString_FromString( value->string ) );
+ PyList_SetItem( result, i, PyString_FromString( object_str( value->value ) ) );
 
     return result;
 }
@@ -2118,10 +2159,10 @@
 
     for ( ; f = f->prev; )
     {
- PyObject * tuple = PyTuple_New( 4 );
- char * file;
- int line;
- char buf[ 32 ];
+ PyObject * tuple = PyTuple_New( 4 );
+ const char * file;
+ int line;
+ char buf[ 32 ];
 
         get_source_line( f->procedure, &file, &line );
         sprintf( buf, "%d", line );
@@ -2129,8 +2170,8 @@
         /* PyTuple_SetItem steals reference. */
         PyTuple_SetItem( tuple, 0, PyString_FromString( file ) );
         PyTuple_SetItem( tuple, 1, PyString_FromString( buf ) );
- PyTuple_SetItem( tuple, 2, PyString_FromString( f->module->name ) );
- PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
+ PyTuple_SetItem( tuple, 2, PyString_FromString( object_str( f->module->name ) ) );
+ PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
 
         PyList_Append( result, tuple );
         Py_DECREF( tuple );
@@ -2140,9 +2181,8 @@
 
 PyObject * bjam_caller( PyObject * self, PyObject * args )
 {
- if ( !frame_before_python_call )
- Py_RETURN_NONE;
- return PyString_FromString(frame_before_python_call->prev->module->name);
+ return PyString_FromString(
+ object_str( frame_before_python_call->prev->module->name ) );
 }
 
 #endif /* #ifdef HAVE_PYTHON */
@@ -2201,7 +2241,7 @@
      * should Windows ever 'fix' this feature.
      * (03.06.2008.) (Jurko)
      */
- static FILE * windows_popen_wrapper( char * command, char * mode )
+ static FILE * windows_popen_wrapper( const char * command, const char * mode )
     {
         int extra_command_quotes_needed = ( strchr( command, '"' ) != 0 );
         string quoted_command;
@@ -2226,11 +2266,11 @@
 #endif
 
 
-static char * rtrim(char *s)
+static char * rtrim( char * s )
 {
- char *p = s;
- while(*p) ++p;
- for(--p; p >= s && isspace(*p); *p-- = 0);
+ char * p = s;
+ while ( *p ) ++p;
+ for ( --p; p >= s && isspace( *p ); *p-- = 0 );
     return s;
 }
 
@@ -2253,15 +2293,15 @@
         LIST * arg = lol_get( frame->args, a );
         while ( arg )
         {
- if ( strcmp( "exit-status", arg->string ) == 0 )
+ if ( strcmp( "exit-status", object_str( arg->value ) ) == 0 )
             {
                 exit_status_opt = 1;
             }
- else if ( strcmp( "no-output", arg->string ) == 0 )
+ else if ( strcmp( "no-output", object_str( arg->value ) ) == 0 )
             {
                 no_output_opt = 1;
             }
- else if ( strcmp("strip-eol", arg->string) == 0 )
+ else if ( strcmp("strip-eol", object_str( arg->value ) ) == 0 )
             {
                 strip_eol_opt = 1;
             }
@@ -2275,7 +2315,7 @@
      */
     fflush( NULL );
 
- p = popen( command->string, "r" );
+ p = popen( object_str( command->value ), "r" );
     if ( p == NULL )
         return L0;
 
@@ -2295,7 +2335,7 @@
     exit_status = pclose( p );
 
     /* The command output is returned first. */
- result = list_new( L0, newstr( s.value ) );
+ result = list_new( L0, object_new( s.value ) );
     string_free( &s );
 
     /* The command exit result next. */
@@ -2306,7 +2346,7 @@
         else
             exit_status = -1;
         sprintf( buffer, "%d", exit_status );
- result = list_new( result, newstr( buffer ) );
+ result = list_new( result, object_new( buffer ) );
     }
 
     return result;

Modified: trunk/tools/build/v2/engine/class.c
==============================================================================
--- trunk/tools/build/v2/engine/class.c (original)
+++ trunk/tools/build/v2/engine/class.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -7,7 +7,7 @@
 #include "variable.h"
 #include "frames.h"
 #include "rules.h"
-#include "newstr.h"
+#include "object.h"
 
 #include "hash.h"
 
@@ -19,26 +19,26 @@
 {
     for ( ; class_names; class_names = class_names->next )
     {
- char * * p = &class_names->string;
+ OBJECT * * p = &class_names->value;
         if ( !hashcheck( classes, (HASHDATA * *)&p ) )
         {
- printf( "Class %s is not defined\n", class_names->string );
+ printf( "Class %s is not defined\n", object_str( class_names->value ) );
             abort();
         }
     }
 }
 
 
-static char * class_module_name( char * declared_name )
+static OBJECT * class_module_name( OBJECT * declared_name )
 {
     string name[ 1 ];
- char * result;
+ OBJECT * result;
 
     string_new( name );
     string_append( name, "class@" );
- string_append( name, declared_name );
+ string_append( name, object_str( declared_name ) );
 
- result = newstr( name->value );
+ result = object_new( name->value );
     string_free( name );
 
     return result;
@@ -47,7 +47,7 @@
 
 struct import_base_data
 {
- char * base_name;
+ OBJECT * base_name;
     module_t * base_module;
     module_t * class_module;
 };
@@ -60,14 +60,19 @@
     RULE * ir2;
     struct import_base_data * d = (struct import_base_data *)d_;
     string qualified_name[ 1 ];
+ OBJECT * qname;
 
     string_new ( qualified_name );
- string_append ( qualified_name, d->base_name );
+ string_append ( qualified_name, object_str( d->base_name ) );
     string_push_back( qualified_name, '.' );
- string_append ( qualified_name, r->name );
+ string_append ( qualified_name, object_str( r->name ) );
+
+ qname = object_new( qualified_name->value );
 
     ir1 = import_rule( r, d->class_module, r->name );
- ir2 = import_rule( r, d->class_module, qualified_name->value );
+ ir2 = import_rule( r, d->class_module, qname );
+
+ object_free( qname );
 
     /* Copy 'exported' flag. */
     ir1->exported = ir2->exported = r->exported;
@@ -87,43 +92,45 @@
  * marked as exported.
  */
 
-static void import_base_rules( module_t * class, char * base )
+static void import_base_rules( module_t * class_, OBJECT * base )
 {
- char * module_name = class_module_name( base );
+ OBJECT * module_name = class_module_name( base );
     module_t * base_module = bindmodule( module_name );
     LIST * imported;
     struct import_base_data d;
     d.base_name = base;
     d.base_module = base_module;
- d.class_module = class;
- freestr( module_name );
+ d.class_module = class_;
+ object_free( module_name );
 
     if ( base_module->rules )
         hashenumerate( base_module->rules, import_base_rule, &d );
 
     imported = imported_modules( base_module );
- import_module( imported, class );
+ import_module( imported, class_ );
     list_free( imported );
 }
 
 
-char * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
+OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
 {
- char * name = class_module_name( xname->string );
- char * * pp = &xname->string;
+ OBJECT * name = class_module_name( xname->value );
+ OBJECT * * pp = &xname->value;
     module_t * class_module = 0;
     module_t * outer_module = frame->module;
+ OBJECT * name_ = object_new( "__name__" );
+ OBJECT * bases_ = object_new( "__bases__" );
 
     if ( !classes )
- classes = hashinit( sizeof( char * ), "classes" );
+ classes = hashinit( sizeof( OBJECT * ), "classes" );
 
     if ( hashenter( classes, (HASHDATA * *)&pp ) )
     {
- *pp = copystr( xname->string );
+ *pp = object_copy( xname->value );
     }
     else
     {
- printf( "Class %s already defined\n", xname->string );
+ printf( "Class %s already defined\n", object_str( xname->value ) );
         abort();
     }
     check_defined( bases );
@@ -133,21 +140,24 @@
     exit_module( outer_module );
     enter_module( class_module );
 
- var_set( "__name__", xname, VAR_SET );
- var_set( "__bases__", bases, VAR_SET );
+ var_set( name_, xname, VAR_SET );
+ var_set( bases_, bases, VAR_SET );
 
     exit_module( class_module );
     enter_module( outer_module );
 
     for ( ; bases; bases = bases->next )
- import_base_rules( class_module, bases->string );
+ import_base_rules( class_module, bases->value );
+
+ object_free( bases_ );
+ object_free( name_ );
 
     return name;
 }
 
 static void free_class( void * xclass, void * data )
 {
- freestr( *(char **)xclass );
+ object_free( *(OBJECT * *)xclass );
 }
 
 void class_done( void )

Modified: trunk/tools/build/v2/engine/class.h
==============================================================================
--- trunk/tools/build/v2/engine/class.h (original)
+++ trunk/tools/build/v2/engine/class.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,7 +8,7 @@
 #include "lists.h"
 #include "frames.h"
 
-char* make_class_module(LIST* xname, LIST* bases, FRAME* frame);
+OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame );
 void class_done( void );
 
 #endif

Modified: trunk/tools/build/v2/engine/command.c
==============================================================================
--- trunk/tools/build/v2/engine/command.c (original)
+++ trunk/tools/build/v2/engine/command.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -34,7 +34,7 @@
 {
     CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
     /* Lift line-length limitation entirely when JAMSHELL is just "%". */
- int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
+ int no_limit = ( shell && !strcmp(object_str(shell->value),"%") && !list_next(shell) );
     int max_line = MAXLINE;
     int allocated = -1;
 
@@ -56,7 +56,7 @@
         if ( cmd->buf == 0 )
             break;
 
- allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
+ allocated = var_string( object_str( rule->actions->command ), cmd->buf, max_line, &cmd->args );
 
         max_line = max_line * 2;
     }

Modified: trunk/tools/build/v2/engine/command.h
==============================================================================
--- trunk/tools/build/v2/engine/command.h (original)
+++ trunk/tools/build/v2/engine/command.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -36,6 +36,9 @@
  * CMD - an action, ready to be formatted into a buffer and executed.
  */
 
+#ifndef COMMAND_SW20111118_H
+#define COMMAND_SW20111118_H
+
 typedef struct _cmd CMD;
 
 struct _cmd
@@ -59,3 +62,5 @@
 void cmd_free( CMD * );
 
 #define cmd_next( c ) ( ( c )->next )
+
+#endif

Modified: trunk/tools/build/v2/engine/compile.c
==============================================================================
--- trunk/tools/build/v2/engine/compile.c (original)
+++ trunk/tools/build/v2/engine/compile.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -18,7 +18,7 @@
 # include "variable.h"
 # include "expand.h"
 # include "rules.h"
-# include "newstr.h"
+# include "object.h"
 # include "make.h"
 # include "search.h"
 # include "hdrmacro.h"
@@ -27,6 +27,7 @@
 # include "strings.h"
 # include "builtins.h"
 # include "class.h"
+# include "constants.h"
 
 # include <assert.h>
 # include <string.h>
@@ -86,15 +87,17 @@
  * 01/10/00 (seiwald) - built-ins split out to builtin.c.
  */
 
-static void debug_compile( int which, char *s, FRAME* frame );
-int glob( char *s, char *c );
+static void debug_compile( int which, const char * s, FRAME * frame );
+int glob( const char * s, const char * c );
 /* Internal functions from builtins.c */
-void backtrace( FRAME *frame );
-void backtrace_line( FRAME *frame );
-void print_source_line( PARSE* p );
+void backtrace( FRAME * frame );
+void backtrace_line( FRAME * frame );
+void print_source_line( PARSE * p );
 
 struct frame * frame_before_python_call;
 
+static OBJECT * module_scope;
+
 void frame_init( FRAME* frame )
 {
     frame->prev = 0;
@@ -142,8 +145,8 @@
 
     while ( !status && ( t || s ) )
     {
- char *st = t ? t->string : "";
- char *ss = s ? s->string : "";
+ const char *st = t ? object_str( t->value ) : "";
+ const char *ss = s ? object_str( s->value ) : "";
 
         status = strcmp( st, ss );
 
@@ -187,7 +190,7 @@
         for ( t = ll; t; t = list_next( t ) )
         {
             for ( s = lr; s; s = list_next( s ) )
- if ( !strcmp( t->string, s->string ) )
+ if ( object_equal( t->value, s->value ) )
                 break;
             if ( !s ) break;
         }
@@ -220,7 +223,7 @@
     if ( !status ) t = 0;
     else if ( ll ) t = ll, ll = 0;
     else if ( lr ) t = lr, lr = 0;
- else t = list_new( L0, newstr( "1" ) );
+ else t = list_new( L0, object_new( "1" ) );
 
     if ( ll ) list_free( ll );
     if ( lr ) list_free( lr );
@@ -255,7 +258,7 @@
 
     for ( l = nv; l; l = list_next( l ) )
     {
- LIST * val = list_new( L0, copystr( l->string ) );
+ LIST * val = list_new( L0, object_copy( l->value ) );
         var_set( parse->string, val, VAR_SET );
         list_free( parse_evaluate( parse->right, frame ) );
     }
@@ -324,7 +327,7 @@
 
     if ( nt )
     {
- TARGET * t = bindtarget( nt->string );
+ TARGET * t = bindtarget( nt->value );
 
         /* DWA 2001/10/22 - Perforce Jam cleared the arguments here, which
          * prevents an included file from being treated as part of the body of a
@@ -340,7 +343,7 @@
         /* We don't expect that file to be included is generated by some
            action. Therefore, pass 0 as third argument.
            If the name resolves to directory, let it error out. */
- freestr( t->boundname );
+ object_free( t->boundname );
         t->boundname = search( t->name, &t->time, 0, 0 );
         popsettings( t->settings );
 
@@ -352,7 +355,7 @@
     return L0;
 }
 
-static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame)
+static LIST* evaluate_in_module ( OBJECT * module_name, PARSE * p, FRAME* frame)
 {
     LIST* result;
 
@@ -382,7 +385,7 @@
 {
     /* Here we are entering a module declaration block. */
     LIST * module_name = parse_evaluate( p->left, frame );
- LIST * result = evaluate_in_module( module_name ? module_name->string : 0,
+ LIST * result = evaluate_in_module( module_name ? module_name->value : 0,
                                        p->right, frame );
     list_free( module_name );
     return result;
@@ -394,7 +397,7 @@
     /** Todo: check for empty class name.
         Check for class redeclaration. */
 
- char * class_module = 0;
+ OBJECT * class_module = 0;
 
     LIST * name = parse_evaluate( p->left->right, frame );
     LIST * bases = 0;
@@ -404,7 +407,7 @@
 
     class_module = make_class_module( name, bases, frame );
     evaluate_in_module( class_module, p->right, frame );
- freestr( class_module );
+ object_free( class_module );
 
     return L0;
 }
@@ -419,8 +422,9 @@
 LIST * compile_list( PARSE * parse, FRAME * frame )
 {
     /* s is a copyable string */
- char * s = parse->string;
- return var_expand( L0, s, s + strlen( s ), frame->args, 1 );
+ OBJECT * o = parse->string;
+ const char * s = object_str( o );
+ return var_expand( L0, s, s + strlen( s ), frame->args, o );
 }
 
 
@@ -451,7 +455,7 @@
 
     /* Initial value is ns. */
     for ( l = nt; l; l = list_next( l ) )
- s = addsettings( s, VAR_SET, l->string, list_copy( (LIST *)0, ns ) );
+ s = addsettings( s, VAR_SET, l->value, list_copy( L0, ns ) );
 
     list_free( ns );
     list_free( nt );
@@ -503,7 +507,7 @@
 
     if ( nt )
     {
- TARGET * t = bindtarget( nt->string );
+ TARGET * t = bindtarget( nt->value );
         pushsettings( t->settings );
         result = parse_evaluate( parse->right, frame );
         popsettings( t->settings );
@@ -553,7 +557,7 @@
 }
 
 
-static void argument_error( char * message, RULE * rule, FRAME * frame, LIST* arg )
+static void argument_error( const char * message, RULE * rule, FRAME * frame, LIST * arg )
 {
     LOL * actual = frame->args;
     assert( frame->procedure != 0 );
@@ -562,9 +566,9 @@
     lol_print( rule->arguments->data );
     printf( " )\n* called with: ( " );
     lol_print( actual );
- printf( " )\n* %s %s\n", message, arg ? arg->string : "" );
+ printf( " )\n* %s %s\n", message, arg ? object_str ( arg->value ) : "" );
     print_source_line( rule->procedure );
- printf( "see definition of rule '%s' being called\n", rule->name );
+ printf( "see definition of rule '%s' being called\n", object_str( rule->name ) );
     backtrace( frame->prev );
     exit( 1 );
 }
@@ -581,7 +585,7 @@
  * specification.
  */
 
-static int is_type_name( char * s )
+static int is_type_name( const char * s )
 {
     return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
         ( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
@@ -598,7 +602,7 @@
 {
     if ( formal->next )
     {
- char * next = formal->next->string;
+ const char * next = object_str( formal->next->value );
         if ( next && ( next[ 0 ] != 0 ) && ( next[ 1 ] == 0 ) )
             return next[ 0 ];
     }
@@ -621,11 +625,11 @@
 
 static void type_check
 (
- char * type_name,
- LIST * values,
- FRAME * caller,
- RULE * called,
- LIST * arg_name
+ OBJECT * type_name,
+ LIST * values,
+ FRAME * caller,
+ RULE * called,
+ LIST * arg_name
 )
 {
     static module_t * typecheck = 0;
@@ -635,7 +639,11 @@
         return;
 
     if ( !typecheck )
- typecheck = bindmodule( ".typecheck" );
+ {
+ OBJECT * str_typecheck = object_new( ".typecheck" );
+ typecheck = bindmodule( str_typecheck );
+ object_free( str_typecheck );
+ }
 
     /* If the checking rule can not be found, also bail. */
     {
@@ -659,13 +667,13 @@
 
         enter_module( typecheck );
         /* Prepare the argument list */
- lol_add( frame->args, list_new( L0, copystr( values->string ) ) );
+ lol_add( frame->args, list_new( L0, object_copy( values->value ) ) );
         error = evaluate_rule( type_name, frame );
 
         exit_module( typecheck );
 
         if ( error )
- argument_error( error->string, called, caller, arg_name );
+ argument_error( object_str( error->value ), called, caller, arg_name );
 
         frame_free( frame );
         values = values->next;
@@ -694,14 +702,14 @@
         for ( n = 0; n < max ; ++n )
         {
             LIST *actual = lol_get( all_actual, n );
- char *type_name = 0;
+ OBJECT * type_name = 0;
 
             LIST *formal;
             for ( formal = lol_get( all_formal, n ); formal; formal = formal->next )
             {
- char* name = formal->string;
+ OBJECT * name = formal->value;
 
- if ( is_type_name(name) )
+ if ( is_type_name( object_str( name ) ) )
                 {
                     if ( type_name )
                         argument_error( "missing argument name before type name:", rule, frame, formal );
@@ -709,7 +717,7 @@
                     if ( !formal->next )
                         argument_error( "missing argument name after type name:", rule, frame, formal );
 
- type_name = formal->string;
+ type_name = formal->value;
                 }
                 else
                 {
@@ -719,7 +727,7 @@
                     int multiple = 0;
 
                     /* Stop now if a variable number of arguments are specified */
- if ( name[0] == '*' && name[1] == 0 )
+ if ( object_str( name )[0] == '*' && object_str( name )[1] == 0 )
                         return locals;
 
                     modifier = arg_modifier( formal );
@@ -744,7 +752,7 @@
                     default:
                         if ( actual ) /* in case actual is missing */
                         {
- value = list_new( 0, copystr( actual->string ) );
+ value = list_new( 0, object_copy( actual->value ) );
                             actual = actual->next;
                         }
                     }
@@ -777,14 +785,12 @@
    code instead of said object.
    If the object is string, use the string value
    If the object implemenets __jam_repr__ method, use that.
- Otherwise return 0.
-
- The result value is newstr-ed. */
-char *python_to_string(PyObject* value)
+ Otherwise return 0. */
+OBJECT *python_to_string(PyObject* value)
 {
     if (PyString_Check(value))
     {
- return newstr(PyString_AsString(value));
+ return object_new(PyString_AsString(value));
     }
     else
     {
@@ -802,7 +808,7 @@
                 Py_DECREF(arguments2);
                 if (PyString_Check(value2))
                 {
- return newstr(PyString_AsString(value2));
+ return object_new(PyString_AsString(value2));
                 }
                 Py_DECREF(value2);
             }
@@ -819,6 +825,7 @@
     PyObject * kw = NULL;
     int i ;
     PyObject * py_result;
+ FRAME * prev_frame_before_python_call;
 
     if (r->arguments)
     {
@@ -829,13 +836,13 @@
 
         for (args = collect_arguments(r, frame); args; args = args->next)
         {
- PyObject *key = PyString_FromString(args->symbol);
+ PyObject *key = PyString_FromString(object_str(args->symbol));
             PyObject *value = 0;
             if (args->multiple)
                 value = list_to_python(args->value);
             else {
                 if (args->value)
- value = PyString_FromString(args->value->string);
+ value = PyString_FromString(object_str(args->value->value));
             }
 
             if (value)
@@ -854,7 +861,7 @@
             
             for ( ; l; l = l->next )
             {
- PyObject * v = PyString_FromString(l->string);
+ PyObject * v = PyString_FromString(object_str(l->value));
                 PyList_Append( arg, v );
                 Py_DECREF(v);
             }
@@ -863,9 +870,10 @@
         }
     }
 
+ prev_frame_before_python_call = frame_before_python_call;
     frame_before_python_call = frame;
     py_result = PyObject_Call( r->python_function, arguments, kw );
- frame_before_python_call = NULL;
+ frame_before_python_call = prev_frame_before_python_call;
     Py_DECREF(arguments);
     Py_XDECREF(kw);
     if ( py_result != NULL )
@@ -877,11 +885,11 @@
             for ( i = 0; i < size; ++i )
             {
                 PyObject * item = PyList_GetItem( py_result, i );
- char *s = python_to_string (item);
+ OBJECT *s = python_to_string (item);
                 if (!s) {
                     fprintf( stderr, "Non-string object returned by Python call.\n" );
                 } else {
- result = list_new (result, newstr( s ) );
+ result = list_new (result, s);
                 }
             }
         }
@@ -891,9 +899,9 @@
         }
         else
         {
- char *s = python_to_string(py_result);
+ OBJECT *s = python_to_string(py_result);
             if (s)
- result = list_new(0, newstr( s ) );
+ result = list_new(0, s);
             else
                 /* We have tried all we could. Return empty list. There are
                    cases, e.g. feature.feature function that should return
@@ -920,7 +928,7 @@
 {
     static module_t * python = 0;
     if ( !python )
- python = bindmodule("__python__");
+ python = bindmodule(constant_python);
     return python;
 }
 
@@ -933,8 +941,8 @@
 
 LIST *
 evaluate_rule(
- char * rulename,
- FRAME * frame )
+ OBJECT * rulename,
+ FRAME * frame )
 {
     LIST * result = L0;
     RULE * rule;
@@ -948,18 +956,18 @@
             lol_init(arg_context);
         else
             arg_context = frame->prev->args;
- l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 );
+ l = var_expand( L0, object_str( rulename ), object_str( rulename )+strlen(object_str( rulename )), arg_context, 0 );
     }
 
     if ( !l )
     {
         backtrace_line( frame->prev );
- printf( "warning: rulename %s expands to empty string\n", rulename );
+ printf( "warning: rulename %s expands to empty string\n", object_str( rulename ) );
         backtrace( frame->prev );
         return result;
     }
 
- rule = bindrule( l->string, frame->module );
+ rule = bindrule( l->value, frame->module );
     rulename = rule->name;
 
 #ifdef HAVE_PYTHON
@@ -1007,16 +1015,16 @@
     {
         /* Try hard to indicate in which module the rule is going to execute. */
         if ( rule->module != frame->module
- && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) )
+ && rule->procedure != 0 && !object_equal( rulename, rule->procedure->rulename ) )
         {
             char buf[256] = "";
- strncat( buf, rule->module->name, sizeof( buf ) - 1 );
- strncat( buf, rule->name, sizeof( buf ) - 1 );
+ strncat( buf, object_str( rule->module->name ), sizeof( buf ) - 1 );
+ strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 );
             debug_compile( 1, buf, frame );
         }
         else
         {
- debug_compile( 1, rulename, frame );
+ debug_compile( 1, object_str( rulename ), frame );
         }
 
         lol_print( frame->args );
@@ -1036,7 +1044,7 @@
     /* Record current rule name in frame. */
     if ( rule->procedure )
     {
- frame->rulename = rulename;
+ frame->rulename = object_str( rulename );
         /* And enter record profile info. */
         if ( DEBUG_PROFILE )
             profile_enter( rule->procedure->rulename, prof );
@@ -1046,7 +1054,7 @@
     if ( !rule->actions && !rule->procedure )
     {
         backtrace_line( frame->prev );
- printf( "rule %s unknown in module %s\n", rule->name, frame->module->name );
+ printf( "rule %s unknown in module %s\n", object_str( rule->name ), object_str( frame->module->name ) );
         backtrace( frame->prev );
         exit( 1 );
     }
@@ -1160,7 +1168,7 @@
  * which might be implemented in Jam.
  */
 
-LIST * call_rule( char * rulename, FRAME * caller_frame, ... )
+LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... )
 {
     va_list va;
     LIST * result;
@@ -1256,7 +1264,7 @@
 
     /* Call var_set to set variable. var_set keeps ns, so need to copy it. */
     for ( l = nt; l; l = list_next( l ) )
- var_set( l->string, list_copy( L0, ns ), setflag );
+ var_set( l->value, list_copy( L0, ns ), setflag );
     list_free( nt );
     return ns;
 }
@@ -1342,11 +1350,11 @@
      */
     for ( ts = targets; ts; ts = list_next( ts ) )
     {
- TARGET * t = bindtarget( ts->string );
+ TARGET * t = bindtarget( ts->value );
         LIST * l;
 
         for ( l = nt; l; l = list_next( l ) )
- t->settings = addsettings( t->settings, setflag, l->string,
+ t->settings = addsettings( t->settings, setflag, l->value,
             list_copy( (LIST *)0, ns ) );
     }
 
@@ -1384,7 +1392,7 @@
     /* Step through cases. */
     for ( parse = parse->right; parse; parse = parse->right )
     {
- if ( !glob( parse->left->string, nt ? nt->string : "" ) )
+ if ( !glob( object_str( parse->left->string ), nt ? object_str( nt->value ) : "" ) )
         {
             /* Get & exec parse tree for this case. */
             parse = parse->left->left;
@@ -1402,7 +1410,7 @@
  * debug_compile() - printf with indent to show rule expansion.
  */
 
-static void debug_compile( int which, char * s, FRAME * frame )
+static void debug_compile( int which, const char * s, FRAME * frame )
 {
     static int level = 0;
     static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";

Modified: trunk/tools/build/v2/engine/compile.h
==============================================================================
--- trunk/tools/build/v2/engine/compile.h (original)
+++ trunk/tools/build/v2/engine/compile.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -16,6 +16,7 @@
 # include "frames.h"
 # include "parse.h"
 # include "regexp.h"
+# include "object.h"
 
 /*
  * compile.h - compile parsed jam statements
@@ -43,10 +44,10 @@
 LIST *compile_switch( PARSE *parse, FRAME *frame );
 LIST *compile_while( PARSE *parse, FRAME *frame );
 
-LIST *evaluate_rule( char *rulename, FRAME *frame );
-LIST *call_rule( char *rulename, FRAME* caller_frame, ...);
+LIST *evaluate_rule( OBJECT * rulename, FRAME * frame );
+LIST *call_rule( OBJECT * rulename, FRAME * caller_frame, ...);
 
-regexp* regex_compile( const char* pattern );
+regexp* regex_compile( OBJECT * pattern );
 
 /* Flags for compile_set(), etc */
 

Added: trunk/tools/build/v2/engine/constants.c
==============================================================================
--- (empty file)
+++ trunk/tools/build/v2/engine/constants.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 Steven Watanabe
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+# include "constants.h"
+# include "object.h"
+
+/*
+ * constants.c - constant objects
+ *
+ * External functions:
+ *
+ * constants_init() - initialize constants
+ * constants_done() - free constants
+ *
+ */
+
+void constants_init( void )
+{
+ constant_builtin = object_new( "(builtin)" );
+ constant_other = object_new( "[OTHER]" );
+ constant_total = object_new( "[TOTAL]" );
+ constant_FILE_DIRSCAN = object_new( "FILE_DIRSCAN" );
+ constant_MAIN = object_new( "MAIN" );
+ constant_MAIN_MAKE = object_new( "MAIN_MAKE" );
+ constant_MAKE_MAKE0 = object_new( "MAKE_MAKE0" );
+ constant_MAKE_MAKE1 = object_new( "MAKE_MAKE1" );
+ constant_MAKE_MAKE0SORT = object_new( "MAKE_MAKE0SORT" );
+ constant_BINDMODULE = object_new( "BINDMODULE" );
+ constant_IMPORT_MODULE = object_new( "IMPORT_MODULE" );
+ constant_BUILTIN_GLOB_BACK = object_new( "BUILTIN_GLOB_BACK" );
+ constant_timestamp = object_new( "timestamp" );
+ constant_python = object_new("__python__");
+ constant_python_interface = object_new( "python_interface" );
+ constant_extra_pythonpath = object_new( "EXTRA_PYTHONPATH" );
+ constant_MAIN_PYTHON = object_new( "MAIN_PYTHON" );
+}
+
+void constants_done( void )
+{
+ object_free( constant_builtin );
+ object_free( constant_other );
+ object_free( constant_total );
+ object_free( constant_FILE_DIRSCAN );
+ object_free( constant_MAIN );
+ object_free( constant_MAIN_MAKE );
+ object_free( constant_MAKE_MAKE0 );
+ object_free( constant_MAKE_MAKE1 );
+ object_free( constant_MAKE_MAKE0SORT );
+ object_free( constant_BINDMODULE );
+ object_free( constant_IMPORT_MODULE );
+ object_free( constant_BUILTIN_GLOB_BACK );
+ object_free( constant_timestamp );
+ object_free( constant_python );
+ object_free( constant_python_interface );
+ object_free( constant_extra_pythonpath );
+ object_free( constant_MAIN_PYTHON );
+}
+
+OBJECT * constant_builtin;
+OBJECT * constant_other;
+OBJECT * constant_total;
+OBJECT * constant_FILE_DIRSCAN;
+OBJECT * constant_MAIN;
+OBJECT * constant_MAIN_MAKE;
+OBJECT * constant_MAKE_MAKE0;
+OBJECT * constant_MAKE_MAKE1;
+OBJECT * constant_MAKE_MAKE0SORT;
+OBJECT * constant_BINDMODULE;
+OBJECT * constant_IMPORT_MODULE;
+OBJECT * constant_BUILTIN_GLOB_BACK;
+OBJECT * constant_timestamp;
+OBJECT * constant_python;
+OBJECT * constant_python_interface;
+OBJECT * constant_extra_pythonpath;
+OBJECT * constant_MAIN_PYTHON;

Added: trunk/tools/build/v2/engine/constants.h
==============================================================================
--- (empty file)
+++ trunk/tools/build/v2/engine/constants.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011 Steven Watanabe
+ *
+ * This file is part of Jam - see jam.c for Copyright information.
+ */
+
+/*
+ * constants.h - constant objects
+ */
+
+#ifndef BOOST_JAM_CONSTANTS_H
+#define BOOST_JAM_CONSTANTS_H
+
+#include "object.h"
+
+void constants_init( void );
+void constants_done( void );
+
+extern OBJECT * constant_builtin; /* "(builtin)" */
+extern OBJECT * constant_other; /* "[OTHER]" */
+extern OBJECT * constant_total; /* "[TOTAL]" */
+extern OBJECT * constant_FILE_DIRSCAN; /* "FILE_DIRSCAN" */
+extern OBJECT * constant_MAIN; /* "MAIN" */
+extern OBJECT * constant_MAIN_MAKE; /* "MAIN_MAKE" */
+extern OBJECT * constant_MAKE_MAKE0; /* "MAKE_MAKE0" */
+extern OBJECT * constant_MAKE_MAKE1; /* "MAKE_MAKE1" */
+extern OBJECT * constant_MAKE_MAKE0SORT; /* "MAKE_MAKE0SORT" */
+extern OBJECT * constant_BINDMODULE; /* "BINDMODULE" */
+extern OBJECT * constant_IMPORT_MODULE; /* "IMPORT_MODULE" */
+extern OBJECT * constant_BUILTIN_GLOB_BACK; /* "BUILTIN_GLOB_BACK" */
+extern OBJECT * constant_timestamp; /* "timestamp" */
+extern OBJECT * constant_python; /* "__python__" */
+extern OBJECT * constant_python_interface; /* "python_interface" */
+extern OBJECT * constant_extra_pythonpath; /* "EXTRA_PYTHONPATH" */
+extern OBJECT * constant_MAIN_PYTHON; /* "MAIN_PYTHON" */
+
+#endif

Modified: trunk/tools/build/v2/engine/debug.c
==============================================================================
--- trunk/tools/build/v2/engine/debug.c (original)
+++ trunk/tools/build/v2/engine/debug.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -14,18 +14,18 @@
 
 static profile_frame * profile_stack = 0;
 static struct hash * profile_hash = 0;
-static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
-static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
+static profile_info profile_other = { 0, 0, 0, 0, 0, 0 };
+static profile_info profile_total = { 0, 0, 0, 0, 0, 0 };
 
 
-profile_frame * profile_init( char * rulename, profile_frame * frame )
+profile_frame * profile_init( OBJECT * rulename, profile_frame * frame )
 {
     if ( DEBUG_PROFILE ) profile_enter( rulename, frame );
     return frame;
 }
 
 
-void profile_enter( char * rulename, profile_frame * frame )
+void profile_enter( OBJECT * rulename, profile_frame * frame )
 {
     if ( DEBUG_PROFILE )
     {
@@ -126,7 +126,9 @@
         printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--",
             "--net--", "--each--", "--mem--", "--each--", "--name--" );
         hashenumerate( profile_hash, dump_profile_entry, 0 );
+ profile_other.name = constant_other;
         dump_profile_entry( &profile_other, 0 );
+ profile_total.name = constant_total;
         dump_profile_entry( &profile_total, (void *)1 );
     }
 }

Modified: trunk/tools/build/v2/engine/debug.h
==============================================================================
--- trunk/tools/build/v2/engine/debug.h (original)
+++ trunk/tools/build/v2/engine/debug.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -6,6 +6,7 @@
 #ifndef BJAM_DEBUG_H
 #define BJAM_DEBUG_H
 
+#include "constants.h"
 #include "jam.h"
 #include <time.h>
 
@@ -13,7 +14,7 @@
 struct profile_info
 {
     /* name of rule being called */
- char* name;
+ OBJECT * name;
     /* cumulative time spent in rule */
     clock_t cumulative;
     /* time spent in rule proper */
@@ -42,13 +43,13 @@
 };
 typedef struct profile_frame profile_frame;
 
-profile_frame * profile_init( char * rulename, profile_frame * frame );
-void profile_enter( char* rulename, profile_frame * frame );
+profile_frame * profile_init( OBJECT * rulename, profile_frame * frame );
+void profile_enter( OBJECT * rulename, profile_frame * frame );
 void profile_memory( long mem );
 void profile_exit( profile_frame * frame );
 void profile_dump();
 
-#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( #scope, &PROF_ ## scope )
+#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( constant_ ## scope, &PROF_ ## scope )
 #define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
 
 #endif

Modified: trunk/tools/build/v2/engine/execcmd.h
==============================================================================
--- trunk/tools/build/v2/engine/execcmd.h (original)
+++ trunk/tools/build/v2/engine/execcmd.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -28,12 +28,12 @@
 
 void exec_cmd
 (
- char * string,
- void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ const char * string,
+ void (* func)( void * closure, int status, timing_info *, const char *, const char * ),
     void * closure,
     LIST * shell,
- char * action,
- char * target
+ const char * action,
+ const char * target
 );
 
 int exec_wait();

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

Modified: trunk/tools/build/v2/engine/execunix.c
==============================================================================
--- trunk/tools/build/v2/engine/execunix.c (original)
+++ trunk/tools/build/v2/engine/execunix.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -88,7 +88,7 @@
     char *target; /* buffer to hold action and target invoked */
     char *command; /* buffer to hold command being invoked */
     char *buffer[2]; /* buffer to hold stdout and stderr, if any */
- void (*func)( void *closure, int status, timing_info*, char *, char * );
+ void (*func)( void *closure, int status, timing_info*, const char *, const char * );
     void *closure;
     time_t start_dt; /* start of command timestamp */
 } cmdtab[ MAXJOBS ] = {{0}};
@@ -110,12 +110,12 @@
 
 void exec_cmd
 (
- char * string,
- void (*func)( void *closure, int status, timing_info*, char *, char * ),
+ const char * string,
+ void (*func)( void *closure, int status, timing_info*, const char *, const char * ),
     void * closure,
     LIST * shell,
- char * action,
- char * target
+ const char * action,
+ const char * target
 )
 {
     static int initialized = 0;
@@ -123,7 +123,7 @@
     int err[2];
     int slot;
     int len;
- char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
+ const char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
 
     /* Find a slot in the running commands table for this one. */
     for ( slot = 0; slot < MAXJOBS; ++slot )
@@ -149,11 +149,11 @@
 
         for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
         {
- switch ( shell->string[0] )
+ switch ( object_str( shell->value )[0] )
             {
                 case '%': argv[ i ] = string; ++gotpercent; break;
                 case '!': argv[ i ] = jobno; break;
- default : argv[ i ] = shell->string;
+ default : argv[ i ] = object_str( shell->value );
             }
             if ( DEBUG_EXECCMD )
                 printf( "argv[%d] = '%s'\n", i, argv[ i ] );
@@ -242,7 +242,7 @@
             setrlimit( RLIMIT_CPU, &r_limit );
         }
         setpgid( pid,pid );
- execvp( argv[0], argv );
+ execvp( argv[0], (char * *)argv );
         perror( "execvp" );
         _exit( 127 );
     }

Modified: trunk/tools/build/v2/engine/execvms.c
==============================================================================
--- trunk/tools/build/v2/engine/execvms.c (original)
+++ trunk/tools/build/v2/engine/execvms.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -29,7 +29,7 @@
  *
  * If the command is multi-line, or longer than WRTLEN, we write the command
  * block to a temp file, splitting long lines (using "-" at the end of the line
- * to indicate contiuation), and then source that temp file. We use special
+ * to indicate continuation), and then source that temp file. We use special
  * logic to make sure we do not continue in the middle of a quoted string.
  *
  * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
@@ -48,19 +48,24 @@
 
 void exec_cmd
 (
- char * string,
- void (* func)( void * closure, int status, timing_info *, char *, char * ),
+ const char * string,
+ void (* func)( void * closure, int status, timing_info *, const char *, const char * ),
     void * closure,
     LIST * shell,
- char * rule_name,
- char * target
+ const char * rule_name,
+ const char * target
 )
 {
- char * s;
- char * e;
- cahr * p;
+ const char * s;
+ const char * e;
+ const char * p;
     int rstat = EXEC_CMD_OK;
     int status;
+ timing_info timing;
+
+ timing.system = 0;
+ timing.user = 0;
+ timing.start = time( 0 );
 
     /* See if string is more than one line discounting leading/trailing white
      * space.
@@ -89,7 +94,8 @@
         if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
         {
             printf( "can't open command file\n" );
- (*func)( closure, EXEC_CMD_FAIL );
+ timing.end = time( 0 );
+ (*func)( closure, EXEC_CMD_FAIL, &timing, "", "" );
             return;
         }
 
@@ -104,9 +110,9 @@
             /* For each chunk of a line that needs to be split. */
             while ( len > 0 )
             {
- char * q = string;
- char * qe = string + MIN( len, WRTLEN );
- char * qq = q;
+ const char * q = string;
+ const char * qe = string + MIN( len, WRTLEN );
+ const char * qq = q;
                 int quote = 0;
 
                 /* Look for matching "s. */
@@ -141,15 +147,25 @@
     {
         /* Execute single line command. Strip trailing newline before execing.
          */
- if ( e ) *e = 0;
+ if ( e )
+ {
+ s = strdup( s );
+ e = strchr( s, '\n' );
+ *(char *)e = 0;
+ }
         status = system( s ) & 0x07;
+ if ( e )
+ {
+ free( (void *)s );
+ }
     }
 
     /* Fail for error or fatal error. OK on OK, warning or info exit. */
     if ( ( status == 2 ) || ( status == 4 ) )
         rstat = EXEC_CMD_FAIL;
-
- (*func)( closure, rstat );
+
+ timing.end = time( 0 );
+ (*func)( closure, rstat, &timing, "", "" );
 }
 
 

Modified: trunk/tools/build/v2/engine/expand.c
==============================================================================
--- trunk/tools/build/v2/engine/expand.c (original)
+++ trunk/tools/build/v2/engine/expand.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,7 +9,7 @@
 # include "variable.h"
 # include "expand.h"
 # include "pathsys.h"
-# include "newstr.h"
+# include "object.h"
 # include <assert.h>
 # include <stdlib.h>
 # include <limits.h>
@@ -50,8 +50,8 @@
     PATHPART join; /* :J -- join list with char */
 } VAR_EDITS ;
 
-static void var_edit_parse( char * mods, VAR_EDITS * edits );
-static void var_edit_file ( char * in, string * out, VAR_EDITS * edits );
+static void var_edit_parse( const char * mods, VAR_EDITS * edits );
+static void var_edit_file ( const char * in, string * out, VAR_EDITS * edits );
 static void var_edit_shift( string * out, VAR_EDITS * edits );
 
 #define MAGIC_COLON '\001'
@@ -70,14 +70,14 @@
  * Returns a newly created list.
  */
 
-LIST * var_expand( LIST * l, char * in, char * end, LOL * lol, int cancopyin )
+LIST * var_expand( LIST * l, const char * in, const char * end, LOL * lol, OBJECT * cancopyin )
 {
     char out_buf[ MAXSYM ];
     string buf[ 1 ];
     string out1[ 1 ]; /* temporary buffer */
     size_t prefix_length;
     char * out;
- char * inp = in;
+ const char * inp = in;
     char * ov; /* for temp copy of variable in outbuf */
     int depth;
 
@@ -151,7 +151,7 @@
         {
             LIST * r;
             string_copy( buf, at_buf );
- r = list_new( l, newstr( buf->value ) );
+ r = list_new( l, object_new( buf->value ) );
             string_free( buf );
             BJAM_FREE( at_buf );
             return r;
@@ -167,17 +167,17 @@
     /* No variables expanded - just add copy of input string to list. */
 
     /* 'cancopyin' is an optimization: if the input was already a list item, we
- * can use copystr() to put it on the new list. Otherwise, we use the slower
- * newstr().
+ * can use obect_copy() to put it on the new list. Otherwise, we use the slower
+ * object_new().
      */
     if ( cancopyin )
- return list_new( l, copystr( inp ) );
+ return list_new( l, object_copy( cancopyin ) );
 
     {
         LIST * r;
         string_new( buf );
         string_append_range( buf, inp, end );
- r = list_new( l, newstr( buf->value ) );
+ r = list_new( l, object_new( buf->value ) );
         string_free( buf );
         return r;
     }
@@ -282,7 +282,7 @@
             /* Look for a : modifier in the variable name. Must copy into
              * varname so we can modify it.
              */
- string_copy( variable, vars->string );
+ string_copy( variable, object_str( vars->value ) );
             varname = variable->value;
 
             if ( ( colon = strchr( varname, MAGIC_COLON ) ) )
@@ -378,7 +378,11 @@
             }
 
             if ( !value )
- value = var_get( varname );
+ {
+ OBJECT * v = object_new( varname );
+ value = var_get( v );
+ object_free( v );
+ }
 
             /* Handle negitive indexes: part two. */
             {
@@ -416,7 +420,7 @@
 
             /* Empty w/ :E=default?. */
             if ( !value && colon && edits.empty.ptr )
- evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
+ evalue = value = list_new( L0, object_new( edits.empty.ptr ) );
 
             /* For each variable value. */
             string_new( out1 );
@@ -435,9 +439,9 @@
                 /* Apply : mods, if present */
 
                 if ( colon && edits.filemods )
- var_edit_file( value->string, out1, &edits );
+ var_edit_file( object_str( value->value ), out1, &edits );
                 else
- string_append( out1, value->string );
+ string_append( out1, object_str( value->value ) );
 
                 if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
                     var_edit_shift( out1, &edits );
@@ -461,7 +465,7 @@
                 /* If no remainder, append result to output chain. */
                 if ( in == end )
                 {
- l = list_new( l, newstr( buf->value ) );
+ l = list_new( l, object_new( buf->value ) );
                     continue;
                 }
 
@@ -473,8 +477,8 @@
                 for ( rem = remainder; rem; rem = list_next( rem ) )
                 {
                     string_truncate( buf, postfix_start );
- string_append( buf, rem->string );
- l = list_new( l, newstr( buf->value ) );
+ string_append( buf, object_str( rem->value ) );
+ l = list_new( l, object_new( buf->value ) );
                 }
             }
             string_free( out1 );
@@ -538,7 +542,7 @@
  * var_edit_file() below and path_build() obligingly follow this convention.
  */
 
-static void var_edit_parse( char * mods, VAR_EDITS * edits )
+static void var_edit_parse( const char * mods, VAR_EDITS * edits )
 {
     int havezeroed = 0;
     memset( (char *)edits, 0, sizeof( *edits ) );
@@ -619,7 +623,7 @@
  * var_edit_file() - copy input target name to output, modifying filename.
  */
 
-static void var_edit_file( char * in, string * out, VAR_EDITS * edits )
+static void var_edit_file( const char * in, string * out, VAR_EDITS * edits )
 {
     PATHNAME pathname;
 
@@ -680,11 +684,14 @@
     LOL lol[ 1 ];
     LIST * l;
     LIST * l2;
- LIST * expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
+ LIST * expected = list_new( list_new( L0, object_new( "axb" ) ), object_new( "ayb" ) );
     LIST * e2;
     char axyb[] = "a$(xy)b";
     char azb[] = "a$($(z))b";
     char path[] = "$(p:W)";
+ OBJECT * xy = object_new( "xy" );
+ OBJECT * z = object_new( "z" );
+ OBJECT * p = object_new( "p" );
 
 # ifdef OS_CYGWIN
     char cygpath[ 256 ];
@@ -694,20 +701,20 @@
 # endif
 
     lol_init(lol);
- var_set( "xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
- var_set( "z", list_new( L0, newstr( "xy" ) ), VAR_SET );
- var_set( "p", list_new( L0, newstr( cygpath ) ), VAR_SET );
+ var_set( xy, list_new( list_new( L0, object_new( "x" ) ), object_new( "y" ) ), VAR_SET );
+ var_set( z, list_new( L0, object_new( "xy" ) ), VAR_SET );
+ var_set( p, list_new( L0, object_new( cygpath ) ), VAR_SET );
 
     l = var_expand( 0, axyb, axyb + sizeof( axyb ) - 1, lol, 0 );
     for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
- assert( !strcmp( e2->string, l2->string ) );
+ assert( object_equal( e2->value, l2->value ) );
     assert( l2 == 0 );
     assert( e2 == 0 );
     list_free( l );
 
     l = var_expand( 0, azb, azb + sizeof( azb ) - 1, lol, 0 );
     for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) )
- assert( !strcmp( e2->string, l2->string ) );
+ assert( object_equal( e2->value, l2->value ) );
     assert( l2 == 0 );
     assert( e2 == 0 );
     list_free( l );
@@ -721,11 +728,14 @@
      * to C:\ as opposed to C:\cygwin. Since case of the drive letter will not
      * matter, we allow for both.
      */
- assert( !strcmp( l->string, "c:\\foo\\bar" ) ||
- !strcmp( l->string, "C:\\foo\\bar" ) );
+ assert( !strcmp( object_str( l->value ), "c:\\foo\\bar" ) ||
+ !strcmp( object_str( l->value ), "C:\\foo\\bar" ) );
 # else
- assert( !strcmp( l->string, cygpath ) );
+ assert( !strcmp( object_str( l->value), cygpath ) );
 # endif
+ object_free(xy);
+ object_free(z);
+ object_free(p);
     list_free( l );
     list_free( expected );
     lol_free( lol );

Modified: trunk/tools/build/v2/engine/expand.h
==============================================================================
--- trunk/tools/build/v2/engine/expand.h (original)
+++ trunk/tools/build/v2/engine/expand.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,7 +8,13 @@
  * expand.h - expand a buffer, given variable values
  */
 
+#ifndef EXPAND_SW20111118_H
+#define EXPAND_SW20111118_H
+
 #include "lists.h"
+#include "object.h"
 
-LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
+LIST * var_expand( LIST * l, const char * in, const char *end, LOL * lol, OBJECT * cancopyin );
 void var_expand_unit_test();
+
+#endif

Modified: trunk/tools/build/v2/engine/filent.c
==============================================================================
--- trunk/tools/build/v2/engine/filent.c (original)
+++ trunk/tools/build/v2/engine/filent.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -16,7 +16,7 @@
 # include "filesys.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 
 # ifdef OS_NT
 
@@ -57,7 +57,7 @@
  * file_dirscan() - scan a directory for files
  */
 
-void file_dirscan( char * dir, scanback func, void * closure )
+void file_dirscan( OBJECT * dir, scanback func, void * closure )
 {
     PROFILE_ENTER( FILE_DIRSCAN );
 
@@ -84,11 +84,11 @@
         int ret;
         struct _finddata_t finfo[ 1 ];
         LIST * files = L0;
- int d_length = strlen( d->name );
+ int d_length = strlen( object_str( d->name ) );
 
         memset( (char *)&f, '\0', sizeof( f ) );
 
- f.f_dir.ptr = d->name;
+ f.f_dir.ptr = object_str( d->name );
         f.f_dir.len = d_length;
 
         /* Now enter contents of directory */
@@ -103,8 +103,8 @@
              * its trailing path separator or otherwise we would not support the
              * Windows root folder specified without its drive letter, i.e. '\'.
              */
- char trailingChar = d->name[ d_length - 1 ] ;
- string_copy( filespec, d->name );
+ char trailingChar = object_str( d->name )[ d_length - 1 ] ;
+ string_copy( filespec, object_str( d->name ) );
             if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
                 string_append( filespec, "\\" );
             string_append( filespec, "*" );
@@ -132,7 +132,7 @@
             string_truncate( filename, 0 );
             path_build( &f, filename );
 
- files = list_new( files, newstr(filename->value) );
+ files = list_new( files, object_new(filename->value) );
             ff = file_info( filename->value );
             ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
             ff->is_dir = finfo->ff_attrib & FA_DIREC ? 1 : 0;
@@ -154,6 +154,7 @@
         string_new( filename );
         while ( !ret )
         {
+ OBJECT * filename_obj;
             file_info_t * ff = 0;
 
             f.f_base.ptr = finfo->name;
@@ -162,8 +163,9 @@
             string_truncate( filename, 0 );
             path_build( &f, filename, 0 );
 
- files = list_new( files, newstr( filename->value ) );
- ff = file_info( filename->value );
+ filename_obj = object_new( filename->value );
+ files = list_new( files, filename_obj );
+ ff = file_info( filename_obj );
             ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
             ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
             ff->size = finfo->size;
@@ -182,10 +184,12 @@
 
     /* Special case \ or d:\ : enter it */
     {
- unsigned long len = strlen(d->name);
- if ( len == 1 && d->name[0] == '\\' )
+ unsigned long len = strlen( object_str( d->name ) );
+ if ( len == 1 && object_str( d->name )[0] == '\\' )
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
- else if ( len == 3 && d->name[1] == ':' ) {
+ else if ( len == 3 && object_str( d->name )[1] == ':' ) {
+ char buf[4];
+ OBJECT * dir2;
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
             /* We've just entered 3-letter drive name spelling (with trailing
                slash), into the hash table. Now enter two-letter variant,
@@ -199,8 +203,11 @@
                There will be no trailing slash in $(p), but there will be one
                in $(p2). But, that seems rather fragile.
             */
- d->name[2] = 0;
- (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ strcpy( buf, object_str( d->name ) );
+ buf[2] = 0;
+ dir2 = object_new( buf );
+ (*func)( closure, dir2, 1 /* stat()'ed */, d->time );
+ object_free( dir2 );
         }
     }
 
@@ -210,7 +217,7 @@
         LIST * files = d->files;
         while ( files )
         {
- file_info_t * ff = file_info( files->string );
+ file_info_t * ff = file_info( files->value );
             (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
             files = list_next( files );
         }
@@ -219,14 +226,14 @@
     PROFILE_EXIT( FILE_DIRSCAN );
 }
 
-file_info_t * file_query( char * filename )
+file_info_t * file_query( OBJECT * filename )
 {
     file_info_t * ff = file_info( filename );
     if ( ! ff->time )
     {
         struct stat statbuf;
 
- if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ if ( stat( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
             return 0;
 
         ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -243,8 +250,8 @@
 
 int
 file_time(
- char *filename,
- time_t *time )
+ OBJECT * filename,
+ time_t * time )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
@@ -252,14 +259,14 @@
     return 0;
 }
 
-int file_is_file(char* filename)
+int file_is_file( OBJECT * filename )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
     return ff->is_file;
 }
 
-int file_mkdir(char *pathname)
+int file_mkdir( const char * pathname )
 {
     return _mkdir(pathname);
 }
@@ -290,9 +297,9 @@
 
 void
 file_archscan(
- char *archive,
- scanback func,
- void *closure )
+ const char * archive,
+ scanback func,
+ void * closure )
 {
     struct ar_hdr ar_hdr;
     char *string_table = 0;
@@ -320,9 +327,10 @@
     {
         long lar_date;
         long lar_size;
- char *name = 0;
- char *endname;
- char *c;
+ char * name = 0;
+ char * endname;
+ char * c;
+ OBJECT * member;
 
         sscanf( ar_hdr.ar_date, "%ld", &lar_date );
         sscanf( ar_hdr.ar_size, "%ld", &lar_size );
@@ -375,7 +383,9 @@
         name = c + 1;
 
         sprintf( buf, "%s(%.*s)", archive, endname - name, name );
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
 
         offset += SARHDR + lar_size;
         lseek( fd, offset, 0 );

Modified: trunk/tools/build/v2/engine/filesys.c
==============================================================================
--- trunk/tools/build/v2/engine/filesys.c (original)
+++ trunk/tools/build/v2/engine/filesys.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -1,7 +1,7 @@
 # include "jam.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 # include "filesys.h"
 # include "lists.h"
 
@@ -36,7 +36,7 @@
 static struct hash * filecache_hash = 0;
 static file_info_t filecache_finfo;
 
-file_info_t * file_info(char * filename)
+file_info_t * file_info( OBJECT * filename )
 {
     file_info_t *finfo = &filecache_finfo;
 
@@ -52,7 +52,7 @@
     if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) )
     {
         /* printf( "file_info: %s\n", filename ); */
- finfo->name = newstr( finfo->name );
+ finfo->name = object_copy( finfo->name );
     }
 
     return finfo;
@@ -66,7 +66,7 @@
        more than once */
     while ( files_to_remove )
     {
- remove( files_to_remove->string );
+ remove( object_str( files_to_remove->value ) );
         files_to_remove = list_pop_front( files_to_remove );
     }
 }
@@ -74,7 +74,7 @@
 static void free_file_info ( void * xfile, void * data )
 {
     file_info_t * file = (file_info_t *)xfile;
- freestr( file->name );
+ object_free( file->name );
     list_free( file->files );
 }
 
@@ -85,7 +85,7 @@
     hashdone( filecache_hash );
 }
 
-void file_remove_atexit( const char * path )
+void file_remove_atexit( OBJECT * path )
 {
- files_to_remove = list_new( files_to_remove, newstr((char*)path) );
+ files_to_remove = list_new( files_to_remove, object_copy( path ) );
 }

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

Modified: trunk/tools/build/v2/engine/fileunix.c
==============================================================================
--- trunk/tools/build/v2/engine/fileunix.c (original)
+++ trunk/tools/build/v2/engine/fileunix.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -15,7 +15,7 @@
 # include "filesys.h"
 # include "strings.h"
 # include "pathsys.h"
-# include "newstr.h"
+# include "object.h"
 # include <stdio.h>
 # include <sys/stat.h>
 
@@ -125,7 +125,7 @@
  * file_dirscan() - scan a directory for files.
  */
 
-void file_dirscan( char * dir, scanback func, void * closure )
+void file_dirscan( OBJECT * dir, scanback func, void * closure )
 {
     PROFILE_ENTER( FILE_DIRSCAN );
 
@@ -146,30 +146,32 @@
         DIR *dd;
         STRUCT_DIRENT *dirent;
         string filename[1];
+ const char * dirstr = object_str( dir );
 
         /* First enter directory itself */
 
         memset( (char *)&f, '\0', sizeof( f ) );
 
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
+ f.f_dir.ptr = dirstr;
+ f.f_dir.len = strlen( dirstr );
 
- dir = *dir ? dir : ".";
+ dirstr = *dirstr ? dirstr : ".";
 
         /* Now enter contents of directory. */
 
- if ( !( dd = opendir( dir ) ) )
+ if ( !( dd = opendir( dirstr ) ) )
         {
             PROFILE_EXIT( FILE_DIRSCAN );
             return;
         }
 
         if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
+ printf( "scan directory %s\n", dirstr );
 
         string_new( filename );
         while ( ( dirent = readdir( dd ) ) )
         {
+ OBJECT * filename_obj;
             # ifdef old_sinix
             /* Broken structure definition on sinix. */
             f.f_base.ptr = dirent->d_name - 2;
@@ -181,8 +183,9 @@
             string_truncate( filename, 0 );
             path_build( &f, filename, 0 );
 
- files = list_new( files, newstr(filename->value) );
- file_query( filename->value );
+ filename_obj = object_new( filename->value );
+ files = list_new( files, filename_obj );
+ file_query( filename_obj );
         }
         string_free( filename );
 
@@ -193,8 +196,7 @@
 
     /* Special case / : enter it */
     {
- unsigned long len = strlen(d->name);
- if ( ( len == 1 ) && ( d->name[0] == '/' ) )
+ if ( strcmp( object_str( d->name ), "/" ) == 0 )
             (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
     }
 
@@ -204,7 +206,7 @@
         LIST * files = d->files;
         while ( files )
         {
- file_info_t * ff = file_info( files->string );
+ file_info_t * ff = file_info( files->value );
             (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
             files = list_next( files );
         }
@@ -214,14 +216,14 @@
 }
 
 
-file_info_t * file_query( char * filename )
+file_info_t * file_query( OBJECT * filename )
 {
     file_info_t * ff = file_info( filename );
     if ( ! ff->time )
     {
         struct stat statbuf;
 
- if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ if ( stat( *object_str( filename ) ? object_str( filename ) : ".", &statbuf ) < 0 )
             return 0;
 
         ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
@@ -238,8 +240,8 @@
 
 int
 file_time(
- char *filename,
- time_t *time )
+ OBJECT * filename,
+ time_t * time )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
@@ -247,16 +249,16 @@
     return 0;
 }
 
-int file_is_file(char* filename)
+int file_is_file( OBJECT * filename )
 {
     file_info_t * ff = file_query( filename );
     if ( !ff ) return -1;
     return ff->is_file;
 }
 
-int file_mkdir(char* pathname)
+int file_mkdir( const char * pathname )
 {
- return mkdir(pathname, 0766);
+ return mkdir( pathname, 0766 );
 }
 
 /*
@@ -270,9 +272,9 @@
 
 void
 file_archscan(
- char *archive,
+ const char * archive,
     scanback func,
- void *closure )
+ void * closure )
 {
 # ifndef NO_AR
     struct ar_hdr ar_hdr;
@@ -312,6 +314,7 @@
         char * c;
         char * src;
         char * dest;
+ OBJECT * member;
 
         strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
 
@@ -356,14 +359,16 @@
 
         sprintf( buf, "%s(%s)", archive, lar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
 
         offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
         lseek( fd, offset, 0 );
     }
 
- if (string_table)
- BJAM_FREE(string_table);
+ if ( string_table )
+ BJAM_FREE( string_table );
 
     close( fd );
 
@@ -396,10 +401,11 @@
 
     while ( ( offset > 0 )
            && ( lseek( fd, offset, 0 ) >= 0 )
- && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) ) )
+ && ( read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= (int)sizeof( ar_hdr.hdr ) ) )
     {
         long lar_date;
         int lar_namlen;
+ OBJECT * member;
 
         sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
         sscanf( ar_hdr.hdr.ar_date , "%ld", &lar_date );
@@ -412,7 +418,9 @@
 
         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
     }
 }
 
@@ -446,6 +454,7 @@
     {
         long lar_date;
         int lar_namlen;
+ OBJECT * member;
 
         sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
         sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
@@ -458,19 +467,21 @@
 
         sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
 
- (*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
+ member = object_new( buf );
+ (*func)( closure, member, 1 /* time valid */, (time_t)lar_date );
+ object_free( member );
     }
 
 }
 
 #endif /* AR_HSZ_BIG */
 
-void file_archscan(char *archive, scanback func, void *closure)
+void file_archscan( const char * archive, scanback func, void *closure)
 {
     int fd;
     char fl_magic[SAIAMAG];
 
- if (( fd = open(archive, O_RDONLY, 0)) < 0)
+ if (( fd = open( archive, O_RDONLY, 0)) < 0)
         return;
 
     if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
@@ -480,16 +491,16 @@
         return;
     }
 
- if (strncmp(AIAMAG, fl_magic, SAIAMAG) == 0)
+ if ( strncmp( AIAMAG, fl_magic, SAIAMAG ) == 0 )
     {
         /* read small variant */
- file_archscan_small(fd, archive, func, closure);
+ file_archscan_small( fd, archive, func, closure );
     }
 #ifdef AR_HSZ_BIG
- else if (strncmp(AIAMAGBIG, fl_magic, SAIAMAG) == 0)
+ else if ( strncmp( AIAMAGBIG, fl_magic, SAIAMAG ) == 0 )
     {
         /* read big variant */
- file_archscan_big(fd, archive, func, closure);
+ file_archscan_big( fd, archive, func, closure );
     }
 #endif
 

Modified: trunk/tools/build/v2/engine/filevms.c
==============================================================================
--- trunk/tools/build/v2/engine/filevms.c (original)
+++ trunk/tools/build/v2/engine/filevms.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -37,7 +37,7 @@
 
 # include <rms.h>
 # include <iodef.h>
-# include <ssdef.h>
+# include <ssdef.h>*/
 # include <string.h>
 # include <stdlib.h>
 # include <stdio.h>
@@ -109,9 +109,9 @@
 
 void
 file_dirscan(
- char *dir,
+ OBJECT * dir,
     scanback func,
- void *closure )
+ void * closure )
 {
 
     struct FAB xfab;
@@ -126,8 +126,8 @@
 
     memset( (char *)&f, '\0', sizeof( f ) );
 
- f.f_root.ptr = dir;
- f.f_root.len = strlen( dir );
+ f.f_root.ptr = object_str( dir );
+ f.f_root.len = strlen( object_str( dir ) );
 
     /* get the input file specification
      */
@@ -145,8 +145,8 @@
     xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
     xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
     xfab.fab$l_fop = FAB$M_NAM;
- xfab.fab$l_fna = dir; /* address of file name */
- xfab.fab$b_fns = strlen( dir ); /* length of file name */
+ xfab.fab$l_fna = object_str( dir ); /* address of file name */
+ xfab.fab$b_fns = strlen( object_str( dir ) ); /* length of file name */
     xfab.fab$l_nam = &xnam; /* address of NAB block */
     xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
 
@@ -154,7 +154,7 @@
     status = sys$parse( &xfab );
 
     if ( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
+ printf( "scan directory %s\n", object_str( dir ) );
 
     if ( !( status & 1 ) )
     return;
@@ -163,81 +163,86 @@
 
     /* Add bogus directory for [000000] */
 
- if ( !strcmp( dir, "[000000]" ) )
+ if ( !strcmp( object_str( dir ), "[000000]" ) )
     {
- (*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
+ (*func)( closure, dir, 1 /* time valid */, 1 /* old but true */ );
     }
 
     /* Add bogus directory for [] */
 
- if ( !strcmp( dir, "[]" ) )
+ if ( !strcmp( object_str( dir ), "[]" ) )
     {
- (*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
- (*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
+ OBJECT * dir2 = object_new( "[-]" );
+ (*func)( closure, dir, 1 /* time valid */, 1 /* old but true */ );
+ (*func)( closure, dir2, 1 /* time valid */, 1 /* old but true */ );
+ object_free( dir2 );
     }
 
     string_new( filename2 );
     while ( (status = sys$search( &xfab )) & 1 )
     {
- char *s;
- time_t time;
-
- /* "I think that might work" - eml */
-
- sys$open( &xfab );
- sys$close( &xfab );
-
- file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
-
- filename[xnam.nam$b_rsl] = '\0';
-
- /* What we do with the name depends on the suffix: */
- /* .dir is a directory */
- /* .xxx is a file with a suffix */
- /* . is no suffix at all */
-
- if ( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
- {
- /* directory */
- sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
- f.f_dir.ptr = dirname;
- f.f_dir.len = strlen( dirname );
- f.f_base.ptr = 0;
- f.f_base.len = 0;
- f.f_suffix.ptr = 0;
- f.f_suffix.len = 0;
- }
- else
- {
- /* normal file with a suffix */
- f.f_dir.ptr = 0;
- f.f_dir.len = 0;
- f.f_base.ptr = xnam.nam$l_name;
- f.f_base.len = xnam.nam$b_name;
- f.f_suffix.ptr = xnam.nam$l_type;
- f.f_suffix.len = xnam.nam$b_type;
- }
+ char *s;
+ time_t time;
+ OBJECT * filename2_obj;
+
+ /* "I think that might work" - eml */
+
+ sys$open( &xfab );
+ sys$close( &xfab );
+
+ file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
+
+ filename[xnam.nam$b_rsl] = '\0';
+
+ /* What we do with the name depends on the suffix: */
+ /* .dir is a directory */
+ /* .xxx is a file with a suffix */
+ /* . is no suffix at all */
+
+ if ( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
+ {
+ /* directory */
+ sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
+ f.f_dir.ptr = dirname;
+ f.f_dir.len = strlen( dirname );
+ f.f_base.ptr = 0;
+ f.f_base.len = 0;
+ f.f_suffix.ptr = 0;
+ f.f_suffix.len = 0;
+ }
+ else
+ {
+ /* normal file with a suffix */
+ f.f_dir.ptr = 0;
+ f.f_dir.len = 0;
+ f.f_base.ptr = xnam.nam$l_name;
+ f.f_base.len = xnam.nam$b_name;
+ f.f_suffix.ptr = xnam.nam$l_type;
+ f.f_suffix.len = xnam.nam$b_type;
+ }
 
         string_truncate( filename2, 0 );
- path_build( &f, filename2, 0 );
-
- /*
- if ( DEBUG_SEARCH )
- printf("root '%s' base %.*s suf %.*s = %s\n",
- dir,
- xnam.nam$b_name, xnam.nam$l_name,
- xnam.nam$b_type, xnam.nam$l_type,
- filename2 );
- */
+ path_build( &f, filename2, 0 );
 
- (*func)( closure, filename2->value, 1 /* time valid */, time );
+ /*
+ if ( DEBUG_SEARCH )
+ printf("root '%s' base %.*s suf %.*s = %s\n",
+ object_str( dir ),
+ xnam.nam$b_name, xnam.nam$l_name,
+ xnam.nam$b_type, xnam.nam$l_type,
+ filename2->value );
+ */
+
+ filename2_obj = object_new( filename2->value );
+ (*func)( closure, filename2_obj, 1 /* time valid */, time );
+ object_free( filename2_obj );
     }
     string_free( filename2 );
 }
 
 int
 file_time(
- char *filename,
+ OBJECT *filename,
     time_t *time )
 {
     /* This should never be called, as all files are */
@@ -245,7 +250,7 @@
     return -1;
 }
 
-static char *VMS_archive = 0;
+static const char *VMS_archive = 0;
 static scanback VMS_func;
 static void *VMS_closure;
 static void *context;
@@ -268,6 +273,8 @@
     register int i;
     register char *p;
 
+ OBJECT * member;
+
     bufdsc.dsc$a_pointer = filename;
     bufdsc.dsc$w_length = sizeof( filename );
     status = lbr$set_module( &context, rfa, &bufdsc,
@@ -287,13 +294,15 @@
 
     sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
 
- (*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
+ member = object_new( buf );
+ (*VMS_func)( VMS_closure, member, 1 /* time valid */, (time_t)library_date );
+ object_free( member );
 
     return ( 1 );
 }
 
 
-void file_archscan( char * archive, scanback func, void * closure )
+void file_archscan( const char * archive, scanback func, void * closure )
 {
     static struct dsc$descriptor_s library =
           {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};

Modified: trunk/tools/build/v2/engine/frames.h
==============================================================================
--- trunk/tools/build/v2/engine/frames.h (original)
+++ trunk/tools/build/v2/engine/frames.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -7,6 +7,7 @@
 #define FRAMES_DWA20011021_H
 
 #include "lists.h"
+#include "object.h"
 #include "modules.h"
 
 typedef struct _PARSE PARSE;
@@ -14,13 +15,13 @@
 
 struct frame
 {
- FRAME * prev;
+ FRAME * prev;
     /* The nearest enclosing frame for which module->user_module is true. */
- FRAME * prev_user;
- LOL args[ 1 ];
- module_t * module;
- PARSE * procedure;
- char * rulename;
+ FRAME * prev_user;
+ LOL args[ 1 ];
+ module_t * module;
+ PARSE * procedure;
+ const char * rulename;
 };
 
 

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

Modified: trunk/tools/build/v2/engine/hash.c
==============================================================================
--- trunk/tools/build/v2/engine/hash.c (original)
+++ trunk/tools/build/v2/engine/hash.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -7,6 +7,7 @@
 # include "jam.h"
 # include "hash.h"
 # include "compile.h"
+# include "object.h"
 # include <assert.h>
 
 /*
@@ -29,14 +30,11 @@
 #define HASH_DEBUG_PROFILE 1
 /* */
 
-char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
-
 /* Header attached to all data items entered into a hash table. */
 
 struct hashhdr
 {
     struct item * next;
- unsigned int keyval; /* for quick comparisons */
 };
 
 /* This structure overlays the one handed to hashenter(). Its actual size is
@@ -45,7 +43,7 @@
 
 struct hashdata
 {
- char * key;
+ OBJECT * key;
     /* rest of user data */
 };
 
@@ -89,7 +87,7 @@
         } lists[ MAX_LISTS ];
     } items;
 
- char * name; /* just for hashstats() */
+ const char * name; /* just for hashstats() */
 };
 
 static void hashrehash( struct hash *hp );
@@ -100,39 +98,9 @@
 static void hash_mem_finalizer(char * key, struct hash * hp);
 #endif
 
-static unsigned int jenkins_one_at_a_time_hash(const unsigned char *key)
+static unsigned int hash_keyval( OBJECT * key )
 {
- unsigned int hash = 0;
-
- while ( *key )
- {
- hash += *key++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash;
-}
-
-/*
-static unsigned int knuth_hash(const unsigned char *key)
-{
- unsigned int keyval = *key;
- while ( *key )
- keyval = keyval * 2147059363 + *key++;
- return keyval;
-}
-*/
-
-static unsigned int hash_keyval( const char * key_ )
-{
- /*
- return knuth_hash((const unsigned char *)key_);
- */
- return jenkins_one_at_a_time_hash((const unsigned char *)key_);
+ return object_hash( key );
 }
 
 #define hash_bucket(hp,keyval) ((hp)->tab.base + ( (keyval) % (hp)->tab.nel ))
@@ -145,7 +113,7 @@
 static ITEM * hash_search(
     struct hash *hp,
     unsigned int keyval,
- const char * keydata,
+ OBJECT * keydata,
     ITEM * * previous )
 {
     ITEM * i = *hash_bucket(hp,keyval);
@@ -153,8 +121,7 @@
 
     for ( ; i; i = i->hdr.next )
     {
- if ( ( keyval == i->hdr.keyval ) &&
- !strcmp( i->data.key, keydata ) )
+ if ( object_equal( i->data.key, keydata ) )
         {
             if (previous)
             {
@@ -213,7 +180,7 @@
     int enter )
 {
     register ITEM *i;
- char *b = (*data)->key;
+ OBJECT *b = (*data)->key;
     unsigned int keyval = hash_keyval(b);
 
     #ifdef HASH_DEBUG_PROFILE
@@ -262,7 +229,6 @@
         }
         hp->items.more--;
         memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
- i->hdr.keyval = keyval;
         i->hdr.next = *base;
         *base = i;
         *data = &i->data;
@@ -312,7 +278,7 @@
         for ( ; nel--; next += hp->items.size )
         {
             register ITEM *i = (ITEM *)next;
- ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
+ ITEM **ip = hp->tab.base + object_hash( i->data.key ) % hp->tab.nel;
             /* code currently assumes rehashing only when there are no free items */
             assert( i->data.key != 0 );
 
@@ -352,7 +318,7 @@
 struct hash *
 hashinit(
     int datalen,
- char *name )
+ const char *name )
 {
     struct hash *hp = (struct hash *)hash_mem_alloc( datalen, sizeof( *hp ) );
 
@@ -376,7 +342,7 @@
  */
 
 void
-hashdone( struct hash *hp )
+hashdone( struct hash * hp )
 {
     int i;
 
@@ -393,7 +359,7 @@
     hash_mem_free( hp->items.datalen, (char *)hp );
 }
 
-char *
+const char *
 hashname ( struct hash * hp )
 {
     return hp->name;
@@ -424,7 +390,7 @@
 }
 
 #ifdef OPT_BOEHM_GC
-static void hash_mem_finalizer(char * key, struct hash * hp)
+static void hash_mem_finalizer(OBJECT * key, struct hash * hp)
 {
     HASHDATA d;
     d.key = key;
@@ -441,7 +407,7 @@
     int nel = hp->tab.nel;
     int count = 0;
     int sets = 0;
- int run = ( tab[ nel - 1 ] != (ITEM *)0 );
+ int run = tab && ( tab[ nel - 1 ] != (ITEM *)0 );
     int i;
     int here;
 

Modified: trunk/tools/build/v2/engine/hash.h
==============================================================================
--- trunk/tools/build/v2/engine/hash.h (original)
+++ trunk/tools/build/v2/engine/hash.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -13,12 +13,12 @@
 
 typedef struct hashdata HASHDATA;
 
-struct hash * hashinit ( int datalen, char * name );
+struct hash * hashinit ( int datalen, const char * name );
 int hashitem ( struct hash * hp, HASHDATA * * data, int enter );
 void hashdone ( struct hash * hp );
 void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data );
-int hash_free ( struct hash * hp, HASHDATA * data);
-char * hashname ( struct hash * hp );
+int hash_free ( struct hash * hp, HASHDATA * data );
+const char * hashname ( struct hash * hp );
 
 #define hashenter( hp, data ) ( !hashitem( hp, data, !0 ) )
 #define hashcheck( hp, data ) hashitem( hp, data, 0 )

Modified: trunk/tools/build/v2/engine/hcache.c
==============================================================================
--- trunk/tools/build/v2/engine/hcache.c (original)
+++ trunk/tools/build/v2/engine/hcache.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,7 +8,7 @@
 # include "rules.h"
 # include "regexp.h"
 # include "headers.h"
-# include "newstr.h"
+# include "object.h"
 # include "hash.h"
 # include "hcache.h"
 # include "variable.h"
@@ -43,7 +43,7 @@
 
 struct hcachedata
 {
- char * boundname;
+ OBJECT * boundname;
     time_t time;
     LIST * includes;
     LIST * hdrscan; /* the HDRSCAN value for this target */
@@ -70,31 +70,33 @@
  * the result so the user can not change the cache file during header scanning.
  */
 
-static char * cache_name( void )
+static const char * cache_name( void )
 {
- static char * name = 0;
+ static OBJECT * name = 0;
     if ( !name )
     {
- LIST * hcachevar = var_get( "HCACHEFILE" );
+ OBJECT * hcachename = object_new( "HCACHEFILE" );
+ LIST * hcachevar = var_get( hcachename );
+ object_free( hcachename );
 
         if ( hcachevar )
         {
- TARGET * t = bindtarget( hcachevar->string );
+ TARGET * t = bindtarget( hcachevar->value );
 
             pushsettings( t->settings );
             /* Do not expect the cache file to be generated, so pass 0 as the
              * third argument to search. Expect the location to be specified via
              * LOCATE, so pass 0 as the fourth arugment.
              */
- freestr( t->boundname );
+ object_free( t->boundname );
             t->boundname = search( t->name, &t->time, 0, 0 );
             popsettings( t->settings );
 
             if ( hcachevar )
- name = copystr( t->boundname );
+ name = object_copy( t->boundname );
         }
     }
- return name;
+ return name ? object_str( name ) : 0;
 }
 
 
@@ -106,10 +108,12 @@
 static int cache_maxage( void )
 {
     int age = 100;
- LIST * var = var_get( "HCACHEMAXAGE" );
+ OBJECT * hcacheage = object_new( "HCACHEMAXAGE" );
+ LIST * var = var_get( hcacheage );
+ object_free( hcacheage );
     if ( var )
     {
- age = atoi( var->string );
+ age = atoi( object_str( var->value ) );
         if ( age < 0 )
             age = 0;
     }
@@ -119,10 +123,10 @@
 
 /*
  * Read a netstring. The caveat is that the string can not contain ASCII 0. The
- * returned value is as returned by newstr(), so it need not be freed.
+ * returned value is as returned by object_new().
  */
 
-char * read_netstring( FILE * f )
+OBJECT * read_netstring( FILE * f )
 {
     unsigned long len;
     static char * buf = NULL;
@@ -155,7 +159,7 @@
         return NULL;
 
     buf[ len ] = 0;
- return newstr( buf );
+ return object_new( buf );
 }
 
 
@@ -176,9 +180,9 @@
     HCACHEDATA cachedata;
     HCACHEDATA * c;
     FILE * f;
- char * version;
+ OBJECT * version;
     int header_count = 0;
- char * hcachename;
+ const char * hcachename;
 
     if ( hcachehash )
         return;
@@ -192,7 +196,7 @@
         return;
 
     version = read_netstring( f );
- if ( !version || strcmp( version, CACHE_FILE_VERSION ) )
+ if ( !version || strcmp( object_str( version ), CACHE_FILE_VERSION ) )
     {
         fclose( f );
         return;
@@ -200,14 +204,14 @@
 
     while ( 1 )
     {
- char * record_type;
- char * time_str;
- char * age_str;
- char * includes_count_str;
- char * hdrscan_count_str;
- int i;
- int count;
- LIST * l;
+ OBJECT * record_type;
+ OBJECT * time_str;
+ OBJECT * age_str;
+ OBJECT * includes_count_str;
+ OBJECT * hdrscan_count_str;
+ int i;
+ int count;
+ LIST * l;
 
         record_type = read_netstring( f );
         if ( !record_type )
@@ -215,12 +219,12 @@
             fprintf( stderr, "invalid %s\n", hcachename );
             goto bail;
         }
- if ( !strcmp( record_type, CACHE_RECORD_END ) )
+ if ( !strcmp( object_str( record_type ), CACHE_RECORD_END ) )
             break;
- if ( strcmp( record_type, CACHE_RECORD_HEADER ) )
+ if ( strcmp( object_str( record_type ), CACHE_RECORD_HEADER ) )
         {
             fprintf( stderr, "invalid %s with record separator <%s>\n",
- hcachename, record_type ? record_type : "<null>" );
+ hcachename, record_type ? object_str( record_type ) : "<null>" );
             goto bail;
         }
 
@@ -237,13 +241,13 @@
             goto bail;
         }
 
- c->time = atoi( time_str );
- c->age = atoi( age_str ) + 1;
+ c->time = atoi( object_str( time_str ) );
+ c->age = atoi( object_str( age_str ) ) + 1;
 
- count = atoi( includes_count_str );
+ count = atoi( object_str( includes_count_str ) );
         for ( l = 0, i = 0; i < count; ++i )
         {
- char * s = read_netstring( f );
+ OBJECT * s = read_netstring( f );
             if ( !s )
             {
                 fprintf( stderr, "invalid %s\n", hcachename );
@@ -261,10 +265,10 @@
             goto bail;
         }
 
- count = atoi( hdrscan_count_str );
+ count = atoi( object_str( hdrscan_count_str ) );
         for ( l = 0, i = 0; i < count; ++i )
         {
- char * s = read_netstring( f );
+ OBJECT * s = read_netstring( f );
             if ( !s )
             {
                 fprintf( stderr, "invalid %s\n", hcachename );
@@ -300,7 +304,7 @@
     FILE * f;
     HCACHEDATA * c;
     int header_count = 0;
- char * hcachename;
+ const char * hcachename;
     int maxage;
 
     if ( !hcachehash )
@@ -337,15 +341,15 @@
         sprintf( age_str, "%lu", (long unsigned) c->age );
 
         write_netstring( f, CACHE_RECORD_HEADER );
- write_netstring( f, c->boundname );
+ write_netstring( f, object_str( c->boundname ) );
         write_netstring( f, time_str );
         write_netstring( f, age_str );
         write_netstring( f, includes_count_str );
         for ( l = c->includes; l; l = list_next( l ) )
- write_netstring( f, l->string );
+ write_netstring( f, object_str( l->value ) );
         write_netstring( f, hdrscan_count_str );
         for ( l = c->hdrscan; l; l = list_next( l ) )
- write_netstring( f, l->string );
+ write_netstring( f, object_str( l->value ) );
         fputs( "\n", f );
         ++header_count;
     }
@@ -362,11 +366,13 @@
     {
         list_free( c->includes );
         list_free( c->hdrscan );
- freestr( c->boundname );
+ object_free( c->boundname );
     }
 
     hcachelist = 0;
- hashdone( hcachehash );
+ if ( hcachehash )
+ hashdone( hcachehash );
+ hcachehash = 0;
 }
 
 
@@ -387,7 +393,7 @@
     {
         LIST *l1 = hdrscan, *l2 = c->hdrscan;
         while (l1 && l2) {
- if (l1->string != l2->string) {
+ if (l1->value != l2->value) {
             l1 = NULL;
         } else {
             l1 = list_next(l1);
@@ -397,9 +403,9 @@
         if (l1 || l2) {
         if (DEBUG_HEADER)
             printf("HDRSCAN out of date in cache for %s\n",
- t->boundname);
+ object_str( t->boundname ));
 
- printf("HDRSCAN out of date for %s\n", t->boundname);
+ printf("HDRSCAN out of date for %s\n", object_str( t->boundname ) );
         printf(" real : ");
         list_print(hdrscan);
         printf("\n cached: ");
@@ -412,7 +418,7 @@
         c->hdrscan = 0;
         } else {
         if (DEBUG_HEADER)
- printf ("using header cache for %s\n", t->boundname);
+ printf ("using header cache for %s\n", object_str( t->boundname ) );
         c->age = 0;
         ++hits;
         l = list_copy (0, c->includes);
@@ -420,7 +426,7 @@
         }
     } else {
         if (DEBUG_HEADER)
- printf ("header cache out of date for %s\n", t->boundname);
+ printf ("header cache out of date for %s\n", object_str( t->boundname ) );
         list_free (c->includes);
         list_free(c->hdrscan);
         c->includes = 0;
@@ -428,7 +434,7 @@
     }
     } else {
     if (hashenter (hcachehash, (HASHDATA **)&c)) {
- c->boundname = newstr (c->boundname);
+ c->boundname = object_copy( c->boundname );
         c->next = hcachelist;
         hcachelist = c;
     }

Modified: trunk/tools/build/v2/engine/hcache.h
==============================================================================
--- trunk/tools/build/v2/engine/hcache.h (original)
+++ trunk/tools/build/v2/engine/hcache.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -11,8 +11,8 @@
 # include "regexp.h"
 # include "lists.h"
 
-void hcache_init(void);
-void hcache_done(void);
-LIST *hcache(TARGET *t, int rec, regexp *re[], LIST *hdrscan);
+void hcache_init( void );
+void hcache_done( void );
+LIST * hcache( TARGET *t, int rec, regexp * re[], LIST * hdrscan );
 
 #endif

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

Modified: trunk/tools/build/v2/engine/hdrmacro.h
==============================================================================
--- trunk/tools/build/v2/engine/hdrmacro.h (original)
+++ trunk/tools/build/v2/engine/hdrmacro.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,6 +9,11 @@
  * #define MACRO "filename" definitions
  */
 
+#ifndef HDRMACRO_SW20111118_H
+#define HDRMACRO_SW20111118_H
+
 void macro_headers( TARGET *t );
 
-char* macro_header_get( const char* macro_name );
+OBJECT * macro_header_get( OBJECT * macro_name );
+
+#endif

Modified: trunk/tools/build/v2/engine/headers.c
==============================================================================
--- trunk/tools/build/v2/engine/headers.c (original)
+++ trunk/tools/build/v2/engine/headers.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -18,7 +18,7 @@
 # include "regexp.h"
 # include "headers.h"
 # include "hdrmacro.h"
-# include "newstr.h"
+# include "object.h"
 
 #ifdef OPT_HEADER_CACHE_EXT
 # include "hcache.h"
@@ -46,7 +46,7 @@
  */
 
 #ifndef OPT_HEADER_CACHE_EXT
-static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
+static LIST * headers1( LIST * l, OBJECT * file, int rec, regexp * re[]);
 #endif
 
 /*
@@ -65,18 +65,28 @@
         #endif
     regexp * re[ MAXINC ];
     int rec = 0;
+ OBJECT * hdrscan_str;
+ OBJECT * hdrrule_str;
 
- if ( !( hdrscan = var_get( "HDRSCAN" ) ) ||
- !( hdrrule = var_get( "HDRRULE" ) ) )
+ hdrscan_str = object_new( "HDRSCAN" );
+ hdrscan = var_get( hdrscan_str );
+ object_free( hdrscan_str );
+ if ( !hdrscan )
+ return;
+
+ hdrrule_str = object_new( "HDRRULE" );
+ hdrrule = var_get( hdrrule_str );
+ object_free( hdrrule_str );
+ if ( !hdrrule )
         return;
 
     if ( DEBUG_HEADER )
- printf( "header scan %s\n", t->name );
+ printf( "header scan %s\n", object_str( t->name ) );
 
     /* Compile all regular expressions in HDRSCAN */
     while ( ( rec < MAXINC ) && hdrscan )
     {
- re[ rec++ ] = regex_compile( hdrscan->string );
+ re[ rec++ ] = regex_compile( hdrscan->value );
         hdrscan = list_next( hdrscan );
     }
 
@@ -85,7 +95,7 @@
     {
         FRAME frame[1];
         frame_init( frame );
- lol_add( frame->args, list_new( L0, copystr( t->name ) ) );
+ lol_add( frame->args, list_new( L0, object_copy( t->name ) ) );
 #ifdef OPT_HEADER_CACHE_EXT
         lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
 #else
@@ -96,9 +106,9 @@
         {
             /* The third argument to HDRRULE is the bound name of
              * $(<) */
- lol_add( frame->args, list_new( L0, copystr( t->boundname ) ) );
+ lol_add( frame->args, list_new( L0, object_copy( t->boundname ) ) );
 
- list_free( evaluate_rule( hdrrule->string, frame ) );
+ list_free( evaluate_rule( hdrrule->value, frame ) );
         }
 
         /* Clean up. */
@@ -118,7 +128,7 @@
 #endif
 headers1(
     LIST * l,
- char * file,
+ OBJECT * file,
     int rec,
     regexp * re[] )
 {
@@ -137,10 +147,14 @@
     /* the following regexp is used to detect cases where a */
     /* file is included through a line line "#include MACRO" */
     if ( re_macros == 0 )
- re_macros = regex_compile(
+ {
+ OBJECT * re_str = object_new(
             "^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
+ re_macros = regex_compile( re_str );
+ object_free( re_str );
+ }
 
- if ( !( f = fopen( file, "r" ) ) )
+ if ( !( f = fopen( object_str( file ), "r" ) ) )
         return l;
 
     while ( fgets( buf, sizeof( buf ), f ) )
@@ -158,30 +172,33 @@
         for ( i = 0; i < rec; ++i )
             if ( regexec( re[i], buf ) && re[i]->startp[1] )
             {
- re[i]->endp[1][0] = '\0';
+ ((char *)re[i]->endp[1])[0] = '\0';
 
                 if ( DEBUG_HEADER )
                     printf( "header found: %s\n", re[i]->startp[1] );
 
- l = list_new( l, newstr( re[i]->startp[1] ) );
+ l = list_new( l, object_new( re[i]->startp[1] ) );
             }
 
         /* special treatment for #include MACRO */
         if ( regexec( re_macros, buf ) && re_macros->startp[1] )
         {
- char* header_filename;
+ OBJECT * header_filename;
+ OBJECT * macro_name;
 
- re_macros->endp[1][0] = '\0';
+ ((char *)re_macros->endp[1])[0] = '\0';
 
             if ( DEBUG_HEADER )
                 printf( "macro header found: %s", re_macros->startp[1] );
 
- header_filename = macro_header_get( re_macros->startp[1] );
+ macro_name = object_new( re_macros->startp[1] );
+ header_filename = macro_header_get( macro_name );
+ object_free( macro_name );
             if ( header_filename )
             {
                 if ( DEBUG_HEADER )
- printf( " resolved to '%s'\n", header_filename );
- l = list_new( l, newstr( header_filename ) );
+ printf( " resolved to '%s'\n", object_str( header_filename ) );
+ l = list_new( l, object_copy( header_filename ) );
             }
             else
             {
@@ -197,7 +214,7 @@
 }
 
 
-void regerror( char * s )
+void regerror( const char * s )
 {
     printf( "re error %s\n", s );
 }

Modified: trunk/tools/build/v2/engine/headers.h
==============================================================================
--- trunk/tools/build/v2/engine/headers.h (original)
+++ trunk/tools/build/v2/engine/headers.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,9 +8,18 @@
  * headers.h - handle #includes in source files
  */
 
-void headers( TARGET *t );
+#ifndef HEADERS_SW20111118_H
+#define HEADERS_SW20111118_H
+
+#include "object.h"
+#include "rules.h"
+#include "regexp.h"
+
+void headers( TARGET * t );
 
 #ifdef OPT_HEADER_CACHE_EXT
 struct regexp;
-LIST *headers1( LIST *l, char *file, int rec, struct regexp *re[] );
+LIST * headers1( LIST *l, OBJECT * file, int rec, struct regexp *re[] );
+#endif
+
 #endif

Modified: trunk/tools/build/v2/engine/jam.c
==============================================================================
--- trunk/tools/build/v2/engine/jam.c (original)
+++ trunk/tools/build/v2/engine/jam.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -54,18 +54,18 @@
  * are layered thus:
  *
  * variable|expand
- * / | | |
- * / | | |
- * / | | |
- * lists | | pathsys
- * \ | |
- * \ | |
- * \ | |
- * newstr |
+ * / | |
+ * / | |
+ * / | |
+ * lists | pathsys
+ * \ |
+ * \ hash
+ * \ |
+ * \ |
  * \ |
  * \ |
  * \ |
- * hash
+ * object
  *
  * Roughly, the modules are:
  *
@@ -84,7 +84,7 @@
  * lists.c - maintain lists of strings
  * make.c - bring a target up to date, once rules are in place
  * make1.c - execute command to bring targets up to date
- * newstr.c - string manipulation routines
+ * object.c - string manipulation routines
  * option.c - command line option processing
  * parse.c - make and destroy parse trees as driven by the parser
  * path*.c - manipulate file names on *
@@ -115,7 +115,7 @@
 #include "compile.h"
 #include "builtins.h"
 #include "rules.h"
-#include "newstr.h"
+#include "object.h"
 #include "scan.h"
 #include "timestamp.h"
 #include "make.h"
@@ -123,6 +123,10 @@
 #include "expand.h"
 #include "filesys.h"
 #include "output.h"
+#include "search.h"
+#include "class.h"
+#include "execcmd.h"
+#include "constants.h"
 
 /* Macintosh is "special" */
 #ifdef OS_MAC
@@ -213,7 +217,7 @@
 
 void regex_done();
 
-char *saved_argv0;
+const char *saved_argv0;
 
 int main( int argc, char * * argv, char * * arg_environ )
 {
@@ -225,6 +229,8 @@
     int arg_c = argc;
     char * * arg_v = argv;
     char const * progname = argv[0];
+ OBJECT * varname;
+ module_t * environ_module;
 
     saved_argv0 = argv[0];
 
@@ -340,6 +346,8 @@
             globs.debug[i--] = 1;
     }
 
+ constants_init();
+
     {
         PROFILE_ENTER( MAIN );
 
@@ -379,15 +387,19 @@
 #endif
 
         /* Set JAMDATE. */
- var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
+ varname = object_new( "JAMDATE" );
+ var_set( varname, list_new( L0, outf_time(time(0)) ), VAR_SET );
+ object_free( varname );
 
         /* Set JAM_VERSION. */
- var_set( "JAM_VERSION",
+ varname = object_new( "JAM_VERSION" );
+ var_set( varname,
                  list_new( list_new( list_new( L0,
- newstr( VERSION_MAJOR_SYM ) ),
- newstr( VERSION_MINOR_SYM ) ),
- newstr( VERSION_PATCH_SYM ) ),
+ object_new( VERSION_MAJOR_SYM ) ),
+ object_new( VERSION_MINOR_SYM ) ),
+ object_new( VERSION_PATCH_SYM ) ),
                    VAR_SET );
+ object_free( varname );
 
         /* Set JAMUNAME. */
 #ifdef unix
@@ -396,17 +408,19 @@
 
             if ( uname( &u ) >= 0 )
             {
- var_set( "JAMUNAME",
+ varname = object_new( "JAMUNAME" );
+ var_set( varname,
                          list_new(
                              list_new(
                                  list_new(
                                      list_new(
                                          list_new( L0,
- newstr( u.sysname ) ),
- newstr( u.nodename ) ),
- newstr( u.release ) ),
- newstr( u.version ) ),
- newstr( u.machine ) ), VAR_SET );
+ object_new( u.sysname ) ),
+ object_new( u.nodename ) ),
+ object_new( u.release ) ),
+ object_new( u.version ) ),
+ object_new( u.machine ) ), VAR_SET );
+ object_free( varname );
             }
         }
 #endif /* unix */
@@ -418,10 +432,13 @@
          */
         var_defines( use_environ, 1 );
 
+ varname = object_new( ".ENVIRON" );
+ environ_module = bindmodule( varname );
+ object_free( varname );
         /* Then into .ENVIRON, without splitting. */
- enter_module( bindmodule(".ENVIRON") );
+ enter_module( environ_module );
         var_defines( use_environ, 0 );
- exit_module( bindmodule(".ENVIRON") );
+ exit_module( environ_module );
 
         /*
          * Jam defined variables OS & OSPLAT. We load them after environment, so
@@ -437,15 +454,19 @@
             symv[ 0 ] = s;
             symv[ 1 ] = 0;
             var_defines( symv, 1 );
- enter_module( bindmodule(".ENVIRON") );
+ enter_module( environ_module );
             var_defines( symv, 0 );
- exit_module( bindmodule(".ENVIRON") );
+ exit_module( environ_module );
         }
 
         /* Set the ARGV to reflect the complete list of arguments of invocation.
          */
+ varname = object_new( "ARGV" );
         for ( n = 0; n < arg_c; ++n )
- var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
+ {
+ var_set( varname, list_new( L0, object_new( arg_v[n] ) ), VAR_APPEND );
+ }
+ object_free( varname );
 
         /* Initialize built-in rules. */
         load_builtins();
@@ -461,29 +482,47 @@
             }
             else
             {
- mark_target_for_updating( arg_v[ n ] );
+ OBJECT * target = object_new( arg_v[ n ] );
+ mark_target_for_updating( target );
+ object_free( target );
             }
         }
 
         if (!targets_to_update())
- mark_target_for_updating("all");
+ {
+ OBJECT * target = object_new( "all" );
+ mark_target_for_updating( target );
+ object_free( target );
+ }
 
         /* Parse ruleset. */
         {
             FRAME frame[ 1 ];
             frame_init( frame );
             for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
- parse_file( s, frame );
+ {
+ OBJECT * filename = object_new( s );
+ parse_file( filename, frame );
+ object_free( filename );
+ }
 
             if ( !n )
- parse_file( "+", frame );
+ {
+ OBJECT * filename = object_new( "+" );
+ parse_file( filename, frame );
+ object_free( filename );
+ }
         }
 
         status = yyanyerrors();
 
         /* Manually touch -t targets. */
         for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
- touch_target( s );
+ {
+ OBJECT * target = object_new( s );
+ touch_target( target );
+ object_free( target );
+ }
 
         /* If an output file is specified, set globs.cmdout to that. */
         if ( ( s = getoptval( optv, 'o', 0 ) ) )
@@ -500,13 +539,15 @@
            options. */
         {
             LIST *p = L0;
- p = var_get ("PARALLELISM");
- if (p)
+ varname = object_new( "PARALLELISM" );
+ p = var_get ( varname );
+ object_free( varname );
+ if ( p )
             {
- int j = atoi (p->string);
- if (j == -1)
+ int j = atoi( object_str( p->value ) );
+ if ( j == -1 )
                 {
- printf( "Invalid value of PARALLELISM: %s\n", p->string);
+ printf( "Invalid value of PARALLELISM: %s\n", object_str( p->value ) );
                 }
                 else
                 {
@@ -518,11 +559,13 @@
         /* KEEP_GOING overrides -q option. */
         {
             LIST *p = L0;
- p = var_get ("KEEP_GOING");
- if (p)
+ varname = object_new( "KEEP_GOING" );
+ p = var_get( varname );
+ object_free(varname);
+ if ( p )
             {
- int v = atoi (p->string);
- if (v == 0)
+ int v = atoi( object_str( p->value ) );
+ if ( v == 0 )
                     globs.quitquick = 1;
                 else
                     globs.quitquick = 0;
@@ -537,11 +580,11 @@
             if (targets)
             {
                 int targets_count = list_length( targets );
- const char * * targets2 = (const char * *)
- BJAM_MALLOC( targets_count * sizeof( char * ) );
+ OBJECT * * targets2 = (OBJECT * *)
+ BJAM_MALLOC( targets_count * sizeof( OBJECT * ) );
                 int n = 0;
                 for ( ; targets; targets = list_next( targets ) )
- targets2[ n++ ] = targets->string;
+ targets2[ n++ ] = targets->value;
                 status |= make( targets_count, targets2, anyhow );
                 BJAM_FREE( (void *)targets2 );
             }
@@ -576,8 +619,10 @@
     modules_done();
     regex_done();
     exec_done();
+ pwd_done();
     list_done();
- str_done();
+ constants_done();
+ object_done();
 
     /* Close cmdout. */
     if ( globs.cmdout )
@@ -594,7 +639,7 @@
 
 #if defined(_WIN32)
 #include <windows.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     DWORD ret = GetModuleFileName(NULL, buf, sizeof(buf));
     if (ret == 0 || ret == sizeof(buf)) return NULL;
@@ -602,7 +647,7 @@
 }
 #elif defined(__APPLE__) /* Not tested */
 #include <mach-o/dyld.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     uint32_t size = sizeof(buf);
     int ret = _NSGetExecutablePath(buf, &size);
@@ -612,12 +657,12 @@
 #elif defined(sun) || defined(__sun) /* Not tested */
 #include <stdlib.h>
 
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     return strdup(getexecname());
 }
 #elif defined(__FreeBSD__)
 #include <sys/sysctl.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     int mib[4];
     mib[0] = CTL_KERN;
     mib[1] = KERN_PROC;
@@ -631,16 +676,16 @@
 }
 #elif defined(__linux__)
 #include <unistd.h>
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     char buf[1024];
     ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf));
     if (ret == 0 || ret == sizeof(buf)) return NULL;
     return strndup(buf, ret);
 }
 #else
-char *executable_path(char *argv0) {
+char *executable_path(const char *argv0) {
     /* If argv0 is absolute path, assume it's the right absolute path. */
- if (argv0[0] == "/")
+ if (argv0[0] == '/')
         return strdup(argv0);
     return NULL;
 }

Modified: trunk/tools/build/v2/engine/jamgram.c
==============================================================================
--- trunk/tools/build/v2/engine/jamgram.c (original)
+++ trunk/tools/build/v2/engine/jamgram.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -75,14 +75,14 @@
 #include "parse.h"
 #include "scan.h"
 #include "compile.h"
-#include "newstr.h"
+#include "object.h"
 #include "rules.h"
 
 # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
 # define F0 (LIST *(*)(PARSE *, FRAME *))0
 # define P0 (PARSE *)0
-# define S0 (char *)0
+# define S0 (OBJECT *)0
 
 # define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
 # define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )

Modified: trunk/tools/build/v2/engine/jamgram.y
==============================================================================
--- trunk/tools/build/v2/engine/jamgram.y (original)
+++ trunk/tools/build/v2/engine/jamgram.y 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -100,14 +100,14 @@
 #include "parse.h"
 #include "scan.h"
 #include "compile.h"
-#include "newstr.h"
+#include "object.h"
 #include "rules.h"
 
 # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
 # define F0 (LIST *(*)(PARSE *, FRAME *))0
 # define P0 (PARSE *)0
-# define S0 (char *)0
+# define S0 (OBJECT *)0
 
 # define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
 # define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )

Modified: trunk/tools/build/v2/engine/jamgram.yy
==============================================================================
--- trunk/tools/build/v2/engine/jamgram.yy (original)
+++ trunk/tools/build/v2/engine/jamgram.yy 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -56,14 +56,14 @@
 #include "parse.h"
 #include "scan.h"
 #include "compile.h"
-#include "newstr.h"
+#include "object.h"
 #include "rules.h"
 
 # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
 
 # define F0 (LIST *(*)(PARSE *, FRAME *))0
 # define P0 (PARSE *)0
-# define S0 (char *)0
+# define S0 (OBJECT *)0
 
 # define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
 # define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )

Modified: trunk/tools/build/v2/engine/lists.c
==============================================================================
--- trunk/tools/build/v2/engine/lists.c (original)
+++ trunk/tools/build/v2/engine/lists.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -5,11 +5,11 @@
  */
 
 # include "jam.h"
-# include "newstr.h"
+# include "object.h"
 # include "lists.h"
 
 /*
- * lists.c - maintain lists of strings
+ * lists.c - maintain lists of objects
  *
  * This implementation essentially uses a singly linked list, but
  * guarantees that the head element of every list has a valid pointer
@@ -55,12 +55,12 @@
  * list_new() - tack a string onto the end of a list of strings
  */
 
-LIST * list_new( LIST * head, char * string )
+LIST * list_new( LIST * head, OBJECT * value )
 {
     LIST * l;
 
     if ( DEBUG_LISTS )
- printf( "list > %s <\n", string );
+ printf( "list > %s <\n", object_str( value ) );
 
     /* Get list struct from freelist, if one available. */
     /* Otherwise allocate. */
@@ -69,7 +69,7 @@
     if ( freelist )
     {
         l = freelist;
- freestr( l->string );
+ object_free( l->value );
         freelist = freelist->next;
     }
     else
@@ -86,7 +86,7 @@
     head->tail = l;
     l->next = 0;
 
- l->string = string;
+ l->value = value;
 
     return head;
 }
@@ -99,7 +99,7 @@
 LIST * list_copy( LIST * l, LIST * nl )
 {
     for ( ; nl; nl = list_next( nl ) )
- l = list_new( l, copystr( nl->string ) );
+ l = list_new( l, object_copy( nl->value ) );
     return l;
 }
 
@@ -113,16 +113,16 @@
     LIST * nl = 0;
     for ( ; l && start--; l = list_next( l ) );
     for ( ; l && count--; l = list_next( l ) )
- nl = list_new( nl, copystr( l->string ) );
+ nl = list_new( nl, object_copy( l->value ) );
     return nl;
 }
 
 
 static int str_ptr_compare( void const * va, void const * vb )
 {
- char * a = *( (char * *)va );
- char * b = *( (char * *)vb );
- return strcmp(a, b);
+ OBJECT * a = *( (OBJECT * *)va );
+ OBJECT * b = *( (OBJECT * *)vb );
+ return strcmp(object_str(a), object_str(b));
 }
 
 
@@ -130,7 +130,7 @@
 {
     int len;
     int ii;
- char * * strings;
+ OBJECT * * objects;
     LIST * listp;
     LIST * result = 0;
 
@@ -138,21 +138,21 @@
         return L0;
 
     len = list_length( l );
- strings = (char * *)BJAM_MALLOC( len * sizeof(char*) );
+ objects = (OBJECT * *)BJAM_MALLOC( len * sizeof(OBJECT*) );
 
     listp = l;
     for ( ii = 0; ii < len; ++ii )
     {
- strings[ ii ] = listp->string;
+ objects[ ii ] = listp->value;
         listp = listp->next;
     }
 
- qsort( strings, len, sizeof( char * ), str_ptr_compare );
+ qsort( objects, len, sizeof( OBJECT * ), str_ptr_compare );
 
     for ( ii = 0; ii < len; ++ii )
- result = list_append( result, list_new( 0, copystr( strings[ ii ] ) ) );
+ result = list_append( result, list_new( 0, object_copy( objects[ ii ] ) ) );
 
- BJAM_FREE( strings );
+ BJAM_FREE( objects );
 
     return result;
 }
@@ -168,8 +168,8 @@
     LIST *l, *tmp;
     for( l = head; l; )
     {
- freestr( l->string );
- l->string = 0;
+ object_free( l->value );
+ l->value = 0;
         tmp = l;
         l = l->next;
         BJAM_FREE( tmp );
@@ -212,9 +212,9 @@
     LIST * p = 0;
     for ( ; l; p = l, l = list_next( l ) )
         if ( p )
- printf( "%s ", p->string );
+ printf( "%s ", object_str( p->value ) );
     if ( p )
- printf( "%s", p->string );
+ printf( "%s", object_str( p->value ) );
 }
 
 
@@ -230,10 +230,10 @@
 }
 
 
-int list_in( LIST * l, char * value )
+int list_in( LIST * l, OBJECT * value )
 {
     for ( ; l; l = l->next )
- if ( strcmp( l->string, value ) == 0 )
+ if ( object_equal( l->value, value ) )
             return 1;
     return 0;
 }
@@ -246,9 +246,9 @@
 
     for ( ; sorted_list; sorted_list = sorted_list->next )
     {
- if ( !last_added || strcmp( sorted_list->string, last_added->string ) != 0 )
+ if ( !last_added || !object_equal( sorted_list->value, last_added->value ) )
         {
- result = list_new( result, copystr( sorted_list->string ) );
+ result = list_new( result, object_copy( sorted_list->value ) );
             last_added = sorted_list;
         }
     }
@@ -260,8 +260,8 @@
     LIST *l, *tmp;
     for( l = freelist; l; )
     {
- freestr( l->string );
- l->string = 0;
+ object_free( l->value );
+ l->value = 0;
         tmp = l;
         l = l->next;
         BJAM_FREE( tmp );
@@ -337,7 +337,7 @@
 
     for (; l; l = l->next)
     {
- PyObject* s = PyString_FromString(l->string);
+ PyObject* s = PyString_FromString(object_str(l->value));
         PyList_Append(result, s);
         Py_DECREF(s);
     }
@@ -354,7 +354,7 @@
     for (i = 0; i < n; ++i)
     {
         PyObject *v = PySequence_GetItem(l, i);
- result = list_new (result, newstr (PyString_AsString(v)));
+ result = list_new (result, object_new (PyString_AsString(v)));
         Py_DECREF(v);
     }
 

Modified: trunk/tools/build/v2/engine/lists.h
==============================================================================
--- trunk/tools/build/v2/engine/lists.h (original)
+++ trunk/tools/build/v2/engine/lists.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -13,23 +13,23 @@
 /*
  * lists.h - the LIST structure and routines to manipulate them
  *
- * The whole of jam relies on lists of strings as a datatype. This
- * module, in conjunction with newstr.c, handles these relatively
+ * The whole of jam relies on lists of objects as a datatype. This
+ * module, in conjunction with object.c, handles these relatively
  * efficiently.
  *
  * Structures defined:
  *
- * LIST - list of strings
+ * LIST - list of OBJECTs
  * LOL - list of LISTs
  *
  * External routines:
  *
  * list_append() - append a list onto another one, returning total
- * list_new() - tack a string onto the end of a list of strings
- * list_copy() - copy a whole list of strings
- * list_sublist() - copy a subset of a list of strings
- * list_free() - free a list of strings
- * list_print() - print a list of strings to stdout
+ * list_new() - tack an object onto the end of a list of objects
+ * list_copy() - copy a whole list of objects
+ * list_sublist() - copy a subset of a list of objects
+ * list_free() - free a list of objects
+ * list_print() - print a list of objects to stdout
  * list_length() - return the number of items in the list
  *
  * lol_init() - initialize a LOL (list of lists)
@@ -45,6 +45,8 @@
 #ifndef LISTS_DWA20011022_H
 # define LISTS_DWA20011022_H
 
+#include "object.h"
+
 #ifdef HAVE_PYTHON
 #include <Python.h>
 #endif
@@ -58,7 +60,7 @@
 struct _list {
     LIST *next;
     LIST *tail; /* only valid in head node */
- char *string; /* private copy */
+ OBJECT *value; /* private copy */
 };
 
 /*
@@ -77,14 +79,14 @@
 LIST * list_append( LIST *l, LIST *nl );
 LIST * list_copy( LIST *l, LIST *nl );
 void list_free( LIST *head );
-LIST * list_new( LIST *head, char *string );
+LIST * list_new( LIST *head, OBJECT *string );
 void list_print( LIST *l );
 int list_length( LIST *l );
 LIST * list_sublist( LIST *l, int start, int count );
 LIST * list_pop_front( LIST *l );
 LIST * list_sort( LIST *l);
 LIST * list_unique( LIST *sorted_list);
-int list_in(LIST* l, char* value);
+int list_in(LIST* l, OBJECT* value);
 void list_done();
 
 # define list_next( l ) ((l)->next)
@@ -96,7 +98,7 @@
 void lol_free( LOL *lol );
 LIST * lol_get( LOL *lol, int i );
 void lol_print( LOL *lol );
-void lol_build( LOL* lol, char** elements );
+void lol_build( LOL* lol, const char** elements );
 
 #ifdef HAVE_PYTHON
 

Modified: trunk/tools/build/v2/engine/make.c
==============================================================================
--- trunk/tools/build/v2/engine/make.c (original)
+++ trunk/tools/build/v2/engine/make.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -58,7 +58,7 @@
 #endif
 
 #include "search.h"
-#include "newstr.h"
+#include "object.h"
 #include "make.h"
 #include "headers.h"
 #include "command.h"
@@ -106,7 +106,7 @@
  * make() - make a target, given its name.
  */
 
-int make( int n_targets, char const * * targets, int anyhow )
+int make( int n_targets, OBJECT * * targets, int anyhow )
 {
     int i;
     COUNTS counts[ 1 ];
@@ -191,7 +191,7 @@
             if ( DEBUG_FATE )
             {
                 printf( "fate change %s from %s to %s (as dependant of %s)\n",
- p->name, target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], t->name );
+ object_str( p->name ), target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], object_str( t->name ) );
             }
 
             /* If we are done visiting it, go back and make sure its dependants
@@ -220,7 +220,7 @@
         {
             if ( DEBUG_FATE )
                 printf( "fate change %s from %s to %s (by rebuild)\n",
- r->name, target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] );
+ object_str( r->name ), target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] );
 
             /* Force rebuild it. */
             r->fate = T_FATE_REBUILD;
@@ -262,14 +262,14 @@
 #endif
 
     if ( DEBUG_MAKEPROG )
- printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+ printf( "make\t--\t%s%s\n", spaces( depth ), object_str( t->name ) );
 
     /*
      * Step 1: initialize
      */
 
     if ( DEBUG_MAKEPROG )
- printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
+ printf( "make\t--\t%s%s\n", spaces( depth ), object_str( t->name ) );
 
     t->fate = T_FATE_MAKING;
 
@@ -285,8 +285,8 @@
     /* Step 2b: find and timestamp the target file (if it is a file). */
     if ( ( t->binding == T_BIND_UNBOUND ) && !( t->flags & T_FLAG_NOTFILE ) )
     {
- char * another_target;
- freestr( t->boundname );
+ OBJECT * another_target;
+ object_free( t->boundname );
         t->boundname = search( t->name, &t->time, &another_target,
                                t->flags & T_FLAG_ISFILE );
         /* If it was detected that this target refers to an already existing and
@@ -314,10 +314,12 @@
 
 #ifdef OPT_SEMAPHORE
     {
- LIST * var = var_get( "JAM_SEMAPHORE" );
+ OBJECT * jam_semaphore = object_new( "JAM_SEMAPHORE" );
+ LIST * var = var_get( jam_semaphore );
+ object_free( jam_semaphore );
         if ( var )
         {
- TARGET * semaphore = bindtarget( var->string );
+ TARGET * semaphore = bindtarget( var->value );
             semaphore->progress = T_MAKE_SEMAPHORE;
             t->semaphore = semaphore;
         }
@@ -338,9 +340,9 @@
 
     if ( DEBUG_BIND )
     {
- if ( strcmp( t->name, t->boundname ) )
+ if ( ! object_equal( t->name, t->boundname ) )
             printf( "bind\t--\t%s%s: %s\n",
- spaces( depth ), t->name, t->boundname );
+ spaces( depth ), object_str( t->name ), object_str( t->boundname ) );
 
         switch ( t->binding )
         {
@@ -348,12 +350,12 @@
         case T_BIND_MISSING:
         case T_BIND_PARENTS:
             printf( "time\t--\t%s%s: %s\n",
- spaces( depth ), t->name, target_bind[ (int) t->binding ] );
+ spaces( depth ), object_str( t->name ), target_bind[ (int) t->binding ] );
             break;
 
         case T_BIND_EXISTS:
             printf( "time\t--\t%s%s: %s",
- spaces( depth ), t->name, ctime( &t->time ) );
+ spaces( depth ), object_str( t->name ), ctime( &t->time ) );
             break;
         }
     }
@@ -373,7 +375,7 @@
         if ( c->target->fate == T_FATE_INIT )
             make0( c->target, ptime, depth + 1, counts, anyhow );
         else if ( c->target->fate == T_FATE_MAKING && !internal )
- printf( "warning: %s depends on itself\n", c->target->name );
+ printf( "warning: %s depends on itself\n", object_str( c->target->name ) );
     }
 
     /* Step 3b: recursively make0() internal includes node. */
@@ -417,8 +419,8 @@
         if ( DEBUG_FATE )
             if ( fate < c->target->fate )
                 printf( "fate change %s from %s to %s by dependency %s\n",
- t->name, target_fate[(int) fate], target_fate[(int) c->target->fate],
- c->target->name );
+ object_str( t->name ), target_fate[(int) fate], target_fate[(int) c->target->fate],
+ object_str( c->target->name ) );
 #endif
     }
 
@@ -442,8 +444,8 @@
 #ifdef OPT_GRAPH_DEBUG_EXT
         if ( DEBUG_FATE )
             if ( fate != T_FATE_STABLE )
- printf( "fate change %s back to stable, NOUPDATE.\n", t->name
- );
+ printf( "fate change %s back to stable, NOUPDATE.\n",
+ object_str( t->name ) );
 #endif
 
         last = 0;
@@ -538,10 +540,10 @@
     if ( DEBUG_FATE && ( fate != savedFate ) )
         {
         if ( savedFate == T_FATE_STABLE )
- printf( "fate change %s set to %s%s\n", t->name,
+ printf( "fate change %s set to %s%s\n", object_str( t->name ),
                 target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" );
         else
- printf( "fate change %s from %s to %s%s\n", t->name,
+ printf( "fate change %s from %s to %s%s\n", object_str( t->name ),
                 target_fate[ savedFate ], target_fate[ fate ],
                 oldTimeStamp ? " (by timestamp)" : "" );
         }
@@ -561,13 +563,13 @@
             if ( DEBUG_FATE )
                 printf( "fate change %s to STABLE from %s, "
                     "no actions, no dependencies and do not care\n",
- t->name, target_fate[ fate ] );
+ object_str( t->name ), target_fate[ fate ] );
 #endif
             fate = T_FATE_STABLE;
         }
         else
         {
- printf( "don't know how to make %s\n", t->name );
+ printf( "don't know how to make %s\n", object_str( t->name ) );
             fate = T_FATE_CANTFIND;
         }
     }
@@ -634,7 +636,7 @@
 
     if ( DEBUG_MAKEPROG )
         printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int) t->fate ],
- spaces( depth ), t->name );
+ spaces( depth ), object_str( t->name ) );
 }
 
 
@@ -645,10 +647,10 @@
     static char buf[ 1000 ];
     if ( t->flags & T_FLAG_INTERNAL )
     {
- sprintf( buf, "%s (internal node)", t->name );
+ sprintf( buf, "%s (internal node)", object_str( t->name ) );
         return buf;
     }
- return t->name;
+ return object_str( t->name );
 }
 
 
@@ -678,8 +680,8 @@
         break;
     }
 
- if ( strcmp( t->name, t->boundname ) )
- printf( " %s Loc: %s\n", spaces( depth ), t->boundname );
+ if ( ! object_equal( t->name, t->boundname ) )
+ printf( " %s Loc: %s\n", spaces( depth ), object_str( t->boundname ) );
 
     switch ( t->fate )
     {
@@ -792,9 +794,9 @@
 static LIST * targets_to_update_ = 0;
 
 
-void mark_target_for_updating( char * target )
+void mark_target_for_updating( OBJECT * target )
 {
- targets_to_update_ = list_new( targets_to_update_, newstr( target ) );
+ targets_to_update_ = list_new( targets_to_update_, object_copy( target ) );
 }
 
 

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

Modified: trunk/tools/build/v2/engine/make1.c
==============================================================================
--- trunk/tools/build/v2/engine/make1.c (original)
+++ trunk/tools/build/v2/engine/make1.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -57,7 +57,7 @@
 #include "headers.h"
 
 #include "search.h"
-#include "newstr.h"
+#include "object.h"
 #include "make.h"
 #include "command.h"
 #include "execcmd.h"
@@ -107,7 +107,7 @@
 static void make1b ( state * );
 static void make1c ( state * );
 static void make1d ( state * );
-static void make_closure( void * closure, int status, timing_info *, char *, char * );
+static void make_closure( void * closure, int status, timing_info *, const char *, const char * );
 
 typedef struct _stack
 {
@@ -350,10 +350,10 @@
 
 static void make1b( state * pState )
 {
- TARGET * t = pState->t;
- TARGETS * c;
- TARGET * failed = 0;
- char * failed_name = "dependencies";
+ TARGET * t = pState->t;
+ TARGETS * c;
+ TARGET * failed = 0;
+ const char * failed_name = "dependencies";
 
     /* If any dependencies are still outstanding, wait until they call make1b()
      * to signal their completion.
@@ -376,7 +376,7 @@
 
         if ( DEBUG_EXECCMD )
             printf( "SEM: %s is busy, delaying launch of %s\n",
- t->semaphore->name, t->name );
+ object_str( t->semaphore->name ), object_str( t->name ) );
         pop_state( &state_stack );
         return;
     }
@@ -398,7 +398,7 @@
     {
         failed_name = failed->flags & T_FLAG_INTERNAL
             ? failed->failed
- : failed->name;
+ : object_str( failed->name );
     }
     t->failed = failed_name;
 
@@ -410,11 +410,11 @@
         ++counts->skipped;
         if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
         {
- if ( !unlink( pState->t->boundname ) )
- printf( "...removing outdated %s\n", pState->t->boundname );
+ if ( !unlink( object_str( pState->t->boundname ) ) )
+ printf( "...removing outdated %s\n", object_str( pState->t->boundname ) );
         }
         else
- printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name );
+ printf( "...skipped %s for lack of %s...\n", object_str( pState->t->name ), failed_name );
     }
 
     if ( pState->t->status == EXEC_CMD_OK )
@@ -436,7 +436,7 @@
 
         case T_FATE_ISTMP:
             if ( DEBUG_MAKE )
- printf( "...using %s...\n", pState->t->name );
+ printf( "...using %s...\n", object_str( pState->t->name ) );
             break;
 
         case T_FATE_TOUCHED:
@@ -467,7 +467,7 @@
 
             /* All possible fates should have been accounted for by now. */
         default:
- printf( "ERROR: %s has bad fate %d", pState->t->name,
+ printf( "ERROR: %s has bad fate %d", object_str( pState->t->name ),
                 pState->t->fate );
             abort();
         }
@@ -484,8 +484,8 @@
     {
         ++pState->t->semaphore->asynccnt;
         if ( DEBUG_EXECCMD )
- printf( "SEM: %s now used by %s\n", pState->t->semaphore->name,
- pState->t->name );
+ printf( "SEM: %s now used by %s\n", object_str( pState->t->semaphore->name ),
+ object_str( pState->t->name ) );
     }
 #endif
 
@@ -508,14 +508,14 @@
 
     if ( cmd && ( pState->t->status == EXEC_CMD_OK ) )
     {
- char * rule_name = 0;
- char * target = 0;
+ const char * rule_name = 0;
+ const char * target = 0;
 
         if ( DEBUG_MAKEQ ||
             ( !( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE ) )
         {
- rule_name = cmd->rule->name;
- target = lol_get( &cmd->args, 0 )->string;
+ rule_name = object_str( cmd->rule->name );
+ target = object_str( lol_get( &cmd->args, 0 )->value );
             if ( globs.noexec )
                 out_action( rule_name, target, cmd->buf, "", "", EXIT_OK );
         }
@@ -631,7 +631,7 @@
                 --t->semaphore->asynccnt;
 
                 if ( DEBUG_EXECCMD )
- printf( "SEM: %s is now free\n", t->semaphore->name );
+ printf( "SEM: %s is now free\n", object_str( t->semaphore->name ) );
 
                 /* If anything is waiting, notify the next target. There is no
                  * point in notifying waiting targets, since they will be
@@ -645,7 +645,7 @@
                     t->semaphore->parents = first->next;
 
                     if ( DEBUG_EXECCMD )
- printf( "SEM: placing %s on stack\n", first->target->name );
+ printf( "SEM: placing %s on stack\n", object_str( first->target->name ) );
                     push_state( &temp_stack, first->target, NULL, T_STATE_MAKE1B );
                     BJAM_FREE( first );
                 }
@@ -671,10 +671,13 @@
 static void call_timing_rule( TARGET * target, timing_info * time )
 {
     LIST * timing_rule;
+ OBJECT * varname;
 
+ varname = object_new( "__TIMING_RULE__" );
     pushsettings( target->settings );
- timing_rule = var_get( "__TIMING_RULE__" );
+ timing_rule = var_get( varname );
     popsettings( target->settings );
+ object_free( varname );
 
     if ( timing_rule )
     {
@@ -688,7 +691,7 @@
         lol_add( frame->args, list_copy( L0, timing_rule->next ) );
 
         /* target :: the name of the target */
- lol_add( frame->args, list_new( L0, copystr( target->name ) ) );
+ lol_add( frame->args, list_new( L0, object_copy( target->name ) ) );
 
         /* start end user system :: info about the action command */
         lol_add( frame->args, list_new( list_new( list_new( list_new( L0,
@@ -698,7 +701,7 @@
             outf_double( time->system ) ) );
 
         /* Call the rule. */
- evaluate_rule( timing_rule->string, frame );
+ evaluate_rule( timing_rule->value, frame );
 
         /* Clean up. */
         frame_free( frame );
@@ -717,15 +720,18 @@
     TARGET * target,
     int status,
     timing_info * time,
- char * executed_command,
- char * command_output
+ const char * executed_command,
+ const char * command_output
 )
 {
- LIST * action_rule;
+ LIST * action_rule;
+ OBJECT * varname;
 
+ varname = object_new( "__ACTION_RULE__" );
     pushsettings( target->settings );
- action_rule = var_get( "__ACTION_RULE__" );
+ action_rule = var_get( varname );
     popsettings( target->settings );
+ object_free( varname );
 
     if ( action_rule )
     {
@@ -743,12 +749,12 @@
         lol_add( frame->args, list_copy( L0, action_rule->next ) );
 
         /* target :: the name of the target */
- lol_add( frame->args, list_new( L0, copystr( target->name ) ) );
+ lol_add( frame->args, list_new( L0, object_copy( target->name ) ) );
 
         /* command status start end user system :: info about the action command */
         lol_add( frame->args,
             list_new( list_new( list_new( list_new( list_new( list_new( L0,
- newstr( executed_command ) ),
+ object_new( executed_command ) ),
                 outf_int( status ) ),
                 outf_time( time->start ) ),
                 outf_time( time->end ) ),
@@ -757,12 +763,12 @@
 
         /* output ? :: the output of the action command */
         if ( command_output )
- lol_add( frame->args, list_new( L0, newstr( command_output ) ) );
+ lol_add( frame->args, list_new( L0, object_new( command_output ) ) );
         else
             lol_add( frame->args, L0 );
 
         /* Call the rule. */
- evaluate_rule( action_rule->string, frame );
+ evaluate_rule( action_rule->value, frame );
 
         /* Clean up. */
         frame_free( frame );
@@ -780,8 +786,8 @@
     void * closure,
     int status,
     timing_info * time,
- char * executed_command,
- char * command_output
+ const char * executed_command,
+ const char * command_output
 )
 {
     TARGET * built = (TARGET *)closure;
@@ -835,7 +841,7 @@
         if ( !DEBUG_EXEC )
             printf( "%s\n", cmd->buf );
 
- printf( "...failed %s ", cmd->rule->name );
+ printf( "...failed %s ", object_str( cmd->rule->name ) );
         list_print( lol_get( &cmd->args, 0 ) );
         printf( "...\n" );
     }
@@ -855,13 +861,13 @@
         for ( ; targets; targets = list_next( targets ) )
         {
             int need_unlink = 1;
- TARGET* t = bindtarget ( targets->string );
+ TARGET* t = bindtarget ( targets->value );
             if (t->flags & T_FLAG_PRECIOUS)
             {
                 need_unlink = 0;
             }
- if (need_unlink && !unlink( targets->string ) )
- printf( "...removing %s\n", targets->string );
+ if (need_unlink && !unlink( object_str( targets->value ) ) )
+ printf( "...removing %s\n", object_str( targets->value ) );
         }
     }
 
@@ -979,7 +985,11 @@
 
         swap_settings( &settings_module, &settings_target, rule->module, t );
         if ( !shell )
- shell = var_get( "JAMSHELL" ); /* shell is per-target */
+ {
+ OBJECT * varname = object_new( "JAMSHELL" );
+ shell = var_get( varname ); /* shell is per-target */
+ object_free( varname );
+ }
 
         /* If we had 'actions xxx bind vars' we bind the vars now. */
         boundvars = make1settings( actions->bindlist );
@@ -1028,13 +1038,13 @@
             else
             {
                 /* Too long and not splittable. */
- printf( "%s actions too long (max %d):\n", rule->name, MAXLINE
+ printf( "%s actions too long (max %d):\n", object_str( rule->name ), MAXLINE
                     );
 
                 /* Tell the user what didn't fit. */
                 cmd = cmd_new( rule, list_copy( L0, nt ),
                     list_sublist( ns, start, chunk ),
- list_new( L0, newstr( "%" ) ) );
+ list_new( L0, object_new( "%" ) ) );
                 fputs( cmd->buf, stdout );
                 exit( EXITBAD );
             }
@@ -1089,14 +1099,14 @@
         {
             LIST * m;
             for ( m = l; m; m = m->next )
- if ( !strcmp( m->string, t->boundname ) )
+ if ( object_equal( m->value, t->boundname ) )
                     break;
             if ( m )
                 continue;
         }
 
         /* Build new list. */
- l = list_new( l, copystr( t->boundname ) );
+ l = list_new( l, object_copy( t->boundname ) );
     }
 
     return l;
@@ -1113,23 +1123,23 @@
 
     for ( ; vars; vars = list_next( vars ) )
     {
- LIST * l = var_get( vars->string );
+ LIST * l = var_get( vars->value );
         LIST * nl = 0;
 
         for ( ; l; l = list_next( l ) )
         {
- TARGET * t = bindtarget( l->string );
+ TARGET * t = bindtarget( l->value );
 
             /* Make sure the target is bound. */
             if ( t->binding == T_BIND_UNBOUND )
                 make1bind( t );
 
             /* Build a new list. */
- nl = list_new( nl, copystr( t->boundname ) );
+ nl = list_new( nl, object_copy( t->boundname ) );
         }
 
         /* Add to settings chain. */
- settings = addsettings( settings, VAR_SET, vars->string, nl );
+ settings = addsettings( settings, VAR_SET, vars->value, nl );
     }
 
     return settings;
@@ -1149,7 +1159,7 @@
         return;
 
     pushsettings( t->settings );
- freestr( t->boundname );
+ object_free( t->boundname );
     t->boundname = search( t->name, &t->time, 0, ( t->flags & T_FLAG_ISFILE ) );
     t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
     popsettings( t->settings );

Modified: trunk/tools/build/v2/engine/modules.c
==============================================================================
--- trunk/tools/build/v2/engine/modules.c (original)
+++ trunk/tools/build/v2/engine/modules.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,7 +8,7 @@
 #include "modules.h"
 #include "string.h"
 #include "hash.h"
-#include "newstr.h"
+#include "object.h"
 #include "lists.h"
 #include "parse.h"
 #include "rules.h"
@@ -20,19 +20,7 @@
 static struct hash * module_hash = 0;
 
 
-static char * new_module_str( module_t * m, char * suffix )
-{
- char * result;
- string s;
- string_copy( &s, m->name );
- string_append( &s, suffix );
- result = newstr( s.value );
- string_free( &s );
- return result;
-}
-
-
-module_t * bindmodule( char * name )
+module_t * bindmodule( OBJECT * name )
 {
     PROFILE_ENTER( BINDMODULE );
 
@@ -46,15 +34,15 @@
     string_new( &s );
     if ( name )
     {
- string_append( &s, name );
+ string_append( &s, object_str( name ) );
         string_push_back( &s, '.' );
     }
 
- m->name = s.value;
+ m->name = name = object_new( s.value );
 
     if ( hashenter( module_hash, (HASHDATA * *)&m ) )
     {
- m->name = newstr( m->name );
+ m->name = m->name;
         m->variables = 0;
         m->rules = 0;
         m->imported_modules = 0;
@@ -62,6 +50,10 @@
         m->native_rules = 0;
         m->user_module = 0;
     }
+ else
+ {
+ object_free( name );
+ }
     string_free( &s );
 
     PROFILE_EXIT( BINDMODULE );
@@ -75,7 +67,7 @@
 struct hash * demand_rules( module_t * m )
 {
     if ( !m->rules )
- m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
+ m->rules = hashinit( sizeof( RULE ), "rules" );
     return m->rules;
 }
 
@@ -95,7 +87,7 @@
     native_rule_t * rule = (native_rule_t *)xrule;
     if ( rule->arguments )
         args_free( rule->arguments );
- freestr( rule->name );
+ object_free( rule->name );
     if ( rule->procedure )
         parse_free( rule->procedure );
 }
@@ -103,7 +95,7 @@
 
 static void delete_imported_modules( void * xmodule_name, void * data )
 {
- freestr( *(char * *)xmodule_name );
+ object_free( *(OBJECT * *)xmodule_name );
 }
 
 
@@ -112,17 +104,13 @@
     /* Clear out all the rules. */
     if ( m->rules )
     {
- char * name;
         hashenumerate( m->rules, delete_rule_, (void *)0 );
- name = hashname( m->rules );
         hashdone( m->rules );
- freestr( name );
         m->rules = 0;
     }
 
     if ( m->native_rules )
     {
- char * name;
         hashenumerate( m->native_rules, delete_native_rule, (void *)0 );
         hashdone( m->native_rules );
         m->native_rules = 0;
@@ -153,7 +141,7 @@
 
     if ( m->name )
     {
- freestr( m->name );
+ object_free( m->name );
     }
 }
 
@@ -196,11 +184,11 @@
 
     for ( ; module_names; module_names = module_names->next )
     {
- char * s = module_names->string;
- char * * ss = &s;
+ OBJECT * s = module_names->value;
+ OBJECT * * ss = &s;
         if( hashenter( h, (HASHDATA * *)&ss ) )
         {
- *ss = copystr( s );
+ *ss = object_copy( s );
         }
     }
 
@@ -210,10 +198,10 @@
 
 static void add_module_name( void * r_, void * result_ )
 {
- char * * r = (char * *)r_;
+ OBJECT * * r = (OBJECT * *)r_;
     LIST * * result = (LIST * *)result_;
 
- *result = list_new( *result, copystr( *r ) );
+ *result = list_new( *result, object_copy( *r ) );
 }
 
 

Modified: trunk/tools/build/v2/engine/modules.h
==============================================================================
--- trunk/tools/build/v2/engine/modules.h (original)
+++ trunk/tools/build/v2/engine/modules.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -10,27 +10,27 @@
 
 struct module_t
 {
- char* name;
- struct hash* rules;
- struct hash* variables;
- struct hash* imported_modules;
- struct module_t* class_module;
- struct hash* native_rules;
+ OBJECT * name;
+ struct hash * rules;
+ struct hash * variables;
+ struct hash * imported_modules;
+ struct module_t * class_module;
+ struct hash * native_rules;
     int user_module;
 };
 
 typedef struct module_t module_t ; /* MSVC debugger gets confused unless this is provided */
 
-module_t* bindmodule( char* name );
-module_t* root_module();
-void enter_module( module_t* );
-void exit_module( module_t* );
-void delete_module( module_t* );
+module_t * bindmodule( OBJECT * name );
+module_t * root_module();
+void enter_module( module_t * );
+void exit_module( module_t * );
+void delete_module( module_t * );
 
-void import_module(LIST* module_names, module_t* target_module);
+void import_module( LIST * module_names, module_t * target_module );
 LIST* imported_modules(module_t* module);
 
-struct hash* demand_rules( module_t* );
+struct hash * demand_rules( module_t * );
 
 void modules_done();
 

Modified: trunk/tools/build/v2/engine/modules/order.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/order.c (original)
+++ trunk/tools/build/v2/engine/modules/order.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -5,7 +5,7 @@
 #include "../native.h"
 #include "../lists.h"
 #include "../strings.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../variable.h"
 
 
@@ -16,7 +16,7 @@
 {
     LIST* arg = lol_get( frame->args, 0 );
 
- var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
+ var_set(arg->value, list_copy(0, arg->next), VAR_APPEND);
 
     return L0;
 }
@@ -24,11 +24,11 @@
 /** Given a list and a value, returns position of that value in
     the list, or -1 if not found.
 */
-int list_index(LIST* list, const char* value)
+int list_index(LIST* list, OBJECT* value)
 {
     int result = 0;
     for(; list; list = list->next, ++result) {
- if (strcmp(list->string, value) == 0)
+ if (object_equal(list->value, value))
             return result;
     }
     return -1;
@@ -92,12 +92,12 @@
     for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
         /* For all object this one depend upon, add elements
            to 'graph' */
- LIST* dependencies = var_get(tmp->string);
+ LIST* dependencies = var_get(tmp->value);
         int index = 0;
 
         graph[src] = (int*)BJAM_CALLOC(list_length(dependencies)+1, sizeof(int));
         for(; dependencies; dependencies = dependencies->next) {
- int dst = list_index(arg, dependencies->string);
+ int dst = list_index(arg, dependencies->value);
             if (dst != -1)
                 graph[src][index++] = dst;
         }
@@ -112,7 +112,7 @@
             int i;
             tmp = arg;
             for (i = 0; i < order[index]; ++i, tmp = tmp->next);
- result = list_new(result, copystr(tmp->string));
+ result = list_new(result, object_copy(tmp->value));
         }
     }
 
@@ -131,12 +131,12 @@
 void init_order()
 {
     {
- char* args[] = { "first", "second", 0 };
+ const char* args[] = { "first", "second", 0 };
         declare_native_rule("class_at_order", "add-pair", args, add_pair, 1);
     }
 
     {
- char* args[] = { "objects", "*", 0 };
+ const char* args[] = { "objects", "*", 0 };
         declare_native_rule("class_at_order", "order", args, order, 1);
     }
 

Modified: trunk/tools/build/v2/engine/modules/path.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/path.c (original)
+++ trunk/tools/build/v2/engine/modules/path.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -4,17 +4,17 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 
 LIST *path_exists( PARSE *parse, FRAME *frame )
 {
     LIST* l = lol_get( frame->args, 0 );
 
     time_t time;
- timestamp(l->string, &time);
+ timestamp(l->value, &time);
     if (time != 0)
     {
- return list_new(0, newstr("true"));
+ return list_new(0, object_new("true"));
     }
     else
     {
@@ -25,7 +25,7 @@
 void init_path()
 {
     {
- char* args[] = { "location", 0 };
+ const char* args[] = { "location", 0 };
         declare_native_rule("path", "exists", args, path_exists, 1);
     }
 

Modified: trunk/tools/build/v2/engine/modules/property-set.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/property-set.c (original)
+++ trunk/tools/build/v2/engine/modules/property-set.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -4,7 +4,7 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../strings.h"
 #include "../lists.h"
 #include "../variable.h"
@@ -19,7 +19,7 @@
     string_new(s);
 
     string_append_range(s, f, end+1);
- result = list_new(0, newstr(s->value));
+ result = list_new(0, object_new(s->value));
 
     string_free(s);
     return result;
@@ -52,6 +52,7 @@
     LIST* tmp;
     LIST* val;
     string var[1];
+ OBJECT* name;
 
 #if 0
     /* Sort all properties which are not order sensitive */
@@ -77,22 +78,26 @@
     string_append(var, ".ps.");
 
     for(tmp = unique; tmp; tmp = tmp->next) {
- string_append(var, tmp->string);
+ string_append(var, object_str( tmp->value ));
         string_push_back(var, '-');
     }
- val = var_get(var->value);
+ name = object_new(var->value);
+ val = var_get(name);
     if (val == 0)
     {
- val = call_rule("new", frame,
- list_append(list_new(0, newstr("property-set")), unique), 0);
+ OBJECT* rulename = object_new("new");
+ val = call_rule(rulename, frame,
+ list_append(list_new(0, object_new("property-set")), unique), 0);
+ object_free(rulename);
 
- var_set(var->value, list_copy(0, val), VAR_SET);
+ var_set(name, list_copy(0, val), VAR_SET);
     }
     else
     {
         list_free(unique);
         val = list_copy(0, val);
     }
+ object_free(name);
 
     string_free(var);
     /* The 'unique' variable is freed in 'call_rule'. */
@@ -105,7 +110,7 @@
 void init_property_set()
 {
     {
- char* args[] = { "raw-properties", "*", 0 };
+ const char* args[] = { "raw-properties", "*", 0 };
         declare_native_rule("property-set", "create", args, property_set_create, 1);
     }
 }

Modified: trunk/tools/build/v2/engine/modules/regex.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/regex.c (original)
+++ trunk/tools/build/v2/engine/modules/regex.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -4,7 +4,7 @@
 
 #include "../native.h"
 #include "../timestamp.h"
-#include "../newstr.h"
+#include "../object.h"
 #include "../strings.h"
 #include "../regexp.h"
 #include "../compile.h"
@@ -44,7 +44,7 @@
         indices = (int*)BJAM_MALLOC(size*sizeof(int));
         for(p = indices; indices_list; indices_list = indices_list->next)
         {
- *p++ = atoi(indices_list->string);
+ *p++ = atoi(object_str(indices_list->value));
         }
     }
     else
@@ -56,11 +56,11 @@
 
     {
         /* Result is cached and intentionally never freed */
- regexp *re = regex_compile( pattern->string );
+ regexp *re = regex_compile( pattern->value );
 
         for(; l; l = l->next)
         {
- if( regexec( re, l->string ) )
+ if( regexec( re, object_str( l->value ) ) )
             {
                 int i = 0;
                 for(; i < size; ++i)
@@ -73,7 +73,7 @@
                     if (re->startp[index] != re->endp[index])
                     {
                         string_append_range( buf, re->startp[index], re->endp[index] );
- result = list_new( result, newstr( buf->value ) );
+ result = list_new( result, object_new( buf->value ) );
                         string_truncate( buf, 0 );
                     }
                 }
@@ -90,7 +90,7 @@
 void init_regex()
 {
     {
- char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
+ const char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 };
         declare_native_rule("regex", "transform", args, regex_transform, 2);
     }
 }

Modified: trunk/tools/build/v2/engine/modules/sequence.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/sequence.c (original)
+++ trunk/tools/build/v2/engine/modules/sequence.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -3,7 +3,7 @@
 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
-#include "../newstr.h"
+#include "../object.h"
 
 # ifndef max
 # define max( a,b ) ((a)>(b)?(a):(b))
@@ -23,11 +23,11 @@
     int highest_rank = -1;
 
     for (tmp = rank; tmp; tmp = tmp->next)
- highest_rank = max(highest_rank, atoi(tmp->string));
+ highest_rank = max(highest_rank, atoi(object_str(tmp->value)));
 
     for (; rank; rank = rank->next, elements = elements->next)
- if (atoi(rank->string) == highest_rank)
- result = list_new(result, copystr(elements->string));
+ if (atoi(object_str(rank->value)) == highest_rank)
+ result = list_new(result, object_copy(elements->value));
 
     return result;
 }
@@ -35,7 +35,7 @@
 void init_sequence()
 {
     {
- char* args[] = { "elements", "*", ":", "rank", "*", 0 };
+ const char* args[] = { "elements", "*", ":", "rank", "*", 0 };
         declare_native_rule("sequence", "select-highest-ranked", args,
                             sequence_select_highest_ranked, 1);
     }

Modified: trunk/tools/build/v2/engine/modules/set.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/set.c (original)
+++ trunk/tools/build/v2/engine/modules/set.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -3,7 +3,7 @@
 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
 
 #include "../native.h"
-#include "../newstr.h"
+#include "../object.h"
 
 /*
     local result = ;
@@ -26,8 +26,8 @@
     LIST* result = 0;
     for(; b; b = b->next)
     {
- if (!list_in(a, b->string))
- result = list_new(result, copystr(b->string));
+ if (!list_in(a, b->value))
+ result = list_new(result, object_copy(b->value));
     }
     return result;
 }
@@ -35,7 +35,7 @@
 void init_set()
 {
     {
- char* args[] = { "B", "*", ":", "A", "*", 0 };
+ const char* args[] = { "B", "*", ":", "A", "*", 0 };
         declare_native_rule("set", "difference", args, set_difference, 1);
     }
 

Modified: trunk/tools/build/v2/engine/native.c
==============================================================================
--- trunk/tools/build/v2/engine/native.c (original)
+++ trunk/tools/build/v2/engine/native.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -4,23 +4,33 @@
 
 #include "native.h"
 #include "hash.h"
-#include "newstr.h"
+#include "object.h"
 
 # define P0 (PARSE *)0
-# define C0 (char *)0
+# define C0 (OBJECT *)0
 
 
-void declare_native_rule(char* module, char* rule, char** args,
- LIST*(*f)(PARSE*, FRAME*), int version)
+void declare_native_rule( const char * module, const char * rule, const char * * args,
+ LIST * (*f)( PARSE *, FRAME * ), int version )
 {
- module_t* m = bindmodule(module);
+ OBJECT * module_obj = 0;
+ module_t * m;
+ if ( module )
+ {
+ module_obj = object_new( module );
+ }
+ m = bindmodule( module_obj );
+ if ( module_obj )
+ {
+ object_free( module_obj );
+ }
     if (m->native_rules == 0) {
         m->native_rules = hashinit( sizeof( native_rule_t ), "native rules");
     }
 
     {
         native_rule_t n, *np = &n;
- n.name = newstr( rule );
+ n.name = object_new( rule );
         if (args)
         {
             n.arguments = args_new();

Modified: trunk/tools/build/v2/engine/native.h
==============================================================================
--- trunk/tools/build/v2/engine/native.h (original)
+++ trunk/tools/build/v2/engine/native.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,9 +9,9 @@
 
 struct native_rule_t
 {
- char* name;
- argument_list* arguments;
- PARSE* procedure;
+ OBJECT * name;
+ argument_list * arguments;
+ PARSE * procedure;
     /* Version of the interface that the native rule provides.
        It's possible that we want to change the set parameter
        for existing native rule. In that case, version number
@@ -26,8 +26,8 @@
 /* MSVC debugger gets confused unless this is provided */
 typedef struct native_rule_t native_rule_t ;
 
-void declare_native_rule(char* module, char* rule, char** args,
- LIST*(*f)(PARSE*, FRAME*), int version);
+void declare_native_rule( const char * module, const char * rule, const char * * args,
+ LIST * (*f)( PARSE *, FRAME * ), int version );
 
 
 

Deleted: trunk/tools/build/v2/engine/newstr.c
==============================================================================
--- trunk/tools/build/v2/engine/newstr.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
+++ (empty file)
@@ -1,311 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-# include "jam.h"
-# include "newstr.h"
-# include "compile.h"
-# include <stddef.h>
-# include <stdlib.h>
-
-/*
- * newstr.c - string manipulation routines
- *
- * To minimize string copying, string creation, copying, and freeing
- * is done through newstr.
- *
- * External functions:
- *
- * newstr() - return a dynamically allocated copy of a string
- * copystr() - return a copy of a string previously returned by newstr()
- * freestr() - free a string returned by newstr() or copystr()
- * str_done() - free string tables
- *
- * Once a string is passed to newstr(), the returned string is readonly.
- *
- * This implementation builds a hash table of all strings, so that multiple
- * calls of newstr() on the same string allocate memory for the string once.
- * Strings are never actually freed.
- */
-
-struct hash_header
-{
- unsigned int hash;
- struct hash_item * next;
-};
-
-struct hash_item
-{
- struct hash_header header;
- char data[1];
-};
-
-#define ALLOC_ALIGNMENT ( sizeof( struct hash_item ) - sizeof( struct hash_header ) )
-
-typedef struct string_set
-{
- unsigned int num;
- unsigned int size;
- struct hash_item * * data;
-} string_set;
-
-static string_set strhash;
-static int strtotal = 0;
-static int strcount_in = 0;
-static int strcount_out = 0;
-
-
-/*
- * Immortal string allocator implementation speeds string allocation and cuts
- * down on internal fragmentation.
- */
-
-# define STRING_BLOCK 4096
-typedef struct strblock
-{
- struct strblock * next;
- char data[STRING_BLOCK];
-} strblock;
-
-static strblock * strblock_chain = 0;
-
-/* Storage remaining in the current strblock */
-static char * storage_start = 0;
-static char * storage_finish = 0;
-
-
-/*
- * allocate() - Allocate n bytes of immortal string storage.
- */
-
-static char * allocate( size_t n )
-{
-#ifdef BJAM_NEWSTR_NO_ALLOCATE
- return (char*)BJAM_MALLOC(n);
-#else
- /* See if we can grab storage from an existing block. */
- size_t remaining = storage_finish - storage_start;
- n = ((n + ALLOC_ALIGNMENT - 1) / ALLOC_ALIGNMENT) * ALLOC_ALIGNMENT;
- if ( remaining >= n )
- {
- char * result = storage_start;
- storage_start += n;
- return result;
- }
- else /* Must allocate a new block. */
- {
- strblock * new_block;
- size_t nalloc = n;
- if ( nalloc < STRING_BLOCK )
- nalloc = STRING_BLOCK;
-
- /* Allocate a new block and link into the chain. */
- new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof( new_block->data[0] ) );
- if ( new_block == 0 )
- return 0;
- new_block->next = strblock_chain;
- strblock_chain = new_block;
-
- /* Take future allocations out of the larger remaining space. */
- if ( remaining < nalloc - n )
- {
- storage_start = new_block->data + n;
- storage_finish = new_block->data + nalloc;
- }
- return new_block->data;
- }
-#endif
-}
-
-static unsigned int hash_keyval( const char * key )
-{
- unsigned int hash = 0;
- unsigned i;
- unsigned int len = strlen( key );
-
- for ( i = 0; i < len / sizeof( unsigned int ); ++i )
- {
- unsigned int val;
- memcpy( &val, key, sizeof( unsigned int ) );
- hash = hash * 2147059363 + val;
- key += sizeof( unsigned int );
- }
-
- {
- unsigned int val = 0;
- memcpy( &val, key, len % sizeof( unsigned int ) );
- hash = hash * 2147059363 + val;
- }
-
- hash += (hash >> 17);
-
- return hash;
-}
-
-static void string_set_init(string_set * set)
-{
- set->size = 0;
- set->num = 4;
- set->data = (struct hash_item * *)BJAM_MALLOC( set->num * sizeof( struct hash_item * ) );
- memset( set->data, 0, set->num * sizeof( struct hash_item * ) );
-}
-
-static void string_set_done(string_set * set)
-{
- BJAM_FREE( set->data );
-}
-
-static void string_set_resize(string_set *set)
-{
- unsigned i;
- string_set new_set;
- new_set.num = set->num * 2;
- new_set.size = set->size;
- new_set.data = (struct hash_item * *)BJAM_MALLOC( sizeof( struct hash_item * ) * new_set.num );
- memset(new_set.data, 0, sizeof(struct hash_item *) * new_set.num);
- for ( i = 0; i < set->num; ++i )
- {
- while ( set->data[i] )
- {
- int k = 0;
- struct hash_item * temp = set->data[i];
- unsigned pos = temp->header.hash % new_set.num;
- set->data[i] = temp->header.next;
- temp->header.next = new_set.data[pos];
- new_set.data[pos] = temp;
- }
- }
- BJAM_FREE( set->data );
- *set = new_set;
-}
-
-static const char * string_set_insert ( string_set * set, const char * string )
-{
- unsigned hash = hash_keyval( string );
- unsigned pos = hash % set->num;
- unsigned l;
- unsigned aligned;
-
- struct hash_item * result;
-
- for ( result = set->data[pos]; result; result = result->header.next )
- {
- if ( strcmp( result->data, string ) == 0 )
- {
- return result->data;
- }
- }
-
- if( set->size >= set->num )
- {
- string_set_resize( set );
- pos = hash % set->num;
- }
-
- l = strlen( string );
- result = (struct hash_item *)allocate( sizeof( struct hash_header ) + l + 1 );
- result->header.hash = hash;
- result->header.next = set->data[pos];
- memcpy( result->data, string, l + 1 );
- set->data[pos] = result;
- strtotal += l + 1;
- ++set->size;
-
- return result->data;
-}
-
-/*
- * newstr() - return a dynamically allocated copy of a string.
- */
-
-char * newstr( char * string )
-{
-#ifdef BJAM_NO_MEM_CACHE
- int l = strlen( string );
- char * m = (char *)BJAM_MALLOC( l + 1 );
-
- strtotal += l + 1;
- memcpy( m, string, l + 1 );
- return m;
-#else
- if ( ! strhash.data )
- string_set_init( &strhash );
-
- strcount_in += 1;
-
- return (char *)string_set_insert( &strhash, string );
-#endif
-}
-
-
-/*
- * copystr() - return a copy of a string previously returned by newstr()
- */
-
-char * copystr( char * s )
-{
-#ifdef BJAM_NO_MEM_CACHE
- return newstr( s );
-#else
- strcount_in += 1;
- return s;
-#endif
-}
-
-
-/*
- * freestr() - free a string returned by newstr() or copystr()
- */
-
-void freestr( char * s )
-{
-#ifdef BJAM_NO_MEM_CACHE
- BJAM_FREE( s );
-#endif
- if( s )
- strcount_out += 1;
-}
-
-
-/*
- * str_done() - free string tables.
- */
-
-void str_done()
-{
-
-#ifdef BJAM_NEWSTR_NO_ALLOCATE
-
- unsigned i;
-
- for ( i = 0; i < strhash.num; ++i )
- {
- while ( strhash.data[i] )
- {
- struct hash_item * item = strhash.data[i];
- strhash.data[i] = item->header.next;
- BJAM_FREE( item );
- }
- }
-
-#else
-
- /* Reclaim string blocks. */
- while ( strblock_chain != 0 )
- {
- strblock * n = strblock_chain->next;
- BJAM_FREE(strblock_chain);
- strblock_chain = n;
- }
-
-#endif
-
- string_set_done( &strhash );
-
- if ( DEBUG_MEM )
- printf( "%dK in strings\n", strtotal / 1024 );
-
- /* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
-}

Deleted: trunk/tools/build/v2/engine/newstr.h
==============================================================================
--- trunk/tools/build/v2/engine/newstr.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
+++ (empty file)
@@ -1,14 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/*
- * newstr.h - string manipulation routines
- */
-
-char * copystr ( char * );
-void freestr ( char * );
-char * newstr ( char * );
-void str_done();

Copied: trunk/tools/build/v2/engine/object.c (from r75606, /trunk/tools/build/v2/engine/newstr.c)
==============================================================================
--- /trunk/tools/build/v2/engine/newstr.c (original)
+++ trunk/tools/build/v2/engine/object.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -1,37 +1,39 @@
 /*
  * Copyright 1993, 1995 Christopher Seiwald.
+ * Copyright 2011 Steven Watanabe
  *
  * This file is part of Jam - see jam.c for Copyright information.
  */
 
 # include "jam.h"
-# include "newstr.h"
-# include "compile.h"
+# include "object.h"
 # include <stddef.h>
 # include <stdlib.h>
+# include <assert.h>
 
 /*
- * newstr.c - string manipulation routines
- *
- * To minimize string copying, string creation, copying, and freeing
- * is done through newstr.
+ * object.c - object manipulation routines
  *
  * External functions:
  *
- * newstr() - return a dynamically allocated copy of a string
- * copystr() - return a copy of a string previously returned by newstr()
- * freestr() - free a string returned by newstr() or copystr()
- * str_done() - free string tables
- *
- * Once a string is passed to newstr(), the returned string is readonly.
+ * object_new() - create an object from a string
+ * object_copy() - return a copy of an object
+ * object_free() - free an object
+ * object_str() - get the string value of an object
+ * object_done() - free string tables
  *
  * This implementation builds a hash table of all strings, so that multiple
- * calls of newstr() on the same string allocate memory for the string once.
+ * calls of object_new() on the same string allocate memory for the string once.
  * Strings are never actually freed.
  */
 
+#define OBJECT_MAGIC 0xa762e0e3u
+
 struct hash_header
 {
+#ifndef NDEBUG
+ unsigned int magic;
+#endif
     unsigned int hash;
     struct hash_item * next;
 };
@@ -169,7 +171,6 @@
     {
         while ( set->data[i] )
         {
- int k = 0;
             struct hash_item * temp = set->data[i];
             unsigned pos = temp->header.hash % new_set.num;
             set->data[i] = temp->header.next;
@@ -186,7 +187,6 @@
     unsigned hash = hash_keyval( string );
     unsigned pos = hash % set->num;
     unsigned l;
- unsigned aligned;
 
     struct hash_item * result;
 
@@ -208,6 +208,9 @@
     result = (struct hash_item *)allocate( sizeof( struct hash_header ) + l + 1 );
     result->header.hash = hash;
     result->header.next = set->data[pos];
+#ifndef NDEBUG
+ result->header.magic = OBJECT_MAGIC;
+#endif
     memcpy( result->data, string, l + 1 );
     set->data[pos] = result;
     strtotal += l + 1;
@@ -216,64 +219,121 @@
     return result->data;
 }
 
+
+static struct hash_item * object_get_item( OBJECT * obj )
+{
+ return (struct hash_item *)( (char *)obj - offsetof( struct hash_item, data ) );
+}
+
+
+static void object_validate( OBJECT * obj )
+{
+ assert( object_get_item( obj )->header.magic == OBJECT_MAGIC );
+}
+
+
 /*
- * newstr() - return a dynamically allocated copy of a string.
+ * object_new() - create an object from a string.
  */
 
-char * newstr( char * string )
+OBJECT * object_new( const char * string )
 {
 #ifdef BJAM_NO_MEM_CACHE
     int l = strlen( string );
- char * m = (char *)BJAM_MALLOC( l + 1 );
+ struct hash_item * m = (struct hash_item *)BJAM_MALLOC( sizeof(struct hash_header) + l + 1 );
 
     strtotal += l + 1;
- memcpy( m, string, l + 1 );
- return m;
+ memcpy( m->data, string, l + 1 );
+ m->header.magic = OBJECT_MAGIC;
+ return (OBJECT *)m->data;
 #else
     if ( ! strhash.data )
         string_set_init( &strhash );
 
     strcount_in += 1;
 
- return (char *)string_set_insert( &strhash, string );
+ return (OBJECT *)string_set_insert( &strhash, string );
 #endif
 }
 
 
 /*
- * copystr() - return a copy of a string previously returned by newstr()
+ * object_copy() - return a copy of an object
  */
 
-char * copystr( char * s )
+OBJECT * object_copy( OBJECT * obj )
 {
+ object_validate( obj );
 #ifdef BJAM_NO_MEM_CACHE
- return newstr( s );
+ return object_new( object_str( obj ) );
 #else
     strcount_in += 1;
- return s;
+ return obj;
+#endif
+}
+
+
+/*
+ * object_free() - free an object
+ */
+
+void object_free( OBJECT * obj )
+{
+ object_validate( obj );
+#ifdef BJAM_NO_MEM_CACHE
+ BJAM_FREE( object_get_item( obj ) );
 #endif
+ strcount_out += 1;
+}
+
+
+/*
+ * object_str() - return the
+ */
+
+const char * object_str( OBJECT * obj )
+{
+ object_validate( obj );
+ return (const char *)obj;
 }
 
 
 /*
- * freestr() - free a string returned by newstr() or copystr()
+ * object_equal() - compare two objects
  */
 
-void freestr( char * s )
+int object_equal( OBJECT * lhs, OBJECT * rhs )
 {
+ object_validate( lhs );
+ object_validate( rhs );
 #ifdef BJAM_NO_MEM_CACHE
- BJAM_FREE( s );
+ return strcmp(object_str(lhs), object_str(rhs)) == 0;
+#else
+ assert( (lhs == rhs) == ( strcmp(object_str(lhs), object_str(rhs)) == 0 ) );
+ return lhs == rhs;
 #endif
- if( s )
- strcount_out += 1;
 }
 
 
 /*
- * str_done() - free string tables.
+ * object_hash() - returns the hash value of an object
+ */
+
+unsigned int object_hash( OBJECT * obj )
+{
+ object_validate( obj );
+#ifdef BJAM_NO_MEM_CACHE
+ return hash_keyval( object_str( obj ) );
+#else
+ return object_get_item( obj )->header.hash;
+#endif
+}
+
+/*
+ * object_done() - free string tables.
  */
 
-void str_done()
+void object_done()
 {
 
 #ifdef BJAM_NEWSTR_NO_ALLOCATE

Copied: trunk/tools/build/v2/engine/object.h (from r75606, /trunk/tools/build/v2/engine/newstr.h)
==============================================================================
--- /trunk/tools/build/v2/engine/newstr.h (original)
+++ trunk/tools/build/v2/engine/object.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -1,14 +1,24 @@
 /*
- * Copyright 1993, 1995 Christopher Seiwald.
+ * Copyright 2011 Steven Watanabe
  *
  * This file is part of Jam - see jam.c for Copyright information.
  */
 
 /*
- * newstr.h - string manipulation routines
+ * object.h - object manipulation routines
  */
 
-char * copystr ( char * );
-void freestr ( char * );
-char * newstr ( char * );
-void str_done();
+#ifndef BOOST_JAM_OBJECT_H
+#define BOOST_JAM_OBJECT_H
+
+typedef struct _object OBJECT;
+
+OBJECT * object_new ( const char * );
+OBJECT * object_copy ( OBJECT * );
+void object_free ( OBJECT * );
+const char * object_str ( OBJECT * );
+void object_done ( void );
+int object_equal ( OBJECT *, OBJECT * );
+unsigned int object_hash ( OBJECT * );
+
+#endif

Modified: trunk/tools/build/v2/engine/output.c
==============================================================================
--- trunk/tools/build/v2/engine/output.c (original)
+++ trunk/tools/build/v2/engine/output.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -6,7 +6,7 @@
 
 #include "jam.h"
 #include "output.h"
-#include "newstr.h"
+#include "object.h"
 #include <stdio.h>
 
 #define bjam_out (stdout)
@@ -101,25 +101,25 @@
 }
 
 
-char * outf_int( int value )
+OBJECT * outf_int( int value )
 {
     char buffer[50];
     sprintf( buffer, "%i", value );
- return newstr( buffer );
+ return object_new( buffer );
 }
 
 
-char * outf_double( double value )
+OBJECT * outf_double( double value )
 {
     char buffer[50];
     sprintf( buffer, "%f", value );
- return newstr( buffer );
+ return object_new( buffer );
 }
 
 
-char * outf_time( time_t value )
+OBJECT * outf_time( time_t value )
 {
     char buffer[50];
     strftime( buffer, 49, "%Y-%m-%d %H:%M:%SZ", gmtime( &value ) );
- return newstr( buffer );
+ return object_new( buffer );
 }

Modified: trunk/tools/build/v2/engine/output.h
==============================================================================
--- trunk/tools/build/v2/engine/output.h (original)
+++ trunk/tools/build/v2/engine/output.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -7,6 +7,7 @@
 #ifndef BJAM_OUTPUT_H
 #define BJAM_OUTPUT_H
 
+#include "object.h"
 #include <time.h>
 
 #define EXIT_OK 0
@@ -22,8 +23,8 @@
     int exit_reason
     );
 
-char * outf_int( int value );
-char * outf_double( double value );
-char * outf_time( time_t value );
+OBJECT * outf_int( int value );
+OBJECT * outf_double( double value );
+OBJECT * outf_time( time_t value );
 
 #endif

Modified: trunk/tools/build/v2/engine/parse.c
==============================================================================
--- trunk/tools/build/v2/engine/parse.c (original)
+++ trunk/tools/build/v2/engine/parse.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -14,7 +14,7 @@
 #include "lists.h"
 #include "parse.h"
 #include "scan.h"
-#include "newstr.h"
+#include "object.h"
 #include "modules.h"
 #include "frames.h"
 
@@ -29,7 +29,7 @@
 
 static PARSE * yypsave;
 
-void parse_file( char * f, FRAME * frame )
+void parse_file( OBJECT * f, FRAME * frame )
 {
     /* Suspend scan of current file and push this new file in the stream. */
     yyfparse( f );
@@ -63,13 +63,13 @@
 
 
 PARSE * parse_make(
- LIST * (* func)( PARSE *, FRAME * ),
- PARSE * left,
- PARSE * right,
- PARSE * third,
- char * string,
- char * string1,
- int num )
+ LIST * (* func)( PARSE *, FRAME * ),
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ OBJECT * string,
+ OBJECT * string1,
+ int num )
 {
     PARSE * p = (PARSE *)BJAM_MALLOC( sizeof( PARSE ) );
 
@@ -85,13 +85,13 @@
 
     if ( left )
     {
- p->file = copystr( left->file );
+ p->file = object_copy( left->file );
         p->line = left->line;
     }
     else
     {
         yyinput_stream( &p->file, &p->line );
- p->file = copystr( p->file );
+ p->file = object_copy( p->file );
     }
 
     return p;
@@ -110,9 +110,9 @@
         return;
 
     if ( p->string )
- freestr( p->string );
+ object_free( p->string );
     if ( p->string1 )
- freestr( p->string1 );
+ object_free( p->string1 );
     if ( p->left )
         parse_free( p->left );
     if ( p->right )
@@ -120,9 +120,9 @@
     if ( p->third )
         parse_free( p->third );
     if ( p->rulename )
- freestr( p->rulename );
+ object_free( p->rulename );
     if ( p->file )
- freestr( p->file );
+ object_free( p->file );
 
     BJAM_FREE( (char *)p );
 }

Modified: trunk/tools/build/v2/engine/parse.h
==============================================================================
--- trunk/tools/build/v2/engine/parse.h (original)
+++ trunk/tools/build/v2/engine/parse.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -30,27 +30,27 @@
     PARSE * left;
     PARSE * right;
     PARSE * third;
- char * string;
- char * string1;
+ OBJECT * string;
+ OBJECT * string1;
     int num;
     int refs;
 /* module * module; */
- char * rulename;
- char * file;
+ OBJECT * rulename;
+ OBJECT * file;
     int line;
 };
 
-void parse_file( char *, FRAME * );
+void parse_file( OBJECT *, FRAME * );
 void parse_save( PARSE * );
 
 PARSE * parse_make(
- LIST * (* func)( PARSE *, FRAME * ),
- PARSE * left,
- PARSE * right,
- PARSE * third,
- char * string,
- char * string1,
- int num );
+ LIST * (* func)( PARSE *, FRAME * ),
+ PARSE * left,
+ PARSE * right,
+ PARSE * third,
+ OBJECT * string,
+ OBJECT * string1,
+ int num );
 
 void parse_refer ( PARSE * );
 void parse_free ( PARSE * );

Modified: trunk/tools/build/v2/engine/pathsys.h
==============================================================================
--- trunk/tools/build/v2/engine/pathsys.h (original)
+++ trunk/tools/build/v2/engine/pathsys.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -24,14 +24,15 @@
 # define PATHSYS_VP_20020211_H
 
 #include "strings.h"
+#include "object.h"
 
 typedef struct _pathname PATHNAME;
 typedef struct _pathpart PATHPART;
 
 struct _pathpart
 {
- char * ptr;
- int len;
+ const char * ptr;
+ int len;
 };
 
 struct _pathname
@@ -52,15 +53,15 @@
 void path_build( PATHNAME * f, string * file, int binding );
 void path_build1( PATHNAME * f, string * file );
 
-void path_parse( char * file, PATHNAME * f );
+void path_parse( const char * file, PATHNAME * f );
 void path_parent( PATHNAME * f );
 
 #ifdef NT
 
-/** Returns newstr-allocated string with long equivivalent of 'short_name'.
+/** Returns object_new-allocated string with long equivivalent of 'short_name'.
     If none exists -- i.e. 'short_path' is already long path, it's returned
     unaltered. */
-char * short_path_to_long_path( char * short_path );
+OBJECT * short_path_to_long_path( OBJECT * short_path );
 
 #endif
 
@@ -72,11 +73,11 @@
 
 /** Returns a new temporary name.
 */
-const char * path_tmpnam( void );
+OBJECT * path_tmpnam( void );
 
 /** Returns a new temporary path.
 */
-const char * path_tmpfile( void );
+OBJECT * path_tmpfile( void );
 #endif
 
 /** Give the first argument to 'main', return a full path to
@@ -86,6 +87,6 @@
 
     Implemented in jam.c
 */
-char * executable_path (char *argv0);
+char * executable_path (const char *argv0);
 
 #endif

Modified: trunk/tools/build/v2/engine/pathunix.c
==============================================================================
--- trunk/tools/build/v2/engine/pathunix.c (original)
+++ trunk/tools/build/v2/engine/pathunix.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -14,7 +14,7 @@
 # include "jam.h"
 # include "pathsys.h"
 # include "strings.h"
-# include "newstr.h"
+# include "object.h"
 # include "filesys.h"
 # include <time.h>
 # include <stdlib.h>
@@ -56,11 +56,11 @@
  * path_parse() - split a file name into dir/base/suffix/member
  */
 
-void path_parse( char * file, PATHNAME * f )
+void path_parse( const char * file, PATHNAME * f )
 {
- char * p;
- char * q;
- char * end;
+ const char * p;
+ const char * q;
+ const char * end;
 
     memset( (char *)f, 0, sizeof( *f ) );
 
@@ -382,15 +382,15 @@
     return len;
 }
 
-char* short_path_to_long_path(char* short_path)
+OBJECT * short_path_to_long_path( OBJECT * short_path )
 {
     char buffer2[_MAX_PATH];
- int ret = ShortPathToLongPath(short_path, buffer2, _MAX_PATH);
+ int ret = ShortPathToLongPath( object_str( short_path ), buffer2, _MAX_PATH );
 
     if (ret)
- return newstr(buffer2);
+ return object_new( buffer2 );
     else
- return newstr(short_path);
+ return object_copy( short_path );
 }
 
 #endif
@@ -424,7 +424,7 @@
     return path_tmpdir_result;
 }
 
-const char * path_tmpnam(void)
+OBJECT * path_tmpnam(void)
 {
     char name_buffer[64];
     # ifdef OS_NT
@@ -436,18 +436,21 @@
     if (0 == c1) c1 = time(0)&0xffff;
     c1 += 1;
     sprintf(name_buffer,"jam%lx%lx.000",c0,c1);
- return newstr(name_buffer);
+ return object_new(name_buffer);
 }
 
-const char * path_tmpfile(void)
+OBJECT * path_tmpfile(void)
 {
- const char * result = 0;
+ OBJECT * result = 0;
+ OBJECT * tmpnam;
 
     string file_path;
     string_copy(&file_path,path_tmpdir());
     string_push_back(&file_path,PATH_DELIM);
- string_append(&file_path,path_tmpnam());
- result = newstr(file_path.value);
+ tmpnam = path_tmpnam();
+ string_append(&file_path,object_str(tmpnam));
+ object_free(tmpnam);
+ result = object_new(file_path.value);
     string_free(&file_path);
 
     return result;

Modified: trunk/tools/build/v2/engine/pathvms.c
==============================================================================
--- trunk/tools/build/v2/engine/pathvms.c (original)
+++ trunk/tools/build/v2/engine/pathvms.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -41,11 +41,11 @@
  * path_parse() - split a file name into dir/base/suffix/member.
  */
 
-void path_parse( char * file, PATHNAME * f )
+void path_parse( const char * file, PATHNAME * f )
 {
- char * p;
- char * q;
- char * end;
+ const char * p;
+ const char * q;
+ const char * end;
 
     memset( (char *)f, 0, sizeof( *f ) );
 
@@ -163,12 +163,12 @@
 
     struct
     {
- char * ptr;
+ const char * ptr;
         int len;
     } dev, dir;
 };
 
-static char * strnchr( char * buf, int c, int len )
+static const char * strnchr( const char * buf, int c, int len )
 {
     while ( len-- )
         if ( *buf && ( *buf++ == c ) )
@@ -177,9 +177,9 @@
 }
 
 
-static void dir_flags( char * buf, int len, struct dirinf * i )
+static void dir_flags( const char * buf, int len, struct dirinf * i )
 {
- char * p;
+ const char * p;
 
     if ( !buf || !len )
     {

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

Modified: trunk/tools/build/v2/engine/pwd.h
==============================================================================
--- trunk/tools/build/v2/engine/pwd.h (original)
+++ trunk/tools/build/v2/engine/pwd.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -5,6 +5,7 @@
 #ifndef PWD_H
 #define PWD_H
 
-LIST* pwd(void);
+LIST * pwd( void );
+void pwd_done( void );
 
 #endif

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

Modified: trunk/tools/build/v2/engine/regexp.h
==============================================================================
--- trunk/tools/build/v2/engine/regexp.h (original)
+++ trunk/tools/build/v2/engine/regexp.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,8 +9,8 @@
 
 #define NSUBEXP 10
 typedef struct regexp {
- char *startp[NSUBEXP];
- char *endp[NSUBEXP];
+ const char *startp[NSUBEXP];
+ const char *endp[NSUBEXP];
     char regstart; /* Internal use only. */
     char reganch; /* Internal use only. */
     char *regmust; /* Internal use only. */
@@ -18,9 +18,9 @@
     char program[1]; /* Unwarranted chumminess with compiler. */
 } regexp;
 
-regexp *regcomp( char *exp );
-int regexec( regexp *prog, char *string );
-void regerror( char *s );
+regexp *regcomp( const char *exp );
+int regexec( regexp *prog, const char *string );
+void regerror( const char *s );
 
 /*
  * The first byte of the regexp internal "program" is actually this magic

Modified: trunk/tools/build/v2/engine/rules.c
==============================================================================
--- trunk/tools/build/v2/engine/rules.c (original)
+++ trunk/tools/build/v2/engine/rules.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,7 +9,7 @@
 # include "parse.h"
 # include "variable.h"
 # include "rules.h"
-# include "newstr.h"
+# include "object.h"
 # include "hash.h"
 # include "modules.h"
 # include "search.h"
@@ -51,7 +51,7 @@
 
 struct _located_target
 {
- char * file_name;
+ OBJECT * file_name;
     TARGET * target;
 };
 typedef struct _located_target LOCATED_TARGET ;
@@ -83,7 +83,7 @@
  * target_module.
  */
 
-static RULE * enter_rule( char * rulename, module_t * target_module )
+static RULE * enter_rule( OBJECT * rulename, module_t * target_module )
 {
     RULE rule;
     RULE * r = &rule;
@@ -92,7 +92,7 @@
 
     if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) )
     {
- r->name = newstr( rulename ); /* never freed */
+ r->name = object_copy( rulename );
         r->procedure = (PARSE *)0;
         r->module = 0;
         r->actions = 0;
@@ -116,7 +116,7 @@
 static RULE * define_rule
 (
     module_t * src_module,
- char * rulename,
+ OBJECT * rulename,
     module_t * target_module
 )
 {
@@ -133,8 +133,8 @@
 
 void rule_free( RULE * r )
 {
- freestr( r->name );
- r->name = "";
+ object_free( r->name );
+ r->name = 0;
     if ( r->procedure )
         parse_free( r->procedure );
     r->procedure = 0;
@@ -144,6 +144,11 @@
     if ( r->actions )
         actions_free( r->actions );
     r->actions = 0;
+#ifdef HAVE_PYTHON
+ if ( r->python_function )
+ Py_DECREF( r->python_function );
+ r->python_function = 0;
+#endif
 }
 
 
@@ -151,7 +156,7 @@
  * bindtarget() - return pointer to TARGET, creating it if necessary.
  */
 
-TARGET * bindtarget( char const * target_name )
+TARGET * bindtarget( OBJECT * target_name )
 {
     TARGET target;
     TARGET * t = &target;
@@ -159,20 +164,19 @@
     if ( !targethash )
         targethash = hashinit( sizeof( TARGET ), "targets" );
 
- /* Perforce added const everywhere. No time to merge that change. */
 #ifdef NT
- target_name = short_path_to_long_path( (char *)target_name );
+ target_name = short_path_to_long_path( target_name );
 #endif
- t->name = (char *)target_name;
+ t->name = target_name;
 
     if ( hashenter( targethash, (HASHDATA * *)&t ) )
     {
         memset( (char *)t, '\0', sizeof( *t ) );
- t->name = newstr( (char *)target_name ); /* never freed */
- t->boundname = copystr( t->name ); /* default for T_FLAG_NOTFILE */
+ t->name = object_copy( target_name );
+ t->boundname = object_copy( t->name ); /* default for T_FLAG_NOTFILE */
     }
 #ifdef NT
- freestr( (char *)target_name );
+ object_free( target_name );
 #endif
 
     return t;
@@ -188,13 +192,13 @@
         SETTINGS * s = t->settings;
         for ( ; s ; s = s->next )
         {
- if ( strcmp( s->symbol, "LOCATE" ) == 0 )
+ if ( strcmp( object_str( s->symbol ), "LOCATE" ) == 0 )
             {
                 pushsettings( t->settings );
                 /* We are binding a target with explicit LOCATE. So third
                  * argument is of no use: nothing will be returned through it.
                  */
- freestr( t->boundname );
+ object_free( t->boundname );
                 t->boundname = search( t->name, &t->time, 0, 0 );
                 popsettings( t->settings );
                 break;
@@ -213,10 +217,10 @@
 
 /* TODO: It is probably not a good idea to use functions in other modules like
   this. */
-void call_bind_rule( char * target, char * boundname );
+void call_bind_rule( OBJECT * target, OBJECT * boundname );
 
 
-TARGET * search_for_target ( char * name, LIST * search_path )
+TARGET * search_for_target ( OBJECT * name, LIST * search_path )
 {
     PATHNAME f[1];
     string buf[1];
@@ -228,20 +232,21 @@
 
     string_new( buf );
 
- path_parse( name, f );
+ path_parse( object_str( name ), f );
 
     f->f_grist.ptr = 0;
     f->f_grist.len = 0;
 
     while ( search_path )
     {
- f->f_root.ptr = search_path->string;
- f->f_root.len = strlen( search_path->string );
+ OBJECT * key;
+ f->f_root.ptr = object_str( search_path->value );
+ f->f_root.len = strlen( object_str( search_path->value ) );
 
         string_truncate( buf, 0 );
         path_build( f, buf, 1 );
 
- lt.file_name = buf->value ;
+ lt.file_name = key = object_new( buf->value ) ;
 
         if ( !located_targets )
             located_targets = hashinit( sizeof(LOCATED_TARGET),
@@ -249,10 +254,13 @@
 
         if ( hashcheck( located_targets, (HASHDATA * *)&lta ) )
         {
+ object_free( key );
+ string_free( buf );
             return lta->target;
         }
 
- timestamp( buf->value, &time );
+ timestamp( key, &time );
+ object_free( key );
         if ( time )
         {
             found = 1;
@@ -264,17 +272,20 @@
 
     if ( !found )
     {
+ OBJECT * key;
         f->f_root.ptr = 0;
         f->f_root.len = 0;
 
         string_truncate( buf, 0 );
         path_build( f, buf, 1 );
 
- timestamp( buf->value, &time );
+ key = object_new( buf->value );
+ timestamp( key, &time );
+ object_free( key );
     }
 
     result = bindtarget( name );
- result->boundname = newstr( buf->value );
+ result->boundname = object_new( buf->value );
     result->time = time;
     result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;
 
@@ -296,8 +307,8 @@
 {
     TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
     memset( (char *)t, '\0', sizeof( *t ) );
- t->name = copystr( ot->name );
- t->boundname = copystr( t->name );
+ t->name = object_copy( ot->name );
+ t->boundname = object_copy( t->name );
 
     t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
 
@@ -309,7 +320,7 @@
  * touch_target() - mark a target to simulate being new.
  */
 
-void touch_target( char * t )
+void touch_target( OBJECT * t )
 {
     bindtarget( t )->flags |= T_FLAG_TOUCHED;
 }
@@ -326,7 +337,7 @@
 TARGETS * targetlist( TARGETS * chain, LIST * target_names )
 {
     for ( ; target_names; target_names = list_next( target_names ) )
- chain = targetentry( chain, bindtarget( target_names->string ) );
+ chain = targetentry( chain, bindtarget( target_names->value ) );
     return chain;
 }
 
@@ -418,13 +429,13 @@
  * the head of the settings chain.
  */
 
-SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
+SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol, LIST * value )
 {
     SETTINGS * v;
 
     /* Look for previous settings. */
     for ( v = head; v; v = v->next )
- if ( !strcmp( v->symbol, symbol ) )
+ if ( object_equal( v->symbol, symbol ) )
             break;
 
     /* If not previously set, alloc a new. */
@@ -439,7 +450,7 @@
         else
             v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
 
- v->symbol = newstr( symbol );
+ v->symbol = object_copy( symbol );
         v->value = value;
         v->next = head;
         v->multiple = 0;
@@ -537,7 +548,7 @@
     while ( v )
     {
         SETTINGS * n = v->next;
- freestr( v->symbol );
+ object_free( v->symbol );
         list_free( v->value );
         v->next = settings_freelist;
         settings_freelist = v;
@@ -549,13 +560,13 @@
 static void freetarget( void * xt, void * data )
 {
     TARGET * t = (TARGET *)xt;
- if ( t->name ) freestr ( t->name );
- if ( t->boundname ) freestr ( t->boundname );
- if ( t->settings ) freesettings( t->settings );
- if ( t->depends ) freetargets ( t->depends );
- if ( t->dependants ) freetargets ( t->dependants );
- if ( t->parents ) freetargets ( t->parents );
- if ( t->actions ) freeactions ( t->actions );
+ if ( t->name ) object_free ( t->name );
+ if ( t->boundname ) object_free ( t->boundname );
+ if ( t->settings ) freesettings( t->settings );
+ if ( t->depends ) freetargets ( t->depends );
+ if ( t->dependants ) freetargets ( t->dependants );
+ if ( t->parents ) freetargets ( t->parents );
+ if ( t->actions ) freeactions ( t->actions );
 
     if ( t->includes )
     {
@@ -637,7 +648,7 @@
 {
     if ( --a->reference_count <= 0 )
     {
- freestr( a->command );
+ object_free( a->command );
         list_free( a->bindlist );
         BJAM_FREE( a );
     }
@@ -669,16 +680,16 @@
  * global module.
  */
 
-static char * global_rule_name( RULE * r )
+static OBJECT * global_rule_name( RULE * r )
 {
     if ( r->module == root_module() )
- return copystr( r->name );
+ return object_copy( r->name );
 
     {
         char name[4096] = "";
- strncat( name, r->module->name, sizeof( name ) - 1 );
- strncat( name, r->name, sizeof( name ) - 1 );
- return newstr( name);
+ strncat( name, object_str( r->module->name ), sizeof( name ) - 1 );
+ strncat( name, object_str( r->name ), sizeof( name ) - 1 );
+ return object_new( name );
     }
 }
 
@@ -694,9 +705,9 @@
         return r;
 
     {
- char * name = global_rule_name( r );
+ OBJECT * name = global_rule_name( r );
         RULE * result = define_rule( r->module, name, root_module() );
- freestr( name );
+ object_free( name );
         return result;
     }
 }
@@ -708,7 +719,7 @@
  * exported to the global module as modulename.rulename.
  */
 
-RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported )
+RULE * new_rule_body( module_t * m, OBJECT * rulename, argument_list * args, PARSE * procedure, int exported )
 {
     RULE * local = define_rule( m, rulename, m );
     local->exported = exported;
@@ -736,10 +747,10 @@
 }
 
 
-static rule_actions * actions_new( char * command, LIST * bindlist, int flags )
+static rule_actions * actions_new( OBJECT * command, LIST * bindlist, int flags )
 {
     rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
- result->command = copystr( command );
+ result->command = object_copy( command );
     result->bindlist = bindlist;
     result->flags = flags;
     result->reference_count = 0;
@@ -747,7 +758,7 @@
 }
 
 
-RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags )
+RULE * new_rule_actions( module_t * m, OBJECT * rulename, OBJECT * command, LIST * bindlist, int flags )
 {
     RULE * local = define_rule( m, rulename, m );
     RULE * global = global_rule( local );
@@ -764,7 +775,7 @@
  * modules, look in module 'name1' for rule 'name2'.
  */
 
-RULE * lookup_rule( char * rulename, module_t * m, int local_only )
+RULE * lookup_rule( OBJECT * rulename, module_t * m, int local_only )
 {
     RULE rule;
     RULE * r = &rule;
@@ -781,15 +792,24 @@
     else if ( !local_only && m->imported_modules )
     {
         /* Try splitting the name into module and rule. */
- char *p = strchr( r->name, '.' ) ;
+ char *p = strchr( object_str( r->name ), '.' ) ;
         if ( p )
         {
- *p = '\0';
+ string buf[1];
+ OBJECT * module_part;
+ OBJECT * rule_part;
+ string_new( buf );
+ string_append_range( buf, object_str( r->name ), p );
+ module_part = object_new( buf->value );
+ rule_part = object_new( p + 1 );
+ r->name = module_part;
             /* Now, r->name keeps the module name, and p+1 keeps the rule name.
              */
             if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
- result = lookup_rule( p + 1, bindmodule( rulename ), 1 );
- *p = '.';
+ result = lookup_rule( rule_part, bindmodule( module_part ), 1 );
+ object_free( rule_part );
+ object_free( module_part );
+ string_free( buf );
         }
     }
 
@@ -817,7 +837,7 @@
 }
 
 
-RULE * bindrule( char * rulename, module_t * m )
+RULE * bindrule( OBJECT * rulename, module_t * m )
 {
     RULE * result = lookup_rule( rulename, m, 0 );
     if ( !result )
@@ -832,7 +852,7 @@
 }
 
 
-RULE * import_rule( RULE * source, module_t * m, char * name )
+RULE * import_rule( RULE * source, module_t * m, OBJECT * name )
 {
     RULE * dest = define_rule( source->module, name, m );
     set_rule_body( dest, source->arguments, source->procedure );

Modified: trunk/tools/build/v2/engine/rules.h
==============================================================================
--- trunk/tools/build/v2/engine/rules.h (original)
+++ trunk/tools/build/v2/engine/rules.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -62,10 +62,10 @@
 /* Build actions corresponding to a rule. */
 struct rule_actions
 {
- int reference_count;
- char * command; /* command string from ACTIONS */
- LIST * bindlist;
- int flags; /* modifiers on ACTIONS */
+ int reference_count;
+ OBJECT * command; /* command string from ACTIONS */
+ LIST * bindlist;
+ int flags; /* modifiers on ACTIONS */
 
 #define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
 #define RULE_TOGETHER 0x02 /* combine actions on single target */
@@ -80,7 +80,7 @@
 
 struct _rule
 {
- char * name;
+ OBJECT * name;
     PARSE * procedure; /* parse tree from RULE */
     argument_list * arguments; /* argument checking info, or NULL for unchecked
                                  */
@@ -118,7 +118,7 @@
 struct _settings
 {
     SETTINGS * next;
- char * symbol; /* symbol name for var_set() */
+ OBJECT * symbol; /* symbol name for var_set() */
     LIST * value; /* symbol value for var_set() */
     int multiple;
 };
@@ -134,8 +134,8 @@
 /* TARGET - an entity (e.g. a file) that can be built. */
 struct _target
 {
- char * name;
- char * boundname; /* if search() relocates target */
+ OBJECT * name;
+ OBJECT * boundname; /* if search() relocates target */
     ACTIONS * actions; /* rules to execute, if any */
     SETTINGS * settings; /* variables to define */
 
@@ -236,7 +236,7 @@
     TARGETS * parents; /* used by make1() for completion */
     char * cmds; /* type-punned command list */
 
- char * failed;
+ const char * failed;
 };
 
 
@@ -244,7 +244,7 @@
 void action_free ( ACTION * );
 ACTIONS * actionlist ( ACTIONS *, ACTION * );
 void freeactions ( ACTIONS * );
-SETTINGS * addsettings ( SETTINGS *, int flag, char * symbol, LIST * value );
+SETTINGS * addsettings ( SETTINGS *, int flag, OBJECT * symbol, LIST * value );
 void pushsettings ( SETTINGS * );
 void popsettings ( SETTINGS * );
 SETTINGS * copysettings ( SETTINGS * );
@@ -258,23 +258,23 @@
 void args_refer( argument_list * );
 
 /* Rule related functions. */
-RULE * bindrule ( char * rulename, module_t * );
-RULE * import_rule ( RULE * source, module_t *, char * name );
-RULE * new_rule_body ( module_t *, char * rulename, argument_list *, PARSE * procedure, int exprt );
-RULE * new_rule_actions( module_t *, char * rulename, char * command, LIST * bindlist, int flags );
+RULE * bindrule ( OBJECT * rulename, module_t * );
+RULE * import_rule ( RULE * source, module_t *, OBJECT * name );
+RULE * new_rule_body ( module_t *, OBJECT * rulename, argument_list *, PARSE * procedure, int exprt );
+RULE * new_rule_actions( module_t *, OBJECT * rulename, OBJECT * command, LIST * bindlist, int flags );
 void rule_free ( RULE * );
 
 /* Target related functions. */
 void bind_explicitly_located_targets();
-TARGET * bindtarget ( char const * target_name );
+TARGET * bindtarget ( OBJECT * target_name );
 TARGET * copytarget ( TARGET const * t );
 void freetargets ( TARGETS * );
-TARGET * search_for_target ( char * name, LIST * search_path );
+TARGET * search_for_target ( OBJECT * name, LIST * search_path );
 TARGETS * targetchain ( TARGETS * chain, TARGETS * );
 TARGETS * targetentry ( TARGETS * chain, TARGET * );
 void target_include ( TARGET * including, TARGET * included );
 TARGETS * targetlist ( TARGETS * chain, LIST * target_names );
-void touch_target ( char * t );
+void touch_target ( OBJECT * t );
 void clear_includes ( TARGET * );
 
 /* Final module cleanup. */

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

Modified: trunk/tools/build/v2/engine/scan.h
==============================================================================
--- trunk/tools/build/v2/engine/scan.h (original)
+++ trunk/tools/build/v2/engine/scan.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -31,25 +31,26 @@
 
 typedef struct _YYSTYPE
 {
- int type;
- char * string;
- PARSE * parse;
- LIST * list;
- int number;
- char * file;
- int line;
+ int type;
+ OBJECT * string;
+ PARSE * parse;
+ LIST * list;
+ int number;
+ OBJECT * file;
+ int line;
+ const char * keyword;
 } YYSTYPE;
 
 extern YYSTYPE yylval;
 
 void yymode( int n );
-void yyerror( char * s );
+void yyerror( const char * s );
 int yyanyerrors();
-void yyfparse( char * s );
+void yyfparse( OBJECT * s );
 int yyline();
 int yylex();
 int yyparse();
-void yyinput_stream( char * * name, int * line );
+void yyinput_stream( OBJECT * * name, int * line );
 
 # define SCAN_NORMAL 0 /* normal parsing */
 # define SCAN_STRING 1 /* look only for matching } */

Modified: trunk/tools/build/v2/engine/search.c
==============================================================================
--- trunk/tools/build/v2/engine/search.c (original)
+++ trunk/tools/build/v2/engine/search.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -16,7 +16,7 @@
 #include "timestamp.h"
 #include "pathsys.h"
 #include "variable.h"
-#include "newstr.h"
+#include "object.h"
 #include "compile.h"
 #include "strings.h"
 #include "hash.h"
@@ -26,8 +26,8 @@
 
 typedef struct _binding
 {
- char * binding;
- char * target;
+ OBJECT * binding;
+ OBJECT * target;
 } BINDING;
 
 static struct hash *explicit_bindings = 0;
@@ -35,22 +35,17 @@
 
 void call_bind_rule
 (
- char * target_,
- char * boundname_
+ OBJECT * target_,
+ OBJECT * boundname_
 )
 {
- LIST * bind_rule = var_get( "BINDRULE" );
+ OBJECT * varname = object_new( "BINDRULE" );
+ LIST * bind_rule = var_get( varname );
+ object_free( varname );
     if ( bind_rule )
     {
- /* No guarantee that the target is an allocated string, so be on the
- * safe side.
- */
- char * target = copystr( target_ );
-
- /* Likewise, do not rely on implementation details of newstr.c: allocate
- * a copy of boundname.
- */
- char * boundname = copystr( boundname_ );
+ OBJECT * target = object_copy( target_ );
+ OBJECT * boundname = object_copy( boundname_ );
         if ( boundname && target )
         {
             /* Prepare the argument list. */
@@ -62,7 +57,7 @@
 
             lol_add( frame->args, list_new( L0, boundname ) );
             if ( lol_get( frame->args, 1 ) )
- list_free( evaluate_rule( bind_rule->string, frame ) );
+ list_free( evaluate_rule( bind_rule->value, frame ) );
 
             /* Clean up */
             frame_free( frame );
@@ -70,9 +65,9 @@
         else
         {
             if ( boundname )
- freestr( boundname );
+ object_free( boundname );
             if ( target )
- freestr( target );
+ object_free( target );
         }
     }
 }
@@ -93,21 +88,22 @@
  * the third argument.
  */
 
-char *
+OBJECT *
 search(
- char *target,
+ OBJECT * target,
     time_t *time,
- char **another_target,
+ OBJECT * * another_target,
     int file
 )
 {
     PATHNAME f[1];
- LIST *varlist;
- string buf[1];
- int found = 0;
+ LIST * varlist;
+ string buf[1];
+ int found = 0;
     /* Will be set to 1 if target location is specified via LOCATE. */
- int explicitly_located = 0;
- char *boundname = 0;
+ int explicitly_located = 0;
+ OBJECT * boundname = 0;
+ OBJECT * varname;
 
     if ( another_target )
         *another_target = 0;
@@ -119,55 +115,67 @@
     string_new( buf );
     /* Parse the filename */
 
- path_parse( target, f );
+ path_parse( object_str( target ), f );
 
     f->f_grist.ptr = 0;
     f->f_grist.len = 0;
 
- if ( ( varlist = var_get( "LOCATE" ) ) )
- {
- f->f_root.ptr = varlist->string;
- f->f_root.len = strlen( varlist->string );
+ varname = object_new( "LOCATE" );
+ varlist = var_get( varname );
+ object_free( varname );
+ if ( varlist )
+ {
+ OBJECT * key;
+ f->f_root.ptr = object_str( varlist->value );
+ f->f_root.len = strlen( object_str( varlist->value ) );
 
         path_build( f, buf, 1 );
 
         if ( DEBUG_SEARCH )
- printf( "locate %s: %s\n", target, buf->value );
+ printf( "locate %s: %s\n", object_str( target ), buf->value );
 
         explicitly_located = 1;
 
- timestamp( buf->value, time );
+ key = object_new( buf->value );
+ timestamp( key, time );
+ object_free( key );
         found = 1;
     }
- else if ( ( varlist = var_get( "SEARCH" ) ) )
+ else if ( ( varname = object_new( "SEARCH" ),
+ varlist = var_get( varname ),
+ object_free( varname ),
+ varlist ) )
     {
         while ( varlist )
         {
             BINDING b, *ba = &b;
             file_info_t *ff;
+ OBJECT * key;
 
- f->f_root.ptr = varlist->string;
- f->f_root.len = strlen( varlist->string );
+ f->f_root.ptr = object_str( varlist->value );
+ f->f_root.len = strlen( object_str( varlist->value ) );
 
             string_truncate( buf, 0 );
             path_build( f, buf, 1 );
 
             if ( DEBUG_SEARCH )
- printf( "search %s: %s\n", target, buf->value );
+ printf( "search %s: %s\n", object_str( target ), buf->value );
 
- ff = file_query(buf->value);
- timestamp( buf->value, time );
+ key = object_new( buf->value );
+ ff = file_query( key );
+ timestamp( key, time );
 
- b.binding = buf->value;
+ b.binding = key;
 
             if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
             {
                 if ( DEBUG_SEARCH )
                     printf(" search %s: found explicitly located target %s\n",
- target, ba->target);
+ object_str( target ), object_str( ba->target ) );
                 if ( another_target )
                     *another_target = ba->target;
                 found = 1;
+ object_free( key );
                 break;
             }
             else if ( ff && ff->time )
@@ -175,9 +183,11 @@
                 if ( !file || ff->is_file )
                 {
                     found = 1;
+ object_free( key );
                     break;
                 }
             }
+ object_free( key );
 
             varlist = list_next( varlist );
         }
@@ -188,6 +198,7 @@
         /* Look for the obvious */
         /* This is a questionable move. Should we look in the */
         /* obvious place if SEARCH is set? */
+ OBJECT * key;
 
         f->f_root.ptr = 0;
         f->f_root.len = 0;
@@ -196,12 +207,14 @@
         path_build( f, buf, 1 );
 
         if ( DEBUG_SEARCH )
- printf( "search %s: %s\n", target, buf->value );
+ printf( "search %s: %s\n", object_str( target ), buf->value );
 
- timestamp( buf->value, time );
+ key = object_new( buf->value );
+ timestamp( key, time );
+ object_free( key );
     }
 
- boundname = newstr( buf->value );
+ boundname = object_new( buf->value );
     string_free( buf );
 
     if ( explicitly_located )
@@ -215,7 +228,7 @@
            compatibility, though. */
         if ( hashenter( explicit_bindings, (HASHDATA * *)&ba ) )
         {
- ba->binding = copystr( boundname );
+ ba->binding = object_copy( boundname );
         }
     }
 
@@ -229,7 +242,7 @@
 static void free_binding( void * xbinding, void * data )
 {
     BINDING * binding = (BINDING *)xbinding;
- freestr( binding->binding );
+ object_free( binding->binding );
 }
 
 void search_done( void )

Modified: trunk/tools/build/v2/engine/search.h
==============================================================================
--- trunk/tools/build/v2/engine/search.h (original)
+++ trunk/tools/build/v2/engine/search.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,5 +8,13 @@
  * search.h - find a target along $(SEARCH) or $(LOCATE)
  */
 
-char *search( char *target, time_t *time, char **another_target, int file );
+#ifndef SEARCH_SW20111118_H
+#define SEARCH_SW20111118_H
+
+#include "object.h"
+#include <time.h>
+
+OBJECT * search( OBJECT * target, time_t * time, OBJECT * * another_target, int file );
 void search_done( void );
+
+#endif

Modified: trunk/tools/build/v2/engine/subst.c
==============================================================================
--- trunk/tools/build/v2/engine/subst.c (original)
+++ trunk/tools/build/v2/engine/subst.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -3,7 +3,7 @@
 #include "regexp.h"
 #include "hash.h"
 
-#include "newstr.h"
+#include "object.h"
 #include "lists.h"
 #include "parse.h"
 #include "compile.h"
@@ -11,14 +11,14 @@
 
 struct regex_entry
 {
- const char* pattern;
+ OBJECT* pattern;
     regexp* regex;
 };
 typedef struct regex_entry regex_entry;
 
 static struct hash* regex_hash;
 
-regexp* regex_compile( const char* pattern )
+regexp* regex_compile( OBJECT* pattern )
 {
     regex_entry entry, *e = &entry;
     entry.pattern = pattern;
@@ -28,7 +28,7 @@
 
     if ( hashenter( regex_hash, (HASHDATA **)&e ) )
     {
- e->pattern = newstr( (char*)pattern );
+ e->pattern = object_copy( pattern );
         e->regex = regcomp( (char*)pattern );
     }
 
@@ -46,8 +46,8 @@
   if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) )
   {
 
- const char* source = arg1->string;
- const char* pattern = list_next(arg1)->string;
+ const char* source = object_str( arg1->value );
+ OBJECT * pattern = list_next(arg1)->value;
       regexp* repat = regex_compile( pattern );
 
       if ( regexec( repat, (char*)source) )
@@ -58,10 +58,10 @@
           {
 # define BUFLEN 4096
               char buf[BUFLEN + 1];
- const char* in = subst->string;
+ const char* in = object_str( subst->value );
               char* out = buf;
 
- for ( in = subst->string; *in && out < buf + BUFLEN; ++in )
+ for ( in = object_str( subst->value ); *in && out < buf + BUFLEN; ++in )
               {
                   if ( *in == '\\' || *in == '$' )
                   {
@@ -86,7 +86,7 @@
               }
               *out = 0;
 
- result = list_new( result, newstr( buf ) );
+ result = list_new( result, object_new( buf ) );
 #undef BUFLEN
           }
       }
@@ -99,7 +99,7 @@
 static void free_regex( void * xregex, void * data )
 {
     regex_entry * regex = (regex_entry *)xregex;
- freestr( (char *)regex->pattern );
+ object_free( regex->pattern );
     BJAM_FREE( regex->regex );
 }
 

Modified: trunk/tools/build/v2/engine/timestamp.c
==============================================================================
--- trunk/tools/build/v2/engine/timestamp.c (original)
+++ trunk/tools/build/v2/engine/timestamp.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -16,7 +16,7 @@
 # include "filesys.h"
 # include "pathsys.h"
 # include "timestamp.h"
-# include "newstr.h"
+# include "object.h"
 # include "strings.h"
 
 /*
@@ -32,12 +32,12 @@
 typedef struct _binding BINDING;
 
 struct _binding {
- char *name;
- short flags;
+ OBJECT * name;
+ short flags;
 
 # define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
 
- short progress;
+ short progress;
 
 # define BIND_INIT 0 /* never seen */
 # define BIND_NOENTRY 1 /* timestamp requested but file never found */
@@ -45,11 +45,11 @@
 # define BIND_MISSING 3 /* file found but can't get timestamp */
 # define BIND_FOUND 4 /* file found and time stamped */
 
- time_t time; /* update time - 0 if not exist */
+ time_t time; /* update time - 0 if not exist */
 };
 
 static struct hash * bindhash = 0;
-static void time_enter( void *, char *, int, time_t );
+static void time_enter( void *, OBJECT *, int, time_t );
 
 static char * time_progress[] =
 {
@@ -65,7 +65,7 @@
  * timestamp() - return timestamp on a file, if present.
  */
 
-void timestamp( char * target, time_t * time )
+void timestamp( OBJECT * target, time_t * time )
 {
     PROFILE_ENTER( timestamp );
 
@@ -80,7 +80,7 @@
 #endif
 
 #ifdef DOWNSHIFT_PATHS
- string_copy( &path, target );
+ string_copy( &path, object_str( target ) );
     p = path.value;
 
     do
@@ -94,7 +94,7 @@
     }
     while ( *p++ );
 
- target = path.value;
+ target = object_new( path.value );
 #endif /* #ifdef DOWNSHIFT_PATHS */
     string_new( buf );
 
@@ -107,7 +107,7 @@
     b->progress = BIND_INIT;
 
     if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( target ); /* never freed */
+ b->name = object_copy( target ); /* never freed */
 
     if ( b->progress != BIND_INIT )
         goto afterscanning;
@@ -115,30 +115,33 @@
     b->progress = BIND_NOENTRY;
 
     /* Not found - have to scan for it. */
- path_parse( target, &f1 );
+ path_parse( object_str( target ), &f1 );
 
     /* Scan directory if not already done so. */
     {
         BINDING binding;
         BINDING * b = &binding;
+ OBJECT * name;
 
         f2 = f1;
         f2.f_grist.len = 0;
         path_parent( &f2 );
         path_build( &f2, buf, 0 );
 
- b->name = buf->value;
+ b->name = name = object_new( buf->value );
         b->time = b->flags = 0;
         b->progress = BIND_INIT;
 
         if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( buf->value ); /* never freed */
+ b->name = object_copy( name );
 
         if ( !( b->flags & BIND_SCANNED ) )
         {
- file_dirscan( buf->value, time_enter, bindhash );
+ file_dirscan( name, time_enter, bindhash );
             b->flags |= BIND_SCANNED;
         }
+
+ object_free( name );
     }
 
     /* Scan archive if not already done so. */
@@ -146,6 +149,7 @@
     {
         BINDING binding;
         BINDING * b = &binding;
+ OBJECT * name;
 
         f2 = f1;
         f2.f_grist.len = 0;
@@ -153,18 +157,20 @@
         string_truncate( buf, 0 );
         path_build( &f2, buf, 0 );
 
- b->name = buf->value;
+ b->name = name = object_new( buf->value );
         b->time = b->flags = 0;
         b->progress = BIND_INIT;
 
         if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( buf->value ); /* never freed */
+ b->name = object_copy( name );
 
         if ( !( b->flags & BIND_SCANNED ) )
         {
             file_archscan( buf->value, time_enter, bindhash );
             b->flags |= BIND_SCANNED;
         }
+
+ object_free( name );
     }
 
     afterscanning:
@@ -180,13 +186,14 @@
         string_free( buf );
 #ifdef DOWNSHIFT_PATHS
     string_free( &path );
+ object_free( target );
 #endif
 
     PROFILE_EXIT( timestamp );
 }
 
 
-static void time_enter( void * closure, char * target, int found, time_t time )
+static void time_enter( void * closure, OBJECT * target, int found, time_t time )
 {
     BINDING binding;
     BINDING * b = &binding;
@@ -195,29 +202,34 @@
 #ifdef DOWNSHIFT_PATHS
     char path[ MAXJPATH ];
     char * p = path;
+ const char * t = object_str( target );
 
- do *p++ = tolower( *target );
- while ( *target++ );
+ do *p++ = tolower( *t );
+ while ( *t++ );
 
- target = path;
+ target = object_new( path );
 #endif
 
     b->name = target;
     b->flags = 0;
 
     if ( hashenter( bindhash, (HASHDATA * *)&b ) )
- b->name = newstr( target ); /* never freed */
+ b->name = object_copy( target ); /* never freed */
 
     b->time = time;
     b->progress = found ? BIND_FOUND : BIND_SPOTTED;
 
     if ( DEBUG_BINDSCAN )
- printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] );
+ printf( "time ( %s ) : %s\n", object_str( target ), time_progress[ b->progress ] );
+
+#ifdef DOWNSHIFT_PATHS
+ object_free( target );
+#endif
 }
 
 static void free_timestamps ( void * xbinding, void * data )
 {
- freestr( ((BINDING *)xbinding)->name );
+ object_free( ((BINDING *)xbinding)->name );
 }
 
 /*

Modified: trunk/tools/build/v2/engine/timestamp.h
==============================================================================
--- trunk/tools/build/v2/engine/timestamp.h (original)
+++ trunk/tools/build/v2/engine/timestamp.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,5 +8,13 @@
  * timestamp.h - get the timestamp of a file or archive member
  */
 
-void timestamp( char * target, time_t * time );
+#ifndef TIMESTAMP_H_SW_2011_11_18
+#define TIMESTAMP_H_SW_2011_11_18
+
+#include "object.h"
+#include "time.h"
+
+void timestamp( OBJECT * target, time_t * time );
 void stamps_done();
+
+#endif

Modified: trunk/tools/build/v2/engine/variable.c
==============================================================================
--- trunk/tools/build/v2/engine/variable.c (original)
+++ trunk/tools/build/v2/engine/variable.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -19,7 +19,7 @@
 #include "expand.h"
 #include "hash.h"
 #include "filesys.h"
-#include "newstr.h"
+#include "object.h"
 #include "strings.h"
 #include "pathsys.h"
 #include <stdlib.h>
@@ -59,12 +59,12 @@
 
 struct _variable
 {
- char * symbol;
- LIST * value;
+ OBJECT * symbol;
+ LIST * value;
 };
 
-static VARIABLE * var_enter( char * symbol );
-static void var_dump( char * symbol, LIST * value, char * what );
+static VARIABLE * var_enter( OBJECT * symbol );
+static void var_dump( OBJECT * symbol, LIST * value, char * what );
 
 
 /*
@@ -103,6 +103,7 @@
     for ( ; *e; ++e )
     {
         char * val;
+ OBJECT * varname;
 
 # ifdef OS_MAC
         /* On the mac (MPW), the var=val is actually var\0val */
@@ -133,7 +134,7 @@
             if ( quoted && preprocess )
             {
                 string_append_range( buf, val + 2, val + len );
- l = list_new( l, newstr( buf->value ) );
+ l = list_new( l, object_new( buf->value ) );
                 string_truncate( buf, 0 );
             }
             else
@@ -156,16 +157,18 @@
                 )
                 {
                     string_append_range( buf, pp, p );
- l = list_new( l, newstr( buf->value ) );
+ l = list_new( l, object_new( buf->value ) );
                     string_truncate( buf, 0 );
                 }
 
- l = list_new( l, newstr( pp ) );
+ l = list_new( l, object_new( pp ) );
             }
 
             /* Get name. */
             string_append_range( buf, *e, val );
- var_set( buf->value, l, VAR_SET );
+ varname = object_new( buf->value );
+ var_set( varname, l, VAR_SET );
+ object_free( varname );
             string_truncate( buf, 0 );
         }
     }
@@ -179,7 +182,7 @@
  * Copies in to out; doesn't modify targets & sources.
  */
 
-int var_string( char * in, char * out, int outsize, LOL * lol )
+int var_string( const char * in, char * out, int outsize, LOL * lol )
 {
     char * out0 = out;
     char * oute = out + outsize - 1;
@@ -214,8 +217,8 @@
             else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
             {
                 int depth = 1;
- char * ine = in + 2;
- char * split = 0;
+ const char * ine = in + 2;
+ const char * split = 0;
 
                 /* Scan the content of the response file @() section. */
                 while ( *ine && ( depth > 0 ) )
@@ -249,6 +252,7 @@
                 else if ( depth == 0 )
                 {
                     string file_name_v;
+ OBJECT * file_name = 0;
                     int file_name_l = 0;
                     const char * file_name_s = 0;
 
@@ -274,7 +278,9 @@
                     {
                         int err_redir = strcmp( "STDERR", out ) == 0;
                         out[ 0 ] = '\0';
- file_name_s = path_tmpfile();
+
+ file_name = path_tmpfile();
+ file_name_s = object_str(file_name);
                         file_name_l = strlen(file_name_s);
                         #ifdef OS_NT
                         if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
@@ -290,13 +296,18 @@
                         /* We also make sure that the temp files created by this
                          * get nuked eventually.
                          */
- file_remove_atexit( file_name_s );
+ file_remove_atexit( file_name );
                     }
 
                     /* Expand the file value into the file reference. */
                     var_string_to_file( split + 3, ine - split - 4, file_name_s,
                         lol );
 
+ if ( file_name )
+ {
+ object_free( file_name );
+ }
+
                     /* Continue on with the expansion. */
                     out += strlen( out );
                 }
@@ -329,12 +340,12 @@
 
             while ( l )
             {
- int so = strlen( l->string );
+ int so = strlen( object_str( l->value ) );
 
                 if ( out + so >= oute )
                     return -1;
 
- strcpy( out, l->string );
+ strcpy( out, object_str( l->value ) );
                 out += so;
                 l = list_next( l );
                 if ( l ) *out++ = ' ';
@@ -429,8 +440,8 @@
 
             while ( l )
             {
- if ( out_file ) fputs( l->string, out_file );
- if ( out_debug ) puts( l->string );
+ if ( out_file ) fputs( object_str( l->value ), out_file );
+ if ( out_debug ) puts( object_str( l->value ) );
                 l = list_next( l );
                 if ( l )
                 {
@@ -483,35 +494,35 @@
  * Returns NULL if symbol unset.
  */
 
-LIST * var_get( char * symbol )
+LIST * var_get( OBJECT * symbol )
 {
     LIST * result = 0;
 #ifdef OPT_AT_FILES
     /* Some "fixed" variables... */
- if ( strcmp( "TMPDIR", symbol ) == 0 )
+ if ( strcmp( "TMPDIR", object_str( symbol ) ) == 0 )
     {
         list_free( saved_var );
- result = saved_var = list_new( L0, newstr( (char *)path_tmpdir() ) );
+ result = saved_var = list_new( L0, object_new( path_tmpdir() ) );
     }
- else if ( strcmp( "TMPNAME", symbol ) == 0 )
+ else if ( strcmp( "TMPNAME", object_str( symbol ) ) == 0 )
     {
         list_free( saved_var );
- result = saved_var = list_new( L0, (char *)path_tmpnam() );
+ result = saved_var = list_new( L0, path_tmpnam() );
     }
- else if ( strcmp( "TMPFILE", symbol ) == 0 )
+ else if ( strcmp( "TMPFILE", object_str( symbol ) ) == 0 )
     {
         list_free( saved_var );
- result = saved_var = list_new( L0, (char *)path_tmpfile() );
+ result = saved_var = list_new( L0, path_tmpfile() );
     }
- else if ( strcmp( "STDOUT", symbol ) == 0 )
+ else if ( strcmp( "STDOUT", object_str( symbol ) ) == 0 )
     {
         list_free( saved_var );
- result = saved_var = list_new( L0, newstr( "STDOUT" ) );
+ result = saved_var = list_new( L0, object_new( "STDOUT" ) );
     }
- else if ( strcmp( "STDERR", symbol ) == 0 )
+ else if ( strcmp( "STDERR", object_str( symbol ) ) == 0 )
     {
         list_free( saved_var );
- result = saved_var = list_new( L0, newstr( "STDERR" ) );
+ result = saved_var = list_new( L0, object_new( "STDERR" ) );
     }
     else
 #endif
@@ -542,7 +553,7 @@
  * Copies symbol. Takes ownership of value.
  */
 
-void var_set( char * symbol, LIST * value, int flag )
+void var_set( OBJECT * symbol, LIST * value, int flag )
 {
     VARIABLE * v = var_enter( symbol );
 
@@ -577,7 +588,7 @@
  * var_swap() - swap a variable's value with the given one.
  */
 
-LIST * var_swap( char * symbol, LIST * value )
+LIST * var_swap( OBJECT * symbol, LIST * value )
 {
     VARIABLE * v = var_enter( symbol );
     LIST * oldvalue = v->value;
@@ -592,7 +603,7 @@
  * var_enter() - make new var symbol table entry, returning var ptr.
  */
 
-static VARIABLE * var_enter( char * symbol )
+static VARIABLE * var_enter( OBJECT * symbol )
 {
     VARIABLE var;
     VARIABLE * v = &var;
@@ -604,7 +615,7 @@
     v->value = 0;
 
     if ( hashenter( varhash, (HASHDATA * *)&v ) )
- v->symbol = newstr( symbol ); /* never freed */
+ v->symbol = object_copy( symbol );
 
     return v;
 }
@@ -614,9 +625,9 @@
  * var_dump() - dump a variable to stdout.
  */
 
-static void var_dump( char * symbol, LIST * value, char * what )
+static void var_dump( OBJECT * symbol, LIST * value, char * what )
 {
- printf( "%s %s = ", what, symbol );
+ printf( "%s %s = ", what, object_str( symbol ) );
     list_print( value );
     printf( "\n" );
 }
@@ -629,7 +640,7 @@
 static void delete_var_( void * xvar, void * data )
 {
     VARIABLE * v = (VARIABLE *)xvar;
- freestr( v->symbol );
+ object_free( v->symbol );
     list_free( v-> value );
 }
 

Modified: trunk/tools/build/v2/engine/variable.h
==============================================================================
--- trunk/tools/build/v2/engine/variable.h (original)
+++ trunk/tools/build/v2/engine/variable.h 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -8,15 +8,18 @@
  * variable.h - handle jam multi-element variables
  */
 
+#ifndef VARIABLE_SW20111119_H
+#define VARIABLE_SW20111119_H
+
 struct hash;
 
 void var_defines( char* const *e, int preprocess );
-int var_string( char *in, char *out, int outsize, LOL *lol );
-LIST * var_get( char *symbol );
-void var_set( char *symbol, LIST *value, int flag );
-LIST * var_swap( char *symbol, LIST *value );
+int var_string( const char * in, char * out, int outsize, LOL * lol );
+LIST * var_get( OBJECT * symbol );
+void var_set( OBJECT * symbol, LIST * value, int flag );
+LIST * var_swap( OBJECT * symbol, LIST *value );
 void var_done();
-void var_hash_swap( struct hash** );
+void var_hash_swap( struct hash * * );
 
 /** Expands the "in" expression directly into the "out" file.
     The file can be one of: a path, STDOUT, or STDERR to send
@@ -33,3 +36,4 @@
 # define VAR_APPEND 1 /* append to previous value */
 # define VAR_DEFAULT 2 /* set only if no previous value */
 
+#endif

Modified: trunk/tools/build/v2/engine/w32_getreg.c
==============================================================================
--- trunk/tools/build/v2/engine/w32_getreg.c (original)
+++ trunk/tools/build/v2/engine/w32_getreg.c 2011-11-22 18:04:09 EST (Tue, 22 Nov 2011)
@@ -9,7 +9,7 @@
 # if defined( OS_NT ) || defined( OS_CYGWIN )
 
 # include "lists.h"
-# include "newstr.h"
+# include "object.h"
 # include "parse.h"
 # include "frames.h"
 # include "strings.h"
@@ -62,7 +62,7 @@
     PARSE *parse,
     FRAME *frame )
 {
- char const* path = lol_get(frame->args, 0)->string;
+ char const* path = object_str( lol_get(frame->args, 0)->value );
     LIST* result = L0;
     HKEY key = get_key(&path);
 
@@ -77,7 +77,7 @@
         LIST const* const field = lol_get(frame->args, 1);
 
         if ( ERROR_SUCCESS ==
- RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
+ RegQueryValueEx(key, field ? object_str( field->value ) : 0, 0, &type, data, &len) )
         {
             switch (type)
             {
@@ -97,7 +97,7 @@
 
                      expanded->size = len - 1;
 
- result = list_new( result, newstr(expanded->value) );
+ result = list_new( result, object_new(expanded->value) );
                      string_free( expanded );
                  }
                  break;
@@ -107,7 +107,7 @@
                      char* s;
 
                      for (s = (char*)data; *s; s += strlen(s) + 1)
- result = list_new( result, newstr(s) );
+ result = list_new( result, object_new(s) );
 
                  }
                  break;
@@ -116,12 +116,12 @@
                  {
                      char buf[100];
                      sprintf( buf, "%u", *(PDWORD)data );
- result = list_new( result, newstr(buf) );
+ result = list_new( result, object_new(buf) );
                  }
                  break;
 
              case REG_SZ:
- result = list_new( result, newstr((char*)data) );
+ result = list_new( result, object_new( (const char *)data ) );
                  break;
             }
         }
@@ -151,7 +151,7 @@
         )
         {
             name[name_size] = 0;
- result = list_append(result, list_new(0, newstr(name)));
+ result = list_append(result, list_new(0, object_new(name)));
         }
 
         RegCloseKey(key);
@@ -178,7 +178,7 @@
         )
         {
             name[name_size] = 0;
- result = list_append(result, list_new(0, newstr(name)));
+ result = list_append(result, list_new(0, object_new(name)));
         }
 
         RegCloseKey(key);
@@ -192,8 +192,8 @@
     PARSE *parse,
     FRAME *frame )
 {
- char const* path = lol_get(frame->args, 0)->string;
- char const* result_type = lol_get(frame->args, 1)->string;
+ char const* path = object_str( lol_get(frame->args, 0)->value );
+ char const* result_type = object_str( lol_get(frame->args, 1)->value );
 
     HKEY key = get_key(&path);
 


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