1 /* ------------------------------------------------------------------------- */
2 /* "memory" : Memory management and ICL memory setting commands */
3 /* (For "memoryerror", see "errors.c") */
5 /* Copyright (c) Graham Nelson 1993 - 2018 */
7 /* This file is part of Inform. */
9 /* Inform is free software: you can redistribute it and/or modify */
10 /* it under the terms of the GNU General Public License as published by */
11 /* the Free Software Foundation, either version 3 of the License, or */
12 /* (at your option) any later version. */
14 /* Inform is distributed in the hope that it will be useful, */
15 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17 /* GNU General Public License for more details. */
19 /* You should have received a copy of the GNU General Public License */
20 /* along with Inform. If not, see https://gnu.org/licenses/ */
22 /* ------------------------------------------------------------------------- */
26 int32 malloced_bytes=0; /* Total amount of memory allocated */
30 extern void *my_malloc(int32 size, char *whatfor)
33 printf("Allocating %ld bytes for %s\n",size,whatfor);
34 if (size==0) return(NULL);
35 c=(char _huge *)halloc(size,1); malloced_bytes+=size;
36 if (c==0) memory_out_error(size, 1, whatfor);
40 extern void my_realloc(void *pointer, int32 oldsize, int32 size,
44 my_free(pointer, whatfor);
47 c=halloc(size,1); malloced_bytes+=size;
48 if (c==0) memory_out_error(size, 1, whatfor);
50 printf("Increasing allocation to %ld bytes for %s was (%08lx) \
52 (long int) size,whatfor,(long int) (*(int **)pointer),
54 memcpy(c, *(int **)pointer, MIN(oldsize, size));
55 hfree(*(int **)pointer);
59 extern void *my_calloc(int32 size, int32 howmany, char *whatfor)
62 printf("Allocating %d bytes: array (%ld entries size %ld) for %s\n",
63 size*howmany,howmany,size,whatfor);
64 if ((size*howmany) == 0) return(NULL);
65 c=(void _huge *)halloc(howmany*size,1); malloced_bytes+=size*howmany;
66 if (c==0) memory_out_error(size, howmany, whatfor);
70 extern void my_recalloc(void *pointer, int32 size, int32 oldhowmany,
71 int32 howmany, char *whatfor)
73 if (size*howmany==0) {
74 my_free(pointer, whatfor);
77 c=(void _huge *)halloc(size*howmany,1); malloced_bytes+=size*howmany;
78 if (c==0) memory_out_error(size, howmany, whatfor);
80 printf("Increasing allocation to %ld bytes: array (%ld entries size %ld) \
81 for %s was (%08lx) now (%08lx)\n",
82 ((long int)size) * ((long int)howmany),
83 (long int)howmany,(long int)size,whatfor,
84 (long int) *(int **)pointer, (long int) c);
85 memcpy(c, *(int **)pointer, MIN(size*oldhowmany, size*howmany));
86 hfree(*(int **)pointer);
92 extern void *my_malloc(int32 size, char *whatfor)
94 if (size==0) return(NULL);
95 c=malloc((size_t) size); malloced_bytes+=size;
96 if (c==0) memory_out_error(size, 1, whatfor);
98 printf("Allocating %ld bytes for %s at (%08lx)\n",
99 (long int) size,whatfor,(long int) c);
103 extern void my_realloc(void *pointer, int32 oldsize, int32 size,
107 my_free(pointer, whatfor);
110 c=realloc(*(int **)pointer, (size_t) size); malloced_bytes+=size;
111 if (c==0) memory_out_error(size, 1, whatfor);
113 printf("Increasing allocation to %ld bytes for %s was (%08lx) \
115 (long int) size,whatfor,(long int) (*(int **)pointer),
117 *(int **)pointer = c;
120 extern void *my_calloc(int32 size, int32 howmany, char *whatfor)
122 if (size*howmany==0) return(NULL);
123 c=calloc(howmany,(size_t) size); malloced_bytes+=size*howmany;
124 if (c==0) memory_out_error(size, howmany, whatfor);
126 printf("Allocating %ld bytes: array (%ld entries size %ld) \
127 for %s at (%08lx)\n",
128 ((long int)size) * ((long int)howmany),
129 (long int)howmany,(long int)size,whatfor,
134 extern void my_recalloc(void *pointer, int32 size, int32 oldhowmany,
135 int32 howmany, char *whatfor)
137 if (size*howmany==0) {
138 my_free(pointer, whatfor);
141 c=realloc(*(int **)pointer, (size_t)size*(size_t)howmany);
142 malloced_bytes+=size*howmany;
143 if (c==0) memory_out_error(size, howmany, whatfor);
145 printf("Increasing allocation to %ld bytes: array (%ld entries size %ld) \
146 for %s was (%08lx) now (%08lx)\n",
147 ((long int)size) * ((long int)howmany),
148 (long int)howmany,(long int)size,whatfor,
149 (long int) *(int **)pointer, (long int) c);
150 *(int **)pointer = c;
155 extern void my_free(void *pointer, char *whatitwas)
157 if (*(int **)pointer != NULL)
159 printf("Freeing memory for %s at (%08lx)\n",
160 whatitwas, (long int) (*(int **)pointer));
162 hfree(*(int **)pointer);
164 free(*(int **)pointer);
166 *(int **)pointer = NULL;
170 /* ------------------------------------------------------------------------- */
171 /* Extensible blocks of memory, providing a kind of RAM disc as an */
172 /* alternative to the temporary files option */
173 /* ------------------------------------------------------------------------- */
175 static char chunk_name_buffer[60];
176 static char *chunk_name(memory_block *MB, int no)
177 { char *p = "(unknown)";
178 if (MB == &static_strings_area) p = "static strings area";
179 if (MB == &zcode_area) p = "Z-code area";
180 if (MB == &link_data_area) p = "link data area";
181 if (MB == &zcode_backpatch_table) p = "Z-code backpatch table";
182 if (MB == &zmachine_backpatch_table) p = "Z-machine backpatch table";
183 sprintf(chunk_name_buffer, "%s chunk %d", p, no);
184 return(chunk_name_buffer);
187 extern void initialise_memory_block(memory_block *MB)
190 for (i=0; i<72; i++) MB->chunk[i] = NULL;
191 MB->extent_of_last = 0;
195 extern void deallocate_memory_block(memory_block *MB)
198 if (MB->chunk[i] != NULL)
199 my_free(&(MB->chunk[i]), chunk_name(MB, i));
201 MB->extent_of_last = 0;
204 extern int read_byte_from_memory_block(memory_block *MB, int32 index)
206 p = MB->chunk[index/ALLOC_CHUNK_SIZE];
208 { compiler_error_named("memory: read from unwritten byte in",
209 chunk_name(MB, index/ALLOC_CHUNK_SIZE));
212 return p[index % ALLOC_CHUNK_SIZE];
215 extern void write_byte_to_memory_block(memory_block *MB, int32 index, int value)
216 { uchar *p; int ch = index/ALLOC_CHUNK_SIZE;
218 { compiler_error_named("memory: negative index to", chunk_name(MB, 0));
221 if (ch >= 72) memoryerror("ALLOC_CHUNK_SIZE", ALLOC_CHUNK_SIZE);
223 if (MB->chunk[ch] == NULL)
225 MB->chunk[ch] = my_malloc(ALLOC_CHUNK_SIZE, chunk_name(MB, ch));
227 for (i=0; i<ALLOC_CHUNK_SIZE; i++) p[i] = 255;
231 p[index % ALLOC_CHUNK_SIZE] = value;
234 /* ------------------------------------------------------------------------- */
235 /* Where the memory settings are declared as variables */
236 /* ------------------------------------------------------------------------- */
240 int SYMBOLS_CHUNK_SIZE;
246 int MAX_DICT_ENTRIES;
248 int MAX_PROP_TABLE_SIZE;
250 int MAX_EXPRESSION_NODES;
255 int32 MAX_STATIC_STRINGS;
256 int32 MAX_ZCODE_SIZE;
258 int32 MAX_TRANSCRIPT_SIZE;
260 int32 MAX_LINK_DATA_SIZE;
261 int MAX_INCLUSION_DEPTH;
262 int MAX_SOURCE_FILES;
263 int32 MAX_INDIV_PROP_TABLE_SIZE;
264 int32 MAX_OBJ_PROP_TABLE_SIZE;
265 int MAX_OBJ_PROP_COUNT;
266 int MAX_LOCAL_VARIABLES;
267 int MAX_GLOBAL_VARIABLES;
268 int DICT_WORD_SIZE; /* number of characters in a dict word */
269 int DICT_CHAR_SIZE; /* (glulx) 1 for one-byte chars, 4 for Unicode chars */
270 int DICT_WORD_BYTES; /* DICT_WORD_SIZE*DICT_CHAR_SIZE */
271 int ZCODE_HEADER_EXT_WORDS; /* (zcode 1.0) requested header extension size */
272 int ZCODE_HEADER_FLAGS_3; /* (zcode 1.1) value to place in Flags 3 word */
274 int GLULX_OBJECT_EXT_BYTES; /* (glulx) extra bytes for each object record */
275 int32 MAX_NUM_STATIC_STRINGS;
276 int32 MAX_UNICODE_CHARS;
277 int32 MAX_STACK_SIZE;
278 int32 MEMORY_MAP_EXTENSION;
279 int ALLOC_CHUNK_SIZE;
280 int WARN_UNUSED_ROUTINES; /* 0: no, 1: yes except in system files, 2: yes always */
281 int OMIT_UNUSED_ROUTINES; /* 0: no, 1: yes */
283 /* The way memory sizes are set causes great nuisance for those parameters
284 which have different defaults under Z-code and Glulx. We have to get
285 the defaults right whether the user sets "-G $HUGE" or "$HUGE -G".
286 And an explicit value set by the user should override both defaults. */
287 static int32 MAX_ZCODE_SIZE_z, MAX_ZCODE_SIZE_g;
288 static int MAX_PROP_TABLE_SIZE_z, MAX_PROP_TABLE_SIZE_g;
289 static int MAX_GLOBAL_VARIABLES_z, MAX_GLOBAL_VARIABLES_g;
290 static int MAX_LOCAL_VARIABLES_z, MAX_LOCAL_VARIABLES_g;
291 static int DICT_WORD_SIZE_z, DICT_WORD_SIZE_g;
292 static int NUM_ATTR_BYTES_z, NUM_ATTR_BYTES_g;
293 static int ALLOC_CHUNK_SIZE_z, ALLOC_CHUNK_SIZE_g;
295 /* ------------------------------------------------------------------------- */
296 /* Memory control from the command line */
297 /* ------------------------------------------------------------------------- */
299 static void list_memory_sizes(void)
300 { printf("+--------------------------------------+\n");
301 printf("| %25s = %-7s |\n","Memory setting","Value");
302 printf("+--------------------------------------+\n");
303 printf("| %25s = %-7d |\n","MAX_ABBREVS",MAX_ABBREVS);
304 printf("| %25s = %-7d |\n","MAX_ACTIONS",MAX_ACTIONS);
305 printf("| %25s = %-7d |\n","MAX_ADJECTIVES",MAX_ADJECTIVES);
306 printf("| %25s = %-7d |\n","ALLOC_CHUNK_SIZE",ALLOC_CHUNK_SIZE);
307 printf("| %25s = %-7d |\n","MAX_ARRAYS",MAX_ARRAYS);
308 printf("| %25s = %-7d |\n","NUM_ATTR_BYTES",NUM_ATTR_BYTES);
309 printf("| %25s = %-7d |\n","MAX_CLASSES",MAX_CLASSES);
310 printf("| %25s = %-7d |\n","MAX_DICT_ENTRIES",MAX_DICT_ENTRIES);
311 printf("| %25s = %-7d |\n","DICT_WORD_SIZE",DICT_WORD_SIZE);
313 printf("| %25s = %-7d |\n","DICT_CHAR_SIZE",DICT_CHAR_SIZE);
314 printf("| %25s = %-7d |\n","MAX_EXPRESSION_NODES",MAX_EXPRESSION_NODES);
315 printf("| %25s = %-7d |\n","MAX_GLOBAL_VARIABLES",MAX_GLOBAL_VARIABLES);
316 printf("| %25s = %-7d |\n","HASH_TAB_SIZE",HASH_TAB_SIZE);
318 printf("| %25s = %-7d |\n","ZCODE_HEADER_EXT_WORDS",ZCODE_HEADER_EXT_WORDS);
320 printf("| %25s = %-7d |\n","ZCODE_HEADER_FLAGS_3",ZCODE_HEADER_FLAGS_3);
321 printf("| %25s = %-7d |\n","MAX_INCLUSION_DEPTH",MAX_INCLUSION_DEPTH);
322 printf("| %25s = %-7d |\n","MAX_INDIV_PROP_TABLE_SIZE", MAX_INDIV_PROP_TABLE_SIZE);
323 printf("| %25s = %-7d |\n","INDIV_PROP_START", INDIV_PROP_START);
324 printf("| %25s = %-7d |\n","MAX_LABELS",MAX_LABELS);
325 printf("| %25s = %-7d |\n","MAX_LINESPACE",MAX_LINESPACE);
326 printf("| %25s = %-7d |\n","MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE);
328 printf("| %25s = %-7d |\n","MAX_LOCAL_VARIABLES",MAX_LOCAL_VARIABLES);
329 printf("| %25s = %-7d |\n","MAX_LOW_STRINGS",MAX_LOW_STRINGS);
331 printf("| %25s = %-7d |\n","MEMORY_MAP_EXTENSION",
332 MEMORY_MAP_EXTENSION);
334 printf("| %25s = %-7d |\n","MAX_NUM_STATIC_STRINGS",
335 MAX_NUM_STATIC_STRINGS);
336 printf("| %25s = %-7d |\n","MAX_OBJECTS",MAX_OBJECTS);
338 printf("| %25s = %-7d |\n","GLULX_OBJECT_EXT_BYTES",
339 GLULX_OBJECT_EXT_BYTES);
341 printf("| %25s = %-7d |\n","MAX_OBJ_PROP_COUNT",
344 printf("| %25s = %-7d |\n","MAX_OBJ_PROP_TABLE_SIZE",
345 MAX_OBJ_PROP_TABLE_SIZE);
346 printf("| %25s = %-7d |\n","MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
347 printf("| %25s = %-7d |\n","MAX_QTEXT_SIZE",MAX_QTEXT_SIZE);
348 printf("| %25s = %-7d |\n","MAX_SOURCE_FILES",MAX_SOURCE_FILES);
350 printf("| %25s = %-7ld |\n","MAX_STACK_SIZE",
351 (long int) MAX_STACK_SIZE);
352 printf("| %25s = %-7d |\n","MAX_STATIC_DATA",MAX_STATIC_DATA);
353 printf("| %25s = %-7ld |\n","MAX_STATIC_STRINGS",
354 (long int) MAX_STATIC_STRINGS);
355 printf("| %25s = %-7d |\n","MAX_SYMBOLS",MAX_SYMBOLS);
356 printf("| %25s = %-7d |\n","SYMBOLS_CHUNK_SIZE",SYMBOLS_CHUNK_SIZE);
357 printf("| %25s = %-7ld |\n","MAX_TRANSCRIPT_SIZE",
358 (long int) MAX_TRANSCRIPT_SIZE);
360 printf("| %25s = %-7ld |\n","MAX_UNICODE_CHARS",
361 (long int) MAX_UNICODE_CHARS);
362 printf("| %25s = %-7d |\n","WARN_UNUSED_ROUTINES",WARN_UNUSED_ROUTINES);
363 printf("| %25s = %-7d |\n","OMIT_UNUSED_ROUTINES",OMIT_UNUSED_ROUTINES);
364 printf("| %25s = %-7d |\n","MAX_VERBS",MAX_VERBS);
365 printf("| %25s = %-7d |\n","MAX_VERBSPACE",MAX_VERBSPACE);
366 printf("| %25s = %-7ld |\n","MAX_ZCODE_SIZE",
367 (long int) MAX_ZCODE_SIZE);
368 printf("+--------------------------------------+\n");
371 extern void set_memory_sizes(int size_flag)
373 if (size_flag == HUGE_SIZE)
375 MAX_QTEXT_SIZE = 4000;
378 SYMBOLS_CHUNK_SIZE = 5000;
385 MAX_DICT_ENTRIES = 2000;
386 MAX_STATIC_DATA = 10000;
388 MAX_PROP_TABLE_SIZE_z = 30000;
389 MAX_PROP_TABLE_SIZE_g = 60000;
393 MAX_EXPRESSION_NODES = 100;
395 MAX_VERBSPACE = 4096;
397 MAX_LINESPACE = 16000;
399 MAX_STATIC_STRINGS = 8000;
400 MAX_ZCODE_SIZE_z = 20000;
401 MAX_ZCODE_SIZE_g = 40000;
402 MAX_LINK_DATA_SIZE = 2000;
404 MAX_LOW_STRINGS = 2048;
406 MAX_TRANSCRIPT_SIZE = 200000;
407 MAX_NUM_STATIC_STRINGS = 20000;
411 MAX_OBJ_PROP_COUNT = 128;
412 MAX_OBJ_PROP_TABLE_SIZE = 4096;
414 MAX_INDIV_PROP_TABLE_SIZE = 15000;
417 MAX_GLOBAL_VARIABLES_z = 240;
418 MAX_GLOBAL_VARIABLES_g = 512;
420 ALLOC_CHUNK_SIZE_z = 8192;
421 ALLOC_CHUNK_SIZE_g = 32768;
423 if (size_flag == LARGE_SIZE)
425 MAX_QTEXT_SIZE = 4000;
428 SYMBOLS_CHUNK_SIZE = 5000;
435 MAX_DICT_ENTRIES = 1300;
436 MAX_STATIC_DATA = 10000;
438 MAX_PROP_TABLE_SIZE_z = 15000;
439 MAX_PROP_TABLE_SIZE_g = 30000;
443 MAX_EXPRESSION_NODES = 100;
445 MAX_VERBSPACE = 4096;
446 MAX_LINESPACE = 10000;
449 MAX_STATIC_STRINGS = 8000;
450 MAX_ZCODE_SIZE_z = 20000;
451 MAX_ZCODE_SIZE_g = 40000;
452 MAX_LINK_DATA_SIZE = 2000;
454 MAX_LOW_STRINGS = 2048;
456 MAX_TRANSCRIPT_SIZE = 200000;
457 MAX_NUM_STATIC_STRINGS = 20000;
461 MAX_OBJ_PROP_COUNT = 64;
462 MAX_OBJ_PROP_TABLE_SIZE = 2048;
464 MAX_INDIV_PROP_TABLE_SIZE = 10000;
467 MAX_GLOBAL_VARIABLES_z = 240;
468 MAX_GLOBAL_VARIABLES_g = 512;
470 ALLOC_CHUNK_SIZE_z = 8192;
471 ALLOC_CHUNK_SIZE_g = 16384;
473 if (size_flag == SMALL_SIZE)
475 MAX_QTEXT_SIZE = 4000;
478 SYMBOLS_CHUNK_SIZE = 2500;
485 MAX_DICT_ENTRIES = 700;
486 MAX_STATIC_DATA = 10000;
488 MAX_PROP_TABLE_SIZE_z = 8000;
489 MAX_PROP_TABLE_SIZE_g = 16000;
493 MAX_EXPRESSION_NODES = 40;
495 MAX_VERBSPACE = 2048;
496 MAX_LINESPACE = 10000;
499 MAX_STATIC_STRINGS = 8000;
500 MAX_ZCODE_SIZE_z = 10000;
501 MAX_ZCODE_SIZE_g = 20000;
502 MAX_LINK_DATA_SIZE = 1000;
504 MAX_LOW_STRINGS = 1024;
506 MAX_TRANSCRIPT_SIZE = 100000;
507 MAX_NUM_STATIC_STRINGS = 10000;
511 MAX_OBJ_PROP_COUNT = 64;
512 MAX_OBJ_PROP_TABLE_SIZE = 1024;
514 MAX_INDIV_PROP_TABLE_SIZE = 5000;
517 MAX_GLOBAL_VARIABLES_z = 240;
518 MAX_GLOBAL_VARIABLES_g = 256;
520 ALLOC_CHUNK_SIZE_z = 8192;
521 ALLOC_CHUNK_SIZE_g = 8192;
524 /* Regardless of size_flag... */
525 MAX_SOURCE_FILES = 256;
526 MAX_INCLUSION_DEPTH = 5;
527 MAX_LOCAL_VARIABLES_z = 16;
528 MAX_LOCAL_VARIABLES_g = 32;
530 DICT_WORD_SIZE_z = 6;
531 DICT_WORD_SIZE_g = 9;
532 NUM_ATTR_BYTES_z = 6;
533 NUM_ATTR_BYTES_g = 7;
534 /* Backwards-compatible behavior: allow for a unicode table
535 whether we need one or not. The user can set this to zero if
536 there's no unicode table. */
537 ZCODE_HEADER_EXT_WORDS = 3;
538 ZCODE_HEADER_FLAGS_3 = 0;
539 GLULX_OBJECT_EXT_BYTES = 0;
540 MAX_UNICODE_CHARS = 64;
541 MEMORY_MAP_EXTENSION = 0;
542 /* We estimate the default Glulx stack size at 4096. That's about
543 enough for 90 nested function calls with 8 locals each -- the
544 same capacity as the Z-Spec's suggestion for Z-machine stack
545 size. Note that Inform 7 wants more stack; I7-generated code
546 sets MAX_STACK_SIZE to 65536 by default. */
547 MAX_STACK_SIZE = 4096;
548 OMIT_UNUSED_ROUTINES = 0;
549 WARN_UNUSED_ROUTINES = 0;
551 adjust_memory_sizes();
554 extern void adjust_memory_sizes()
557 MAX_ZCODE_SIZE = MAX_ZCODE_SIZE_z;
558 MAX_PROP_TABLE_SIZE = MAX_PROP_TABLE_SIZE_z;
559 MAX_GLOBAL_VARIABLES = MAX_GLOBAL_VARIABLES_z;
560 MAX_LOCAL_VARIABLES = MAX_LOCAL_VARIABLES_z;
561 DICT_WORD_SIZE = DICT_WORD_SIZE_z;
562 NUM_ATTR_BYTES = NUM_ATTR_BYTES_z;
563 ALLOC_CHUNK_SIZE = ALLOC_CHUNK_SIZE_z;
564 INDIV_PROP_START = 64;
567 MAX_ZCODE_SIZE = MAX_ZCODE_SIZE_g;
568 MAX_PROP_TABLE_SIZE = MAX_PROP_TABLE_SIZE_g;
569 MAX_GLOBAL_VARIABLES = MAX_GLOBAL_VARIABLES_g;
570 MAX_LOCAL_VARIABLES = MAX_LOCAL_VARIABLES_g;
571 DICT_WORD_SIZE = DICT_WORD_SIZE_g;
572 NUM_ATTR_BYTES = NUM_ATTR_BYTES_g;
573 ALLOC_CHUNK_SIZE = ALLOC_CHUNK_SIZE_g;
574 INDIV_PROP_START = 256;
578 static void explain_parameter(char *command)
580 if (strcmp(command,"MAX_QTEXT_SIZE")==0)
582 " MAX_QTEXT_SIZE is the maximum length of a quoted string. Increasing\n\
583 by 1 costs 5 bytes (for lexical analysis memory). Inform automatically\n\
584 ensures that MAX_STATIC_STRINGS is at least twice the size of this.");
587 if (strcmp(command,"MAX_SYMBOLS")==0)
589 " MAX_SYMBOLS is the maximum number of symbols - names of variables, \n\
590 objects, routines, the many internal Inform-generated names and so on.\n");
593 if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0)
595 " The symbols names are stored in memory which is allocated in chunks \n\
596 of size SYMBOLS_CHUNK_SIZE.\n");
599 if (strcmp(command,"HASH_TAB_SIZE")==0)
601 " HASH_TAB_SIZE is the size of the hash tables used for the heaviest \n\
605 if (strcmp(command,"MAX_OBJECTS")==0)
607 " MAX_OBJECTS is the maximum number of objects. (If compiling a version-3 \n\
608 game, 255 is an absolute maximum in any event.)\n");
611 if (strcmp(command,"MAX_ACTIONS")==0)
613 " MAX_ACTIONS is the maximum number of actions - that is, routines such as \n\
614 TakeSub which are referenced in the grammar table.\n");
617 if (strcmp(command,"MAX_ADJECTIVES")==0)
619 " MAX_ADJECTIVES is the maximum number of different \"adjectives\" in the \n\
620 grammar table. Adjectives are misleadingly named: they are words such as \n\
621 \"in\", \"under\" and the like.\n");
624 if (strcmp(command,"MAX_DICT_ENTRIES")==0)
626 " MAX_DICT_ENTRIES is the maximum number of words which can be entered \n\
627 into the game's dictionary. It costs 29 bytes to increase this by one.\n");
630 if (strcmp(command,"DICT_WORD_SIZE")==0)
632 " DICT_WORD_SIZE is the number of characters in a dictionary word. In \n\
633 Z-code this is always 6 (only 4 are used in v3 games). In Glulx it \n\
634 can be any number.\n");
637 if (strcmp(command,"DICT_CHAR_SIZE")==0)
639 " DICT_CHAR_SIZE is the byte size of one character in the dictionary. \n\
640 (This is only meaningful in Glulx, since Z-code has compressed dictionary \n\
641 words.) It can be either 1 (the default) or 4 (to enable full Unicode \n\
645 if (strcmp(command,"NUM_ATTR_BYTES")==0)
647 " NUM_ATTR_BYTES is the space used to store attribute flags. Each byte \n\
648 stores eight attributes. In Z-code this is always 6 (only 4 are used in \n\
649 v3 games). In Glulx it can be any number which is a multiple of four, \n\
653 if (strcmp(command,"ZCODE_HEADER_EXT_WORDS")==0)
655 " ZCODE_HEADER_EXT_WORDS is the number of words in the Z-code header \n\
656 extension table (Z-Spec 1.0). The -W switch also sets this. It defaults \n\
657 to 3, but can be set higher. (It can be set lower if no Unicode \n\
658 translation table is created.)\n");
661 if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0)
663 " ZCODE_HEADER_FLAGS_3 is the value to store in the Flags 3 word of the \n\
664 header extension table (Z-Spec 1.1).\n");
667 if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0)
669 " GLULX_OBJECT_EXT_BYTES is an amount of additional space to add to each \n\
670 object record. It is initialized to zero bytes, and the game is free to \n\
671 use it as desired. (This is only meaningful in Glulx, since Z-code \n\
672 specifies the object structure.)\n");
675 if (strcmp(command,"MAX_STATIC_DATA")==0)
677 " MAX_STATIC_DATA is the size of an array of integers holding initial \n\
678 values for arrays and strings stored as ASCII inside the Z-machine. It \n\
679 should be at least 1024 but seldom needs much more.\n");
682 if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0)
684 " MAX_PROP_TABLE_SIZE is the number of bytes allocated to hold the \n\
685 properties table.\n");
688 if (strcmp(command,"MAX_ABBREVS")==0)
690 " MAX_ABBREVS is the maximum number of declared abbreviations. It is not \n\
691 allowed to exceed 64.\n");
694 if (strcmp(command,"MAX_ARRAYS")==0)
696 " MAX_ARRAYS is the maximum number of declared arrays.\n");
699 if (strcmp(command,"MAX_EXPRESSION_NODES")==0)
701 " MAX_EXPRESSION_NODES is the maximum number of nodes in the expression \n\
702 evaluator's storage for parse trees. In effect, it measures how \n\
703 complicated algebraic expressions are allowed to be. Increasing it by \n\
704 one costs about 80 bytes.\n");
707 if (strcmp(command,"MAX_VERBS")==0)
709 " MAX_VERBS is the maximum number of verbs (such as \"take\") which can be \n\
710 defined, each with its own grammar. To increase it by one costs about\n\
711 128 bytes. A full game will contain at least 100.\n");
714 if (strcmp(command,"MAX_VERBSPACE")==0)
716 " MAX_VERBSPACE is the size of workspace used to store verb words, so may\n\
717 need increasing in games with many synonyms: unlikely to exceed 4K.\n");
720 if (strcmp(command,"MAX_LABELS")==0)
722 " MAX_LABELS is the maximum number of label points in any one routine.\n\
723 (If the -k debugging information switch is set, MAX_LABELS is raised to\n\
724 a minimum level of 2000, as about twice the normal number of label points\n\
725 are needed to generate tables of how source code corresponds to positions\n\
726 in compiled code.)");
729 if (strcmp(command,"MAX_LINESPACE")==0)
731 " MAX_LINESPACE is the size of workspace used to store grammar lines, so \n\
732 may need increasing in games with complex or extensive grammars.\n");
735 if (strcmp(command,"MAX_STATIC_STRINGS")==0)
738 " MAX_STATIC_STRINGS is the size in bytes of a buffer to hold compiled\n\
739 strings before they're written into longer-term storage. 2000 bytes is \n\
740 plenty, allowing string constants of up to about 3000 characters long.\n\
741 Inform automatically ensures that this is at least twice the size of\n\
742 MAX_QTEXT_SIZE, to be on the safe side.");
745 if (strcmp(command,"MAX_ZCODE_SIZE")==0)
748 " MAX_ZCODE_SIZE is the size in bytes of a buffer to hold compiled \n\
749 code for a single routine. (It applies to both Z-code and Glulx, \n\
750 despite the name.) As a guide, the longest library routine is \n\
751 about 6500 bytes long in Z-code; about twice that in Glulx.");
754 if (strcmp(command,"MAX_LINK_DATA_SIZE")==0)
757 " MAX_LINK_DATA_SIZE is the size in bytes of a buffer to hold module \n\
758 link data before it's written into longer-term storage. 2000 bytes \n\
762 if (strcmp(command,"MAX_LOW_STRINGS")==0)
764 " MAX_LOW_STRINGS is the size in bytes of a buffer to hold all the \n\
765 compiled \"low strings\" which are to be written above the synonyms table \n\
766 in the Z-machine. 1024 is plenty.\n");
769 if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0)
771 " MAX_TRANSCRIPT_SIZE is only allocated for the abbreviations optimisation \n\
772 switch, and has the size in bytes of a buffer to hold the entire text of\n\
773 the game being compiled: it has to be enormous, say 100000 to 200000.\n");
776 if (strcmp(command,"MAX_CLASSES")==0)
778 " MAX_CLASSES maximum number of object classes which can be defined. This\n\
779 is cheap to increase.\n");
782 if (strcmp(command,"MAX_INCLUSION_DEPTH")==0)
784 " MAX_INCLUSION_DEPTH is the number of nested includes permitted.\n");
787 if (strcmp(command,"MAX_SOURCE_FILES")==0)
789 " MAX_SOURCE_FILES is the number of source files that can be read in the \n\
793 if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0)
795 " MAX_INDIV_PROP_TABLE_SIZE is the number of bytes allocated to hold the \n\
796 table of ..variable values.\n");
799 if (strcmp(command,"INDIV_PROP_START")==0)
801 " Properties 1 to INDIV_PROP_START-1 are common properties; individual\n\
802 properties are numbered INDIV_PROP_START and up.\n");
805 if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0)
807 " MAX_OBJ_PROP_COUNT is the maximum number of properties a single object \n\
808 can have. (Glulx only)\n");
811 if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0)
813 " MAX_OBJ_PROP_TABLE_SIZE is the number of words allocated to hold a \n\
814 single object's properties. (Glulx only)\n");
817 if (strcmp(command,"MAX_LOCAL_VARIABLES")==0)
819 " MAX_LOCAL_VARIABLES is the number of local variables (including \n\
820 arguments) allowed in a procedure. (Glulx only)\n");
823 if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0)
825 " MAX_GLOBAL_VARIABLES is the number of global variables allowed in the \n\
826 program. (Glulx only)\n");
829 if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0)
832 " MAX_NUM_STATIC_STRINGS is the maximum number of compiled strings \n\
833 allowed in the program. (Glulx only)\n");
836 if (strcmp(command,"MAX_UNICODE_CHARS")==0)
839 " MAX_UNICODE_CHARS is the maximum number of different Unicode characters \n\
840 (beyond the Latin-1 range, $00..$FF) which the game text can use. \n\
844 if (strcmp(command,"ALLOC_CHUNK_SIZE")==0)
847 " ALLOC_CHUNK_SIZE is a base unit of Inform's internal memory allocation \n\
848 for various structures.\n");
851 if (strcmp(command,"MAX_STACK_SIZE")==0)
854 " MAX_STACK_SIZE is the maximum size (in bytes) of the interpreter stack \n\
855 during gameplay. (Glulx only)\n");
858 if (strcmp(command,"MEMORY_MAP_EXTENSION")==0)
861 " MEMORY_MAP_EXTENSION is the number of bytes (all zeroes) to map into \n\
862 memory after the game file. (Glulx only)\n");
865 if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
868 " WARN_UNUSED_ROUTINES, if set to 2, will display a warning for each \n\
869 routine in the game file which is never called. (This includes \n\
870 routines called only from uncalled routines, etc.) If set to 1, will warn \n\
871 only about functions in game code, not in the system library.\n");
874 if (strcmp(command,"OMIT_UNUSED_ROUTINES")==0)
877 " OMIT_UNUSED_ROUTINES, if set to 1, will avoid compiling unused routines \n\
878 into the game file.\n");
881 if (strcmp(command,"SERIAL")==0)
884 " SERIAL, if set, will be used as the six digit serial number written into \n\
885 the header of the output file.\n");
889 printf("No such memory setting as \"%s\"\n",command);
894 /* Parse a decimal number as an int32. Return true if a valid number
895 was found; otherwise print a warning and return false.
897 Anything over nine digits is considered an overflow; we report a
898 warning but return +/- 999999999 (and true). This is not entirely
899 clever about leading zeroes ("0000000001" is treated as an
900 overflow) but this is better than trying to detect genuine
903 (Some Glulx settings might conceivably want to go up to $7FFFFFFF,
904 which is a ten-digit number, but we're not going to allow that
907 This used to rely on atoi(), and we retain the atoi() behavior of
908 ignoring garbage characters after a valid decimal number.
910 static int parse_memory_setting(char *str, char *label, int32 *result)
918 while (*cx == ' ') cx++;
920 val = strtol(cx, &ex, 10);
923 printf("Bad numerical setting in $ command \"%s=%s\"\n",
931 printf("Numerical setting underflowed in $ command \"%s=%s\" (limiting to %ld)\n",
938 printf("Numerical setting overflowed in $ command \"%s=%s\" (limiting to %ld)\n",
943 *result = (int32)val;
947 extern void memory_command(char *command)
948 { int i, k, flag=0; int32 j;
950 for (k=0; command[k]!=0; k++)
951 if (islower(command[k])) command[k]=toupper(command[k]);
953 if (command[0]=='?') { explain_parameter(command+1); return; }
955 if (strcmp(command, "HUGE")==0) { set_memory_sizes(HUGE_SIZE); return; }
956 if (strcmp(command, "LARGE")==0) { set_memory_sizes(LARGE_SIZE); return; }
957 if (strcmp(command, "SMALL")==0) { set_memory_sizes(SMALL_SIZE); return; }
958 if (strcmp(command, "LIST")==0) { list_memory_sizes(); return; }
959 for (i=0; command[i]!=0; i++)
960 { if (command[i]=='=')
962 if (!parse_memory_setting(command+i+1, command, &j)) {
965 if (strcmp(command,"BUFFER_LENGTH")==0)
967 if (strcmp(command,"MAX_QTEXT_SIZE")==0)
968 { MAX_QTEXT_SIZE=j, flag=1;
969 if (2*MAX_QTEXT_SIZE > MAX_STATIC_STRINGS)
970 MAX_STATIC_STRINGS = 2*MAX_QTEXT_SIZE;
972 if (strcmp(command,"MAX_SYMBOLS")==0)
973 MAX_SYMBOLS=j, flag=1;
974 if (strcmp(command,"MAX_BANK_SIZE")==0)
976 if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0)
977 SYMBOLS_CHUNK_SIZE=j, flag=1;
978 if (strcmp(command,"BANK_CHUNK_SIZE")==0)
980 if (strcmp(command,"HASH_TAB_SIZE")==0)
981 HASH_TAB_SIZE=j, flag=1;
982 if (strcmp(command,"MAX_OBJECTS")==0)
983 MAX_OBJECTS=j, flag=1;
984 if (strcmp(command,"MAX_ACTIONS")==0)
985 MAX_ACTIONS=j, flag=1;
986 if (strcmp(command,"MAX_ADJECTIVES")==0)
987 MAX_ADJECTIVES=j, flag=1;
988 if (strcmp(command,"MAX_DICT_ENTRIES")==0)
989 MAX_DICT_ENTRIES=j, flag=1;
990 if (strcmp(command,"DICT_WORD_SIZE")==0)
991 { DICT_WORD_SIZE=j, flag=1;
992 DICT_WORD_SIZE_g=DICT_WORD_SIZE_z=j;
994 if (strcmp(command,"DICT_CHAR_SIZE")==0)
995 DICT_CHAR_SIZE=j, flag=1;
996 if (strcmp(command,"NUM_ATTR_BYTES")==0)
997 { NUM_ATTR_BYTES=j, flag=1;
998 NUM_ATTR_BYTES_g=NUM_ATTR_BYTES_z=j;
1000 if (strcmp(command,"ZCODE_HEADER_EXT_WORDS")==0)
1001 ZCODE_HEADER_EXT_WORDS=j, flag=1;
1002 if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0)
1003 ZCODE_HEADER_FLAGS_3=j, flag=1;
1004 if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0)
1005 GLULX_OBJECT_EXT_BYTES=j, flag=1;
1006 if (strcmp(command,"MAX_STATIC_DATA")==0)
1007 MAX_STATIC_DATA=j, flag=1;
1008 if (strcmp(command,"MAX_OLDEPTH")==0)
1010 if (strcmp(command,"MAX_ROUTINES")==0)
1012 if (strcmp(command,"MAX_GCONSTANTS")==0)
1014 if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0)
1015 { MAX_PROP_TABLE_SIZE=j, flag=1;
1016 MAX_PROP_TABLE_SIZE_g=MAX_PROP_TABLE_SIZE_z=j;
1018 if (strcmp(command,"MAX_FORWARD_REFS")==0)
1020 if (strcmp(command,"STACK_SIZE")==0)
1022 if (strcmp(command,"STACK_LONG_SLOTS")==0)
1024 if (strcmp(command,"STACK_SHORT_LENGTH")==0)
1026 if (strcmp(command,"MAX_ABBREVS")==0)
1027 MAX_ABBREVS=j, flag=1;
1028 if (strcmp(command,"MAX_ARRAYS")==0)
1029 MAX_ARRAYS=j, flag=1;
1030 if (strcmp(command,"MAX_EXPRESSION_NODES")==0)
1031 MAX_EXPRESSION_NODES=j, flag=1;
1032 if (strcmp(command,"MAX_VERBS")==0)
1033 MAX_VERBS=j, flag=1;
1034 if (strcmp(command,"MAX_VERBSPACE")==0)
1035 MAX_VERBSPACE=j, flag=1;
1036 if (strcmp(command,"MAX_LABELS")==0)
1037 MAX_LABELS=j, flag=1;
1038 if (strcmp(command,"MAX_LINESPACE")==0)
1039 MAX_LINESPACE=j, flag=1;
1040 if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0)
1041 MAX_NUM_STATIC_STRINGS=j, flag=1;
1042 if (strcmp(command,"MAX_STATIC_STRINGS")==0)
1043 { MAX_STATIC_STRINGS=j, flag=1;
1044 if (2*MAX_QTEXT_SIZE > MAX_STATIC_STRINGS)
1045 MAX_STATIC_STRINGS = 2*MAX_QTEXT_SIZE;
1047 if (strcmp(command,"MAX_ZCODE_SIZE")==0)
1048 { MAX_ZCODE_SIZE=j, flag=1;
1049 MAX_ZCODE_SIZE_g=MAX_ZCODE_SIZE_z=j;
1051 if (strcmp(command,"MAX_LINK_DATA_SIZE")==0)
1052 MAX_LINK_DATA_SIZE=j, flag=1;
1053 if (strcmp(command,"MAX_LOW_STRINGS")==0)
1054 MAX_LOW_STRINGS=j, flag=1;
1055 if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0)
1056 MAX_TRANSCRIPT_SIZE=j, flag=1;
1057 if (strcmp(command,"MAX_CLASSES")==0)
1058 MAX_CLASSES=j, flag=1;
1059 if (strcmp(command,"MAX_INCLUSION_DEPTH")==0)
1060 MAX_INCLUSION_DEPTH=j, flag=1;
1061 if (strcmp(command,"MAX_SOURCE_FILES")==0)
1062 MAX_SOURCE_FILES=j, flag=1;
1063 if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0)
1064 MAX_INDIV_PROP_TABLE_SIZE=j, flag=1;
1065 if (strcmp(command,"INDIV_PROP_START")==0)
1066 INDIV_PROP_START=j, flag=1;
1067 if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0)
1068 MAX_OBJ_PROP_TABLE_SIZE=j, flag=1;
1069 if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0)
1070 MAX_OBJ_PROP_COUNT=j, flag=1;
1071 if (strcmp(command,"MAX_LOCAL_VARIABLES")==0)
1072 { MAX_LOCAL_VARIABLES=j, flag=1;
1073 MAX_LOCAL_VARIABLES_g=MAX_LOCAL_VARIABLES_z=j;
1075 if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0)
1076 { MAX_GLOBAL_VARIABLES=j, flag=1;
1077 MAX_GLOBAL_VARIABLES_g=MAX_GLOBAL_VARIABLES_z=j;
1079 if (strcmp(command,"ALLOC_CHUNK_SIZE")==0)
1080 { ALLOC_CHUNK_SIZE=j, flag=1;
1081 ALLOC_CHUNK_SIZE_g=ALLOC_CHUNK_SIZE_z=j;
1083 if (strcmp(command,"MAX_UNICODE_CHARS")==0)
1084 MAX_UNICODE_CHARS=j, flag=1;
1085 if (strcmp(command,"MAX_STACK_SIZE")==0)
1087 MAX_STACK_SIZE=j, flag=1;
1088 /* Adjust up to a 256-byte boundary. */
1089 MAX_STACK_SIZE = (MAX_STACK_SIZE + 0xFF) & (~0xFF);
1091 if (strcmp(command,"MEMORY_MAP_EXTENSION")==0)
1093 MEMORY_MAP_EXTENSION=j, flag=1;
1094 /* Adjust up to a 256-byte boundary. */
1095 MEMORY_MAP_EXTENSION = (MEMORY_MAP_EXTENSION + 0xFF) & (~0xFF);
1097 if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
1099 WARN_UNUSED_ROUTINES=j, flag=1;
1100 if (WARN_UNUSED_ROUTINES > 2 || WARN_UNUSED_ROUTINES < 0)
1101 WARN_UNUSED_ROUTINES = 2;
1103 if (strcmp(command,"OMIT_UNUSED_ROUTINES")==0)
1105 OMIT_UNUSED_ROUTINES=j, flag=1;
1106 if (OMIT_UNUSED_ROUTINES > 1 || OMIT_UNUSED_ROUTINES < 0)
1107 OMIT_UNUSED_ROUTINES = 1;
1109 if (strcmp(command,"SERIAL")==0)
1111 if (j >= 0 && j <= 999999)
1113 sprintf(serial_code_buffer,"%06d",j);
1114 serial_code_given_in_program = TRUE;
1120 printf("No such memory setting as \"%s\"\n", command);
1122 printf("The Inform 5 memory setting \"%s\" has been withdrawn.\n\
1123 It should be safe to omit it (putting nothing in its place).\n", command);
1127 printf("No such memory $ command as \"%s\"\n",command);
1130 extern void print_memory_usage(void)
1132 printf("Properties table used %d\n",
1133 properties_table_size);
1134 printf("Allocated a total of %ld bytes of memory\n",
1135 (long int) malloced_bytes);
1138 /* ========================================================================= */
1139 /* Data structure management routines */
1140 /* ------------------------------------------------------------------------- */
1142 extern void init_memory_vars(void)
1143 { malloced_bytes = 0;
1146 extern void memory_begin_pass(void) { }
1148 extern void memory_allocate_arrays(void) { }
1150 extern void memory_free_arrays(void) { }
1152 /* ========================================================================= */