/* "bpatch" : Keeps track of, and finally acts on, backpatch markers, */
/* correcting symbol values not known at compilation time */
/* */
-/* Part of Inform 6.40 */
-/* copyright (c) Graham Nelson 1993 - 2022 */
+/* Part of Inform 6.42 */
+/* copyright (c) Graham Nelson 1993 - 2024 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
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 STATIC_ARRAY_MV: return("internal static 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");
+
+ /* Only occurs secondary to another reported error */
+ case ERROR_MV: return("error");
+
+ }
+ return("** No such MV **");
+}
+
+extern char *describe_mv_short(int mval)
+{ switch(mval)
+ { case NULL_MV: return("");
+
+ /* Marker values used in ordinary story file backpatching */
+
+ case DWORD_MV: return("dict");
+ case STRING_MV: return("str");
+ case INCON_MV: return("syscon");
+ case IROUTINE_MV: return("rtn");
+ case VROUTINE_MV: return("vrtn");
+ case ARRAY_MV: return("arr");
+ case STATIC_ARRAY_MV: return("stat-arr");
+ case NO_OBJS_MV: return("obj-count");
+ case INHERIT_MV: return("inh-com");
+ case INDIVPT_MV: return("indiv-ptab");
+ case INHERIT_INDIV_MV: return("inh-indiv");
+ case MAIN_MV: return("main");
+ case SYMBOL_MV: return("sym");
+
+ /* Additional marker values used in Glulx backpatching
+ (IDENT_MV is not really used at all any more) */
+
+ case VARIABLE_MV: return("glob");
+ case IDENT_MV: return("prop");
+ case ACTION_MV: return("action");
+ case OBJECT_MV: return("obj");
+
+ case LABEL_MV: return("lbl");
+ case DELETED_MV: return("del");
+
+ /* Only occurs secondary to another reported error */
+ case ERROR_MV: return("err");
+
+ }
+ if (mval >= BRANCH_MV && mval < BRANCHMAX_MV) return "br";
+
+ return("???");
+}
+
/* ------------------------------------------------------------------------- */
/* The mending operation */
/* ------------------------------------------------------------------------- */
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);
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);
value += individuals_offset;
break;
case MAIN_MV:
- value = symbol_index("Main", -1);
- if (symbols[value].type != ROUTINE_T)
+ value = get_symbol_index("Main");
+ if (value < 0 || (symbols[value].flags & UNKNOWN_SFLAG)) {
error("No 'Main' routine has been defined");
+ value = 0;
+ break;
+ }
+ if (symbols[value].type != ROUTINE_T) {
+ ebf_symbol_error("'Main' routine", symbols[value].name, typename(symbols[value].type), symbols[value].line);
+ value = 0;
+ break;
+ }
symbols[value].flags |= USED_SFLAG;
value = symbols[value].value;
if (OMIT_UNUSED_ROUTINES)
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;
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",
symbols[value].name);
- backpatch_error_flag = TRUE;
- }
+ backpatch_error_flag = TRUE;
}
else
symbols[value].value = backpatch_value_z((symbols[value].value) % 0x10000);
}
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);
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);
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);
value += individuals_offset;
break;
case MAIN_MV:
- value = symbol_index("Main", -1);
- if (symbols[value].type != ROUTINE_T)
+ value = get_symbol_index("Main");
+ if (value < 0 || (symbols[value].flags & UNKNOWN_SFLAG)) {
error("No 'Main' routine has been defined");
+ value = 0;
+ break;
+ }
+ if (symbols[value].type != ROUTINE_T) {
+ ebf_symbol_error("'Main' routine", symbols[value].name, typename(symbols[value].type), symbols[value].line);
+ value = 0;
+ break;
+ }
symbols[value].flags |= USED_SFLAG;
value = symbols[value].value;
if (OMIT_UNUSED_ROUTINES)
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;
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",
symbols[value].name);
- backpatch_error_flag = TRUE;
- }
+ backpatch_error_flag = TRUE;
}
else
symbols[value].value = backpatch_value_g(symbols[value].value);
}
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);
}
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;
- }
+{
+ 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);
}
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.
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;
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);
}
}
}
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;
}
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);
}
}
}