struct.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /* Copyright (C) 1996, 97, 98, 99, 2000, 2002 Free Software Foundation, Inc.
  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
  15. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 USA
  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.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <stdio.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/chars.h"
  44. #include "libguile/eval.h"
  45. #include "libguile/alist.h"
  46. #include "libguile/weaks.h"
  47. #include "libguile/hashtab.h"
  48. #include "libguile/ports.h"
  49. #include "libguile/strings.h"
  50. #include "libguile/validate.h"
  51. #include "libguile/struct.h"
  52. #ifdef HAVE_STRING_H
  53. #include <string.h>
  54. #endif
  55. static SCM required_vtable_fields = SCM_BOOL_F;
  56. SCM scm_struct_table;
  57. SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
  58. (SCM fields),
  59. "Return a new structure layout object.\n\n"
  60. "@var{fields} must be a read-only string made up of pairs of characters\n"
  61. "strung together. The first character of each pair describes a field\n"
  62. "type, the second a field protection. Allowed types are 'p' for\n"
  63. "GC-protected Scheme data, 'u' for unprotected binary data, and 's' for\n"
  64. "fields that should point to the structure itself. Allowed protections\n"
  65. "are 'w' for mutable fields, 'r' for read-only fields, and 'o' for opaque \n"
  66. "fields. The last field protection specification may be capitalized to\n"
  67. "indicate that the field is a tail-array.")
  68. #define FUNC_NAME s_scm_make_struct_layout
  69. {
  70. SCM new_sym;
  71. SCM_VALIDATE_ROSTRING (1,fields);
  72. { /* scope */
  73. char * field_desc;
  74. int len;
  75. int x;
  76. len = SCM_ROLENGTH (fields);
  77. field_desc = SCM_ROCHARS (fields);
  78. SCM_ASSERT (!(len & 1), fields, "odd length field specification", FUNC_NAME);
  79. for (x = 0; x < len; x += 2)
  80. {
  81. switch (field_desc[x])
  82. {
  83. case 'u':
  84. case 'p':
  85. #if 0
  86. case 'i':
  87. case 'd':
  88. #endif
  89. case 's':
  90. break;
  91. default:
  92. SCM_ASSERT (0, SCM_MAKE_CHAR (field_desc[x]) , "unrecognized field type", FUNC_NAME);
  93. }
  94. switch (field_desc[x + 1])
  95. {
  96. case 'w':
  97. SCM_ASSERT (field_desc[x] != 's', SCM_MAKE_CHAR (field_desc[x + 1]),
  98. "self fields not writable", FUNC_NAME);
  99. case 'r':
  100. case 'o':
  101. break;
  102. case 'R':
  103. case 'W':
  104. case 'O':
  105. SCM_ASSERT (field_desc[x] != 's', SCM_MAKE_CHAR (field_desc[x + 1]),
  106. "self fields not allowed in tail array",
  107. FUNC_NAME);
  108. SCM_ASSERT (x == len - 2, SCM_MAKE_CHAR (field_desc[x + 1]),
  109. "tail array field must be last field in layout",
  110. FUNC_NAME);
  111. break;
  112. default:
  113. SCM_ASSERT (0, SCM_MAKE_CHAR (field_desc[x]) , "unrecognized ref specification", FUNC_NAME);
  114. }
  115. #if 0
  116. if (field_desc[x] == 'd')
  117. {
  118. SCM_ASSERT (field_desc[x + 2] == '-', SCM_MAKINUM (x / 2), "missing dash field", FUNC_NAME);
  119. x += 2;
  120. goto recheck_ref;
  121. }
  122. #endif
  123. }
  124. new_sym = SCM_CAR (scm_intern_obarray (field_desc, len, SCM_BOOL_F));
  125. }
  126. return scm_return_first (new_sym, fields);
  127. }
  128. #undef FUNC_NAME
  129. void
  130. scm_struct_init (SCM handle, int tail_elts, SCM inits)
  131. {
  132. SCM layout = SCM_STRUCT_LAYOUT (handle);
  133. unsigned char * fields_desc = (unsigned char *) SCM_CHARS (layout) - 2;
  134. unsigned char prot = 0;
  135. int n_fields = SCM_LENGTH (layout) / 2;
  136. scm_bits_t * mem = SCM_STRUCT_DATA (handle);
  137. int tailp = 0;
  138. while (n_fields)
  139. {
  140. if (!tailp)
  141. {
  142. fields_desc += 2;
  143. prot = fields_desc[1];
  144. if (SCM_LAYOUT_TAILP (prot))
  145. {
  146. tailp = 1;
  147. prot = prot == 'R' ? 'r' : prot == 'W' ? 'w' : 'o';
  148. *mem++ = tail_elts;
  149. n_fields += tail_elts - 1;
  150. if (n_fields == 0)
  151. break;
  152. }
  153. }
  154. switch (*fields_desc)
  155. {
  156. #if 0
  157. case 'i':
  158. if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
  159. *mem = 0;
  160. else
  161. {
  162. *mem = scm_num2long (SCM_CAR (inits), SCM_ARGn, "scm_struct_init");
  163. inits = SCM_CDR (inits);
  164. }
  165. break;
  166. #endif
  167. case 'u':
  168. if ((prot != 'r' && prot != 'w') || SCM_NULLP (inits))
  169. *mem = 0;
  170. else
  171. {
  172. *mem = scm_num2ulong (SCM_CAR (inits),
  173. SCM_ARGn,
  174. "scm_struct_init");
  175. inits = SCM_CDR (inits);
  176. }
  177. break;
  178. case 'p':
  179. if ((prot != 'r' && prot != 'w') || SCM_NULLP (inits))
  180. *mem = SCM_UNPACK (SCM_BOOL_F);
  181. else
  182. {
  183. *mem = SCM_UNPACK (SCM_CAR (inits));
  184. inits = SCM_CDR (inits);
  185. }
  186. break;
  187. #if 0
  188. case 'd':
  189. if ((prot != 'r' && prot != 'w') || inits == SCM_EOL)
  190. *((double *)mem) = 0.0;
  191. else
  192. {
  193. *mem = scm_num2dbl (SCM_CAR (inits), "scm_struct_init");
  194. inits = SCM_CDR (inits);
  195. }
  196. fields_desc += 2;
  197. break;
  198. #endif
  199. case 's':
  200. *mem = SCM_UNPACK (handle);
  201. break;
  202. }
  203. n_fields--;
  204. mem++;
  205. }
  206. }
  207. SCM_DEFINE (scm_struct_p, "struct?", 1, 0, 0,
  208. (SCM x),
  209. "Return #t iff @var{obj} is a structure object, else #f.")
  210. #define FUNC_NAME s_scm_struct_p
  211. {
  212. return SCM_BOOL(SCM_STRUCTP (x));
  213. }
  214. #undef FUNC_NAME
  215. SCM_DEFINE (scm_struct_vtable_p, "struct-vtable?", 1, 0, 0,
  216. (SCM x),
  217. "Return #t iff obj is a vtable structure.")
  218. #define FUNC_NAME s_scm_struct_vtable_p
  219. {
  220. SCM layout;
  221. scm_bits_t * mem;
  222. if (!SCM_STRUCTP (x))
  223. return SCM_BOOL_F;
  224. layout = SCM_STRUCT_LAYOUT (x);
  225. if (SCM_LENGTH (layout) < SCM_LENGTH (required_vtable_fields))
  226. return SCM_BOOL_F;
  227. if (strncmp (SCM_CHARS (layout), SCM_CHARS (required_vtable_fields),
  228. SCM_LENGTH (required_vtable_fields)))
  229. return SCM_BOOL_F;
  230. mem = SCM_STRUCT_DATA (x);
  231. if (mem[1] != 0)
  232. return SCM_BOOL_F;
  233. return SCM_BOOL (SCM_SYMBOLP (SCM_PACK (mem[0])));
  234. }
  235. #undef FUNC_NAME
  236. /* All struct data must be allocated at an address whose bottom three
  237. bits are zero. This is because the tag for a struct lives in the
  238. bottom three bits of the struct's car, and the upper bits point to
  239. the data of its vtable, which is a struct itself. Thus, if the
  240. address of that data doesn't end in three zeros, tagging it will
  241. destroy the pointer.
  242. This function allocates a block of memory, and returns a pointer at
  243. least scm_struct_n_extra_words words into the block. Furthermore,
  244. it guarantees that that pointer's least three significant bits are
  245. all zero.
  246. The argument n_words should be the number of words that should
  247. appear after the returned address. (That is, it shouldn't include
  248. scm_struct_n_extra_words.)
  249. This function initializes the following fields of the struct:
  250. scm_struct_i_ptr --- the actual start of the block of memory; the
  251. address you should pass to 'free' to dispose of the block.
  252. This field allows us to both guarantee that the returned
  253. address is divisible by eight, and allow the GC to free the
  254. block.
  255. scm_struct_i_n_words --- the number of words allocated to the
  256. block, including the extra fields. This is used by the GC.
  257. Ugh. */
  258. scm_bits_t *
  259. scm_alloc_struct (int n_words, int n_extra, char *who)
  260. {
  261. int size = sizeof (scm_bits_t) * (n_words + n_extra) + 7;
  262. void * block = scm_must_malloc (size, who);
  263. /* Adjust the pointer to hide the extra words. */
  264. scm_bits_t * p = (scm_bits_t *) block + n_extra;
  265. /* Adjust it even further so it's aligned on an eight-byte boundary. */
  266. p = (scm_bits_t *) (((scm_bits_t) p + 7) & ~7);
  267. /* Initialize a few fields as described above. */
  268. p[scm_struct_i_free] = (scm_bits_t) scm_struct_free_standard;
  269. p[scm_struct_i_ptr] = (scm_bits_t) block;
  270. p[scm_struct_i_n_words] = n_words;
  271. p[scm_struct_i_flags] = 0;
  272. return p;
  273. }
  274. scm_sizet
  275. scm_struct_free_0 (scm_bits_t * vtable, scm_bits_t * data)
  276. {
  277. return 0;
  278. }
  279. scm_sizet
  280. scm_struct_free_light (scm_bits_t * vtable, scm_bits_t * data)
  281. {
  282. scm_must_free (data);
  283. return vtable [scm_struct_i_size] & ~SCM_STRUCTF_MASK;
  284. }
  285. scm_sizet
  286. scm_struct_free_standard (scm_bits_t * vtable, scm_bits_t * data)
  287. {
  288. size_t n = (data[scm_struct_i_n_words] + scm_struct_n_extra_words)
  289. * sizeof (scm_bits_t) + 7;
  290. scm_must_free ((void *) data[scm_struct_i_ptr]);
  291. return n;
  292. }
  293. scm_sizet
  294. scm_struct_free_entity (scm_bits_t * vtable, scm_bits_t * data)
  295. {
  296. size_t n = (data[scm_struct_i_n_words] + scm_struct_entity_n_extra_words)
  297. * sizeof (scm_bits_t) + 7;
  298. scm_must_free ((void *) data[scm_struct_i_ptr]);
  299. return n;
  300. }
  301. SCM_DEFINE (scm_make_struct, "make-struct", 2, 0, 1,
  302. (SCM vtable, SCM tail_array_size, SCM init),
  303. "Create a new structure.\n\n"
  304. "@var{type} must be a vtable structure (@xref{Vtables}).\n\n"
  305. "@var{tail-elts} must be a non-negative integer. If the layout\n"
  306. "specification indicated by @var{type} includes a tail-array,\n"
  307. "this is the number of elements allocated to that array.\n\n"
  308. "The @var{inits} are optional arguments describing how successive fields\n"
  309. "of the structure should be initialized. Only fields with protection 'r'\n"
  310. "or 'w' can be initialized -- fields of protection 's' are automatically\n"
  311. "initialized to point to the new structure itself; fields of protection 'o'\n"
  312. "can not be initialized by Scheme programs.")
  313. #define FUNC_NAME s_scm_make_struct
  314. {
  315. SCM layout;
  316. int basic_size;
  317. int tail_elts;
  318. scm_bits_t * data;
  319. SCM handle;
  320. SCM_VALIDATE_VTABLE (1,vtable);
  321. SCM_VALIDATE_INUM (2,tail_array_size);
  322. SCM_VALIDATE_REST_ARGUMENT (init);
  323. layout = SCM_PACK (SCM_STRUCT_DATA (vtable) [scm_vtable_index_layout]);
  324. basic_size = SCM_LENGTH (layout) / 2;
  325. tail_elts = SCM_INUM (tail_array_size);
  326. SCM_NEWCELL (handle);
  327. SCM_DEFER_INTS;
  328. if (SCM_STRUCT_DATA (vtable)[scm_struct_i_flags] & SCM_STRUCTF_ENTITY)
  329. {
  330. data = scm_alloc_struct (basic_size + tail_elts,
  331. scm_struct_entity_n_extra_words,
  332. "make-struct");
  333. data[scm_struct_i_procedure] = SCM_UNPACK (SCM_BOOL_F);
  334. data[scm_struct_i_setter] = SCM_UNPACK (SCM_BOOL_F);
  335. }
  336. else
  337. data = scm_alloc_struct (basic_size + tail_elts,
  338. scm_struct_n_extra_words,
  339. "make-struct");
  340. SCM_SET_CELL_WORD_1 (handle, data);
  341. SCM_SET_CELL_WORD_0 (handle, (scm_bits_t) SCM_STRUCT_DATA (vtable) + scm_tc3_cons_gloc);
  342. scm_struct_init (handle, tail_elts, init);
  343. SCM_ALLOW_INTS;
  344. return handle;
  345. }
  346. #undef FUNC_NAME
  347. SCM_DEFINE (scm_make_vtable_vtable, "make-vtable-vtable", 2, 0, 1,
  348. (SCM extra_fields, SCM tail_array_size, SCM init),
  349. "Return a new, self-describing vtable structure.\n\n"
  350. "@var{new-fields} is a layout specification describing fields\n"
  351. "of the resulting structure beginning at the position bound to\n"
  352. "@code{vtable-offset-user}.\n\n"
  353. "@var{tail-size} specifies the size of the tail-array (if any) of\n"
  354. "this vtable.\n\n"
  355. "@var{inits} initializes the fields of the vtable. Minimally, one\n"
  356. "initializer must be provided: the layout specification for instances\n"
  357. "of the type this vtable will describe. If a second initializer is\n"
  358. "provided, it will be interpreted as a print call-back function.\n\n"
  359. "@example\n"
  360. ";;; loading ,a...\n"
  361. "(define x\n"
  362. " (make-vtable-vtable (make-struct-layout (quote pw))\n"
  363. " 0\n"
  364. " 'foo))\n\n"
  365. "(struct? x)\n"
  366. "@result{} #t\n"
  367. "(struct-vtable? x)\n"
  368. "@result{} #t\n"
  369. "(eq? x (struct-vtable x))\n"
  370. "@result{} #t\n"
  371. "(struct-ref x vtable-offset-user)\n"
  372. "@result{} foo\n"
  373. "(struct-ref x 0)\n"
  374. "@result{} pruosrpwpw\n\n\n"
  375. "(define y\n"
  376. " (make-struct x\n"
  377. " 0\n"
  378. " (make-struct-layout (quote pwpwpw))\n"
  379. " 'bar))\n\n"
  380. "(struct? y)\n"
  381. "@result{} #t\n"
  382. "(struct-vtable? y)\n"
  383. "@result{} #t\n"
  384. "(eq? x y)\n"
  385. "@result{} ()\n"
  386. "(eq? x (struct-vtable y))\n"
  387. "@result{} #t\n"
  388. "(struct-ref y 0)\n"
  389. "@result{} pwpwpw\n"
  390. "(struct-ref y vtable-offset-user)\n"
  391. "@result{} bar\n\n\n"
  392. "(define z (make-struct y 0 'a 'b 'c))\n\n"
  393. "(struct? z)\n"
  394. "@result{} #t\n"
  395. "(struct-vtable? z)\n"
  396. "@result{} ()\n"
  397. "(eq? y (struct-vtable z))\n"
  398. "@result{} #t\n"
  399. "(map (lambda (n) (struct-ref z n)) '(0 1 2))\n"
  400. "@result{} (a b c)\n"
  401. "@end example\n"
  402. "")
  403. #define FUNC_NAME s_scm_make_vtable_vtable
  404. {
  405. SCM fields;
  406. SCM layout;
  407. int basic_size;
  408. int tail_elts;
  409. scm_bits_t * data;
  410. SCM handle;
  411. SCM_VALIDATE_ROSTRING (1,extra_fields);
  412. SCM_VALIDATE_INUM (2,tail_array_size);
  413. SCM_VALIDATE_REST_ARGUMENT (init);
  414. fields = scm_string_append (scm_listify (required_vtable_fields,
  415. extra_fields,
  416. SCM_UNDEFINED));
  417. layout = scm_make_struct_layout (fields);
  418. basic_size = SCM_LENGTH (layout) / 2;
  419. tail_elts = SCM_INUM (tail_array_size);
  420. SCM_NEWCELL (handle);
  421. SCM_DEFER_INTS;
  422. data = scm_alloc_struct (basic_size + tail_elts,
  423. scm_struct_n_extra_words,
  424. "make-vtable-vtable");
  425. SCM_SET_CELL_WORD_1 (handle, data);
  426. SCM_SET_CELL_WORD_0 (handle, (scm_bits_t) data + scm_tc3_cons_gloc);
  427. SCM_SET_STRUCT_LAYOUT (handle, layout);
  428. scm_struct_init (handle, tail_elts, scm_cons (layout, init));
  429. SCM_ALLOW_INTS;
  430. return handle;
  431. }
  432. #undef FUNC_NAME
  433. SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
  434. (SCM handle, SCM pos),
  435. "@deffnx primitive struct-set! struct n value\n"
  436. "Access (or modify) the @var{n}th field of @var{struct}.\n\n"
  437. "If the field is of type 'p', then it can be set to an arbitrary value.\n\n"
  438. "If the field is of type 'u', then it can only be set to a non-negative\n"
  439. "integer value small enough to fit in one machine word.")
  440. #define FUNC_NAME s_scm_struct_ref
  441. {
  442. SCM answer = SCM_UNDEFINED;
  443. scm_bits_t * data;
  444. SCM layout;
  445. int p;
  446. scm_bits_t n_fields;
  447. unsigned char * fields_desc;
  448. unsigned char field_type = 0;
  449. SCM_VALIDATE_STRUCT (1,handle);
  450. SCM_VALIDATE_INUM (2,pos);
  451. layout = SCM_STRUCT_LAYOUT (handle);
  452. data = SCM_STRUCT_DATA (handle);
  453. p = SCM_INUM (pos);
  454. fields_desc = (unsigned char *) SCM_CHARS (layout);
  455. n_fields = data[scm_struct_i_n_words];
  456. SCM_ASSERT_RANGE(1,pos, p < n_fields);
  457. if (p * 2 < SCM_LENGTH (layout))
  458. {
  459. unsigned char ref;
  460. field_type = fields_desc[p * 2];
  461. ref = fields_desc[p * 2 + 1];
  462. if ((ref != 'r') && (ref != 'w'))
  463. {
  464. if ((ref == 'R') || (ref == 'W'))
  465. field_type = 'u';
  466. else
  467. SCM_ASSERT (0, pos, "ref denied", FUNC_NAME);
  468. }
  469. }
  470. else if (fields_desc[SCM_LENGTH (layout) - 1] != 'O')
  471. field_type = fields_desc[SCM_LENGTH (layout) - 2];
  472. else
  473. {
  474. SCM_ASSERT (0, pos, "ref denied", FUNC_NAME);
  475. abort ();
  476. }
  477. switch (field_type)
  478. {
  479. case 'u':
  480. answer = scm_ulong2num (data[p]);
  481. break;
  482. #if 0
  483. case 'i':
  484. answer = scm_long2num (data[p]);
  485. break;
  486. case 'd':
  487. answer = scm_make_real (*((double *)&(data[p])));
  488. break;
  489. #endif
  490. case 's':
  491. case 'p':
  492. answer = SCM_PACK (data[p]);
  493. break;
  494. default:
  495. SCM_ASSERT (0, SCM_MAKE_CHAR (field_type), "unrecognized field type", FUNC_NAME);
  496. break;
  497. }
  498. return answer;
  499. }
  500. #undef FUNC_NAME
  501. SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
  502. (SCM handle, SCM pos, SCM val),
  503. "")
  504. #define FUNC_NAME s_scm_struct_set_x
  505. {
  506. scm_bits_t * data;
  507. SCM layout;
  508. int p;
  509. int n_fields;
  510. unsigned char * fields_desc;
  511. unsigned char field_type = 0;
  512. SCM_VALIDATE_STRUCT (1,handle);
  513. SCM_VALIDATE_INUM (2,pos);
  514. layout = SCM_STRUCT_LAYOUT (handle);
  515. data = SCM_STRUCT_DATA (handle);
  516. p = SCM_INUM (pos);
  517. fields_desc = (unsigned char *)SCM_CHARS (layout);
  518. n_fields = data[scm_struct_i_n_words];
  519. SCM_ASSERT_RANGE (1,pos, p < n_fields);
  520. if (p * 2 < SCM_LENGTH (layout))
  521. {
  522. unsigned char set_x;
  523. field_type = fields_desc[p * 2];
  524. set_x = fields_desc [p * 2 + 1];
  525. if (set_x != 'w')
  526. SCM_ASSERT (0, pos, "set_x denied", FUNC_NAME);
  527. }
  528. else if (fields_desc[SCM_LENGTH (layout) - 1] == 'W')
  529. field_type = fields_desc[SCM_LENGTH (layout) - 2];
  530. else
  531. {
  532. SCM_ASSERT (0, pos, "set_x denied", FUNC_NAME);
  533. abort ();
  534. }
  535. switch (field_type)
  536. {
  537. case 'u':
  538. data[p] = SCM_NUM2ULONG (3, val);
  539. break;
  540. #if 0
  541. case 'i':
  542. data[p] = SCM_NUM2LONG (3,val);
  543. break;
  544. case 'd':
  545. *((double *)&(data[p])) = scm_num2dbl (val, (char *)SCM_ARG3);
  546. break;
  547. #endif
  548. case 'p':
  549. data[p] = SCM_UNPACK (val);
  550. break;
  551. case 's':
  552. SCM_ASSERT (0, SCM_MAKE_CHAR (field_type), "self fields immutable", FUNC_NAME);
  553. break;
  554. default:
  555. SCM_ASSERT (0, SCM_MAKE_CHAR (field_type), "unrecognized field type", FUNC_NAME);
  556. break;
  557. }
  558. return val;
  559. }
  560. #undef FUNC_NAME
  561. SCM_DEFINE (scm_struct_vtable, "struct-vtable", 1, 0, 0,
  562. (SCM handle),
  563. "Return the vtable structure that describes the type of @var{struct}.")
  564. #define FUNC_NAME s_scm_struct_vtable
  565. {
  566. SCM_VALIDATE_STRUCT (1,handle);
  567. return SCM_STRUCT_VTABLE (handle);
  568. }
  569. #undef FUNC_NAME
  570. SCM_DEFINE (scm_struct_vtable_tag, "struct-vtable-tag", 1, 0, 0,
  571. (SCM handle),
  572. "")
  573. #define FUNC_NAME s_scm_struct_vtable_tag
  574. {
  575. SCM_VALIDATE_VTABLE (1,handle);
  576. return scm_long2num ((long) SCM_STRUCT_DATA (handle) >> 3);
  577. }
  578. #undef FUNC_NAME
  579. /* {Associating names and classes with vtables}
  580. *
  581. * The name of a vtable should probably be stored as a slot. This is
  582. * a backward compatible solution until agreement has been achieved on
  583. * how to associate names with vtables.
  584. */
  585. unsigned int
  586. scm_struct_ihashq (SCM obj, unsigned int n)
  587. {
  588. /* The length of the hash table should be a relative prime it's not
  589. necessary to shift down the address. */
  590. return SCM_UNPACK (obj) % n;
  591. }
  592. SCM
  593. scm_struct_create_handle (SCM obj)
  594. {
  595. SCM handle = scm_hash_fn_create_handle_x (scm_struct_table,
  596. obj,
  597. SCM_BOOL_F,
  598. scm_struct_ihashq,
  599. scm_sloppy_assq,
  600. 0);
  601. if (SCM_FALSEP (SCM_CDR (handle)))
  602. SCM_SETCDR (handle, scm_cons (SCM_BOOL_F, SCM_BOOL_F));
  603. return handle;
  604. }
  605. SCM_DEFINE (scm_struct_vtable_name, "struct-vtable-name", 1, 0, 0,
  606. (SCM vtable),
  607. "")
  608. #define FUNC_NAME s_scm_struct_vtable_name
  609. {
  610. SCM_VALIDATE_VTABLE (1,vtable);
  611. return SCM_STRUCT_TABLE_NAME (SCM_CDR (scm_struct_create_handle (vtable)));
  612. }
  613. #undef FUNC_NAME
  614. SCM_DEFINE (scm_set_struct_vtable_name_x, "set-struct-vtable-name!", 2, 0, 0,
  615. (SCM vtable, SCM name),
  616. "")
  617. #define FUNC_NAME s_scm_set_struct_vtable_name_x
  618. {
  619. SCM_VALIDATE_VTABLE (1,vtable);
  620. SCM_VALIDATE_SYMBOL (2,name);
  621. SCM_SET_STRUCT_TABLE_NAME (SCM_CDR (scm_struct_create_handle (vtable)),
  622. name);
  623. return SCM_UNSPECIFIED;
  624. }
  625. #undef FUNC_NAME
  626. void
  627. scm_print_struct (SCM exp, SCM port, scm_print_state *pstate)
  628. {
  629. if (SCM_NFALSEP (scm_procedure_p (SCM_STRUCT_PRINTER (exp))))
  630. scm_printer_apply (SCM_STRUCT_PRINTER (exp), exp, port, pstate);
  631. else
  632. {
  633. SCM vtable = SCM_STRUCT_VTABLE (exp);
  634. SCM name = scm_struct_vtable_name (vtable);
  635. scm_puts ("#<", port);
  636. if (SCM_NFALSEP (name))
  637. scm_display (name, port);
  638. else
  639. scm_puts ("struct", port);
  640. scm_putc (' ', port);
  641. scm_intprint (SCM_UNPACK (vtable), 16, port);
  642. scm_putc (':', port);
  643. scm_intprint (SCM_UNPACK (exp), 16, port);
  644. scm_putc ('>', port);
  645. }
  646. }
  647. void
  648. scm_init_struct ()
  649. {
  650. scm_struct_table
  651. = scm_permanent_object (scm_make_weak_key_hash_table (SCM_MAKINUM (31)));
  652. required_vtable_fields = SCM_CAR (scm_intern_obarray ("pruosrpw", sizeof ("pruosrpw") - 1, SCM_BOOL_F));
  653. scm_permanent_object (required_vtable_fields);
  654. scm_sysintern ("vtable-index-layout", SCM_MAKINUM (scm_vtable_index_layout));
  655. scm_sysintern ("vtable-index-vtable", SCM_MAKINUM (scm_vtable_index_vtable));
  656. scm_sysintern ("vtable-index-printer", SCM_MAKINUM (scm_vtable_index_printer));
  657. scm_sysintern ("vtable-offset-user", SCM_MAKINUM (scm_vtable_offset_user));
  658. #include "libguile/struct.x"
  659. }
  660. /*
  661. Local Variables:
  662. c-file-style: "gnu"
  663. End:
  664. */