/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* debugger.c: Vim script debugger functions
*/
#include "vim.h"
#if defined(FEAT_EVAL) || defined(PROTO)
static int debug_greedy = FALSE; /* batch mode debugging: don't save
and restore typeahead. */
static void do_setdebugtracelevel(char_u *arg);
static void do_checkbacktracelevel(void);
static void do_showbacktrace(char_u *cmd);
static char_u *debug_oldval = NULL; /* old and newval for debug expressions */
static char_u *debug_newval = NULL;
static int debug_expr = 0; /* use debug_expr */
int
has_watchexpr(void)
{
return debug_expr;
}
/*
* do_debug(): Debug mode.
* Repeatedly get Ex commands, until told to continue normal execution.
*/
void
do_debug(char_u *cmd)
{
int save_msg_scroll = msg_scroll;
int save_State = State;
int save_did_emsg = did_emsg;
int save_cmd_silent = cmd_silent;
int save_msg_silent = msg_silent;
int save_emsg_silent = emsg_silent;
int save_redir_off = redir_off;
tasave_T typeaheadbuf;
int typeahead_saved = FALSE;
int save_ignore_script = 0;
int save_ex_normal_busy;
int n;
char_u *cmdline = NULL;
char_u *p;
char *tail = NULL;
static int last_cmd = 0;
#define CMD_CONT 1
#define CMD_NEXT 2
#define CMD_STEP 3
#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. */
if (!gui.in_use)
{
/* Break as soon as possible. */
debug_break_level = 9999;
return;
}
#endif
/* Make sure we are in raw mode and start termcap mode. Might have side
* effects... */
settmode(TMODE_RAW);
starttermcap();
++RedrawingDisabled; /* don't redisplay the window */
++no_wait_return; /* don't wait for return */
did_emsg = FALSE; /* don't use error from debugged stuff */
cmd_silent = FALSE; /* display commands */
msg_silent = FALSE; /* display messages */
emsg_silent = FALSE; /* display error messages */
redir_off = TRUE; /* don't redirect debug commands */
State = NORMAL;
debug_mode = TRUE;
if (!debug_did_msg)
msg(_("Entering Debug mode. Type \"cont\" to continue."));
if (debug_oldval != NULL)
{
smsg(_("Oldval = \"%s\""), debug_oldval);
vim_free(debug_oldval);
debug_oldval = NULL;
}
if (debug_newval != NULL)
{
smsg(_("Newval = \"%s\""), debug_newval);
vim_free(debug_newval);
debug_newval = NULL;
}
if (sourcing_name != NULL)
msg((char *)sourcing_name);
if (sourcing_lnum != 0)
smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd);
else
smsg(_("cmd: %s"), cmd);
/*
* Repeat getting a command and executing it.
*/
for (;;)
{
msg_scroll = TRUE;
need_wait_return = FALSE;
/* Save the current typeahead buffer and replace it with an empty one.
* This makes sure we get input from the user here and don't interfere
* with the commands being executed. Reset "ex_normal_busy" to avoid
* the side effects of using ":normal". Save the stuff buffer and make
* it empty. Set ignore_script to avoid reading from script input. */
save_ex_normal_busy = ex_normal_busy;
ex_normal_busy = 0;
if (!debug_greedy)
{
save_typeahead(&typeaheadbuf);
typeahead_saved = TRUE;
save_ignore_script = ignore_script;
ignore_script = TRUE;
}
vim_free(cmdline);
cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
if (typeahead_saved)
{
restore_typeahead(&typeaheadbuf);
ignore_script = save_ignore_script;
}
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".
* For a blank line use previous command. */
p = skipwhite(cmdline);
if (*p != NUL)
{
switch (*p)
{
case 'c': last_cmd = CMD_CONT;
tail = "ont";
break;
case 'n': last_cmd = CMD_NEXT;
tail = "ext";
break;
case 's': last_cmd = CMD_STEP;
tail = "tep";
break;
case 'f':
last_cmd = 0;
if (p[