Optimizations of how variable expansion implementation

darcs-hash:20060212112930-ac50b-9b8bb640ef1a5bd14230ecd276167a80d6d986c9.gz
This commit is contained in:
axel 2006-02-12 21:29:30 +10:00
parent 8fdb4d2a17
commit eeaa241be8

154
expand.c
View file

@ -156,6 +156,9 @@ static wchar_t *expand_var( wchar_t *in )
return env_get( in ); return env_get( in );
} }
static string_buffer_t *var_tmp = 0;
static array_list_t *var_idx_list;
void expand_variable_array( const wchar_t *val, array_list_t *out ) void expand_variable_array( const wchar_t *val, array_list_t *out )
{ {
if( val ) if( val )
@ -390,8 +393,6 @@ static int find_process( const wchar_t *proc,
This is a numeric job string, like '%2' This is a numeric job string, like '%2'
*/ */
// fwprintf( stderr, L"Numeric\n\n\n" );
if( flags & ACCEPT_INCOMPLETE ) if( flags & ACCEPT_INCOMPLETE )
{ {
for( j=first_job; j != 0; j=j->next ) for( j=first_job; j != 0; j=j->next )
@ -401,7 +402,6 @@ static int find_process( const wchar_t *proc,
continue; continue;
swprintf( jid, 16, L"%d", j->job_id ); swprintf( jid, 16, L"%d", j->job_id );
// fwprintf( stderr, L"Jid %ls\n", jid );
if( wcsncmp( proc, jid, wcslen(proc ) )==0 ) if( wcsncmp( proc, jid, wcslen(proc ) )==0 )
{ {
@ -714,6 +714,30 @@ static int expand_pid( wchar_t *in,
return 1; return 1;
} }
static void var_tmp_init()
{
if( !var_tmp )
{
var_tmp = sb_halloc( global_context );
if( !var_tmp )
die_mem();
}
else
{
sb_clear(var_tmp );
}
if( !var_idx_list )
{
var_idx_list = al_halloc( global_context );
if( !var_idx_list )
die_mem();
}
else
{
al_truncate( var_idx_list, 0 );
}
}
/** /**
Expand all environment variables in the string *ptr. Expand all environment variables in the string *ptr.
@ -729,7 +753,7 @@ static int expand_pid( wchar_t *in,
happens, don't edit it unless you know exactly what you are doing, happens, don't edit it unless you know exactly what you are doing,
and do proper testing afterwards. and do proper testing afterwards.
*/ */
static int expand_variables( wchar_t *in, array_list_t *out ) static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
{ {
wchar_t c; wchar_t c;
wchar_t prev_char=0; wchar_t prev_char=0;
@ -737,7 +761,7 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int is_ok= 1; int is_ok= 1;
int empty=0; int empty=0;
for( i=wcslen(in)-1; (i>=0) && is_ok && !empty; i-- ) for( i=last_idx; (i>=0) && is_ok && !empty; i-- )
{ {
c = in[i]; c = in[i];
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) ) if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
@ -745,11 +769,10 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int start_pos = i+1; int start_pos = i+1;
int stop_pos; int stop_pos;
int var_len, new_len; int var_len, new_len;
wchar_t *var_name;
wchar_t * var_val; wchar_t * var_val;
wchar_t * new_in; wchar_t * new_in;
array_list_t l;
int is_single = (c==VARIABLE_EXPAND_SINGLE); int is_single = (c==VARIABLE_EXPAND_SINGLE);
int var_name_stop_pos;
stop_pos = start_pos; stop_pos = start_pos;
@ -763,6 +786,7 @@ static int expand_variables( wchar_t *in, array_list_t *out )
stop_pos++; stop_pos++;
} }
var_name_stop_pos = stop_pos;
/* printf( "Stop for '%c'\n", in[stop_pos]);*/ /* printf( "Stop for '%c'\n", in[stop_pos]);*/
@ -812,22 +836,17 @@ static int expand_variables( wchar_t *in, array_list_t *out )
break; break;
} }
var_tmp_init();
if( !(var_name = malloc( sizeof(wchar_t)*(var_len+1) ))) sb_append_substring( var_tmp, &in[start_pos], var_len );
{
die_mem();
}
wcsncpy( var_name, &in[start_pos], var_len );
var_name[var_len]='\0';
/* printf( "Variable name is %s, len is %d\n", var_name, var_len );*/
wchar_t *var_val_orig = expand_var( var_name );
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) ) var_val = expand_var( (wchar_t *)var_tmp->buff );
if( var_val )
{ {
int all_vars=1; int all_vars=1;
array_list_t idx; array_list_t var_item_list;
al_init( &idx ); al_init( &var_item_list );
al_init( &l );
if( in[stop_pos] == L'[' ) if( in[stop_pos] == L'[' )
{ {
@ -861,43 +880,42 @@ static int expand_variables( wchar_t *in, array_list_t *out )
is_ok = 0; is_ok = 0;
break; break;
} }
al_push( &idx, (void *)tmp ); al_push( var_idx_list, (void *)tmp );
stop_pos = end-in; stop_pos = end-in;
} }
} }
if( is_ok ) if( is_ok )
{ {
expand_variable_array( var_val, &l ); expand_variable_array( var_val, &var_item_list );
if( !all_vars ) if( !all_vars )
{ {
int j; int j;
for( j=0; j<al_get_count( &idx ); j++) for( j=0; j<al_get_count( var_idx_list ); j++)
{ {
int tmp = (int)al_get( &idx, j ); int tmp = (int)al_get( var_idx_list, j );
if( tmp < 1 || tmp > al_get_count( &l ) ) if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
{ {
error( SYNTAX_ERROR, error( SYNTAX_ERROR,
-1, -1,
L"Array index out of bounds" ); L"Array index out of bounds" );
is_ok=0; is_ok=0;
al_truncate( &idx, j ); al_truncate( var_idx_list, j );
break; break;
} }
else else
{ {
/* Move string from list l to list idx */ /* Move string from list l to list idx */
al_set( &idx, j, al_get( &l, tmp-1 ) ); al_set( var_idx_list, j, al_get( &var_item_list, tmp-1 ) );
al_set( &l, tmp-1, 0 ); al_set( &var_item_list, tmp-1, 0 );
} }
} }
/* Free remaining strings in list l and truncate it */ /* Free remaining strings in list l and truncate it */
al_foreach( &l, (void (*)(const void *))&free ); al_foreach( &var_item_list, (void (*)(const void *))&free );
al_truncate( &l, 0 ); al_truncate( &var_item_list, 0 );
/* Add items from list idx back to list l */ /* Add items from list idx back to list l */
al_push_all( &l, &idx ); al_push_all( &var_item_list, var_idx_list );
} }
free( var_val );
} }
if( is_ok ) if( is_ok )
@ -906,16 +924,15 @@ static int expand_variables( wchar_t *in, array_list_t *out )
if( is_single ) if( is_single )
{ {
string_buffer_t res; string_buffer_t res;
sb_init( &res );
in[i]=0; in[i]=0;
sb_init( &res );
sb_append( &res, in ); sb_append( &res, in );
sb_append_char( &res, INTERNAL_SEPARATOR ); sb_append_char( &res, INTERNAL_SEPARATOR );
for( j=0; j<al_get_count( &l); j++ ) for( j=0; j<al_get_count( &var_item_list); j++ )
{ {
wchar_t *next = (wchar_t *)al_get( &l, j ); wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok ) if( is_ok )
{ {
@ -926,52 +943,58 @@ static int expand_variables( wchar_t *in, array_list_t *out )
free( next ); free( next );
} }
sb_append( &res, &in[stop_pos] ); sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( (wchar_t *)res.buff, out ); is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
} }
else else
{ {
for( j=0; j<al_get_count( &l); j++ ) for( j=0; j<al_get_count( &var_item_list); j++ )
{ {
wchar_t *next = (wchar_t *)al_get( &l, j ); wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok && (i == 0) && (!in[stop_pos]) )
if( is_ok ) {
al_push( out, next );
}
else
{ {
new_len = wcslen(in) - (stop_pos-start_pos+1) + wcslen( next) +2; if( is_ok )
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
{
die_mem();
}
else
{ {
new_len = wcslen(in) - (stop_pos-start_pos+1);
new_len += wcslen( next) +2;
wcsncpy( new_in, in, start_pos-1 ); if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
{ {
new_in[start_pos-1]=INTERNAL_SEPARATOR; die_mem();
new_in[start_pos]=L'\0';
} }
else else
new_in[start_pos-1]=L'\0'; {
wcscat( new_in, next ); wcsncpy( new_in, in, start_pos-1 );
wcscat( new_in, &in[stop_pos] );
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
{
new_in[start_pos-1]=INTERNAL_SEPARATOR;
new_in[start_pos]=L'\0';
}
else
new_in[start_pos-1]=L'\0';
wcscat( new_in, next );
wcscat( new_in, &in[stop_pos] );
// fwprintf( stderr, L"New value %ls\n", new_in ); // fwprintf( stderr, L"New value %ls\n", new_in );
is_ok &= expand_variables( new_in, out ); is_ok &= expand_variables( new_in, out, i );
}
} }
free( next );
} }
free( next );
} }
} }
} }
al_destroy( &l );
al_destroy( &idx );
free(in); free(in);
free(var_name ); al_destroy( &var_item_list );
return is_ok; return is_ok;
} }
else else
@ -997,19 +1020,14 @@ static int expand_variables( wchar_t *in, array_list_t *out )
in[i]=0; in[i]=0;
sb_append( &res, in ); sb_append( &res, in );
sb_append( &res, &in[stop_pos] ); sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
sb_destroy( &res ); is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
free(in); free(in);
free(var_name );
return is_ok; return is_ok;
} }
} }
free(var_name );
} }
@ -1483,7 +1501,7 @@ int expand_string( void *context,
} }
else else
{ {
if(!expand_variables( next, out )) if(!expand_variables( next, out, wcslen(next)-1 ))
{ {
al_destroy( in ); al_destroy( in );
al_destroy( out ); al_destroy( out );
@ -1560,6 +1578,7 @@ int expand_string( void *context,
int wc_res; int wc_res;
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags ); remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
wildcard_has( next, 1 ) ) wildcard_has( next, 1 ) )
{ {
@ -1589,7 +1608,6 @@ int expand_string( void *context,
al_push_all( end_out, out ); al_push_all( end_out, out );
al_truncate( out, 0 ); al_truncate( out, 0 );
break; break;
} }
} }
else else