* __scm.h: Added SCM_DEBUG as default debug option.
[bpt/guile.git] / libguile / stacks.c
CommitLineData
782d171c 1/* Representation of stack frame debug information
7dc6e754 2 * Copyright (C) 1996,1997 Free Software Foundation
782d171c
MD
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; see the file COPYING. If not, write to
82892bed
JB
16 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307 USA
782d171c
MD
18 *
19 * As a special exception, the Free Software Foundation gives permission
20 * for additional uses of the text contained in its release of GUILE.
21 *
22 * The exception is that, if you link the GUILE library with other files
23 * to produce an executable, this does not by itself cause the
24 * resulting executable to be covered by the GNU General Public License.
25 * Your use of that executable is in no way restricted on account of
26 * linking the GUILE library code into it.
27 *
28 * This exception does not however invalidate any other reasons why
29 * the executable file might be covered by the GNU General Public License.
30 *
31 * This exception applies only to the code released by the
32 * Free Software Foundation under the name GUILE. If you copy
33 * code from other Free Software Foundation releases into a copy of
34 * GUILE, as the General Public License permits, the exception does
35 * not apply to the code that you add in this way. To avoid misleading
36 * anyone as to the status of such modified files, you must delete
37 * this exception notice from them.
38 *
39 * If you write modifications of your own for GUILE, it is your choice
40 * whether to permit this exception to apply to your modifications.
41 * If you do not wish that, delete this exception notice.
42 *
43 * The author can be reached at djurfeldt@nada.kth.se
82892bed 44 * Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN */
1bbd0b84
GB
45
46/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
47 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
48
782d171c
MD
49\f
50
51#include <stdio.h>
a0599745
MD
52#include "libguile/_scm.h"
53#include "libguile/eval.h"
54#include "libguile/debug.h"
55#include "libguile/continuations.h"
56#include "libguile/struct.h"
57#include "libguile/macros.h"
58#include "libguile/procprop.h"
59#include "libguile/modules.h"
60#include "libguile/root.h"
61#include "libguile/strings.h"
62
63#include "libguile/validate.h"
64#include "libguile/stacks.h"
782d171c
MD
65
66\f
67/* {Frames and stacks}
68 *
69 * The debugging evaluator creates debug frames on the stack. These
70 * are linked from the innermost frame and outwards. The last frame
71 * created can always be accessed as SCM_LAST_DEBUG_FRAME.
72 * Continuations contain a pointer to the innermost debug frame on the
73 * continuation stack.
74 *
75 * Each debug frame contains a set of flags and information about one
76 * or more stack frames. The case of multiple frames occurs due to
77 * tail recursion. The maximal number of stack frames which can be
78 * recorded in one debug frame can be set dynamically with the debug
79 * option FRAMES.
80 *
81 * Stack frame information is of two types: eval information (the
82 * expression being evaluated and its environment) and apply
83 * information (the procedure being applied and its arguments). A
84 * stack frame normally corresponds to an eval/apply pair, but macros
85 * and special forms (which are implemented as macros in Guile) only
86 * have eval information and apply calls leads to apply only frames.
87 *
88 * Since we want to record the total stack information and later
89 * manipulate this data at the scheme level in the debugger, we need
90 * to transform it into a new representation. In the following code
91 * section you'll find the functions implementing this data type.
92 *
93 * Representation:
94 *
7115d1e4
MD
95 * The stack is represented as a struct with an id slot and a tail
96 * array of scm_info_frame structs.
782d171c
MD
97 *
98 * A frame is represented as a pair where the car contains a stack and
99 * the cdr an inum. The inum is an index to the first SCM value of
100 * the scm_info_frame struct.
101 *
102 * Stacks
103 * Constructor
104 * make-stack
7115d1e4
MD
105 * Selectors
106 * stack-id
782d171c
MD
107 * stack-ref
108 * Inspector
109 * stack-length
110 *
111 * Frames
112 * Constructor
113 * last-stack-frame
114 * Selectors
115 * frame-number
116 * frame-source
117 * frame-procedure
118 * frame-arguments
119 * frame-previous
120 * frame-next
121 * Predicates
122 * frame-real?
123 * frame-procedure?
124 * frame-evaluating-args?
7115d1e4 125 * frame-overflow? */
782d171c
MD
126
127\f
128
129/* Some auxiliary functions for reading debug frames off the stack.
130 */
131
c0ab1b8d
JB
132/* Stacks often contain pointers to other items on the stack; for
133 example, each scm_debug_frame structure contains a pointer to the
134 next frame out. When we capture a continuation, we copy the stack
135 into the heap, and just leave all the pointers unchanged. This
136 makes it simple to restore the continuation --- just copy the stack
137 back! However, if we retrieve a pointer from the heap copy to
138 another item that was originally on the stack, we have to add an
139 offset to the pointer to discover the new referent.
140
141 If PTR is a pointer retrieved from a continuation, whose original
142 target was on the stack, and OFFSET is the appropriate offset from
143 the original stack to the continuation, then RELOC_MUMBLE (PTR,
144 OFFSET) is a pointer to the copy in the continuation of the
145 original referent, cast to an scm_debug_MUMBLE *. */
146#define RELOC_INFO(ptr, offset) \
147 ((scm_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
148#define RELOC_FRAME(ptr, offset) \
149 ((scm_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
150
151
782d171c
MD
152/* Count number of debug info frames on a stack, beginning with
153 * DFRAME. OFFSET is used for relocation of pointers when the stack
154 * is read from a continuation.
155 */
782d171c 156static int
1bbd0b84 157stack_depth (scm_debug_frame *dframe,long offset,SCM *id,int *maxp)
782d171c 158{
ab66ae47 159 int n;
782d171c 160 int max_depth = SCM_BACKTRACE_MAXDEPTH;
782d171c 161 for (n = 0;
66f45472 162 dframe && !SCM_VOIDFRAMEP (*dframe) && n < max_depth;
c0ab1b8d 163 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
164 {
165 if (SCM_EVALFRAMEP (*dframe))
166 {
ab66ae47 167 scm_debug_info * info = RELOC_INFO (dframe->info, offset);
782d171c
MD
168 n += (info - dframe->vect) / 2 + 1;
169 /* Data in the apply part of an eval info frame comes from previous
170 stack frame if the scm_debug_info vector is overflowed. */
171 if ((((info - dframe->vect) & 1) == 0)
172 && SCM_OVERFLOWP (*dframe)
173 && !SCM_UNBNDP (info[1].a.proc))
174 ++n;
175 }
176 else
177 ++n;
178 }
66f45472
MD
179 if (dframe && SCM_VOIDFRAMEP (*dframe))
180 *id = dframe->vect[0].id;
181 else if (dframe)
782d171c
MD
182 *maxp = 1;
183 return n;
184}
185
186/* Read debug info from DFRAME into IFRAME.
187 */
782d171c 188static void
1bbd0b84 189read_frame (scm_debug_frame *dframe,long offset,scm_info_frame *iframe)
782d171c 190{
f1267706 191 scm_bits_t flags = SCM_UNPACK (SCM_INUM0); /* UGh. */
782d171c
MD
192 if (SCM_EVALFRAMEP (*dframe))
193 {
ab66ae47 194 scm_debug_info * info = RELOC_INFO (dframe->info, offset);
782d171c
MD
195 if ((info - dframe->vect) & 1)
196 {
197 /* Debug.vect ends with apply info. */
198 --info;
54778cd3 199 if (!SCM_UNBNDP (info[1].a.proc))
782d171c
MD
200 {
201 flags |= SCM_FRAMEF_PROC;
202 iframe->proc = info[1].a.proc;
203 iframe->args = info[1].a.args;
204 if (!SCM_ARGS_READY_P (*dframe))
205 flags |= SCM_FRAMEF_EVAL_ARGS;
206 }
207 }
6629eb1c 208 iframe->source = scm_make_memoized (info[0].e.exp, info[0].e.env);
782d171c
MD
209 }
210 else
211 {
212 flags |= SCM_FRAMEF_PROC;
213 iframe->proc = dframe->vect[0].a.proc;
214 iframe->args = dframe->vect[0].a.args;
215 }
216 iframe->flags = flags;
217}
218
7a13c3ae
MD
219/* Look up the first body form of the apply closure. We'll use this
220 below to prevent it from being displayed.
221*/
222static SCM
223get_applybody ()
224{
225 SCM proc = SCM_CDR (scm_sym2vcell (scm_sym_apply, SCM_BOOL_F, SCM_BOOL_F));
0c95b57d 226 if (SCM_CLOSUREP (proc))
7a13c3ae
MD
227 return SCM_CADR (SCM_CODE (proc));
228 else
229 return SCM_UNDEFINED;
230}
7115d1e4
MD
231
232#define NEXT_FRAME(iframe, n, quit) \
d3a6bc94 233do { \
7a13c3ae 234 if (SCM_NIMP (iframe->source) \
54778cd3 235 && SCM_EQ_P (SCM_MEMOIZED_EXP (iframe->source), applybody)) \
7a13c3ae
MD
236 { \
237 iframe->source = SCM_BOOL_F; \
238 if (SCM_FALSEP (iframe->proc)) \
239 { \
240 --iframe; \
241 ++n; \
242 } \
243 } \
7115d1e4
MD
244 ++iframe; \
245 if (--n == 0) \
246 goto quit; \
d3a6bc94 247} while (0)
7115d1e4
MD
248
249
7a13c3ae
MD
250/* Fill the scm_info_frame vector IFRAME with data from N stack frames
251 * starting with the first stack frame represented by debug frame
252 * DFRAME.
253 */
254
7c939801 255static int
1bbd0b84 256read_frames (scm_debug_frame *dframe,long offset,int n,scm_info_frame *iframes)
782d171c 257{
782d171c
MD
258 scm_info_frame *iframe = iframes;
259 scm_debug_info *info;
7a13c3ae 260 static SCM applybody = SCM_UNDEFINED;
782d171c 261
7a13c3ae
MD
262 /* The value of applybody has to be setup after r4rs.scm has executed. */
263 if (SCM_UNBNDP (applybody))
264 applybody = get_applybody ();
782d171c 265 for (;
66f45472 266 dframe && !SCM_VOIDFRAMEP (*dframe) && n > 0;
c0ab1b8d 267 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
268 {
269 read_frame (dframe, offset, iframe);
270 if (SCM_EVALFRAMEP (*dframe))
271 {
6629eb1c
MD
272 /* If current frame is a macro during expansion, we should
273 skip the previously recorded macro transformer
274 application frame. */
275 if (SCM_MACROEXPP (*dframe) && iframe > iframes)
7c939801
MD
276 {
277 *(iframe - 1) = *iframe;
278 --iframe;
279 }
c0ab1b8d 280 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
281 if ((info - dframe->vect) & 1)
282 --info;
283 /* Data in the apply part of an eval info frame comes from
284 previous stack frame if the scm_debug_info vector is overflowed. */
285 else if (SCM_OVERFLOWP (*dframe)
286 && !SCM_UNBNDP (info[1].a.proc))
287 {
7115d1e4 288 NEXT_FRAME (iframe, n, quit);
f1267706 289 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
290 iframe->proc = info[1].a.proc;
291 iframe->args = info[1].a.args;
292 }
293 if (SCM_OVERFLOWP (*dframe))
294 iframe->flags |= SCM_FRAMEF_OVERFLOW;
295 info -= 2;
7115d1e4 296 NEXT_FRAME (iframe, n, quit);
782d171c
MD
297 while (info >= dframe->vect)
298 {
299 if (!SCM_UNBNDP (info[1].a.proc))
300 {
f1267706 301 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
302 iframe->proc = info[1].a.proc;
303 iframe->args = info[1].a.args;
304 }
305 else
f1267706 306 iframe->flags = SCM_UNPACK (SCM_INUM0);
782d171c
MD
307 iframe->source = scm_make_memoized (info[0].e.exp,
308 info[0].e.env);
309 info -= 2;
7115d1e4 310 NEXT_FRAME (iframe, n, quit);
782d171c
MD
311 }
312 }
54778cd3 313 else if (SCM_EQ_P (iframe->proc, scm_f_gsubr_apply))
7c939801
MD
314 /* Skip gsubr apply frames. */
315 continue;
782d171c
MD
316 else
317 {
7115d1e4 318 NEXT_FRAME (iframe, n, quit);
782d171c
MD
319 }
320 quit:
321 if (iframe > iframes)
322 (iframe - 1) -> flags |= SCM_FRAMEF_REAL;
323 }
7c939801 324 return iframe - iframes; /* Number of frames actually read */
782d171c
MD
325}
326
c3a6c6f9
MD
327/* Narrow STACK by cutting away stackframes (mutatingly).
328 *
329 * Inner frames (most recent) are cut by advancing the frames pointer.
330 * Outer frames are cut by decreasing the recorded length.
331 *
332 * Cut maximally INNER inner frames and OUTER outer frames using
333 * the keys INNER_KEY and OUTER_KEY.
334 *
335 * Frames are cut away starting at the end points and moving towards
336 * the center of the stack. The key is normally compared to the
337 * operator in application frames. Frames up to and including the key
338 * are cut.
339 *
340 * If INNER_KEY is #t a different scheme is used for inner frames:
341 *
342 * Frames up to but excluding the first source frame originating from
343 * a user module are cut, except for possible application frames
344 * between the user frame and the last system frame previously
345 * encountered.
346 */
347
7115d1e4 348static void
1bbd0b84 349narrow_stack (SCM stack,int inner,SCM inner_key,int outer,SCM outer_key)
7115d1e4
MD
350{
351 scm_stack *s = SCM_STACK (stack);
352 int i;
353 int n = s->length;
354
355 /* Cut inner part. */
54778cd3 356 if (SCM_TRUE_P (inner_key))
c3a6c6f9
MD
357 /* Cut all frames up to user module code */
358 {
359 for (i = 0; inner; ++i, --inner)
360 {
361 SCM m = s->frames[i].source;
368cf54d 362 if ( SCM_MEMOIZEDP (m)
c3a6c6f9
MD
363 && SCM_NIMP (SCM_MEMOIZED_ENV (m))
364 && SCM_FALSEP (scm_system_module_env_p (SCM_MEMOIZED_ENV (m))))
365 {
366 /* Back up in order to include any non-source frames */
367 while (i > 0
368cf54d 368 && !((m = s->frames[i - 1].source, SCM_MEMOIZEDP (m))
c3a6c6f9
MD
369 || (SCM_NIMP (m = s->frames[i - 1].proc)
370 && SCM_NFALSEP (scm_procedure_p (m))
371 && SCM_NFALSEP (scm_procedure_property
372 (m, scm_sym_system_procedure)))))
373 {
374 --i;
375 ++inner;
376 }
377 break;
378 }
379 }
380 }
381 else
382 /* Use standard cutting procedure. */
383 {
384 for (i = 0; inner; --inner)
fee7ef83 385 if (SCM_EQ_P (s->frames[i++].proc, inner_key))
c3a6c6f9
MD
386 break;
387 }
7115d1e4
MD
388 s->frames = &s->frames[i];
389 n -= i;
390
391 /* Cut outer part. */
392 for (; n && outer; --outer)
fee7ef83 393 if (SCM_EQ_P (s->frames[--n].proc, outer_key))
7115d1e4
MD
394 break;
395
396 s->length = n;
397}
398
782d171c
MD
399\f
400
401/* Stacks
402 */
403
66f45472
MD
404SCM scm_stack_type;
405
a1ec6916 406SCM_DEFINE (scm_stack_p, "stack?", 1, 0, 0,
1bbd0b84 407 (SCM obj),
b380b885 408 "Return @code{#t} if @var{obj} is a calling stack.")
1bbd0b84 409#define FUNC_NAME s_scm_stack_p
66f45472 410{
0c95b57d 411 return SCM_BOOL(SCM_STACKP (obj));
66f45472 412}
1bbd0b84 413#undef FUNC_NAME
66f45472 414
a1ec6916 415SCM_DEFINE (scm_make_stack, "make-stack", 0, 0, 1,
1bbd0b84 416 (SCM args),
b380b885 417 "")
1bbd0b84 418#define FUNC_NAME s_scm_make_stack
782d171c 419{
7115d1e4 420 int n, maxp, size;
25748c78 421 scm_debug_frame *dframe = scm_last_debug_frame;
782d171c
MD
422 scm_info_frame *iframe;
423 long offset = 0;
66f45472 424 SCM stack, id;
f6f88e0d 425 SCM obj, inner_cut, outer_cut;
782d171c 426
0c95b57d 427 SCM_ASSERT (SCM_CONSP (args),
1bbd0b84 428 SCM_FUNC_NAME, SCM_WNA, NULL);
f6f88e0d
MD
429 obj = SCM_CAR (args);
430 args = SCM_CDR (args);
431
432 /* Extract a pointer to the innermost frame of whatever object
433 scm_make_stack was given. */
25748c78
GB
434 /* just use dframe == scm_last_debug_frame
435 (from initialization of dframe, above) if obj is #t */
54778cd3 436 if (!SCM_TRUE_P (obj))
782d171c 437 {
1bbd0b84 438 SCM_ASSERT (SCM_NIMP (obj), obj, SCM_ARG1, FUNC_NAME);
782d171c
MD
439 if (SCM_DEBUGOBJP (obj))
440 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
441 else if (scm_tc7_contin == SCM_TYP7 (obj))
442 {
443 offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
444 - SCM_BASE (obj));
445#ifndef STACK_GROWS_UP
446 offset += SCM_LENGTH (obj);
447#endif
c0ab1b8d 448 dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
782d171c 449 }
3323ad08
JB
450 else
451 {
5d2d2ffc 452 SCM_WTA (SCM_ARG1, obj);
3323ad08
JB
453 abort ();
454 }
782d171c
MD
455 }
456
f6f88e0d
MD
457 /* Count number of frames. Also get stack id tag and check whether
458 there are more stackframes than we want to record
459 (SCM_BACKTRACE_MAXDEPTH). */
66f45472
MD
460 id = SCM_BOOL_F;
461 maxp = 0;
7115d1e4 462 n = stack_depth (dframe, offset, &id, &maxp);
782d171c
MD
463 size = n * SCM_FRAME_N_SLOTS;
464
f6f88e0d 465 /* Make the stack object. */
66f45472
MD
466 stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (size), SCM_EOL);
467 SCM_STACK (stack) -> id = id;
7115d1e4
MD
468 iframe = &SCM_STACK (stack) -> tail[0];
469 SCM_STACK (stack) -> frames = iframe;
7115d1e4 470
f6f88e0d 471 /* Translate the current chain of stack frames into debugging information. */
7c939801
MD
472 n = read_frames (RELOC_FRAME (dframe, offset), offset, n, iframe);
473 SCM_STACK (stack) -> length = n;
7115d1e4 474
f6f88e0d 475 /* Narrow the stack according to the arguments given to scm_make_stack. */
0c95b57d 476 while (n > 0 && SCM_CONSP (args))
f6f88e0d
MD
477 {
478 inner_cut = SCM_CAR (args);
479 args = SCM_CDR (args);
0c95b57d 480 if (SCM_CONSP (args))
f6f88e0d
MD
481 {
482 outer_cut = SCM_CAR (args);
483 args = SCM_CDR (args);
484 }
485 else
486 outer_cut = SCM_INUM0;
487
488 narrow_stack (stack,
489 SCM_INUMP (inner_cut) ? SCM_INUM (inner_cut) : n,
490 SCM_INUMP (inner_cut) ? 0 : inner_cut,
491 SCM_INUMP (outer_cut) ? SCM_INUM (outer_cut) : n,
492 SCM_INUMP (outer_cut) ? 0 : outer_cut);
493
494 n = SCM_STACK (stack) -> length;
495 }
496
7115d1e4 497 if (n > 0)
f6f88e0d
MD
498 {
499 if (maxp)
500 iframe[n - 1].flags |= SCM_FRAMEF_OVERFLOW;
501 return stack;
502 }
7115d1e4
MD
503 else
504 return SCM_BOOL_F;
782d171c 505}
1bbd0b84 506#undef FUNC_NAME
782d171c 507
a1ec6916 508SCM_DEFINE (scm_stack_id, "stack-id", 1, 0, 0,
1bbd0b84 509 (SCM stack),
b380b885 510 "Return the identifier given to @var{stack} by @code{start-stack}.")
1bbd0b84 511#define FUNC_NAME s_scm_stack_id
66f45472 512{
7115d1e4
MD
513 scm_debug_frame *dframe;
514 long offset = 0;
54778cd3 515 if (SCM_TRUE_P (stack))
7115d1e4
MD
516 dframe = scm_last_debug_frame;
517 else
518 {
6b5a304f 519 SCM_VALIDATE_NIM (1,stack);
7115d1e4
MD
520 if (SCM_DEBUGOBJP (stack))
521 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (stack);
522 else if (scm_tc7_contin == SCM_TYP7 (stack))
523 {
524 offset = ((SCM_STACKITEM *) (SCM_CHARS (stack) + sizeof (scm_contregs))
525 - SCM_BASE (stack));
526#ifndef STACK_GROWS_UP
527 offset += SCM_LENGTH (stack);
528#endif
c0ab1b8d 529 dframe = RELOC_FRAME (SCM_DFRAME (stack), offset);
7115d1e4
MD
530 }
531 else if (SCM_STACKP (stack))
532 return SCM_STACK (stack) -> id;
c3a6c6f9 533 else
1bbd0b84 534 SCM_WRONG_TYPE_ARG (1, stack);
7115d1e4
MD
535 }
536 while (dframe && !SCM_VOIDFRAMEP (*dframe))
c0ab1b8d 537 dframe = RELOC_FRAME (dframe->prev, offset);
7115d1e4
MD
538 if (dframe && SCM_VOIDFRAMEP (*dframe))
539 return dframe->vect[0].id;
540 return SCM_BOOL_F;
66f45472 541}
1bbd0b84 542#undef FUNC_NAME
66f45472 543
a1ec6916 544SCM_DEFINE (scm_stack_ref, "stack-ref", 2, 0, 0,
1bbd0b84 545 (SCM stack, SCM i),
b380b885 546 "")
1bbd0b84 547#define FUNC_NAME s_scm_stack_ref
782d171c 548{
3b3b36dd
GB
549 SCM_VALIDATE_STACK (1,stack);
550 SCM_VALIDATE_INUM (2,i);
1bbd0b84
GB
551 SCM_ASSERT_RANGE (1,i,
552 SCM_INUM (i) >= 0 &&
553 SCM_INUM (i) < SCM_STACK_LENGTH (stack));
782d171c
MD
554 return scm_cons (stack, i);
555}
1bbd0b84 556#undef FUNC_NAME
782d171c 557
3b3b36dd 558SCM_DEFINE (scm_stack_length, "stack-length", 1, 0, 0,
1bbd0b84 559 (SCM stack),
b380b885 560 "")
1bbd0b84 561#define FUNC_NAME s_scm_stack_length
782d171c 562{
3b3b36dd 563 SCM_VALIDATE_STACK (1,stack);
782d171c
MD
564 return SCM_MAKINUM (SCM_STACK_LENGTH (stack));
565}
1bbd0b84 566#undef FUNC_NAME
782d171c
MD
567
568/* Frames
569 */
570
a1ec6916 571SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
1bbd0b84 572 (SCM obj),
b380b885 573 "")
1bbd0b84 574#define FUNC_NAME s_scm_frame_p
66f45472 575{
0c95b57d 576 return SCM_BOOL(SCM_FRAMEP (obj));
66f45472 577}
1bbd0b84 578#undef FUNC_NAME
66f45472 579
3b3b36dd 580SCM_DEFINE (scm_last_stack_frame, "last-stack-frame", 1, 0, 0,
1bbd0b84 581 (SCM obj),
b380b885 582 "")
1bbd0b84 583#define FUNC_NAME s_scm_last_stack_frame
782d171c
MD
584{
585 scm_debug_frame *dframe;
586 long offset = 0;
7115d1e4 587 SCM stack;
782d171c 588
6b5a304f 589 SCM_VALIDATE_NIM (1,obj);
782d171c
MD
590 if (SCM_DEBUGOBJP (obj))
591 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
592 else if (scm_tc7_contin == SCM_TYP7 (obj))
593 {
594 offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
595 - SCM_BASE (obj));
596#ifndef STACK_GROWS_UP
597 offset += SCM_LENGTH (obj);
598#endif
c0ab1b8d 599 dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
782d171c 600 }
3323ad08
JB
601 else
602 {
1bbd0b84 603 SCM_WTA (1,obj);
3323ad08
JB
604 abort ();
605 }
782d171c 606
66f45472 607 if (!dframe || SCM_VOIDFRAMEP (*dframe))
782d171c
MD
608 return SCM_BOOL_F;
609
c0ab1b8d
JB
610 stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (SCM_FRAME_N_SLOTS),
611 SCM_EOL);
7115d1e4
MD
612 SCM_STACK (stack) -> length = 1;
613 SCM_STACK (stack) -> frames = &SCM_STACK (stack) -> tail[0];
c0ab1b8d
JB
614 read_frame (dframe, offset,
615 (scm_info_frame *) &SCM_STACK (stack) -> frames[0]);
782d171c 616
7115d1e4 617 return scm_cons (stack, SCM_INUM0);;
782d171c 618}
1bbd0b84 619#undef FUNC_NAME
782d171c 620
3b3b36dd 621SCM_DEFINE (scm_frame_number, "frame-number", 1, 0, 0,
1bbd0b84 622 (SCM frame),
b380b885 623 "")
1bbd0b84 624#define FUNC_NAME s_scm_frame_number
782d171c 625{
3b3b36dd 626 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
627 return SCM_MAKINUM (SCM_FRAME_NUMBER (frame));
628}
1bbd0b84 629#undef FUNC_NAME
782d171c 630
3b3b36dd 631SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
1bbd0b84 632 (SCM frame),
b380b885 633 "")
1bbd0b84 634#define FUNC_NAME s_scm_frame_source
782d171c 635{
3b3b36dd 636 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
637 return SCM_FRAME_SOURCE (frame);
638}
1bbd0b84 639#undef FUNC_NAME
782d171c 640
3b3b36dd 641SCM_DEFINE (scm_frame_procedure, "frame-procedure", 1, 0, 0,
1bbd0b84 642 (SCM frame),
b380b885 643 "")
1bbd0b84 644#define FUNC_NAME s_scm_frame_procedure
782d171c 645{
3b3b36dd 646 SCM_VALIDATE_FRAME (1,frame);
782d171c 647 return (SCM_FRAME_PROC_P (frame)
afa92d19
TP
648 ? SCM_FRAME_PROC (frame)
649 : SCM_BOOL_F);
782d171c 650}
1bbd0b84 651#undef FUNC_NAME
782d171c 652
3b3b36dd 653SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
1bbd0b84 654 (SCM frame),
b380b885 655 "")
1bbd0b84 656#define FUNC_NAME s_scm_frame_arguments
782d171c 657{
3b3b36dd 658 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
659 return SCM_FRAME_ARGS (frame);
660}
1bbd0b84 661#undef FUNC_NAME
782d171c 662
3b3b36dd 663SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
1bbd0b84 664 (SCM frame),
b380b885 665 "")
1bbd0b84 666#define FUNC_NAME s_scm_frame_previous
782d171c
MD
667{
668 int n;
3b3b36dd 669 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
670 n = SCM_INUM (SCM_CDR (frame)) + 1;
671 if (n >= SCM_STACK_LENGTH (SCM_CAR (frame)))
672 return SCM_BOOL_F;
673 else
674 return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
675}
1bbd0b84 676#undef FUNC_NAME
782d171c 677
3b3b36dd 678SCM_DEFINE (scm_frame_next, "frame-next", 1, 0, 0,
1bbd0b84 679 (SCM frame),
b380b885 680 "")
1bbd0b84 681#define FUNC_NAME s_scm_frame_next
782d171c
MD
682{
683 int n;
3b3b36dd 684 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
685 n = SCM_INUM (SCM_CDR (frame)) - 1;
686 if (n < 0)
687 return SCM_BOOL_F;
688 else
689 return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
690}
1bbd0b84 691#undef FUNC_NAME
782d171c 692
3b3b36dd 693SCM_DEFINE (scm_frame_real_p, "frame-real?", 1, 0, 0,
1bbd0b84 694 (SCM frame),
b380b885 695 "")
1bbd0b84 696#define FUNC_NAME s_scm_frame_real_p
782d171c 697{
3b3b36dd 698 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 699 return SCM_BOOL(SCM_FRAME_REAL_P (frame));
782d171c 700}
1bbd0b84 701#undef FUNC_NAME
782d171c 702
3b3b36dd 703SCM_DEFINE (scm_frame_procedure_p, "frame-procedure?", 1, 0, 0,
1bbd0b84 704 (SCM frame),
b380b885 705 "")
1bbd0b84 706#define FUNC_NAME s_scm_frame_procedure_p
782d171c 707{
3b3b36dd 708 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 709 return SCM_BOOL(SCM_FRAME_PROC_P (frame));
782d171c 710}
1bbd0b84 711#undef FUNC_NAME
782d171c 712
3b3b36dd 713SCM_DEFINE (scm_frame_evaluating_args_p, "frame-evaluating-args?", 1, 0, 0,
1bbd0b84 714 (SCM frame),
b380b885 715 "")
1bbd0b84 716#define FUNC_NAME s_scm_frame_evaluating_args_p
782d171c 717{
3b3b36dd 718 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 719 return SCM_BOOL(SCM_FRAME_EVAL_ARGS_P (frame));
782d171c 720}
1bbd0b84 721#undef FUNC_NAME
782d171c 722
3b3b36dd 723SCM_DEFINE (scm_frame_overflow_p, "frame-overflow?", 1, 0, 0,
1bbd0b84 724 (SCM frame),
b380b885 725 "")
1bbd0b84 726#define FUNC_NAME s_scm_frame_overflow_p
782d171c 727{
3b3b36dd 728 SCM_VALIDATE_FRAME (1,frame);
156dcb09 729 return SCM_BOOL(SCM_FRAME_OVERFLOW_P (frame));
782d171c 730}
1bbd0b84 731#undef FUNC_NAME
782d171c
MD
732
733\f
734
735void
736scm_init_stacks ()
737{
66f45472
MD
738 SCM vtable;
739 SCM vtable_layout = scm_make_struct_layout (scm_nullstr);
c0ab1b8d
JB
740 SCM stack_layout
741 = scm_make_struct_layout (scm_makfrom0str (SCM_STACK_LAYOUT));
66f45472 742 vtable = scm_make_vtable_vtable (vtable_layout, SCM_INUM0, SCM_EOL);
c0ab1b8d
JB
743 scm_stack_type
744 = scm_permanent_object (scm_make_struct (vtable, SCM_INUM0,
745 scm_cons (stack_layout,
746 SCM_EOL)));
fe970d84
MD
747 scm_set_struct_vtable_name_x (scm_stack_type,
748 SCM_CAR (scm_intern0 ("stack")));
a0599745 749#include "libguile/stacks.x"
782d171c 750}
89e00824
ML
751
752/*
753 Local Variables:
754 c-file-style: "gnu"
755 End:
756*/