1 /* ------------------------------------------------------------------------- */
2 /* "memory" : Memory management and ICL memory setting commands */
4 /* Part of Inform 6.40 */
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(" LINKER: show module linking info\n");
631 printf(" LINKER=2: more verbose (or 3, 4 for even more)\n");
632 printf(" MAP: print memory map of the virtual machine (same as -z)\n");
633 printf(" MAP=2: also show percentage of VM that each segment occupies\n");
634 printf(" MEM: show internal memory allocations\n");
635 printf(" OBJECTS: display the object table\n");
636 printf(" PROPS: show attributes and properties defined\n");
637 printf(" RUNTIME: show game function calls at runtime (same as -g)\n");
638 printf(" RUNTIME=2: also show library calls (not supported in Glulx)\n");
639 printf(" RUNTIME=3: also show veneer calls (not supported in Glulx)\n");
640 printf(" STATS: give compilation statistics (same as -s)\n");
641 printf(" SYMBOLS: display the symbol table\n");
642 printf(" SYMBOLS=2: also show compiler-defined symbols\n");
643 printf(" SYMDEF: show when symbols are noticed and defined\n");
644 printf(" TOKENS: show token lexing\n");
645 printf(" TOKENS=2: also show token types\n");
646 printf(" TOKENS=3: also show lexical context\n");
647 printf(" VERBS: display the verb grammar table\n");
651 for (cx=command; *cx && *cx != '='; cx++) {
652 if (!(*cx >= 'A' && *cx <= 'Z')) {
653 printf("Invalid $! trace command \"%s\"\n", command);
661 value = strtol(cx+1, &ex, 10);
663 if (ex == cx+1 || *ex != '\0' || value < 0) {
664 printf("Bad numerical setting in $! trace command \"%s\"\n", command);
671 /* We accept some reasonable synonyms, including plausible singular/plural confusion. */
673 if (strcmp(command, "ASSEMBLY")==0 || strcmp(command, "ASM")==0) {
674 asm_trace_setting = value;
676 else if (strcmp(command, "ACTION")==0 || strcmp(command, "ACTIONS")==0) {
677 printactions_switch = value;
679 else if (strcmp(command, "BPATCH")==0 || strcmp(command, "BACKPATCH")==0) {
680 bpatch_trace_setting = value;
682 else if (strcmp(command, "DICTIONARY")==0 || strcmp(command, "DICT")==0) {
683 list_dict_setting = value;
685 else if (strcmp(command, "EXPR")==0 || strcmp(command, "EXPRESSION")==0 || strcmp(command, "EXPRESSIONS")==0) {
686 expr_trace_setting = value;
688 else if (strcmp(command, "FILE")==0 || strcmp(command, "FILES")==0) {
689 files_trace_setting = value;
691 else if (strcmp(command, "FINDABBREV")==0 || strcmp(command, "FINDABBREVS")==0) {
692 optabbrevs_trace_setting = value;
694 else if (strcmp(command, "FREQUENCY")==0 || strcmp(command, "FREQUENCIES")==0 || strcmp(command, "FREQ")==0) {
695 frequencies_setting = value;
697 else if (strcmp(command, "LINK")==0 || strcmp(command, "LINKER")==0) {
698 linker_trace_setting = value;
700 else if (strcmp(command, "MAP")==0) {
701 memory_map_setting = value;
703 else if (strcmp(command, "MEM")==0 || strcmp(command, "MEMORY")==0) {
704 memout_switch = value;
706 else if (strcmp(command, "OBJECTS")==0 || strcmp(command, "OBJECT")==0 || strcmp(command, "OBJS")==0 || strcmp(command, "OBJ")==0) {
707 list_objects_setting = value;
709 else if (strcmp(command, "PROP")==0 || strcmp(command, "PROPERTY")==0 || strcmp(command, "PROPS")==0 || strcmp(command, "PROPERTIES")==0) {
710 printprops_switch = value;
712 else if (strcmp(command, "RUNTIME")==0) {
713 trace_fns_setting = value;
715 else if (strcmp(command, "STATISTICS")==0 || strcmp(command, "STATS")==0 || strcmp(command, "STAT")==0) {
716 statistics_switch = value;
718 else if (strcmp(command, "SYMBOLS")==0 || strcmp(command, "SYMBOL")==0) {
719 list_symbols_setting = value;
721 else if (strcmp(command, "SYMDEF")==0 || strcmp(command, "SYMBOLDEF")==0) {
722 symdef_trace_setting = value;
724 else if (strcmp(command, "TOKEN")==0 || strcmp(command, "TOKENS")==0) {
725 tokens_trace_setting = value;
727 else if (strcmp(command, "VERBS")==0 || strcmp(command, "VERB")==0) {
728 list_verbs_setting = value;
731 printf("Unrecognized $! trace command \"%s\"\n", command);
735 /* Handle a dollar-sign command option: $LIST, $FOO=VAL, and so on.
736 The option may come from the command line, an ICL file, or a header
739 (Unix-style command-line options are converted to dollar-sign format
740 before being sent here.)
742 The name of this function is outdated. Many of these settings are not
743 really about memory allocation.
745 extern void memory_command(char *command)
746 { int i, k, flag=0; int32 j;
748 for (k=0; command[k]!=0; k++)
749 if (islower(command[k])) command[k]=toupper(command[k]);
751 if (command[0]=='?') { explain_parameter(command+1); return; }
752 if (command[0]=='#') { add_predefined_symbol(command+1); return; }
753 if (command[0]=='!') { set_trace_option(command+1); return; }
755 if (strcmp(command, "HUGE")==0
756 || strcmp(command, "LARGE")==0
757 || strcmp(command, "SMALL")==0) {
758 if (!nowarnings_switch)
759 printf("The Inform 6 memory size commands (\"SMALL, LARGE, HUGE\") are no longer needed and has been withdrawn.\n");
763 if (strcmp(command, "LIST")==0) { list_memory_sizes(); return; }
765 for (i=0; command[i]!=0; i++)
766 { if (command[i]=='=')
768 if (!parse_memory_setting(command+i+1, command, &j)) {
771 if (strcmp(command,"BUFFER_LENGTH")==0)
773 if (strcmp(command,"MAX_QTEXT_SIZE")==0)
775 if (strcmp(command,"MAX_SYMBOLS")==0)
777 if (strcmp(command,"MAX_BANK_SIZE")==0)
779 if (strcmp(command,"SYMBOLS_CHUNK_SIZE")==0)
781 if (strcmp(command,"BANK_CHUNK_SIZE")==0)
783 if (strcmp(command,"HASH_TAB_SIZE")==0)
784 HASH_TAB_SIZE=j, flag=1;
785 if (strcmp(command,"MAX_OBJECTS")==0)
787 if (strcmp(command,"MAX_ACTIONS")==0)
789 if (strcmp(command,"MAX_ADJECTIVES")==0)
791 if (strcmp(command,"MAX_DICT_ENTRIES")==0)
793 if (strcmp(command,"DICT_WORD_SIZE")==0)
794 { DICT_WORD_SIZE=j, flag=1;
795 DICT_WORD_SIZE_g=DICT_WORD_SIZE_z=j;
797 if (strcmp(command,"DICT_CHAR_SIZE")==0)
798 DICT_CHAR_SIZE=j, flag=1;
799 if (strcmp(command,"NUM_ATTR_BYTES")==0)
800 { NUM_ATTR_BYTES=j, flag=1;
801 NUM_ATTR_BYTES_g=NUM_ATTR_BYTES_z=j;
803 if (strcmp(command,"ZCODE_HEADER_EXT_WORDS")==0)
804 ZCODE_HEADER_EXT_WORDS=j, flag=1;
805 if (strcmp(command,"ZCODE_HEADER_FLAGS_3")==0)
806 ZCODE_HEADER_FLAGS_3=j, flag=1;
807 if (strcmp(command,"ZCODE_LESS_DICT_DATA")==0)
808 ZCODE_LESS_DICT_DATA=j, flag=1;
809 if (strcmp(command,"GLULX_OBJECT_EXT_BYTES")==0)
810 GLULX_OBJECT_EXT_BYTES=j, flag=1;
811 if (strcmp(command,"MAX_STATIC_DATA")==0)
813 if (strcmp(command,"MAX_OLDEPTH")==0)
815 if (strcmp(command,"MAX_ROUTINES")==0)
817 if (strcmp(command,"MAX_GCONSTANTS")==0)
819 if (strcmp(command,"MAX_PROP_TABLE_SIZE")==0)
821 if (strcmp(command,"MAX_FORWARD_REFS")==0)
823 if (strcmp(command,"STACK_SIZE")==0)
825 if (strcmp(command,"STACK_LONG_SLOTS")==0)
827 if (strcmp(command,"STACK_SHORT_LENGTH")==0)
829 if (strcmp(command,"MAX_ABBREVS")==0)
830 MAX_ABBREVS=j, flag=1;
831 if (strcmp(command,"MAX_DYNAMIC_STRINGS")==0)
832 { MAX_DYNAMIC_STRINGS=j, flag=1;
833 MAX_DYNAMIC_STRINGS_g=MAX_DYNAMIC_STRINGS_z=j;
835 if (strcmp(command,"MAX_ARRAYS")==0)
837 if (strcmp(command,"MAX_EXPRESSION_NODES")==0)
839 if (strcmp(command,"MAX_VERBS")==0)
841 if (strcmp(command,"MAX_VERBSPACE")==0)
843 if (strcmp(command,"MAX_LABELS")==0)
845 if (strcmp(command,"MAX_LINESPACE")==0)
847 if (strcmp(command,"MAX_NUM_STATIC_STRINGS")==0)
849 if (strcmp(command,"MAX_STATIC_STRINGS")==0)
851 if (strcmp(command,"MAX_ZCODE_SIZE")==0)
853 if (strcmp(command,"MAX_LINK_DATA_SIZE")==0)
855 if (strcmp(command,"MAX_LOW_STRINGS")==0)
857 if (strcmp(command,"MAX_TRANSCRIPT_SIZE")==0)
859 if (strcmp(command,"MAX_CLASSES")==0)
861 if (strcmp(command,"MAX_INCLUSION_DEPTH")==0)
863 if (strcmp(command,"MAX_SOURCE_FILES")==0)
865 if (strcmp(command,"MAX_INDIV_PROP_TABLE_SIZE")==0)
867 if (strcmp(command,"INDIV_PROP_START")==0)
868 INDIV_PROP_START=j, flag=1;
869 if (strcmp(command,"MAX_OBJ_PROP_TABLE_SIZE")==0)
871 if (strcmp(command,"MAX_OBJ_PROP_COUNT")==0)
873 if (strcmp(command,"MAX_LOCAL_VARIABLES")==0)
875 if (strcmp(command,"MAX_GLOBAL_VARIABLES")==0)
877 if (strcmp(command,"ALLOC_CHUNK_SIZE")==0)
879 if (strcmp(command,"MAX_UNICODE_CHARS")==0)
881 if (strcmp(command,"MAX_STACK_SIZE")==0)
883 MAX_STACK_SIZE=j, flag=1;
884 /* Adjust up to a 256-byte boundary. */
885 MAX_STACK_SIZE = (MAX_STACK_SIZE + 0xFF) & (~0xFF);
887 if (strcmp(command,"MEMORY_MAP_EXTENSION")==0)
889 MEMORY_MAP_EXTENSION=j, flag=1;
890 /* Adjust up to a 256-byte boundary. */
891 MEMORY_MAP_EXTENSION = (MEMORY_MAP_EXTENSION + 0xFF) & (~0xFF);
893 if (strcmp(command,"TRANSCRIPT_FORMAT")==0)
895 TRANSCRIPT_FORMAT=j, flag=1;
896 if (TRANSCRIPT_FORMAT > 1 || TRANSCRIPT_FORMAT < 0)
897 TRANSCRIPT_FORMAT = 1;
899 if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
901 WARN_UNUSED_ROUTINES=j, flag=1;
902 if (WARN_UNUSED_ROUTINES > 2 || WARN_UNUSED_ROUTINES < 0)
903 WARN_UNUSED_ROUTINES = 2;
905 if (strcmp(command,"OMIT_UNUSED_ROUTINES")==0)
907 OMIT_UNUSED_ROUTINES=j, flag=1;
908 if (OMIT_UNUSED_ROUTINES > 1 || OMIT_UNUSED_ROUTINES < 0)
909 OMIT_UNUSED_ROUTINES = 1;
911 if (strcmp(command,"STRIP_UNREACHABLE_LABELS")==0)
913 STRIP_UNREACHABLE_LABELS=j, flag=1;
914 if (STRIP_UNREACHABLE_LABELS > 1 || STRIP_UNREACHABLE_LABELS < 0)
915 STRIP_UNREACHABLE_LABELS = 1;
917 if (strcmp(command,"SERIAL")==0)
919 if (j >= 0 && j <= 999999)
921 sprintf(serial_code_buffer,"%06d",j);
922 serial_code_given_in_program = TRUE;
928 printf("No such memory setting as \"%s\"\n", command);
929 if (flag==2 && !nowarnings_switch)
930 printf("The Inform 5 memory setting \"%s\" has been withdrawn.\n", command);
931 if (flag==3 && !nowarnings_switch)
932 printf("The Inform 6 memory setting \"%s\" is no longer needed and has been withdrawn.\n", command);
936 printf("No such memory $ command as \"%s\"\n",command);
939 extern void print_memory_usage(void)
941 printf("Properties table used %d\n",
942 properties_table_size);
943 printf("Allocated a total of %ld bytes of memory\n",
944 (long int) malloced_bytes);
947 /* ========================================================================= */
948 /* Data structure management routines */
949 /* ------------------------------------------------------------------------- */
951 extern void init_memory_vars(void)
952 { malloced_bytes = 0;
955 extern void memory_begin_pass(void) { }
957 extern void memory_allocate_arrays(void) { }
959 extern void memory_free_arrays(void) { }
961 /* ========================================================================= */