1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 04:10:18 +02:00

fix a prompt bug

* libguile/control.h:
* libguile/control.c (scm_c_make_prompt): Instead of taking a VM arg,
  take the registers directly.
  (scm_c_abort): Declare as returning void. In fact it will never
  return.

* libguile/eval.c (eval):
* libguile/throw.c (pre_init_catch): Adapt to prompt API change.

* libguile/vm-i-system.c (prompt): Pass the abort ip as the ip to
  scm_c_make_prompt. This fixes a bug in which we used the "offset"
  local var, but it wasn't guaranteed to be around after a longjmp.
This commit is contained in:
Andy Wingo 2010-02-25 17:33:12 +01:00
parent b8af64db76
commit d296431516
4 changed files with 26 additions and 19 deletions

View file

@ -32,8 +32,8 @@ SCM scm_sys_default_prompt_tag;
SCM SCM
scm_c_make_prompt (SCM vm, SCM k, scm_t_uint8 escape_only_p, scm_c_make_prompt (SCM k, SCM *fp, SCM *sp, scm_t_uint8 *abort_ip,
scm_t_int64 vm_cookie) scm_t_uint8 escape_only_p, scm_t_int64 vm_cookie)
{ {
scm_t_bits tag; scm_t_bits tag;
SCM ret; SCM ret;
@ -45,9 +45,9 @@ scm_c_make_prompt (SCM vm, SCM k, scm_t_uint8 escape_only_p,
ret = scm_words (tag, 5); ret = scm_words (tag, 5);
regs = scm_gc_malloc_pointerless (sizeof (*regs), "prompt registers"); regs = scm_gc_malloc_pointerless (sizeof (*regs), "prompt registers");
regs->fp = SCM_VM_DATA (vm)->fp; regs->fp = fp;
regs->sp = SCM_VM_DATA (vm)->sp; regs->sp = sp;
regs->ip = SCM_VM_DATA (vm)->ip; regs->ip = abort_ip;
regs->cookie = vm_cookie; regs->cookie = vm_cookie;
SCM_SET_CELL_OBJECT (ret, 1, k); SCM_SET_CELL_OBJECT (ret, 1, k);
@ -190,7 +190,7 @@ reify_partial_continuation (SCM vm, SCM prompt, SCM extwinds,
return ret; return ret;
} }
SCM void
scm_c_abort (SCM vm, SCM tag, size_t n, SCM *argv, scm_t_int64 cookie) scm_c_abort (SCM vm, SCM tag, size_t n, SCM *argv, scm_t_int64 cookie)
{ {
SCM cont, winds, prompt = SCM_BOOL_F; SCM cont, winds, prompt = SCM_BOOL_F;

View file

@ -45,11 +45,13 @@ struct scm_prompt_registers
SCM_INTERNAL SCM scm_sys_default_prompt_tag; SCM_INTERNAL SCM scm_sys_default_prompt_tag;
SCM_INTERNAL SCM scm_c_make_prompt (SCM vm, SCM k, scm_t_uint8 escape_only_p, SCM_INTERNAL SCM scm_c_make_prompt (SCM k, SCM *fp, SCM *sp,
scm_t_int64 cookie); scm_t_uint8 *abort_ip,
scm_t_uint8 escape_only_p,
scm_t_int64 vm_cookie);
SCM_INTERNAL SCM scm_i_prompt_pop_abort_args_x (SCM prompt); SCM_INTERNAL SCM scm_i_prompt_pop_abort_args_x (SCM prompt);
SCM_INTERNAL SCM scm_c_abort (SCM vm, SCM tag, size_t n, SCM *argv, SCM_INTERNAL void scm_c_abort (SCM vm, SCM tag, size_t n, SCM *argv,
scm_t_int64 cookie) SCM_NORETURN; scm_t_int64 cookie) SCM_NORETURN;
SCM_INTERNAL SCM scm_at_abort (SCM tag, SCM args) SCM_NORETURN; SCM_INTERNAL SCM scm_at_abort (SCM tag, SCM args) SCM_NORETURN;

View file

@ -427,9 +427,12 @@ eval (SCM x, SCM env)
case SCM_M_PROMPT: case SCM_M_PROMPT:
{ {
SCM prompt, handler, res; SCM vm, prompt, handler, res;
prompt = scm_c_make_prompt (scm_the_vm (), eval (CAR (mx), env), 0, -1); vm = scm_the_vm ();
prompt = scm_c_make_prompt (eval (CAR (mx), env), SCM_VM_DATA (vm)->fp,
SCM_VM_DATA (vm)->sp, SCM_VM_DATA (vm)->ip,
0, -1);
handler = eval (CDDR (mx), env); handler = eval (CDDR (mx), env);
scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ())); scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));

View file

@ -1479,19 +1479,21 @@ VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 4, 2, 0)
POP (k); POP (k);
SYNC_REGISTER (); SYNC_REGISTER ();
/* Push the prompt onto the dynamic stack. The setjmp itself has to be local /* Push the prompt onto the dynamic stack. */
to this procedure. */ prompt = scm_c_make_prompt (k, fp, sp, ip + offset, escape_only_p, vm_cookie);
/* FIXME: do more error checking */
prompt = scm_c_make_prompt (vm, k, escape_only_p, vm_cookie);
scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ())); scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
if (SCM_PROMPT_SETJMP (prompt)) if (SCM_PROMPT_SETJMP (prompt))
{ {
/* The prompt exited nonlocally. Cache the regs back from the vp, and go /* The prompt exited nonlocally. Cache the regs back from the vp, and go
to the handler. to the handler.
Note, at this point, we must assume that any variable local to
vm_engine that can be assigned *has* been assigned. So we need to pull
all our state back from the ip/fp/sp.
*/ */
CACHE_REGISTER (); /* Really we only need SP. FP and IP should be CACHE_REGISTER ();
unmodified. */ program = SCM_FRAME_PROGRAM (fp);
ip += offset; CACHE_PROGRAM ();
NEXT; NEXT;
} }