Implement a Makefile for Inform.
[inform.git] / src / bpatch.c
index ccc87badabc23049659ce1bf93f754e3487620b9..c1bd1bbb5c48e77417ec39481771775c416f8ccd 100644 (file)
@@ -2,9 +2,8 @@
 /*   "bpatch" : Keeps track of, and finally acts on, backpatch markers,      */
 /*              correcting symbol values not known at compilation time       */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2018                                   */
-/*                                                                           */
-/* This file is part of Inform.                                              */
+/*   Part of Inform 6.41                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2022                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
 
 #include "header.h"
 
-memory_block zcode_backpatch_table, zmachine_backpatch_table;
-int32 zcode_backpatch_size, zmachine_backpatch_size;
+uchar *staticarray_backpatch_table; /* Allocated to staticarray_backpatch_size */
+memory_list staticarray_backpatch_table_memlist;
+uchar *zmachine_backpatch_table; /* Allocated to zmachine_backpatch_size */
+memory_list zmachine_backpatch_table_memlist;
+uchar *zcode_backpatch_table; /* Allocated to zcode_backpatch_size */
+memory_list zcode_backpatch_table_memlist;
+int32 zcode_backpatch_size, staticarray_backpatch_size,
+    zmachine_backpatch_size;
+
+/* ------------------------------------------------------------------------- */
+/*   Marker values                                                           */
+/* ------------------------------------------------------------------------- */
+
+extern char *describe_mv(int mval)
+{   switch(mval)
+    {   case NULL_MV:       return("null");
+
+        /*  Marker values used in ordinary story file backpatching  */
+
+        case DWORD_MV:      return("dictionary word");
+        case STRING_MV:     return("string literal");
+        case INCON_MV:      return("system constant");
+        case IROUTINE_MV:   return("routine");
+        case VROUTINE_MV:   return("veneer routine");
+        case ARRAY_MV:      return("internal array");
+        case NO_OBJS_MV:    return("the number of objects");
+        case INHERIT_MV:    return("inherited common p value");
+        case INDIVPT_MV:    return("indiv prop table address");
+        case INHERIT_INDIV_MV: return("inherited indiv p value");
+        case MAIN_MV:       return("ref to Main");
+        case SYMBOL_MV:     return("ref to symbol value");
+
+        /*  Additional marker values used in Glulx backpatching
+            (IDENT_MV is not really used at all any more) */
+
+        case VARIABLE_MV:   return("global variable");
+        case IDENT_MV:      return("prop identifier number");
+        case ACTION_MV:     return("action");
+        case OBJECT_MV:     return("internal object");
+
+    }
+    return("** No such MV **");
+}
 
 /* ------------------------------------------------------------------------- */
 /*   The mending operation                                                   */
@@ -37,7 +77,7 @@ static int32 backpatch_value_z(int32 value)
 
     ASSERT_ZCODE();
 
-    if (asm_trace_level >= 4)
+    if (bpatch_trace_setting)
         printf("BP %s applied to %04x giving ",
             describe_mv(backpatch_marker), value);
 
@@ -46,6 +86,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);
@@ -53,7 +95,7 @@ static int32 backpatch_value_z(int32 value)
             break;
         case VROUTINE_MV:
             if ((value<0) || (value>=VENEER_ROUTINES))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error
                     ("Backpatch veneer routine number out of range"))
                 {   printf("Illegal BP veneer routine number: %d\n", value);
@@ -71,7 +113,7 @@ static int32 backpatch_value_z(int32 value)
             value = no_objects; break;
         case INCON_MV:
             if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error
                     ("Backpatch system constant number out of range"))
                 {   printf("Illegal BP system constant number: %d\n", value);
@@ -83,7 +125,7 @@ static int32 backpatch_value_z(int32 value)
             value = value_of_system_constant(value); break;
         case DWORD_MV:
             value = dictionary_offset + 7 +
-                    final_dict_order[value]*((version_number==3)?7:9);
+                    final_dict_order[value]*(DICT_ENTRY_BYTE_LENGTH);
             break;
         case ACTION_MV:
             break;
@@ -102,17 +144,17 @@ static int32 backpatch_value_z(int32 value)
             break;
         case MAIN_MV:
             value = symbol_index("Main", -1);
-            if (stypes[value] != ROUTINE_T)
+            if (symbols[value].type != ROUTINE_T)
                 error("No 'Main' routine has been defined");
-            sflags[value] |= USED_SFLAG;
-            value = svals[value];
+            symbols[value].flags |= USED_SFLAG;
+            value = symbols[value].value;
             if (OMIT_UNUSED_ROUTINES)
                 value = df_stripped_address_for_address(value);
             value += code_offset/scale_factor;
             break;
         case SYMBOL_MV:
             if ((value<0) || (value>=no_symbols))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error("Backpatch symbol number out of range"))
                 {   printf("Illegal BP symbol number: %d\n", value);
                     backpatch_error_flag = TRUE;
@@ -120,34 +162,32 @@ static int32 backpatch_value_z(int32 value)
                 value = 0;
                 break;
             }
