+
+/* All struct data must be allocated at an address whose bottom three
+ bits are zero. This is because the tag for a struct lives in the
+ bottom three bits of the struct's car, and the upper bits point to
+ the data of its vtable, which is a struct itself. Thus, if the
+ address of that data doesn't end in three zeros, tagging it will
+ destroy the pointer.
+
+ This function allocates a block of memory, and returns a pointer at
+ least scm_struct_n_extra_words words into the block. Furthermore,
+ it guarantees that that pointer's least three significant bits are
+ all zero.
+
+ The argument n_words should be the number of words that should
+ appear after the returned address. (That is, it shouldn't include
+ scm_struct_n_extra_words.)
+
+ This function initializes the following fields of the struct:
+
+ scm_struct_i_ptr --- the actual stort of the block of memory; the
+ address you should pass to 'free' to dispose of the block.
+ This field allows us to both guarantee that the returned
+ address is divisible by eight, and allow the GC to free the
+ block.
+
+ scm_struct_i_n_words --- the number of words allocated to the
+ block, including the extra fields. This is used by the GC.
+
+ scm_struct_i_tag --- a unique tag assigned to this struct,
+ allocated according to struct_num.
+
+ Ugh. */
+
+
+static SCM *alloc_struct SCM_P ((int n_words, char *who));
+
+static SCM *
+alloc_struct (n_words, who)
+ int n_words;
+ char *who;
+{
+ int size = sizeof (SCM) * (n_words + scm_struct_n_extra_words) + 7;
+ SCM *block = (SCM *) scm_must_malloc (size, who);
+
+ /* Adjust the pointer to hide the extra words. */
+ SCM *p = block + scm_struct_n_extra_words;
+
+ /* Adjust it even further so it's aligned on an eight-byte boundary. */
+ p = (SCM *) (((SCM) p + 7) & ~7);
+
+ /* Initialize a few fields as described above. */
+ p[scm_struct_i_ptr] = (SCM) block;
+ p[scm_struct_i_n_words] = (SCM) (scm_struct_n_extra_words + n_words);
+ p[scm_struct_i_tag] = struct_num++;
+
+ return p;
+}
+
+