$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r75889 - trunk/tools/build/v2/engine
From: steven_at_[hidden]
Date: 2011-12-10 20:55:35
Author: steven_watanabe
Date: 2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
New Revision: 75889
URL: http://svn.boost.org/trac/boost/changeset/75889
Log:
Eliminate the last uses of var_expand and remove it.
Removed:
   trunk/tools/build/v2/engine/expand.c
   trunk/tools/build/v2/engine/expand.h
Text files modified: 
   trunk/tools/build/v2/engine/build.bat  |     2                                         
   trunk/tools/build/v2/engine/build.jam  |     2                                         
   trunk/tools/build/v2/engine/build.sh   |     2                                         
   trunk/tools/build/v2/engine/builtins.c |     8                                         
   trunk/tools/build/v2/engine/command.c  |    31 +--                                     
   trunk/tools/build/v2/engine/command.h  |     6                                         
   trunk/tools/build/v2/engine/compile.c  |     1                                         
   trunk/tools/build/v2/engine/function.c |   163 +++++++++++++++++---                    
   trunk/tools/build/v2/engine/function.h |     4                                         
   trunk/tools/build/v2/engine/jam.c      |     3                                         
   trunk/tools/build/v2/engine/make1.c    |     6                                         
   trunk/tools/build/v2/engine/rules.c    |     9                                         
   trunk/tools/build/v2/engine/rules.h    |    10                                         
   trunk/tools/build/v2/engine/variable.c |   311 ----------------------------------------
   trunk/tools/build/v2/engine/variable.h |     8 -                                       
   15 files changed, 180 insertions(+), 386 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-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -438,7 +438,7 @@
 set YYACC_SOURCES=yyacc.c
 set MKJAMBASE_SOURCES=mkjambase.c
 set BJAM_SOURCES=
-set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c constants.c debug.c execnt.c expand.c filent.c function.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c constants.c debug.c execnt.c filent.c function.c glob.c hash.c
 set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
 set BJAM_SOURCES=%BJAM_SOURCES% 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
Modified: trunk/tools/build/v2/engine/build.jam
==============================================================================
--- trunk/tools/build/v2/engine/build.jam	(original)
+++ trunk/tools/build/v2/engine/build.jam	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -471,7 +471,7 @@
 
 # We have some different files for UNIX, and NT.
 jam.source =
-    command.c compile.c constants.c debug.c expand.c function.c glob.c
+    command.c compile.c constants.c debug.c function.c glob.c
     hash.c hcache.c headers.c hdrmacro.c
     jam.c jambase.c jamgram.c
     lists.c make.c make1.c mem.c object.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-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -245,7 +245,7 @@
 YYACC_SOURCES="yyacc.c"
 MKJAMBASE_SOURCES="mkjambase.c"
 BJAM_SOURCES="\
- command.c compile.c constants.c debug.c expand.c function.c glob.c hash.c\
+ command.c compile.c constants.c debug.c function.c glob.c hash.c\
  hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
  object.c option.c output.c parse.c pathunix.c regexp.c\
  rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
Modified: trunk/tools/build/v2/engine/builtins.c
==============================================================================
--- trunk/tools/build/v2/engine/builtins.c	(original)
+++ trunk/tools/build/v2/engine/builtins.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -2100,7 +2100,7 @@
     int        n;
     int        i;
     OBJECT   * name_str;
-    OBJECT   * body_str;
+    FUNCTION * body_func;
 
     if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
                           &PyList_Type, &bindlist_python, &flags ) )
@@ -2120,9 +2120,9 @@
     }
 
     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 );
+    body_func = function_compile_actions( body, constant_builtin, -1 );
+    new_rule_actions( root_module(), name_str, body_func, bindlist, flags );
+    function_free( body_func );
     object_free( name_str );
 
     Py_INCREF( Py_None );
Modified: trunk/tools/build/v2/engine/command.c
==============================================================================
--- trunk/tools/build/v2/engine/command.c	(original)
+++ trunk/tools/build/v2/engine/command.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -36,7 +36,7 @@
     /* Lift line-length limitation entirely when JAMSHELL is just "%". */
     int no_limit = ( shell && !strcmp(object_str(shell->value),"%") && !list_next(shell) );
     int max_line = MAXLINE;
-    int allocated = -1;
+    FRAME frame[1];
 
     cmd->rule = rule;
     cmd->shell = shell;
@@ -45,27 +45,20 @@
     lol_init( &cmd->args );
     lol_add( &cmd->args, targets );
     lol_add( &cmd->args, sources );
-    cmd->buf = 0;
+    string_new( cmd->buf );
 