-            if (sflags[value] & UNKNOWN_SFLAG)
-            {   if (!(sflags[value] & UERROR_SFLAG))
-                {   sflags[value] |= UERROR_SFLAG;
+            if (symbols[value].flags & UNKNOWN_SFLAG)
+            {   if (!(symbols[value].flags & UERROR_SFLAG))
+                {   symbols[value].flags |= UERROR_SFLAG;
                     error_named_at("No such constant as",
-                        (char *) symbs[value], slines[value]);
+                        symbols[value].name, symbols[value].line);
                 }
             }
             else
-            if (sflags[value] & CHANGE_SFLAG)
-            {   sflags[value] &= (~(CHANGE_SFLAG));
-                backpatch_marker = (svals[value]/0x10000);
+            if (symbols[value].flags & CHANGE_SFLAG)
+            {   symbols[value].flags &= (~(CHANGE_SFLAG));
+                backpatch_marker = (symbols[value].marker);
                 if ((backpatch_marker < 0)
                     || (backpatch_marker > LARGEST_BPATCH_MV))
                 {
-                    if (no_link_errors == 0)
-                    {   compiler_error_named(
+                    compiler_error_named(
                         "Illegal backpatch marker attached to symbol",
-                        (char *) symbs[value]);
-                        backpatch_error_flag = TRUE;
-                    }
+                        symbols[value].name);
+                    backpatch_error_flag = TRUE;
                 }
                 else
-                    svals[value] = backpatch_value_z((svals[value]) % 0x10000);
+                    symbols[value].value = backpatch_value_z((symbols[value].value) % 0x10000);
             }
 
-            sflags[value] |= USED_SFLAG;
-            {   int t = stypes[value];
-                value = svals[value];
+            symbols[value].flags |= USED_SFLAG;
+            {   int t = symbols[value].type;
+                value = symbols[value].value;
                 switch(t)
                 {   case ROUTINE_T: 
                         if (OMIT_UNUSED_ROUTINES)
@@ -155,11 +195,11 @@ 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;
         default:
-            if (no_link_errors > 0) break;
             if (compiler_error("Illegal backpatch marker"))
             {   printf("Illegal backpatch marker %d value %04x\n",
                     backpatch_marker, value);
@@ -168,7 +208,7 @@ static int32 backpatch_value_z(int32 value)
             break;
     }
 
-    if (asm_trace_level >= 4) printf(" %04x\n", value);
+    if (bpatch_trace_setting) printf(" %04x\n", value);
 
     return(value);
 }
@@ -179,7 +219,7 @@ static int32 backpatch_value_g(int32 value)
 
     ASSERT_GLULX();
 
-    if (asm_trace_level >= 4)
+    if (bpatch_trace_setting)
         printf("BP %s applied to %04x giving ",
             describe_mv(backpatch_marker), value);
 
@@ -196,6 +236,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:
@@ -203,7 +245,7 @@ static int32 backpatch_value_g(int32 value)
             break;
         case VROUTINE_MV:
             if ((value<0) || (value>=VENEER_ROUTINES))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error
                     ("Backpatch veneer routine number out of range"))
                 {   printf("Illegal BP veneer routine number: %d\n", value);
@@ -221,7 +263,7 @@ static int32 backpatch_value_g(int32 value)
             value = no_objects; break;
         case INCON_MV:
             if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error
                     ("Backpatch system constant number out of range"))
                 {   printf("Illegal BP system constant number: %d\n", value);
@@ -249,17 +291,17 @@ static int32 backpatch_value_g(int32 value)
             break;
         case MAIN_MV:
             value = symbol_index("Main", -1);
-            if (stypes[value] != ROUTINE_T)
+            if (symbols[value].type != ROUTINE_T)
                 error("No 'Main' routine has been defined");
-            sflags[value] |= USED_SFLAG;
-            value = svals[value];
+            symbols[value].flags |= USED_SFLAG;
+            value = symbols[value].value;
             if (OMIT_UNUSED_ROUTINES)
                 value = df_stripped_address_for_address(value);
             value += code_offset;
             break;
         case SYMBOL_MV:
             if ((value<0) || (value>=no_symbols))
-            {   if (no_link_errors > 0) break;
+            {
                 if (compiler_error("Backpatch symbol number out of range"))
                 {   printf("Illegal BP symbol number: %d\n", value);
                     backpatch_error_flag = TRUE;
@@ -267,34 +309,32 @@ static int32 backpatch_value_g(int32 value)
                 value = 0;
                 break;
             }
-            if (sflags[value] & UNKNOWN_SFLAG)
-            {   if (!(sflags[value] & UERROR_SFLAG))
-                {   sflags[value] |= UERROR_SFLAG;
+            if (symbols[value].flags & UNKNOWN_SFLAG)
+            {   if (!(symbols[value].flags & UERROR_SFLAG))
+                {   symbols[value].flags |= UERROR_SFLAG;
                     error_named_at("No such constant as",
-                        (char *) symbs[value], slines[value]);
+                        symbols[value].name, symbols[value].line);
                 }
             }
             else
-            if (sflags[value] & CHANGE_SFLAG)
-            {   sflags[value] &= (~(CHANGE_SFLAG));
-                backpatch_marker = smarks[value];
+            if (symbols[value].flags & CHANGE_SFLAG)
+            {   symbols[value].flags &= (~(CHANGE_SFLAG));
+                backpatch_marker = symbols[value].marker;
                 if ((backpatch_marker < 0)
                     || (backpatch_marker > LARGEST_BPATCH_MV))
                 {
-                    if (no_link_errors == 0)
-                    {   compiler_error_named(
+                    compiler_error_named(
                         "Illegal backpatch marker attached to symbol",
-                        (char *) symbs[value]);
-                        backpatch_error_flag = TRUE;
-                    }
+                        symbols[value].name);
+                    backpatch_error_flag = TRUE;
                 }
                 else
-                    svals[value] = backpatch_value_g(svals[value]);
+                    symbols[value].value = backpatch_value_g(symbols[value].value);
             }
 
-            sflags[value] |= USED_SFLAG;
-            {   int t = stypes[value];
-                value = svals[value];
+            symbols[value].flags |= USED_SFLAG;
+            {   int t = symbols[value].type;
+                value = symbols[value].value;
                 switch(t)
                 {
                     case ROUTINE_T:
@@ -303,6 +343,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 + 
@@ -313,6 +354,7 @@ static int32 backpatch_value_g(int32 value)
                       break;
                     case CONSTANT_T:
                     case INDIVIDUAL_PROPERTY_T:
+                    case PROPERTY_T:
                       /* value is unchanged */
                       break;
                     default:
@@ -323,7 +365,6 @@ symbol");
             }
             break;
         default:
-            if (no_link_errors > 0) break;
             if (compiler_error("Illegal backpatch marker"))
             {   printf("Illegal backpatch marker %d value %04x\n",
                     backpatch_marker, value);
@@ -332,7 +373,7 @@ symbol");
             break;
     }
 
-    if (asm_trace_level >= 4) printf(" %04x\n", value);
+    if (bpatch_trace_setting) printf(" %04x\n", value);
 
     return(value);
 }
@@ -346,35 +387,25 @@ extern int32 backpatch_value(int32 value)
 }
 
 static void backpatch_zmachine_z(int mv, int zmachine_area, int32 offset)
-{   if (module_switch)
-    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
-    }
-    else
-    {   if (mv == OBJECT_MV) return;
-        if (mv == IDENT_MV) return;
-        if (mv == ACTION_MV) return;
-    }
-
-    /* printf("MV %d ZA %d Off %04x\n", mv, zmachine_area, offset); */
-
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, mv);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, zmachine_area);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, offset/256);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, offset%256);
+{   
+    if (mv == OBJECT_MV) return;
+    if (mv == IDENT_MV) return;
+    if (mv == ACTION_MV) return;
+
+    if (bpatch_trace_setting >= 2)
+        printf("BP added: MV %d ZA %d Off %04x\n", mv, zmachine_area, offset);
+
+    ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+4);
+    zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = offset/256;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = offset%256;
 }
 
 static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
-{   if (module_switch)
-    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
-    }
-    else
-    {   if (mv == IDENT_MV) return;
-        if (mv == ACTION_MV) return;
-    }
+{   
+    if (mv == IDENT_MV) return;
+    if (mv == ACTION_MV) return;
 
 /* The backpatch table format for Glulx:
    First, the marker byte.
@@ -382,20 +413,16 @@ static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
    Then the four-byte address.
 */
 
-/*    printf("+MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);  */
-
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, mv);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, zmachine_area);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 24) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 16) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset >> 8) & 0xFF);
-    write_byte_to_memory_block(&zmachine_backpatch_table,
-        zmachine_backpatch_size++, (offset) & 0xFF);
+    if (bpatch_trace_setting >= 2)
+        printf("BP added: MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);
+
+    ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+6);
+    zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 24) & 0xFF;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 16) & 0xFF;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 8) & 0xFF;
+    zmachine_backpatch_table[zmachine_backpatch_size++] = (offset) & 0xFF;
 }
 
 extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
