1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
4 /* Copyright (c) Graham Nelson 1993 - 2016 */
6 /* This file is part of Inform. */
8 /* Inform is free software: you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation, either version 3 of the License, or */
11 /* (at your option) any later version. */
13 /* Inform is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with Inform. If not, see https://gnu.org/licenses/ */
21 /* ------------------------------------------------------------------------- */
25 /* ------------------------------------------------------------------------- */
26 /* This section of Inform is a service detached from the rest. */
27 /* Only two variables are accessible from the outside: */
28 /* ------------------------------------------------------------------------- */
30 int no_symbols; /* Total number of symbols defined */
31 int no_named_constants; /* Copied into story file */
33 /* ------------------------------------------------------------------------- */
34 /* Plus six arrays. Each symbol has its own index n (an int32) and */
36 /* svals[n] is its value (must be 32 bits wide, i.e. an int32, tho' */
37 /* it is used to hold an unsigned 16 bit Z-machine value) */
38 /* sflags[n] holds flags (see "header.h" for a list) */
39 /* stypes[n] is the "type", distinguishing between the data type of */
40 /* different kinds of constants/variables. */
41 /* (See the "typename()" below.) */
42 /* symbs[n] (needs to be cast to (char *) to be used) is the name */
43 /* of the symbol, in the same case form as when created. */
44 /* slines[n] is the source line on which the symbol value was first */
46 /* symbol_debug_backpatch_positions[n] */
47 /* is a file position in the debug information file where */
48 /* the symbol's value should be written after backpatching, */
49 /* or else the null position if the value was known and */
50 /* written beforehand */
51 /* replacement_debug_backpatch_positions[n] */
52 /* is a file position in the debug information file where */
53 /* the symbol's name can be erased if it is replaced, or */
54 /* else null if the name will never need to be replaced */
56 /* Comparison is case insensitive. */
57 /* Note that local variable names are not entered into the symbols table, */
58 /* as their numbers and scope are too limited for this to be efficient. */
59 /* ------------------------------------------------------------------------- */
60 /* Caveat editor: some array types are set up to work even on machines */
61 /* where sizeof(int32 *) differs from, e.g., sizeof(char *): so do not */
62 /* alter the types unless you understand what is going on! */
63 /* ------------------------------------------------------------------------- */
67 int *smarks; /* Glulx-only */
71 char *stypes; /* In VAX C, insanely, "signed char" is illegal */
75 maybe_file_position *symbol_debug_backpatch_positions;
76 maybe_file_position *replacement_debug_backpatch_positions;
78 /* ------------------------------------------------------------------------- */
79 /* Memory to hold the text of symbol names: note that this memory is */
80 /* allocated as needed in chunks of size SYMBOLS_CHUNK_SIZE. */
81 /* ------------------------------------------------------------------------- */
83 #define MAX_SYMBOL_CHUNKS (100)
85 static uchar *symbols_free_space, /* Next byte free to hold new names */
86 *symbols_ceiling; /* Pointer to the end of the current
87 allocation of memory for names */
89 static char** symbol_name_space_chunks; /* For chunks of memory used to hold
90 the name strings of symbols */
91 static int no_symbol_name_space_chunks;
93 typedef struct value_pair_struct {
97 static value_pair_t *symbol_replacements;
98 static int symbol_replacements_count;
99 static int symbol_replacements_size; /* calloced size */
101 /* ------------------------------------------------------------------------- */
102 /* The symbols table is "hash-coded" into a disjoint union of linked */
103 /* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
104 /* that it's the last in its list) or the next in the list. */
106 /* Each list contains, in alphabetical order, all the symbols which share */
107 /* the same "hash code" (a numerical function of the text of the symbol */
108 /* name, designed with the aim that roughly equal numbers of symbols are */
109 /* given each possible hash code). The hash codes are 0 to HASH_TAB_SIZE */
110 /* (which is a memory setting) minus 1: start_of_list[h] gives the first */
111 /* symbol with hash code h, or -1 if no symbol exists with hash code h. */
113 /* Note that the running time of the symbol search algorithm is about */
115 /* O ( n^2 / HASH_TAB_SIZE ) */
117 /* (where n is the number of symbols in the program) so that it is a good */
118 /* idea to choose HASH_TAB_SIZE as large as conveniently possible. */
119 /* ------------------------------------------------------------------------- */
121 static int *next_entry;
122 static int32 *start_of_list;
124 /* ------------------------------------------------------------------------- */
125 /* Initialisation. */
126 /* ------------------------------------------------------------------------- */
128 static void init_symbol_banks(void)
130 for (i=0; i<HASH_TAB_SIZE; i++) start_of_list[i] = -1;
133 /* ------------------------------------------------------------------------- */
134 /* The hash coding we use is quite standard; the variable hashcode is */
135 /* expected to overflow a good deal. (The aim is to produce a number */
136 /* so that similar names do not produce the same number.) Note that */
137 /* 30011 is prime. It doesn't matter if the unsigned int to int cast */
138 /* behaves differently on different ports. */
139 /* ------------------------------------------------------------------------- */
141 int case_conversion_grid[128];
143 static void make_case_conversion_grid(void)
145 /* Assumes that A to Z are contiguous in the host OS character set:
146 true for ASCII but not for EBCDIC, for instance. */
149 for (i=0; i<128; i++) case_conversion_grid[i] = i;
150 for (i=0; i<26; i++) case_conversion_grid['A'+i]='a'+i;
153 extern int hash_code_from_string(char *p)
155 for (; *p; p++) hashcode=hashcode*30011 + case_conversion_grid[(uchar)*p];
156 return (int) (hashcode % HASH_TAB_SIZE);
159 extern int strcmpcis(char *p, char *q)
161 /* Case insensitive strcmp */
164 for (i=0;p[i] != 0;i++)
165 { pc = p[i]; if (isupper(pc)) pc = tolower(pc);
166 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
170 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
174 /* ------------------------------------------------------------------------- */
175 /* Symbol finding, creating, and removing. */
176 /* ------------------------------------------------------------------------- */
178 extern int symbol_index(char *p, int hashcode)
180 /* Return the index in the symbs/svals/sflags/stypes/... arrays of symbol
181 "p", creating a new symbol with that name if it isn't already there.
183 New symbols are created with flag UNKNOWN_SFLAG, value 0x100
184 (a 2-byte quantity in Z-machine terms) and type CONSTANT_T.
186 The string "p" is undamaged. */
188 int32 new_entry, this, last; char *r;
190 if (hashcode == -1) hashcode = hash_code_from_string(p);
192 this = start_of_list[hashcode]; last = -1;
195 { if (this == -1) break;
197 r = (char *)symbs[this];
198 new_entry = strcmpcis(r, p);
201 if (track_unused_routines)
202 df_note_function_symbol(this);
205 if (new_entry > 0) break;
208 this = next_entry[this];
209 } while (this != -1);
211 if (no_symbols >= MAX_SYMBOLS)
212 memoryerror("MAX_SYMBOLS", MAX_SYMBOLS);
215 { next_entry[no_symbols]=start_of_list[hashcode];
216 start_of_list[hashcode]=no_symbols;
219 { next_entry[no_symbols]=this;
220 next_entry[last]=no_symbols;
223 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
225 = my_malloc(SYMBOLS_CHUNK_SIZE, "symbol names chunk");
226 symbols_ceiling = symbols_free_space + SYMBOLS_CHUNK_SIZE;
227 /* If we've passed MAX_SYMBOL_CHUNKS chunks, we print an error
228 message telling the user to increase SYMBOLS_CHUNK_SIZE.
229 That is the correct cure, even though the error comes out
230 worded inaccurately. */
231 if (no_symbol_name_space_chunks >= MAX_SYMBOL_CHUNKS)
232 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
233 symbol_name_space_chunks[no_symbol_name_space_chunks++]
234 = (char *) symbols_free_space;
235 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
236 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
239 strcpy((char *) symbols_free_space, p);
240 symbs[no_symbols] = (int32 *) symbols_free_space;
241 symbols_free_space += strlen((char *)symbols_free_space) + 1;
243 svals[no_symbols] = 0x100; /* ###-wrong? Would this fix the
244 unbound-symbol-causes-asm-error? */
245 sflags[no_symbols] = UNKNOWN_SFLAG;
246 stypes[no_symbols] = CONSTANT_T;
247 slines[no_symbols] = ErrorReport.line_number
248 + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
249 if (debugfile_switch)
250 { nullify_debug_file_position
251 (&symbol_debug_backpatch_positions[no_symbols]);
252 nullify_debug_file_position
253 (&replacement_debug_backpatch_positions[no_symbols]);
256 if (track_unused_routines)
257 df_note_function_symbol(no_symbols);
258 return(no_symbols++);
261 extern void end_symbol_scope(int k)
263 /* Remove the given symbol from the hash table, making it
264 invisible to symbol_index. This is used by the Undef directive.
265 If the symbol is not found, this silently does nothing.
269 j = hash_code_from_string((char *) symbs[k]);
270 if (start_of_list[j] == k)
271 { start_of_list[j] = next_entry[k];
274 j = start_of_list[j];
277 if (next_entry[j] == k)
278 { next_entry[j] = next_entry[k];
285 /* ------------------------------------------------------------------------- */
286 /* Printing diagnostics */
287 /* ------------------------------------------------------------------------- */
289 extern char *typename(int type)
292 /* These are the possible symbol types. Note that local variables
293 do not reside in the symbol table (for scope and efficiency
294 reasons) and actions have their own name-space (via routine
295 names with "Sub" appended). */
297 case ROUTINE_T: return("Routine");
298 case LABEL_T: return("Label");
299 case GLOBAL_VARIABLE_T: return("Global variable");
300 case ARRAY_T: return("Array");
301 case CONSTANT_T: return("Defined constant");
302 case ATTRIBUTE_T: return("Attribute");
303 case PROPERTY_T: return("Property");
304 case INDIVIDUAL_PROPERTY_T: return("Individual property");
305 case OBJECT_T: return("Object");
306 case CLASS_T: return("Class");
307 case FAKE_ACTION_T: return("Fake action");
309 default: return("(Unknown type)");
313 static void describe_flags(int flags)
314 { if (flags & UNKNOWN_SFLAG) printf("(?) ");
315 if (flags & USED_SFLAG) printf("(used) ");
316 if (flags & REPLACE_SFLAG) printf("(Replaced) ");
317 if (flags & DEFCON_SFLAG) printf("(Defaulted) ");
318 if (flags & STUB_SFLAG) printf("(Stubbed) ");
319 if (flags & CHANGE_SFLAG) printf("(value will change) ");
320 if (flags & IMPORT_SFLAG) printf("(Imported) ");
321 if (flags & EXPORT_SFLAG) printf("(Exported) ");
322 if (flags & SYSTEM_SFLAG) printf("(System) ");
323 if (flags & INSF_SFLAG) printf("(created in sys file) ");
324 if (flags & UERROR_SFLAG) printf("('Unknown' error issued) ");
325 if (flags & ALIASED_SFLAG) printf("(aliased) ");
326 if (flags & ACTION_SFLAG) printf("(Action name) ");
327 if (flags & REDEFINABLE_SFLAG) printf("(Redefinable) ");
330 extern void describe_symbol(int k)
331 { printf("%4d %-16s %2d:%04d %04x %s ",
332 k, (char *) (symbs[k]),
333 (int)(slines[k]/FILE_LINE_SCALE_FACTOR),
334 (int)(slines[k]%FILE_LINE_SCALE_FACTOR),
335 svals[k], typename(stypes[k]));
336 describe_flags(sflags[k]);
339 extern void list_symbols(int level)
341 for (k=0; k<no_symbols; k++)
343 ((sflags[k] & (SYSTEM_SFLAG + UNKNOWN_SFLAG + INSF_SFLAG)) == 0))
344 { describe_symbol(k); printf("\n");
349 extern void issue_unused_warnings(void)
352 if (module_switch) return;
354 /* Update any ad-hoc variables that might help the library */
356 { global_initial_value[10]=statusline_flag;
358 /* Now back to mark anything necessary as used */
360 i = symbol_index("Main", -1);
361 if (!(sflags[i] & UNKNOWN_SFLAG)) sflags[i] |= USED_SFLAG;
363 for (i=0;i<no_symbols;i++)
365 & (SYSTEM_SFLAG + UNKNOWN_SFLAG + EXPORT_SFLAG
366 + INSF_SFLAG + USED_SFLAG + REPLACE_SFLAG)) == 0)
367 && (stypes[i] != OBJECT_T))
368 dbnu_warning(typename(stypes[i]), (char *) symbs[i], slines[i]);
372 /* ------------------------------------------------------------------------- */
373 /* These are arrays used only during story file (never module) creation, */
374 /* and not allocated until then. */
376 int32 *individual_name_strings; /* Packed addresses of Z-encoded
377 strings of the names of the
378 properties: this is an array
379 indexed by the property ID */
380 int32 *action_name_strings; /* Ditto for actions */
381 int32 *attribute_name_strings; /* Ditto for attributes */
382 int32 *array_name_strings; /* Ditto for arrays */
384 extern void write_the_identifier_names(void)
385 { int i, j, k, t, null_value; char idname_string[256];
386 static char unknown_attribute[20] = "<unknown attribute>";
388 for (i=0; i<no_individual_properties; i++)
389 individual_name_strings[i] = 0;
391 if (module_switch) return;
395 null_value = compile_string(unknown_attribute, FALSE, FALSE);
396 for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
398 for (i=0; i<no_symbols; i++)
400 if ((t == INDIVIDUAL_PROPERTY_T) || (t == PROPERTY_T))
401 { if (sflags[i] & ALIASED_SFLAG)
402 { if (individual_name_strings[svals[i]] == 0)
403 { sprintf(idname_string, "%s", (char *) symbs[i]);
405 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
406 { if ((stypes[j] == stypes[i])
407 && (svals[j] == svals[i]))
408 { sprintf(idname_string+strlen(idname_string),
409 "/%s", (char *) symbs[j]);
414 individual_name_strings[svals[i]]
415 = compile_string(idname_string, FALSE, FALSE);
419 { sprintf(idname_string, "%s", (char *) symbs[i]);
421 individual_name_strings[svals[i]]
422 = compile_string(idname_string, FALSE, FALSE);
425 if (t == ATTRIBUTE_T)
426 { if (sflags[i] & ALIASED_SFLAG)
427 { if (attribute_name_strings[svals[i]] == null_value)
428 { sprintf(idname_string, "%s", (char *) symbs[i]);
430 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
431 { if ((stypes[j] == stypes[i])
432 && (svals[j] == svals[i]))
433 { sprintf(idname_string+strlen(idname_string),
434 "/%s", (char *) symbs[j]);
439 attribute_name_strings[svals[i]]
440 = compile_string(idname_string, FALSE, FALSE);
444 { sprintf(idname_string, "%s", (char *) symbs[i]);
446 attribute_name_strings[svals[i]]
447 = compile_string(idname_string, FALSE, FALSE);
450 if (sflags[i] & ACTION_SFLAG)
451 { sprintf(idname_string, "%s", (char *) symbs[i]);
452 idname_string[strlen(idname_string)-3] = 0;
454 if (debugfile_switch)
455 { debug_file_printf("<action>");
457 ("<identifier>##%s</identifier>", idname_string);
458 debug_file_printf("<value>%d</value>", svals[i]);
459 debug_file_printf("</action>");
462 action_name_strings[svals[i]]
463 = compile_string(idname_string, FALSE, FALSE);
467 for (i=0; i<no_symbols; i++)
468 { if (stypes[i] == FAKE_ACTION_T)
469 { sprintf(idname_string, "%s", (char *) symbs[i]);
470 idname_string[strlen(idname_string)-3] = 0;
472 action_name_strings[svals[i]
473 - ((grammar_version_number==1)?256:4096) + no_actions]
474 = compile_string(idname_string, FALSE, FALSE);
478 for (j=0; j<no_arrays; j++)
479 { i = array_symbols[j];
480 sprintf(idname_string, "%s", (char *) symbs[i]);
482 array_name_strings[j]
483 = compile_string(idname_string, FALSE, FALSE);
485 if (define_INFIX_switch)
486 { for (i=0; i<no_symbols; i++)
487 { if (stypes[i] == GLOBAL_VARIABLE_T)
488 { sprintf(idname_string, "%s", (char *) symbs[i]);
489 array_name_strings[no_arrays + svals[i] -16]
490 = compile_string(idname_string, FALSE, FALSE);
494 for (i=0; i<no_named_routines; i++)
495 { sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
496 array_name_strings[no_arrays + no_globals + i]
497 = compile_string(idname_string, FALSE, FALSE);
500 for (i=0, no_named_constants=0; i<no_symbols; i++)
501 { if (((stypes[i] == OBJECT_T) || (stypes[i] == CLASS_T)
502 || (stypes[i] == CONSTANT_T))
503 && ((sflags[i] & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
504 { sprintf(idname_string, "%s", (char *) symbs[i]);
505 array_name_strings[no_arrays + no_globals + no_named_routines
506 + no_named_constants++]
507 = compile_string(idname_string, FALSE, FALSE);
514 /* ------------------------------------------------------------------------- */
515 /* Creating symbols */
516 /* ------------------------------------------------------------------------- */
518 static void assign_symbol_base(int index, int32 value, int type)
519 { svals[index] = value;
520 stypes[index] = type;
521 if (sflags[index] & UNKNOWN_SFLAG)
522 { sflags[index] &= (~UNKNOWN_SFLAG);
523 if (is_systemfile()) sflags[index] |= INSF_SFLAG;
524 slines[index] = ErrorReport.line_number
525 + FILE_LINE_SCALE_FACTOR*ErrorReport.file_number;
529 extern void assign_symbol(int index, int32 value, int type)
532 assign_symbol_base(index, value, type);
536 assign_symbol_base(index, value, type);
540 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
543 assign_symbol_base(index, (int32)marker*0x10000 + (value % 0x10000),
547 smarks[index] = marker;
548 assign_symbol_base(index, value, type);
552 static void emit_debug_information_for_predefined_symbol
553 (char *name, int32 symbol, int32 value, int type)
554 { if (debugfile_switch)
557 debug_file_printf("<constant>");
558 debug_file_printf("<identifier>%s</identifier>", name);
559 write_debug_symbol_optional_backpatch(symbol);
560 debug_file_printf("</constant>");
562 case GLOBAL_VARIABLE_T:
563 debug_file_printf("<global-variable>");
564 debug_file_printf("<identifier>%s</identifier>", name);
565 debug_file_printf("<address>");
566 write_debug_global_backpatch(value);
567 debug_file_printf("</address>");
568 debug_file_printf("</global-variable>");
572 { compiler_error("Non-nothing object predefined");
574 debug_file_printf("<object>");
575 debug_file_printf("<identifier>%s</identifier>", name);
576 debug_file_printf("<value>0</value>");
577 debug_file_printf("</object>");
580 debug_file_printf("<attribute>");
581 debug_file_printf("<identifier>%s</identifier>", name);
582 debug_file_printf("<value>%d</value>", value);
583 debug_file_printf("</attribute>");
586 case INDIVIDUAL_PROPERTY_T:
587 debug_file_printf("<property>");
588 debug_file_printf("<identifier>%s</identifier>", name);
589 debug_file_printf("<value>%d</value>", value);
590 debug_file_printf("</property>");
594 ("Unable to emit debug information for predefined symbol");
600 static void create_symbol(char *p, int32 value, int type)
601 { int i = symbol_index(p, -1);
602 svals[i] = value; stypes[i] = type; slines[i] = 0;
603 sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
604 emit_debug_information_for_predefined_symbol(p, i, value, type);
607 static void create_rsymbol(char *p, int value, int type)
608 { int i = symbol_index(p, -1);
609 svals[i] = value; stypes[i] = type; slines[i] = 0;
610 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
611 emit_debug_information_for_predefined_symbol(p, i, value, type);
614 static void stockup_symbols(void)
617 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
619 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
621 create_symbol("nothing", 0, OBJECT_T);
622 create_symbol("name", 1, PROPERTY_T);
624 create_symbol("true", 1, CONSTANT_T);
625 create_symbol("false", 0, CONSTANT_T);
627 /* Glulx defaults to GV2; Z-code to GV1 */
629 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
631 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
632 grammar_version_symbol = symbol_index("Grammar__Version", -1);
635 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
637 if (runtime_error_checking_switch)
638 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
640 if (define_DEBUG_switch)
641 create_rsymbol("DEBUG", 0, CONSTANT_T);
643 if (define_USE_MODULES_switch)
644 create_rsymbol("USE_MODULES",0, CONSTANT_T);
646 if (define_INFIX_switch)
647 { create_rsymbol("INFIX", 0, CONSTANT_T);
648 create_symbol("infix__watching", 0, ATTRIBUTE_T);
651 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
652 create_symbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
654 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
655 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
658 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
659 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
660 if (DICT_CHAR_SIZE != 1)
661 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
662 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
663 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
664 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
665 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
666 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
667 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
668 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
669 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
670 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
671 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
675 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
676 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
677 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
678 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
679 create_symbol("self", 251, GLOBAL_VARIABLE_T);
680 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
681 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
683 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
684 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
685 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
687 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
688 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
689 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
690 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
691 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
692 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
693 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
694 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
697 /* In Glulx, these system globals are entered in order, not down
699 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
701 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
703 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
705 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
707 create_symbol("self", MAX_LOCAL_VARIABLES+4,
709 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
711 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
714 /* These are almost certainly meaningless, and can be removed. */
715 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
717 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
719 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
722 /* value of statusline_flag to be written later */
723 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
726 /* These are created in order, but not necessarily at a fixed
728 create_symbol("create", INDIV_PROP_START+0,
729 INDIVIDUAL_PROPERTY_T);
730 create_symbol("recreate", INDIV_PROP_START+1,
731 INDIVIDUAL_PROPERTY_T);
732 create_symbol("destroy", INDIV_PROP_START+2,
733 INDIVIDUAL_PROPERTY_T);
734 create_symbol("remaining", INDIV_PROP_START+3,
735 INDIVIDUAL_PROPERTY_T);
736 create_symbol("copy", INDIV_PROP_START+4,
737 INDIVIDUAL_PROPERTY_T);
738 create_symbol("call", INDIV_PROP_START+5,
739 INDIVIDUAL_PROPERTY_T);
740 create_symbol("print", INDIV_PROP_START+6,
741 INDIVIDUAL_PROPERTY_T);
742 create_symbol("print_to_array",INDIV_PROP_START+7,
743 INDIVIDUAL_PROPERTY_T);
745 /* Floating-point constants. Note that FLOAT_NINFINITY is not
746 -FLOAT_INFINITY, because float negation doesn't work that
747 way. Also note that FLOAT_NAN is just one of many possible
748 "not-a-number" values. */
749 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
750 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
751 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
755 /* ------------------------------------------------------------------------- */
756 /* The symbol replacement table. This is needed only for the */
757 /* "Replace X Y" directive. */
758 /* ------------------------------------------------------------------------- */
760 extern void add_symbol_replacement_mapping(int original, int renamed)
764 if (original == renamed) {
765 error_named("A routine cannot be 'Replace'd to itself:", (char *)symbs[original]);
769 if (symbol_replacements_count == symbol_replacements_size) {
770 int oldsize = symbol_replacements_size;
771 if (symbol_replacements_size == 0)
772 symbol_replacements_size = 4;
774 symbol_replacements_size *= 2;
775 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
776 symbol_replacements_size, "symbol replacement table");
779 /* If the original form is already in our table, report an error.
780 Same goes if the replaced form is already in the table as an
781 original. (Other collision cases have already been
784 for (ix=0; ix<symbol_replacements_count; ix++) {
785 if (original == symbol_replacements[ix].original_symbol) {
786 error_named("A routine cannot be 'Replace'd to more than one new name:", (char *)symbs[original]);
788 if (renamed == symbol_replacements[ix].original_symbol) {
789 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", (char *)symbs[original]);
793 symbol_replacements[symbol_replacements_count].original_symbol = original;
794 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
795 symbol_replacements_count++;
798 extern int find_symbol_replacement(int *value)
803 if (!symbol_replacements)
806 for (ix=0; ix<symbol_replacements_count; ix++) {
807 if (*value == symbol_replacements[ix].original_symbol) {
808 *value = symbol_replacements[ix].renamed_symbol;
816 /* ------------------------------------------------------------------------- */
817 /* The dead-function removal optimization. */
818 /* ------------------------------------------------------------------------- */
820 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
821 OMIT_UNUSED_ROUTINES is nonzero */
822 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
823 static int df_tables_closed; /* set at end of compiler pass */
825 typedef struct df_function_struct df_function_t;
826 typedef struct df_reference_struct df_reference_t;
828 struct df_function_struct {
829 char *name; /* borrowed reference, generally to the symbs[] table */
830 int32 source_line; /* copied from routine_starts_line */
831 int sysfile; /* does this occur in a system file? */
832 uint32 address; /* function offset in zcode_area (not the final address) */
833 uint32 newaddress; /* function offset after stripping */
836 df_reference_t *refs; /* chain of references made *from* this function */
839 df_function_t *funcnext; /* in forward functions order */
840 df_function_t *todonext; /* in the todo chain */
841 df_function_t *next; /* in the hash table */
844 struct df_reference_struct {
845 uint32 address; /* function offset in zcode_area (not the final address) */
846 int symbol; /* index in symbols array */
848 df_reference_t *refsnext; /* in the function's refs chain */
849 df_reference_t *next; /* in the hash table */
852 /* Bitmask flags for how functions are used: */
853 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
854 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
855 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
856 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
858 #define DF_FUNCTION_HASH_BUCKETS (1023)
860 /* Table of all compiled functions. (Only created if track_unused_routines
861 is set.) This is a hash table. */
862 static df_function_t **df_functions;
863 /* List of all compiled functions, in address order. The first entry
864 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
865 static df_function_t *df_functions_head;
866 static df_function_t *df_functions_tail;
867 /* Used during output_file(), to track how far the code-area output has
869 static df_function_t *df_iterator;
871 /* Array of all compiled functions in address order. (Does not include
872 the global namespace entry.) This is generated only if needed. */
873 static df_function_t **df_functions_sorted;
874 static int df_functions_sorted_count;
876 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
877 #define DF_SYMBOL_HASH_BUCKETS (4095)
879 /* Map of what functions reference what other functions. (Only created if
880 track_unused_routines is set.) */
881 static df_reference_t **df_symbol_map;
883 /* Globals used while a function is being compiled. When a function
884 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
885 and df_current_function will refer to the global namespace record. */
886 static df_function_t *df_current_function;
887 static char *df_current_function_name;
888 static uint32 df_current_function_addr;
890 /* Size totals for compiled code. These are only meaningful if
891 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
892 these values will be set, but the "after" value will not affect the
894 uint32 df_total_size_before_stripping;
895 uint32 df_total_size_after_stripping;
897 /* When we begin compiling a function, call this to note that fact.
898 Any symbol referenced from now on will be associated with the function.
900 extern void df_note_function_start(char *name, uint32 address,
901 int embedded_flag, int32 source_line)
906 if (df_tables_closed)
907 error("Internal error in stripping: Tried to start a new function after tables were closed.");
909 /* We retain the name only for debugging output. Note that embedded
910 functions all show up as "<embedded>" -- their "obj.prop" name
911 never gets stored in permanent memory. */
912 df_current_function_name = name;
913 df_current_function_addr = address;
915 func = my_malloc(sizeof(df_function_t), "df function entry");
916 memset(func, 0, sizeof(df_function_t));
918 func->address = address;
919 func->source_line = source_line;
920 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
921 /* An embedded function is stored in an object property, so we
922 consider it to be used a priori. */
924 func->usage |= DF_USAGE_EMBEDDED;
926 if (!df_functions_head) {
927 df_functions_head = func;
928 df_functions_tail = func;
931 df_functions_tail->funcnext = func;
932 df_functions_tail = func;
935 bucket = address % DF_FUNCTION_HASH_BUCKETS;
936 func->next = df_functions[bucket];
937 df_functions[bucket] = func;
939 df_current_function = func;
942 /* When we're done compiling a function, call this. Any symbol referenced
943 from now on will be associated with the global namespace.
945 extern void df_note_function_end(uint32 endaddress)
947 df_current_function->length = endaddress - df_current_function->address;
949 df_current_function_name = NULL;
950 df_current_function_addr = DF_NOT_IN_FUNCTION;
951 df_current_function = df_functions_head; /* the global namespace */
954 /* Find the function record for a given address. (Addresses are offsets
957 static df_function_t *df_function_for_address(uint32 address)
959 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
961 for (func = df_functions[bucket]; func; func = func->next) {
962 if (func->address == address)
968 /* Whenever a function is referenced, we call this to note who called it.
970 extern void df_note_function_symbol(int symbol)
975 /* If the compiler pass is over, looking up symbols does not create
976 a global reference. */
977 if (df_tables_closed)
979 /* In certain cases during parsing, looking up symbols does not
980 create a global reference. (For example, when reading the name
981 of a function being defined.) */
982 if (df_dont_note_global_symbols)
985 /* We are only interested in functions, or forward-declared symbols
986 that might turn out to be functions. */
987 symtype = stypes[symbol];
988 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
990 if (symtype == CONSTANT_T && !(sflags[symbol] & UNKNOWN_SFLAG))
993 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
994 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
995 if (ent->address == df_current_function_addr && ent->symbol == symbol)
999 /* Create a new reference entry in df_symbol_map. */
1000 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
1001 ent->address = df_current_function_addr;
1002 ent->symbol = symbol;
1003 ent->next = df_symbol_map[bucket];
1004 df_symbol_map[bucket] = ent;
1006 /* Add the reference to the function's entry as well. */
1007 /* The current function is the most recently added, so it will be
1008 at the top of its bucket. That makes this call fast. Unless
1009 we're in global scope, in which case it might be slower.
1010 (I suppose we could cache the df_function_t pointer of the
1011 current function, to speed things up.) */
1012 if (!df_current_function || df_current_function_addr != df_current_function->address)
1013 compiler_error("DF: df_current_function does not match current address.");
1014 ent->refsnext = df_current_function->refs;
1015 df_current_function->refs = ent;
1018 /* This does the hard work of figuring out what functions are truly dead.
1019 It's called near the end of run_pass() in inform.c.
1021 extern void locate_dead_functions(void)
1023 df_function_t *func, *tofunc;
1024 df_reference_t *ent;
1027 if (!track_unused_routines)
1028 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1030 df_tables_closed = TRUE;
1031 df_current_function = NULL;
1033 /* Note that Main__ was tagged as global implicitly during
1034 compile_initial_routine(). Main was tagged during
1035 issue_unused_warnings(). But for the sake of thoroughness,
1036 we'll mark them specially. */
1038 ix = symbol_index("Main__", -1);
1039 if (stypes[ix] == ROUTINE_T) {
1040 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1041 tofunc = df_function_for_address(addr);
1043 tofunc->usage |= DF_USAGE_MAIN;
1045 ix = symbol_index("Main", -1);
1046 if (stypes[ix] == ROUTINE_T) {
1047 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1048 tofunc = df_function_for_address(addr);
1050 tofunc->usage |= DF_USAGE_MAIN;
1053 /* Go through all the functions referenced at the global level;
1054 mark them as used. */
1056 func = df_functions_head;
1057 if (!func || func->address != DF_NOT_IN_FUNCTION)
1058 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1060 for (ent = func->refs; ent; ent=ent->refsnext) {
1062 int symbol = ent->symbol;
1063 if (stypes[symbol] != ROUTINE_T)
1065 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1066 tofunc = df_function_for_address(addr);
1068 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1071 /* A function may be marked here more than once. That's fine. */
1072 tofunc->usage |= DF_USAGE_GLOBAL;
1075 /* Perform a breadth-first search through functions, starting with
1076 the ones that are known to be used at the top level. */
1078 df_function_t *todo, *todotail;
1079 df_function_t *func;
1083 for (func = df_functions_head; func; func = func->funcnext) {
1084 if (func->address == DF_NOT_IN_FUNCTION)
1086 if (func->usage == 0)
1093 todotail->todonext = func;
1098 /* todo is a linked list of functions which are known to be
1099 used. If a function's usage field is nonzero, it must be
1100 either be on the todo list or have come off already (in
1101 which case processed will be set). */
1104 /* Pop the next function. */
1106 todo = todo->todonext;
1110 if (func->processed)
1111 error_named("Internal error in stripping: function has been processed twice:", func->name);
1113 /* Go through the function's symbol references. Any
1114 reference to a routine, push it into the todo list (if
1115 it isn't there already). */
1117 for (ent = func->refs; ent; ent=ent->refsnext) {
1119 int symbol = ent->symbol;
1120 if (stypes[symbol] != ROUTINE_T)
1122 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1123 tofunc = df_function_for_address(addr);
1125 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1131 /* Not yet known to be used. Add it to the todo list. */
1132 tofunc->usage |= DF_USAGE_FUNCTION;
1138 todotail->todonext = tofunc;
1143 func->processed = TRUE;
1147 /* Go through all functions; figure out how much space is consumed,
1148 with and without useless functions. */
1151 df_function_t *func;
1153 df_total_size_before_stripping = 0;
1154 df_total_size_after_stripping = 0;
1156 for (func = df_functions_head; func; func = func->funcnext) {
1157 if (func->address == DF_NOT_IN_FUNCTION)
1160 if (func->address != df_total_size_before_stripping)
1161 compiler_error("DF: Address gap in function list");
1163 df_total_size_before_stripping += func->length;
1165 func->newaddress = df_total_size_after_stripping;
1166 df_total_size_after_stripping += func->length;
1169 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1170 compiler_error("DF: New function address is not aligned");
1172 if (WARN_UNUSED_ROUTINES && !func->usage) {
1173 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1174 uncalled_routine_warning("Routine", func->name, func->source_line);
1179 /* df_measure_hash_table_usage(); */
1182 /* Given an original function address, return where it winds up after
1183 unused-function stripping. The function must not itself be unused.
1185 Both the input and output are offsets, and already scaled by
1188 This is used by the backpatching system.
1190 extern uint32 df_stripped_address_for_address(uint32 addr)
1192 df_function_t *func;
1194 if (!track_unused_routines)
1195 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1198 func = df_function_for_address(addr*scale_factor);
1200 func = df_function_for_address(addr);
1203 compiler_error("DF: Unable to find function while backpatching");
1207 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1210 return func->newaddress / scale_factor;
1212 return func->newaddress;
1215 /* Given an address in the function area, return where it winds up after
1216 unused-function stripping. The address can be a function or anywhere
1217 within the function. If the address turns out to be in a stripped
1218 function, returns 0 (and sets *stripped).
1220 The input and output are offsets, but *not* scaled.
1222 This is only used by the debug-file system.
1224 uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
1226 df_function_t *func;
1229 if (!track_unused_routines)
1230 compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
1232 if (!df_functions_sorted) {
1233 /* To do this efficiently, we need a binary-searchable table. Fine,
1234 we'll make one. Include both used and unused functions. */
1236 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1237 if (func->address == DF_NOT_IN_FUNCTION)
1241 df_functions_sorted_count = count;
1243 df_functions_sorted = my_calloc(sizeof(df_function_t *), df_functions_sorted_count, "df function sorted table");
1245 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1246 if (func->address == DF_NOT_IN_FUNCTION)
1248 df_functions_sorted[count] = func;
1253 /* Do a binary search. Maintain beg <= res < end, where res is the
1254 function containing the desired address. */
1256 int end = df_functions_sorted_count;
1258 /* Set stripped flag until we decide on a non-stripped function. */
1263 error("DF: offset_for_code_offset: Could not locate address.");
1267 func = df_functions_sorted[beg];
1268 if (func->usage == 0)
1271 return func->newaddress + (offset - func->address);
1273 int new = (beg + end) / 2;
1274 if (new <= beg || new >= end)
1275 compiler_error("DF: binary search went off the rails");
1277 func = df_functions_sorted[new];
1278 if (offset >= func->address) {
1279 if (offset < func->address+func->length) {
1280 /* We don't need to loop further; decide here. */
1281 if (func->usage == 0)
1284 return func->newaddress + (offset - func->address);
1294 /* The output_file() routines in files.c have to run down the list of
1295 functions, deciding who is in and who is out. But I don't want to
1296 export the df_function_t list structure. Instead, I provide this
1297 silly iterator pair. Set it up with df_prepare_function_iterate();
1298 then repeatedly call df_next_function_iterate().
1301 extern void df_prepare_function_iterate(void)
1303 df_iterator = df_functions_head;
1304 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1305 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1306 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1307 compiler_error("DF: First function entry is not second in the chain.");
1310 /* This returns the end of the next function, and whether the next function
1313 extern uint32 df_next_function_iterate(int *funcused)
1316 df_iterator = df_iterator->funcnext;
1319 return df_total_size_before_stripping+1;
1321 *funcused = (df_iterator->usage != 0);
1322 return df_iterator->address + df_iterator->length;
1325 /* ========================================================================= */
1326 /* Data structure management routines */
1327 /* ------------------------------------------------------------------------- */
1329 extern void init_symbols_vars(void)
1337 start_of_list = NULL;
1339 symbol_name_space_chunks = NULL;
1340 no_symbol_name_space_chunks = 0;
1341 symbols_free_space=NULL;
1342 symbols_ceiling=symbols_free_space;
1346 symbol_replacements = NULL;
1347 symbol_replacements_count = 0;
1348 symbol_replacements_size = 0;
1350 make_case_conversion_grid();
1352 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1353 df_tables_closed = FALSE;
1354 df_symbol_map = NULL;
1355 df_functions = NULL;
1356 df_functions_head = NULL;
1357 df_functions_tail = NULL;
1358 df_current_function = NULL;
1359 df_functions_sorted = NULL;
1360 df_functions_sorted_count = 0;
1363 extern void symbols_begin_pass(void)
1365 df_total_size_before_stripping = 0;
1366 df_total_size_after_stripping = 0;
1367 df_dont_note_global_symbols = FALSE;
1371 extern void symbols_allocate_arrays(void)
1373 symbs = my_calloc(sizeof(char *), MAX_SYMBOLS, "symbols");
1374 svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
1376 smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
1377 slines = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol lines");
1378 stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
1379 sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
1380 if (debugfile_switch)
1381 { symbol_debug_backpatch_positions =
1382 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1383 "symbol debug information backpatch positions");
1384 replacement_debug_backpatch_positions =
1385 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1386 "replacement debug information backpatch positions");
1388 next_entry = my_calloc(sizeof(int), MAX_SYMBOLS,
1389 "symbol linked-list forward links");
1390 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1391 "hash code list beginnings");
1393 symbol_name_space_chunks
1394 = my_calloc(sizeof(char *), MAX_SYMBOL_CHUNKS, "symbol names chunk addresses");
1396 if (track_unused_routines) {
1397 df_tables_closed = FALSE;
1399 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1400 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1402 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1403 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1404 df_functions_head = NULL;
1405 df_functions_tail = NULL;
1407 df_functions_sorted = NULL;
1408 df_functions_sorted_count = 0;
1410 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, -1);
1411 df_note_function_end(DF_NOT_IN_FUNCTION);
1412 /* Now df_current_function is df_functions_head. */
1415 init_symbol_banks();
1418 /* Allocated as needed */
1419 symbol_replacements = NULL;
1421 /* Allocated during story file construction, not now */
1422 individual_name_strings = NULL;
1423 attribute_name_strings = NULL;
1424 action_name_strings = NULL;
1425 array_name_strings = NULL;
1428 extern void symbols_free_arrays(void)
1431 for (i=0; i<no_symbol_name_space_chunks; i++)
1432 my_free(&(symbol_name_space_chunks[i]),
1433 "symbol names chunk");
1435 my_free(&symbol_name_space_chunks, "symbol names chunk addresses");
1437 my_free(&symbs, "symbols");
1438 my_free(&svals, "symbol values");
1439 my_free(&smarks, "symbol markers");
1440 my_free(&slines, "symbol lines");
1441 my_free(&stypes, "symbol types");
1442 my_free(&sflags, "symbol flags");
1443 if (debugfile_switch)
1445 (&symbol_debug_backpatch_positions,
1446 "symbol debug information backpatch positions");
1448 (&replacement_debug_backpatch_positions,
1449 "replacement debug information backpatch positions");
1451 my_free(&next_entry, "symbol linked-list forward links");
1452 my_free(&start_of_list, "hash code list beginnings");
1454 if (symbol_replacements)
1455 my_free(&symbol_replacements, "symbol replacement table");
1457 if (df_symbol_map) {
1458 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1459 df_reference_t *ent = df_symbol_map[i];
1461 df_reference_t *next = ent->next;
1462 my_free(&ent, "df symbol map entry");
1466 my_free(&df_symbol_map, "df symbol-map hash table");
1468 if (df_functions_sorted) {
1469 my_free(&df_functions, "df function sorted table");
1472 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1473 df_function_t *func = df_functions[i];
1475 df_function_t *next = func->next;
1476 my_free(&func, "df function entry");
1480 my_free(&df_functions, "df function hash table");
1482 df_functions_head = NULL;
1483 df_functions_tail = NULL;
1485 if (individual_name_strings != NULL)
1486 my_free(&individual_name_strings, "property name strings");
1487 if (action_name_strings != NULL)
1488 my_free(&action_name_strings, "action name strings");
1489 if (attribute_name_strings != NULL)
1490 my_free(&attribute_name_strings, "attribute name strings");
1491 if (array_name_strings != NULL)
1492 my_free(&array_name_strings, "array name strings");
1495 /* ========================================================================= */