-    do
-    {
-        BJAM_FREE( cmd->buf );  /* free any buffer from previous iteration */
-
-        cmd->buf = (char*)BJAM_MALLOC_ATOMIC( max_line + 1 );
-
-        if ( cmd->buf == 0 )
-            break;
-
-        allocated = var_string( object_str( rule->actions->command ), cmd->buf, max_line, &cmd->args );
-
-        max_line = max_line * 2;
-    }
-    while ( ( allocated < 0 ) && ( max_line < INT_MAX / 2 ) );
+    frame_init( frame );
+    frame->module = rule->module;
+    lol_init( frame->args );
+    lol_add( frame->args, list_copy( L0, targets ) );
+    lol_add( frame->args, list_copy( L0, sources ) );
+    function_run_actions( rule->actions->command, frame, stack_global(), cmd->buf );
+    frame_free( frame );
 
     if ( !no_limit )
     {
         /* Bail if the result will not fit in MAXLINE. */
-        char * s = cmd->buf;
+        char * s = cmd->buf->value;
         while ( *s )
         {
             size_t l = strcspn( s, "\n" );
@@ -95,6 +88,6 @@
 {
     lol_free( &cmd->args );
     list_free( cmd->shell );
-    BJAM_FREE( cmd->buf );
-    BJAM_FREE( (char *)cmd );
+    string_free( cmd->buf );
+    BJAM_FREE( (void *)cmd );
 }
Modified: trunk/tools/build/v2/engine/command.h
==============================================================================
--- trunk/tools/build/v2/engine/command.h	(original)
+++ trunk/tools/build/v2/engine/command.h	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -39,6 +39,10 @@
 #ifndef COMMAND_SW20111118_H
 #define COMMAND_SW20111118_H
 
+#include "lists.h"
+#include "rules.h"
+#include "strings.h"
+
 typedef struct _cmd CMD;
 
 struct _cmd
@@ -48,7 +52,7 @@
     RULE * rule;   /* rule->actions contains shell script */
     LIST * shell;  /* $(SHELL) value */
     LOL    args;   /* LISTs for $(<), $(>) */
-    char * buf;    /* actual commands */
+    string buf[1]; /* actual commands */
 };
 
 CMD * cmd_new
Modified: trunk/tools/build/v2/engine/compile.c
==============================================================================
--- trunk/tools/build/v2/engine/compile.c	(original)
+++ trunk/tools/build/v2/engine/compile.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -16,7 +16,6 @@
 # include "parse.h"
 # include "compile.h"
 # include "variable.h"
-# include "expand.h"
 # include "rules.h"
 # include "object.h"
 # include "make.h"
Deleted: trunk/tools/build/v2/engine/expand.c
==============================================================================
--- trunk/tools/build/v2/engine/expand.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
+++ (empty file)
@@ -1,743 +0,0 @@
-/*
- * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-# include "jam.h"
-# include "lists.h"
-# include "variable.h"
-# include "expand.h"
-# include "pathsys.h"
-# include "object.h"
-# include <assert.h>
-# include <stdlib.h>
-# include <limits.h>
-
-# ifdef OS_CYGWIN
-#  include <sys/cygwin.h>
-#  include <windows.h>
-# endif
-
-/*
- * expand.c - expand a buffer, given variable values
- *
- * External routines:
- *
- *  var_expand() - variable-expand input string into list of strings
- *
- * Internal routines:
- *
- *  var_edit_parse() - parse : modifiers into PATHNAME structure.
- *  var_edit_file() - copy input target name to output, modifying filename.
- *  var_edit_shift() - do upshift/downshift mods.
- *
- * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
- * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
- * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
- */
-
-typedef struct
-{
-    PATHNAME f;           /* :GDBSMR -- pieces */
-    char     parent;      /* :P -- go to parent directory */
-    char     filemods;    /* one of the above applied */
-    char     downshift;   /* :L -- downshift result */
-    char     upshift;     /* :U -- upshift result */
-    char     to_slashes;  /* :T -- convert "\" to "/" */
-    char     to_windows;  /* :W -- convert cygwin to native paths */
-    PATHPART empty;       /* :E -- default for empties */
-    PATHPART join;        /* :J -- join list with char */
-} VAR_EDITS ;
-
-static void var_edit_parse( 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'
-#define MAGIC_LEFT  '\002'
-#define MAGIC_RIGHT '\003'
-
-
-/*
- * var_expand() - variable-expand input string into list of strings.
- *
- * Would just copy input to output, performing variable expansion, except that
- * since variables can contain multiple values the result of variable expansion
- * may contain multiple values (a list). Properly performs "product" operations
- * that occur in "$(var1)xxx$(var2)" or even "$($(var2))".
- *
- * Returns a newly created list.
- */
-
-LIST * var_expand( LIST * l, 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;
-    const char * inp = in;
-    char * ov;  /* for temp copy of variable in outbuf */
-    int depth;
-
-    if ( DEBUG_VAREXP )
-        printf( "expand '%.*s'\n", (int)( end - in ), in );
-
-    /* This gets a lot of cases: $(<) and $(>). */
-    if
-    (
-        ( in[ 0 ] == '$'  ) &&
-        ( in[ 1 ] == '('  ) &&
-        ( in[ 3 ] == ')'  ) &&
-        ( in[ 4 ] == '\0' )
-    )
-    {
-        switch ( in[ 2 ] )
-        {
-            case '<': return list_copy( l, lol_get( lol, 0 ) );
-            case '>': return list_copy( l, lol_get( lol, 1 ) );
-
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-                return list_copy( l, lol_get( lol, in[ 2 ] - '1' ) );
-        }
-    }
-    else if ( in[0] == '$' && in[1] == '(' && in[2] == '1' && in[4] == ')' &&
-              in[5] == '\0') {
-
-        switch( in[3] )
-        {
-        case '0':
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9':
-            return list_copy( l, lol_get( lol, in[3]-'0'+10-1 ) );
-        }
-    }
-
-    /* Expand @() files, to single item plus accompanying file. */
-    if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) && ( *( end - 1 ) == ')' ) )
-    {
-        /* We try the expansion until it fits within the propective output
-         * buffer.
-         */
-        char * at_buf = 0;
-        int at_size = MAXJPATH;
-        int at_len = 0;
-        do
-        {
-            BJAM_FREE( at_buf );
-            at_buf = (char *)BJAM_MALLOC_ATOMIC( at_size + 1 );
-            at_len = var_string( in, at_buf, at_size, lol );
-            at_size *= 2;
-        }
-        while ( ( at_len < 0 ) && ( at_size < INT_MAX / 2 ) );
-        /* Return the result as a single item list. */
-        if ( at_len > 0 )
-        {
-            LIST * r;
-            string_copy( buf, at_buf );
-            r = list_new( l, object_new( buf->value ) );
-            string_free( buf );
-            BJAM_FREE( at_buf );
-            return r;
-        }
-        BJAM_FREE( at_buf );
-    }
-
-    /* Just try simple copy of in to out. */
-    while ( in < end )
-        if ( ( *in++ == '$' ) && ( *in == '(' ) )
-            goto expand;
-
-    /* No variables expanded - just add copy of input string to list. */
-
-    /* 'cancopyin' is an optimization: if the input was already a list item, we
-     * can use obect_copy() to put it on the new list. Otherwise, we use the slower
-     * object_new().
-     */
-    if ( cancopyin )
-        return list_new( l, object_copy( cancopyin ) );
-
-    {
-        LIST * r;
-        string_new( buf );
-        string_append_range( buf, inp, end );
-        r = list_new( l, object_new( buf->value ) );
-        string_free( buf );
-        return r;
-    }
-
-expand:
-    string_new( buf );
-    string_append_range( buf, inp, in - 1 );  /* Copy the part before '$'. */
-    /*
-     * Input so far (ignore blanks):
-     *
-     *  stuff-in-outbuf $(variable) remainder
-     *                   ^                   ^
-     *                   in                  end
-     * Output so far:
-     *
-     *  stuff-in-outbuf $
-     *  ^                ^
-     *  out_buf          out
-     *
-     *
-     * We just copied the $ of $(...), so back up one on the output. We now find
-     * the matching close paren, copying the variable and modifiers between the
-     * $( and ) temporarily into out_buf, so that we can replace :'s with
-     * MAGIC_COLON. This is necessary to avoid being confused by modifier values
-     * that are variables containing :'s. Ugly.
-     */
-
-    depth = 1;
-    inp = ++in;  /* Skip over the '('. */
-
-    while ( ( in < end ) && depth )
-    {
-        switch ( *in++ )
-        {
-            case '(': ++depth; break;
-            case ')': --depth; break;
-        }
-    }
-
-    /*
-     * Input so far (ignore blanks):
-     *
-     *  stuff-in-outbuf $(variable) remainder
-     *                    ^        ^         ^
-     *                    inp      in        end
-     */
-    prefix_length = buf->size;
-    string_append_range( buf, inp, in - 1 );
-
-    out = buf->value + prefix_length;
-    for ( ov = out; ov < buf->value + buf->size; ++ov )
-    {
-        switch ( *ov )
-        {
-            case ':': *ov = MAGIC_COLON; break;
-            case '[': *ov = MAGIC_LEFT ; break;
-            case ']': *ov = MAGIC_RIGHT; break;
-        }
-    }
-
-    /*
-     * Input so far (ignore blanks):
-     *
-     *  stuff-in-outbuf $(variable) remainder
-     *                              ^        ^
-     *                              in       end
-     * Output so far:
-     *
-     *  stuff-in-outbuf variable
-     *  ^               ^       ^
-     *  out_buf         out     ov
-     *
-     * Later we will overwrite 'variable' in out_buf, but we will be done with
-     * it by then. 'variable' may be a multi-element list, so may each value for
-     * '$(variable element)', and so may 'remainder'. Thus we produce a product
-     * of three lists.
-     */
-    {
-        LIST * variables = 0;
-        LIST * remainder = 0;
-        LIST * vars;
-
-        /* Recursively expand variable name & rest of input. */
-        if ( out < ov ) variables = var_expand( L0, out, ov, lol, 0 );
-        if ( in < end ) remainder = var_expand( L0, in, end, lol, 0 );
-
-        /* Now produce the result chain. */
-
-        /* For each variable name. */
-        for ( vars = variables; vars; vars = list_next( vars ) )
-        {
-            LIST * value = 0;
-            LIST * evalue = 0;
-            char * colon;
-            char * bracket;
-            string variable[1];
-            char * varname;
-            int sub1 = 0;
-            int sub2 = -1;
-            VAR_EDITS edits;
-
-            /* Look for a : modifier in the variable name. Must copy into
-             * varname so we can modify it.
-             */
-            string_copy( variable, object_str( vars->value ) );
-            varname = variable->value;
-
-            if ( ( colon = strchr( varname, MAGIC_COLON ) ) )
-            {
-                string_truncate( variable, colon - varname );
-                var_edit_parse( colon + 1, &edits );
-            }
-
-            /* Look for [x-y] subscripting. sub1 and sub2 are x and y. */
-            if ( ( bracket = strchr( varname, MAGIC_LEFT ) ) )
-            {
-                /* Make all syntax errors in [] subscripting result in the same
-                 * behavior: silenty return an empty expansion (by setting sub2
-                 * = 0). Brute force parsing; May get moved into yacc someday.
-                 */
-
-                char * s = bracket + 1;
-
-                string_truncate( variable, bracket - varname );
-
-                do  /* so we can use "break" */
-                {
-                    /* Allow negative indexes. */
-                    if ( !isdigit( *s ) && ( *s != '-' ) )
-                    {
-                        sub2 = 0;
-                        break;
-                    }
-                    sub1 = atoi( s );
-
-                    /* Skip over the first symbol, which is either a digit or dash. */
-                    ++s;
-                    while ( isdigit( *s ) ) ++s;
-
-                    if ( *s == MAGIC_RIGHT )
-                    {
-                        sub2 = sub1;
-                        break;
-                    }
-
-                    if ( *s != '-' )
-                    {
-                        sub2 = 0;
-                        break;
-                    }
-
-                    ++s;
-
-                    if ( *s == MAGIC_RIGHT )
-                    {
-                        sub2 = -1;
-                        break;
-                    }
-
-                    if ( !isdigit( *s ) && ( *s != '-' ) )
-                    {
-                        sub2 = 0;
-                        break;
-                    }
-
-                    /* First, compute the index of the last element. */
-                    sub2 = atoi( s );
-                    while ( isdigit( *++s ) );
-
-                    if ( *s != MAGIC_RIGHT )
-                        sub2 = 0;
-
-                } while ( 0 );
-
-                /* Anything but the end of the string, or the colon introducing
-                 * a modifier is a syntax error.
-                 */
-                ++s;
-                if ( *s && ( *s != MAGIC_COLON ) )
-                    sub2 = 0;
-
-                *bracket = '\0';
-            }
-
-            /* Get variable value, with special handling for $(<), $(>), $(n).
-             */
-            if ( !varname[1] )
-            {
-                if ( varname[0] == '<' )
-                    value = lol_get( lol, 0 );
-                else if ( varname[0] == '>' )
-                    value = lol_get( lol, 1 );
-                else if ( ( varname[0] >= '1' ) && ( varname[0] <= '9' ) )
-                    value = lol_get( lol, varname[0] - '1' );
-                else if( varname[0] == '1' && varname[1] >= '0' &&
-                     varname[1] <= '9' && !varname[2] )
-                value = lol_get( lol, varname[1] - '0' + 10 - 1 );
-            }
-
-            if ( !value )
-            {
-                OBJECT * v = object_new( varname );
-                value = var_get( v );
-                object_free( v );
-            }
-
-            /* Handle negitive indexes: part two. */
-            {
-                int length = list_length( value );
-
-                if ( sub1 < 0 )
-                    sub1 = length + sub1;
-                else
-                    sub1 -= 1;
-
-                if ( sub2 < 0 )
-                    sub2 = length + 1 + sub2 - sub1;
-                else
-                    sub2 -= sub1;
-                /* The "sub2 < 0" test handles the semantic error of sub2 <
-                 * sub1.
-                 */
-                if ( sub2 < 0 )
-                    sub2 = 0;
-            }
-
-            /* The fast path: $(x) - just copy the variable value. This is only
-             * an optimization.
-             */
-            if ( ( out == out_buf ) && !bracket && !colon && ( in == end ) )
-            {
-                string_free( variable );
-                l = list_copy( l, value );
-                continue;
-            }
-
-            /* Handle start subscript. */
-            while ( ( sub1 > 0 ) && value )
-                --sub1, value = list_next( value );
-
-            /* Empty w/ :E=default?. */
-            if ( !value && colon && edits.empty.ptr )
-                evalue = value = list_new( L0, object_new( edits.empty.ptr ) );
-
-            /* For each variable value. */
-            string_new( out1 );
-            for ( ; value; value = list_next( value ) )
-            {
-                LIST * rem;
-                size_t postfix_start;
-
-                /* Handle end subscript (length actually). */
-
-                if ( sub2 >= 0 && --sub2 < 0 )
-                    break;
-
-                string_truncate( buf, prefix_length );
-
-                /* Apply : mods, if present */
-
-                if ( colon && edits.filemods )
-                    var_edit_file( object_str( value->value ), out1, &edits );
-                else
-                    string_append( out1, object_str( value->value ) );
-
-                if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) )
-                    var_edit_shift( out1, &edits );
-
-                /* Handle :J=joinval */
-                /* If we have more values for this var, just keep appending them
-                 * (using the join value) rather than creating separate LIST
-                 * elements.
-                 */
-                if ( colon && edits.join.ptr &&
-                    ( list_next( value ) || list_next( vars ) ) )
-                {
-                    string_append( out1, edits.join.ptr );
-                    continue;
-                }
-
-                string_append( buf, out1->value );
-                string_free( out1 );
-                string_new( out1 );
-
-                /* If no remainder, append result to output chain. */
-                if ( in == end )
-                {
-                    l = list_new( l, object_new( buf->value ) );
-                    continue;
-                }
-
-                /* For each remainder, append the complete string to the output
-                 * chain. Remember the end of the variable expansion so we can
-                 * just tack on each instance of 'remainder'.
-                 */
-                postfix_start = buf->size;
-                for ( rem = remainder; rem; rem = list_next( rem ) )
-                {
-                    string_truncate( buf, postfix_start );
-                    string_append( buf, object_str( rem->value ) );
-                    l = list_new( l, object_new( buf->value ) );
-                }
-            }
-            string_free( out1 );
-
-            /* Toss used empty. */
-            if ( evalue )
-                list_free( evalue );
-
-            string_free( variable );
-        }
-
-        /* variables & remainder were gifts from var_expand and must be freed. */
-        if ( variables ) list_free( variables );
-        if ( remainder ) list_free( remainder );
-
-        if ( DEBUG_VAREXP )
-        {
-            printf( "expanded to " );
-            list_print( l );
-            printf( "\n" );
-        }
-
-        string_free( buf );
-        return l;
-    }
-}
-
-
-/*
- * var_edit_parse() - parse : modifiers into PATHNAME structure
- *
- * The : modifiers in a $(varname:modifier) currently support replacing or
- * omitting elements of a filename, and so they are parsed into a PATHNAME
- * structure (which contains pointers into the original string).
- *
- * Modifiers of the form "X=value" replace the component X with the given value.
- * Modifiers without the "=value" cause everything but the component X to be
- * omitted. X is one of:
- *
- *  G <grist>
- *  D directory name
- *  B base name
- *  S .suffix
- *  M (member)
- *  R root directory - prepended to whole path
- *
- * This routine sets:
- *
- *  f->f_xxx.ptr = 0
- *  f->f_xxx.len = 0
- *      -> leave the original component xxx
- *
- *  f->f_xxx.ptr = string
- *  f->f_xxx.len = strlen( string )
- *      -> replace component xxx with string
- *
- *  f->f_xxx.ptr = ""
- *  f->f_xxx.len = 0
- *      -> omit component xxx
- *
- * var_edit_file() below and path_build() obligingly follow this convention.
- */
-
-static void var_edit_parse( const char * mods, VAR_EDITS * edits )
-{
-    int havezeroed = 0;
-    memset( (char *)edits, 0, sizeof( *edits ) );
-
-    while ( *mods )
-    {
-        char * p;
-        PATHPART * fp;
-
-        switch ( *mods++ )
-        {
-            case 'L': edits->downshift = 1; continue;
-            case 'U': edits->upshift = 1; continue;
-            case 'P': edits->parent = edits->filemods = 1; continue;
-            case 'E': fp = &edits->empty; goto strval;
-            case 'J': fp = &edits->join; goto strval;
-            case 'G': fp = &edits->f.f_grist; goto fileval;
-            case 'R': fp = &edits->f.f_root; goto fileval;
-            case 'D': fp = &edits->f.f_dir; goto fileval;
-            case 'B': fp = &edits->f.f_base; goto fileval;
-            case 'S': fp = &edits->f.f_suffix; goto fileval;
-            case 'M': fp = &edits->f.f_member; goto fileval;
-            case 'T': edits->to_slashes = 1; continue;
-            case 'W': edits->to_windows = 1; continue;
-            default:
-                return;  /* Should complain, but so what... */
-        }
-
-    fileval:
-        /* Handle :CHARS, where each char (without a following =) selects a
-         * particular file path element. On the first such char, we deselect all
-         * others (by setting ptr = "", len = 0) and for each char we select
-         * that element (by setting ptr = 0).
-         */
-        edits->filemods = 1;
-
-        if ( *mods != '=' )
-        {
-            if ( !havezeroed++ )
-            {
-                int i;
-                for ( i = 0; i < 6; ++i )
-                {
-                    edits->f.part[ i ].len = 0;
-                    edits->f.part[ i ].ptr = "";
-                }
-            }
-
-            fp->ptr = 0;
-            continue;
-        }
-
-    strval:
-        /* Handle :X=value, or :X */
-        if ( *mods != '=' )
-        {
-            fp->ptr = "";
-            fp->len = 0;
-        }
-        else if ( ( p = strchr( mods, MAGIC_COLON ) ) )
-        {
-            *p = 0;
-            fp->ptr = ++mods;
-            fp->len = p - mods;
-            mods = p + 1;
-        }
-        else
-        {
-            fp->ptr = ++mods;
-            fp->len = strlen( mods );
-            mods += fp->len;
-        }
-    }
-}
-
-
-/*
- * var_edit_file() - copy input target name to output, modifying filename.
- */
-
-static void var_edit_file( const char * in, string * out, VAR_EDITS * edits )
-{
-    PATHNAME pathname;
-
-    /* Parse apart original filename, putting parts into "pathname". */
-    path_parse( in, &pathname );
-
-    /* Replace any pathname with edits->f */
-    if ( edits->f.f_grist .ptr ) pathname.f_grist  = edits->f.f_grist;
-    if ( edits->f.f_root  .ptr ) pathname.f_root   = edits->f.f_root;
-    if ( edits->f.f_dir   .ptr ) pathname.f_dir    = edits->f.f_dir;
-    if ( edits->f.f_base  .ptr ) pathname.f_base   = edits->f.f_base;
-    if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix;
-    if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member;
-
-    /* If requested, modify pathname to point to parent. */
-    if ( edits->parent )
-        path_parent( &pathname );
-
-    /* Put filename back together. */
-    path_build( &pathname, out, 0 );
-}
-
-
-/*
- * var_edit_shift() - do upshift/downshift mods.
- */
-
-static void var_edit_shift( string * out, VAR_EDITS * edits )
-{
-    /* Handle upshifting, downshifting and slash translation now. */
-    char * p;
-    for ( p = out->value; *p; ++p)
-    {
-        if ( edits->upshift )
-            *p = toupper( *p );
-        else if ( edits->downshift )
-            *p = tolower( *p );
-        if ( edits->to_slashes && ( *p == '\\' ) )
-            *p = '/';
-# ifdef OS_CYGWIN
-        if ( edits->to_windows )
-        {
-            char result[ MAX_PATH + 1 ];
-            cygwin_conv_to_win32_path( out->value, result );
-            assert( strlen( result ) <= MAX_PATH );
-            string_free( out );
-            string_copy( out, result );
-        }
-# endif
-    }
-    out->size = p - out->value;
-}
-
-
-#ifndef NDEBUG
-void var_expand_unit_test()
-{
-    LOL lol[ 1 ];
-    LIST * l;
-    LIST * l2;
-    LIST * expected = list_new( list_new( L0, 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 ];
-    cygwin_conv_to_posix_path( "c:\\foo\\bar", cygpath );
-# else
-    char cygpath[] = "/cygdrive/c/foo/bar";
-# endif
-
-    lol_init(lol);
-    var_set( xy, list_new( list_new( L0, 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( 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( object_equal( e2->value, l2->value ) );
-    assert( l2 == 0 );
-    assert( e2 == 0 );
-    list_free( l );
-
-    l = var_expand( 0, path, path + sizeof( path ) - 1, lol, 0 );
-    assert( l != 0 );
-    assert( list_next( l ) == 0 );
-# ifdef OS_CYGWIN
-    /* On some installations of cygwin the drive letter is expanded to other
-     * case. This has been reported to be the case if cygwin has been installed
-     * to C:\ as opposed to C:\cygwin. Since case of the drive letter will not
-     * matter, we allow for both.
-     */
-    assert( !strcmp( object_str( l->value ), "c:\\foo\\bar" ) ||
-            !strcmp( object_str( l->value ), "C:\\foo\\bar" ) );
-# else
-    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 );
-}
-#endif
Deleted: trunk/tools/build/v2/engine/expand.h
==============================================================================
--- trunk/tools/build/v2/engine/expand.h	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
+++ (empty file)
@@ -1,20 +0,0 @@
-/*
- * Copyright 1993, 1995 Christopher Seiwald.
- *
- * This file is part of Jam - see jam.c for Copyright information.
- */
-
-/*
- * expand.h - expand a buffer, given variable values
- */
-
-#ifndef EXPAND_SW20111118_H
-#define EXPAND_SW20111118_H
-
-#include "lists.h"
-#include "object.h"
-
-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/function.c
==============================================================================
--- trunk/tools/build/v2/engine/function.c	(original)
+++ trunk/tools/build/v2/engine/function.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -99,6 +99,7 @@
 
 #define INSTR_APPEND_STRINGS                53
 #define INSTR_WRITE_FILE                    54
+#define INSTR_OUTPUT_STRINGS                55
 
 typedef struct instruction
 {
@@ -116,9 +117,9 @@
 
 typedef struct _subaction
 {
-    OBJECT * name;
-    OBJECT * command;
-    int      flags;
+    OBJECT   * name;
+    FUNCTION * command;
+    int        flags;
 } SUBACTION;
 
 #define FUNCTION_BUILTIN    0
@@ -1172,12 +1173,12 @@
     return (int)( c->rules->size - 1 );
 }
 
-static int compile_emit_actions( compiler * c, OBJECT * name, OBJECT * command, int flags )
+static int compile_emit_actions( compiler * c, PARSE * parse )
 {
     SUBACTION a;
-    a.name = object_copy( name );
-    a.command = object_copy( command );
-    a.flags = flags;
+    a.name = object_copy( parse->string );
+    a.command = function_compile_actions( object_str( parse->string1 ), parse->file, parse->line );
+    a.flags = parse->num;
     dynamic_array_push( c->actions, a );
     return (int)( c->actions->size - 1 );
 }
@@ -1228,6 +1229,11 @@
     struct dynamic_array elems[1];
 } VAR_PARSE_GROUP;
 
+typedef struct VAR_PARSE_ACTIONS
+{
+    struct dynamic_array elems[1];
+} VAR_PARSE_ACTIONS;
+
 #define VAR_PARSE_TYPE_VAR      0
 #define VAR_PARSE_TYPE_STRING   1
 #define VAR_PARSE_TYPE_FILE     2
@@ -1302,6 +1308,41 @@
     }
 }
 
+VAR_PARSE_STRING * var_parse_group_as_literal( VAR_PARSE_GROUP * group )
+{
+    if ( group->elems->size == 1  )
+    {
+        VAR_PARSE * result = dynamic_array_at( VAR_PARSE *, group->elems, 0 );
+        if ( result->type == VAR_PARSE_TYPE_STRING )
+        {
+            return (VAR_PARSE_STRING *)result;
+        }
+    }
+    return 0;
+}
+
+/*
+ * VAR_PARSE_ACTIONS
+ */
+
+static VAR_PARSE_ACTIONS * var_parse_actions_new()
+{
+    VAR_PARSE_ACTIONS * result = (VAR_PARSE_ACTIONS *)BJAM_MALLOC( sizeof(VAR_PARSE_ACTIONS) );
+    dynamic_array_init( result->elems );
+    return result;
+}
+
+static void var_parse_actions_free( VAR_PARSE_ACTIONS * actions )
+{
+    int i;
+    for ( i = 0; i < actions->elems->size; ++i )
+    {
+        var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *, actions->elems, i ) );
+    }
+    dynamic_array_free( actions->elems );
+    BJAM_FREE( actions );
+}
+
 /*
  * VAR_PARSE_VAR
  */
