summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-07-31 21:32:31 +0200
committerBram Moolenaar <Bram@vim.org>2021-07-31 21:32:31 +0200
commit620c959c6c00e469c4d3b1ab2e08e4767ee142a4 (patch)
tree9e366b7306b60f49c4fc2f37cb2236f915ff1df9
parent78db17c6f335f518752ca221ec6bde79db584e15 (diff)
patch 8.2.3259: when 'indentexpr' causes an error did_throw may hangv8.2.3259
Problem: When 'indentexpr' causes an error the did_throw flag may remain set. Solution: Reset did_throw and show the error. (closes #8677)
-rw-r--r--src/ex_docmd.c129
-rw-r--r--src/indent.c7
-rw-r--r--src/proto/ex_docmd.pro1
-rw-r--r--src/version.c2
4 files changed, 78 insertions, 61 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index fbfba52dd4..61feda257d 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1268,67 +1268,7 @@ do_cmdline(
* commands are executed.
*/
if (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();
- }
+ handle_did_throw();
/*
* On an interrupt or an aborting error not converted to an exception,
@@ -1448,6 +1388,73 @@ do_cmdline(
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
/*
* Obtain a line when inside a ":while" or ":for" loop.
diff --git a/src/indent.c b/src/indent.c
index 89653c7771..99951c81bf 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1822,6 +1822,13 @@ get_expr_indent(void)
check_cursor();
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 (indent < 0)
indent = get_indent();
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index 959f209ac1..d22d40689c 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -3,6 +3,7 @@ void do_exmode(int improved);
int do_cmdline_cmd(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);
+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));
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);
diff --git a/src/version.c b/src/version.c
index a2247dccab..a3f1d12505 100644
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3259,
+/**/
3258,
/**/
3257,