1 /* Copyright (C) 1996 Free Software Foundation, Inc.
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)
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.
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
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
52 static SCM required_vtable_fields
= SCM_BOOL_F
;
53 static int struct_num
= 0;
56 SCM_PROC (s_struct_make_layout
, "make-struct-layout", 1, 0, 0, scm_make_struct_layout
);
59 scm_make_struct_layout (SCM fields
)
62 scm_make_struct_layout (fields
)
67 SCM_ASSERT (SCM_NIMP (fields
) && SCM_ROSTRINGP (fields
),
68 fields
, SCM_ARG1
, s_struct_make_layout
);
75 len
= SCM_ROLENGTH (fields
);
76 field_desc
= SCM_ROCHARS (fields
);
77 SCM_ASSERT (!(len
& 1), fields
, "odd length field specification", s_struct_make_layout
);
79 for (x
= 0; x
< len
; x
+= 2)
81 switch (field_desc
[x
])
92 SCM_ASSERT (0, SCM_MAKICHR (field_desc
[x
]) , "unrecognized field type", s_struct_make_layout
);
95 switch (field_desc
[x
+ 1])
98 SCM_ASSERT ((field_desc
[x
] != 's'), SCM_MAKICHR (field_desc
[x
+ 1]),
99 "self fields not writable", s_struct_make_layout
);
105 SCM_ASSERT (0, SCM_MAKICHR (field_desc
[x
]) , "unrecognized ref specification", s_struct_make_layout
);
108 if (field_desc
[x
] == 'd')
110 SCM_ASSERT (field_desc
[x
+ 2] == '-', SCM_MAKINUM (x
/ 2), "missing dash field", s_struct_make_layout
);
116 new_sym
= SCM_CAR (scm_intern_obarray (field_desc
, len
, SCM_BOOL_F
));
118 return scm_return_first (new_sym
, fields
);
126 init_struct (SCM handle
, SCM tail_elts
, SCM inits
)
129 init_struct (handle
, tail_elts
, inits
)
137 unsigned char * fields_desc
;
141 layout
= SCM_STRUCT_LAYOUT (handle
);
142 data
= SCM_STRUCT_DATA (handle
);
143 fields_desc
= (unsigned char *)SCM_CHARS (layout
);
144 n_fields
= SCM_LENGTH (layout
) / 2;
145 mem
= SCM_STRUCT_DATA (handle
);
148 switch (*fields_desc
)
152 if ( ((fields_desc
[1] != 'r') && (fields_desc
[1] != 'w'))
153 || ((inits
== SCM_EOL
) || !SCM_NUMBERP (SCM_CAR (inits
))))
157 *mem
= scm_num2long (SCM_CAR (inits
), SCM_ARGn
, "init_struct");
158 inits
= SCM_CDR (inits
);
164 if ( ((fields_desc
[1] != 'r') && (fields_desc
[1] != 'w'))
165 || ((inits
== SCM_EOL
) || !SCM_NUMBERP (SCM_CAR (inits
))))
169 *mem
= scm_num2ulong (SCM_CAR (inits
), SCM_ARGn
, "init_struct");
170 inits
= SCM_CDR (inits
);
175 if ( ((fields_desc
[1] != 'r') && (fields_desc
[1] != 'w'))
176 || (inits
== SCM_EOL
))
180 *mem
= SCM_CAR (inits
);
181 inits
= SCM_CDR (inits
);
188 if ( ((fields_desc
[1] != 'r') && (fields_desc
[1] != 'w'))
189 || ((inits
== SCM_EOL
) || !SCM_NUMBERP (SCM_CAR (inits
))))
190 *((double *)mem
) = 0.0;
193 *mem
= scm_num2dbl (SCM_CAR (inits
), "init_struct");
194 inits
= SCM_CDR (inits
);
212 SCM_PROC (s_struct_p
, "struct?", 1, 0, 0, scm_struct_p
);
222 return ((SCM_NIMP (x
) && SCM_STRUCTP (x
))
227 SCM_PROC (s_struct_vtable_p
, "struct-vtable?", 1, 0, 0, scm_struct_vtable_p
);
230 scm_struct_vtable_p (SCM x
)
233 scm_struct_vtable_p (x
)
243 if (!SCM_STRUCTP (x
))
246 layout
= SCM_STRUCT_LAYOUT (x
);
248 if (SCM_LENGTH (layout
) < SCM_LENGTH (required_vtable_fields
))
251 if (strncmp (SCM_CHARS (layout
), SCM_CHARS (required_vtable_fields
),
252 SCM_LENGTH (required_vtable_fields
)))
255 mem
= SCM_STRUCT_DATA (x
);
260 if (SCM_IMP (mem
[0]))
263 return (SCM_SYMBOLP (mem
[0])
268 SCM_PROC (s_make_struct
, "make-struct", 2, 0, 1, scm_make_struct
);
271 scm_make_struct (SCM vtable
, SCM tail_array_size
, SCM init
)
274 scm_make_struct (vtable
, tail_array_size
, init
)
286 SCM_ASSERT ((SCM_BOOL_F
!= scm_struct_vtable_p (vtable
)),
287 vtable
, SCM_ARG1
, s_make_struct
);
288 SCM_ASSERT (SCM_INUMP (tail_array_size
), tail_array_size
, SCM_ARG2
, s_make_struct
);
290 layout
= SCM_STRUCT_DATA (vtable
)[scm_struct_i_layout
];
291 basic_size
= SCM_LENGTH (layout
) / 2;
292 tail_elts
= SCM_INUM (tail_array_size
);
293 SCM_NEWCELL (handle
);
295 data
= (SCM
*)scm_must_malloc (sizeof (SCM
) * (2 + basic_size
+ tail_elts
), "structure");
296 *data
= (SCM
)(2 + basic_size
+ tail_elts
);
297 data
[1] = struct_num
++;
299 SCM_SETCDR (handle
, data
);
300 SCM_SETCAR (handle
, ((SCM
)SCM_STRUCT_DATA (vtable
)) + 1);
301 init_struct (handle
, tail_elts
, init
);
308 SCM_PROC (s_make_vtable_vtable
, "make-vtable-vtable", 2, 0, 1, scm_make_vtable_vtable
);
311 scm_make_vtable_vtable (SCM extra_fields
, SCM tail_array_size
, SCM init
)
314 scm_make_vtable_vtable (extra_fields
, tail_array_size
, init
)
327 SCM_ASSERT (SCM_NIMP (extra_fields
) && SCM_ROSTRINGP (extra_fields
),
328 extra_fields
, SCM_ARG1
, s_make_vtable_vtable
);
329 SCM_ASSERT (SCM_INUMP (tail_array_size
), tail_array_size
, SCM_ARG3
, s_make_vtable_vtable
);
332 fields
= scm_string_append (scm_listify (required_vtable_fields
,
335 layout
= scm_make_struct_layout (fields
);
336 basic_size
= SCM_LENGTH (layout
) / 2;
337 tail_elts
= SCM_INUM (tail_array_size
);
338 SCM_NEWCELL (handle
);
340 data
= (SCM
*)scm_must_malloc (sizeof (SCM
) * (2 + basic_size
+ tail_elts
), "structure");
341 *data
= (SCM
)(2 + basic_size
+ tail_elts
);
342 data
[1] = struct_num
++;
344 SCM_SETCDR (handle
, data
);
345 SCM_SETCAR (handle
, ((SCM
)data
) + 1);
346 SCM_STRUCT_LAYOUT (handle
) = layout
;
347 init_struct (handle
, tail_elts
, scm_cons (layout
, init
));
355 SCM_PROC (s_struct_ref
, "struct-ref", 2, 0, 0, scm_struct_ref
);
358 scm_struct_ref (SCM handle
, SCM pos
)
361 scm_struct_ref (handle
, pos
)
371 unsigned char * fields_desc
;
372 unsigned char field_type
;
375 SCM_ASSERT (SCM_NIMP (handle
) && SCM_STRUCTP (handle
), handle
,
376 SCM_ARG1
, s_struct_ref
);
377 SCM_ASSERT (SCM_INUMP (pos
), pos
, SCM_ARG2
, s_struct_ref
);
379 layout
= SCM_STRUCT_LAYOUT (handle
);
380 data
= SCM_STRUCT_DATA (handle
);
383 fields_desc
= (unsigned char *)SCM_CHARS (layout
);
384 n_fields
= SCM_LENGTH (layout
) / 2;
386 SCM_ASSERT (p
<= n_fields
, pos
, SCM_OUTOFRANGE
, s_struct_ref
);
388 field_type
= fields_desc
[p
* 2];
391 ref
= fields_desc
[p
* 2 + 1];
392 if ((ref
!= 'r') && (ref
!= 'w'))
394 if ((ref
== 'R') || (ref
== 'W'))
397 SCM_ASSERT (0, pos
, "ref denied", s_struct_ref
);
403 answer
= scm_ulong2num (data
[p
]);
408 answer
= scm_long2num (data
[p
]);
412 answer
= scm_makdbl (*((double *)&(data
[p
])), 0.0);
423 SCM_ASSERT (0, SCM_MAKICHR (field_type
), "unrecognized field type", s_struct_ref
);
431 SCM_PROC (s_struct_set_x
, "struct-set!", 3, 0, 0, scm_struct_set_x
);
434 scm_struct_set_x (SCM handle
, SCM pos
, SCM val
)
437 scm_struct_set_x (handle
, pos
, val
)
447 unsigned char * fields_desc
;
448 unsigned char field_type
;
452 SCM_ASSERT (SCM_NIMP (handle
) && SCM_STRUCTP (handle
), handle
,
453 SCM_ARG1
, s_struct_ref
);
454 SCM_ASSERT (SCM_INUMP (pos
), pos
, SCM_ARG2
, s_struct_ref
);
456 layout
= SCM_STRUCT_LAYOUT (handle
);
457 data
= SCM_STRUCT_DATA (handle
);
460 fields_desc
= (unsigned char *)SCM_CHARS (layout
);
461 n_fields
= SCM_LENGTH (layout
) / 2;
463 SCM_ASSERT (p
<= n_fields
, pos
, SCM_OUTOFRANGE
, s_struct_set_x
);
465 field_type
= fields_desc
[p
* 2];
468 set_x
= fields_desc
[p
* 2 + 1];
470 SCM_ASSERT (0, pos
, "set_x denied", s_struct_set_x
);
475 data
[p
] = (SCM
)scm_num2ulong (val
, (char *)SCM_ARG3
, s_struct_set_x
);
480 data
[p
] = scm_num2long (val
, (char *)SCM_ARG3
, s_struct_set_x
);
484 *((double *)&(data
[p
])) = scm_num2dbl (val
, (char *)SCM_ARG3
);
493 SCM_ASSERT (0, SCM_MAKICHR (field_type
), "self fields immutable", s_struct_set_x
);
497 SCM_ASSERT (0, SCM_MAKICHR (field_type
), "unrecognized field type", s_struct_set_x
);
505 SCM_PROC (s_struct_vtable
, "struct-vtable", 1, 0, 0, scm_struct_vtable
);
508 scm_struct_vtable (SCM handle
)
511 scm_struct_vtable (handle
)
515 SCM_ASSERT (SCM_NIMP (handle
) && SCM_STRUCTP (handle
), handle
,
516 SCM_ARG1
, s_struct_vtable
);
517 return SCM_STRUCT_VTABLE (handle
);
521 SCM_PROC (s_struct_vtable_tag
, "struct-vtable-tag", 1, 0, 0, scm_struct_vtable_tag
);
524 scm_struct_vtable_tag (SCM handle
)
527 scm_struct_vtable_tag (handle
)
531 SCM_ASSERT (SCM_NIMP (handle
) && (SCM_BOOL_F
!= scm_struct_vtable_p (handle
)),
532 handle
, SCM_ARG1
, s_struct_vtable_tag
);
533 return scm_long2num (SCM_STRUCT_DATA (handle
)[-1]);
541 scm_init_struct (void)
547 required_vtable_fields
= SCM_CAR (scm_intern_obarray ("pruosr", sizeof ("pruosr") - 1, SCM_BOOL_F
));
548 scm_permanent_object (required_vtable_fields
);
549 scm_sysintern ("struct-vtable-offset", SCM_MAKINUM (scm_struct_i_vtable_offset
));