*** empty log message ***
[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>
52#include "_scm.h"
c3a6c6f9 53#include "eval.h"
782d171c
MD
54#include "debug.h"
55#include "continuations.h"
66f45472 56#include "struct.h"
7c939801 57#include "macros.h"
c3a6c6f9 58#include "procprop.h"
650de6d7 59#include "modules.h"
ba11fd4c 60#include "root.h"
7ab3fdd5 61#include "strings.h"
782d171c 62
b6791b2e 63#include "validate.h"
782d171c
MD
64#include "stacks.h"
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
MD
158{
159 int n, size;
160 int max_depth = SCM_BACKTRACE_MAXDEPTH;
161 scm_debug_info *info;
162 for (n = 0;
66f45472 163 dframe && !SCM_VOIDFRAMEP (*dframe) && n < max_depth;
c0ab1b8d 164 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
165 {
166 if (SCM_EVALFRAMEP (*dframe))
167 {
168 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 169 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
170 n += (info - dframe->vect) / 2 + 1;
171 /* Data in the apply part of an eval info frame comes from previous
172 stack frame if the scm_debug_info vector is overflowed. */
173 if ((((info - dframe->vect) & 1) == 0)
174 && SCM_OVERFLOWP (*dframe)
175 && !SCM_UNBNDP (info[1].a.proc))
176 ++n;
177 }
178 else
179 ++n;
180 }
66f45472
MD
181 if (dframe && SCM_VOIDFRAMEP (*dframe))
182 *id = dframe->vect[0].id;
183 else if (dframe)
782d171c
MD
184 *maxp = 1;
185 return n;
186}
187
188/* Read debug info from DFRAME into IFRAME.
189 */
782d171c 190static void
1bbd0b84 191read_frame (scm_debug_frame *dframe,long offset,scm_info_frame *iframe)
782d171c 192{
f1267706 193 scm_bits_t flags = SCM_UNPACK (SCM_INUM0); /* UGh. */
782d171c
MD
194 int size;
195 scm_debug_info *info;
196 if (SCM_EVALFRAMEP (*dframe))
197 {
198 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 199 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
200 if ((info - dframe->vect) & 1)
201 {
202 /* Debug.vect ends with apply info. */
203 --info;
204 if (info[1].a.proc != SCM_UNDEFINED)
205 {
206 flags |= SCM_FRAMEF_PROC;
207 iframe->proc = info[1].a.proc;
208 iframe->args = info[1].a.args;
209 if (!SCM_ARGS_READY_P (*dframe))
210 flags |= SCM_FRAMEF_EVAL_ARGS;
211 }
212 }
6629eb1c 213 iframe->source = scm_make_memoized (info[0].e.exp, info[0].e.env);
782d171c
MD
214 }
215 else
216 {
217 flags |= SCM_FRAMEF_PROC;
218 iframe->proc = dframe->vect[0].a.proc;
219 iframe->args = dframe->vect[0].a.args;
220 }
221 iframe->flags = flags;
222}
223
7a13c3ae
MD
224/* Look up the first body form of the apply closure. We'll use this
225 below to prevent it from being displayed.
226*/
227static SCM
228get_applybody ()
229{
230 SCM proc = SCM_CDR (scm_sym2vcell (scm_sym_apply, SCM_BOOL_F, SCM_BOOL_F));
0c95b57d 231 if (SCM_CLOSUREP (proc))
7a13c3ae
MD
232 return SCM_CADR (SCM_CODE (proc));
233 else
234 return SCM_UNDEFINED;
235}
7115d1e4
MD
236
237#define NEXT_FRAME(iframe, n, quit) \
d3a6bc94 238do { \
7a13c3ae
MD
239 if (SCM_NIMP (iframe->source) \
240 && SCM_MEMOIZED_EXP (iframe->source) == applybody) \
241 { \
242 iframe->source = SCM_BOOL_F; \
243 if (SCM_FALSEP (iframe->proc)) \
244 { \
245 --iframe; \
246 ++n; \
247 } \
248 } \
7115d1e4
MD
249 ++iframe; \
250 if (--n == 0) \
251 goto quit; \
d3a6bc94 252} while (0)
7115d1e4
MD
253
254
7a13c3ae
MD
255/* Fill the scm_info_frame vector IFRAME with data from N stack frames
256 * starting with the first stack frame represented by debug frame
257 * DFRAME.
258 */
259
7c939801 260static int
1bbd0b84 261read_frames (scm_debug_frame *dframe,long offset,int n,scm_info_frame *iframes)
782d171c
MD
262{
263 int size;
264 scm_info_frame *iframe = iframes;
265 scm_debug_info *info;
7a13c3ae 266 static SCM applybody = SCM_UNDEFINED;
782d171c 267
7a13c3ae
MD
268 /* The value of applybody has to be setup after r4rs.scm has executed. */
269 if (SCM_UNBNDP (applybody))
270 applybody = get_applybody ();
782d171c 271 for (;
66f45472 272 dframe && !SCM_VOIDFRAMEP (*dframe) && n > 0;
c0ab1b8d 273 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
274 {
275 read_frame (dframe, offset, iframe);
276 if (SCM_EVALFRAMEP (*dframe))
277 {
6629eb1c
MD
278 /* If current frame is a macro during expansion, we should
279 skip the previously recorded macro transformer
280 application frame. */
281 if (SCM_MACROEXPP (*dframe) && iframe > iframes)
7c939801
MD
282 {
283 *(iframe - 1) = *iframe;
284 --iframe;
285 }
782d171c 286 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 287 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
288 if ((info - dframe->vect) & 1)
289 --info;
290 /* Data in the apply part of an eval info frame comes from
291 previous stack frame if the scm_debug_info vector is overflowed. */
292 else if (SCM_OVERFLOWP (*dframe)
293 && !SCM_UNBNDP (info[1].a.proc))
294 {
7115d1e4 295 NEXT_FRAME (iframe, n, quit);
f1267706 296 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
297 iframe->proc = info[1].a.proc;
298 iframe->args = info[1].a.args;
299 }
300 if (SCM_OVERFLOWP (*dframe))
301 iframe->flags |= SCM_FRAMEF_OVERFLOW;
302 info -= 2;
7115d1e4 303 NEXT_FRAME (iframe, n, quit);
782d171c
MD
304 while (info >= dframe->vect)
305 {
306 if (!SCM_UNBNDP (info[1].a.proc))
307 {
f1267706 308 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
309 iframe->proc = info[1].a.proc;
310 iframe->args = info[1].a.args;
311 }
312 else
f1267706 313 iframe->flags = SCM_UNPACK (SCM_INUM0);
782d171c
MD
314 iframe->source = scm_make_memoized (info[0].e.exp,
315 info[0].e.env);
316 info -= 2;
7115d1e4 317 NEXT_FRAME (iframe, n, quit);
782d171c
MD
318 }
319 }
7c939801
MD
320 else if (iframe->proc == scm_f_gsubr_apply)
321 /* Skip gsubr apply frames. */
322 continue;
782d171c
MD
323 else
324 {
7115d1e4 325 NEXT_FRAME (iframe, n, quit);
782d171c
MD
326 }
327 quit:
328 if (iframe > iframes)
329 (iframe - 1) -> flags |= SCM_FRAMEF_REAL;
330 }
7c939801 331 return iframe - iframes; /* Number of frames actually read */
782d171c
MD
332}
333
c3a6c6f9
MD
334/* Narrow STACK by cutting away stackframes (mutatingly).
335 *
336 * Inner frames (most recent) are cut by advancing the frames pointer.
337 * Outer frames are cut by decreasing the recorded length.
338 *
339 * Cut maximally INNER inner frames and OUTER outer frames using
340 * the keys INNER_KEY and OUTER_KEY.
341 *
342 * Frames are cut away starting at the end points and moving towards
343 * the center of the stack. The key is normally compared to the
344 * operator in application frames. Frames up to and including the key
345 * are cut.
346 *
347 * If INNER_KEY is #t a different scheme is used for inner frames:
348 *
349 * Frames up to but excluding the first source frame originating from
350 * a user module are cut, except for possible application frames
351 * between the user frame and the last system frame previously
352 * encountered.
353 */
354
7115d1e4 355static void
1bbd0b84 356narrow_stack (SCM stack,int inner,SCM inner_key,int outer,SCM outer_key)
7115d1e4
MD
357{
358 scm_stack *s = SCM_STACK (stack);
359 int i;
360 int n = s->length;
361
362 /* Cut inner part. */
c3a6c6f9
MD
363 if (inner_key == SCM_BOOL_T)
364 /* Cut all frames up to user module code */
365 {
366 for (i = 0; inner; ++i, --inner)
367 {
368 SCM m = s->frames[i].source;
368cf54d 369 if ( SCM_MEMOIZEDP (m)
c3a6c6f9
MD
370 && SCM_NIMP (SCM_MEMOIZED_ENV (m))
371 && SCM_FALSEP (scm_system_module_env_p (SCM_MEMOIZED_ENV (m))))
372 {
373 /* Back up in order to include any non-source frames */
374 while (i > 0
368cf54d 375 && !((m = s->frames[i - 1].source, SCM_MEMOIZEDP (m))
c3a6c6f9
MD
376 || (SCM_NIMP (m = s->frames[i - 1].proc)
377 && SCM_NFALSEP (scm_procedure_p (m))
378 && SCM_NFALSEP (scm_procedure_property
379 (m, scm_sym_system_procedure)))))
380 {
381 --i;
382 ++inner;
383 }
384 break;
385 }
386 }
387 }
388 else
389 /* Use standard cutting procedure. */
390 {
391 for (i = 0; inner; --inner)
392 if (s->frames[i++].proc == inner_key)
393 break;
394 }
7115d1e4
MD
395 s->frames = &s->frames[i];
396 n -= i;
397
398 /* Cut outer part. */
399 for (; n && outer; --outer)
400 if (s->frames[--n].proc == outer_key)
401 break;
402
403 s->length = n;
404}
405
782d171c
MD
406\f
407
408/* Stacks
409 */
410
66f45472
MD
411SCM scm_stack_type;
412
a1ec6916 413SCM_DEFINE (scm_stack_p, "stack?", 1, 0, 0,
1bbd0b84 414 (SCM obj),
b380b885 415 "Return @code{#t} if @var{obj} is a calling stack.")
1bbd0b84 416#define FUNC_NAME s_scm_stack_p
66f45472 417{
0c95b57d 418 return SCM_BOOL(SCM_STACKP (obj));
66f45472 419}
1bbd0b84 420#undef FUNC_NAME
66f45472 421
a1ec6916 422SCM_DEFINE (scm_make_stack, "make-stack", 0, 0, 1,
1bbd0b84 423 (SCM args),
b380b885 424 "")
1bbd0b84 425#define FUNC_NAME s_scm_make_stack
782d171c 426{
7115d1e4 427 int n, maxp, size;
25748c78 428 scm_debug_frame *dframe = scm_last_debug_frame;
782d171c
MD
429 scm_info_frame *iframe;
430 long offset = 0;
66f45472 431 SCM stack, id;
f6f88e0d 432 SCM obj, inner_cut, outer_cut;
782d171c 433
0c95b57d 434 SCM_ASSERT (SCM_CONSP (args),
1bbd0b84 435 SCM_FUNC_NAME, SCM_WNA, NULL);
f6f88e0d
MD
436 obj = SCM_CAR (args);
437 args = SCM_CDR (args);
438
439 /* Extract a pointer to the innermost frame of whatever object
440 scm_make_stack was given. */
25748c78
GB
441 /* just use dframe == scm_last_debug_frame
442 (from initialization of dframe, above) if obj is #t */
443 if (obj != SCM_BOOL_T)
782d171c 444 {
1bbd0b84 445 SCM_ASSERT (SCM_NIMP (obj), obj, SCM_ARG1, FUNC_NAME);
782d171c
MD
446 if (SCM_DEBUGOBJP (obj))
447 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
448 else if (scm_tc7_contin == SCM_TYP7 (obj))
449 {
450 offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
451 - SCM_BASE (obj));
452#ifndef STACK_GROWS_UP
453 offset += SCM_LENGTH (obj);
454#endif
c0ab1b8d 455 dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
782d171c 456 }
3323ad08
JB
457 else
458 {
5d2d2ffc 459 SCM_WTA (SCM_ARG1, obj);
3323ad08
JB
460 abort ();
461 }
782d171c
MD
462 }
463
f6f88e0d
MD
464 /* Count number of frames. Also get stack id tag and check whether
465 there are more stackframes than we want to record
466 (SCM_BACKTRACE_MAXDEPTH). */
66f45472
MD
467 id = SCM_BOOL_F;
468 maxp = 0;
7115d1e4 469 n = stack_depth (dframe, offset, &id, &maxp);
782d171c
MD
470 size = n * SCM_FRAME_N_SLOTS;
471
f6f88e0d 472 /* Make the stack object. */
66f45472
MD
473 stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (size), SCM_EOL);
474 SCM_STACK (stack) -> id = id;
7115d1e4
MD
475 iframe = &SCM_STACK (stack) -> tail[0];
476 SCM_STACK (stack) -> frames = iframe;
7115d1e4 477
f6f88e0d 478 /* Translate the current chain of stack frames into debugging information. */
7c939801
MD
479 n = read_frames (RELOC_FRAME (dframe, offset), offset, n, iframe);
480 SCM_STACK (stack) -> length = n;
7115d1e4 481
f6f88e0d 482 /* Narrow the stack according to the arguments given to scm_make_stack. */
0c95b57d 483 while (n > 0 && SCM_CONSP (args))
f6f88e0d
MD
484 {
485 inner_cut = SCM_CAR (args);
486 args = SCM_CDR (args);
0c95b57d 487 if (SCM_CONSP (args))
f6f88e0d
MD
488 {
489 outer_cut = SCM_CAR (args);
490 args = SCM_CDR (args);
491 }
492 else
493 outer_cut = SCM_INUM0;
494
495 narrow_stack (stack,
496 SCM_INUMP (inner_cut) ? SCM_INUM (inner_cut) : n,
497 SCM_INUMP (inner_cut) ? 0 : inner_cut,
498 SCM_INUMP (outer_cut) ? SCM_INUM (outer_cut) : n,
499 SCM_INUMP (outer_cut) ? 0 : outer_cut);
500
501 n = SCM_STACK (stack) -> length;
502 }
503
7115d1e4 504 if (n > 0)
f6f88e0d
MD
505 {
506 if (maxp)
507 iframe[n - 1].flags |= SCM_FRAMEF_OVERFLOW;
508 return stack;
509 }
7115d1e4
MD
510 else
511 return SCM_BOOL_F;
782d171c 512}
1bbd0b84 513#undef FUNC_NAME
782d171c 514
a1ec6916 515SCM_DEFINE (scm_stack_id, "stack-id", 1, 0, 0,
1bbd0b84 516 (SCM stack),
b380b885 517 "Return the identifier given to @var{stack} by @code{start-stack}.")
1bbd0b84 518#define FUNC_NAME s_scm_stack_id
66f45472 519{
7115d1e4
MD
520 scm_debug_frame *dframe;
521 long offset = 0;
522 if (stack == SCM_BOOL_T)
523 dframe = scm_last_debug_frame;
524 else
525 {
6b5a304f 526 SCM_VALIDATE_NIM (1,stack);
7115d1e4
MD
527 if (SCM_DEBUGOBJP (stack))
528 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (stack);
529 else if (scm_tc7_contin == SCM_TYP7 (stack))
530 {
531 offset = ((SCM_STACKITEM *) (SCM_CHARS (stack) + sizeof (scm_contregs))
532 - SCM_BASE (stack));
533#ifndef STACK_GROWS_UP
534 offset += SCM_LENGTH (stack);
535#endif
c0ab1b8d 536 dframe = RELOC_FRAME (SCM_DFRAME (stack), offset);
7115d1e4
MD
537 }
538 else if (SCM_STACKP (stack))
539 return SCM_STACK (stack) -> id;
c3a6c6f9 540 else
1bbd0b84 541 SCM_WRONG_TYPE_ARG (1, stack);
7115d1e4
MD
542 }
543 while (dframe && !SCM_VOIDFRAMEP (*dframe))
c0ab1b8d 544 dframe = RELOC_FRAME (dframe->prev, offset);
7115d1e4
MD
545 if (dframe && SCM_VOIDFRAMEP (*dframe))
546 return dframe->vect[0].id;
547 return SCM_BOOL_F;
66f45472 548}
1bbd0b84 549#undef FUNC_NAME
66f45472 550
a1ec6916 551SCM_DEFINE (scm_stack_ref, "stack-ref", 2, 0, 0,
1bbd0b84 552 (SCM stack, SCM i),
b380b885 553 "")
1bbd0b84 554#define FUNC_NAME s_scm_stack_ref
782d171c 555{
3b3b36dd
GB
556 SCM_VALIDATE_STACK (1,stack);
557 SCM_VALIDATE_INUM (2,i);
1bbd0b84
GB
558 SCM_ASSERT_RANGE (1,i,
559 SCM_INUM (i) >= 0 &&
560 SCM_INUM (i) < SCM_STACK_LENGTH (stack));
782d171c
MD
561 return scm_cons (stack, i);
562}
1bbd0b84 563#undef FUNC_NAME
782d171c 564
3b3b36dd 565SCM_DEFINE (scm_stack_length, "stack-length", 1, 0, 0,
1bbd0b84 566 (SCM stack),
b380b885 567 "")
1bbd0b84 568#define FUNC_NAME s_scm_stack_length
782d171c 569{
3b3b36dd 570 SCM_VALIDATE_STACK (1,stack);
782d171c
MD
571 return SCM_MAKINUM (SCM_STACK_LENGTH (stack));
572}
1bbd0b84 573#undef FUNC_NAME
782d171c
MD
574
575/* Frames
576 */
577
a1ec6916 578SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
1bbd0b84 579 (SCM obj),
b380b885 580 "")
1bbd0b84 581#define FUNC_NAME s_scm_frame_p
66f45472 582{
0c95b57d 583 return SCM_BOOL(SCM_FRAMEP (obj));
66f45472 584}
1bbd0b84 585#undef FUNC_NAME
66f45472 586
3b3b36dd 587SCM_DEFINE (scm_last_stack_frame, "last-stack-frame", 1, 0, 0,
1bbd0b84 588 (SCM obj),
b380b885 589 "")
1bbd0b84 590#define FUNC_NAME s_scm_last_stack_frame
782d171c
MD
591{
592 scm_debug_frame *dframe;
593 long offset = 0;
7115d1e4 594 SCM stack;
782d171c 595
6b5a304f 596 SCM_VALIDATE_NIM (1,obj);
782d171c
MD
597 if (SCM_DEBUGOBJP (obj))
598 dframe = (scm_debug_frame *) SCM_DEBUGOBJ_FRAME (obj);
599 else if (scm_tc7_contin == SCM_TYP7 (obj))
600 {
601 offset = ((SCM_STACKITEM *) (SCM_CHARS (obj) + sizeof (scm_contregs))
602 - SCM_BASE (obj));
603#ifndef STACK_GROWS_UP
604 offset += SCM_LENGTH (obj);
605#endif
c0ab1b8d 606 dframe = RELOC_FRAME (SCM_DFRAME (obj), offset);
782d171c 607 }
3323ad08
JB
608 else
609 {
1bbd0b84 610 SCM_WTA (1,obj);
3323ad08
JB
611 abort ();
612 }
782d171c 613
66f45472 614 if (!dframe || SCM_VOIDFRAMEP (*dframe))
782d171c
MD
615 return SCM_BOOL_F;
616
c0ab1b8d
JB
617 stack = scm_make_struct (scm_stack_type, SCM_MAKINUM (SCM_FRAME_N_SLOTS),
618 SCM_EOL);
7115d1e4
MD
619 SCM_STACK (stack) -> length = 1;
620 SCM_STACK (stack) -> frames = &SCM_STACK (stack) -> tail[0];
c0ab1b8d
JB
621 read_frame (dframe, offset,
622 (scm_info_frame *) &SCM_STACK (stack) -> frames[0]);
782d171c 623
7115d1e4 624 return scm_cons (stack, SCM_INUM0);;
782d171c 625}
1bbd0b84 626#undef FUNC_NAME
782d171c 627
3b3b36dd 628SCM_DEFINE (scm_frame_number, "frame-number", 1, 0, 0,
1bbd0b84 629 (SCM frame),
b380b885 630 "")
1bbd0b84 631#define FUNC_NAME s_scm_frame_number
782d171c 632{
3b3b36dd 633 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
634 return SCM_MAKINUM (SCM_FRAME_NUMBER (frame));
635}
1bbd0b84 636#undef FUNC_NAME
782d171c 637
3b3b36dd 638SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
1bbd0b84 639 (SCM frame),
b380b885 640 "")
1bbd0b84 641#define FUNC_NAME s_scm_frame_source
782d171c 642{
3b3b36dd 643 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
644 return SCM_FRAME_SOURCE (frame);
645}
1bbd0b84 646#undef FUNC_NAME
782d171c 647
3b3b36dd 648SCM_DEFINE (scm_frame_procedure, "frame-procedure", 1, 0, 0,
1bbd0b84 649 (SCM frame),
b380b885 650 "")
1bbd0b84 651#define FUNC_NAME s_scm_frame_procedure
782d171c 652{
3b3b36dd 653 SCM_VALIDATE_FRAME (1,frame);
782d171c 654 return (SCM_FRAME_PROC_P (frame)
afa92d19
TP
655 ? SCM_FRAME_PROC (frame)
656 : SCM_BOOL_F);
782d171c 657}
1bbd0b84 658#undef FUNC_NAME
782d171c 659
3b3b36dd 660SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
1bbd0b84 661 (SCM frame),
b380b885 662 "")
1bbd0b84 663#define FUNC_NAME s_scm_frame_arguments
782d171c 664{
3b3b36dd 665 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
666 return SCM_FRAME_ARGS (frame);
667}
1bbd0b84 668#undef FUNC_NAME
782d171c 669
3b3b36dd 670SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
1bbd0b84 671 (SCM frame),
b380b885 672 "")
1bbd0b84 673#define FUNC_NAME s_scm_frame_previous
782d171c
MD
674{
675 int n;
3b3b36dd 676 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
677 n = SCM_INUM (SCM_CDR (frame)) + 1;
678 if (n >= SCM_STACK_LENGTH (SCM_CAR (frame)))
679 return SCM_BOOL_F;
680 else
681 return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
682}
1bbd0b84 683#undef FUNC_NAME
782d171c 684
3b3b36dd 685SCM_DEFINE (scm_frame_next, "frame-next", 1, 0, 0,
1bbd0b84 686 (SCM frame),
b380b885 687 "")
1bbd0b84 688#define FUNC_NAME s_scm_frame_next
782d171c
MD
689{
690 int n;
3b3b36dd 691 SCM_VALIDATE_FRAME (1,frame);
782d171c
MD
692 n = SCM_INUM (SCM_CDR (frame)) - 1;
693 if (n < 0)
694 return SCM_BOOL_F;
695 else
696 return scm_cons (SCM_CAR (frame), SCM_MAKINUM (n));
697}
1bbd0b84 698#undef FUNC_NAME
782d171c 699
3b3b36dd 700SCM_DEFINE (scm_frame_real_p, "frame-real?", 1, 0, 0,
1bbd0b84 701 (SCM frame),
b380b885 702 "")
1bbd0b84 703#define FUNC_NAME s_scm_frame_real_p
782d171c 704{
3b3b36dd 705 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 706 return SCM_BOOL(SCM_FRAME_REAL_P (frame));
782d171c 707}
1bbd0b84 708#undef FUNC_NAME
782d171c 709
3b3b36dd 710SCM_DEFINE (scm_frame_procedure_p, "frame-procedure?", 1, 0, 0,
1bbd0b84 711 (SCM frame),
b380b885 712 "")
1bbd0b84 713#define FUNC_NAME s_scm_frame_procedure_p
782d171c 714{
3b3b36dd 715 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 716 return SCM_BOOL(SCM_FRAME_PROC_P (frame));
782d171c 717}
1bbd0b84 718#undef FUNC_NAME
782d171c 719
3b3b36dd 720SCM_DEFINE (scm_frame_evaluating_args_p, "frame-evaluating-args?", 1, 0, 0,
1bbd0b84 721 (SCM frame),
b380b885 722 "")
1bbd0b84 723#define FUNC_NAME s_scm_frame_evaluating_args_p
782d171c 724{
3b3b36dd 725 SCM_VALIDATE_FRAME (1,frame);
1bbd0b84 726 return SCM_BOOL(SCM_FRAME_EVAL_ARGS_P (frame));
782d171c 727}
1bbd0b84 728#undef FUNC_NAME
782d171c 729
3b3b36dd 730SCM_DEFINE (scm_frame_overflow_p, "frame-overflow?", 1, 0, 0,
1bbd0b84 731 (SCM frame),
b380b885 732 "")
1bbd0b84 733#define FUNC_NAME s_scm_frame_overflow_p
782d171c 734{
3b3b36dd 735 SCM_VALIDATE_FRAME (1,frame);
156dcb09 736 return SCM_BOOL(SCM_FRAME_OVERFLOW_P (frame));
782d171c 737}
1bbd0b84 738#undef FUNC_NAME
782d171c
MD
739
740\f
741
742void
743scm_init_stacks ()
744{
66f45472
MD
745 SCM vtable;
746 SCM vtable_layout = scm_make_struct_layout (scm_nullstr);
c0ab1b8d
JB
747 SCM stack_layout
748 = scm_make_struct_layout (scm_makfrom0str (SCM_STACK_LAYOUT));
66f45472 749 vtable = scm_make_vtable_vtable (vtable_layout, SCM_INUM0, SCM_EOL);
c0ab1b8d
JB
750 scm_stack_type
751 = scm_permanent_object (scm_make_struct (vtable, SCM_INUM0,
752 scm_cons (stack_layout,
753 SCM_EOL)));
fe970d84
MD
754 scm_set_struct_vtable_name_x (scm_stack_type,
755 SCM_CAR (scm_intern0 ("stack")));
782d171c
MD
756#include "stacks.x"
757}