1 /* ------------------------------------------------------------------------- */
2 /* "memory" : Memory management and ICL memory setting commands */
4 /* Part of Inform 6.41 */
5 /* copyright (c) Graham Nelson 1993 - 2022 */
7 /* Inform is free software: you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation, either version 3 of the License, or */
10 /* (at your option) any later version. */
12 /* Inform is distributed in the hope that it will be useful, */
13 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
15 /* GNU General Public License for more details. */
17 /* You should have received a copy of the GNU General Public License */
18 /* along with Inform. If not, see https://gnu.org/licenses/ */
20 /* ------------------------------------------------------------------------- */
24 size_t malloced_bytes=0; /* Total amount of memory allocated */
26 /* Wrappers for malloc(), realloc(), etc.
28 Note that all of these functions call memory_out_error() on failure.
29 This is a fatal error and does not return. However, we check my_malloc()
30 return values anyway as a matter of good habit.
35 extern void *my_malloc(size_t size, char *whatfor)
38 printf("Allocating %ld bytes for %s\n",size,whatfor);
39 if (size==0) return(NULL);
40 c=(char _huge *)halloc(size,1);
42 if (c==0) memory_out_error(size, 1, whatfor);
46 extern void my_realloc(void *pointer, size_t oldsize, size_t size,
50 my_free(pointer, whatfor);
54 malloced_bytes+=(size-oldsize);
55 if (c==0) memory_out_error(size, 1, whatfor);
57 printf("Increasing allocation from %ld to %ld bytes for %s was (%08lx) now (%08lx)\n",
58 (long int) oldsize, (long int) size, whatfor,
59 (long int) (*(int **)pointer),
61 memcpy(c, *(int **)pointer, MIN(oldsize, size));
62 hfree(*(int **)pointer);
66 extern void *my_calloc(size_t size, size_t howmany, char *whatfor)
69 printf("Allocating %d bytes: array (%ld entries size %ld) for %s\n",
70 size*howmany,howmany,size,whatfor);
71 if ((size*howmany) == 0) return(NULL);
72 c=(void _huge *)halloc(howmany*size,1);
73 malloced_bytes+=size*howmany;
74 if (c==0) memory_out_error(size, howmany, whatfor);
78 extern void my_recalloc(void *pointer, size_t size, size_t oldhowmany,
79 int32 howmany, char *whatfor)
81 if (size*howmany==0) {
82 my_free(pointer, whatfor);
85 c=(void _huge *)halloc(size*howmany,1);
86 malloced_bytes+=size*(howmany-oldhowmany);
87 if (c==0) memory_out_error(size, howmany, whatfor);
89 printf("Increasing allocation from %ld to %ld bytes: array (%ld entries size %ld) for %s was (%08lx) now (%08lx)\n",
90 ((long int)size) * ((long int)oldhowmany),
91 ((long int)size) * ((long int)howmany),
92 (long int)howmany, (long int)size, whatfor,
93 (long int) *(int **)pointer, (long int) c);
94 memcpy(c, *(int **)pointer, MIN(size*oldhowmany, size*howmany));
95 hfree(*(int **)pointer);
101 extern void *my_malloc(size_t size, char *whatfor)
103 if (size==0) return(NULL);
105 malloced_bytes+=size;
106 if (c==0) memory_out_error(size, 1, whatfor);
108 printf("Allocating %ld bytes for %s at (%08lx)\n",
109 (long int) size,whatfor,(long int) c);
113 extern void my_realloc(void *pointer, size_t oldsize, size_t size,
117 my_free(pointer, whatfor);
120 c=realloc(*(int **)pointer, size);
121 malloced_bytes+=(size-oldsize);
122 if (c==0) memory_out_error(size, 1, whatfor);
124 printf("Increasing allocation from %ld to %ld bytes for %s was (%08lx) now (%08lx)\n",
125 (long int) oldsize, (long int) size, whatfor,
126 (long int) (*(int **)pointer),
128 *(int **)pointer = c;
131 extern void *my_calloc(size_t size, size_t howmany, char *whatfor)
133 if (size*howmany==0) return(NULL);
134 c=calloc(howmany, size);
135 malloced_bytes+=size*howmany;
136 if (c==0) memory_out_error(size, howmany, whatfor);
138 printf("Allocating %ld bytes: array (%ld entries size %ld) \
139 for %s at (%08lx)\n",
140 ((long int)size) * ((long int)howmany),
141 (long int)howmany,(long int)size,whatfor,
146 extern void my_recalloc(void *pointer, size_t size, size_t oldhowmany,
147 size_t howmany, char *whatfor)
149 if (size*howmany==0) {
150 my_free(pointer, whatfor);
153 c=realloc(*(int **)pointer, size*howmany);
154 malloced_bytes+=size*(howmany-oldhowmany);
155 if (c==0) memory_out_error(size, howmany, whatfor);
157 printf("Increasing allocation from %ld to %ld bytes: array (%ld entries size %ld) for %s was (%08lx) now (%08lx)\n",
158 ((long int)size) * ((long int)oldhowmany),
159 ((long int)size) * ((long int)howmany),
160 (long int)howmany, (long int)size, whatfor,
161 (long int) *(int **)pointer, (long int) c);
162 *(int **)pointer = c;
167 extern void my_free(void *pointer, char *whatitwas)
169 if (*(int **)pointer != NULL)
171 printf("Freeing memory for %s at (%08lx)\n",
172 whatitwas, (long int) (*(int **)pointer));
174 hfree(*(int **)pointer);
176 free(*(int **)pointer);
178 *(int **)pointer = NULL;
182 /* ------------------------------------------------------------------------- */
183 /* A dynamic memory array. This grows as needed (but never shrinks). */
184 /* Call ensure_memory_list_available(N) before accessing array item N-1. */
186 /* whatfor must be a static string describing the list. initalloc is */
187 /* (optionally) the number of items to allocate right away. */
189 /* You typically initialise this with extpointer referring to an array of */
190 /* structs or whatever type you need. Whenever the memory list grows, the */
191 /* external array will be updated to refer to the new data. */
193 /* Add "#define DEBUG_MEMLISTS" to allocate exactly the number of items */
194 /* needed, rather than increasing allocations exponentially. This is very */
195 /* slow but it lets us track down array overruns. */
196 /* ------------------------------------------------------------------------- */
198 void initialise_memory_list(memory_list *ML, size_t itemsize, size_t initalloc, void **extpointer, char *whatfor)
200 #ifdef DEBUG_MEMLISTS
201 initalloc = 0; /* No initial allocation */
204 ML->whatfor = whatfor;
205 ML->itemsize = itemsize;
208 ML->extpointer = extpointer;
211 ML->count = initalloc;
212 ML->data = my_calloc(ML->itemsize, ML->count, ML->whatfor);
213 if (ML->data == NULL) return;
217 *(ML->extpointer) = ML->data;
220 void deallocate_memory_list(memory_list *ML)
226 my_free(&(ML->data), ML->whatfor);
229 *(ML->extpointer) = NULL;
230 ML->extpointer = NULL;
233 /* After this is called, at least count items will be available in the list.
234 That is, you can freely access array[0] through array[count-1]. */
235 void ensure_memory_list_available(memory_list *ML, size_t count)
239 if (ML->itemsize == 0) {
240 /* whatfor is also null! */
241 compiler_error("memory: attempt to access uninitialized memory_list");
245 if (ML->count >= count) {
249 oldcount = ML->count;
250 ML->count = 2*count+8; /* Allow headroom for future growth */
252 #ifdef DEBUG_MEMLISTS
253 ML->count = count; /* No headroom */
256 if (ML->data == NULL)
257 ML->data = my_calloc(ML->itemsize, ML->count, ML->whatfor);
259 my_recalloc(&(ML->data), ML->itemsize, oldcount, ML->count, ML->whatfor);
260 if (ML->data == NULL) return;
263 *(ML->extpointer) = ML->data;
266 /* ------------------------------------------------------------------------- */
267 /* Where the memory settings are declared as variables */
268 /* ------------------------------------------------------------------------- */
272 int MAX_DYNAMIC_STRINGS;
273 int MAX_LOCAL_VARIABLES;
274 int DICT_WORD_SIZE; /* number of characters in a dict word */
275 int DICT_CHAR_SIZE; /* (glulx) 1 for one-byte chars, 4 for Unicode chars */
276 int DICT_WORD_BYTES; /* DICT_WORD_SIZE*DICT_CHAR_SIZE */
277 int ZCODE_HEADER_EXT_WORDS; /* (zcode 1.0) requested header extension size */
278 int ZCODE_HEADER_FLAGS_3; /* (zcode 1.1) value to place in Flags 3 word */
279 int ZCODE_LESS_DICT_DATA; /* (zcode) use 2 data bytes per dict word instead of 3 */
281 int GLULX_OBJECT_EXT_BYTES; /* (glulx) extra bytes for each object record */
282 int32 MAX_STACK_SIZE;
283 int32 MEMORY_MAP_EXTENSION;
284 int WARN_UNUSED_ROUTINES; /* 0: no, 1: yes except in system files, 2: yes always */
285 int OMIT_UNUSED_ROUTINES; /* 0: no, 1: yes */
286 int STRIP_UNREACHABLE_LABELS; /* 0: no, 1: yes (default) */
287 int TRANSCRIPT_FORMAT; /* 0: classic, 1: prefixed */
289 /* The way memory sizes are set causes great nuisance for those parameters
290 which have different defaults under Z-code and Glulx. We have to get
291 the defaults right whether the user sets "-G $HUGE" or "$HUGE -G".
292 And an explicit value set by the user should override both defaults. */
293 static int DICT_WORD_SIZE_z, DICT_WORD_SIZE_g;
294 static int NUM_ATTR_BYTES_z, NUM_ATTR_BYTES_g;
295 static int MAX_DYNAMIC_STRINGS_z, MAX_DYNAMIC_STRINGS_g;
297 /* ------------------------------------------------------------------------- */
298 /* Memory control from the command line */
299 /* ------------------------------------------------------------------------- */
301 static void list_memory_sizes(void)
302 { printf("+--------------------------------------+\n");
303 printf("| %25s = %-7s |\n","Memory setting","Value");
304 printf("+--------------------------------------+\n");
305 printf("| %25s = %-7d |\n","MAX_ABBREVS",MAX_ABBREVS);
306 printf("| %25s = %-7d |\n","NUM_ATTR_BYTES",NUM_ATTR_BYTES);
307 printf("| %25s = %-7d |\n","DICT_WORD_SIZE",DICT_WORD_SIZE);
309 printf("| %25s = %-7d |\n","DICT_CHAR_SIZE",DICT_CHAR_SIZE);
310 printf("| %25s = %-7d |\n","MAX_DYNAMIC_STRINGS",MAX_DYNAMIC_STRINGS);
311 printf("| %25s = %-7d |\n","HASH_TAB_SIZE",HASH_TAB_SIZE);
313 printf("| %25s = %-7d |\n","ZCODE_HEADER_EXT_WORDS",ZCODE_HEADER_EXT_WORDS);
315 printf("| %25s = %-7d |\n","ZCODE_HEADER_FLAGS_3",ZCODE_HEADER_FLAGS_3);
317 printf("| %25s = %-7d |\n","ZCODE_LESS_DICT_DATA",ZCODE_LESS_DICT_DATA);
318 printf("| %25s = %-7d |\n","INDIV_PROP_START", INDIV_PROP_START);
320 printf("| %25s = %-7d |\n","MEMORY_MAP_EXTENSION",
321 MEMORY_MAP_EXTENSION);
323 printf("| %25s = %-7d |\n","GLULX_OBJECT_EXT_BYTES",
324 GLULX_OBJECT_EXT_BYTES);
326 printf("| %25s = %-7ld |\n","MAX_STACK_SIZE",
327 (long int) MAX_STACK_SIZE);
328 printf("| %25s = %-7d |\n","TRANSCRIPT_FORMAT",TRANSCRIPT_FORMAT);
329 printf("| %25s = %-7d |\n","WARN_UNUSED_ROUTINES",WARN_UNUSED_ROUTINES);
330 printf("| %25s = %-7d |\n","OMIT_UNUSED_ROUTINES",OMIT_UNUSED_ROUTINES);
331 printf("| %25s = %-7d |\n","STRIP_UNREACHABLE_LABELS",STRIP_UNREACHABLE_LABELS);
332 printf("+--------------------------------------+\n");
335 extern void set_memory_sizes(void)
339 DICT_WORD_SIZE_z = 6;
340 DICT_WORD_SIZE_g = 9;
341 NUM_ATTR_BYTES_z = 6;
342 NUM_ATTR_BYTES_g = 7;
344 MAX_DYNAMIC_STRINGS_z = 32;
345 MAX_DYNAMIC_STRINGS_g = 100;
346 /* Backwards-compatible behavior: allow for a unicode table
347 whether we need one or not. The user can set this to zero if
348 there's no unicode table. */
349 ZCODE_HEADER_EXT_WORDS = 3;
350 ZCODE_HEADER_FLAGS_3 = 0;
351 ZCODE_LESS_DICT_DATA = 0;
352 GLULX_OBJECT_EXT_BYTES = 0;
353 MEMORY_MAP_EXTENSION = 0;
354 /* We estimate the default Glulx stack size at 4096. That's about
355 enough for 90 nested function calls with 8 locals each -- the
356 same capacity as the Z-Spec's suggestion for Z-machine stack
357 size. Note that Inform 7 wants more stack; I7-generated code
358 sets MAX_STACK_SIZE to 65536 by default. */
359 MAX_STACK_SIZE = 4096;
360 OMIT_UNUSED_ROUTINES = 0;
361 WARN_UNUSED_ROUTINES = 0;
362 STRIP_UNREACHABLE_LABELS = 1;
363 TRANSCRIPT_FORMAT = 0;
365 adjust_memory_sizes();
368 extern void adjust_memory_sizes()
371 DICT_WORD_SIZE = DICT_WORD_SIZE_z;
372 NUM_ATTR_BYTES = NUM_ATTR_BYTES_z;
373 MAX_DYNAMIC_STRINGS = MAX_DYNAMIC_STRINGS_z;
374 INDIV_PROP_START = 64;
377 DICT_WORD_SIZE = DICT_WORD_SIZE_g;
378 NUM_ATTR_BYTES = NUM_ATTR_BYTES_g;
379 MAX_DYNAMIC_STRINGS = MAX_DYNAMIC_STRINGS_g;
380 INDIV_PROP_START = 256;
384 static void explain_parameter(char *command)
386 if (strcmp(command,"HASH_TAB_SIZE")==0)
388 " HASH_TAB_SIZE is the size of the hash tables used for the heaviest \n\
392 if (strcmp(command,"DICT_WORD_SIZE")==0)
394 " DICT_WORD_SIZE is the number of characters in a dictionary word. In \n\
395 Z-code this is always 6 (only 4 are used in v3 games). In Glulx it \n\
396 can be any number.\n");
399 if (strcmp(command,"DICT_CHAR_SIZE")==0)
401 " DICT_CHAR_SIZE is the byte size of one character in the dictionary. \n\
402 (This is only meaningful in Glulx, since Z-code has compressed dictionary \n\
403 words.) It can be either 1 (the default) or 4 (to enable full Unicode \n\
407 if (strcmp(command,"NUM_ATTR_BYTES")==0)
409 " NUM_ATTR_BYTES is the space used to store attribute flags. Each byte \n\
410 stores eight attributes. In Z-code this is always 6 (only 4 are used in \n\
411 v3 games). In Glulx it can be any number which is a multiple of four, \n\
415 if (strcmp(command,"ZCODE_HEADER_EXT_WORDS")==0)
417 " ZCODE_HEADER_EXT_WORDS is the number of words in the Z-code header \n\
418 extension table (Z-Spec 1.0). The -W switch also sets this. It defaults \n\
419 to 3, but can be set higher. (It can be set lower if no Unicode \n\
420 translation table is created.)\n");
423 if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0)
425 " ZCODE_HEADER_FLAGS_3 is the value to store in the Flags 3 word of the \n\
426 header extension table (Z-Spec 1.1).\n");
429 if (strcmp(command,"ZCODE_LESS_DICT_DATA")==0)
431 " ZCODE_LESS_DICT_DATA, if set, provides each dict word with two data bytes\n\
432 rather than three. (Z-code only.)\n");
435 if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0)
437 " GLULX_OBJECT_EXT_BYTES is an amount of additional space to add to each \n\
438 object record. It is initialized to zero bytes, and the game is free to \n\
439 use it as desired. (This is only meaningful in Glulx, since Z-code \n\
440 specifies the object structure.)\n");
443 if (strcmp(command,"MAX_ABBREVS")==0)
445 " MAX_ABBREVS is the maximum number of declared abbreviations. It is not \n\
446 allowed to exceed 96 in Z-code. (This is not meaningful in Glulx, where \n\
447 there is no limit on abbreviations.)\n");
450 if (strcmp(command,"MAX_DYNAMIC_STRINGS")==0)
452 " MAX_DYNAMIC_STRINGS is the maximum number of string substitution variables\n\
453 (\"@00\" or \"@(0)\"). It is not allowed to exceed 96 in Z-code.\n");
456 if (strcmp(command,"INDIV_PROP_START")==0)
458 " Properties 1 to INDIV_PROP_START-1 are common properties; individual\n\
459 properties are numbered INDIV_PROP_START and up.\n");
462 if (strcmp(command,"MAX_STACK_SIZE")==0)
465 " MAX_STACK_SIZE is the maximum size (in bytes) of the interpreter stack \n\
466 during gameplay. (Glulx only)\n");
469 if (strcmp(command,"MEMORY_MAP_EXTENSION")==0)
472 " MEMORY_MAP_EXTENSION is the number of bytes (all zeroes) to map into \n\
473 memory after the game file. (Glulx only)\n");
476 if (strcmp(command,"TRANSCRIPT_FORMAT")==0)
479 " TRANSCRIPT_FORMAT, if set to 1, adjusts the gametext.txt transcript for \n\
480 easier machine processing; each line will be prefixed by its context.\n");
483 if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
486 " WARN_UNUSED_ROUTINES, if set to 2, will display a warning for each \n\
487 routine in the game file which is never called. (This includes \n\
488 routines called only from uncalled routines, etc.) If set to 1, will warn \n\
489 only about functions in game code, not in the system library.\n");
492 if (strcmp(command,"OMIT_UNUSED_ROUTINES")==0)
495 " OMIT_UNUSED_ROUTINES, if set to 1, will avoid compiling unused routines \n\
496 into the game file.\n");
499 if (strcmp(command,"STRIP_UNREACHABLE_LABELS")==0)
502 " STRIP_UNREACHABLE_LABELS, if set to 1, will skip labels in unreachable \n\
503 statements. Jumping to a skipped label is an error. If 0, all labels \n\
504 will be compiled, at the cost of less optimized code. The default is 1.\n");
507 if (strcmp(command,"SERIAL")==0)
510 " SERIAL, if set, will be used as the six digit serial number written into \n\
511 the header of the output file.\n");
515 printf("No such memory setting as \"%s\"\n",command);
520 /* Parse a decimal number as an int32. Return true if a valid number
521 was found; otherwise print a warning and return false.
523 Anything over nine digits is considered an overflow; we report a
524 warning but return +/- 999999999 (and true). This is not entirely
525 clever about leading zeroes ("0000000001" is treated as an
526 overflow) but this is better than trying to detect genuine
529 (Some Glulx settings might conceivably want to go up to $7FFFFFFF,
530 which is a ten-digit number, but we're not going to allow that
533 This used to rely on atoi(), and we retain the atoi() behavior of
534 ignoring garbage characters after a valid decimal number.
536 static int parse_memory_setting(char *str, char *label, int32 *result)
544 while (*cx == ' ') cx++;
546 val = strtol(cx, &ex, 10);
549 printf("Bad numerical setting in $ command \"%s=%s\"\n",
557 printf("Numerical setting underflowed in $ command \"%s=%s\" (limiting to %ld)\n",
564 printf("Numerical setting overflowed in $ command \"%s=%s\" (limiting to %ld)\n",
569 *result = (int32)val;
573 static void add_predefined_symbol(char *command)
580 for (ix=0; command[ix]; ix++) {
581 if (command[ix] == '=') {
582 valpos = command+(ix+1);
588 for (ix=0; command[ix]; ix++) {
589 if ((ix == 0 && isdigit(command[ix]))
590 || !(isalnum(command[ix]) || command[ix] == '_')) {
591 printf("Attempt to define invalid symbol: %s\n", command);
597 if (!parse_memory_setting(valpos, command, &value)) {
602 add_config_symbol_definition(command, value);
605 static void set_trace_option(char *command)
610 /* Parse options of the form STRING or STRING=NUM. (The $! has already been eaten.) If the string is null or empty, show help. */
612 if (!command || *command == '\0') {
613 printf("The full list of trace options:\n\n");
614 printf(" ACTIONS: show actions defined\n");
615 printf(" ASM: trace assembly (same as -a)\n");
616 printf(" ASM=2: also show hex dumps\n");
617 printf(" ASM=3: also show branch optimization info\n");
618 printf(" ASM=4: more verbose branch info\n");
619 printf(" BPATCH: show backpatch results\n");
620 printf(" BPATCH=2: also show markers added\n");
621 printf(" DICT: display the dictionary table\n");
622 printf(" DICT=2: also the byte encoding of entries\n");
623 printf(" EXPR: show expression trees\n");
624 printf(" EXPR=2: more verbose\n");
625 printf(" EXPR=3: even more verbose\n");
626 printf(" FILES: show files opened\n");
627 printf(" FINDABBREVS: show selection decisions during abbreviation optimization\n (only meaningful with -u)\n");
628 printf(" FINDABBREVS=2: also show three-letter-block decisions\n");
629 printf(" FREQ: show how efficient abbreviations were (same as -f)\n (only meaningful with -e)\n");
630 printf(" MAP: print memory map of the virtual machine (same as -z)\n");
631 printf(" MAP=2: also show percentage of VM that each segment occupies\n");
632 printf(" MEM: show internal memory allocations\n");
633 printf(" OBJECTS: display the object table\n");
634 printf(" PROPS: show attributes and properties defined\n");
635 printf(" RUNTIME: show game function calls at runtime (same as -g)\n");
636 printf(" RUNTIME=2: also show library calls (not supported in Glulx)\n");
637 printf(" RUNTIME=3: also show veneer calls (not supported in Glulx)\n");
638 printf(" STATS: give compilation statistics (same as -s)\n");
639 printf(" SYMBOLS: display the symbol table\n");
640 printf(" SYMBOLS=2: also show compiler-defined symbols\n");
641 printf(" SYMDEF: show when symbols are noticed and defined\n");
642 printf(" TOKENS: show token lexing\n");
643 printf(" TOKENS=2: also show token types\n");
644 printf(" TOKENS=3: also show lexical context\n");
645 printf(" VERBS: display the verb grammar table\n");
649 for (cx=command; *cx && *cx != '='; cx++) {
650 if (!(*cx >= 'A' && *cx <= 'Z')) {
651 printf("Invalid $! trace command \"%s\"\n", command);
659 value = strtol(cx+1, &ex, 10);
661 if (ex == cx+1 || *ex != '\0' || value < 0) {
662 printf("Bad numerical setting in $! trace command \"%s\"\n", command);
669 /* We accept some reasonable synonyms, including plausible singular/plural confusion. */
671 if (strcmp(command, "ASSEMBLY")==0 || strcmp(command, "ASM")==0) {
672 asm_trace_setting = value;
674 else if (strcmp(command, "ACTION")==0 || strcmp(command, "ACTIONS")==0) {
675 printactions_switch = value;
677 else if (strcmp(command, "BPATCH")==0 || strcmp(command, "BACKPATCH")==0) {
678 bpatch_trace_setting = value;
680 else if (strcmp(command, "DICTIONARY")==0 || strcmp(command, "DICT")==0) {
681 list_dict_setting = value;
683 else if (strcmp(command, "EXPR")==0 || strcmp(command, "EXPRESSION")==0 || strcmp(command, "EXPRESSIONS")==0) {
684 expr_trace_setting = value;
686 else if (strcmp(command, "FILE")==0 || strcmp(command, "FILES")==0) {
687 files_trace_setting = value;
689 else if (strcmp(command, "FINDABBREV")==0 || strcmp(command, "FINDABBREVS")==0) {
690 optabbrevs_trace_setting = value;
692 else if (strcmp(command, "FREQUENCY")==0 || strcmp(command, "FREQUENCIES")==0 || strcmp(command, "FREQ")==0) {
693 frequencies_setting = value;
695 else if (strcmp(command, "MAP")==0) {
696 memory_map_setting = value;
698 else if (strcmp(command, "MEM")==0 || strcmp(command, "MEMORY")==0) {
699 memout_switch = value;
701 else if (strcmp(command, "OBJECTS")==0 || strcmp(command, "OBJECT")==0 || strcmp(command, "OBJS")==0 || strcmp(command, "OBJ")==0) {
702 list_objects_setting = value;
704 else if (strcmp(command, "PROP")==0 || strcmp(command, "PROPERTY")==0 || strcmp(command, "PROPS")==0 || strcmp(command, "PROPERTIES")==0) {
705 printprops_switch = value;
707 else if (strcmp(command, "RUNTIME")==0) {
708 trace_fns_setting = value;
710 else if (strcmp(command, "STATISTICS")==0 || strcmp(command, "STATS")==0 || strcmp(command, "STAT")==0) {
711 statistics_switch = value;
713 else if (strcmp(command, "SYMBOLS")==0 || strcmp(command, "SYMBOL")==0) {
714 list_symbols_setting = value;
716 else if (strcmp(command, "SYMDEF")==0 || strcmp(command, "SYMBOLDEF")==0) {
717 symdef_trace_setting = value;
719 else if (strcmp(command, "TOKEN")==0 || strcmp(command, "TOKENS")==0) {
720 tokens_trace_setting = value;
722 else if (strcmp(command, "VERBS")==0 || strcmp(command, "VERB")==0) {
723 list_verbs_setting = value;
726 printf("Unrecognized $! trace command \"%s\"\n", command);
730 /* Handle a dollar-sign command option: $LIST, $FOO=VAL, and so on.
731 The option may come from the command line, an ICL file, or a header
734 (Unix-style command-line options are converted to dollar-sign format
735 before being sent here.)
737 The name of this function is outdated. Many of these settings are not
738 really about memory allocation.
740 extern void memory_command(char *command)
741 { int i, k, flag=0; int32 j;
743 for (k=0; command[k]!=0; k++)
744 if (islower(command[k])) command[k]=toupper(command[k]);
746 if (command[0]=='?') { explain_parameter(command+1); return; }
747 if (command[0]=='#') { add_predefined_symbol(command+1); return; }
748 if (command[0]=='!') { set_trace_option(command+1); return; }
750 if (strcmp(command, "HUGE")==0
751 || strcmp(command, "LARGE")==0
752 || strcmp(command, "SMALL")==0) {
753 if (!nowarnings_switch)
754 printf("The Inform 6 memory size commands (\"SMALL, LARGE, HUGE\") are no longer needed and has been withdrawn.\n");
758 if (strcmp(command, "LIST")==0) { list_memory_sizes(); return; }
760 for (i=0; command[i]!=0; i++)
761 { if (command[i]=='=')
763 if (!parse_memory_setting(command+i+1, command, &j)) {
766 if (strcmp(command,"BUFFER_LENGTH")==0)
768 if (strcmp(command,"MAX_QTEXT_SIZE")==0)
770 if (strcmp(command,"MAX_SYMBOLS")==0)
772 if (strcmp(command,"MAX_BANK_SIZE")==0)
774 if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0)
776 if (strcmp(command,"BANK_CHUNK_SIZE")==0)
778 if (strcmp(command,"HASH_TAB_SIZE")==0)
779 HASH_TAB_SIZE=j, flag=1;
780 if (strcmp(command,"MAX_OBJECTS")==0)
782 if (strcmp(command,"MAX_ACTIONS")==0)
784 if (strcmp(command,"MAX_ADJECTIVES")==0)
786 if (strcmp(command,"MAX_DICT_ENTRIES")==0)
788 if (strcmp(command,"DICT_WORD_SIZE")==0)
789 { DICT_WORD_SIZE=j, flag=1;
790 DICT_WORD_SIZE_g=DICT_WORD_SIZE_z=j;
792 if (strcmp(command,"DICT_CHAR_SIZE")==0)
793 DICT_CHAR_SIZE=j, flag=1;
794 if (strcmp(command,"NUM_ATTR_BYTES")==0)
795 { NUM_ATTR_BYTES=j, flag=1;
796 NUM_ATTR_BYTES_g=NUM_ATTR_BYTES_z=j;
798 if (strcmp(command,"ZCODE_HEADER_EXT_WORDS")==0)
799 ZCODE_HEADER_EXT_WORDS=j, flag=1;
800 if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0)
801 ZCODE_HEADER_FLAGS_3=j, flag=1;
802 if (strcmp(command,"ZCODE_LESS_DICT_DATA")==0)
803 ZCODE_LESS_DICT_DATA=j, flag=1;
804 if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0)
805 GLULX_OBJECT_EXT_BYTES=j, flag=1;
806 if (strcmp(command,"MAX_STATIC_DATA")==0)
808 if (strcmp(command,"MAX_OLDEPTH")==0)
810 if (strcmp(command,"MAX_ROUTINES")==0)
812 if (strcmp(command,"MAX_GCONSTANTS")==0)
814 if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0)
816 if (strcmp(command,"MAX_FORWARD_REFS")==0)
818 if (strcmp(command,"STACK_SIZE")==0)
820 if (strcmp(command,"STACK_LONG_SLOTS")==0)
822 if (strcmp(command,"STACK_SHORT_LENGTH")==0)
824 if (strcmp(command,"MAX_ABBREVS")==0)
825 MAX_ABBREVS=j, flag=1;
826 if (strcmp(command,"MAX_DYNAMIC_STRINGS")==0)
827 { MAX_DYNAMIC_STRINGS=j, flag=1;
828 MAX_DYNAMIC_STRINGS_g=MAX_DYNAMIC_STRINGS_z=j;
830 if (strcmp(command,"MAX_ARRAYS")==0)
832 if (strcmp(command,"MAX_EXPRESSION_NODES")==0)
834 if (strcmp(command,"MAX_VERBS")==0)
836 if (strcmp(command,"MAX_VERBSPACE")==0)
838 if (strcmp(command,"MAX_LABELS")==0)
840 if (strcmp(command,"MAX_LINESPACE")==0)
842 if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0)
844 if (strcmp(command,"MAX_STATIC_STRINGS")==0)
846 if (strcmp(command,"MAX_ZCODE_SIZE")==0)
848 if (strcmp(command,"MAX_LINK_DATA_SIZE")==0)
850 if (strcmp(command,"MAX_LOW_STRINGS")==0)
852 if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0)
854 if (strcmp(command,"MAX_CLASSES")==0)
856 if (strcmp(command,"MAX_INCLUSION_DEPTH")==0)
858 if (strcmp(command,"MAX_SOURCE_FILES")==0)
860 if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0)
862 if (strcmp(command,"INDIV_PROP_START")==0)
863 INDIV_PROP_START=j, flag=1;
864 if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0)
866 if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0)
868 if (strcmp(command,"MAX_LOCAL_VARIABLES")==0)
870 if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0)
872 if (strcmp(command,"ALLOC_CHUNK_SIZE")==0)
874 if (strcmp(command,"MAX_UNICODE_CHARS")==0)
876 if (strcmp(command,"MAX_STACK_SIZE")==0)
878 MAX_STACK_SIZE=j, flag=1;
879 /* Adjust up to a 256-byte boundary. */
880 MAX_STACK_SIZE = (MAX_STACK_SIZE + 0xFF) & (~0xFF);
882 if (strcmp(command,"MEMORY_MAP_EXTENSION")==0)
884 MEMORY_MAP_EXTENSION=j, flag=1;
885 /* Adjust up to a 256-byte boundary. */
886 MEMORY_MAP_EXTENSION = (MEMORY_MAP_EXTENSION + 0xFF) & (~0xFF);
888 if (strcmp(command,"TRANSCRIPT_FORMAT")==0)
890 TRANSCRIPT_FORMAT=j, flag=1;
891 if (TRANSCRIPT_FORMAT > 1 || TRANSCRIPT_FORMAT < 0)
892 TRANSCRIPT_FORMAT = 1;
894 if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
896 WARN_UNUSED_ROUTINES=j, flag=1;
897 if (WARN_UNUSED_ROUTINES > 2 || WARN_UNUSED_ROUTINES < 0)
898 WARN_UNUSED_ROUTINES = 2;
900 if (strcmp(command,"OMIT_UNUSED_ROUTINES")==0)
902 OMIT_UNUSED_ROUTINES=j, flag=1;
903 if (OMIT_UNUSED_ROUTINES > 1 || OMIT_UNUSED_ROUTINES < 0)
904 OMIT_UNUSED_ROUTINES = 1;
906 if (strcmp(command,"STRIP_UNREACHABLE_LABELS")==0)
908 STRIP_UNREACHABLE_LABELS=j, flag=1;
909 if (STRIP_UNREACHABLE_LABELS > 1 || STRIP_UNREACHABLE_LABELS < 0)
910 STRIP_UNREACHABLE_LABELS = 1;
912 if (strcmp(command,"SERIAL")==0)
914 if (j >= 0 && j <= 999999)
916 sprintf(serial_code_buffer,"%06d",j);
917 serial_code_given_in_program = TRUE;
923 printf("No such memory setting as \"%s\"\n", command);
924 if (flag==2 && !nowarnings_switch)
925 printf("The Inform 5 memory setting \"%s\" has been withdrawn.\n", command);
926 if (flag==3 && !nowarnings_switch)
927 printf("The Inform 6 memory setting \"%s\" is no longer needed and has been withdrawn.\n", command);
931 printf("No such memory $ command as \"%s\"\n",command);
934 extern void print_memory_usage(void)
936 printf("Properties table used %d\n",
937 properties_table_size);
938 printf("Allocated a total of %ld bytes of memory\n",
939 (long int) malloced_bytes);
942 /* ========================================================================= */
943 /* Data structure management routines */
944 /* ------------------------------------------------------------------------- */
946 extern void init_memory_vars(void)
947 { malloced_bytes = 0;
950 extern void memory_begin_pass(void) { }
952 extern void memory_allocate_arrays(void) { }
954 extern void memory_free_arrays(void) { }
956 /* ========================================================================= */