Fix typo in scheme-using.texi
[bpt/guile.git] / libguile / struct.c
CommitLineData
75ba64d6 1/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
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.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
0f2d19dd 19\f
dbb605f5 20#ifdef HAVE_CONFIG_H
a6f7f57d
RB
21# include <config.h>
22#endif
0f2d19dd 23
66e78727 24#include <alloca.h>
aa42c036 25#include <assert.h>
66e78727 26
6d46f1e4
AW
27#define SCM_BUILDING_DEPRECATED_CODE
28
a0599745 29#include "libguile/_scm.h"
4e047c3e 30#include "libguile/async.h"
a0599745
MD
31#include "libguile/chars.h"
32#include "libguile/eval.h"
33#include "libguile/alist.h"
34#include "libguile/weaks.h"
35#include "libguile/hashtab.h"
36#include "libguile/ports.h"
37#include "libguile/strings.h"
27646f41 38#include "libguile/srfi-13.h"
a0599745
MD
39
40#include "libguile/validate.h"
41#include "libguile/struct.h"
0f2d19dd 42
d15ad007
LC
43#include "libguile/eq.h"
44
95b88819
GH
45#ifdef HAVE_STRING_H
46#include <string.h>
47#endif
48
1c44468d 49#include "libguile/bdw-gc.h"
5e67dc27 50
0f2d19dd
JB
51\f
52
b6cf4d02
AW
53/* A needlessly obscure test. */
54#define SCM_LAYOUT_TAILP(X) (((X) & 32) == 0) /* R, W or O */
55
0f2d19dd 56static SCM required_vtable_fields = SCM_BOOL_F;
b6cf4d02
AW
57static SCM required_applicable_fields = SCM_BOOL_F;
58static SCM required_applicable_with_setter_fields = SCM_BOOL_F;
db5ed685
AW
59SCM scm_applicable_struct_vtable_vtable;
60SCM scm_applicable_struct_with_setter_vtable_vtable;
61SCM scm_standard_vtable_vtable;
62
0f2d19dd
JB
63
64\f
a1ec6916 65SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
1bbd0b84 66 (SCM fields),
b380b885 67 "Return a new structure layout object.\n\n"
7c31152f 68 "@var{fields} must be a string made up of pairs of characters\n"
b380b885
MD
69 "strung together. The first character of each pair describes a field\n"
70 "type, the second a field protection. Allowed types are 'p' for\n"
71 "GC-protected Scheme data, 'u' for unprotected binary data, and 's' for\n"
04323af4 72 "a field that points to the structure itself. Allowed protections\n"
b6cf4d02
AW
73 "are 'w' for mutable fields, 'h' for hidden fields, 'r' for read-only\n"
74 "fields, and 'o' for opaque fields.\n\n"
75 "Hidden fields are writable, but they will not consume an initializer arg\n"
76 "passed to @code{make-struct}. They are useful to add slots to a struct\n"
77 "in a way that preserves backward-compatibility with existing calls to\n"
78 "@code{make-struct}, especially for derived vtables.\n\n"
79 "The last field protection specification may be capitalized to indicate\n"
80 "that the field is a tail-array.")
1bbd0b84 81#define FUNC_NAME s_scm_make_struct_layout
0f2d19dd
JB
82{
83 SCM new_sym;
27646f41 84 scm_t_wchar c;
2ade72d7 85
7f991c7d
LC
86 SCM_VALIDATE_STRING (1, fields);
87
1bbd0b84 88 { /* scope */
1be6b49c 89 size_t len;
0f2d19dd
JB
90 int x;
91
cc95e00a 92 len = scm_i_string_length (fields);
2ade72d7
DH
93 if (len % 2 == 1)
94 SCM_MISC_ERROR ("odd length field specification: ~S",
1afff620 95 scm_list_1 (fields));
2ade72d7 96
0f2d19dd
JB
97 for (x = 0; x < len; x += 2)
98 {
27646f41 99 switch (c = scm_i_string_ref (fields, x))
0f2d19dd
JB
100 {
101 case 'u':
102 case 'p':
103#if 0
104 case 'i':
105 case 'd':
106#endif
107 case 's':
108 break;
109 default:
2ade72d7 110 SCM_MISC_ERROR ("unrecognized field type: ~S",
27646f41 111 scm_list_1 (SCM_MAKE_CHAR (c)));
0f2d19dd
JB
112 }
113
27646f41 114 switch (c = scm_i_string_ref (fields, x + 1))
0f2d19dd
JB
115 {
116 case 'w':
b6cf4d02 117 case 'h':
27646f41 118 if (scm_i_string_ref (fields, x) == 's')
2ade72d7 119 SCM_MISC_ERROR ("self fields not writable", SCM_EOL);
0f2d19dd
JB
120 case 'r':
121 case 'o':
122 break;
2c36c351
MD
123 case 'R':
124 case 'W':
125 case 'O':
27646f41 126 if (scm_i_string_ref (fields, x) == 's')
2ade72d7
DH
127 SCM_MISC_ERROR ("self fields not allowed in tail array",
128 SCM_EOL);
129 if (x != len - 2)
130 SCM_MISC_ERROR ("tail array field must be last field in layout",
131 SCM_EOL);
2c36c351 132 break;
0f2d19dd 133 default:
2ade72d7 134 SCM_MISC_ERROR ("unrecognized ref specification: ~S",
27646f41 135 scm_list_1 (SCM_MAKE_CHAR (c)));
0f2d19dd
JB
136 }
137#if 0
27646f41 138 if (scm_i_string_ref (fields, x, 'd'))
0f2d19dd 139 {
27646f41 140 if (!scm_i_string_ref (fields, x+2, '-'))
2ade72d7 141 SCM_MISC_ERROR ("missing dash field at position ~A",
e11e83f3 142 scm_list_1 (scm_from_int (x / 2)));
0f2d19dd
JB
143 x += 2;
144 goto recheck_ref;
145 }
146#endif
147 }
cc95e00a 148 new_sym = scm_string_to_symbol (fields);
0f2d19dd 149 }
8824ac88
MV
150 scm_remember_upto_here_1 (fields);
151 return new_sym;
0f2d19dd 152}
1bbd0b84 153#undef FUNC_NAME
0f2d19dd
JB
154
155\f
aa42c036
LC
156/* Check whether VTABLE instances have a simple layout (i.e., either only "pr"
157 or only "pw" fields) and update its flags accordingly. */
158static void
159set_vtable_layout_flags (SCM vtable)
160{
161 size_t len, field;
162 SCM layout;
163 const char *c_layout;
164 scm_t_bits flags = SCM_VTABLE_FLAG_SIMPLE;
165
166 layout = SCM_VTABLE_LAYOUT (vtable);
167 c_layout = scm_i_symbol_chars (layout);
168 len = scm_i_symbol_length (layout);
169
170 assert (len % 2 == 0);
171
172 /* Update FLAGS according to LAYOUT. */
173 for (field = 0;
174 field < len && flags & SCM_VTABLE_FLAG_SIMPLE;
175 field += 2)
176 {
177 if (c_layout[field] != 'p')
178 flags = 0;
179 else
180 switch (c_layout[field + 1])
181 {
182 case 'w':
183 case 'W':
e03b7f73 184 if (field == 0)
aa42c036
LC
185 flags |= SCM_VTABLE_FLAG_SIMPLE_RW;
186 break;
187
188 case 'r':
189 case 'R':
e03b7f73 190 flags &= ~SCM_VTABLE_FLAG_SIMPLE_RW;
aa42c036
LC
191 break;
192
193 default:
194 flags = 0;
195 }
196 }
197
198 if (flags & SCM_VTABLE_FLAG_SIMPLE)
199 {
200 /* VTABLE is simple so update its flags and record the size of its
201 instances. */
202 SCM_SET_VTABLE_FLAGS (vtable, flags);
203 SCM_STRUCT_DATA_SET (vtable, scm_vtable_index_size, len / 2);
204 }
205}
0f2d19dd 206
631237b4
AW
207static int
208scm_is_valid_vtable_layout (SCM layout)
209{
210 size_t len, n;
211 const char *c_layout;
212
213 c_layout = scm_i_symbol_chars (layout);
214 len = scm_i_symbol_length (layout);
215
216 if (len % 2)
217 return 0;
218
219 for (n = 0; n < len; n += 2)
220 switch (c_layout[n])
221 {
222 case 'u':
223 case 'p':
224 case 's':
225 switch (c_layout[n+1])
226 {
227 case 'W':
228 case 'R':
229 case 'O':
230 if (n + 2 != len)
231 return 0;
232 case 'w':
233 case 'h':
234 case 'r':
235 case 'o':
236 break;
237 default:
238 return 0;
239 }
240 break;
241 default:
242 return 0;
243 }
244 return 1;
245}
246
696ac4df
LC
247/* Have OBJ, a newly created vtable, inherit flags from VTABLE. VTABLE is a
248 vtable-vtable and OBJ is an instance of VTABLE. */
51f66c91
AW
249void
250scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj)
251#define FUNC_NAME "%inherit-vtable-magic"
252{
253 /* Verily, what is the deal here, you ask? Basically, we need to know a couple
254 of properties of structures at runtime. For example, "is this structure a
255 vtable of vtables (a metaclass)?"; also, "is this structure applicable?".
256 Both of these questions also imply a certain layout of the structure. So
257 instead of checking the layout at runtime, what we do is pre-verify the
258 layout -- so that at runtime we can just check the applicable flag and
696ac4df 259 dispatch directly to the Scheme procedure in slot 0. */
51f66c91
AW
260 SCM olayout;
261
696ac4df 262 /* Verify that OBJ is a valid vtable. */
631237b4 263 if (! scm_is_valid_vtable_layout (SCM_VTABLE_LAYOUT (obj)))
a2220d7e 264 SCM_MISC_ERROR ("invalid layout for new vtable: ~a",
51f66c91
AW
265 scm_list_1 (SCM_VTABLE_LAYOUT (obj)));
266
aa42c036
LC
267 set_vtable_layout_flags (obj);
268
696ac4df
LC
269 /* If OBJ's vtable is compatible with the required vtable (class) layout, it
270 is a metaclass. */
51f66c91
AW
271 olayout = scm_symbol_to_string (SCM_VTABLE_LAYOUT (obj));
272 if (scm_is_true (scm_leq_p (scm_string_length (required_vtable_fields),
273 scm_string_length (olayout)))
274 && scm_is_true (scm_string_eq (olayout, required_vtable_fields,
275 scm_from_size_t (0),
276 scm_string_length (required_vtable_fields),
277 scm_from_size_t (0),
278 scm_string_length (required_vtable_fields))))
279 SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_VTABLE);
280
696ac4df
LC
281 /* Finally, if OBJ is an applicable class, verify that its vtable is
282 compatible with the required applicable layout. */
51f66c91
AW
283 if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SETTER_VTABLE))
284 {
285 if (scm_is_false (scm_string_eq (olayout, required_applicable_with_setter_fields,
286 scm_from_size_t (0),
287 scm_from_size_t (4),
288 scm_from_size_t (0),
289 scm_from_size_t (4))))
a2220d7e 290 SCM_MISC_ERROR ("invalid applicable-with-setter struct layout",
51f66c91
AW
291 scm_list_1 (olayout));
292 SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_APPLICABLE | SCM_VTABLE_FLAG_SETTER);
293 }
294 else if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_APPLICABLE_VTABLE))
295 {
296 if (scm_is_false (scm_string_eq (olayout, required_applicable_fields,
297 scm_from_size_t (0),
298 scm_from_size_t (2),
299 scm_from_size_t (0),
300 scm_from_size_t (2))))
a2220d7e 301 SCM_MISC_ERROR ("invalid applicable struct layout",
51f66c91
AW
302 scm_list_1 (olayout));
303 SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_APPLICABLE);
304 }
a2220d7e
AW
305
306 SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_VALIDATED);
51f66c91
AW
307}
308#undef FUNC_NAME
0f2d19dd 309
1cc91f1b 310
f7620510 311static void
66e78727
AW
312scm_struct_init (SCM handle, SCM layout, size_t n_tail,
313 size_t n_inits, scm_t_bits *inits)
0f2d19dd 314{
aa42c036
LC
315 SCM vtable;
316 scm_t_bits *mem;
317
318 vtable = SCM_STRUCT_VTABLE (handle);
319 mem = SCM_STRUCT_DATA (handle);
320
321 if (SCM_UNPACK (vtable) != 0
322 && SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
323 && n_tail == 0
324 && n_inits == SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size))
325 /* The fast path: HANDLE has N_INITS "p" fields. */
326 memcpy (mem, inits, n_inits * sizeof (SCM));
327 else
0f2d19dd 328 {
aa42c036
LC
329 scm_t_wchar prot = 0;
330 int n_fields = scm_i_symbol_length (layout) / 2;
331 int tailp = 0;
332 int i;
333 size_t inits_idx = 0;
334
335 i = -2;
336 while (n_fields)
2c36c351 337 {
aa42c036 338 if (!tailp)
2c36c351 339 {
aa42c036
LC
340 i += 2;
341 prot = scm_i_symbol_ref (layout, i+1);
342 if (SCM_LAYOUT_TAILP (prot))
343 {
344 tailp = 1;
345 prot = prot == 'R' ? 'r' : prot == 'W' ? 'w' : 'o';
346 *mem++ = (scm_t_bits)n_tail;
347 n_fields += n_tail - 1;
348 if (n_fields == 0)
349 break;
350 }
2c36c351 351 }
aa42c036 352 switch (scm_i_symbol_ref (layout, i))
0f2d19dd 353 {
aa42c036
LC
354 case 'u':
355 if ((prot != 'r' && prot != 'w') || inits_idx == n_inits)
356 *mem = 0;
357 else
358 {
359 *mem = scm_to_ulong (SCM_PACK (inits[inits_idx]));
360 inits_idx++;
361 }
362 break;
363
364 case 'p':
365 if ((prot != 'r' && prot != 'w') || inits_idx == n_inits)
366 *mem = SCM_UNPACK (SCM_BOOL_F);
367 else
368 {
369 *mem = inits[inits_idx];
370 inits_idx++;
371 }
372
373 break;
374
375 case 's':
376 *mem = SCM_UNPACK (handle);
377 break;
0f2d19dd 378 }
0f2d19dd 379
aa42c036
LC
380 n_fields--;
381 mem++;
0f2d19dd 382 }
0f2d19dd
JB
383 }
384}
385
386
a1ec6916 387SCM_DEFINE (scm_struct_p, "struct?", 1, 0, 0,
1bbd0b84 388 (SCM x),
0233bfc1 389 "Return @code{#t} iff @var{x} is a structure object, else\n"
942e5b91 390 "@code{#f}.")
1bbd0b84 391#define FUNC_NAME s_scm_struct_p
0f2d19dd 392{
7888309b 393 return scm_from_bool(SCM_STRUCTP (x));
0f2d19dd 394}
1bbd0b84 395#undef FUNC_NAME
0f2d19dd 396
a1ec6916 397SCM_DEFINE (scm_struct_vtable_p, "struct-vtable?", 1, 0, 0,
1bbd0b84 398 (SCM x),
0233bfc1 399 "Return @code{#t} iff @var{x} is a vtable structure.")
1bbd0b84 400#define FUNC_NAME s_scm_struct_vtable_p
0f2d19dd 401{
a2220d7e
AW
402 if (!SCM_STRUCTP (x)
403 || !SCM_STRUCT_VTABLE_FLAG_IS_SET (x, SCM_VTABLE_FLAG_VTABLE))
404 return SCM_BOOL_F;
405 if (!SCM_VTABLE_FLAG_IS_SET (x, SCM_VTABLE_FLAG_VALIDATED))
406 SCM_MISC_ERROR ("vtable has invalid layout: ~A",
407 scm_list_1 (SCM_VTABLE_LAYOUT (x)));
408 return SCM_BOOL_T;
0f2d19dd 409}
1bbd0b84 410#undef FUNC_NAME
0f2d19dd 411
14d1400f 412
51f66c91
AW
413/* Finalization: invoke the finalizer of the struct pointed to by PTR. */
414static void
6922d92f 415struct_finalizer_trampoline (void *ptr, void *unused_data)
51f66c91
AW
416{
417 SCM obj = PTR2SCM (ptr);
418 scm_t_struct_finalize finalize = SCM_STRUCT_FINALIZER (obj);
419
420 if (finalize)
421 finalize (obj);
422}
423
14d1400f
JB
424/* All struct data must be allocated at an address whose bottom three
425 bits are zero. This is because the tag for a struct lives in the
426 bottom three bits of the struct's car, and the upper bits point to
427 the data of its vtable, which is a struct itself. Thus, if the
428 address of that data doesn't end in three zeros, tagging it will
429 destroy the pointer.
430
b6cf4d02
AW
431 I suppose we should make it clear here that, the data must be 8-byte aligned,
432 *within* the struct, and the struct itself should be 8-byte aligned. In
433 practice we ensure this because the data starts two words into a struct.
14d1400f 434
b6cf4d02
AW
435 This function allocates an 8-byte aligned block of memory, whose first word
436 points to the given vtable data, then a data pointer, then n_words of data.
437 */
438SCM
96a44c1c 439scm_i_alloc_struct (scm_t_bits *vtable_data, int n_words)
14d1400f 440{
9a974fd3
AW
441 SCM ret;
442
443 ret = scm_words ((scm_t_bits)vtable_data | scm_tc3_struct, n_words + 2);
444 SCM_SET_CELL_WORD_1 (ret, (scm_t_bits)SCM_CELL_OBJECT_LOC (ret, 2));
5e67dc27 445
51f66c91
AW
446 /* vtable_data can be null when making a vtable vtable */
447 if (vtable_data && vtable_data[scm_vtable_index_instance_finalize])
75ba64d6
AW
448 /* Register a finalizer for the newly created instance. */
449 scm_i_set_finalizer (SCM2PTR (ret), struct_finalizer_trampoline, NULL);
5e67dc27 450
9a974fd3 451 return ret;
5e67dc27
LC
452}
453
5e67dc27 454\f
66e78727
AW
455SCM
456scm_c_make_structv (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits *init)
457#define FUNC_NAME "make-struct"
0f2d19dd
JB
458{
459 SCM layout;
a55c2b68 460 size_t basic_size;
b6cf4d02 461 SCM obj;
0f2d19dd 462
34d19ef6 463 SCM_VALIDATE_VTABLE (1, vtable);
0f2d19dd 464
b6cf4d02 465 layout = SCM_VTABLE_LAYOUT (vtable);
cc95e00a 466 basic_size = scm_i_symbol_length (layout) / 2;
651f2cd2 467
66e78727 468 if (n_tail != 0)
651f2cd2
KR
469 {
470 SCM layout_str, last_char;
471
472 if (basic_size == 0)
473 {
474 bad_tail:
475 SCM_MISC_ERROR ("tail array not allowed unless layout ends R, W, or O", SCM_EOL);
476 }
477
478 layout_str = scm_symbol_to_string (layout);
479 last_char = scm_string_ref (layout_str,
480 scm_from_size_t (2 * basic_size - 1));
481 if (! SCM_LAYOUT_TAILP (SCM_CHAR (last_char)))
482 goto bad_tail;
483 }
cb823e63 484
96a44c1c 485 obj = scm_i_alloc_struct (SCM_STRUCT_DATA (vtable), basic_size + n_tail);
5e67dc27 486
66e78727 487 scm_struct_init (obj, layout, n_tail, n_init, init);
b6cf4d02 488
a2220d7e
AW
489 /* If we're making a vtable, validate its layout and inherit
490 flags. However we allow for separation of allocation and
491 initialization, to humor GOOPS, so only validate if the layout was
492 passed as an initarg. */
b6cf4d02 493 if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_VTABLE)
b6cf4d02 494 && scm_is_true (SCM_VTABLE_LAYOUT (obj)))
51f66c91 495 scm_i_struct_inherit_vtable_magic (vtable, obj);
651f2cd2 496
b6cf4d02 497 return obj;
0f2d19dd 498}
1bbd0b84 499#undef FUNC_NAME
0f2d19dd 500
66e78727
AW
501SCM
502scm_c_make_struct (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits init, ...)
503{
504 va_list foo;
505 scm_t_bits *v;
506 size_t i;
507
508 v = alloca (sizeof (scm_t_bits) * n_init);
509
510 va_start (foo, init);
511 for (i = 0; i < n_init; i++)
512 {
513 v[i] = init;
514 init = va_arg (foo, scm_t_bits);
515 }
516 va_end (foo);
517
518 return scm_c_make_structv (vtable, n_tail, n_init, v);
519}
520
521SCM_DEFINE (scm_make_struct, "make-struct", 2, 0, 1,
522 (SCM vtable, SCM tail_array_size, SCM init),
523 "Create a new structure.\n\n"
b7e64f8b
BT
524 "@var{vtable} must be a vtable structure (@pxref{Vtables}).\n\n"
525 "@var{tail_array_size} must be a non-negative integer. If the layout\n"
526 "specification indicated by @var{vtable} includes a tail-array,\n"
66e78727
AW
527 "this is the number of elements allocated to that array.\n\n"
528 "The @var{init1}, @dots{} are optional arguments describing how\n"
529 "successive fields of the structure should be initialized. Only fields\n"
530 "with protection 'r' or 'w' can be initialized, except for fields of\n"
531 "type 's', which are automatically initialized to point to the new\n"
532 "structure itself. Fields with protection 'o' can not be initialized by\n"
533 "Scheme programs.\n\n"
534 "If fewer optional arguments than initializable fields are supplied,\n"
535 "fields of type 'p' get default value #f while fields of type 'u' are\n"
536 "initialized to 0.\n\n"
537 "For more information, see the documentation for @code{make-vtable-vtable}.")
538#define FUNC_NAME s_scm_make_struct
539{
540 size_t i, n_init;
541 long ilen;
542 scm_t_bits *v;
543
544 SCM_VALIDATE_VTABLE (1, vtable);
545 ilen = scm_ilength (init);
546 if (ilen < 0)
547 SCM_MISC_ERROR ("Rest arguments do not form a proper list.", SCM_EOL);
548
549 n_init = (size_t)ilen;
550
551 /* best to use alloca, but init could be big, so hack to avoid a possible
552 stack overflow */
553 if (n_init < 64)
554 v = alloca (n_init * sizeof(scm_t_bits));
555 else
556 v = scm_gc_malloc (n_init * sizeof(scm_t_bits), "struct");
557
558 for (i = 0; i < n_init; i++, init = SCM_CDR (init))
559 v[i] = SCM_UNPACK (SCM_CAR (init));
560
561 return scm_c_make_structv (vtable, scm_to_size_t (tail_array_size), n_init, v);
562}
563#undef FUNC_NAME
564
0f2d19dd
JB
565
566
6d46f1e4
AW
567#if SCM_ENABLE_DEPRECATED == 1
568SCM
569scm_make_vtable_vtable (SCM user_fields, SCM tail_array_size, SCM init)
570#define FUNC_NAME "make-vtable-vtable"
0f2d19dd 571{
696ac4df
LC
572 SCM fields, layout, obj;
573 size_t basic_size, n_tail, i, n_init;
66e78727
AW
574 long ilen;
575 scm_t_bits *v;
0f2d19dd 576
d1ca2c64 577 SCM_VALIDATE_STRING (1, user_fields);
66e78727
AW
578 ilen = scm_ilength (init);
579 if (ilen < 0)
580 SCM_MISC_ERROR ("Rest arguments do not form a proper list.", SCM_EOL);
581
582 n_init = (size_t)ilen + 1; /* + 1 for the layout */
583
584 /* best to use alloca, but init could be big, so hack to avoid a possible
585 stack overflow */
586 if (n_init < 64)
587 v = alloca (n_init * sizeof(scm_t_bits));
588 else
589 v = scm_gc_malloc (n_init * sizeof(scm_t_bits), "struct");
0f2d19dd 590
1afff620
KN
591 fields = scm_string_append (scm_list_2 (required_vtable_fields,
592 user_fields));
0f2d19dd 593 layout = scm_make_struct_layout (fields);
a2220d7e
AW
594 if (!scm_is_valid_vtable_layout (layout))
595 SCM_MISC_ERROR ("invalid user fields", scm_list_1 (user_fields));
596
cc95e00a 597 basic_size = scm_i_symbol_length (layout) / 2;
66e78727
AW
598 n_tail = scm_to_size_t (tail_array_size);
599
600 i = 0;
601 v[i++] = SCM_UNPACK (layout);
602 for (; i < n_init; i++, init = SCM_CDR (init))
603 v[i] = SCM_UNPACK (SCM_CAR (init));
604
9de87eea 605 SCM_CRITICAL_SECTION_START;
96a44c1c 606 obj = scm_i_alloc_struct (NULL, basic_size + n_tail);
696ac4df
LC
607 /* Make it so that the vtable of OBJ is itself. */
608 SCM_SET_CELL_WORD_0 (obj, (scm_t_bits) SCM_STRUCT_DATA (obj) | scm_tc3_struct);
9de87eea 609 SCM_CRITICAL_SECTION_END;
696ac4df 610
66e78727 611 scm_struct_init (obj, layout, n_tail, n_init, v);
a2220d7e
AW
612 SCM_SET_VTABLE_FLAGS (obj,
613 SCM_VTABLE_FLAG_VTABLE | SCM_VTABLE_FLAG_VALIDATED);
696ac4df 614
b6cf4d02 615 return obj;
0f2d19dd 616}
1bbd0b84 617#undef FUNC_NAME
6d46f1e4
AW
618#endif
619
620SCM
621scm_i_make_vtable_vtable (SCM user_fields)
622#define FUNC_NAME "make-vtable-vtable"
623{
624 SCM fields, layout, obj;
625 size_t basic_size;
626 scm_t_bits v;
627
628 SCM_VALIDATE_STRING (1, user_fields);
629
630 fields = scm_string_append (scm_list_2 (required_vtable_fields,
631 user_fields));
632 layout = scm_make_struct_layout (fields);
633 if (!scm_is_valid_vtable_layout (layout))
634 SCM_MISC_ERROR ("invalid user fields", scm_list_1 (user_fields));
635
636 basic_size = scm_i_symbol_length (layout) / 2;
637
638 obj = scm_i_alloc_struct (NULL, basic_size);
639 /* Make it so that the vtable of OBJ is itself. */
640 SCM_SET_CELL_WORD_0 (obj, (scm_t_bits) SCM_STRUCT_DATA (obj) | scm_tc3_struct);
0f2d19dd 641
6d46f1e4
AW
642 v = SCM_UNPACK (layout);
643 scm_struct_init (obj, layout, 0, 1, &v);
644 SCM_SET_VTABLE_FLAGS (obj,
645 SCM_VTABLE_FLAG_VTABLE | SCM_VTABLE_FLAG_VALIDATED);
646
647 return obj;
648}
649#undef FUNC_NAME
d15ad007 650
651f2cd2
KR
651SCM_DEFINE (scm_make_vtable, "make-vtable", 1, 1, 0,
652 (SCM fields, SCM printer),
653 "Create a vtable, for creating structures with the given\n"
654 "@var{fields}.\n"
655 "\n"
656 "The optional @var{printer} argument is a function to be called\n"
657 "@code{(@var{printer} struct port)} on the structures created.\n"
658 "It should look at @var{struct} and write to @var{port}.")
659#define FUNC_NAME s_scm_make_vtable
660{
661 if (SCM_UNBNDP (printer))
662 printer = SCM_BOOL_F;
663
db5ed685 664 return scm_make_struct (scm_standard_vtable_vtable, SCM_INUM0,
651f2cd2
KR
665 scm_list_2 (scm_make_struct_layout (fields),
666 printer));
667}
668#undef FUNC_NAME
669
670
d15ad007
LC
671/* Return true if S1 and S2 are equal structures, i.e., if their vtable and
672 contents are the same. Field protections are honored. Thus, it is an
673 error to test the equality of structures that contain opaque fields. */
674SCM
675scm_i_struct_equalp (SCM s1, SCM s2)
676#define FUNC_NAME "scm_i_struct_equalp"
677{
678 SCM vtable1, vtable2, layout;
679 size_t struct_size, field_num;
680
681 SCM_VALIDATE_STRUCT (1, s1);
682 SCM_VALIDATE_STRUCT (2, s2);
683
684 vtable1 = SCM_STRUCT_VTABLE (s1);
685 vtable2 = SCM_STRUCT_VTABLE (s2);
686
687 if (!scm_is_eq (vtable1, vtable2))
688 return SCM_BOOL_F;
689
690 layout = SCM_STRUCT_LAYOUT (s1);
691 struct_size = scm_i_symbol_length (layout) / 2;
692
693 for (field_num = 0; field_num < struct_size; field_num++)
694 {
695 SCM s_field_num;
696 SCM field1, field2;
697
698 /* We have to use `scm_struct_ref ()' here so that fields are accessed
699 consistently, notably wrt. field types and access rights. */
700 s_field_num = scm_from_size_t (field_num);
701 field1 = scm_struct_ref (s1, s_field_num);
702 field2 = scm_struct_ref (s2, s_field_num);
703
42ddb3cb
LC
704 /* Self-referencing fields (type `s') must be skipped to avoid infinite
705 recursion. */
706 if (!(scm_is_eq (field1, s1) && (scm_is_eq (field2, s2))))
707 if (scm_is_false (scm_equal_p (field1, field2)))
708 return SCM_BOOL_F;
d15ad007
LC
709 }
710
42ddb3cb
LC
711 /* FIXME: Tail elements should be tested for equality. */
712
d15ad007
LC
713 return SCM_BOOL_T;
714}
715#undef FUNC_NAME
716
717
0f2d19dd
JB
718\f
719
720
a1ec6916 721SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
1bbd0b84 722 (SCM handle, SCM pos),
b7e64f8b
BT
723 "Access the @var{pos}th field of struct associated with\n"
724 "@var{handle}.\n"
725 "\n"
726 "If the field is of type 'p', then it can be set to an arbitrary\n"
727 "value.\n"
728 "\n"
729 "If the field is of type 'u', then it can only be set to a\n"
730 "non-negative integer value small enough to fit in one machine\n"
731 "word.")
1bbd0b84 732#define FUNC_NAME s_scm_struct_ref
0f2d19dd 733{
aa42c036
LC
734 SCM vtable, answer = SCM_UNDEFINED;
735 scm_t_bits *data;
a55c2b68 736 size_t p;
0f2d19dd 737
34d19ef6 738 SCM_VALIDATE_STRUCT (1, handle);
0f2d19dd 739
aa42c036 740 vtable = SCM_STRUCT_VTABLE (handle);
0f2d19dd 741 data = SCM_STRUCT_DATA (handle);
a55c2b68 742 p = scm_to_size_t (pos);
0f2d19dd 743
aa42c036
LC
744 if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
745 && p < SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size)))
e03b7f73
LC
746 /* The fast path: HANDLE is a struct with only "p" fields. */
747 answer = SCM_PACK (data[p]);
2c36c351 748 else
0f2d19dd 749 {
aa42c036
LC
750 SCM layout;
751 size_t layout_len, n_fields;
752 scm_t_wchar field_type = 0;
753
754 layout = SCM_STRUCT_LAYOUT (handle);
755 layout_len = scm_i_symbol_length (layout);
756 n_fields = layout_len / 2;
757
758 if (SCM_LAYOUT_TAILP (scm_i_symbol_ref (layout, layout_len - 1)))
759 n_fields += data[n_fields - 1];
760
761 SCM_ASSERT_RANGE (1, pos, p < n_fields);
762
763 if (p * 2 < layout_len)
764 {
765 scm_t_wchar ref;
766 field_type = scm_i_symbol_ref (layout, p * 2);
767 ref = scm_i_symbol_ref (layout, p * 2 + 1);
768 if ((ref != 'r') && (ref != 'w') && (ref != 'h'))
769 {
770 if ((ref == 'R') || (ref == 'W'))
771 field_type = 'u';
772 else
773 SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
774 }
775 }
776 else if (scm_i_symbol_ref (layout, layout_len - 1) != 'O')
777 field_type = scm_i_symbol_ref(layout, layout_len - 2);
778 else
779 SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
780
781 switch (field_type)
782 {
783 case 'u':
784 answer = scm_from_ulong (data[p]);
785 break;
0f2d19dd
JB
786
787#if 0
aa42c036
LC
788 case 'i':
789 answer = scm_from_long (data[p]);
790 break;
0f2d19dd 791
aa42c036
LC
792 case 'd':
793 answer = scm_make_real (*((double *)&(data[p])));
794 break;
0f2d19dd
JB
795#endif
796
aa42c036
LC
797 case 's':
798 case 'p':
799 answer = SCM_PACK (data[p]);
800 break;
0f2d19dd
JB
801
802
aa42c036
LC
803 default:
804 SCM_MISC_ERROR ("unrecognized field type: ~S",
805 scm_list_1 (SCM_MAKE_CHAR (field_type)));
806 }
0f2d19dd
JB
807 }
808
809 return answer;
810}
1bbd0b84 811#undef FUNC_NAME
0f2d19dd
JB
812
813
a1ec6916 814SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
1bbd0b84 815 (SCM handle, SCM pos, SCM val),
e3239868
DH
816 "Set the slot of the structure @var{handle} with index @var{pos}\n"
817 "to @var{val}. Signal an error if the slot can not be written\n"
818 "to.")
1bbd0b84 819#define FUNC_NAME s_scm_struct_set_x
0f2d19dd 820{
aa42c036
LC
821 SCM vtable;
822 scm_t_bits *data;
a55c2b68 823 size_t p;
0f2d19dd 824
34d19ef6 825 SCM_VALIDATE_STRUCT (1, handle);
0f2d19dd 826
aa42c036 827 vtable = SCM_STRUCT_VTABLE (handle);
0f2d19dd 828 data = SCM_STRUCT_DATA (handle);
a55c2b68 829 p = scm_to_size_t (pos);
0f2d19dd 830
aa42c036
LC
831 if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
832 && SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE_RW)
833 && p < SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size)))
e03b7f73 834 /* The fast path: HANDLE is a struct with only "pw" fields. */
aa42c036
LC
835 data[p] = SCM_UNPACK (val);
836 else
837 {
838 SCM layout;
839 size_t layout_len, n_fields;
840 scm_t_wchar field_type = 0;
0f2d19dd 841
aa42c036
LC
842 layout = SCM_STRUCT_LAYOUT (handle);
843 layout_len = scm_i_symbol_length (layout);
844 n_fields = layout_len / 2;
0f2d19dd 845
aa42c036
LC
846 if (SCM_LAYOUT_TAILP (scm_i_symbol_ref (layout, layout_len - 1)))
847 n_fields += data[n_fields - 1];
848
849 SCM_ASSERT_RANGE (1, pos, p < n_fields);
850
851 if (p * 2 < layout_len)
852 {
853 char set_x;
854 field_type = scm_i_symbol_ref (layout, p * 2);
855 set_x = scm_i_symbol_ref (layout, p * 2 + 1);
856 if (set_x != 'w' && set_x != 'h')
857 SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
858 }
859 else if (scm_i_symbol_ref (layout, layout_len - 1) == 'W')
860 field_type = scm_i_symbol_ref (layout, layout_len - 2);
861 else
1afff620 862 SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
aa42c036
LC
863
864 switch (field_type)
865 {
866 case 'u':
867 data[p] = SCM_NUM2ULONG (3, val);
868 break;
0f2d19dd
JB
869
870#if 0
aa42c036
LC
871 case 'i':
872 data[p] = SCM_NUM2LONG (3, val);
873 break;
0f2d19dd 874
aa42c036
LC
875 case 'd':
876 *((double *)&(data[p])) = scm_num2dbl (val, (char *)SCM_ARG3);
877 break;
0f2d19dd
JB
878#endif
879
aa42c036
LC
880 case 'p':
881 data[p] = SCM_UNPACK (val);
882 break;
0f2d19dd 883
aa42c036
LC
884 case 's':
885 SCM_MISC_ERROR ("self fields immutable", SCM_EOL);
0f2d19dd 886
aa42c036
LC
887 default:
888 SCM_MISC_ERROR ("unrecognized field type: ~S",
889 scm_list_1 (SCM_MAKE_CHAR (field_type)));
890 }
0f2d19dd
JB
891 }
892
893 return val;
894}
1bbd0b84 895#undef FUNC_NAME
0f2d19dd
JB
896
897
a1ec6916 898SCM_DEFINE (scm_struct_vtable, "struct-vtable", 1, 0, 0,
1bbd0b84 899 (SCM handle),
b7e64f8b
BT
900 "Return the vtable structure that describes the type of struct\n"
901 "associated with @var{handle}.")
1bbd0b84 902#define FUNC_NAME s_scm_struct_vtable
0f2d19dd 903{
34d19ef6 904 SCM_VALIDATE_STRUCT (1, handle);
0f2d19dd
JB
905 return SCM_STRUCT_VTABLE (handle);
906}
1bbd0b84 907#undef FUNC_NAME
0f2d19dd
JB
908
909
98d5f601
MD
910/* {Associating names and classes with vtables}
911 *
912 * The name of a vtable should probably be stored as a slot. This is
913 * a backward compatible solution until agreement has been achieved on
914 * how to associate names with vtables.
915 */
916
c014a02e 917unsigned long
d587c9e8 918scm_struct_ihashq (SCM obj, unsigned long n, void *closure)
98d5f601 919{
ad196599
MD
920 /* The length of the hash table should be a relative prime it's not
921 necessary to shift down the address. */
f1267706 922 return SCM_UNPACK (obj) % n;
98d5f601
MD
923}
924
8ac870de
LC
925/* Return the hash of struct OBJ, modulo N. Traverse OBJ's fields to
926 compute the result, unless DEPTH is zero. */
927unsigned long
928scm_i_struct_hash (SCM obj, unsigned long n, size_t depth)
929#define FUNC_NAME "hash"
930{
931 SCM layout;
932 scm_t_bits *data;
933 size_t struct_size, field_num;
934 unsigned long hash;
935
936 SCM_VALIDATE_STRUCT (1, obj);
937
938 layout = SCM_STRUCT_LAYOUT (obj);
939 struct_size = scm_i_symbol_length (layout) / 2;
940 data = SCM_STRUCT_DATA (obj);
941
942 hash = SCM_UNPACK (SCM_STRUCT_VTABLE (obj)) % n;
943 if (depth > 0)
944 for (field_num = 0; field_num < struct_size; field_num++)
945 {
946 int protection;
947
948 protection = scm_i_symbol_ref (layout, field_num * 2 + 1);
949 if (protection != 'h' && protection != 'o')
950 {
951 int type;
952 type = scm_i_symbol_ref (layout, field_num * 2);
953 switch (type)
954 {
955 case 'p':
956 hash ^= scm_hasher (SCM_PACK (data[field_num]), n,
957 depth / 2);
958 break;
959 case 'u':
960 hash ^= data[field_num] % n;
961 break;
962 default:
963 /* Ignore 's' fields. */;
964 }
965 }
966 }
967
968 /* FIXME: Tail elements should be taken into account. */
969
970 return hash % n;
971}
972#undef FUNC_NAME
973
a1ec6916 974SCM_DEFINE (scm_struct_vtable_name, "struct-vtable-name", 1, 0, 0,
1bbd0b84 975 (SCM vtable),
e3239868 976 "Return the name of the vtable @var{vtable}.")
1bbd0b84 977#define FUNC_NAME s_scm_struct_vtable_name
98d5f601 978{
34d19ef6 979 SCM_VALIDATE_VTABLE (1, vtable);
f3c6a02c 980 return SCM_VTABLE_NAME (vtable);
98d5f601 981}
1bbd0b84 982#undef FUNC_NAME
98d5f601 983
a1ec6916 984SCM_DEFINE (scm_set_struct_vtable_name_x, "set-struct-vtable-name!", 2, 0, 0,
1bbd0b84 985 (SCM vtable, SCM name),
e3239868 986 "Set the name of the vtable @var{vtable} to @var{name}.")
1bbd0b84 987#define FUNC_NAME s_scm_set_struct_vtable_name_x
98d5f601 988{
34d19ef6
HWN
989 SCM_VALIDATE_VTABLE (1, vtable);
990 SCM_VALIDATE_SYMBOL (2, name);
f3c6a02c
AW
991 SCM_SET_VTABLE_NAME (vtable, name);
992 /* FIXME: remove this, and implement proper struct classes instead.
993 (Vtables *are* classes.) */
994 scm_i_define_class_for_vtable (vtable);
98d5f601 995 return SCM_UNSPECIFIED;
0f2d19dd 996}
1bbd0b84 997#undef FUNC_NAME
0f2d19dd
JB
998
999
1000\f
1001
bafcafb2 1002void
1bbd0b84 1003scm_print_struct (SCM exp, SCM port, scm_print_state *pstate)
bafcafb2 1004{
7888309b 1005 if (scm_is_true (scm_procedure_p (SCM_STRUCT_PRINTER (exp))))
4bfdf158
MD
1006 scm_printer_apply (SCM_STRUCT_PRINTER (exp), exp, port, pstate);
1007 else
bafcafb2 1008 {
a1ae1799
MD
1009 SCM vtable = SCM_STRUCT_VTABLE (exp);
1010 SCM name = scm_struct_vtable_name (vtable);
1011 scm_puts ("#<", port);
7888309b 1012 if (scm_is_true (name))
b6cf4d02
AW
1013 {
1014 scm_display (name, port);
1015 scm_putc (' ', port);
1016 }
a1ae1799 1017 else
b6cf4d02
AW
1018 {
1019 if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_VTABLE))
1020 scm_puts ("vtable:", port);
1021 else
1022 scm_puts ("struct:", port);
1023 scm_uintprint (SCM_UNPACK (vtable), 16, port);
1024 scm_putc (' ', port);
1025 scm_write (SCM_VTABLE_LAYOUT (vtable), port);
1026 scm_putc (' ', port);
1027 }
0345e278 1028 scm_uintprint (SCM_UNPACK (exp), 16, port);
b6cf4d02
AW
1029 /* hackety hack */
1030 if (SCM_STRUCT_APPLICABLE_P (exp))
1031 {
1032 if (scm_is_true (SCM_STRUCT_PROCEDURE (exp)))
1033 {
1034 scm_puts (" proc: ", port);
1035 if (scm_is_true (scm_procedure_p (SCM_STRUCT_PROCEDURE (exp))))
1036 scm_write (SCM_STRUCT_PROCEDURE (exp), port);
1037 else
1038 scm_puts ("(not a procedure?)", port);
1039 }
1040 if (SCM_STRUCT_SETTER_P (exp))
1041 {
1042 scm_puts (" setter: ", port);
1043 scm_write (SCM_STRUCT_SETTER (exp), port);
1044 }
1045 }
b7f3516f 1046 scm_putc ('>', port);
bafcafb2 1047 }
bafcafb2 1048}
1cc91f1b 1049
0f2d19dd
JB
1050void
1051scm_init_struct ()
0f2d19dd 1052{
880e114b
AW
1053 SCM name;
1054
01e74380
LC
1055 /* The first word of a struct is equal to `SCM_STRUCT_DATA (vtable) +
1056 scm_tc3_struct', and `SCM_STRUCT_DATA (vtable)' is 2 words after VTABLE by
1057 default. */
1058 GC_REGISTER_DISPLACEMENT (2 * sizeof (scm_t_bits) + scm_tc3_struct);
b6cf4d02 1059
227eff6a
LC
1060 /* In the general case, `SCM_STRUCT_DATA (obj)' points 2 words after the
1061 beginning of a GC-allocated region; that region is different from that of
1062 OBJ once OBJ has undergone class redefinition. */
1063 GC_REGISTER_DISPLACEMENT (2 * sizeof (scm_t_bits));
1064
b6cf4d02 1065 required_vtable_fields = scm_from_locale_string (SCM_VTABLE_BASE_LAYOUT);
2921f537 1066 scm_c_define ("standard-vtable-fields", required_vtable_fields);
b6cf4d02
AW
1067 required_applicable_fields = scm_from_locale_string (SCM_APPLICABLE_BASE_LAYOUT);
1068 required_applicable_with_setter_fields = scm_from_locale_string (SCM_APPLICABLE_WITH_SETTER_BASE_LAYOUT);
651f2cd2 1069
6d46f1e4 1070 scm_standard_vtable_vtable = scm_i_make_vtable_vtable (scm_nullstr);
880e114b
AW
1071 name = scm_from_utf8_symbol ("<standard-vtable>");
1072 scm_set_struct_vtable_name_x (scm_standard_vtable_vtable, name);
1073 scm_define (name, scm_standard_vtable_vtable);
b6cf4d02
AW
1074
1075 scm_applicable_struct_vtable_vtable =
db5ed685 1076 scm_make_struct (scm_standard_vtable_vtable, SCM_INUM0,
b6cf4d02 1077 scm_list_1 (scm_make_struct_layout (required_vtable_fields)));
880e114b 1078 name = scm_from_utf8_symbol ("<applicable-struct-vtable>");
b6cf4d02
AW
1079 SCM_SET_VTABLE_FLAGS (scm_applicable_struct_vtable_vtable,
1080 SCM_VTABLE_FLAG_APPLICABLE_VTABLE);
880e114b
AW
1081 scm_set_struct_vtable_name_x (scm_applicable_struct_vtable_vtable, name);
1082 scm_define (name, scm_applicable_struct_vtable_vtable);
b6cf4d02
AW
1083
1084 scm_applicable_struct_with_setter_vtable_vtable =
db5ed685 1085 scm_make_struct (scm_standard_vtable_vtable, SCM_INUM0,
b6cf4d02 1086 scm_list_1 (scm_make_struct_layout (required_vtable_fields)));
880e114b
AW
1087 name = scm_from_utf8_symbol ("<applicable-struct-with-setter-vtable>");
1088 scm_set_struct_vtable_name_x (scm_applicable_struct_with_setter_vtable_vtable, name);
b6cf4d02
AW
1089 SCM_SET_VTABLE_FLAGS (scm_applicable_struct_with_setter_vtable_vtable,
1090 SCM_VTABLE_FLAG_APPLICABLE_VTABLE | SCM_VTABLE_FLAG_SETTER_VTABLE);
880e114b 1091 scm_define (name, scm_applicable_struct_with_setter_vtable_vtable);
651f2cd2 1092
e11e83f3 1093 scm_c_define ("vtable-index-layout", scm_from_int (scm_vtable_index_layout));
86d31dfe 1094 scm_c_define ("vtable-index-printer",
b6cf4d02 1095 scm_from_int (scm_vtable_index_instance_printer));
e11e83f3 1096 scm_c_define ("vtable-offset-user", scm_from_int (scm_vtable_offset_user));
a0599745 1097#include "libguile/struct.x"
6d46f1e4
AW
1098#if SCM_ENABLE_DEPRECATED
1099 scm_c_define_gsubr ("make-vtable-vtable", 2, 0, 1, scm_make_vtable_vtable);
1100#endif
0f2d19dd 1101}
89e00824
ML
1102
1103/*
1104 Local Variables:
1105 c-file-style: "gnu"
1106 End:
1107*/