mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
updated for version 7.4.107
Problem: Python: When vim.eval() encounters a Vim error, a try/catch in the Python code doesn't catch it. (Yggdroot Chen) Solution: Throw exceptions on errors in vim.eval(). (ZyX)
This commit is contained in:
132
src/ex_eval.c
132
src/ex_eval.c
@@ -320,6 +320,17 @@ free_msglist(l)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Free global "*msg_list" and the messages it contains, then set "*msg_list"
|
||||
* to NULL.
|
||||
*/
|
||||
void
|
||||
free_global_msglist()
|
||||
{
|
||||
free_msglist(*msg_list);
|
||||
*msg_list = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Throw the message specified in the call to cause_errthrow() above as an
|
||||
* error exception. If cstack is NULL, postpone the throw until do_cmdline()
|
||||
@@ -410,66 +421,41 @@ do_intthrow(cstack)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throw a new exception. Return FAIL when out of memory or it was tried to
|
||||
* throw an illegal user exception. "value" is the exception string for a user
|
||||
* or interrupt exception, or points to a message list in case of an error
|
||||
* exception.
|
||||
* Get an exception message that is to be stored in current_exception->value.
|
||||
*/
|
||||
static int
|
||||
throw_exception(value, type, cmdname)
|
||||
char_u *
|
||||
get_exception_string(value, type, cmdname, should_free)
|
||||
void *value;
|
||||
int type;
|
||||
char_u *cmdname;
|
||||
int *should_free;
|
||||
{
|
||||
except_T *excp;
|
||||
char_u *p, *mesg, *val;
|
||||
char_u *ret, *mesg;
|
||||
int cmdlen;
|
||||
|
||||
/*
|
||||
* Disallow faking Interrupt or error exceptions as user exceptions. They
|
||||
* would be treated differently from real interrupt or error exceptions when
|
||||
* no active try block is found, see do_cmdline().
|
||||
*/
|
||||
if (type == ET_USER)
|
||||
{
|
||||
if (STRNCMP((char_u *)value, "Vim", 3) == 0 &&
|
||||
(((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':' ||
|
||||
((char_u *)value)[3] == '('))
|
||||
{
|
||||
EMSG(_("E608: Cannot :throw exceptions with 'Vim' prefix"));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
excp = (except_T *)alloc((unsigned)sizeof(except_T));
|
||||
if (excp == NULL)
|
||||
goto nomem;
|
||||
char_u *p, *val;
|
||||
|
||||
if (type == ET_ERROR)
|
||||
{
|
||||
/* Store the original message and prefix the exception value with
|
||||
* "Vim:" or, if a command name is given, "Vim(cmdname):". */
|
||||
excp->messages = (struct msglist *)value;
|
||||
mesg = excp->messages->throw_msg;
|
||||
*should_free = FALSE;
|
||||
mesg = ((struct msglist *)value)->throw_msg;
|
||||
if (cmdname != NULL && *cmdname != NUL)
|
||||
{
|
||||
cmdlen = (int)STRLEN(cmdname);
|
||||
excp->value = vim_strnsave((char_u *)"Vim(",
|
||||
ret = vim_strnsave((char_u *)"Vim(",
|
||||
4 + cmdlen + 2 + (int)STRLEN(mesg));
|
||||
if (excp->value == NULL)
|
||||
goto nomem;
|
||||
STRCPY(&excp->value[4], cmdname);
|
||||
STRCPY(&excp->value[4 + cmdlen], "):");
|
||||
val = excp->value + 4 + cmdlen + 2;
|
||||
if (ret == NULL)
|
||||
return ret;
|
||||
STRCPY(&ret[4], cmdname);
|
||||
STRCPY(&ret[4 + cmdlen], "):");
|
||||
val = ret + 4 + cmdlen + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
excp->value = vim_strnsave((char_u *)"Vim:", 4 + (int)STRLEN(mesg));
|
||||
if (excp->value == NULL)
|
||||
goto nomem;
|
||||
val = excp->value + 4;
|
||||
ret = vim_strnsave((char_u *)"Vim:", 4 + (int)STRLEN(mesg));
|
||||
if (ret == NULL)
|
||||
return ret;
|
||||
val = ret + 4;
|
||||
}
|
||||
|
||||
/* msg_add_fname may have been used to prefix the message with a file
|
||||
@@ -506,14 +492,65 @@ throw_exception(value, type, cmdname)
|
||||
}
|
||||
}
|
||||
else
|
||||
excp->value = value;
|
||||
{
|
||||
*should_free = FALSE;
|
||||
ret = (char_u *) value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throw a new exception. Return FAIL when out of memory or it was tried to
|
||||
* throw an illegal user exception. "value" is the exception string for a
|
||||
* user or interrupt exception, or points to a message list in case of an
|
||||
* error exception.
|
||||
*/
|
||||
static int
|
||||
throw_exception(value, type, cmdname)
|
||||
void *value;
|
||||
int type;
|
||||
char_u *cmdname;
|
||||
{
|
||||
except_T *excp;
|
||||
int should_free;
|
||||
|
||||
/*
|
||||
* Disallow faking Interrupt or error exceptions as user exceptions. They
|
||||
* would be treated differently from real interrupt or error exceptions
|
||||
* when no active try block is found, see do_cmdline().
|
||||
*/
|
||||
if (type == ET_USER)
|
||||
{
|
||||
if (STRNCMP((char_u *)value, "Vim", 3) == 0
|
||||
&& (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':'
|
||||
|| ((char_u *)value)[3] == '('))
|
||||
{
|
||||
EMSG(_("E608: Cannot :throw exceptions with 'Vim' prefix"));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
excp = (except_T *)alloc((unsigned)sizeof(except_T));
|
||||
if (excp == NULL)
|
||||
goto nomem;
|
||||
|
||||
if (type == ET_ERROR)
|
||||
/* Store the original message and prefix the exception value with
|
||||
* "Vim:" or, if a command name is given, "Vim(cmdname):". */
|
||||
excp->messages = (struct msglist *)value;
|
||||
|
||||
excp->value = get_exception_string(value, type, cmdname, &should_free);
|
||||
if (excp->value == NULL && should_free)
|
||||
goto nomem;
|
||||
|
||||
excp->type = type;
|
||||
excp->throw_name = vim_strsave(sourcing_name == NULL
|
||||
? (char_u *)"" : sourcing_name);
|
||||
if (excp->throw_name == NULL)
|
||||
{
|
||||
if (type == ET_ERROR)
|
||||
if (should_free)
|
||||
vim_free(excp->value);
|
||||
goto nomem;
|
||||
}
|
||||
@@ -2033,10 +2070,7 @@ leave_cleanup(csp)
|
||||
/* If an error was about to be converted to an exception when
|
||||
* enter_cleanup() was called, free the message list. */
|
||||
if (msg_list != NULL)
|
||||
{
|
||||
free_msglist(*msg_list);
|
||||
*msg_list = NULL;
|
||||
}
|
||||
free_global_msglist();
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user