diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 29 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 135 | ||||
-rw-r--r-- | src/nvim/globals.h | 9 | ||||
-rw-r--r-- | src/nvim/version.c | 5 |
4 files changed, 164 insertions, 14 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 712ee06b85..201a71facb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -18123,6 +18123,25 @@ static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, in return HI2DI(hi); } +// Get function call environment based on backtrace debug level +static funccall_T *get_funccal(void) +{ + funccall_T *funccal = current_funccal; + if (debug_backtrace_level > 0) { + for (int i = 0; i < debug_backtrace_level; i++) { + funccall_T *temp_funccal = funccal->caller; + if (temp_funccal) { + funccal = temp_funccal; + } else { + // backtrace level overflow. reset to max + debug_backtrace_level = i; + } + } + } + + return funccal; +} + // Find the dict and hashtable used for a variable name. Set "varname" to the // start of name without ':'. static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) @@ -18147,7 +18166,11 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) return &compat_hashtab; } - *d = current_funccal ? ¤t_funccal->l_vars : &globvardict; + if (current_funccal == NULL) { + *d = &globvardict; + } else { + *d = &get_funccal()->l_vars; // l: variable + } goto end; } @@ -18169,9 +18192,9 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d) } else if (*name == 'v') { // v: variable *d = &vimvardict; } else if (*name == 'a' && current_funccal != NULL) { // function argument - *d = ¤t_funccal->l_avars; + *d = &get_funccal()->l_avars; } else if (*name == 'l' && current_funccal != NULL) { // local variable - *d = ¤t_funccal->l_vars; + *d = &get_funccal()->l_vars; } else if (*name == 's' // script variable && current_SID > 0 && current_SID <= ga_scripts.ga_len) { *d = &SCRIPT_SV(current_SID)->sv_dict; diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index df387f9a60..5fe6209a0a 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -144,6 +144,10 @@ void do_debug(char_u *cmd) #define CMD_FINISH 4 #define CMD_QUIT 5 #define CMD_INTERRUPT 6 +#define CMD_BACKTRACE 7 +#define CMD_FRAME 8 +#define CMD_UP 9 +#define CMD_DOWN 10 ++RedrawingDisabled; /* don't redisplay the window */ @@ -185,6 +189,7 @@ void do_debug(char_u *cmd) ignore_script = TRUE; } + xfree(cmdline); cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); if (typeahead_saved) { @@ -194,6 +199,7 @@ void do_debug(char_u *cmd) ex_normal_busy = save_ex_normal_busy; cmdline_row = msg_row; + msg_starthere(); if (cmdline != NULL) { /* If this is a debug command, set "last_cmd". * If not, reset "last_cmd". @@ -210,8 +216,15 @@ void do_debug(char_u *cmd) case 's': last_cmd = CMD_STEP; tail = "tep"; break; - case 'f': last_cmd = CMD_FINISH; - tail = "inish"; + case 'f': + last_cmd = 0; + if (p[1] == 'r') { + last_cmd = CMD_FRAME; + tail = "rame"; + } else { + last_cmd = CMD_FINISH; + tail = "inish"; + } break; case 'q': last_cmd = CMD_QUIT; tail = "uit"; @@ -219,6 +232,26 @@ void do_debug(char_u *cmd) case 'i': last_cmd = CMD_INTERRUPT; tail = "nterrupt"; break; + case 'b': + last_cmd = CMD_BACKTRACE; + if (p[1] == 't') { + tail = "t"; + } else { + tail = "acktrace"; + } + break; + case 'w': + last_cmd = CMD_BACKTRACE; + tail = "here"; + break; + case 'u': + last_cmd = CMD_UP; + tail = "p"; + break; + case 'd': + last_cmd = CMD_DOWN; + tail = "own"; + break; default: last_cmd = 0; } if (last_cmd != 0) { @@ -228,8 +261,9 @@ void do_debug(char_u *cmd) ++p; ++tail; } - if (ASCII_ISALPHA(*p)) + if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME) { last_cmd = 0; + } } } @@ -259,7 +293,28 @@ void do_debug(char_u *cmd) /* Do not repeat ">interrupt" cmd, continue stepping. */ last_cmd = CMD_STEP; break; + case CMD_BACKTRACE: + do_showbacktrace(cmd); + continue; + case CMD_FRAME: + if (*p == NUL) { + do_showbacktrace(cmd); + } else { + p = skipwhite(p); + do_setdebugtracelevel(p); + } + continue; + case CMD_UP: + debug_backtrace_level++; + do_checkbacktracelevel(); + continue; + case CMD_DOWN: + debug_backtrace_level--; + do_checkbacktracelevel(); + continue; } + // Going out reset backtrace_level + debug_backtrace_level = 0; break; } @@ -269,8 +324,6 @@ void do_debug(char_u *cmd) (void)do_cmdline(cmdline, getexline, NULL, DOCMD_VERBOSE|DOCMD_EXCRESET); debug_break_level = n; - - xfree(cmdline); } lines_left = (int)(Rows - 1); } @@ -294,6 +347,78 @@ void do_debug(char_u *cmd) debug_did_msg = TRUE; } +static int get_maxbacktrace_level(void) +{ + int maxbacktrace = 0; + + if (sourcing_name != NULL) { + char *p = (char *)sourcing_name; + char *q; + while ((q = strstr(p, "..")) != NULL) { + p = q + 2; + maxbacktrace++; + } + } + return maxbacktrace; +} + +static void do_setdebugtracelevel(char_u *arg) +{ + int level = atoi((char *)arg); + if (*arg == '+' || level < 0) { + debug_backtrace_level += level; + } else { + debug_backtrace_level = level; + } + + do_checkbacktracelevel(); +} + +static void do_checkbacktracelevel(void) +{ + if (debug_backtrace_level < 0) { + debug_backtrace_level = 0; + MSG(_("frame is zero")); + } else { + int max = get_maxbacktrace_level(); + if (debug_backtrace_level > max) { + debug_backtrace_level = max; + smsg(_("frame at highest level: %d"), max); + } + } +} + +static void do_showbacktrace(char_u *cmd) +{ + if (sourcing_name != NULL) { + int i = 0; + int max = get_maxbacktrace_level(); + char *cur = (char *)sourcing_name; + while (!got_int) { + char *next = strstr(cur, ".."); + if (next != NULL) { + *next = NUL; + } + if (i == max - debug_backtrace_level) { + smsg("->%d %s", max - i, cur); + } else { + smsg(" %d %s", max - i, cur); + } + i++; + if (next == NULL) { + break; + } + *next = '.'; + cur = next + 2; + } + } + if (sourcing_lnum != 0) { + smsg(_("line %" PRId64 ": %s"), (int64_t)sourcing_lnum, cmd); + } else { + smsg(_("cmd: %s"), cmd); + } +} + /* * ":debug". */ diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 49d1de21d9..30fe97c8db 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -293,10 +293,11 @@ EXTERN int msg_no_more INIT(= FALSE); /* don't use more prompt, truncate EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */ EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */ -EXTERN int ex_nesting_level INIT(= 0); /* nesting level */ -EXTERN int debug_break_level INIT(= -1); /* break below this level */ -EXTERN int debug_did_msg INIT(= FALSE); /* did "debug mode" message */ -EXTERN int debug_tick INIT(= 0); /* breakpoint change count */ +EXTERN int ex_nesting_level INIT(= 0); // nesting level +EXTERN int debug_break_level INIT(= -1); // break below this level +EXTERN int debug_did_msg INIT(= false); // did "debug mode" message +EXTERN int debug_tick INIT(= 0); // breakpoint change count +EXTERN int debug_backtrace_level INIT(= 0); // breakpoint backtrace level /* Values for "do_profiling". */ #define PROF_NONE 0 /* profiling not started */ diff --git a/src/nvim/version.c b/src/nvim/version.c index 3746f53e1f..48db7d86ee 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -69,6 +69,7 @@ static char *features[] = { // clang-format off static int included_patches[] = { + 1832, 1809, 1808, 1806, @@ -573,7 +574,7 @@ static int included_patches[] = { 1113, 1112, // 1111, - // 1110, + 1110, // 1109 NA // 1108, 1107, @@ -581,7 +582,7 @@ static int included_patches[] = { 1105, // 1104 NA // 1103 NA - // 1102, + 1102, 1101, // 1100 NA // 1099 NA |