@@ -1541,6 +1582,16 @@
     }
 }
 
+static void var_parse_actions_compile( const VAR_PARSE_ACTIONS * actions, compiler * c )
+{
+    int i;
+    for ( i = 0; i < actions->elems->size; ++i )
+    {
+        var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *, actions->elems, actions->elems->size - i - 1 ), c );
+    }
+    compile_emit( c, INSTR_OUTPUT_STRINGS, actions->elems->size );
+}
+
 /*
  * Parse VAR_PARSE_VAR
  */
@@ -1549,6 +1600,7 @@
 static VAR_PARSE * parse_variable( const char * * string );
 static int try_parse_variable( const char * * s_, const char * * string, VAR_PARSE_GROUP * out);
 static void balance_parentheses( const char * * s_, const char * * string, VAR_PARSE_GROUP * out);
+static void parse_var_string( const char * first, const char * last, struct dynamic_array * out );
 
 /*
  * Parses a string that can contain variables to expand.
@@ -1573,6 +1625,13 @@
     }
 }
 
+static VAR_PARSE_ACTIONS * parse_actions( const char * string )
+{
+    VAR_PARSE_ACTIONS * result = var_parse_actions_new();
+    parse_var_string( string, string + strlen( string ), result->elems );
+    return result;
+}
+
 /*
  * Checks whether the string a *s_ starts with
  * a variable expansion "$(".  *string should point
@@ -1767,25 +1826,46 @@
 static void parse_var_string( const char * first, const char * last, struct dynamic_array * out )
 {
     const char * saved = first;
-    string buf[1];
-    int state = isspace( *first ) != 0;
-    string_new( buf );
-    for ( ; ; ++first )
+    for ( ; ; )
     {
-        if ( first == last || ( isspace( *first ) != 0 ) != state )
+        /* Handle whitespace */
+        for ( ; first != last; ++first ) if ( !isspace(*first) ) break;
+        if ( saved != first )
         {
-            VAR_PARSE_GROUP * group;
-            const char * s = buf->value;
-            string_append_range( buf, saved, first );
+            VAR_PARSE_GROUP * group = var_parse_group_new();
+            var_parse_group_maybe_add_constant( group, saved, first );
             saved = first;
-            group = parse_expansion( &s );
-            string_truncate( buf, 0 );
             dynamic_array_push( out, group );
-            state = !state;
+        }
+
+        if ( first == last ) break;
+
+        /* Handle non-whitespace */
+
+        {
+            VAR_PARSE_GROUP * group = var_parse_group_new();
+            for ( ; ; )
+            {
+                
+                if( first == last || isspace( *first ) )
+                {
+                    var_parse_group_maybe_add_constant( group, saved, first );
+                    saved = first;
+                    break;
+                }
+                else if ( try_parse_variable( &first, &saved, group ) )
+                {
+                    assert( first <= last );
+                }
+                else 
+                {
+                    ++first;
+                }
+            }
+            dynamic_array_push( out, group );
         }
         if ( first == last ) break;
     }
