int function_exists_no_autoload( const wcstring &cmd, const env_vars_snapshot_t &vars ) { if( parser_keywords_is_reserved(cmd) ) return 0; scoped_lock lock(functions_lock); return loaded_functions.find(cmd) != loaded_functions.end() || function_autoloader.can_load(cmd, vars); }
int function_exists( const wcstring &cmd ) { if( parser_keywords_is_reserved(cmd) ) return 0; scoped_lock lock(functions_lock); load(cmd); return loaded_functions.find(cmd) != loaded_functions.end(); }
void function_set_desc(const wcstring &name, const wcstring &desc) { load(name); scoped_lock locker(functions_lock); function_map_t::iterator iter = loaded_functions.find(name); if (iter != loaded_functions.end()) { iter->second.description = desc; } }
static const function_info_t *function_get(const wcstring &name) { // The caller must lock the functions_lock before calling this; however our mutex is currently // recursive, so trylock will never fail. We need a way to correctly check if a lock is locked // (or better yet, make our lock non-recursive). // ASSERT_IS_LOCKED(functions_lock); function_map_t::iterator iter = loaded_functions.find(name); if (iter == loaded_functions.end()) { return NULL; } return &iter->second; }
bool function_copy(const wcstring &name, const wcstring &new_name) { bool result = false; scoped_lock lock(functions_lock); function_map_t::const_iterator iter = loaded_functions.find(name); if (iter != loaded_functions.end()) { // This new instance of the function shouldn't be tied to the definition file of the original, so pass NULL filename, etc. const function_map_t::value_type new_pair(new_name, function_info_t(iter->second, NULL, 0, false)); loaded_functions.insert(new_pair); result = true; } return result; }
void function_add(const function_data_t &data, const parser_t &parser) { ASSERT_IS_MAIN_THREAD(); CHECK(! data.name.empty(),); CHECK(data.definition,); scoped_lock lock(functions_lock); /* Remove the old function */ function_remove(data.name); /* Create and store a new function */ const wchar_t *filename = reader_current_filename(); int def_offset = -1; if (parser.current_block() != NULL) { def_offset = parser.line_number_of_character_at_offset(parser.current_block()->tok_pos); } const function_map_t::value_type new_pair(data.name, function_info_t(data, filename, def_offset, is_autoload)); loaded_functions.insert(new_pair); /* Add event handlers */ for (std::vector<event_t>::const_iterator iter = data.events.begin(); iter != data.events.end(); ++iter) { event_add_handler(*iter); } }
/** Make sure that if the specified function is a dynamically loaded function, it has been fully loaded. */ static int load( const wcstring &name ) { ASSERT_IS_MAIN_THREAD(); scoped_lock lock(functions_lock); bool was_autoload = is_autoload; int res; function_map_t::iterator iter = loaded_functions.find(name); if( iter != loaded_functions.end() && !iter->second.is_autoload ) { /* We have a non-autoload version already */ return 0; } is_autoload = true; res = function_autoloader.load( name, true ); is_autoload = was_autoload; return res; }
wcstring_list_t function_get_names(int get_hidden) { std::set<wcstring> names; scoped_lock locker(functions_lock); autoload_names(names, get_hidden); function_map_t::const_iterator iter; for (iter = loaded_functions.begin(); iter != loaded_functions.end(); ++iter) { const wcstring &name = iter->first; // Maybe skip hidden. if (!get_hidden) { if (name.empty() || name.at(0) == L'_') continue; } names.insert(name); } return wcstring_list_t(names.begin(), names.end()); }
static bool function_remove_ignore_autoload(const wcstring &name, bool tombstone) { // Note: the lock may be held at this point, but is recursive. scoped_lock locker(functions_lock); function_map_t::iterator iter = loaded_functions.find(name); // Not found. Not erasing. if (iter == loaded_functions.end()) return false; // Removing an auto-loaded function. Prevent it from being auto-reloaded. if (iter->second.is_autoload && tombstone) function_tombstones.insert(name); loaded_functions.erase(iter); event_t ev(EVENT_ANY); ev.function_name = name; event_remove(ev); return true; }
/// Make sure that if the specified function is a dynamically loaded function, it has been fully /// loaded. static int load(const wcstring &name) { ASSERT_IS_MAIN_THREAD(); scoped_lock locker(functions_lock); bool was_autoload = is_autoload; int res; bool no_more_autoload = function_tombstones.count(name) > 0; if (no_more_autoload) return 0; function_map_t::iterator iter = loaded_functions.find(name); if (iter != loaded_functions.end() && !iter->second.is_autoload) { // We have a non-autoload version already. return 0; } is_autoload = true; res = function_autoloader.load(name, true); is_autoload = was_autoload; return res; }
static bool function_remove_ignore_autoload(const wcstring &name) { scoped_lock lock(functions_lock); bool erased = (loaded_functions.erase(name) > 0); if (erased) { event_t ev(EVENT_ANY); ev.function_name=name; event_remove( &ev ); } return erased; }
void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset) { ASSERT_IS_MAIN_THREAD(); CHECK(!data.name.empty(), ); CHECK(data.definition, ); scoped_lock locker(functions_lock); // Remove the old function. function_remove(data.name); // Create and store a new function. const wchar_t *filename = reader_current_filename(); const function_map_t::value_type new_pair( data.name, function_info_t(data, filename, definition_line_offset, is_autoload)); loaded_functions.insert(new_pair); // Add event handlers. for (std::vector<event_t>::const_iterator iter = data.events.begin(); iter != data.events.end(); ++iter) { event_add_handler(*iter); } }