Update to Inform v6.42
[inform.git] / src / tables.c
index 389eb4bca1506a9d4aa99fe161d461717442ea30..cea36903917e88d891b400be50c77f0e1c0d6f18 100644 (file)
@@ -1,10 +1,10 @@
 /* ------------------------------------------------------------------------- */
-/*   "tables" :  Constructs the story file or module (the output) up to the  */
-/*               end of dynamic memory, gluing together all the required     */
+/*   "tables" :  Constructs the story file (the output) up to the end        */
+/*               of dynamic memory, gluing together all the required         */
 /*               tables.                                                     */
 /*                                                                           */
-/*   Part of Inform 6.40                                                     */
-/*   copyright (c) Graham Nelson 1993 - 2022                                 */
+/*   Part of Inform 6.42                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2024                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
@@ -99,7 +99,7 @@ int flags2_requirements[16];           /* An array of which bits in Flags 2 of
                                           Values are 0 or 1.                 */
 
 /* ------------------------------------------------------------------------- */
-/*   Construct story/module file (up to code area start).                    */
+/*   Construct story file (up to code area start).                           */
 /*                                                                           */
 /*   (To understand what follows, you really need to look at the run-time    */
 /*   system's specification, the Z-Machine Standards document.)              */
@@ -112,17 +112,23 @@ extern void write_serial_number(char *buffer)
         the ability to work out today's date                                 */
 
     time_t tt;  tt=time(0);
-    if (serial_code_given_in_program)
+    if (serial_code_given_in_program) {
         strcpy(buffer, serial_code_buffer);
-    else
+    }
+    else {
 #ifdef TIME_UNAVAILABLE
         sprintf(buffer,"970000");
 #else
-        strftime(buffer,10,"%y%m%d",localtime(&tt));
+        /* Write a six-digit date, null-terminated. Fall back to "970000"
+           if that fails. */
+        int len = strftime(buffer,7,"%y%m%d",localtime(&tt));
+        if (len != 6)
+            sprintf(buffer,"970000");
 #endif
+    }
 }
 
-static char percentage_buffer[32];
+static char percentage_buffer[64];
 
 static char *show_percentage(int32 x, int32 total)
 {
@@ -132,9 +138,12 @@ static char *show_percentage(int32 x, int32 total)
     else if (x == 0) {
         sprintf(percentage_buffer, "  ( --- )");
     }
-    else {
+    else if (memory_map_setting < 3) {
         sprintf(percentage_buffer, "  (%.1f %%)", (float)x * 100.0 / (float)total);
     }
+    else {
+        sprintf(percentage_buffer, "  (%.1f %%, %d bytes)", (float)x * 100.0 / (float)total, x);
+    }
     return percentage_buffer;
 }
 
@@ -146,6 +155,7 @@ static char *version_name(int v)
         case 4: return "Plus";
         case 5: return "Advanced";
         case 6: return "Graphical";
+        case 7: return "Extended Alternate";
         case 8: return "Extended";
     }
     return "experimental format";
@@ -181,7 +191,7 @@ static int32 rough_size_of_paged_memory_z(void)
     total += 2*((version_number==3)?31:63)        /* property default values */
             + no_objects*((version_number==3)?9:14)     /* object tree table */
             + properties_table_size            /* property values of objects */
-            + (no_classes+1)*(module_switch?4:2)
+            + (no_classes+1)*2
                                                /* class object numbers table */
             + no_symbols*2                       /* names of numerous things */
             + individuals_length                 /* tables of prop variables */
@@ -201,7 +211,7 @@ static int32 rough_size_of_paged_memory_z(void)
               + 2*no_grammar_token_routines;     /* general parsing routines */
 
     total += (dictionary_top)                            /* dictionary size */
-             + ((module_switch)?30:0);                        /* module map */
+             + (0);                                           /* module map */
 
     total += static_array_area_size;                       /* static arrays */
 
