Update to commit d9e45a19b61c54bc804232fdc67485b84c7af8e9 dated May 21, 2020. These...
authorJason Self <j@jxself.org>
Mon, 25 May 2020 22:52:13 +0000 (15:52 -0700)
committerJason Self <j@jxself.org>
Mon, 25 May 2020 22:52:13 +0000 (15:52 -0700)
22 files changed:
src/arrays.c
src/asm.c
src/bpatch.c
src/chars.c
src/directs.c
src/errors.c
src/expressc.c
src/expressp.c
src/files.c
src/header.h
src/inform.c
src/lexer.c
src/linker.c
src/memory.c
src/objects.c
src/states.c
src/symbols.c
src/syntax.c
src/tables.c
src/text.c
src/veneer.c
src/verbs.c

index 93cc31ee6f75394b6ba1fe8d3490b96787393216..fc4f7af2c5e6abb7f1f951920138bf7dbdfd991a 100644 (file)
@@ -3,7 +3,7 @@
 /*               likewise global variables, which are in some ways a         */
 /*               simpler form of the same thing.                             */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -29,6 +29,8 @@
 /*                                                                           */
 /*    int    dynamic_array_area[]         Initial values for the bytes of    */
 /*                                        the dynamic array area             */
+/*    int    static_array_area[]          Initial values for the bytes of    */
+/*                                        the static array area              */
 /*    int32  global_initial_value[n]      The initialised value of the nth   */
 /*                                        global variable (counting 0 - 239) */
 /*                                                                           */
 /*   In Glulx, that 240 is changed to MAX_GLOBAL_VAR_NUMBER, and we take     */
 /*   correspondingly more space for the globals. This *really* ought to be   */
 /*   split into two segments.                                                */
+/*                                                                           */
+/*   We can also store arrays (but not globals) into static memory (ROM).    */
+/*   The storage for these goes, unsurprisingly, into static_array_area --   */
+/*   a separate allocation of MAX_STATIC_DATA bytes.                         */
 /* ------------------------------------------------------------------------- */
 int     *dynamic_array_area;           /* See above                          */
 int32   *global_initial_value;
@@ -54,9 +60,15 @@ int no_globals;                        /* Number of global variables used
 
 int dynamic_array_area_size;           /* Size in bytes                      */
 
+int     *static_array_area;
+int static_array_area_size;
+
 int no_arrays;
 int32   *array_symbols;
-int     *array_sizes, *array_types;
+int     *array_sizes, *array_types, *array_locs;
+/* array_sizes[N] gives the length of array N; array_types[N] is one of
+   the constants BYTE_ARRAY, WORD_ARRAY, etc; array_locs[N] is true for
+   static arrays, false for dynamic arrays.                                  */
 
 static int array_entry_size,           /* 1 for byte array, 2 for word array */
            array_base;                 /* Offset in dynamic array area of the
@@ -70,60 +82,89 @@ static int array_entry_size,           /* 1 for byte array, 2 for word array */
                                        /* In Glulx, of course, that will be
                                           4 instead of 2.                    */
 
