Update to Inform v6.42
[inform.git] / src / files.c
index 742e965e67ec379273f000d608ba19f9eb45e11f..68d1c5581a8130a7009848b7e3d9c3f7b383b4b1 100644 (file)
@@ -7,9 +7,8 @@
 /*             routines in "inform.c", since they are tied up with ICL       */
 /*             settings and are very host OS-dependent.                      */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2020                                   */
-/*                                                                           */
-/* This file is part of Inform.                                              */
+/*   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      */
@@ -41,7 +40,7 @@ int32 total_chars_read;                 /* Characters read in (from all
 static int checksum_low_byte,           /* For calculating the Z-machine's   */
            checksum_high_byte;          /* "verify" checksum                 */
 
-static int32 checksum_long;             /* For the Glulx checksum,           */
+static uint32 checksum_long;             /* For the Glulx checksum,          */
 static int checksum_count;              /* similarly                         */
 
 /* ------------------------------------------------------------------------- */
@@ -49,10 +48,9 @@ static int checksum_count;              /* similarly                         */
 /*   level is only concerned with file names and handles.                    */
 /* ------------------------------------------------------------------------- */
 
-FileId *InputFiles=NULL;                /*  Ids for all the source files     */
-static char *filename_storage,          /*  Translated filenames             */
-            *filename_storage_p;
-static int filename_storage_left;
+FileId *InputFiles=NULL;                /*  Ids for all the source files
+                                            Allocated to total_files         */
+static memory_list InputFiles_memlist;
 
 /* ------------------------------------------------------------------------- */
 /*   When emitting debug information, we won't have addresses of routines,   */
@@ -88,13 +86,6 @@ static debug_backpatch_accumulator global_backpatch_accumulator;
 static debug_backpatch_accumulator array_backpatch_accumulator;
 static debug_backpatch_accumulator grammar_backpatch_accumulator;
 
-/* ------------------------------------------------------------------------- */
-/*   File handles and names for temporary files.                             */
-/* ------------------------------------------------------------------------- */
-
-FILE *Temp1_fp=NULL, *Temp2_fp=NULL,  *Temp3_fp=NULL;
-char Temp1_Name[PATHLEN], Temp2_Name[PATHLEN], Temp3_Name[PATHLEN];
-
 /* ------------------------------------------------------------------------- */
 /*   Opening and closing source code files                                   */
 /* ------------------------------------------------------------------------- */
@@ -119,23 +110,16 @@ extern void load_sourcefile(char *filename_given, int same_directory_flag)
     int x = 0;
     FILE *handle;
 
-    if (total_files == MAX_SOURCE_FILES)
-        memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
+    ensure_memory_list_available(&InputFiles_memlist, total_files+1);
 
     do
     {   x = translate_in_filename(x, name, filename_given, same_directory_flag,
                 (total_files==0)?1:0);
-        handle = fopen(name,"r");
+        handle = fopen(name,"rb");
     } while ((handle == NULL) && (x != 0));
 
