/// @file runtime.c /// /// Management of runtime files (including packages) #include #include #include #include #include #include #include #include #include #include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/autocmd_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/debugger.h" #include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_eval_defs.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/hashtab_defs.h" #include "nvim/lua/executor.h" #include "nvim/macros_defs.h" #include "nvim/map_defs.h" #include "nvim/mbyte.h" #include "nvim/mbyte_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/memory_defs.h" #include "nvim/message.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/option_vars.h" #include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/os_defs.h" #include "nvim/os/stdpaths_defs.h" #include "nvim/path.h" #include "nvim/pos_defs.h" #include "nvim/profile.h" #include "nvim/regexp.h" #include "nvim/regexp_defs.h" #include "nvim/runtime.h" #include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/usercmd.h" #include "nvim/vim_defs.h" #ifdef USE_CRNL # include "nvim/highlight.h" #endif /// Structure used to store info for each sourced file. /// It is shared between do_source() and getsourceline(). /// This is required, because it needs to be handed to do_cmdline() and /// sourcing can be done recursively. typedef struct { FILE *fp; ///< opened file for sourcing char *nextline; ///< if not NULL: line that was read ahead linenr_T sourcing_lnum; ///< line number of the source file int finished; ///< ":finish" used #ifdef USE_CRNL int fileformat; ///< EOL_UNKNOWN, EOL_UNIX or EOL_DOS bool error; ///< true if LF found after CR-LF #endif linenr_T breakpoint; ///< next line with breakpoint or zero char *fname; ///< name of sourced file int dbg_tick; ///< debug_tick when breakpoint was set int level; ///< top nesting level of sourced file vimconv_T conv; ///< type of conversion } source_cookie_T; typedef struct { char *path; bool after; TriState has_lua; } SearchPathItem; typedef kvec_t(SearchPathItem) RuntimeSearchPath; typedef kvec_t(char *) CharVec; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "runtime.c.generated.h" #endif garray_T exestack = { 0, 0, sizeof(estack_T), 50, NULL }; garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL }; /// The names of packages that once were loaded are remembered. static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL }; static int last_current_SID_seq = 0; /// Initialize the execution stack. void estack_init(void) { ga_grow(&exestack, 10); estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len; entry->es_type = ETYPE_TOP; entry->es_name = NULL; entry->es_lnum = 0; entry->es_info.ufunc = NULL; exestack.ga_len++; } /// Add an item to the execution stack. /// @return the new entry estack_T *estack_push(etype_T type, char *name, linenr_T lnum) { ga_grow(&exestack, 1); estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len; entry->es_type = type; entry->es_name = name; entry->es_lnum = lnum; entry->es_info.ufunc = NULL; exestack.ga_len++; return entry; } /// Add a user function to the execution stack. void estack_push_ufunc(ufunc_T *ufunc, linenr_T lnum) { estack_T *entry = estack_push(ETYPE_UFUNC, ufunc->uf_name_exp != NULL ? ufunc->uf_name_exp : ufunc->uf_name, lnum); if (entry != NULL) { entry->es_info.ufunc = ufunc; } } /// Take an item off of the execution stack. void estack_pop(void) { if (exestack.ga_len > 1) { exestack.ga_len--; } } /// Get the current value for in allocated memory. /// @param which ESTACK_SFILE for , ESTACK_STACK for or /// ESTACK_SCRIPT for