Imported Upstream version 6.33.1~b2+dfsg.1
[debian_inform6.git] / src / symbols.c
blob734c0acba2c5649fdc17c585a8481fb4dd38abad
1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
3 /* */
4 /* Part of Inform 6.33 */
5 /* copyright (c) Graham Nelson 1993 - 2014 */
6 /* */
7 /* ------------------------------------------------------------------------- */
9 #include "header.h"
11 /* ------------------------------------------------------------------------- */
12 /* This section of Inform is a service detached from the rest. */
13 /* Only two variables are accessible from the outside: */
14 /* ------------------------------------------------------------------------- */
16 int no_symbols; /* Total number of symbols defined */
17 int no_named_constants; /* Copied into story file */
19 /* ------------------------------------------------------------------------- */
20 /* Plus six arrays. Each symbol has its own index n (an int32) and */
21 /* */
22 /* svals[n] is its value (must be 32 bits wide, i.e. an int32, tho' */
23 /* it is used to hold an unsigned 16 bit Z-machine value) */
24 /* sflags[n] holds flags (see "header.h" for a list) */
25 /* stypes[n] is the "type", distinguishing between the data type of */
26 /* different kinds of constants/variables. */
27 /* (See the "typename()" below.) */
28 /* symbs[n] (needs to be cast to (char *) to be used) is the name */
29 /* of the symbol, in the same case form as when created. */
30 /* slines[n] is the source line on which the symbol value was first */
31 /* assigned */
32 /* symbol_debug_backpatch_positions[n] */
33 /* is a file position in the debug information file where */
34 /* the symbol's value should be written after backpatching, */
35 /* or else the null position if the value was known and */
36 /* written beforehand */
37 /* replacement_debug_backpatch_positions[n] */
38 /* is a file position in the debug information file where */
39 /* the symbol's name can be erased if it is replaced, or */
40 /* else null if the name will never need to be replaced */
41 /* */
42 /* Comparison is case insensitive. */
43 /* Note that local variable names are not entered into the symbols table, */
44 /* as their numbers and scope are too limited for this to be efficient. */
45 /* ------------------------------------------------------------------------- */
46 /* Caveat editor: some array types are set up to work even on machines */
47 /* where sizeof(int32 *) differs from, e.g., sizeof(char *): so do not */
48 /* alter the types unless you understand what is going on! */
49 /* ------------------------------------------------------------------------- */
51 int32 **symbs;
52 int32 *svals;
53 int *smarks; /* Glulx-only */
54 int32 *slines;
55 int *sflags;
56 #ifdef VAX
57 char *stypes; /* In VAX C, insanely, "signed char" is illegal */
58 #else
59 signed char *stypes;
60 #endif
61 maybe_file_position *symbol_debug_backpatch_positions;
62 maybe_file_position *replacement_debug_backpatch_positions;
64 /* ------------------------------------------------------------------------- */
65 /* Memory to hold the text of symbol names: note that this memory is */
66 /* allocated as needed in chunks of size SYMBOLS_CHUNK_SIZE. */
67 /* ------------------------------------------------------------------------- */
69 #define MAX_SYMBOL_CHUNKS (100)
71 static uchar *symbols_free_space, /* Next byte free to hold new names */
72 *symbols_ceiling; /* Pointer to the end of the current
73 allocation of memory for names */
75 static char** symbol_name_space_chunks; /* For chunks of memory used to hold
76 the name strings of symbols */
77 static int no_symbol_name_space_chunks;
79 typedef struct value_pair_struct {
80 int original_symbol;
81 int renamed_symbol;
82 } value_pair_t;
83 static value_pair_t *symbol_replacements;
84 static int symbol_replacements_count;
85 static int symbol_replacements_size; /* calloced size */
87 /* ------------------------------------------------------------------------- */
88 /* The symbols table is "hash-coded" into a disjoint union of linked */
89 /* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
90 /* that it's the last in its list) or the next in the list. */
91 /* */
92 /* Each list contains, in alphabetical order, all the symbols which share */
93 /* the same "hash code" (a numerical function of the text of the symbol */
94 /* name, designed with the aim that roughly equal numbers of symbols are */
95 /* given each possible hash code). The hash codes are 0 to HASH_TAB_SIZE */
96 /* (which is a memory setting) minus 1: start_of_list[h] gives the first */
97 /* symbol with hash code h, or -1 if no symbol exists with hash code h. */
98 /* */
99 /* Note that the running time of the symbol search algorithm is about */
100 /* */
101 /* O ( n^2 / HASH_TAB_SIZE ) */
102 /* */
103 /* (where n is the number of symbols in the program) so that it is a good */
104 /* idea to choose HASH_TAB_SIZE as large as conveniently possible. */
105 /* ------------------------------------------------------------------------- */
107 static int *next_entry;
108 static int32 *start_of_list;
110 /* ------------------------------------------------------------------------- */
111 /* Initialisation. */
112 /* ------------------------------------------------------------------------- */
114 static void init_symbol_banks(void)
115 { int i;
116 for (i=0; i<HASH_TAB_SIZE; i++) start_of_list[i] = -1;
119 /* ------------------------------------------------------------------------- */
120 /* The hash coding we use is quite standard; the variable hashcode is */
121 /* expected to overflow a good deal. (The aim is to produce a number */
122 /* so that similar names do not produce the same number.) Note that */
123 /* 30011 is prime. It doesn't matter if the unsigned int to int cast */
124 /* behaves differently on different ports. */
125 /* ------------------------------------------------------------------------- */
127 int case_conversion_grid[128];
129 static void make_case_conversion_grid(void)
131 /* Assumes that A to Z are contiguous in the host OS character set:
132 true for ASCII but not for EBCDIC, for instance. */
134 int i;
135 for (i=0; i<128; i++) case_conversion_grid[i] = i;
136 for (i=0; i<26; i++) case_conversion_grid['A'+i]='a'+i;
139 extern int hash_code_from_string(char *p)
140 { uint32 hashcode=0;
141 for (; *p; p++) hashcode=hashcode*30011 + case_conversion_grid[(uchar)*p];
142 return (int) (hashcode % HASH_TAB_SIZE);
145 extern int strcmpcis(char *p, char *q)
147 /* Case insensitive strcmp */
149 int i, j, pc, qc;
150 for (i=0;p[i] != 0;i++)
151 { pc = p[i]; if (isupper(pc)) pc = tolower(pc);
152 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
153 j = pc - qc;
154 if (j!=0) return j;
156 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
157 return -qc;
160 /* ------------------------------------------------------------------------- */
161 /* Symbol finding, creating, and removing. */
162 /* ------------------------------------------------------------------------- */
164 extern int symbol_index(char *p, int hashcode)
166 /* Return the index in the symbs/svals/sflags/stypes/... arrays of symbol
167 "p", creating a new symbol with that name if it isn't already there.
169 New symbols are created with flag UNKNOWN_SFLAG, value 0x100
170 (a 2-byte quantity in Z-machine terms) and type CONSTANT_T.
172 The string "p" is undamaged. */
174 int32 new_entry, this, last; char *r;
176 if (hashcode == -1) hashcode = hash_code_from_string(p);
178 this = start_of_list[hashcode]; last = -1;
181 { if (this == -1) break;
183 r = (char *)symbs[this];
184 new_entry = strcmpcis(r, p);
185 if (new_entry == 0)
187 if (track_unused_routines)
188 df_note_function_symbol(this);
189 return this;
191 if (new_entry > 0) break;
193 last = this;
194 this = next_entry[this];
195 } while (this != -1);
197 if (no_symbols >= MAX_SYMBOLS)
198 memoryerror("MAX_SYMBOLS", MAX_SYMBOLS);
200 if (last == -1)
201 { next_entry[no_symbols]=start_of_list[hashcode];
202 start_of_list[hashcode]=no_symbols;
204 else
205 { next_entry[no_symbols]=this;
206 next_entry[last]=no_symbols;
209 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
210 { symbols_free_space
211 = my_malloc(SYMBOLS_CHUNK_SIZE, "symbol names chunk");
212 symbols_ceiling = symbols_free_space + SYMBOLS_CHUNK_SIZE;
213 /* If we've passed MAX_SYMBOL_CHUNKS chunks, we print an error
214 message telling the user to increase SYMBOLS_CHUNK_SIZE.
215 That is the correct cure, even though the error comes out
216 worded inaccurately. */
217 if (no_symbol_name_space_chunks >= MAX_SYMBOL_CHUNKS)
218 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
219 symbol_name_space_chunks[no_symbol_name_space_chunks++]
220 = (char *) symbols_free_space;
221 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
222 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
225 strcpy((char *) symbols_free_space, p);
226 symbs[no_symbols] = (int32 *) symbols_free_space;
227 symbols_free_space += strlen((char *)symbols_free_space) + 1;
229 svals[no_symbols] = 0x100; /* ###-wrong? Would this fix the
230 unbound-symbol-causes-asm-error? */
231 sflags[no_symbols] = UNKNOWN_SFLAG;
232 stypes[no_symbols] = CONSTANT_T;
233 slines[no_symbols] = ErrorReport.line_number
234 + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
235 if (debugfile_switch)
236 { nullify_debug_file_position
237 (&symbol_debug_backpatch_positions[no_symbols]);
238 nullify_debug_file_position
239 (&replacement_debug_backpatch_positions[no_symbols]);
242 if (track_unused_routines)
243 df_note_function_symbol(no_symbols);
244 return(no_symbols++);
247 extern void end_symbol_scope(int k)
249 /* Remove the given symbol from the hash table, making it
250 invisible to symbol_index. This is used by the Undef directive.
251 If the symbol is not found, this silently does nothing.
254 int j;
255 j = hash_code_from_string((char *) symbs[k]);
256 if (start_of_list[j] == k)
257 { start_of_list[j] = next_entry[k];
258 return;
260 j = start_of_list[j];
261 while (j != -1)
263 if (next_entry[j] == k)
264 { next_entry[j] = next_entry[k];
265 return;
267 j = next_entry[j];
271 /* ------------------------------------------------------------------------- */
272 /* Printing diagnostics */
273 /* ------------------------------------------------------------------------- */
275 extern char *typename(int type)
276 { switch(type)
278 /* These are the possible symbol types. Note that local variables
279 do not reside in the symbol table (for scope and efficiency
280 reasons) and actions have their own name-space (via routine
281 names with "Sub" appended). */
283 case ROUTINE_T: return("Routine");
284 case LABEL_T: return("Label");
285 case GLOBAL_VARIABLE_T: return("Global variable");
286 case ARRAY_T: return("Array");
287 case CONSTANT_T: return("Defined constant");
288 case ATTRIBUTE_T: return("Attribute");
289 case PROPERTY_T: return("Property");
290 case INDIVIDUAL_PROPERTY_T: return("Individual property");
291 case OBJECT_T: return("Object");
292 case CLASS_T: return("Class");
293 case FAKE_ACTION_T: return("Fake action");
295 default: return("(Unknown type)");
299 static void describe_flags(int flags)
300 { if (flags & UNKNOWN_SFLAG) printf("(?) ");
301 if (flags & USED_SFLAG) printf("(used) ");
302 if (flags & REPLACE_SFLAG) printf("(Replaced) ");
303 if (flags & DEFCON_SFLAG) printf("(Defaulted) ");
304 if (flags & STUB_SFLAG) printf("(Stubbed) ");
305 if (flags & CHANGE_SFLAG) printf("(value will change) ");
306 if (flags & IMPORT_SFLAG) printf("(Imported) ");
307 if (flags & EXPORT_SFLAG) printf("(Exported) ");
308 if (flags & SYSTEM_SFLAG) printf("(System) ");
309 if (flags & INSF_SFLAG) printf("(created in sys file) ");
310 if (flags & UERROR_SFLAG) printf("('Unknown' error issued) ");
311 if (flags & ALIASED_SFLAG) printf("(aliased) ");
312 if (flags & ACTION_SFLAG) printf("(Action name) ");
313 if (flags & REDEFINABLE_SFLAG) printf("(Redefinable) ");
316 extern void describe_symbol(int k)
317 { printf("%4d %-16s %2d:%04d %04x %s ",
318 k, (char *) (symbs[k]),
319 (int)(slines[k]/FILE_LINE_SCALE_FACTOR),
320 (int)(slines[k]%FILE_LINE_SCALE_FACTOR),
321 svals[k], typename(stypes[k]));
322 describe_flags(sflags[k]);
325 extern void list_symbols(int level)
326 { int k;
327 for (k=0; k<no_symbols; k++)
328 { if ((level==2) ||
329 ((sflags[k] & (SYSTEM_SFLAG + UNKNOWN_SFLAG + INSF_SFLAG)) == 0))
330 { describe_symbol(k); printf("\n");
335 extern void issue_unused_warnings(void)
336 { int32 i;
338 if (module_switch) return;
340 /* Update any ad-hoc variables that might help the library */
341 if (glulx_mode)
342 { global_initial_value[10]=statusline_flag;
344 /* Now back to mark anything necessary as used */
346 i = symbol_index("Main", -1);
347 if (!(sflags[i] & UNKNOWN_SFLAG)) sflags[i] |= USED_SFLAG;
349 for (i=0;i<no_symbols;i++)
350 { if (((sflags[i]
351 & (SYSTEM_SFLAG + UNKNOWN_SFLAG + EXPORT_SFLAG
352 + INSF_SFLAG + USED_SFLAG + REPLACE_SFLAG)) == 0)
353 && (stypes[i] != OBJECT_T))
354 dbnu_warning(typename(stypes[i]), (char *) symbs[i], slines[i]);
358 /* ------------------------------------------------------------------------- */
359 /* These are arrays used only during story file (never module) creation, */
360 /* and not allocated until then. */
362 int32 *individual_name_strings; /* Packed addresses of Z-encoded
363 strings of the names of the
364 properties: this is an array
365 indexed by the property ID */
366 int32 *action_name_strings; /* Ditto for actions */
367 int32 *attribute_name_strings; /* Ditto for attributes */
368 int32 *array_name_strings; /* Ditto for arrays */
370 extern void write_the_identifier_names(void)
371 { int i, j, k, t, null_value; char idname_string[256];
372 static char unknown_attribute[20] = "<unknown attribute>";
374 for (i=0; i<no_individual_properties; i++)
375 individual_name_strings[i] = 0;
377 if (module_switch) return;
379 veneer_mode = TRUE;
381 null_value = compile_string(unknown_attribute, FALSE, FALSE);
382 for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
384 for (i=0; i<no_symbols; i++)
385 { t=stypes[i];
386 if ((t == INDIVIDUAL_PROPERTY_T) || (t == PROPERTY_T))
387 { if (sflags[i] & ALIASED_SFLAG)
388 { if (individual_name_strings[svals[i]] == 0)
389 { sprintf(idname_string, "%s", (char *) symbs[i]);
391 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
392 { if ((stypes[j] == stypes[i])
393 && (svals[j] == svals[i]))
394 { sprintf(idname_string+strlen(idname_string),
395 "/%s", (char *) symbs[j]);
396 k++;
400 individual_name_strings[svals[i]]
401 = compile_string(idname_string, FALSE, FALSE);
404 else
405 { sprintf(idname_string, "%s", (char *) symbs[i]);
407 individual_name_strings[svals[i]]
408 = compile_string(idname_string, FALSE, FALSE);
411 if (t == ATTRIBUTE_T)
412 { if (sflags[i] & ALIASED_SFLAG)
413 { if (attribute_name_strings[svals[i]] == null_value)
414 { sprintf(idname_string, "%s", (char *) symbs[i]);
416 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
417 { if ((stypes[j] == stypes[i])
418 && (svals[j] == svals[i]))
419 { sprintf(idname_string+strlen(idname_string),
420 "/%s", (char *) symbs[j]);
421 k++;
425 attribute_name_strings[svals[i]]
426 = compile_string(idname_string, FALSE, FALSE);
429 else
430 { sprintf(idname_string, "%s", (char *) symbs[i]);
432 attribute_name_strings[svals[i]]
433 = compile_string(idname_string, FALSE, FALSE);
436 if (sflags[i] & ACTION_SFLAG)
437 { sprintf(idname_string, "%s", (char *) symbs[i]);
438 idname_string[strlen(idname_string)-3] = 0;
440 if (debugfile_switch)
441 { debug_file_printf("<action>");
442 debug_file_printf
443 ("<identifier>##%s</identifier>", idname_string);
444 debug_file_printf("<value>%d</value>", svals[i]);
445 debug_file_printf("</action>");
448 action_name_strings[svals[i]]
449 = compile_string(idname_string, FALSE, FALSE);
453 for (i=0; i<no_symbols; i++)
454 { if (stypes[i] == FAKE_ACTION_T)
455 { sprintf(idname_string, "%s", (char *) symbs[i]);
456 idname_string[strlen(idname_string)-3] = 0;
458 action_name_strings[svals[i]
459 - ((grammar_version_number==1)?256:4096) + no_actions]
460 = compile_string(idname_string, FALSE, FALSE);
464 for (j=0; j<no_arrays; j++)
465 { i = array_symbols[j];
466 sprintf(idname_string, "%s", (char *) symbs[i]);
468 array_name_strings[j]
469 = compile_string(idname_string, FALSE, FALSE);
471 if (define_INFIX_switch)
472 { for (i=0; i<no_symbols; i++)
473 { if (stypes[i] == GLOBAL_VARIABLE_T)
474 { sprintf(idname_string, "%s", (char *) symbs[i]);
475 array_name_strings[no_arrays + svals[i] -16]
476 = compile_string(idname_string, FALSE, FALSE);
480 for (i=0; i<no_named_routines; i++)
481 { sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
482 array_name_strings[no_arrays + no_globals + i]
483 = compile_string(idname_string, FALSE, FALSE);
486 for (i=0, no_named_constants=0; i<no_symbols; i++)
487 { if (((stypes[i] == OBJECT_T) || (stypes[i] == CLASS_T)
488 || (stypes[i] == CONSTANT_T))
489 && ((sflags[i] & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
490 { sprintf(idname_string, "%s", (char *) symbs[i]);
491 array_name_strings[no_arrays + no_globals + no_named_routines
492 + no_named_constants++]
493 = compile_string(idname_string, FALSE, FALSE);
498 veneer_mode = FALSE;
500 /* ------------------------------------------------------------------------- */
501 /* Creating symbols */
502 /* ------------------------------------------------------------------------- */
504 static void assign_symbol_base(int index, int32 value, int type)
505 { svals[index] = value;
506 stypes[index] = type;
507 if (sflags[index] & UNKNOWN_SFLAG)
508 { sflags[index] &= (~UNKNOWN_SFLAG);
509 if (is_systemfile()) sflags[index] |= INSF_SFLAG;
510 slines[index] = ErrorReport.line_number
511 + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
515 extern void assign_symbol(int index, int32 value, int type)
517 if (!glulx_mode) {
518 assign_symbol_base(index, value, type);
520 else {
521 smarks[index] = 0;
522 assign_symbol_base(index, value, type);
526 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
528 if (!glulx_mode) {
529 assign_symbol_base(index, (int32)marker*0x10000 + (value % 0x10000),
530 type);
532 else {
533 smarks[index] = marker;
534 assign_symbol_base(index, value, type);
538 static void emit_debug_information_for_predefined_symbol
539 (char *name, int32 symbol, int32 value, int type)
540 { if (debugfile_switch)
541 { switch (type)
542 { case CONSTANT_T:
543 debug_file_printf("<constant>");
544 debug_file_printf("<identifier>%s</identifier>", name);
545 write_debug_symbol_optional_backpatch(symbol);
546 debug_file_printf("</constant>");
547 break;
548 case GLOBAL_VARIABLE_T:
549 debug_file_printf("<global-variable>");
550 debug_file_printf("<identifier>%s</identifier>", name);
551 debug_file_printf("<address>");
552 write_debug_global_backpatch(value);
553 debug_file_printf("</address>");
554 debug_file_printf("</global-variable>");
555 break;
556 case OBJECT_T:
557 if (value)
558 { compiler_error("Non-nothing object predefined");
560 debug_file_printf("<object>");
561 debug_file_printf("<identifier>%s</identifier>", name);
562 debug_file_printf("<value>0</value>");
563 debug_file_printf("</object>");
564 break;
565 case ATTRIBUTE_T:
566 debug_file_printf("<attribute>");
567 debug_file_printf("<identifier>%s</identifier>", name);
568 debug_file_printf("<value>%d</value>", value);
569 debug_file_printf("</attribute>");
570 break;
571 case PROPERTY_T:
572 case INDIVIDUAL_PROPERTY_T:
573 debug_file_printf("<property>");
574 debug_file_printf("<identifier>%s</identifier>", name);
575 debug_file_printf("<value>%d</value>", value);
576 debug_file_printf("</property>");
577 break;
578 default:
579 compiler_error
580 ("Unable to emit debug information for predefined symbol");
581 break;
586 static void create_symbol(char *p, int32 value, int type)
587 { int i = symbol_index(p, -1);
588 svals[i] = value; stypes[i] = type; slines[i] = 0;
589 sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
590 emit_debug_information_for_predefined_symbol(p, i, value, type);
593 static void create_rsymbol(char *p, int value, int type)
594 { int i = symbol_index(p, -1);
595 svals[i] = value; stypes[i] = type; slines[i] = 0;
596 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
597 emit_debug_information_for_predefined_symbol(p, i, value, type);
600 static void stockup_symbols(void)
602 if (!glulx_mode)
603 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
604 else
605 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
607 create_symbol("nothing", 0, OBJECT_T);
608 create_symbol("name", 1, PROPERTY_T);
610 create_symbol("true", 1, CONSTANT_T);
611 create_symbol("false", 0, CONSTANT_T);
613 /* Glulx defaults to GV2; Z-code to GV1 */
614 if (!glulx_mode)
615 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
616 else
617 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
618 grammar_version_symbol = symbol_index("Grammar__Version", -1);
620 if (module_switch)
621 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
623 if (runtime_error_checking_switch)
624 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
626 if (define_DEBUG_switch)
627 create_rsymbol("DEBUG", 0, CONSTANT_T);
629 if (define_USE_MODULES_switch)
630 create_rsymbol("USE_MODULES",0, CONSTANT_T);
632 if (define_INFIX_switch)
633 { create_rsymbol("INFIX", 0, CONSTANT_T);
634 create_symbol("infix__watching", 0, ATTRIBUTE_T);
637 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
638 create_symbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
639 if (!glulx_mode) {
640 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
641 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
643 else {
644 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
645 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
646 if (DICT_CHAR_SIZE != 1)
647 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
648 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
649 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
650 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
651 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
652 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
653 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
654 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
655 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
656 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
657 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
660 if (!glulx_mode) {
661 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
662 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
663 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
664 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
665 create_symbol("self", 251, GLOBAL_VARIABLE_T);
666 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
667 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
669 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
670 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
671 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
673 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
674 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
675 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
676 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
677 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
678 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
679 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
680 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
682 else {
683 /* In Glulx, these system globals are entered in order, not down
684 from 255. */
685 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
686 GLOBAL_VARIABLE_T);
687 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
688 GLOBAL_VARIABLE_T);
689 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
690 GLOBAL_VARIABLE_T);
691 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
692 GLOBAL_VARIABLE_T);
693 create_symbol("self", MAX_LOCAL_VARIABLES+4,
694 GLOBAL_VARIABLE_T);
695 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
696 GLOBAL_VARIABLE_T);
697 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
698 GLOBAL_VARIABLE_T);
700 /* These are almost certainly meaningless, and can be removed. */
701 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
702 GLOBAL_VARIABLE_T);
703 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
704 GLOBAL_VARIABLE_T);
705 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
706 GLOBAL_VARIABLE_T);
708 /* value of statusline_flag to be written later */
709 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
710 GLOBAL_VARIABLE_T);
712 /* These are created in order, but not necessarily at a fixed
713 value. */
714 create_symbol("create", INDIV_PROP_START+0,
715 INDIVIDUAL_PROPERTY_T);
716 create_symbol("recreate", INDIV_PROP_START+1,
717 INDIVIDUAL_PROPERTY_T);
718 create_symbol("destroy", INDIV_PROP_START+2,
719 INDIVIDUAL_PROPERTY_T);
720 create_symbol("remaining", INDIV_PROP_START+3,
721 INDIVIDUAL_PROPERTY_T);
722 create_symbol("copy", INDIV_PROP_START+4,
723 INDIVIDUAL_PROPERTY_T);
724 create_symbol("call", INDIV_PROP_START+5,
725 INDIVIDUAL_PROPERTY_T);
726 create_symbol("print", INDIV_PROP_START+6,
727 INDIVIDUAL_PROPERTY_T);
728 create_symbol("print_to_array",INDIV_PROP_START+7,
729 INDIVIDUAL_PROPERTY_T);
731 /* Floating-point constants. Note that FLOAT_NINFINITY is not
732 -FLOAT_INFINITY, because float negation doesn't work that
733 way. Also note that FLOAT_NAN is just one of many possible
734 "not-a-number" values. */
735 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
736 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
737 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
741 /* ------------------------------------------------------------------------- */
742 /* The symbol replacement table. This is needed only for the */
743 /* "Replace X Y" directive. */
744 /* ------------------------------------------------------------------------- */
746 extern void add_symbol_replacement_mapping(int original, int renamed)
748 int ix;
750 if (original == renamed) {
751 error_named("A routine cannot be 'Replace'd to itself:", (char *)symbs[original]);
752 return;
755 if (symbol_replacements_count == symbol_replacements_size) {
756 int oldsize = symbol_replacements_size;
757 if (symbol_replacements_size == 0)
758 symbol_replacements_size = 4;
759 else
760 symbol_replacements_size *= 2;
761 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
762 symbol_replacements_size, "symbol replacement table");
765 /* If the original form is already in our table, report an error.
766 Same goes if the replaced form is already in the table as an
767 original. (Other collision cases have already been
768 detected.) */
770 for (ix=0; ix<symbol_replacements_count; ix++) {
771 if (original == symbol_replacements[ix].original_symbol) {
772 error_named("A routine cannot be 'Replace'd to more than one new name:", (char *)symbs[original]);
774 if (renamed == symbol_replacements[ix].original_symbol) {
775 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", (char *)symbs[original]);
779 symbol_replacements[symbol_replacements_count].original_symbol = original;
780 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
781 symbol_replacements_count++;
784 extern int find_symbol_replacement(int *value)
786 int changed = FALSE;
787 int ix;
789 if (!symbol_replacements)
790 return FALSE;
792 for (ix=0; ix<symbol_replacements_count; ix++) {
793 if (*value == symbol_replacements[ix].original_symbol) {
794 *value = symbol_replacements[ix].renamed_symbol;
795 changed = TRUE;
799 return changed;
802 /* ------------------------------------------------------------------------- */
803 /* The dead-function removal optimization. */
804 /* ------------------------------------------------------------------------- */
806 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
807 OMIT_UNUSED_ROUTINES is nonzero */
808 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
809 static int df_tables_closed; /* set at end of compiler pass */
811 typedef struct df_function_struct df_function_t;
812 typedef struct df_reference_struct df_reference_t;
814 struct df_function_struct {
815 char *name; /* borrowed reference, generally to the symbs[] table */
816 int32 source_line; /* copied from routine_starts_line */
817 int sysfile; /* does this occur in a system file? */
818 uint32 address; /* function offset in zcode_area (not the final address) */
819 uint32 newaddress; /* function offset after stripping */
820 uint32 length;
821 int usage;
822 df_reference_t *refs; /* chain of references made *from* this function */
823 int processed;
825 df_function_t *funcnext; /* in forward functions order */
826 df_function_t *todonext; /* in the todo chain */
827 df_function_t *next; /* in the hash table */
830 struct df_reference_struct {
831 uint32 address; /* function offset in zcode_area (not the final address) */
832 int symbol; /* index in symbols array */
834 df_reference_t *refsnext; /* in the function's refs chain */
835 df_reference_t *next; /* in the hash table */
838 /* Bitmask flags for how functions are used: */
839 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
840 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
841 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
842 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
844 #define DF_FUNCTION_HASH_BUCKETS (1023)
846 /* Table of all compiled functions. (Only created if track_unused_routines
847 is set.) */
848 static df_function_t **df_functions;
849 /* List of all compiled functions, in address order. The first entry
850 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
851 static df_function_t *df_functions_head;
852 static df_function_t *df_functions_tail;
853 /* Used during output_file(), to track how far the code-area output has
854 gotten. */
855 static df_function_t *df_iterator;
857 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
858 #define DF_SYMBOL_HASH_BUCKETS (4095)
860 /* Map of what functions reference what other functions. (Only created if
861 track_unused_routines is set.) */
862 static df_reference_t **df_symbol_map;
864 /* Globals used while a function is being compiled. When a function
865 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
866 and df_current_function will refer to the global namespace record. */
867 static df_function_t *df_current_function;
868 static char *df_current_function_name;
869 static uint32 df_current_function_addr;
871 /* Size totals for compiled code. These are only meaningful if
872 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
873 these values will be set, but the "after" value will not affect the
874 final game file.) */
875 uint32 df_total_size_before_stripping;
876 uint32 df_total_size_after_stripping;
878 /* When we begin compiling a function, call this to note that fact.
879 Any symbol referenced from now on will be associated with the function.
881 extern void df_note_function_start(char *name, uint32 address,
882 int embedded_flag, int32 source_line)
884 df_function_t *func;
885 int bucket;
887 if (df_tables_closed)
888 error("Internal error in stripping: Tried to start a new function after tables were closed.");
890 /* We retain the name only for debugging output. Note that embedded
891 functions all show up as "<embedded>" -- their "obj.prop" name
892 never gets stored in permanent memory. */
893 df_current_function_name = name;
894 df_current_function_addr = address;
896 func = my_malloc(sizeof(df_function_t), "df function entry");
897 memset(func, 0, sizeof(df_function_t));
898 func->name = name;
899 func->address = address;
900 func->source_line = source_line;
901 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
902 /* An embedded function is stored in an object property, so we
903 consider it to be used a priori. */
904 if (embedded_flag)
905 func->usage |= DF_USAGE_EMBEDDED;
907 if (!df_functions_head) {
908 df_functions_head = func;
909 df_functions_tail = func;
911 else {
912 df_functions_tail->funcnext = func;
913 df_functions_tail = func;
916 bucket = address % DF_FUNCTION_HASH_BUCKETS;
917 func->next = df_functions[bucket];
918 df_functions[bucket] = func;
920 df_current_function = func;
923 /* When we're done compiling a function, call this. Any symbol referenced
924 from now on will be associated with the global namespace.
926 extern void df_note_function_end(uint32 endaddress)
928 df_current_function->length = endaddress - df_current_function->address;
930 df_current_function_name = NULL;
931 df_current_function_addr = DF_NOT_IN_FUNCTION;
932 df_current_function = df_functions_head; /* the global namespace */
935 /* Find the function record for a given address. (Addresses are offsets
936 in zcode_area.)
938 static df_function_t *df_function_for_address(uint32 address)
940 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
941 df_function_t *func;
942 for (func = df_functions[bucket]; func; func = func->next) {
943 if (func->address == address)
944 return func;
946 return NULL;
949 /* Whenever a function is referenced, we call this to note who called it.
951 extern void df_note_function_symbol(int symbol)
953 int bucket, symtype;
954 df_reference_t *ent;
956 /* If the compiler pass is over, looking up symbols does not create
957 a global reference. */
958 if (df_tables_closed)
959 return;
960 /* In certain cases during parsing, looking up symbols does not
961 create a global reference. (For example, when reading the name
962 of a function being defined.) */
963 if (df_dont_note_global_symbols)
964 return;
966 /* We are only interested in functions, or forward-declared symbols
967 that might turn out to be functions. */
968 symtype = stypes[symbol];
969 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
970 return;
971 if (symtype == CONSTANT_T && !(sflags[symbol] & UNKNOWN_SFLAG))
972 return;
974 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
975 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
976 if (ent->address == df_current_function_addr && ent->symbol == symbol)
977 return;
980 /* Create a new reference entry in df_symbol_map. */
981 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
982 ent->address = df_current_function_addr;
983 ent->symbol = symbol;
984 ent->next = df_symbol_map[bucket];
985 df_symbol_map[bucket] = ent;
987 /* Add the reference to the function's entry as well. */
988 /* The current function is the most recently added, so it will be
989 at the top of its bucket. That makes this call fast. Unless
990 we're in global scope, in which case it might be slower.
991 (I suppose we could cache the df_function_t pointer of the
992 current function, to speed things up.) */
993 if (!df_current_function || df_current_function_addr != df_current_function->address)
994 compiler_error("DF: df_current_function does not match current address.");
995 ent->refsnext = df_current_function->refs;
996 df_current_function->refs = ent;
999 /* This does the hard work of figuring out what functions are truly dead.
1000 It's called near the end of run_pass() in inform.c.
1002 extern void locate_dead_functions(void)
1004 df_function_t *func, *tofunc;
1005 df_reference_t *ent;
1006 int ix;
1008 if (!track_unused_routines)
1009 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1011 df_tables_closed = TRUE;
1012 df_current_function = NULL;
1014 /* Note that Main__ was tagged as global implicitly during
1015 compile_initial_routine(). Main was tagged during
1016 issue_unused_warnings(). But for the sake of thoroughness,
1017 we'll mark them specially. */
1019 ix = symbol_index("Main__", -1);
1020 if (stypes[ix] == ROUTINE_T) {
1021 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1022 tofunc = df_function_for_address(addr);
1023 if (tofunc)
1024 tofunc->usage |= DF_USAGE_MAIN;
1026 ix = symbol_index("Main", -1);
1027 if (stypes[ix] == ROUTINE_T) {
1028 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1029 tofunc = df_function_for_address(addr);
1030 if (tofunc)
1031 tofunc->usage |= DF_USAGE_MAIN;
1034 /* Go through all the functions referenced at the global level;
1035 mark them as used. */
1037 func = df_functions_head;
1038 if (!func || func->address != DF_NOT_IN_FUNCTION)
1039 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1041 for (ent = func->refs; ent; ent=ent->refsnext) {
1042 uint32 addr;
1043 int symbol = ent->symbol;
1044 if (stypes[symbol] != ROUTINE_T)
1045 continue;
1046 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1047 tofunc = df_function_for_address(addr);
1048 if (!tofunc) {
1049 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1050 continue;
1052 /* A function may be marked here more than once. That's fine. */
1053 tofunc->usage |= DF_USAGE_GLOBAL;
1056 /* Perform a breadth-first search through functions, starting with
1057 the ones that are known to be used at the top level. */
1059 df_function_t *todo, *todotail;
1060 df_function_t *func;
1061 todo = NULL;
1062 todotail = NULL;
1064 for (func = df_functions_head; func; func = func->funcnext) {
1065 if (func->address == DF_NOT_IN_FUNCTION)
1066 continue;
1067 if (func->usage == 0)
1068 continue;
1069 if (!todo) {
1070 todo = func;
1071 todotail = func;
1073 else {
1074 todotail->todonext = func;
1075 todotail = func;
1079 /* todo is a linked list of functions which are known to be
1080 used. If a function's usage field is nonzero, it must be
1081 either be on the todo list or have come off already (in
1082 which case processed will be set). */
1084 while (todo) {
1085 /* Pop the next function. */
1086 func = todo;
1087 todo = todo->todonext;
1088 if (!todo)
1089 todotail = NULL;
1091 if (func->processed)
1092 error_named("Internal error in stripping: function has been processed twice:", func->name);
1094 /* Go through the function's symbol references. Any
1095 reference to a routine, push it into the todo list (if
1096 it isn't there already). */
1098 for (ent = func->refs; ent; ent=ent->refsnext) {
1099 uint32 addr;
1100 int symbol = ent->symbol;
1101 if (stypes[symbol] != ROUTINE_T)
1102 continue;
1103 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1104 tofunc = df_function_for_address(addr);
1105 if (!tofunc) {
1106 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1107 continue;
1109 if (tofunc->usage)
1110 continue;
1112 /* Not yet known to be used. Add it to the todo list. */
1113 tofunc->usage |= DF_USAGE_FUNCTION;
1114 if (!todo) {
1115 todo = tofunc;
1116 todotail = tofunc;
1118 else {
1119 todotail->todonext = tofunc;
1120 todotail = tofunc;
1124 func->processed = TRUE;
1128 /* Go through all functions; figure out how much space is consumed,
1129 with and without useless functions. */
1132 df_function_t *func;
1134 df_total_size_before_stripping = 0;
1135 df_total_size_after_stripping = 0;
1137 for (func = df_functions_head; func; func = func->funcnext) {
1138 if (func->address == DF_NOT_IN_FUNCTION)
1139 continue;
1141 if (func->address != df_total_size_before_stripping)
1142 compiler_error("DF: Address gap in function list");
1144 df_total_size_before_stripping += func->length;
1145 if (func->usage) {
1146 func->newaddress = df_total_size_after_stripping;
1147 df_total_size_after_stripping += func->length;
1150 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1151 compiler_error("DF: New function address is not aligned");
1153 if (WARN_UNUSED_ROUTINES && !func->usage) {
1154 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1155 uncalled_routine_warning("Routine", func->name, func->source_line);
1160 /* df_measure_hash_table_usage(); */
1163 extern uint32 df_stripped_address_for_address(uint32 addr)
1165 df_function_t *func;
1167 if (!track_unused_routines)
1168 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1170 if (!glulx_mode)
1171 func = df_function_for_address(addr*scale_factor);
1172 else
1173 func = df_function_for_address(addr);
1175 if (!func) {
1176 compiler_error("DF: Unable to find function while backpatching");
1177 return 0;
1179 if (!func->usage)
1180 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1182 if (!glulx_mode)
1183 return func->newaddress / scale_factor;
1184 else
1185 return func->newaddress;
1188 /* The output_file() routines in files.c have to run down the list of
1189 functions, deciding who is in and who is out. But I don't want to
1190 export the df_function_t list structure. Instead, I provide this
1191 silly iterator pair. Set it up with df_prepare_function_iterate();
1192 then repeatedly call df_next_function_iterate().
1195 extern void df_prepare_function_iterate(void)
1197 df_iterator = df_functions_head;
1198 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1199 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1200 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1201 compiler_error("DF: First function entry is not second in the chain.");
1204 /* This returns the end of the next function, and whether the next function
1205 is used (live).
1207 extern uint32 df_next_function_iterate(int *funcused)
1209 if (df_iterator)
1210 df_iterator = df_iterator->funcnext;
1211 if (!df_iterator) {
1212 *funcused = TRUE;
1213 return df_total_size_before_stripping+1;
1215 *funcused = (df_iterator->usage != 0);
1216 return df_iterator->address + df_iterator->length;
1219 /* ========================================================================= */
1220 /* Data structure management routines */
1221 /* ------------------------------------------------------------------------- */
1223 extern void init_symbols_vars(void)
1225 symbs = NULL;
1226 svals = NULL;
1227 smarks = NULL;
1228 stypes = NULL;
1229 sflags = NULL;
1230 next_entry = NULL;
1231 start_of_list = NULL;
1233 symbol_name_space_chunks = NULL;
1234 no_symbol_name_space_chunks = 0;
1235 symbols_free_space=NULL;
1236 symbols_ceiling=symbols_free_space;
1238 no_symbols = 0;
1240 symbol_replacements = NULL;
1241 symbol_replacements_count = 0;
1242 symbol_replacements_size = 0;
1244 make_case_conversion_grid();
1246 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1247 df_tables_closed = FALSE;
1248 df_symbol_map = NULL;
1249 df_functions = NULL;
1250 df_functions_head = NULL;
1251 df_functions_tail = NULL;
1252 df_current_function = NULL;
1255 extern void symbols_begin_pass(void)
1257 df_total_size_before_stripping = 0;
1258 df_total_size_after_stripping = 0;
1259 df_dont_note_global_symbols = FALSE;
1260 df_iterator = NULL;
1263 extern void symbols_allocate_arrays(void)
1265 symbs = my_calloc(sizeof(char *), MAX_SYMBOLS, "symbols");
1266 svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
1267 if (glulx_mode)
1268 smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
1269 slines = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol lines");
1270 stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
1271 sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
1272 if (debugfile_switch)
1273 { symbol_debug_backpatch_positions =
1274 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1275 "symbol debug information backpatch positions");
1276 replacement_debug_backpatch_positions =
1277 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1278 "replacement debug information backpatch positions");
1280 next_entry = my_calloc(sizeof(int), MAX_SYMBOLS,
1281 "symbol linked-list forward links");
1282 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1283 "hash code list beginnings");
1285 symbol_name_space_chunks
1286 = my_calloc(sizeof(char *), MAX_SYMBOL_CHUNKS, "symbol names chunk addresses");
1288 if (track_unused_routines) {
1289 df_tables_closed = FALSE;
1291 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1292 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1294 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1295 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1296 df_functions_head = NULL;
1297 df_functions_tail = NULL;
1299 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, -1);
1300 df_note_function_end(DF_NOT_IN_FUNCTION);
1301 /* Now df_current_function is df_functions_head. */
1304 init_symbol_banks();
1305 stockup_symbols();
1307 /* Allocated as needed */
1308 symbol_replacements = NULL;
1310 /* Allocated during story file construction, not now */
1311 individual_name_strings = NULL;
1312 attribute_name_strings = NULL;
1313 action_name_strings = NULL;
1314 array_name_strings = NULL;
1317 extern void symbols_free_arrays(void)
1318 { int i;
1320 for (i=0; i<no_symbol_name_space_chunks; i++)
1321 my_free(&(symbol_name_space_chunks[i]),
1322 "symbol names chunk");
1324 my_free(&symbol_name_space_chunks, "symbol names chunk addresses");
1326 my_free(&symbs, "symbols");
1327 my_free(&svals, "symbol values");
1328 my_free(&smarks, "symbol markers");
1329 my_free(&slines, "symbol lines");
1330 my_free(&stypes, "symbol types");
1331 my_free(&sflags, "symbol flags");
1332 if (debugfile_switch)
1333 { my_free
1334 (&symbol_debug_backpatch_positions,
1335 "symbol debug information backpatch positions");
1336 my_free
1337 (&replacement_debug_backpatch_positions,
1338 "replacement debug information backpatch positions");
1340 my_free(&next_entry, "symbol linked-list forward links");
1341 my_free(&start_of_list, "hash code list beginnings");
1343 if (symbol_replacements)
1344 my_free(&symbol_replacements, "symbol replacement table");
1346 if (df_symbol_map) {
1347 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1348 df_reference_t *ent = df_symbol_map[i];
1349 while (ent) {
1350 df_reference_t *next = ent->next;
1351 my_free(&ent, "df symbol map entry");
1352 ent = next;
1355 my_free(&df_symbol_map, "df symbol-map hash table");
1357 if (df_functions) {
1358 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1359 df_function_t *func = df_functions[i];
1360 while (func) {
1361 df_function_t *next = func->next;
1362 my_free(&func, "df function entry");
1363 func = next;
1366 my_free(&df_functions, "df function hash table");
1367 df_functions_head = NULL;
1368 df_functions_tail = NULL;
1371 if (individual_name_strings != NULL)
1372 my_free(&individual_name_strings, "property name strings");
1373 if (action_name_strings != NULL)
1374 my_free(&action_name_strings, "action name strings");
1375 if (attribute_name_strings != NULL)
1376 my_free(&attribute_name_strings, "attribute name strings");
1377 if (array_name_strings != NULL)
1378 my_free(&array_name_strings, "array name strings");
1381 /* ========================================================================= */