Loading ...
Sorry, an error occurred while loading the content.

exception creation oddities

Expand Messages
  • Hari Krishna Dara
    In the following two functions, the exception creation looks odd to me. In the first case (function T), the exception gets created too late and in the second
    Message 1 of 8 , Jun 26, 2003
    • 0 Attachment
      In the following two functions, the exception creation looks odd to me.
      In the first case (function T), the exception gets created too late and
      in the second case (function P), IMO the exception shouldn't have got
      created at all.

      In function T, I wouldn't have expected to see the input() prompt at
      all. Also, if you comment the input() line and uncomment the return
      line, you can see that the exception doesn't even get generated and
      result in a syntax error. If you instead uncomment the first line, then
      you wouldn't observe any oddity, and everything would seem to have worked
      fine.

      In function P, I don't know if it was deliberate, but IMO echoerr
      shouldn't create an exception, we have throw for that. Echoerr is meant
      for reporting programmatic error messages that result in Vim generating
      a context in addition to the message. If an exception is created, it is
      not the same.

      Thanks,
      Hari

      >>>>
      function! T()
      try
      "call remote_expr('GVIM2', 'xxx')
      "return remote_expr('GVIM2', 'xxx')
      call input('Got: ' . remote_expr('XXX', 'xxx'))
      catch
      call input('exception: ' . v:exception)
      endtry
      endfunction


      function! P()
      try
      echoerr 'About to generate an exception'
      throw 'My Exception'
      catch
      call input('Exception received: ' . v:exception)
      endtry
      endfunction
      <<<<

      __________________________________
      Do you Yahoo!?
      SBC Yahoo! DSL - Now only $29.95 per month!
      http://sbc.yahoo.com
    • Bram Moolenaar
      ... I can fix this with the patch below. However, I am not sure if this doesn t cause another problem. I ll await comments from Servatius about that. ...
      Message 2 of 8 , Jun 26, 2003
      • 0 Attachment
        Hari Krishna Dara wrote:

        > In the following two functions, the exception creation looks odd to me.
        > In the first case (function T), the exception gets created too late and
        > in the second case (function P), IMO the exception shouldn't have got
        > created at all.
        >
        > In function T, I wouldn't have expected to see the input() prompt at
        > all. Also, if you comment the input() line and uncomment the return
        > line, you can see that the exception doesn't even get generated and
        > result in a syntax error. If you instead uncomment the first line, then
        > you wouldn't observe any oddity, and everything would seem to have worked
        > fine.

        I can fix this with the patch below. However, I am not sure if this
        doesn't cause another problem. I'll await comments from Servatius about
        that.

        > In function P, I don't know if it was deliberate, but IMO echoerr
        > shouldn't create an exception, we have throw for that. Echoerr is meant
        > for reporting programmatic error messages that result in Vim generating
        > a context in addition to the message. If an exception is created, it is
        > not the same.

        This was done intentionally: ":echoerr" reports an error, and an error
        produces an exception.


        *** eval.c~ Tue Jun 24 19:56:47 2003
        --- eval.c Thu Jun 26 22:06:05 2003
        ***************
        *** 2975,2985 ****
        else
        ret = FAIL;

        ! if (ret == OK)
        ! ret = call_func(name, len, retvar, argcount, argvars,
        firstline, lastline, doesrange, evaluate);
        ! else if (!aborting())
        ! EMSG2(_("E116: Invalid arguments for function %s"), name);

        while (--argcount >= 0)
        clear_var(&argvars[argcount]);
        --- 2975,2988 ----
        else
        ret = FAIL;

        ! if (!aborting())
        ! {
        ! if (ret == OK)
        ! ret = call_func(name, len, retvar, argcount, argvars,
        firstline, lastline, doesrange, evaluate);
        ! else
        ! EMSG2(_("E116: Invalid arguments for function %s"), name);
        ! }

        while (--argcount >= 0)
        clear_var(&argvars[argcount]);

        --
        hundred-and-one symptoms of being an internet addict:
        206. You religiously respond immediately to e-mail, while ignoring
        your growing pile of snail mail.

        /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
        /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
        \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
        \\\ Help AIDS victims, buy at Amazon -- http://ICCF.nl/click1.html ///
      • Hari Krishna Dara
        On Thu, 26 Jun 2003 at 10:13pm, Bram Moolenaar wrote: [snip] patch [/snip] Thanks for the patch, I will test it out. ... Then how is it different from :throw
        Message 3 of 8 , Jun 26, 2003
        • 0 Attachment
          On Thu, 26 Jun 2003 at 10:13pm, Bram Moolenaar wrote:

          [snip]

          patch

          [/snip]

          Thanks for the patch, I will test it out.

          >
          > > In function P, I don't know if it was deliberate, but IMO echoerr
          > > shouldn't create an exception, we have throw for that. Echoerr is meant
          > > for reporting programmatic error messages that result in Vim generating
          > > a context in addition to the message. If an exception is created, it is
          > > not the same.
          >
          > This was done intentionally: ":echoerr" reports an error, and an error
          > produces an exception.

          Then how is it different from :throw command? If my intention is to
          generate an exception, then I can as well :throw a message as an
          exception. I would expect :echoerr to serve its purpose even if it is
          under a try block. Anyway, I just observed that this behavior is already
          documented, and I wonder why this approach was taken. I still have your
          reply dated 18-Feb-2002 for my message with subject "echoerr: bug in vim
          or documentation?" where you said:

          : The ":echoerr" command is intended to give the same kind of error
          : message that Vim would give for an error. It's useful if you want to
          : give a specific message about an error that your script detects.

          In any case, my point is that there is no use for :echoerr to throw an
          exception as you can always use the :throw command for this purpose.


          Talking about :echoerr, I just remembered another aspect of :echoerr
          that I observed recently. Normally, :echoerr would print a context
          around the message, which is very useful both for debugging as well as
          for its intended purpose of reporting bugs. I wanted to capture this
          message and extract this context out, as a substitute for missing :where
          command in debugging. But it looks like this doesn't work. If I use the
          following command:

          :redir @z | silent! echoerr "Dummy" | redir END

          then, I just get the message, no context. If I remove the ! for silent
          as,

          :redir @z | silent echoerr "Dummy" | redir END

          then, I get the context, but I see it on screen as well. It will be
          great (and useful to me) if this works the same as other message
          generating commands.

          Thanks a lot,
          Hari

          __________________________________
          Do you Yahoo!?
          SBC Yahoo! DSL - Now only $29.95 per month!
          http://sbc.yahoo.com
        • Bram Moolenaar
          ... The :echoerr command existed long before exception handling. To keep it work as if an error was generated by Vim itself it must do the same thing. That
          Message 4 of 8 , Jun 27, 2003
          • 0 Attachment
            Hari Krishna Dara wrote:

            > > > In function P, I don't know if it was deliberate, but IMO echoerr
            > > > shouldn't create an exception, we have throw for that. Echoerr is meant
            > > > for reporting programmatic error messages that result in Vim generating
            > > > a context in addition to the message. If an exception is created, it is
            > > > not the same.
            > >
            > > This was done intentionally: ":echoerr" reports an error, and an error
            > > produces an exception.
            >
            > Then how is it different from :throw command? If my intention is to
            > generate an exception, then I can as well :throw a message as an
            > exception. I would expect :echoerr to serve its purpose even if it is
            > under a try block. Anyway, I just observed that this behavior is already
            > documented, and I wonder why this approach was taken. I still have your
            > reply dated 18-Feb-2002 for my message with subject "echoerr: bug in vim
            > or documentation?" where you said:

            The ":echoerr" command existed long before exception handling. To keep
            it work as if an error was generated by Vim itself it must do the same
            thing. That now includes throwing an exception.

            If you just want to give a message without the side effects of an actual
            error message you should use ":echomsg", possibly with ":echohl".

            > Talking about :echoerr, I just remembered another aspect of :echoerr
            > that I observed recently. Normally, :echoerr would print a context
            > around the message, which is very useful both for debugging as well as
            > for its intended purpose of reporting bugs. I wanted to capture this
            > message and extract this context out, as a substitute for missing :where
            > command in debugging. But it looks like this doesn't work. If I use the
            > following command:
            >
            > :redir @z | silent! echoerr "Dummy" | redir END
            >
            > then, I just get the message, no context. If I remove the ! for silent
            > as,
            >
            > :redir @z | silent echoerr "Dummy" | redir END
            >
            > then, I get the context, but I see it on screen as well. It will be
            > great (and useful to me) if this works the same as other message
            > generating commands.

            Yes, this is inconsistent. It was done this way for implementation
            reasons (need to skip flushing buffers when ":silent!" is used). You
            don't get the same message. I'll add a remark in the todo list.

            --
            hundred-and-one symptoms of being an internet addict:
            217. Your sex life has drastically improved...so what if it's only cyber-sex!

            /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
            /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
            \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
            \\\ Help AIDS victims, buy at Amazon -- http://ICCF.nl/click1.html ///
          • Hari Krishna Dara
            On Fri, 27 Jun 2003 at 11:15am, Bram Moolenaar wrote: [snip] ... Originally, echomsg with echohl wasn t working as expected. I forgot what was wrong, either
            Message 5 of 8 , Jun 30, 2003
            • 0 Attachment
              On Fri, 27 Jun 2003 at 11:15am, Bram Moolenaar wrote:

              [snip]

              >
              > The ":echoerr" command existed long before exception handling. To keep
              > it work as if an error was generated by Vim itself it must do the same
              > thing. That now includes throwing an exception.
              >
              > If you just want to give a message without the side effects of an actual
              > error message you should use ":echomsg", possibly with ":echohl".

              Originally, echomsg with echohl wasn't working as expected. I forgot
              what was wrong, either the highlighting won't work, or the highlighting
              won't go into the history, but I verified it again and found out that it
              works as expected now, so the problem must have been fixed.

              >
              > > Talking about :echoerr, I just remembered another aspect of :echoerr
              > > that I observed recently. Normally, :echoerr would print a context
              > > around the message, which is very useful both for debugging as well as
              > > for its intended purpose of reporting bugs. I wanted to capture this
              > > message and extract this context out, as a substitute for missing :where
              > > command in debugging. But it looks like this doesn't work. If I use the
              > > following command:
              > >
              > > :redir @z | silent! echoerr "Dummy" | redir END
              > >
              > > then, I just get the message, no context. If I remove the ! for silent
              > > as,
              > >
              > > :redir @z | silent echoerr "Dummy" | redir END
              > >
              > > then, I get the context, but I see it on screen as well. It will be
              > > great (and useful to me) if this works the same as other message
              > > generating commands.
              >
              > Yes, this is inconsistent. It was done this way for implementation
              > reasons (need to skip flushing buffers when ":silent!" is used). You
              > don't get the same message. I'll add a remark in the todo list.
              >

              Thanks for adding it into the todo list, I will wait for it to be fixed.
              I have couple of ideas on using this output for breakpoints.

              Thank you,
              Hari

              __________________________________
              Do you Yahoo!?
              SBC Yahoo! DSL - Now only $29.95 per month!
              http://sbc.yahoo.com
            • Bram Moolenaar
              ... Don t hold your breath. I don t expect to have much time for working on Vim the coming weeks. But perhaps someone else can make a patch for this. It s
              Message 6 of 8 , Jul 1, 2003
              • 0 Attachment
                Hari Krishna Dara wrote:

                > > > Talking about :echoerr, I just remembered another aspect of :echoerr
                > > > that I observed recently. Normally, :echoerr would print a context
                > > > around the message, which is very useful both for debugging as well as
                > > > for its intended purpose of reporting bugs. I wanted to capture this
                > > > message and extract this context out, as a substitute for missing :where
                > > > command in debugging. But it looks like this doesn't work. If I use the
                > > > following command:
                > > >
                > > > :redir @z | silent! echoerr "Dummy" | redir END
                > > >
                > > > then, I just get the message, no context. If I remove the ! for silent
                > > > as,
                > > >
                > > > :redir @z | silent echoerr "Dummy" | redir END
                > > >
                > > > then, I get the context, but I see it on screen as well. It will be
                > > > great (and useful to me) if this works the same as other message
                > > > generating commands.
                > >
                > > Yes, this is inconsistent. It was done this way for implementation
                > > reasons (need to skip flushing buffers when ":silent!" is used). You
                > > don't get the same message. I'll add a remark in the todo list.
                > >
                >
                > Thanks for adding it into the todo list, I will wait for it to be fixed.
                > I have couple of ideas on using this output for breakpoints.

                Don't hold your breath. I don't expect to have much time for working on
                Vim the coming weeks. But perhaps someone else can make a patch for
                this. It's all in the emsg() function.

                --
                hundred-and-one symptoms of being an internet addict:
                269. You receive an e-mail from the wife of a deceased president, offering
                to send you twenty million dollar, and you are not even surprised.

                /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
                /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
                \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
                \\\ Help AIDS victims, buy at Amazon -- http://ICCF.nl/click1.html ///
              • Brandt, Servatius
                ... Bram - I answer so late because I was on vacation. The problem is that after an error in a builtin function, the result of aborting() is not reliable:
                Message 7 of 8 , Jul 11, 2003
                • 0 Attachment
                  Bram Moolenaar wrote:

                  > Hari Krishna Dara wrote:
                  >
                  > > In the following two functions, the exception creation looks odd to me.
                  > > In the first case (function T), the exception gets created too late and
                  > > in the second case (function P), IMO the exception shouldn't have got
                  > > created at all.
                  > >
                  > > In function T, I wouldn't have expected to see the input() prompt at
                  > > all. Also, if you comment the input() line and uncomment the return
                  > > line, you can see that the exception doesn't even get generated and
                  > > result in a syntax error. If you instead uncomment the first line, then
                  > > you wouldn't observe any oddity, and everything would seem to have worked
                  > > fine.
                  >
                  > I can fix this with the patch below. However, I am not sure if this
                  > doesn't cause another problem. I'll await comments from Servatius about
                  > that.
                  >
                  > *** eval.c~ Tue Jun 24 19:56:47 2003
                  > --- eval.c Thu Jun 26 22:06:05 2003
                  > ***************
                  > *** 2975,2985 ****
                  > else
                  > ret = FAIL;
                  >
                  > ! if (ret == OK)
                  > ! ret = call_func(name, len, retvar, argcount, argvars,
                  > firstline, lastline, doesrange, evaluate);
                  > ! else if (!aborting())
                  > ! EMSG2(_("E116: Invalid arguments for function %s"), name);
                  >
                  > while (--argcount >= 0)
                  > clear_var(&argvars[argcount]);
                  > --- 2975,2988 ----
                  > else
                  > ret = FAIL;
                  >
                  > ! if (!aborting())
                  > ! {
                  > ! if (ret == OK)
                  > ! ret = call_func(name, len, retvar, argcount, argvars,
                  > firstline, lastline, doesrange, evaluate);
                  > ! else
                  > ! EMSG2(_("E116: Invalid arguments for function %s"), name);
                  > ! }
                  >
                  > while (--argcount >= 0)
                  > clear_var(&argvars[argcount]);


                  Bram -

                  I answer so late because I was on vacation.

                  The problem is that after an error in a builtin function, the result of
                  aborting() is not reliable: "force_abort", which is updated for
                  user-defined functions at the throw point of the error exception in
                  do_one_cmd(), is not updated for builtin functions (because do_one_cmd()
                  is not invoked).

                  Therefor, the check of aborting() in eval7() after the call of the
                  failing builtin function does not work, so that eval1(), which is called
                  in get_func_var() for evaluation of the argument that calls the builtin
                  function, returns OK instead of FAIL.

                  When aborting() is made reliable also after a builtin function has
                  failed (see the patch below), eval1() returns FAIL. That is, the
                  situation where aborting() returns TRUE although eval1() returned OK
                  (ret == OK) does no longer occur. So your patch is no longer necessary.

                  Your patch addressed just the problem that a function was executed
                  although the evaluation of one of its arguments called a builtin
                  function that failed (that is, called emsg()) and caused an error
                  exception. But there were several other problems (all when inside
                  a ":try"/":endtry" region):

                  - After the error exception in the builtin function in one of
                  the function arguments, other arguments were still evaluated.

                  - On a ":{range}call" of a builtin function that caused an error
                  exception, further calls were made for the remaining lines in
                  the range.

                  - On a ":return" with an argument that called a builtin function
                  that failed, no error exception was raised and the function
                  returned.

                  - On a ":throw" with an argument that called a builtin function
                  that failed, no error exception was raised, but some
                  accidental value was thrown as a user exception.

                  The patch below fixes all these problems at a central place. I added
                  also a new test case in test49.vim.

                  Furthermore, I made the e_trailing message in ex_call() a severe message
                  because syntax errors should take precedence over other errors in the
                  ":call" command.

                  - Servatius


                  --- src/proto/ex_eval.pro.orig Sun Jun 1 12:26:09 2003
                  +++ src/proto/ex_eval.pro Thu Jul 10 14:33:48 2003
                  @@ -1,5 +1,6 @@
                  /* ex_eval.c */
                  int aborting __ARGS((void));
                  +void update_force_abort __ARGS((void));
                  int should_abort __ARGS((int retcode));
                  int aborted_in_try __ARGS((void));
                  int cause_errthrow __ARGS((char_u *msg, int severe, int *ignore));
                  --- src/ex_eval.c.orig Fri May 30 21:45:31 2003
                  +++ src/ex_eval.c Fri Jul 11 10:58:47 2003
                  @@ -72,10 +72,11 @@
                  /*
                  * When several errors appear in a row, setting "force_abort" is delayed until
                  * the failing command returned. "cause_abort" is set to TRUE meanwhile, in
                  - * order to indicate that situation. This is useful for aborting expression
                  - * evaluation when a function call set "force_abort" without producing any
                  - * error messages, but giving all error messages on a parsing error during the
                  - * expression evaluation (even if a try conditional is active).
                  + * order to indicate that situation. This is useful when "force_abort" was set
                  + * during execution of a function call from an expression: the aborting of the
                  + * expression evaluation is done without producing any error messages, but all
                  + * error messages on parsing errors during the expression evaluation are given
                  + * (even if a try conditional is active).
                  */
                  static int cause_abort = FALSE;

                  @@ -85,8 +86,8 @@
                  * to check whether an aborted function that does not handle a range itself
                  * should be called again for the next line in the range. Also used for
                  * cancelling expression evaluation after a function call caused an immediate
                  - * abort. Note that the first emsg() call temporarily resets force_abort until
                  - * the throw point for error messages has been reached. That is, during
                  + * abort. Note that the first emsg() call temporarily resets "force_abort"
                  + * until the throw point for error messages has been reached. That is, during
                  * cancellation of an expression evaluation after an aborting function call or
                  * due to a parsing error, aborting() always returns the same value.
                  */
                  @@ -94,6 +95,19 @@
                  aborting()
                  {
                  return (did_emsg && force_abort) || got_int || did_throw;
                  +}
                  +
                  +/*
                  + * The value of "force_abort" is temporarily reset by the first emsg() call
                  + * during an expression evaluation, and "cause_abort" is used instead. It might
                  + * be necessary to restore "force_abort" even before the throw point for the
                  + * error message has been reached. update_force_abort() should be called then.
                  + */
                  + void
                  +update_force_abort()
                  +{
                  + if (cause_abort)
                  + force_abort = TRUE;
                  }

                  /*
                  --- src/eval.c.orig Fri May 30 21:11:19 2003
                  +++ src/eval.c Fri Jul 11 11:01:11 2003
                  @@ -1302,7 +1302,9 @@
                  if (doesrange || eap->skip)
                  break;
                  /* Stop when immediately aborting on error, or when an interrupt
                  - * occurred or an exception was thrown but not caught. */
                  + * occurred or an exception was thrown but not caught. get_func_var()
                  + * returned OK, so that the check for trailing characters below is
                  + * executed. */
                  if (aborting())
                  break;
                  }
                  @@ -1313,7 +1315,10 @@
                  {
                  /* Check for trailing illegal characters and a following command. */
                  if (!ends_excmd(*arg))
                  + {
                  + emsg_severe = TRUE;
                  EMSG(_(e_trailing));
                  + }
                  else
                  eap->nextcmd = check_nextcmd(arg);
                  }
                  @@ -3128,6 +3133,17 @@
                  }
                  }
                  }
                  + /*
                  + * The function call (or "FuncUndefined" autocommand sequence) might
                  + * have been aborted by an error, an interrupt, or an explicitly thrown
                  + * exception that has not been caught so far. This situation can be
                  + * tested for by calling aborting(). For an error in an internal
                  + * function or for the "E132" error in call_user_func(), however, the
                  + * throw point at which the "force_abort" flag (temporarily reset by
                  + * emsg()) is normally updated has not been reached yet. We need to
                  + * update that flag first to make aborting() reliable.
                  + */
                  + update_force_abort();
                  }
                  if (error == ERROR_NONE)
                  ret = OK;
                  --- src/testdir/test49.ok.orig Fri May 30 21:45:31 2003
                  +++ src/testdir/test49.ok Fri Jul 11 10:28:10 2003
                  @@ -73,18 +73,19 @@
                  *** Test 71: OK (1789569365)
                  *** Test 72: OK (9032615)
                  *** Test 73: OK (224907669)
                  -*** Test 74: OK (1610087935)
                  -*** Test 75: OK (1388671)
                  -*** Test 76: OK (134217728)
                  -*** Test 77: OK (70288929)
                  -*** Test 78: OK (17895765)
                  -*** Test 79: OK (387)
                  -*** Test 80: OK (8454401)
                  -*** Test 81: OK (2835)
                  -*** Test 82: OK (934782101)
                  -*** Test 83: OK (198689)
                  ---- Test 84: All tests were run with throwing exceptions on error.
                  +*** Test 74: OK (2000403408)
                  +*** Test 75: OK (1610087935)
                  +*** Test 76: OK (1388671)
                  +*** Test 77: OK (134217728)
                  +*** Test 78: OK (70288929)
                  +*** Test 79: OK (17895765)
                  +*** Test 80: OK (387)
                  +*** Test 81: OK (8454401)
                  +*** Test 82: OK (2835)
                  +*** Test 83: OK (934782101)
                  +*** Test 84: OK (198689)
                  +--- Test 85: All tests were run with throwing exceptions on error.
                  The $VIMNOERRTHROW control is not configured.
                  ---- Test 84: All tests were run with throwing exceptions on interrupt.
                  +--- Test 85: All tests were run with throwing exceptions on interrupt.
                  The $VIMNOINTTHROW control is not configured.
                  -*** Test 84: OK (50443995)
                  +*** Test 85: OK (50443995)
                  --- src/testdir/test49.vim.orig Fri May 30 21:45:31 2003
                  +++ src/testdir/test49.vim Fri Jul 11 10:27:58 2003
                  @@ -7563,7 +7563,188 @@


                  "-------------------------------------------------------------------------------
                  -" Test 74: Errors, interupts, :throw during expression evaluation {{{1
                  +" Test 74: Errors in builtin functions. {{{1
                  +"
                  +" On an error in a builtin function called inside a :try/:endtry
                  +" region, the evaluation of the expression calling that function and
                  +" the command containing that expression are abandoned. The error can
                  +" be caught as an exception.
                  +"
                  +" A simple :call of the builtin function is a trivial case. If the
                  +" builtin function is called in the argument list of another function,
                  +" no further arguments are evaluated, and the other function is not
                  +" executed. If the builtin function is called from the argument of
                  +" a :return command, the :return command is not executed. If the
                  +" builtin function is called from the argument of a :throw command,
                  +" the :throw command is not executed. The evaluation of the
                  +" expression calling the builtin function is abandoned.
                  +"-------------------------------------------------------------------------------
                  +
                  +XpathINIT
                  +
                  +function! F1(arg1)
                  + Xpath 1 " X: 0
                  +endfunction
                  +
                  +function! F2(arg1, arg2)
                  + Xpath 2 " X: 0
                  +endfunction
                  +
                  +function! G()
                  + Xpath 4 " X: 0
                  +endfunction
                  +
                  +function! H()
                  + Xpath 8 " X: 0
                  +endfunction
                  +
                  +function! R()
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 16 " X: 16
                  + return append(1, "s")
                  + catch /E21/
                  + let caught = 1
                  + catch /.*/
                  + Xpath 32 " X: 0
                  + finally
                  + Xpath 64 " X: 64
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 128 " X: 128
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  + Xpath 256 " X: 256
                  +endfunction
                  +
                  +try
                  + set noma " let append() fail with "E21"
                  +
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 512 " X: 512
                  + call append(1, "s")
                  + catch /E21/
                  + let caught = 1
                  + catch /.*/
                  + Xpath 1024 " X: 0
                  + finally
                  + Xpath 2048 " X: 2048
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 4096 " X: 4096
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  +
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 8192 " X: 8192
                  + call F1('x' . append(1, "s"))
                  + catch /E21/
                  + let caught = 1
                  + catch /.*/
                  + Xpath 16384 " X: 0
                  + finally
                  + Xpath 32768 " X: 32768
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 65536 " X: 65536
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  +
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 131072 " X: 131072
                  + call F2('x' . append(1, "s"), G())
                  + catch /E21/
                  + let caught = 1
                  + catch /.*/
                  + Xpath 262144 " X: 0
                  + finally
                  + Xpath 524288 " X: 524288
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 1048576 " X: 1048576
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  +
                  + call R()
                  +
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 2097152 " X: 2097152
                  + throw "T" . append(1, "s")
                  + catch /E21/
                  + let caught = 1
                  + catch /^T.*/
                  + Xpath 4194304 " X: 0
                  + catch /.*/
                  + Xpath 8388608 " X: 0
                  + finally
                  + Xpath 16777216 " X: 16777216
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 33554432 " X: 33554432
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  +
                  + while 1
                  + try
                  + let caught = 0
                  + let v:errmsg = ""
                  + Xpath 67108864 " X: 67108864
                  + let x = "a"
                  + let x = x . "b" . append(1, "s") . H()
                  + catch /E21/
                  + let caught = 1
                  + catch /.*/
                  + Xpath 134217728 " X: 0
                  + finally
                  + Xpath 268435456 " X: 268435456
                  + if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
                  + Xpath 536870912 " X: 536870912
                  + endif
                  + if x == "a"
                  + Xpath 1073741824 " X: 1073741824
                  + endif
                  + break " discard error for $VIMNOERRTHROW
                  + endtry
                  + endwhile
                  +catch /.*/
                  + " The Xpath command does not accept 2^31 (negative); add explicitly:
                  + let Xpath = Xpath + 2147483648 " X: 0
                  + Xout v:exception "in" v:throwpoint
                  +finally
                  + set ma&
                  +endtry
                  +
                  +unlet! caught x
                  +delfunction F1
                  +delfunction F2
                  +delfunction G
                  +delfunction H
                  +delfunction R
                  +
                  +Xcheck 2000403408
                  +
                  +
                  +"-------------------------------------------------------------------------------
                  +" Test 75: Errors, interupts, :throw during expression evaluation {{{1
                  "
                  " When a function call made during expression evaluation is aborted
                  " due to an error inside a :try/:endtry region or due to an interrupt
                  @@ -7849,7 +8030,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 75: Errors, interupts, :throw in name{brace-expression} {{{1
                  +" Test 76: Errors, interupts, :throw in name{brace-expression} {{{1
                  "
                  " When a function call made during evaluation of an expression in
                  " braces as part of a function name after ":function" is aborted due
                  @@ -7979,7 +8160,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 76: Messages on parsing errors in expression evaluation {{{1
                  +" Test 77: Messages on parsing errors in expression evaluation {{{1
                  "
                  " When an expression evaluation detects a parsing error, an error
                  " message is given and converted to an exception, and the expression
                  @@ -8168,7 +8349,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 77: Throwing one of several errors for the same command {{{1
                  +" Test 78: Throwing one of several errors for the same command {{{1
                  "
                  " When several errors appear in a row (for instance during expression
                  " evaluation), the first as the most specific one is used when
                  @@ -8363,7 +8544,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 78: Syntax error in expression for illegal :elseif {{{1
                  +" Test 79: Syntax error in expression for illegal :elseif {{{1
                  "
                  " If there is a syntax error in the expression after an illegal
                  " :elseif, an error message is given (or an error exception thrown)
                  @@ -8548,7 +8729,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 79: Discarding exceptions after an error or interrupt {{{1
                  +" Test 80: Discarding exceptions after an error or interrupt {{{1
                  "
                  " When an exception is thrown from inside a :try conditional without
                  " :catch and :finally clauses and an error or interrupt occurs before
                  @@ -8594,7 +8775,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 80: Ignoring :catch clauses after an error or interrupt {{{1
                  +" Test 81: Ignoring :catch clauses after an error or interrupt {{{1
                  "
                  " When an exception is thrown and an error or interrupt occurs before
                  " the matching :catch clause is reached, the exception is discarded
                  @@ -8702,7 +8883,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 81: Executing :finally clauses after an error or interrupt {{{1
                  +" Test 82: Executing :finally clauses after an error or interrupt {{{1
                  "
                  " When an exception is thrown and an error or interrupt occurs before
                  " the :finally of the innermost :try is reached, the exception is
                  @@ -8752,7 +8933,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 82: Exceptions in autocommand sequences. {{{1
                  +" Test 83: Exceptions in autocommand sequences. {{{1
                  "
                  " When an exception occurs in a sequence of autocommands for
                  " a specific event, the rest of the sequence is not executed. The
                  @@ -8927,7 +9108,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 83: Error exceptions in autocommands for I/O command events {{{1
                  +" Test 84: Error exceptions in autocommands for I/O command events {{{1
                  "
                  " When an I/O command is inside :try/:endtry, autocommands to be
                  " executed after it should be skipped on an error (exception) in the
                  @@ -9174,7 +9355,7 @@


                  "-------------------------------------------------------------------------------
                  -" Test 84: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
                  +" Test 85: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
                  "
                  " It is possible to configure Vim for throwing exceptions on error
                  " or interrupt, controlled by variables $VIMNOERRTHROW and

                  ------------------------------------------------------------------------
                  Servatius Brandt Phone: +49 89 636-41504
                  Fujitsu Siemens Computers Fax: +49 89 636-48716
                  EP LP AD C++ Email: Servatius.Brandt@...
                • Bram Moolenaar
                  ... Same for me. ... [...] Thanks for checking this out properly. I ll put a remark in my todo list to include your patch instead of mine. -- It s not hard to
                  Message 8 of 8 , Jul 20, 2003
                  • 0 Attachment
                    Servatius Brandt wrote:

                    > I answer so late because I was on vacation.

                    Same for me.

                    > The problem is that after an error in a builtin function, the result of
                    > aborting() is not reliable: "force_abort", which is updated for
                    > user-defined functions at the throw point of the error exception in
                    > do_one_cmd(), is not updated for builtin functions (because do_one_cmd()
                    > is not invoked).
                    >
                    > Therefor, the check of aborting() in eval7() after the call of the
                    > failing builtin function does not work, so that eval1(), which is called
                    > in get_func_var() for evaluation of the argument that calls the builtin
                    > function, returns OK instead of FAIL.
                    >
                    > When aborting() is made reliable also after a builtin function has
                    > failed (see the patch below), eval1() returns FAIL. That is, the
                    > situation where aborting() returns TRUE although eval1() returned OK
                    > (ret == OK) does no longer occur. So your patch is no longer necessary.
                    [...]

                    Thanks for checking this out properly. I'll put a remark in my todo
                    list to include your patch instead of mine.

                    --
                    It's not hard to meet expenses, they're everywhere.

                    /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
                    /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
                    \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
                    \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///
                  Your message has been successfully submitted and would be delivered to recipients shortly.