mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-07 01:51:14 -03:00
Overhaul of the script autoloader. This should make sure that old scripts are unloaded and new scripts are loaded when the fish_function_path and fish_complete_path variables change
darcs-hash:20060712142242-ac50b-3966a0e96a32facc8bc1164d6d0837fc551e4733.gz
This commit is contained in:
175
parse_util.c
175
parse_util.c
@@ -29,9 +29,36 @@
|
||||
#include "intern.h"
|
||||
#include "exec.h"
|
||||
#include "env.h"
|
||||
#include "translate.h"
|
||||
#include "wildcard.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
A structure representing the autoload state for a specific variable, e.g. fish_complete_path
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
A table containing the modification times of all loaded
|
||||
files. Failed loads (non-existing files) have modification time
|
||||
0.
|
||||
*/
|
||||
hash_table_t load_time;
|
||||
/**
|
||||
A string containg the path used to find any files to load. If
|
||||
this differs from the current environment variable, the
|
||||
autoloader needs to drop all loaded files and reload them.
|
||||
*/
|
||||
wchar_t *old_path;
|
||||
/**
|
||||
A table containing all the files that are currently being
|
||||
loaded. This is here to help prevent recursion.
|
||||
*/
|
||||
hash_table_t is_loading;
|
||||
}
|
||||
autoload_t;
|
||||
|
||||
|
||||
/**
|
||||
Set of files which have been autoloaded
|
||||
*/
|
||||
@@ -448,20 +475,32 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
/**
|
||||
Free hash value, but not hash key
|
||||
*/
|
||||
static void clear_hash_value( void *key, void *data )
|
||||
static void clear_hash_value( void *key, void *data, void *aux )
|
||||
{
|
||||
if( aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
void (*handler)(const wchar_t *)= (void (*)(const wchar_t *))aux;
|
||||
handler( name );
|
||||
}
|
||||
|
||||
free( (void *)data );
|
||||
}
|
||||
|
||||
/**
|
||||
Part of the autoloader cleanup
|
||||
*/
|
||||
static void clear_loaded_entry( void *key, void *data )
|
||||
static void clear_loaded_entry( void *key,
|
||||
void *data,
|
||||
void *handler )
|
||||
{
|
||||
hash_table_t *loaded = (hash_table_t *)data;
|
||||
hash_foreach( loaded,
|
||||
&clear_hash_value );
|
||||
hash_destroy( loaded );
|
||||
autoload_t *loaded = (autoload_t *)data;
|
||||
hash_foreach2( &loaded->load_time,
|
||||
&clear_hash_value,
|
||||
handler );
|
||||
hash_destroy( &loaded->load_time );
|
||||
|
||||
free( loaded->old_path );
|
||||
free( loaded );
|
||||
free( (void *)key );
|
||||
}
|
||||
@@ -475,8 +514,9 @@ static void parse_util_destroy()
|
||||
{
|
||||
if( all_loaded )
|
||||
{
|
||||
hash_foreach( all_loaded,
|
||||
&clear_loaded_entry );
|
||||
hash_foreach2( all_loaded,
|
||||
&clear_loaded_entry,
|
||||
0 );
|
||||
|
||||
hash_destroy( all_loaded );
|
||||
free( all_loaded );
|
||||
@@ -484,18 +524,61 @@ static void parse_util_destroy()
|
||||
}
|
||||
}
|
||||
|
||||
void parse_util_load_reset( const wchar_t *path_var )
|
||||
void parse_util_load_reset( const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, );
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
if( !path_var )
|
||||
return;
|
||||
|
||||
if( all_loaded )
|
||||
{
|
||||
void *key, *data;
|
||||
hash_remove( all_loaded, path_var, &key, &data );
|
||||
hash_remove( all_loaded, path_var_name, &key, &data );
|
||||
if( key )
|
||||
clear_loaded_entry( key, data );
|
||||
clear_loaded_entry( key, data, (void *)on_load );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int parse_util_unload( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
autoload_t *loaded;
|
||||
void *val;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hash_remove( &loaded->load_time, cmd, 0, &val );
|
||||
if( val )
|
||||
{
|
||||
if( on_load )
|
||||
{
|
||||
on_load( (wchar_t *)val );
|
||||
}
|
||||
free( val );
|
||||
}
|
||||
|
||||
return !!val;
|
||||
}
|
||||
|
||||
int parse_util_load( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
@@ -508,16 +591,22 @@ int parse_util_load( const wchar_t *cmd,
|
||||
int i;
|
||||
time_t *tm;
|
||||
int reloaded = 0;
|
||||
hash_table_t *loaded;
|
||||
autoload_t *loaded;
|
||||
|
||||
wchar_t *path_var = env_get( path_var_name );
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
/*
|
||||
Do we know where to look
|
||||
*/
|
||||
|
||||
if( !path_var )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
@@ -530,23 +619,52 @@ int parse_util_load( const wchar_t *cmd,
|
||||
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( loaded )
|
||||
{
|
||||
loaded = malloc( sizeof( hash_table_t ) );
|
||||
if( hash_get( &loaded->is_loading, cmd ) )
|
||||
{
|
||||
debug( 0, _(L"Could not autoload item %ls, it is already being autoloaded. This is a circular dependency in the autoloading scripts, please remove it."), cmd );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if the lookup path has changed. If so, drop all loaded
|
||||
files and start from scratch.
|
||||
*/
|
||||
if( wcscmp( path_var, loaded->old_path ) != 0 )
|
||||
{
|
||||
parse_util_load_reset( path_var_name, on_load);
|
||||
reload = parse_util_load( cmd, path_var_name, on_load, reload );
|
||||
return reload;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
We have never tried to autoload using this name before, set up initial data
|
||||
*/
|
||||
loaded = malloc( sizeof( autoload_t ) );
|
||||
if( !loaded )
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_init( &loaded->load_time, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_put( all_loaded, wcsdup(path_var_name), loaded );
|
||||
|
||||
hash_init( &loaded->is_loading, &hash_wcs_func, &hash_wcs_cmp );
|
||||
|
||||
loaded->old_path = wcsdup( path_var );
|
||||
}
|
||||
|
||||
hash_put( &loaded->is_loading, cmd, cmd );
|
||||
|
||||
|
||||
/*
|
||||
Get modification time of file
|
||||
*/
|
||||
tm = (time_t *)hash_get( loaded, cmd );
|
||||
tm = (time_t *)hash_get( &loaded->load_time, cmd );
|
||||
|
||||
/*
|
||||
Did we just check this?
|
||||
@@ -555,6 +673,7 @@ int parse_util_load( const wchar_t *cmd,
|
||||
{
|
||||
if(time(0)-tm[1]<=1)
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -563,7 +682,10 @@ int parse_util_load( const wchar_t *cmd,
|
||||
Return if already loaded and we are skipping reloading
|
||||
*/
|
||||
if( !reload && tm )
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !path_list )
|
||||
path_list = al_halloc( global_context);
|
||||
@@ -601,7 +723,7 @@ int parse_util_load( const wchar_t *cmd,
|
||||
|
||||
tm[0] = buf.st_mtime;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded,
|
||||
hash_put( &loaded->load_time,
|
||||
intern( cmd ),
|
||||
tm );
|
||||
|
||||
@@ -634,12 +756,13 @@ int parse_util_load( const wchar_t *cmd,
|
||||
|
||||
tm[0] = 0;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded, intern( cmd ), tm );
|
||||
hash_put( &loaded->load_time, intern( cmd ), tm );
|
||||
}
|
||||
|
||||
al_foreach( path_list, &free );
|
||||
al_truncate( path_list, 0 );
|
||||
|
||||
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return reloaded;
|
||||
}
|
||||
|
||||
@@ -670,7 +793,11 @@ void parse_util_set_argv( wchar_t **argv )
|
||||
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
|
||||
{
|
||||
wchar_t *in, *out;
|
||||
wchar_t *unescaped = wcsdup(str);
|
||||
wchar_t *unescaped;
|
||||
|
||||
CHECK( str, 0 );
|
||||
|
||||
unescaped = wcsdup(str);
|
||||
|
||||
if( !unescaped )
|
||||
DIE_MEM();
|
||||
|
||||
Reference in New Issue
Block a user