1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
4 /* Part of Inform 6.35 */
5 /* copyright (c) Graham Nelson 1993 - 2021 */
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 /* ------------------------------------------------------------------------- */
25 /* This section of Inform is a service detached from the rest. */
26 /* Only two variables are accessible from the outside: */
27 /* ------------------------------------------------------------------------- */
29 int no_symbols; /* Total number of symbols defined */
30 int no_named_constants; /* Copied into story file */
32 /* ------------------------------------------------------------------------- */
33 /* Plus six arrays. Each symbol has its own index n (an int32) and */
35 /* svals[n] is its value (must be 32 bits wide, i.e. an int32, tho' */
36 /* it is used to hold an unsigned 16 bit Z-machine value) */
37 /* sflags[n] holds flags (see "header.h" for a list) */
38 /* stypes[n] is the "type", distinguishing between the data type of */
39 /* different kinds of constants/variables. */
40 /* (See the "typename()" below.) */
41 /* symbs[n] (needs to be cast to (char *) to be used) is the name */
42 /* of the symbol, in the same case form as when created. */
43 /* slines[n] is the source line on which the symbol value was first */
45 /* symbol_debug_backpatch_positions[n] */
46 /* is a file position in the debug information file where */
47 /* the symbol's value should be written after backpatching, */
48 /* or else the null position if the value was known and */
49 /* written beforehand */
50 /* replacement_debug_backpatch_positions[n] */
51 /* is a file position in the debug information file where */
52 /* the symbol's name can be erased if it is replaced, or */
53 /* else null if the name will never need to be replaced */
55 /* Comparison is case insensitive. */
56 /* Note that local variable names are not entered into the symbols table, */
57 /* as their numbers and scope are too limited for this to be efficient. */
58 /* ------------------------------------------------------------------------- */
59 /* Caveat editor: some array types are set up to work even on machines */
60 /* where sizeof(int32 *) differs from, e.g., sizeof(char *): so do not */
61 /* alter the types unless you understand what is going on! */
62 /* ------------------------------------------------------------------------- */
66 int *smarks; /* Glulx-only */
67 brief_location *slines;
70 char *stypes; /* In VAX C, insanely, "signed char" is illegal */
74 maybe_file_position *symbol_debug_backpatch_positions;
75 maybe_file_position *replacement_debug_backpatch_positions;
77 /* ------------------------------------------------------------------------- */
78 /* Memory to hold the text of symbol names: note that this memory is */
79 /* allocated as needed in chunks of size SYMBOLS_CHUNK_SIZE. */
80 /* ------------------------------------------------------------------------- */
82 #define MAX_SYMBOL_CHUNKS (100)
84 static uchar *symbols_free_space, /* Next byte free to hold new names */
85 *symbols_ceiling; /* Pointer to the end of the current
86 allocation of memory for names */
88 static char** symbol_name_space_chunks; /* For chunks of memory used to hold
89 the name strings of symbols */
90 static int no_symbol_name_space_chunks;
92 /* Symbol replacements (used by the "Replace X Y" directive). */
94 typedef struct value_pair_struct {
98 static value_pair_t *symbol_replacements;
99 static int symbol_replacements_count;
100 static int symbol_replacements_size; /* calloced size */
102 /* Symbol definitions requested at compile time. (There may not be any.)
103 These are set up at command-line parse time, not in init_symbols_vars().
104 Similarly, they are not cleaned up by symbols_free_arrays(). */
106 typedef struct keyvalue_pair_struct {
110 static keyvalue_pair_t *symbol_definitions = NULL;
111 static int symbol_definitions_count = 0;
112 static int symbol_definitions_size = 0; /* calloced size */
114 /* ------------------------------------------------------------------------- */
115 /* The symbols table is "hash-coded" into a disjoint union of linked */
116 /* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
117 /* that it's the last in its list) or the next in the list. */
119 /* Each list contains, in alphabetical order, all the symbols which share */
120 /* the same "hash code" (a numerical function of the text of the symbol */
121 /* name, designed with the aim that roughly equal numbers of symbols are */
122 /* given each possible hash code). The hash codes are 0 to HASH_TAB_SIZE */
123 /* (which is a memory setting) minus 1: start_of_list[h] gives the first */
124 /* symbol with hash code h, or -1 if no symbol exists with hash code h. */
126 /* Note that the running time of the symbol search algorithm is about */
128 /* O ( n^2 / HASH_TAB_SIZE ) */
130 /* (where n is the number of symbols in the program) so that it is a good */
131 /* idea to choose HASH_TAB_SIZE as large as conveniently possible. */
132 /* ------------------------------------------------------------------------- */
134 static int *next_entry;
135 static int32 *start_of_list;
137 /* ------------------------------------------------------------------------- */
138 /* Initialisation. */
139 /* ------------------------------------------------------------------------- */
141 static void init_symbol_banks(void)
143 for (i=0; i<HASH_TAB_SIZE; i++) start_of_list[i] = -1;
146 /* ------------------------------------------------------------------------- */
147 /* The hash coding we use is quite standard; the variable hashcode is */
148 /* expected to overflow a good deal. (The aim is to produce a number */
149 /* so that similar names do not produce the same number.) Note that */
150 /* 30011 is prime. It doesn't matter if the unsigned int to int cast */
151 /* behaves differently on different ports. */
152 /* ------------------------------------------------------------------------- */
154 int case_conversion_grid[128];
156 static void make_case_conversion_grid(void)
158 /* Assumes that A to Z are contiguous in the host OS character set:
159 true for ASCII but not for EBCDIC, for instance. */
162 for (i=0; i<128; i++) case_conversion_grid[i] = i;
163 for (i=0; i<26; i++) case_conversion_grid['A'+i]='a'+i;
166 extern int hash_code_from_string(char *p)
168 for (; *p; p++) hashcode=hashcode*30011 + case_conversion_grid[(uchar)*p];
169 return (int) (hashcode % HASH_TAB_SIZE);
172 extern int strcmpcis(char *p, char *q)
174 /* Case insensitive strcmp */
177 for (i=0;p[i] != 0;i++)
178 { pc = p[i]; if (isupper(pc)) pc = tolower(pc);
179 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
183 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
187 /* ------------------------------------------------------------------------- */
189 extern void add_config_symbol_definition(char *symbol, int32 value)
191 if (symbol_definitions_count == symbol_definitions_size) {
192 int oldsize = symbol_definitions_size;
193 if (symbol_definitions_size == 0)
194 symbol_definitions_size = 4;
196 symbol_definitions_size *= 2;
197 my_recalloc(&symbol_definitions, sizeof(keyvalue_pair_t), oldsize,
198 symbol_definitions_size, "symbol definition table");
201 char *str = my_malloc(strlen(symbol)+1, "symbol name");
204 symbol_definitions[symbol_definitions_count].symbol = str;
205 symbol_definitions[symbol_definitions_count].value = value;
206 symbol_definitions_count++;
209 /* ------------------------------------------------------------------------- */
210 /* Symbol finding, creating, and removing. */
211 /* ------------------------------------------------------------------------- */
213 extern int symbol_index(char *p, int hashcode)
215 /* Return the index in the symbs/svals/sflags/stypes/... arrays of symbol
216 "p", creating a new symbol with that name if it isn't already there.
218 New symbols are created with flag UNKNOWN_SFLAG, value 0x100
219 (a 2-byte quantity in Z-machine terms) and type CONSTANT_T.
221 The string "p" is undamaged. */
223 int32 new_entry, this, last; char *r;
225 if (hashcode == -1) hashcode = hash_code_from_string(p);
227 this = start_of_list[hashcode]; last = -1;
230 { if (this == -1) break;
232 r = (char *)symbs[this];
233 new_entry = strcmpcis(r, p);
236 if (track_unused_routines)
237 df_note_function_symbol(this);
240 if (new_entry > 0) break;
243 this = next_entry[this];
244 } while (this != -1);
246 if (no_symbols >= MAX_SYMBOLS)
247 memoryerror("MAX_SYMBOLS", MAX_SYMBOLS);
250 { next_entry[no_symbols]=start_of_list[hashcode];
251 start_of_list[hashcode]=no_symbols;
254 { next_entry[no_symbols]=this;
255 next_entry[last]=no_symbols;
258 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
260 = my_malloc(SYMBOLS_CHUNK_SIZE, "symbol names chunk");
261 symbols_ceiling = symbols_free_space + SYMBOLS_CHUNK_SIZE;
262 /* If we've passed MAX_SYMBOL_CHUNKS chunks, we print an error
263 message telling the user to increase SYMBOLS_CHUNK_SIZE.
264 That is the correct cure, even though the error comes out
265 worded inaccurately. */
266 if (no_symbol_name_space_chunks >= MAX_SYMBOL_CHUNKS)
267 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
268 symbol_name_space_chunks[no_symbol_name_space_chunks++]
269 = (char *) symbols_free_space;
270 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
271 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
274 strcpy((char *) symbols_free_space, p);
275 symbs[no_symbols] = (int32 *) symbols_free_space;
276 symbols_free_space += strlen((char *)symbols_free_space) + 1;
278 svals[no_symbols] = 0x100; /* ###-wrong? Would this fix the
279 unbound-symbol-causes-asm-error? */
280 sflags[no_symbols] = UNKNOWN_SFLAG;
281 stypes[no_symbols] = CONSTANT_T;
282 slines[no_symbols] = get_brief_location(&ErrorReport);
283 if (debugfile_switch)
284 { nullify_debug_file_position
285 (&symbol_debug_backpatch_positions[no_symbols]);
286 nullify_debug_file_position
287 (&replacement_debug_backpatch_positions[no_symbols]);
290 if (track_unused_routines)
291 df_note_function_symbol(no_symbols);
292 return(no_symbols++);
295 extern void end_symbol_scope(int k)
297 /* Remove the given symbol from the hash table, making it
298 invisible to symbol_index. This is used by the Undef directive.
299 If the symbol is not found, this silently does nothing.
303 j = hash_code_from_string((char *) symbs[k]);
304 if (start_of_list[j] == k)
305 { start_of_list[j] = next_entry[k];
308 j = start_of_list[j];
311 if (next_entry[j] == k)
312 { next_entry[j] = next_entry[k];
319 /* ------------------------------------------------------------------------- */
320 /* Printing diagnostics */
321 /* ------------------------------------------------------------------------- */
323 extern char *typename(int type)
326 /* These are the possible symbol types. Note that local variables
327 do not reside in the symbol table (for scope and efficiency
328 reasons) and actions have their own name-space (via routine
329 names with "Sub" appended). */
331 case ROUTINE_T: return("Routine");
332 case LABEL_T: return("Label");
333 case GLOBAL_VARIABLE_T: return("Global variable");
334 case ARRAY_T: return("Array");
335 case STATIC_ARRAY_T: return("Static array");
336 case CONSTANT_T: return("Defined constant");
337 case ATTRIBUTE_T: return("Attribute");
338 case PROPERTY_T: return("Property");
339 case INDIVIDUAL_PROPERTY_T: return("Individual property");
340 case OBJECT_T: return("Object");
341 case CLASS_T: return("Class");
342 case FAKE_ACTION_T: return("Fake action");
344 default: return("(Unknown type)");
348 static void describe_flags(int flags)
349 { if (flags & UNKNOWN_SFLAG) printf("(?) ");
350 if (flags & USED_SFLAG) printf("(used) ");
351 if (flags & REPLACE_SFLAG) printf("(Replaced) ");
352 if (flags & DEFCON_SFLAG) printf("(Defaulted) ");
353 if (flags & STUB_SFLAG) printf("(Stubbed) ");
354 if (flags & CHANGE_SFLAG) printf("(value will change) ");
355 if (flags & IMPORT_SFLAG) printf("(Imported) ");
356 if (flags & EXPORT_SFLAG) printf("(Exported) ");
357 if (flags & SYSTEM_SFLAG) printf("(System) ");
358 if (flags & INSF_SFLAG) printf("(created in sys file) ");
359 if (flags & UERROR_SFLAG) printf("('Unknown' error issued) ");
360 if (flags & ALIASED_SFLAG) printf("(aliased) ");
361 if (flags & ACTION_SFLAG) printf("(Action name) ");
362 if (flags & REDEFINABLE_SFLAG) printf("(Redefinable) ");
365 extern void describe_symbol(int k)
366 { printf("%4d %-16s %2d:%04d %04x %s ",
367 k, (char *) (symbs[k]),
368 (int)(slines[k].file_index),
369 (int)(slines[k].line_number),
370 svals[k], typename(stypes[k]));
371 describe_flags(sflags[k]);
374 extern void list_symbols(int level)
376 for (k=0; k<no_symbols; k++)
378 ((sflags[k] & (SYSTEM_SFLAG + UNKNOWN_SFLAG + INSF_SFLAG)) == 0))
379 { describe_symbol(k); printf("\n");
384 extern void issue_unused_warnings(void)
387 if (module_switch) return;
389 /* Update any ad-hoc variables that might help the library */
391 { global_initial_value[10]=statusline_flag;
393 /* Now back to mark anything necessary as used */
395 i = symbol_index("Main", -1);
396 if (!(sflags[i] & UNKNOWN_SFLAG)) sflags[i] |= USED_SFLAG;
398 for (i=0;i<no_symbols;i++)
400 & (SYSTEM_SFLAG + UNKNOWN_SFLAG + EXPORT_SFLAG
401 + INSF_SFLAG + USED_SFLAG + REPLACE_SFLAG)) == 0)
402 && (stypes[i] != OBJECT_T))
403 dbnu_warning(typename(stypes[i]), (char *) symbs[i], slines[i]);
407 /* ------------------------------------------------------------------------- */
408 /* These are arrays used only during story file (never module) creation, */
409 /* and not allocated until then. */
411 int32 *individual_name_strings; /* Packed addresses of Z-encoded
412 strings of the names of the
413 properties: this is an array
414 indexed by the property ID */
415 int32 *action_name_strings; /* Ditto for actions */
416 int32 *attribute_name_strings; /* Ditto for attributes */
417 int32 *array_name_strings; /* Ditto for arrays */
419 extern void write_the_identifier_names(void)
420 { int i, j, k, t, null_value; char idname_string[256];
421 static char unknown_attribute[20] = "<unknown attribute>";
423 for (i=0; i<no_individual_properties; i++)
424 individual_name_strings[i] = 0;
426 if (module_switch) return;
430 null_value = compile_string(unknown_attribute, STRCTX_SYMBOL);
431 for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
433 for (i=0; i<no_symbols; i++)
435 if ((t == INDIVIDUAL_PROPERTY_T) || (t == PROPERTY_T))
436 { if (sflags[i] & ALIASED_SFLAG)
437 { if (individual_name_strings[svals[i]] == 0)
438 { sprintf(idname_string, "%s", (char *) symbs[i]);
440 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
441 { if ((stypes[j] == stypes[i])
442 && (svals[j] == svals[i]))
443 { sprintf(idname_string+strlen(idname_string),
444 "/%s", (char *) symbs[j]);
449 individual_name_strings[svals[i]]
450 = compile_string(idname_string, STRCTX_SYMBOL);
454 { sprintf(idname_string, "%s", (char *) symbs[i]);
456 individual_name_strings[svals[i]]
457 = compile_string(idname_string, STRCTX_SYMBOL);
460 if (t == ATTRIBUTE_T)
461 { if (sflags[i] & ALIASED_SFLAG)
462 { if (attribute_name_strings[svals[i]] == null_value)
463 { sprintf(idname_string, "%s", (char *) symbs[i]);
465 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
466 { if ((stypes[j] == stypes[i])
467 && (svals[j] == svals[i]))
468 { sprintf(idname_string+strlen(idname_string),
469 "/%s", (char *) symbs[j]);
474 attribute_name_strings[svals[i]]
475 = compile_string(idname_string, STRCTX_SYMBOL);
479 { sprintf(idname_string, "%s", (char *) symbs[i]);
481 attribute_name_strings[svals[i]]
482 = compile_string(idname_string, STRCTX_SYMBOL);
485 if (sflags[i] & ACTION_SFLAG)
486 { sprintf(idname_string, "%s", (char *) symbs[i]);
487 idname_string[strlen(idname_string)-3] = 0;
489 if (debugfile_switch)
490 { debug_file_printf("<action>");
492 ("<identifier>##%s</identifier>", idname_string);
493 debug_file_printf("<value>%d</value>", svals[i]);
494 debug_file_printf("</action>");
497 action_name_strings[svals[i]]
498 = compile_string(idname_string, STRCTX_SYMBOL);
502 for (i=0; i<no_symbols; i++)
503 { if (stypes[i] == FAKE_ACTION_T)
504 { sprintf(idname_string, "%s", (char *) symbs[i]);
505 idname_string[strlen(idname_string)-3] = 0;
507 action_name_strings[svals[i]
508 - ((grammar_version_number==1)?256:4096) + no_actions]
509 = compile_string(idname_string, STRCTX_SYMBOL);
513 for (j=0; j<no_arrays; j++)
514 { i = array_symbols[j];
515 sprintf(idname_string, "%s", (char *) symbs[i]);
517 array_name_strings[j]
518 = compile_string(idname_string, STRCTX_SYMBOL);
520 if (define_INFIX_switch)
521 { for (i=0; i<no_symbols; i++)
522 { if (stypes[i] == GLOBAL_VARIABLE_T)
523 { sprintf(idname_string, "%s", (char *) symbs[i]);
524 array_name_strings[no_arrays + svals[i] -16]
525 = compile_string(idname_string, STRCTX_SYMBOL);
529 for (i=0; i<no_named_routines; i++)
530 { sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
531 array_name_strings[no_arrays + no_globals + i]
532 = compile_string(idname_string, STRCTX_SYMBOL);
535 for (i=0, no_named_constants=0; i<no_symbols; i++)
536 { if (((stypes[i] == OBJECT_T) || (stypes[i] == CLASS_T)
537 || (stypes[i] == CONSTANT_T))
538 && ((sflags[i] & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
539 { sprintf(idname_string, "%s", (char *) symbs[i]);
540 array_name_strings[no_arrays + no_globals + no_named_routines
541 + no_named_constants++]
542 = compile_string(idname_string, STRCTX_SYMBOL);
549 /* ------------------------------------------------------------------------- */
550 /* Creating symbols */
551 /* ------------------------------------------------------------------------- */
553 static void assign_symbol_base(int index, int32 value, int type)
554 { svals[index] = value;
555 stypes[index] = type;
556 if (sflags[index] & UNKNOWN_SFLAG)
557 { sflags[index] &= (~UNKNOWN_SFLAG);
558 if (is_systemfile()) sflags[index] |= INSF_SFLAG;
559 slines[index] = get_brief_location(&ErrorReport);
563 extern void assign_symbol(int index, int32 value, int type)
566 assign_symbol_base(index, value, type);
570 assign_symbol_base(index, value, type);
574 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
577 assign_symbol_base(index, (int32)marker*0x10000 + (value % 0x10000),
581 smarks[index] = marker;
582 assign_symbol_base(index, value, type);
586 static void emit_debug_information_for_predefined_symbol
587 (char *name, int32 symbol, int32 value, int type)
588 { if (debugfile_switch)
591 debug_file_printf("<constant>");
592 debug_file_printf("<identifier>%s</identifier>", name);
593 write_debug_symbol_optional_backpatch(symbol);
594 debug_file_printf("</constant>");
596 case GLOBAL_VARIABLE_T:
597 debug_file_printf("<global-variable>");
598 debug_file_printf("<identifier>%s</identifier>", name);
599 debug_file_printf("<address>");
600 write_debug_global_backpatch(value);
601 debug_file_printf("</address>");
602 debug_file_printf("</global-variable>");
606 { compiler_error("Non-nothing object predefined");
608 debug_file_printf("<object>");
609 debug_file_printf("<identifier>%s</identifier>", name);
610 debug_file_printf("<value>0</value>");
611 debug_file_printf("</object>");
614 debug_file_printf("<attribute>");
615 debug_file_printf("<identifier>%s</identifier>", name);
616 debug_file_printf("<value>%d</value>", value);
617 debug_file_printf("</attribute>");
620 case INDIVIDUAL_PROPERTY_T:
621 debug_file_printf("<property>");
622 debug_file_printf("<identifier>%s</identifier>", name);
623 debug_file_printf("<value>%d</value>", value);
624 debug_file_printf("</property>");
628 ("Unable to emit debug information for predefined symbol");
634 static void create_symbol(char *p, int32 value, int type)
635 { int i = symbol_index(p, -1);
636 if (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))) {
637 /* Symbol already defined! */
638 if (svals[i] == value && stypes[i] == type) {
639 /* Special case: the symbol was already defined with this same
640 value. We let it pass. */
644 ebf_symbol_error("new symbol", p, typename(stypes[i]), slines[i]);
648 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
649 /* If the symbol already existed with REDEFINABLE_SFLAG, we keep that. */
650 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + (sflags[i] & REDEFINABLE_SFLAG);
651 emit_debug_information_for_predefined_symbol(p, i, value, type);
654 static void create_rsymbol(char *p, int value, int type)
655 { int i = symbol_index(p, -1);
656 /* This is only called for a few symbols with known names.
657 They will not collide. */
658 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
659 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
660 emit_debug_information_for_predefined_symbol(p, i, value, type);
663 static void stockup_symbols(void)
666 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
668 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
670 create_symbol("nothing", 0, OBJECT_T);
671 create_symbol("name", 1, PROPERTY_T);
673 create_symbol("true", 1, CONSTANT_T);
674 create_symbol("false", 0, CONSTANT_T);
676 /* Glulx defaults to GV2; Z-code to GV1 */
678 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
680 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
681 grammar_version_symbol = symbol_index("Grammar__Version", -1);
684 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
686 if (runtime_error_checking_switch)
687 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
689 if (define_DEBUG_switch)
690 create_rsymbol("DEBUG", 0, CONSTANT_T);
692 if (define_USE_MODULES_switch)
693 create_rsymbol("USE_MODULES",0, CONSTANT_T);
695 if (define_INFIX_switch)
696 { create_rsymbol("INFIX", 0, CONSTANT_T);
697 create_symbol("infix__watching", 0, ATTRIBUTE_T);
700 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
701 create_symbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
703 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
704 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
707 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
708 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
709 if (DICT_CHAR_SIZE != 1)
710 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
711 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
712 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
713 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
714 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
715 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
716 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
717 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
718 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
719 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
720 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
724 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
725 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
726 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
727 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
728 create_symbol("self", 251, GLOBAL_VARIABLE_T);
729 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
730 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
732 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
733 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
734 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
736 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
737 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
738 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
739 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
740 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
741 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
742 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
743 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
746 /* In Glulx, these system globals are entered in order, not down
748 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
750 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
752 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
754 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
756 create_symbol("self", MAX_LOCAL_VARIABLES+4,
758 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
760 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
763 /* These are almost certainly meaningless, and can be removed. */
764 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
766 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
768 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
771 /* value of statusline_flag to be written later */
772 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
775 /* These are created in order, but not necessarily at a fixed
777 create_symbol("create", INDIV_PROP_START+0,
778 INDIVIDUAL_PROPERTY_T);
779 create_symbol("recreate", INDIV_PROP_START+1,
780 INDIVIDUAL_PROPERTY_T);
781 create_symbol("destroy", INDIV_PROP_START+2,
782 INDIVIDUAL_PROPERTY_T);
783 create_symbol("remaining", INDIV_PROP_START+3,
784 INDIVIDUAL_PROPERTY_T);
785 create_symbol("copy", INDIV_PROP_START+4,
786 INDIVIDUAL_PROPERTY_T);
787 create_symbol("call", INDIV_PROP_START+5,
788 INDIVIDUAL_PROPERTY_T);
789 create_symbol("print", INDIV_PROP_START+6,
790 INDIVIDUAL_PROPERTY_T);
791 create_symbol("print_to_array",INDIV_PROP_START+7,
792 INDIVIDUAL_PROPERTY_T);
794 /* Floating-point constants. Note that FLOAT_NINFINITY is not
795 -FLOAT_INFINITY, because float negation doesn't work that
796 way. Also note that FLOAT_NAN is just one of many possible
797 "not-a-number" values. */
798 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
799 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
800 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
803 if (symbol_definitions && symbol_definitions_count) {
805 for (ix=0; ix<symbol_definitions_count; ix++) {
806 char *str = symbol_definitions[ix].symbol;
807 int32 val = symbol_definitions[ix].value;
808 create_symbol(str, val, CONSTANT_T);
813 /* ------------------------------------------------------------------------- */
814 /* The symbol replacement table. This is needed only for the */
815 /* "Replace X Y" directive. */
816 /* ------------------------------------------------------------------------- */
818 extern void add_symbol_replacement_mapping(int original, int renamed)
822 if (original == renamed) {
823 error_named("A routine cannot be 'Replace'd to itself:", (char *)symbs[original]);
827 if (symbol_replacements_count == symbol_replacements_size) {
828 int oldsize = symbol_replacements_size;
829 if (symbol_replacements_size == 0)
830 symbol_replacements_size = 4;
832 symbol_replacements_size *= 2;
833 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
834 symbol_replacements_size, "symbol replacement table");
837 /* If the original form is already in our table, report an error.
838 Same goes if the replaced form is already in the table as an
839 original. (Other collision cases have already been
842 for (ix=0; ix<symbol_replacements_count; ix++) {
843 if (original == symbol_replacements[ix].original_symbol) {
844 error_named("A routine cannot be 'Replace'd to more than one new name:", (char *)symbs[original]);
846 if (renamed == symbol_replacements[ix].original_symbol) {
847 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", (char *)symbs[original]);
851 symbol_replacements[symbol_replacements_count].original_symbol = original;
852 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
853 symbol_replacements_count++;
856 extern int find_symbol_replacement(int *value)
861 if (!symbol_replacements)
864 for (ix=0; ix<symbol_replacements_count; ix++) {
865 if (*value == symbol_replacements[ix].original_symbol) {
866 *value = symbol_replacements[ix].renamed_symbol;
874 /* ------------------------------------------------------------------------- */
875 /* The dead-function removal optimization. */
876 /* ------------------------------------------------------------------------- */
878 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
879 OMIT_UNUSED_ROUTINES is nonzero */
880 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
881 static int df_tables_closed; /* set at end of compiler pass */
883 typedef struct df_function_struct df_function_t;
884 typedef struct df_reference_struct df_reference_t;
886 struct df_function_struct {
887 char *name; /* borrowed reference, generally to the symbs[] table */
888 brief_location source_line; /* copied from routine_starts_line */
889 int sysfile; /* does this occur in a system file? */
890 uint32 address; /* function offset in zcode_area (not the final address) */
891 uint32 newaddress; /* function offset after stripping */
894 df_reference_t *refs; /* chain of references made *from* this function */
897 df_function_t *funcnext; /* in forward functions order */
898 df_function_t *todonext; /* in the todo chain */
899 df_function_t *next; /* in the hash table */
902 struct df_reference_struct {
903 uint32 address; /* function offset in zcode_area (not the final address) */
904 int symbol; /* index in symbols array */
906 df_reference_t *refsnext; /* in the function's refs chain */
907 df_reference_t *next; /* in the hash table */
910 /* Bitmask flags for how functions are used: */
911 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
912 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
913 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
914 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
916 #define DF_FUNCTION_HASH_BUCKETS (1023)
918 /* Table of all compiled functions. (Only created if track_unused_routines
919 is set.) This is a hash table. */
920 static df_function_t **df_functions;
921 /* List of all compiled functions, in address order. The first entry
922 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
923 static df_function_t *df_functions_head;
924 static df_function_t *df_functions_tail;
925 /* Used during output_file(), to track how far the code-area output has
927 static df_function_t *df_iterator;
929 /* Array of all compiled functions in address order. (Does not include
930 the global namespace entry.) This is generated only if needed. */
931 static df_function_t **df_functions_sorted;
932 static int df_functions_sorted_count;
934 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
935 #define DF_SYMBOL_HASH_BUCKETS (4095)
937 /* Map of what functions reference what other functions. (Only created if
938 track_unused_routines is set.) */
939 static df_reference_t **df_symbol_map;
941 /* Globals used while a function is being compiled. When a function
942 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
943 and df_current_function will refer to the global namespace record. */
944 static df_function_t *df_current_function;
945 static char *df_current_function_name;
946 static uint32 df_current_function_addr;
948 /* Size totals for compiled code. These are only meaningful if
949 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
950 these values will be set, but the "after" value will not affect the
952 uint32 df_total_size_before_stripping;
953 uint32 df_total_size_after_stripping;
955 /* When we begin compiling a function, call this to note that fact.
956 Any symbol referenced from now on will be associated with the function.
958 extern void df_note_function_start(char *name, uint32 address,
959 int embedded_flag, brief_location source_line)
964 if (df_tables_closed)
965 error("Internal error in stripping: Tried to start a new function after tables were closed.");
967 /* We retain the name only for debugging output. Note that embedded
968 functions all show up as "<embedded>" -- their "obj.prop" name
969 never gets stored in permanent memory. */
970 df_current_function_name = name;
971 df_current_function_addr = address;
973 func = my_malloc(sizeof(df_function_t), "df function entry");
974 memset(func, 0, sizeof(df_function_t));
976 func->address = address;
977 func->source_line = source_line;
978 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
979 /* An embedded function is stored in an object property, so we
980 consider it to be used a priori. */
982 func->usage |= DF_USAGE_EMBEDDED;
984 if (!df_functions_head) {
985 df_functions_head = func;
986 df_functions_tail = func;
989 df_functions_tail->funcnext = func;
990 df_functions_tail = func;
993 bucket = address % DF_FUNCTION_HASH_BUCKETS;
994 func->next = df_functions[bucket];
995 df_functions[bucket] = func;
997 df_current_function = func;
1000 /* When we're done compiling a function, call this. Any symbol referenced
1001 from now on will be associated with the global namespace.
1003 extern void df_note_function_end(uint32 endaddress)
1005 df_current_function->length = endaddress - df_current_function->address;
1007 df_current_function_name = NULL;
1008 df_current_function_addr = DF_NOT_IN_FUNCTION;
1009 df_current_function = df_functions_head; /* the global namespace */
1012 /* Find the function record for a given address. (Addresses are offsets
1015 static df_function_t *df_function_for_address(uint32 address)
1017 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
1018 df_function_t *func;
1019 for (func = df_functions[bucket]; func; func = func->next) {
1020 if (func->address == address)
1026 /* Whenever a function is referenced, we call this to note who called it.
1028 extern void df_note_function_symbol(int symbol)
1030 int bucket, symtype;
1031 df_reference_t *ent;
1033 /* If the compiler pass is over, looking up symbols does not create
1034 a global reference. */
1035 if (df_tables_closed)
1037 /* In certain cases during parsing, looking up symbols does not
1038 create a global reference. (For example, when reading the name
1039 of a function being defined.) */
1040 if (df_dont_note_global_symbols)
1043 /* We are only interested in functions, or forward-declared symbols
1044 that might turn out to be functions. */
1045 symtype = stypes[symbol];
1046 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
1048 if (symtype == CONSTANT_T && !(sflags[symbol] & UNKNOWN_SFLAG))
1051 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
1052 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
1053 if (ent->address == df_current_function_addr && ent->symbol == symbol)
1057 /* Create a new reference entry in df_symbol_map. */
1058 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
1059 ent->address = df_current_function_addr;
1060 ent->symbol = symbol;
1061 ent->next = df_symbol_map[bucket];
1062 df_symbol_map[bucket] = ent;
1064 /* Add the reference to the function's entry as well. */
1065 /* The current function is the most recently added, so it will be
1066 at the top of its bucket. That makes this call fast. Unless
1067 we're in global scope, in which case it might be slower.
1068 (I suppose we could cache the df_function_t pointer of the
1069 current function, to speed things up.) */
1070 if (!df_current_function || df_current_function_addr != df_current_function->address)
1071 compiler_error("DF: df_current_function does not match current address.");
1072 ent->refsnext = df_current_function->refs;
1073 df_current_function->refs = ent;
1076 /* This does the hard work of figuring out what functions are truly dead.
1077 It's called near the end of run_pass() in inform.c.
1079 extern void locate_dead_functions(void)
1081 df_function_t *func, *tofunc;
1082 df_reference_t *ent;
1085 if (!track_unused_routines)
1086 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1088 df_tables_closed = TRUE;
1089 df_current_function = NULL;
1091 /* Note that Main__ was tagged as global implicitly during
1092 compile_initial_routine(). Main was tagged during
1093 issue_unused_warnings(). But for the sake of thoroughness,
1094 we'll mark them specially. */
1096 ix = symbol_index("Main__", -1);
1097 if (stypes[ix] == ROUTINE_T) {
1098 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1099 tofunc = df_function_for_address(addr);
1101 tofunc->usage |= DF_USAGE_MAIN;
1103 ix = symbol_index("Main", -1);
1104 if (stypes[ix] == ROUTINE_T) {
1105 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1106 tofunc = df_function_for_address(addr);
1108 tofunc->usage |= DF_USAGE_MAIN;
1111 /* Go through all the functions referenced at the global level;
1112 mark them as used. */
1114 func = df_functions_head;
1115 if (!func || func->address != DF_NOT_IN_FUNCTION) {
1116 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1120 for (ent = func->refs; ent; ent=ent->refsnext) {
1122 int symbol = ent->symbol;
1123 if (stypes[symbol] != ROUTINE_T)
1125 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1126 tofunc = df_function_for_address(addr);
1128 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1131 /* A function may be marked here more than once. That's fine. */
1132 tofunc->usage |= DF_USAGE_GLOBAL;
1135 /* Perform a breadth-first search through functions, starting with
1136 the ones that are known to be used at the top level. */
1138 df_function_t *todo, *todotail;
1139 df_function_t *func;
1143 for (func = df_functions_head; func; func = func->funcnext) {
1144 if (func->address == DF_NOT_IN_FUNCTION)
1146 if (func->usage == 0)
1153 todotail->todonext = func;
1158 /* todo is a linked list of functions which are known to be
1159 used. If a function's usage field is nonzero, it must be
1160 either be on the todo list or have come off already (in
1161 which case processed will be set). */
1164 /* Pop the next function. */
1166 todo = todo->todonext;
1170 if (func->processed)
1171 error_named("Internal error in stripping: function has been processed twice:", func->name);
1173 /* Go through the function's symbol references. Any
1174 reference to a routine, push it into the todo list (if
1175 it isn't there already). */
1177 for (ent = func->refs; ent; ent=ent->refsnext) {
1179 int symbol = ent->symbol;
1180 if (stypes[symbol] != ROUTINE_T)
1182 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1183 tofunc = df_function_for_address(addr);
1185 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1191 /* Not yet known to be used. Add it to the todo list. */
1192 tofunc->usage |= DF_USAGE_FUNCTION;
1198 todotail->todonext = tofunc;
1203 func->processed = TRUE;
1207 /* Go through all functions; figure out how much space is consumed,
1208 with and without useless functions. */
1211 df_function_t *func;
1213 df_total_size_before_stripping = 0;
1214 df_total_size_after_stripping = 0;
1216 for (func = df_functions_head; func; func = func->funcnext) {
1217 if (func->address == DF_NOT_IN_FUNCTION)
1220 if (func->address != df_total_size_before_stripping)
1221 compiler_error("DF: Address gap in function list");
1223 df_total_size_before_stripping += func->length;
1225 func->newaddress = df_total_size_after_stripping;
1226 df_total_size_after_stripping += func->length;
1229 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1230 compiler_error("DF: New function address is not aligned");
1232 if (WARN_UNUSED_ROUTINES && !func->usage) {
1233 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1234 uncalled_routine_warning("Routine", func->name, func->source_line);
1239 /* df_measure_hash_table_usage(); */
1242 /* Given an original function address, return where it winds up after
1243 unused-function stripping. The function must not itself be unused.
1245 Both the input and output are offsets, and already scaled by
1248 This is used by the backpatching system.
1250 extern uint32 df_stripped_address_for_address(uint32 addr)
1252 df_function_t *func;
1254 if (!track_unused_routines)
1255 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1258 func = df_function_for_address(addr*scale_factor);
1260 func = df_function_for_address(addr);
1263 compiler_error("DF: Unable to find function while backpatching");
1267 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1270 return func->newaddress / scale_factor;
1272 return func->newaddress;
1275 /* Given an address in the function area, return where it winds up after
1276 unused-function stripping. The address can be a function or anywhere
1277 within the function. If the address turns out to be in a stripped
1278 function, returns 0 (and sets *stripped).
1280 The input and output are offsets, but *not* scaled.
1282 This is only used by the debug-file system.
1284 uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
1286 df_function_t *func;
1291 if (!track_unused_routines)
1292 compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
1294 if (!df_functions_sorted) {
1295 /* To do this efficiently, we need a binary-searchable table. Fine,
1296 we'll make one. Include both used and unused functions. */
1298 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1299 if (func->address == DF_NOT_IN_FUNCTION)
1303 df_functions_sorted_count = count;
1305 df_functions_sorted = my_calloc(sizeof(df_function_t *), df_functions_sorted_count, "df function sorted table");
1307 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1308 if (func->address == DF_NOT_IN_FUNCTION)
1310 df_functions_sorted[count] = func;
1315 /* Do a binary search. Maintain beg <= res < end, where res is the
1316 function containing the desired address. */
1318 end = df_functions_sorted_count;
1320 /* Set stripped flag until we decide on a non-stripped function. */
1326 error("DF: offset_for_code_offset: Could not locate address.");
1330 func = df_functions_sorted[beg];
1331 if (func->usage == 0)
1334 return func->newaddress + (offset - func->address);
1336 new = (beg + end) / 2;
1337 if (new <= beg || new >= end)
1338 compiler_error("DF: binary search went off the rails");
1340 func = df_functions_sorted[new];
1341 if (offset >= func->address) {
1342 if (offset < func->address+func->length) {
1343 /* We don't need to loop further; decide here. */
1344 if (func->usage == 0)
1347 return func->newaddress + (offset - func->address);
1357 /* The output_file() routines in files.c have to run down the list of
1358 functions, deciding who is in and who is out. But I don't want to
1359 export the df_function_t list structure. Instead, I provide this
1360 silly iterator pair. Set it up with df_prepare_function_iterate();
1361 then repeatedly call df_next_function_iterate().
1364 extern void df_prepare_function_iterate(void)
1366 df_iterator = df_functions_head;
1367 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1368 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1369 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1370 compiler_error("DF: First function entry is not second in the chain.");
1373 /* This returns the end of the next function, and whether the next function
1376 extern uint32 df_next_function_iterate(int *funcused)
1379 df_iterator = df_iterator->funcnext;
1382 return df_total_size_before_stripping+1;
1384 *funcused = (df_iterator->usage != 0);
1385 return df_iterator->address + df_iterator->length;
1388 /* ========================================================================= */
1389 /* Data structure management routines */
1390 /* ------------------------------------------------------------------------- */
1392 extern void init_symbols_vars(void)
1400 start_of_list = NULL;
1402 symbol_name_space_chunks = NULL;
1403 no_symbol_name_space_chunks = 0;
1404 symbols_free_space=NULL;
1405 symbols_ceiling=symbols_free_space;
1409 symbol_replacements = NULL;
1410 symbol_replacements_count = 0;
1411 symbol_replacements_size = 0;
1413 make_case_conversion_grid();
1415 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1416 df_tables_closed = FALSE;
1417 df_symbol_map = NULL;
1418 df_functions = NULL;
1419 df_functions_head = NULL;
1420 df_functions_tail = NULL;
1421 df_current_function = NULL;
1422 df_functions_sorted = NULL;
1423 df_functions_sorted_count = 0;
1426 extern void symbols_begin_pass(void)
1428 df_total_size_before_stripping = 0;
1429 df_total_size_after_stripping = 0;
1430 df_dont_note_global_symbols = FALSE;
1434 extern void symbols_allocate_arrays(void)
1436 symbs = my_calloc(sizeof(char *), MAX_SYMBOLS, "symbols");
1437 svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
1439 smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
1440 slines = my_calloc(sizeof(brief_location), MAX_SYMBOLS, "symbol lines");
1441 stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
1442 sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
1443 if (debugfile_switch)
1444 { symbol_debug_backpatch_positions =
1445 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1446 "symbol debug information backpatch positions");
1447 replacement_debug_backpatch_positions =
1448 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1449 "replacement debug information backpatch positions");
1451 next_entry = my_calloc(sizeof(int), MAX_SYMBOLS,
1452 "symbol linked-list forward links");
1453 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1454 "hash code list beginnings");
1456 symbol_name_space_chunks
1457 = my_calloc(sizeof(char *), MAX_SYMBOL_CHUNKS, "symbol names chunk addresses");
1459 if (track_unused_routines) {
1460 df_tables_closed = FALSE;
1462 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1463 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1465 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1466 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1467 df_functions_head = NULL;
1468 df_functions_tail = NULL;
1470 df_functions_sorted = NULL;
1471 df_functions_sorted_count = 0;
1473 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, blank_brief_location);
1474 df_note_function_end(DF_NOT_IN_FUNCTION);
1475 /* Now df_current_function is df_functions_head. */
1478 init_symbol_banks();
1481 /* Allocated as needed */
1482 symbol_replacements = NULL;
1484 /* Allocated during story file construction, not now */
1485 individual_name_strings = NULL;
1486 attribute_name_strings = NULL;
1487 action_name_strings = NULL;
1488 array_name_strings = NULL;
1491 extern void symbols_free_arrays(void)
1494 for (i=0; i<no_symbol_name_space_chunks; i++)
1495 my_free(&(symbol_name_space_chunks[i]),
1496 "symbol names chunk");
1498 my_free(&symbol_name_space_chunks, "symbol names chunk addresses");
1500 my_free(&symbs, "symbols");
1501 my_free(&svals, "symbol values");
1502 my_free(&smarks, "symbol markers");
1503 my_free(&slines, "symbol lines");
1504 my_free(&stypes, "symbol types");
1505 my_free(&sflags, "symbol flags");
1506 if (debugfile_switch)
1508 (&symbol_debug_backpatch_positions,
1509 "symbol debug information backpatch positions");
1511 (&replacement_debug_backpatch_positions,
1512 "replacement debug information backpatch positions");
1514 my_free(&next_entry, "symbol linked-list forward links");
1515 my_free(&start_of_list, "hash code list beginnings");
1517 if (symbol_replacements)
1518 my_free(&symbol_replacements, "symbol replacement table");
1520 if (df_symbol_map) {
1521 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1522 df_reference_t *ent = df_symbol_map[i];
1524 df_reference_t *next = ent->next;
1525 my_free(&ent, "df symbol map entry");
1529 my_free(&df_symbol_map, "df symbol-map hash table");
1531 if (df_functions_sorted) {
1532 my_free(&df_functions, "df function sorted table");
1535 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1536 df_function_t *func = df_functions[i];
1538 df_function_t *next = func->next;
1539 my_free(&func, "df function entry");
1543 my_free(&df_functions, "df function hash table");
1545 df_functions_head = NULL;
1546 df_functions_tail = NULL;
1548 if (individual_name_strings != NULL)
1549 my_free(&individual_name_strings, "property name strings");
1550 if (action_name_strings != NULL)
1551 my_free(&action_name_strings, "action name strings");
1552 if (attribute_name_strings != NULL)
1553 my_free(&attribute_name_strings, "attribute name strings");
1554 if (array_name_strings != NULL)
1555 my_free(&array_name_strings, "array name strings");
1558 /* ========================================================================= */