-    if (filename_storage_left <= (int)strlen(name))
-        memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
-
-    filename_storage_left -= strlen(name)+1;
-    strcpy(filename_storage_p, name);
-    InputFiles[total_files].filename = filename_storage_p;
-
-    filename_storage_p += strlen(name)+1;
+    InputFiles[total_files].filename = my_malloc(strlen(name)+1, "filename storage");
+    strcpy(InputFiles[total_files].filename, name);
 
     if (debugfile_switch)
     {   debug_file_printf("<source index=\"%d\">", total_files);
@@ -158,8 +142,10 @@ extern void load_sourcefile(char *filename_given, int same_directory_flag)
         fatalerror_named("Couldn't open source file", name);
 
     InputFiles[total_files].is_input = TRUE;
+    InputFiles[total_files].initial_buffering = TRUE;
 
-    if (line_trace_level > 0) printf("\nOpening file \"%s\"\n",name);
+    if (files_trace_setting > 0)
+        printf("Opening file \"%s\"\n",name);
 
     total_files++;
     total_input_files++;
@@ -170,7 +156,8 @@ static void close_sourcefile(int file_number)
 {
     if (InputFiles[file_number-1].handle == NULL) return;
 
-    /*  Close this file.  */
+    /*  Close this file. But keep the InputFiles entry around, including
+        its filename. */
 
     if (ferror(InputFiles[file_number-1].handle))
         fatalerror_named("I/O failure: couldn't read from source file",
@@ -180,7 +167,10 @@ static void close_sourcefile(int file_number)
 
     InputFiles[file_number-1].handle = NULL;
 
-    if (line_trace_level > 0) printf("\nClosing file\n");
+    if (files_trace_setting > 0) {
+        char *str = (InputFiles[file_number-1].initial_buffering ? " (in initial buffering)" : "");
+        printf("Closing file \"%s\"%s\n", InputFiles[file_number-1].filename, str);
+    }
 }
 
 extern void close_all_source(void)
@@ -196,6 +186,7 @@ extern void close_all_source(void)
 extern int register_orig_sourcefile(char *filename)
 {
     int ix;
+    char *name;
 
     /* If the filename has already been used as an origsource filename,
        return that entry. We check the most-recently-used file first, and
@@ -217,19 +208,12 @@ extern int register_orig_sourcefile(char *filename)
     /* This filename has never been used before. Allocate a new InputFiles
        entry. */
 
-    char *name = filename; /* no translation */
+    name = filename; /* no translation */
 
-    if (total_files == MAX_SOURCE_FILES)
-        memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
+    ensure_memory_list_available(&InputFiles_memlist, total_files+1);
 
-    if (filename_storage_left <= (int)strlen(name))
-        memoryerror("MAX_SOURCE_FILES", MAX_SOURCE_FILES);
-
-    filename_storage_left -= strlen(name)+1;
-    strcpy(filename_storage_p, name);
-    InputFiles[total_files].filename = filename_storage_p;
-
-    filename_storage_p += strlen(name)+1;
+    InputFiles[total_files].filename = my_malloc(strlen(name)+1, "filename storage");
+    strcpy(InputFiles[total_files].filename, name);
 
     if (debugfile_switch)
     {   debug_file_printf("<source index=\"%d\">", total_files);
@@ -242,6 +226,7 @@ extern int register_orig_sourcefile(char *filename)
 
     InputFiles[total_files].handle = NULL;
     InputFiles[total_files].is_input = FALSE;
+    InputFiles[total_files].initial_buffering = FALSE;
 
     total_files++;
     current_origsource_file = total_files;
@@ -288,7 +273,7 @@ extern int file_load_chars(int file_number, char *buffer, int length)
 }
 
 /* ------------------------------------------------------------------------- */
-/*   Final assembly and output of the story file/module.                     */
+/*   Final assembly and output of the story file.                            */
 /* ------------------------------------------------------------------------- */
 
 FILE *sf_handle;
@@ -298,9 +283,7 @@ static void sf_put(int c)
     if (!glulx_mode) {
 
       /*  The checksum is the unsigned sum mod 65536 of the bytes in the
-          story file from 0x0040 (first byte after header) to the end.
-
-          The link data does not contribute to the checksum of a module.     */
+          story file from 0x0040 (first byte after header) to the end.       */
 
       checksum_low_byte += c;
       if (checksum_low_byte>=256)
@@ -317,16 +300,16 @@ static void sf_put(int c)
 
       switch (checksum_count) {
       case 0:
-        checksum_long += (((int32)(c & 0xFF)) << 24);
+        checksum_long += (((uint32)(c & 0xFF)) << 24);
         break;
       case 1:
-        checksum_long += (((int32)(c & 0xFF)) << 16);
+        checksum_long += (((uint32)(c & 0xFF)) << 16);
         break;
       case 2:
-        checksum_long += (((int32)(c & 0xFF)) << 8);
+        checksum_long += (((uint32)(c & 0xFF)) << 8);
         break;
       case 3:
-        checksum_long += ((int32)(c & 0xFF));
+        checksum_long += ((uint32)(c & 0xFF));
         break;
       }
       
@@ -374,7 +357,7 @@ static void output_compression(int entnum, int32 *size, int *count)
     (*size) += 1;
     break;
   case 3:
-    cx = (char *)abbreviations_at + ent->u.val*MAX_ABBREV_LENGTH;
+    cx = abbreviation_text(ent->u.val);
     while (*cx) {
       sf_put(*cx);
       cx++;
@@ -403,7 +386,7 @@ static void output_compression(int entnum, int32 *size, int *count)
 }
 
 static void output_file_z(void)
-{   FILE *fin=NULL; char new_name[PATHLEN];
+{   char new_name[PATHLEN];
     int32 length, blanks=0, size, i, j, offset;
     uint32 code_length, size_before_code, next_cons_check;
     int use_function;
@@ -415,9 +398,6 @@ static void output_file_z(void)
     /*  Enter the length information into the header.                        */
 
     length=((int32) Write_Strings_At) + static_strings_extent;
-    if (module_switch) length += link_data_size +
-                                 zcode_backpatch_size +
-                                 zmachine_backpatch_size;
 
     while ((length%length_scale_factor)!=0) { length++; blanks++; }
     length=length/length_scale_factor;
@@ -440,7 +420,7 @@ static void output_file_z(void)
     /*  Set the type and creator to Andrew Plotkin's MaxZip, a popular
         Z-code interpreter on the Macintosh  */
 
-    if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
+    fsetfileinfo(new_name, 'mxZR', 'ZCOD');
 #endif
 
     /*  (1)  Output the paged memory.                                        */
@@ -457,14 +437,6 @@ static void output_file_z(void)
 
     /*  (2)  Output the compiled code area.                                  */
 
-    if (temporary_files_switch)
-    {   fclose(Temp2_fp);
-        Temp2_fp = NULL;
-        fin=fopen(Temp2_Name,"rb");
-        if (fin==NULL)
-            fatalerror("I/O failure: couldn't reopen temporary file 2");
-    }
-
     if (!OMIT_UNUSED_ROUTINES) {
         /* This is the old-fashioned case, which is easy. All of zcode_area
            (zmachine_pc bytes) will be output. next_cons_check will be
@@ -491,15 +463,14 @@ static void output_file_z(void)
     size_before_code = size;
 
     j=0;
-    if (!module_switch)
     for (i=0; i<zcode_backpatch_size; i=i+3)
     {   int long_flag = TRUE;
         offset
-            = 256*read_byte_from_memory_block(&zcode_backpatch_table, i+1)
-              + read_byte_from_memory_block(&zcode_backpatch_table, i+2);
+            = 256*zcode_backpatch_table[i+1]
+              + zcode_backpatch_table[i+2];
         backpatch_error_flag = FALSE;
         backpatch_marker
-            = read_byte_from_memory_block(&zcode_backpatch_table, i);
+            = zcode_backpatch_table[i];
         if (backpatch_marker >= 0x80) long_flag = FALSE;
         backpatch_marker &= 0x7f;
         offset = offset + (backpatch_marker/32)*0x10000;
@@ -514,17 +485,13 @@ static void output_file_z(void)
         while (j<offset) {
             if (!use_function) {
                 while (j<offset && j<next_cons_check) {
-                    /* get dummy value */
-                    ((temporary_files_switch)?fgetc(fin):
-                        read_byte_from_memory_block(&zcode_area, j));
                     j++;
                 }
             }
             else {
                 while (j<offset && j<next_cons_check) {
                     size++;
-                    sf_put((temporary_files_switch)?fgetc(fin):
-                        read_byte_from_memory_block(&zcode_area, j));
+                    sf_put(zcode_area[j]);
                     j++;
                 }
             }
@@ -533,10 +500,8 @@ static void output_file_z(void)
         }
 
         if (long_flag)
-        {   int32 v = (temporary_files_switch)?fgetc(fin):
-                read_byte_from_memory_block(&zcode_area, j);
-            v = 256*v + ((temporary_files_switch)?fgetc(fin):
-                read_byte_from_memory_block(&zcode_area, j+1));
+        {   int32 v = zcode_area[j];
+            v = 256*v + (zcode_area[j+1]);
             j += 2;
             if (use_function) {
                 v = backpatch_value(v);
@@ -545,8 +510,7 @@ static void output_file_z(void)
             }
         }
         else
-        {   int32 v = (temporary_files_switch)?fgetc(fin):
-                read_byte_from_memory_block(&zcode_area, j);
+        {   int32 v = zcode_area[j];
             j++;
             if (use_function) {
                 v = backpatch_value(v);
@@ -570,17 +534,13 @@ static void output_file_z(void)
     while (j<offset) {
         if (!use_function) {
             while (j<offset && j<next_cons_check) {
-                /* get dummy value */
-                ((temporary_files_switch)?fgetc(fin):
-                    read_byte_from_memory_block(&zcode_area, j));
                 j++;
             }
         }
         else {
             while (j<offset && j<next_cons_check) {
                 size++;
-                sf_put((temporary_files_switch)?fgetc(fin):
-                    read_byte_from_memory_block(&zcode_area, j));
+                sf_put(zcode_area[j]);
                 j++;
             }
         }
@@ -588,13 +548,6 @@ static void output_file_z(void)
             next_cons_check = df_next_function_iterate(&use_function);
     }
 
-    if (temporary_files_switch)
-    {   if (ferror(fin))
-            fatalerror("I/O failure: couldn't read from temporary file 2");
-        fclose(fin);
-        fin = NULL;
-    }
-
     if (size_before_code + code_length != size)
         compiler_error("Code output length did not match");
 
@@ -605,53 +558,12 @@ static void output_file_z(void)
 
     /*  (4)  Output the static strings area.                                 */
 
-    if (temporary_files_switch)
-    {   fclose(Temp1_fp);
-        Temp1_fp = NULL;
-        fin=fopen(Temp1_Name,"rb");
-        if (fin==NULL)
-            fatalerror("I/O failure: couldn't reopen temporary file 1");
-        for (i=0; i<static_strings_extent; i++) sf_put(fgetc(fin));
-        if (ferror(fin))
-            fatalerror("I/O failure: couldn't read from temporary file 1");
-        fclose(fin);
-        fin = NULL;
-        remove(Temp1_Name); remove(Temp2_Name);
-    }
-    else
-      for (i=0; i<static_strings_extent; i++) {
-        sf_put(read_byte_from_memory_block(&static_strings_area,i));
+    for (i=0; i<static_strings_extent; i++) {
+        sf_put(static_strings_area[i]);
         size++;
-      }
-
-    /*  (5)  Output the linking data table (in the case of a module).        */
-
-    if (temporary_files_switch)
-    {   if (module_switch)
-        {   fclose(Temp3_fp);
-            Temp3_fp = NULL;
-            fin=fopen(Temp3_Name,"rb");
-            if (fin==NULL)
-                fatalerror("I/O failure: couldn't reopen temporary file 3");
-            for (j=0; j<link_data_size; j++) sf_put(fgetc(fin));
-            if (ferror(fin))
-                fatalerror("I/O failure: couldn't read from temporary file 3");
-            fclose(fin);
-            fin = NULL;
-            remove(Temp3_Name);
-        }
     }
-    else
-        if (module_switch)
-            for (i=0; i<link_data_size; i++)
-                sf_put(read_byte_from_memory_block(&link_data_area,i));
 
-    if (module_switch)
-    {   for (i=0; i<zcode_backpatch_size; i++)
-            sf_put(read_byte_from_memory_block(&zcode_backpatch_table, i));
-        for (i=0; i<zmachine_backpatch_size; i++)
-            sf_put(read_byte_from_memory_block(&zmachine_backpatch_table, i));
-    }
+    /*  (5)  When modules existed, we output link data here.                 */
 
     /*  (6)  Output null bytes to reach a multiple of 0.5K.                  */
 
@@ -700,17 +612,13 @@ static void output_file_z(void)
     }
 #endif
 #ifdef MAC_FACE
-     if (module_switch)
-         InformFiletypes (new_name, INF_MODULE_TYPE);
-     else
-         InformFiletypes (new_name, INF_ZCODE_TYPE);
+    InformFiletypes (new_name, INF_ZCODE_TYPE);
 #endif
 }
 
 static void output_file_g(void)
-{   FILE *fin=NULL; char new_name[PATHLEN];
+{   char new_name[PATHLEN];
     int32 size, i, j, offset;
-    int32 VersionNum;
     uint32 code_length, size_before_code, next_cons_check;
     int use_function;
     int first_byte_of_triple, second_byte_of_triple, third_byte_of_triple;
@@ -729,7 +637,7 @@ static void output_file_g(void)
     /*  Set the type and creator to Andrew Plotkin's MaxZip, a popular
         Z-code interpreter on the Macintosh  */
 
-    if (!module_switch) fsetfileinfo(new_name, 'mxZR', 'ZCOD');
+    fsetfileinfo(new_name, 'mxZR', 'GLUL');
 #endif
 
     checksum_long = 0;
@@ -737,32 +645,33 @@ static void output_file_g(void)
 
     /* Determine the version number. */
 
-    VersionNum = 0x00020000;
+    final_glulx_version = 0x00020000;
 
     /* Increase for various features the game may have used. */
     if (no_unicode_chars != 0 || (uses_unicode_features)) {
-      VersionNum = 0x00030000;
+      final_glulx_version = 0x00030000;
     }
     if (uses_memheap_features) {
-      VersionNum = 0x00030100;
+      final_glulx_version = 0x00030100;
     }
     if (uses_acceleration_features) {
-      VersionNum = 0x00030101;
+      final_glulx_version = 0x00030101;
     }
     if (uses_float_features) {
-      VersionNum = 0x00030102;
+      final_glulx_version = 0x00030102;
+    }
+    if (uses_double_features || uses_extundo_features) {
+      final_glulx_version = 0x00030103;
     }
 
     /* And check if the user has requested a specific version. */
     if (requested_glulx_version) {
-      if (requested_glulx_version < VersionNum) {
-        static char error_message_buff[256];
-        sprintf(error_message_buff, "Version 0x%08lx requested, but \
-game features require version 0x%08lx", (long)requested_glulx_version, (long)VersionNum);
-        warning(error_message_buff);
+      if (requested_glulx_version < final_glulx_version) {
+        warning_fmt("Version 0x%08lx requested, but game features require version 0x%08lx",
+                    (long)requested_glulx_version, (long)final_glulx_version);
       }
       else {
-        VersionNum = requested_glulx_version;
+        final_glulx_version = requested_glulx_version;
       }
     }
 
@@ -775,10 +684,10 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
     sf_put('u');
     sf_put('l');
     /* Version number. */
-    sf_put((VersionNum >> 24));
-    sf_put((VersionNum >> 16));
-    sf_put((VersionNum >> 8));
-    sf_put((VersionNum));
+    sf_put((final_glulx_version >> 24));
+    sf_put((final_glulx_version >> 16));
+    sf_put((final_glulx_version >> 8));
+    sf_put((final_glulx_version));
     /* RAMSTART */
     sf_put((Write_RAM_At >> 24));
     sf_put((Write_RAM_At >> 16));
@@ -850,14 +759,6 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
 
     /*  (2)  Output the compiled code area. */
 
-    if (temporary_files_switch)
-    {   fclose(Temp2_fp);
-        Temp2_fp = NULL;
-        fin=fopen(Temp2_Name,"rb");
-        if (fin==NULL)
-            fatalerror("I/O failure: couldn't reopen temporary file 2");
-    }
-
     if (!OMIT_UNUSED_ROUTINES) {
         /* This is the old-fashioned case, which is easy. All of zcode_area
            (zmachine_pc bytes) will be output. next_cons_check will be
@@ -884,37 +785,32 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
     size_before_code = size;
 
     j=0;
-    if (!module_switch)
       for (i=0; i<zcode_backpatch_size; i=i+6) {
         int data_len;
         int32 v;
         offset = 
-          (read_byte_from_memory_block(&zcode_backpatch_table, i+2) << 24)
-          | (read_byte_from_memory_block(&zcode_backpatch_table, i+3) << 16)
-          | (read_byte_from_memory_block(&zcode_backpatch_table, i+4) << 8)
-          | (read_byte_from_memory_block(&zcode_backpatch_table, i+5));
+          (zcode_backpatch_table[i+2] << 24)
+          | (zcode_backpatch_table[i+3] << 16)
+          | (zcode_backpatch_table[i+4] << 8)
+          | (zcode_backpatch_table[i+5]);
         backpatch_error_flag = FALSE;
         backpatch_marker =
-          read_byte_from_memory_block(&zcode_backpatch_table, i);
+          zcode_backpatch_table[i];
         data_len =
-          read_byte_from_memory_block(&zcode_backpatch_table, i+1);
+          zcode_backpatch_table[i+1];
 
         /* All code up until the next backpatch marker gets flushed out
            as-is. (Unless we're in a stripped-out function.) */
         while (j<offset) {
             if (!use_function) {
                 while (j<offset && j<next_cons_check) {
-                    /* get dummy value */
-                    ((temporary_files_switch)?fgetc(fin):
-                        read_byte_from_memory_block(&zcode_area, j));
                     j++;
                 }
             }
             else {
                 while (j<offset && j<next_cons_check) {
                     size++;
-                    sf_put((temporary_files_switch)?fgetc(fin):
-                        read_byte_from_memory_block(&zcode_area, j));
+                    sf_put(zcode_area[j]);
                     j++;
                 }
             }
@@ -927,14 +823,10 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
         switch (data_len) {
 
         case 4:
-          v = ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j));
-          v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j+1));
-          v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j+2));
-          v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j+3));
+          v = (zcode_area[j]);
+          v = (v << 8) | (zcode_area[j+1]);
+          v = (v << 8) | (zcode_area[j+2]);
+          v = (v << 8) | (zcode_area[j+3]);
           j += 4;
           if (!use_function)
               break;
@@ -947,10 +839,8 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
           break;
 
         case 2:
-          v = ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j));
-          v = (v << 8) | ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j+1));
+          v = (zcode_area[j]);
+          v = (v << 8) | (zcode_area[j+1]);
           j += 2;
           if (!use_function)
               break;
@@ -965,8 +855,7 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
           break;
 
         case 1:
-          v = ((temporary_files_switch)?fgetc(fin):
-            read_byte_from_memory_block(&zcode_area, j));
+          v = (zcode_area[j]);
           j += 1;
           if (!use_function)
               break;
@@ -1000,17 +889,13 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
     while (j<offset) {
         if (!use_function) {
             while (j<offset && j<next_cons_check) {
-                /* get dummy value */
-                ((temporary_files_switch)?fgetc(fin):
-                    read_byte_from_memory_block(&zcode_area, j));
                 j++;
             }
         }
         else {
             while (j<offset && j<next_cons_check) {
                 size++;
-                sf_put((temporary_files_switch)?fgetc(fin):
-                    read_byte_from_memory_block(&zcode_area, j));
+                sf_put(zcode_area[j]);
                 j++;
             }
         }
@@ -1018,21 +903,11 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
             next_cons_check = df_next_function_iterate(&use_function);
     }
 
-    if (temporary_files_switch)
-    {   if (ferror(fin))
-            fatalerror("I/O failure: couldn't read from temporary file 2");
-        fclose(fin);
-        fin = NULL;
-    }
-
     if (size_before_code + code_length != size)
         compiler_error("Code output length did not match");
 
     /*  (4)  Output the static strings area.                                 */
 
-    if (temporary_files_switch) {
-      fseek(Temp1_fp, 0, SEEK_SET);
-    }
     {
       int32 ix, lx;
       int ch, jx, curbyte, bx;
@@ -1086,10 +961,7 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
         jx = 0; 
         curbyte = 0;
         while (!done) {
-          if (temporary_files_switch)
-            ch = fgetc(Temp1_fp);
-          else
-            ch = read_byte_from_memory_block(&static_strings_area, ix);
+          ch = static_strings_area[ix];
           ix++;
           if (ix > static_strings_extent || ch < 0)
             compiler_error("Read too much not-yet-compressed text.");
@@ -1191,13 +1063,13 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
         int32 val, ix, jx;
         for (ix=0, jx=0; ix<staticarray_backpatch_size; ix += 5) {
             backpatch_error_flag = FALSE;
-            backpatch_marker = read_byte_from_memory_block(&staticarray_backpatch_table, ix);
+            backpatch_marker = staticarray_backpatch_table[ix];
             /* datalen is always 4 for array backpatching */
             offset = 
-                (read_byte_from_memory_block(&staticarray_backpatch_table, ix+1) << 24)
-                | (read_byte_from_memory_block(&staticarray_backpatch_table, ix+2) << 16)
-                | (read_byte_from_memory_block(&staticarray_backpatch_table, ix+3) << 8)
-                | (read_byte_from_memory_block(&staticarray_backpatch_table, ix+4));
+                (staticarray_backpatch_table[ix+1] << 24)
+                | (staticarray_backpatch_table[ix+2] << 16)
+                | (staticarray_backpatch_table[ix+3] << 8)
+                | (staticarray_backpatch_table[ix+4]);
             while (jx<offset) {
                 sf_put(static_array_area[jx]);
                 size++;
@@ -1282,10 +1154,7 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
     }
 #endif
 #ifdef MAC_FACE
-     if (module_switch)
-         InformFiletypes (new_name, INF_MODULE_TYPE);
-     else
-         InformFiletypes (new_name, INF_ZCODE_TYPE);
+    InformFiletypes (new_name, INF_GLULX_TYPE);
 #endif
 }
 
@@ -1303,8 +1172,38 @@ extern void output_file(void)
 
 FILE *transcript_file_handle; int transcript_open;
 
-extern void write_to_transcript_file(char *text)
-{   fputs(text, transcript_file_handle);
+extern void write_to_transcript_file(char *text, int linetype)
+{
+    if (TRANSCRIPT_FORMAT == 1) {
+        char ch = '?';
+        switch (linetype) {
+            case STRCTX_INFO:
+                ch = 'I'; break;
+            case STRCTX_GAME:
+                ch = 'G'; break;
+            case STRCTX_GAMEOPC:
+                ch = 'H'; break;
+            case STRCTX_VENEER:
+                ch = 'V'; break;
+            case STRCTX_VENEEROPC:
+                ch = 'W'; break;
+            case STRCTX_LOWSTRING:
+                ch = 'L'; break;
+            case STRCTX_ABBREV:
+                ch = 'A'; break;
+            case STRCTX_DICT:
+                ch = 'D'; break;
+            case STRCTX_OBJNAME:
+                ch = 'O'; break;
+            case STRCTX_SYMBOL:
+                ch = 'S'; break;
+            case STRCTX_INFIX:
+                ch = 'X'; break;
+        }
+        fputc(ch, transcript_file_handle);
+        fputs(": ", transcript_file_handle);
+    }
+    fputs(text, transcript_file_handle);
     fputc('\n', transcript_file_handle);
 }
 
@@ -1318,9 +1217,16 @@ extern void open_transcript_file(char *what_of)
 
     transcript_open = TRUE;
 
-    sprintf(topline_buffer, "Transcript of the text of \"%s\"\n\
-[From %s]\n", what_of, banner_line);
-    write_to_transcript_file(topline_buffer);
+    snprintf(topline_buffer, 256, "Transcript of the text of \"%s\"", what_of);
+    write_to_transcript_file(topline_buffer, STRCTX_INFO);
+    snprintf(topline_buffer, 256, "[From %s]", banner_line);
+    write_to_transcript_file(topline_buffer, STRCTX_INFO);
+    if (TRANSCRIPT_FORMAT == 1) {
+        write_to_transcript_file("[I:info, G:game text, V:veneer text, L:lowmem string, A:abbreviation, D:dict word, O:object name, S:symbol, X:infix]", STRCTX_INFO);
+        if (!glulx_mode)
+            write_to_transcript_file("[H:game text inline in opcode, W:veneer text inline in opcode]", STRCTX_INFO);
+    }
+    write_to_transcript_file("",  STRCTX_INFO);
 }
 
 extern void abort_transcript_file(void)
@@ -1333,10 +1239,24 @@ extern void close_transcript_file(void)
 {   char botline_buffer[256];
     char sn_buffer[7];
 
+    write_to_transcript_file("",  STRCTX_INFO);
+
+    if (!glulx_mode) {
+        snprintf(botline_buffer, 256, "[Compiled Z-machine version %d]", version_number);
+    }
+    else {
+        int32 major = (final_glulx_version >> 16) & 0xFFFF;
+        int32 minor = (final_glulx_version >> 8) & 0xFF;
+        int32 patch = final_glulx_version & 0xFF;
+        snprintf(botline_buffer, 256, "[Compiled Glulx version %d.%d.%d]", major, minor, patch);
+    }
+    write_to_transcript_file(botline_buffer, STRCTX_INFO);
+    
     write_serial_number(sn_buffer);
-    sprintf(botline_buffer, "\n[End of transcript: release %d.%s]\n",
+    snprintf(botline_buffer, 256, "[End of transcript: release %d, serial %s]",
         release_number, sn_buffer);
-    write_to_transcript_file(botline_buffer);
+    write_to_transcript_file(botline_buffer, STRCTX_INFO);
+    write_to_transcript_file("",  STRCTX_INFO);
 
     if (ferror(transcript_file_handle))
         fatalerror("I/O failure: couldn't write to transcript file");
@@ -1528,45 +1448,45 @@ extern void write_debug_locations(debug_locations locations)
 }
 
 extern void write_debug_optional_identifier(int32 symbol_index)
-{   if (stypes[symbol_index] != ROUTINE_T)
+{   if (symbols[symbol_index].type != ROUTINE_T)
     {   compiler_error
             ("Attempt to write a replaceable identifier for a non-routine");
     }
-    if (replacement_debug_backpatch_positions[symbol_index].valid)
+    if (symbol_debug_info[symbol_index].replacement_backpatch_pos.valid)
     {   if (fsetpos
                 (Debug_fp,
-                 &replacement_debug_backpatch_positions[symbol_index].position))
+                 &symbol_debug_info[symbol_index].replacement_backpatch_pos.position))
         {   fatalerror("I/O failure: can't seek in debugging information file");
         }
         debug_file_printf
             ("<identifier artificial=\"true\">%s "
                  "(superseded replacement)</identifier>",
-             symbs[symbol_index]);
+             symbols[symbol_index].name);
         if (fseek(Debug_fp, 0L, SEEK_END))
         {   fatalerror("I/O failure: can't seek in debugging information file");
         }
     }
     fgetpos
-      (Debug_fp, &replacement_debug_backpatch_positions[symbol_index].position);
-    replacement_debug_backpatch_positions[symbol_index].valid = TRUE;
-    debug_file_printf("<identifier>%s</identifier>", symbs[symbol_index]);
+      (Debug_fp, &symbol_debug_info[symbol_index].replacement_backpatch_pos.position);
+    symbol_debug_info[symbol_index].replacement_backpatch_pos.valid = TRUE;
+    debug_file_printf("<identifier>%s</identifier>", symbols[symbol_index].name);
     /* Space for:       artificial="true" (superseded replacement) */
     debug_file_printf("                                           ");
 }
 
 extern void write_debug_symbol_backpatch(int32 symbol_index)
-{   if (symbol_debug_backpatch_positions[symbol_index].valid) {
+{   if (symbol_debug_info[symbol_index].backpatch_pos.valid) {
         compiler_error("Symbol entry incorrectly reused in debug information "
                        "file backpatching");
     }
-    fgetpos(Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position);
-    symbol_debug_backpatch_positions[symbol_index].valid = TRUE;
+    fgetpos(Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position);
+    symbol_debug_info[symbol_index].backpatch_pos.valid = TRUE;
     /* Reserve space for up to 10 digits plus a negative sign. */
     debug_file_printf("*BACKPATCH*");
 }
 
 extern void write_debug_symbol_optional_backpatch(int32 symbol_index)
-{   if (symbol_debug_backpatch_positions[symbol_index].valid) {
+{   if (symbol_debug_info[symbol_index].backpatch_pos.valid) {
         compiler_error("Symbol entry incorrectly reused in debug information "
                        "file backpatching");
     }
@@ -1575,8 +1495,8 @@ extern void write_debug_symbol_optional_backpatch(int32 symbol_index)
        so that we'll be in the same case as above if the symbol is eventually
        defined. */
     debug_file_printf("<value>");
-    fgetpos(Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position);
-    symbol_debug_backpatch_positions[symbol_index].valid = TRUE;
+    fgetpos(Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position);
+    symbol_debug_info[symbol_index].backpatch_pos.valid = TRUE;
     debug_file_printf("*BACKPATCH*</value>");
 }
 
@@ -1692,18 +1612,18 @@ extern void end_writing_debug_sections(int32 end_address)
 }
 
 extern void write_debug_undef(int32 symbol_index)
-{   if (!symbol_debug_backpatch_positions[symbol_index].valid)
+{   if (!symbol_debug_info[symbol_index].backpatch_pos.valid)
     {   compiler_error
             ("Attempt to erase debugging information never written or since "
                 "erased");
     }
-    if (stypes[symbol_index] != CONSTANT_T)
+    if (symbols[symbol_index].type != CONSTANT_T)
     {   compiler_error
             ("Attempt to erase debugging information for a non-constant "
              "because of an #undef");
     }
     if (fsetpos
-         (Debug_fp, &symbol_debug_backpatch_positions[symbol_index].position))
+         (Debug_fp, &symbol_debug_info[symbol_index].backpatch_pos.position))
     {   fatalerror("I/O failure: can't seek in debugging information file");
     }
     /* There are 7 characters in ``<value>''. */
@@ -1713,7 +1633,7 @@ extern void write_debug_undef(int32 symbol_index)
     /* Overwrite:      <value>*BACKPATCH*</value> */
     debug_file_printf("                          ");
     nullify_debug_file_position
-        (&symbol_debug_backpatch_positions[symbol_index]);
+        (&symbol_debug_info[symbol_index].backpatch_pos);
     if (fseek(Debug_fp, 0L, SEEK_END))
     {   fatalerror("I/O failure: can't seek in debugging information file");
     }
@@ -1744,14 +1664,13 @@ static void apply_debug_information_backpatches
 static void apply_debug_information_symbol_backpatches()
 {   int backpatch_symbol;
     for (backpatch_symbol = no_symbols; backpatch_symbol--;)
-    {   if (symbol_debug_backpatch_positions[backpatch_symbol].valid)
+    {   if (symbol_debug_info[backpatch_symbol].backpatch_pos.valid)
         {   if (fsetpos(Debug_fp,
-                        &symbol_debug_backpatch_positions
-                            [backpatch_symbol].position))
+                        &symbol_debug_info[backpatch_symbol].backpatch_pos.position))
             {   fatalerror
                     ("I/O failure: can't seek in debugging information file");
             }
-            debug_file_printf("%11d", svals[backpatch_symbol]);
+            debug_file_printf("%11d", symbols[backpatch_symbol].value);
         }
     }
 }
@@ -1795,57 +1714,6 @@ extern void end_debug_file()
     close_debug_file();
 }
 
-/* ------------------------------------------------------------------------- */
-/*  Temporary storage files:                                                 */
-/*                                                                           */
-/*      Temp file 1 is used to hold the static strings area, as compiled     */
-/*                2 to hold compiled routines of Z-code                      */
-/*                3 to hold the link data table (but only for modules)       */
-/*                                                                           */
-/*  (Though annoying, this procedure typically saves about 200K of memory,   */
-/*  an important point for Amiga and sub-386 PC users of Inform)             */
-/* ------------------------------------------------------------------------- */
-
-extern void open_temporary_files(void)
-{   translate_temp_filename(1);
-    Temp1_fp=fopen(Temp1_Name,"wb");
-    if (Temp1_fp==NULL) fatalerror_named("Couldn't open temporary file 1",
-        Temp1_Name);
-    translate_temp_filename(2);
-    Temp2_fp=fopen(Temp2_Name,"wb");
-    if (Temp2_fp==NULL) fatalerror_named("Couldn't open temporary file 2",
-        Temp2_Name);
-
-    if (!module_switch) return;
-    translate_temp_filename(3);
-    Temp3_fp=fopen(Temp3_Name,"wb");
-    if (Temp3_fp==NULL) fatalerror_named("Couldn't open temporary file 3",
-        Temp3_Name);
-}
-
-extern void check_temp_files(void)
-{
-    if (ferror(Temp1_fp))
-        fatalerror("I/O failure: couldn't write to temporary file 1");
-    if (ferror(Temp2_fp))
-        fatalerror("I/O failure: couldn't write to temporary file 2");
-    if (module_switch && ferror(Temp3_fp))
-        fatalerror("I/O failure: couldn't write to temporary file 3");
-}
-
-extern void remove_temp_files(void)
-{   if (Temp1_fp != NULL) fclose(Temp1_fp);
-    Temp1_fp = NULL;
-    if (Temp2_fp != NULL) fclose(Temp2_fp);
-    Temp2_fp = NULL;
-    remove(Temp1_Name); remove(Temp2_Name);
-    if (module_switch)
-    {   if (Temp3_fp != NULL) fclose(Temp3_fp);
-        Temp3_fp = NULL;
-        remove(Temp3_Name);
-    }
-}
-
 /* ========================================================================= */
 /*   Data structure management routines                                      */
 /* ------------------------------------------------------------------------- */
@@ -1869,8 +1737,6 @@ extern void files_begin_prepass(void)
 
 extern void files_begin_pass(void)
 {   total_chars_read=0;
-    if (temporary_files_switch)
-        open_temporary_files();
 }
 
 static void initialise_accumulator
@@ -1888,10 +1754,9 @@ static void initialise_accumulator
 }
 
 extern void files_allocate_arrays(void)
-{   filename_storage = my_malloc(MAX_SOURCE_FILES*64, "filename storage");
-    filename_storage_p = filename_storage;
-    filename_storage_left = MAX_SOURCE_FILES*64;
-    InputFiles = my_malloc(MAX_SOURCE_FILES*sizeof(FileId), 
+{
+    initialise_memory_list(&InputFiles_memlist,
+        sizeof(FileId), 16, (void**)&InputFiles,
         "input file storage");
     if (debugfile_switch)
     {   if (glulx_mode)
@@ -1920,8 +1785,14 @@ static void tear_down_accumulator(debug_backpatch_accumulator *accumulator)
 }
 
 extern void files_free_arrays(void)
-{   my_free(&filename_storage, "filename storage");
-    my_free(&InputFiles, "input file storage");
+{
+    int ix;
+    for (ix=0; ix<total_files; ix++)
+    {
+        my_free(&InputFiles[ix].filename, "filename storage");
+    }
+    deallocate_memory_list(&InputFiles_memlist);
+    
     if (debugfile_switch)
     {   if (!glulx_mode)
         {   tear_down_accumulator(&object_backpatch_accumulator);