-    string_free( buf );
 }
 
 /*
@@ -2335,7 +2415,7 @@
     }
     else if ( parse->type == PARSE_SETEXEC )
     {
-        int actions_id = compile_emit_actions( c, parse->string, parse->string1, parse->num );
+        int actions_id = compile_emit_actions( c, parse );
 
         compile_parse( parse->left, c, RESULT_STACK );
 
@@ -2436,6 +2516,24 @@
     return (FUNCTION *)result;
 }
 
+FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int line )
+{
+    compiler c[1];
+    JAM_FUNCTION * result;
+    VAR_PARSE_ACTIONS * parse;
+    current_file = object_str( file );
+    current_line = line;
+    parse = parse_actions( actions );
+    compiler_init( c );
+    var_parse_actions_compile( parse, c );
+    compile_emit( c, INSTR_RETURN, 0 );
+    result = compile_to_function( c );
+    compiler_free( c );
+    result->file = object_copy( file );
+    result->line = line;
+    return (FUNCTION *)result;
+}
+
 void function_refer( FUNCTION * func )
 {
     ++func->reference_count;
@@ -2470,7 +2568,7 @@
         for ( i = 0; i < func->num_subactions; ++i )
         {
             object_free( func->actions[i].name );
-            object_free( func->actions[i].command );
+            function_free( func->actions[i].command );
         }
         BJAM_FREE( func->actions );
 
@@ -2501,6 +2599,13 @@
 static char check_ptr_size1[ sizeof(LIST *) <= sizeof(void *) ? 1 : -1 ];
 static char check_ptr_size2[ sizeof(char *) <= sizeof(void *) ? 1 : -1 ];
 
+void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string * out )
+{
+    *(string * *)stack_allocate( s, sizeof( string * ) ) = out;
+    list_free( function_run( function, frame, s ) );
+    stack_deallocate( s, sizeof( string * ) );
+}
+
 /*
  * WARNING: The instruction set is tuned for Jam and
  * is not really generic.  Be especially careful about
@@ -3310,10 +3415,13 @@
             if ( out_debug ) printf( "\nfile %s\n", out );
 
             if ( out_file ) fputs( buf->value, out_file );
-            if ( out_debug ) puts( buf->value );
+            if ( out_debug ) fputs( buf->value, stdout );
             
-            fflush( out_file );
-            fclose( out_file );
+            if ( out_file )
+            {
+                fflush( out_file );
+                fclose( out_file );
+            }
             string_free( buf );
             if ( tmp_filename )
                 object_free( tmp_filename );
@@ -3323,6 +3431,13 @@
             break;
         }
 
+        case INSTR_OUTPUT_STRINGS:
+        {
+            string * buf = *(string * *)( (char *)stack_get( s ) + ( code->arg * sizeof( LIST * ) ) );
+            combine_strings( s, code->arg, buf );
+            break;
+        }
+
         }
         ++code;
     }
Modified: trunk/tools/build/v2/engine/function.h
==============================================================================
--- trunk/tools/build/v2/engine/function.h	(original)
+++ trunk/tools/build/v2/engine/function.h	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -11,6 +11,7 @@
 #include "frames.h"
 #include "lists.h"
 #include "parse.h"
+#include "strings.h"
 
 typedef struct _function FUNCTION;
 typedef struct _stack STACK;
@@ -28,6 +29,9 @@
 void function_location( FUNCTION *, OBJECT * *, int * );
 LIST * function_run( FUNCTION * function, FRAME * frame, STACK * s );
 
+FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int line );
+void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string * out );
+
 void function_done( void );
 
 #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-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -73,7 +73,6 @@
  *  command.c - maintain lists of commands
  *  compile.c - compile parsed jam statements
  *  execunix.c - execute a shell script on UNIX
- *  expand.c - expand a buffer, given variable values
  *  file*.c - scan directories and archives on *
  *  hash.c - simple in-memory hashing routines
  *  hdrmacro.c - handle header file parsing for filename macro definitions
@@ -119,7 +118,6 @@
 #include "timestamp.h"
 #include "make.h"
 #include "strings.h"
-#include "expand.h"
 #include "filesys.h"
 #include "output.h"
 #include "search.h"
@@ -202,7 +200,6 @@
     execnt_unit_test();
 #endif
     string_unit_test();
-    var_expand_unit_test();
 }
 #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-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -517,7 +517,7 @@
             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 );
+                out_action( rule_name, target, cmd->buf->value, "", "", EXIT_OK );
         }
 
         if ( globs.noexec )
@@ -529,7 +529,7 @@
         {
             /* Pop state first because exec_cmd() could push state. */
             pop_state( &state_stack );
