/* 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. */
/* */
/* */
/* 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;
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
/* 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");
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");
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
{
/* | = <value> */
/* | <array specification> */
/* */
-/* Array <arrayname> <array specification> */
+/* Array <arrayname> [static] <array specification> */
/* */
/* where an array specification is: */
/* */
/* | --> | <entry-1> ... <entry-n> */
/* | string | [ <entry-1> [,] [;] <entry-2> ... <entry-n> ]; */
/* | table */
+/* | buffer */
+/* */
+/* The "static" keyword (arrays only) places the array in static memory. */
/* */
/* ------------------------------------------------------------------------- */
int32 i;
int array_type, data_type;
+ int is_static = FALSE;
assembly_operand AO;
int32 global_symbol;
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;
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) {
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)
{
}
}
- { 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;
}
}
- array_entry(i, AO);
+ array_entry(i, is_static, AO);
i++;
} while (TRUE);
put_token_back();
}
chars.marker = 0;
set_constant_ot(&chars);
- array_entry(i, chars);
+ array_entry(i, is_static, chars);
}
}
break;
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>");
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);
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;
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;
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;
}
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");
}
/* ------------------------------------------------------------------------- */
/* "asm" : The Inform assembler */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
/* "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 */
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);
value += code_offset/scale_factor;
break;
case ARRAY_T: value += variables_offset; break;
+ case STATIC_ARRAY_T: value += static_arrays_offset; break;
}
}
break;
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:
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 +
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"))
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"))
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;
}
extern void bpatch_free_arrays(void)
{ deallocate_memory_block(&zcode_backpatch_table);
+ deallocate_memory_block(&staticarray_backpatch_table);
deallocate_memory_block(&zmachine_backpatch_table);
}
/* ------------------------------------------------------------------------- */
/* "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. */
/* */
/* ------------------------------------------------------------------------- */
/* "directs" : Directives (# commands) */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
/* "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. */
/* */
/* ------------------------------------------------------------------------- */
/* "expressc" : The expression code generator */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
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);
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 {
/* 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++;
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;
}
}
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)
{
/* 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 */
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);
{ 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);
/* ------------------------------------------------------------------------- */
/* "expressp" : The expression parser */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
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;
/* 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. */
/* */
}
- /* (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++;
/* ------------------------------------------------------------------------- */
/* 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. */
/* */
#define OBJECT_T 9
#define CLASS_T 10
#define FAKE_ACTION_T 11
+#define STATIC_ARRAY_T 12
/* ------------------------------------------------------------------------- */
/* Statusline_flag values */
#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") */
#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
#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 */
/* ------------------------------------------------------------------------- */
#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 */
#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: */
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" */
/* 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);
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 */
/* "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. */
/* */
/* ------------------------------------------------------------------------- */
/* "lexer" : Lexical analyser */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
"string", "table", "buffer", "data", "initial", "initstr",
"with", "private", "has", "class",
"error", "fatalerror", "warning",
- "terminating",
+ "terminating", "static",
"" },
DIR_KEYWORD_TT, FALSE, TRUE
};
/* ------------------------------------------------------------------------- */
/* "linker" : For compiling and linking modules */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
/* "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. */
/* */
/* ------------------------------------------------------------------------- */
/* 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];
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);
/* 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. */
/* */
/* ------------------------------------------------------------------------- */
/* "states" : Statement translator */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
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);
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");
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");
/* ------------------------------------------------------------------------- */
/* "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. */
/* */
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");
/* ------------------------------------------------------------------------- */
/* "syntax" : Syntax analyser and compiler */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2018 */
+/* Copyright (c) Graham Nelson 1993 - 2020 */
/* */
/* This file is part of Inform. */
/* */
/* 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. */
/* */
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 */
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,
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) */
{
/* 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;
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";
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) */
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;
(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",
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";
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++;
code_offset = Write_Code_At;
strings_offset = Write_Strings_At;
+ static_arrays_offset = static_arrays_at;
/* --------------------------- The Header ----------------------------- */
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 "
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");
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;
individuals_offset=0x12345;
identifier_names_offset=0x12345;
class_numbers_offset = 0x12345;
+ static_arrays_offset = 0x12345;
}
}
/* ------------------------------------------------------------------------- */
/* "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. */
/* */
/* 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. */
/* */
{ 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;\
]", "", "", "", "", ""
},
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);
}
/* "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. */
/* */