-extern void finish_array(int32 i)
+extern void finish_array(int32 i, int is_static)
 {
+  int *area;
+  int area_size;
+  
+  if (!is_static) {
+      area = dynamic_array_area;
+      area_size = dynamic_array_area_size;
+  }
+  else {
+      area = static_array_area;
+      area_size = static_array_area_size;
+  }
+  
     /*  Write the array size into the 0th byte/word of the array, if it's
         a "table" or "string" array                                          */
   if (!glulx_mode) {
 
-    if (array_base!=dynamic_array_area_size)
-    {   if (dynamic_array_area_size-array_base==2)
-        {   dynamic_array_area[array_base]   = i/256;
-            dynamic_array_area[array_base+1] = i%256;
+    if (array_base != area_size)
+    {   if (area_size-array_base==2)
+        {   area[array_base]   = i/256;
+            area[array_base+1] = i%256;
         }
         else
         {   if (i>=256)
                 error("A 'string' array can have at most 256 entries");
-            dynamic_array_area[array_base] = i;
+            area[array_base] = i;
         }
     }
 
   }
   else {
-    if (array_base!=dynamic_array_area_size)
-    {   if (dynamic_array_area_size-array_base==4)
+    if (array_base != area_size)
+    {   if (area_size-array_base==4)
         {   
-            dynamic_array_area[array_base]   = (i >> 24) & 0xFF;
-            dynamic_array_area[array_base+1] = (i >> 16) & 0xFF;
-            dynamic_array_area[array_base+2] = (i >> 8) & 0xFF;
-            dynamic_array_area[array_base+3] = (i) & 0xFF;
+            area[array_base]   = (i >> 24) & 0xFF;
+            area[array_base+1] = (i >> 16) & 0xFF;
+            area[array_base+2] = (i >> 8) & 0xFF;
+            area[array_base+3] = (i) & 0xFF;
         }
         else
         {   if (i>=256)
                 error("A 'string' array can have at most 256 entries");
-            dynamic_array_area[array_base] = i;
+            area[array_base] = i;
         }
     }
     
   }
 
-  /*  Move on the dynamic array size so that it now points to the next
-      available free space                                                   */
+  /*  Move on the static/dynamic array size so that it now points to the
+      next available free space                                              */
 
-  dynamic_array_area_size += i*array_entry_size;
+  if (!is_static) {
+      dynamic_array_area_size += i*array_entry_size;
+  }
+  else {
+      static_array_area_size += i*array_entry_size;
+  }
 
 }
 
-extern void array_entry(int32 i, assembly_operand VAL)
+extern void array_entry(int32 i, int is_static, assembly_operand VAL)
 {
+  int *area;
+  int area_size;
+  
+  if (!is_static) {
+      area = dynamic_array_area;
+      area_size = dynamic_array_area_size;
+  }
+  else {
+      area = static_array_area;
+      area_size = static_array_area_size;
+  }
+  
   if (!glulx_mode) {
     /*  Array entry i (initial entry has i=0) is set to Z-machine value j    */
 
-    if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
+    if (area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
 
     if (array_entry_size==1)
-    {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value)%256;
+    {   area[area_size+i] = (VAL.value)%256;
 
         if (VAL.marker != 0)
            error("Entries in byte arrays and strings must be known constants");
@@ -135,21 +176,30 @@ extern void array_entry(int32 i, assembly_operand VAL)
             warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
     }
     else
-    {   dynamic_array_area[dynamic_array_area_size + 2*i]   = (VAL.value)/256;
-        dynamic_array_area[dynamic_array_area_size + 2*i+1] = (VAL.value)%256;
-        if (VAL.marker != 0)
-            backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA,
-                dynamic_array_area_size + 2*i);
+    {
+        int32 addr = area_size + 2*i;
+        area[addr]   = (VAL.value)/256;
+        area[addr+1] = (VAL.value)%256;
+        if (VAL.marker != 0) {
+            if (!is_static) {
+                backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA,
+                    addr);
+            }
+            else {
+                backpatch_zmachine(VAL.marker, STATIC_ARRAY_ZA,
+                    addr);
+            }
+        }
     }
   }
   else {
     /*  Array entry i (initial entry has i=0) is set to value j              */
 
-    if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
+    if (area_size+(i+1)*array_entry_size > MAX_STATIC_DATA)
         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
 
     if (array_entry_size==1)
-    {   dynamic_array_area[dynamic_array_area_size+i] = (VAL.value) & 0xFF;
+    {   area[area_size+i] = (VAL.value) & 0xFF;
 
         if (VAL.marker != 0)
            error("Entries in byte arrays and strings must be known constants");
@@ -161,13 +211,33 @@ extern void array_entry(int32 i, assembly_operand VAL)
             warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
     }
     else if (array_entry_size==4)
-    {   dynamic_array_area[dynamic_array_area_size + 4*i]   = (VAL.value >> 24) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+1] = (VAL.value >> 16) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+2] = (VAL.value >> 8) & 0xFF;
-        dynamic_array_area[dynamic_array_area_size + 4*i+3] = (VAL.value) & 0xFF;
-        if (VAL.marker != 0)
-            backpatch_zmachine(VAL.marker, ARRAY_ZA,
-                dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES + 4*i);
+    {
+        int32 addr = area_size + 4*i;
+        area[addr]   = (VAL.value >> 24) & 0xFF;
+        area[addr+1] = (VAL.value >> 16) & 0xFF;
+        area[addr+2] = (VAL.value >> 8) & 0xFF;
+        area[addr+3] = (VAL.value) & 0xFF;
+        if (VAL.marker != 0) {
+            if (!is_static) {
+                backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA,
+                    addr - 4*MAX_GLOBAL_VARIABLES);
+            }
+            else {
+                /* We can't use backpatch_zmachine() because that only applies to RAM. Instead we add an entry to staticarray_backpatch_table.
+                   A backpatch entry is five bytes: *_MV followed by the array offset (in static array area). */
+                write_byte_to_memory_block(&staticarray_backpatch_table,
+                    staticarray_backpatch_size++,
+                    VAL.marker);
+                write_byte_to_memory_block(&staticarray_backpatch_table,
+                    staticarray_backpatch_size++, ((addr >> 24) & 0xFF));
+                write_byte_to_memory_block(&staticarray_backpatch_table,
+                    staticarray_backpatch_size++, ((addr >> 16) & 0xFF));
+                write_byte_to_memory_block(&staticarray_backpatch_table,
+                    staticarray_backpatch_size++, ((addr >> 8) & 0xFF));
+                write_byte_to_memory_block(&staticarray_backpatch_table,
+                    staticarray_backpatch_size++, (addr & 0xFF));
+            }
+        }
     }
     else
     {
@@ -183,7 +253,7 @@ extern void array_entry(int32 i, assembly_operand VAL)
 /*                            | = <value>                                    */
 /*                            | <array specification>                        */
 /*                                                                           */
-/*      Array <arrayname> <array specification>                              */
+/*      Array <arrayname> [static] <array specification>                     */
 /*                                                                           */
 /*   where an array specification is:                                        */
 /*                                                                           */
@@ -191,6 +261,9 @@ extern void array_entry(int32 i, assembly_operand VAL)
 /*      | -->      |  <entry-1> ... <entry-n>                                */
 /*      | string   |  [ <entry-1> [,] [;] <entry-2> ... <entry-n> ];         */
 /*      | table                                                              */
+/*      | buffer                                                             */
+/*                                                                           */
+/*   The "static" keyword (arrays only) places the array in static memory.   */
 /*                                                                           */
 /* ------------------------------------------------------------------------- */
 
@@ -214,6 +287,7 @@ extern void make_global(int array_flag, int name_only)
 
     int32 i;
     int array_type, data_type;
+    int is_static = FALSE;
     assembly_operand AO;
 
     int32 global_symbol;
@@ -248,13 +322,32 @@ extern void make_global(int array_flag, int name_only)
     if ((!array_flag) && (sflags[i] & USED_SFLAG))
         error_named("Variable must be defined before use:", token_text);
 
+    directive_keywords.enabled = TRUE;
+    get_next_token();
+    directive_keywords.enabled = FALSE;
+    if ((token_type==DIR_KEYWORD_TT)&&(token_value==STATIC_DK)) {
+        if (array_flag) {
+            is_static = TRUE;
+        }
+        else {
+            error("Global variables cannot be static");
+        }
+    }
+    else {
+        put_token_back();
+    }
+    
     if (array_flag)
-    {   
-        if (!glulx_mode)
-            assign_symbol(i, dynamic_array_area_size, ARRAY_T);
-        else
-            assign_symbol(i, 
-                dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES, ARRAY_T);
+    {   if (!is_static) {
+            if (!glulx_mode)
+                assign_symbol(i, dynamic_array_area_size, ARRAY_T);
+            else
+                assign_symbol(i, 
+                    dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES, ARRAY_T);
+        }
+        else {
+            assign_symbol(i, static_array_area_size, STATIC_ARRAY_T);
+        }
         if (no_arrays == MAX_ARRAYS)
             memoryerror("MAX_ARRAYS", MAX_ARRAYS);
         array_symbols[no_arrays] = i;
@@ -313,6 +406,7 @@ extern void make_global(int array_flag, int name_only)
 
     if (!array_flag)
     {
+        /* is_static is always false in this case */
         if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
         {   AO = parse_expression(CONSTANT_CONTEXT);
             if (!glulx_mode) {
@@ -418,15 +512,29 @@ extern void make_global(int array_flag, int name_only)
         case ASCII_AI: obsolete_warning("use '->' instead of 'initstr'"); break;
     }
 
-    array_base = dynamic_array_area_size;
-
     /*  Leave room to write the array size in later, if string/table array   */
-
+    
+    int extraspace = 0;
     if ((array_type==STRING_ARRAY) || (array_type==TABLE_ARRAY))
-        dynamic_array_area_size += array_entry_size;
+        extraspace += array_entry_size;
     if (array_type==BUFFER_ARRAY)
-        dynamic_array_area_size += WORDSIZE;
+        extraspace += WORDSIZE;
+
+    int orig_area_size;
+    
+    if (!is_static) {
+        orig_area_size = dynamic_array_area_size;
+        array_base = dynamic_array_area_size;
+        dynamic_array_area_size += extraspace;
+    }
+    else {
+        orig_area_size = static_array_area_size;
+        array_base = static_array_area_size;
+        static_array_area_size += extraspace;
+    }
+
     array_types[no_arrays] = array_type;
+    array_locs[no_arrays] = is_static;
 
     switch(data_type)
     {
@@ -454,7 +562,7 @@ extern void make_global(int array_flag, int name_only)
                 }
             }
 
-            {   for (i=0; i<AO.value; i++) array_entry(i, zero_operand);
+            {   for (i=0; i<AO.value; i++) array_entry(i, is_static, zero_operand);
             }
             break;
 
@@ -491,7 +599,7 @@ extern void make_global(int array_flag, int name_only)
                     }
                 }
 
-                array_entry(i, AO);
+                array_entry(i, is_static, AO);
                 i++;
             } while (TRUE);
             put_token_back();
@@ -539,7 +647,7 @@ advance as part of 'Zcharacter table':", unicode);
                     }
                     chars.marker = 0;
                     set_constant_ot(&chars);
-                    array_entry(i, chars);
+                    array_entry(i, is_static, chars);
                 }
             }
             break;
@@ -566,12 +674,12 @@ advance as part of 'Zcharacter table':", unicode);
                     put_token_back(); break;
                 }
                 put_token_back();
-                array_entry(i, parse_expression(ARRAY_CONTEXT));
+                array_entry(i, is_static, parse_expression(ARRAY_CONTEXT));
                 i++;
             }
     }
 