-            exec_cmd( cmd->buf, make_closure, pState->t, cmd->shell, rule_name,
+            exec_cmd( cmd->buf->value, make_closure, pState->t, cmd->shell, rule_name,
                 target );
         }
     }
@@ -1045,7 +1045,7 @@
                 cmd = cmd_new( rule, list_copy( L0, nt ),
                     list_sublist( ns, start, chunk ),
                     list_new( L0, object_new( "%" ) ) );
-                fputs( cmd->buf, stdout );
+                fputs( cmd->buf->value, stdout );
                 exit( EXITBAD );
             }
         }
Modified: trunk/tools/build/v2/engine/rules.c
==============================================================================
--- trunk/tools/build/v2/engine/rules.c	(original)
+++ trunk/tools/build/v2/engine/rules.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -642,7 +642,7 @@
 {
     if ( --a->reference_count <= 0 )
     {
-        object_free( a->command );
+        function_free( a->command );
         list_free( a->bindlist );
         BJAM_FREE( a );
     }
@@ -745,10 +745,11 @@
 }
 
 
-static rule_actions * actions_new( OBJECT * command, LIST * bindlist, int flags )
+static rule_actions * actions_new( FUNCTION * command, LIST * bindlist, int flags )
 {
     rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
-    result->command = object_copy( command );
+    function_refer( command );
+    result->command = command;
     result->bindlist = bindlist;
     result->flags = flags;
     result->reference_count = 0;
@@ -756,7 +757,7 @@
 }
 
 
