0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 7.4.1102

Problem:    Debugger has no stack backtrace support.
Solution:   Add "backtrace", "frame", "up" and "down" commands. (Alberto
            Fanjul, closes #433)
This commit is contained in:
Bram Moolenaar
2016-01-16 15:40:53 +01:00
parent e39b3d9fb4
commit f1f60f859c
8 changed files with 382 additions and 8 deletions

View File

@@ -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".
*/