2 * Copyright 2001-2004 David Abrahams.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
20 static struct hash * module_hash = 0;
23 module_t * bindmodule( OBJECT * name )
32 PROFILE_ENTER( BINDMODULE );
38 module_hash = hashinit( sizeof( module_t ), "modules" );
40 m = (module_t *)hash_insert( module_hash, name, &found );
43 m->name = object_copy( name );
45 m->variable_indices = 0;
46 m->num_fixed_variables = 0;
47 m->fixed_variables = 0;
49 m->imported_modules = 0;
55 PROFILE_EXIT( BINDMODULE );
62 * demand_rules() - Get the module's "rules" hash on demand.
64 struct hash * demand_rules( module_t * m )
67 m->rules = hashinit( sizeof( RULE ), "rules" );
73 * delete_module() - wipe out the module's rules and variables.
76 static void delete_rule_( void * xrule, void * data )
78 rule_free( (RULE *)xrule );
82 static void delete_native_rule( void * xrule, void * data )
84 native_rule_t * rule = (native_rule_t *)xrule;
85 object_free( rule->name );
86 if ( rule->procedure )
87 function_free( rule->procedure );
91 static void delete_imported_modules( void * xmodule_name, void * data )
93 object_free( *(OBJECT * *)xmodule_name );
96 static void free_fixed_variable( void * xvar, void * data );
98 void delete_module( module_t * m )
100 /* Clear out all the rules. */
103 hashenumerate( m->rules, delete_rule_, (void *)0 );
104 hash_free( m->rules );
108 if ( m->native_rules )
110 hashenumerate( m->native_rules, delete_native_rule, (void *)0 );
111 hash_free( m->native_rules );
121 if ( m->fixed_variables )
124 for ( i = 0; i < m->num_fixed_variables; ++i )
126 list_free( m->fixed_variables[ i ] );
128 BJAM_FREE( m->fixed_variables );
129 m->fixed_variables = 0;
132 if ( m->variable_indices )
134 hashenumerate( m->variable_indices, &free_fixed_variable, (void *)0 );
135 hash_free( m->variable_indices );
136 m->variable_indices = 0;
139 if ( m->imported_modules )
141 hashenumerate( m->imported_modules, delete_imported_modules, (void *)0 );
142 hash_free( m->imported_modules );
143 m->imported_modules = 0;
150 OBJECT * module_name;
151 struct hashstats rules_stats[ 1 ];
152 struct hashstats variables_stats[ 1 ];
153 struct hashstats variable_indices_stats[ 1 ];
154 struct hashstats imported_modules_stats[ 1 ];
158 static void module_stat( struct hash * hp, OBJECT * module, const char * name )
162 struct hashstats stats[ 1 ];
164 hashstats_init( stats );
166 string_append( id, object_str( module ) );
167 string_push_back( id, ' ' );
168 string_append( id, name );
170 hashstats_add( stats, hp );
171 hashstats_print( stats, id->value );
178 static void class_module_stat( struct hashstats * stats, OBJECT * module, const char * name )
180 if ( stats->item_size )
184 string_append( id, object_str( module ) );
185 string_append( id, " object " );
186 string_append( id, name );
188 hashstats_print( stats, id->value );
195 static void stat_module( void * xmodule, void * data )
197 module_t *m = (module_t *)xmodule;
199 if ( DEBUG_MEM || DEBUG_PROFILE )
201 struct hash * class_info = (struct hash *)data;
202 if ( m->class_module )
205 struct module_stats * ms = (struct module_stats *)hash_insert( class_info, m->class_module->name, &found );
208 ms->module_name = m->class_module->name;
209 hashstats_init( ms->rules_stats );
210 hashstats_init( ms->variables_stats );
211 hashstats_init( ms->variable_indices_stats );
212 hashstats_init( ms->imported_modules_stats );
215 hashstats_add( ms->rules_stats, m->rules );
216 hashstats_add( ms->variables_stats, m->variables );
217 hashstats_add( ms->variable_indices_stats, m->variable_indices );
218 hashstats_add( ms->imported_modules_stats, m->imported_modules );
222 module_stat( m->rules, m->name, "rules" );
223 module_stat( m->variables, m->name, "variables" );
224 module_stat( m->variable_indices, m->name, "fixed variables" );
225 module_stat( m->imported_modules, m->name, "imported modules" );
230 object_free( m->name );
233 static void print_class_stats( void * xstats, void * data )
235 struct module_stats * stats = (struct module_stats *)xstats;
236 class_module_stat( stats->rules_stats, stats->module_name, "rules" );
237 class_module_stat( stats->variables_stats, stats->module_name, "variables" );
238 class_module_stat( stats->variable_indices_stats, stats->module_name, "fixed variables" );
239 class_module_stat( stats->imported_modules_stats, stats->module_name, "imported modules" );
243 static void delete_module_( void * xmodule, void * data )
245 module_t *m = (module_t *)xmodule;
248 object_free( m->name );
254 if ( DEBUG_MEM || DEBUG_PROFILE )
256 struct hash * class_hash = hashinit( sizeof( struct module_stats ), "object info" );
257 hashenumerate( module_hash, stat_module, (void *)class_hash );
258 hashenumerate( class_hash, print_class_stats, (void *)0 );
259 hash_free( class_hash );
261 hashenumerate( module_hash, delete_module_, (void *)0 );
262 hashdone( module_hash );
264 delete_module( &root );
267 module_t * root_module()
273 void import_module( LIST * module_names, module_t * target_module )
275 PROFILE_ENTER( IMPORT_MODULE );
280 if ( !target_module->imported_modules )
281 target_module->imported_modules = hashinit( sizeof( char * ), "imported" );
282 h = target_module->imported_modules;
284 iter = list_begin( module_names ), end = list_end( module_names );
285 for ( ; iter != end; iter = list_next( iter ) )
288 OBJECT * s = list_item( iter );
289 OBJECT * * ss = (OBJECT * *)hash_insert( h, s, &found );
292 *ss = object_copy( s );
296 PROFILE_EXIT( IMPORT_MODULE );
300 static void add_module_name( void * r_, void * result_ )
302 OBJECT * * r = (OBJECT * *)r_;
303 LIST * * result = (LIST * *)result_;
305 *result = list_push_back( *result, object_copy( *r ) );
309 LIST * imported_modules( module_t * module )
312 if ( module->imported_modules )
313 hashenumerate( module->imported_modules, add_module_name, &result );
318 FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter );
319 FUNCTION * function_unbind_variables( FUNCTION * f );
321 struct fixed_variable
333 static void free_fixed_variable( void * xvar, void * data )
335 object_free( ( (struct fixed_variable *)xvar )->key );
338 static void bind_variables_for_rule( void * xrule, void * xdata )
340 RULE * rule = (RULE *)xrule;
341 struct bind_vars_t * data = (struct bind_vars_t *)xdata;
342 if ( rule->procedure && rule->module == data->module )
343 rule->procedure = function_bind_variables( rule->procedure, data->module, &data->counter );
346 void module_bind_variables( struct module_t * m )
348 if ( m != root_module() && m->rules )
350 struct bind_vars_t data;
352 data.counter = m->num_fixed_variables;
353 hashenumerate( m->rules, &bind_variables_for_rule, &data );
354 module_set_fixed_variables( m, data.counter );
358 int module_add_fixed_var( struct module_t * m, OBJECT * name, int * counter )
360 struct fixed_variable * v;
363 assert( !m->class_module );
365 if ( !m->variable_indices )
366 m->variable_indices = hashinit( sizeof( struct fixed_variable ), "variable index table" );
368 v = (struct fixed_variable *)hash_insert( m->variable_indices, name, &found );
371 v->key = object_copy( name );
378 LIST * var_get_and_clear_raw( module_t * m, OBJECT * name );
380 static void load_fixed_variable( void * xvar, void * data )
382 struct fixed_variable * var = (struct fixed_variable *)xvar;
383 struct module_t * m = (struct module_t *)data;
384 if ( var->n >= m->num_fixed_variables )
386 m->fixed_variables[ var->n ] = var_get_and_clear_raw( m, var->key );
390 void module_set_fixed_variables( struct module_t * m, int n_variables )
393 struct hash * variable_indices;
394 LIST * * fixed_variables = BJAM_MALLOC( n_variables * sizeof( LIST * ) );
395 if ( m->fixed_variables )
397 memcpy( fixed_variables, m->fixed_variables, n_variables * sizeof( LIST * ) );
398 BJAM_FREE( m->fixed_variables );
400 m->fixed_variables = fixed_variables;
401 if ( m->class_module )
403 variable_indices = m->class_module->variable_indices;
407 variable_indices = m->variable_indices;
409 if ( variable_indices )
410 hashenumerate( variable_indices, &load_fixed_variable, m );
411 m->num_fixed_variables = n_variables;
414 int module_get_fixed_var( struct module_t * m_, OBJECT * name )
416 struct fixed_variable * v;
417 struct module_t * m = m_;
419 if ( m->class_module )
424 if ( !m->variable_indices )
427 v = (struct fixed_variable *)hash_find( m->variable_indices, name );
428 if ( v && v->n < m_->num_fixed_variables )