summaryrefslogtreecommitdiffstats
path: root/src/ex_cmds2.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-01-16 15:40:53 +0100
committerBram Moolenaar <Bram@vim.org>2016-01-16 15:40:53 +0100
commitf1f60f859cdbb2638b3662ccf7b1d179865fe7dc (patch)
tree739551087fb1b9948568366dc5d6187861dbcaf5 /src/ex_cmds2.c
parente39b3d9fb4e4006684c33847d1ef6a0d742699dd (diff)
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.c150
1 files changed, 147 insertions, 3 deletions
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 05baa7e99e..676cf117b4 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".
*/