home *** CD-ROM | disk | FTP | other *** search
- To: vim-dev@vim.org
- Subject: Patch 6.3.040
- Fcc: outbox
- From: Bram Moolenaar <Bram@moolenaar.net>
- Mime-Version: 1.0
- Content-Type: text/plain; charset=ISO-8859-1
- Content-Transfer-Encoding: 8bit
- ------------
-
- Patch 6.3.040
- Problem: Error handling does not always work properly and may cause a
- buffer to be marked as if it's viewed in a window while it isn't.
- Also when selecting "Abort" at the attention prompt.
- Solution: Add enter_cleanup() and leave_cleanup() functions to move
- saving/restoring things for error handling to one place.
- Clear a buffer read error when it's unloaded.
- Files: src/buffer.c, src/ex_docmd.c, src/ex_eval.c,
- src/proto/ex_eval.pro, src/structs.h, src/vim.h
-
-
- *** ../vim-6.3.039/src/buffer.c Wed Jun 9 14:56:27 2004
- --- src/buffer.c Sun Dec 5 16:15:05 2004
- ***************
- *** 408,415 ****
- if (!buf_valid(buf))
- return;
- # ifdef FEAT_EVAL
- ! /* Autocommands may abort script processing. */
- ! if (aborting())
- return;
- # endif
-
- --- 408,414 ----
- if (!buf_valid(buf))
- return;
- # ifdef FEAT_EVAL
- ! if (aborting()) /* autocmds may abort script processing */
- return;
- # endif
-
- ***************
- *** 564,569 ****
- --- 563,569 ----
- #ifdef FEAT_SYN_HL
- syntax_clear(buf); /* reset syntax info */
- #endif
- + buf->b_flags &= ~BF_READERR; /* a read error is no longer relevant */
- }
-
- /*
- ***************
- *** 666,674 ****
- --- 666,688 ----
- && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
- if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + cleanup_T cs;
- +
- + /* Reset the error/interrupt/exception state here so that
- + * aborting() returns FALSE when closing a window. */
- + enter_cleanup(&cs);
- + # endif
- +
- /* Quitting means closing the split window, nothing else. */
- win_close(curwin, TRUE);
- swap_exists_action = SEA_NONE;
- +
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Restore the error/interrupt/exception state if not discarded by a
- + * new aborting error, interrupt, or uncaught exception. */
- + leave_cleanup(&cs);
- + # endif
- }
- else
- handle_swap_exists(old_curbuf);
- ***************
- *** 685,712 ****
- handle_swap_exists(old_curbuf)
- buf_T *old_curbuf;
- {
- if (swap_exists_action == SEA_QUIT)
- {
- /* User selected Quit at ATTENTION prompt. Go back to previous
- * buffer. If that buffer is gone or the same as the current one,
- * open a new, empty buffer. */
- swap_exists_action = SEA_NONE; /* don't want it again */
- close_buffer(curwin, curbuf, DOBUF_UNLOAD);
- if (!buf_valid(old_curbuf) || old_curbuf == curbuf)
- ! old_curbuf = buflist_new(NULL, NULL, 1L,
- ! BLN_CURBUF | BLN_LISTED | BLN_FORCE);
- if (old_curbuf != NULL)
- enter_buffer(old_curbuf);
- /* If "old_curbuf" is NULL we are in big trouble here... */
- }
- else if (swap_exists_action == SEA_RECOVER)
- {
- /* User selected Recover at ATTENTION prompt. */
- msg_scroll = TRUE;
- ml_recover();
- MSG_PUTS("\n"); /* don't overwrite the last message */
- cmdline_row = msg_row;
- do_modelines();
- }
- swap_exists_action = SEA_NONE;
- }
- --- 699,753 ----
- handle_swap_exists(old_curbuf)
- buf_T *old_curbuf;
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + cleanup_T cs;
- + # endif
- +
- if (swap_exists_action == SEA_QUIT)
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Reset the error/interrupt/exception state here so that
- + * aborting() returns FALSE when closing a buffer. */
- + enter_cleanup(&cs);
- + # endif
- +
- /* User selected Quit at ATTENTION prompt. Go back to previous
- * buffer. If that buffer is gone or the same as the current one,
- * open a new, empty buffer. */
- swap_exists_action = SEA_NONE; /* don't want it again */
- close_buffer(curwin, curbuf, DOBUF_UNLOAD);
- if (!buf_valid(old_curbuf) || old_curbuf == curbuf)
- ! old_curbuf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED);
- if (old_curbuf != NULL)
- enter_buffer(old_curbuf);
- /* If "old_curbuf" is NULL we are in big trouble here... */
- +
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Restore the error/interrupt/exception state if not discarded by a
- + * new aborting error, interrupt, or uncaught exception. */
- + leave_cleanup(&cs);
- + # endif
- }
- else if (swap_exists_action == SEA_RECOVER)
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Reset the error/interrupt/exception state here so that
- + * aborting() returns FALSE when closing a buffer. */
- + enter_cleanup(&cs);
- + # endif
- +
- /* User selected Recover at ATTENTION prompt. */
- msg_scroll = TRUE;
- ml_recover();
- MSG_PUTS("\n"); /* don't overwrite the last message */
- cmdline_row = msg_row;
- do_modelines();
- +
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Restore the error/interrupt/exception state if not discarded by a
- + * new aborting error, interrupt, or uncaught exception. */
- + leave_cleanup(&cs);
- + # endif
- }
- swap_exists_action = SEA_NONE;
- }
- ***************
- *** 1380,1386 ****
- * If (flags & BLN_CURBUF) is TRUE, may use current buffer.
- * If (flags & BLN_LISTED) is TRUE, add new buffer to buffer list.
- * If (flags & BLN_DUMMY) is TRUE, don't count it as a real buffer.
- - * If (flags & BLN_FORCE) is TRUE, don't abort on an error.
- * This is the ONLY way to create a new buffer.
- */
- static int top_file_num = 1; /* highest file number */
- --- 1421,1426 ----
- ***************
- *** 1455,1462 ****
- if (buf == curbuf)
- apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
- # ifdef FEAT_EVAL
- ! /* autocmds may abort script processing */
- ! if (!(flags & BLN_FORCE) && aborting())
- return NULL;
- # endif
- #endif
- --- 1495,1501 ----
- if (buf == curbuf)
- apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
- # ifdef FEAT_EVAL
- ! if (aborting()) /* autocmds may abort script processing */
- return NULL;
- # endif
- #endif
- ***************
- *** 1509,1516 ****
- if (buf != curbuf) /* autocommands deleted the buffer! */
- return NULL;
- #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- ! /* autocmds may abort script processing */
- ! if (!(flags & BLN_FORCE) && aborting())
- return NULL;
- #endif
- /* buf->b_nwindows = 0; why was this here? */
- --- 1548,1554 ----
- if (buf != curbuf) /* autocommands deleted the buffer! */
- return NULL;
- #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- ! if (aborting()) /* autocmds may abort script processing */
- return NULL;
- #endif
- /* buf->b_nwindows = 0; why was this here? */
- ***************
- *** 1586,1593 ****
- if (flags & BLN_LISTED)
- apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
- # ifdef FEAT_EVAL
- ! /* autocmds may abort script processing */
- ! if (!(flags & BLN_FORCE) && aborting())
- return NULL;
- # endif
- }
- --- 1624,1630 ----
- if (flags & BLN_LISTED)
- apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
- # ifdef FEAT_EVAL
- ! if (aborting()) /* autocmds may abort script processing */
- return NULL;
- # endif
- }
- ***************
- *** 4217,4229 ****
- #endif
- set_curbuf(buf, DOBUF_GOTO);
- #ifdef FEAT_AUTOCMD
- - # ifdef FEAT_EVAL
- - /* Autocommands deleted the buffer or aborted script
- - * processing!!! */
- - if (!buf_valid(buf) || aborting())
- - # else
- if (!buf_valid(buf)) /* autocommands deleted the buffer!!! */
- - # endif
- {
- #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
- swap_exists_action = SEA_NONE;
- --- 4254,4260 ----
- ***************
- *** 4234,4243 ****
- --- 4265,4289 ----
- #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
- if (swap_exists_action == SEA_QUIT)
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + cleanup_T cs;
- +
- + /* Reset the error/interrupt/exception state here so that
- + * aborting() returns FALSE when closing a window. */
- + enter_cleanup(&cs);
- + # endif
- +
- /* User selected Quit at ATTENTION prompt; close this window. */
- win_close(curwin, TRUE);
- --open_wins;
- swap_exists_action = SEA_NONE;
- +
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Restore the error/interrupt/exception state if not
- + * discarded by a new aborting error, interrupt, or uncaught
- + * exception. */
- + leave_cleanup(&cs);
- + # endif
- }
- else
- handle_swap_exists(NULL);
- ***************
- *** 4250,4255 ****
- --- 4296,4306 ----
- (void)vgetc(); /* only break the file loading, not the rest */
- break;
- }
- + #ifdef FEAT_EVAL
- + /* Autocommands deleted the buffer or aborted script processing!!! */
- + if (aborting())
- + break;
- + #endif
- }
- #ifdef FEAT_AUTOCMD
- --autocmd_no_enter;
- *** ../vim-6.3.039/src/ex_docmd.c Wed Jun 9 14:59:11 2004
- --- src/ex_docmd.c Sun Dec 5 15:24:08 2004
- ***************
- *** 6610,6619 ****
- --- 6610,6633 ----
- need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
- if (!need_hide || P_HID(curbuf))
- {
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + cleanup_T cs;
- +
- + /* Reset the error/interrupt/exception state here so that
- + * aborting() returns FALSE when closing a window. */
- + enter_cleanup(&cs);
- + # endif
- # ifdef FEAT_GUI
- need_mouse_correct = TRUE;
- # endif
- win_close(curwin, !need_hide && !P_HID(curbuf));
- +
- + # if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- + /* Restore the error/interrupt/exception state if not
- + * discarded by a new aborting error, interrupt, or
- + * uncaught exception. */
- + leave_cleanup(&cs);
- + # endif
- }
- }
- #endif
- *** ../vim-6.3.039/src/ex_eval.c Wed Jun 9 14:56:26 2004
- --- src/ex_eval.c Sun Dec 5 15:25:04 2004
- ***************
- *** 1820,1825 ****
- --- 1820,1979 ----
- }
-
- /*
- + * enter_cleanup() and leave_cleanup()
- + *
- + * Functions to be called before/after invoking a sequence of autocommands for
- + * cleanup for a failed command. (Failure means here that a call to emsg()
- + * has been made, an interrupt occurred, or there is an uncaught exception
- + * from a previous autocommand execution of the same command.)
- + *
- + * Call enter_cleanup() with a pointer to a cleanup_T and pass the same
- + * pointer to leave_cleanup(). The cleanup_T structure stores the pending
- + * error/interrupt/exception state.
- + */
- +
- + /*
- + * This function works a bit like ex_finally() except that there was not
- + * actually an extra try block around the part that failed and an error or
- + * interrupt has not (yet) been converted to an exception. This function
- + * saves the error/interrupt/ exception state and prepares for the call to
- + * do_cmdline() that is going to be made for the cleanup autocommand
- + * execution.
- + */
- + void
- + enter_cleanup(csp)
- + cleanup_T *csp;
- + {
- + int pending = CSTP_NONE;
- +
- + /*
- + * Postpone did_emsg, got_int, did_throw. The pending values will be
- + * restored by leave_cleanup() except if there was an aborting error,
- + * interrupt, or uncaught exception after this function ends.
- + */
- + if (did_emsg || got_int || did_throw || need_rethrow)
- + {
- + csp->pending = (did_emsg ? CSTP_ERROR : 0)
- + | (got_int ? CSTP_INTERRUPT : 0)
- + | (did_throw ? CSTP_THROW : 0)
- + | (need_rethrow ? CSTP_THROW : 0);
- +
- + /* If we are currently throwing an exception (did_throw), save it as
- + * well. On an error not yet converted to an exception, update
- + * "force_abort" and reset "cause_abort" (as do_errthrow() would do).
- + * This is needed for the do_cmdline() call that is going to be made
- + * for autocommand execution. We need not save *msg_list because
- + * there is an extra instance for every call of do_cmdline(), anyway.
- + */
- + if (did_throw || need_rethrow)
- + csp->exception = current_exception;
- + else
- + {
- + csp->exception = NULL;
- + if (did_emsg)
- + {
- + force_abort |= cause_abort;
- + cause_abort = FALSE;
- + }
- + }
- + did_emsg = got_int = did_throw = need_rethrow = FALSE;
- +
- + /* Report if required by the 'verbose' option or when debugging. */
- + report_make_pending(pending, csp->exception);
- + }
- + else
- + {
- + csp->pending = CSTP_NONE;
- + csp->exception = NULL;
- + }
- + }
- +
- + /*
- + * See comment above enter_cleanup() for how this function is used.
- + *
- + * This function is a bit like ex_endtry() except that there was not actually
- + * an extra try block around the part that failed and an error or interrupt
- + * had not (yet) been converted to an exception when the cleanup autocommand
- + * sequence was invoked.
- + *
- + * This function has to be called with the address of the cleanup_T structure
- + * filled by enter_cleanup() as an argument; it restores the error/interrupt/
- + * exception state saved by that function - except there was an aborting
- + * error, an interrupt or an uncaught exception during execution of the
- + * cleanup autocommands. In the latter case, the saved error/interrupt/
- + * exception state is discarded.
- + */
- + void
- + leave_cleanup(csp)
- + cleanup_T *csp;
- + {
- + int pending = csp->pending;
- +
- + if (pending == CSTP_NONE) /* nothing to do */
- + return;
- +
- + /* If there was an aborting error, an interrupt, or an uncaught exception
- + * after the corresponding call to enter_cleanup(), discard what has been
- + * made pending by it. Report this to the user if required by the
- + * 'verbose' option or when debugging. */
- + if (aborting() || need_rethrow)
- + {
- + if (pending & CSTP_THROW)
- + /* Cancel the pending exception (includes report). */
- + discard_exception((except_T *)csp->exception, FALSE);
- + else
- + report_discard_pending(pending, NULL);
- +
- + /* If an error was about to be converted to an exception when
- + * enter_cleanup() was called, free the message list. */
- + free_msglist(*msg_list);
- + *msg_list = NULL;
- + }
- +
- + /*
- + * If there was no new error, interrupt, or throw between the calls
- + * to enter_cleanup() and leave_cleanup(), restore the pending
- + * error/interrupt/exception state.
- + */
- + else
- + {
- + /*
- + * If there was an exception being thrown when enter_cleanup() was
- + * called, we need to rethrow it. Make it the exception currently
- + * being thrown.
- + */
- + if (pending & CSTP_THROW)
- + current_exception = csp->exception;
- +
- + /*
- + * If an error was about to be converted to an exception when
- + * enter_cleanup() was called, let "cause_abort" take the part of
- + * "force_abort" (as done by cause_errthrow()).
- + */
- + else if (pending & CSTP_ERROR)
- + {
- + cause_abort = force_abort;
- + force_abort = FALSE;
- + }
- +
- + /*
- + * Restore the pending values of did_emsg, got_int, and did_throw.
- + */
- + if (pending & CSTP_ERROR)
- + did_emsg = TRUE;
- + if (pending & CSTP_INTERRUPT)
- + got_int = TRUE;
- + if (pending & CSTP_THROW)
- + need_rethrow = TRUE; /* did_throw will be set by do_one_cmd() */
- +
- + /* Report if required by the 'verbose' option or when debugging. */
- + report_resume_pending(pending,
- + (pending & CSTP_THROW) ? (void *)current_exception : NULL);
- + }
- + }
- +
- +
- + /*
- * Make conditionals inactive and discard what's pending in finally clauses
- * until the conditional type searched for or a try conditional not in its
- * finally clause is reached. If this is in an active catch clause, finish the
- *** ../vim-6.3.039/src/proto/ex_eval.pro Wed Jun 9 14:56:24 2004
- --- src/proto/ex_eval.pro Sun Dec 5 15:25:27 2004
- ***************
- *** 23,28 ****
- --- 23,30 ----
- void ex_catch __ARGS((exarg_T *eap));
- void ex_finally __ARGS((exarg_T *eap));
- void ex_endtry __ARGS((exarg_T *eap));
- + void enter_cleanup __ARGS((cleanup_T *csp));
- + void leave_cleanup __ARGS((cleanup_T *csp));
- int cleanup_conditionals __ARGS((struct condstack *cstack, int searched_cond, int inclusive));
- void ex_endfunction __ARGS((exarg_T *eap));
- int has_while_cmd __ARGS((char_u *p));
- *** ../vim-6.3.039/src/structs.h Sat Sep 18 20:28:07 2004
- --- src/structs.h Sun Dec 5 15:26:11 2004
- ***************
- *** 665,670 ****
- --- 665,681 ----
- #define ET_ERROR 1 /* error exception */
- #define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */
-
- + /*
- + * Structure to save the error/interrupt/exception state between calls to
- + * enter_cleanup() and leave_cleanup(). Must be allocated as an automatic
- + * variable by the (common) caller of these functions.
- + */
- + typedef struct cleanup_stuff cleanup_T;
- + struct cleanup_stuff
- + {
- + int pending; /* error/interrupt/exception state */
- + except_T *exception; /* exception value */
- + };
-
- #ifdef FEAT_SYN_HL
- /* struct passed to in_id_list() */
- *** ../vim-6.3.039/src/vim.h Sat Sep 4 19:43:59 2004
- --- src/vim.h Sun Dec 5 15:26:56 2004
- ***************
- *** 714,720 ****
- #define BLN_CURBUF 1 /* May re-use curbuf for new buffer */
- #define BLN_LISTED 2 /* Put new buffer in buffer list */
- #define BLN_DUMMY 4 /* Allocating dummy buffer */
- - #define BLN_FORCE 8 /* Don't abort on error */
-
- /* Values for in_cinkeys() */
- #define KEY_OPEN_FORW 0x101
- --- 714,719 ----
- *** ../vim-6.3.039/src/version.c Sun Dec 5 14:57:15 2004
- --- src/version.c Sun Dec 5 16:16:22 2004
- ***************
- *** 643,644 ****
- --- 643,646 ----
- { /* Add new patch number below this line */
- + /**/
- + 40,
- /**/
-
- --
- If your company is not involved in something called "ISO 9000" you probably
- have no idea what it is. If your company _is_ involved in ISO 9000 then you
- definitely have no idea what it is.
- (Scott Adams - The Dilbert principle)
-
- /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
- /// Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
- \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
- \\\ Buy LOTR 3 and help AIDS victims -- http://ICCF.nl/lotr.html ///
-