-RULE * new_rule_actions( module_t * m, OBJECT * rulename, OBJECT * command, LIST * bindlist, int flags )
+RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags )
 {
     RULE * local = define_rule( m, rulename, m );
     RULE * global = global_rule( local );
Modified: trunk/tools/build/v2/engine/rules.h
==============================================================================
--- trunk/tools/build/v2/engine/rules.h	(original)
+++ trunk/tools/build/v2/engine/rules.h	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -62,10 +62,10 @@
 /* Build actions corresponding to a rule. */
 struct rule_actions
 {
-    int      reference_count;
-    OBJECT * command;          /* command string from ACTIONS */
-    LIST   * bindlist;
-    int      flags;            /* modifiers on ACTIONS */
+    int        reference_count;
+    FUNCTION * command;          /* command string from ACTIONS */
+    LIST     * bindlist;
+    int        flags;            /* modifiers on ACTIONS */
 
 #define RULE_NEWSRCS   0x01  /* $(>) is updated sources only */
 #define RULE_TOGETHER  0x02  /* combine actions on single target */
@@ -261,7 +261,7 @@
 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 *, FUNCTION * func, int exprt );
-RULE * new_rule_actions( module_t *, OBJECT * rulename, OBJECT * command, LIST * bindlist, int flags );
+RULE * new_rule_actions( module_t *, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags );
 void   rule_free       ( RULE * );
 
 /* Target related functions. */
Modified: trunk/tools/build/v2/engine/variable.c
==============================================================================
--- trunk/tools/build/v2/engine/variable.c	(original)
+++ trunk/tools/build/v2/engine/variable.c	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -16,7 +16,6 @@
 #include "lists.h"
 #include "parse.h"
 #include "variable.h"
-#include "expand.h"
 #include "hash.h"
 #include "filesys.h"
 #include "object.h"
@@ -176,316 +175,6 @@
 }
 
 
