diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-01-16 15:40:53 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-01-16 15:40:53 +0100 |
commit | f1f60f859cdbb2638b3662ccf7b1d179865fe7dc (patch) | |
tree | 739551087fb1b9948568366dc5d6187861dbcaf5 /src/ex_cmds2.c | |
parent | e39b3d9fb4e4006684c33847d1ef6a0d742699dd (diff) | |
download | vim-git-f1f60f859cdbb2638b3662ccf7b1d179865fe7dc.tar.gz |
patch 7.4.1102v7.4.1102
Problem: Debugger has no stack backtrace support.
Solution: Add "backtrace", "frame", "up" and "down" commands. (Alberto
Fanjul, closes #433)
Diffstat (limited to 'src/ex_cmds2.c')
-rw-r--r-- | src/ex_cmds2.c | 150 |
1 files changed, 147 insertions, 3 deletions
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 05baa7e99..676cf117b 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -68,6 +68,10 @@ typedef struct sn_prl_S #if defined(FEAT_EVAL) || defined(PROTO) static int debug_greedy = FALSE; /* batch mode debugging: don't save and restore typeahead. */ +static int get_maxbacktrace_level(void); +static void do_setdebugtracelevel(char_u *arg); +static void do_checkbacktracelevel(void); +static void do_showbacktrace(char_u *cmd); /* * do_debug(): Debug mode. @@ -101,6 +105,10 @@ do_debug(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 #ifdef ALWAYS_USE_GUI /* Can't do this when there is no terminal for input/output. */ @@ -178,6 +186,7 @@ do_debug(cmd) # endif cmdline_row = msg_row; + msg_starthere(); if (cmdline != NULL) { /* If this is a debug command, set "last_cmd". @@ -197,8 +206,18 @@ do_debug(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"; @@ -206,6 +225,21 @@ do_debug(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) @@ -217,7 +251,7 @@ do_debug(cmd) ++p; ++tail; } - if (ASCII_ISALPHA(*p)) + if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME) last_cmd = 0; } } @@ -250,7 +284,31 @@ do_debug(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; } @@ -285,6 +343,92 @@ do_debug(cmd) debug_did_msg = TRUE; } + static int +get_maxbacktrace_level(void) +{ + char *p, *q; + int maxbacktrace = 1; + + maxbacktrace = 0; + if (sourcing_name != NULL) + { + p = (char *)sourcing_name; + while ((q = strstr(p, "..")) != NULL) + { + p = q + 2; + maxbacktrace++; + } + } + return maxbacktrace; +} + + static void +do_setdebugtracelevel(char_u *arg) +{ + int level; + + 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((char_u *)_("frame at highest level: %d"), max); + } + } +} + + static void +do_showbacktrace(char_u *cmd) +{ + char *cur; + char *next; + int i = 0; + int max = get_maxbacktrace_level(); + + if (sourcing_name != NULL) + { + cur = (char *)sourcing_name; + while (!got_int) + { + next = strstr(cur, ".."); + if (next != NULL) + *next = NUL; + if (i == max - debug_backtrace_level) + smsg((char_u *)"->%d %s", max - i, cur); + else + smsg((char_u *)" %d %s", max - i, cur); + ++i; + if (next == NULL) + break; + *next = '.'; + cur = next + 2; + } + } + if (sourcing_lnum != 0) + smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); + else + smsg((char_u *)_("cmd: %s"), cmd); +} + /* * ":debug". */ |