forked from aniani/vim
patch 8.2.3259: when 'indentexpr' causes an error did_throw may hang
Problem: When 'indentexpr' causes an error the did_throw flag may remain set. Solution: Reset did_throw and show the error. (closes #8677)
This commit is contained in:
129
src/ex_docmd.c
129
src/ex_docmd.c
@@ -1268,67 +1268,7 @@ do_cmdline(
|
|||||||
* commands are executed.
|
* commands are executed.
|
||||||
*/
|
*/
|
||||||
if (did_throw)
|
if (did_throw)
|
||||||
{
|
handle_did_throw();
|
||||||
char *p = NULL;
|
|
||||||
msglist_T *messages = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the uncaught exception is a user exception, report it as an
|
|
||||||
* error. If it is an error exception, display the saved error
|
|
||||||
* message now. For an interrupt exception, do nothing; the
|
|
||||||
* interrupt message is given elsewhere.
|
|
||||||
*/
|
|
||||||
switch (current_exception->type)
|
|
||||||
{
|
|
||||||
case ET_USER:
|
|
||||||
vim_snprintf((char *)IObuff, IOSIZE,
|
|
||||||
_("E605: Exception not caught: %s"),
|
|
||||||
current_exception->value);
|
|
||||||
p = (char *)vim_strsave(IObuff);
|
|
||||||
break;
|
|
||||||
case ET_ERROR:
|
|
||||||
messages = current_exception->messages;
|
|
||||||
current_exception->messages = NULL;
|
|
||||||
break;
|
|
||||||
case ET_INTERRUPT:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
|
|
||||||
current_exception->throw_lnum);
|
|
||||||
ESTACK_CHECK_SETUP
|
|
||||||
current_exception->throw_name = NULL;
|
|
||||||
|
|
||||||
discard_current_exception(); // uses IObuff if 'verbose'
|
|
||||||
suppress_errthrow = TRUE;
|
|
||||||
force_abort = TRUE;
|
|
||||||
|
|
||||||
if (messages != NULL)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
msglist_T *next = messages->next;
|
|
||||||
int save_compiling = estack_compiling;
|
|
||||||
|
|
||||||
estack_compiling = messages->msg_compiling;
|
|
||||||
emsg(messages->msg);
|
|
||||||
vim_free(messages->msg);
|
|
||||||
vim_free(messages->sfile);
|
|
||||||
vim_free(messages);
|
|
||||||
messages = next;
|
|
||||||
estack_compiling = save_compiling;
|
|
||||||
}
|
|
||||||
while (messages != NULL);
|
|
||||||
}
|
|
||||||
else if (p != NULL)
|
|
||||||
{
|
|
||||||
emsg(p);
|
|
||||||
vim_free(p);
|
|
||||||
}
|
|
||||||
vim_free(SOURCING_NAME);
|
|
||||||
ESTACK_CHECK_NOW
|
|
||||||
estack_pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On an interrupt or an aborting error not converted to an exception,
|
* On an interrupt or an aborting error not converted to an exception,
|
||||||
@@ -1448,6 +1388,73 @@ do_cmdline(
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle when "did_throw" is set after executing commands.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
handle_did_throw()
|
||||||
|
{
|
||||||
|
char *p = NULL;
|
||||||
|
msglist_T *messages = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the uncaught exception is a user exception, report it as an
|
||||||
|
* error. If it is an error exception, display the saved error
|
||||||
|
* message now. For an interrupt exception, do nothing; the
|
||||||
|
* interrupt message is given elsewhere.
|
||||||
|
*/
|
||||||
|
switch (current_exception->type)
|
||||||
|
{
|
||||||
|
case ET_USER:
|
||||||
|
vim_snprintf((char *)IObuff, IOSIZE,
|
||||||
|
_("E605: Exception not caught: %s"),
|
||||||
|
current_exception->value);
|
||||||
|
p = (char *)vim_strsave(IObuff);
|
||||||
|
break;
|
||||||
|
case ET_ERROR:
|
||||||
|
messages = current_exception->messages;
|
||||||
|
current_exception->messages = NULL;
|
||||||
|
break;
|
||||||
|
case ET_INTERRUPT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
|
||||||
|
current_exception->throw_lnum);
|
||||||
|
ESTACK_CHECK_SETUP
|
||||||
|
current_exception->throw_name = NULL;
|
||||||
|
|
||||||
|
discard_current_exception(); // uses IObuff if 'verbose'
|
||||||
|
suppress_errthrow = TRUE;
|
||||||
|
force_abort = TRUE;
|
||||||
|
|
||||||
|
if (messages != NULL)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
msglist_T *next = messages->next;
|
||||||
|
int save_compiling = estack_compiling;
|
||||||
|
|
||||||
|
estack_compiling = messages->msg_compiling;
|
||||||
|
emsg(messages->msg);
|
||||||
|
vim_free(messages->msg);
|
||||||
|
vim_free(messages->sfile);
|
||||||
|
vim_free(messages);
|
||||||
|
messages = next;
|
||||||
|
estack_compiling = save_compiling;
|
||||||
|
}
|
||||||
|
while (messages != NULL);
|
||||||
|
}
|
||||||
|
else if (p != NULL)
|
||||||
|
{
|
||||||
|
emsg(p);
|
||||||
|
vim_free(p);
|
||||||
|
}
|
||||||
|
vim_free(SOURCING_NAME);
|
||||||
|
ESTACK_CHECK_NOW
|
||||||
|
estack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
/*
|
/*
|
||||||
* Obtain a line when inside a ":while" or ":for" loop.
|
* Obtain a line when inside a ":while" or ":for" loop.
|
||||||
|
@@ -1822,6 +1822,13 @@ get_expr_indent(void)
|
|||||||
check_cursor();
|
check_cursor();
|
||||||
State = save_State;
|
State = save_State;
|
||||||
|
|
||||||
|
// Reset did_throw, unless 'debug' has "throw" and inside a try/catch.
|
||||||
|
if (did_throw && (vim_strchr(p_debug, 't') == NULL || trylevel == 0))
|
||||||
|
{
|
||||||
|
handle_did_throw();
|
||||||
|
did_throw = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// If there is an error, just keep the current indent.
|
// If there is an error, just keep the current indent.
|
||||||
if (indent < 0)
|
if (indent < 0)
|
||||||
indent = get_indent();
|
indent = get_indent();
|
||||||
|
@@ -3,6 +3,7 @@ void do_exmode(int improved);
|
|||||||
int do_cmdline_cmd(char_u *cmd);
|
int do_cmdline_cmd(char_u *cmd);
|
||||||
int do_cmd_argument(char_u *cmd);
|
int do_cmd_argument(char_u *cmd);
|
||||||
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, int flags);
|
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, int flags);
|
||||||
|
void handle_did_throw(void);
|
||||||
int getline_equal(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, char_u *(*func)(int, void *, int, getline_opt_T));
|
int getline_equal(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, char_u *(*func)(int, void *, int, getline_opt_T));
|
||||||
void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
||||||
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
|
||||||
|
@@ -755,6 +755,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
3259,
|
||||||
/**/
|
/**/
|
||||||
3258,
|
3258,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user