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