@@ -412,12 +439,12 @@ extern void backpatch_zmachine_image_z(void)
     backpatch_error_flag = FALSE;
     while (bm < zmachine_backpatch_size)
     {   backpatch_marker
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
+            = zmachine_backpatch_table[bm];
         zmachine_area
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
+            = zmachine_backpatch_table[bm+1];
         offset
-          = 256*read_byte_from_memory_block(&zmachine_backpatch_table,bm+2)
-            + read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
+          = 256*zmachine_backpatch_table[bm+2]
+            + zmachine_backpatch_table[bm+3];
         bm += 4;
 
         switch(zmachine_area)
@@ -425,10 +452,10 @@ 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"))
-                        backpatch_error_flag = TRUE;
+                if (compiler_error("Illegal area to backpatch"))
+                    backpatch_error_flag = TRUE;
         }
         addr += offset;
 
@@ -440,9 +467,8 @@ extern void backpatch_zmachine_image_z(void)
 
         if (backpatch_error_flag)
         {   backpatch_error_flag = FALSE;
-            if (no_link_errors == 0)
-                printf("*** MV %d ZA %d Off %04x ***\n",
-                    backpatch_marker, zmachine_area, offset);
+            printf("*** MV %d ZA %d Off %04x ***\n",
+                backpatch_marker, zmachine_area, offset);
         }
     }
 }