-/*
- * var_string() - expand a string with variables in it
- *
- * Copies in to out; doesn't modify targets & sources.
- */
-
-int var_string( const char * in, char * out, int outsize, LOL * lol )
-{
-    char * out0 = out;
-    char * oute = out + outsize - 1;
-
-    while ( *in )
-    {
-        char * lastword;
-        int    dollar = 0;
-
-        /* Copy white space. */
-        while ( isspace( *in ) )
-        {
-            if ( out >= oute )
-                return -1;
-            *out++ = *in++;
-        }
-
-        lastword = out;
-
-        /* Copy non-white space, watching for variables. */
-        while ( *in && !isspace( *in ) )
-        {
-            if ( out >= oute )
-                return -1;
-
-            if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) )
-            {
-                ++dollar;
-                *out++ = *in++;
-            }
-            #ifdef OPT_AT_FILES
-            else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
-            {
-                int depth = 1;
-                const char * ine = in + 2;
-                const char * split = 0;
-
-                /* Scan the content of the response file @() section. */
-                while ( *ine && ( depth > 0 ) )
-                {
-                    switch ( *ine )
-                    {
-                    case '(': ++depth; break;
-                    case ')': --depth; break;
-                    case ':':
-                        if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
-                            split = ine;
-                        break;
-                    }
-                    ++ine;
-                }
-
-                if ( !split )
-                {
-                    /*  the @() reference doesn't match the @(foo:E=bar) format.
-                        hence we leave it alone by copying directly to output. */
-                    int l = 0;
-                    if ( out + 2 >= oute ) return -1;
-                    *( out++ ) = '@';
-                    *( out++ ) = '(';
-                    l = var_string( in + 2, out, oute - out, lol );
-                    if ( l < 0 ) return -1;
-                    out += l;
-                    if ( out + 1 >= oute ) return -1;
-                    *( out++ ) = ')';
-                }
-                else if ( depth == 0 )
-                {
-                    string file_name_v;
-                    OBJECT * file_name = 0;
-                    int file_name_l = 0;
-                    const char * file_name_s = 0;
-
-                    /* Expand the temporary file name var inline. */
-                    #if 0
-                    string_copy( &file_name_v, "$(" );
-                    string_append_range( &file_name_v, in + 2, split );
-                    string_push_back( &file_name_v, ')' );
-                    #else
-                    string_new( &file_name_v );
-                    string_append_range( &file_name_v, in + 2, split );
-                    #endif
-                    file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol );
-                    string_free( &file_name_v );
-                    if ( file_name_l < 0 ) return -1;
-                    file_name_s = out;
-
-                    /* For stdout/stderr we will create a temp file and generate
-                     * a command that outputs the content as needed.
-                     */
-                    if ( ( strcmp( "STDOUT", out ) == 0 ) ||
-                        ( strcmp( "STDERR", out ) == 0 ) )
-                    {
-                        int err_redir = strcmp( "STDERR", out ) == 0;
-                        out[ 0 ] = '\0';
-
-                        file_name = 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 )
-                            return -1;
-                        sprintf( out,"type \"%s\"%s", file_name_s,
-                            err_redir ? " 1>&2" : "" );
-                        #else
-                        if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
-                            return -1;
-                        sprintf( out,"cat \"%s\"%s", file_name_s,
-                            err_redir ? " 1>&2" : "" );
-                        #endif
-                        /* We also make sure that the temp files created by this
-                         * get nuked eventually.
-                         */
-                        file_remove_atexit( file_name );
-                    }
-
-                    /* 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 );
-                }
-
-                /* And continue with the parsing just past the @() reference. */
-                in = ine;
-            }
-            #endif
-            else
-            {
-                *out++ = *in++;
-            }
-        }
-
-        /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
-        if ( out >= oute )
-            return -1;
-        /* Do not increment, intentionally. */
-        *out = '\0';
-
-        /* If a variable encountered, expand it and and embed the
-         * space-separated members of the list in the output.
-         */
-        if ( dollar )
-        {
-            LIST * l = var_expand( L0, lastword, out, lol, 0 );
-            LIST * saved = l;
-
-            out = lastword;
-
-            while ( l )
-            {
-                int so = strlen( object_str( l->value ) );
-
-                if ( out + so >= oute )
-                    return -1;
-
-                strcpy( out, object_str( l->value ) );
-                out += so;
-                l = list_next( l );
-                if ( l ) *out++ = ' ';
-            }
-
-            list_free( saved );
-        }
-    }
-
-    if ( out >= oute )
-        return -1;
-
-    *out++ = '\0';
-
-    return out - out0;
-}
-
-
-void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )
-{
-    char const * ine = in + insize;
-    FILE * out_file = 0;
-    int out_debug = DEBUG_EXEC ? 1 : 0;
-    if ( globs.noexec )
-    {
-        /* out_debug = 1; */
-    }
-    else if ( strcmp( out, "STDOUT" ) == 0 )
-    {
-        out_file = stdout;
-    }
-    else if ( strcmp( out, "STDERR" ) == 0 )
-    {
-        out_file = stderr;
-    }
-    else
-    {
-        /* Handle "path to file" filenames. */
-        string out_name;
-        if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
-        {
-            string_copy( &out_name, out + 1 );
-            string_truncate( &out_name, out_name.size - 1 );
-        }
-        else
-        {
-            string_copy( &out_name,out );
-        }
-        out_file = fopen( out_name.value, "w" );
-        if ( !out_file )
-        {
-            printf( "failed to write output file '%s'!\n", out_name.value );
-            exit( EXITBAD );
-        }
-        string_free( &out_name );
-    }
-
-    if ( out_debug ) printf( "\nfile %s\n", out );
-
-    while ( *in && ( in < ine ) )
-    {
-        int dollar = 0;
-        const char * output_0 = in;
-        const char * output_1 = in;
-
-        /* Copy white space. */
-        while ( ( output_1 < ine ) && isspace( *output_1 ) )
-            ++output_1;
-
-        if ( output_0 < output_1 )
-        {
-            if ( out_file  ) fwrite( output_0, output_1 - output_0, 1, out_file );
-            if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout   );
-        }
-        output_0 = output_1;
-
-        /* Copy non-white space, watching for variables. */
-        while ( ( output_1 < ine ) && *output_1 && !isspace( *output_1 ) )
-        {
-            if ( ( output_1[ 0 ] == '$' ) && ( output_1[ 1 ] == '(' ) )
-                ++dollar;
-            ++output_1;
-        }
-
-        /* If a variable encountered, expand it and embed the space-separated
-         * members of the list in the output.
-         */
-        if ( dollar )
-        {
-            LIST * l = var_expand( L0, (char *)output_0, (char *)output_1, lol, 0 );
-            LIST * saved = l;
-
-            while ( l )
-            {
-                if ( out_file ) fputs( object_str( l->value ), out_file );
-                if ( out_debug ) puts( object_str( l->value ) );
-                l = list_next( l );
-                if ( l )
-                {
-                    if ( out_file ) fputc( ' ', out_file );
-                    if ( out_debug ) fputc( ' ', stdout );
-                }
-            }
-
-            list_free( saved );
-        }
-        else if ( output_0 < output_1 )
-        {
-            if ( out_file )
-            {
-                const char * output_n = output_0;
-                while ( output_n < output_1 )
-                {
-                    output_n += fwrite( output_n, 1, output_1-output_n, out_file );
-                }
-            }
-            if ( out_debug )
-            {
-                const char * output_n = output_0;
-                while ( output_n < output_1 )
-                {
-                    output_n += fwrite( output_n, 1, output_1-output_n, stdout );
-                }
-            }
-        }
-
-        in = output_1;
-    }
-
-    if ( out_file && ( out_file != stdout ) && ( out_file != stderr ) )
-    {
-        fflush( out_file );
-        fclose( out_file );
-    }
-
-    if ( out_debug ) fputc( '\n', stdout );
-}
-
-
-
 static LIST * saved_var = 0;
 
 /*
Modified: trunk/tools/build/v2/engine/variable.h
==============================================================================
--- trunk/tools/build/v2/engine/variable.h	(original)
+++ trunk/tools/build/v2/engine/variable.h	2011-12-10 20:55:33 EST (Sat, 10 Dec 2011)
@@ -14,20 +14,12 @@
 struct hash;
 
 void    var_defines( char* const *e, int preprocess );
-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 * * );
 
-/** Expands the "in" expression directly into the "out" file.
-    The file can be one of: a path, STDOUT, or STDERR to send
-    the output to a file overwriting previous content, to
-    the console, or to the error output respectively.
-*/
-void var_string_to_file( const char * in, int insize, const char * out, LOL * lol );
-
 /*
  * Defines for var_set().
  */