mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
Rename to cpp files and add dev builds of b2.
This commit is contained in:
431
src/engine/modules.cpp
Normal file
431
src/engine/modules.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include "jam.h"
|
||||
#include "modules.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "lists.h"
|
||||
#include "native.h"
|
||||
#include "object.h"
|
||||
#include "parse.h"
|
||||
#include "rules.h"
|
||||
#include "strings.h"
|
||||
#include "variable.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct hash * module_hash = 0;
|
||||
static module_t root;
|
||||
|
||||
|
||||
module_t * bindmodule( OBJECT * name )
|
||||
{
|
||||
if ( !name )
|
||||
return &root;
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* demand_rules() - Get the module's "rules" hash on demand.
|
||||
*/
|
||||
struct hash * demand_rules( module_t * m )
|
||||
{
|
||||
if ( !m->rules )
|
||||
m->rules = hashinit( sizeof( RULE ), "rules" );
|
||||
return m->rules;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* delete_module() - wipe out the module's rules and variables.
|
||||
*/
|
||||
|
||||
static void delete_rule_( void * xrule, void * data )
|
||||
{
|
||||
rule_free( (RULE *)xrule );
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
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" );
|
||||
}
|
||||
|
||||
|
||||
static void delete_module_( void * xmodule, void * data )
|
||||
{
|
||||
module_t *m = (module_t *)xmodule;
|
||||
|
||||
delete_module( m );
|
||||
object_free( m->name );
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
return &root;
|
||||
}
|
||||
|
||||
|
||||
void import_module( LIST * module_names, module_t * target_module )
|
||||
{
|
||||
PROFILE_ENTER( IMPORT_MODULE );
|
||||
|
||||
struct hash * h;
|
||||
LISTITER iter;
|
||||
LISTITER end;
|
||||
|
||||
if ( !target_module->imported_modules )
|
||||
target_module->imported_modules = hashinit( sizeof( char * ), "imported"
|
||||
);
|
||||
h = target_module->imported_modules;
|
||||
|
||||
iter = list_begin( module_names );
|
||||
end = list_end( module_names );
|
||||
for ( ; iter != end; iter = list_next( iter ) )
|
||||
{
|
||||
int found;
|
||||
OBJECT * const s = list_item( iter );
|
||||
OBJECT * * const ss = (OBJECT * *)hash_insert( h, s, &found );
|
||||
if ( !found )
|
||||
*ss = object_copy( s );
|
||||
}
|
||||
|
||||
PROFILE_EXIT( IMPORT_MODULE );
|
||||
}
|
||||
|
||||
|
||||
static void add_module_name( void * r_, void * result_ )
|
||||
{
|
||||
OBJECT * * const r = (OBJECT * *)r_;
|
||||
LIST * * const result = (LIST * *)result_;
|
||||
*result = list_push_back( *result, object_copy( *r ) );
|
||||
}
|
||||
|
||||
|
||||
LIST * imported_modules( module_t * module )
|
||||
{
|
||||
LIST * result = L0;
|
||||
if ( module->imported_modules )
|
||||
hashenumerate( module->imported_modules, add_module_name, &result );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION * function_bind_variables( FUNCTION *, module_t *, int * counter );
|
||||
FUNCTION * function_unbind_variables( FUNCTION * );
|
||||
|
||||
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 = (LIST * *)BJAM_MALLOC( n_variables * sizeof( LIST * ) );
|
||||
if ( m->fixed_variables )
|
||||
{
|
||||
memcpy( fixed_variables, m->fixed_variables, m->num_fixed_variables * sizeof( LIST * ) );
|
||||
BJAM_FREE( m->fixed_variables );
|
||||
}
|
||||
m->fixed_variables = fixed_variables;
|
||||
variable_indices = m->class_module
|
||||
? m->class_module->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 );
|
||||
return v && v->n < m_->num_fixed_variables ? v->n : -1;
|
||||
}
|
||||
Reference in New Issue
Block a user