#include "systime.h"
#include "atimer.h"
#include "process.h"
+#include "guile.h"
#include <errno.h>
#ifdef HAVE_PTHREAD
/* For longjmp to where kbd input is being done. */
-static sys_jmp_buf getcjmp;
+static Lisp_Object getctag;
/* True while doing kbd input. */
bool waiting_for_input;
static Lisp_Object make_lispy_focus_out (Lisp_Object);
#endif /* HAVE_WINDOW_SYSTEM */
static bool help_char_p (Lisp_Object);
-static void save_getcjmp (sys_jmp_buf *);
-static void restore_getcjmp (sys_jmp_buf *);
static Lisp_Object apply_modifiers (int, Lisp_Object);
static void clear_event (struct input_event *);
static void restore_kboard_configuration (int);
Lisp_Object
recursive_edit_1 (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
if (command_loop_level > 0)
if (STRINGP (val))
xsignal1 (Qerror, val);
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
/* When an auto-save happens, record the "time", and don't do again soon. */
This function is called by the editor initialization to begin editing. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object buffer;
/* If we enter while input is blocked, don't lock up here.
This may happen through the debugger during redisplay. */
- if (input_blocked_p ())
+ if (input_blocked_p ()) {
+ dynwind_end ();
return Qnil;
+ }
if (command_loop_level >= 0
&& current_buffer != XBUFFER (XWINDOW (selected_window)->contents))
temporarily_switch_to_single_kboard (SELECTED_FRAME ());
recursive_edit_1 ();
- return unbind_to (count, Qnil);
+ dynwind_end ();
+ return Qnil;
}
void
value to us. A value of nil means that command_loop_1 itself
returned due to end of file (or end of kbd macro). */
+static Lisp_Object
+command_loop_2_body (void *ignore)
+{
+ return command_loop_1 ();
+}
+
+static Lisp_Object
+command_loop_2_handler (void *ignore, SCM key, SCM args)
+{
+ return Fsignal (Qerror,
+ list3 (build_string ("Scheme error"), key, args));
+}
+
+static Lisp_Object
+command_loop_2_inner (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ command_loop_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
command_loop_2 (Lisp_Object ignore)
{
register Lisp_Object val;
do
- val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+ val = internal_condition_case (command_loop_2_inner, Qerror, cmd_error);
while (!NILP (val));
return Qnil;
}
static Lisp_Object
-top_level_2 (void)
+top_level_2_body (void *ignore)
{
return Feval (Vtop_level, Qnil);
}
+static Lisp_Object
+top_level_2 (void)
+{
+ return scm_c_with_throw_handler (SCM_BOOL_T,
+ top_level_2_body, NULL,
+ command_loop_2_handler, NULL,
+ 0);
+}
+
static Lisp_Object
top_level_1 (Lisp_Object ignore)
{
usage: (track-mouse BODY...) */)
(Lisp_Object args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
record_unwind_protect (tracking_off, do_mouse_tracking);
do_mouse_tracking = Qt;
val = Fprogn (args);
- return unbind_to (count, val);
+ dynwind_end ();
+ return val;
}
/* If mouse has moved on some frame, return one of those frames.
read_menu_command (void)
{
Lisp_Object keybuf[30];
- ptrdiff_t count = SPECPDL_INDEX ();
+ scm_dynwind_begin (0);
int i;
/* We don't want to echo the keystrokes while navigating the
i = read_key_sequence (keybuf, ARRAYELTS (keybuf),
Qnil, 0, 1, 1, 1);
- unbind_to (count, Qnil);
+ scm_dynwind_end ();
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
Fkill_emacs (Qnil);
/* FIXME: our `internal_condition_case' does not provide any way to pass data
to its body or to its handlers other than via globals such as
dynamically-bound variables ;-) */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_quit, hook);
run_hook_with_args (1, &hook, safe_run_hook_funcall);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
\f
static Lisp_Object
read_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf *local_getcjmp,
+ Lisp_Object local_tag,
bool *used_mouse_menu)
{
Lisp_Object c = Qnil;
+ Lisp_Object save_tag = Qnil;
sys_jmp_buf *save_jump = xmalloc (sizeof *save_jump);
KBOARD *kb IF_LINT (= NULL);
return c;
/* Actually read a character, waiting if necessary. */
- save_getcjmp (save_jump);
- restore_getcjmp (local_getcjmp);
+ save_tag = getctag;
+ getctag = local_tag;
if (!end_time)
timer_start_idle ();
c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
- restore_getcjmp (save_jump);
+ getctag = save_tag;
if (! NILP (c) && (kb != current_kboard))
{
to tty input. */
static Lisp_Object
read_decoded_event_from_main_queue (struct timespec *end_time,
- sys_jmp_buf *local_getcjmp,
+ Lisp_Object local_getcjmp,
Lisp_Object prev_event,
bool *used_mouse_menu)
{
bool *used_mouse_menu;
struct timespec *end_time;
Lisp_Object c;
- ptrdiff_t jmpcount;
- sys_jmp_buf *local_getcjmp;
- sys_jmp_buf *save_jump;
+ Lisp_Object tag;
+ Lisp_Object local_tag;
+ Lisp_Object save_tag;
Lisp_Object previous_echo_area_message;
Lisp_Object also_record;
bool reread;
static Lisp_Object read_char_1 (bool, volatile struct read_char_state *);
+static Lisp_Object
+read_char_thunk (void *data)
+{
+ return read_char_1 (false, data);
+}
+
+static Lisp_Object
+read_char_handle_quit (void *data, Lisp_Object k)
+{
+ struct read_char_state *state = data;
+ /* Handle quits while reading the keyboard. */
+ /* We must have saved the outer value of getcjmp here,
+ so restore it now. */
+ getctag = state->save_tag;
+ XSETINT (state->c, quit_char);
+ internal_last_event_frame = selected_frame;
+ Vlast_event_frame = internal_last_event_frame;
+ /* If we report the quit char as an event,
+ don't do so more than once. */
+ if (!NILP (Vinhibit_quit))
+ Vquit_flag = Qnil;
+
+ {
+ KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
+ if (kb != current_kboard)
+ {
+ Lisp_Object last = KVAR (kb, kbd_queue);
+ /* We shouldn't get here if we were in single-kboard mode! */
+ if (single_kboard)
+ emacs_abort ();
+ if (CONSP (last))
+ {
+ while (CONSP (XCDR (last)))
+ last = XCDR (last);
+ if (!NILP (XCDR (last)))
+ emacs_abort ();
+ }
+ if (!CONSP (last))
+ kset_kbd_queue (kb, list1 (state->c));
+ else
+ XSETCDR (last, list1 (state->c));
+ kb->kbd_queue_has_data = 1;
+ current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ UNGCPRO;
+ return make_number (-2); /* wrong_kboard_jmpbuf */
+ }
+ }
+ return read_char_1 (true, state);
+}
+
/* {{coccinelle:skip_start}} */
Lisp_Object
read_char (int commandflag, Lisp_Object map,
Lisp_Object prev_event,
bool *used_mouse_menu, struct timespec *end_time)
{
- volatile struct read_char_state *state = xmalloc (sizeof *state);
+ struct read_char_state *state = xmalloc (sizeof *state);
state->commandflag = commandflag;
state->map = map;
state->used_mouse_menu = used_mouse_menu;
state->end_time = end_time;
state->c = Qnil;
- state->local_getcjmp = xmalloc (sizeof (*state->local_getcjmp));
- state->save_jump = xmalloc (sizeof (*state->save_jump));
+ state->local_tag = Qnil;
+ state->save_tag = Qnil;
state->previous_echo_area_message = Qnil;
state->also_record = Qnil;
state->reread = false;
around any call to sit_for or kbd_buffer_get_event;
it *must not* be in effect when we call redisplay. */
- state->jmpcount = SPECPDL_INDEX ();
- if (sys_setjmp (*state->local_getcjmp))
- {
- /* Handle quits while reading the keyboard. */
- /* We must have saved the outer value of getcjmp here,
- so restore it now. */
- restore_getcjmp (state->save_jump);
- pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
- unbind_to (state->jmpcount, Qnil);
- XSETINT (state->c, quit_char);
- internal_last_event_frame = selected_frame;
- Vlast_event_frame = internal_last_event_frame;
- /* If we report the quit char as an event,
- don't do so more than once. */
- if (!NILP (Vinhibit_quit))
- Vquit_flag = Qnil;
-
- {
- KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
- if (kb != current_kboard)
- {
- Lisp_Object last = KVAR (kb, kbd_queue);
- /* We shouldn't get here if we were in single-kboard mode! */
- if (single_kboard)
- emacs_abort ();
- if (CONSP (last))
- {
- while (CONSP (XCDR (last)))
- last = XCDR (last);
- if (!NILP (XCDR (last)))
- emacs_abort ();
- }
- if (!CONSP (last))
- kset_kbd_queue (kb, list1 (state->c));
- else
- XSETCDR (last, list1 (state->c));
- kb->kbd_queue_has_data = 1;
- current_kboard = kb;
- /* This is going to exit from read_char
- so we had better get rid of this frame's stuff. */
- UNGCPRO;
- return make_number (-2); /* wrong_kboard_jmpbuf */
- }
- }
- return read_char_1 (true, state);
- }
+ state->tag = state->local_tag = make_prompt_tag ();
- return read_char_1 (false, state);
+ return call_with_prompt (state->tag,
+ make_c_closure (read_char_thunk, state, 0, 0),
+ make_c_closure (read_char_handle_quit, state, 1, 0));
}
static Lisp_Object
#define end_time state->end_time
#define c state->c
#define jmpcount state->jmpcount
-#define local_getcjmp state->local_getcjmp
-#define save_jump state->save_jump
+#define local_getcjmp state->local_tag
+#define save_jump state->save_tag
#define previous_echo_area_message state->previous_echo_area_message
#define also_record state->also_record
#define reread state->reread
#define polling_stopped_here state->polling_stopped_here
#define orig_kboard state->orig_kboard
+#define save_getcjmp(x) (x = getctag)
+#define restore_getcjmp(x) (getctag = x)
Lisp_Object tem, save;
if (jump)
#undef reread
#undef polling_stopped_here
#undef orig_kboard
+#undef save_getcjmp
+#undef restore_getcjmp
}
/* {{coccinelle:skip_end}} */
unblock_input ();
}
}
-
-/* Copy out or in the info on where C-g should throw to.
- This is used when running Lisp code from within get_char,
- in case get_char is called recursively.
- See read_process_output. */
-
-static void
-save_getcjmp (sys_jmp_buf *temp)
-{
- memcpy (*temp, getcjmp, sizeof getcjmp);
-}
-
-static void
-restore_getcjmp (sys_jmp_buf *temp)
-{
- memcpy (getcjmp, *temp, sizeof getcjmp);
-}
\f
/* Low level keyboard/mouse input.
kbd_buffer_store_event places events in kbd_buffer, and
{
if (NILP (AREF (chosen_timer, 0)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
call1 (Qtimer_event_handler, chosen_timer);
Vdeactivate_mark = old_deactivate_mark;
timers_run++;
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Since we have handled the event,
we don't need to tell the caller to wake up and do it. */
Lisp_Object
menu_item_eval_property (Lisp_Object sexpr)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
menu_item_eval_property_1);
- return unbind_to (count, val);
+ dynwind_end ();
+ return val;
}
/* This function parses a menu item and leaves the result in the
(such as lmenu.el set it up), check if the
original command matches the cached command. */
&& !(SYMBOLP (def)
- && EQ (tem, XSYMBOL (def)->function))))
+ && EQ (tem, SYMBOL_FUNCTION (def)))))
keys = Qnil;
}
/* Handle a symbol whose function definition is a keymap
or an array. */
if (SYMBOLP (next) && !NILP (Ffboundp (next))
- && (ARRAYP (XSYMBOL (next)->function)
- || KEYMAPP (XSYMBOL (next)->function)))
- next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
+ && (ARRAYP (SYMBOL_FUNCTION (next))
+ || KEYMAPP (SYMBOL_FUNCTION (next))))
+ next = Fautoload_do_load (SYMBOL_FUNCTION (next),
+ next, Qnil);
/* If the keymap gives a function, not an
array, then call the function with one arg and use
Lisp_Object keybuf[30];
register int i;
struct gcpro gcpro1;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
if (!NILP (prompt))
CHECK_STRING (prompt);
QUIT;
}
UNGCPRO;
- return unbind_to (count,
- ((allow_string ? make_event_array : Fvector)
- (i, keybuf)));
+ Lisp_Object tem0 = ((allow_string ? make_event_array : Fvector) (i, keybuf));
+ dynwind_end ();
+ return tem0;
}
DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
On such systems, Emacs starts a subshell instead of suspending. */)
(Lisp_Object stuffstring)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int old_height, old_width;
int width, height;
struct gcpro gcpro1;
sys_subshell ();
else
sys_suspend ();
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Check if terminal/window size has changed.
Note that this is not useful when we are running directly
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
0, 0, Qnil);
- sys_longjmp (getcjmp, 1);
+ abort_to_prompt (getctag, SCM_EOL);
}
\f
DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,