@@ -453,28 +479,26 @@ extern void backpatch_zmachine_image_g(void)
     backpatch_error_flag = FALSE;
     while (bm < zmachine_backpatch_size)
     {   backpatch_marker
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
+            = zmachine_backpatch_table[bm];
         zmachine_area
-            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
-        offset = read_byte_from_memory_block(&zmachine_backpatch_table, bm+2);
+            = zmachine_backpatch_table[bm+1];
+        offset = zmachine_backpatch_table[bm+2];
         offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
+          zmachine_backpatch_table[bm+3];
         offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+4);
+          zmachine_backpatch_table[bm+4];
         offset = (offset << 8) |
-          read_byte_from_memory_block(&zmachine_backpatch_table, bm+5);
-            bm += 6;
-
-        /* printf("-MV %d ZA %d Off %06x\n", backpatch_marker, zmachine_area, offset);  */
+          zmachine_backpatch_table[bm+5];
+        bm += 6;
 
             switch(zmachine_area) {   
         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"))
               backpatch_error_flag = TRUE;
         }
@@ -492,9 +516,8 @@ extern void backpatch_zmachine_image_g(void)
 
         if (backpatch_error_flag)
         {   backpatch_error_flag = FALSE;
-            if (no_link_errors == 0)
-                printf("*** MV %d ZA %d Off %04x ***\n",
-                    backpatch_marker, zmachine_area, offset);
+            printf("*** MV %d ZA %d Off %04x ***\n",
+                backpatch_marker, zmachine_area, offset);
         }
     }
 }
@@ -504,22 +527,34 @@ extern void backpatch_zmachine_image_g(void)
 /* ------------------------------------------------------------------------- */
 
 extern void init_bpatch_vars(void)
-{   initialise_memory_block(&zcode_backpatch_table);
-    initialise_memory_block(&zmachine_backpatch_table);
+{   zcode_backpatch_table = NULL;
+    staticarray_backpatch_table = NULL;
+    zmachine_backpatch_table = NULL;
 }
 
 extern void bpatch_begin_pass(void)
 {   zcode_backpatch_size = 0;
+    staticarray_backpatch_size = 0;
     zmachine_backpatch_size = 0;
 }
 
 extern void bpatch_allocate_arrays(void)
 {
+    initialise_memory_list(&zcode_backpatch_table_memlist,
+        sizeof(uchar), 128, (void**)&zcode_backpatch_table,
+        "code backpatch table");
+    initialise_memory_list(&staticarray_backpatch_table_memlist,
+        sizeof(uchar), 128, (void**)&staticarray_backpatch_table,
+        "static array backpatch table");
+    initialise_memory_list(&zmachine_backpatch_table_memlist,
+        sizeof(uchar), 128, (void**)&zmachine_backpatch_table,
+        "machine backpatch table");
 }
 
 extern void bpatch_free_arrays(void)
-{   deallocate_memory_block(&zcode_backpatch_table);
-    deallocate_memory_block(&zmachine_backpatch_table);
+{   deallocate_memory_list(&zcode_backpatch_table_memlist);
+    deallocate_memory_list(&staticarray_backpatch_table_memlist);
+    deallocate_memory_list(&zmachine_backpatch_table_memlist);
 }
 
 /* ========================================================================= */