- New powerful internal error-trapping API for support of running Lisp
code within critical sections (e.g within redisplay, for example
BIDI display time reordering and general char->font mapping)
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/* call_trapping_problems():
This is equivalent to (*fun) (arg), except that various conditions
can be trapped or inhibited, according to FLAGS.
If FLAGS does not contain NO_INHIBIT_ERRORS, when an error occurs,
the error is caught and a warning is issued, specifying the
specific error that occurred and a backtrace. In that case,
WARNING_STRING should be given, and will be printed at the
beginning of the error to indicate where the error occurred.
If FLAGS does not contain NO_INHIBIT_THROWS, all attempts to
`throw' out of the function being called are trapped, and a warning
issued. (Again, WARNING_STRING should be given.)
(If FLAGS contains INHIBIT_WARNING_ISSUE, no warnings are issued;
this applies to recursive invocations of call_trapping_problems, too.)
Note: If neither of NO_INHIBIT_THROWS or NO_INHIBIT_ERRORS is
given, you are *guaranteed* that there will be no non-local exits
out of this function.
If FLAGS contains INHIBIT_QUIT, QUIT using C-g is inhibited. (This
is *rarely* a good idea. Unless you use NO_INHIBIT_ERRORS, QUIT is
automatically caught as well, and treated as an error; you can
check for this using EQ (problems->error_conditions, Qquit).
If FLAGS contains INHIBIT_GC, garbage collection is inhibited.
This is useful for Lisp called within redisplay or inside of the
QUIT macro (where GC is generally not expected), for example.
If FLAGS contains INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION,
Lisp code is not allowed to delete any window, buffers, frames, devices,
or consoles that were already in existence at the time this function
was called. (However, it's perfectly legal for code to create a new
buffer and then delete it.)
#### It might be useful to have a flag that inhibits deletion of a
specific permanent display object and everything it's attached to
(e.g. a window, and the buffer, frame, device, and console it's
attached to.)
If FLAGS contains INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION, Lisp
code is not allowed to modify the text of any buffers that were
already in existence at the time this function was called.
(However, it's perfectly legal for code to create a new buffer and
then modify its text.)
[These last two flags are implemented using global variables
Vdeletable_permanent_display_objects and Vmodifiable_buffers,
which keep track of a list of all buffers or permanent display
objects created since the last time one of these flags was set.
The code that deletes buffers, etc. and modifies buffers checks
(1) if the corresponding flag is set (through the global variable
inhibit_flags or its accessor function get_inhibit_flags()), and
(2) if the object to be modified or deleted is not in the
appropriate list.
If so, it signals an error.
Recursive calls to call_trapping_problems() are allowed. In
the case of the two flags mentioned above, the current values
of the global variables are stored in an unwind-protect, and
they're reset to nil.]
If FLAGS contains INHIBIT_ENTERING_DEBUGGER, the debugger will not
be entered if an error occurs inside the Lisp code being called,
even when the user has requested an error. In such case, a warning
is issued stating that access to the debugger is denied, unless
INHIBIT_WARNING_ISSUE has also been supplied. This is useful when
calling Lisp code inside redisplay, in menu callbacks, etc. because
in such cases either the display is in an inconsistent state or
doing window operations is explicitly forbidden by the OS, and the
debugger would cause visual changes on the screen and might create
another frame.
If FLAGS contains INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY, no
changes of any sort to extents, faces, glyphs, buffer text,
specifiers relating to display, other variables relating to
display, splitting, deleting, or resizing windows or frames,
deleting buffers, windows, frames, devices, or consoles, etc. is
allowed. This is for things called absolutely in the middle of
redisplay, which expects things to be *exactly* the same after the
call as before. This isn't completely implemented and needs to be
thought out some more to determine exactly what its semantics are.
For the moment, turning on this flag also turns on
INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION
INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION
INHIBIT_ENTERING_DEBUGGER
INHIBIT_WARNING_ISSUE
INHIBIT_GC
#### The following five flags are defined, but unimplemented:
#define INHIBIT_EXISTING_CODING_SYSTEM_DELETION (1<<6)
#define INHIBIT_EXISTING_CHARSET_DELETION (1<<7)
#define INHIBIT_PERMANENT_DISPLAY_OBJECT_CREATION (1<<8)
#define INHIBIT_CODING_SYSTEM_CREATION (1<<9)
#define INHIBIT_CHARSET_CREATION (1<<10)
If PROBLEM is non-zero, it should be a pointer to a structure into
which exact information about any occurring problems (either an
error or an attempted throw past this boundary).
If a problem occurred and aborted operation (error, quit, or
invalid throw), Qunbound is returned. Otherwise the return value
from the call to (*fun) (arg) is returned. */
struct call_trapping_problems
{
Lisp_Object catchtag;
Lisp_Object error_conditions;
Lisp_Object data;
Lisp_Object backtrace;
Lisp_Object warning_class;
const char *warning_string;
Lisp_Object (*fun) (void *);
void *arg;
};
Lisp_Object
call_trapping_problems (Lisp_Object warning_class,
const char *warning_string,
int flags,
struct call_trapping_problems_result *problem,
Lisp_Object (*fun) (void *),
void *arg)
#define NO_INHIBIT_ERRORS (1<<0)
#define NO_INHIBIT_THROWS (1<<1)
#define INTERNAL_INHIBIT_ERRORS (1<<0)
#define INTERNAL_INHIBIT_THROWS (1<<1)
#define INHIBIT_WARNING_ISSUE (1<<2)
#define INHIBIT_QUIT (1<<3)
#define INHIBIT_GC (1<<4)
#define INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION (1<<5)
#define INHIBIT_EXISTING_CODING_SYSTEM_DELETION (1<<6)
#define INHIBIT_EXISTING_CHARSET_DELETION (1<<7)
#define INHIBIT_PERMANENT_DISPLAY_OBJECT_CREATION (1<<8)
#define INHIBIT_CODING_SYSTEM_CREATION (1<<9)
#define INHIBIT_CHARSET_CREATION (1<<10)
#define INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION (1<<11)
#define INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY (1<<12)
#define INHIBIT_ENTERING_DEBUGGER (1<<13)
enum check_allowed_operation
{
OPERATION_DELETE_OBJECT,
OPERATION_CREATE_OBJECT,
OPERATION_MODIFY_BUFFER_TEXT,
OPERATION_MODIFY_OBJECT_PROPERTY,
};
/* Buffers, frames, windows, devices, and consoles created since most
recent active
call_trapping_problems (INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION).
*/
Lisp_Object Vdeletable_permanent_display_objects;
/* Buffers created since most recent active
call_trapping_problems (INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION). */
Lisp_Object Vmodifiable_buffers;
int get_inhibit_flags (void);
void check_allowed_operation (int what, Lisp_Object obj, Lisp_Object prop);
void note_object_created (Lisp_Object obj);
void note_object_deleted (Lisp_Object obj);
Lisp_Object call_with_condition_handler (Lisp_Object (*handler) (Lisp_Object,
Lisp_Object,
Lisp_Object),
Lisp_Object handler_arg,
Lisp_Object (*fun) (Lisp_Object),
Lisp_Object arg);
Lisp_Object call_trapping_problems (Lisp_Object warning_class,
const char *warning_string,
int flags,
struct call_trapping_problems_result
*problem,
Lisp_Object (*fun) (void *),
void *arg);
Lisp_Object va_call_trapping_problems (Lisp_Object warning_class,
const char *warning_string,
int flags,
struct call_trapping_problems_result
*problem,
lisp_fn_t fun, int nargs, ...);
Lisp_Object call0_trapping_problems (const char *, Lisp_Object, int);
Lisp_Object call1_trapping_problems (const char *, Lisp_Object, Lisp_Object,
int);
Lisp_Object call2_trapping_problems (const char *, Lisp_Object, Lisp_Object,
Lisp_Object, int);
Lisp_Object call3_trapping_problems (const char *, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object, int);
Lisp_Object call4_trapping_problems (const char *, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object, Lisp_Object,
int);
Lisp_Object call5_trapping_problems (const char *, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, int);
Lisp_Object eval_in_buffer_trapping_problems (const char *, struct buffer *,
Lisp_Object, int);
Lisp_Object run_hook_trapping_problems (const char *, Lisp_Object, int);
Lisp_Object safe_run_hook_trapping_problems (const char *, Lisp_Object, int);
Lisp_Object run_hook_with_args_in_buffer_trapping_problems (const char
*warning_string,
struct buffer
*buf, int nargs,
Lisp_Object *args,
enum
run_hooks_condition
cond, int flags);
Lisp_Object run_hook_with_args_trapping_problems (const char *warning_string,
int nargs,
Lisp_Object *args,
enum run_hooks_condition
cond,
int flags);
Lisp_Object va_run_hook_with_args_trapping_problems (const char
*warning_string,
Lisp_Object hook_var,
int nargs, ...);
Lisp_Object va_run_hook_with_args_in_buffer_trapping_problems (const char
*warning_string,
struct buffer
*buf,
Lisp_Object
hook_var,
int nargs, ...);
Lisp_Object call_with_suspended_errors (lisp_fn_t, volatile Lisp_Object,
Lisp_Object,
Error_behavior, int, ...);