2016-04-19 12:35:53 +08:00
|
|
|
// The classes responsible for autoloading functions and completions.
|
2012-01-26 03:47:45 +08:00
|
|
|
#ifndef FISH_AUTOLOAD_H
|
|
|
|
#define FISH_AUTOLOAD_H
|
2012-01-25 16:36:55 +08:00
|
|
|
|
2015-07-25 23:14:25 +08:00
|
|
|
#include <pthread.h>
|
2016-05-04 07:23:30 +08:00
|
|
|
#include <stdbool.h>
|
2015-07-25 23:14:25 +08:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <time.h>
|
2012-01-25 16:36:55 +08:00
|
|
|
#include <set>
|
2016-04-21 14:00:54 +08:00
|
|
|
|
2012-01-25 16:36:55 +08:00
|
|
|
#include "common.h"
|
2012-02-06 12:54:41 +08:00
|
|
|
#include "lru.h"
|
2012-01-25 16:36:55 +08:00
|
|
|
|
2016-06-06 10:24:23 +08:00
|
|
|
/// Recording an attempt to access a file.
|
2016-04-19 12:35:53 +08:00
|
|
|
struct file_access_attempt_t {
|
2016-06-06 10:24:23 +08:00
|
|
|
/// modification time of the file
|
|
|
|
time_t mod_time;
|
|
|
|
/// when we last checked the file
|
|
|
|
time_t last_checked;
|
|
|
|
/// whether we believe we could access this file
|
|
|
|
bool accessible;
|
|
|
|
/// whether the access attempt is stale
|
|
|
|
bool stale;
|
|
|
|
/// if we could not access the file, the error code
|
|
|
|
int error;
|
2012-01-25 16:36:55 +08:00
|
|
|
};
|
2012-01-26 03:47:45 +08:00
|
|
|
file_access_attempt_t access_file(const wcstring &path, int mode);
|
2012-01-25 16:36:55 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
struct autoload_function_t : public lru_node_t {
|
|
|
|
explicit autoload_function_t(const wcstring &key)
|
|
|
|
: lru_node_t(key),
|
|
|
|
access(),
|
|
|
|
is_loaded(false),
|
|
|
|
is_placeholder(false),
|
|
|
|
is_internalized(false) {}
|
2016-06-06 10:24:23 +08:00
|
|
|
/// the last access attempt
|
|
|
|
file_access_attempt_t access;
|
|
|
|
/// whether we have actually loaded this function
|
|
|
|
bool is_loaded;
|
|
|
|
/// Whether we are a placeholder that stands in for "no such function". If this is true, then
|
|
|
|
/// is_loaded must be false.
|
2016-04-19 12:35:53 +08:00
|
|
|
bool is_placeholder;
|
2016-06-06 10:24:23 +08:00
|
|
|
/// Whether this function came from a builtin "internalized" script.
|
2016-04-19 12:35:53 +08:00
|
|
|
bool is_internalized;
|
2012-01-26 10:59:35 +08:00
|
|
|
};
|
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
struct builtin_script_t {
|
2012-12-11 08:23:08 +08:00
|
|
|
const wchar_t *name;
|
|
|
|
const char *def;
|
2012-12-09 13:41:38 +08:00
|
|
|
};
|
2012-01-26 10:59:35 +08:00
|
|
|
|
2012-07-21 11:39:31 +08:00
|
|
|
class env_vars_snapshot_t;
|
2012-01-26 10:59:35 +08:00
|
|
|
|
2016-06-06 10:24:23 +08:00
|
|
|
/// A class that represents a path from which we can autoload, and the autoloaded contents.
|
2016-04-19 12:35:53 +08:00
|
|
|
class autoload_t : private lru_cache_t<autoload_function_t> {
|
|
|
|
private:
|
|
|
|
// Lock for thread safety.
|
2012-01-29 06:56:13 +08:00
|
|
|
pthread_mutex_t lock;
|
2016-04-19 12:35:53 +08:00
|
|
|
// The environment variable name.
|
2012-01-26 10:59:35 +08:00
|
|
|
const wcstring env_var_name;
|
2016-04-19 12:35:53 +08:00
|
|
|
// Builtin script array.
|
2012-01-26 10:59:35 +08:00
|
|
|
const struct builtin_script_t *const builtin_scripts;
|
2016-04-19 12:35:53 +08:00
|
|
|
// Builtin script count.
|
2012-01-26 10:59:35 +08:00
|
|
|
const size_t builtin_script_count;
|
2016-04-19 12:35:53 +08:00
|
|
|
// The path from which we most recently autoloaded.
|
2012-04-01 06:17:14 +08:00
|
|
|
wcstring last_path;
|
2016-04-19 12:35:53 +08:00
|
|
|
// That path, tokenized (split on separators).
|
2014-02-25 05:06:26 +08:00
|
|
|
wcstring_list_t last_path_tokenized;
|
2012-01-26 10:59:35 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
// A table containing all the files that are currently being loaded. This is here to help
|
|
|
|
// prevent recursion.
|
2012-01-26 10:59:35 +08:00
|
|
|
std::set<wcstring> is_loading_set;
|
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
void remove_all_functions(void) { this->evict_all_nodes(); }
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
bool locate_file_and_maybe_load_it(const wcstring &cmd, bool really_load, bool reload,
|
|
|
|
const wcstring_list_t &path_list);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2012-01-26 10:59:35 +08:00
|
|
|
virtual void node_was_evicted(autoload_function_t *node);
|
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
autoload_function_t *get_autoloaded_function_with_creation(const wcstring &cmd,
|
|
|
|
bool allow_eviction);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Overridable callback for when a command is removed.
|
|
|
|
virtual void command_removed(const wcstring &cmd) {}
|
|
|
|
|
|
|
|
public:
|
|
|
|
// Create an autoload_t for the given environment variable name.
|
|
|
|
autoload_t(const wcstring &env_var_name_var, const builtin_script_t *scripts,
|
|
|
|
size_t script_count);
|
|
|
|
|
|
|
|
virtual ~autoload_t(); // destructor
|
|
|
|
|
|
|
|
// Autoload the specified file, if it exists in the specified path. Do not load it multiple
|
|
|
|
// times unless its timestamp changes or parse_util_unload is called.
|
|
|
|
//
|
|
|
|
// Autoloading one file may unload another.
|
|
|
|
//
|
|
|
|
// \param cmd the filename to search for. The suffix '.fish' is always added to this name
|
|
|
|
// \param on_unload a callback function to run if a suitable file is found, which has not
|
|
|
|
// already been run. unload will also be called for old files which are unloaded.
|
|
|
|
// \param reload wheter to recheck file timestamps on already loaded files
|
2012-11-19 08:30:30 +08:00
|
|
|
int load(const wcstring &cmd, bool reload);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
// Check whether we have tried loading the given command. Does not do any I/O.
|
2012-11-19 08:30:30 +08:00
|
|
|
bool has_tried_loading(const wcstring &cmd);
|
2012-01-26 10:59:35 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
// Tell the autoloader that the specified file, in the specified path, is no longer loaded.
|
|
|
|
//
|
|
|
|
// \param cmd the filename to search for. The suffix '.fish' is always added to this name
|
|
|
|
// \param on_unload a callback function which will be called before (re)loading a file, may be
|
|
|
|
// used to unload the previous file.
|
|
|
|
// \return non-zero if the file was removed, zero if the file had not yet been loaded
|
2012-11-19 08:30:30 +08:00
|
|
|
int unload(const wcstring &cmd);
|
2012-11-18 18:23:22 +08:00
|
|
|
|
2016-04-19 12:35:53 +08:00
|
|
|
// Check whether the given command could be loaded, but do not load it.
|
2012-11-19 08:30:30 +08:00
|
|
|
bool can_load(const wcstring &cmd, const env_vars_snapshot_t &vars);
|
2012-01-26 10:59:35 +08:00
|
|
|
};
|
2012-01-25 16:36:55 +08:00
|
|
|
#endif
|