2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-13 12:22:17 +00:00

Internal Boost Jam cleanup - function.c module's expand() function cleaned up a bit (used to resolve concatenated variable references in Jam scripts).

[SVN r80313]
This commit is contained in:
Jurko Gospodnetić
2012-08-29 21:27:07 +00:00
parent cfb54c8213
commit 57a424c5f7

View File

@@ -1024,56 +1024,116 @@ static LIST * apply_subscript_and_modifiers( STACK * s, int n )
return result;
}
/*
* expand() - expands a list of concatenated strings and variable refereces
*
* Takes a list of expansion items - each representing one element to be
* concatenated and each containing a list of its values. Returns a list of all
* possible values constructed by selecting a single value from each of the
* elements and concatenating them together.
*
* For example, in the following code:
*
* local a = one two three four ;
* local b = foo bar ;
* ECHO /$(a)/$(b)/$(a)/ ;
*
* When constructing the result of /$(a)/$(b)/ this function would get called
* with the following 7 expansion items:
* 1. /
* 2. one two three four
* 3. /
* 4. foo bar
* 5. /
* 6. one two three four
* 7. /
*
* And would result in a list containing 32 values:
* 1. /one/foo/one/
* 2. /one/foo/two/
* 3. /one/foo/three/
* 4. /one/foo/four/
* 5. /one/bar/one/
* ...
*
*/
typedef struct expansion_item
{
LISTITER elem;
LIST * saved;
int size;
/* Item's value list initialized prior to calling expand(). */
LIST * values;
/* Internal data initialized and used inside expand(). */
LISTITER current; /* Currently used value. */
int size; /* Concatenated string length prior to concatenating the
* item's current value.
*/
} expansion_item;
static LIST * expand( expansion_item * elem, int length )
static LIST * expand( expansion_item * items, int const length )
{
LIST * result = L0;
string buf[ 1 ];
int size = 0;
int i;
assert( length > 0 );
for ( i = 0; i < length; ++i )
{
int max = 0;
LISTITER iter = elem[ i ].elem;
LISTITER const end = list_end( elem[ i ].saved );
if ( iter == end ) return result;
for ( ; iter != end; iter = list_next( iter ) )
LISTITER iter = list_begin( items[ i ].values );
LISTITER const end = list_end( items[ i ].values );
/* If any of the items has no values - the result is an empty list. */
if ( iter == end ) return L0;
/* Set each item's 'current' to its first listed value. This indicates
* each item's next value to be used when constructing the list of all
* possible concatenated values.
*/
items[ i ].current = iter;
/* Calculate the longest concatenated string length - to know how much
* memory we need to allocate as a buffer for holding the concatenated
* strings.
*/
{
int const len = strlen( object_str( list_item( iter ) ) );
if ( len > max ) max = len;
int max = 0;
for ( ; iter != end; iter = list_next( iter ) )
{
int const len = strlen( object_str( list_item( iter ) ) );
if ( len > max ) max = len;
}
size += max;
}
size += max;
}
string_new( buf );
string_reserve( buf, size );
i = 0;
{
loop:
for ( ; i < length; ++i )
{
elem[ i ].size = buf->size;
string_append( buf, object_str( list_item( elem[ i ].elem ) ) );
items[ i ].size = buf->size;
string_append( buf, object_str( list_item( items[ i ].current ) ) );
}
result = list_push_back( result, object_new( buf->value ) );
while ( --i >= 0 )
{
if ( list_next( elem[ i ].elem ) != list_end( elem[ i ].saved ) )
if ( list_next( items[ i ].current ) != list_end( items[ i ].values
) )
{
elem[ i ].elem = list_next( elem[ i ].elem );
string_truncate( buf, elem[ i ].size );
items[ i ].current = list_next( items[ i ].current );
string_truncate( buf, items[ i ].size );
goto loop;
}
else
elem[ i ].elem = list_begin( elem[ i ].saved );
items[ i ].current = list_begin( items[ i ].values );
}
}
string_free( buf );
return result;
}
@@ -4052,16 +4112,13 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_COMBINE_STRINGS:
{
LIST * result;
size_t buffer_size = code->arg * sizeof( expansion_item );
LIST * * stack_pos = stack_get( s );
size_t const buffer_size = code->arg * sizeof( expansion_item );
LIST * * const stack_pos = stack_get( s );
expansion_item * items = stack_allocate( s, buffer_size );
LIST * result;
int i;
for ( i = 0; i < code->arg; ++i )
{
items[ i ].saved = stack_pos[ i ];
items[ i ].elem = list_begin( items[ i ].saved );
}
items[ i ].values = stack_pos[ i ];
result = expand( items, code->arg );
stack_deallocate( s, buffer_size );
for ( i = 0; i < code->arg; ++i )