X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fmemory.c;h=d437ceebee986b4cc5b47503be4ad44ca1bb318d;hb=HEAD;hp=fc8a446f1c7d83219231d063054be2d2bd8b5024;hpb=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;p=inform.git diff --git a/src/memory.c b/src/memory.c index fc8a446..d437cee 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,10 +1,8 @@ /* ------------------------------------------------------------------------- */ /* "memory" : Memory management and ICL memory setting commands */ -/* (For "memoryerror", see "errors.c") */ /* */ -/* Copyright (c) Graham Nelson 1993 - 2018 */ -/* */ -/* This file is part of Inform. */ +/* 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 */ @@ -23,64 +21,75 @@ #include "header.h" -int32 malloced_bytes=0; /* Total amount of memory allocated */ +size_t malloced_bytes=0; /* Total amount of memory allocated */ + +/* Wrappers for malloc(), realloc(), etc. + + Note that all of these functions call fatalerror_memory_out() on failure. + This is a fatal error and does not return. However, we check my_malloc() + return values anyway as a matter of good habit. + */ #ifdef PC_QUICKC -extern void *my_malloc(int32 size, char *whatfor) +extern void *my_malloc(size_t size, char *whatfor) { char _huge *c; if (memout_switch) printf("Allocating %ld bytes for %s\n",size,whatfor); if (size==0) return(NULL); - c=(char _huge *)halloc(size,1); malloced_bytes+=size; - if (c==0) memory_out_error(size, 1, whatfor); + c=(char _huge *)halloc(size,1); + malloced_bytes+=size; + if (c==0) fatalerror_memory_out(size, 1, whatfor); return(c); } -extern void my_realloc(void *pointer, int32 oldsize, int32 size, +extern void my_realloc(void *pointer, size_t oldsize, size_t size, char *whatfor) { char _huge *c; if (size==0) { my_free(pointer, whatfor); return; } - c=halloc(size,1); malloced_bytes+=size; - if (c==0) memory_out_error(size, 1, whatfor); + c=halloc(size,1); + malloced_bytes+=(size-oldsize); + if (c==0) fatalerror_memory_out(size, 1, whatfor); if (memout_switch) - printf("Increasing allocation to %ld bytes for %s was (%08lx) \ -now (%08lx)\n", - (long int) size,whatfor,(long int) (*(int **)pointer), + printf("Increasing allocation from %ld to %ld bytes for %s was (%08lx) now (%08lx)\n", + (long int) oldsize, (long int) size, whatfor, + (long int) (*(int **)pointer), (long int) c); memcpy(c, *(int **)pointer, MIN(oldsize, size)); hfree(*(int **)pointer); *(int **)pointer = c; } -extern void *my_calloc(int32 size, int32 howmany, char *whatfor) +extern void *my_calloc(size_t size, size_t howmany, char *whatfor) { void _huge *c; if (memout_switch) printf("Allocating %d bytes: array (%ld entries size %ld) for %s\n", size*howmany,howmany,size,whatfor); if ((size*howmany) == 0) return(NULL); - c=(void _huge *)halloc(howmany*size,1); malloced_bytes+=size*howmany; - if (c==0) memory_out_error(size, howmany, whatfor); + c=(void _huge *)halloc(howmany*size,1); + malloced_bytes+=size*howmany; + if (c==0) fatalerror_memory_out(size, howmany, whatfor); return(c); } -extern void my_recalloc(void *pointer, int32 size, int32 oldhowmany, +extern void my_recalloc(void *pointer, size_t size, size_t oldhowmany, int32 howmany, char *whatfor) { void _huge *c; if (size*howmany==0) { my_free(pointer, whatfor); return; } - c=(void _huge *)halloc(size*howmany,1); malloced_bytes+=size*howmany; - if (c==0) memory_out_error(size, howmany, whatfor); + c=(void _huge *)halloc(size*howmany,1); + malloced_bytes+=size*(howmany-oldhowmany); + if (c==0) fatalerror_memory_out(size, howmany, whatfor); if (memout_switch) - printf("Increasing allocation to %ld bytes: array (%ld entries size %ld) \ -for %s was (%08lx) now (%08lx)\n", + printf("Increasing allocation from %ld to %ld bytes: array (%ld entries size %ld) for %s was (%08lx) now (%08lx)\n", + ((long int)size) * ((long int)oldhowmany), ((long int)size) * ((long int)howmany), - (long int)howmany,(long int)size,whatfor, + (long int)howmany, (long int)size, whatfor, (long int) *(int **)pointer, (long int) c); memcpy(c, *(int **)pointer, MIN(size*oldhowmany, size*howmany)); hfree(*(int **)pointer); @@ -89,64 +98,64 @@ for %s was (%08lx) now (%08lx)\n", #else -extern void *my_malloc(int32 size, char *whatfor) +extern void *my_malloc(size_t size, char *whatfor) { char *c; if (size==0) return(NULL); - c=malloc((size_t) size); malloced_bytes+=size; - if (c==0) memory_out_error(size, 1, whatfor); + c=malloc(size); + malloced_bytes+=size; + if (c==0) fatalerror_memory_out(size, 1, whatfor); if (memout_switch) - printf("Allocating %ld bytes for %s at (%08lx)\n", - (long int) size,whatfor,(long int) c); + printf("Allocating %ld bytes for %s at (%p)\n", + (long int) size, whatfor, c); return(c); } -extern void my_realloc(void *pointer, int32 oldsize, int32 size, +extern void my_realloc(void *pointer, size_t oldsize, size_t size, char *whatfor) { void *c; if (size==0) { my_free(pointer, whatfor); return; } - c=realloc(*(int **)pointer, (size_t) size); malloced_bytes+=size; - if (c==0) memory_out_error(size, 1, whatfor); + c=realloc(*(int **)pointer, size); + malloced_bytes+=(size-oldsize); + if (c==0) fatalerror_memory_out(size, 1, whatfor); if (memout_switch) - printf("Increasing allocation to %ld bytes for %s was (%08lx) \ -now (%08lx)\n", - (long int) size,whatfor,(long int) (*(int **)pointer), - (long int) c); + printf("Increasing allocation from %ld to %ld bytes for %s was (%p) now (%p)\n", + (long int) oldsize, (long int) size, whatfor, pointer, c); *(int **)pointer = c; } -extern void *my_calloc(int32 size, int32 howmany, char *whatfor) +extern void *my_calloc(size_t size, size_t howmany, char *whatfor) { void *c; if (size*howmany==0) return(NULL); - c=calloc(howmany,(size_t) size); malloced_bytes+=size*howmany; - if (c==0) memory_out_error(size, howmany, whatfor); + c=calloc(howmany, size); + malloced_bytes+=size*howmany; + if (c==0) fatalerror_memory_out(size, howmany, whatfor); if (memout_switch) printf("Allocating %ld bytes: array (%ld entries size %ld) \ -for %s at (%08lx)\n", +for %s at (%p)\n", ((long int)size) * ((long int)howmany), - (long int)howmany,(long int)size,whatfor, - (long int) c); + (long int)howmany,(long int)size, whatfor, c); return(c); } -extern void my_recalloc(void *pointer, int32 size, int32 oldhowmany, - int32 howmany, char *whatfor) +extern void my_recalloc(void *pointer, size_t size, size_t oldhowmany, + size_t howmany, char *whatfor) { void *c; if (size*howmany==0) { my_free(pointer, whatfor); return; } - c=realloc(*(int **)pointer, (size_t)size*(size_t)howmany); - malloced_bytes+=size*howmany; - if (c==0) memory_out_error(size, howmany, whatfor); + c=realloc(*(int **)pointer, size*howmany); + malloced_bytes+=size*(howmany-oldhowmany); + if (c==0) fatalerror_memory_out(size, howmany, whatfor); if (memout_switch) - printf("Increasing allocation to %ld bytes: array (%ld entries size %ld) \ -for %s was (%08lx) now (%08lx)\n", + printf("Increasing allocation from %ld to %ld bytes: array (%ld entries size %ld) for %s was (%p) now (%p)\n", + ((long int)size) * ((long int)oldhowmany), ((long int)size) * ((long int)howmany), - (long int)howmany,(long int)size,whatfor, - (long int) *(int **)pointer, (long int) c); + (long int)howmany, (long int)size, whatfor, + pointer, c); *(int **)pointer = c; } @@ -156,8 +165,8 @@ extern void my_free(void *pointer, char *whatitwas) { if (*(int **)pointer != NULL) { if (memout_switch) - printf("Freeing memory for %s at (%08lx)\n", - whatitwas, (long int) (*(int **)pointer)); + printf("Freeing memory for %s at (%p)\n", + whatitwas, pointer); #ifdef PC_QUICKC hfree(*(int **)pointer); #else @@ -168,129 +177,122 @@ extern void my_free(void *pointer, char *whatitwas) } /* ------------------------------------------------------------------------- */ -/* Extensible blocks of memory, providing a kind of RAM disc as an */ -/* alternative to the temporary files option */ +/* A dynamic memory array. This grows as needed (but never shrinks). */ +/* Call ensure_memory_list_available(N) before accessing array item N-1. */ +/* */ +/* whatfor must be a static string describing the list. initalloc is */ +/* (optionally) the number of items to allocate right away. */ +/* */ +/* You typically initialise this with extpointer referring to an array of */ +/* structs or whatever type you need. Whenever the memory list grows, the */ +/* external array will be updated to refer to the new data. */ +/* */ +/* Add "#define DEBUG_MEMLISTS" to allocate exactly the number of items */ +/* needed, rather than increasing allocations exponentially. This is very */ +/* slow but it lets us track down array overruns. */ /* ------------------------------------------------------------------------- */ -static char chunk_name_buffer[60]; -static char *chunk_name(memory_block *MB, int no) -{ char *p = "(unknown)"; - if (MB == &static_strings_area) p = "static strings area"; - 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 == &zmachine_backpatch_table) p = "Z-machine backpatch table"; - sprintf(chunk_name_buffer, "%s chunk %d", p, no); - return(chunk_name_buffer); -} - -extern void initialise_memory_block(memory_block *MB) -{ int i; - MB->chunks = 0; - for (i=0; i<72; i++) MB->chunk[i] = NULL; - MB->extent_of_last = 0; - MB->write_pos = 0; +void initialise_memory_list(memory_list *ML, size_t itemsize, size_t initalloc, void **extpointer, char *whatfor) +{ + #ifdef DEBUG_MEMLISTS + initalloc = 0; /* No initial allocation */ + #endif + + ML->whatfor = whatfor; + ML->itemsize = itemsize; + ML->count = 0; + ML->data = NULL; + ML->extpointer = extpointer; + + if (initalloc) { + ML->count = initalloc; + ML->data = my_calloc(ML->itemsize, ML->count, ML->whatfor); + if (ML->data == NULL) return; + } + + if (ML->extpointer) + *(ML->extpointer) = ML->data; } -extern void deallocate_memory_block(memory_block *MB) -{ int i; - for (i=0; i<72; i++) - if (MB->chunk[i] != NULL) - my_free(&(MB->chunk[i]), chunk_name(MB, i)); - MB->chunks = 0; - MB->extent_of_last = 0; +void deallocate_memory_list(memory_list *ML) +{ + ML->itemsize = 0; + ML->count = 0; + + if (ML->data) + my_free(&(ML->data), ML->whatfor); + + if (ML->extpointer) + *(ML->extpointer) = NULL; + ML->extpointer = NULL; } -extern int read_byte_from_memory_block(memory_block *MB, int32 index) -{ uchar *p; - p = MB->chunk[index/ALLOC_CHUNK_SIZE]; - if (p == NULL) - { compiler_error_named("memory: read from unwritten byte in", - chunk_name(MB, index/ALLOC_CHUNK_SIZE)); - return 0; +/* After this is called, at least count items will be available in the list. + That is, you can freely access array[0] through array[count-1]. */ +void ensure_memory_list_available(memory_list *ML, size_t count) +{ + size_t oldcount; + + if (ML->itemsize == 0) { + /* whatfor is also null! */ + compiler_error("memory: attempt to access uninitialized memory_list"); + return; } - return p[index % ALLOC_CHUNK_SIZE]; -} -extern void write_byte_to_memory_block(memory_block *MB, int32 index, int value) -{ uchar *p; int ch = index/ALLOC_CHUNK_SIZE; - if (ch < 0) - { compiler_error_named("memory: negative index to", chunk_name(MB, 0)); + if (ML->count >= count) { return; } - if (ch >= 72) memoryerror("ALLOC_CHUNK_SIZE", ALLOC_CHUNK_SIZE); - if (MB->chunk[ch] == NULL) - { int i; - MB->chunk[ch] = my_malloc(ALLOC_CHUNK_SIZE, chunk_name(MB, ch)); - p = MB->chunk[ch]; - for (i=0; icount; + ML->count = 2*count+8; /* Allow headroom for future growth */ + + #ifdef DEBUG_MEMLISTS + ML->count = count; /* No headroom */ + #endif + + if (ML->data == NULL) + ML->data = my_calloc(ML->itemsize, ML->count, ML->whatfor); + else + my_recalloc(&(ML->data), ML->itemsize, oldcount, ML->count, ML->whatfor); + if (ML->data == NULL) return; - p = MB->chunk[ch]; - p[index % ALLOC_CHUNK_SIZE] = value; + if (ML->extpointer) + *(ML->extpointer) = ML->data; } /* ------------------------------------------------------------------------- */ /* Where the memory settings are declared as variables */ /* ------------------------------------------------------------------------- */ -int MAX_QTEXT_SIZE; -int MAX_SYMBOLS; -int SYMBOLS_CHUNK_SIZE; int HASH_TAB_SIZE; -int MAX_OBJECTS; -int MAX_ARRAYS; -int MAX_ACTIONS; -int MAX_ADJECTIVES; -int MAX_DICT_ENTRIES; -int MAX_STATIC_DATA; -int MAX_PROP_TABLE_SIZE; int MAX_ABBREVS; -int MAX_EXPRESSION_NODES; -int MAX_VERBS; -int MAX_VERBSPACE; -int MAX_LABELS; -int MAX_LINESPACE; -int32 MAX_STATIC_STRINGS; -int32 MAX_ZCODE_SIZE; -int MAX_LOW_STRINGS; -int32 MAX_TRANSCRIPT_SIZE; -int MAX_CLASSES; -int32 MAX_LINK_DATA_SIZE; -int MAX_INCLUSION_DEPTH; -int MAX_SOURCE_FILES; -int32 MAX_INDIV_PROP_TABLE_SIZE; -int32 MAX_OBJ_PROP_TABLE_SIZE; -int MAX_OBJ_PROP_COUNT; +int MAX_DYNAMIC_STRINGS; int MAX_LOCAL_VARIABLES; -int MAX_GLOBAL_VARIABLES; int DICT_WORD_SIZE; /* number of characters in a dict word */ int DICT_CHAR_SIZE; /* (glulx) 1 for one-byte chars, 4 for Unicode chars */ int DICT_WORD_BYTES; /* DICT_WORD_SIZE*DICT_CHAR_SIZE */ int ZCODE_HEADER_EXT_WORDS; /* (zcode 1.0) requested header extension size */ int ZCODE_HEADER_FLAGS_3; /* (zcode 1.1) value to place in Flags 3 word */ +int ZCODE_LESS_DICT_DATA; /* (zcode) use 2 data bytes per dict word instead of 3 */ +int ZCODE_MAX_INLINE_STRING; /* (zcode) length of string literals that can be inlined */ int NUM_ATTR_BYTES; int GLULX_OBJECT_EXT_BYTES; /* (glulx) extra bytes for each object record */ -int32 MAX_NUM_STATIC_STRINGS; -int32 MAX_UNICODE_CHARS; int32 MAX_STACK_SIZE; int32 MEMORY_MAP_EXTENSION; -int ALLOC_CHUNK_SIZE; int WARN_UNUSED_ROUTINES; /* 0: no, 1: yes except in system files, 2: yes always */ int OMIT_UNUSED_ROUTINES; /* 0: no, 1: yes */ +int STRIP_UNREACHABLE_LABELS; /* 0: no, 1: yes (default) */ +int OMIT_SYMBOL_TABLE; /* 0: no, 1: yes */ +int LONG_DICT_FLAG_BUG; /* 0: no bug, 1: bug (default for historic reasons) */ +int TRANSCRIPT_FORMAT; /* 0: classic, 1: prefixed */ /* The way memory sizes are set causes great nuisance for those parameters which have different defaults under Z-code and Glulx. We have to get the defaults right whether the user sets "-G $HUGE" or "$HUGE -G". And an explicit value set by the user should override both defaults. */ -static int32 MAX_ZCODE_SIZE_z, MAX_ZCODE_SIZE_g; -static int MAX_PROP_TABLE_SIZE_z, MAX_PROP_TABLE_SIZE_g; -static int MAX_GLOBAL_VARIABLES_z, MAX_GLOBAL_VARIABLES_g; -static int MAX_LOCAL_VARIABLES_z, MAX_LOCAL_VARIABLES_g; static int DICT_WORD_SIZE_z, DICT_WORD_SIZE_g; static int NUM_ATTR_BYTES_z, NUM_ATTR_BYTES_g; -static int ALLOC_CHUNK_SIZE_z, ALLOC_CHUNK_SIZE_g; +static int MAX_DYNAMIC_STRINGS_z, MAX_DYNAMIC_STRINGS_g; /* ------------------------------------------------------------------------- */ /* Memory control from the command line */ @@ -301,243 +303,58 @@ static void list_memory_sizes(void) printf("| %25s = %-7s |\n","Memory setting","Value"); printf("+--------------------------------------+\n"); printf("| %25s = %-7d |\n","MAX_ABBREVS",MAX_ABBREVS); - printf("| %25s = %-7d |\n","MAX_ACTIONS",MAX_ACTIONS); - printf("| %25s = %-7d |\n","MAX_ADJECTIVES",MAX_ADJECTIVES); - printf("| %25s = %-7d |\n","ALLOC_CHUNK_SIZE",ALLOC_CHUNK_SIZE); - printf("| %25s = %-7d |\n","MAX_ARRAYS",MAX_ARRAYS); printf("| %25s = %-7d |\n","NUM_ATTR_BYTES",NUM_ATTR_BYTES); - printf("| %25s = %-7d |\n","MAX_CLASSES",MAX_CLASSES); - printf("| %25s = %-7d |\n","MAX_DICT_ENTRIES",MAX_DICT_ENTRIES); printf("| %25s = %-7d |\n","DICT_WORD_SIZE",DICT_WORD_SIZE); if (glulx_mode) printf("| %25s = %-7d |\n","DICT_CHAR_SIZE",DICT_CHAR_SIZE); - printf("| %25s = %-7d |\n","MAX_EXPRESSION_NODES",MAX_EXPRESSION_NODES); - printf("| %25s = %-7d |\n","MAX_GLOBAL_VARIABLES",MAX_GLOBAL_VARIABLES); + printf("| %25s = %-7d |\n","MAX_DYNAMIC_STRINGS",MAX_DYNAMIC_STRINGS); printf("| %25s = %-7d |\n","HASH_TAB_SIZE",HASH_TAB_SIZE); if (!glulx_mode) printf("| %25s = %-7d |\n","ZCODE_HEADER_EXT_WORDS",ZCODE_HEADER_EXT_WORDS); if (!glulx_mode) printf("| %25s = %-7d |\n","ZCODE_HEADER_FLAGS_3",ZCODE_HEADER_FLAGS_3); - printf("| %25s = %-7d |\n","MAX_INCLUSION_DEPTH",MAX_INCLUSION_DEPTH); - printf("| %25s = %-7d |\n","MAX_INDIV_PROP_TABLE_SIZE", MAX_INDIV_PROP_TABLE_SIZE); + if (!glulx_mode) + printf("| %25s = %-7d |\n","ZCODE_LESS_DICT_DATA",ZCODE_LESS_DICT_DATA); + if (!glulx_mode) + printf("| %25s = %-7d |\n","ZCODE_MAX_INLINE_STRING",ZCODE_MAX_INLINE_STRING); printf("| %25s = %-7d |\n","INDIV_PROP_START", INDIV_PROP_START); - printf("| %25s = %-7d |\n","MAX_LABELS",MAX_LABELS); - printf("| %25s = %-7d |\n","MAX_LINESPACE",MAX_LINESPACE); - printf("| %25s = %-7d |\n","MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE); - if (glulx_mode) - printf("| %25s = %-7d |\n","MAX_LOCAL_VARIABLES",MAX_LOCAL_VARIABLES); - printf("| %25s = %-7d |\n","MAX_LOW_STRINGS",MAX_LOW_STRINGS); if (glulx_mode) printf("| %25s = %-7d |\n","MEMORY_MAP_EXTENSION", MEMORY_MAP_EXTENSION); - if (glulx_mode) - printf("| %25s = %-7d |\n","MAX_NUM_STATIC_STRINGS", - MAX_NUM_STATIC_STRINGS); - printf("| %25s = %-7d |\n","MAX_OBJECTS",MAX_OBJECTS); if (glulx_mode) printf("| %25s = %-7d |\n","GLULX_OBJECT_EXT_BYTES", GLULX_OBJECT_EXT_BYTES); - if (glulx_mode) - printf("| %25s = %-7d |\n","MAX_OBJ_PROP_COUNT", - MAX_OBJ_PROP_COUNT); - if (glulx_mode) - printf("| %25s = %-7d |\n","MAX_OBJ_PROP_TABLE_SIZE", - MAX_OBJ_PROP_TABLE_SIZE); - printf("| %25s = %-7d |\n","MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE); - printf("| %25s = %-7d |\n","MAX_QTEXT_SIZE",MAX_QTEXT_SIZE); - printf("| %25s = %-7d |\n","MAX_SOURCE_FILES",MAX_SOURCE_FILES); if (glulx_mode) printf("| %25s = %-7ld |\n","MAX_STACK_SIZE", (long int) MAX_STACK_SIZE); - printf("| %25s = %-7d |\n","MAX_STATIC_DATA",MAX_STATIC_DATA); - printf("| %25s = %-7ld |\n","MAX_STATIC_STRINGS", - (long int) MAX_STATIC_STRINGS); - printf("| %25s = %-7d |\n","MAX_SYMBOLS",MAX_SYMBOLS); - printf("| %25s = %-7d |\n","SYMBOLS_CHUNK_SIZE",SYMBOLS_CHUNK_SIZE); - printf("| %25s = %-7ld |\n","MAX_TRANSCRIPT_SIZE", - (long int) MAX_TRANSCRIPT_SIZE); - if (glulx_mode) - printf("| %25s = %-7ld |\n","MAX_UNICODE_CHARS", - (long int) MAX_UNICODE_CHARS); + printf("| %25s = %-7d |\n","TRANSCRIPT_FORMAT",TRANSCRIPT_FORMAT); printf("| %25s = %-7d |\n","WARN_UNUSED_ROUTINES",WARN_UNUSED_ROUTINES); printf("| %25s = %-7d |\n","OMIT_UNUSED_ROUTINES",OMIT_UNUSED_ROUTINES); - printf("| %25s = %-7d |\n","MAX_VERBS",MAX_VERBS); - printf("| %25s = %-7d |\n","MAX_VERBSPACE",MAX_VERBSPACE); - printf("| %25s = %-7ld |\n","MAX_ZCODE_SIZE", - (long int) MAX_ZCODE_SIZE); + printf("| %25s = %-7d |\n","STRIP_UNREACHABLE_LABELS",STRIP_UNREACHABLE_LABELS); + printf("| %25s = %-7d |\n","OMIT_SYMBOL_TABLE",OMIT_SYMBOL_TABLE); + printf("| %25s = %-7d |\n","LONG_DICT_FLAG_BUG",LONG_DICT_FLAG_BUG); printf("+--------------------------------------+\n"); } -extern void set_memory_sizes(int size_flag) +extern void set_memory_sizes(void) { - if (size_flag == HUGE_SIZE) - { - MAX_QTEXT_SIZE = 4000; - MAX_SYMBOLS = 10000; - - SYMBOLS_CHUNK_SIZE = 5000; - HASH_TAB_SIZE = 512; - - MAX_OBJECTS = 640; - - MAX_ACTIONS = 200; - MAX_ADJECTIVES = 50; - MAX_DICT_ENTRIES = 2000; - MAX_STATIC_DATA = 10000; - - MAX_PROP_TABLE_SIZE_z = 30000; - MAX_PROP_TABLE_SIZE_g = 60000; - - MAX_ABBREVS = 64; - - MAX_EXPRESSION_NODES = 100; - MAX_VERBS = 200; - MAX_VERBSPACE = 4096; - MAX_LABELS = 1000; - MAX_LINESPACE = 16000; - - MAX_STATIC_STRINGS = 8000; - MAX_ZCODE_SIZE_z = 20000; - MAX_ZCODE_SIZE_g = 40000; - MAX_LINK_DATA_SIZE = 2000; - - MAX_LOW_STRINGS = 2048; - - MAX_TRANSCRIPT_SIZE = 200000; - MAX_NUM_STATIC_STRINGS = 20000; - - MAX_CLASSES = 64; - - MAX_OBJ_PROP_COUNT = 128; - MAX_OBJ_PROP_TABLE_SIZE = 4096; - - MAX_INDIV_PROP_TABLE_SIZE = 15000; - MAX_ARRAYS = 128; - - MAX_GLOBAL_VARIABLES_z = 240; - MAX_GLOBAL_VARIABLES_g = 512; - - ALLOC_CHUNK_SIZE_z = 8192; - ALLOC_CHUNK_SIZE_g = 32768; - } - if (size_flag == LARGE_SIZE) - { - MAX_QTEXT_SIZE = 4000; - MAX_SYMBOLS = 6400; - - SYMBOLS_CHUNK_SIZE = 5000; - HASH_TAB_SIZE = 512; - - MAX_OBJECTS = 512; - - MAX_ACTIONS = 200; - MAX_ADJECTIVES = 50; - MAX_DICT_ENTRIES = 1300; - MAX_STATIC_DATA = 10000; - - MAX_PROP_TABLE_SIZE_z = 15000; - MAX_PROP_TABLE_SIZE_g = 30000; - - MAX_ABBREVS = 64; - - MAX_EXPRESSION_NODES = 100; - MAX_VERBS = 140; - MAX_VERBSPACE = 4096; - MAX_LINESPACE = 10000; - - MAX_LABELS = 1000; - MAX_STATIC_STRINGS = 8000; - MAX_ZCODE_SIZE_z = 20000; - MAX_ZCODE_SIZE_g = 40000; - MAX_LINK_DATA_SIZE = 2000; - - MAX_LOW_STRINGS = 2048; - - MAX_TRANSCRIPT_SIZE = 200000; - MAX_NUM_STATIC_STRINGS = 20000; - - MAX_CLASSES = 64; - - MAX_OBJ_PROP_COUNT = 64; - MAX_OBJ_PROP_TABLE_SIZE = 2048; - - MAX_INDIV_PROP_TABLE_SIZE = 10000; - MAX_ARRAYS = 128; - - MAX_GLOBAL_VARIABLES_z = 240; - MAX_GLOBAL_VARIABLES_g = 512; - - ALLOC_CHUNK_SIZE_z = 8192; - ALLOC_CHUNK_SIZE_g = 16384; - } - if (size_flag == SMALL_SIZE) - { - MAX_QTEXT_SIZE = 4000; - MAX_SYMBOLS = 3000; - - SYMBOLS_CHUNK_SIZE = 2500; - HASH_TAB_SIZE = 512; - - MAX_OBJECTS = 300; - - MAX_ACTIONS = 200; - MAX_ADJECTIVES = 50; - MAX_DICT_ENTRIES = 700; - MAX_STATIC_DATA = 10000; - - MAX_PROP_TABLE_SIZE_z = 8000; - MAX_PROP_TABLE_SIZE_g = 16000; - - MAX_ABBREVS = 64; - - MAX_EXPRESSION_NODES = 40; - MAX_VERBS = 110; - MAX_VERBSPACE = 2048; - MAX_LINESPACE = 10000; - MAX_LABELS = 1000; - - MAX_STATIC_STRINGS = 8000; - MAX_ZCODE_SIZE_z = 10000; - MAX_ZCODE_SIZE_g = 20000; - MAX_LINK_DATA_SIZE = 1000; - - MAX_LOW_STRINGS = 1024; - - MAX_TRANSCRIPT_SIZE = 100000; - MAX_NUM_STATIC_STRINGS = 10000; - - MAX_CLASSES = 32; - - MAX_OBJ_PROP_COUNT = 64; - MAX_OBJ_PROP_TABLE_SIZE = 1024; - - MAX_INDIV_PROP_TABLE_SIZE = 5000; - MAX_ARRAYS = 64; - - MAX_GLOBAL_VARIABLES_z = 240; - MAX_GLOBAL_VARIABLES_g = 256; - - ALLOC_CHUNK_SIZE_z = 8192; - ALLOC_CHUNK_SIZE_g = 8192; - } - - /* Regardless of size_flag... */ - MAX_SOURCE_FILES = 256; - MAX_INCLUSION_DEPTH = 5; - MAX_LOCAL_VARIABLES_z = 16; - MAX_LOCAL_VARIABLES_g = 32; + HASH_TAB_SIZE = 512; DICT_CHAR_SIZE = 1; DICT_WORD_SIZE_z = 6; DICT_WORD_SIZE_g = 9; NUM_ATTR_BYTES_z = 6; NUM_ATTR_BYTES_g = 7; + MAX_ABBREVS = 64; + MAX_DYNAMIC_STRINGS_z = 32; + MAX_DYNAMIC_STRINGS_g = 100; /* Backwards-compatible behavior: allow for a unicode table whether we need one or not. The user can set this to zero if there's no unicode table. */ ZCODE_HEADER_EXT_WORDS = 3; ZCODE_HEADER_FLAGS_3 = 0; + ZCODE_LESS_DICT_DATA = 0; + ZCODE_MAX_INLINE_STRING = 32; GLULX_OBJECT_EXT_BYTES = 0; - MAX_UNICODE_CHARS = 64; MEMORY_MAP_EXTENSION = 0; /* We estimate the default Glulx stack size at 4096. That's about enough for 90 nested function calls with 8 locals each -- the @@ -547,6 +364,10 @@ extern void set_memory_sizes(int size_flag) MAX_STACK_SIZE = 4096; OMIT_UNUSED_ROUTINES = 0; WARN_UNUSED_ROUTINES = 0; + STRIP_UNREACHABLE_LABELS = 1; + OMIT_SYMBOL_TABLE = 0; + LONG_DICT_FLAG_BUG = 1; + TRANSCRIPT_FORMAT = 0; adjust_memory_sizes(); } @@ -554,79 +375,27 @@ extern void set_memory_sizes(int size_flag) extern void adjust_memory_sizes() { if (!glulx_mode) { - MAX_ZCODE_SIZE = MAX_ZCODE_SIZE_z; - MAX_PROP_TABLE_SIZE = MAX_PROP_TABLE_SIZE_z; - MAX_GLOBAL_VARIABLES = MAX_GLOBAL_VARIABLES_z; - MAX_LOCAL_VARIABLES = MAX_LOCAL_VARIABLES_z; DICT_WORD_SIZE = DICT_WORD_SIZE_z; NUM_ATTR_BYTES = NUM_ATTR_BYTES_z; - ALLOC_CHUNK_SIZE = ALLOC_CHUNK_SIZE_z; + MAX_DYNAMIC_STRINGS = MAX_DYNAMIC_STRINGS_z; INDIV_PROP_START = 64; } else { - MAX_ZCODE_SIZE = MAX_ZCODE_SIZE_g; - MAX_PROP_TABLE_SIZE = MAX_PROP_TABLE_SIZE_g; - MAX_GLOBAL_VARIABLES = MAX_GLOBAL_VARIABLES_g; - MAX_LOCAL_VARIABLES = MAX_LOCAL_VARIABLES_g; DICT_WORD_SIZE = DICT_WORD_SIZE_g; NUM_ATTR_BYTES = NUM_ATTR_BYTES_g; - ALLOC_CHUNK_SIZE = ALLOC_CHUNK_SIZE_g; + MAX_DYNAMIC_STRINGS = MAX_DYNAMIC_STRINGS_g; INDIV_PROP_START = 256; } } static void explain_parameter(char *command) { printf("\n"); - if (strcmp(command,"MAX_QTEXT_SIZE")==0) - { printf( -" MAX_QTEXT_SIZE is the maximum length of a quoted string. Increasing\n\ - by 1 costs 5 bytes (for lexical analysis memory). Inform automatically\n\ - ensures that MAX_STATIC_STRINGS is at least twice the size of this."); - return; - } - if (strcmp(command,"MAX_SYMBOLS")==0) - { printf( -" MAX_SYMBOLS is the maximum number of symbols - names of variables, \n\ - objects, routines, the many internal Inform-generated names and so on.\n"); - return; - } - if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0) - { printf( -" The symbols names are stored in memory which is allocated in chunks \n\ - of size SYMBOLS_CHUNK_SIZE.\n"); - return; - } if (strcmp(command,"HASH_TAB_SIZE")==0) { printf( " HASH_TAB_SIZE is the size of the hash tables used for the heaviest \n\ symbols banks.\n"); return; } - if (strcmp(command,"MAX_OBJECTS")==0) - { printf( -" MAX_OBJECTS is the maximum number of objects. (If compiling a version-3 \n\ - game, 255 is an absolute maximum in any event.)\n"); - return; - } - if (strcmp(command,"MAX_ACTIONS")==0) - { printf( -" MAX_ACTIONS is the maximum number of actions - that is, routines such as \n\ - TakeSub which are referenced in the grammar table.\n"); - return; - } - if (strcmp(command,"MAX_ADJECTIVES")==0) - { printf( -" MAX_ADJECTIVES is the maximum number of different \"adjectives\" in the \n\ - grammar table. Adjectives are misleadingly named: they are words such as \n\ - \"in\", \"under\" and the like.\n"); - return; - } - if (strcmp(command,"MAX_DICT_ENTRIES")==0) - { printf( -" MAX_DICT_ENTRIES is the maximum number of words which can be entered \n\ - into the game's dictionary. It costs 29 bytes to increase this by one.\n"); - return; - } if (strcmp(command,"DICT_WORD_SIZE")==0) { printf( " DICT_WORD_SIZE is the number of characters in a dictionary word. In \n\ @@ -664,136 +433,37 @@ static void explain_parameter(char *command) header extension table (Z-Spec 1.1).\n"); return; } - if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0) + if (strcmp(command,"ZCODE_LESS_DICT_DATA")==0) { printf( -" GLULX_OBJECT_EXT_BYTES is an amount of additional space to add to each \n\ - object record. It is initialized to zero bytes, and the game is free to \n\ - use it as desired. (This is only meaningful in Glulx, since Z-code \n\ - specifies the object structure.)\n"); +" ZCODE_LESS_DICT_DATA, if set, provides each dict word with two data bytes\n\ + rather than three. (Z-code only.)\n"); return; } - if (strcmp(command,"MAX_STATIC_DATA")==0) + if (strcmp(command,"ZCODE_MAX_INLINE_STRING")==0) { printf( -" MAX_STATIC_DATA is the size of an array of integers holding initial \n\ - values for arrays and strings stored as ASCII inside the Z-machine. It \n\ - should be at least 1024 but seldom needs much more.\n"); +" ZCODE_MAX_INLINE_STRING is the length beyond which string literals cannot\n\ + be inlined in assembly opcodes. (Z-code only.)\n"); return; } - if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0) + if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0) { printf( -" MAX_PROP_TABLE_SIZE is the number of bytes allocated to hold the \n\ - properties table.\n"); +" GLULX_OBJECT_EXT_BYTES is an amount of additional space to add to each \n\ + object record. It is initialized to zero bytes, and the game is free to \n\ + use it as desired. (This is only meaningful in Glulx, since Z-code \n\ + specifies the object structure.)\n"); return; } if (strcmp(command,"MAX_ABBREVS")==0) { printf( " MAX_ABBREVS is the maximum number of declared abbreviations. It is not \n\ - allowed to exceed 64.\n"); - return; - } - if (strcmp(command,"MAX_ARRAYS")==0) - { printf( -" MAX_ARRAYS is the maximum number of declared arrays.\n"); - return; - } - if (strcmp(command,"MAX_EXPRESSION_NODES")==0) - { printf( -" MAX_EXPRESSION_NODES is the maximum number of nodes in the expression \n\ - evaluator's storage for parse trees. In effect, it measures how \n\ - complicated algebraic expressions are allowed to be. Increasing it by \n\ - one costs about 80 bytes.\n"); - return; - } - if (strcmp(command,"MAX_VERBS")==0) - { printf( -" MAX_VERBS is the maximum number of verbs (such as \"take\") which can be \n\ - defined, each with its own grammar. To increase it by one costs about\n\ - 128 bytes. A full game will contain at least 100.\n"); - return; - } - if (strcmp(command,"MAX_VERBSPACE")==0) - { printf( -" MAX_VERBSPACE is the size of workspace used to store verb words, so may\n\ - need increasing in games with many synonyms: unlikely to exceed 4K.\n"); - return; - } - if (strcmp(command,"MAX_LABELS")==0) - { printf( -" MAX_LABELS is the maximum number of label points in any one routine.\n\ - (If the -k debugging information switch is set, MAX_LABELS is raised to\n\ - a minimum level of 2000, as about twice the normal number of label points\n\ - are needed to generate tables of how source code corresponds to positions\n\ - in compiled code.)"); + allowed to exceed 96 in Z-code. (This is not meaningful in Glulx, where \n\ + there is no limit on abbreviations.)\n"); return; } - if (strcmp(command,"MAX_LINESPACE")==0) + if (strcmp(command,"MAX_DYNAMIC_STRINGS")==0) { printf( -" MAX_LINESPACE is the size of workspace used to store grammar lines, so \n\ - may need increasing in games with complex or extensive grammars.\n"); - return; - } - if (strcmp(command,"MAX_STATIC_STRINGS")==0) - { - printf( -" MAX_STATIC_STRINGS is the size in bytes of a buffer to hold compiled\n\ - strings before they're written into longer-term storage. 2000 bytes is \n\ - plenty, allowing string constants of up to about 3000 characters long.\n\ - Inform automatically ensures that this is at least twice the size of\n\ - MAX_QTEXT_SIZE, to be on the safe side."); - return; - } - if (strcmp(command,"MAX_ZCODE_SIZE")==0) - { - printf( -" MAX_ZCODE_SIZE is the size in bytes of a buffer to hold compiled \n\ - code for a single routine. (It applies to both Z-code and Glulx, \n\ - despite the name.) As a guide, the longest library routine is \n\ - about 6500 bytes long in Z-code; about twice that in Glulx."); - return; - } - if (strcmp(command,"MAX_LINK_DATA_SIZE")==0) - { - printf( -" MAX_LINK_DATA_SIZE is the size in bytes of a buffer to hold module \n\ - link data before it's written into longer-term storage. 2000 bytes \n\ - is plenty."); - return; - } - if (strcmp(command,"MAX_LOW_STRINGS")==0) - { printf( -" MAX_LOW_STRINGS is the size in bytes of a buffer to hold all the \n\ - compiled \"low strings\" which are to be written above the synonyms table \n\ - in the Z-machine. 1024 is plenty.\n"); - return; - } - if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0) - { printf( -" MAX_TRANSCRIPT_SIZE is only allocated for the abbreviations optimisation \n\ - switch, and has the size in bytes of a buffer to hold the entire text of\n\ - the game being compiled: it has to be enormous, say 100000 to 200000.\n"); - return; - } - if (strcmp(command,"MAX_CLASSES")==0) - { printf( -" MAX_CLASSES maximum number of object classes which can be defined. This\n\ - is cheap to increase.\n"); - return; - } - if (strcmp(command,"MAX_INCLUSION_DEPTH")==0) - { printf( -" MAX_INCLUSION_DEPTH is the number of nested includes permitted.\n"); - return; - } - if (strcmp(command,"MAX_SOURCE_FILES")==0) - { printf( -" MAX_SOURCE_FILES is the number of source files that can be read in the \n\ - compilation.\n"); - return; - } - if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0) - { printf( -" MAX_INDIV_PROP_TABLE_SIZE is the number of bytes allocated to hold the \n\ - table of ..variable values.\n"); +" MAX_DYNAMIC_STRINGS is the maximum number of string substitution variables\n\ + (\"@00\" or \"@(0)\"). It is not allowed to exceed 96 in Z-code.\n"); return; } if (strcmp(command,"INDIV_PROP_START")==0) @@ -802,52 +472,6 @@ static void explain_parameter(char *command) properties are numbered INDIV_PROP_START and up.\n"); return; } - if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0) - { printf( -" MAX_OBJ_PROP_COUNT is the maximum number of properties a single object \n\ - can have. (Glulx only)\n"); - return; - } - if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0) - { printf( -" MAX_OBJ_PROP_TABLE_SIZE is the number of words allocated to hold a \n\ - single object's properties. (Glulx only)\n"); - return; - } - if (strcmp(command,"MAX_LOCAL_VARIABLES")==0) - { printf( -" MAX_LOCAL_VARIABLES is the number of local variables (including \n\ - arguments) allowed in a procedure. (Glulx only)\n"); - return; - } - if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0) - { printf( -" MAX_GLOBAL_VARIABLES is the number of global variables allowed in the \n\ - program. (Glulx only)\n"); - return; - } - if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0) - { - printf( -" MAX_NUM_STATIC_STRINGS is the maximum number of compiled strings \n\ - allowed in the program. (Glulx only)\n"); - return; - } - if (strcmp(command,"MAX_UNICODE_CHARS")==0) - { - printf( -" MAX_UNICODE_CHARS is the maximum number of different Unicode characters \n\ - (beyond the Latin-1 range, $00..$FF) which the game text can use. \n\ - (Glulx only)\n"); - return; - } - if (strcmp(command,"ALLOC_CHUNK_SIZE")==0) - { - printf( -" ALLOC_CHUNK_SIZE is a base unit of Inform's internal memory allocation \n\ - for various structures.\n"); - return; - } if (strcmp(command,"MAX_STACK_SIZE")==0) { printf( @@ -862,6 +486,13 @@ static void explain_parameter(char *command) memory after the game file. (Glulx only)\n"); return; } + if (strcmp(command,"TRANSCRIPT_FORMAT")==0) + { + printf( +" TRANSCRIPT_FORMAT, if set to 1, adjusts the gametext.txt transcript for \n\ + easier machine processing; each line will be prefixed by its context.\n"); + return; + } if (strcmp(command,"WARN_UNUSED_ROUTINES")==0) { printf( @@ -878,6 +509,29 @@ static void explain_parameter(char *command) into the game file.\n"); return; } + if (strcmp(command,"STRIP_UNREACHABLE_LABELS")==0) + { + printf( +" STRIP_UNREACHABLE_LABELS, if set to 1, will skip labels in unreachable \n\ + statements. Jumping to a skipped label is an error. If 0, all labels \n\ + will be compiled, at the cost of less optimized code. The default is 1.\n"); + return; + } + if (strcmp(command,"OMIT_SYMBOL_TABLE")==0) + { + printf( +" OMIT_SYMBOL_TABLE, if set to 1, will skip compiling debug symbol names \n\ + into the game file.\n"); + return; + } + if (strcmp(command,"LONG_DICT_FLAG_BUG")==0) + { + printf( +" LONG_DICT_FLAG_BUG, if set to 0, will fix the old bug which ignores \n\ + the '//p' flag in long dictionary words. If 1, the buggy behavior is \n\ + retained.\n"); + return; + } if (strcmp(command,"SERIAL")==0) { printf( @@ -944,6 +598,174 @@ static int parse_memory_setting(char *str, char *label, int32 *result) return 1; } +static void add_predefined_symbol(char *command) +{ + int ix; + + int value = 0; + char *valpos = NULL; + + for (ix=0; command[ix]; ix++) { + if (command[ix] == '=') { + valpos = command+(ix+1); + command[ix] = '\0'; + break; + } + } + + for (ix=0; command[ix]; ix++) { + if ((ix == 0 && isdigit(command[ix])) + || !(isalnum(command[ix]) || command[ix] == '_')) { + printf("Attempt to define invalid symbol: %s\n", command); + return; + } + } + + if (valpos) { + if (!parse_memory_setting(valpos, command, &value)) { + return; + }; + } + + add_config_symbol_definition(command, value); +} + +static void set_trace_option(char *command) +{ + char *cx; + int value; + + /* Parse options of the form STRING or STRING=NUM. (The $! has already been eaten.) If the string is null or empty, show help. */ + + if (!command || *command == '\0') { + printf("The full list of trace options:\n\n"); + printf(" ACTIONS: show actions defined\n"); + printf(" ASM: trace assembly (same as -a)\n"); + printf(" ASM=2: also show hex dumps\n"); + printf(" ASM=3: also show branch optimization info\n"); + printf(" ASM=4: more verbose branch info\n"); + printf(" BPATCH: show backpatch results\n"); + printf(" BPATCH=2: also show markers added\n"); + printf(" DICT: display the dictionary table\n"); + printf(" DICT=2: also the byte encoding of entries\n"); + printf(" EXPR: show expression trees\n"); + printf(" EXPR=2: more verbose\n"); + printf(" EXPR=3: even more verbose\n"); + printf(" FILES: show files opened\n"); + printf(" FINDABBREVS: show selection decisions during abbreviation optimization\n (only meaningful with -u)\n"); + printf(" FINDABBREVS=2: also show three-letter-block decisions\n"); + printf(" FREQ: show how efficient abbreviations were (same as -f)\n (only meaningful with -e)\n"); + printf(" MAP: print memory map of the virtual machine (same as -z)\n"); + printf(" MAP=2: also show percentage of VM that each segment occupies\n"); + printf(" MAP=3: also show number of bytes that each segment occupies\n"); + printf(" MEM: show internal memory allocations\n"); + printf(" OBJECTS: display the object table\n"); + printf(" PROPS: show attributes and properties defined\n"); + printf(" RUNTIME: show game function calls at runtime (same as -g)\n"); + printf(" RUNTIME=2: also show library calls (not supported in Glulx)\n"); + printf(" RUNTIME=3: also show veneer calls (not supported in Glulx)\n"); + printf(" STATS: give compilation statistics (same as -s)\n"); + printf(" SYMBOLS: display the symbol table\n"); + printf(" SYMBOLS=2: also show compiler-defined symbols\n"); + printf(" SYMDEF: show when symbols are noticed and defined\n"); + printf(" TOKENS: show token lexing\n"); + printf(" TOKENS=2: also show token types\n"); + printf(" TOKENS=3: also show lexical context\n"); + printf(" VERBS: display the verb grammar table\n"); + return; + } + + for (cx=command; *cx && *cx != '='; cx++) { + if (!(*cx >= 'A' && *cx <= 'Z')) { + printf("Invalid $! trace command \"%s\"\n", command); + return; + } + } + + value = 1; + if (*cx == '=') { + char *ex; + value = strtol(cx+1, &ex, 10); + + if (ex == cx+1 || *ex != '\0' || value < 0) { + printf("Bad numerical setting in $! trace command \"%s\"\n", command); + return; + } + + *cx = '\0'; + } + + /* We accept some reasonable synonyms, including plausible singular/plural confusion. */ + + if (strcmp(command, "ASSEMBLY")==0 || strcmp(command, "ASM")==0) { + asm_trace_setting = value; + } + else if (strcmp(command, "ACTION")==0 || strcmp(command, "ACTIONS")==0) { + printactions_switch = value; + } + else if (strcmp(command, "BPATCH")==0 || strcmp(command, "BACKPATCH")==0) { + bpatch_trace_setting = value; + } + else if (strcmp(command, "DICTIONARY")==0 || strcmp(command, "DICT")==0) { + list_dict_setting = value; + } + else if (strcmp(command, "EXPR")==0 || strcmp(command, "EXPRESSION")==0 || strcmp(command, "EXPRESSIONS")==0) { + expr_trace_setting = value; + } + else if (strcmp(command, "FILE")==0 || strcmp(command, "FILES")==0) { + files_trace_setting = value; + } + else if (strcmp(command, "FINDABBREV")==0 || strcmp(command, "FINDABBREVS")==0) { + optabbrevs_trace_setting = value; + } + else if (strcmp(command, "FREQUENCY")==0 || strcmp(command, "FREQUENCIES")==0 || strcmp(command, "FREQ")==0) { + frequencies_setting = value; + } + else if (strcmp(command, "MAP")==0) { + memory_map_setting = value; + } + else if (strcmp(command, "MEM")==0 || strcmp(command, "MEMORY")==0) { + memout_switch = value; + } + else if (strcmp(command, "OBJECTS")==0 || strcmp(command, "OBJECT")==0 || strcmp(command, "OBJS")==0 || strcmp(command, "OBJ")==0) { + list_objects_setting = value; + } + else if (strcmp(command, "PROP")==0 || strcmp(command, "PROPERTY")==0 || strcmp(command, "PROPS")==0 || strcmp(command, "PROPERTIES")==0) { + printprops_switch = value; + } + else if (strcmp(command, "RUNTIME")==0) { + trace_fns_setting = value; + } + else if (strcmp(command, "STATISTICS")==0 || strcmp(command, "STATS")==0 || strcmp(command, "STAT")==0) { + statistics_switch = value; + } + else if (strcmp(command, "SYMBOLS")==0 || strcmp(command, "SYMBOL")==0) { + list_symbols_setting = value; + } + else if (strcmp(command, "SYMDEF")==0 || strcmp(command, "SYMBOLDEF")==0) { + symdef_trace_setting = value; + } + else if (strcmp(command, "TOKEN")==0 || strcmp(command, "TOKENS")==0) { + tokens_trace_setting = value; + } + else if (strcmp(command, "VERBS")==0 || strcmp(command, "VERB")==0) { + list_verbs_setting = value; + } + else { + printf("Unrecognized $! trace command \"%s\"\n", command); + } +} + +/* Handle a dollar-sign command option: $LIST, $FOO=VAL, and so on. + The option may come from the command line, an ICL file, or a header + comment. + + (Unix-style command-line options are converted to dollar-sign format + before being sent here.) + + The name of this function is outdated. Many of these settings are not + really about memory allocation. +*/ extern void memory_command(char *command) { int i, k, flag=0; int32 j; @@ -951,11 +773,19 @@ extern void memory_command(char *command) if (islower(command[k])) command[k]=toupper(command[k]); if (command[0]=='?') { explain_parameter(command+1); return; } + if (command[0]=='#') { add_predefined_symbol(command+1); return; } + if (command[0]=='!') { set_trace_option(command+1); return; } - if (strcmp(command, "HUGE")==0) { set_memory_sizes(HUGE_SIZE); return; } - if (strcmp(command, "LARGE")==0) { set_memory_sizes(LARGE_SIZE); return; } - if (strcmp(command, "SMALL")==0) { set_memory_sizes(SMALL_SIZE); return; } + if (strcmp(command, "HUGE")==0 + || strcmp(command, "LARGE")==0 + || strcmp(command, "SMALL")==0) { + if (!nowarnings_switch) + printf("The Inform 6 memory size commands (\"SMALL, LARGE, HUGE\") are no longer needed and has been withdrawn.\n"); + return; + } + if (strcmp(command, "LIST")==0) { list_memory_sizes(); return; } + for (i=0; command[i]!=0; i++) { if (command[i]=='=') { command[i]=0; @@ -965,28 +795,25 @@ extern void memory_command(char *command) if (strcmp(command,"BUFFER_LENGTH")==0) flag=2; if (strcmp(command,"MAX_QTEXT_SIZE")==0) - { MAX_QTEXT_SIZE=j, flag=1; - if (2*MAX_QTEXT_SIZE > MAX_STATIC_STRINGS) - MAX_STATIC_STRINGS = 2*MAX_QTEXT_SIZE; - } + flag=3; if (strcmp(command,"MAX_SYMBOLS")==0) - MAX_SYMBOLS=j, flag=1; + flag=3; if (strcmp(command,"MAX_BANK_SIZE")==0) flag=2; if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0) - SYMBOLS_CHUNK_SIZE=j, flag=1; + flag=3; if (strcmp(command,"BANK_CHUNK_SIZE")==0) flag=2; if (strcmp(command,"HASH_TAB_SIZE")==0) HASH_TAB_SIZE=j, flag=1; if (strcmp(command,"MAX_OBJECTS")==0) - MAX_OBJECTS=j, flag=1; + flag=3; if (strcmp(command,"MAX_ACTIONS")==0) - MAX_ACTIONS=j, flag=1; + flag=3; if (strcmp(command,"MAX_ADJECTIVES")==0) - MAX_ADJECTIVES=j, flag=1; + flag=3; if (strcmp(command,"MAX_DICT_ENTRIES")==0) - MAX_DICT_ENTRIES=j, flag=1; + flag=3; if (strcmp(command,"DICT_WORD_SIZE")==0) { DICT_WORD_SIZE=j, flag=1; DICT_WORD_SIZE_g=DICT_WORD_SIZE_z=j; @@ -1001,10 +828,14 @@ extern void memory_command(char *command) ZCODE_HEADER_EXT_WORDS=j, flag=1; if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0) ZCODE_HEADER_FLAGS_3=j, flag=1; + if (strcmp(command,"ZCODE_LESS_DICT_DATA")==0) + ZCODE_LESS_DICT_DATA=j, flag=1; + if (strcmp(command,"ZCODE_MAX_INLINE_STRING")==0) + ZCODE_MAX_INLINE_STRING=j, flag=1; if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0) GLULX_OBJECT_EXT_BYTES=j, flag=1; if (strcmp(command,"MAX_STATIC_DATA")==0) - MAX_STATIC_DATA=j, flag=1; + flag=3; if (strcmp(command,"MAX_OLDEPTH")==0) flag=2; if (strcmp(command,"MAX_ROUTINES")==0) @@ -1012,9 +843,7 @@ extern void memory_command(char *command) if (strcmp(command,"MAX_GCONSTANTS")==0) flag=2; if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0) - { MAX_PROP_TABLE_SIZE=j, flag=1; - MAX_PROP_TABLE_SIZE_g=MAX_PROP_TABLE_SIZE_z=j; - } + flag=3; if (strcmp(command,"MAX_FORWARD_REFS")==0) flag=2; if (strcmp(command,"STACK_SIZE")==0) @@ -1025,63 +854,56 @@ extern void memory_command(char *command) flag=2; if (strcmp(command,"MAX_ABBREVS")==0) MAX_ABBREVS=j, flag=1; + if (strcmp(command,"MAX_DYNAMIC_STRINGS")==0) + { MAX_DYNAMIC_STRINGS=j, flag=1; + MAX_DYNAMIC_STRINGS_g=MAX_DYNAMIC_STRINGS_z=j; + } if (strcmp(command,"MAX_ARRAYS")==0) - MAX_ARRAYS=j, flag=1; + flag=3; if (strcmp(command,"MAX_EXPRESSION_NODES")==0) - MAX_EXPRESSION_NODES=j, flag=1; + flag=3; if (strcmp(command,"MAX_VERBS")==0) - MAX_VERBS=j, flag=1; + flag=3; if (strcmp(command,"MAX_VERBSPACE")==0) - MAX_VERBSPACE=j, flag=1; + flag=3; if (strcmp(command,"MAX_LABELS")==0) - MAX_LABELS=j, flag=1; + flag=3; if (strcmp(command,"MAX_LINESPACE")==0) - MAX_LINESPACE=j, flag=1; + flag=3; if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0) - MAX_NUM_STATIC_STRINGS=j, flag=1; + flag=3; if (strcmp(command,"MAX_STATIC_STRINGS")==0) - { MAX_STATIC_STRINGS=j, flag=1; - if (2*MAX_QTEXT_SIZE > MAX_STATIC_STRINGS) - MAX_STATIC_STRINGS = 2*MAX_QTEXT_SIZE; - } + flag=3; if (strcmp(command,"MAX_ZCODE_SIZE")==0) - { MAX_ZCODE_SIZE=j, flag=1; - MAX_ZCODE_SIZE_g=MAX_ZCODE_SIZE_z=j; - } + flag=3; if (strcmp(command,"MAX_LINK_DATA_SIZE")==0) - MAX_LINK_DATA_SIZE=j, flag=1; + flag=3; if (strcmp(command,"MAX_LOW_STRINGS")==0) - MAX_LOW_STRINGS=j, flag=1; + flag=3; if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0) - MAX_TRANSCRIPT_SIZE=j, flag=1; + flag=3; if (strcmp(command,"MAX_CLASSES")==0) - MAX_CLASSES=j, flag=1; + flag=3; if (strcmp(command,"MAX_INCLUSION_DEPTH")==0) - MAX_INCLUSION_DEPTH=j, flag=1; + flag=3; if (strcmp(command,"MAX_SOURCE_FILES")==0) - MAX_SOURCE_FILES=j, flag=1; + flag=3; if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0) - MAX_INDIV_PROP_TABLE_SIZE=j, flag=1; + flag=3; if (strcmp(command,"INDIV_PROP_START")==0) INDIV_PROP_START=j, flag=1; if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0) - MAX_OBJ_PROP_TABLE_SIZE=j, flag=1; + flag=3; if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0) - MAX_OBJ_PROP_COUNT=j, flag=1; + flag=3; if (strcmp(command,"MAX_LOCAL_VARIABLES")==0) - { MAX_LOCAL_VARIABLES=j, flag=1; - MAX_LOCAL_VARIABLES_g=MAX_LOCAL_VARIABLES_z=j; - } + flag=3; if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0) - { MAX_GLOBAL_VARIABLES=j, flag=1; - MAX_GLOBAL_VARIABLES_g=MAX_GLOBAL_VARIABLES_z=j; - } + flag=3; if (strcmp(command,"ALLOC_CHUNK_SIZE")==0) - { ALLOC_CHUNK_SIZE=j, flag=1; - ALLOC_CHUNK_SIZE_g=ALLOC_CHUNK_SIZE_z=j; - } + flag=3; if (strcmp(command,"MAX_UNICODE_CHARS")==0) - MAX_UNICODE_CHARS=j, flag=1; + flag=3; if (strcmp(command,"MAX_STACK_SIZE")==0) { MAX_STACK_SIZE=j, flag=1; @@ -1094,6 +916,12 @@ extern void memory_command(char *command) /* Adjust up to a 256-byte boundary. */ MEMORY_MAP_EXTENSION = (MEMORY_MAP_EXTENSION + 0xFF) & (~0xFF); } + if (strcmp(command,"TRANSCRIPT_FORMAT")==0) + { + TRANSCRIPT_FORMAT=j, flag=1; + if (TRANSCRIPT_FORMAT > 1 || TRANSCRIPT_FORMAT < 0) + TRANSCRIPT_FORMAT = 1; + } if (strcmp(command,"WARN_UNUSED_ROUTINES")==0) { WARN_UNUSED_ROUTINES=j, flag=1; @@ -1106,6 +934,24 @@ extern void memory_command(char *command) if (OMIT_UNUSED_ROUTINES > 1 || OMIT_UNUSED_ROUTINES < 0) OMIT_UNUSED_ROUTINES = 1; } + if (strcmp(command,"STRIP_UNREACHABLE_LABELS")==0) + { + STRIP_UNREACHABLE_LABELS=j, flag=1; + if (STRIP_UNREACHABLE_LABELS > 1 || STRIP_UNREACHABLE_LABELS < 0) + STRIP_UNREACHABLE_LABELS = 1; + } + if (strcmp(command,"OMIT_SYMBOL_TABLE")==0) + { + OMIT_SYMBOL_TABLE=j, flag=1; + if (OMIT_SYMBOL_TABLE > 1 || OMIT_SYMBOL_TABLE < 0) + OMIT_SYMBOL_TABLE = 1; + } + if (strcmp(command,"LONG_DICT_FLAG_BUG")==0) + { + LONG_DICT_FLAG_BUG=j, flag=1; + if (LONG_DICT_FLAG_BUG > 1 || LONG_DICT_FLAG_BUG < 0) + LONG_DICT_FLAG_BUG = 1; + } if (strcmp(command,"SERIAL")==0) { if (j >= 0 && j <= 999999) @@ -1118,9 +964,10 @@ extern void memory_command(char *command) if (flag==0) printf("No such memory setting as \"%s\"\n", command); - if (flag==2) - printf("The Inform 5 memory setting \"%s\" has been withdrawn.\n\ -It should be safe to omit it (putting nothing in its place).\n", command); + if (flag==2 && !nowarnings_switch) + printf("The Inform 5 memory setting \"%s\" has been withdrawn.\n", command); + if (flag==3 && !nowarnings_switch) + printf("The Inform 6 memory setting \"%s\" is no longer needed and has been withdrawn.\n", command); return; } }