-    finish_array(i);
+    finish_array(i, is_static);
 
     if (debugfile_switch)
     {   debug_file_printf("<array>");
@@ -579,9 +687,10 @@ advance as part of 'Zcharacter table':", unicode);
         debug_file_printf("<value>");
         write_debug_array_backpatch(svals[global_symbol]);
         debug_file_printf("</value>");
+        int32 new_area_size = (!is_static ? dynamic_array_area_size : static_array_area_size);
         debug_file_printf
             ("<byte-count>%d</byte-count>",
-             dynamic_array_area_size - array_base);
+             new_area_size - array_base);
         debug_file_printf
             ("<bytes-per-element>%d</bytes-per-element>",
              array_entry_size);
@@ -602,8 +711,9 @@ advance as part of 'Zcharacter table':", unicode);
 
 extern int32 begin_table_array(void)
 {
-    /*  The "box" statement needs to be able to construct (static) table
-        arrays of strings like this                                          */
+    /*  The "box" statement needs to be able to construct table
+        arrays of strings like this. (Static data, but we create a dynamic
+        array for maximum backwards compatibility.) */
 
     array_base = dynamic_array_area_size;
     array_entry_size = WORDSIZE;
@@ -621,7 +731,8 @@ extern int32 begin_table_array(void)
 extern int32 begin_word_array(void)
 {
     /*  The "random(a, b, ...)" function needs to be able to construct
-        (static) word arrays like this                                       */
+        word arrays like this. (Static data, but we create a dynamic
+        array for maximum backwards compatibility.) */
 
     array_base = dynamic_array_area_size;
     array_entry_size = WORDSIZE;
@@ -638,6 +749,7 @@ extern int32 begin_word_array(void)
 
 extern void init_arrays_vars(void)
 {   dynamic_array_area = NULL;
+    static_array_area = NULL;
     global_initial_value = NULL;
     array_sizes = NULL; array_symbols = NULL; array_types = NULL;
 }
@@ -649,23 +761,29 @@ extern void arrays_begin_pass(void)
     else
         no_globals=11;
     dynamic_array_area_size = WORDSIZE * MAX_GLOBAL_VARIABLES;
+    static_array_area_size = 0;
 }
 
 extern void arrays_allocate_arrays(void)
 {   dynamic_array_area = my_calloc(sizeof(int), MAX_STATIC_DATA, 
-        "static data");
+        "dynamic array data");
+    static_array_area = my_calloc(sizeof(int), MAX_STATIC_DATA, 
+        "static array data");
     array_sizes = my_calloc(sizeof(int), MAX_ARRAYS, "array sizes");
     array_types = my_calloc(sizeof(int), MAX_ARRAYS, "array types");
+    array_locs = my_calloc(sizeof(int), MAX_ARRAYS, "array locations");
     array_symbols = my_calloc(sizeof(int32), MAX_ARRAYS, "array symbols");
     global_initial_value = my_calloc(sizeof(int32), MAX_GLOBAL_VARIABLES, 
         "global values");
 }
 
 extern void arrays_free_arrays(void)
