* Makefile.am: Fix ETAGS_ARGS to recognize GUILE_PROC,
[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"
782d171c 60
1bbd0b84 61#include "scm_validate.h"
782d171c
MD
62#include "stacks.h"
63
64\f
65/* {Frames and stacks}
66 *
67 * The debugging evaluator creates debug frames on the stack. These
68 * are linked from the innermost frame and outwards. The last frame
69 * created can always be accessed as SCM_LAST_DEBUG_FRAME.
70 * Continuations contain a pointer to the innermost debug frame on the
71 * continuation stack.
72 *
73 * Each debug frame contains a set of flags and information about one
74 * or more stack frames. The case of multiple frames occurs due to
75 * tail recursion. The maximal number of stack frames which can be
76 * recorded in one debug frame can be set dynamically with the debug
77 * option FRAMES.
78 *
79 * Stack frame information is of two types: eval information (the
80 * expression being evaluated and its environment) and apply
81 * information (the procedure being applied and its arguments). A
82 * stack frame normally corresponds to an eval/apply pair, but macros
83 * and special forms (which are implemented as macros in Guile) only
84 * have eval information and apply calls leads to apply only frames.
85 *
86 * Since we want to record the total stack information and later
87 * manipulate this data at the scheme level in the debugger, we need
88 * to transform it into a new representation. In the following code
89 * section you'll find the functions implementing this data type.
90 *
91 * Representation:
92 *
7115d1e4
MD
93 * The stack is represented as a struct with an id slot and a tail
94 * array of scm_info_frame structs.
782d171c
MD
95 *
96 * A frame is represented as a pair where the car contains a stack and
97 * the cdr an inum. The inum is an index to the first SCM value of
98 * the scm_info_frame struct.
99 *
100 * Stacks
101 * Constructor
102 * make-stack
7115d1e4
MD
103 * Selectors
104 * stack-id
782d171c
MD
105 * stack-ref
106 * Inspector
107 * stack-length
108 *
109 * Frames
110 * Constructor
111 * last-stack-frame
112 * Selectors
113 * frame-number
114 * frame-source
115 * frame-procedure
116 * frame-arguments
117 * frame-previous
118 * frame-next
119 * Predicates
120 * frame-real?
121 * frame-procedure?
122 * frame-evaluating-args?
7115d1e4 123 * frame-overflow? */
782d171c
MD
124
125\f
126
127/* Some auxiliary functions for reading debug frames off the stack.
128 */
129
c0ab1b8d
JB
130/* Stacks often contain pointers to other items on the stack; for
131 example, each scm_debug_frame structure contains a pointer to the
132 next frame out. When we capture a continuation, we copy the stack
133 into the heap, and just leave all the pointers unchanged. This
134 makes it simple to restore the continuation --- just copy the stack
135 back! However, if we retrieve a pointer from the heap copy to
136 another item that was originally on the stack, we have to add an
137 offset to the pointer to discover the new referent.
138
139 If PTR is a pointer retrieved from a continuation, whose original
140 target was on the stack, and OFFSET is the appropriate offset from
141 the original stack to the continuation, then RELOC_MUMBLE (PTR,
142 OFFSET) is a pointer to the copy in the continuation of the
143 original referent, cast to an scm_debug_MUMBLE *. */
144#define RELOC_INFO(ptr, offset) \
145 ((scm_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
146#define RELOC_FRAME(ptr, offset) \
147 ((scm_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
148
149
782d171c
MD
150/* Count number of debug info frames on a stack, beginning with
151 * DFRAME. OFFSET is used for relocation of pointers when the stack
152 * is read from a continuation.
153 */
782d171c 154static int
1bbd0b84 155stack_depth (scm_debug_frame *dframe,long offset,SCM *id,int *maxp)
782d171c
MD
156{
157 int n, size;
158 int max_depth = SCM_BACKTRACE_MAXDEPTH;
159 scm_debug_info *info;
160 for (n = 0;
66f45472 161 dframe && !SCM_VOIDFRAMEP (*dframe) && n < max_depth;
c0ab1b8d 162 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
163 {
164 if (SCM_EVALFRAMEP (*dframe))
165 {
166 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 167 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
MD
190{
191 SCM flags = SCM_INUM0;
192 int size;
193 scm_debug_info *info;
194 if (SCM_EVALFRAMEP (*dframe))
195 {
196 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 197 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
198 if ((info - dframe->vect) & 1)
199 {
200 /* Debug.vect ends with apply info. */
201 --info;
202 if (info[1].a.proc != SCM_UNDEFINED)
203 {
204 flags |= SCM_FRAMEF_PROC;
205 iframe->proc = info[1].a.proc;
206 iframe->args = info[1].a.args;
207 if (!SCM_ARGS_READY_P (*dframe))
208 flags |= SCM_FRAMEF_EVAL_ARGS;
209 }
210 }
6629eb1c 211 iframe->source = scm_make_memoized (info[0].e.exp, info[0].e.env);
782d171c
MD
212 }
213 else
214 {
215 flags |= SCM_FRAMEF_PROC;
216 iframe->proc = dframe->vect[0].a.proc;
217 iframe->args = dframe->vect[0].a.args;
218 }
219 iframe->flags = flags;
220}
221
7a13c3ae
MD
222/* Look up the first body form of the apply closure. We'll use this
223 below to prevent it from being displayed.
224*/
225static SCM
226get_applybody ()
227{
228 SCM proc = SCM_CDR (scm_sym2vcell (scm_sym_apply, SCM_BOOL_F, SCM_BOOL_F));
229 if (SCM_NIMP (proc) && SCM_CLOSUREP (proc))
230 return SCM_CADR (SCM_CODE (proc));
231 else
232 return SCM_UNDEFINED;
233}
7115d1e4
MD
234
235#define NEXT_FRAME(iframe, n, quit) \
236{ \
7a13c3ae
MD
237 if (SCM_NIMP (iframe->source) \
238 && SCM_MEMOIZED_EXP (iframe->source) == applybody) \
239 { \
240 iframe->source = SCM_BOOL_F; \
241 if (SCM_FALSEP (iframe->proc)) \
242 { \
243 --iframe; \
244 ++n; \
245 } \
246 } \
7115d1e4
MD
247 ++iframe; \
248 if (--n == 0) \
249 goto quit; \
250} \
251
252
7a13c3ae
MD
253/* Fill the scm_info_frame vector IFRAME with data from N stack frames
254 * starting with the first stack frame represented by debug frame
255 * DFRAME.
256 */
257
7c939801 258static int
1bbd0b84 259read_frames (scm_debug_frame *dframe,long offset,int n,scm_info_frame *iframes)
782d171c
MD
260{
261 int size;
262 scm_info_frame *iframe = iframes;
263 scm_debug_info *info;
7a13c3ae 264 static SCM applybody = SCM_UNDEFINED;
782d171c 265
7a13c3ae
MD
266 /* The value of applybody has to be setup after r4rs.scm has executed. */
267 if (SCM_UNBNDP (applybody))
268 applybody = get_applybody ();
782d171c 269 for (;
66f45472 270 dframe && !SCM_VOIDFRAMEP (*dframe) && n > 0;
c0ab1b8d 271 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
272 {
273 read_frame (dframe, offset, iframe);
274 if (SCM_EVALFRAMEP (*dframe))
275 {
6629eb1c
MD
276 /* If current frame is a macro during expansion, we should
277 skip the previously recorded macro transformer
278 application frame. */
279 if (SCM_MACROEXPP (*dframe) && iframe > iframes)
7c939801
MD
280 {
281 *(iframe - 1) = *iframe;
282 --iframe;
283 }
782d171c 284 size = dframe->status & SCM_MAX_FRAME_SIZE;
c0ab1b8d 285 info = RELOC_INFO (dframe->info, offset);
782d171c
MD
286 if ((info - dframe->vect) & 1)
287 --info;
288 /* Data in the apply part of an eval info frame comes from
289 previous stack frame if the scm_debug_info vector is overflowed. */
290 else if (SCM_OVERFLOWP (*dframe)
291 && !SCM_UNBNDP (info[1].a.proc))
292 {
7115d1e4 293 NEXT_FRAME (iframe, n, quit);
782d171c
MD
294 iframe->flags = SCM_INUM0 | SCM_FRAMEF_PROC;
295 iframe->proc = info[1].a.proc;
296 iframe->args = info[1].a.args;
297 }
298 if (SCM_OVERFLOWP (*dframe))
299 iframe->flags |= SCM_FRAMEF_OVERFLOW;
300 info -= 2;
7115d1e4 301 NEXT_FRAME (iframe, n, quit);
782d171c
MD
302 while (info >= dframe->vect)
303 {
304 if (!SCM_UNBNDP (info[1].a.proc))
305 {
306 iframe->flags = SCM_INUM0 | SCM_FRAMEF_PROC;
307 iframe->proc = info[1].a.proc;
308 iframe->args = info[1].a.args;
309 }
310 else
311 iframe->flags = SCM_INUM0;
312 iframe->source = scm_make_memoized (info[0].e.exp,
313 info[0].e.env);
314 info -= 2;
7115d1e4 315 NEXT_FRAME (iframe, n, quit);
782d171c
MD
316 }
317 }
7c939801
MD
318 else if (iframe->proc == scm_f_gsubr_apply)
319 /* Skip gsubr apply frames. */
320 continue;
782d171c
MD
321 else
322 {
7115d1e4 323 NEXT_FRAME (iframe, n, quit);
782d171c
MD
324 }
325 quit:
326 if (iframe > iframes)
327 (iframe - 1) -> flags |= SCM_FRAMEF_REAL;
328 }
7c939801 329 return iframe - iframes; /* Number of frames actually read */
782d171c
MD
330}
331
c3a6c6f9
MD
332/* Narrow STACK by cutting away stackframes (mutatingly).
333 *
334 * Inner frames (most recent) are cut by advancing the frames pointer.
335 * Outer frames are cut by decreasing the recorded length.
336 *
337 * Cut maximally INNER inner frames and OUTER outer frames using
338 * the keys INNER_KEY and OUTER_KEY.
339 *
340 * Frames are cut away starting at the end points and moving towards
341 * the center of the stack. The key is normally compared to the
342 * operator in application frames. Frames up to and including the key
343 * are cut.
344 *
345 * If INNER_KEY is #t a different scheme is used for inner frames:
346 *
347 * Frames up to but excluding the first source frame originating from
348 * a user module are cut, except for possible application frames
349 * between the user frame and the last system frame previously
350 * encountered.
351 */
352
7115d1e4 353static void
1bbd0b84 354narrow_stack (SCM stack,int inner,SCM inner_key,int outer,SCM outer_key)
7115d1e4
MD
355{
356 scm_stack *s = SCM_STACK (stack);
357 int i;
358 int n = s->length;
359
360 /* Cut inner part. */
c3a6c6f9
MD
361 if (inner_key == SCM_BOOL_T)
362 /* Cut all frames up to user module code */
363 {
364 for (i = 0; inner; ++i, --inner)
365 {
366 SCM m = s->frames[i].source;
367 if (SCM_NIMP (m)
368 && SCM_MEMOIZEDP (m)
369 && SCM_NIMP (SCM_MEMOIZED_ENV (m))
370 && SCM_FALSEP (scm_system_module_env_p (SCM_MEMOIZED_ENV (m))))
371 {
372 /* Back up in order to include any non-source frames */
373 while (i > 0
374 && !((SCM_NIMP (m = s->frames[i - 1].source)
375 && SCM_MEMOIZEDP (m))
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
1bbd0b84
GB
413GUILE_PROC (scm_stack_p, "stack?", 1, 0, 0,
414 (SCM obj),
4079f87e 415"Return @code{#t} if @var{obj} is a calling stack.")
1bbd0b84 416#define FUNC_NAME s_scm_stack_p
66f45472 417{
1bbd0b84 418 return SCM_BOOL(SCM_NIMP (obj) && SCM_STACKP (obj));
66f45472 419}
1bbd0b84 420#undef FUNC_NAME
66f45472 421
1bbd0b84
GB
422GUILE_PROC (scm_make_stack, "make-stack", 0, 0, 1,
423 (SCM args),
424"")
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
0824b524 434 SCM_ASSERT (SCM_NIMP (args) && 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 {
1bbd0b84 459 scm_wta (obj, (char *) SCM_ARG1, FUNC_NAME);
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
MD
482 /* Narrow the stack according to the arguments given to scm_make_stack. */
483 while (n > 0 && SCM_NIMP (args) && SCM_CONSP (args))
484 {
485 inner_cut = SCM_CAR (args);
486 args = SCM_CDR (args);
487 if (SCM_NIMP (args) && SCM_CONSP (args))
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
1bbd0b84
GB
515GUILE_PROC (scm_stack_id, "stack-id", 1, 0, 0,
516 (SCM stack),
4079f87e 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
1bbd0b84
GB
551GUILE_PROC (scm_stack_ref, "stack-ref", 2, 0, 0,
552 (SCM stack, SCM i),
553"")
554#define FUNC_NAME s_scm_stack_ref
782d171c 555{
1bbd0b84
GB
556 SCM_VALIDATE_STACK(1,stack);
557 SCM_VALIDATE_INT(2,i);
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
1bbd0b84
GB
565GUILE_PROC(scm_stack_length, "stack-length", 1, 0, 0,
566 (SCM stack),
567"")
568#define FUNC_NAME s_scm_stack_length
782d171c 569{
1bbd0b84 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
1bbd0b84
GB
578GUILE_PROC (scm_frame_p, "frame?", 1, 0, 0,
579 (SCM obj),
580"")
581#define FUNC_NAME s_scm_frame_p
66f45472 582{
1bbd0b84 583 return SCM_BOOL(SCM_NIMP (obj) && SCM_FRAMEP (obj));
66f45472 584}
1bbd0b84 585#undef FUNC_NAME
66f45472 586
1bbd0b84
GB
587GUILE_PROC(scm_last_stack_frame, "last-stack-frame", 1, 0, 0,
588 (SCM obj),
589"")
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
1bbd0b84
GB
628GUILE_PROC(scm_frame_number, "frame-number", 1, 0, 0,
629 (SCM frame),
630"")
631#define FUNC_NAME s_scm_frame_number
782d171c 632{
1bbd0b84 633 SCM_VALIDATE_FRAME(1,frame);
782d171c
MD
634 return SCM_MAKINUM (SCM_FRAME_NUMBER (frame));
635}
1bbd0b84 636#undef FUNC_NAME
782d171c 637
1bbd0b84
GB
638GUILE_PROC(scm_frame_source, "frame-source", 1, 0, 0,
639 (SCM frame),
640"")
641#define FUNC_NAME s_scm_frame_source
782d171c 642{
1bbd0b84 643 SCM_VALIDATE_FRAME(1,frame);
782d171c
MD
644 return SCM_FRAME_SOURCE (frame);
645}
1bbd0b84 646#undef FUNC_NAME
782d171c 647
1bbd0b84
GB
648GUILE_PROC(scm_frame_procedure, "frame-procedure", 1, 0, 0,
649 (SCM frame),
650"")
651#define FUNC_NAME s_scm_frame_procedure
782d171c 652{
1bbd0b84 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
1bbd0b84
GB
660GUILE_PROC(scm_frame_arguments, "frame-arguments", 1, 0, 0,
661 (SCM frame),
662"")
663#define FUNC_NAME s_scm_frame_arguments
782d171c 664{
1bbd0b84 665 SCM_VALIDATE_FRAME(1,frame);
782d171c
MD
666 return SCM_FRAME_ARGS (frame);
667}
1bbd0b84 668#undef FUNC_NAME
782d171c 669
1bbd0b84
GB
670GUILE_PROC(scm_frame_previous, "frame-previous", 1, 0, 0,
671 (SCM frame),
672"")
673#define FUNC_NAME s_scm_frame_previous
782d171c
MD
674{
675 int n;
1bbd0b84 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
1bbd0b84
GB
685GUILE_PROC(scm_frame_next, "frame-next", 1, 0, 0,
686 (SCM frame),
687"")
688#define FUNC_NAME s_scm_frame_next
782d171c
MD
689{
690 int n;
1bbd0b84 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
1bbd0b84
GB
700GUILE_PROC(scm_frame_real_p, "frame-real?", 1, 0, 0,
701 (SCM frame),
702"")
703#define FUNC_NAME s_scm_frame_real_p
782d171c 704{
1bbd0b84
GB
705 SCM_VALIDATE_FRAME(1,frame);
706 return SCM_BOOL(SCM_FRAME_REAL_P (frame));
782d171c 707}
1bbd0b84 708#undef FUNC_NAME
782d171c 709
1bbd0b84
GB
710GUILE_PROC(scm_frame_procedure_p, "frame-procedure?", 1, 0, 0,
711 (SCM frame),
712"")
713#define FUNC_NAME s_scm_frame_procedure_p
782d171c 714{
1bbd0b84
GB
715 SCM_VALIDATE_FRAME(1,frame);
716 return SCM_BOOL(SCM_FRAME_PROC_P (frame));
782d171c 717}
1bbd0b84 718#undef FUNC_NAME
782d171c 719
1bbd0b84
GB
720GUILE_PROC(scm_frame_evaluating_args_p, "frame-evaluating-args?", 1, 0, 0,
721 (SCM frame),
722"")
723#define FUNC_NAME s_scm_frame_evaluating_args_p
782d171c 724{
1bbd0b84
GB
725 SCM_VALIDATE_FRAME(1,frame);
726 return SCM_BOOL(SCM_FRAME_EVAL_ARGS_P (frame));
782d171c 727}
1bbd0b84 728#undef FUNC_NAME
782d171c 729
1bbd0b84
GB
730GUILE_PROC(scm_frame_overflow_p, "frame-overflow?", 1, 0, 0,
731 (SCM frame),
732"")
733#define FUNC_NAME s_scm_frame_overflow_p
782d171c 734{
1bbd0b84 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}