1996-10-14 03:26:51 +00:00
|
|
|
|
/* Representation of stack frame debug information
|
* __scm.h, alist.c, async.c, async.h, backtrace.h, chars.c,
continuations.c, debug.c, debug.h, dynl-dl.c, dynl.c, dynl.h,
dynwind.c, dynwind.h, eq.c, error.c, error.h, eval.c, eval.h,
feature.c, filesys.c, filesys.h, fports.c, fports.h, gc.c, gc.h,
genio.c, genio.h, gh.h, gh_data.c, gsubr.c, gsubr.h, hash.c,
hashtab.c, init.c, init.h, ioext.c, ioext.h, kw.c, libguile.h,
list.c, list.h, load.c, load.h, mallocs.c, markers.c,
mit-pthreads.c, net_db.c, numbers.c, numbers.h, options.c,
ports.c, ports.h, posix.c, posix.h, print.c, print.h, procprop.c,
procprop.h, procs.c, procs.h, ramap.c, ramap.h, regex-posix.c,
regex-posix.h, root.c, root.h, scmsigs.c, scmsigs.h, script.c,
script.h, simpos.c, simpos.h, smob.c, smob.h, snarf.h, socket.c,
srcprop.c, stackchk.c, stackchk.h, stacks.c, stime.c, stime.h,
strings.c, strings.h, strports.c, struct.c, struct.h, symbols.c,
symbols.h, tags.h, threads.c, throw.h, unif.c, variable.c,
vectors.c, vectors.h, version.h, vports.c, weaks.c: Update
copyright years.
1998-10-19 21:36:50 +00:00
|
|
|
|
* Copyright (C) 1996,1997 Free Software Foundation
|
1996-10-14 03:26:51 +00:00
|
|
|
|
*
|
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
|
|
* any later version.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
*
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
|
* along with this software; see the file COPYING. If not, write to
|
1997-05-26 22:34:48 +00:00
|
|
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
|
|
|
|
* Boston, MA 02111-1307 USA
|
1996-10-14 03:26:51 +00:00
|
|
|
|
*
|
|
|
|
|
|
* As a special exception, the Free Software Foundation gives permission
|
|
|
|
|
|
* for additional uses of the text contained in its release of GUILE.
|
|
|
|
|
|
*
|
|
|
|
|
|
* The exception is that, if you link the GUILE library with other files
|
|
|
|
|
|
* to produce an executable, this does not by itself cause the
|
|
|
|
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
|
|
|
|
* Your use of that executable is in no way restricted on account of
|
|
|
|
|
|
* linking the GUILE library code into it.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This exception does not however invalidate any other reasons why
|
|
|
|
|
|
* the executable file might be covered by the GNU General Public License.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This exception applies only to the code released by the
|
|
|
|
|
|
* Free Software Foundation under the name GUILE. If you copy
|
|
|
|
|
|
* code from other Free Software Foundation releases into a copy of
|
|
|
|
|
|
* GUILE, as the General Public License permits, the exception does
|
|
|
|
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
|
|
|
|
* anyone as to the status of such modified files, you must delete
|
|
|
|
|
|
* this exception notice from them.
|
|
|
|
|
|
*
|
|
|
|
|
|
* If you write modifications of your own for GUILE, it is your choice
|
|
|
|
|
|
* whether to permit this exception to apply to your modifications.
|
|
|
|
|
|
* If you do not wish that, delete this exception notice.
|
|
|
|
|
|
*
|
|
|
|
|
|
* The author can be reached at djurfeldt@nada.kth.se
|
1997-05-26 22:34:48 +00:00
|
|
|
|
* Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN */
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include "_scm.h"
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
#include "continuations.h"
|
1996-10-14 20:27:14 +00:00
|
|
|
|
#include "struct.h"
|
1998-11-09 16:46:08 +00:00
|
|
|
|
#include "macros.h"
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
#include "stacks.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* {Frames and stacks}
|
|
|
|
|
|
*
|
|
|
|
|
|
* The debugging evaluator creates debug frames on the stack. These
|
|
|
|
|
|
* are linked from the innermost frame and outwards. The last frame
|
|
|
|
|
|
* created can always be accessed as SCM_LAST_DEBUG_FRAME.
|
|
|
|
|
|
* Continuations contain a pointer to the innermost debug frame on the
|
|
|
|
|
|
* continuation stack.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Each debug frame contains a set of flags and information about one
|
|
|
|
|
|
* or more stack frames. The case of multiple frames occurs due to
|
|
|
|
|
|
* tail recursion. The maximal number of stack frames which can be
|
|
|
|
|
|
* recorded in one debug frame can be set dynamically with the debug
|
|
|
|
|
|
* option FRAMES.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Stack frame information is of two types: eval information (the
|
|
|
|
|
|
* expression being evaluated and its environment) and apply
|
|
|
|
|
|
* information (the procedure being applied and its arguments). A
|
|
|
|
|
|
* stack frame normally corresponds to an eval/apply pair, but macros
|
|
|
|
|
|
* and special forms (which are implemented as macros in Guile) only
|
|
|
|
|
|
* have eval information and apply calls leads to apply only frames.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Since we want to record the total stack information and later
|
|
|
|
|
|
* manipulate this data at the scheme level in the debugger, we need
|
|
|
|
|
|
* to transform it into a new representation. In the following code
|
|
|
|
|
|
* section you'll find the functions implementing this data type.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Representation:
|
|
|
|
|
|
*
|
1996-10-17 23:32:25 +00:00
|
|
|
|
* The stack is represented as a struct with an id slot and a tail
|
|
|
|
|
|
* array of scm_info_frame structs.
|
1996-10-14 03:26:51 +00:00
|
|
|
|
*
|
|
|
|
|
|
* A frame is represented as a pair where the car contains a stack and
|
|
|
|
|
|
* the cdr an inum. The inum is an index to the first SCM value of
|
|
|
|
|
|
* the scm_info_frame struct.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Stacks
|
|
|
|
|
|
* Constructor
|
|
|
|
|
|
* make-stack
|
1996-10-17 23:32:25 +00:00
|
|
|
|
* Selectors
|
|
|
|
|
|
* stack-id
|
1996-10-14 03:26:51 +00:00
|
|
|
|
* stack-ref
|
|
|
|
|
|
* Inspector
|
|
|
|
|
|
* stack-length
|
|
|
|
|
|
*
|
|
|
|
|
|
* Frames
|
|
|
|
|
|
* Constructor
|
|
|
|
|
|
* last-stack-frame
|
|
|
|
|
|
* Selectors
|
|
|
|
|
|
* frame-number
|
|
|
|
|
|
* frame-source
|
|
|
|
|
|
* frame-procedure
|
|
|
|
|
|
* frame-arguments
|
|
|
|
|
|
* frame-previous
|
|
|
|
|
|
* frame-next
|
|
|
|
|
|
* Predicates
|
|
|
|
|
|
* frame-real?
|
|
|
|
|
|
* frame-procedure?
|
|
|
|
|
|
* frame-evaluating-args?
|
1996-10-17 23:32:25 +00:00
|
|
|
|
* frame-overflow? */
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Some auxiliary functions for reading debug frames off the stack.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
/* Stacks often contain pointers to other items on the stack; for
|
|
|
|
|
|
example, each scm_debug_frame structure contains a pointer to the
|
|
|
|
|
|
next frame out. When we capture a continuation, we copy the stack
|
|
|
|
|
|
into the heap, and just leave all the pointers unchanged. This
|
|
|
|
|
|
makes it simple to restore the continuation --- just copy the stack
|
|
|
|
|
|
back! However, if we retrieve a pointer from the heap copy to
|
|
|
|
|
|
another item that was originally on the stack, we have to add an
|
|
|
|
|
|
offset to the pointer to discover the new referent.
|
|
|
|
|
|
|
|
|
|
|
|
If PTR is a pointer retrieved from a continuation, whose original
|
|
|
|
|
|
target was on the stack, and OFFSET is the appropriate offset from
|
|
|
|
|
|
the original stack to the continuation, then RELOC_MUMBLE (PTR,
|
|
|
|
|
|
OFFSET) is a pointer to the copy in the continuation of the
|
|
|
|
|
|
original referent, cast to an scm_debug_MUMBLE *. */
|
|
|
|
|
|
#define RELOC_INFO(ptr, offset) \
|
|
|
|
|
|
((scm_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
|
|
|
|
|
|
#define RELOC_FRAME(ptr, offset) \
|
|
|
|
|
|
((scm_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
|
|
|
|
|
|
|
|
|
|
|
|
|
1996-10-14 03:26:51 +00:00
|
|
|
|
/* Count number of debug info frames on a stack, beginning with
|
|
|
|
|
|
* DFRAME. OFFSET is used for relocation of pointers when the stack
|
|
|
|
|
|
* is read from a continuation.
|
|
|
|
|
|
*/
|
1996-10-14 20:27:14 +00:00
|
|
|
|
static int stack_depth SCM_P ((scm_debug_frame *dframe, long offset, SCM *id, int *maxp));
|
1996-10-14 03:26:51 +00:00
|
|
|
|
static int
|
1996-10-14 20:27:14 +00:00
|
|
|
|
stack_depth (dframe, offset, id, maxp)
|
1996-10-14 03:26:51 +00:00
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
long offset;
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM *id;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
int *maxp;
|
|
|
|
|
|
{
|
|
|
|
|
|
int n, size;
|
|
|
|
|
|
int max_depth = SCM_BACKTRACE_MAXDEPTH;
|
|
|
|
|
|
scm_debug_info *info;
|
|
|
|
|
|
for (n = 0;
|
1996-10-14 20:27:14 +00:00
|
|
|
|
dframe && !SCM_VOIDFRAMEP (*dframe) && n < max_depth;
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (dframe->prev, offset))
|
1996-10-14 03:26:51 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (SCM_EVALFRAMEP (*dframe))
|
|
|
|
|
|
{
|
|
|
|
|
|
size = dframe->status & SCM_MAX_FRAME_SIZE;
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
info = RELOC_INFO (dframe->info, offset);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
n += (info - dframe->vect) / 2 + 1;
|
|
|
|
|
|
/* Data in the apply part of an eval info frame comes from previous
|
|
|
|
|
|
stack frame if the scm_debug_info vector is overflowed. */
|
|
|
|
|
|
if ((((info - dframe->vect) & 1) == 0)
|
|
|
|
|
|
&& SCM_OVERFLOWP (*dframe)
|
|
|
|
|
|
&& !SCM_UNBNDP (info[1].a.proc))
|
|
|
|
|
|
++n;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
++n;
|
|
|
|
|
|
}
|
1996-10-14 20:27:14 +00:00
|
|
|
|
if (dframe && SCM_VOIDFRAMEP (*dframe))
|
|
|
|
|
|
*id = dframe->vect[0].id;
|
|
|
|
|
|
else if (dframe)
|
1996-10-14 03:26:51 +00:00
|
|
|
|
*maxp = 1;
|
|
|
|
|
|
return n;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read debug info from DFRAME into IFRAME.
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void read_frame SCM_P ((scm_debug_frame *dframe, long offset, scm_info_frame *iframe));
|
|
|
|
|
|
static void
|
|
|
|
|
|
read_frame (dframe, offset, iframe)
|
|
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
long offset;
|
|
|
|
|
|
scm_info_frame *iframe;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM flags = SCM_INUM0;
|
|
|
|
|
|
int size;
|
|
|
|
|
|
scm_debug_info *info;
|
|
|
|
|
|
if (SCM_EVALFRAMEP (*dframe))
|
|
|
|
|
|
{
|
|
|
|
|
|
size = dframe->status & SCM_MAX_FRAME_SIZE;
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
info = RELOC_INFO (dframe->info, offset);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
if ((info - dframe->vect) & 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Debug.vect ends with apply info. */
|
|
|
|
|
|
--info;
|
|
|
|
|
|
if (info[1].a.proc != SCM_UNDEFINED)
|
|
|
|
|
|
{
|
|
|
|
|
|
flags |= SCM_FRAMEF_PROC;
|
|
|
|
|
|
iframe->proc = info[1].a.proc;
|
|
|
|
|
|
iframe->args = info[1].a.args;
|
|
|
|
|
|
if (!SCM_ARGS_READY_P (*dframe))
|
|
|
|
|
|
flags |= SCM_FRAMEF_EVAL_ARGS;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
1998-11-10 06:10:33 +00:00
|
|
|
|
iframe->source = scm_make_memoized (info[0].e.exp, info[0].e.env);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
flags |= SCM_FRAMEF_PROC;
|
|
|
|
|
|
iframe->proc = dframe->vect[0].a.proc;
|
|
|
|
|
|
iframe->args = dframe->vect[0].a.args;
|
|
|
|
|
|
}
|
|
|
|
|
|
iframe->flags = flags;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1998-11-10 07:57:51 +00:00
|
|
|
|
SCM_SYMBOL (scm_sym_apply, "apply");
|
|
|
|
|
|
|
|
|
|
|
|
/* Look up the first body form of the apply closure. We'll use this
|
|
|
|
|
|
below to prevent it from being displayed.
|
|
|
|
|
|
*/
|
|
|
|
|
|
static SCM
|
|
|
|
|
|
get_applybody ()
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM proc = SCM_CDR (scm_sym2vcell (scm_sym_apply, SCM_BOOL_F, SCM_BOOL_F));
|
|
|
|
|
|
if (SCM_NIMP (proc) && SCM_CLOSUREP (proc))
|
|
|
|
|
|
return SCM_CADR (SCM_CODE (proc));
|
|
|
|
|
|
else
|
|
|
|
|
|
return SCM_UNDEFINED;
|
|
|
|
|
|
}
|
1996-10-17 23:32:25 +00:00
|
|
|
|
|
|
|
|
|
|
#define NEXT_FRAME(iframe, n, quit) \
|
|
|
|
|
|
{ \
|
1998-11-10 07:57:51 +00:00
|
|
|
|
if (SCM_NIMP (iframe->source) \
|
|
|
|
|
|
&& SCM_MEMOIZED_EXP (iframe->source) == applybody) \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
iframe->source = SCM_BOOL_F; \
|
|
|
|
|
|
if (SCM_FALSEP (iframe->proc)) \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
--iframe; \
|
|
|
|
|
|
++n; \
|
|
|
|
|
|
} \
|
|
|
|
|
|
} \
|
1996-10-17 23:32:25 +00:00
|
|
|
|
++iframe; \
|
|
|
|
|
|
if (--n == 0) \
|
|
|
|
|
|
goto quit; \
|
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-11-10 07:57:51 +00:00
|
|
|
|
/* Fill the scm_info_frame vector IFRAME with data from N stack frames
|
|
|
|
|
|
* starting with the first stack frame represented by debug frame
|
|
|
|
|
|
* DFRAME.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
1998-11-09 16:46:08 +00:00
|
|
|
|
static int read_frames SCM_P ((scm_debug_frame *dframe, long offset, int nframes, scm_info_frame *iframes));
|
|
|
|
|
|
static int
|
1996-10-17 23:32:25 +00:00
|
|
|
|
read_frames (dframe, offset, n, iframes)
|
1996-10-14 03:26:51 +00:00
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
long offset;
|
|
|
|
|
|
int n;
|
|
|
|
|
|
scm_info_frame *iframes;
|
|
|
|
|
|
{
|
|
|
|
|
|
int size;
|
|
|
|
|
|
scm_info_frame *iframe = iframes;
|
|
|
|
|
|
scm_debug_info *info;
|
1998-11-10 07:57:51 +00:00
|
|
|
|
static SCM applybody = SCM_UNDEFINED;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
1998-11-10 07:57:51 +00:00
|
|
|
|
/* The value of applybody has to be setup after r4rs.scm has executed. */
|
|
|
|
|
|
if (SCM_UNBNDP (applybody))
|
|
|
|
|
|
applybody = get_applybody ();
|
1996-10-14 03:26:51 +00:00
|
|
|
|
for (;
|
1996-10-14 20:27:14 +00:00
|
|
|
|
dframe && !SCM_VOIDFRAMEP (*dframe) && n > 0;
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (dframe->prev, offset))
|
1996-10-14 03:26:51 +00:00
|
|
|
|
{
|
|
|
|
|
|
read_frame (dframe, offset, iframe);
|
|
|
|
|
|
if (SCM_EVALFRAMEP (*dframe))
|
|
|
|
|
|
{
|
1998-11-10 06:10:33 +00:00
|
|
|
|
/* If current frame is a macro during expansion, we should
|
|
|
|
|
|
skip the previously recorded macro transformer
|
|
|
|
|
|
application frame. */
|
|
|
|
|
|
if (SCM_MACROEXPP (*dframe) && iframe > iframes)
|
1998-11-09 16:46:08 +00:00
|
|
|
|
{
|
|
|
|
|
|
*(iframe - 1) = *iframe;
|
|
|
|
|
|
--iframe;
|
|
|
|
|
|
}
|
1996-10-14 03:26:51 +00:00
|
|
|
|
size = dframe->status & SCM_MAX_FRAME_SIZE;
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
info = RELOC_INFO (dframe->info, offset);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
if ((info - dframe->vect) & 1)
|
|
|
|
|
|
--info;
|
|
|
|
|
|
/* Data in the apply part of an eval info frame comes from
|
|
|
|
|
|
previous stack frame if the scm_debug_info vector is overflowed. */
|
|
|
|
|
|
else if (SCM_OVERFLOWP (*dframe)
|
|
|
|
|
|
&& !SCM_UNBNDP (info[1].a.proc))
|
|
|
|
|
|
{
|
1996-10-17 23:32:25 +00:00
|
|
|
|
NEXT_FRAME (iframe, n, quit);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
iframe->flags = SCM_INUM0 | SCM_FRAMEF_PROC;
|
|
|
|
|
|
iframe->proc = info[1].a.proc;
|
|
|
|
|
|
iframe->args = info[1].a.args;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (SCM_OVERFLOWP (*dframe))
|
|
|
|
|
|
iframe->flags |= SCM_FRAMEF_OVERFLOW;
|
|
|
|
|
|
info -= 2;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
NEXT_FRAME (iframe, n, quit);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
while (info >= dframe->vect)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!SCM_UNBNDP (info[1].a.proc))
|
|
|
|
|
|
{
|
|
|
|
|
|
iframe->flags = SCM_INUM0 | SCM_FRAMEF_PROC;
|
|
|
|
|
|
iframe->proc = info[1].a.proc;
|
|
|
|
|
|
iframe->args = info[1].a.args;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
iframe->flags = SCM_INUM0;
|
|
|
|
|
|
iframe->source = scm_make_memoized (info[0].e.exp,
|
|
|
|
|
|
info[0].e.env);
|
|
|
|
|
|
info -= 2;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
NEXT_FRAME (iframe, n, quit);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
1998-11-09 16:46:08 +00:00
|
|
|
|
else if (iframe->proc == scm_f_gsubr_apply)
|
|
|
|
|
|
/* Skip gsubr apply frames. */
|
|
|
|
|
|
continue;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
else
|
|
|
|
|
|
{
|
1996-10-17 23:32:25 +00:00
|
|
|
|
NEXT_FRAME (iframe, n, quit);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
quit:
|
|
|
|
|
|
if (iframe > iframes)
|
|
|
|
|
|
(iframe - 1) -> flags |= SCM_FRAMEF_REAL;
|
|
|
|
|
|
}
|
1998-11-09 16:46:08 +00:00
|
|
|
|
return iframe - iframes; /* Number of frames actually read */
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
1996-10-17 23:32:25 +00:00
|
|
|
|
static void narrow_stack SCM_P ((SCM stack, int inner, SCM inner_key, int outer, SCM outer_key));
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
narrow_stack (stack, inner, inner_key, outer, outer_key)
|
|
|
|
|
|
SCM stack;
|
|
|
|
|
|
int inner;
|
|
|
|
|
|
SCM inner_key;
|
|
|
|
|
|
int outer;
|
|
|
|
|
|
SCM outer_key;
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_stack *s = SCM_STACK (stack);
|
|
|
|
|
|
int i;
|
|
|
|
|
|
int n = s->length;
|
|
|
|
|
|
|
|
|
|
|
|
/* Cut inner part. */
|
|
|
|
|
|
for (i = 0; inner; --inner)
|
|
|
|
|
|
if (s->frames[i++].proc == inner_key)
|
|
|
|
|
|
break;
|
|
|
|
|
|
s->frames = &s->frames[i];
|
|
|
|
|
|
n -= i;
|
|
|
|
|
|
|
|
|
|
|
|
/* Cut outer part. */
|
|
|
|
|
|
for (; n && outer; --outer)
|
|
|
|
|
|
if (s->frames[--n].proc == outer_key)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
s->length = n;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Stacks
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM scm_stack_type;
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC (s_stack_p, "stack?", 1, 0, 0, scm_stack_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_stack_p (obj)
|
|
|
|
|
|
SCM obj;
|
|
|
|
|
|
{
|
|
|
|
|
|
return SCM_NIMP (obj) && SCM_STACKP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1996-11-02 20:54:19 +00:00
|
|
|
|
SCM_PROC (s_make_stack, "make-stack", 0, 0, 1, scm_make_stack);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
SCM
|
1996-11-02 20:54:19 +00:00
|
|
|
|
scm_make_stack (args)
|
|
|
|
|
|
SCM args;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
{
|
1996-10-17 23:32:25 +00:00
|
|
|
|
int n, maxp, size;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
scm_info_frame *iframe;
|
|
|
|
|
|
long offset = 0;
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM stack, id;
|
1996-11-02 20:54:19 +00:00
|
|
|
|
SCM obj, inner_cut, outer_cut;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
1997-08-14 15:00:03 +00:00
|
|
|
|
SCM_ASSERT (SCM_NIMP (args) && SCM_CONSP (args),
|
|
|
|
|
|
scm_makfrom0str (s_make_stack),
|
|
|
|
|
|
SCM_WNA,
|
|
|
|
|
|
NULL);
|
1996-11-02 20:54:19 +00:00
|
|
|
|
obj = SCM_CAR (args);
|
|
|
|
|
|
args = SCM_CDR (args);
|
|
|
|
|
|
|
|
|
|
|
|
/* Extract a pointer to the innermost frame of whatever object
|
|
|
|
|
|
scm_make_stack was given. */
|
1996-10-17 23:32:25 +00:00
|
|
|
|
if (obj == SCM_BOOL_T)
|
1996-10-14 03:26:51 +00:00
|
|
|
|
dframe = scm_last_debug_frame;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (obj), obj, SCM_ARG1, s_make_stack);
|
|
|
|
|
|
if (SCM_DEBUGOBJP (obj))
|
|
|
|
|
|
dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
|
|
|
|
|
|
else if (scm_tc7_contin == SCM_TYP7 (obj))
|
|
|
|
|
|
{
|
|
|
|
|
|
offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
|
|
|
|
|
|
- SCM_BASE (obj));
|
|
|
|
|
|
#ifndef STACK_GROWS_UP
|
|
|
|
|
|
offset += SCM_LENGTH (obj);
|
|
|
|
|
|
#endif
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
Give GCC more control flow information, so it can be sure that
variables aren't used uninitialized.
* error.h (scm_error, scm_syserror, scm_syserror_msg,
scm_sysmissing, scm_num_overflow, scm_out_of_range,
scm_wrong_num_args, scm_wrong_type_arg, scm_memory_error,
scm_misc_error): Tell GCC that these functions never return.
* struct.c (scm_struct_ref, scm_struct_set_x): If we can't figure
out the field type, call abort if SCM_ASSERT returns, to placate
the optimizer.
* stacks.c (scm_make_stack, scm_last_stack_frame): abort if
scm_wta ever returns. We can't handle this case anyway, and this
gives the optimizer more information.
* unif.c (scm_uniform_vector_ref, scm_array_set_x): Abort if
scm_wta ever returns.
1996-12-18 21:39:44 +00:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_wta (obj, (char *) SCM_ARG1, s_make_stack);
|
|
|
|
|
|
abort ();
|
|
|
|
|
|
}
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
1996-11-02 20:54:19 +00:00
|
|
|
|
/* Count number of frames. Also get stack id tag and check whether
|
|
|
|
|
|
there are more stackframes than we want to record
|
|
|
|
|
|
(SCM_BACKTRACE_MAXDEPTH). */
|
1996-10-14 20:27:14 +00:00
|
|
|
|
id = SCM_BOOL_F;
|
|
|
|
|
|
maxp = 0;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
n = stack_depth (dframe, offset, &id, &maxp);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
size = n * SCM_FRAME_N_SLOTS;
|
|
|
|
|
|
|
1996-11-02 20:54:19 +00:00
|
|
|
|
/* Make the stack object. */
|
1996-10-14 20:27:14 +00:00
|
|
|
|
stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (size), SCM_EOL);
|
|
|
|
|
|
SCM_STACK (stack) -> id = id;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
iframe = &SCM_STACK (stack) -> tail[0];
|
|
|
|
|
|
SCM_STACK (stack) -> frames = iframe;
|
|
|
|
|
|
|
1996-11-02 20:54:19 +00:00
|
|
|
|
/* Translate the current chain of stack frames into debugging information. */
|
1998-11-09 16:46:08 +00:00
|
|
|
|
n = read_frames (RELOC_FRAME (dframe, offset), offset, n, iframe);
|
|
|
|
|
|
SCM_STACK (stack) -> length = n;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
|
1996-11-02 20:54:19 +00:00
|
|
|
|
/* Narrow the stack according to the arguments given to scm_make_stack. */
|
|
|
|
|
|
while (n > 0 && SCM_NIMP (args) && SCM_CONSP (args))
|
|
|
|
|
|
{
|
|
|
|
|
|
inner_cut = SCM_CAR (args);
|
|
|
|
|
|
args = SCM_CDR (args);
|
|
|
|
|
|
if (SCM_NIMP (args) && SCM_CONSP (args))
|
|
|
|
|
|
{
|
|
|
|
|
|
outer_cut = SCM_CAR (args);
|
|
|
|
|
|
args = SCM_CDR (args);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
outer_cut = SCM_INUM0;
|
|
|
|
|
|
|
|
|
|
|
|
narrow_stack (stack,
|
|
|
|
|
|
SCM_INUMP (inner_cut) ? SCM_INUM (inner_cut) : n,
|
|
|
|
|
|
SCM_INUMP (inner_cut) ? 0 : inner_cut,
|
|
|
|
|
|
SCM_INUMP (outer_cut) ? SCM_INUM (outer_cut) : n,
|
|
|
|
|
|
SCM_INUMP (outer_cut) ? 0 : outer_cut);
|
|
|
|
|
|
|
|
|
|
|
|
n = SCM_STACK (stack) -> length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1996-10-17 23:32:25 +00:00
|
|
|
|
if (n > 0)
|
1996-11-02 20:54:19 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (maxp)
|
|
|
|
|
|
iframe[n - 1].flags |= SCM_FRAMEF_OVERFLOW;
|
|
|
|
|
|
return stack;
|
|
|
|
|
|
}
|
1996-10-17 23:32:25 +00:00
|
|
|
|
else
|
|
|
|
|
|
return SCM_BOOL_F;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM_PROC (s_stack_id, "stack-id", 1, 0, 0, scm_stack_id);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_stack_id (stack)
|
|
|
|
|
|
SCM stack;
|
|
|
|
|
|
{
|
1996-10-17 23:32:25 +00:00
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
long offset = 0;
|
|
|
|
|
|
if (stack == SCM_BOOL_T)
|
|
|
|
|
|
dframe = scm_last_debug_frame;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (stack), stack, SCM_ARG1, s_make_stack);
|
|
|
|
|
|
if (SCM_DEBUGOBJP (stack))
|
|
|
|
|
|
dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (stack);
|
|
|
|
|
|
else if (scm_tc7_contin == SCM_TYP7 (stack))
|
|
|
|
|
|
{
|
|
|
|
|
|
offset = ((SCM_STACKITEM *) (SCM_CHARS (stack) + sizeof (scm_contregs))
|
|
|
|
|
|
- SCM_BASE (stack));
|
|
|
|
|
|
#ifndef STACK_GROWS_UP
|
|
|
|
|
|
offset += SCM_LENGTH (stack);
|
|
|
|
|
|
#endif
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (SCM_DFRAME (stack), offset);
|
1996-10-17 23:32:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if (SCM_STACKP (stack))
|
|
|
|
|
|
return SCM_STACK (stack) -> id;
|
|
|
|
|
|
else scm_wrong_type_arg (s_stack_id, SCM_ARG1, stack);
|
|
|
|
|
|
}
|
|
|
|
|
|
while (dframe && !SCM_VOIDFRAMEP (*dframe))
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (dframe->prev, offset);
|
1996-10-17 23:32:25 +00:00
|
|
|
|
if (dframe && SCM_VOIDFRAMEP (*dframe))
|
|
|
|
|
|
return dframe->vect[0].id;
|
|
|
|
|
|
return SCM_BOOL_F;
|
1996-10-14 20:27:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC (s_stack_ref, "stack-ref", 2, 0, 0, scm_stack_ref);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
SCM
|
|
|
|
|
|
scm_stack_ref (stack, i)
|
|
|
|
|
|
SCM stack;
|
|
|
|
|
|
SCM i;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (stack)
|
|
|
|
|
|
&& SCM_STACKP (stack),
|
|
|
|
|
|
stack,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_stack_ref);
|
|
|
|
|
|
SCM_ASSERT (SCM_INUMP (i), i, SCM_ARG2, s_stack_ref);
|
|
|
|
|
|
SCM_ASSERT (SCM_INUM (i) >= 0
|
|
|
|
|
|
&& SCM_INUM (i) < SCM_STACK_LENGTH (stack),
|
|
|
|
|
|
i,
|
|
|
|
|
|
SCM_OUTOFRANGE,
|
|
|
|
|
|
s_stack_ref);
|
|
|
|
|
|
return scm_cons (stack, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_stack_length, "stack-length", 1, 0, 0, scm_stack_length);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_stack_length (stack)
|
|
|
|
|
|
SCM stack;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (stack)
|
|
|
|
|
|
&& SCM_STACKP (stack),
|
|
|
|
|
|
stack,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_stack_length);
|
|
|
|
|
|
return SCM_MAKINUM (SCM_STACK_LENGTH (stack));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Frames
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM_PROC (s_frame_p, "frame?", 1, 0, 0, scm_frame_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_p (obj)
|
|
|
|
|
|
SCM obj;
|
|
|
|
|
|
{
|
|
|
|
|
|
return SCM_NIMP (obj) && SCM_FRAMEP (obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1996-10-14 03:26:51 +00:00
|
|
|
|
SCM_PROC(s_last_stack_frame, "last-stack-frame", 1, 0, 0, scm_last_stack_frame);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_last_stack_frame (obj)
|
|
|
|
|
|
SCM obj;
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_debug_frame *dframe;
|
|
|
|
|
|
long offset = 0;
|
1996-10-17 23:32:25 +00:00
|
|
|
|
SCM stack;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (obj), obj, SCM_ARG1, s_last_stack_frame);
|
|
|
|
|
|
if (SCM_DEBUGOBJP (obj))
|
|
|
|
|
|
dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
|
|
|
|
|
|
else if (scm_tc7_contin == SCM_TYP7 (obj))
|
|
|
|
|
|
{
|
|
|
|
|
|
offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
|
|
|
|
|
|
- SCM_BASE (obj));
|
|
|
|
|
|
#ifndef STACK_GROWS_UP
|
|
|
|
|
|
offset += SCM_LENGTH (obj);
|
|
|
|
|
|
#endif
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
Give GCC more control flow information, so it can be sure that
variables aren't used uninitialized.
* error.h (scm_error, scm_syserror, scm_syserror_msg,
scm_sysmissing, scm_num_overflow, scm_out_of_range,
scm_wrong_num_args, scm_wrong_type_arg, scm_memory_error,
scm_misc_error): Tell GCC that these functions never return.
* struct.c (scm_struct_ref, scm_struct_set_x): If we can't figure
out the field type, call abort if SCM_ASSERT returns, to placate
the optimizer.
* stacks.c (scm_make_stack, scm_last_stack_frame): abort if
scm_wta ever returns. We can't handle this case anyway, and this
gives the optimizer more information.
* unif.c (scm_uniform_vector_ref, scm_array_set_x): Abort if
scm_wta ever returns.
1996-12-18 21:39:44 +00:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_wta (obj, (char *) SCM_ARG1, s_last_stack_frame);
|
|
|
|
|
|
abort ();
|
|
|
|
|
|
}
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
1996-10-14 20:27:14 +00:00
|
|
|
|
if (!dframe || SCM_VOIDFRAMEP (*dframe))
|
1996-10-14 03:26:51 +00:00
|
|
|
|
return SCM_BOOL_F;
|
|
|
|
|
|
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (SCM_FRAME_N_SLOTS),
|
|
|
|
|
|
SCM_EOL);
|
1996-10-17 23:32:25 +00:00
|
|
|
|
SCM_STACK (stack) -> length = 1;
|
|
|
|
|
|
SCM_STACK (stack) -> frames = &SCM_STACK (stack) -> tail[0];
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
read_frame (dframe, offset,
|
|
|
|
|
|
(scm_info_frame *) &SCM_STACK (stack) -> frames[0]);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
|
1996-10-17 23:32:25 +00:00
|
|
|
|
return scm_cons (stack, SCM_INUM0);;
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_number, "frame-number", 1, 0, 0, scm_frame_number);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_number (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_number);
|
|
|
|
|
|
return SCM_MAKINUM (SCM_FRAME_NUMBER (frame));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_source, "frame-source", 1, 0, 0, scm_frame_source);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_source (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_source);
|
|
|
|
|
|
return SCM_FRAME_SOURCE (frame);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_procedure, "frame-procedure", 1, 0, 0, scm_frame_procedure);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_procedure (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_procedure);
|
|
|
|
|
|
return (SCM_FRAME_PROC_P (frame)
|
1997-12-02 17:34:07 +00:00
|
|
|
|
? SCM_FRAME_PROC (frame)
|
|
|
|
|
|
: SCM_BOOL_F);
|
1996-10-14 03:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_arguments, "frame-arguments", 1, 0, 0, scm_frame_arguments);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_arguments (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_arguments);
|
|
|
|
|
|
return SCM_FRAME_ARGS (frame);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_previous, "frame-previous", 1, 0, 0, scm_frame_previous);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_previous (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
int n;
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_previous);
|
|
|
|
|
|
n = SCM_INUM (SCM_CDR (frame)) + 1;
|
|
|
|
|
|
if (n >= SCM_STACK_LENGTH (SCM_CAR (frame)))
|
|
|
|
|
|
return SCM_BOOL_F;
|
|
|
|
|
|
else
|
|
|
|
|
|
return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_next, "frame-next", 1, 0, 0, scm_frame_next);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_next (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
int n;
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_next);
|
|
|
|
|
|
n = SCM_INUM (SCM_CDR (frame)) - 1;
|
|
|
|
|
|
if (n < 0)
|
|
|
|
|
|
return SCM_BOOL_F;
|
|
|
|
|
|
else
|
|
|
|
|
|
return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_real_p, "frame-real?", 1, 0, 0, scm_frame_real_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_real_p (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_real_p);
|
|
|
|
|
|
return SCM_FRAME_REAL_P (frame) ? SCM_BOOL_T : SCM_BOOL_F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_procedure_p, "frame-procedure?", 1, 0, 0, scm_frame_procedure_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_procedure_p (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_procedure_p);
|
|
|
|
|
|
return SCM_FRAME_PROC_P (frame) ? SCM_BOOL_T : SCM_BOOL_F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_evaluating_args_p, "frame-evaluating-args?", 1, 0, 0, scm_frame_evaluating_args_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_evaluating_args_p (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_evaluating_args_p);
|
|
|
|
|
|
return SCM_FRAME_EVAL_ARGS_P (frame) ? SCM_BOOL_T : SCM_BOOL_F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_PROC(s_frame_overflow_p, "frame-overflow?", 1, 0, 0, scm_frame_overflow_p);
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_frame_overflow_p (frame)
|
|
|
|
|
|
SCM frame;
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_ASSERT (SCM_NIMP (frame) && SCM_FRAMEP (frame),
|
|
|
|
|
|
frame,
|
|
|
|
|
|
SCM_ARG1,
|
|
|
|
|
|
s_frame_overflow_p);
|
|
|
|
|
|
return SCM_FRAME_OVERFLOW_P (frame) ? SCM_BOOL_T : SCM_BOOL_F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_init_stacks ()
|
|
|
|
|
|
{
|
1996-10-14 20:27:14 +00:00
|
|
|
|
SCM vtable;
|
|
|
|
|
|
SCM vtable_layout = scm_make_struct_layout (scm_nullstr);
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
SCM stack_layout
|
|
|
|
|
|
= scm_make_struct_layout (scm_makfrom0str (SCM_STACK_LAYOUT));
|
1996-10-14 20:27:14 +00:00
|
|
|
|
vtable = scm_make_vtable_vtable (vtable_layout, SCM_INUM0, SCM_EOL);
|
Don't use GCC extensions to allocate space for debugging frames.
(Here he goes again! Why do we put up with this?!)
* debug.h (scm_debug_frame): Make the 'vect' member a pointer to
an scm_debug_info structure, not an in-line array of them. Add
'info' member, to say how many vect elements we've used, for eval
frames.
* eval.c (SCM_CEVAL): Use alloca to allocate space for vect. Use
a new variable debug_info_end to mark the end of vect, instead of
the address of the 'info' pointer itself.
[DEVAL] (ENTER_APPLY, SCM_CEVAL, SCM_APPLY): Remove casts of
&debug to scm_debug_frame *; debug is a real scm_debug_frame now.
(SCM_APPLY): Explicitly allocate space for debug.vect.
* debug.c (scm_m_start_stack): Same, for vframe.vect.
* stacks.c: Adjusted for new debug frame structure.
(RELOC_INFO, RELOC_FRAME): New macros.
(stack_depth, read_frames): Use them, and new scm_debug_frame
element 'info', instead of magically knowing that eval frames have
an info pointer sitting after vect.
(scm_make_stack, scm_stack_id, scm_last_stack_frame): Use
RELOC_FRAME.
(scm_init_stacks): Formatting tweaks.
1996-12-19 07:55:42 +00:00
|
|
|
|
scm_stack_type
|
|
|
|
|
|
= scm_permanent_object (scm_make_struct (vtable, SCM_INUM0,
|
|
|
|
|
|
scm_cons (stack_layout,
|
|
|
|
|
|
SCM_EOL)));
|
1996-10-14 03:26:51 +00:00
|
|
|
|
#include "stacks.x"
|
|
|
|
|
|
}
|