aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/runtime.c')
-rw-r--r--src/nvim/runtime.c140
1 files changed, 109 insertions, 31 deletions
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 89848b43bd..8299f8ec45 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -50,8 +50,94 @@ struct source_cookie {
# 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), 4, NULL };
+/// 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,
+ (char *)(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 <sfile> in allocated memory.
+char *estack_sfile(void)
+{
+ estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
+ if (entry->es_name == NULL) {
+ return NULL;
+ }
+ if (entry->es_info.ufunc == NULL) {
+ return xstrdup(entry->es_name);
+ }
+
+ // For a function we compose the call stack, as it was done in the past:
+ // "function One[123]..Two[456]..Three"
+ size_t len = STRLEN(entry->es_name) + 10;
+ int idx;
+ for (idx = exestack.ga_len - 2; idx >= 0; idx--) {
+ entry = ((estack_T *)exestack.ga_data) + idx;
+ if (entry->es_name == NULL || entry->es_info.ufunc == NULL) {
+ idx++;
+ break;
+ }
+ len += STRLEN(entry->es_name) + 15;
+ }
+
+ char *res = (char *)xmalloc(len);
+ STRCPY(res, "function ");
+ size_t done;
+ while (idx < exestack.ga_len - 1) {
+ done = STRLEN(res);
+ entry = ((estack_T *)exestack.ga_data) + idx;
+ vim_snprintf(res + done, len - done, "%s[%" PRIdLINENR "]..", entry->es_name, entry->es_lnum);
+ idx++;
+ }
+ done = STRLEN(res);
+ entry = ((estack_T *)exestack.ga_data) + idx;
+ vim_snprintf(res + done, len - done, "%s", entry->es_name);
+ return res;
+}
+
static bool runtime_search_path_valid = false;
static int *runtime_search_path_ref = NULL;
static RuntimeSearchPath runtime_search_path;
@@ -1645,18 +1731,19 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out)
static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name)
{
- char *save_sourcing_name = sourcing_name;
- linenr_T save_sourcing_lnum = sourcing_lnum;
+ char *save_sourcing_name = SOURCING_NAME;
+ linenr_T save_sourcing_lnum = SOURCING_LNUM;
char sourcing_name_buf[256];
+ char *sname;
if (save_sourcing_name == NULL) {
- sourcing_name = (char *)traceback_name;
+ sname = (char *)traceback_name;
} else {
snprintf((char *)sourcing_name_buf, sizeof(sourcing_name_buf),
"%s called at %s:%" PRIdLINENR, traceback_name, save_sourcing_name,
save_sourcing_lnum);
- sourcing_name = sourcing_name_buf; // -V507 reassigned below, before return.
+ sname = sourcing_name_buf;
}
- sourcing_lnum = 0;
+ estack_push(ETYPE_SCRIPT, sname, 0);
const sctx_T save_current_sctx = current_sctx;
if (current_sctx.sc_sid != SID_LUA) {
@@ -1668,8 +1755,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
save_funccal(&entry);
int retval = do_cmdline(NULL, fgetline, cookie,
DOCMD_VERBOSE | DOCMD_NOWAIT | DOCMD_REPEAT);
- sourcing_lnum = save_sourcing_lnum;
- sourcing_name = save_sourcing_name;
+ estack_pop();
current_sctx = save_current_sctx;
restore_funccal();
return retval;
@@ -1736,8 +1822,6 @@ int do_source_str(const char *cmd, const char *traceback_name)
int do_source(char *fname, int check_other, int is_vimrc)
{
struct source_cookie cookie;
- char *save_sourcing_name;
- linenr_T save_sourcing_lnum;
char *p;
char *fname_exp;
uint8_t *firstline = NULL;
@@ -1791,11 +1875,11 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (cookie.fp == NULL) {
if (p_verbose > 1) {
verbose_enter();
- if (sourcing_name == NULL) {
+ if (SOURCING_NAME == NULL) {
smsg(_("could not source \"%s\""), fname);
} else {
smsg(_("line %" PRId64 ": could not source \"%s\""),
- (int64_t)sourcing_lnum, fname);
+ (int64_t)SOURCING_LNUM, fname);
}
verbose_leave();
}
@@ -1807,11 +1891,10 @@ int do_source(char *fname, int check_other, int is_vimrc)
// - For a vimrc file, may want to call vimrc_found().
if (p_verbose > 1) {
verbose_enter();
- if (sourcing_name == NULL) {
+ if (SOURCING_NAME == NULL) {
smsg(_("sourcing \"%s\""), fname);
} else {
- smsg(_("line %" PRId64 ": sourcing \"%s\""),
- (int64_t)sourcing_lnum, fname);
+ smsg(_("line %" PRId64 ": sourcing \"%s\""), (int64_t)SOURCING_LNUM, fname);
}
verbose_leave();
}
@@ -1841,10 +1924,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
cookie.level = ex_nesting_level;
// Keep the sourcing name/lnum, for recursive calls.
- save_sourcing_name = sourcing_name;
- sourcing_name = fname_exp;
- save_sourcing_lnum = sourcing_lnum;
- sourcing_lnum = 0;
+ estack_push(ETYPE_SCRIPT, fname_exp, 0);
// start measuring script load time if --startuptime was passed and
// time_fd was successfully opened afterwards.
@@ -1901,14 +1981,13 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (path_with_extension((const char *)fname_exp, "lua")) {
const sctx_T current_sctx_backup = current_sctx;
- const linenr_T sourcing_lnum_backup = sourcing_lnum;
current_sctx.sc_sid = SID_LUA;
current_sctx.sc_lnum = 0;
- sourcing_lnum = 0;
+ estack_push(ETYPE_SCRIPT, NULL, 0);
// Source the file as lua
nlua_exec_file((const char *)fname_exp);
current_sctx = current_sctx_backup;
- sourcing_lnum = sourcing_lnum_backup;
+ estack_pop();
} else {
// Call do_cmdline, which will call getsourceline() to get the lines.
do_cmdline((char *)firstline, getsourceline, (void *)&cookie,
@@ -1931,13 +2010,12 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (got_int) {
emsg(_(e_interr));
}
- sourcing_name = save_sourcing_name;
- sourcing_lnum = save_sourcing_lnum;
+ estack_pop();
if (p_verbose > 1) {
verbose_enter();
smsg(_("finished sourcing %s"), fname);
- if (sourcing_name != NULL) {
- smsg(_("continuing in %s"), sourcing_name);
+ if (SOURCING_NAME != NULL) {
+ smsg(_("continuing in %s"), SOURCING_NAME);
}
verbose_leave();
}
@@ -2110,7 +2188,7 @@ linenr_T get_sourced_lnum(LineGetter fgetline, void *cookie)
{
return fgetline == getsourceline
? ((struct source_cookie *)cookie)->sourcing_lnum
- : sourcing_lnum;
+ : SOURCING_LNUM;
}
/// Get one full line from a sourced file.
@@ -2126,14 +2204,14 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
// If breakpoints have been added/deleted need to check for it.
if (sp->dbg_tick < debug_tick) {
- sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, sourcing_lnum);
+ sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
}
if (do_profiling == PROF_YES) {
script_line_end();
}
// Set the current sourcing line number.
- sourcing_lnum = sp->sourcing_lnum + 1;
+ SOURCING_LNUM = sp->sourcing_lnum + 1;
// Get current line. If there is a read-ahead line, use it, otherwise get
// one now.
if (sp->finished) {
@@ -2191,10 +2269,10 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat)
}
// Did we encounter a breakpoint?
- if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) {
- dbg_breakpoint((char_u *)sp->fname, sourcing_lnum);
+ if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) {
+ dbg_breakpoint((char_u *)sp->fname, SOURCING_LNUM);
// Find next breakpoint.
- sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, sourcing_lnum);
+ sp->breakpoint = dbg_find_breakpoint(true, (char_u *)sp->fname, SOURCING_LNUM);
sp->dbg_tick = debug_tick;
}