-{   my_free(&dynamic_array_area, "static data");
+{   my_free(&dynamic_array_area, "dynamic array data");
+    my_free(&static_array_area, "static array data");
     my_free(&global_initial_value, "global values");
     my_free(&array_sizes, "array sizes");
-    my_free(&array_types, "array sizes");
+    my_free(&array_types, "array types");
+    my_free(&array_locs, "array locations");
     my_free(&array_symbols, "array sizes");
 }
 
index a5444fd589d92f71d0838a53bfb0493b17d3d66a..3467100ad779290ad9bbb123dafed7db9a496be4 100644 (file)
--- a/src/asm.c
+++ b/src/asm.c
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "asm" : The Inform assembler                                            */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index ccc87badabc23049659ce1bf93f754e3487620b9..43078d2d16796d7d89d70e099f5102e263555809 100644 (file)
@@ -2,7 +2,7 @@
 /*   "bpatch" : Keeps track of, and finally acts on, backpatch markers,      */
 /*              correcting symbol values not known at compilation time       */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
 
 #include "header.h"
 
-memory_block zcode_backpatch_table, zmachine_backpatch_table;
-int32 zcode_backpatch_size, zmachine_backpatch_size;
+memory_block zcode_backpatch_table, staticarray_backpatch_table,
+    zmachine_backpatch_table;
+int32 zcode_backpatch_size, staticarray_backpatch_size,
+    zmachine_backpatch_size;
 
 /* ------------------------------------------------------------------------- */
 /*   The mending operation                                                   */
@@ -46,6 +48,8 @@ static int32 backpatch_value_z(int32 value)
             value += strings_offset/scale_factor; break;
         case ARRAY_MV:
             value += variables_offset; break;
+        case STATIC_ARRAY_MV:
+            value += static_arrays_offset; break;
         case IROUTINE_MV:
             if (OMIT_UNUSED_ROUTINES)
                 value = df_stripped_address_for_address(value);
@@ -155,6 +159,7 @@ static int32 backpatch_value_z(int32 value)
                         value += code_offset/scale_factor; 
                         break;
                     case ARRAY_T: value += variables_offset; break;
+                    case STATIC_ARRAY_T: value += static_arrays_offset; break;
                 }
             }
             break;
@@ -196,6 +201,8 @@ static int32 backpatch_value_g(int32 value)
             break;
         case ARRAY_MV:
             value += arrays_offset; break;
+        case STATIC_ARRAY_MV:
+            value += static_arrays_offset; break;
         case VARIABLE_MV:
             value = variables_offset + (4*value); break;
         case OBJECT_MV:
@@ -303,6 +310,7 @@ static int32 backpatch_value_g(int32 value)
                         value += code_offset;
                         break;
                     case ARRAY_T: value += arrays_offset; break;
+                    case STATIC_ARRAY_T: value += static_arrays_offset; break;
                     case OBJECT_T:
                     case CLASS_T:
                       value = object_tree_offset + 
@@ -425,6 +433,7 @@ extern void backpatch_zmachine_image_z(void)
             case PROP_ZA:            addr = prop_values_offset; break;
             case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
             case DYNAMIC_ARRAY_ZA:   addr = variables_offset; break;
+            case STATIC_ARRAY_ZA:    addr = static_arrays_offset; break;
             default:
                 if (no_link_errors == 0)
                     if (compiler_error("Illegal area to backpatch"))
@@ -471,8 +480,9 @@ extern void backpatch_zmachine_image_g(void)
         case PROP_DEFAULTS_ZA:   addr = prop_defaults_offset+4; break;
         case PROP_ZA:            addr = prop_values_offset; break;
         case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
-        case ARRAY_ZA:           addr = arrays_offset; break;
+        case DYNAMIC_ARRAY_ZA:   addr = arrays_offset; break;
         case GLOBALVAR_ZA:       addr = variables_offset; break;
+        /* STATIC_ARRAY_ZA is in ROM and therefore not handled here */
         default:
           if (no_link_errors == 0)
             if (compiler_error("Illegal area to backpatch"))
@@ -505,11 +515,13 @@ extern void backpatch_zmachine_image_g(void)
 
 extern void init_bpatch_vars(void)
 {   initialise_memory_block(&zcode_backpatch_table);
+    initialise_memory_block(&staticarray_backpatch_table);
     initialise_memory_block(&zmachine_backpatch_table);
 }
 
 extern void bpatch_begin_pass(void)
 {   zcode_backpatch_size = 0;
+    staticarray_backpatch_size = 0;
     zmachine_backpatch_size = 0;
 }
 
@@ -519,6 +531,7 @@ extern void bpatch_allocate_arrays(void)
 
 extern void bpatch_free_arrays(void)
 {   deallocate_memory_block(&zcode_backpatch_table);
+    deallocate_memory_block(&staticarray_backpatch_table);
     deallocate_memory_block(&zmachine_backpatch_table);
 }
 
