1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libguile/_scm.h"
29 #include "libguile/async.h"
30 #include "libguile/objects.h"
31 #include "libguile/goops.h"
32 #include "libguile/ports.h"
38 #include "libguile/smob.h"
40 #include "libguile/boehm-gc.h"
41 #include <gc/gc_mark.h>
46 /* scm_smobs scm_numsmob
47 * implement a fixed sized array of smob records.
48 * Indexes into this table are used when generating type
49 * tags for smobjects (if you know a tag you can get an index and conversely).
52 #define MAX_SMOB_COUNT 256
54 scm_smob_descriptor scm_smobs
[MAX_SMOB_COUNT
];
56 /* Lower 16 bit of data must be zero.
59 scm_i_set_smob_flags (SCM x
, scm_t_bits data
)
61 SCM_SET_CELL_WORD_0 (x
, (SCM_CELL_WORD_0 (x
) & 0xFFFF) | data
);
65 scm_assert_smob_type (scm_t_bits tag
, SCM val
)
67 if (!SCM_SMOB_PREDICATE (tag
, val
))
68 scm_wrong_type_arg_msg (NULL
, 0, val
, scm_smobs
[SCM_TC2SMOBNUM(tag
)].name
);
74 /* This function is vestigial. It used to be the mark function's
75 responsibility to set the mark bit on the smob or port, but now the
76 generic marking routine in gc.c takes care of that, and a zero
77 pointer for a mark function means "don't bother". So you never
80 However, we leave it here because it's harmless to call it, and
81 people out there have smob code that uses it, and there's no reason
82 to make their links fail. */
85 scm_mark0 (SCM ptr SCM_UNUSED
)
91 /* Dirk::FIXME: The name markcdr is misleading, since the term cdr should only
92 be used for real pairs. */
95 return SCM_CELL_OBJECT_1 (ptr
);
102 scm_free0 (SCM ptr SCM_UNUSED
)
108 scm_smob_free (SCM obj
)
110 long n
= SCM_SMOBNUM (obj
);
111 if (scm_smobs
[n
].size
> 0)
112 scm_gc_free ((void *) SCM_CELL_WORD_1 (obj
),
113 scm_smobs
[n
].size
, SCM_SMOBNAME (n
));
121 scm_smob_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
123 long n
= SCM_SMOBNUM (exp
);
124 scm_puts ("#<", port
);
125 scm_puts (SCM_SMOBNAME (n
) ? SCM_SMOBNAME (n
) : "smob", port
);
126 scm_putc (' ', port
);
127 if (scm_smobs
[n
].size
)
128 scm_uintprint (SCM_CELL_WORD_1 (exp
), 16, port
);
130 scm_uintprint (SCM_UNPACK (exp
), 16, port
);
131 scm_putc ('>', port
);
138 #define SCM_SMOB_APPLY0(SMOB) \
139 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB)
140 #define SCM_SMOB_APPLY1(SMOB, A1) \
141 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1)
142 #define SCM_SMOB_APPLY2(SMOB, A1, A2) \
143 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2)
144 #define SCM_SMOB_APPLY3(SMOB, A1, A2, A3) \
145 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2, A3)
148 scm_smob_apply_0_010 (SCM smob
)
150 return SCM_SMOB_APPLY1 (smob
, SCM_UNDEFINED
);
154 scm_smob_apply_0_020 (SCM smob
)
156 return SCM_SMOB_APPLY2 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
);
160 scm_smob_apply_0_030 (SCM smob
)
162 return SCM_SMOB_APPLY3 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
, SCM_UNDEFINED
);
166 scm_smob_apply_0_001 (SCM smob
)
168 return SCM_SMOB_APPLY1 (smob
, SCM_EOL
);
172 scm_smob_apply_0_011 (SCM smob
)
174 return SCM_SMOB_APPLY2 (smob
, SCM_UNDEFINED
, SCM_EOL
);
178 scm_smob_apply_0_021 (SCM smob
)
180 return SCM_SMOB_APPLY3 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
, SCM_EOL
);
184 scm_smob_apply_0_error (SCM smob
)
186 scm_wrong_num_args (smob
);
190 scm_smob_apply_1_020 (SCM smob
, SCM a1
)
192 return SCM_SMOB_APPLY2 (smob
, a1
, SCM_UNDEFINED
);
196 scm_smob_apply_1_030 (SCM smob
, SCM a1
)
198 return SCM_SMOB_APPLY3 (smob
, a1
, SCM_UNDEFINED
, SCM_UNDEFINED
);
202 scm_smob_apply_1_001 (SCM smob
, SCM a1
)
204 return SCM_SMOB_APPLY1 (smob
, scm_list_1 (a1
));
208 scm_smob_apply_1_011 (SCM smob
, SCM a1
)
210 return SCM_SMOB_APPLY2 (smob
, a1
, SCM_EOL
);
214 scm_smob_apply_1_021 (SCM smob
, SCM a1
)
216 return SCM_SMOB_APPLY3 (smob
, a1
, SCM_UNDEFINED
, SCM_EOL
);
220 scm_smob_apply_1_error (SCM smob
, SCM a1 SCM_UNUSED
)
222 scm_wrong_num_args (smob
);
226 scm_smob_apply_2_030 (SCM smob
, SCM a1
, SCM a2
)
228 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_UNDEFINED
);
232 scm_smob_apply_2_001 (SCM smob
, SCM a1
, SCM a2
)
234 return SCM_SMOB_APPLY1 (smob
, scm_list_2 (a1
, a2
));
238 scm_smob_apply_2_011 (SCM smob
, SCM a1
, SCM a2
)
240 return SCM_SMOB_APPLY2 (smob
, a1
, scm_list_1 (a2
));
244 scm_smob_apply_2_021 (SCM smob
, SCM a1
, SCM a2
)
246 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_EOL
);
250 scm_smob_apply_2_error (SCM smob
, SCM a1 SCM_UNUSED
, SCM a2 SCM_UNUSED
)
252 scm_wrong_num_args (smob
);
256 scm_smob_apply_3_030 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
258 if (!scm_is_null (SCM_CDR (rst
)))
259 scm_wrong_num_args (smob
);
260 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_CAR (rst
));
264 scm_smob_apply_3_001 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
266 return SCM_SMOB_APPLY1 (smob
, scm_cons2 (a1
, a2
, rst
));
270 scm_smob_apply_3_011 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
272 return SCM_SMOB_APPLY2 (smob
, a1
, scm_cons (a2
, rst
));
276 scm_smob_apply_3_021 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
278 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, rst
);
282 scm_smob_apply_3_error (SCM smob
,
287 scm_wrong_num_args (smob
);
293 scm_make_smob_type (char const *name
, size_t size
)
294 #define FUNC_NAME "scm_make_smob_type"
298 SCM_CRITICAL_SECTION_START
;
299 new_smob
= scm_numsmob
;
300 if (scm_numsmob
!= MAX_SMOB_COUNT
)
302 SCM_CRITICAL_SECTION_END
;
304 if (new_smob
== MAX_SMOB_COUNT
)
305 scm_misc_error (FUNC_NAME
, "maximum number of smobs exceeded", SCM_EOL
);
307 scm_smobs
[new_smob
].name
= name
;
310 scm_smobs
[new_smob
].size
= size
;
311 scm_smobs
[new_smob
].free
= scm_smob_free
;
314 /* Make a class object if Goops is present. */
316 scm_smob_class
[new_smob
] = scm_make_extended_class (name
, 0);
318 return scm_tc7_smob
+ new_smob
* 256;
324 scm_set_smob_mark (scm_t_bits tc
, SCM (*mark
) (SCM
))
326 scm_smobs
[SCM_TC2SMOBNUM (tc
)].mark
= mark
;
330 scm_set_smob_free (scm_t_bits tc
, size_t (*free
) (SCM
))
332 scm_smobs
[SCM_TC2SMOBNUM (tc
)].free
= free
;
336 scm_set_smob_print (scm_t_bits tc
, int (*print
) (SCM
, SCM
, scm_print_state
*))
338 scm_smobs
[SCM_TC2SMOBNUM (tc
)].print
= print
;
342 scm_set_smob_equalp (scm_t_bits tc
, SCM (*equalp
) (SCM
, SCM
))
344 scm_smobs
[SCM_TC2SMOBNUM (tc
)].equalp
= equalp
;
348 scm_set_smob_apply (scm_t_bits tc
, SCM (*apply
) (),
349 unsigned int req
, unsigned int opt
, unsigned int rst
)
351 SCM (*apply_0
) (SCM
);
352 SCM (*apply_1
) (SCM
, SCM
);
353 SCM (*apply_2
) (SCM
, SCM
, SCM
);
354 SCM (*apply_3
) (SCM
, SCM
, SCM
, SCM
);
355 int type
= SCM_GSUBR_MAKTYPE (req
, opt
, rst
);
357 if (rst
> 1 || req
+ opt
+ rst
> 3)
359 puts ("Unsupported smob application type");
365 case SCM_GSUBR_MAKTYPE (0, 0, 0):
366 apply_0
= apply
; break;
367 case SCM_GSUBR_MAKTYPE (0, 1, 0):
368 apply_0
= scm_smob_apply_0_010
; break;
369 case SCM_GSUBR_MAKTYPE (0, 2, 0):
370 apply_0
= scm_smob_apply_0_020
; break;
371 case SCM_GSUBR_MAKTYPE (0, 3, 0):
372 apply_0
= scm_smob_apply_0_030
; break;
373 case SCM_GSUBR_MAKTYPE (0, 0, 1):
374 apply_0
= scm_smob_apply_0_001
; break;
375 case SCM_GSUBR_MAKTYPE (0, 1, 1):
376 apply_0
= scm_smob_apply_0_011
; break;
377 case SCM_GSUBR_MAKTYPE (0, 2, 1):
378 apply_0
= scm_smob_apply_0_021
; break;
380 apply_0
= scm_smob_apply_0_error
; break;
385 case SCM_GSUBR_MAKTYPE (1, 0, 0):
386 case SCM_GSUBR_MAKTYPE (0, 1, 0):
387 apply_1
= apply
; break;
388 case SCM_GSUBR_MAKTYPE (1, 1, 0):
389 case SCM_GSUBR_MAKTYPE (0, 2, 0):
390 apply_1
= scm_smob_apply_1_020
; break;
391 case SCM_GSUBR_MAKTYPE (1, 2, 0):
392 case SCM_GSUBR_MAKTYPE (0, 3, 0):
393 apply_1
= scm_smob_apply_1_030
; break;
394 case SCM_GSUBR_MAKTYPE (0, 0, 1):
395 apply_1
= scm_smob_apply_1_001
; break;
396 case SCM_GSUBR_MAKTYPE (1, 0, 1):
397 case SCM_GSUBR_MAKTYPE (0, 1, 1):
398 apply_1
= scm_smob_apply_1_011
; break;
399 case SCM_GSUBR_MAKTYPE (1, 1, 1):
400 case SCM_GSUBR_MAKTYPE (0, 2, 1):
401 apply_1
= scm_smob_apply_1_021
; break;
403 apply_1
= scm_smob_apply_1_error
; break;
408 case SCM_GSUBR_MAKTYPE (2, 0, 0):
409 case SCM_GSUBR_MAKTYPE (1, 1, 0):
410 case SCM_GSUBR_MAKTYPE (0, 2, 0):
411 apply_2
= apply
; break;
412 case SCM_GSUBR_MAKTYPE (2, 1, 0):
413 case SCM_GSUBR_MAKTYPE (1, 2, 0):
414 case SCM_GSUBR_MAKTYPE (0, 3, 0):
415 apply_2
= scm_smob_apply_2_030
; break;
416 case SCM_GSUBR_MAKTYPE (0, 0, 1):
417 apply_2
= scm_smob_apply_2_001
; break;
418 case SCM_GSUBR_MAKTYPE (1, 0, 1):
419 case SCM_GSUBR_MAKTYPE (0, 1, 1):
420 apply_2
= scm_smob_apply_2_011
; break;
421 case SCM_GSUBR_MAKTYPE (2, 0, 1):
422 case SCM_GSUBR_MAKTYPE (1, 1, 1):
423 case SCM_GSUBR_MAKTYPE (0, 2, 1):
424 apply_2
= scm_smob_apply_2_021
; break;
426 apply_2
= scm_smob_apply_2_error
; break;
431 case SCM_GSUBR_MAKTYPE (3, 0, 0):
432 case SCM_GSUBR_MAKTYPE (2, 1, 0):
433 case SCM_GSUBR_MAKTYPE (1, 2, 0):
434 case SCM_GSUBR_MAKTYPE (0, 3, 0):
435 apply_3
= scm_smob_apply_3_030
; break;
436 case SCM_GSUBR_MAKTYPE (0, 0, 1):
437 apply_3
= scm_smob_apply_3_001
; break;
438 case SCM_GSUBR_MAKTYPE (1, 0, 1):
439 case SCM_GSUBR_MAKTYPE (0, 1, 1):
440 apply_3
= scm_smob_apply_3_011
; break;
441 case SCM_GSUBR_MAKTYPE (2, 0, 1):
442 case SCM_GSUBR_MAKTYPE (1, 1, 1):
443 case SCM_GSUBR_MAKTYPE (0, 2, 1):
444 apply_3
= scm_smob_apply_3_021
; break;
446 apply_3
= scm_smob_apply_3_error
; break;
449 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply
= apply
;
450 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_0
= apply_0
;
451 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_1
= apply_1
;
452 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_2
= apply_2
;
453 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_3
= apply_3
;
454 scm_smobs
[SCM_TC2SMOBNUM (tc
)].gsubr_type
= type
;
457 scm_i_inherit_applicable (scm_smob_class
[SCM_TC2SMOBNUM (tc
)]);
461 scm_make_smob (scm_t_bits tc
)
463 scm_t_bits n
= SCM_TC2SMOBNUM (tc
);
464 size_t size
= scm_smobs
[n
].size
;
465 scm_t_bits data
= (size
> 0
466 ? (scm_t_bits
) scm_gc_malloc (size
, SCM_SMOBNAME (n
))
469 SCM_RETURN_NEWSMOB (tc
, data
);
473 /* {Initialization for the type of free cells}
477 free_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
480 sprintf (buf
, "#<freed cell %p; GC missed a reference>",
481 (void *) SCM_UNPACK (exp
));
482 scm_puts (buf
, port
);
484 #if (SCM_DEBUG_CELL_ACCESSES == 1)
485 if (scm_debug_cell_accesses_p
)
494 /* Marking SMOBs using user-supplied mark procedures. */
497 /* The freelist and GC kind used for SMOB types that provide a custom mark
499 static void **smob_freelist
= NULL
;
500 static int smob_gc_kind
= 0;
503 /* The generic SMOB mark procedure that gets called for SMOBs allocated with
504 `scm_i_new_smob_with_mark_proc ()'. */
505 static struct GC_ms_entry
*
506 smob_mark (GC_word
*addr
, struct GC_ms_entry
*mark_stack_ptr
,
507 struct GC_ms_entry
*mark_stack_limit
, GC_word env
)
510 register scm_t_bits tc
, smobnum
;
512 cell
= PTR2SCM (addr
);
514 if (SCM_TYP7 (cell
) != scm_tc7_smob
)
515 /* It is likely that the GC passed us a pointer to a free-list element
516 which we must ignore (see warning in `gc/gc_mark.h'). */
517 return mark_stack_ptr
;
519 tc
= SCM_CELL_WORD_0 (cell
);
520 smobnum
= SCM_TC2SMOBNUM (tc
);
522 if (smobnum
>= scm_numsmob
)
523 /* The first word looks corrupt. */
526 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_1 (cell
)),
528 mark_stack_limit
, NULL
);
529 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_2 (cell
)),
531 mark_stack_limit
, NULL
);
532 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_3 (cell
)),
534 mark_stack_limit
, NULL
);
536 if (scm_smobs
[smobnum
].mark
)
540 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
541 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= mark_stack_limit
;
543 /* Invoke the SMOB's mark procedure, which will in turn invoke
544 `scm_gc_mark ()', which may modify `current_mark_stack_ptr'. */
545 obj
= scm_smobs
[smobnum
].mark (cell
);
547 mark_stack_ptr
= SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
;
550 /* Mark the returned object. */
551 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (obj
),
553 mark_stack_limit
, NULL
);
555 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= NULL
;
556 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= NULL
;
559 return mark_stack_ptr
;
563 /* Mark object O. We assume that this function is only called during the
564 mark phase, i.e., from within `smob_mark ()' or one of its
569 #define CURRENT_MARK_PTR \
570 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_ptr))
571 #define CURRENT_MARK_LIMIT \
572 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_limit))
576 /* At this point, the `current_mark_*' fields of the current thread
577 must be defined (they are set in `smob_mark ()'). */
578 register struct GC_ms_entry
*mark_stack_ptr
;
580 if (!CURRENT_MARK_PTR
)
581 /* The function was not called from a mark procedure. */
584 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (o
),
585 CURRENT_MARK_PTR
, CURRENT_MARK_LIMIT
,
587 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
589 #undef CURRENT_MARK_PTR
590 #undef CURRENT_MARK_LIMIT
593 /* Return a SMOB with typecode TC. The SMOB type corresponding to TC may
594 provide a custom mark procedure and it will be honored. */
596 scm_i_new_smob_with_mark_proc (scm_t_bits tc
, scm_t_bits data1
,
597 scm_t_bits data2
, scm_t_bits data3
)
599 /* Return a double cell. */
600 SCM cell
= SCM_PACK (GC_generic_malloc (2 * sizeof (scm_t_cell
),
603 SCM_SET_CELL_WORD_3 (cell
, data3
);
604 SCM_SET_CELL_WORD_2 (cell
, data2
);
605 SCM_SET_CELL_WORD_1 (cell
, data1
);
606 SCM_SET_CELL_WORD_0 (cell
, tc
);
612 /* Finalize SMOB by calling its SMOB type's free function, if any. */
614 scm_i_finalize_smob (GC_PTR ptr
, GC_PTR data
)
617 size_t (* free_smob
) (SCM
);
619 smob
= PTR2SCM (ptr
);
621 printf ("finalizing SMOB %p (smobnum: %u)\n",
622 ptr
, SCM_SMOBNUM (smob
));
625 free_smob
= scm_smobs
[SCM_SMOBNUM (smob
)].free
;
632 scm_smob_prehistory ()
637 smob_freelist
= GC_new_free_list ();
638 smob_gc_kind
= GC_new_kind ((void **)smob_freelist
,
639 GC_MAKE_PROC (GC_new_proc (smob_mark
), 0),
643 for (i
= 0; i
< MAX_SMOB_COUNT
; ++i
)
645 scm_smobs
[i
].name
= 0;
646 scm_smobs
[i
].size
= 0;
647 scm_smobs
[i
].mark
= 0;
648 scm_smobs
[i
].free
= 0;
649 scm_smobs
[i
].print
= scm_smob_print
;
650 scm_smobs
[i
].equalp
= 0;
651 scm_smobs
[i
].apply
= 0;
652 scm_smobs
[i
].apply_0
= 0;
653 scm_smobs
[i
].apply_1
= 0;
654 scm_smobs
[i
].apply_2
= 0;
655 scm_smobs
[i
].apply_3
= 0;
656 scm_smobs
[i
].gsubr_type
= 0;
659 /* WARNING: This scm_make_smob_type call must be done first. */
660 tc
= scm_make_smob_type ("free", 0);
661 scm_set_smob_print (tc
, free_print
);