int make( int n_targets, const char **targets, int anyhow ) { int i; COUNTS counts[1]; int status = 0; /* 1 if anything fails */ #ifdef OPT_HEADER_CACHE_EXT hcache_init(); #endif memset( (char *)counts, 0, sizeof( *counts ) ); for( i = 0; i < n_targets; i++ ) { TARGET *t = bindtarget( targets[i] ); make0( t, 0, 0, counts, anyhow ); } if( DEBUG_MAKE ) { if( counts->targets ) printf( "...found %d target(s)...\n", counts->targets ); if( counts->temp ) printf( "...using %d temp target(s)...\n", counts->temp ); if( counts->updating ) printf( "...updating %d target(s)...\n", counts->updating ); if( counts->cantfind ) printf( "...can't find %d target(s)...\n", counts->cantfind ); if( counts->cantmake ) printf( "...can't make %d target(s)...\n", counts->cantmake ); } #ifdef OPT_HEADER_CACHE_EXT hcache_done(); #endif status = counts->cantfind || counts->cantmake; for( i = 0; i < n_targets; i++ ) status |= make1( bindtarget( targets[i] ) ); return status; }
LIST * builtin_md5file( PARSE *parse, LOL *args, int *jmp ) { MD5_CTX context; unsigned char digest[16]; unsigned char digest_string[33]; unsigned char* p; int i; LIST *l; LIST *result; const size_t BUFFER_SIZE = 100 * 1024; unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE); MD5Init(&context); /* For each argument */ for (i = 0; i < args->count; ++i) { l = lol_get(args, i); if (l) { do { FILE* file; TARGET *t = bindtarget(l->string); pushsettings( t->settings ); t->boundname = search( t->name, &t->time ); popsettings( t->settings ); file = fopen(t->boundname, "rb"); if (file) { size_t readSize; do { readSize = fread(buffer, 1, BUFFER_SIZE, file); MD5Update(&context, buffer, readSize); } while (readSize != 0); fclose(file); } l = list_next(l); } while (l); } } free(buffer); MD5Final(digest, &context); p = digest_string; for (i = 0, p = digest_string; i < 16; i++, p += 2) { sprintf((char*)p, "%02x", digest[i]); } *p = 0; result = list_new(L0, (const char*)digest_string, 0); return result; }
static SETTINGS * make1settings( LIST *vars ) { SETTINGS *settings = 0; for( ; vars; vars = list_next( vars ) ) { LIST *l = var_get( vars->string ); LIST *nl = 0; for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); /* Make sure the target is bound, warning if it is not in the */ /* dependency graph. */ if( t->binding == T_BIND_UNBOUND ) make1bind( t, 1 ); /* Build new list */ nl = list_new( nl, t->boundname, 1 ); } /* Add to settings chain */ settings = addsettings( settings, 0, vars->string, nl ); } return settings; }
LIST * builtin_usefilecache( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); const char* cachevar = l2 ? l2->string : "generic"; BUFFER buff; buffer_init( &buff ); buffer_addstring( &buff, "FILECACHE.", 10 ); buffer_addstring( &buff, cachevar, strlen( cachevar ) ); buffer_addchar( &buff, 0 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->settings = addsettings( t->settings, VAR_SET, "FILECACHE", list_new( L0, buffer_ptr( &buff ), 0 ) ); t->flags |= parse->num; } buffer_free( &buff ); return L0; }
static SETTINGS * make1settings( struct module_t * module, LIST * vars ) { SETTINGS * settings = 0; LISTITER vars_iter = list_begin( vars ); LISTITER const vars_end = list_end( vars ); for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) ) { LIST * const l = var_get( module, list_item( vars_iter ) ); LIST * nl = L0; LISTITER iter = list_begin( l ); LISTITER const end = list_end( l ); for ( ; iter != end; iter = list_next( iter ) ) { TARGET * const t = bindtarget( list_item( iter ) ); /* Make sure the target is bound. */ if ( t->binding == T_BIND_UNBOUND ) make1bind( t ); /* Build a new list. */ nl = list_push_back( nl, object_copy( t->boundname ) ); } /* Add to settings chain. */ settings = addsettings( settings, VAR_SET, list_item( vars_iter ), nl ); } return settings; }
static SETTINGS * make1settings( LIST *vars ) { SETTINGS *settings = 0; for( ; vars; vars = list_next( vars ) ) { LIST *l = var_get( vars->string ); LIST *nl = 0; for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); /* Make sure the target is bound */ if( t->binding == T_BIND_UNBOUND ) make1bind( t ); /* Build new list */ nl = list_new( nl, copystr( t->boundname ) ); } /* Add to settings chain */ settings = addsettings( settings, 0, vars->string, nl ); } return settings; }
int LS_jam_setvar(ls_lua_State *L) { int numParams = ls_lua_gettop(L); if (numParams < 2 || numParams > 3) return 0; if (!ls_lua_isstring(L, 1)) return 0; if (numParams == 2) { var_set(ls_lua_tostring(L, 1), luahelper_addtolist(L, L0, 2), VAR_SET); } else { TARGET *t; if (!ls_lua_isstring(L, 2)) return 0; t = bindtarget(ls_lua_tostring(L, 1)); pushsettings(t->settings); var_set(ls_lua_tostring(L, 2), luahelper_addtolist(L, L0, 3), VAR_SET); popsettings(t->settings); } return 0; }
/* * Get a filename in cache for given md5sum. */ const char *filecache_getpath(TARGET *t) { char buffer[1024]; LIST *filecache; const char *cachedir = NULL; LIST *cachevar; pushsettings( t->settings ); filecache = var_get( "FILECACHE" ); if ( !filecache ) { popsettings( t->settings ); return NULL; } /* get directory where objcache should reside */ strcpy( buffer, filecache->string ); strcat( buffer, ".PATH" ); cachevar = var_get( buffer ); if( cachevar ) { TARGET *t = bindtarget( cachevar->string ); t->boundname = search( t->name, &t->time ); cachedir = copystr( t->boundname ); } popsettings( t->settings ); return cachedir; }
static const char * cache_name( void ) { static OBJECT * name = 0; if ( !name ) { LIST * hcachevar = var_get( root_module(), constant_HCACHEFILE ); if ( !list_empty( hcachevar ) ) { TARGET * t = bindtarget( list_front( hcachevar ) ); pushsettings( root_module(), t->settings ); /* Do not expect the cache file to be generated, so pass 0 as the * third argument to search. Expect the location to be specified via * LOCATE, so pass 0 as the fourth arugment. */ object_free( t->boundname ); t->boundname = search( t->name, &t->time, 0, 0 ); popsettings( root_module(), t->settings ); name = object_copy( t->boundname ); } } return name ? object_str( name ) : 0; }
static const char * cache_name( void ) { static OBJECT * name = 0; if ( !name ) { OBJECT * hcachename = object_new( "HCACHEFILE" ); LIST * hcachevar = var_get( hcachename ); object_free( hcachename ); if ( hcachevar ) { TARGET * t = bindtarget( hcachevar->value ); pushsettings( t->settings ); /* Do not expect the cache file to be generated, so pass 0 as the * third argument to search. Expect the location to be specified via * LOCATE, so pass 0 as the fourth arugment. */ object_free( t->boundname ); t->boundname = search( t->name, &t->time, 0, 0 ); popsettings( t->settings ); if ( hcachevar ) name = object_copy( t->boundname ); } } return name ? object_str( name ) : 0; }
LIST * compile_on( PARSE *parse, FRAME *frame ) { LIST *nt = parse_evaluate( parse->left, frame ); LIST *result = 0; if( DEBUG_COMPILE ) { debug_compile( 0, "on", frame ); list_print( nt ); printf( "\n" ); } if( nt ) { TARGET *t = bindtarget( nt->string ); pushsettings( t->settings ); result = parse_evaluate( parse->right, frame ); popsettings( t->settings ); } list_free( nt ); return result; }
TARGETS * targetlist( TARGETS *chain, LIST *targets ) { for( ; targets; targets = list_next( targets ) ) chain = targetentry( chain, bindtarget( targets->string ) ); return chain; }
LIST * builtin_flags( PARSE *parse, FRAME *frame ) { LIST *l = lol_get( frame->args, 0 ); for( ; l; l = list_next( l ) ) bindtarget( l->string )->flags |= parse->num; return L0; }
LIST * builtin_flags( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); for( ; l; l = list_next( l ) ) bindtarget( l->string )->flags |= parse->num; return L0; }
LIST * builtin_depends( PARSE *parse, FRAME *frame ) { LIST *targets = lol_get( frame->args, 0 ); LIST *sources = lol_get( frame->args, 1 ); LIST *l; for( l = targets; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); /* If doing INCLUDES, switch to the TARGET's include */ /* TARGET, creating it if needed. The internal include */ /* TARGET shares the name of its parent. */ if( parse->num ) { if( !t->includes ) { t->includes = copytarget( t ); t->includes->original_target = t; } t = t->includes; } t->depends = targetlist( t->depends, sources ); } /* Enter reverse links */ for( l = sources; l; l = list_next( l ) ) { TARGET *s = bindtarget( l->string ); s->dependents = targetlist( s->dependents, targets ); } return L0; }
/* push the next MAKE1C state after a command is run. */ static void push_cmds( CMDLIST * cmds, int status ) { CMDLIST * cmd_iter; for( cmd_iter = cmds; cmd_iter; cmd_iter = cmd_iter->next ) { if ( cmd_iter->iscmd ) { CMD * next_cmd = cmd_iter->impl.cmd; /* Propagate the command status. */ if ( next_cmd->status < status ) next_cmd->status = status; if ( --next_cmd->asynccnt == 0 ) { /* Select the first target associated with the action. * This is safe because sibling CMDs cannot have targets * in common. */ TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) ); first_target->cmds = (char *)next_cmd; push_state( &state_stack, first_target, NULL, T_STATE_MAKE1C ); } else if ( DEBUG_EXECCMD ) { TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) ); printf( "Delaying %s %s: %d targets not ready\n", object_str( next_cmd->rule->name ), object_str( first_target->boundname ), next_cmd->asynccnt ); } } else { /* This is a target that we're finished updating */ TARGET * updated_target = cmd_iter->impl.t; if ( updated_target->status < status ) updated_target->status = status; updated_target->cmds = NULL; push_state( &state_stack, updated_target, NULL, T_STATE_MAKE1C ); } } }
LIST * builtin_flags_nocare( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); for( ; l; l = list_next( l ) ) { TARGET* t = bindtarget( l->string ); if ( ! ( t->flags & T_FLAG_FORCECARE ) ) t->flags |= T_FLAG_NOCARE; } return L0; }
LIST * builtin_usemd5callback( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->settings = addsettings( t->settings, VAR_SET, "MD5CALLBACK", list_copy( L0, l2 ) ); } return L0; }
LIST * builtin_depends( PARSE *parse, LOL *args, int *jmp ) { int curindex = 0; while ( 1 ) { LIST *targets = lol_get( args, curindex ); LIST *sources = lol_get( args, curindex + 1 ); LIST *l; if ( !sources ) break; for( l = targets; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); /* If doing INCLUDES, switch to the TARGET's include */ /* TARGET, creating it if needed. The internal include */ /* TARGET shares the name of its parent. */ #ifdef OPT_BUILTIN_NEEDS_EXT if( parse->num==1 ) #else if( parse->num ) #endif { if( !t->includes ) t->includes = copytarget( t ); t = t->includes; } #ifdef OPT_BUILTIN_NEEDS_EXT t->depends = targetlist( t->depends, sources, (char)(parse->num==2) ); #else t->depends = targetlist( t->depends, sources ); #endif } ++curindex; } return L0; }
LIST * builtin_usecommandline( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->settings = addsettings( t->settings, VAR_SET, "COMMANDLINE", list_copy( L0, l2 ) ); t->flags |= parse->num; } return L0; }
LIST * builtin_rebuilds( PARSE *parse, FRAME *frame ) { LIST *targets = lol_get( frame->args, 0 ); LIST *rebuilds = lol_get( frame->args, 1 ); LIST *l; for( l = targets; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->rebuilds = targetlist( t->rebuilds, rebuilds ); } return L0; }
LIST * builtin_usedepcache( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); if ( l2 ) t->settings = addsettings( t->settings, VAR_SET, "DEPCACHE", list_copy( L0, l2 ) ); else t->settings = addsettings( t->settings, VAR_SET, "DEPCACHE", L0 ); t->flags |= parse->num; } return L0; }
LIST * compile_include( PARSE *parse, FRAME *frame ) { LIST *nt = parse_evaluate( parse->left, frame ); if( DEBUG_COMPILE ) { debug_compile( 0, "include", frame); list_print( nt ); printf( "\n" ); } if( nt ) { TARGET *t = bindtarget( nt->string ); /* DWA 2001/10/22 - Perforce Jam clears the arguments here, which * prevents an included file from being treated as part of the body * of a rule. I didn't see any reason to do that, so I lifted the * restriction. */ /* Bind the include file under the influence of */ /* "on-target" variables. Though they are targets, */ /* include files are not built with make(). */ pushsettings( t->settings ); /* We don't expect that file to be included is generated by some action. Therefore, pass 0 as third argument. */ t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); parse_file( t->boundname, frame ); } list_free( nt ); return L0; }
int LS_jam_getvar(ls_lua_State *L) { LIST *list; LISTITEM* item; int index; int numParams = ls_lua_gettop(L); if (numParams < 1 || numParams > 2) return 0; if (!ls_lua_isstring(L, 1)) return 0; if (numParams == 1) { list = var_get(ls_lua_tostring(L, 1)); } else { TARGET *t; if (!ls_lua_isstring(L, 2)) return 0; t = bindtarget(ls_lua_tostring(L, 1)); pushsettings(t->settings); list = var_get(ls_lua_tostring(L, 2)); popsettings(t->settings); } ls_lua_newtable(L); index = 1; for (item = list_first(list); item; item = list_next(item), ++index) { ls_lua_pushnumber(L, index); ls_lua_pushstring(L, list_value(item)); ls_lua_settable(L, -3); } return 1; }
LIST * compile_settings( PARSE *parse, FRAME *frame ) { LIST *nt = parse_evaluate( parse->left, frame ); LIST *ns = parse_evaluate( parse->third, frame ); LIST *targets = parse_evaluate( parse->right, frame ); LIST *ts; int append = parse->num == ASSIGN_APPEND; if( DEBUG_COMPILE ) { debug_compile( 0, "set", frame); list_print( nt ); printf( " on " ); list_print( targets ); printf( " %s ", append ? "+=" : "=" ); list_print( ns ); printf( "\n" ); } /* Call addsettings to save variable setting */ /* addsettings keeps ns, so need to copy it */ /* Pass append flag to addsettings() */ for( ts = targets; ts; ts = list_next( ts ) ) { TARGET *t = bindtarget( ts->string ); LIST *l; for( l = nt; l; l = list_next( l ) ) t->settings = addsettings( t->settings, append, l->string, list_copy( (LIST*)0, ns ) ); } list_free( nt ); list_free( targets ); return ns; }
LIST * compile_settings( PARSE *parse, LOL *args, int *jmp ) { LIST *nt = (*parse->left->func)( parse->left, args, jmp ); LIST *ns = (*parse->third->func)( parse->third, args, jmp ); LIST *targets = (*parse->right->func)( parse->right, args, jmp ); LISTITEM *ts; if( DEBUG_COMPILE ) { debug_compile( 0, "set" ); list_print( nt ); printf( "on " ); list_print( targets ); printf( " %s ", set_names[ parse->num ] ); list_print( ns ); printf( "\n" ); } /* Call addsettings to save variable setting */ /* addsettings keeps ns, so need to copy it */ /* Pass append flag to addsettings() */ for( ts = list_first(targets); ts; ts = list_next( ts ) ) { TARGET *t = bindtarget( list_value(ts) ); LISTITEM *l; for( l = list_first(nt); l; l = list_next( l ) ) t->settings = addsettings( t->settings, parse->num, list_value(l), list_copy( NULL, ns ) ); } list_free( nt ); list_free( targets ); return ns; }
/* * Return the name of the header cache file. May return NULL. * * The user sets this by setting the HCACHEFILE variable in a Jamfile. * We cache the result so the user can't change the cache file during * header scanning. */ static char* cache_name(void) { static char* name = 0; if (!name) { LIST *hcachevar = var_get("HCACHEFILE"); if (hcachevar) { TARGET *t = bindtarget( hcachevar->string ); pushsettings( t->settings ); t->boundname = search( t->name, &t->time ); popsettings( t->settings ); if (hcachevar) { name = copystr(t->boundname); } } } return name; }
const char *checksums_filename() { LIST *var; if ( checksumsfilename ) { return checksumsfilename; } var = var_get( "JAM_CHECKSUMS_FILE" ); if ( list_first( var ) ) { const char *value = list_value( list_first( var ) ); TARGET *t = bindtarget( value ); checksumsfilename = copystr( search_using_target_settings( t, t->name, &t->time ) ); } if ( !checksumsfilename ) { PATHNAME f[1]; char buf[ MAXJPATH ]; var = var_get( "ALL_LOCATE_TARGET" ); if ( !var ) { var = var_get( "CWD" ); } path_parse( ".jamchecksums", f ); f->f_grist.ptr = 0; f->f_grist.len = 0; if ( var ) { f->f_root.ptr = list_value( list_first( var ) ); f->f_root.len = (int)( strlen( f->f_root.ptr ) ); } path_build( f, buf, 1, 1 ); checksumsfilename = newstr( buf ); } return checksumsfilename; }
LIST * compile_include( PARSE *parse, LOL *args, int *jmp ) { LIST *nt = (*parse->left->func)( parse->left, args, jmp ); if( DEBUG_COMPILE ) { debug_compile( 0, "include" ); list_print( nt ); printf( "\n" ); } if( nt && list_first(nt) ) { TARGET *t = bindtarget( list_value(list_first(nt)) ); /* Bind the include file under the influence of */ /* "on-target" variables. Though they are targets, */ /* include files are not built with make(). */ /* Needn't copysettings(), as search sets no vars. */ pushsettings( t->settings ); t->boundname = search( t->name, &t->time ); popsettings( t->settings ); /* Don't parse missing file if NOCARE set */ if( t->time || !( t->flags & T_FLAG_NOCARE ) ) parse_file( t->boundname ); } list_free( nt ); return L0; }
/* * Return the name of the header cache file. May return NULL. * * The user sets this by setting the HCACHEFILE variable in a Jamfile. * We cache the result so the user can't change the cache file during * header scanning. */ static char* cache_name(void) { static char* name = 0; if (!name) { LIST *hcachevar = var_get("HCACHEFILE"); if (hcachevar) { TARGET *t = bindtarget( hcachevar->string ); pushsettings( t->settings ); /* Don't expect cache file to be generated, so pass 0 as third argument to search. */ t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); if (hcachevar) { name = copystr(t->boundname); } } } return name; }