123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "libguile/_scm.h"
- #include "libguile/control.h"
- #include "libguile/eval.h"
- #include "libguile/debug.h"
- #include "libguile/continuations.h"
- #include "libguile/struct.h"
- #include "libguile/macros.h"
- #include "libguile/procprop.h"
- #include "libguile/modules.h"
- #include "libguile/root.h"
- #include "libguile/strings.h"
- #include "libguile/vm.h"
- #include "libguile/frames.h"
- #include "libguile/validate.h"
- #include "libguile/stacks.h"
- #include "libguile/private-options.h"
- static SCM scm_sys_stacks;
- static long
- stack_depth (enum scm_vm_frame_kind kind, const struct scm_frame *frame)
- {
- struct scm_frame tmp;
- long n = 1;
- memcpy (&tmp, frame, sizeof tmp);
- while (scm_c_frame_previous (kind, &tmp))
- ++n;
- return n;
- }
- static scm_t_ptrdiff
- find_prompt (SCM key)
- {
- scm_t_ptrdiff fp_offset;
- if (!scm_dynstack_find_prompt (&SCM_I_CURRENT_THREAD->dynstack, key,
- NULL, &fp_offset, NULL, NULL, NULL))
- scm_misc_error ("make-stack", "Prompt tag not found while narrowing stack",
- scm_list_1 (key));
- return fp_offset;
- }
- static long
- narrow_stack (long len, enum scm_vm_frame_kind kind, struct scm_frame *frame,
- SCM inner_cut, SCM outer_cut)
- {
-
- if (scm_is_true (scm_program_p (inner_cut)))
- {
- SCM addr_range = scm_program_address_range (inner_cut);
- if (scm_is_pair (addr_range))
- inner_cut = addr_range;
- }
- if (scm_is_true (scm_program_p (outer_cut)))
- {
- SCM addr_range = scm_program_address_range (outer_cut);
- if (scm_is_pair (addr_range))
- outer_cut = addr_range;
- }
-
- if (scm_is_true (scm_procedure_p (inner_cut)))
- {
-
- for (; len ;)
- {
- SCM proc = scm_c_frame_closure (kind, frame);
- len--;
- scm_c_frame_previous (kind, frame);
- if (scm_is_eq (proc, inner_cut))
- break;
- }
- }
- else if (scm_is_pair (inner_cut)
- && scm_is_integer (scm_car (inner_cut))
- && scm_is_integer (scm_cdr (inner_cut)))
- {
-
- scm_t_uintptr low_pc, high_pc, pc;
- low_pc = scm_to_uintptr_t (scm_car (inner_cut));
- high_pc = scm_to_uintptr_t (scm_cdr (inner_cut));
- for (; len ;)
- {
- pc = (scm_t_uintptr) frame->ip;
- len--;
- scm_c_frame_previous (kind, frame);
- if (low_pc <= pc && pc < high_pc)
- break;
- }
- }
- else if (scm_is_integer (inner_cut))
- {
-
- long inner = scm_to_int (inner_cut);
-
- for (; inner && len; --inner)
- {
- len--;
- scm_c_frame_previous (kind, frame);
- }
- }
- else
- {
-
- scm_t_ptrdiff fp_offset = find_prompt (inner_cut);
- for (; len; len--, scm_c_frame_previous (kind, frame))
- if (fp_offset == frame->fp_offset)
- break;
- }
-
- if (scm_is_true (scm_procedure_p (outer_cut)))
- {
- long i, new_len;
- struct scm_frame tmp;
- memcpy (&tmp, frame, sizeof tmp);
-
- for (new_len = i = 0; i < len; i++, scm_c_frame_previous (kind, &tmp))
- if (scm_is_eq (scm_c_frame_closure (kind, &tmp), outer_cut))
- new_len = i;
- len = new_len;
- }
- else if (scm_is_pair (outer_cut)
- && scm_is_integer (scm_car (outer_cut))
- && scm_is_integer (scm_cdr (outer_cut)))
- {
-
- scm_t_uintptr low_pc, high_pc, pc;
- long i, new_len;
- struct scm_frame tmp;
- low_pc = scm_to_uintptr_t (scm_car (outer_cut));
- high_pc = scm_to_uintptr_t (scm_cdr (outer_cut));
- memcpy (&tmp, frame, sizeof tmp);
-
- for (new_len = i = 0; i < len; i++, scm_c_frame_previous (kind, &tmp))
- {
- pc = (scm_t_uintptr) tmp.ip;
- if (low_pc <= pc && pc < high_pc)
- new_len = i;
- }
- len = new_len;
- }
- else if (scm_is_integer (outer_cut))
- {
-
- long outer = scm_to_int (outer_cut);
-
- if (outer < len)
- len -= outer;
- else
- len = 0;
- }
- else
- {
-
- long i;
- struct scm_frame tmp;
- scm_t_ptrdiff fp_offset = find_prompt (outer_cut);
- memcpy (&tmp, frame, sizeof tmp);
- for (i = 0; i < len; i++, scm_c_frame_previous (kind, &tmp))
- if (tmp.fp_offset == fp_offset)
- break;
- if (i < len)
- len = i;
- else
- len = 0;
- }
- return len;
- }
- SCM scm_stack_type;
- SCM_DEFINE (scm_stack_p, "stack?", 1, 0, 0,
- (SCM obj),
- "Return @code{#t} if @var{obj} is a calling stack.")
- #define FUNC_NAME s_scm_stack_p
- {
- return scm_from_bool(SCM_STACKP (obj));
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_make_stack, "make-stack", 1, 0, 1,
- (SCM obj, SCM args),
- "Create a new stack. If @var{obj} is @code{#t}, the current\n"
- "evaluation stack is used for creating the stack frames,\n"
- "otherwise the frames are taken from @var{obj} (which must be\n"
- "a continuation or a frame object).\n"
- "\n"
- "@var{args} should be a list containing any combination of\n"
- "integer, procedure, address range, prompt tag and @code{#t}\n"
- "values.\n"
- "\n"
- "These values specify various ways of cutting away uninteresting\n"
- "stack frames from the top and bottom of the stack that\n"
- "@code{make-stack} returns. They come in pairs like this:\n"
- "@code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2}\n"
- "@var{outer_cut_2} @dots{})}.\n"
- "\n"
- "Each @var{inner_cut_i} can be an integer, a procedure, an\n"
- "address range, or a prompt tag. An integer means to cut away\n"
- "exactly that number of frames. A procedure means to cut\n"
- "away all frames up to but excluding the frame whose procedure\n"
- "matches the specified one. An address range is a pair of\n"
- "integers indicating the low and high addresses of a procedure's\n"
- "code, and is the same as cutting away to a procedure (though\n"
- "with less work). Anything else is interpreted as a prompt tag\n"
- "which cuts away all frames that are inside a prompt with the\n"
- "given tag.\n"
- "\n"
- "Each @var{outer_cut_i} can be an integer, a procedure, an\n"
- "address range, or a prompt tag. An integer means to cut away\n"
- "that number of frames. A procedure means to cut away frames\n"
- "down to but excluding the frame whose procedure matches the\n"
- "specified one. An address range is the same, but with the\n"
- "procedure's code specified as an address range. Anything else\n"
- "is taken to be a prompt tag, which cuts away all frames that are\n"
- "outside a prompt with the given tag.\n"
- "\n"
- "If the @var{outer_cut_i} of the last pair is missing, it is\n"
- "taken as 0.")
- #define FUNC_NAME s_scm_make_stack
- {
- long n;
- SCM inner_cut, outer_cut;
- enum scm_vm_frame_kind kind;
- struct scm_frame frame;
-
- if (scm_is_eq (obj, SCM_BOOL_T))
- {
- SCM cont;
- struct scm_vm_cont *c;
- union scm_vm_stack_element *stack_top;
- cont = scm_i_capture_current_stack ();
- c = SCM_VM_CONT_DATA (cont);
-
- stack_top = c->stack_bottom + c->stack_size;
- kind = SCM_VM_FRAME_KIND_CONT;
- frame.stack_holder = c;
- frame.fp_offset = stack_top - (c->fp + c->reloc);
- frame.sp_offset = c->stack_size;
- frame.ip = c->ra;
- }
- else if (SCM_VM_FRAME_P (obj))
- {
- kind = SCM_VM_FRAME_KIND (obj);
- memcpy (&frame, SCM_VM_FRAME_DATA (obj), sizeof frame);
- }
- else if (SCM_CONTINUATIONP (obj))
-
- {
- kind = SCM_VM_FRAME_KIND_CONT;
- if (!scm_i_continuation_to_frame (obj, &frame))
- return SCM_BOOL_F;
- }
- else if (SCM_PROGRAM_P (obj) && SCM_PROGRAM_IS_PARTIAL_CONTINUATION (obj))
- {
- kind = SCM_VM_FRAME_KIND_CONT;
- if (!scm_i_vm_cont_to_frame (SCM_PROGRAM_FREE_VARIABLE_REF (obj, 0),
- &frame))
- return SCM_BOOL_F;
- }
- else
- {
- SCM_WRONG_TYPE_ARG (SCM_ARG1, obj);
-
- }
-
- if (SCM_PROGRAM_P (scm_c_frame_closure (kind, &frame))
- && SCM_PROGRAM_IS_BOOT (scm_c_frame_closure (kind, &frame))
- && !scm_c_frame_previous (kind, &frame))
- return SCM_BOOL_F;
-
- n = stack_depth (kind, &frame);
-
- SCM_VALIDATE_REST_ARGUMENT (args);
- while (n > 0 && !scm_is_null (args))
- {
- inner_cut = SCM_CAR (args);
- args = SCM_CDR (args);
- if (scm_is_null (args))
- {
- outer_cut = SCM_INUM0;
- }
- else
- {
- outer_cut = SCM_CAR (args);
- args = SCM_CDR (args);
- }
-
- n = narrow_stack (n, kind, &frame, inner_cut, outer_cut);
- }
-
- if (n > 0)
- {
-
- SCM stack = scm_make_struct (scm_stack_type, SCM_INUM0, SCM_EOL);
- SCM_SET_STACK_LENGTH (stack, n);
- SCM_SET_STACK_ID (stack, scm_stack_id (obj));
- SCM_SET_STACK_FRAME (stack, scm_c_make_frame (kind, &frame));
- return stack;
- }
- else
- return SCM_BOOL_F;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_stack_id, "stack-id", 1, 0, 0,
- (SCM stack),
- "Return the identifier given to @var{stack} by @code{start-stack}.")
- #define FUNC_NAME s_scm_stack_id
- {
- if (scm_is_eq (stack, SCM_BOOL_T)
-
- || SCM_VM_FRAME_P (stack))
- {
-
- SCM stacks = scm_fluid_ref (scm_sys_stacks);
- return scm_is_pair (stacks) ? scm_caar (stacks) : SCM_BOOL_F;
- }
- else if (SCM_CONTINUATIONP (stack))
-
- return SCM_BOOL_F;
- else if (SCM_PROGRAM_P (stack) && SCM_PROGRAM_IS_PARTIAL_CONTINUATION (stack))
-
- return SCM_BOOL_F;
- else
- {
- SCM_WRONG_TYPE_ARG (SCM_ARG1, stack);
-
- }
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_stack_ref, "stack-ref", 2, 0, 0,
- (SCM stack, SCM index),
- "Return the @var{index}'th frame from @var{stack}.")
- #define FUNC_NAME s_scm_stack_ref
- {
- unsigned long int c_index;
- SCM frame;
- SCM_VALIDATE_STACK (1, stack);
- c_index = scm_to_unsigned_integer (index, 0, SCM_STACK_LENGTH(stack)-1);
- frame = SCM_STACK_FRAME (stack);
- while (c_index--)
- frame = scm_frame_previous (frame);
- return frame;
- }
- #undef FUNC_NAME
- SCM_DEFINE (scm_stack_length, "stack-length", 1, 0, 0,
- (SCM stack),
- "Return the length of @var{stack}.")
- #define FUNC_NAME s_scm_stack_length
- {
- SCM_VALIDATE_STACK (1, stack);
- return scm_from_long (SCM_STACK_LENGTH (stack));
- }
- #undef FUNC_NAME
- void
- scm_init_stacks ()
- {
- scm_sys_stacks = scm_make_fluid ();
- scm_c_define ("%stacks", scm_sys_stacks);
-
- scm_stack_type = scm_make_vtable (scm_from_locale_string (SCM_STACK_LAYOUT),
- SCM_UNDEFINED);
- scm_set_struct_vtable_name_x (scm_stack_type,
- scm_from_latin1_symbol ("stack"));
- #include "libguile/stacks.x"
- }
|