index e91e9c191f9d041f91a0bb3f3ef56ca217ed8732..701d14eec585e2689bb10a5f925d77d1ac2cc357 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "chars" : Character set mappings and the Z-machine alphabet table       */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index d3b7f32c6032e1f7548700b691f8ff3c7212a05a..b802d5ec7e6bfbbea86a8467efb022410450063f 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "directs" : Directives (# commands)                                     */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index 8a4d288f4b34a6800b2d277f59003e83ee90428e..73fa1be7430d277998fd9c070b003bc96bf7fabb 100644 (file)
@@ -2,7 +2,7 @@
 /*   "errors" : Warnings, errors and fatal errors                            */
 /*              (with error throwback code for RISC OS machines)             */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index e6db119c32cd23378932b4eff41b98a60a483847..876804b4110786f14d2cc1ff2db9f17c1f6bcfaa 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "expressc" :  The expression code generator                             */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -451,7 +451,7 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2,
         index_ao;
     int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE, from_module = FALSE;
 
-    if (AO1.marker == ARRAY_MV)
+    if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)
     {   
         INITAO(&zero_ao);
 
@@ -465,10 +465,16 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2,
 
         size_ao = zero_ao; size_ao.value = -1;
         for (x=0; x<no_arrays; x++)
-        {   if (AO1.value == svals[array_symbols[x]])
+        {   if (((AO1.marker == ARRAY_MV) == (!array_locs[x]))
+                && (AO1.value == svals[array_symbols[x]]))
             {   size_ao.value = array_sizes[x]; y=x;
             }
         }
+        
+        if (array_locs[y] && !read_flag) {
+            error("Cannot write to a static array");
+        }
+
         if (size_ao.value==-1) 
             from_module=TRUE;
         else {
@@ -504,7 +510,7 @@ static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2,
     /* If we recognise AO1 as arising textually from a declared
        array, we can check bounds explicitly. */
 
-    if ((AO1.marker == ARRAY_MV) && (!from_module))
+    if ((AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV) && (!from_module))
     {   
         int passed_label = next_label++, failed_label = next_label++,
             final_label = next_label++; 
@@ -816,13 +822,14 @@ static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2,
     else 
       read_flag = FALSE;
 
-    if (AO1.marker == ARRAY_MV)
+    if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)
     {   
         INITAO(&zero_ao);
 
         size_ao = zero_ao; size_ao.value = -1;
         for (x=0; x<no_arrays; x++)
-        {   if (AO1.value == svals[array_symbols[x]])
+        {   if (((AO1.marker == ARRAY_MV) == (!array_locs[x]))
+                && (AO1.value == svals[array_symbols[x]]))
             {   size_ao.value = array_sizes[x]; y=x;
             }
         }
@@ -830,6 +837,10 @@ static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2,
 
         type_ao = zero_ao; type_ao.value = array_types[y];
 
+        if (array_locs[y] && !read_flag) {
+            error("Cannot write to a static array");
+        }
+
         if ((!is_systemfile()))
         {   if (data_len == 1)
             {
@@ -856,7 +867,7 @@ static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2,
     /* If we recognise AO1 as arising textually from a declared
        array, we can check bounds explicitly. */
 
-    if (AO1.marker == ARRAY_MV)
+    if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)
     {   
         /* Calculate the largest permitted array entry + 1
            Here "size_ao.value" = largest permitted entry of its own kind */
@@ -1789,9 +1800,9 @@ static void generate_code_from(int n, int void_flag)
                                  arg_c++, arg_et = ET[arg_et].right)
                             {   if (ET[arg_et].value.type == VARIABLE_OT)
               error("Only constants can be used as possible 'random' results");
-                                array_entry(arg_c, ET[arg_et].value);
+                                array_entry(arg_c, FALSE, ET[arg_et].value);
                             }
-                            finish_array(arg_c);
+                            finish_array(arg_c, FALSE);
 
                             assemblez_1_to(random_zc, AO, temp_var1);
                             assemblez_dec(temp_var1);
@@ -2525,9 +2536,9 @@ static void generate_code_from(int n, int void_flag)
                             {   if (ET[arg_et].value.type == LOCALVAR_OT
                                     || ET[arg_et].value.type == GLOBALVAR_OT)
               error("Only constants can be used as possible 'random' results");
-                                array_entry(arg_c, ET[arg_et].value);
+                                array_entry(arg_c, FALSE, ET[arg_et].value);
                             }
-                            finish_array(arg_c);
+                            finish_array(arg_c, FALSE);
 
                             assembleg_2(random_gc, AO, stack_pointer);
                             assembleg_3(aload_gc, AO2, stack_pointer, Result);
index 79f7c7a30227b01e69d7cff5c03fab16870eefde..c5f79bcfff89b5c2c7d3dfb344f1363acc6e0250 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "expressp" :  The expression parser                                     */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -164,6 +164,9 @@ but not used as a value:", unicode);
                 case ARRAY_T:
                     current_token.marker = ARRAY_MV;
                     break;
+                case STATIC_ARRAY_T:
+                    current_token.marker = STATIC_ARRAY_MV;
+                    break;
                 case INDIVIDUAL_PROPERTY_T:
                     if (module_switch) current_token.marker = IDENT_MV;
                     break;
index 6e4bec4314c757805640562a28cb57b75041902d..156b21501d726263479fb0bb898ac15ccc65927d 100644 (file)
@@ -7,7 +7,7 @@
 /*             routines in "inform.c", since they are tied up with ICL       */
 /*             settings and are very host OS-dependent.                      */
 /*                                                                           */
-/*  Copyright (c) Graham Nelson 1993 - 2018                                  */
+/*  Copyright (c) Graham Nelson 1993 - 2020                                  */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -1184,12 +1184,57 @@ game features require version 0x%08lx", (long)requested_glulx_version, (long)Ver
 
     }
     
-    /*  (4.5)  Output any null bytes (required to reach a GPAGESIZE address)
+    /*  (5)  Output static arrays (if any). */
+    {
+        /* We have to backpatch entries mentioned in staticarray_backpatch_table. */
+        int32 size_before_arrays = size;
+        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);
+            /* 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));
+            while (jx<offset) {
+                sf_put(static_array_area[jx]);
+                size++;
+                jx++;
+            }
+
+            /* Write out the converted value of the backpatch marker. */
+            val = static_array_area[jx++];
+            val = (val << 8) | static_array_area[jx++];
+            val = (val << 8) | static_array_area[jx++];
+            val = (val << 8) | static_array_area[jx++];
+            val = backpatch_value(val);
+            sf_put((val >> 24) & 0xFF);
+            sf_put((val >> 16) & 0xFF);
+            sf_put((val >> 8) & 0xFF);
+            sf_put((val) & 0xFF);
+            size += 4;
+        }
+
+        /* Flush out the last bit of static_array_area, after the last backpatch marker. */
+        offset = static_array_area_size;
+        while (jx<offset) {
+            sf_put(static_array_area[jx]);
+            size++;
+            jx++;
+        }
+
+        if (size_before_arrays + static_array_area_size != size)
+            compiler_error("Static array output length did not match");
+    }
+
+    /*  (5.5)  Output any null bytes (required to reach a GPAGESIZE address)
              before RAMSTART. */
 
     while (size % GPAGESIZE) { sf_put(0); size++; }
 
-    /*  (5)  Output RAM. */
+    /*  (6)  Output RAM. */
 
     for (i=0; i<RAM_Size; i++)
     {   sf_put(zmachine_paged_memory[i]); size++;
index 66c57cfb32d3e20123352d354917c55073cf063a..d9e1cac3b32989e18a3a0535363c1f3c06df2eec 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   Header file for Inform:  Z-machine ("Infocom" format) compiler          */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -1303,6 +1303,7 @@ typedef struct operator_s
 #define OBJECT_T              9
 #define CLASS_T               10
 #define FAKE_ACTION_T         11
+#define STATIC_ARRAY_T        12
 
 /* ------------------------------------------------------------------------- */
 /*   Statusline_flag values                                                  */
@@ -1478,6 +1479,7 @@ typedef struct operator_s
 #define FATALERROR_DK   33
 #define WARNING_DK      34
 #define TERMINATING_DK  35
+#define STATIC_DK       36
 
 /*  Index numbers into the keyword group "trace_keywords" (see "lexer.c")  */
 
@@ -1859,7 +1861,7 @@ typedef struct operator_s
 #define PROP_ZA                4
 #define CLASS_NUMBERS_ZA       5
 #define INDIVIDUAL_PROP_ZA     6
-#define DYNAMIC_ARRAY_ZA       7 /* Z-code only */
+#define DYNAMIC_ARRAY_ZA       7
 #define GRAMMAR_ZA             8
 #define ACTIONS_ZA             9
 #define PREACTIONS_ZA         10
@@ -1870,8 +1872,7 @@ typedef struct operator_s
 #define LINK_DATA_ZA          15
 
 #define SYMBOLS_ZA            16
-
-#define ARRAY_ZA              17 /* Glulx only */
+#define STATIC_ARRAY_ZA       17 /* Z-code only */
 #define GLOBALVAR_ZA          18 /* Glulx only */
 
 /* ------------------------------------------------------------------------- */
@@ -1887,7 +1888,7 @@ typedef struct operator_s
 #define INCON_MV               3     /* "Hardware" constant (table address) */
 #define IROUTINE_MV            4     /* Call to internal routine */
 #define VROUTINE_MV            5     /* Call to veneer routine */
-#define ARRAY_MV               6     /* Ref to internal array address */
+#define ARRAY_MV               6     /* Ref to internal dynam array address */
 #define NO_OBJS_MV             7     /* Ref to number of game objects */
 #define INHERIT_MV             8     /* Inherited property value */
 #define INHERIT_INDIV_MV       9     /* Inherited indiv property value */
@@ -1903,8 +1904,9 @@ typedef struct operator_s
 #define INDIVPT_MV            14     /* Individual prop table address */
 #define ACTION_MV             15     /* Action number */
 #define OBJECT_MV             16     /* Ref to internal object number */
+#define STATIC_ARRAY_MV       17     /* Ref to internal static array address */
 
-#define LARGEST_BPATCH_MV     16     /* Larger marker values are never written
+#define LARGEST_BPATCH_MV     17     /* Larger marker values are never written
                                         to backpatch tables */
 
 /* Value indicating an imported symbol record: */
@@ -2059,17 +2061,19 @@ extern void verbs_free_arrays(void);
 extern int no_globals, no_arrays;
 extern int dynamic_array_area_size;
 extern int *dynamic_array_area;
+extern int static_array_area_size;
+extern int *static_array_area;
 extern int32 *global_initial_value;
 extern int32 *array_symbols;
-extern int  *array_sizes, *array_types;
+extern int  *array_sizes, *array_types, *array_locs;
 
 extern void make_global(int array_flag, int name_only);
 extern void set_variable_value(int i, int32 v);
 extern void check_globals(void);
 extern int32 begin_table_array(void);
 extern int32 begin_word_array(void);
-extern void array_entry(int32 i, assembly_operand VAL);
-extern void finish_array(int32 i);
+extern void array_entry(int32 i, int is_static, assembly_operand VAL);
+extern void finish_array(int32 i, int is_static);
 
 /* ------------------------------------------------------------------------- */
 /*   Extern definitions for "asm"                                            */
@@ -2195,8 +2199,10 @@ extern void parse_assembly(void);
 /*   Extern definitions for "bpatch"                                         */
 /* ------------------------------------------------------------------------- */
 
-extern memory_block zcode_backpatch_table, zmachine_backpatch_table;
-extern int32 zcode_backpatch_size, zmachine_backpatch_size;
+extern memory_block zcode_backpatch_table, staticarray_backpatch_table,
+    zmachine_backpatch_table;
+extern int32 zcode_backpatch_size, staticarray_backpatch_size,
+    zmachine_backpatch_size;
 extern int   backpatch_marker, backpatch_error_flag;
 
 extern int32 backpatch_value(int32 value);
@@ -2678,7 +2684,8 @@ extern int32
     action_names_offset,    fake_action_names_offset,
     routine_names_offset,   routines_array_offset, routine_flags_array_offset,
     global_names_offset,    global_flags_array_offset,
-    array_flags_array_offset, constant_names_offset, constants_array_offset;
+    array_flags_array_offset, constant_names_offset, constants_array_offset,
+    static_arrays_offset;
 extern int32
     arrays_offset, object_tree_offset, grammar_table_offset,
     abbreviations_offset;    /* For Glulx */
index ac8db8ecf352c0aeaba633d9afb776ea4c08d8c5..083d21a732a96547893b2cf98186db0e6fec53c5 100644 (file)
@@ -2,7 +2,7 @@
 /*   "inform" :  The top level of Inform: switches, pathnames, filenaming    */
 /*               conventions, ICL (Inform Command Line) files, main          */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index f03aba5703428703b503cf1f2c5e3c002167f541..e136994da20b156dc1d20defc3ecdcf5475c8b72 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "lexer" : Lexical analyser                                              */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -493,7 +493,7 @@ keyword_group directive_keywords =
     "string", "table", "buffer", "data", "initial", "initstr",
     "with", "private", "has", "class",
     "error", "fatalerror", "warning",
-    "terminating",
+    "terminating", "static",
     "" },
     DIR_KEYWORD_TT, FALSE, TRUE
 };
index 5841fdc4c57b1f4016b3c9496fef54110746a612..4966a689e2f08ebd0c6b08a83cf00b8dcb8994fd 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "linker" : For compiling and linking modules                            */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index fc8a446f1c7d83219231d063054be2d2bd8b5024..21dcf57efc10b500d9e95cd0f2988d0dcd2a5e37 100644 (file)
@@ -2,7 +2,7 @@
 /*   "memory" : Memory management and ICL memory setting commands            */
 /*              (For "memoryerror", see "errors.c")                          */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -170,6 +170,14 @@ extern void my_free(void *pointer, char *whatitwas)
 /* ------------------------------------------------------------------------- */
 /*   Extensible blocks of memory, providing a kind of RAM disc as an         */
 /*   alternative to the temporary files option                               */
+/*                                                                           */
+/*   The allocation is slightly confusing. A block can store up to 72        */
+/*   chunks, which are allocated as needed when data is written. (Data does  */
+/*   not have to be written in order, but you should not try to read a byte  */
+/*   before writing it.) The size of a chunk is defined by ALLOC_CHUNK_SIZE. */
+/*   So any block can store any amount of data, but you increase the limit   */
+/*   (for all blocks) by increasing ALLOC_CHUNK_SIZE, not the number of      */
+/*   chunks.                                                                 */
 /* ------------------------------------------------------------------------- */
 
 static char chunk_name_buffer[60];
@@ -179,6 +187,7 @@ static char *chunk_name(memory_block *MB, int no)
     if (MB == &zcode_area)          p = "Z-code area";
     if (MB == &link_data_area)      p = "link data area";
     if (MB == &zcode_backpatch_table) p = "Z-code backpatch table";
+    if (MB == &staticarray_backpatch_table) p = "Static array backpatch table";
     if (MB == &zmachine_backpatch_table) p = "Z-machine backpatch table";
     sprintf(chunk_name_buffer, "%s chunk %d", p, no);
     return(chunk_name_buffer);
index 88b1b6ab03f6fbdc49db305b9417e2eccf823da5..6039828132c7efd34c8a3b64fcd687b4bf4de3c7 100644 (file)
@@ -6,7 +6,7 @@
 /*                    checks syntax and translates such directives into      */
 /*                    specifications for the object-maker.                   */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index cd3b695a5777486926eec58c57e950c634bc8dc5..5fe55b3b9c2f27c646217b4fd2613a84064c4f8b 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "states" :  Statement translator                                        */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -184,7 +184,7 @@ static void parse_action(void)
             if (version_number==4)
                 assemblez_4_to(call_vs_zc, AO, AO2, AO3, AO4, temp_var1);
             else
-                assemblez_4(call_zc, AO, AO2, AO3, AO4);
+                assemblez_4_to(call_zc, AO, AO2, AO3, AO4, temp_var1);
             break;
           case 3:
             AO5 = code_generate(AO5, QUANTITY_CONTEXT, -1);
@@ -854,9 +854,9 @@ static void parse_statement_z(int break_label, int continue_label)
                          if (j > ln2) ln2 = j;
                      }
                      put_token_back();
-                     array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
+                     array_entry(ln++, FALSE, parse_expression(CONSTANT_CONTEXT));
                  } while (TRUE);
