X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Farrays.c;h=320287b3c0c5fef909acd4f0355a26c5fd3cff3e;hb=8e63120c630c94c598d4e2d6ba823dac59bce8fa;hp=9c001ccb0ed57ec678f1c6542910ac257c8be8c2;hpb=d11f2f726ed7feea617476d99cf7505ddd9a27ce;p=inform.git diff --git a/src/arrays.c b/src/arrays.c index 9c001cc..320287b 100644 --- a/src/arrays.c +++ b/src/arrays.c @@ -3,8 +3,8 @@ /* likewise global variables, which are in some ways a */ /* simpler form of the same thing. */ /* */ -/* Part of Inform 6.35 */ -/* copyright (c) Graham Nelson 1993 - 2021 */ +/* Part of Inform 6.40 */ +/* 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 */ @@ -26,29 +26,30 @@ /* ------------------------------------------------------------------------- */ /* Arrays defined below: */ /* */ -/* int dynamic_array_area[] Initial values for the bytes of */ +/* uchar dynamic_array_area[] Initial values for the bytes of */ /* the dynamic array area */ -/* int static_array_area[] Initial values for the bytes of */ +/* uchar 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) */ +/* global variable (counting 0 - 239, */ +/* or higher for Glulx) */ /* */ /* The "dynamic array area" is the Z-machine area holding the current */ /* values of the global variables (in 240x2 = 480 bytes) followed by any */ -/* (dynamic) arrays which may be defined. Owing to a poor choice of name */ -/* some years ago, this is also called the "static data area", which is */ -/* why the memory setting for its maximum extent is "MAX_STATIC_DATA". */ +/* (dynamic) arrays which may be defined. */ /* */ -/* 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. */ +/* In Glulx, we don't keep the global variables in dynamic_array_area. */ +/* Array data starts at the start. */ /* */ /* 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. */ +/* The storage for these goes, unsurprisingly, into static_array_area. */ /* ------------------------------------------------------------------------- */ -int *dynamic_array_area; /* See above */ -int32 *global_initial_value; +uchar *dynamic_array_area; /* See above */ +memory_list dynamic_array_area_memlist; +int dynamic_array_area_size; /* Size in bytes */ + +int32 *global_initial_value; /* Allocated to no_globals */ +static memory_list global_initial_value_memlist; int no_globals; /* Number of global variables used by the programmer (Inform itself @@ -57,17 +58,13 @@ int no_globals; /* Number of global variables used /* In Glulx, Inform uses the bottom ten. */ -int dynamic_array_area_size; /* Size in bytes */ - -int *static_array_area; +uchar *static_array_area; +memory_list static_array_area_memlist; int static_array_area_size; int no_arrays; -int32 *array_symbols; -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. */ +arrayinfo *arrays; +static memory_list arrays_memlist; static int array_entry_size, /* 1 for byte array, 2 for word array */ array_base; /* Offset in dynamic array area of the @@ -81,16 +78,24 @@ static int array_entry_size, /* 1 for byte array, 2 for word array */ /* In Glulx, of course, that will be 4 instead of 2. */ +static memory_list current_array_name; /* The name of the global or array + currently being compiled. */ + +/* Complete the array. Fill in the size field (if it has one) and + advance foo_array_area_size. +*/ extern void finish_array(int32 i, int is_static) { - int *area; + uchar *area; int area_size; if (!is_static) { + ensure_memory_list_available(&dynamic_array_area_memlist, dynamic_array_area_size+array_base+1*array_entry_size); area = dynamic_array_area; area_size = dynamic_array_area_size; } else { + ensure_memory_list_available(&static_array_area_memlist, static_array_area_size+array_base+1*array_entry_size); area = static_array_area; area_size = static_array_area_size; } @@ -146,16 +151,22 @@ extern void finish_array(int32 i, int is_static) } +/* Fill in array entry i (in either the static or dynamic area). + When this is called, foo_array_area_size is the end of the previous + array; we're writing after that. +*/ extern void array_entry(int32 i, int is_static, assembly_operand VAL) { - int *area; + uchar *area; int area_size; if (!is_static) { + ensure_memory_list_available(&dynamic_array_area_memlist, dynamic_array_area_size+(i+1)*array_entry_size); area = dynamic_array_area; area_size = dynamic_array_area_size; } else { + ensure_memory_list_available(&static_array_area_memlist, static_array_area_size+(i+1)*array_entry_size); area = static_array_area; area_size = static_array_area_size; } @@ -163,9 +174,6 @@ extern void array_entry(int32 i, int is_static, assembly_operand VAL) if (!glulx_mode) { /* Array entry i (initial entry has i=0) is set to Z-machine value j */ - if (area_size+(i+1)*array_entry_size > MAX_STATIC_DATA) - memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA); - if (array_entry_size==1) { area[area_size+i] = (VAL.value)%256; @@ -198,9 +206,6 @@ extern void array_entry(int32 i, int is_static, assembly_operand VAL) else { /* Array entry i (initial entry has i=0) is set to value j */ - if (area_size+(i+1)*array_entry_size > MAX_STATIC_DATA) - memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA); - if (array_entry_size==1) { area[area_size+i] = (VAL.value) & 0xFF; @@ -223,22 +228,19 @@ extern void array_entry(int32 i, int is_static, assembly_operand VAL) if (VAL.marker != 0) { if (!is_static) { backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA, - addr - 4*MAX_GLOBAL_VARIABLES); + addr); } 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)); + if (bpatch_trace_setting >= 2) + printf("BP added: MV %d staticarray %04x\n", VAL.marker, addr); + ensure_memory_list_available(&staticarray_backpatch_table_memlist, staticarray_backpatch_size+5); + staticarray_backpatch_table[staticarray_backpatch_size++] = VAL.marker; + staticarray_backpatch_table[staticarray_backpatch_size++] = ((addr >> 24) & 0xFF); + staticarray_backpatch_table[staticarray_backpatch_size++] = ((addr >> 16) & 0xFF); + staticarray_backpatch_table[staticarray_backpatch_size++] = ((addr >> 8) & 0xFF); + staticarray_backpatch_table[staticarray_backpatch_size++] = (addr & 0xFF); } } } @@ -271,7 +273,11 @@ extern void array_entry(int32 i, int is_static, assembly_operand VAL) /* ------------------------------------------------------------------------- */ extern void set_variable_value(int i, int32 v) -{ global_initial_value[i]=v; +{ + /* This can be called during module-load to create a new global, + so we call ensure. */ + ensure_memory_list_available(&global_initial_value_memlist, i+1); + global_initial_value[i]=v; } /* There are four ways to initialise arrays: */ @@ -289,6 +295,7 @@ extern void make_global(int array_flag, int name_only) array_flag is always FALSE in that case. */ int32 i; + int name_length; int array_type, data_type; int is_static = FALSE; assembly_operand AO; @@ -296,7 +303,6 @@ extern void make_global(int array_flag, int name_only) int extraspace; int32 global_symbol; - const char *global_name; debug_location_beginning beginning_debug_location = get_token_location_beginning(); @@ -304,15 +310,18 @@ extern void make_global(int array_flag, int name_only) get_next_token(); i = token_value; global_symbol = i; - global_name = token_text; + + name_length = strlen(token_text) + 1; + ensure_memory_list_available(¤t_array_name, name_length); + strncpy(current_array_name.data, token_text, name_length); if (!glulx_mode) { - if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T) - && (svals[i] >= LOWEST_SYSTEM_VAR_NUMBER)) + if ((token_type==SYMBOL_TT) && (symbols[i].type==GLOBAL_VARIABLE_T) + && (symbols[i].value >= LOWEST_SYSTEM_VAR_NUMBER)) goto RedefinitionOfSystemVar; } else { - if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T)) + if ((token_type==SYMBOL_TT) && (symbols[i].type==GLOBAL_VARIABLE_T)) goto RedefinitionOfSystemVar; } @@ -324,15 +333,15 @@ extern void make_global(int array_flag, int name_only) panic_mode_error_recovery(); return; } - if (!(sflags[i] & UNKNOWN_SFLAG)) + if (!(symbols[i].flags & UNKNOWN_SFLAG)) { discard_token_location(beginning_debug_location); if (array_flag) - ebf_symbol_error("new array name", token_text, typename(stypes[i]), slines[i]); - else ebf_symbol_error("new global variable name", token_text, typename(stypes[i]), slines[i]); + ebf_symbol_error("new array name", token_text, typename(symbols[i].type), symbols[i].line); + else ebf_symbol_error("new global variable name", token_text, typename(symbols[i].type), symbols[i].line); panic_mode_error_recovery(); return; } - if ((!array_flag) && (sflags[i] & USED_SFLAG)) + if ((!array_flag) && (symbols[i].flags & USED_SFLAG)) error_named("Variable must be defined before use:", token_text); directive_keywords.enabled = TRUE; @@ -352,18 +361,13 @@ extern void make_global(int array_flag, int name_only) if (array_flag) { 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); + assign_symbol(i, dynamic_array_area_size, 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; + ensure_memory_list_available(&arrays_memlist, no_arrays+1); + arrays[no_arrays].symbol = i; } else { if (!glulx_mode && no_globals==233) @@ -372,19 +376,19 @@ extern void make_global(int array_flag, int name_only) panic_mode_error_recovery(); return; } - if (glulx_mode && no_globals==MAX_GLOBAL_VARIABLES) - { discard_token_location(beginning_debug_location); - memoryerror("MAX_GLOBAL_VARIABLES", MAX_GLOBAL_VARIABLES); - panic_mode_error_recovery(); - return; - } - - variable_tokens[MAX_LOCAL_VARIABLES+no_globals] = i; + + ensure_memory_list_available(&variables_memlist, MAX_LOCAL_VARIABLES+no_globals+1); + variables[MAX_LOCAL_VARIABLES+no_globals].token = i; + variables[MAX_LOCAL_VARIABLES+no_globals].usage = FALSE; assign_symbol(i, MAX_LOCAL_VARIABLES+no_globals, GLOBAL_VARIABLE_T); - variable_tokens[svals[i]] = i; - if (name_only) import_symbol(i); - else global_initial_value[no_globals++]=0; + if (name_only) { + import_symbol(i); + } + else { + ensure_memory_list_available(&global_initial_value_memlist, no_globals+1); + global_initial_value[no_globals++]=0; + } } directive_keywords.enabled = TRUE; @@ -405,10 +409,12 @@ extern void make_global(int array_flag, int name_only) } put_token_back(); if (debugfile_switch && !array_flag) - { debug_file_printf(""); + { + char *global_name = current_array_name.data; + debug_file_printf(""); debug_file_printf("%s", global_name); debug_file_printf("
"); - write_debug_global_backpatch(svals[global_symbol]); + write_debug_global_backpatch(symbols[global_symbol].value); debug_file_printf("
"); write_debug_locations (get_token_location_end(beginning_debug_location)); @@ -434,10 +440,12 @@ extern void make_global(int array_flag, int name_only) } global_initial_value[no_globals-1] = AO.value; if (debugfile_switch) - { debug_file_printf(""); + { + char *global_name = current_array_name.data; + debug_file_printf(""); debug_file_printf("%s", global_name); debug_file_printf("
"); - write_debug_global_backpatch(svals[global_symbol]); + write_debug_global_backpatch(symbols[global_symbol].value); debug_file_printf("
"); write_debug_locations (get_token_location_end(beginning_debug_location)); @@ -456,7 +464,7 @@ extern void make_global(int array_flag, int name_only) else { backpatch_zmachine(ARRAY_MV, GLOBALVAR_ZA, 4*(no_globals-1)); global_initial_value[no_globals-1] - = dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES; + = dynamic_array_area_size; } } @@ -542,9 +550,12 @@ extern void make_global(int array_flag, int name_only) static_array_area_size += extraspace; } - array_types[no_arrays] = array_type; - array_locs[no_arrays] = is_static; + arrays[no_arrays].type = array_type; + arrays[no_arrays].loc = is_static; + /* Note that, from this point, we must continue through finish_array(). + Exiting this routine on error causes problems. */ + switch(data_type) { case NULLS_AI: @@ -582,7 +593,12 @@ extern void make_global(int array_flag, int name_only) i=0; do - { get_next_token(); + { + /* This isn't the start of a statement, but it's safe to + release token texts anyway. Expressions in an array + list are independent of each other. */ + release_token_texts(); + get_next_token(); if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break; @@ -592,7 +608,6 @@ extern void make_global(int array_flag, int name_only) { discard_token_location(beginning_debug_location); error("Missing ';' to end the initial array values " "before \"[\" or \"]\""); - return; } put_token_back(); @@ -669,7 +684,12 @@ advance as part of 'Zcharacter table':", unicode); i = 0; while (TRUE) - { get_next_token(); + { + /* This isn't the start of a statement, but it's safe to + release token texts anyway. Expressions in an array + list are independent of each other. */ + release_token_texts(); + get_next_token(); if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) continue; if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP)) @@ -693,10 +713,11 @@ advance as part of 'Zcharacter table':", unicode); if (debugfile_switch) { int32 new_area_size; + char *global_name = current_array_name.data; debug_file_printf(""); debug_file_printf("%s", global_name); debug_file_printf(""); - write_debug_array_backpatch(svals[global_symbol]); + write_debug_array_backpatch(symbols[global_symbol].value); debug_file_printf(""); new_area_size = (!is_static ? dynamic_array_area_size : static_array_area_size); debug_file_printf @@ -717,7 +738,7 @@ advance as part of 'Zcharacter table':", unicode); if ((array_type==BYTE_ARRAY) || (array_type==WORD_ARRAY)) i--; if (array_type==BUFFER_ARRAY) i+=WORDSIZE-1; - array_sizes[no_arrays++] = i; + arrays[no_arrays++].size = i; } extern int32 begin_table_array(void) @@ -733,10 +754,7 @@ extern int32 begin_table_array(void) dynamic_array_area_size += array_entry_size; - if (!glulx_mode) - return array_base; - else - return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES; + return array_base; } extern int32 begin_word_array(void) @@ -748,10 +766,7 @@ extern int32 begin_word_array(void) array_base = dynamic_array_area_size; array_entry_size = WORDSIZE; - if (!glulx_mode) - return array_base; - else - return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES; + return array_base; } /* ========================================================================= */ @@ -761,41 +776,85 @@ extern int32 begin_word_array(void) extern void init_arrays_vars(void) { dynamic_array_area = NULL; static_array_area = NULL; + arrays = NULL; global_initial_value = NULL; - array_sizes = NULL; array_symbols = NULL; array_types = NULL; + variables = NULL; } extern void arrays_begin_pass(void) -{ no_arrays = 0; - if (!glulx_mode) - no_globals=0; - else - no_globals=11; - dynamic_array_area_size = WORDSIZE * MAX_GLOBAL_VARIABLES; +{ + int ix, totalvar; + + no_arrays = 0; + if (!glulx_mode) { + no_globals = 0; + /* The compiler-defined globals start at 239 and go down, so + we need to initialize the entire list from the start. */ + totalvar = MAX_ZCODE_GLOBAL_VARS; + } + else { + /* The compiler-defined globals run from 0 to 10. */ + no_globals = 11; + totalvar = no_globals; + } + + ensure_memory_list_available(&global_initial_value_memlist, totalvar); + for (ix=0; ix