1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009 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 License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * 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
28 #include "libguile/_scm.h"
30 #include "libguile/async.h"
31 #include "libguile/objects.h"
32 #include "libguile/goops.h"
33 #include "libguile/ports.h"
39 #include "libguile/smob.h"
41 #include "libguile/bdw-gc.h"
42 #include <gc/gc_mark.h>
47 /* scm_smobs scm_numsmob
48 * implement a fixed sized array of smob records.
49 * Indexes into this table are used when generating type
50 * tags for smobjects (if you know a tag you can get an index and conversely).
53 #define MAX_SMOB_COUNT SCM_I_MAX_SMOB_TYPE_COUNT
56 scm_smob_descriptor scm_smobs
[MAX_SMOB_COUNT
];
58 /* Lower 16 bit of data must be zero.
61 scm_i_set_smob_flags (SCM x
, scm_t_bits data
)
63 SCM_SET_CELL_WORD_0 (x
, (SCM_CELL_WORD_0 (x
) & 0xFFFF) | data
);
67 scm_assert_smob_type (scm_t_bits tag
, SCM val
)
69 if (!SCM_SMOB_PREDICATE (tag
, val
))
70 scm_wrong_type_arg_msg (NULL
, 0, val
, scm_smobs
[SCM_TC2SMOBNUM(tag
)].name
);
76 /* This function is vestigial. It used to be the mark function's
77 responsibility to set the mark bit on the smob or port, but now the
78 generic marking routine in gc.c takes care of that, and a zero
79 pointer for a mark function means "don't bother". So you never
82 However, we leave it here because it's harmless to call it, and
83 people out there have smob code that uses it, and there's no reason
84 to make their links fail. */
87 scm_mark0 (SCM ptr SCM_UNUSED
)
93 /* Dirk::FIXME: The name markcdr is misleading, since the term cdr should only
94 be used for real pairs. */
97 return SCM_CELL_OBJECT_1 (ptr
);
105 scm_free0 (SCM ptr SCM_UNUSED
)
115 scm_smob_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
117 long n
= SCM_SMOBNUM (exp
);
118 scm_puts ("#<", port
);
119 scm_puts (SCM_SMOBNAME (n
) ? SCM_SMOBNAME (n
) : "smob", port
);
120 scm_putc (' ', port
);
121 if (scm_smobs
[n
].size
)
122 scm_uintprint (SCM_CELL_WORD_1 (exp
), 16, port
);
124 scm_uintprint (SCM_UNPACK (exp
), 16, port
);
125 scm_putc ('>', port
);
132 #define SCM_SMOB_APPLY0(SMOB) \
133 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB)
134 #define SCM_SMOB_APPLY1(SMOB, A1) \
135 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1)
136 #define SCM_SMOB_APPLY2(SMOB, A1, A2) \
137 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2)
138 #define SCM_SMOB_APPLY3(SMOB, A1, A2, A3) \
139 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2, A3)
142 scm_smob_apply_0_010 (SCM smob
)
144 return SCM_SMOB_APPLY1 (smob
, SCM_UNDEFINED
);
148 scm_smob_apply_0_020 (SCM smob
)
150 return SCM_SMOB_APPLY2 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
);
154 scm_smob_apply_0_030 (SCM smob
)
156 return SCM_SMOB_APPLY3 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
, SCM_UNDEFINED
);
160 scm_smob_apply_0_001 (SCM smob
)
162 return SCM_SMOB_APPLY1 (smob
, SCM_EOL
);
166 scm_smob_apply_0_011 (SCM smob
)
168 return SCM_SMOB_APPLY2 (smob
, SCM_UNDEFINED
, SCM_EOL
);
172 scm_smob_apply_0_021 (SCM smob
)
174 return SCM_SMOB_APPLY3 (smob
, SCM_UNDEFINED
, SCM_UNDEFINED
, SCM_EOL
);
178 scm_smob_apply_0_error (SCM smob
)
180 scm_wrong_num_args (smob
);
184 scm_smob_apply_1_020 (SCM smob
, SCM a1
)
186 return SCM_SMOB_APPLY2 (smob
, a1
, SCM_UNDEFINED
);
190 scm_smob_apply_1_030 (SCM smob
, SCM a1
)
192 return SCM_SMOB_APPLY3 (smob
, a1
, SCM_UNDEFINED
, SCM_UNDEFINED
);
196 scm_smob_apply_1_001 (SCM smob
, SCM a1
)
198 return SCM_SMOB_APPLY1 (smob
, scm_list_1 (a1
));
202 scm_smob_apply_1_011 (SCM smob
, SCM a1
)
204 return SCM_SMOB_APPLY2 (smob
, a1
, SCM_EOL
);
208 scm_smob_apply_1_021 (SCM smob
, SCM a1
)
210 return SCM_SMOB_APPLY3 (smob
, a1
, SCM_UNDEFINED
, SCM_EOL
);
214 scm_smob_apply_1_error (SCM smob
, SCM a1 SCM_UNUSED
)
216 scm_wrong_num_args (smob
);
220 scm_smob_apply_2_030 (SCM smob
, SCM a1
, SCM a2
)
222 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_UNDEFINED
);
226 scm_smob_apply_2_001 (SCM smob
, SCM a1
, SCM a2
)
228 return SCM_SMOB_APPLY1 (smob
, scm_list_2 (a1
, a2
));
232 scm_smob_apply_2_011 (SCM smob
, SCM a1
, SCM a2
)
234 return SCM_SMOB_APPLY2 (smob
, a1
, scm_list_1 (a2
));
238 scm_smob_apply_2_021 (SCM smob
, SCM a1
, SCM a2
)
240 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_EOL
);
244 scm_smob_apply_2_error (SCM smob
, SCM a1 SCM_UNUSED
, SCM a2 SCM_UNUSED
)
246 scm_wrong_num_args (smob
);
250 scm_smob_apply_3_030 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
252 if (!scm_is_null (SCM_CDR (rst
)))
253 scm_wrong_num_args (smob
);
254 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, SCM_CAR (rst
));
258 scm_smob_apply_3_001 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
260 return SCM_SMOB_APPLY1 (smob
, scm_cons2 (a1
, a2
, rst
));
264 scm_smob_apply_3_011 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
266 return SCM_SMOB_APPLY2 (smob
, a1
, scm_cons (a2
, rst
));
270 scm_smob_apply_3_021 (SCM smob
, SCM a1
, SCM a2
, SCM rst
)
272 return SCM_SMOB_APPLY3 (smob
, a1
, a2
, rst
);
276 scm_smob_apply_3_error (SCM smob
,
281 scm_wrong_num_args (smob
);
287 scm_make_smob_type (char const *name
, size_t size
)
288 #define FUNC_NAME "scm_make_smob_type"
292 SCM_CRITICAL_SECTION_START
;
293 new_smob
= scm_numsmob
;
294 if (scm_numsmob
!= MAX_SMOB_COUNT
)
296 SCM_CRITICAL_SECTION_END
;
298 if (new_smob
== MAX_SMOB_COUNT
)
299 scm_misc_error (FUNC_NAME
, "maximum number of smobs exceeded", SCM_EOL
);
301 scm_smobs
[new_smob
].name
= name
;
302 scm_smobs
[new_smob
].size
= size
;
304 /* Make a class object if Goops is present. */
305 if (SCM_UNPACK (scm_smob_class
[0]) != 0)
306 scm_smob_class
[new_smob
] = scm_make_extended_class (name
, 0);
308 return scm_tc7_smob
+ new_smob
* 256;
314 scm_set_smob_mark (scm_t_bits tc
, SCM (*mark
) (SCM
))
316 scm_smobs
[SCM_TC2SMOBNUM (tc
)].mark
= mark
;
320 scm_set_smob_free (scm_t_bits tc
, size_t (*free
) (SCM
))
322 scm_smobs
[SCM_TC2SMOBNUM (tc
)].free
= free
;
326 scm_set_smob_print (scm_t_bits tc
, int (*print
) (SCM
, SCM
, scm_print_state
*))
328 scm_smobs
[SCM_TC2SMOBNUM (tc
)].print
= print
;
332 scm_set_smob_equalp (scm_t_bits tc
, SCM (*equalp
) (SCM
, SCM
))
334 scm_smobs
[SCM_TC2SMOBNUM (tc
)].equalp
= equalp
;
338 scm_set_smob_apply (scm_t_bits tc
, SCM (*apply
) (),
339 unsigned int req
, unsigned int opt
, unsigned int rst
)
341 SCM (*apply_0
) (SCM
);
342 SCM (*apply_1
) (SCM
, SCM
);
343 SCM (*apply_2
) (SCM
, SCM
, SCM
);
344 SCM (*apply_3
) (SCM
, SCM
, SCM
, SCM
);
345 int type
= SCM_GSUBR_MAKTYPE (req
, opt
, rst
);
347 if (rst
> 1 || req
+ opt
+ rst
> 3)
349 puts ("Unsupported smob application type");
355 case SCM_GSUBR_MAKTYPE (0, 0, 0):
356 apply_0
= apply
; break;
357 case SCM_GSUBR_MAKTYPE (0, 1, 0):
358 apply_0
= scm_smob_apply_0_010
; break;
359 case SCM_GSUBR_MAKTYPE (0, 2, 0):
360 apply_0
= scm_smob_apply_0_020
; break;
361 case SCM_GSUBR_MAKTYPE (0, 3, 0):
362 apply_0
= scm_smob_apply_0_030
; break;
363 case SCM_GSUBR_MAKTYPE (0, 0, 1):
364 apply_0
= scm_smob_apply_0_001
; break;
365 case SCM_GSUBR_MAKTYPE (0, 1, 1):
366 apply_0
= scm_smob_apply_0_011
; break;
367 case SCM_GSUBR_MAKTYPE (0, 2, 1):
368 apply_0
= scm_smob_apply_0_021
; break;
370 apply_0
= scm_smob_apply_0_error
; break;
375 case SCM_GSUBR_MAKTYPE (1, 0, 0):
376 case SCM_GSUBR_MAKTYPE (0, 1, 0):
377 apply_1
= apply
; break;
378 case SCM_GSUBR_MAKTYPE (1, 1, 0):
379 case SCM_GSUBR_MAKTYPE (0, 2, 0):
380 apply_1
= scm_smob_apply_1_020
; break;
381 case SCM_GSUBR_MAKTYPE (1, 2, 0):
382 case SCM_GSUBR_MAKTYPE (0, 3, 0):
383 apply_1
= scm_smob_apply_1_030
; break;
384 case SCM_GSUBR_MAKTYPE (0, 0, 1):
385 apply_1
= scm_smob_apply_1_001
; break;
386 case SCM_GSUBR_MAKTYPE (1, 0, 1):
387 case SCM_GSUBR_MAKTYPE (0, 1, 1):
388 apply_1
= scm_smob_apply_1_011
; break;
389 case SCM_GSUBR_MAKTYPE (1, 1, 1):
390 case SCM_GSUBR_MAKTYPE (0, 2, 1):
391 apply_1
= scm_smob_apply_1_021
; break;
393 apply_1
= scm_smob_apply_1_error
; break;
398 case SCM_GSUBR_MAKTYPE (2, 0, 0):
399 case SCM_GSUBR_MAKTYPE (1, 1, 0):
400 case SCM_GSUBR_MAKTYPE (0, 2, 0):
401 apply_2
= apply
; break;
402 case SCM_GSUBR_MAKTYPE (2, 1, 0):
403 case SCM_GSUBR_MAKTYPE (1, 2, 0):
404 case SCM_GSUBR_MAKTYPE (0, 3, 0):
405 apply_2
= scm_smob_apply_2_030
; break;
406 case SCM_GSUBR_MAKTYPE (0, 0, 1):
407 apply_2
= scm_smob_apply_2_001
; break;
408 case SCM_GSUBR_MAKTYPE (1, 0, 1):
409 case SCM_GSUBR_MAKTYPE (0, 1, 1):
410 apply_2
= scm_smob_apply_2_011
; break;
411 case SCM_GSUBR_MAKTYPE (2, 0, 1):
412 case SCM_GSUBR_MAKTYPE (1, 1, 1):
413 case SCM_GSUBR_MAKTYPE (0, 2, 1):
414 apply_2
= scm_smob_apply_2_021
; break;
416 apply_2
= scm_smob_apply_2_error
; break;
421 case SCM_GSUBR_MAKTYPE (3, 0, 0):
422 case SCM_GSUBR_MAKTYPE (2, 1, 0):
423 case SCM_GSUBR_MAKTYPE (1, 2, 0):
424 case SCM_GSUBR_MAKTYPE (0, 3, 0):
425 apply_3
= scm_smob_apply_3_030
; break;
426 case SCM_GSUBR_MAKTYPE (0, 0, 1):
427 apply_3
= scm_smob_apply_3_001
; break;
428 case SCM_GSUBR_MAKTYPE (1, 0, 1):
429 case SCM_GSUBR_MAKTYPE (0, 1, 1):
430 apply_3
= scm_smob_apply_3_011
; break;
431 case SCM_GSUBR_MAKTYPE (2, 0, 1):
432 case SCM_GSUBR_MAKTYPE (1, 1, 1):
433 case SCM_GSUBR_MAKTYPE (0, 2, 1):
434 apply_3
= scm_smob_apply_3_021
; break;
436 apply_3
= scm_smob_apply_3_error
; break;
439 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply
= apply
;
440 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_0
= apply_0
;
441 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_1
= apply_1
;
442 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_2
= apply_2
;
443 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_3
= apply_3
;
444 scm_smobs
[SCM_TC2SMOBNUM (tc
)].gsubr_type
= type
;
446 if (SCM_UNPACK (scm_smob_class
[0]) != 0)
447 scm_i_inherit_applicable (scm_smob_class
[SCM_TC2SMOBNUM (tc
)]);
451 scm_make_smob (scm_t_bits tc
)
453 scm_t_bits n
= SCM_TC2SMOBNUM (tc
);
454 size_t size
= scm_smobs
[n
].size
;
455 scm_t_bits data
= (size
> 0
456 ? (scm_t_bits
) scm_gc_malloc (size
, SCM_SMOBNAME (n
))
459 SCM_RETURN_NEWSMOB (tc
, data
);
464 /* Marking SMOBs using user-supplied mark procedures. */
467 /* The GC kind used for SMOB types that provide a custom mark procedure. */
468 static int smob_gc_kind
;
471 /* The generic SMOB mark procedure that gets called for SMOBs allocated with
472 `scm_i_new_smob_with_mark_proc ()'. */
473 static struct GC_ms_entry
*
474 smob_mark (GC_word
*addr
, struct GC_ms_entry
*mark_stack_ptr
,
475 struct GC_ms_entry
*mark_stack_limit
, GC_word env
)
478 register scm_t_bits tc
, smobnum
;
480 cell
= PTR2SCM (addr
);
482 if (SCM_TYP7 (cell
) != scm_tc7_smob
)
483 /* It is likely that the GC passed us a pointer to a free-list element
484 which we must ignore (see warning in `gc/gc_mark.h'). */
485 return mark_stack_ptr
;
487 tc
= SCM_CELL_WORD_0 (cell
);
488 smobnum
= SCM_TC2SMOBNUM (tc
);
490 if (smobnum
>= scm_numsmob
)
491 /* The first word looks corrupt. */
494 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_1 (cell
)),
496 mark_stack_limit
, NULL
);
497 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_2 (cell
)),
499 mark_stack_limit
, NULL
);
500 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_3 (cell
)),
502 mark_stack_limit
, NULL
);
504 if (scm_smobs
[smobnum
].mark
)
508 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
509 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= mark_stack_limit
;
511 /* Invoke the SMOB's mark procedure, which will in turn invoke
512 `scm_gc_mark ()', which may modify `current_mark_stack_ptr'. */
513 obj
= scm_smobs
[smobnum
].mark (cell
);
515 mark_stack_ptr
= SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
;
518 /* Mark the returned object. */
519 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (obj
),
521 mark_stack_limit
, NULL
);
523 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= NULL
;
524 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= NULL
;
527 return mark_stack_ptr
;
531 /* Mark object O. We assume that this function is only called during the
532 mark phase, i.e., from within `smob_mark ()' or one of its
537 #define CURRENT_MARK_PTR \
538 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_ptr))
539 #define CURRENT_MARK_LIMIT \
540 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_limit))
544 /* At this point, the `current_mark_*' fields of the current thread
545 must be defined (they are set in `smob_mark ()'). */
546 register struct GC_ms_entry
*mark_stack_ptr
;
548 if (!CURRENT_MARK_PTR
)
549 /* The function was not called from a mark procedure. */
552 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (o
),
553 CURRENT_MARK_PTR
, CURRENT_MARK_LIMIT
,
555 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
557 #undef CURRENT_MARK_PTR
558 #undef CURRENT_MARK_LIMIT
561 /* Return a SMOB with typecode TC. The SMOB type corresponding to TC may
562 provide a custom mark procedure and it will be honored. */
564 scm_i_new_smob_with_mark_proc (scm_t_bits tc
, scm_t_bits data1
,
565 scm_t_bits data2
, scm_t_bits data3
)
567 /* Return a double cell. */
568 SCM cell
= SCM_PACK (GC_generic_malloc (2 * sizeof (scm_t_cell
),
571 SCM_SET_CELL_WORD_3 (cell
, data3
);
572 SCM_SET_CELL_WORD_2 (cell
, data2
);
573 SCM_SET_CELL_WORD_1 (cell
, data1
);
574 SCM_SET_CELL_WORD_0 (cell
, tc
);
580 /* Finalize SMOB by calling its SMOB type's free function, if any. */
582 scm_i_finalize_smob (GC_PTR ptr
, GC_PTR data
)
585 size_t (* free_smob
) (SCM
);
587 smob
= PTR2SCM (ptr
);
589 printf ("finalizing SMOB %p (smobnum: %u)\n",
590 ptr
, SCM_SMOBNUM (smob
));
593 free_smob
= scm_smobs
[SCM_SMOBNUM (smob
)].free
;
600 scm_smob_prehistory ()
604 smob_gc_kind
= GC_new_kind (GC_new_free_list (),
605 GC_MAKE_PROC (GC_new_proc (smob_mark
), 0),
607 /* Clear new objects. As of version 7.1, libgc
608 doesn't seem to support passing 0 here. */
612 for (i
= 0; i
< MAX_SMOB_COUNT
; ++i
)
614 scm_smobs
[i
].name
= 0;
615 scm_smobs
[i
].size
= 0;
616 scm_smobs
[i
].mark
= 0;
617 scm_smobs
[i
].free
= 0;
618 scm_smobs
[i
].print
= scm_smob_print
;
619 scm_smobs
[i
].equalp
= 0;
620 scm_smobs
[i
].apply
= 0;
621 scm_smobs
[i
].apply_0
= 0;
622 scm_smobs
[i
].apply_1
= 0;
623 scm_smobs
[i
].apply_2
= 0;
624 scm_smobs
[i
].apply_3
= 0;
625 scm_smobs
[i
].gsubr_type
= 0;