-                 finish_array(ln);
+                 finish_array(ln, FALSE);
                  if (ln == 0)
                      error("No lines of text given for 'box' display");
 
@@ -1815,9 +1815,9 @@ static void parse_statement_g(int break_label, int continue_label)
                          if (j > ln2) ln2 = j;
                      }
                      put_token_back();
-                     array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
+                     array_entry(ln++, FALSE, parse_expression(CONSTANT_CONTEXT));
                  } while (TRUE);
-                 finish_array(ln);
+                 finish_array(ln, FALSE);
                  if (ln == 0)
                      error("No lines of text given for 'box' display");
 
index 326316651af503cb2237cdd5bf86f6e72f3e8160..4d437ac65bc2401d5419546d9a1bf7a9b5545fc8 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "symbols" :  The symbols table; creating stock of reserved words        */
 /*                                                                           */
-/*  Copyright (c) Graham Nelson 1993 - 2018                                  */
+/*  Copyright (c) Graham Nelson 1993 - 2020                                  */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -297,6 +297,7 @@ extern char *typename(int type)
         case LABEL_T:               return("Label");
         case GLOBAL_VARIABLE_T:     return("Global variable");
         case ARRAY_T:               return("Array");
+        case STATIC_ARRAY_T:        return("Static array");
         case CONSTANT_T:            return("Defined constant");
         case ATTRIBUTE_T:           return("Attribute");
         case PROPERTY_T:            return("Property");
