* gc.h, gc.c (scm_gc_sweep): Issue deprecation warning when
[bpt/guile.git] / libguile / smob.c
CommitLineData
2ade72d7 1/* Copyright (C) 1995,1996,1998,1999,2000,2001 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84 41
1bbd0b84 42
0f2d19dd
JB
43\f
44
45#include <stdio.h>
e6e2e95a
MD
46#include <errno.h>
47
a0599745 48#include "libguile/_scm.h"
20e6290e 49
a0599745
MD
50#include "libguile/objects.h"
51#include "libguile/ports.h"
d7ec6b9f 52
0f2d19dd
JB
53#ifdef HAVE_MALLOC_H
54#include <malloc.h>
55#endif
56
a0599745 57#include "libguile/smob.h"
9dd5943c 58
0f2d19dd
JB
59\f
60
61/* scm_smobs scm_numsmob
7a7f7c53 62 * implement a fixed sized array of smob records.
0f2d19dd
JB
63 * Indexes into this table are used when generating type
64 * tags for smobjects (if you know a tag you can get an index and conversely).
65 */
7a7f7c53
DH
66
67#define MAX_SMOB_COUNT 256
c014a02e 68long scm_numsmob;
7a7f7c53 69scm_smob_descriptor scm_smobs[MAX_SMOB_COUNT];
0f2d19dd 70
9dd5943c
MD
71/* {Mark}
72 */
73
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
78 need scm_mark0.
79
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. */
83
84SCM
e81d98ec 85scm_mark0 (SCM ptr SCM_UNUSED)
9dd5943c
MD
86{
87 return SCM_BOOL_F;
88}
89
90SCM
22a52da1
DH
91/* Dirk::FIXME: The name markcdr is misleading, since the term cdr should only
92 be used for real pairs. */
6e8d25a6 93scm_markcdr (SCM ptr)
9dd5943c 94{
22a52da1 95 return SCM_CELL_OBJECT_1 (ptr);
9dd5943c
MD
96}
97
98/* {Free}
99 */
100
1be6b49c 101size_t
e81d98ec 102scm_free0 (SCM ptr SCM_UNUSED)
9dd5943c
MD
103{
104 return 0;
105}
106
1be6b49c 107size_t
9dd5943c
MD
108scm_smob_free (SCM obj)
109{
4c9419ac
MV
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));
114 return 0;
9dd5943c
MD
115}
116
117/* {Print}
118 */
119
120int
e81d98ec 121scm_smob_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
9dd5943c 122{
c014a02e 123 long n = SCM_SMOBNUM (exp);
9dd5943c 124 scm_puts ("#<", port);
2c16a78a 125 scm_puts (SCM_SMOBNAME (n) ? SCM_SMOBNAME (n) : "smob", port);
9dd5943c 126 scm_putc (' ', port);
7a7f7c53
DH
127 if (scm_smobs[n].size)
128 scm_intprint (SCM_CELL_WORD_1 (exp), 16, port);
129 else
130 scm_intprint (SCM_UNPACK (exp), 16, port);
9dd5943c
MD
131 scm_putc ('>', port);
132 return 1;
133}
1cc91f1b 134
0717dfd8
KN
135/* {Apply}
136 */
137
cb1c46c5
KN
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)
146
cb1c46c5
KN
147static SCM
148scm_smob_apply_0_010 (SCM smob)
0717dfd8 149{
cb1c46c5 150 return SCM_SMOB_APPLY1 (smob, SCM_UNDEFINED);
0717dfd8
KN
151}
152
cb1c46c5
KN
153static SCM
154scm_smob_apply_0_020 (SCM smob)
0717dfd8 155{
cb1c46c5 156 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
157}
158
cb1c46c5
KN
159static SCM
160scm_smob_apply_0_030 (SCM smob)
0717dfd8 161{
cb1c46c5 162 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
163}
164
cb1c46c5
KN
165static SCM
166scm_smob_apply_0_001 (SCM smob)
0717dfd8 167{
cb1c46c5
KN
168 return SCM_SMOB_APPLY1 (smob, SCM_EOL);
169}
170
171static SCM
172scm_smob_apply_0_011 (SCM smob)
173{
174 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_EOL);
175}
176
177static SCM
178scm_smob_apply_0_021 (SCM smob)
179{
180 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_EOL);
181}
182
183static SCM
184scm_smob_apply_0_error (SCM smob)
185{
186 scm_wrong_num_args (smob);
187}
188
cb1c46c5
KN
189static SCM
190scm_smob_apply_1_020 (SCM smob, SCM a1)
191{
192 return SCM_SMOB_APPLY2 (smob, a1, SCM_UNDEFINED);
193}
194
195static SCM
196scm_smob_apply_1_030 (SCM smob, SCM a1)
197{
198 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_UNDEFINED);
199}
200
201static SCM
202scm_smob_apply_1_001 (SCM smob, SCM a1)
203{
1afff620 204 return SCM_SMOB_APPLY1 (smob, scm_list_1 (a1));
cb1c46c5
KN
205}
206
207static SCM
208scm_smob_apply_1_011 (SCM smob, SCM a1)
209{
210 return SCM_SMOB_APPLY2 (smob, a1, SCM_EOL);
211}
212
213static SCM
214scm_smob_apply_1_021 (SCM smob, SCM a1)
215{
216 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_EOL);
217}
218
219static SCM
e81d98ec 220scm_smob_apply_1_error (SCM smob, SCM a1 SCM_UNUSED)
cb1c46c5
KN
221{
222 scm_wrong_num_args (smob);
223}
224
cb1c46c5
KN
225static SCM
226scm_smob_apply_2_030 (SCM smob, SCM a1, SCM a2)
227{
228 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_UNDEFINED);
229}
230
231static SCM
232scm_smob_apply_2_001 (SCM smob, SCM a1, SCM a2)
233{
1afff620 234 return SCM_SMOB_APPLY1 (smob, scm_list_2 (a1, a2));
7c58e21b 235}
cb1c46c5
KN
236
237static SCM
238scm_smob_apply_2_011 (SCM smob, SCM a1, SCM a2)
239{
1afff620 240 return SCM_SMOB_APPLY2 (smob, a1, scm_list_1 (a2));
cb1c46c5
KN
241}
242
243static SCM
244scm_smob_apply_2_021 (SCM smob, SCM a1, SCM a2)
245{
246 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_EOL);
247}
248
249static SCM
e81d98ec 250scm_smob_apply_2_error (SCM smob, SCM a1 SCM_UNUSED, SCM a2 SCM_UNUSED)
cb1c46c5
KN
251{
252 scm_wrong_num_args (smob);
253}
254
255static SCM
256scm_smob_apply_3_030 (SCM smob, SCM a1, SCM a2, SCM rst)
257{
258 if (!SCM_NULLP (SCM_CDR (rst)))
259 scm_wrong_num_args (smob);
260 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_CAR (rst));
261}
262
263static SCM
264scm_smob_apply_3_001 (SCM smob, SCM a1, SCM a2, SCM rst)
265{
266 return SCM_SMOB_APPLY1 (smob, scm_cons2 (a1, a2, rst));
0717dfd8
KN
267}
268
cb1c46c5
KN
269static SCM
270scm_smob_apply_3_011 (SCM smob, SCM a1, SCM a2, SCM rst)
271{
272 return SCM_SMOB_APPLY2 (smob, a1, scm_cons (a2, rst));
273}
274
275static SCM
276scm_smob_apply_3_021 (SCM smob, SCM a1, SCM a2, SCM rst)
277{
278 return SCM_SMOB_APPLY3 (smob, a1, a2, rst);
279}
280
281static SCM
e81d98ec
DH
282scm_smob_apply_3_error (SCM smob,
283 SCM a1 SCM_UNUSED,
284 SCM a2 SCM_UNUSED,
285 SCM rst SCM_UNUSED)
cb1c46c5
KN
286{
287 scm_wrong_num_args (smob);
288}
289
290\f
7a7f7c53 291
92c2555f 292scm_t_bits
1be6b49c 293scm_make_smob_type (char *name, size_t size)
7a7f7c53 294#define FUNC_NAME "scm_make_smob_type"
0f2d19dd 295{
c014a02e 296 long new_smob;
7a7f7c53
DH
297
298 SCM_ENTER_A_SECTION; /* scm_numsmob */
299 new_smob = scm_numsmob;
300 if (scm_numsmob != MAX_SMOB_COUNT)
301 ++scm_numsmob;
302 SCM_EXIT_A_SECTION;
303
304 if (new_smob == MAX_SMOB_COUNT)
305 scm_misc_error (FUNC_NAME, "maximum number of smobs exceeded", SCM_EOL);
306
307 scm_smobs[new_smob].name = name;
308 if (size != 0)
2500356c 309 {
7a7f7c53
DH
310 scm_smobs[new_smob].size = size;
311 scm_smobs[new_smob].free = scm_smob_free;
2500356c 312 }
7a7f7c53 313
d7ec6b9f
MD
314 /* Make a class object if Goops is present. */
315 if (scm_smob_class)
7a7f7c53
DH
316 scm_smob_class[new_smob] = scm_make_extended_class (name);
317
318 return scm_tc7_smob + new_smob * 256;
0f2d19dd 319}
7a7f7c53
DH
320#undef FUNC_NAME
321
0f2d19dd 322
9dd5943c 323void
92c2555f 324scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM))
9dd5943c
MD
325{
326 scm_smobs[SCM_TC2SMOBNUM (tc)].mark = mark;
327}
328
329void
92c2555f 330scm_set_smob_free (scm_t_bits tc, size_t (*free) (SCM))
9dd5943c
MD
331{
332 scm_smobs[SCM_TC2SMOBNUM (tc)].free = free;
333}
334
335void
92c2555f 336scm_set_smob_print (scm_t_bits tc, int (*print) (SCM, SCM, scm_print_state*))
9dd5943c
MD
337{
338 scm_smobs[SCM_TC2SMOBNUM (tc)].print = print;
339}
340
341void
92c2555f 342scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM))
9dd5943c
MD
343{
344 scm_smobs[SCM_TC2SMOBNUM (tc)].equalp = equalp;
345}
346
0717dfd8 347void
92c2555f 348scm_set_smob_apply (scm_t_bits tc, SCM (*apply) (),
7c58e21b 349 unsigned int req, unsigned int opt, unsigned int rst)
0717dfd8 350{
cb1c46c5
KN
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);
356
7c58e21b 357 if (rst > 1 || req + opt + rst > 3)
cb1c46c5
KN
358 {
359 puts ("Unsupported smob application type");
360 abort ();
361 }
362
363 switch (type)
364 {
365 case SCM_GSUBR_MAKTYPE (0, 0, 0):
7c58e21b 366 apply_0 = apply; break;
cb1c46c5
KN
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;
379 default:
380 apply_0 = scm_smob_apply_0_error; break;
381 }
382
383 switch (type)
384 {
385 case SCM_GSUBR_MAKTYPE (1, 0, 0):
386 case SCM_GSUBR_MAKTYPE (0, 1, 0):
7c58e21b 387 apply_1 = apply; break;
cb1c46c5
KN
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;
402 default:
403 apply_1 = scm_smob_apply_1_error; break;
404 }
405
406 switch (type)
407 {
408 case SCM_GSUBR_MAKTYPE (2, 0, 0):
409 case SCM_GSUBR_MAKTYPE (1, 1, 0):
410 case SCM_GSUBR_MAKTYPE (0, 2, 0):
7c58e21b 411 apply_2 = apply; break;
cb1c46c5
KN
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;
425 default:
426 apply_2 = scm_smob_apply_2_error; break;
427 }
428
429 switch (type)
430 {
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;
445 default:
446 apply_3 = scm_smob_apply_3_error; break;
447 }
448
03416a99 449 scm_smobs[SCM_TC2SMOBNUM (tc)].apply = apply;
cb1c46c5
KN
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;
68b06924 454 scm_smobs[SCM_TC2SMOBNUM (tc)].gsubr_type = type;
0717dfd8
KN
455}
456
9dd5943c 457SCM
92c2555f 458scm_make_smob (scm_t_bits tc)
9dd5943c 459{
c014a02e 460 long n = SCM_TC2SMOBNUM (tc);
1be6b49c 461 size_t size = scm_smobs[n].size;
16d4699b 462 scm_t_bits data = (size > 0
4c9419ac 463 ? (scm_t_bits) scm_gc_malloc (size, SCM_SMOBNAME (n))
16d4699b
MV
464 : 0);
465 return scm_alloc_cell (tc, data);
9dd5943c
MD
466}
467
ceef3208 468\f
0f2d19dd
JB
469/* {Initialization for i/o types, float, bignum, the type of free cells}
470 */
471
ceef3208 472static int
e81d98ec 473free_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
ceef3208
JB
474{
475 char buf[100];
476
e841c3e0
KN
477 sprintf (buf, "#<freed cell %p; GC missed a reference>",
478 (void *) SCM_UNPACK (exp));
ceef3208
JB
479 scm_puts (buf, port);
480
481 return 1;
482}
483
0f2d19dd
JB
484void
485scm_smob_prehistory ()
0f2d19dd 486{
c014a02e 487 long i;
92c2555f 488 scm_t_bits tc;
e841c3e0 489
0f2d19dd 490 scm_numsmob = 0;
7a7f7c53
DH
491 for (i = 0; i < MAX_SMOB_COUNT; ++i)
492 {
493 scm_smobs[i].name = 0;
494 scm_smobs[i].size = 0;
495 scm_smobs[i].mark = 0;
496 scm_smobs[i].free = 0;
497 scm_smobs[i].print = scm_smob_print;
498 scm_smobs[i].equalp = 0;
499 scm_smobs[i].apply = 0;
500 scm_smobs[i].apply_0 = 0;
501 scm_smobs[i].apply_1 = 0;
502 scm_smobs[i].apply_2 = 0;
503 scm_smobs[i].apply_3 = 0;
504 scm_smobs[i].gsubr_type = 0;
505 }
9dd5943c
MD
506
507 /* WARNING: These scm_make_smob_type calls must be done in this order */
e841c3e0
KN
508 tc = scm_make_smob_type ("free", 0);
509 scm_set_smob_print (tc, free_print);
23a62151 510
7a7f7c53 511 tc = scm_make_smob_type ("big", 0); /* freed in gc */
e841c3e0
KN
512 scm_set_smob_print (tc, scm_bigprint);
513 scm_set_smob_equalp (tc, scm_bigequal);
23a62151 514
e841c3e0
KN
515 tc = scm_make_smob_type ("real", 0); /* freed in gc */
516 scm_set_smob_print (tc, scm_print_real);
517 scm_set_smob_equalp (tc, scm_real_equalp);
16d35552 518
7a7f7c53 519 tc = scm_make_smob_type ("complex", 0); /* freed in gc */
e841c3e0
KN
520 scm_set_smob_print (tc, scm_print_complex);
521 scm_set_smob_equalp (tc, scm_complex_equalp);
0f2d19dd 522}
89e00824
ML
523
524/*
525 Local Variables:
526 c-file-style: "gnu"
527 End:
528*/