@@ -258,36 +268,39 @@ static void construct_storyfile_z(void)
 {   uchar *p;
     int32 i, j, k, l, mark, objs, strings_length, code_length,
           limit=0, excess=0, extend_offset=0, headerext_length=0;
-    int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
+    int32 globals_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
           abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
-          map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
+          grammar_table_at=0, charset_at=0, headerext_at=0,
           terminating_chars_at=0, unicode_at=0, id_names_length=0,
           static_arrays_at=0;
+    int32 rough_size;
     int skip_backpatching = FALSE;
-    char *output_called = (module_switch)?"module":"story file";
+    char *output_called = "story file";
 
     ASSERT_ZCODE();
 
-    individual_name_strings =
-        my_calloc(sizeof(int32), no_individual_properties,
-            "identifier name strings");
-    action_name_strings =
-        my_calloc(sizeof(int32), no_actions + no_fake_actions,
-            "action name strings");
-    attribute_name_strings =
-        my_calloc(sizeof(int32), 48,
-            "attribute name strings");
-    array_name_strings =
-        my_calloc(sizeof(int32),
-            no_symbols,
-            "array name strings");
+    if (!OMIT_SYMBOL_TABLE) {
+        individual_name_strings =
+            my_calloc(sizeof(int32), no_individual_properties,
+                      "identifier name strings");
+        action_name_strings =
+            my_calloc(sizeof(int32), no_actions + no_fake_actions,
+                      "action name strings");
+        attribute_name_strings =
+            my_calloc(sizeof(int32), 48,
+                      "attribute name strings");
+        array_name_strings =
+            my_calloc(sizeof(int32),
+                      no_symbols,
+                      "array name strings");
 
-    write_the_identifier_names();
+        write_the_identifier_names();
+    }
 
     /*  We now know how large the buffer to hold our construction has to be  */
 
-    zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
-        "output buffer");
+    rough_size = rough_size_of_paged_memory_z();
+    zmachine_paged_memory = my_malloc(rough_size, "output buffer");
 
     /*  Foolish code to make this routine compile on all ANSI compilers      */
 
@@ -297,7 +310,8 @@ static void construct_storyfile_z(void)
         points its value will be recorded for milestones like
         "dictionary table start".  It begins at 0x40, just after the header  */
 
-    mark = 0x40;
+    for (mark=0; mark<0x40; mark++)
+        p[mark] = 0x0;
 
     /*  ----------------- Low Strings and Abbreviations -------------------- */
 
@@ -423,14 +437,8 @@ static void construct_storyfile_z(void)
             p[objs+9]=(objectsz[i].next)%256;
             p[objs+10]=(objectsz[i].child)/256;
             p[objs+11]=(objectsz[i].child)%256;
-            if (!module_switch)
-            {   p[objs+12]=mark/256;
-                p[objs+13]=mark%256;
-            }
-            else
-            {   p[objs+12]=objectsz[i].propsize/256;
-                p[objs+13]=objectsz[i].propsize%256;
-            }
+            p[objs+12]=mark/256;
+            p[objs+13]=mark%256;
             objs+=14;
         }
         mark+=objectsz[i].propsize;
@@ -442,10 +450,6 @@ static void construct_storyfile_z(void)
     for (i=0; i<no_classes; i++)
     {   p[mark++] = class_info[i].object_number/256;
         p[mark++] = class_info[i].object_number%256;
-        if (module_switch)
-        {   p[mark++] = class_info[i].begins_at/256;
-            p[mark++] = class_info[i].begins_at%256;
-        }
     }
     p[mark++] = 0;
     p[mark++] = 0;
@@ -454,7 +458,7 @@ static void construct_storyfile_z(void)
 
     identifier_names_offset = mark;
 
-    if (!module_switch)
+    if (!OMIT_SYMBOL_TABLE)
     {   p[mark++] = no_individual_properties/256;
         p[mark++] = no_individual_properties%256;
         for (i=1; i<no_individual_properties; i++)
@@ -488,6 +492,17 @@ static void construct_storyfile_z(void)
 
         id_names_length = (mark - identifier_names_offset)/2;
     }
