/* 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_u *sname;
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
save_timeout_for_debugging(); // disable regexp timeout flag
State = MODE_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_CLEAR(debug_oldval);
}
if (debug_newval != NULL)
{
smsg(_("Newval = \"%s\""), debug_newval);
VIM_CLEAR(debug_newval);
}
sname = estack_sfile(ESTACK_NONE);
if (sname != NULL)
msg((char *)sname);
vim_free(sname);
if (SOURCING_LNUM != 0)
smsg(_("line %ld: %s"), 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;
}
// don't debug any function call, e.g. from an expression mapping
n = debug_break_level;
debug_break_level = -1;
vim_free(cmdline);
cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
debug_break_level = n;
if (typeahead_saved)
{
restore_typeahead(&typeaheadbuf, TRUE);
ignore_script = save_ignore_script;
}
ex_normal_busy = save_ex_normal_busy;
cmdline_row = msg_row;
msg_starthere();
if (cmdline