Update to commit a469d404a7dc4e87e18f367eb4d8e05fc32d20a7
[inform.git] / src / tables.c
index 4158253d8e5af79a89fc1bf38db8e6d8d301a627..389eb4bca1506a9d4aa99fe161d461717442ea30 100644 (file)
@@ -3,8 +3,8 @@
 /*               end of dynamic memory, gluing together all the required     */
 /*               tables.                                                     */
 /*                                                                           */
-/*   Part of Inform 6.35                                                     */
-/*   copyright (c) Graham Nelson 1993 - 2021                                 */
+/*   Part of Inform 6.40                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2022                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
@@ -17,7 +17,7 @@
 /* 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/                  *
+/* along with Inform. If not, see https://gnu.org/licenses/                  */
 /*                                                                           */
 /* ------------------------------------------------------------------------- */
 
@@ -122,8 +122,20 @@ extern void write_serial_number(char *buffer)
 #endif
 }
 
-static void percentage(char *name, int32 x, int32 total)
-{   printf("   %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10);
+static char percentage_buffer[32];
+
+static char *show_percentage(int32 x, int32 total)
+{
+    if (memory_map_setting < 2) {
+        percentage_buffer[0] = '\0';
+    }
+    else if (x == 0) {
+        sprintf(percentage_buffer, "  ( --- )");
+    }
+    else {
+        sprintf(percentage_buffer, "  (%.1f %%)", (float)x * 100.0 / (float)total);
+    }
+    return percentage_buffer;
 }
 
 static char *version_name(int v)
@@ -154,7 +166,7 @@ static int32 rough_size_of_paged_memory_z(void)
     ASSERT_ZCODE();
 
     total = 64                                                     /* header */
-            + 2 + subtract_pointers(low_strings_top, low_strings)
+            + 2 + low_strings_top
                                                          /* low strings pool */
             + 6*32;                                   /* abbreviations table */
 
@@ -188,7 +200,7 @@ static int32 rough_size_of_paged_memory_z(void)
               + 2*no_actions                              /* action routines */
               + 2*no_grammar_token_routines;     /* general parsing routines */
 
-    total += (subtract_pointers(dictionary_top, dictionary))  /* dictionary */
+    total += (dictionary_top)                            /* dictionary size */
              + ((module_switch)?30:0);                        /* module map */
 
     total += static_array_area_size;                       /* static arrays */
@@ -212,7 +224,8 @@ static int32 rough_size_of_paged_memory_g(void)
     /* No header for us! */
     total = 1000; /* bit of a fudge factor */
 
-    total += dynamic_array_area_size; /* arrays and global variables */
+    total += no_globals * 4; /* global variables */
+    total += dynamic_array_area_size; /* arrays */
 
     total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
     total += properties_table_size; /* property tables */
@@ -233,7 +246,7 @@ static int32 rough_size_of_paged_memory_g(void)
     total += 4 + no_actions * 4; /* actions functions table */
 
     total += 4;
-    total += subtract_pointers(dictionary_top, dictionary);
+    total += dictionary_top;
 
     while (total % GPAGESIZE)
       total++;
@@ -291,7 +304,7 @@ static void construct_storyfile_z(void)
     p[mark]=0x80; p[mark+1]=0; mark+=2;        /* Start the low strings pool
                                          with a useful default string, "   " */
 
-    for (i=0; i+low_strings<low_strings_top; mark++, i++) /* Low strings pool */
+    for (i=0; i<low_strings_top; mark++, i++)  /* Low strings pool */
         p[0x42+i]=low_strings[i];
 
     abbrevs_at = mark;
@@ -309,7 +322,7 @@ static void construct_storyfile_z(void)
        strings". Write the abbreviations after these. */
     k = abbrevs_at+2*MAX_DYNAMIC_STRINGS;
     for (i=0; i<no_abbreviations; i++)
-    {   j=abbrev_values[i];
+    {   j=abbreviations[i].value;
         p[k++]=j/256;
         p[k++]=j%256;
     }
@@ -361,8 +374,7 @@ static void construct_storyfile_z(void)
     /*  -------------------- Objects and Properties ------------------------ */
 
     /* The object table must be word-aligned. The Z-machine spec does not
-       require this, but the RA__Pr() veneer routine does. See 
-       http://inform7.com/mantis/view.php?id=1712.
+       require this, but the RA__Pr() veneer routine does.
     */
     while ((mark%2) != 0) p[mark++]=0;
 
@@ -371,8 +383,8 @@ static void construct_storyfile_z(void)
     p[mark++]=0; p[mark++]=0;
 
     for (i=2; i< ((version_number==3)?32:64); i++)
-    {   p[mark++]=prop_default_value[i]/256;
-        p[mark++]=prop_default_value[i]%256;
+    {   p[mark++]=commonprops[i].default_value/256;
+        p[mark++]=commonprops[i].default_value%256;
     }
 
     object_tree_at = mark;
@@ -428,11 +440,11 @@ static void construct_storyfile_z(void)
 
     class_numbers_offset = mark;
     for (i=0; i<no_classes; i++)
-    {   p[mark++] = class_object_numbers[i]/256;
-        p[mark++] = class_object_numbers[i]%256;
+    {   p[mark++] = class_info[i].object_number/256;
+        p[mark++] = class_info[i].object_number%256;
         if (module_switch)
-        {   p[mark++] = class_begins_at[i]/256;
-            p[mark++] = class_begins_at[i]%256;
+        {   p[mark++] = class_info[i].begins_at/256;
+            p[mark++] = class_info[i].begins_at%256;
         }
     }
     p[mark++] = 0;
@@ -480,7 +492,7 @@ static void construct_storyfile_z(void)
 
     if (define_INFIX_switch)
     {   for (i=0, k=1, l=0; i<no_named_routines; i++)
-        {   if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
+        {   if (symbols[named_routine_symbols[i]].flags & STAR_SFLAG) l=l+k;
             k=k*2;
             if (k==256) { p[mark++] = l; k=1; l=0; }
         }
@@ -581,7 +593,7 @@ table format requested (producing number 2 format instead)");
 
         for (i=0; i<no_adjectives; i++)
         {   j = final_dict_order[adjectives[no_adjectives-i-1]]
-                *((version_number==3)?7:9)
+                *DICT_ENTRY_BYTE_LENGTH
                 + dictionary_offset + 7;
             p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
             p[mark++]=(256-no_adjectives+i);
@@ -601,19 +613,19 @@ table format requested (producing number 2 format instead)");
                      dictionary[2]=',';                 /* force words apart */
                      dictionary[3]='"';
 
-    dictionary[4]=(version_number==3)?7:9;           /* Length of each entry */
+    dictionary[4]=DICT_ENTRY_BYTE_LENGTH;           /* Length of each entry */
     dictionary[5]=(dict_entries/256);                   /* Number of entries */
     dictionary[6]=(dict_entries%256);
 
     for (i=0; i<7; i++) p[mark++] = dictionary[i];
 
     for (i=0; i<dict_entries; i++)
-    {   k = 7 + i*((version_number==3)?7:9);
-        j = mark + final_dict_order[i]*((version_number==3)?7:9);
-        for (l = 0; l<((version_number==3)?7:9); l++)
+    {   k = 7 + i*DICT_ENTRY_BYTE_LENGTH;
+        j = mark + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
+        for (l = 0; l<DICT_ENTRY_BYTE_LENGTH; l++)
             p[j++] = dictionary[k++];
     }
-    mark += dict_entries * ((version_number==3)?7:9);
+    mark += dict_entries * DICT_ENTRY_BYTE_LENGTH;
 
     /*  ------------------------- Module Map ------------------------------- */
 
@@ -643,7 +655,7 @@ table format requested (producing number 2 format instead)");
 size of the Z-machine format. See the memory map below: the start \
 of the area marked \"above readable memory\" must be brought down to $FFFE \
 or less.");
-        memory_map_switch = TRUE;
+        memory_map_setting = 1;
         /* Backpatching the grammar tables requires us to trust some of the */
         /* addresses we've written into Z-machine memory, but they may have */
         /* been truncated to 16 bits, so we can't do it.                    */
@@ -912,7 +924,7 @@ or less.");
 
         mark = actions_at;
         for (i=0; i<no_actions; i++)
-        {   j=action_byte_offset[i];
+        {   j=actions[i].byte_offset;
             if (OMIT_UNUSED_ROUTINES)
                 j = df_stripped_address_for_address(j);
             j += code_offset/scale_factor;
@@ -942,7 +954,7 @@ or less.");
                         switch(topbits)
                         {   case 1:
                                 value = final_dict_order[value]
-                                        *((version_number==3)?7:9)
+                                        *DICT_ENTRY_BYTE_LENGTH
                                         + dictionary_offset + 7;
                                 break;
                             case 2:
@@ -962,115 +974,6 @@ or less.");
 
     /*  ---- From here on, it's all reportage: construction is finished ---- */
 
-    if (statistics_switch)
-    {   int32 k_long, rate; char *k_str="";
-        k_long=(Out_Size/1024);
-        if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
-        else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
-        if (total_bytes_trans == 0) rate = 0;
-        else rate=total_bytes_trans*1000/total_chars_trans;
-
-        {   printf("In:\
-%3d source code files            %6d syntactic lines\n\
-%6d textual lines              %8ld characters ",
-            total_input_files, no_syntax_lines,
-            total_source_line_count, (long int) total_chars_read);
-            if (character_set_unicode) printf("(UTF-8)\n");
-            else if (character_set_setting == 0) printf("(plain ASCII)\n");
-            else
-            {   printf("(ISO 8859-%d %s)\n", character_set_setting,
-                    name_of_iso_set(character_set_setting));
-            }
-
-            printf("Allocated:\n\
-%6d symbols (maximum %4d)    %8ld bytes of memory\n\
-Out:   Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
-                 no_symbols, MAX_SYMBOLS,
-                 (long int) malloced_bytes,
-                 version_number,
-                 version_name(version_number),
-                 output_called,
-                 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
-                 (long int) k_long, k_str);
-
-            printf("\
-%6d classes (maximum %3d)        %6d objects (maximum %3d)\n\
-%6d global vars (maximum 233)    %6d variable/array space (maximum %d)\n",
-                 no_classes, MAX_CLASSES,
-                 no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
-                 no_globals,
-                 dynamic_array_area_size, MAX_STATIC_DATA);
-
-            printf(
-"%6d verbs (maximum %3d)          %6d dictionary entries (maximum %d)\n\
-%6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
-%6d actions (maximum %3d)        %6d attributes (maximum %2d)\n\
-%6d common props (maximum %2d)    %6d individual props (unlimited)\n",
-                 no_Inform_verbs, MAX_VERBS,
-                 dict_entries, MAX_DICT_ENTRIES,
-                 no_grammar_lines, grammar_version_number,
-                 no_grammar_tokens,
-                 no_actions, MAX_ACTIONS,
-                 no_attributes, ((version_number==3)?32:48),
-                 no_properties-2, ((version_number==3)?30:62),
-                 no_individual_properties - 64);
-
-            if (track_unused_routines)
-            {
-                uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
-                printf(
-"%6ld bytes of Z-code              %6ld unused bytes %s (%.1f%%)\n",
-                 (long int) df_total_size_before_stripping, (long int) diff,
-                 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
-                 100 * (float)diff / (float)df_total_size_before_stripping);
-            }
-
-            printf(
-"%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
-%6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
-%6ld instructions of Z-code       %6d sequence points\n\
-%6ld bytes readable memory used (maximum 65536)\n\
-%6ld bytes used in Z-machine      %6ld bytes free in Z-machine\n",
-                 (long int) total_chars_trans,
-                 (long int) total_bytes_trans,
-                 (total_chars_trans>total_bytes_trans)?0:1,
-                 (long int) rate,
-                 no_abbreviations, MAX_ABBREVS,
-                 no_routines,
-                 (long int) no_instructions, no_sequence_points,
-                 (long int) Write_Code_At,
-                 (long int) Out_Size,
-                 (long int)
-                      (((long int) (limit*1024L)) - ((long int) Out_Size)));
-
-        }
-    }
-
-    if (offsets_switch)
-    {
-        {   printf(
-"\nOffsets in %s:\n\
-%05lx Synonyms     %05lx Defaults     %05lx Objects    %05lx Properties\n\
-%05lx Variables    %05lx Parse table  %05lx Actions    %05lx Preactions\n\
-%05lx Adjectives   %05lx Dictionary   %05lx Code       %05lx Strings\n",
-            output_called,
-            (long int) abbrevs_at,
-            (long int) prop_defaults_at,
-            (long int) object_tree_at,
-            (long int) object_props_at,
-            (long int) globals_at,
-            (long int) grammar_table_at,
-            (long int) actions_at,
-            (long int) preactions_at,
-            (long int) adjectives_offset,
-            (long int) dictionary_at,
-            (long int) Write_Code_At,
-            (long int) Write_Strings_At);
-            if (module_switch)
-                printf("%05lx Linking data\n",(long int) link_table_at);
-        }
-    }
-
     if (debugfile_switch)
     {   begin_writing_debug_sections();
         write_debug_section("abbreviations", 64);
@@ -1100,130 +1003,125 @@ Out:   Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
         end_writing_debug_sections(Out_Size);
     }
 
-    if (memory_map_switch)
+    if (memory_map_setting)
     {
+        int32 addr;
         {
 printf("Dynamic +---------------------+   00000\n");
-printf("memory  |       header        |\n");
+printf("memory  |       header        |   %s\n",
+    show_percentage(0x40, Out_Size));
 printf("        +---------------------+   00040\n");
-printf("        |    abbreviations    |\n");
+printf("        |    abbreviations    |   %s\n",
+    show_percentage(abbrevs_at-0x40, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n", (long int) abbrevs_at);
-printf("        | abbreviations table |\n");
+printf("        | abbreviations table |   %s\n",
+    show_percentage(headerext_at-abbrevs_at, Out_Size));
 printf("        +---------------------+   %05lx\n", (long int) headerext_at);
-printf("        |  header extension   |\n");
+addr = (alphabet_modified ? charset_at : (zscii_defn_modified ? unicode_at : prop_defaults_at));
+printf("        |  header extension   |   %s\n",
+    show_percentage(addr-headerext_at, Out_Size));
             if (alphabet_modified)
             {
 printf("        + - - - - - - - - - - +   %05lx\n", (long int) charset_at);
-printf("        |   alphabets table   |\n");
+addr = (zscii_defn_modified ? unicode_at : prop_defaults_at);
+printf("        |   alphabets table   |   %s\n",
+    show_percentage(addr-charset_at, Out_Size));
             }
             if (zscii_defn_modified)
             {
 printf("        + - - - - - - - - - - +   %05lx\n", (long int) unicode_at);
-printf("        |    Unicode table    |\n");
+printf("        |    Unicode table    |   %s\n",
+    show_percentage(prop_defaults_at-unicode_at, Out_Size));
             }
 printf("        +---------------------+   %05lx\n",
                                           (long int) prop_defaults_at);
-printf("        |  property defaults  |\n");
+printf("        |  property defaults  |   %s\n",
+    show_percentage(object_tree_at-prop_defaults_at, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n", (long int) object_tree_at);
-printf("        |       objects       |\n");
+printf("        |       objects       |   %s\n",
+    show_percentage(object_props_at-object_tree_at, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) object_props_at);
 printf("        | object short names, |\n");
-printf("        | common prop values  |\n");
+printf("        | common prop values  |   %s\n",
+    show_percentage(class_numbers_offset-object_props_at, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) class_numbers_offset);
-printf("        | class numbers table |\n");
+printf("        | class numbers table |   %s\n",
+    show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) identifier_names_offset);
-printf("        | symbol names table  |\n");
+printf("        | symbol names table  |   %s\n",
+    show_percentage(individuals_offset-identifier_names_offset, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) individuals_offset);
-printf("        | indiv prop values   |\n");
+printf("        | indiv prop values   |   %s\n",
+    show_percentage(globals_at-individuals_offset, Out_Size));
 printf("        +---------------------+   %05lx\n", (long int) globals_at);
-printf("        |  global variables   |\n");
+printf("        |  global variables   |   %s\n",
+    show_percentage(480, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           ((long int) globals_at)+480L);
-printf("        |       arrays        |\n");
+printf("        |       arrays        |   %s\n",
+    show_percentage(grammar_table_at-(globals_at+480), Out_Size));
 printf("        +=====================+   %05lx\n",
                                           (long int) grammar_table_at);
-printf("Readable|    grammar table    |\n");
+printf("Readable|    grammar table    |   %s\n",
+    show_percentage(actions_at-grammar_table_at, Out_Size));
 printf("memory  + - - - - - - - - - - +   %05lx\n", (long int) actions_at);
-printf("        |       actions       |\n");
+printf("        |       actions       |   %s\n",
+    show_percentage(preactions_at-actions_at, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n", (long int) preactions_at);
-printf("        |   parsing routines  |\n");
+printf("        |   parsing routines  |   %s\n",
+    show_percentage(adjectives_offset-preactions_at, Out_Size));
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) adjectives_offset);
-printf("        |     adjectives      |\n");
+printf("        |     adjectives      |   %s\n",
+    show_percentage(dictionary_at-adjectives_offset, Out_Size));
 printf("        +---------------------+   %05lx\n", (long int) dictionary_at);
-printf("        |     dictionary      |\n");
+addr = (module_switch ? map_of_module : (static_array_area_size ? static_arrays_at : Write_Code_At));
+printf("        |     dictionary      |   %s\n",
+    show_percentage(addr-dictionary_at, Out_Size));
 if (module_switch)
 {
 printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) map_of_module);
-printf("        | map of module addrs |\n");
+addr = (static_array_area_size ? static_arrays_at : Write_Code_At);
+printf("        | map of module addrs |   %s\n",
+    show_percentage(addr-map_of_module, Out_Size));
 }
 if (static_array_area_size)
 {
 printf("        +---------------------+   %05lx\n", (long int) static_arrays_at);
-printf("        |    static arrays    |\n");
+printf("        |    static arrays    |   %s\n",
+    show_percentage(Write_Code_At-static_arrays_at, Out_Size));
 }
 printf("        +=====================+   %05lx\n", (long int) Write_Code_At);
-printf("Above   |       Z-code        |\n");
+printf("Above   |       Z-code        |   %s\n",
+    show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
 printf("readable+---------------------+   %05lx\n",
                                           (long int) Write_Strings_At);
-printf("memory  |       strings       |\n");
+addr = (module_switch ? link_table_at : Out_Size);
+printf("memory  |       strings       |   %s\n",
+    show_percentage(addr-Write_Strings_At, Out_Size));
 if (module_switch)
 {
 printf("        +=====================+   %05lx\n", (long int) link_table_at);
-printf("        | module linking data |\n");
+printf("        | module linking data |   %s\n",
+    show_percentage(Out_Size-link_table_at, Out_Size));
 }
 printf("        +---------------------+   %05lx\n", (long int) Out_Size);
         }
     }
-    if (percentages_switch)
-    {   printf("Approximate percentage breakdown of %s:\n",
-                output_called);
-        percentage("Z-code",             code_length,Out_Size);
-        if (module_switch)
-            percentage("Linking data",   link_data_size,Out_Size);
-        percentage("Static strings",     strings_length,Out_Size);
-        percentage("Dictionary",         Write_Code_At-dictionary_at,Out_Size);
-        percentage("Objects",            globals_at-prop_defaults_at,Out_Size);
-        percentage("Globals",            grammar_table_at-globals_at,Out_Size);
-        percentage("Parsing tables",   dictionary_at-grammar_table_at,Out_Size);
-        percentage("Header and synonyms", prop_defaults_at,Out_Size);
-        percentage("Total of save area", grammar_table_at,Out_Size);
-        percentage("Total of text",      total_bytes_trans,Out_Size);
-    }
-    if (frequencies_switch)
-    {
-        {   printf("How frequently abbreviations were used, and roughly\n");
-            printf("how many bytes they saved:  ('_' denotes spaces)\n");
-            for (i=0; i<no_abbreviations; i++)
-            {   char abbrev_string[MAX_ABBREV_LENGTH];
-                strcpy(abbrev_string,
-                    (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
-                for (j=0; abbrev_string[j]!=0; j++)
-                    if (abbrev_string[j]==' ') abbrev_string[j]='_';
-                printf("%10s %5d/%5d   ",abbrev_string,abbrev_freqs[i],
-                    2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
-                if ((i%3)==2) printf("\n");
-            }
-            if ((i%3)!=0) printf("\n");
-            if (no_abbreviations==0) printf("None were declared.\n");
-        }
-    }
 }
 
 static void construct_storyfile_g(void)
 {   uchar *p;
-    int32 i, j, k, l, mark, strings_length, limit;
+    int32 i, j, k, l, mark, strings_length;
     int32 globals_at, dictionary_at, actions_at, preactions_at,
           abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
-          grammar_table_at, charset_at, headerext_at,
-        unicode_at, arrays_at, static_arrays_at;
+          grammar_table_at, arrays_at, static_arrays_at;
     int32 threespaces, code_length;
-    char *output_called = (module_switch)?"module":"story file";
 
     ASSERT_GLULX();
 
@@ -1302,7 +1200,7 @@ static void construct_storyfile_g(void)
     }
 
     arrays_at = mark;
-    for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
+    for (i=0; i<dynamic_array_area_size; i++)
         p[mark++] = dynamic_array_area[i];
 
     /* -------------------------- Dynamic Strings -------------------------- */
@@ -1316,16 +1214,6 @@ static void construct_storyfile_g(void)
       mark += 4;
     }
 
-    /* ---------------- Various Things I'm Not Sure About ------------------ */
-    /* Actually, none of these are relevant to Glulx. */
-    headerext_at = mark;
-    charset_at = 0;
-    if (alphabet_modified)
-      charset_at = mark;
-    unicode_at = 0;
-    if (zscii_defn_modified)
-      unicode_at = mark;
-
     /*  -------------------- Objects and Properties ------------------------ */
 
     object_tree_at = mark;
@@ -1408,7 +1296,7 @@ static void construct_storyfile_g(void)
 
     prop_defaults_at = mark;
     for (i=0; i<no_properties; i++) {
-      k = prop_default_value[i];
+      k = commonprops[i].default_value;
       WriteInt32(p+mark, k);
       mark += 4;
     }
@@ -1418,7 +1306,7 @@ static void construct_storyfile_g(void)
     class_numbers_offset = mark;
     for (i=0; i<no_classes; i++) {
       j = Write_RAM_At + object_tree_at +
-        (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
+        (OBJECT_BYTE_LENGTH*(class_info[i].object_number-1));
       WriteInt32(p+mark, j);
       mark += 4;
     }
@@ -1577,7 +1465,6 @@ table format requested (producing number 2 format instead)");
     RAM_Size = mark;
 
     Out_Size = Write_RAM_At + RAM_Size;
-    limit=1024*1024;
 
     /*  --------------------------- Offsets -------------------------------- */
 
@@ -1606,7 +1493,7 @@ table format requested (producing number 2 format instead)");
 
         mark = actions_at + 4;
         for (i=0; i<no_actions; i++) {
-          j = action_byte_offset[i];
+          j = actions[i].byte_offset;
           if (OMIT_UNUSED_ROUTINES)
             j = df_stripped_address_for_address(j);
           j += code_offset;
@@ -1648,118 +1535,6 @@ table format requested (producing number 2 format instead)");
 
     /*  ---- From here on, it's all reportage: construction is finished ---- */
 
-    if (statistics_switch)
-    {   int32 k_long, rate; char *k_str="";
-        k_long=(Out_Size/1024);
-        if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
-        else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
-        if (strings_length == 0) rate = 0;
-        else rate=strings_length*1000/total_chars_trans;
-
-        {   printf("In:\
-%3d source code files            %6d syntactic lines\n\
-%6d textual lines              %8ld characters ",
-            total_input_files, no_syntax_lines,
-            total_source_line_count, (long int) total_chars_read);
-            if (character_set_unicode) printf("(UTF-8)\n");
-            else if (character_set_setting == 0) printf("(plain ASCII)\n");
-            else
-            {   printf("(ISO 8859-%d %s)\n", character_set_setting,
-                    name_of_iso_set(character_set_setting));
-            }
-
-            {char serialnum[8];
-            write_serial_number(serialnum);
-            printf("Allocated:\n\
-%6d symbols (maximum %4d)    %8ld bytes of memory\n\
-Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
-                 no_symbols, MAX_SYMBOLS,
-                 (long int) malloced_bytes,
-                 version_name(version_number),
-                 output_called,
-                 release_number,
-                 serialnum[0], serialnum[1], serialnum[2],
-                 serialnum[3], serialnum[4], serialnum[5],
-                 (long int) k_long, k_str);
-            } 
-
-            printf("\
-%6d classes (maximum %3d)        %6d objects (maximum %3d)\n\
-%6d global vars (maximum %3d)    %6d variable/array space (maximum %d)\n",
-                 no_classes, MAX_CLASSES,
-                 no_objects, MAX_OBJECTS,
-                 no_globals, MAX_GLOBAL_VARIABLES,
-                 dynamic_array_area_size, MAX_STATIC_DATA);
-
-            printf(
-"%6d verbs (maximum %3d)          %6d dictionary entries (maximum %d)\n\
-%6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
-%6d actions (maximum %3d)        %6d attributes (maximum %2d)\n\
-%6d common props (maximum %3d)   %6d individual props (unlimited)\n",
-                 no_Inform_verbs, MAX_VERBS,
-                 dict_entries, MAX_DICT_ENTRIES,
-                 no_grammar_lines, grammar_version_number,
-                 no_grammar_tokens,
-                 no_actions, MAX_ACTIONS,
-                 no_attributes, NUM_ATTR_BYTES*8,
-                 no_properties, INDIV_PROP_START,
-                 no_individual_properties - INDIV_PROP_START);
-
-            if (track_unused_routines)
-            {
-                uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
-                printf(
-"%6ld bytes of code                %6ld unused bytes %s (%.1f%%)\n",
-                 (long int) df_total_size_before_stripping, (long int) diff,
-                 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
-                 100 * (float)diff / (float)df_total_size_before_stripping);
-            }
-
-            printf(
-"%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
-%6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
-%6ld instructions of code         %6d sequence points\n\
-%6ld bytes writable memory used   %6ld bytes read-only memory used\n\
-%6ld bytes used in machine    %10ld bytes free in machine\n",
-                 (long int) total_chars_trans,
-                 (long int) strings_length,
-                 (total_chars_trans>strings_length)?0:1,
-                 (long int) rate,
-                 no_abbreviations, MAX_ABBREVS,
-                 no_routines,
-                 (long int) no_instructions, no_sequence_points,
-                 (long int) (Out_Size - Write_RAM_At),
-                 (long int) Write_RAM_At,
-                 (long int) Out_Size,
-                 (long int)
-                      (((long int) (limit*1024L)) - ((long int) Out_Size)));
-
-        }
-    }
-
-    if (offsets_switch)
-    {
-        {   printf(
-"\nOffsets in %s:\n\
-%05lx Synonyms     %05lx Defaults     %05lx Objects    %05lx Properties\n\
-%05lx Variables    %05lx Parse table  %05lx Actions    %05lx Preactions\n\
-%05lx Adjectives   %05lx Dictionary   %05lx Code       %05lx Strings\n",
-            output_called,
-            (long int) abbrevs_at,
-            (long int) prop_defaults_at,
-            (long int) object_tree_at,
-            (long int) object_props_at,
-            (long int) globals_at,
-            (long int) grammar_table_at,
-            (long int) actions_at,
-            (long int) preactions_at,
-            (long int) adjectives_offset,
-            (long int) dictionary_at,
-            (long int) Write_Code_At,
-            (long int) Write_Strings_At);
-        }
-    }
-
     if (debugfile_switch)
     {   begin_writing_debug_sections();
         write_debug_section("memory layout id", GLULX_HEADER_SIZE);
@@ -1797,73 +1572,79 @@ Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
         end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
     }
 
-    if (memory_map_switch)
+    if (memory_map_setting)
     {
-
+        int32 addr;
         {
 printf("        +---------------------+   000000\n");
-printf("Read-   |       header        |\n");
+printf("Read-   |       header        |   %s\n",
+    show_percentage(GLULX_HEADER_SIZE, Out_Size));
 printf(" only   +=====================+   %06lx\n", (long int) GLULX_HEADER_SIZE);
-printf("memory  |  memory layout id   |\n");
+printf("memory  |  memory layout id   |   %s\n",
+    show_percentage(Write_Code_At-GLULX_HEADER_SIZE, Out_Size));
 printf("        +---------------------+   %06lx\n", (long int) Write_Code_At);
-printf("        |        code         |\n");
+printf("        |        code         |   %s\n",
+    show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
 printf("        +---------------------+   %06lx\n",
   (long int) Write_Strings_At);
-printf("        | string decode table |\n");
+printf("        | string decode table |   %s\n",
+    show_percentage(compression_table_size, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) Write_Strings_At + compression_table_size);
-printf("        |       strings       |\n");
+addr = (static_array_area_size ? static_arrays_at : Write_RAM_At+globals_at);
+printf("        |       strings       |   %s\n",
+    show_percentage(addr-(Write_Strings_At + compression_table_size), Out_Size));
             if (static_array_area_size)
             {
 printf("        +---------------------+   %06lx\n", 
   (long int) (static_arrays_at));
-printf("        |    static arrays    |\n");
+printf("        |    static arrays    |   %s\n",
+    show_percentage(Write_RAM_At+globals_at-static_arrays_at, Out_Size));
             }
 printf("        +=====================+   %06lx\n", 
   (long int) (Write_RAM_At+globals_at));
-printf("Dynamic |  global variables   |\n");
+printf("Dynamic |  global variables   |   %s\n",
+    show_percentage(arrays_at-globals_at, Out_Size));
 printf("memory  + - - - - - - - - - - +   %06lx\n",
   (long int) (Write_RAM_At+arrays_at));
-printf("        |       arrays        |\n");
+printf("        |       arrays        |   %s\n",
+    show_percentage(abbrevs_at-arrays_at, Out_Size));
 printf("        +---------------------+   %06lx\n",
   (long int) (Write_RAM_At+abbrevs_at));
-printf("        | printing variables  |\n");
-            if (alphabet_modified)
-            {
-printf("        + - - - - - - - - - - +   %06lx\n", 
-  (long int) (Write_RAM_At+charset_at));
-printf("        |   alphabets table   |\n");
-            }
-            if (zscii_defn_modified)
-            {
-printf("        + - - - - - - - - - - +   %06lx\n", 
-  (long int) (Write_RAM_At+unicode_at));
-printf("        |    Unicode table    |\n");
-            }
+printf("        | printing variables  |   %s\n",
+    show_percentage(object_tree_at-abbrevs_at, Out_Size));
 printf("        +---------------------+   %06lx\n", 
   (long int) (Write_RAM_At+object_tree_at));
-printf("        |       objects       |\n");
+printf("        |       objects       |   %s\n",
+    show_percentage(object_props_at-object_tree_at, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) (Write_RAM_At+object_props_at));
-printf("        |   property values   |\n");
+printf("        |   property values   |   %s\n",
+    show_percentage(prop_defaults_at-object_props_at, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) (Write_RAM_At+prop_defaults_at));
-printf("        |  property defaults  |\n");
+printf("        |  property defaults  |   %s\n",
+    show_percentage(class_numbers_offset-prop_defaults_at, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) (Write_RAM_At+class_numbers_offset));
-printf("        | class numbers table |\n");
+printf("        | class numbers table |   %s\n",
+    show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) (Write_RAM_At+identifier_names_offset));
-printf("        |   id names table    |\n");
+printf("        |   id names table    |   %s\n",
+    show_percentage(grammar_table_at-identifier_names_offset, Out_Size));
 printf("        +---------------------+   %06lx\n",
   (long int) (Write_RAM_At+grammar_table_at));
-printf("        |    grammar table    |\n");
+printf("        |    grammar table    |   %s\n",
+    show_percentage(actions_at-grammar_table_at, Out_Size));
 printf("        + - - - - - - - - - - +   %06lx\n", 
   (long int) (Write_RAM_At+actions_at));
-printf("        |       actions       |\n");
+printf("        |       actions       |   %s\n",
+    show_percentage(dictionary_offset-(Write_RAM_At+actions_at), Out_Size));
 printf("        +---------------------+   %06lx\n", 
   (long int) dictionary_offset);
-printf("        |     dictionary      |\n");
+printf("        |     dictionary      |   %s\n",
+    show_percentage(Out_Size-dictionary_offset, Out_Size));
             if (MEMORY_MAP_EXTENSION == 0)
             {
 printf("        +---------------------+   %06lx\n", (long int) Out_Size);
@@ -1871,56 +1652,276 @@ printf("        +---------------------+   %06lx\n", (long int) Out_Size);
             else
             {
 printf("        +=====================+   %06lx\n", (long int) Out_Size);
-printf("Runtime |       (empty)       |\n");
+printf("Runtime |       (empty)       |\n");   /* no percentage */
 printf("  extn  +---------------------+   %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
             }
 
         }
 
     }
+}
 
+static void display_frequencies()
+{
+    int i, j;
+    
+    printf("How frequently abbreviations were used, and roughly\n");
+    printf("how many bytes they saved:  ('_' denotes spaces)\n");
+    
+    for (i=0; i<no_abbreviations; i++) {
+        int32 saving;
+        if (!glulx_mode)
+            saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
+        else
+            saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
+        
+        char abbrev_string[MAX_ABBREV_LENGTH];
+        strcpy(abbrev_string,
+               (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
+        for (j=0; abbrev_string[j]!=0; j++)
+            if (abbrev_string[j]==' ') abbrev_string[j]='_';
+        
+        printf("%10s %5d/%5d   ",abbrev_string,abbreviations[i].freq, saving);
+        
+        if ((i%3)==2) printf("\n");
+    }
+    if ((i%3)!=0) printf("\n");
+    
+    if (no_abbreviations==0) printf("None were declared.\n");
+}
 
-    if (percentages_switch)
-    {   printf("Approximate percentage breakdown of %s:\n",
-                output_called);
-        percentage("Code",               code_length,Out_Size);
-        if (module_switch)
-            percentage("Linking data",   link_data_size,Out_Size);
-        percentage("Static strings",     strings_length,Out_Size);
-        percentage("Dictionary",         Write_Code_At-dictionary_at,Out_Size);
-        percentage("Objects",            globals_at-prop_defaults_at,Out_Size);
-        percentage("Globals",            grammar_table_at-globals_at,Out_Size);
-        percentage("Parsing tables",   dictionary_at-grammar_table_at,Out_Size);
-        percentage("Header and synonyms", prop_defaults_at,Out_Size);
-        percentage("Total of save area", grammar_table_at,Out_Size);
-        percentage("Total of text",      strings_length,Out_Size);
-    }
-    if (frequencies_switch)
-    {
-        {   printf("How frequently abbreviations were used, and roughly\n");
-            printf("how many bytes they saved:  ('_' denotes spaces)\n");
-            for (i=0; i<no_abbreviations; i++)
-            {   char abbrev_string[MAX_ABBREV_LENGTH];
-                strcpy(abbrev_string,
-                    (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
-                for (j=0; abbrev_string[j]!=0; j++)
-                    if (abbrev_string[j]==' ') abbrev_string[j]='_';
-                printf("%10s %5d/%5d   ",abbrev_string,abbrev_freqs[i],
-                    2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
-                if ((i%3)==2) printf("\n");
+static void display_statistics_z()
+{
+    int32 k_long, rate;
+    char *k_str = "";
+    uchar *p = (uchar *) zmachine_paged_memory;
+    char *output_called = (module_switch)?"module":"story file";
+    int limit = 0;
+
+    /* Yeah, we're repeating this calculation from construct_storyfile_z() */
+    switch(version_number)
+    {   case 3: limit = 128; break;
+        case 4:
+        case 5: limit = 256; break;
+        case 6:
+        case 7:
+        case 8: limit = 512; break;
+    }
+
+    k_long=(Out_Size/1024);
+    if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
+    else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
+    if (total_bytes_trans == 0) rate = 0;
+    else rate=total_bytes_trans*1000/total_chars_trans;
+    
+    {   printf("In:\
+%3d source code files            %6d syntactic lines\n\
+%6d textual lines              %8ld characters ",
+               total_input_files, no_syntax_lines,
+               total_source_line_count, (long int) total_chars_read);
+        if (character_set_unicode) printf("(UTF-8)\n");
+        else if (character_set_setting == 0) printf("(plain ASCII)\n");
+        else
+            {   printf("(ISO 8859-%d %s)\n", character_set_setting,
+                       name_of_iso_set(character_set_setting));
             }
-            if ((i%3)!=0) printf("\n");
-            if (no_abbreviations==0) printf("None were declared.\n");
-        }
+
+        printf("Allocated:\n\
+%6d symbols                    %8ld bytes of memory\n\
+Out:   Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
+               no_symbols,
+               (long int) malloced_bytes,
+               version_number,
+               version_name(version_number),
+               output_called,
+               release_number, p[18], p[19], p[20], p[21], p[22], p[23],
+               (long int) k_long, k_str);
+
+        printf("\
+%6d classes                      %6d objects\n\
+%6d global vars (maximum 233)    %6d variable/array space\n",
+               no_classes,
+               no_objects,
+               no_globals,
+               dynamic_array_area_size);
+
+        printf(
+               "%6d verbs                        %6d dictionary entries\n\
+%6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
+%6d actions                      %6d attributes (maximum %2d)\n\
+%6d common props (maximum %2d)    %6d individual props (unlimited)\n",
+               no_Inform_verbs,
+               dict_entries,
+               no_grammar_lines, grammar_version_number,
+               no_grammar_tokens,
+               no_actions,
+               no_attributes, ((version_number==3)?32:48),
+               no_properties-3, ((version_number==3)?29:61),
+               no_individual_properties - 64);
+
+        if (track_unused_routines)
+            {
+                uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
+                printf(
+                       "%6ld bytes of Z-code              %6ld unused bytes %s (%.1f%%)\n",
+                       (long int) df_total_size_before_stripping, (long int) diff,
+                       (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
+                       100 * (float)diff / (float)df_total_size_before_stripping);
+            }
+
+        printf(
+               "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
+%6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
+%6ld instructions of Z-code       %6d sequence points\n\
+%6ld bytes readable memory used (maximum 65536)\n\
+%6ld bytes used in Z-machine      %6ld bytes free in Z-machine\n",
+               (long int) total_chars_trans,
+               (long int) total_bytes_trans,
+               (total_chars_trans>total_bytes_trans)?0:1,
+               (long int) rate,
+               no_abbreviations, MAX_ABBREVS,
+               no_routines,
+               (long int) no_instructions, no_sequence_points,
+               (long int) Write_Code_At,
+               (long int) Out_Size,
+               (long int)
+               (((long int) (limit*1024L)) - ((long int) Out_Size)));
+
+    }
+}
+
+static void display_statistics_g()
+{
+    int32 k_long, rate;
+    char *k_str = "";
+    int32 limit = 1024*1024;
+    int32 strings_length = compression_table_size + compression_string_size;
+    char *output_called = (module_switch)?"module":"story file";
+    
+    k_long=(Out_Size/1024);
+    if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
+    else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
+    
+    if (strings_length == 0) rate = 0;
+    else rate=strings_length*1000/total_chars_trans;
+
+    {   printf("In:\
+%3d source code files            %6d syntactic lines\n\
+%6d textual lines              %8ld characters ",
+               total_input_files, no_syntax_lines,
+               total_source_line_count, (long int) total_chars_read);
+        if (character_set_unicode) printf("(UTF-8)\n");
+        else if (character_set_setting == 0) printf("(plain ASCII)\n");
+        else
+            {   printf("(ISO 8859-%d %s)\n", character_set_setting,
+                       name_of_iso_set(character_set_setting));
+            }
+
+        {char serialnum[8];
+            write_serial_number(serialnum);
+            printf("Allocated:\n\
+%6d symbols                    %8ld bytes of memory\n\
+Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
+                   no_symbols,
+                   (long int) malloced_bytes,
+                   version_name(version_number),
+                   output_called,
+                   release_number,
+                   serialnum[0], serialnum[1], serialnum[2],
+                   serialnum[3], serialnum[4], serialnum[5],
+                   (long int) k_long, k_str);
+        } 
+
+        printf("\
+%6d classes                      %6d objects\n\
+%6d global vars                  %6d variable/array space\n",
+               no_classes,
+               no_objects,
+               no_globals,
+               dynamic_array_area_size);
+
+        printf(
+               "%6d verbs                        %6d dictionary entries\n\
+%6d grammar lines (version %d)    %6d grammar tokens (unlimited)\n\
+%6d actions                      %6d attributes (maximum %2d)\n\
+%6d common props (maximum %3d)   %6d individual props (unlimited)\n",
+               no_Inform_verbs,
+               dict_entries,
+               no_grammar_lines, grammar_version_number,
+               no_grammar_tokens,
+               no_actions,
+               no_attributes, NUM_ATTR_BYTES*8,
+               no_properties-3, INDIV_PROP_START-3,
+               no_individual_properties - INDIV_PROP_START);
+
+        if (track_unused_routines)
+            {
+                uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
+                printf(
+                       "%6ld bytes of code                %6ld unused bytes %s (%.1f%%)\n",
+                       (long int) df_total_size_before_stripping, (long int) diff,
+                       (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
+                       100 * (float)diff / (float)df_total_size_before_stripping);
+            }
+
+        printf(
+               "%6ld characters used in text      %6ld bytes compressed (rate %d.%3ld)\n\
+%6d abbreviations (maximum %d)   %6d routines (unlimited)\n\
+%6ld instructions of code         %6d sequence points\n\
+%6ld bytes writable memory used   %6ld bytes read-only memory used\n\
+%6ld bytes used in machine    %10ld bytes free in machine\n",
+               (long int) total_chars_trans,
+               (long int) strings_length,
+               (total_chars_trans>strings_length)?0:1,
+               (long int) rate,
+               no_abbreviations, MAX_ABBREVS,
+               no_routines,
+               (long int) no_instructions, no_sequence_points,
+               (long int) (Out_Size - Write_RAM_At),
+               (long int) Write_RAM_At,
+               (long int) Out_Size,
+               (long int)
+               (((long int) (limit*1024L)) - ((long int) Out_Size)));
+
     }
 }
 
+
 extern void construct_storyfile(void)
 {
-  if (!glulx_mode)
-    construct_storyfile_z();
-  else
-    construct_storyfile_g();
+    if (!glulx_mode)
+        construct_storyfile_z();
+    else
+        construct_storyfile_g();
+
+    /* Display all the trace/stats info that came out of compilation.
+
+       (Except for the memory map, which uses a bunch of local variables
+       from construct_storyfile_z/g(), so it's easier to do that inside
+       that function.)
+    */
+    
+    if (frequencies_setting)
+        display_frequencies();
+
+    if (list_symbols_setting)
+        list_symbols(list_symbols_setting);
+    
+    if (list_dict_setting)
+        show_dictionary(list_dict_setting);
+    
+    if (list_verbs_setting)
+        list_verb_table();
+
+    if (list_objects_setting)
+        list_object_tree();
+    
+    if (statistics_switch) {
+        if (!glulx_mode)
+            display_statistics_z();
+        else
+            display_statistics_g();
+    }
 }
 
 /* ========================================================================= */