summaryrefslogtreecommitdiff
path: root/tools/build/v2/engine/modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/build/v2/engine/modules.c')
-rw-r--r--tools/build/v2/engine/modules.c394
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;
+ }
+}