*** empty log message ***
[bpt/guile.git] / libguile / struct.c
CommitLineData
78a0461a 1/* Copyright (C) 1996, 1997, 1998, 1999 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. */
0f2d19dd
JB
41\f
42
43#include <stdio.h>
44#include "_scm.h"
20e6290e 45#include "chars.h"
bafcafb2 46#include "genio.h"
916d65b1 47#include "eval.h"
98d5f601
MD
48#include "alist.h"
49#include "weaks.h"
50#include "hashtab.h"
20e6290e
JB
51
52#include "struct.h"
0f2d19dd 53
95b88819
GH
54#ifdef HAVE_STRING_H
55#include <string.h>
56#endif
57
0f2d19dd
JB
58\f
59
60static SCM required_vtable_fields = SCM_BOOL_F;
98d5f601 61SCM scm_struct_table;
0f2d19dd
JB
62
63\f
64SCM_PROC (s_struct_make_layout, "make-struct-layout", 1, 0, 0, scm_make_struct_layout);
1cc91f1b 65
0f2d19dd
JB
66SCM
67scm_make_struct_layout (fields)
68 SCM fields;
0f2d19dd
JB
69{
70 SCM new_sym;
71 SCM_ASSERT (SCM_NIMP (fields) && SCM_ROSTRINGP (fields),
72 fields, SCM_ARG1, s_struct_make_layout);
73
74 {
75 char * field_desc;
76 int len;
77 int x;
78
79 len = SCM_ROLENGTH (fields);
80 field_desc = SCM_ROCHARS (fields);
81 SCM_ASSERT (!(len & 1), fields, "odd length field specification", s_struct_make_layout);
82
83 for (x = 0; x < len; x += 2)
84 {
85 switch (field_desc[x])
86 {
87 case 'u':
88 case 'p':
89#if 0
90 case 'i':
91 case 'd':
92#endif
93 case 's':
94 break;
95 default:
96 SCM_ASSERT (0, SCM_MAKICHR (field_desc[x]) , "unrecognized field type", s_struct_make_layout);
97 }
98
99 switch (field_desc[x + 1])
100 {
101 case 'w':
2c36c351 102 SCM_ASSERT (field_desc[x] != 's', SCM_MAKICHR (field_desc[x + 1]),
0f2d19dd
JB
103 "self fields not writable", s_struct_make_layout);
104
105 case 'r':
106 case 'o':
107 break;
2c36c351
MD
108 case 'R':
109 case 'W':
110 case 'O':
111 SCM_ASSERT (field_desc[x] != 's', SCM_MAKICHR (field_desc[x + 1]),
112 "self fields not allowed in tail array",
113 s_struct_make_layout);
114 SCM_ASSERT (x == len - 2, SCM_MAKICHR (field_desc[x + 1]),
115 "tail array field must be last field in layout",
116 s_struct_make_layout);
117 break;
0f2d19dd
JB
118 default:
119 SCM_ASSERT (0, SCM_MAKICHR (field_desc[x]) , "unrecognized ref specification", s_struct_make_layout);
120 }
121#if 0
122 if (field_desc[x] == 'd')
123 {
124 SCM_ASSERT (field_desc[x + 2] == '-', SCM_MAKINUM (x / 2), "missing dash field", s_struct_make_layout);
125 x += 2;
126 goto recheck_ref;
127 }
128#endif
129 }
130 new_sym = SCM_CAR (scm_intern_obarray (field_desc, len, SCM_BOOL_F));
131 }
132 return scm_return_first (new_sym, fields);
133}
134
135\f
136
137
1cc91f1b 138
a5bfe84d
MD
139void
140scm_struct_init (handle, tail_elts, inits)
0f2d19dd 141 SCM handle;
2c36c351 142 int tail_elts;
0f2d19dd 143 SCM inits;
0f2d19dd
JB
144{
145 SCM layout;
146 SCM * data;
147 unsigned char * fields_desc;
35de7ebe 148 unsigned char prot = 0;
0f2d19dd
JB
149 int n_fields;
150 SCM * mem;
2c36c351
MD
151 int tailp = 0;
152
0f2d19dd
JB
153 layout = SCM_STRUCT_LAYOUT (handle);
154 data = SCM_STRUCT_DATA (handle);
2c36c351 155 fields_desc = (unsigned char *) SCM_CHARS (layout) - 2;
0f2d19dd
JB
156 n_fields = SCM_LENGTH (layout) / 2;
157 mem = SCM_STRUCT_DATA (handle);
158 while (n_fields)
159 {
2c36c351
MD
160 if (!tailp)
161 {
162 fields_desc += 2;
163 prot = fields_desc[1];
164 if (SCM_LAYOUT_TAILP (prot))
165 {
166 tailp = 1;
167 prot = prot == 'R' ? 'r' : prot == 'W' ? 'w' : 'o';
168 *mem++ = tail_elts;
169 n_fields += tail_elts - 1;
170 if (n_fields == 0)
171 break;
172 }
173 }
174
0f2d19dd
JB
175 switch (*fields_desc)
176 {
177#if 0
178 case 'i':
2c36c351 179 if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
0f2d19dd
JB
180 *mem = 0;
181 else
182 {
a5bfe84d 183 *mem = scm_num2long (SCM_CAR (inits), SCM_ARGn, "scm_struct_init");
0f2d19dd
JB
184 inits = SCM_CDR (inits);
185 }
186 break;
187#endif
188
189 case 'u':
2c36c351 190 if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
0f2d19dd
JB
191 *mem = 0;
192 else
193 {
a5bfe84d 194 *mem = scm_num2ulong (SCM_CAR (inits), SCM_ARGn, "scm_struct_init");
0f2d19dd
JB
195 inits = SCM_CDR (inits);
196 }
197 break;
198
199 case 'p':
2c36c351 200 if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
916d65b1 201 *mem = SCM_BOOL_F;
0f2d19dd
JB
202 else
203 {
204 *mem = SCM_CAR (inits);
205 inits = SCM_CDR (inits);
206 }
207
208 break;
209
210#if 0
211 case 'd':
2c36c351 212 if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
0f2d19dd
JB
213 *((double *)mem) = 0.0;
214 else
215 {
a5bfe84d 216 *mem = scm_num2dbl (SCM_CAR (inits), "scm_struct_init");
0f2d19dd
JB
217 inits = SCM_CDR (inits);
218 }
219 fields_desc += 2;
220 break;
221#endif
222
223 case 's':
224 *mem = handle;
225 break;
226 }
227
0f2d19dd
JB
228 n_fields--;
229 mem++;
230 }
231}
232
233
234SCM_PROC (s_struct_p, "struct?", 1, 0, 0, scm_struct_p);
1cc91f1b 235
0f2d19dd
JB
236SCM
237scm_struct_p (x)
238 SCM x;
0f2d19dd
JB
239{
240 return ((SCM_NIMP (x) && SCM_STRUCTP (x))
241 ? SCM_BOOL_T
242 : SCM_BOOL_F);
243}
244
245SCM_PROC (s_struct_vtable_p, "struct-vtable?", 1, 0, 0, scm_struct_vtable_p);
1cc91f1b 246
0f2d19dd
JB
247SCM
248scm_struct_vtable_p (x)
249 SCM x;
0f2d19dd
JB
250{
251 SCM layout;
252 SCM * mem;
253
254 if (SCM_IMP (x))
255 return SCM_BOOL_F;
256
257 if (!SCM_STRUCTP (x))
258 return SCM_BOOL_F;
259
260 layout = SCM_STRUCT_LAYOUT (x);
261
262 if (SCM_LENGTH (layout) < SCM_LENGTH (required_vtable_fields))
263 return SCM_BOOL_F;
264
265 if (strncmp (SCM_CHARS (layout), SCM_CHARS (required_vtable_fields),
266 SCM_LENGTH (required_vtable_fields)))
267 return SCM_BOOL_F;
268
269 mem = SCM_STRUCT_DATA (x);
270
271 if (mem[1] != 0)
272 return SCM_BOOL_F;
273
274 if (SCM_IMP (mem[0]))
275 return SCM_BOOL_F;
276
277 return (SCM_SYMBOLP (mem[0])
278 ? SCM_BOOL_T
279 : SCM_BOOL_F);
280}
281
14d1400f
JB
282
283/* All struct data must be allocated at an address whose bottom three
284 bits are zero. This is because the tag for a struct lives in the
285 bottom three bits of the struct's car, and the upper bits point to
286 the data of its vtable, which is a struct itself. Thus, if the
287 address of that data doesn't end in three zeros, tagging it will
288 destroy the pointer.
289
290 This function allocates a block of memory, and returns a pointer at
291 least scm_struct_n_extra_words words into the block. Furthermore,
292 it guarantees that that pointer's least three significant bits are
293 all zero.
294
295 The argument n_words should be the number of words that should
296 appear after the returned address. (That is, it shouldn't include
297 scm_struct_n_extra_words.)
298
299 This function initializes the following fields of the struct:
300
ad196599 301 scm_struct_i_ptr --- the actual start of the block of memory; the
14d1400f
JB
302 address you should pass to 'free' to dispose of the block.
303 This field allows us to both guarantee that the returned
304 address is divisible by eight, and allow the GC to free the
305 block.
306
307 scm_struct_i_n_words --- the number of words allocated to the
308 block, including the extra fields. This is used by the GC.
309
14d1400f
JB
310 Ugh. */
311
312
a5bfe84d
MD
313SCM *
314scm_alloc_struct (int n_words, int n_extra, char *who)
14d1400f 315{
a5bfe84d 316 int size = sizeof (SCM) * (n_words + n_extra) + 7;
14d1400f
JB
317 SCM *block = (SCM *) scm_must_malloc (size, who);
318
319 /* Adjust the pointer to hide the extra words. */
a5bfe84d 320 SCM *p = block + n_extra;
14d1400f
JB
321
322 /* Adjust it even further so it's aligned on an eight-byte boundary. */
323 p = (SCM *) (((SCM) p + 7) & ~7);
324
ad196599
MD
325 /* Initialize a few fields as described above. */
326 p[scm_struct_i_free] = (SCM) scm_struct_free_standard;
14d1400f 327 p[scm_struct_i_ptr] = (SCM) block;
ad196599
MD
328 p[scm_struct_i_n_words] = (SCM) n_words;
329 p[scm_struct_i_flags] = 0;
14d1400f
JB
330
331 return p;
332}
333
97056309 334scm_sizet
ad196599
MD
335scm_struct_free_0 (SCM *vtable, SCM *data)
336{
337 return 0;
338}
339
97056309 340scm_sizet
ad196599
MD
341scm_struct_free_light (SCM *vtable, SCM *data)
342{
343 free (data);
344 return vtable[scm_struct_i_size] & ~SCM_STRUCTF_MASK;
345}
346
97056309 347scm_sizet
ad196599
MD
348scm_struct_free_standard (SCM *vtable, SCM *data)
349{
350 size_t n = ((data[scm_struct_i_n_words] + scm_struct_n_extra_words)
351 * sizeof (SCM) + 7);
352 free ((void *) data[scm_struct_i_ptr]);
353 return n;
354}
355
97056309 356scm_sizet
ad196599
MD
357scm_struct_free_entity (SCM *vtable, SCM *data)
358{
359 size_t n = ((data[scm_struct_i_n_words] + scm_struct_entity_n_extra_words)
360 * sizeof (SCM) + 7);
361 free ((void *) data[scm_struct_i_ptr]);
362 return n;
363}
14d1400f 364
0f2d19dd 365SCM_PROC (s_make_struct, "make-struct", 2, 0, 1, scm_make_struct);
1cc91f1b 366
0f2d19dd
JB
367SCM
368scm_make_struct (vtable, tail_array_size, init)
369 SCM vtable;
370 SCM tail_array_size;
371 SCM init;
0f2d19dd
JB
372{
373 SCM layout;
374 int basic_size;
375 int tail_elts;
376 SCM * data;
377 SCM handle;
378
379 SCM_ASSERT ((SCM_BOOL_F != scm_struct_vtable_p (vtable)),
380 vtable, SCM_ARG1, s_make_struct);
14d1400f
JB
381 SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG2,
382 s_make_struct);
0f2d19dd 383
4bfdf158 384 layout = SCM_STRUCT_DATA (vtable)[scm_vtable_index_layout];
0f2d19dd
JB
385 basic_size = SCM_LENGTH (layout) / 2;
386 tail_elts = SCM_INUM (tail_array_size);
387 SCM_NEWCELL (handle);
388 SCM_DEFER_INTS;
a5bfe84d
MD
389 if (SCM_STRUCT_DATA (vtable)[scm_struct_i_flags] & SCM_STRUCTF_ENTITY)
390 {
391 data = scm_alloc_struct (basic_size + tail_elts,
98d5f601 392 scm_struct_entity_n_extra_words,
a5bfe84d 393 "make-struct");
2c53acd5 394 data[scm_struct_i_procedure] = SCM_BOOL_F;
25c94826 395 data[scm_struct_i_setter] = SCM_BOOL_F;
a5bfe84d
MD
396 }
397 else
398 data = scm_alloc_struct (basic_size + tail_elts,
399 scm_struct_n_extra_words,
400 "make-struct");
0f2d19dd 401 SCM_SETCDR (handle, data);
35457f1e 402 SCM_SETCAR (handle, ((SCM)SCM_STRUCT_DATA (vtable)) + scm_tc3_cons_gloc);
a5bfe84d 403 scm_struct_init (handle, tail_elts, init);
0f2d19dd
JB
404 SCM_ALLOW_INTS;
405 return handle;
406}
407
408
409
410SCM_PROC (s_make_vtable_vtable, "make-vtable-vtable", 2, 0, 1, scm_make_vtable_vtable);
1cc91f1b 411
0f2d19dd
JB
412SCM
413scm_make_vtable_vtable (extra_fields, tail_array_size, init)
414 SCM extra_fields;
415 SCM tail_array_size;
416 SCM init;
0f2d19dd
JB
417{
418 SCM fields;
419 SCM layout;
420 int basic_size;
421 int tail_elts;
422 SCM * data;
423 SCM handle;
424
425 SCM_ASSERT (SCM_NIMP (extra_fields) && SCM_ROSTRINGP (extra_fields),
426 extra_fields, SCM_ARG1, s_make_vtable_vtable);
14d1400f
JB
427 SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG2,
428 s_make_vtable_vtable);
0f2d19dd
JB
429
430 fields = scm_string_append (scm_listify (required_vtable_fields,
431 extra_fields,
432 SCM_UNDEFINED));
433 layout = scm_make_struct_layout (fields);
434 basic_size = SCM_LENGTH (layout) / 2;
435 tail_elts = SCM_INUM (tail_array_size);
436 SCM_NEWCELL (handle);
437 SCM_DEFER_INTS;
a5bfe84d
MD
438 data = scm_alloc_struct (basic_size + tail_elts,
439 scm_struct_n_extra_words,
440 "make-vtable-vtable");
0f2d19dd 441 SCM_SETCDR (handle, data);
35457f1e 442 SCM_SETCAR (handle, ((SCM)data) + scm_tc3_cons_gloc);
0f2d19dd 443 SCM_STRUCT_LAYOUT (handle) = layout;
a5bfe84d 444 scm_struct_init (handle, tail_elts, scm_cons (layout, init));
0f2d19dd
JB
445 SCM_ALLOW_INTS;
446 return handle;
447}
448
449\f
450
451
452SCM_PROC (s_struct_ref, "struct-ref", 2, 0, 0, scm_struct_ref);
1cc91f1b 453
0f2d19dd
JB
454SCM
455scm_struct_ref (handle, pos)
456 SCM handle;
457 SCM pos;
0f2d19dd 458{
5e840c2e 459 SCM answer = SCM_UNDEFINED;
0f2d19dd
JB
460 SCM * data;
461 SCM layout;
462 int p;
463 int n_fields;
464 unsigned char * fields_desc;
f3667f52 465 unsigned char field_type = 0;
0f2d19dd
JB
466
467
468 SCM_ASSERT (SCM_NIMP (handle) && SCM_STRUCTP (handle), handle,
469 SCM_ARG1, s_struct_ref);
470 SCM_ASSERT (SCM_INUMP (pos), pos, SCM_ARG2, s_struct_ref);
471
472 layout = SCM_STRUCT_LAYOUT (handle);
473 data = SCM_STRUCT_DATA (handle);
474 p = SCM_INUM (pos);
475
ad196599
MD
476 fields_desc = (unsigned char *) SCM_CHARS (layout);
477 n_fields = data[scm_struct_i_n_words];
2c36c351
MD
478
479 SCM_ASSERT (p < n_fields, pos, SCM_OUTOFRANGE, s_struct_ref);
0f2d19dd 480
2c36c351
MD
481 if (p * 2 < SCM_LENGTH (layout))
482 {
483 unsigned char ref;
484 field_type = fields_desc[p * 2];
485 ref = fields_desc[p * 2 + 1];
486 if ((ref != 'r') && (ref != 'w'))
487 {
488 if ((ref == 'R') || (ref == 'W'))
489 field_type = 'u';
490 else
491 SCM_ASSERT (0, pos, "ref denied", s_struct_ref);
492 }
493 }
494 else if (fields_desc[SCM_LENGTH (layout) - 1] != 'O')
495 field_type = fields_desc[SCM_LENGTH (layout) - 2];
496 else
497 {
498 SCM_ASSERT (0, pos, "ref denied", s_struct_ref);
35de7ebe 499 abort ();
2c36c351
MD
500 }
501
0f2d19dd
JB
502 switch (field_type)
503 {
504 case 'u':
505 answer = scm_ulong2num (data[p]);
506 break;
507
508#if 0
509 case 'i':
510 answer = scm_long2num (data[p]);
511 break;
512
513 case 'd':
514 answer = scm_makdbl (*((double *)&(data[p])), 0.0);
515 break;
516#endif
517
518 case 's':
519 case 'p':
520 answer = data[p];
521 break;
522
523
524 default:
525 SCM_ASSERT (0, SCM_MAKICHR (field_type), "unrecognized field type", s_struct_ref);
526 break;
527 }
528
529 return answer;
530}
531
532
533SCM_PROC (s_struct_set_x, "struct-set!", 3, 0, 0, scm_struct_set_x);
1cc91f1b 534
0f2d19dd
JB
535SCM
536scm_struct_set_x (handle, pos, val)
537 SCM handle;
538 SCM pos;
539 SCM val;
0f2d19dd
JB
540{
541 SCM * data;
542 SCM layout;
543 int p;
544 int n_fields;
545 unsigned char * fields_desc;
f3667f52 546 unsigned char field_type = 0;
0f2d19dd
JB
547
548
549
550 SCM_ASSERT (SCM_NIMP (handle) && SCM_STRUCTP (handle), handle,
551 SCM_ARG1, s_struct_ref);
552 SCM_ASSERT (SCM_INUMP (pos), pos, SCM_ARG2, s_struct_ref);
553
554 layout = SCM_STRUCT_LAYOUT (handle);
555 data = SCM_STRUCT_DATA (handle);
556 p = SCM_INUM (pos);
557
558 fields_desc = (unsigned char *)SCM_CHARS (layout);
ad196599 559 n_fields = data[scm_struct_i_n_words];
0f2d19dd 560
2c36c351 561 SCM_ASSERT (p < n_fields, pos, SCM_OUTOFRANGE, s_struct_set_x);
0f2d19dd 562
2c36c351
MD
563 if (p * 2 < SCM_LENGTH (layout))
564 {
565 unsigned char set_x;
566 field_type = fields_desc[p * 2];
567 set_x = fields_desc [p * 2 + 1];
568 if (set_x != 'w')
569 SCM_ASSERT (0, pos, "set_x denied", s_struct_set_x);
570 }
571 else if (fields_desc[SCM_LENGTH (layout) - 1] == 'W')
572 field_type = fields_desc[SCM_LENGTH (layout) - 2];
573 else
574 {
575 SCM_ASSERT (0, pos, "set_x denied", s_struct_ref);
35de7ebe 576 abort ();
2c36c351
MD
577 }
578
0f2d19dd
JB
579 switch (field_type)
580 {
581 case 'u':
582 data[p] = (SCM)scm_num2ulong (val, (char *)SCM_ARG3, s_struct_set_x);
583 break;
584
585#if 0
586 case 'i':
587 data[p] = scm_num2long (val, (char *)SCM_ARG3, s_struct_set_x);
588 break;
589
590 case 'd':
591 *((double *)&(data[p])) = scm_num2dbl (val, (char *)SCM_ARG3);
592 break;
593#endif
594
595 case 'p':
596 data[p] = val;
597 break;
598
599 case 's':
600 SCM_ASSERT (0, SCM_MAKICHR (field_type), "self fields immutable", s_struct_set_x);
601 break;
602
603 default:
604 SCM_ASSERT (0, SCM_MAKICHR (field_type), "unrecognized field type", s_struct_set_x);
605 break;
606 }
607
608 return val;
609}
610
611
612SCM_PROC (s_struct_vtable, "struct-vtable", 1, 0, 0, scm_struct_vtable);
1cc91f1b 613
0f2d19dd
JB
614SCM
615scm_struct_vtable (handle)
616 SCM handle;
0f2d19dd
JB
617{
618 SCM_ASSERT (SCM_NIMP (handle) && SCM_STRUCTP (handle), handle,
619 SCM_ARG1, s_struct_vtable);
620 return SCM_STRUCT_VTABLE (handle);
621}
622
623
624SCM_PROC (s_struct_vtable_tag, "struct-vtable-tag", 1, 0, 0, scm_struct_vtable_tag);
1cc91f1b 625
0f2d19dd
JB
626SCM
627scm_struct_vtable_tag (handle)
628 SCM handle;
0f2d19dd 629{
98d5f601 630 SCM_ASSERT (SCM_NFALSEP (scm_struct_vtable_p (handle)),
0f2d19dd 631 handle, SCM_ARG1, s_struct_vtable_tag);
ad196599 632 return scm_long2num ((long) SCM_STRUCT_DATA (handle) >> 3);
98d5f601
MD
633}
634
635/* {Associating names and classes with vtables}
636 *
637 * The name of a vtable should probably be stored as a slot. This is
638 * a backward compatible solution until agreement has been achieved on
639 * how to associate names with vtables.
640 */
641
642unsigned int
643scm_struct_ihashq (SCM obj, unsigned int n)
644{
ad196599
MD
645 /* The length of the hash table should be a relative prime it's not
646 necessary to shift down the address. */
647 return obj % n;
98d5f601
MD
648}
649
650SCM
651scm_struct_create_handle (SCM obj)
652{
653 SCM handle = scm_hash_fn_create_handle_x (scm_struct_table,
654 obj,
655 SCM_BOOL_F,
656 scm_struct_ihashq,
657 scm_sloppy_assq,
658 0);
659 if (SCM_FALSEP (SCM_CDR (handle)))
660 SCM_SETCDR (handle, scm_cons (SCM_BOOL_F, SCM_BOOL_F));
661 return handle;
662}
663
664SCM_PROC (s_struct_vtable_name, "struct-vtable-name", 1, 0, 0, scm_struct_vtable_name);
665
666SCM
667scm_struct_vtable_name (SCM vtable)
668{
669 SCM_ASSERT (SCM_NFALSEP (scm_struct_vtable_p (vtable)),
670 vtable, SCM_ARG1, s_struct_vtable_name);
671
672 return SCM_STRUCT_TABLE_NAME (SCM_CDR (scm_struct_create_handle (vtable)));
673}
674
675SCM_PROC (s_set_struct_vtable_name_x, "set-struct-vtable-name!", 2, 0, 0, scm_set_struct_vtable_name_x);
676
677SCM
678scm_set_struct_vtable_name_x (SCM vtable, SCM name)
679{
680 SCM_ASSERT (SCM_NIMP (vtable) && SCM_NFALSEP (scm_struct_vtable_p (vtable)),
681 vtable, SCM_ARG1, s_set_struct_vtable_name_x);
682 SCM_ASSERT (SCM_NIMP (name) && SCM_SYMBOLP (name),
683 name, SCM_ARG2, s_set_struct_vtable_name_x);
684 SCM_SET_STRUCT_TABLE_NAME (SCM_CDR (scm_struct_create_handle (vtable)),
685 name);
686 return SCM_UNSPECIFIED;
0f2d19dd
JB
687}
688
689
690\f
691
bafcafb2
MV
692void
693scm_print_struct (exp, port, pstate)
694 SCM exp;
695 SCM port;
696 scm_print_state *pstate;
697{
4bfdf158
MD
698 if (SCM_NFALSEP (scm_procedure_p (SCM_STRUCT_PRINTER (exp))))
699 scm_printer_apply (SCM_STRUCT_PRINTER (exp), exp, port, pstate);
700 else
bafcafb2 701 {
a1ae1799
MD
702 SCM vtable = SCM_STRUCT_VTABLE (exp);
703 SCM name = scm_struct_vtable_name (vtable);
704 scm_puts ("#<", port);
705 if (SCM_NFALSEP (name))
706 scm_display (name, port);
707 else
708 scm_puts ("struct", port);
709 scm_putc (' ', port);
710 scm_intprint (vtable, 16, port);
b7f3516f 711 scm_putc (':', port);
916d65b1 712 scm_intprint (exp, 16, port);
b7f3516f 713 scm_putc ('>', port);
bafcafb2 714 }
bafcafb2 715}
1cc91f1b 716
0f2d19dd
JB
717void
718scm_init_struct ()
0f2d19dd 719{
98d5f601
MD
720 scm_struct_table
721 = scm_permanent_object (scm_make_weak_key_hash_table (SCM_MAKINUM (31)));
4bfdf158 722 required_vtable_fields = SCM_CAR (scm_intern_obarray ("pruosrpw", sizeof ("pruosrpw") - 1, SCM_BOOL_F));
0f2d19dd 723 scm_permanent_object (required_vtable_fields);
4bfdf158
MD
724 scm_sysintern ("vtable-index-layout", SCM_MAKINUM (scm_vtable_index_layout));
725 scm_sysintern ("vtable-index-vtable", SCM_MAKINUM (scm_vtable_index_vtable));
726 scm_sysintern ("vtable-index-printer", SCM_MAKINUM (scm_vtable_index_printer));
727 scm_sysintern ("vtable-offset-user", SCM_MAKINUM (scm_vtable_offset_user));
0f2d19dd
JB
728#include "struct.x"
729}