index 2486decb8969cd421de2bed9c24c74b5d376e72f..0896af9b3427441e3972eafe91f9ebe947ea4da4 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "syntax" : Syntax analyser and compiler                                 */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index 103f6f91e432566d96b63bf53f085c805113c9e5..df3cdfb10313679b342ada031e3b3e131a7b886e 100644 (file)
@@ -3,7 +3,7 @@
 /*               end of dynamic memory, gluing together all the required     */
 /*               tables.                                                     */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -32,7 +32,7 @@ uchar *zmachine_paged_memory;          /* Where we shall store the story file
                                           at the end of the compilation pass */
 
 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
-   the header, the code, and the static strings. */
+   the header, the code, the static arrays, and the static strings. */
 
 /* ------------------------------------------------------------------------- */
 /*   Offsets of various areas in the Z-machine: these are set to nominal     */
@@ -72,7 +72,8 @@ int32 code_offset,
       routine_flags_array_offset,
       global_names_offset,
       global_flags_array_offset,
-      array_flags_array_offset;
+      array_flags_array_offset,
+      static_arrays_offset;
 int32 arrays_offset,
       object_tree_offset,
       grammar_table_offset,
@@ -191,6 +192,8 @@ static int32 rough_size_of_paged_memory_z(void)
     total += (subtract_pointers(dictionary_top, dictionary))  /* dictionary */
              + ((module_switch)?30:0);                        /* module map */
 
+    total += static_array_area_size;                       /* static arrays */
+
     total += scale_factor*0x100            /* maximum null bytes before code */
             + 1000;             /* fudge factor (in case the above is wrong) */
 
@@ -201,7 +204,7 @@ static int32 rough_size_of_paged_memory_g(void)
 {
     /*  This function calculates a modest over-estimate of the amount of
         memory required to store the machine's paged memory area
-        (that is, everything up to the start of the code area).              */
+        (that is, everything past the start of RAM). */
 
     int32 total;
 
@@ -246,7 +249,8 @@ static void construct_storyfile_z(void)
     int32 globals_at=0, link_table_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,
-          terminating_chars_at=0, unicode_at=0, id_names_length=0;
+          terminating_chars_at=0, unicode_at=0, id_names_length=0,
+          static_arrays_at=0;
     int skip_backpatching = FALSE;
     char *output_called = (module_switch)?"module":"story file";
 
@@ -609,6 +613,12 @@ table format requested (producing number 2 format instead)");
         mark += 30;
     }
 
