2019-02-05 02:44:07 +02:00
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* "arrays" : Parses array declarations and constructs arrays from them; */
|
|
|
|
/* likewise global variables, which are in some ways a */
|
|
|
|
/* simpler form of the same thing. */
|
|
|
|
/* */
|
2022-07-24 13:10:45 +03:00
|
|
|
/* Part of Inform 6.41 */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* copyright (c) Graham Nelson 1993 - 2022 */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#include "header.h"
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* Arrays defined below: */
|
|
|
|
/* */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* uchar dynamic_array_area[] Initial values for the bytes of */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* the dynamic array area */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* uchar static_array_area[] Initial values for the bytes of */
|
2020-06-01 20:29:12 +03:00
|
|
|
/* the static array area */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* int32 global_initial_value[n] The initialised value of the nth */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* global variable (counting 0 - 239, */
|
|
|
|
/* or higher for Glulx) */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
|
|
|
/* The "dynamic array area" is the Z-machine area holding the current */
|
|
|
|
/* values of the global variables (in 240x2 = 480 bytes) followed by any */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* (dynamic) arrays which may be defined. */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* In Glulx, we don't keep the global variables in dynamic_array_area. */
|
|
|
|
/* Array data starts at the start. */
|
2020-06-01 20:29:12 +03:00
|
|
|
/* */
|
|
|
|
/* We can also store arrays (but not globals) into static memory (ROM). */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* The storage for these goes, unsurprisingly, into static_array_area. */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* ------------------------------------------------------------------------- */
|
2022-03-03 02:10:25 +02:00
|
|
|
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;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
int no_globals; /* Number of global variables used
|
|
|
|
by the programmer (Inform itself
|
|
|
|
uses the top seven -- but these do
|
|
|
|
not count) */
|
|
|
|
/* In Glulx, Inform uses the bottom
|
|
|
|
ten. */
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
uchar *static_array_area;
|
|
|
|
memory_list static_array_area_memlist;
|
2020-06-01 20:29:12 +03:00
|
|
|
int static_array_area_size;
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
int no_arrays;
|
2022-03-03 02:10:25 +02:00
|
|
|
arrayinfo *arrays;
|
|
|
|
static memory_list arrays_memlist;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
static int array_entry_size, /* 1 for byte array, 2 for word array */
|
|
|
|
array_base; /* Offset in dynamic array area of the
|
|
|
|
array being constructed. During the
|
|
|
|
same time, dynamic_array_area_size
|
|
|
|
is the offset of the initial entry
|
|
|
|
in the array: so for "table" and
|
|
|
|
"string" arrays, these numbers are
|
|
|
|
different (by 2 and 1 bytes resp) */
|
|
|
|
|
|
|
|
/* In Glulx, of course, that will be
|
|
|
|
4 instead of 2. */
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
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.
|
|
|
|
*/
|
2020-06-01 20:29:12 +03:00
|
|
|
extern void finish_array(int32 i, int is_static)
|
2019-02-05 02:44:07 +02:00
|
|
|
{
|
2022-03-03 02:10:25 +02:00
|
|
|
uchar *area;
|
2020-06-01 20:29:12 +03:00
|
|
|
int area_size;
|
|
|
|
|
|
|
|
if (!is_static) {
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&dynamic_array_area_memlist, dynamic_array_area_size+array_base+1*array_entry_size);
|
2020-06-01 20:29:12 +03:00
|
|
|
area = dynamic_array_area;
|
|
|
|
area_size = dynamic_array_area_size;
|
|
|
|
}
|
|
|
|
else {
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&static_array_area_memlist, static_array_area_size+array_base+1*array_entry_size);
|
2020-06-01 20:29:12 +03:00
|
|
|
area = static_array_area;
|
|
|
|
area_size = static_array_area_size;
|
|
|
|
}
|
2022-03-03 02:10:25 +02:00
|
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
error("An array must have at least one entry");
|
|
|
|
}
|
2020-06-01 20:29:12 +03:00
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
/* Write the array size into the 0th byte/word of the array, if it's
|
|
|
|
a "table" or "string" array */
|
|
|
|
if (!glulx_mode) {
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
if (array_base != area_size)
|
|
|
|
{ if (area_size-array_base==2)
|
|
|
|
{ area[array_base] = i/256;
|
|
|
|
area[array_base+1] = i%256;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ if (i>=256)
|
|
|
|
error("A 'string' array can have at most 256 entries");
|
2020-06-01 20:29:12 +03:00
|
|
|
area[array_base] = i;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
2020-06-01 20:29:12 +03:00
|
|
|
if (array_base != area_size)
|
|
|
|
{ if (area_size-array_base==4)
|
2019-02-05 02:44:07 +02:00
|
|
|
{
|
2020-06-01 20:29:12 +03:00
|
|
|
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;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ if (i>=256)
|
|
|
|
error("A 'string' array can have at most 256 entries");
|
2020-06-01 20:29:12 +03:00
|
|
|
area[array_base] = i;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
/* Move on the static/dynamic array size so that it now points to the
|
|
|
|
next available free space */
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
if (!is_static) {
|
|
|
|
dynamic_array_area_size += i*array_entry_size;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
static_array_area_size += i*array_entry_size;
|
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
/* 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.
|
|
|
|
*/
|
2020-06-01 20:29:12 +03:00
|
|
|
extern void array_entry(int32 i, int is_static, assembly_operand VAL)
|
2019-02-05 02:44:07 +02:00
|
|
|
{
|
2022-03-03 02:10:25 +02:00
|
|
|
uchar *area;
|
2020-06-01 20:29:12 +03:00
|
|
|
int area_size;
|
|
|
|
|
|
|
|
if (!is_static) {
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&dynamic_array_area_memlist, dynamic_array_area_size+(i+1)*array_entry_size);
|
2020-06-01 20:29:12 +03:00
|
|
|
area = dynamic_array_area;
|
|
|
|
area_size = dynamic_array_area_size;
|
|
|
|
}
|
|
|
|
else {
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&static_array_area_memlist, static_array_area_size+(i+1)*array_entry_size);
|
2020-06-01 20:29:12 +03:00
|
|
|
area = static_array_area;
|
|
|
|
area_size = static_array_area_size;
|
|
|
|
}
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
if (!glulx_mode) {
|
|
|
|
/* Array entry i (initial entry has i=0) is set to Z-machine value j */
|
|
|
|
|
|
|
|
if (array_entry_size==1)
|
2020-06-01 20:29:12 +03:00
|
|
|
{ area[area_size+i] = (VAL.value)%256;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
if (VAL.marker != 0)
|
|
|
|
error("Entries in byte arrays and strings must be known constants");
|
|
|
|
|
|
|
|
/* If the entry is too large for a byte array, issue a warning
|
|
|
|
and truncate the value */
|
|
|
|
else
|
|
|
|
if (VAL.value >= 256)
|
|
|
|
warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
|
|
|
|
}
|
|
|
|
else
|
2020-06-01 20:29:12 +03:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Array entry i (initial entry has i=0) is set to value j */
|
|
|
|
|
|
|
|
if (array_entry_size==1)
|
2020-06-01 20:29:12 +03:00
|
|
|
{ area[area_size+i] = (VAL.value) & 0xFF;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
if (VAL.marker != 0)
|
|
|
|
error("Entries in byte arrays and strings must be known constants");
|
|
|
|
|
|
|
|
/* If the entry is too large for a byte array, issue a warning
|
|
|
|
and truncate the value */
|
|
|
|
else
|
|
|
|
if (VAL.value >= 256)
|
|
|
|
warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255");
|
|
|
|
}
|
|
|
|
else if (array_entry_size==4)
|
2020-06-01 20:29:12 +03:00
|
|
|
{
|
|
|
|
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,
|
2022-03-03 02:10:25 +02:00
|
|
|
addr);
|
2020-06-01 20:29:12 +03:00
|
|
|
}
|
|
|
|
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). */
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting >= 2)
|
|
|
|
printf("BP added: MV %d staticarray %04x\n", VAL.marker, addr);
|
2022-03-03 02:10:25 +02:00
|
|
|
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);
|
2020-06-01 20:29:12 +03:00
|
|
|
}
|
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error("Somehow created an array of shorts");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* Global and Array directives. */
|
|
|
|
/* */
|
2022-07-24 13:10:45 +03:00
|
|
|
/* Global <variablename> [ [=] <value> ] */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
2020-06-01 20:29:12 +03:00
|
|
|
/* Array <arrayname> [static] <array specification> */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
|
|
|
/* where an array specification is: */
|
|
|
|
/* */
|
|
|
|
/* | -> | <number-of-entries> */
|
|
|
|
/* | --> | <entry-1> ... <entry-n> */
|
2022-03-03 02:10:25 +02:00
|
|
|
/* | string | [ <entry-1> [;] <entry-2> ... <entry-n> ]; */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* | table */
|
2020-06-01 20:29:12 +03:00
|
|
|
/* | buffer */
|
|
|
|
/* */
|
|
|
|
/* The "static" keyword (arrays only) places the array in static memory. */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
extern void set_variable_value(int i, int32 v)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
2022-07-24 13:10:45 +03:00
|
|
|
/* This isn't currently called to create a new global, but it has
|
|
|
|
been used that way within living memory. So we call ensure. */
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&global_initial_value_memlist, i+1);
|
|
|
|
global_initial_value[i]=v;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* There are four ways to initialise arrays: */
|
|
|
|
|
|
|
|
#define UNSPECIFIED_AI -1
|
|
|
|
#define NULLS_AI 0
|
|
|
|
#define DATA_AI 1
|
|
|
|
#define ASCII_AI 2
|
|
|
|
#define BRACKET_AI 3
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
extern void make_global()
|
2019-02-05 02:44:07 +02:00
|
|
|
{
|
|
|
|
int32 i;
|
2022-03-03 02:10:25 +02:00
|
|
|
int name_length;
|
2019-02-05 02:44:07 +02:00
|
|
|
assembly_operand AO;
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
int32 globalnum;
|
2019-02-05 02:44:07 +02:00
|
|
|
int32 global_symbol;
|
|
|
|
debug_location_beginning beginning_debug_location =
|
|
|
|
get_token_location_beginning();
|
|
|
|
|
|
|
|
directive_keywords.enabled = FALSE;
|
|
|
|
get_next_token();
|
|
|
|
i = token_value;
|
|
|
|
global_symbol = i;
|
2022-03-03 02:10:25 +02:00
|
|
|
|
|
|
|
name_length = strlen(token_text) + 1;
|
|
|
|
ensure_memory_list_available(¤t_array_name, name_length);
|
|
|
|
strncpy(current_array_name.data, token_text, name_length);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
if (!glulx_mode) {
|
2022-03-03 02:10:25 +02:00
|
|
|
if ((token_type==SYMBOL_TT) && (symbols[i].type==GLOBAL_VARIABLE_T)
|
2022-07-24 13:10:45 +03:00
|
|
|
&& (symbols[i].value >= LOWEST_SYSTEM_VAR_NUMBER)) {
|
|
|
|
globalnum = symbols[i].value - MAX_LOCAL_VARIABLES;
|
2019-02-05 02:44:07 +02:00
|
|
|
goto RedefinitionOfSystemVar;
|
2022-07-24 13:10:45 +03:00
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else {
|
2022-07-24 13:10:45 +03:00
|
|
|
if ((token_type==SYMBOL_TT) && (symbols[i].type==GLOBAL_VARIABLE_T)) {
|
|
|
|
globalnum = symbols[i].value - MAX_LOCAL_VARIABLES;
|
2019-02-05 02:44:07 +02:00
|
|
|
goto RedefinitionOfSystemVar;
|
2022-07-24 13:10:45 +03:00
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
if (token_type != SYMBOL_TT)
|
2019-02-05 02:44:07 +02:00
|
|
|
{ discard_token_location(beginning_debug_location);
|
2022-07-24 13:10:45 +03:00
|
|
|
ebf_error("new global variable name", token_text);
|
2019-02-05 02:44:07 +02:00
|
|
|
panic_mode_error_recovery(); return;
|
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
if (!(symbols[i].flags & UNKNOWN_SFLAG))
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
2022-07-24 13:10:45 +03:00
|
|
|
ebf_symbol_error("new global variable name", token_text, typename(symbols[i].type), symbols[i].line);
|
2022-03-03 02:10:25 +02:00
|
|
|
panic_mode_error_recovery(); return;
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (symbols[i].flags & USED_SFLAG)
|
2019-02-05 02:44:07 +02:00
|
|
|
error_named("Variable must be defined before use:", token_text);
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
directive_keywords.enabled = TRUE;
|
|
|
|
get_next_token();
|
|
|
|
directive_keywords.enabled = FALSE;
|
|
|
|
if ((token_type==DIR_KEYWORD_TT)&&(token_value==STATIC_DK)) {
|
2022-07-24 13:10:45 +03:00
|
|
|
error("Global variables cannot be static");
|
2020-06-01 20:29:12 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
put_token_back();
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (!glulx_mode && no_globals==233)
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
|
|
|
error("All 233 global variables already declared");
|
|
|
|
panic_mode_error_recovery();
|
|
|
|
return;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
globalnum = no_globals;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
ensure_memory_list_available(&global_initial_value_memlist, no_globals+1);
|
|
|
|
global_initial_value[no_globals++]=0;
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
directive_keywords.enabled = TRUE;
|
|
|
|
|
|
|
|
RedefinitionOfSystemVar:
|
|
|
|
|
|
|
|
get_next_token();
|
|
|
|
|
|
|
|
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
|
|
|
/* No initial value. */
|
2019-02-05 02:44:07 +02:00
|
|
|
put_token_back();
|
2022-07-24 13:10:45 +03:00
|
|
|
if (debugfile_switch)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
char *global_name = current_array_name.data;
|
|
|
|
debug_file_printf("<global-variable>");
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf("<identifier>%s</identifier>", global_name);
|
|
|
|
debug_file_printf("<address>");
|
2022-03-03 02:10:25 +02:00
|
|
|
write_debug_global_backpatch(symbols[global_symbol].value);
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf("</address>");
|
|
|
|
write_debug_locations
|
|
|
|
(get_token_location_end(beginning_debug_location));
|
|
|
|
debug_file_printf("</global-variable>");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (((token_type==SEP_TT)&&(token_value==ARROW_SEP))
|
|
|
|
|| ((token_type==SEP_TT)&&(token_value==DARROW_SEP))
|
|
|
|
|| ((token_type==DIR_KEYWORD_TT)&&(token_value==STRING_DK))
|
|
|
|
|| ((token_type==DIR_KEYWORD_TT)&&(token_value==TABLE_DK))
|
|
|
|
|| ((token_type==DIR_KEYWORD_TT)&&(token_value==BUFFER_DK)))
|
2019-02-05 02:44:07 +02:00
|
|
|
{
|
2022-07-24 13:10:45 +03:00
|
|
|
error("use 'Array' to define arrays, not 'Global'");
|
|
|
|
return;
|
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
/* Skip "=" if present. */
|
|
|
|
if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
|
|
|
|
put_token_back();
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
AO = parse_expression(CONSTANT_CONTEXT);
|
|
|
|
if (!glulx_mode) {
|
|
|
|
if (AO.marker != 0)
|
|
|
|
backpatch_zmachine(AO.marker, DYNAMIC_ARRAY_ZA,
|
|
|
|
2*globalnum);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (AO.marker != 0)
|
|
|
|
backpatch_zmachine(AO.marker, GLOBALVAR_ZA,
|
|
|
|
4*globalnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (globalnum < 0 || globalnum >= global_initial_value_memlist.count)
|
|
|
|
compiler_error("Globalnum out of range");
|
|
|
|
global_initial_value[globalnum] = AO.value;
|
|
|
|
|
|
|
|
if (debugfile_switch)
|
|
|
|
{
|
|
|
|
char *global_name = current_array_name.data;
|
|
|
|
debug_file_printf("<global-variable>");
|
|
|
|
debug_file_printf("<identifier>%s</identifier>", global_name);
|
|
|
|
debug_file_printf("<address>");
|
|
|
|
write_debug_global_backpatch(symbols[global_symbol].value);
|
|
|
|
debug_file_printf("</address>");
|
|
|
|
write_debug_locations
|
|
|
|
(get_token_location_end(beginning_debug_location));
|
|
|
|
debug_file_printf("</global-variable>");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void make_array()
|
|
|
|
{
|
|
|
|
int32 i;
|
|
|
|
int name_length;
|
|
|
|
int array_type, data_type;
|
|
|
|
int is_static = FALSE;
|
|
|
|
assembly_operand AO;
|
|
|
|
|
|
|
|
int extraspace;
|
|
|
|
|
|
|
|
int32 global_symbol;
|
|
|
|
debug_location_beginning beginning_debug_location =
|
|
|
|
get_token_location_beginning();
|
|
|
|
|
|
|
|
directive_keywords.enabled = FALSE;
|
|
|
|
get_next_token();
|
|
|
|
i = token_value;
|
|
|
|
global_symbol = i;
|
|
|
|
|
|
|
|
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 (token_type != SYMBOL_TT)
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
|
|
|
ebf_error("new array name", token_text);
|
|
|
|
panic_mode_error_recovery(); return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(symbols[i].flags & UNKNOWN_SFLAG))
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
|
|
|
ebf_symbol_error("new array name", token_text, typename(symbols[i].type), symbols[i].line);
|
|
|
|
panic_mode_error_recovery(); return;
|
|
|
|
}
|
|
|
|
|
|
|
|
directive_keywords.enabled = TRUE;
|
|
|
|
get_next_token();
|
|
|
|
directive_keywords.enabled = FALSE;
|
|
|
|
if ((token_type==DIR_KEYWORD_TT)&&(token_value==STATIC_DK)) {
|
|
|
|
is_static = TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
put_token_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_static) {
|
|
|
|
assign_symbol(i, dynamic_array_area_size, ARRAY_T);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
assign_symbol(i, static_array_area_size, STATIC_ARRAY_T);
|
|
|
|
}
|
|
|
|
ensure_memory_list_available(&arrays_memlist, no_arrays+1);
|
|
|
|
arrays[no_arrays].symbol = i;
|
|
|
|
|
|
|
|
directive_keywords.enabled = TRUE;
|
|
|
|
|
|
|
|
get_next_token();
|
|
|
|
|
|
|
|
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
|
|
|
|
{
|
|
|
|
discard_token_location(beginning_debug_location);
|
|
|
|
ebf_error("array definition", token_text);
|
|
|
|
put_token_back();
|
|
|
|
return;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
array_type = BYTE_ARRAY; data_type = UNSPECIFIED_AI;
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
/* The keywords "data", "initial", and "initstr" used to be accepted
|
|
|
|
here -- but only in a Global directive, not Array. The Global directive
|
|
|
|
no longer calls here, so those keywords are now (more) obsolete.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((token_type==SEP_TT)&&(token_value==ARROW_SEP))
|
2019-02-05 02:44:07 +02:00
|
|
|
array_type = BYTE_ARRAY;
|
|
|
|
else if ((token_type==SEP_TT)&&(token_value==DARROW_SEP))
|
|
|
|
array_type = WORD_ARRAY;
|
|
|
|
else if ((token_type==DIR_KEYWORD_TT)&&(token_value==STRING_DK))
|
|
|
|
array_type = STRING_ARRAY;
|
|
|
|
else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TABLE_DK))
|
|
|
|
array_type = TABLE_ARRAY;
|
|
|
|
else if ((token_type==DIR_KEYWORD_TT)&&(token_value==BUFFER_DK))
|
|
|
|
array_type = BUFFER_ARRAY;
|
|
|
|
else
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
2022-07-24 13:10:45 +03:00
|
|
|
ebf_error
|
|
|
|
("'->', '-->', 'string', 'table' or 'buffer'", token_text);
|
2019-02-05 02:44:07 +02:00
|
|
|
panic_mode_error_recovery();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
array_entry_size=1;
|
|
|
|
if ((array_type==WORD_ARRAY) || (array_type==TABLE_ARRAY))
|
|
|
|
array_entry_size=WORDSIZE;
|
|
|
|
|
|
|
|
get_next_token();
|
|
|
|
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
|
|
|
error("No array size or initial values given");
|
|
|
|
put_token_back();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(data_type)
|
|
|
|
{ case UNSPECIFIED_AI:
|
|
|
|
if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
|
|
|
|
data_type = BRACKET_AI;
|
|
|
|
else
|
|
|
|
{ data_type = NULLS_AI;
|
|
|
|
if (token_type == DQ_TT) data_type = ASCII_AI;
|
|
|
|
get_next_token();
|
|
|
|
if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
|
|
|
|
data_type = DATA_AI;
|
|
|
|
put_token_back();
|
|
|
|
put_token_back();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NULLS_AI: obsolete_warning("use '->' instead of 'data'"); break;
|
|
|
|
case DATA_AI: obsolete_warning("use '->' instead of 'initial'"); break;
|
|
|
|
case ASCII_AI: obsolete_warning("use '->' instead of 'initstr'"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Leave room to write the array size in later, if string/table array */
|
2020-06-01 20:29:12 +03:00
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
extraspace = 0;
|
2019-02-05 02:44:07 +02:00
|
|
|
if ((array_type==STRING_ARRAY) || (array_type==TABLE_ARRAY))
|
2020-06-01 20:29:12 +03:00
|
|
|
extraspace += array_entry_size;
|
2019-02-05 02:44:07 +02:00
|
|
|
if (array_type==BUFFER_ARRAY)
|
2020-06-01 20:29:12 +03:00
|
|
|
extraspace += WORDSIZE;
|
|
|
|
|
|
|
|
if (!is_static) {
|
|
|
|
array_base = dynamic_array_area_size;
|
|
|
|
dynamic_array_area_size += extraspace;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
array_base = static_array_area_size;
|
|
|
|
static_array_area_size += extraspace;
|
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
arrays[no_arrays].type = array_type;
|
|
|
|
arrays[no_arrays].loc = is_static;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
/* Note that, from this point, we must continue through finish_array().
|
|
|
|
Exiting this routine on error causes problems. */
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
switch(data_type)
|
|
|
|
{
|
|
|
|
case NULLS_AI:
|
|
|
|
|
|
|
|
AO = parse_expression(CONSTANT_CONTEXT);
|
|
|
|
|
|
|
|
CalculatedArraySize:
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
if (AO.marker != 0)
|
|
|
|
{ error("Array sizes must be known now, not defined later");
|
2019-02-05 02:44:07 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!glulx_mode) {
|
|
|
|
if ((AO.value <= 0) || (AO.value >= 32768))
|
|
|
|
{ error("An array must have between 1 and 32767 entries");
|
|
|
|
AO.value = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (AO.value <= 0 || (AO.value & 0x80000000))
|
|
|
|
{ error("An array may not have 0 or fewer entries");
|
|
|
|
AO.value = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
{ for (i=0; i<AO.value; i++) array_entry(i, is_static, zero_operand);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DATA_AI:
|
|
|
|
|
|
|
|
/* In this case the array is initialised to the sequence of
|
|
|
|
constant values supplied on the same line */
|
|
|
|
|
|
|
|
i=0;
|
|
|
|
do
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
/* 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();
|
2019-02-05 02:44:07 +02:00
|
|
|
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ((token_type == SEP_TT)
|
|
|
|
&& ((token_value == OPEN_SQUARE_SEP)
|
|
|
|
|| (token_value == CLOSE_SQUARE_SEP)))
|
|
|
|
{ discard_token_location(beginning_debug_location);
|
|
|
|
error("Missing ';' to end the initial array values "
|
|
|
|
"before \"[\" or \"]\"");
|
|
|
|
}
|
|
|
|
put_token_back();
|
|
|
|
|
|
|
|
AO = parse_expression(ARRAY_CONTEXT);
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
{ get_next_token();
|
|
|
|
put_token_back();
|
|
|
|
if ((token_type == SEP_TT)
|
|
|
|
&& (token_value == SEMICOLON_SEP))
|
|
|
|
{ data_type = NULLS_AI;
|
|
|
|
goto CalculatedArraySize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
array_entry(i, is_static, AO);
|
2019-02-05 02:44:07 +02:00
|
|
|
i++;
|
|
|
|
} while (TRUE);
|
|
|
|
put_token_back();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASCII_AI:
|
|
|
|
|
|
|
|
/* In this case the array is initialised to the ASCII values of
|
|
|
|
the characters of a given "quoted string" */
|
|
|
|
|
|
|
|
get_next_token();
|
|
|
|
if (token_type != DQ_TT)
|
|
|
|
{ ebf_error("literal text in double-quotes", token_text);
|
|
|
|
token_text = "error";
|
|
|
|
}
|
|
|
|
|
|
|
|
{ assembly_operand chars;
|
|
|
|
|
|
|
|
int j;
|
|
|
|
INITAO(&chars);
|
|
|
|
for (i=0,j=0; token_text[j]!=0; i++,j+=textual_form_length)
|
|
|
|
{
|
|
|
|
int32 unicode; int zscii;
|
|
|
|
unicode = text_to_unicode(token_text+j);
|
|
|
|
if (glulx_mode)
|
|
|
|
{
|
|
|
|
if (array_entry_size == 1 && (unicode < 0 || unicode >= 256))
|
|
|
|
{
|
|
|
|
error("Unicode characters beyond Latin-1 cannot be used in a byte array");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
chars.value = unicode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* Z-code */
|
|
|
|
{
|
|
|
|
zscii = unicode_to_zscii(unicode);
|
|
|
|
if ((zscii != 5) && (zscii < 0x100)) chars.value = zscii;
|
|
|
|
else
|
|
|
|
{ unicode_char_error("Character can only be used if declared in \
|
|
|
|
advance as part of 'Zcharacter table':", unicode);
|
|
|
|
chars.value = '?';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
chars.marker = 0;
|
|
|
|
set_constant_ot(&chars);
|
2020-06-01 20:29:12 +03:00
|
|
|
array_entry(i, is_static, chars);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BRACKET_AI:
|
|
|
|
|
|
|
|
/* In this case the array is initialised to the sequence of
|
|
|
|
constant values given over a whole range of compiler-lines,
|
|
|
|
between square brackets [ and ] */
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (TRUE)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
/* 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();
|
2019-02-05 02:44:07 +02:00
|
|
|
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
|
|
|
|
continue;
|
|
|
|
if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP))
|
|
|
|
break;
|
|
|
|
if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
|
|
|
|
{ /* Minimal error recovery: we assume that a ] has
|
|
|
|
been missed, and the programmer is now starting
|
|
|
|
a new routine */
|
|
|
|
|
|
|
|
ebf_error("']'", token_text);
|
|
|
|
put_token_back(); break;
|
|
|
|
}
|
|
|
|
put_token_back();
|
2020-06-01 20:29:12 +03:00
|
|
|
array_entry(i, is_static, parse_expression(ARRAY_CONTEXT));
|
2019-02-05 02:44:07 +02:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
finish_array(i, is_static);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
if (debugfile_switch)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
int32 new_area_size;
|
|
|
|
char *global_name = current_array_name.data;
|
|
|
|
debug_file_printf("<array>");
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf("<identifier>%s</identifier>", global_name);
|
|
|
|
debug_file_printf("<value>");
|
2022-03-03 02:10:25 +02:00
|
|
|
write_debug_array_backpatch(symbols[global_symbol].value);
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf("</value>");
|
2022-03-03 02:10:25 +02:00
|
|
|
new_area_size = (!is_static ? dynamic_array_area_size : static_array_area_size);
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf
|
|
|
|
("<byte-count>%d</byte-count>",
|
2020-06-01 20:29:12 +03:00
|
|
|
new_area_size - array_base);
|
2019-02-05 02:44:07 +02:00
|
|
|
debug_file_printf
|
|
|
|
("<bytes-per-element>%d</bytes-per-element>",
|
|
|
|
array_entry_size);
|
|
|
|
debug_file_printf
|
|
|
|
("<zeroth-element-holds-length>%s</zeroth-element-holds-length>",
|
|
|
|
(array_type == STRING_ARRAY || array_type == TABLE_ARRAY) ?
|
|
|
|
"true" : "false");
|
|
|
|
get_next_token();
|
|
|
|
write_debug_locations(get_token_location_end(beginning_debug_location));
|
|
|
|
put_token_back();
|
|
|
|
debug_file_printf("</array>");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((array_type==BYTE_ARRAY) || (array_type==WORD_ARRAY)) i--;
|
|
|
|
if (array_type==BUFFER_ARRAY) i+=WORDSIZE-1;
|
2022-03-03 02:10:25 +02:00
|
|
|
arrays[no_arrays++].size = i;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern int32 begin_table_array(void)
|
|
|
|
{
|
2020-06-01 20:29:12 +03:00
|
|
|
/* 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.) */
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
array_base = dynamic_array_area_size;
|
|
|
|
array_entry_size = WORDSIZE;
|
|
|
|
|
|
|
|
/* Leave room to write the array size in later */
|
|
|
|
|
|
|
|
dynamic_array_area_size += array_entry_size;
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
return array_base;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern int32 begin_word_array(void)
|
|
|
|
{
|
|
|
|
/* The "random(a, b, ...)" function needs to be able to construct
|
2020-06-01 20:29:12 +03:00
|
|
|
word arrays like this. (Static data, but we create a dynamic
|
|
|
|
array for maximum backwards compatibility.) */
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
array_base = dynamic_array_area_size;
|
|
|
|
array_entry_size = WORDSIZE;
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
return array_base;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
/* Data structure management routines */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
extern void init_arrays_vars(void)
|
|
|
|
{ dynamic_array_area = NULL;
|
2020-06-01 20:29:12 +03:00
|
|
|
static_array_area = NULL;
|
2022-03-03 02:10:25 +02:00
|
|
|
arrays = NULL;
|
2019-02-05 02:44:07 +02:00
|
|
|
global_initial_value = NULL;
|
2022-03-03 02:10:25 +02:00
|
|
|
variables = NULL;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void arrays_begin_pass(void)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
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<totalvar; ix++) {
|
|
|
|
global_initial_value[ix] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ensure_memory_list_available(&variables_memlist, MAX_LOCAL_VARIABLES+totalvar);
|
|
|
|
for (ix=0; ix<MAX_LOCAL_VARIABLES+totalvar; ix++) {
|
|
|
|
variables[ix].token = 0;
|
|
|
|
variables[ix].usage = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dynamic_array_area_size = 0;
|
|
|
|
|
|
|
|
if (!glulx_mode) {
|
|
|
|
int ix;
|
|
|
|
/* This initial segment of dynamic_array_area is never used. It's
|
|
|
|
notionally space for the global variables, but that data is
|
|
|
|
kept in the global_initial_value array. Nonetheless, all the
|
|
|
|
Z-compiler math is set up with the idea that arrays start at
|
|
|
|
WORDSIZE * MAX_ZCODE_GLOBAL_VARS, so we need the blank segment.
|
|
|
|
*/
|
|
|
|
dynamic_array_area_size = WORDSIZE * MAX_ZCODE_GLOBAL_VARS;
|
|
|
|
ensure_memory_list_available(&dynamic_array_area_memlist, dynamic_array_area_size);
|
|
|
|
for (ix=0; ix<WORDSIZE * MAX_ZCODE_GLOBAL_VARS; ix++)
|
|
|
|
dynamic_array_area[ix] = 0;
|
|
|
|
}
|
|
|
|
|
2020-06-01 20:29:12 +03:00
|
|
|
static_array_area_size = 0;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void arrays_allocate_arrays(void)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
initialise_memory_list(&dynamic_array_area_memlist,
|
|
|
|
sizeof(uchar), 10000, (void**)&dynamic_array_area,
|
2020-06-01 20:29:12 +03:00
|
|
|
"dynamic array data");
|
2022-03-03 02:10:25 +02:00
|
|
|
initialise_memory_list(&static_array_area_memlist,
|
|
|
|
sizeof(uchar), 0, (void**)&static_array_area,
|
2020-06-01 20:29:12 +03:00
|
|
|
"static array data");
|
2022-03-03 02:10:25 +02:00
|
|
|
initialise_memory_list(&arrays_memlist,
|
|
|
|
sizeof(arrayinfo), 64, (void**)&arrays,
|
|
|
|
"array info");
|
|
|
|
initialise_memory_list(&global_initial_value_memlist,
|
|
|
|
sizeof(int32), 200, (void**)&global_initial_value,
|
|
|
|
"global variable values");
|
|
|
|
|
|
|
|
initialise_memory_list(¤t_array_name,
|
|
|
|
sizeof(char), MAX_IDENTIFIER_LENGTH+1, NULL,
|
|
|
|
"array name currently being defined");
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void arrays_free_arrays(void)
|
2022-03-03 02:10:25 +02:00
|
|
|
{
|
|
|
|
deallocate_memory_list(&dynamic_array_area_memlist);
|
|
|
|
deallocate_memory_list(&static_array_area_memlist);
|
|
|
|
deallocate_memory_list(&arrays_memlist);
|
|
|
|
deallocate_memory_list(&global_initial_value_memlist);
|
|
|
|
deallocate_memory_list(¤t_array_name);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================= */
|