void checksum_update(TARGET *t, MD5SUM buildmd5sum) { CHECKSUMDATA cachedata, *c = &cachedata; char buildmd5sumstring[33]; /* If the buildmd5sum is empty, then the file doesn't exist. */ if (ismd5empty(buildmd5sum)) return; /* if the target is available in the cache */ strcpy(buildmd5sumstring, md5tostring(buildmd5sum)); c->boundname = buildmd5sumstring; /* Search for the appropriate .link file that matches the target. */ if (!hashcheck(checksumhash, (HASHDATA **)&c)) { if (hashenter(checksumhash, (HASHDATA **)&c)) { c->boundname = newstr( c->boundname ); c->next = checksumdatalist; checksumdatalist = c; } } memcpy(&c->contentmd5sum, t->contentchecksum->contentmd5sum, MD5_SUMSIZE); c->mtime = 1; c->age = 0; checksumsdirty = 1; }
void profile_enter( char * rulename, profile_frame * frame ) { if ( DEBUG_PROFILE ) { clock_t start = clock(); profile_info info; profile_info * p = &info; if ( !rulename ) p = &profile_other; if ( !profile_hash && rulename ) profile_hash = hashinit( sizeof( profile_info ), "profile" ); info.name = rulename; if ( rulename && hashenter( profile_hash, (HASHDATA * *)&p ) ) p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0; ++p->num_entries; ++p->stack_count; frame->info = p; frame->caller = profile_stack; profile_stack = frame; frame->entry_time = clock(); frame->overhead = 0; frame->subrules = 0; /* caller pays for the time it takes to play with the hash table */ if ( frame->caller ) frame->caller->overhead += frame->entry_time - start; } }
const char * newstr( const char *string ) { STRING str, *s = &str; if( !strhash ) strhash = hashinit( sizeof( STRING ), "strings" ); *s = string; if( hashenter( strhash, (HASHDATA **)&s ) ) { int l = strlen( string ); #if 1 if (!stralloc) stralloc = alloc2_init(4096); char *m = alloc2_enter(stralloc, l + 1); #else char *m = (char *)malloc( l + 1 ); #endif if (DEBUG_MEM) printf("newstr: allocating %d bytes\n", l + 1 ); strtotal += l + 1; memcpy( m, string, l + 1 ); *s = m; } return *s; }
void declare_native_rule( const char * module, const char * rule, const char * * args, LIST * (*f)( FRAME *, int ), int version ) { OBJECT * module_obj = 0; module_t * m; if ( module ) { module_obj = object_new( module ); } m = bindmodule( module_obj ); if ( module_obj ) { object_free( module_obj ); } if (m->native_rules == 0) { m->native_rules = hashinit( sizeof( native_rule_t ), "native rules"); } { native_rule_t n, *np = &n; n.name = object_new( rule ); if (args) { n.arguments = args_new(); lol_build( n.arguments->data, args ); } else { n.arguments = 0; } n.procedure = function_builtin( f, 0 ); n.version = version; hashenter(m->native_rules, (HASHDATA**)&np); } }
OBJECT * path_as_key( OBJECT * path ) { struct path_key_entry e, *result = &e; if ( ! path_key_cache ) path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" ); result->path = path; if ( hashenter( path_key_cache, (HASHDATA * *)&result ) ) { string buf[1]; char * s; string_copy( buf, object_str( path ) ); for ( s = buf->value; s < buf->value + buf->size; ++s ) { if ( *s == '/' ) *s = '\\'; else *s = tolower( *s ); } result->path = object_copy( path ); result->key = object_new( buf->value ); string_free( buf ); } return result->key; }
module_t * bindmodule( OBJECT * name ) { if ( !name ) { return &root; } else { PROFILE_ENTER( BINDMODULE ); module_t m_; module_t * m = &m_; if ( !module_hash ) module_hash = hashinit( sizeof( module_t ), "modules" ); m->name = name; if ( hashenter( module_hash, (HASHDATA * *)&m ) ) { m->name = object_copy( name ); m->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; } }
file_info_t * file_info( OBJECT * filename ) { file_info_t *finfo = &filecache_finfo; if ( !filecache_hash ) filecache_hash = hashinit( sizeof( file_info_t ), "file_info" ); filename = path_as_key( filename ); finfo->name = filename; finfo->is_file = 0; finfo->is_dir = 0; finfo->size = 0; finfo->time = 0; finfo->files = 0; if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) ) { /* printf( "file_info: %s\n", filename ); */ finfo->name = object_copy( finfo->name ); } object_free( filename ); return finfo; }
void setcachedmd5sum( TARGET *t ) { CHECKSUMDATA checksumdata, *c = &checksumdata; const char *target = t->boundname; # ifdef DOWNSHIFT_PATHS char path[ MAXJPATH ]; char *p = path; do *p++ = (char)tolower( *target ); while( *target++ ); target = path; # endif c->boundname = target; if( !hashcheck( checksumhash, (HASHDATA **) &c ) ) { if( hashenter( checksumhash, (HASHDATA **)&c ) ) { c->boundname = newstr( c->boundname ); c->next = checksumdatalist; checksumdatalist = c; } } memcpy(c->contentmd5sum, t->contentmd5sum, sizeof(MD5SUM)); c->mtime = t->time; c->age = 0; checksumsdirty = 1; }
static void bind_explicitly_located_target(void* xtarget, void* data) { TARGET* t = (TARGET*)xtarget; if (! (t->flags & T_FLAG_NOTFILE) ) { /* Check if there's a setting for LOCATE_TARGET */ SETTINGS* s = t->settings; for(; s ; s = s->next) { if (strcmp(s->symbol, "LOCATE") == 0) { pushsettings(t->settings); t->boundname = search( t->name, &t->time ); t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; popsettings(t->settings); { LOCATED_TARGET lt, *lta = < lt.file_name = t->boundname; lt.target = t; if (!located_targets) located_targets = hashinit( sizeof(LOCATED_TARGET), "located targets" ); /* TODO: should check if we've entered the item or not. */ hashenter(located_targets, (HASHDATA **)<a); } break; } } } }
static void profile_enter( char* rulename, profile_frame* frame ) { clock_t start = clock(); profile_info info, *p = &info; if ( !profile_hash ) profile_hash = hashinit(sizeof(profile_info), "profile"); info.name = rulename; if ( hashenter( profile_hash, (HASHDATA **)&p ) ) p->cumulative = p->net = p->num_entries = p->stack_count = 0; ++(p->num_entries); ++(p->stack_count); frame->info = p; frame->caller = profile_stack; profile_stack = frame; frame->entry_time = clock(); frame->overhead = 0; frame->subrules = 0; /* caller pays for the time it takes to play with the hash table */ if ( frame->caller ) frame->caller->overhead += frame->entry_time - start; }
RULE * bindrule( const char *rulename ) { RULE rule, *r = &rule; if( !rulehash ) rulehash = hashinit( sizeof( RULE ), "rules" ); r->name = rulename; if( hashenter( rulehash, (HASHDATA **)&r ) ) { r->name = newstr( rulename ); /* never freed */ r->procedure = (PARSE *)0; r->actions = (char *)0; r->bindlist = L0; r->params = L0; r->flags = 0; # ifdef OPT_RULE_PROFILING_EXT if ( DEBUG_PROFILE_RULES ) { r->invocations = 0; r->invocation_time = 0; r->next_profiling_rule = profiling_rule_list; profiling_rule_list = r; } # endif } return r; }
static void time_enter( void *closure, char *target, int found, time_t time ) { BINDING binding, *b = &binding; struct hash *bindhash = (struct hash *)closure; # ifdef DOWNSHIFT_PATHS char path[ MAXJPATH ]; char *p = path; do *p++ = tolower( *target ); while( *target++ ); target = path; # endif b->name = target; b->flags = 0; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( target ); /* never freed */ b->time = time; b->progress = found ? BIND_FOUND : BIND_SPOTTED; if( DEBUG_BINDSCAN ) printf( "time ( %s ) : %s\n", target, time_progress[b->progress] ); }
int hcache_getrulemd5sum( TARGET *t ) { HCACHEDATA cachedata, *c = &cachedata; const char *target = t->name; # ifdef DOWNSHIFT_PATHS char path[ MAXJPATH ]; char *p; # endif HCACHEFILE *file = hcachefile_get( t ); if ( !file->cachefilename ) return 1; # ifdef DOWNSHIFT_PATHS p = path; do *p++ = (char)tolower( *target ); while( *target++ ); target = path; # endif c->boundname = target; if( hashcheck( hcachehash, (HASHDATA **) &c ) ) { if( memcmp( &c->currentrulemd5sum, &t->rulemd5sum, MD5_SUMSIZE ) == 0 ) return 1; memcpy( &c->currentrulemd5sum, &t->rulemd5sum, MD5_SUMSIZE ); } else { // Enter it into the cache. if( hashenter( hcachehash, (HASHDATA **)&c ) ) { c->boundname = newstr( c->boundname ); c->file = file; c->next = c->file->hcachelist; c->file->hcachelist = c; c->mtime = 0; memcpy( &c->currentrulemd5sum, &t->rulemd5sum, MD5_SUMSIZE ); memset( &c->rulemd5sum, 0, MD5_SUMSIZE ); memset( &c->currentcontentmd5sum, 0, MD5_SUMSIZE ); memset( &c->contentmd5sum, 0, MD5_SUMSIZE ); c->time = 0; c->age = 0; c->includes = NULL; c->hdrscan = NULL; } } c->file->dirty = 1; return 0; }
void macro_headers( TARGET *t ) { static regexp *re = 0; FILE *f; char buf[ 1024 ]; if ( DEBUG_HEADER ) printf( "macro header scan for %s\n", t->name ); /* this regexp is used to detect lines of the form */ /* "#define MACRO <....>" or "#define MACRO "....." */ /* in the header macro files.. */ if ( re == 0 ) { re = regex_compile( "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*" "[<\"]([^\">]*)[\">].*$" ); } if ( !( f = fopen( t->boundname, "r" ) ) ) return; while ( fgets( buf, sizeof( buf ), f ) ) { HEADER_MACRO var; HEADER_MACRO *v = &var; if ( regexec( re, buf ) && re->startp[1] ) { /* we detected a line that looks like "#define MACRO filename */ re->endp[1][0] = '\0'; re->endp[2][0] = '\0'; if ( DEBUG_HEADER ) printf( "macro '%s' used to define filename '%s' in '%s'\n", re->startp[1], re->startp[2], t->boundname ); /* add macro definition to hash table */ if ( !header_macros_hash ) header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" ); v->symbol = re->startp[1]; v->filename = 0; if ( hashenter( header_macros_hash, (HASHDATA **)&v ) ) { v->symbol = newstr( re->startp[1] ); /* never freed */ v->filename = newstr( re->startp[2] ); /* never freed */ } /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */ /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */ } } fclose( f ); }
regexp* regex_compile( const char* pattern ) { regex_entry entry, *e = &entry; entry.pattern = pattern; if ( !regex_hash ) regex_hash = hashinit(sizeof(regex_entry), "regex"); if ( hashenter( regex_hash, (HASHDATA **)&e ) ) e->regex = regcomp( (char*)pattern ); return e->regex; }
HEADER *headersDepth(const char *t, time_t time, int depth) { HEADER hdr, *h = &hdr; LIST *l; const char* cachekey=t; /* D support (doesn't affect C(++), because a source file is never included) */ if(depth == 0) { cachekey=malloc(strlen(t)+sizeof("source:")); strcpy((char*)cachekey,"source:"); strcpy((char*)cachekey+7,t); } if (!headerhash) headerhash = hashinit(sizeof(HEADER), "headers"); h->key = cachekey; h->includes = 0; h->time = time; h->headers = 0; h->newest = 0; if (!hashenter(headerhash, (HASHDATA **)&h)) return h; h->key = newstr(t); #ifdef USE_CACHE if (!cache_check(cachekey, time, &h->includes)) { h->includes = headers1(t, depth); cache_enter(cachekey, time, h->includes); } #else h->includes = headers1(t, depth); #endif if(depth == 0) free((char*)cachekey); l = h->includes; while (l) { const char *t2 = search(t, l->string, &time); if (time) h->headers = headerentry(h->headers, headersDepth(t2, time, depth+1)); l = list_next(l); } return h; }
/*! \brief Adds a jcache_entry to a jamfile_cache. \param cache The jamfile_cache. \param entry The jcache_entry to be added. \return \c !0, if everything went fine, 0, if an error occured (out of memory). */ static int add_jcache_entry(jamfile_cache* cache, jcache_entry* entry) { int result = 0; if (cache && entry) { result = push_string(cache->filenames, entry->filename); if (result) { result = hashenter(cache->entries, (HASHDATA**)&entry); if (!result) pop_string(cache->filenames); } } return result; }
static VARIABLE * var_enter( char *symbol ) { VARIABLE var, *v = &var; if( !varhash ) varhash = hashinit( sizeof( VARIABLE ), "variables" ); v->symbol = symbol; v->value = 0; if( hashenter( varhash, (HASHDATA **)&v ) ) v->symbol = newstr( symbol ); /* never freed */ return v; }
static VARIABLE * var_enter( OBJECT * symbol ) { VARIABLE var; VARIABLE * v = &var; if ( !varhash ) varhash = hashinit( sizeof( VARIABLE ), "variables" ); v->symbol = symbol; v->value = 0; if ( hashenter( varhash, (HASHDATA * *)&v ) ) v->symbol = object_copy( symbol ); return v; }
/* * Set cached md5sum of a file. */ void setcachedmd5sum( TARGET *t ) { HCACHEDATA cachedata, *c = &cachedata; const char *target = t->boundname; # ifdef DOWNSHIFT_PATHS char path[ MAXJPATH ]; char *p; #endif HCACHEFILE *file = hcachefile_get( t ); # ifdef DOWNSHIFT_PATHS p = path; do *p++ = (char)tolower( *target ); while( *target++ ); target = path; # endif c->boundname = target; if( !hashcheck( hcachehash, (HASHDATA **) &c ) ) { if( hashenter( hcachehash, (HASHDATA **)&c ) ) { c->boundname = newstr( c->boundname ); c->file = file; c->next = c->file->hcachelist; c->file->hcachelist = c; c->time = t->time; c->includes = NULL; c->hdrscan = NULL; } } c->file->dirty = 1; /* 'c' points at the cache entry. Its out of date. */ memcpy(c->rulemd5sum, t->rulemd5sum, sizeof(MD5SUM)); memcpy(c->currentrulemd5sum, t->rulemd5sum, sizeof(MD5SUM)); memcpy(c->contentmd5sum, t->contentmd5sum, sizeof(MD5SUM)); memcpy(c->currentcontentmd5sum, t->contentmd5sum, sizeof(MD5SUM)); c->mtime = t->time; c->age = 0; }
const char * newstr( const char *string ) { STRING str, *s = &str; if( !strhash ) strhash = hashinit( sizeof( STRING ), "strings" ); *s = string; if( hashenter( strhash, (HASHDATA **)&s ) ) { size_t l = strlen( string ); #ifdef OPT_IMPROVED_MEMUSE_EXT char *m; if (!str_allocbuf || (str_allocbuf + l + 1) >= str_allocend) { str_allocbuf = malloc( l + 1 ); str_allocend = str_allocbuf + l + 1; #ifdef OPT_DEBUG_MEM_TOTALS_EXT ++str_allocs; #endif } m = str_allocbuf; str_allocbuf += (l + 1); #else char *m = (char *)malloc( l + 1 ); if (DEBUG_MEM) printf("newstr: allocating %d bytes\n", l + 1 ); #endif strtotal += l + 1; #ifdef OPT_DEBUG_MEM_TOTALS_EXT #ifndef OPT_IMPROVED_MEMUSE_EXT ++str_allocs; #endif #endif memcpy( m, string, l + 1 ); *s = m; } return *s; }
TARGET * bindtarget( OBJECT * target_name ) { TARGET target; TARGET * t = ⌖ if ( !targethash ) targethash = hashinit( sizeof( TARGET ), "targets" ); t->name = target_name; if ( hashenter( targethash, (HASHDATA * *)&t ) ) { memset( (char *)t, '\0', sizeof( *t ) ); t->name = object_copy( target_name ); t->boundname = object_copy( t->name ); /* default for T_FLAG_NOTFILE */ } return t; }
TARGET * bindtarget( char *targetname ) { TARGET target, *t = ⌖ if( !targethash ) targethash = hashinit( sizeof( TARGET ), "targets" ); t->name = targetname; if( hashenter( targethash, (HASHDATA **)&t ) ) { memset( (char *)t, '\0', sizeof( *t ) ); t->name = newstr( targetname ); /* never freed */ t->boundname = t->name; /* default for T_FLAG_NOTFILE */ } return t; }
/* * enter_rule() - return pointer to RULE, creating it if necessary in * target_module. */ static RULE * enter_rule( char *rulename, module *target_module ) { RULE rule, *r = &rule; r->name = rulename; if ( hashenter( target_module->rules, (HASHDATA **)&r ) ) { r->name = newstr( rulename ); /* never freed */ r->procedure = (PARSE *)0; r->module = 0; r->actions = 0; r->arguments = 0; r->exported = 0; r->module = target_module; } return r; }
OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame ) { OBJECT * name = class_module_name( xname->value ); OBJECT * * pp = &xname->value; module_t * class_module = 0; module_t * outer_module = frame->module; OBJECT * name_ = object_new( "__name__" ); OBJECT * bases_ = object_new( "__bases__" ); if ( !classes ) classes = hashinit( sizeof( OBJECT * ), "classes" ); if ( hashenter( classes, (HASHDATA * *)&pp ) ) { *pp = object_copy( xname->value ); } else { printf( "Class %s already defined\n", object_str( xname->value ) ); abort(); } check_defined( bases ); class_module = bindmodule( name ); exit_module( outer_module ); enter_module( class_module ); var_set( name_, xname, VAR_SET ); var_set( bases_, bases, VAR_SET ); exit_module( class_module ); enter_module( outer_module ); for ( ; bases; bases = bases->next ) import_base_rules( class_module, bases->value ); object_free( bases_ ); object_free( name_ ); return name; }
static HDR *hdr_enter(const char *file) { HDR hdr, *h = &hdr; if (!hdrhash) hdrhash = hashinit(sizeof (HDR), "headers"); h->file = file; h->time = 0; h->includes = 0; h->next = 0; h->tail = 0; if (hashenter(hdrhash, (HASHDATA **)&h)) { h->file = newstr(file); /* never freed */ h->tail = h; hdrlist = hdr_append(hdrlist, h); } return h; }
static RULE * enter_rule( OBJECT * rulename, module_t * target_module ) { RULE rule; RULE * r = &rule; r->name = rulename; if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) ) { r->name = object_copy( rulename ); r->procedure = 0; r->module = 0; r->actions = 0; r->arguments = 0; r->exported = 0; r->module = target_module; #ifdef HAVE_PYTHON r->python_function = 0; #endif } return r; }
void import_module( LIST * module_names, module_t * target_module ) { PROFILE_ENTER( IMPORT_MODULE ); struct hash * h; 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 ) { OBJECT * s = module_names->value; OBJECT * * ss = &s; if( hashenter( h, (HASHDATA * *)&ss ) ) { *ss = object_copy( s ); } } PROFILE_EXIT( IMPORT_MODULE ); }
/* * enter_rule() - return pointer to RULE, creating it if necessary in * target_module. */ static RULE * enter_rule( char *rulename, module_t *target_module ) { RULE rule, *r = &rule; r->name = rulename; if ( hashenter( demand_rules( target_module ), (HASHDATA **)&r ) ) { r->name = newstr( rulename ); /* never freed */ r->procedure = (PARSE *)0; r->module = 0; r->actions = 0; r->arguments = 0; r->exported = 0; r->module = target_module; #ifdef HAVE_PYTHON r->python_function = 0; #endif } return r; }
OBJECT * search( OBJECT * target, time_t *time, OBJECT * * another_target, int file ) { PATHNAME f[1]; LIST * varlist; string buf[1]; int found = 0; /* Will be set to 1 if target location is specified via LOCATE. */ int explicitly_located = 0; OBJECT * boundname = 0; OBJECT * varname; if ( another_target ) *another_target = 0; if (! explicit_bindings ) explicit_bindings = hashinit( sizeof(BINDING), "explicitly specified locations"); string_new( buf ); /* Parse the filename */ path_parse( object_str( target ), f ); f->f_grist.ptr = 0; f->f_grist.len = 0; varname = object_new( "LOCATE" ); varlist = var_get( varname ); object_free( varname ); if ( varlist ) { OBJECT * key; f->f_root.ptr = object_str( varlist->value ); f->f_root.len = strlen( object_str( varlist->value ) ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "locate %s: %s\n", object_str( target ), buf->value ); explicitly_located = 1; key = object_new( buf->value ); timestamp( key, time ); object_free( key ); found = 1; } else if ( ( varname = object_new( "SEARCH" ), varlist = var_get( varname ), object_free( varname ), varlist ) ) { while ( varlist ) { BINDING b, *ba = &b; file_info_t *ff; OBJECT * key; OBJECT * test_path; f->f_root.ptr = object_str( varlist->value ); f->f_root.len = strlen( object_str( varlist->value ) ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); test_path = object_new( buf->value ); key = path_as_key( test_path ); object_free( test_path ); ff = file_query( key ); timestamp( key, time ); b.binding = key; if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) ) { if ( DEBUG_SEARCH ) printf(" search %s: found explicitly located target %s\n", object_str( target ), object_str( ba->target ) ); if ( another_target ) *another_target = ba->target; found = 1; object_free( key ); break; } else if ( ff && ff->time ) { if ( !file || ff->is_file ) { found = 1; object_free( key ); break; } } object_free( key ); varlist = list_next( varlist ); } } if ( !found ) { /* Look for the obvious */ /* This is a questionable move. Should we look in the */ /* obvious place if SEARCH is set? */ OBJECT * key; f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); key = object_new( buf->value ); timestamp( key, time ); object_free( key ); } boundname = object_new( buf->value ); string_free( buf ); if ( explicitly_located ) { BINDING b; BINDING * ba = &b; OBJECT * key = path_as_key( boundname ); b.binding = key; b.target = target; /* CONSIDER: we probably should issue a warning is another file is explicitly bound to the same location. This might break compatibility, though. */ if ( !hashenter( explicit_bindings, (HASHDATA * *)&ba ) ) { object_free( key ); } } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); return boundname; }