+    /*  ------------------------ Static Arrays ----------------------------- */
+
+    static_arrays_at = mark;
+    for (i=0; i<static_array_area_size; i++)
+        p[mark++] = static_array_area[i];
+    
     /*  ----------------- A gap before the code area ----------------------- */
     /*  (so that it will start at an exact packed address and so that all    */
     /*  routine packed addresses are >= 256, hence long constants)           */
@@ -706,6 +716,7 @@ or less.");
     prop_values_offset = object_props_at;
     static_memory_offset = grammar_table_at;
     grammar_table_offset = grammar_table_at;
+    static_arrays_offset = static_arrays_at;
 
     if (extend_memory_map)
     {   extend_offset=256;
@@ -1142,6 +1153,11 @@ printf("        + - - - - - - - - - - +   %05lx\n",
                                           (long int) map_of_module);
 printf("        | map of module addrs |\n");
 }
+if (static_array_area_size)
+{
+printf("        +---------------------+   %05lx\n", (long int) static_arrays_at);
+printf("        |    static arrays    |\n");
+}
 printf("        +=====================+   %05lx\n", (long int) Write_Code_At);
 printf("Above   |       Z-code        |\n");
 printf("readable+---------------------+   %05lx\n",
@@ -1196,7 +1212,7 @@ static void construct_storyfile_g(void)
     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;
+        unicode_at, arrays_at, static_arrays_at;
     int32 threespaces, code_length;
     char *output_called = (module_switch)?"module":"story file";
 
@@ -1256,8 +1272,10 @@ static void construct_storyfile_g(void)
     Write_Strings_At = Write_Code_At + code_length;
     strings_length = compression_table_size + compression_string_size;
 
+    static_arrays_at = Write_Strings_At + strings_length;
+
     /* Now figure out where RAM starts. */
-    Write_RAM_At = Write_Strings_At + strings_length;
+    Write_RAM_At = static_arrays_at + static_array_area_size;
     /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
     while (Write_RAM_At % GPAGESIZE)
       Write_RAM_At++;
@@ -1568,6 +1586,7 @@ table format requested (producing number 2 format instead)");
 
     code_offset = Write_Code_At;
     strings_offset = Write_Strings_At;
+    static_arrays_offset = static_arrays_at;
 
     /*  --------------------------- The Header ----------------------------- */
 
@@ -1739,9 +1758,10 @@ Out:   %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
         write_debug_section("string decoding table", Write_Strings_At);
         write_debug_section("strings area",
                             Write_Strings_At + compression_table_size);
-        if (Write_Strings_At + strings_length < Write_RAM_At)
+        write_debug_section("static array space", static_arrays_at);
+        if (static_arrays_at + static_array_area_size < Write_RAM_At)
         {   write_debug_section
-                ("zero padding", Write_Strings_At + strings_length);
+                ("zero padding", static_arrays_at + static_array_area_size);
         }
         if (globals_at)
         {   compiler_error("Failed assumption that globals are at start of "
@@ -1784,6 +1804,12 @@ printf("        | string decode table |\n");
 printf("        + - - - - - - - - - - +   %06lx\n",
   (long int) Write_Strings_At + compression_table_size);
 printf("        |       strings       |\n");
+            if (static_array_area_size)
+            {
+printf("        +---------------------+   %06lx\n", 
+  (long int) (static_arrays_at));
+printf("        |    static arrays    |\n");
+            }
 printf("        +=====================+   %06lx\n", 
   (long int) (Write_RAM_At+globals_at));
 printf("Dynamic |  global variables   |\n");
@@ -1911,6 +1937,7 @@ extern void init_tables_vars(void)
       identifier_names_offset=0x800;
       class_numbers_offset = 0x800;
       arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
+      static_arrays_offset = 0x0800;
     }
     else {
       code_offset = 0x12345;
@@ -1924,6 +1951,7 @@ extern void init_tables_vars(void)
       individuals_offset=0x12345;
       identifier_names_offset=0x12345;
       class_numbers_offset = 0x12345;
+      static_arrays_offset = 0x12345;
     }
 }
 
index cd2fcd8c7b589fc8a642eb983621cb635f1d6aa1..31612387929280e1516df021592ac09109cf2e4b 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /*   "text" : Text translation, the abbreviations optimiser, the dictionary  */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
index 2f701595ebe104b6a7a0237edc820a800260583e..519e08552617f3547d5122dfcf8837f66784c6d9 100644 (file)
@@ -3,7 +3,7 @@
 /*              by the compiler (e.g. DefArt) which the program doesn't      */
 /*              provide                                                      */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
+/* Copyright (c) Graham Nelson 1993 - 2020                                   */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */
@@ -246,7 +246,11 @@ static VeneerRoutine VRs_z[VENEER_ROUTINES] =
          {   if (identifier >= 1 && identifier < 64 && obj.#identifier <= 2)\
                  return obj.identifier;\
              RT__Err(\"read\", obj, identifier); return; }\
+         #IFV3;\
+         if (obj..#identifier > 2) RT__Err(\"read\", obj, identifier);\
+         #IFNOT;\
          if (obj..#identifier > 2) RT__Err(\"read\", obj, identifier, 2);\
+         #ENDIF;\
          return x-->0;\
          ]", "", "", "", "", ""
     },
@@ -2244,7 +2248,7 @@ static void compile_symbol_table_routine(void)
             AO3.marker = 0;
             assemblez_store(temp_var3, AO3);
             AO3.value = svals[array_symbols[j]];
-            AO3.marker = ARRAY_MV;
+            AO3.marker = (!array_locs[j] ? ARRAY_MV : STATIC_ARRAY_MV);
             assemblez_1(ret_zc, AO3);
             assemble_label_no(nl);
         }
index 1116e096f4c7cada59d97ef9c5e929882a0a4b31..f9f13be90eb94530318d9fffdfaf756fa9d5c43b 100644 (file)
@@ -2,7 +2,7 @@
 /*   "verbs" :  Manages actions and grammar tables; parses the directives    */
 /*              Verb and Extend.                                             */
 /*                                                                           */
-/*  Copyright (c) Graham Nelson 1993 - 2018                                  */
+/*  Copyright (c) Graham Nelson 1993 - 2020                                  */
 /*                                                                           */
 /* This file is part of Inform.                                              */
 /*                                                                           */