* _scm.h: Removed #include <errno.h>.
[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
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46
47#include <stdio.h>
e6e2e95a
MD
48#include <errno.h>
49
a0599745 50#include "libguile/_scm.h"
20e6290e 51
a0599745
MD
52#include "libguile/objects.h"
53#include "libguile/ports.h"
d7ec6b9f 54
0f2d19dd
JB
55#ifdef HAVE_MALLOC_H
56#include <malloc.h>
57#endif
58
a0599745 59#include "libguile/smob.h"
9dd5943c 60
0f2d19dd
JB
61\f
62
63/* scm_smobs scm_numsmob
64 * implement a dynamicly resized array of smob records.
65 * Indexes into this table are used when generating type
66 * tags for smobjects (if you know a tag you can get an index and conversely).
67 */
4e6e2119 68int scm_numsmob;
9dd5943c 69scm_smob_descriptor *scm_smobs;
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
6e8d25a6 85scm_mark0 (SCM ptr)
9dd5943c
MD
86{
87 return SCM_BOOL_F;
88}
89
90SCM
6e8d25a6 91scm_markcdr (SCM ptr)
9dd5943c
MD
92{
93 return SCM_CDR (ptr);
94}
95
96/* {Free}
97 */
98
99scm_sizet
6e8d25a6 100scm_free0 (SCM ptr)
9dd5943c
MD
101{
102 return 0;
103}
104
105scm_sizet
106scm_smob_free (SCM obj)
107{
54778cd3 108 scm_must_free ((char *) SCM_CELL_WORD_1 (obj));
9dd5943c
MD
109 return scm_smobs[SCM_SMOBNUM (obj)].size;
110}
111
112/* {Print}
113 */
114
115int
116scm_smob_print (SCM exp, SCM port, scm_print_state *pstate)
117{
118 int n = SCM_SMOBNUM (exp);
119 scm_puts ("#<", port);
2c16a78a 120 scm_puts (SCM_SMOBNAME (n) ? SCM_SMOBNAME (n) : "smob", port);
9dd5943c 121 scm_putc (' ', port);
f1267706 122 scm_intprint (SCM_UNPACK (scm_smobs[n].size ? SCM_CDR (exp) : exp), 16, port);
9dd5943c
MD
123 scm_putc ('>', port);
124 return 1;
125}
1cc91f1b 126
0717dfd8
KN
127/* {Apply}
128 */
129
cb1c46c5
KN
130#define SCM_SMOB_APPLY0(SMOB) \
131 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB)
132#define SCM_SMOB_APPLY1(SMOB,A1) \
133 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1)
134#define SCM_SMOB_APPLY2(SMOB,A1,A2) \
135 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2)
136#define SCM_SMOB_APPLY3(SMOB,A1,A2,A3) \
137 SCM_SMOB_DESCRIPTOR (SMOB).apply (SMOB, A1, A2, A3)
138
cb1c46c5
KN
139static SCM
140scm_smob_apply_0_010 (SCM smob)
0717dfd8 141{
cb1c46c5 142 return SCM_SMOB_APPLY1 (smob, SCM_UNDEFINED);
0717dfd8
KN
143}
144
cb1c46c5
KN
145static SCM
146scm_smob_apply_0_020 (SCM smob)
0717dfd8 147{
cb1c46c5 148 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
149}
150
cb1c46c5
KN
151static SCM
152scm_smob_apply_0_030 (SCM smob)
0717dfd8 153{
cb1c46c5 154 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_UNDEFINED);
0717dfd8
KN
155}
156
cb1c46c5
KN
157static SCM
158scm_smob_apply_0_001 (SCM smob)
0717dfd8 159{
cb1c46c5
KN
160 return SCM_SMOB_APPLY1 (smob, SCM_EOL);
161}
162
163static SCM
164scm_smob_apply_0_011 (SCM smob)
165{
166 return SCM_SMOB_APPLY2 (smob, SCM_UNDEFINED, SCM_EOL);
167}
168
169static SCM
170scm_smob_apply_0_021 (SCM smob)
171{
172 return SCM_SMOB_APPLY3 (smob, SCM_UNDEFINED, SCM_UNDEFINED, SCM_EOL);
173}
174
175static SCM
176scm_smob_apply_0_error (SCM smob)
177{
178 scm_wrong_num_args (smob);
179}
180
cb1c46c5
KN
181static SCM
182scm_smob_apply_1_020 (SCM smob, SCM a1)
183{
184 return SCM_SMOB_APPLY2 (smob, a1, SCM_UNDEFINED);
185}
186
187static SCM
188scm_smob_apply_1_030 (SCM smob, SCM a1)
189{
190 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_UNDEFINED);
191}
192
193static SCM
194scm_smob_apply_1_001 (SCM smob, SCM a1)
195{
196 return SCM_SMOB_APPLY1 (smob, SCM_LIST1 (a1));
197}
198
199static SCM
200scm_smob_apply_1_011 (SCM smob, SCM a1)
201{
202 return SCM_SMOB_APPLY2 (smob, a1, SCM_EOL);
203}
204
205static SCM
206scm_smob_apply_1_021 (SCM smob, SCM a1)
207{
208 return SCM_SMOB_APPLY3 (smob, a1, SCM_UNDEFINED, SCM_EOL);
209}
210
211static SCM
212scm_smob_apply_1_error (SCM smob, SCM a1)
213{
214 scm_wrong_num_args (smob);
215}
216
cb1c46c5
KN
217static SCM
218scm_smob_apply_2_030 (SCM smob, SCM a1, SCM a2)
219{
220 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_UNDEFINED);
221}
222
223static SCM
224scm_smob_apply_2_001 (SCM smob, SCM a1, SCM a2)
225{
226 return SCM_SMOB_APPLY1 (smob, SCM_LIST2 (a1, a2));
7c58e21b 227}
cb1c46c5
KN
228
229static SCM
230scm_smob_apply_2_011 (SCM smob, SCM a1, SCM a2)
231{
232 return SCM_SMOB_APPLY2 (smob, a1, SCM_LIST1 (a2));
233}
234
235static SCM
236scm_smob_apply_2_021 (SCM smob, SCM a1, SCM a2)
237{
238 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_EOL);
239}
240
241static SCM
242scm_smob_apply_2_error (SCM smob, SCM a1, SCM a2)
243{
244 scm_wrong_num_args (smob);
245}
246
247static SCM
248scm_smob_apply_3_030 (SCM smob, SCM a1, SCM a2, SCM rst)
249{
250 if (!SCM_NULLP (SCM_CDR (rst)))
251 scm_wrong_num_args (smob);
252 return SCM_SMOB_APPLY3 (smob, a1, a2, SCM_CAR (rst));
253}
254
255static SCM
256scm_smob_apply_3_001 (SCM smob, SCM a1, SCM a2, SCM rst)
257{
258 return SCM_SMOB_APPLY1 (smob, scm_cons2 (a1, a2, rst));
0717dfd8
KN
259}
260
cb1c46c5
KN
261static SCM
262scm_smob_apply_3_011 (SCM smob, SCM a1, SCM a2, SCM rst)
263{
264 return SCM_SMOB_APPLY2 (smob, a1, scm_cons (a2, rst));
265}
266
267static SCM
268scm_smob_apply_3_021 (SCM smob, SCM a1, SCM a2, SCM rst)
269{
270 return SCM_SMOB_APPLY3 (smob, a1, a2, rst);
271}
272
273static SCM
274scm_smob_apply_3_error (SCM smob, SCM a1, SCM a2, SCM rst)
275{
276 scm_wrong_num_args (smob);
277}
278
279\f
8a39e3fc 280scm_bits_t
9dd5943c 281scm_make_smob_type (char *name, scm_sizet size)
0f2d19dd
JB
282{
283 char *tmp;
284 if (255 <= scm_numsmob)
285 goto smoberr;
286 SCM_DEFER_INTS;
9dd5943c
MD
287 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_smobs,
288 (1 + scm_numsmob)
289 * sizeof (scm_smob_descriptor)));
0f2d19dd
JB
290 if (tmp)
291 {
9dd5943c 292 scm_smobs = (scm_smob_descriptor *) tmp;
03416a99
KN
293 scm_smobs[scm_numsmob].name = name;
294 scm_smobs[scm_numsmob].size = size;
295 scm_smobs[scm_numsmob].mark = 0;
296 scm_smobs[scm_numsmob].free = (size == 0 ? scm_free0 : scm_smob_free);
297 scm_smobs[scm_numsmob].print = scm_smob_print;
298 scm_smobs[scm_numsmob].equalp = 0;
299 scm_smobs[scm_numsmob].apply = 0;
cb1c46c5
KN
300 scm_smobs[scm_numsmob].apply_0 = 0;
301 scm_smobs[scm_numsmob].apply_1 = 0;
302 scm_smobs[scm_numsmob].apply_2 = 0;
303 scm_smobs[scm_numsmob].apply_3 = 0;
914cceec 304 scm_smobs[scm_numsmob].gsubr_type = 0;
0f2d19dd
JB
305 scm_numsmob++;
306 }
307 SCM_ALLOW_INTS;
2500356c
DH
308 if (!tmp)
309 {
310 smoberr:
311 scm_memory_error ("scm_make_smob_type");
312 }
d7ec6b9f
MD
313 /* Make a class object if Goops is present. */
314 if (scm_smob_class)
315 scm_smob_class[scm_numsmob - 1]
316 = scm_make_extended_class (SCM_SMOBNAME (scm_numsmob - 1));
0f2d19dd
JB
317 return scm_tc7_smob + (scm_numsmob - 1) * 256;
318}
319
9dd5943c 320void
03416a99 321scm_set_smob_mark (scm_bits_t tc, SCM (*mark) (SCM))
9dd5943c
MD
322{
323 scm_smobs[SCM_TC2SMOBNUM (tc)].mark = mark;
324}
325
326void
03416a99 327scm_set_smob_free (scm_bits_t tc, scm_sizet (*free) (SCM))
9dd5943c
MD
328{
329 scm_smobs[SCM_TC2SMOBNUM (tc)].free = free;
330}
331
332void
03416a99 333scm_set_smob_print (scm_bits_t tc, int (*print) (SCM, SCM, scm_print_state*))
9dd5943c
MD
334{
335 scm_smobs[SCM_TC2SMOBNUM (tc)].print = print;
336}
337
338void
03416a99 339scm_set_smob_equalp (scm_bits_t tc, SCM (*equalp) (SCM, SCM))
9dd5943c
MD
340{
341 scm_smobs[SCM_TC2SMOBNUM (tc)].equalp = equalp;
342}
343
0717dfd8 344void
03416a99 345scm_set_smob_apply (scm_bits_t tc, SCM (*apply) (),
7c58e21b 346 unsigned int req, unsigned int opt, unsigned int rst)
0717dfd8 347{
cb1c46c5
KN
348 SCM (*apply_0) (SCM);
349 SCM (*apply_1) (SCM, SCM);
350 SCM (*apply_2) (SCM, SCM, SCM);
351 SCM (*apply_3) (SCM, SCM, SCM, SCM);
352 int type = SCM_GSUBR_MAKTYPE (req, opt, rst);
353
7c58e21b 354 if (rst > 1 || req + opt + rst > 3)
cb1c46c5
KN
355 {
356 puts ("Unsupported smob application type");
357 abort ();
358 }
359
360 switch (type)
361 {
362 case SCM_GSUBR_MAKTYPE (0, 0, 0):
7c58e21b 363 apply_0 = apply; break;
cb1c46c5
KN
364 case SCM_GSUBR_MAKTYPE (0, 1, 0):
365 apply_0 = scm_smob_apply_0_010; break;
366 case SCM_GSUBR_MAKTYPE (0, 2, 0):
367 apply_0 = scm_smob_apply_0_020; break;
368 case SCM_GSUBR_MAKTYPE (0, 3, 0):
369 apply_0 = scm_smob_apply_0_030; break;
370 case SCM_GSUBR_MAKTYPE (0, 0, 1):
371 apply_0 = scm_smob_apply_0_001; break;
372 case SCM_GSUBR_MAKTYPE (0, 1, 1):
373 apply_0 = scm_smob_apply_0_011; break;
374 case SCM_GSUBR_MAKTYPE (0, 2, 1):
375 apply_0 = scm_smob_apply_0_021; break;
376 default:
377 apply_0 = scm_smob_apply_0_error; break;
378 }
379
380 switch (type)
381 {
382 case SCM_GSUBR_MAKTYPE (1, 0, 0):
383 case SCM_GSUBR_MAKTYPE (0, 1, 0):
7c58e21b 384 apply_1 = apply; break;
cb1c46c5
KN
385 case SCM_GSUBR_MAKTYPE (1, 1, 0):
386 case SCM_GSUBR_MAKTYPE (0, 2, 0):
387 apply_1 = scm_smob_apply_1_020; break;
388 case SCM_GSUBR_MAKTYPE (1, 2, 0):
389 case SCM_GSUBR_MAKTYPE (0, 3, 0):
390 apply_1 = scm_smob_apply_1_030; break;
391 case SCM_GSUBR_MAKTYPE (0, 0, 1):
392 apply_1 = scm_smob_apply_1_001; break;
393 case SCM_GSUBR_MAKTYPE (1, 0, 1):
394 case SCM_GSUBR_MAKTYPE (0, 1, 1):
395 apply_1 = scm_smob_apply_1_011; break;
396 case SCM_GSUBR_MAKTYPE (1, 1, 1):
397 case SCM_GSUBR_MAKTYPE (0, 2, 1):
398 apply_1 = scm_smob_apply_1_021; break;
399 default:
400 apply_1 = scm_smob_apply_1_error; break;
401 }
402
403 switch (type)
404 {
405 case SCM_GSUBR_MAKTYPE (2, 0, 0):
406 case SCM_GSUBR_MAKTYPE (1, 1, 0):
407 case SCM_GSUBR_MAKTYPE (0, 2, 0):
7c58e21b 408 apply_2 = apply; break;
cb1c46c5
KN
409 case SCM_GSUBR_MAKTYPE (2, 1, 0):
410 case SCM_GSUBR_MAKTYPE (1, 2, 0):
411 case SCM_GSUBR_MAKTYPE (0, 3, 0):
412 apply_2 = scm_smob_apply_2_030; break;
413 case SCM_GSUBR_MAKTYPE (0, 0, 1):
414 apply_2 = scm_smob_apply_2_001; break;
415 case SCM_GSUBR_MAKTYPE (1, 0, 1):
416 case SCM_GSUBR_MAKTYPE (0, 1, 1):
417 apply_2 = scm_smob_apply_2_011; break;
418 case SCM_GSUBR_MAKTYPE (2, 0, 1):
419 case SCM_GSUBR_MAKTYPE (1, 1, 1):
420 case SCM_GSUBR_MAKTYPE (0, 2, 1):
421 apply_2 = scm_smob_apply_2_021; break;
422 default:
423 apply_2 = scm_smob_apply_2_error; break;
424 }
425
426 switch (type)
427 {
428 case SCM_GSUBR_MAKTYPE (3, 0, 0):
429 case SCM_GSUBR_MAKTYPE (2, 1, 0):
430 case SCM_GSUBR_MAKTYPE (1, 2, 0):
431 case SCM_GSUBR_MAKTYPE (0, 3, 0):
432 apply_3 = scm_smob_apply_3_030; break;
433 case SCM_GSUBR_MAKTYPE (0, 0, 1):
434 apply_3 = scm_smob_apply_3_001; break;
435 case SCM_GSUBR_MAKTYPE (1, 0, 1):
436 case SCM_GSUBR_MAKTYPE (0, 1, 1):
437 apply_3 = scm_smob_apply_3_011; break;
438 case SCM_GSUBR_MAKTYPE (2, 0, 1):
439 case SCM_GSUBR_MAKTYPE (1, 1, 1):
440 case SCM_GSUBR_MAKTYPE (0, 2, 1):
441 apply_3 = scm_smob_apply_3_021; break;
442 default:
443 apply_3 = scm_smob_apply_3_error; break;
444 }
445
03416a99 446 scm_smobs[SCM_TC2SMOBNUM (tc)].apply = apply;
cb1c46c5
KN
447 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_0 = apply_0;
448 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_1 = apply_1;
449 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_2 = apply_2;
450 scm_smobs[SCM_TC2SMOBNUM (tc)].apply_3 = apply_3;
68b06924 451 scm_smobs[SCM_TC2SMOBNUM (tc)].gsubr_type = type;
0717dfd8
KN
452}
453
9dd5943c 454SCM
03416a99 455scm_make_smob (scm_bits_t tc)
9dd5943c
MD
456{
457 int n = SCM_TC2SMOBNUM (tc);
458 scm_sizet size = scm_smobs[n].size;
459 SCM z;
460 SCM_NEWCELL (z);
461 if (size != 0)
462 {
463#if 0
2ade72d7
DH
464 if (scm_smobs[n].mark != 0)
465 {
466 fprintf
467 (stderr,
468 "forbidden operation for smobs with GC data, use SCM_NEWSMOB\n");
469 abort ();
470 }
9dd5943c
MD
471#endif
472 SCM_SET_SMOB_DATA (z, scm_must_malloc (size, SCM_SMOBNAME (n)));
473 }
54778cd3 474 SCM_SET_CELL_TYPE (z, tc);
9dd5943c
MD
475 return z;
476}
477
ceef3208 478\f
7c58e21b
KN
479/* {Deprecated stuff}
480 */
481
482#if (SCM_DEBUG_DEPRECATED == 0)
483
484long
485scm_make_smob_type_mfpe (char *name, scm_sizet size,
486 SCM (*mark) (SCM),
487 scm_sizet (*free) (SCM),
488 int (*print) (SCM, SCM, scm_print_state *),
489 SCM (*equalp) (SCM, SCM))
490{
491 long answer = scm_make_smob_type (name, size);
492 scm_set_smob_mfpe (answer, mark, free, print, equalp);
493 return answer;
494}
495
496void
497scm_set_smob_mfpe (long tc,
498 SCM (*mark) (SCM),
499 scm_sizet (*free) (SCM),
500 int (*print) (SCM, SCM, scm_print_state *),
501 SCM (*equalp) (SCM, SCM))
502{
503 if (mark) scm_set_smob_mark (tc, mark);
504 if (free) scm_set_smob_free (tc, free);
505 if (print) scm_set_smob_print (tc, print);
506 if (equalp) scm_set_smob_equalp (tc, equalp);
507}
508
509#endif /* SCM_DEBUG_DEPRECATED == 0 */
510
511\f
0f2d19dd
JB
512/* {Initialization for i/o types, float, bignum, the type of free cells}
513 */
514
ceef3208 515static int
e841c3e0 516free_print (SCM exp, SCM port, scm_print_state *pstate)
ceef3208
JB
517{
518 char buf[100];
519
e841c3e0
KN
520 sprintf (buf, "#<freed cell %p; GC missed a reference>",
521 (void *) SCM_UNPACK (exp));
ceef3208
JB
522 scm_puts (buf, port);
523
524 return 1;
525}
526
0f2d19dd
JB
527void
528scm_smob_prehistory ()
0f2d19dd 529{
e841c3e0
KN
530 scm_bits_t tc;
531
0f2d19dd 532 scm_numsmob = 0;
9dd5943c
MD
533 scm_smobs = ((scm_smob_descriptor *)
534 malloc (7 * sizeof (scm_smob_descriptor)));
535
536 /* WARNING: These scm_make_smob_type calls must be done in this order */
e841c3e0
KN
537 tc = scm_make_smob_type ("free", 0);
538 scm_set_smob_print (tc, free_print);
23a62151 539
e841c3e0
KN
540 tc = scm_make_smob_type ("big", 0); /* freed in gc */
541 scm_set_smob_print (tc, scm_bigprint);
542 scm_set_smob_equalp (tc, scm_bigequal);
23a62151 543
e841c3e0
KN
544 tc = scm_make_smob_type ("real", 0); /* freed in gc */
545 scm_set_smob_print (tc, scm_print_real);
546 scm_set_smob_equalp (tc, scm_real_equalp);
16d35552 547
e841c3e0
KN
548 tc = scm_make_smob_type ("complex", 0); /* freed in gc */
549 scm_set_smob_print (tc, scm_print_complex);
550 scm_set_smob_equalp (tc, scm_complex_equalp);
0f2d19dd 551}
89e00824
ML
552
553/*
554 Local Variables:
555 c-file-style: "gnu"
556 End:
557*/