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