Update to commit e33eef4f8fab800eaf4a32b2d159cde6c4bbb38e
[inform.git] / src / symbols.c
index 4d437ac65bc2401d5419546d9a1bf7a9b5545fc8..6d736e940832cf1893b288d8417811a57e61fd24 100644 (file)
@@ -1,9 +1,8 @@
 /* ------------------------------------------------------------------------- */
 /*   "symbols" :  The symbols table; creating stock of reserved words        */
 /*                                                                           */
-/*  Copyright (c) Graham Nelson 1993 - 2020                                  */
-/*                                                                           */
-/* This file is part of Inform.                                              */
+/*   Part of Inform 6.35                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2021                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
@@ -16,7 +15,7 @@
 /* GNU General Public License for more details.                              */
 /*                                                                           */
 /* You should have received a copy of the GNU General Public License         */
-/* along with Inform. If not, see https://gnu.org/licenses/                  */
+/* along with Inform. If not, see https://gnu.org/licenses/                  *
 /*                                                                           */
 /* ------------------------------------------------------------------------- */
 
@@ -90,6 +89,8 @@ static char** symbol_name_space_chunks; /* For chunks of memory used to hold
                                            the name strings of symbols       */
 static int no_symbol_name_space_chunks;
 
+/* Symbol replacements (used by the "Replace X Y" directive). */
+
 typedef struct value_pair_struct {
     int original_symbol;
     int renamed_symbol;
@@ -98,6 +99,18 @@ static value_pair_t *symbol_replacements;
 static int symbol_replacements_count;
 static int symbol_replacements_size; /* calloced size */
 
+/* Symbol definitions requested at compile time. (There may not be any.)
+   These are set up at command-line parse time, not in init_symbols_vars().
+   Similarly, they are not cleaned up by symbols_free_arrays(). */
+
+typedef struct keyvalue_pair_struct {
+    char *symbol;
+    int32 value;
+} keyvalue_pair_t;
+static keyvalue_pair_t *symbol_definitions = NULL;
+static int symbol_definitions_count = 0;
+static int symbol_definitions_size = 0; /* calloced size */
+
 /* ------------------------------------------------------------------------- */
 /*   The symbols table is "hash-coded" into a disjoint union of linked       */
 /*   lists, so that for any symbol i, next_entry[i] is either -1 (meaning    */
@@ -171,6 +184,28 @@ extern int strcmpcis(char *p, char *q)
     return -qc;
 }
 
+/* ------------------------------------------------------------------------- */
+
+extern void add_config_symbol_definition(char *symbol, int32 value)
+{
+    if (symbol_definitions_count == symbol_definitions_size) {
+        int oldsize = symbol_definitions_size;
+        if (symbol_definitions_size == 0) 
+            symbol_definitions_size = 4;
+        else
+            symbol_definitions_size *= 2;
+        my_recalloc(&symbol_definitions, sizeof(keyvalue_pair_t), oldsize,
+            symbol_definitions_size, "symbol definition table");
+    }
+
+    char *str = my_malloc(strlen(symbol)+1, "symbol name");
+    strcpy(str, symbol);
+    
+    symbol_definitions[symbol_definitions_count].symbol = str;
+    symbol_definitions[symbol_definitions_count].value = value;
+    symbol_definitions_count++;
+}
+
 /* ------------------------------------------------------------------------- */
 /*   Symbol finding, creating, and removing.                                 */
 /* ------------------------------------------------------------------------- */
@@ -392,7 +427,7 @@ extern void write_the_identifier_names(void)
 
     veneer_mode = TRUE;
 
-    null_value = compile_string(unknown_attribute, FALSE, FALSE);
+    null_value = compile_string(unknown_attribute, STRCTX_SYMBOL);
     for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
 
     for (i=0; i<no_symbols; i++)
@@ -412,14 +447,14 @@ extern void write_the_identifier_names(void)
                     }
 
                     individual_name_strings[svals[i]]
-                        = compile_string(idname_string, FALSE, FALSE);
+                        = compile_string(idname_string, STRCTX_SYMBOL);
                 }
             }
             else
             {   sprintf(idname_string, "%s", (char *) symbs[i]);
 
                 individual_name_strings[svals[i]]
-                    = compile_string(idname_string, FALSE, FALSE);
+                    = compile_string(idname_string, STRCTX_SYMBOL);
             }
         }
         if (t == ATTRIBUTE_T)
@@ -437,14 +472,14 @@ extern void write_the_identifier_names(void)
                     }
 
                     attribute_name_strings[svals[i]]
-                        = compile_string(idname_string, FALSE, FALSE);
+                        = compile_string(idname_string, STRCTX_SYMBOL);
                 }
             }
             else
             {   sprintf(idname_string, "%s", (char *) symbs[i]);
 
                 attribute_name_strings[svals[i]]
-                    = compile_string(idname_string, FALSE, FALSE);
+                    = compile_string(idname_string, STRCTX_SYMBOL);
             }
         }
         if (sflags[i] & ACTION_SFLAG)
@@ -460,7 +495,7 @@ extern void write_the_identifier_names(void)
             }
 
             action_name_strings[svals[i]]