+    else {
+        attribute_names_offset = mark;
+        action_names_offset = mark;
+        fake_action_names_offset = mark;
+        array_names_offset = mark;
+        global_names_offset = mark;
+        routine_names_offset = mark;
+        constant_names_offset = mark;
+        id_names_length = 0;
+    }
+    
     routine_flags_array_offset = mark;
 
     if (define_INFIX_switch)
@@ -540,6 +555,12 @@ table format requested (producing number 2 format instead)");
     for (i=0; i<no_Inform_verbs; i++)
     {   p[grammar_table_at + i*2] = (mark/256);
         p[grammar_table_at + i*2 + 1] = (mark%256);
+        if (!Inform_verbs[i].used) {
+            /* This verb was marked unused at locate_dead_grammar_lines()
+               time. Omit the grammar lines. */
+            p[mark++] = 0;
+            continue;
+        }
         p[mark++] = Inform_verbs[i].lines;
         for (j=0; j<Inform_verbs[i].lines; j++)
         {   k = Inform_verbs[i].l[j];
@@ -629,10 +650,7 @@ table format requested (producing number 2 format instead)");
 
     /*  ------------------------- Module Map ------------------------------- */
 
-    if (module_switch)
-    {   map_of_module = mark;                             /* Filled in below */
-        mark += 30;
-    }
+    /* (no longer used) */
 
     /*  ------------------------ Static Arrays ----------------------------- */
 
@@ -663,9 +681,12 @@ or less.");
     }
 
     /*  -------------------------- Code Area ------------------------------- */
-    /*  (From this point on we don't write any more into the "p" buffer.)    */
+    /*  (From this point on we don't write any higher into the "p" buffer.)  */
     /*  -------------------------------------------------------------------- */
 
+    if (mark > rough_size)
+        compiler_error("Paged size exceeds rough estimate.");
+
     Write_Code_At = mark;
     if (!OMIT_UNUSED_ROUTINES) {
         code_length = zmachine_pc;
@@ -680,10 +701,8 @@ or less.");
     /*  ------------------ Another synchronising gap ----------------------- */
 
     if (oddeven_packing_switch)
-    {   if (module_switch)
-             while ((mark%(scale_factor*2)) != 0) mark++;
-        else
-             while ((mark%(scale_factor*2)) != scale_factor) mark++;
+    {   
+        while ((mark%(scale_factor*2)) != scale_factor) mark++;
     }
     else
         while ((mark%scale_factor) != 0) mark++;
@@ -696,11 +715,7 @@ or less.");
 
     /*  --------------------- Module Linking Data -------------------------- */
 
-    if (module_switch)
-    {   link_table_at = mark; mark += link_data_size;
-        mark += zcode_backpatch_size;
-        mark += zmachine_backpatch_size;
-    }
+    /* (no longer used) */
 
     /*  --------------------- Is the file too big? ------------------------- */
 
@@ -715,16 +730,11 @@ or less.");
         case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
     }
 
-    if (module_switch)
-    {   excess = Out_Size-((int32) 0x10000L); limit=64;
-    }
-
     if (excess > 0)
-    {   char memory_full_error[80];
-        sprintf(memory_full_error,
+    {
+        fatalerror_fmt(
             "The %s exceeds version-%d limit (%dK) by %d bytes",
              output_called, version_number, limit, excess);
-        fatalerror(memory_full_error);
     }
 
     /*  --------------------------- Offsets -------------------------------- */
@@ -758,26 +768,24 @@ or less.");
          */
         excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
         if (excess > 0)
-        {   char code_full_error[80];
-            sprintf(code_full_error,
+        {
+            fatalerror_fmt(
                 "The code area limit has been exceeded by %d bytes",
                  excess);
-            fatalerror(code_full_error);
         }
 
         excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
         if (excess > 0)
-        {   char strings_full_error[140];
+        {
             if (oddeven_packing_switch)
-                sprintf(strings_full_error,
+                fatalerror_fmt(
                     "The strings area limit has been exceeded by %d bytes",
                      excess);
             else
-                sprintf(strings_full_error,
+                fatalerror_fmt(
                     "The code+strings area limit has been exceeded by %d bytes. \
  Try running Inform again with -B on the command line.",
                      excess);
-            fatalerror(strings_full_error);
         }
     }
     else
@@ -865,61 +873,21 @@ or less.");
 
     /*  ----------------- The Header: Extras for modules ------------------- */
 
-    if (module_switch)
-    {   p[0]=p[0]+64;
-        p[1]=MODULE_VERSION_NUMBER;
-        p[6]=map_of_module/256;
-        p[7]=map_of_module%256;
-
-        mark = map_of_module;                       /*  Module map format:   */
-
-        p[mark++]=object_tree_at/256;               /*  0: Object tree addr  */
-        p[mark++]=object_tree_at%256;
-        p[mark++]=object_props_at/256;              /*  2: Prop values addr  */
-        p[mark++]=object_props_at%256;
-        p[mark++]=(Write_Strings_At/scale_factor)/256;  /*  4: Static strs   */
-        p[mark++]=(Write_Strings_At/scale_factor)%256;
-        p[mark++]=class_numbers_offset/256;         /*  6: Class nos addr    */
-        p[mark++]=class_numbers_offset%256;
-        p[mark++]=individuals_offset/256;           /*  8: Indiv prop values */
-        p[mark++]=individuals_offset%256;
-        p[mark++]=individuals_length/256;           /*  10: Length of table  */
-        p[mark++]=individuals_length%256;
-        p[mark++]=no_symbols/256;                   /*  12: No of symbols    */
-        p[mark++]=no_symbols%256;
-        p[mark++]=no_individual_properties/256;     /*  14: Max property no  */
-        p[mark++]=no_individual_properties%256;
-        p[mark++]=no_objects/256;                   /*  16: No of objects    */
-        p[mark++]=no_objects%256;
-        i = link_table_at;
-        p[mark++]=i/256;                            /*  18: Import/exports   */
-        p[mark++]=i%256;
-        p[mark++]=link_data_size/256;               /*  20: Size of          */
-        p[mark++]=link_data_size%256;
-        i += link_data_size;
-        p[mark++]=i/256;                            /*  22: Code backpatch   */
-        p[mark++]=i%256;
-        p[mark++]=zcode_backpatch_size/256;         /*  24: Size of          */
-        p[mark++]=zcode_backpatch_size%256;
-        i += zcode_backpatch_size;
-        p[mark++]=i/256;                            /*  26: Image backpatch  */
-        p[mark++]=i%256;
-        p[mark++]=zmachine_backpatch_size/256;      /*  28: Size of          */
-        p[mark++]=zmachine_backpatch_size%256;
-
-        /*  Further space in this table is reserved for future use  */
-    }
+    /* (no longer used) */
 
     /*  ---- Backpatch the Z-machine, now that all information is in ------- */
 
-    if (!module_switch && !skip_backpatching)
+    if (!skip_backpatching)
     {   backpatch_zmachine_image_z();
-        for (i=1; i<id_names_length; i++)
-        {   int32 v = 256*p[identifier_names_offset + i*2]
-                      + p[identifier_names_offset + i*2 + 1];
-            if (v!=0) v += strings_offset/scale_factor;
-            p[identifier_names_offset + i*2] = v/256;
-            p[identifier_names_offset + i*2 + 1] = v%256;
+
+        if (!OMIT_SYMBOL_TABLE) {
+            for (i=1; i<id_names_length; i++)
+            {   int32 v = 256*p[identifier_names_offset + i*2]
+                    + p[identifier_names_offset + i*2 + 1];
+                if (v!=0) v += strings_offset/scale_factor;
+                p[identifier_names_offset + i*2] = v/256;
+                p[identifier_names_offset + i*2 + 1] = v%256;
+            }
         }
 
         mark = actions_at;
@@ -1079,17 +1047,9 @@ printf("        + - - - - - - - - - - +   %05lx\n",
 printf("        |     adjectives      |   %s\n",
     show_percentage(dictionary_at-adjectives_offset, Out_Size));
 printf("        +---------------------+   %05lx\n", (long int) dictionary_at);
-addr = (module_switch ? map_of_module : (static_array_area_size ? static_arrays_at : Write_Code_At));
+addr = (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);
-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);
@@ -1101,15 +1061,9 @@ 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);
-addr = (module_switch ? link_table_at : Out_Size);
+addr = (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 |   %s\n",
-    show_percentage(Out_Size-link_table_at, Out_Size));
-}
 printf("        +---------------------+   %05lx\n", (long int) Out_Size);
         }
     }
@@ -1122,6 +1076,7 @@ static void construct_storyfile_g(void)
           abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
           grammar_table_at, arrays_at, static_arrays_at;
     int32 threespaces, code_length;
+    int32 rough_size;
 
     ASSERT_GLULX();
 
@@ -1146,8 +1101,8 @@ static void construct_storyfile_g(void)
 
     /*  We now know how large the buffer to hold our construction has to be  */
 
-    zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
-        "output buffer");
+    rough_size = rough_size_of_paged_memory_g();
+    zmachine_paged_memory = my_malloc(rough_size, "output buffer");
 
     /*  Foolish code to make this routine compile on all ANSI compilers      */
 
@@ -1326,63 +1281,71 @@ static void construct_storyfile_g(void)
        number of actions
     */
 
-    identifier_names_offset = mark;
-    mark += 32; /* eight pairs of values, to be filled in. */
-
-    WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
-    WriteInt32(p+identifier_names_offset+4, no_properties);
-    for (i=0; i<no_properties; i++) {
-      j = individual_name_strings[i];
-      if (j)
-        j = Write_Strings_At + compressed_offsets[j-1];
-      WriteInt32(p+mark, j);
-      mark += 4;
-    }
-
-    WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
-    WriteInt32(p+identifier_names_offset+12, 
-      no_individual_properties-INDIV_PROP_START);
-    for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
-      j = individual_name_strings[i];
-      if (j)
-        j = Write_Strings_At + compressed_offsets[j-1];
-      WriteInt32(p+mark, j);
-      mark += 4;
-    }
-
-    WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
-    WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
-    for (i=0; i<NUM_ATTR_BYTES*8; i++) {
-      j = attribute_name_strings[i];
-      if (j)
-        j = Write_Strings_At + compressed_offsets[j-1];
-      WriteInt32(p+mark, j);
+    if (!OMIT_SYMBOL_TABLE) {
+      identifier_names_offset = mark;
+      mark += 32; /* eight pairs of values, to be filled in. */
+  
+      WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
+      WriteInt32(p+identifier_names_offset+4, no_properties);
+      for (i=0; i<no_properties; i++) {
+        j = individual_name_strings[i];
+        if (j)
+          j = Write_Strings_At + compressed_offsets[j-1];
+        WriteInt32(p+mark, j);
+        mark += 4;
+      }
+  
+      WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
+      WriteInt32(p+identifier_names_offset+12, 
+        no_individual_properties-INDIV_PROP_START);
+      for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
+        j = individual_name_strings[i];
+        if (j)
+          j = Write_Strings_At + compressed_offsets[j-1];
+        WriteInt32(p+mark, j);
+        mark += 4;
+      }
+  
+      WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
+      WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
+      for (i=0; i<NUM_ATTR_BYTES*8; i++) {
+        j = attribute_name_strings[i];
+        if (j)
+          j = Write_Strings_At + compressed_offsets[j-1];
+        WriteInt32(p+mark, j);
+        mark += 4;
+      }
+  
+      WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
+      WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
+      action_names_offset = mark;
+      fake_action_names_offset = mark + 4*no_actions;
+      for (i=0; i<no_actions + no_fake_actions; i++) {
+        j = action_name_strings[i];
+        if (j)
+          j = Write_Strings_At + compressed_offsets[j-1];
+        WriteInt32(p+mark, j);
+        mark += 4;
+      }
+  
+      array_names_offset = mark;
+      WriteInt32(p+mark, no_arrays);
       mark += 4;
+      for (i=0; i<no_arrays; i++) {
+        j = array_name_strings[i];
+        if (j)
+          j = Write_Strings_At + compressed_offsets[j-1];
+        WriteInt32(p+mark, j);
+        mark += 4;
+      }
     }
-
-    WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
-    WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
-    action_names_offset = mark;
-    fake_action_names_offset = mark + 4*no_actions;
-    for (i=0; i<no_actions + no_fake_actions; i++) {
-      j = action_name_strings[i];
-      if (j)
-        j = Write_Strings_At + compressed_offsets[j-1];
-      WriteInt32(p+mark, j);
-      mark += 4;
+    else {
+      identifier_names_offset = mark;
+      action_names_offset = mark;
+      fake_action_names_offset = mark;
+      array_names_offset = mark;
     }
 
-    array_names_offset = mark;
-    WriteInt32(p+mark, no_arrays);
-    mark += 4;
-    for (i=0; i<no_arrays; i++) {
-      j = array_name_strings[i];
-      if (j)
-        j = Write_Strings_At + compressed_offsets[j-1];
-      WriteInt32(p+mark, j);
-      mark += 4;
-    }    
-
     individuals_offset = mark;
 
     /*  ------------------------ Grammar Table ----------------------------- */
@@ -1403,6 +1366,12 @@ table format requested (producing number 2 format instead)");
     for (i=0; i<no_Inform_verbs; i++) {
       j = mark + Write_RAM_At;
       WriteInt32(p+(grammar_table_at+4+i*4), j);
+      if (!Inform_verbs[i].used) {
+          /* This verb was marked unused at locate_dead_grammar_lines()
+             time. Omit the grammar lines. */
+          p[mark++] = 0;
+          continue;
+      }
       p[mark++] = Inform_verbs[i].lines;
       for (j=0; j<Inform_verbs[i].lines; j++) {
         int tok;
@@ -1464,6 +1433,9 @@ table format requested (producing number 2 format instead)");
 
     RAM_Size = mark;
 
+    if (RAM_Size > rough_size)
+        compiler_error("RAM size exceeds rough estimate.");
+    
     Out_Size = Write_RAM_At + RAM_Size;
 
     /*  --------------------------- Offsets -------------------------------- */
@@ -1488,7 +1460,7 @@ table format requested (producing number 2 format instead)");
 
     /*  ------ Backpatch the machine, now that all information is in ------- */
 
-    if (!module_switch)
+    if (TRUE)
     {   backpatch_zmachine_image_g();
 
         mark = actions_at + 4;
@@ -1670,18 +1642,23 @@ static void display_frequencies()
     
     for (i=0; i<no_abbreviations; i++) {
         int32 saving;
+        char *astr;
         if (!glulx_mode)
             saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
         else
             saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
+
+        astr = abbreviation_text(i);
+        /* Print the abbreviation text, left-padded to ten spaces, with
+           spaces replaced by underscores. */
+        for (j=strlen(astr); j<10; j++) {
+            putchar(' ');
+        }
+        for (j=0; astr[j]; j++) {
+            putchar(astr[j] == ' ' ? '_' : astr[j]);
+        }
         
-        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);
+        printf(" %5d/%5d   ", abbreviations[i].freq, saving);
         
         if ((i%3)==2) printf("\n");
     }
@@ -1695,7 +1672,7 @@ 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";
+    char *output_called = "story file";
     int limit = 0;
 
     /* Yeah, we're repeating this calculation from construct_storyfile_z() */
@@ -1796,7 +1773,7 @@ static void display_statistics_g()
     char *k_str = "";
     int32 limit = 1024*1024;
     int32 strings_length = compression_table_size + compression_string_size;
-    char *output_called = (module_switch)?"module":"story file";
+    char *output_called = "story file";
     
     k_long=(Out_Size/1024);
     if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }