diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-07-31 21:32:31 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-07-31 21:32:31 +0200 |
commit | 620c959c6c00e469c4d3b1ab2e08e4767ee142a4 (patch) | |
tree | 9e366b7306b60f49c4fc2f37cb2236f915ff1df9 /src | |
parent | 78db17c6f335f518752ca221ec6bde79db584e15 (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)
Diffstat (limited to 'src')
-rw-r--r-- | src/ex_docmd.c | 129 | ||||
-rw-r--r-- | src/indent.c | 7 | ||||
-rw-r--r-- | src/proto/ex_docmd.pro | 1 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |