Synchronized docstrings.
[bpt/guile.git] / libguile / smob.c
CommitLineData
197b0573 1/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
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.
0f2d19dd 7 *
73be1d9e
MV
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.
0f2d19dd 12 *
73be1d9e
MV
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
f9fe039d
RB
20#if HAVE_CONFIG_H
21# include <config.h>
22#endif
0f2d19dd
JB
23
24#include <stdio.h>
e6e2e95a
MD
25#include <errno.h>
26
a0599745 27#include "libguile/_scm.h"
20e6290e 28
a0599745 29#include "libguile/objects.h"
9511876f 30#include "libguile/goops.h"
a0599745 31#include "libguile/ports.h"
d7ec6b9f 32
0f2d19dd
JB
33#ifdef HAVE_MALLOC_H
34#include <malloc.h>
35#endif
36
a0599745 37#include "libguile/smob.h"
9dd5943c 38
0f2d19dd
JB
39\f
40
41/* scm_smobs scm_numsmob
7a7f7c53 42 * implement a fixed sized array of smob records.
0f2d19dd
JB
43 * Indexes into this table are used when generating type
44 * tags for smobjects (if you know a tag you can get an index and conversely).
45 */
7a7f7c53
DH
46
47#define MAX_SMOB_COUNT 256
c014a02e 48long scm_numsmob;
7a7f7c53 49scm_smob_descriptor scm_smobs[MAX_SMOB_COUNT];
0f2d19dd 50
37fc18ae
MV
51/* Lower 16 bit of data must be zero.
52*/
53void
54scm_i_set_smob_flags (SCM x, scm_t_bits data)
55{
56 SCM_SET_CELL_WORD_0 (x, (SCM_CELL_WORD_0 (x) & 0xFFFF) | data);
57}
58
197b0573
MV
59void
60scm_assert_smob_type (scm_t_bits tag, SCM val)
61{
62 if (!SCM_SMOB_PREDICATE (tag, val))
63 scm_wrong_type_arg_msg (NULL, 0, val, scm_smobs[SCM_TC2SMOBNUM(tag)].name);
64}
65
9dd5943c
MD
66/* {Mark}
67 */
68
69/* This function is vestigial. It used to be the mark function's
70 responsibility to set the mark bit on the smob or port, but now the
71 generic marking routine in gc.c takes care of that, and a zero
72 pointer for a mark function means "don't bother". So you never
73 need scm_mark0.
74
75 However, we leave it here because it's harmless to call it, and
76 people out there have smob code that uses it, and there's no reason
77 to make their links fail. */
78
79SCM
e81d98ec 80scm_mark0 (SCM ptr SCM_UNUSED)
9dd5943c
MD
81{
82 return SCM_BOOL_F;
83}
84
85SCM
22a52da1
DH
86/* Dirk::FIXME: The name markcdr is misleading, since the term cdr should only
87 be used for real pairs. */
6e8d25a6 88scm_markcdr (SCM ptr)
9dd5943c 89{
22a52da1 90 return SCM_CELL_OBJECT_1 (ptr);
9dd5943c
MD
91}
92
93/* {Free}
94 */
95
1be6b49c 96size_t
e81d98ec 97scm_free0 (SCM ptr SCM_UNUSED)
9dd5943c
MD
98{
99 return 0;
100}
101
1be6b49c 102size_t
9dd5943c
MD
103scm_smob_free (SCM obj)
104{
4c9419ac
MV
105 long n = SCM_SMOBNUM (obj);
106 if (scm_smobs[n].size > 0)
107 scm_gc_free ((void *) SCM_CELL_WORD_1 (obj),
108 scm_smobs[n].size, SCM_SMOBNAME (n));
109 return 0;
9dd5943c
MD
110}
111
112/* {Print}
113 */
114
115int
e81d98ec 116scm_smob_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
9dd5943c 117{
c014a02e 118 long n = SCM_SMOBNUM (exp);
9dd5943c 119 scm_puts ("#<", port);
2c16a78a 120 scm_puts (SCM_SMOBNAME (n) ? SCM_SMOBNAME (n) : "smob", port);
9dd5943c 121 scm_putc (' ', port);
7a7f7c53 122 if (scm_smobs[n].size)
0345e278 123 scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
7a7f7c53 124 else
0345e278 125 scm_uintprint (SCM_UNPACK (exp), 16, port);
9dd5943c
MD
126 scm_putc ('>', port);
127 return 1;
128}
1cc91f1b 129
0717dfd8
KN
130/* {Apply}
131 */
132
cb1c46c5
KN
133#define SCM_SMOB_APPLY0(SMOB) \
134 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB)
34d19ef6 135#define SCM_SMOB_APPLY1(SMOB, A1) \
cb1c46c5 136 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1)
34d19ef6 137#define SCM_SMOB_APPLY2(SMOB, A1, A2) \
cb1c46c5 138 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2)
34d19ef6 139#define SCM_SMOB_APPLY3(SMOB, A1, A2, A3) \
cb1c46c5
KN
140 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2, A3)
141
cb1c46c5
KN
142static SCM
143scm_smob_apply_0_010 (SCM smob)
0717dfd8 144{
cb1c46c5 145 return SCM_SMOB_APPLY1 (smob, SCM_UNDEFINED);
0717dfd8
KN
146}
147
cb1c46c5
KN
148static SCM
149scm_smob_apply_0_020 (SCM smob)
0717dfd8 150{
cb1c46c5 151 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
152}
153
cb1c46c5
KN
154static SCM
155scm_smob_apply_0_030 (SCM smob)
0717dfd8 156{
cb1c46c5 157 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
158}
159
cb1c46c5
KN
160static SCM
161scm_smob_apply_0_001 (SCM smob)
0717dfd8 162{
cb1c46c5
KN
163 return SCM_SMOB_APPLY1 (smob, SCM_EOL);
164}
165
166static SCM
167scm_smob_apply_0_011 (SCM smob)
168{
169 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_EOL);
170}
171
172static SCM
173scm_smob_apply_0_021 (SCM smob)
174{
175 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_EOL);
176}
177
178static SCM
179scm_smob_apply_0_error (SCM smob)
180{
181 scm_wrong_num_args (smob);
182}
183
cb1c46c5
KN
184static SCM
185scm_smob_apply_1_020 (SCM smob, SCM a1)
186{
187 return SCM_SMOB_APPLY2 (smob, a1, SCM_UNDEFINED);
188}
189
190static SCM
191scm_smob_apply_1_030 (SCM smob, SCM a1)
192{
193 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_UNDEFINED);
194}
195
196static SCM
197scm_smob_apply_1_001 (SCM smob, SCM a1)
198{
1afff620 199 return SCM_SMOB_APPLY1 (smob, scm_list_1 (a1));
cb1c46c5
KN
200}
201
202static SCM
203scm_smob_apply_1_011 (SCM smob, SCM a1)
204{
205 return SCM_SMOB_APPLY2 (smob, a1, SCM_EOL);
206}
207
208static SCM
209scm_smob_apply_1_021 (SCM smob, SCM a1)
210{
211 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_EOL);
212}
213
214static SCM
e81d98ec 215scm_smob_apply_1_error (SCM smob, SCM a1 SCM_UNUSED)
cb1c46c5
KN
216{
217 scm_wrong_num_args (smob);
218}
219
cb1c46c5
KN
220static SCM
221scm_smob_apply_2_030 (SCM smob, SCM a1, SCM a2)
222{
223 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_UNDEFINED);
224}
225
226static SCM
227scm_smob_apply_2_001 (SCM smob, SCM a1, SCM a2)
228{
1afff620 229 return SCM_SMOB_APPLY1 (smob, scm_list_2 (a1, a2));
7c58e21b 230}
cb1c46c5
KN
231
232static SCM
233scm_smob_apply_2_011 (SCM smob, SCM a1, SCM a2)
234{
1afff620 235 return SCM_SMOB_APPLY2 (smob, a1, scm_list_1 (a2));
cb1c46c5
KN
236}
237
238static SCM
239scm_smob_apply_2_021 (SCM smob, SCM a1, SCM a2)
240{
241 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_EOL);
242}
243
244static SCM
e81d98ec 245scm_smob_apply_2_error (SCM smob, SCM a1 SCM_UNUSED, SCM a2 SCM_UNUSED)
cb1c46c5
KN
246{
247 scm_wrong_num_args (smob);
248}
249
250static SCM
251scm_smob_apply_3_030 (SCM smob, SCM a1, SCM a2, SCM rst)
252{
d2e53ed6 253 if (!scm_is_null (SCM_CDR (rst)))
cb1c46c5
KN
254 scm_wrong_num_args (smob);
255 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_CAR (rst));
256}
257
258static SCM
259scm_smob_apply_3_001 (SCM smob, SCM a1, SCM a2, SCM rst)
260{
261 return SCM_SMOB_APPLY1 (smob, scm_cons2 (a1, a2, rst));
0717dfd8
KN
262}
263
cb1c46c5
KN
264static SCM
265scm_smob_apply_3_011 (SCM smob, SCM a1, SCM a2, SCM rst)
266{
267 return SCM_SMOB_APPLY2 (smob, a1, scm_cons (a2, rst));
268}
269
270static SCM
271scm_smob_apply_3_021 (SCM smob, SCM a1, SCM a2, SCM rst)
272{
273 return SCM_SMOB_APPLY3 (smob, a1, a2, rst);
274}
275
276static SCM
e81d98ec
DH
277scm_smob_apply_3_error (SCM smob,
278 SCM a1 SCM_UNUSED,
279 SCM a2 SCM_UNUSED,
280 SCM rst SCM_UNUSED)
cb1c46c5
KN
281{
282 scm_wrong_num_args (smob);
283}
284
285\f
7a7f7c53 286
92c2555f 287scm_t_bits
da0e6c2b 288scm_make_smob_type (char const *name, size_t size)
7a7f7c53 289#define FUNC_NAME "scm_make_smob_type"
0f2d19dd 290{
c014a02e 291 long new_smob;
7a7f7c53 292
9de87eea 293 SCM_CRITICAL_SECTION_START;
7a7f7c53
DH
294 new_smob = scm_numsmob;
295 if (scm_numsmob != MAX_SMOB_COUNT)
296 ++scm_numsmob;
9de87eea 297 SCM_CRITICAL_SECTION_END;
7a7f7c53
DH
298
299 if (new_smob == MAX_SMOB_COUNT)
300 scm_misc_error (FUNC_NAME, "maximum number of smobs exceeded", SCM_EOL);
301
302 scm_smobs[new_smob].name = name;
303 if (size != 0)
2500356c 304 {
7a7f7c53
DH
305 scm_smobs[new_smob].size = size;
306 scm_smobs[new_smob].free = scm_smob_free;
2500356c 307 }
7a7f7c53 308
d7ec6b9f
MD
309 /* Make a class object if Goops is present. */
310 if (scm_smob_class)
74b6d6e4 311 scm_smob_class[new_smob] = scm_make_extended_class (name, 0);
7a7f7c53
DH
312
313 return scm_tc7_smob + new_smob * 256;
0f2d19dd 314}
7a7f7c53
DH
315#undef FUNC_NAME
316
0f2d19dd 317
9dd5943c 318void
92c2555f 319scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM))
9dd5943c
MD
320{
321 scm_smobs[SCM_TC2SMOBNUM (tc)].mark = mark;
322}
323
324void
92c2555f 325scm_set_smob_free (scm_t_bits tc, size_t (*free) (SCM))
9dd5943c
MD
326{
327 scm_smobs[SCM_TC2SMOBNUM (tc)].free = free;
328}
329
330void
92c2555f 331scm_set_smob_print (scm_t_bits tc, int (*print) (SCM, SCM, scm_print_state*))
9dd5943c
MD
332{
333 scm_smobs[SCM_TC2SMOBNUM (tc)].print = print;
334}
335
336void
92c2555f 337scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
9dd5943c
MD
338{
339 scm_smobs[SCM_TC2SMOBNUM (tc)].equalp = equalp;
340}
341
0717dfd8 342void
92c2555f 343scm_set_smob_apply (scm_t_bits tc, SCM (*apply) (),
7c58e21b 344 unsigned int req, unsigned int opt, unsigned int rst)
0717dfd8 345{
cb1c46c5
KN
346 SCM (*apply_0) (SCM);
347 SCM (*apply_1) (SCM, SCM);
348 SCM (*apply_2) (SCM, SCM, SCM);
349 SCM (*apply_3) (SCM, SCM, SCM, SCM);
350 int type = SCM_GSUBR_MAKTYPE (req, opt, rst);
351
7c58e21b 352 if (rst > 1 || req + opt + rst > 3)
cb1c46c5
KN
353 {
354 puts ("Unsupported smob application type");
355 abort ();
356 }
357
358 switch (type)
359 {
360 case SCM_GSUBR_MAKTYPE (0, 0, 0):
7c58e21b 361 apply_0 = apply; break;
cb1c46c5
KN
362 case SCM_GSUBR_MAKTYPE (0, 1, 0):
363 apply_0 = scm_smob_apply_0_010; break;
364 case SCM_GSUBR_MAKTYPE (0, 2, 0):
365 apply_0 = scm_smob_apply_0_020; break;
366 case SCM_GSUBR_MAKTYPE (0, 3, 0):
367 apply_0 = scm_smob_apply_0_030; break;
368 case SCM_GSUBR_MAKTYPE (0, 0, 1):
369 apply_0 = scm_smob_apply_0_001; break;
370 case SCM_GSUBR_MAKTYPE (0, 1, 1):
371 apply_0 = scm_smob_apply_0_011; break;
372 case SCM_GSUBR_MAKTYPE (0, 2, 1):
373 apply_0 = scm_smob_apply_0_021; break;
374 default:
375 apply_0 = scm_smob_apply_0_error; break;
376 }
377
378 switch (type)
379 {
380 case SCM_GSUBR_MAKTYPE (1, 0, 0):
381 case SCM_GSUBR_MAKTYPE (0, 1, 0):
7c58e21b 382 apply_1 = apply; break;
cb1c46c5
KN
383 case SCM_GSUBR_MAKTYPE (1, 1, 0):
384 case SCM_GSUBR_MAKTYPE (0, 2, 0):
385 apply_1 = scm_smob_apply_1_020; break;
386 case SCM_GSUBR_MAKTYPE (1, 2, 0):
387 case SCM_GSUBR_MAKTYPE (0, 3, 0):
388 apply_1 = scm_smob_apply_1_030; break;
389 case SCM_GSUBR_MAKTYPE (0, 0, 1):
390 apply_1 = scm_smob_apply_1_001; break;
391 case SCM_GSUBR_MAKTYPE (1, 0, 1):
392 case SCM_GSUBR_MAKTYPE (0, 1, 1):
393 apply_1 = scm_smob_apply_1_011; break;
394 case SCM_GSUBR_MAKTYPE (1, 1, 1):
395 case SCM_GSUBR_MAKTYPE (0, 2, 1):
396 apply_1 = scm_smob_apply_1_021; break;
397 default:
398 apply_1 = scm_smob_apply_1_error; break;
399 }
400
401 switch (type)
402 {
403 case SCM_GSUBR_MAKTYPE (2, 0, 0):
404 case SCM_GSUBR_MAKTYPE (1, 1, 0):
405 case SCM_GSUBR_MAKTYPE (0, 2, 0):
7c58e21b 406 apply_2 = apply; break;
cb1c46c5
KN
407 case SCM_GSUBR_MAKTYPE (2, 1, 0):
408 case SCM_GSUBR_MAKTYPE (1, 2, 0):
409 case SCM_GSUBR_MAKTYPE (0, 3, 0):
410 apply_2 = scm_smob_apply_2_030; break;
411 case SCM_GSUBR_MAKTYPE (0, 0, 1):
412 apply_2 = scm_smob_apply_2_001; break;
413 case SCM_GSUBR_MAKTYPE (1, 0, 1):
414 case SCM_GSUBR_MAKTYPE (0, 1, 1):
415 apply_2 = scm_smob_apply_2_011; break;
416 case SCM_GSUBR_MAKTYPE (2, 0, 1):
417 case SCM_GSUBR_MAKTYPE (1, 1, 1):
418 case SCM_GSUBR_MAKTYPE (0, 2, 1):
419 apply_2 = scm_smob_apply_2_021; break;
420 default:
421 apply_2 = scm_smob_apply_2_error; break;
422 }
423
424 switch (type)
425 {
426 case SCM_GSUBR_MAKTYPE (3, 0, 0):
427 case SCM_GSUBR_MAKTYPE (2, 1, 0):
428 case SCM_GSUBR_MAKTYPE (1, 2, 0):
429 case SCM_GSUBR_MAKTYPE (0, 3, 0):
430 apply_3 = scm_smob_apply_3_030; break;
431 case SCM_GSUBR_MAKTYPE (0, 0, 1):
432 apply_3 = scm_smob_apply_3_001; break;
433 case SCM_GSUBR_MAKTYPE (1, 0, 1):
434 case SCM_GSUBR_MAKTYPE (0, 1, 1):
435 apply_3 = scm_smob_apply_3_011; break;
436 case SCM_GSUBR_MAKTYPE (2, 0, 1):
437 case SCM_GSUBR_MAKTYPE (1, 1, 1):
438 case SCM_GSUBR_MAKTYPE (0, 2, 1):
439 apply_3 = scm_smob_apply_3_021; break;
440 default:
441 apply_3 = scm_smob_apply_3_error; break;
442 }
443
03416a99 444 scm_smobs[SCM_TC2SMOBNUM (tc)].apply = apply;
cb1c46c5
KN
445 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_0 = apply_0;
446 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_1 = apply_1;
447 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_2 = apply_2;
448 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_3 = apply_3;
68b06924 449 scm_smobs[SCM_TC2SMOBNUM (tc)].gsubr_type = type;
74b6d6e4
MD
450
451 if (scm_smob_class)
452 scm_i_inherit_applicable (scm_smob_class[SCM_TC2SMOBNUM (tc)]);
0717dfd8
KN
453}
454
9dd5943c 455SCM
92c2555f 456scm_make_smob (scm_t_bits tc)
9dd5943c 457{
c014a02e 458 long n = SCM_TC2SMOBNUM (tc);
1be6b49c 459 size_t size = scm_smobs[n].size;
16d4699b 460 scm_t_bits data = (size > 0
4c9419ac 461 ? (scm_t_bits) scm_gc_malloc (size, SCM_SMOBNAME (n))
16d4699b 462 : 0);
228a24ef 463 return scm_cell (tc, data);
9dd5943c
MD
464}
465
ceef3208 466\f
534c55a9 467/* {Initialization for the type of free cells}
0f2d19dd
JB
468 */
469
ceef3208 470static int
e81d98ec 471free_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
ceef3208
JB
472{
473 char buf[100];
e841c3e0
KN
474 sprintf (buf, "#<freed cell %p; GC missed a reference>",
475 (void *) SCM_UNPACK (exp));
ceef3208 476 scm_puts (buf, port);
1e71eafb
HWN
477
478#if (SCM_DEBUG_CELL_ACCESSES == 1)
479 if (scm_debug_cell_accesses_p)
480 abort();
481#endif
482
ceef3208
JB
483
484 return 1;
485}
486
0f2d19dd
JB
487void
488scm_smob_prehistory ()
0f2d19dd 489{
c014a02e 490 long i;
92c2555f 491 scm_t_bits tc;
e841c3e0 492
0f2d19dd 493 scm_numsmob = 0;
7a7f7c53
DH
494 for (i = 0; i < MAX_SMOB_COUNT; ++i)
495 {
496 scm_smobs[i].name = 0;
497 scm_smobs[i].size = 0;
498 scm_smobs[i].mark = 0;
499 scm_smobs[i].free = 0;
500 scm_smobs[i].print = scm_smob_print;
501 scm_smobs[i].equalp = 0;
502 scm_smobs[i].apply = 0;
503 scm_smobs[i].apply_0 = 0;
504 scm_smobs[i].apply_1 = 0;
505 scm_smobs[i].apply_2 = 0;
506 scm_smobs[i].apply_3 = 0;
507 scm_smobs[i].gsubr_type = 0;
508 }
9dd5943c 509
534c55a9 510 /* WARNING: This scm_make_smob_type call must be done first. */
e841c3e0
KN
511 tc = scm_make_smob_type ("free", 0);
512 scm_set_smob_print (tc, free_print);
0f2d19dd 513}
89e00824
ML
514
515/*
516 Local Variables:
517 c-file-style: "gnu"
518 End:
519*/