Move autoload class into autoload.h and cpp

This commit is contained in:
ridiculousfish
2012-01-25 18:59:35 -08:00
parent d6545588a3
commit 843ba4ac2c
4 changed files with 327 additions and 321 deletions

View File

@@ -39,7 +39,6 @@
#include "signal.h"
#include "wildcard.h"
#include "halloc_util.h"
#include "builtin_scripts.h"
/**
Maximum number of autoloaded items opf a specific type to keep in
@@ -601,218 +600,6 @@ void parse_util_token_extent( const wchar_t *buff,
}
autoload_t::autoload_t(const wcstring &env_var_name_var, const builtin_script_t * const scripts, size_t script_count) :
env_var_name(env_var_name_var),
builtin_scripts(scripts),
builtin_script_count(script_count)
{
}
void autoload_t::node_was_evicted(autoload_function_t *node) {
// Tell ourselves that the command was removed, unless it was a placeholder
if (! node->is_placeholder)
this->command_removed(node->key);
delete node;
}
void autoload_t::reset( )
{
this->evict_all_nodes();
}
int autoload_t::unload( const wcstring &cmd )
{
return this->evict_node(cmd);
}
int autoload_t::load( const wcstring &cmd, bool reload )
{
int res;
int c, c2;
CHECK_BLOCK( 0 );
const env_var_t path_var = env_get_string( env_var_name.c_str() );
/*
Do we know where to look?
*/
if( path_var.empty() )
{
return 0;
}
/*
Check if the lookup path has changed. If so, drop all loaded
files.
*/
if( path_var != this->path )
{
this->path = path_var;
this->reset();
}
/**
Warn and fail on infinite recursion
*/
if (this->is_loading(cmd))
{
debug( 0,
_( L"Could not autoload item '%ls', it is already being autoloaded. "
L"This is a circular dependency in the autoloading scripts, please remove it."),
cmd.c_str() );
return 1;
}
std::vector<wcstring> path_list;
tokenize_variable_array2( path_var, path_list );
c = path_list.size();
is_loading_set.insert(cmd);
/*
Do the actual work in the internal helper function
*/
res = this->load_internal( cmd, reload, path_list );
int erased = is_loading_set.erase(cmd);
assert(erased);
c2 = path_list.size();
/**
Make sure we didn't 'drop' something
*/
assert( c == c2 );
return res;
}
static bool script_name_precedes_script_name(const builtin_script_t &script1, const builtin_script_t &script2)
{
return wcscmp(script1.name, script2.name) < 0;
}
/**
This internal helper function does all the real work. By using two
functions, the internal function can return on various places in
the code, and the caller can take care of various cleanup work.
*/
int autoload_t::load_internal( const wcstring &cmd,
int reload,
const wcstring_list_t &path_list )
{
size_t i;
int reloaded = 0;
/* Get the function */
autoload_function_t * func = this->get_function_with_name(cmd);
/* Return if already loaded and we are skipping reloading */
if( !reload && func )
return 0;
/* Nothing to do if we just checked it */
if (func && time(NULL) - func->access.last_checked <= 1)
return 0;
/* The source of the script will end up here */
wcstring script_source;
bool has_script_source = false;
/*
Look for built-in scripts via a binary search
*/
const builtin_script_t *matching_builtin_script = NULL;
if (builtin_script_count > 0)
{
const builtin_script_t test_script = {cmd.c_str(), NULL};
const builtin_script_t *array_end = builtin_scripts + builtin_script_count;
const builtin_script_t *found = std::lower_bound(builtin_scripts, array_end, test_script, script_name_precedes_script_name);
if (found != array_end && ! wcscmp(found->name, test_script.name))
{
/* We found it */
matching_builtin_script = found;
}
}
if (matching_builtin_script) {
has_script_source = true;
script_source = str2wcstring(matching_builtin_script->def);
}
if (! has_script_source)
{
/*
Iterate over path searching for suitable completion files
*/
for( i=0; i<path_list.size(); i++ )
{
wcstring next = path_list.at(i);
wcstring path = next + L"/" + cmd + L".fish";
const file_access_attempt_t access = access_file(path, R_OK);
if (access.accessible) {
if (! func || access.mod_time != func->access.mod_time) {
wcstring esc = escape_string(path, 1);
script_source = L". " + esc;
has_script_source = true;
if( !func )
func = new autoload_function_t(cmd);
func->access = access;
// Remove this command because we are going to reload it
command_removed(cmd);
reloaded = 1;
}
else if( func )
{
/*
If we are rechecking an autoload file, and it hasn't
changed, update the 'last check' timestamp.
*/
func->access = access;
}
break;
}
}
/*
If no file was found we insert a placeholder function. Later we only
research if the current time is at least five seconds later.
This way, the files won't be searched over and over again.
*/
if( !func )
{
func = new autoload_function_t(cmd);
func->access.last_checked = time(NULL);
func->is_placeholder = true;
}
}
/* If we have a script, either built-in or a file source, then run it */
if (has_script_source)
{
if( exec_subshell( script_source.c_str(), 0 ) == -1 )
{
/*
Do nothing on failiure
*/
}
}
return reloaded;
}
void parse_util_set_argv( wchar_t **argv, const wcstring_list_t &named_arguments )
{
if( *argv )