diff options
Diffstat (limited to 'tools/build/v2/engine/modules.c')
-rw-r--r-- | tools/build/v2/engine/modules.c | 394 |
1 files changed, 331 insertions, 63 deletions
diff --git a/tools/build/v2/engine/modules.c b/tools/build/v2/engine/modules.c index 7295259415..8898d18bb0 100644 --- a/tools/build/v2/engine/modules.c +++ b/tools/build/v2/engine/modules.c @@ -8,64 +8,54 @@ #include "modules.h" #include "string.h" #include "hash.h" -#include "newstr.h" +#include "object.h" #include "lists.h" #include "parse.h" #include "rules.h" #include "variable.h" #include "strings.h" +#include "native.h" #include <assert.h> static struct hash * module_hash = 0; +static module_t root; - -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 ); - - string s; - module_t m_; - module_t * m = &m_; - - if ( !module_hash ) - module_hash = hashinit( sizeof( module_t ), "modules" ); - string_new( &s ); - if ( name ) + if ( !name ) { - string_append( &s, name ); - string_push_back( &s, '.' ); + return &root; } - - m->name = s.value; - - if ( hashenter( module_hash, (HASHDATA * *)&m ) ) + else { - m->name = newstr( m->name ); - m->variables = 0; - m->rules = 0; - m->imported_modules = 0; - m->class_module = 0; - m->native_rules = 0; - m->user_module = 0; + PROFILE_ENTER( BINDMODULE ); + + module_t * m; + int found; + + if ( !module_hash ) + module_hash = hashinit( sizeof( module_t ), "modules" ); + + m = (module_t *)hash_insert( module_hash, name, &found ); + if ( !found ) + { + m->name = object_copy( name ); + m->variables = 0; + m->variable_indices = 0; + m->num_fixed_variables = 0; + m->fixed_variables = 0; + m->rules = 0; + m->imported_modules = 0; + m->class_module = 0; + m->native_rules = 0; + m->user_module = 0; + } + + PROFILE_EXIT( BINDMODULE ); + + return m; } - string_free( &s ); - - PROFILE_EXIT( BINDMODULE ); - - return m; } /* @@ -74,7 +64,7 @@ module_t * bindmodule( char * name ) 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; } @@ -89,43 +79,194 @@ static void delete_rule_( void * xrule, void * data ) } +static void delete_native_rule( void * xrule, void * data ) +{ + native_rule_t * rule = (native_rule_t *)xrule; + object_free( rule->name ); + if ( rule->procedure ) + function_free( rule->procedure ); +} + + +static void delete_imported_modules( void * xmodule_name, void * data ) +{ + object_free( *(OBJECT * *)xmodule_name ); +} + +static void free_fixed_variable( void * xvar, void * data ); + void delete_module( module_t * m ) { /* Clear out all the rules. */ if ( m->rules ) { hashenumerate( m->rules, delete_rule_, (void *)0 ); - hashdone( m->rules ); + hash_free( m->rules ); m->rules = 0; } + if ( m->native_rules ) + { + hashenumerate( m->native_rules, delete_native_rule, (void *)0 ); + hash_free( m->native_rules ); + m->native_rules = 0; + } + if ( m->variables ) { - var_hash_swap( &m->variables ); - var_done(); - var_hash_swap( &m->variables ); + var_done( m ); m->variables = 0; } + + if ( m->fixed_variables ) + { + int i; + for ( i = 0; i < m->num_fixed_variables; ++i ) + { + list_free( m->fixed_variables[ i ] ); + } + BJAM_FREE( m->fixed_variables ); + m->fixed_variables = 0; + } + + if ( m->variable_indices ) + { + hashenumerate( m->variable_indices, &free_fixed_variable, (void *)0 ); + hash_free( m->variable_indices ); + m->variable_indices = 0; + } + + if ( m->imported_modules ) + { + hashenumerate( m->imported_modules, delete_imported_modules, (void *)0 ); + hash_free( m->imported_modules ); + m->imported_modules = 0; + } } -module_t * root_module() +struct module_stats +{ + OBJECT * module_name; + struct hashstats rules_stats[ 1 ]; + struct hashstats variables_stats[ 1 ]; + struct hashstats variable_indices_stats[ 1 ]; + struct hashstats imported_modules_stats[ 1 ]; +}; + + +static void module_stat( struct hash * hp, OBJECT * module, const char * name ) +{ + if ( hp ) + { + struct hashstats stats[ 1 ]; + string id[ 1 ]; + hashstats_init( stats ); + string_new( id ); + string_append( id, object_str( module ) ); + string_push_back( id, ' ' ); + string_append( id, name ); + + hashstats_add( stats, hp ); + hashstats_print( stats, id->value ); + + string_free( id ); + } +} + + +static void class_module_stat( struct hashstats * stats, OBJECT * module, const char * name ) +{ + if ( stats->item_size ) + { + string id[ 1 ]; + string_new( id ); + string_append( id, object_str( module ) ); + string_append( id, " object " ); + string_append( id, name ); + + hashstats_print( stats, id->value ); + + string_free( id ); + } +} + + +static void stat_module( void * xmodule, void * data ) +{ + module_t *m = (module_t *)xmodule; + + if ( DEBUG_MEM || DEBUG_PROFILE ) + { + struct hash * class_info = (struct hash *)data; + if ( m->class_module ) + { + int found; + struct module_stats * ms = (struct module_stats *)hash_insert( class_info, m->class_module->name, &found ); + if ( !found ) + { + ms->module_name = m->class_module->name; + hashstats_init( ms->rules_stats ); + hashstats_init( ms->variables_stats ); + hashstats_init( ms->variable_indices_stats ); + hashstats_init( ms->imported_modules_stats ); + } + + hashstats_add( ms->rules_stats, m->rules ); + hashstats_add( ms->variables_stats, m->variables ); + hashstats_add( ms->variable_indices_stats, m->variable_indices ); + hashstats_add( ms->imported_modules_stats, m->imported_modules ); + } + else + { + module_stat( m->rules, m->name, "rules" ); + module_stat( m->variables, m->name, "variables" ); + module_stat( m->variable_indices, m->name, "fixed variables" ); + module_stat( m->imported_modules, m->name, "imported modules" ); + } + } + + delete_module( m ); + object_free( m->name ); +} + +static void print_class_stats( void * xstats, void * data ) { - static module_t * root = 0; - if ( !root ) - root = bindmodule( 0 ); - return root; + struct module_stats * stats = (struct module_stats *)xstats; + class_module_stat( stats->rules_stats, stats->module_name, "rules" ); + class_module_stat( stats->variables_stats, stats->module_name, "variables" ); + class_module_stat( stats->variable_indices_stats, stats->module_name, "fixed variables" ); + class_module_stat( stats->imported_modules_stats, stats->module_name, "imported modules" ); } -void enter_module( module_t * m ) + +static void delete_module_( void * xmodule, void * data ) { - var_hash_swap( &m->variables ); + module_t *m = (module_t *)xmodule; + + delete_module( m ); + object_free( m->name ); } -void exit_module( module_t * m ) +void modules_done() +{ + if ( DEBUG_MEM || DEBUG_PROFILE ) + { + struct hash * class_hash = hashinit( sizeof( struct module_stats ), "object info" ); + hashenumerate( module_hash, stat_module, (void *)class_hash ); + hashenumerate( class_hash, print_class_stats, (void *)0 ); + hash_free( class_hash ); + } + hashenumerate( module_hash, delete_module_, (void *)0 ); + hashdone( module_hash ); + module_hash = 0; + delete_module( &root ); +} + +module_t * root_module() { - var_hash_swap( &m->variables ); + return &root; } @@ -134,16 +275,22 @@ void import_module( LIST * module_names, module_t * target_module ) PROFILE_ENTER( IMPORT_MODULE ); struct hash * h; + LISTITER iter, end; if ( !target_module->imported_modules ) target_module->imported_modules = hashinit( sizeof( char * ), "imported" ); h = target_module->imported_modules; - for ( ; module_names; module_names = module_names->next ) + iter = list_begin( module_names ), end = list_end( module_names ); + for ( ; iter != end; iter = list_next( iter ) ) { - char * s = module_names->string; - char * * ss = &s; - hashenter( h, (HASHDATA * *)&ss ); + int found; + OBJECT * s = list_item( iter ); + OBJECT * * ss = (OBJECT * *)hash_insert( h, s, &found ); + if( !found ) + { + *ss = object_copy( s ); + } } PROFILE_EXIT( IMPORT_MODULE ); @@ -152,10 +299,10 @@ void import_module( LIST * module_names, module_t * target_module ) 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_push_back( *result, object_copy( *r ) ); } @@ -166,3 +313,124 @@ LIST * imported_modules( module_t * module ) hashenumerate( module->imported_modules, add_module_name, &result ); return result; } + + +FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter ); +FUNCTION * function_unbind_variables( FUNCTION * f ); + +struct fixed_variable +{ + OBJECT * key; + int n; +}; + +struct bind_vars_t +{ + module_t * module; + int counter; +}; + +static void free_fixed_variable( void * xvar, void * data ) +{ + object_free( ( (struct fixed_variable *)xvar )->key ); +} + +static void bind_variables_for_rule( void * xrule, void * xdata ) +{ + RULE * rule = (RULE *)xrule; + struct bind_vars_t * data = (struct bind_vars_t *)xdata; + if ( rule->procedure && rule->module == data->module ) + rule->procedure = function_bind_variables( rule->procedure, data->module, &data->counter ); +} + +void module_bind_variables( struct module_t * m ) +{ + if ( m != root_module() && m->rules ) + { + struct bind_vars_t data; + data.module = m; + data.counter = m->num_fixed_variables; + hashenumerate( m->rules, &bind_variables_for_rule, &data ); + module_set_fixed_variables( m, data.counter ); + } +} + +int module_add_fixed_var( struct module_t * m, OBJECT * name, int * counter ) +{ + struct fixed_variable * v; + int found; + + assert( !m->class_module ); + + if ( !m->variable_indices ) + m->variable_indices = hashinit( sizeof( struct fixed_variable ), "variable index table" ); + + v = (struct fixed_variable *)hash_insert( m->variable_indices, name, &found ); + if ( !found ) + { + v->key = object_copy( name ); + v->n = (*counter)++; + } + + return v->n; +} + +LIST * var_get_and_clear_raw( module_t * m, OBJECT * name ); + +static void load_fixed_variable( void * xvar, void * data ) +{ + struct fixed_variable * var = (struct fixed_variable *)xvar; + struct module_t * m = (struct module_t *)data; + if ( var->n >= m->num_fixed_variables ) + { + m->fixed_variables[ var->n ] = var_get_and_clear_raw( m, var->key ); + } +} + +void module_set_fixed_variables( struct module_t * m, int n_variables ) +{ + /* Reallocate */ + struct hash * variable_indices; + LIST * * fixed_variables = BJAM_MALLOC( n_variables * sizeof( LIST * ) ); + if ( m->fixed_variables ) + { + memcpy( fixed_variables, m->fixed_variables, n_variables * sizeof( LIST * ) ); + BJAM_FREE( m->fixed_variables ); + } + m->fixed_variables = fixed_variables; + if ( m->class_module ) + { + variable_indices = m->class_module->variable_indices; + } + else + { + variable_indices = m->variable_indices; + } + if ( variable_indices ) + hashenumerate( variable_indices, &load_fixed_variable, m ); + m->num_fixed_variables = n_variables; +} + +int module_get_fixed_var( struct module_t * m_, OBJECT * name ) +{ + struct fixed_variable * v; + struct module_t * m = m_; + + if ( m->class_module ) + { + m = m->class_module; + } + + if ( !m->variable_indices ) + return -1; + + v = (struct fixed_variable *)hash_find( m->variable_indices, name ); + if ( v && v->n < m_->num_fixed_variables ) + { + return v->n; + } + else + { + return -1; + } +} |