Implement a Makefile for Inform.
[inform.git] / objects.c
diff --git a/objects.c b/objects.c
deleted file mode 100644 (file)
index 88b1b6a..0000000
--- a/objects.c
+++ /dev/null
@@ -1,2269 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*   "objects" :  [1] the object-maker, which constructs objects and enters  */
-/*                    them into the tree, given a low-level specification;   */
-/*                                                                           */
-/*                [2] the parser of Object/Nearby/Class directives, which    */
-/*                    checks syntax and translates such directives into      */
-/*                    specifications for the object-maker.                   */
-/*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
-/*                                                                           */
-/* This file is part of Inform.                                              */
-/*                                                                           */
-/* Inform is free software: you can redistribute it and/or modify            */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation, either version 3 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Inform is distributed in the hope that it will be useful,                 */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with Inform. If not, see https://gnu.org/licenses/                  */
-/*                                                                           */
-/* ------------------------------------------------------------------------- */
-
-#include "header.h"
-
-/* ------------------------------------------------------------------------- */
-/*   Objects.                                                                */
-/* ------------------------------------------------------------------------- */
-
-int no_objects;                        /* Number of objects made so far      */
-
-static int no_embedded_routines;       /* Used for naming routines which
-                                          are given as property values: these
-                                          are called EmbeddedRoutine__1, ... */
-
-static fpropt full_object;             /* "fpropt" is a typedef for a struct
-                                          containing an array to hold the
-                                          attribute and property values of
-                                          a single object.  We only keep one
-                                          of these, for the current object
-                                          being made, and compile it into
-                                          Z-machine tables when each object
-                                          definition is complete, since
-                                          sizeof(fpropt) is about 6200 bytes */
-static fproptg full_object_g;          /* Equivalent for Glulx. This object
-                                          is very small, since the large arrays
-                                          are allocated dynamically by the
-                                          Glulx compiler                     */
-static char shortname_buffer[766];     /* Text buffer to hold the short name
-                                          (which is read in first, but
-                                          written almost last)               */
-static int parent_of_this_obj;
-
-static char *classname_text, *objectname_text;
-                                       /* For printing names of embedded
-                                          routines only                      */
-
-/* ------------------------------------------------------------------------- */
-/*   Classes.                                                                */
-/* ------------------------------------------------------------------------- */
-/*   Arrays defined below:                                                   */
-/*                                                                           */
-/*    int32 class_begins_at[n]            offset of properties block for     */
-/*                                        nth class (always an offset        */
-/*                                        inside the properties_table)       */
-/*    int   classes_to_inherit_from[]     The list of classes to inherit     */
-/*                                        from as taken from the current     */
-/*                                        Nearby/Object/Class definition     */
-/*    int   class_object_numbers[n]       The number of the prototype-object */
-/*                                        for the nth class                  */
-/* ------------------------------------------------------------------------- */
-
-int        no_classes;                 /* Number of class defns made so far  */
-
-static int current_defn_is_class,      /* TRUE if current Nearby/Object/Class
-                                          defn is in fact a Class definition */
-           no_classes_to_inherit_from; /* Number of classes in the list
-                                          of classes to inherit in the
-                                          current Nearby/Object/Class defn   */
-
-/* ------------------------------------------------------------------------- */
-/*   Making attributes and properties.                                       */
-/* ------------------------------------------------------------------------- */
-
-int no_attributes,                 /* Number of attributes defined so far    */
-    no_properties;                 /* Number of properties defined so far,
-                                      plus 1 (properties are numbered from
-                                      1 and Inform creates "name" and two
-                                      others itself, so the variable begins
-                                      the compilation pass set to 4)         */
-
-static void trace_s(char *name, int32 number, int f)
-{   if (!printprops_switch) return;
-    printf("%s  %02ld  ",(f==0)?"Attr":"Prop",(long int) number);
-    if (f==0) printf("  ");
-    else      printf("%s%s",(prop_is_long[number])?"L":" ",
-                            (prop_is_additive[number])?"A":" ");
-    printf("  %s\n",name);
-}
-
-extern void make_attribute(void)
-{   int i; char *name;
-    debug_location_beginning beginning_debug_location =
-        get_token_location_beginning();
-
- if (!glulx_mode) { 
-    if (no_attributes==((version_number==3)?32:48))
-    {   discard_token_location(beginning_debug_location);
-        if (version_number==3)
-            error("All 32 attributes already declared (compile as Advanced \
-game to get an extra 16)");
-        else
-            error("All 48 attributes already declared");
-        panic_mode_error_recovery();
-        put_token_back();
-        return;
-    }
- }
- else {
-    if (no_attributes==NUM_ATTR_BYTES*8) {
-      discard_token_location(beginning_debug_location);
-      error_numbered(
-        "All attributes already declared -- increase NUM_ATTR_BYTES to use \
-more than", 
-        NUM_ATTR_BYTES*8);
-      panic_mode_error_recovery(); 
-      put_token_back();
-      return;
-    }
- }
-
-    get_next_token();
-    i = token_value; name = token_text;
-    if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
-    {   discard_token_location(beginning_debug_location);
-        ebf_error("new attribute name", token_text);
-        panic_mode_error_recovery(); 
-        put_token_back();
-        return;
-    }
-
-    directive_keywords.enabled = TRUE;
-    get_next_token();
-    directive_keywords.enabled = FALSE;
-
-    if ((token_type == DIR_KEYWORD_TT) && (token_value == ALIAS_DK))
-    {   get_next_token();
-        if (!((token_type == SYMBOL_TT)
-              && (stypes[token_value] == ATTRIBUTE_T)))
-        {   discard_token_location(beginning_debug_location);
-            ebf_error("an existing attribute name after 'alias'",
-                token_text);
-            panic_mode_error_recovery();
-            put_token_back();
-            return;
-        }
-        assign_symbol(i, svals[token_value], ATTRIBUTE_T);
-        sflags[token_value] |= ALIASED_SFLAG;
-        sflags[i] |= ALIASED_SFLAG;
-    }
-    else
-    {   assign_symbol(i, no_attributes++, ATTRIBUTE_T);
-        put_token_back();
-    }
-
-    if (debugfile_switch)
-    {   debug_file_printf("<attribute>");
-        debug_file_printf("<identifier>%s</identifier>", name);
-        debug_file_printf("<value>%d</value>", svals[i]);
-        write_debug_locations(get_token_location_end(beginning_debug_location));
-        debug_file_printf("</attribute>");
-    }
-
-    trace_s(name, svals[i], 0);
-    return;
-}
-
-extern void make_property(void)
-{   int32 default_value, i;
-    int additive_flag=FALSE; char *name;
-    assembly_operand AO;
-    debug_location_beginning beginning_debug_location =
-        get_token_location_beginning();
-
-    if (!glulx_mode) {
-        if (no_properties==((version_number==3)?32:64))
-        {   discard_token_location(beginning_debug_location);
-            if (version_number==3)
-                error("All 30 properties already declared (compile as \
-Advanced game to get an extra 62)");
-            else
-                error("All 62 properties already declared");
-            panic_mode_error_recovery();
-            put_token_back();
-            return;
-        }
-    }
-    else {
-        if (no_properties==INDIV_PROP_START) {
-            discard_token_location(beginning_debug_location);
-            error_numbered("All properties already declared -- max is",
-                INDIV_PROP_START);
-            panic_mode_error_recovery(); 
-            put_token_back();
-            return;
-        }
-    }
-
-    do
-    {   directive_keywords.enabled = TRUE;
-        get_next_token();
-        if ((token_type == DIR_KEYWORD_TT) && (token_value == LONG_DK))
-            obsolete_warning("all properties are now automatically 'long'");
-        else
-        if ((token_type == DIR_KEYWORD_TT) && (token_value == ADDITIVE_DK))
-            additive_flag = TRUE;
-        else break;
-    } while (TRUE);
-
-    put_token_back();
-    directive_keywords.enabled = FALSE;
-    get_next_token();
-
-    i = token_value; name = token_text;
-    if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
-    {   discard_token_location(beginning_debug_location);
-        ebf_error("new property name", token_text);
-        panic_mode_error_recovery();
-        put_token_back();
-        return;
-    }
-
-    directive_keywords.enabled = TRUE;
-    get_next_token();
-    directive_keywords.enabled = FALSE;
-
-    if (strcmp(name+strlen(name)-3, "_to") == 0) sflags[i] |= STAR_SFLAG;
-
-    if ((token_type == DIR_KEYWORD_TT) && (token_value == ALIAS_DK))
-    {   discard_token_location(beginning_debug_location);
-        if (additive_flag)
-        {   error("'alias' incompatible with 'additive'");
-            panic_mode_error_recovery();
-            put_token_back();
-            return;
-        }
-        get_next_token();
-        if (!((token_type == SYMBOL_TT)
-            && (stypes[token_value] == PROPERTY_T)))
-        {   ebf_error("an existing property name after 'alias'",
-                token_text);
-            panic_mode_error_recovery();
-            put_token_back();
-            return;
-        }
-
-        assign_symbol(i, svals[token_value], PROPERTY_T);
-        trace_s(name, svals[i], 1);
-        sflags[token_value] |= ALIASED_SFLAG;
-        sflags[i] |= ALIASED_SFLAG;
-        return;
-    }
-
-    default_value = 0;
-    put_token_back();
-
-    if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-    {   AO = parse_expression(CONSTANT_CONTEXT);
-        default_value = AO.value;
-        if (AO.marker != 0)
-            backpatch_zmachine(AO.marker, PROP_DEFAULTS_ZA, 
-                (no_properties-1) * WORDSIZE);
-    }
-
-    prop_default_value[no_properties] = default_value;
-    prop_is_long[no_properties] = TRUE;
-    prop_is_additive[no_properties] = additive_flag;
-
-    assign_symbol(i, no_properties++, PROPERTY_T);
-
-    if (debugfile_switch)
-    {   debug_file_printf("<property>");
-        debug_file_printf("<identifier>%s</identifier>", name);
-        debug_file_printf("<value>%d</value>", svals[i]);
-        write_debug_locations
-            (get_token_location_end(beginning_debug_location));
-        debug_file_printf("</property>");
-    }
-
-    trace_s(name, svals[i], 1);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Properties.                                                             */
-/* ------------------------------------------------------------------------- */
-
-int32 *prop_default_value;             /* Default values for properties      */
-int   *prop_is_long,                   /* Property modifiers, TRUE or FALSE:
-                                          "long" means "never write a 1-byte
-                                          value to this property", and is an
-                                          obsolete feature: since Inform 5
-                                          all properties have been "long"    */
-      *prop_is_additive;               /* "additive" means that values
-                                          accumulate rather than erase each
-                                          other during class inheritance     */
-char *properties_table;                /* Holds the table of property values
-                                          (holding one block for each object
-                                          and coming immediately after the
-                                          object tree in Z-memory)           */
-int properties_table_size;             /* Number of bytes in this table      */
-
-/* ------------------------------------------------------------------------- */
-/*   Individual properties                                                   */
-/*                                                                           */
-/*   Each new i.p. name is given a unique number.  These numbers start from  */
-/*   72, since 0 is reserved as a null, 1 to 63 refer to common properties   */
-/*   and 64 to 71 are kept for methods of the metaclass Class (for example,  */
-/*   64 is "create").                                                        */
-/*                                                                           */
-/*   An object provides individual properties by having property 3 set to a  */
-/*   non-zero value, which must be a byte address of a table in the form:    */
-/*                                                                           */
-/*       <record-1> ... <record-n> 00 00                                     */
-/*                                                                           */
-/*   where a <record> looks like                                             */
-/*                                                                           */
-/*       <identifier>              <size>  <up to 255 bytes of data>         */
-/*       or <identifier + 0x8000>                                            */
-/*       ----- 2 bytes ----------  1 byte  <size> number of bytes            */
-/*                                                                           */
-/*   The <identifier> part is the number allocated to the name of what is    */
-/*   being provided.  The top bit of this word is set to indicate that       */
-/*   although the individual property is being provided, it is provided      */
-/*   only privately (so that it is inaccessible except to the object's own   */
-/*   embedded routines).                                                     */
-/*                                                                           */
-/*   In Glulx: i-props are numbered from INDIV_PROP_START+8 up. And all      */
-/*   properties, common and individual, are stored in the same table.        */
-/* ------------------------------------------------------------------------- */
-
-       int no_individual_properties;   /* Actually equal to the next
-                                          identifier number to be allocated,
-                                          so this is initially 72 even though
-                                          none have been made yet.           */
-static int individual_prop_table_size; /* Size of the table of individual
-                                          properties so far for current obj  */
-       uchar *individuals_table;       /* Table of records, each being the
-                                          i.p. table for an object           */
-       int i_m;                        /* Write mark position in the above   */
-       int individuals_length;         /* Extent of individuals_table        */
-
-/* ------------------------------------------------------------------------- */
-/*   Arrays used by this file                                                */
-/* ------------------------------------------------------------------------- */
-
-objecttz     *objectsz;                /* Z-code only                        */
-objecttg     *objectsg;                /* Glulx only                         */
-uchar        *objectatts;              /* Glulx only                         */
-static int   *classes_to_inherit_from;
-int          *class_object_numbers;
-int32        *class_begins_at;
-
-
-/* ------------------------------------------------------------------------- */
-/*   Tracing for compiler maintenance                                        */
-/* ------------------------------------------------------------------------- */
-
-extern void list_object_tree(void)
-{   int i;
-    printf("obj   par nxt chl   Object tree:\n");
-    for (i=0; i<no_objects; i++)
-        printf("%3d   %3d %3d %3d\n",
-            i+1,objectsz[i].parent,objectsz[i].next, objectsz[i].child);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Object and class manufacture begins here.                               */
-/*                                                                           */
-/*   These definitions have headers (parsed far, far below) and a series     */
-/*   of segments, introduced by keywords and optionally separated by commas. */
-/*   Each segment has its own parsing routine.  Note that when errors are    */
-/*   detected, parsing continues rather than being abandoned, which assists  */
-/*   a little in "error recovery" (i.e. in stopping lots more errors being   */
-/*   produced for essentially the same mistake).                             */
-/* ------------------------------------------------------------------------- */
-
-/* ========================================================================= */
-/*   [1]  The object-maker: builds an object from a specification, viz.:     */
-/*                                                                           */
-/*           full_object,                                                    */
-/*           shortname_buffer,                                               */
-/*           parent_of_this_obj,                                             */
-/*           current_defn_is_class (flag)                                    */
-/*           classes_to_inherit_from[], no_classes_to_inherit_from,          */
-/*           individual_prop_table_size (to date  )                          */
-/*                                                                           */
-/*   For efficiency's sake, the individual properties table has already been */
-/*   created (as far as possible, i.e., all except for inherited individual  */
-/*   properties); unless the flag is clear, in which case the actual         */
-/*   definition did not specify any individual properties.                   */
-/* ========================================================================= */
-/*   Property inheritance from classes.                                      */
-/* ------------------------------------------------------------------------- */
-
-static void property_inheritance_z(void)
-{
-    /*  Apply the property inheritance rules to full_object, which should
-        initially be complete (i.e., this routine takes place after the whole
-        Nearby/Object/Class definition has been parsed through).
-
-        On exit, full_object contains the final state of the properties to
-        be written.                                                          */
-
-    int i, j, k, kmax, class, mark,
-        prop_number, prop_length, prop_in_current_defn;
-    uchar *class_prop_block;
-
-    ASSERT_ZCODE();
-
-    for (class=0; class<no_classes_to_inherit_from; class++)
-    {
-        j=0;
-        mark = class_begins_at[classes_to_inherit_from[class]-1];
-        class_prop_block = (uchar *) (properties_table + mark);
-
-        while (class_prop_block[j]!=0)
-        {   if (version_number == 3)
-            {   prop_number = class_prop_block[j]%32;
-                prop_length = 1 + class_prop_block[j++]/32;
-            }
-            else
-            {   prop_number = class_prop_block[j]%64;
-                prop_length = 1 + class_prop_block[j++]/64;
-                if (prop_length > 2)
-                    prop_length = class_prop_block[j++]%64;
-            }
-
-            /*  So we now have property number prop_number present in the
-                property block for the class being read: its bytes are
-
-                class_prop_block[j, ..., j + prop_length - 1]
-
-                Question now is: is there already a value given in the
-                current definition under this property name?                 */
-
-            prop_in_current_defn = FALSE;
-
-            kmax = full_object.l;
-
-            for (k=0; k<kmax; k++)
-                if (full_object.pp[k].num == prop_number)
-                {   prop_in_current_defn = TRUE;
-
-                    /*  (Note that the built-in "name" property is additive) */
-
-                    if ((prop_number==1) || (prop_is_additive[prop_number]))
-                    {
-                        /*  The additive case: we accumulate the class
-                            property values onto the end of the full_object
-                            property                                         */
-
-                        for (i=full_object.pp[k].l;
-                             i<full_object.pp[k].l+prop_length/2; i++)
-                        {   if (i >= 32)
-                            {   error("An additive property has inherited \
-so many values that the list has overflowed the maximum 32 entries");
-                                break;
-                            }
-                            full_object.pp[k].ao[i].value = mark + j;
-                            j += 2;
-                            full_object.pp[k].ao[i].marker = INHERIT_MV;
-                            full_object.pp[k].ao[i].type = LONG_CONSTANT_OT;
-                        }
-                        full_object.pp[k].l += prop_length/2;
-                    }
-                    else
-                        /*  The ordinary case: the full_object property
-                            values simply overrides the class definition,
-                            so we skip over the values in the class table    */
-
-                        j+=prop_length;
-
-                    if (prop_number==3)
-                    {   int y, z, class_block_offset;
-                        uchar *p;
-
-                        /*  Property 3 holds the address of the table of
-                            instance variables, so this is the case where
-                            the object already has instance variables in its
-                            own table but must inherit some more from the
-                            class  */
-
-                        class_block_offset = class_prop_block[j-2]*256
-                                             + class_prop_block[j-1];
-
-                        p = individuals_table + class_block_offset;
-                        z = class_block_offset;
-                        while ((p[0]!=0)||(p[1]!=0))
-                        {   int already_present = FALSE, l;
-                            for (l = full_object.pp[k].ao[0].value; l < i_m;
-                                 l = l + 3 + individuals_table[l + 2])
-                                if (individuals_table[l] == p[0]
-                                    && individuals_table[l + 1] == p[1])
-                                {   already_present = TRUE; break;
-                                }
-                            if (already_present == FALSE)
-                            {   if (module_switch)
-                                    backpatch_zmachine(IDENT_MV,
-                                        INDIVIDUAL_PROP_ZA, i_m);
-                                if (i_m+3+p[2] > MAX_INDIV_PROP_TABLE_SIZE)
-                                    memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
-                                        MAX_INDIV_PROP_TABLE_SIZE);
-                                individuals_table[i_m++] = p[0];
-                                individuals_table[i_m++] = p[1];
-                                individuals_table[i_m++] = p[2];
-                                for (y=0;y < p[2]/2;y++)
-                                {   individuals_table[i_m++] = (z+3+y*2)/256;
-                                    individuals_table[i_m++] = (z+3+y*2)%256;
-                                    backpatch_zmachine(INHERIT_INDIV_MV,
-                                        INDIVIDUAL_PROP_ZA, i_m-2);
-                                }
-                            }
-                            z += p[2] + 3;
-                            p += p[2] + 3;
-                        }
-                        individuals_length = i_m;
-                    }
-
-                    /*  For efficiency we exit the loop now (this property
-                        number has been dealt with)                          */
-
-                    break;
-                }
-
-            if (!prop_in_current_defn)
-            {
-                /*  The case where the class defined a property which wasn't
-                    defined at all in full_object: we copy out the data into
-                    a new property added to full_object                      */
-
-                k=full_object.l++;
-                full_object.pp[k].num = prop_number;
-                full_object.pp[k].l = prop_length/2;
-                for (i=0; i<prop_length/2; i++)
-                {   full_object.pp[k].ao[i].value = mark + j;
-                    j+=2;
-                    full_object.pp[k].ao[i].marker = INHERIT_MV;
-                    full_object.pp[k].ao[i].type = LONG_CONSTANT_OT;
-                }
-
-                if (prop_number==3)
-                {   int y, z, class_block_offset;
-                    uchar *p;
-
-                    /*  Property 3 holds the address of the table of
-                        instance variables, so this is the case where
-                        the object had no instance variables of its own
-                        but must inherit some more from the class  */
-
-                    if (individual_prop_table_size++ == 0)
-                    {   full_object.pp[k].num = 3;
-                        full_object.pp[k].l = 1;
-                        full_object.pp[k].ao[0].value
-                            = individuals_length;
-                        full_object.pp[k].ao[0].marker = INDIVPT_MV;
-                        full_object.pp[k].ao[0].type = LONG_CONSTANT_OT;
-                        i_m = individuals_length;
-                    }
-                    class_block_offset = class_prop_block[j-2]*256
-                                         + class_prop_block[j-1];
-
-                    p = individuals_table + class_block_offset;
-                    z = class_block_offset;
-                    while ((p[0]!=0)||(p[1]!=0))
-                    {   if (module_switch)
-                        backpatch_zmachine(IDENT_MV, INDIVIDUAL_PROP_ZA, i_m);
-                        if (i_m+3+p[2] > MAX_INDIV_PROP_TABLE_SIZE)
-                            memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
-                                MAX_INDIV_PROP_TABLE_SIZE);
-                        individuals_table[i_m++] = p[0];
-                        individuals_table[i_m++] = p[1];
-                        individuals_table[i_m++] = p[2];
-                        for (y=0;y < p[2]/2;y++)
-                        {   individuals_table[i_m++] = (z+3+y*2)/256;
-                            individuals_table[i_m++] = (z+3+y*2)%256;
-                            backpatch_zmachine(INHERIT_INDIV_MV,
-                                INDIVIDUAL_PROP_ZA, i_m-2);
-                        }
-                        z += p[2] + 3;
-                        p += p[2] + 3;
-                    }
-                    individuals_length = i_m;
-                }
-            }
-        }
-    }
-
-    if (individual_prop_table_size > 0)
-    {
-        if (i_m+2 > MAX_INDIV_PROP_TABLE_SIZE)
-            memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
-                MAX_INDIV_PROP_TABLE_SIZE);
-
-        individuals_table[i_m++] = 0;
-        individuals_table[i_m++] = 0;
-        individuals_length += 2;
-    }
-}
-
-static void property_inheritance_g(void)
-{
-  /*  Apply the property inheritance rules to full_object, which should
-      initially be complete (i.e., this routine takes place after the whole
-      Nearby/Object/Class definition has been parsed through).
-      
-      On exit, full_object contains the final state of the properties to
-      be written. */
-
-  int i, j, k, class, num_props,
-    prop_number, prop_length, prop_flags, prop_in_current_defn;
-  int32 mark, prop_addr;
-  uchar *cpb, *pe;
-
-  ASSERT_GLULX();
-
-  for (class=0; class<no_classes_to_inherit_from; class++) {
-    mark = class_begins_at[classes_to_inherit_from[class]-1];
-    cpb = (uchar *) (properties_table + mark);
-    /* This now points to the compiled property-table for the class.
-       We'll have to go through and decompile it. (For our sins.) */
-    num_props = ReadInt32(cpb);
-    for (j=0; j<num_props; j++) {
-      pe = cpb + 4 + j*10;
-      prop_number = ReadInt16(pe);
-      pe += 2;
-      prop_length = ReadInt16(pe);
-      pe += 2;
-      prop_addr = ReadInt32(pe);
-      pe += 4;
-      prop_flags = ReadInt16(pe);
-      pe += 2;
-
-      /*  So we now have property number prop_number present in the
-          property block for the class being read. Its bytes are
-          cpb[prop_addr ... prop_addr + prop_length - 1]
-          Question now is: is there already a value given in the
-          current definition under this property name? */
-
-      prop_in_current_defn = FALSE;
-
-      for (k=0; k<full_object_g.numprops; k++) {
-        if (full_object_g.props[k].num == prop_number) {
-          prop_in_current_defn = TRUE;
-          break;
-        }
-      }
-
-      if (prop_in_current_defn) {
-        if ((prop_number==1)
-          || (prop_number < INDIV_PROP_START 
-            && prop_is_additive[prop_number])) {
-          /*  The additive case: we accumulate the class
-              property values onto the end of the full_object
-              properties. Remember that k is still the index number
-              of the first prop-block matching our property number. */
-          int prevcont;
-          if (full_object_g.props[k].continuation == 0) {
-            full_object_g.props[k].continuation = 1;
-            prevcont = 1;
-          }
-          else {
-            prevcont = full_object_g.props[k].continuation;
-            for (k++; k<full_object_g.numprops; k++) {
-              if (full_object_g.props[k].num == prop_number) {
-                prevcont = full_object_g.props[k].continuation;
-              }
-            }
-          }
-          k = full_object_g.numprops++;
-          full_object_g.props[k].num = prop_number;
-          full_object_g.props[k].flags = 0;
-          full_object_g.props[k].datastart = full_object_g.propdatasize;
-          full_object_g.props[k].continuation = prevcont+1;
-          full_object_g.props[k].datalen = prop_length;
-          if (full_object_g.propdatasize + prop_length 
-            > MAX_OBJ_PROP_TABLE_SIZE) {
-            memoryerror("MAX_OBJ_PROP_TABLE_SIZE",MAX_OBJ_PROP_TABLE_SIZE);
-          }
-
-          for (i=0; i<prop_length; i++) {
-            int ppos = full_object_g.propdatasize++;
-            full_object_g.propdata[ppos].value = prop_addr + 4*i;
-            full_object_g.propdata[ppos].marker = INHERIT_MV;
-            full_object_g.propdata[ppos].type = CONSTANT_OT;
-          }
-        }
-        else {
-          /*  The ordinary case: the full_object_g property
-              values simply overrides the class definition,
-              so we skip over the values in the class table. */
-        }
-      }
-          else {
-            /*  The case where the class defined a property which wasn't
-                defined at all in full_object_g: we copy out the data into
-                a new property added to full_object_g. */
-            k = full_object_g.numprops++;
-            full_object_g.props[k].num = prop_number;
-            full_object_g.props[k].flags = prop_flags;
-            full_object_g.props[k].datastart = full_object_g.propdatasize;
-            full_object_g.props[k].continuation = 0;
-            full_object_g.props[k].datalen = prop_length;
-            if (full_object_g.propdatasize + prop_length 
-              > MAX_OBJ_PROP_TABLE_SIZE) {
-              memoryerror("MAX_OBJ_PROP_TABLE_SIZE",MAX_OBJ_PROP_TABLE_SIZE);
-            }
-
-            for (i=0; i<prop_length; i++) {
-              int ppos = full_object_g.propdatasize++;
-              full_object_g.propdata[ppos].value = prop_addr + 4*i;
-              full_object_g.propdata[ppos].marker = INHERIT_MV; 
-              full_object_g.propdata[ppos].type = CONSTANT_OT;
-            }
-          }
-
-          if (full_object_g.numprops == MAX_OBJ_PROP_COUNT) {
-            memoryerror("MAX_OBJ_PROP_COUNT",MAX_OBJ_PROP_COUNT);
-          }
-    }
-  }
-  
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Construction of Z-machine-format property blocks.                       */
-/* ------------------------------------------------------------------------- */
-
-static int write_properties_between(uchar *p, int mark, int from, int to)
-{   int j, k, prop_number, prop_length;
-    /* Note that p is properties_table. */
-    for (prop_number=to; prop_number>=from; prop_number--)
-    {   for (j=0; j<full_object.l; j++)
-        {   if ((full_object.pp[j].num == prop_number)
-                && (full_object.pp[j].l != 100))
-            {   prop_length = 2*full_object.pp[j].l;
-                if (mark+2+prop_length >= MAX_PROP_TABLE_SIZE)
-                    memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-                if (version_number == 3)
-                    p[mark++] = prop_number + (prop_length - 1)*32;
-                else
-                {   switch(prop_length)
-                    {   case 1:
-                          p[mark++] = prop_number; break;
-                        case 2:
-                          p[mark++] = prop_number + 0x40; break;
-                        default:
-                          p[mark++] = prop_number + 0x80;
-                          p[mark++] = prop_length + 0x80; break;
-                    }
-                }
-
-                for (k=0; k<full_object.pp[j].l; k++)
-                {   if (full_object.pp[j].ao[k].marker != 0)
-                        backpatch_zmachine(full_object.pp[j].ao[k].marker,
-                            PROP_ZA, mark);
-                    p[mark++] = full_object.pp[j].ao[k].value/256;
-                    p[mark++] = full_object.pp[j].ao[k].value%256;
-                }
-            }
-        }
-    }
-
-    p[mark++]=0;
-    return(mark);
-}
-
-static int write_property_block_z(char *shortname)
-{
-    /*  Compile the (now complete) full_object properties into a
-        property-table block at "p" in Inform's memory.
-        "shortname" is the object's short name, if specified; otherwise
-        NULL.
-
-        Return the number of bytes written to the block.                     */
-
-    int32 mark = properties_table_size, i;
-    uchar *p = (uchar *) properties_table;
-
-    /* printf("Object at %04x\n", mark); */
-
-    if (shortname != NULL)
-    {   uchar *tmp;
-        if (mark+1+510 >= MAX_PROP_TABLE_SIZE)
-            memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-        tmp = translate_text(p+mark+1,p+mark+1+510,shortname);
-        if (!tmp) error ("Short name of object exceeded 765 Z-characters");
-        i = subtract_pointers(tmp,(p+mark+1));
-        p[mark] = i/2;
-        mark += i+1;
-    }
-    if (current_defn_is_class)
-    {   mark = write_properties_between(p,mark,3,3);
-        for (i=0;i<6;i++)
-            p[mark++] = full_object.atts[i];
-        class_begins_at[no_classes++] = mark;
-    }
-
-    mark = write_properties_between(p, mark, 1, (version_number==3)?31:63);
-
-    i = mark - properties_table_size;
-    properties_table_size = mark;
-
-    return(i);
-}
-
-static int gpropsort(void *ptr1, void *ptr2)
-{
-  propg *prop1 = ptr1;
-  propg *prop2 = ptr2;
-  
-  if (prop2->num == -1)
-    return -1;
-  if (prop1->num == -1)
-    return 1;
-  if (prop1->num < prop2->num)
-    return -1;
-  if (prop1->num > prop2->num)
-    return 1;
-
-  return (prop1->continuation - prop2->continuation);
-}
-
-static int32 write_property_block_g(void)
-{
-  /*  Compile the (now complete) full_object properties into a
-      property-table block at "p" in Inform's memory. 
-      Return the number of bytes written to the block. 
-      In Glulx, the shortname property isn't used here; it's already
-      been compiled into an ordinary string. */
-
-  int32 i;
-  int ix, jx, kx, totalprops;
-  int32 mark = properties_table_size;
-  int32 datamark;
-  uchar *p = (uchar *) properties_table;
-
-  if (current_defn_is_class) {
-    for (i=0;i<NUM_ATTR_BYTES;i++)
-      p[mark++] = full_object_g.atts[i];
-    class_begins_at[no_classes++] = mark;
-  }
-
-  qsort(full_object_g.props, full_object_g.numprops, sizeof(propg), 
-    (int (*)(const void *, const void *))(&gpropsort));
-
-  full_object_g.finalpropaddr = mark;
-
-  totalprops = 0;
-
-  for (ix=0; ix<full_object_g.numprops; ix=jx) {
-    int propnum = full_object_g.props[ix].num;
-    if (propnum == -1)
-        break;
-    for (jx=ix; 
-        jx<full_object_g.numprops && full_object_g.props[jx].num == propnum;
-        jx++);
-    totalprops++;
-  }
-
-  /* Write out the number of properties in this table. */
-  if (mark+4 >= MAX_PROP_TABLE_SIZE)
-      memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-  WriteInt32(p+mark, totalprops);
-  mark += 4;
-
-  datamark = mark + 10*totalprops;
-
-  for (ix=0; ix<full_object_g.numprops; ix=jx) {
-    int propnum = full_object_g.props[ix].num;
-    int flags = full_object_g.props[ix].flags;
-    int totallen = 0;
-    int32 datamarkstart = datamark;
-    if (propnum == -1)
-      break;
-    for (jx=ix; 
-        jx<full_object_g.numprops && full_object_g.props[jx].num == propnum;
-        jx++) {
-      int32 datastart = full_object_g.props[jx].datastart;
-      if (datamark+4*full_object_g.props[jx].datalen >= MAX_PROP_TABLE_SIZE)
-        memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-      for (kx=0; kx<full_object_g.props[jx].datalen; kx++) {
-        int32 val = full_object_g.propdata[datastart+kx].value;
-        WriteInt32(p+datamark, val);
-        if (full_object_g.propdata[datastart+kx].marker != 0)
-          backpatch_zmachine(full_object_g.propdata[datastart+kx].marker,
-            PROP_ZA, datamark);
-        totallen++;
-        datamark += 4;
-      }
-    }
-    if (mark+10 >= MAX_PROP_TABLE_SIZE)
-        memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-    WriteInt16(p+mark, propnum);
-    mark += 2;
-    WriteInt16(p+mark, totallen);
-    mark += 2;
-    WriteInt32(p+mark, datamarkstart); 
-    mark += 4;
-    WriteInt16(p+mark, flags);
-    mark += 2;
-  }
-
-  mark = datamark;
-
-  i = mark - properties_table_size;
-  properties_table_size = mark;
-  return i;
-}
-
-/* ------------------------------------------------------------------------- */
-/*   The final stage in Nearby/Object/Class definition processing.           */
-/* ------------------------------------------------------------------------- */
-
-static void manufacture_object_z(void)
-{   int i, j;
-
-    segment_markers.enabled = FALSE;
-    directives.enabled = TRUE;
-
-    property_inheritance_z();
-
-    objectsz[no_objects].parent = parent_of_this_obj;
-    objectsz[no_objects].next = 0;
-    objectsz[no_objects].child = 0;
-
-    if ((parent_of_this_obj > 0) && (parent_of_this_obj != 0x7fff))
-    {   i = objectsz[parent_of_this_obj-1].child;
-        if (i == 0)
-            objectsz[parent_of_this_obj-1].child = no_objects + 1;
-        else
-        {   while(objectsz[i-1].next != 0) i = objectsz[i-1].next;
-            objectsz[i-1].next = no_objects+1;
-        }
-    }
-
-        /*  The properties table consists simply of a sequence of property
-            blocks, one for each object in order of definition, exactly as
-            it will appear in the final Z-machine.                           */
-
-    j = write_property_block_z(shortname_buffer);
-
-    objectsz[no_objects].propsize = j;
-    if (properties_table_size >= MAX_PROP_TABLE_SIZE)
-        memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-
-    if (current_defn_is_class)
-        for (i=0;i<6;i++) objectsz[no_objects].atts[i] = 0;
-    else
-        for (i=0;i<6;i++)
-            objectsz[no_objects].atts[i] = full_object.atts[i];
-
-    no_objects++;
-}
-
-static void manufacture_object_g(void)
-{   int32 i, j;
-
-    segment_markers.enabled = FALSE;
-    directives.enabled = TRUE;
-
-    property_inheritance_g();
-
-    objectsg[no_objects].parent = parent_of_this_obj;
-    objectsg[no_objects].next = 0;
-    objectsg[no_objects].child = 0;
-
-    if ((parent_of_this_obj > 0) && (parent_of_this_obj != 0x7fffffff))
-    {   i = objectsg[parent_of_this_obj-1].child;
-        if (i == 0)
-            objectsg[parent_of_this_obj-1].child = no_objects + 1;
-        else
-        {   while(objectsg[i-1].next != 0) i = objectsg[i-1].next;
-            objectsg[i-1].next = no_objects+1;
-        }
-    }
-
-    objectsg[no_objects].shortname = compile_string(shortname_buffer,
-      FALSE, FALSE);
-
-        /*  The properties table consists simply of a sequence of property
-            blocks, one for each object in order of definition, exactly as
-            it will appear in the final machine image.                      */
-
-    j = write_property_block_g();
-
-    objectsg[no_objects].propaddr = full_object_g.finalpropaddr;
-
-    objectsg[no_objects].propsize = j;
-    if (properties_table_size >= MAX_PROP_TABLE_SIZE)
-        memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
-
-    if (current_defn_is_class)
-        for (i=0;i<NUM_ATTR_BYTES;i++) 
-            objectatts[no_objects*NUM_ATTR_BYTES+i] = 0;
-    else
-        for (i=0;i<NUM_ATTR_BYTES;i++)
-            objectatts[no_objects*NUM_ATTR_BYTES+i] = full_object_g.atts[i];
-
-    no_objects++;
-}
-
-
-/* ========================================================================= */
-/*   [2]  The Object/Nearby/Class directives parser: translating the syntax  */
-/*        into object specifications and then triggering off the above.      */
-/* ========================================================================= */
-/*   Properties ("with" or "private") segment.                               */
-/* ------------------------------------------------------------------------- */
-
-static int *defined_this_segment;
-static long defined_this_segment_size; /* calloc size */
-static int def_t_s;
-
-static void ensure_defined_this_segment(int newsize)
-{
-    int oldsize = defined_this_segment_size;
-    defined_this_segment_size = newsize;
-    my_recalloc(&defined_this_segment, sizeof(int), oldsize,
-        defined_this_segment_size, "defined this segment table");
-}
-
-static void properties_segment_z(int this_segment)
-{
-    /*  Parse through the "with" part of an object/class definition:
-
-        <prop-1> <values...>, <prop-2> <values...>, ..., <prop-n> <values...>
-
-        This routine also handles "private", with this_segment being equal
-        to the token value for the introductory word ("private" or "with").  */
-
-
-    int   i, property_name_symbol, property_number=0, next_prop=0, length,
-          individual_property, this_identifier_number;
-
-    do
-    {   get_next_token_with_directives();
-        if ((token_type == SEGMENT_MARKER_TT)
-            || (token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   put_token_back(); return;
-        }
-
-        if (token_type != SYMBOL_TT)
-        {   ebf_error("property name", token_text);
-            return;
-        }
-
-        individual_property = (stypes[token_value] != PROPERTY_T);
-
-        if (individual_property)
-        {   if (sflags[token_value] & UNKNOWN_SFLAG)
-            {   this_identifier_number = no_individual_properties++;
-                assign_symbol(token_value, this_identifier_number,
-                    INDIVIDUAL_PROPERTY_T);
-
-                if (debugfile_switch)
-                {   debug_file_printf("<property>");
-                    debug_file_printf
-                        ("<identifier>%s</identifier>", token_text);
-                    debug_file_printf
-                        ("<value>%d</value>", this_identifier_number);
-                    debug_file_printf("</property>");
-                }
-
-            }
-            else
-            {   if (stypes[token_value]==INDIVIDUAL_PROPERTY_T)
-                    this_identifier_number = svals[token_value];
-                else
-                {   char already_error[128];
-                    sprintf(already_error,
-                        "\"%s\" is a name already in use (with type %s) \
-and may not be used as a property name too",
-                        token_text, typename(stypes[token_value]));
-                    error(already_error);
-                    return;
-                }
-            }
-
-            if (def_t_s >= defined_this_segment_size)
-                ensure_defined_this_segment(def_t_s*2);
-            defined_this_segment[def_t_s++] = token_value;
-
-            if (individual_prop_table_size++ == 0)
-            {   full_object.pp[full_object.l].num = 3;
-                full_object.pp[full_object.l].l = 1;
-                full_object.pp[full_object.l].ao[0].value
-                    = individuals_length;
-                full_object.pp[full_object.l].ao[0].type = LONG_CONSTANT_OT;
-                full_object.pp[full_object.l].ao[0].marker = INDIVPT_MV;
-
-                i_m = individuals_length;
-                full_object.l++;
-            }
-            individuals_table[i_m] = this_identifier_number/256;
-            if (this_segment == PRIVATE_SEGMENT)
-                individuals_table[i_m] |= 0x80;
-            individuals_table[i_m+1] = this_identifier_number%256;
-            if (module_switch)
-                backpatch_zmachine(IDENT_MV, INDIVIDUAL_PROP_ZA, i_m);
-            individuals_table[i_m+2] = 0;
-        }
-        else
-        {   if (sflags[token_value] & UNKNOWN_SFLAG)
-            {   error_named("No such property name as", token_text);
-                return;
-            }
-            if (this_segment == PRIVATE_SEGMENT)
-                error_named("Property should be declared in 'with', \
-not 'private':", token_text);
-            if (def_t_s >= defined_this_segment_size)
-                ensure_defined_this_segment(def_t_s*2);
-            defined_this_segment[def_t_s++] = token_value;
-            property_number = svals[token_value];
-
-            next_prop=full_object.l++;
-            full_object.pp[next_prop].num = property_number;
-        }
-
-        for (i=0; i<(def_t_s-1); i++)
-            if (defined_this_segment[i] == token_value)
-            {   error_named("Property given twice in the same declaration:",
-                    (char *) symbs[token_value]);
-            }
-            else
-            if (svals[defined_this_segment[i]] == svals[token_value])
-            {   char error_b[128];
-                sprintf(error_b,
-                    "Property given twice in the same declaration, because \
-the names '%s' and '%s' actually refer to the same property",
-                    (char *) symbs[defined_this_segment[i]],
-                    (char *) symbs[token_value]);
-                error(error_b);
-            }
-
-        property_name_symbol = token_value;
-        sflags[token_value] |= USED_SFLAG;
-
-        length=0;
-        do
-        {   assembly_operand AO;
-            get_next_token_with_directives();
-            if ((token_type == EOF_TT)
-                || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-                || ((token_type == SEP_TT) && (token_value == COMMA_SEP)))
-                break;
-
-            if (token_type == SEGMENT_MARKER_TT) { put_token_back(); break; }
-
-            if ((!individual_property) && (property_number==1)
-                && ((token_type != SQ_TT) || (strlen(token_text) <2 )) 
-                && (token_type != DQ_TT)
-                )
-                warning ("'name' property should only contain dictionary words");
-
-            if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
-            {   char embedded_name[80];
-                if (current_defn_is_class)
-                {   sprintf(embedded_name,
-                        "%s::%s", classname_text,
-                        (char *) symbs[property_name_symbol]);
-                }
-                else
-                {   sprintf(embedded_name,
-                        "%s.%s", objectname_text,
-                        (char *) symbs[property_name_symbol]);
-                }
-                AO.value = parse_routine(NULL, TRUE, embedded_name, FALSE, -1);
-                AO.type = LONG_CONSTANT_OT;
-                AO.marker = IROUTINE_MV;
-
-                directives.enabled = FALSE;
-                segment_markers.enabled = TRUE;
-
-                statements.enabled = FALSE;
-                misc_keywords.enabled = FALSE;
-                local_variables.enabled = FALSE;
-                system_functions.enabled = FALSE;
-                conditions.enabled = FALSE;
-            }
-            else
-
-            /*  A special rule applies to values in double-quotes of the
-                built-in property "name", which always has number 1: such
-                property values are dictionary entries and not static
-                strings                                                      */
-
-            if ((!individual_property) &&
-                (property_number==1) && (token_type == DQ_TT))
-            {   AO.value = dictionary_add(token_text, 0x80, 0, 0);
-                AO.type = LONG_CONSTANT_OT;
-                AO.marker = DWORD_MV;
-            }
-            else
-            {   if (length!=0)
-                {
-                    if ((token_type == SYMBOL_TT)
-                        && (stypes[token_value]==PROPERTY_T))
-                    {
-                        /*  This is not necessarily an error: it's possible
-                            to imagine a property whose value is a list
-                            of other properties to look up, but far more
-                            likely that a comma has been omitted in between
-                            two property blocks                              */
-
-                        warning_named(
-               "Missing ','? Property data seems to contain the property name",
-                            token_text);
-                    }
-                }
-
-                /*  An ordinary value, then:                                 */
-
-                put_token_back();
-                AO = parse_expression(ARRAY_CONTEXT);
-            }
-
-            if (length == 64)
-            {   error_named("Limit (of 32 values) exceeded for property",
-                    (char *) symbs[property_name_symbol]);
-                break;
-            }
-
-            if (individual_property)
-            {   if (AO.marker != 0)
-                    backpatch_zmachine(AO.marker, INDIVIDUAL_PROP_ZA,
-                        i_m+3+length);
-                individuals_table[i_m+3+length++] = AO.value/256;
-                individuals_table[i_m+3+length++] = AO.value%256;
-            }
-            else
-            {   full_object.pp[next_prop].ao[length/2] = AO;
-                length = length + 2;
-            }
-
-        } while (TRUE);
-
-        /*  People rarely do, but it is legal to declare a property without
-            a value at all:
-
-                with  name "fish", number, time_left;
-
-            in which case the properties "number" and "time_left" are
-            created as in effect variables and initialised to zero.          */
-
-        if (length == 0)
-        {   if (individual_property)
-            {   individuals_table[i_m+3+length++] = 0;
-                individuals_table[i_m+3+length++] = 0;
-            }
-            else
-            {   full_object.pp[next_prop].ao[0].value = 0;
-                full_object.pp[next_prop].ao[0].type  = LONG_CONSTANT_OT;
-                full_object.pp[next_prop].ao[0].marker = 0;
-                length = 2;
-            }
-        }
-
-        if ((version_number==3) && (!individual_property))
-        {   if (length > 8)
-            {
-       warning_named("Version 3 limit of 4 values per property exceeded \
-(use -v5 to get 32), so truncating property",
-                    (char *) symbs[property_name_symbol]);
-                full_object.pp[next_prop].l=4;
-            }
-        }
-
-        if (individual_property)
-        {
-            if (individuals_length+length+3 > MAX_INDIV_PROP_TABLE_SIZE)
-                memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
-                    MAX_INDIV_PROP_TABLE_SIZE);
-            individuals_table[i_m + 2] = length;
-            individuals_length += length+3;
-            i_m = individuals_length;
-        }
-        else
-            full_object.pp[next_prop].l = length/2;
-
-        if ((token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   put_token_back(); return;
-        }
-
-    } while (TRUE);
-}
-
-
-static void properties_segment_g(int this_segment)
-{
-    /*  Parse through the "with" part of an object/class definition:
-
-        <prop-1> <values...>, <prop-2> <values...>, ..., <prop-n> <values...>
-
-        This routine also handles "private", with this_segment being equal
-        to the token value for the introductory word ("private" or "with").  */
-
-
-    int   i, next_prop,
-          individual_property, this_identifier_number;
-    int32 property_name_symbol, property_number, length;
-
-    do
-    {   get_next_token_with_directives();
-        if ((token_type == SEGMENT_MARKER_TT)
-            || (token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   put_token_back(); return;
-        }
-
-        if (token_type != SYMBOL_TT)
-        {   ebf_error("property name", token_text);
-            return;
-        }
-
-        individual_property = (stypes[token_value] != PROPERTY_T);
-
-        if (individual_property)
-        {   if (sflags[token_value] & UNKNOWN_SFLAG)
-            {   this_identifier_number = no_individual_properties++;
-                assign_symbol(token_value, this_identifier_number,
-                    INDIVIDUAL_PROPERTY_T);
-
-                if (debugfile_switch)
-                {   debug_file_printf("<property>");
-                    debug_file_printf
-                        ("<identifier>%s</identifier>", token_text);
-                    debug_file_printf
-                        ("<value>%d</value>", this_identifier_number);
-                    debug_file_printf("</property>");
-                }
-
-            }
-            else
-            {   if (stypes[token_value]==INDIVIDUAL_PROPERTY_T)
-                    this_identifier_number = svals[token_value];
-                else
-                {   char already_error[128];
-                    sprintf(already_error,
-                        "\"%s\" is a name already in use (with type %s) \
-and may not be used as a property name too",
-                        token_text, typename(stypes[token_value]));
-                    error(already_error);
-                    return;
-                }
-            }
-
-            if (def_t_s >= defined_this_segment_size)
-                ensure_defined_this_segment(def_t_s*2);
-            defined_this_segment[def_t_s++] = token_value;
-            property_number = svals[token_value];
-
-            next_prop=full_object_g.numprops++;
-            full_object_g.props[next_prop].num = property_number;
-            full_object_g.props[next_prop].flags = 
-              ((this_segment == PRIVATE_SEGMENT) ? 1 : 0);
-            full_object_g.props[next_prop].datastart = full_object_g.propdatasize;
-            full_object_g.props[next_prop].continuation = 0;
-            full_object_g.props[next_prop].datalen = 0;
-        }
-        else
-        {   if (sflags[token_value] & UNKNOWN_SFLAG)
-            {   error_named("No such property name as", token_text);
-                return;
-            }
-            if (this_segment == PRIVATE_SEGMENT)
-                error_named("Property should be declared in 'with', \
-not 'private':", token_text);
-
-            if (def_t_s >= defined_this_segment_size)
-                ensure_defined_this_segment(def_t_s*2);
-            defined_this_segment[def_t_s++] = token_value;
-            property_number = svals[token_value];
-
-            next_prop=full_object_g.numprops++;
-            full_object_g.props[next_prop].num = property_number;
-            full_object_g.props[next_prop].flags = 0;
-            full_object_g.props[next_prop].datastart = full_object_g.propdatasize;
-            full_object_g.props[next_prop].continuation = 0;
-            full_object_g.props[next_prop].datalen = 0;
-        }
-
-        for (i=0; i<(def_t_s-1); i++)
-            if (defined_this_segment[i] == token_value)
-            {   error_named("Property given twice in the same declaration:",
-                    (char *) symbs[token_value]);
-            }
-            else
-            if (svals[defined_this_segment[i]] == svals[token_value])
-            {   char error_b[128];
-                sprintf(error_b,
-                    "Property given twice in the same declaration, because \
-the names '%s' and '%s' actually refer to the same property",
-                    (char *) symbs[defined_this_segment[i]],
-                    (char *) symbs[token_value]);
-                error(error_b);
-            }
-
-        if (full_object_g.numprops == MAX_OBJ_PROP_COUNT) {
-          memoryerror("MAX_OBJ_PROP_COUNT",MAX_OBJ_PROP_COUNT);
-        }
-
-        property_name_symbol = token_value;
-        sflags[token_value] |= USED_SFLAG;
-
-        length=0;
-        do
-        {   assembly_operand AO;
-            get_next_token_with_directives();
-            if ((token_type == EOF_TT)
-                || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-                || ((token_type == SEP_TT) && (token_value == COMMA_SEP)))
-                break;
-
-            if (token_type == SEGMENT_MARKER_TT) { put_token_back(); break; }
-
-            if ((!individual_property) && (property_number==1)
-                && (token_type != SQ_TT) && (token_type != DQ_TT)
-                )
-                warning ("'name' property should only contain dictionary words");
-
-            if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
-            {   char embedded_name[80];
-                if (current_defn_is_class)
-                {   sprintf(embedded_name,
-                        "%s::%s", classname_text,
-                        (char *) symbs[property_name_symbol]);
-                }
-                else
-                {   sprintf(embedded_name,
-                        "%s.%s", objectname_text,
-                        (char *) symbs[property_name_symbol]);
-                }
-                AO.value = parse_routine(NULL, TRUE, embedded_name, FALSE, -1);
-                AO.type = CONSTANT_OT; 
-                AO.marker = IROUTINE_MV;
-
-                directives.enabled = FALSE;
-                segment_markers.enabled = TRUE;
-
-                statements.enabled = FALSE;
-                misc_keywords.enabled = FALSE;
-                local_variables.enabled = FALSE;
-                system_functions.enabled = FALSE;
-                conditions.enabled = FALSE;
-            }
-            else
-
-            /*  A special rule applies to values in double-quotes of the
-                built-in property "name", which always has number 1: such
-                property values are dictionary entries and not static
-                strings                                                      */
-
-            if ((!individual_property) &&
-                (property_number==1) && (token_type == DQ_TT))
-            {   AO.value = dictionary_add(token_text, 0x80, 0, 0);
-                AO.type = CONSTANT_OT; 
-                AO.marker = DWORD_MV;
-            }
-            else
-            {   if (length!=0)
-                {
-                    if ((token_type == SYMBOL_TT)
-                        && (stypes[token_value]==PROPERTY_T))
-                    {
-                        /*  This is not necessarily an error: it's possible
-                            to imagine a property whose value is a list
-                            of other properties to look up, but far more
-                            likely that a comma has been omitted in between
-                            two property blocks                              */
-
-                        warning_named(
-               "Missing ','? Property data seems to contain the property name",
-                            token_text);
-                    }
-                }
-
-                /*  An ordinary value, then:                                 */
-
-                put_token_back();
-                AO = parse_expression(ARRAY_CONTEXT);
-            }
-
-            if (length == 32768) /* VENEER_CONSTRAINT_ON_PROP_TABLE_SIZE? */
-            {   error_named("Limit (of 32768 values) exceeded for property",
-                    (char *) symbs[property_name_symbol]);
-                break;
-            }
-
-            if (full_object_g.propdatasize >= MAX_OBJ_PROP_TABLE_SIZE) {
-              memoryerror("MAX_OBJ_PROP_TABLE_SIZE",MAX_OBJ_PROP_TABLE_SIZE);
-            }
-
-            full_object_g.propdata[full_object_g.propdatasize++] = AO;
-            length += 1;
-
-        } while (TRUE);
-
-        /*  People rarely do, but it is legal to declare a property without
-            a value at all:
-
-                with  name "fish", number, time_left;
-
-            in which case the properties "number" and "time_left" are
-            created as in effect variables and initialised to zero.          */
-
-        if (length == 0)
-        {
-            assembly_operand AO;
-            AO.value = 0;
-            AO.type = CONSTANT_OT;
-            AO.marker = 0;
-            full_object_g.propdata[full_object_g.propdatasize++] = AO;
-            length += 1;
-        }
-
-        full_object_g.props[next_prop].datalen = length;
-
-        if ((token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   put_token_back(); return;
-        }
-
-    } while (TRUE);
-}
-
-static void properties_segment(int this_segment)
-{
-  if (!glulx_mode)
-    properties_segment_z(this_segment);
-  else
-    properties_segment_g(this_segment);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Attributes ("has") segment.                                             */
-/* ------------------------------------------------------------------------- */
-
-static void attributes_segment(void)
-{
-    /*  Parse through the "has" part of an object/class definition:
-
-        [~]<attribute-1> [~]<attribute-2> ... [~]<attribute-n>               */
-
-    int attribute_number, truth_state, bitmask;
-    uchar *attrbyte;
-    do
-    {   truth_state = TRUE;
-
-        ParseAttrN:
-
-        get_next_token_with_directives();
-        if ((token_type == SEGMENT_MARKER_TT)
-            || (token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   if (!truth_state)
-                ebf_error("attribute name after '~'", token_text);
-            put_token_back(); return;
-        }
-        if ((token_type == SEP_TT) && (token_value == COMMA_SEP)) return;
-
-        if ((token_type == SEP_TT) && (token_value == ARTNOT_SEP))
-        {   truth_state = !truth_state; goto ParseAttrN;
-        }
-
-        if ((token_type != SYMBOL_TT)
-            || (stypes[token_value] != ATTRIBUTE_T))
-        {   ebf_error("name of an already-declared attribute", token_text);
-            return;
-        }
-
-        attribute_number = svals[token_value];
-        sflags[token_value] |= USED_SFLAG;
-
-        if (!glulx_mode) {
-            bitmask = (1 << (7-attribute_number%8));
-            attrbyte = &(full_object.atts[attribute_number/8]);
-        }
-        else {
-            /* In Glulx, my prejudices rule, and therefore bits are numbered
-               from least to most significant. This is the opposite of the
-               way the Z-machine works. */
-            bitmask = (1 << (attribute_number%8));
-            attrbyte = &(full_object_g.atts[attribute_number/8]);
-        }
-
-        if (truth_state)
-            *attrbyte |= bitmask;     /* Set attribute bit */
-        else
-            *attrbyte &= ~bitmask;    /* Clear attribute bit */
-
-    } while (TRUE);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Classes ("class") segment.                                              */
-/* ------------------------------------------------------------------------- */
-
-static void add_class_to_inheritance_list(int class_number)
-{
-    int i;
-
-    /*  The class number is actually the class's object number, which needs
-        to be translated into its actual class number:                       */
-
-    for (i=0;i<no_classes;i++)
-        if (class_number == class_object_numbers[i])
-        {   class_number = i+1;
-            break;
-        }
-
-    /*  Remember the inheritance list so that property inheritance can
-        be sorted out later on, when the definition has been finished:       */
-
-    classes_to_inherit_from[no_classes_to_inherit_from++] = class_number;
-
-    /*  Inheriting attributes from the class at once:                        */
-
-    if (!glulx_mode) {
-        for (i=0; i<6; i++)
-            full_object.atts[i]
-                |= properties_table[class_begins_at[class_number-1] - 6 + i];
-    }
-    else {
-        for (i=0; i<NUM_ATTR_BYTES; i++)
-            full_object_g.atts[i]
-                |= properties_table[class_begins_at[class_number-1] 
-                    - NUM_ATTR_BYTES + i];
-    }
-}
-
-static void classes_segment(void)
-{
-    /*  Parse through the "class" part of an object/class definition:
-
-        <class-1> ... <class-n>                                              */
-
-    do
-    {   get_next_token_with_directives();
-        if ((token_type == SEGMENT_MARKER_TT)
-            || (token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   put_token_back(); return;
-        }
-        if ((token_type == SEP_TT) && (token_value == COMMA_SEP)) return;
-
-        if ((token_type != SYMBOL_TT)
-            || (stypes[token_value] != CLASS_T))
-        {   ebf_error("name of an already-declared class", token_text);
-            return;
-        }
-
-        sflags[token_value] |= USED_SFLAG;
-        add_class_to_inheritance_list(svals[token_value]);
-    } while (TRUE);
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Parse the body of a Nearby/Object/Class definition.                     */
-/* ------------------------------------------------------------------------- */
-
-static void parse_body_of_definition(void)
-{   int commas_in_row;
-
-    def_t_s = 0;
-
-    do
-    {   commas_in_row = -1;
-        do
-        {   get_next_token_with_directives(); commas_in_row++;
-        } while ((token_type == SEP_TT) && (token_value == COMMA_SEP));
-
-        if (commas_in_row>1)
-            error("Two commas ',' in a row in object/class definition");
-
-        if ((token_type == EOF_TT)
-            || ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
-        {   if (commas_in_row > 0)
-                error("Object/class definition finishes with ','");
-            if (token_type == EOF_TT)
-                error("Object/class definition incomplete (no ';') at end of file");
-            break;
-        }
-
-        if (token_type != SEGMENT_MARKER_TT)
-        {   error_named("Expected 'with', 'has' or 'class' in \
-object/class definition but found", token_text);
-            break;
-        }
-        else
-        switch(token_value)
-        {   case WITH_SEGMENT:
-                properties_segment(WITH_SEGMENT);
-                break;
-            case PRIVATE_SEGMENT:
-                properties_segment(PRIVATE_SEGMENT);
-                break;
-            case HAS_SEGMENT:
-                attributes_segment();
-                break;
-            case CLASS_SEGMENT:
-                classes_segment();
-                break;
-        }
-
-    } while (TRUE);
-
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Class directives:                                                       */
-/*                                                                           */
-/*        Class <name>  <body of definition>                                 */
-/* ------------------------------------------------------------------------- */
-
-static void initialise_full_object(void)
-{
-  int i;
-  if (!glulx_mode) {
-    full_object.l = 0;
-    full_object.atts[0] = 0;
-    full_object.atts[1] = 0;
-    full_object.atts[2] = 0;
-    full_object.atts[3] = 0;
-    full_object.atts[4] = 0;
-    full_object.atts[5] = 0;
-  }
-  else {
-    full_object_g.numprops = 0;
-    full_object_g.propdatasize = 0;
-    for (i=0; i<NUM_ATTR_BYTES; i++)
-      full_object_g.atts[i] = 0;
-  }
-}
-
-extern void make_class(char * metaclass_name)
-{   int n, duplicates_to_make = 0, class_number = no_objects+1,
-        metaclass_flag = (metaclass_name != NULL);
-    char duplicate_name[128];
-    int class_symbol;
-    debug_location_beginning beginning_debug_location =
-        get_token_location_beginning();
-
-    current_defn_is_class = TRUE; no_classes_to_inherit_from = 0;
-    individual_prop_table_size = 0;
-
-    if (no_classes==MAX_CLASSES)
-        memoryerror("MAX_CLASSES", MAX_CLASSES);
-
-    if (no_classes==VENEER_CONSTRAINT_ON_CLASSES)
-        fatalerror("Inform's maximum possible number of classes (whatever \
-amount of memory is allocated) has been reached. If this causes serious \
-inconvenience, please contact the maintainers.");
-
-    directives.enabled = FALSE;
-
-    if (metaclass_flag)
-    {   token_text = metaclass_name;
-        token_value = symbol_index(token_text, -1);
-        token_type = SYMBOL_TT;
-    }
-    else
-    {   get_next_token();
-        if ((token_type != SYMBOL_TT)
-            || (!(sflags[token_value] & UNKNOWN_SFLAG)))
-        {   discard_token_location(beginning_debug_location);
-            ebf_error("new class name", token_text);
-            panic_mode_error_recovery();
-            return;
-        }
-    }
-
-    /*  Each class also creates a modest object representing itself:         */
-
-    strcpy(shortname_buffer, token_text);
-
-    assign_symbol(token_value, class_number, CLASS_T);
-    classname_text = (char *) symbs[token_value];
-
-    if (!glulx_mode) {
-        if (metaclass_flag) sflags[token_value] |= SYSTEM_SFLAG;
-    }
-    else {
-        /*  In Glulx, metaclasses have to be backpatched too! So we can't 
-            mark it as "system", but we should mark it "used". */
-        if (metaclass_flag) sflags[token_value] |= USED_SFLAG;
-    }
-
-    /*  "Class" (object 1) has no parent, whereas all other classes are
-        the children of "Class".  Since "Class" is not present in a module,
-        a special value is used which is corrected to 1 by the linker.       */
-
-    if (metaclass_flag) parent_of_this_obj = 0;
-    else parent_of_this_obj = (module_switch)?MAXINTWORD:1;
-
-    class_object_numbers[no_classes] = class_number;
-
-    initialise_full_object();
-
-    /*  Give the class the (nameless in Inform syntax) "inheritance" property
-        with value its own class number.  (This therefore accumulates onto
-        the inheritance property of any object inheriting from the class,
-        since property 2 is always set to "additive" -- see below)           */
-
-    if (!glulx_mode) {
-      full_object.l = 1;
-      full_object.pp[0].num = 2;
-      full_object.pp[0].l = 1;
-      full_object.pp[0].ao[0].value  = no_objects + 1;
-      full_object.pp[0].ao[0].type   = LONG_CONSTANT_OT;
-      full_object.pp[0].ao[0].marker = OBJECT_MV;
-    }
-    else {
-      full_object_g.numprops = 1;
-      full_object_g.props[0].num = 2;
-      full_object_g.props[0].flags = 0;
-      full_object_g.props[0].datastart = 0;
-      full_object_g.props[0].continuation = 0;
-      full_object_g.props[0].datalen = 1;
-      full_object_g.propdatasize = 1;
-      full_object_g.propdata[0].value  = no_objects + 1;
-      full_object_g.propdata[0].type   = CONSTANT_OT;
-      full_object_g.propdata[0].marker = OBJECT_MV;
-    }
-
-    class_symbol = token_value;
-
-    if (!metaclass_flag)
-    {   get_next_token();
-        if ((token_type == SEP_TT) && (token_value == OPENB_SEP))
-        {   assembly_operand AO;
-            AO = parse_expression(CONSTANT_CONTEXT);
-            if (AO.marker != 0)
-            {   error("Duplicate-number not known at compile time");
-                n=0;
-            }
-            else
-                n = AO.value;
-            if ((n<0) || (n>10000))
-            {   error("The number of duplicates must be 0 to 10000");
-                n=0;
-            }
-
-            /*  Make one extra duplicate, since the veneer routines need
-                always to keep an undamaged prototype for the class in stock */
-
-            duplicates_to_make = n + 1;
-
-            match_close_bracket();
-        } else put_token_back();
-
-        /*  Parse the body of the definition:                                */
-
-        parse_body_of_definition();
-    }
-
-    if (debugfile_switch)
-    {   debug_file_printf("<class>");
-        debug_file_printf("<identifier>%s</identifier>", shortname_buffer);
-        debug_file_printf("<class-number>%d</class-number>", no_classes);
-        debug_file_printf("<value>");
-        write_debug_object_backpatch(no_objects + 1);
-        debug_file_printf("</value>");
-        write_debug_locations
-            (get_token_location_end(beginning_debug_location));
-        debug_file_printf("</class>");
-    }
-
-    if (!glulx_mode)
-      manufacture_object_z();
-    else
-      manufacture_object_g();
-
-    if (individual_prop_table_size >= VENEER_CONSTRAINT_ON_IP_TABLE_SIZE)
-        error("This class is too complex: it now carries too many properties. \
-You may be able to get round this by declaring some of its property names as \
-\"common properties\" using the 'Property' directive.");
-
-    if (duplicates_to_make > 0)
-    {   sprintf(duplicate_name, "%s_1", shortname_buffer);
-        for (n=1; (duplicates_to_make--) > 0; n++)
-        {   if (n>1)
-            {   int i = strlen(duplicate_name);
-                while (duplicate_name[i] != '_') i--;
-                sprintf(duplicate_name+i+1, "%d", n);
-            }
-            make_object(FALSE, duplicate_name, class_number, class_number, -1);
-        }
-    }
-}
-
-/* ------------------------------------------------------------------------- */
-/*   Object/Nearby directives:                                               */
-/*                                                                           */
-/*       Object  <name-1> ... <name-n> "short name"  [parent]  <body of def> */
-/*                                                                           */
-/*       Nearby  <name-1> ... <name-n> "short name"  <body of definition>    */
-/* ------------------------------------------------------------------------- */
-
-static int end_of_header(void)
-{   if (((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
-        || ((token_type == SEP_TT) && (token_value == COMMA_SEP))
-        || (token_type == SEGMENT_MARKER_TT)) return TRUE;
-    return FALSE;
-}
-
-extern void make_object(int nearby_flag,
-    char *textual_name, int specified_parent, int specified_class,
-    int instance_of)
-{
-    /*  Ordinarily this is called with nearby_flag TRUE for "Nearby",
-        FALSE for "Object"; and textual_name NULL, specified_parent and
-        specified_class both -1.  The next three arguments are used when
-        the routine is called for class duplicates manufacture (see above).
-        The last is used to create instances of a particular class.  */
-
-    int i, tree_depth, internal_name_symbol = 0;
-    char internal_name[64];
-    debug_location_beginning beginning_debug_location =
-        get_token_location_beginning();
-
-    directives.enabled = FALSE;
-
-    if (no_objects==MAX_OBJECTS) memoryerror("MAX_OBJECTS", MAX_OBJECTS);
-
-    sprintf(internal_name, "nameless_obj__%d", no_objects+1);
-    objectname_text = internal_name;
-
-    current_defn_is_class = FALSE;
-
-    no_classes_to_inherit_from=0;
-
-    individual_prop_table_size = 0;
-
-    if (nearby_flag) tree_depth=1; else tree_depth=0;
-
-    if (specified_class != -1) goto HeaderPassed;
-
-    get_next_token();
-
-    /*  Read past and count a sequence of "->"s, if any are present          */
-
-    if ((token_type == SEP_TT) && (token_value == ARROW_SEP))
-    {   if (nearby_flag)
-          error("The syntax '->' is only used as an alternative to 'Nearby'");
-
-        while ((token_type == SEP_TT) && (token_value == ARROW_SEP))
-        {   tree_depth++;
-            get_next_token();
-        }
-    }
-
-    sprintf(shortname_buffer, "?");
-
-    segment_markers.enabled = TRUE;
-
-    /*  This first word is either an internal name, or a textual short name,
-        or the end of the header part                                        */
-
-    if (end_of_header()) goto HeaderPassed;
-
-    if (token_type == DQ_TT) textual_name = token_text;
-    else
-    {   if ((token_type != SYMBOL_TT)
-            || (!(sflags[token_value] & UNKNOWN_SFLAG)))
-            ebf_error("name for new object or its textual short name",
-                token_text);
-        else
-        {   internal_name_symbol = token_value;
-            strcpy(internal_name, token_text);
-        }
-    }
-
-    /*  The next word is either a parent object, or
-        a textual short name, or the end of the header part                  */
-
-    get_next_token_with_directives();
-    if (end_of_header()) goto HeaderPassed;
-
-    if (token_type == DQ_TT)
-    {   if (textual_name != NULL)
-            error("Two textual short names given for only one object");
-        else
-            textual_name = token_text;
-    }
-    else
-    {   if ((token_type != SYMBOL_TT)
-            || (sflags[token_value] & UNKNOWN_SFLAG))
-        {   if (textual_name == NULL)
-                ebf_error("parent object or the object's textual short name",
-                    token_text);
-            else
-                ebf_error("parent object", token_text);
-        }
-        else goto SpecParent;
-    }
-
-    /*  Finally, it's possible that there is still a parent object           */
-
-    get_next_token();
-    if (end_of_header()) goto HeaderPassed;
-
-    if (specified_parent != -1)
-        ebf_error("body of object definition", token_text);
-    else
-    {   SpecParent:
-        if ((stypes[token_value] == OBJECT_T)
-            || (stypes[token_value] == CLASS_T))
-        {   specified_parent = svals[token_value];
-            sflags[token_value] |= USED_SFLAG;
-        }
-        else ebf_error("name of (the parent) object", token_text);
-    }
-
-    /*  Now it really has to be the body of the definition.                  */
-
-    get_next_token_with_directives();
-    if (end_of_header()) goto HeaderPassed;
-
-    ebf_error("body of object definition", token_text);
-
-    HeaderPassed:
-    if (specified_class == -1) put_token_back();
-
-    if (internal_name_symbol > 0)
-        assign_symbol(internal_name_symbol, no_objects + 1, OBJECT_T);
-
-    if (listobjects_switch)
-        printf("%3d \"%s\"\n", no_objects+1,
-            (textual_name==NULL)?"(with no short name)":textual_name);
-    if (textual_name == NULL)
-    {   if (internal_name_symbol > 0)
-            sprintf(shortname_buffer, "(%s)",
-                (char *) symbs[internal_name_symbol]);
-        else
-            sprintf(shortname_buffer, "(%d)", no_objects+1);
-    }
-    else
-    {   if (strlen(textual_name)>765)
-            error("Short name of object (in quotes) exceeded 765 characters");
-        strncpy(shortname_buffer, textual_name, 765);
-    }
-
-    if (specified_parent != -1)
-    {   if (tree_depth > 0)
-            error("Use of '->' (or 'Nearby') clashes with giving a parent");
-        parent_of_this_obj = specified_parent;
-    }
-    else
-    {   parent_of_this_obj = 0;
-        if (tree_depth>0)
-        {
-            /*  We have to set the parent object to the most recently defined
-                object at level (tree_depth - 1) in the tree.
-
-                A complication is that objects are numbered 1, 2, ... in the
-                Z-machine (and in the objects[].parent, etc., fields) but
-                0, 1, 2, ... internally (and as indices to object[]).        */
-
-            for (i=no_objects-1; i>=0; i--)
-            {   int j = i, k = 0;
-
-                /*  Metaclass or class objects cannot be '->' parents:  */
-                if ((!module_switch) && (i<4))
-                    continue;
-
-                if (!glulx_mode) {
-                    if (objectsz[i].parent == 1)
-                        continue;
-                    while (objectsz[j].parent != 0)
-                    {   j = objectsz[j].parent - 1; k++; }
-                }
-                else {
-                    if (objectsg[i].parent == 1)
-                        continue;
-                    while (objectsg[j].parent != 0)
-                    {   j = objectsg[j].parent - 1; k++; }
-                }
-
-                if (k == tree_depth - 1)
-                {   parent_of_this_obj = i+1;
-                    break;
-                }
-            }
-            if (parent_of_this_obj == 0)
-            {   if (tree_depth == 1)
-    error("'->' (or 'Nearby') fails because there is no previous object");
-                else
-    error("'-> -> ...' fails because no previous object is deep enough");
-            }
-        }
-    }
-
-    initialise_full_object();
-    if (instance_of != -1) add_class_to_inheritance_list(instance_of);
-
-    if (specified_class == -1) parse_body_of_definition();
-    else add_class_to_inheritance_list(specified_class);
-
-    if (debugfile_switch)
-    {   debug_file_printf("<object>");
-        if (internal_name_symbol > 0)
-        {   debug_file_printf("<identifier>%s</identifier>", internal_name);
-        } else
-        {   debug_file_printf
-                ("<identifier artificial=\"true\">%s</identifier>",
-                 internal_name);
-        }
-        debug_file_printf("<value>");
-        write_debug_object_backpatch(no_objects + 1);
-        debug_file_printf("</value>");
-        write_debug_locations
-            (get_token_location_end(beginning_debug_location));
-        debug_file_printf("</object>");
-    }
-
-    if (!glulx_mode)
-      manufacture_object_z();
-    else
-      manufacture_object_g();
-}
-
-/* ========================================================================= */
-/*   Data structure management routines                                      */
-/* ------------------------------------------------------------------------- */
-
-extern void init_objects_vars(void)
-{
-    properties_table = NULL;
-    prop_is_long = NULL;
-    prop_is_additive = NULL;
-    prop_default_value = NULL;
-
-    objectsz = NULL;
-    objectsg = NULL;
-    objectatts = NULL;
-    classes_to_inherit_from = NULL;
-    class_begins_at = NULL;
-}
-
-extern void objects_begin_pass(void)
-{
-    properties_table_size=0;
-    prop_is_long[1] = TRUE; prop_is_additive[1] = TRUE;            /* "name" */
-    prop_is_long[2] = TRUE; prop_is_additive[2] = TRUE;  /* inheritance prop */
-    if (!glulx_mode)
-        prop_is_long[3] = TRUE; prop_is_additive[3] = FALSE;
-                                         /* instance variables table address */
-    no_properties = 4;
-
-    if (debugfile_switch)
-    {   debug_file_printf("<property>");
-        debug_file_printf
-            ("<identifier artificial=\"true\">inheritance class</identifier>");
-        debug_file_printf("<value>2</value>");
-        debug_file_printf("</property>");
-        debug_file_printf("<property>");
-        debug_file_printf
-            ("<identifier artificial=\"true\">instance variables table address "
-             "(Z-code)</identifier>");
-        debug_file_printf("<value>3</value>");
-        debug_file_printf("</property>");
-    }
-
-    if (define_INFIX_switch) no_attributes = 1;
-    else no_attributes = 0;
-
-    no_objects = 0;
-    if (!glulx_mode) {
-        objectsz[0].parent = 0; objectsz[0].child = 0; objectsz[0].next = 0;
-        no_individual_properties=72;
-    }
-    else {
-        objectsg[0].parent = 0; objectsg[0].child = 0; objectsg[0].next = 0;
-        no_individual_properties = INDIV_PROP_START+8;
-    }
-    no_classes = 0;
-
-    no_embedded_routines = 0;
-
-    individuals_length=0;
-}
-
-extern void objects_allocate_arrays(void)
-{
-    objectsz = NULL;
-    objectsg = NULL;
-    objectatts = NULL;
-
-    prop_default_value    = my_calloc(sizeof(int32), INDIV_PROP_START,
-                                "property default values");
-    prop_is_long          = my_calloc(sizeof(int), INDIV_PROP_START,
-                                "property-is-long flags");
-    prop_is_additive      = my_calloc(sizeof(int), INDIV_PROP_START,
-                                "property-is-additive flags");
-
-    classes_to_inherit_from = my_calloc(sizeof(int), MAX_CLASSES,
-                                "inherited classes list");
-    class_begins_at       = my_calloc(sizeof(int32), MAX_CLASSES,
-                                "pointers to classes");
-    class_object_numbers  = my_calloc(sizeof(int),     MAX_CLASSES,
-                                "class object numbers");
-
-    properties_table      = my_malloc(MAX_PROP_TABLE_SIZE,"properties table");
-    individuals_table     = my_malloc(MAX_INDIV_PROP_TABLE_SIZE,
-                                "individual properties table");
-
-    defined_this_segment_size = 128;
-    defined_this_segment  = my_calloc(sizeof(int), defined_this_segment_size,
-                                "defined this segment table");
-
-    if (!glulx_mode) {
-      objectsz            = my_calloc(sizeof(objecttz), MAX_OBJECTS, 
-                                "z-objects");
-    }
-    else {
-      objectsg            = my_calloc(sizeof(objecttg), MAX_OBJECTS, 
-                                "g-objects");
-      objectatts          = my_calloc(NUM_ATTR_BYTES, MAX_OBJECTS, 
-                                "g-attributes");
-      full_object_g.props = my_calloc(sizeof(propg), MAX_OBJ_PROP_COUNT,
-                              "object property list");
-      full_object_g.propdata = my_calloc(sizeof(assembly_operand),
-                                 MAX_OBJ_PROP_TABLE_SIZE,
-                                 "object property data table");
-    }
-}
-
-extern void objects_free_arrays(void)
-{
-    my_free(&prop_default_value, "property default values");
-    my_free(&prop_is_long,     "property-is-long flags");
-    my_free(&prop_is_additive, "property-is-additive flags");
-
-    my_free(&objectsz,         "z-objects");
-    my_free(&objectsg,         "g-objects");
-    my_free(&objectatts,       "g-attributes");
-    my_free(&class_object_numbers,"class object numbers");
-    my_free(&classes_to_inherit_from, "inherited classes list");
-    my_free(&class_begins_at,  "pointers to classes");
-
-    my_free(&properties_table, "properties table");
-    my_free(&individuals_table,"individual properties table");
-
-    my_free(&defined_this_segment,"defined this segment table");
-
-    if (!glulx_mode) {
-        my_free(&full_object_g.props, "object property list");
-        my_free(&full_object_g.propdata, "object property data table");
-    }
-    
-}
-
-/* ========================================================================= */