-                = compile_string(idname_string, FALSE, FALSE);
+                = compile_string(idname_string, STRCTX_SYMBOL);
         }
     }
 
@@ -471,7 +506,7 @@ extern void write_the_identifier_names(void)
 
             action_name_strings[svals[i]
                     - ((grammar_version_number==1)?256:4096) + no_actions]
-                = compile_string(idname_string, FALSE, FALSE);
+                = compile_string(idname_string, STRCTX_SYMBOL);
         }
     }
 
@@ -480,21 +515,21 @@ extern void write_the_identifier_names(void)
         sprintf(idname_string, "%s", (char *) symbs[i]);
 
         array_name_strings[j]
-            = compile_string(idname_string, FALSE, FALSE);
+            = compile_string(idname_string, STRCTX_SYMBOL);
     }
   if (define_INFIX_switch)
   { for (i=0; i<no_symbols; i++)
     {   if (stypes[i] == GLOBAL_VARIABLE_T)
         {   sprintf(idname_string, "%s", (char *) symbs[i]);
             array_name_strings[no_arrays + svals[i] -16]
-                = compile_string(idname_string, FALSE, FALSE);
+                = compile_string(idname_string, STRCTX_SYMBOL);
         }
     }
 
     for (i=0; i<no_named_routines; i++)
     {   sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
             array_name_strings[no_arrays + no_globals + i]
-                = compile_string(idname_string, FALSE, FALSE);
+                = compile_string(idname_string, STRCTX_SYMBOL);
     }
 
     for (i=0, no_named_constants=0; i<no_symbols; i++)
@@ -504,7 +539,7 @@ extern void write_the_identifier_names(void)
         {   sprintf(idname_string, "%s", (char *) symbs[i]);
             array_name_strings[no_arrays + no_globals + no_named_routines
                 + no_named_constants++]
-                = compile_string(idname_string, FALSE, FALSE);
+                = compile_string(idname_string, STRCTX_SYMBOL);
         }
     }
   }
@@ -598,13 +633,28 @@ static void emit_debug_information_for_predefined_symbol
 
 static void create_symbol(char *p, int32 value, int type)
 {   int i = symbol_index(p, -1);
+    if (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))) {
+        /* Symbol already defined! */
+        if (svals[i] == value && stypes[i] == type) {
+            /* Special case: the symbol was already defined with this same
+               value. We let it pass. */
+            return;
+        }
+        else {
+            ebf_symbol_error("new symbol", p, typename(stypes[i]), slines[i]);
+            return;
+        }
+    }
     svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
-    sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
+    /* If the symbol already existed with REDEFINABLE_SFLAG, we keep that. */
+    sflags[i] = USED_SFLAG + SYSTEM_SFLAG + (sflags[i] & REDEFINABLE_SFLAG);
     emit_debug_information_for_predefined_symbol(p, i, value, type);
 }
 
 static void create_rsymbol(char *p, int value, int type)
 {   int i = symbol_index(p, -1);
+    /* This is only called for a few symbols with known names.
+       They will not collide. */
     svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
     sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
     emit_debug_information_for_predefined_symbol(p, i, value, type);
@@ -749,6 +799,15 @@ static void stockup_symbols(void)
         create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
         create_symbol("FLOAT_NAN",       0x7FC00000, CONSTANT_T);
     }
+
+    if (symbol_definitions && symbol_definitions_count) {
+        int ix;
+        for (ix=0; ix<symbol_definitions_count; ix++) {
+            char *str = symbol_definitions[ix].symbol;
+            int32 val = symbol_definitions[ix].value;
+            create_symbol(str, val, CONSTANT_T);
+        }
+    }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -1053,8 +1112,10 @@ extern void locate_dead_functions(void)
        mark them as used. */
 
     func = df_functions_head;
-    if (!func || func->address != DF_NOT_IN_FUNCTION)
+    if (!func || func->address != DF_NOT_IN_FUNCTION) {
         compiler_error("DF: Global namespace entry is not at the head of the chain.");
+        return;
+    }
 
     for (ent = func->refs; ent; ent=ent->refsnext) {
         uint32 addr;
@@ -1224,6 +1285,8 @@ uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
 {
     df_function_t *func;
     int count;
+    int beg;
+    int end;
 
     if (!track_unused_routines)
         compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
@@ -1251,13 +1314,14 @@ uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
 
     /* Do a binary search. Maintain beg <= res < end, where res is the
        function containing the desired address. */
-    int beg = 0;
-    int end = df_functions_sorted_count;
+    beg = 0;
+    end = df_functions_sorted_count;
 
     /* Set stripped flag until we decide on a non-stripped function. */
     *stripped = TRUE;
 
     while (1) {
+        int new;
         if (beg >= end) {
             error("DF: offset_for_code_offset: Could not locate address.");
             return 0;
@@ -1269,7 +1333,7 @@ uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
             *stripped = FALSE;
             return func->newaddress + (offset - func->address);
         }
-        int new = (beg + end) / 2;
+        new = (beg + end) / 2;
         if (new <= beg || new >= end)
             compiler_error("DF: binary search went off the rails");