1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
4 /* Part of Inform 6.35 */
5 /* copyright (c) Graham Nelson 1993 - 2020 */
7 /* Inform is free software: you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation, either version 3 of the License, or */
10 /* (at your option) any later version. */
12 /* Inform is distributed in the hope that it will be useful, */
13 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
15 /* GNU General Public License for more details. */
17 /* You should have received a copy of the GNU General Public License */
18 /* along with Inform. If not, see https://gnu.org/licenses/ *
20 /* ------------------------------------------------------------------------- */
24 /* ------------------------------------------------------------------------- */
25 /* This section of Inform is a service detached from the rest. */
26 /* Only two variables are accessible from the outside: */
27 /* ------------------------------------------------------------------------- */
29 int no_symbols; /* Total number of symbols defined */
30 int no_named_constants; /* Copied into story file */
32 /* ------------------------------------------------------------------------- */
33 /* Plus six arrays. Each symbol has its own index n (an int32) and */
35 /* svals[n] is its value (must be 32 bits wide, i.e. an int32, tho' */
36 /* it is used to hold an unsigned 16 bit Z-machine value) */
37 /* sflags[n] holds flags (see "header.h" for a list) */
38 /* stypes[n] is the "type", distinguishing between the data type of */
39 /* different kinds of constants/variables. */
40 /* (See the "typename()" below.) */
41 /* symbs[n] (needs to be cast to (char *) to be used) is the name */
42 /* of the symbol, in the same case form as when created. */
43 /* slines[n] is the source line on which the symbol value was first */
45 /* symbol_debug_backpatch_positions[n] */
46 /* is a file position in the debug information file where */
47 /* the symbol's value should be written after backpatching, */
48 /* or else the null position if the value was known and */
49 /* written beforehand */
50 /* replacement_debug_backpatch_positions[n] */
51 /* is a file position in the debug information file where */
52 /* the symbol's name can be erased if it is replaced, or */
53 /* else null if the name will never need to be replaced */
55 /* Comparison is case insensitive. */
56 /* Note that local variable names are not entered into the symbols table, */
57 /* as their numbers and scope are too limited for this to be efficient. */
58 /* ------------------------------------------------------------------------- */
59 /* Caveat editor: some array types are set up to work even on machines */
60 /* where sizeof(int32 *) differs from, e.g., sizeof(char *): so do not */
61 /* alter the types unless you understand what is going on! */
62 /* ------------------------------------------------------------------------- */
66 int *smarks; /* Glulx-only */
67 brief_location *slines;
70 char *stypes; /* In VAX C, insanely, "signed char" is illegal */
74 maybe_file_position *symbol_debug_backpatch_positions;
75 maybe_file_position *replacement_debug_backpatch_positions;
77 /* ------------------------------------------------------------------------- */
78 /* Memory to hold the text of symbol names: note that this memory is */
79 /* allocated as needed in chunks of size SYMBOLS_CHUNK_SIZE. */
80 /* ------------------------------------------------------------------------- */
82 #define MAX_SYMBOL_CHUNKS (100)
84 static uchar *symbols_free_space, /* Next byte free to hold new names */
85 *symbols_ceiling; /* Pointer to the end of the current
86 allocation of memory for names */
88 static char** symbol_name_space_chunks; /* For chunks of memory used to hold
89 the name strings of symbols */
90 static int no_symbol_name_space_chunks;
92 typedef struct value_pair_struct {
96 static value_pair_t *symbol_replacements;
97 static int symbol_replacements_count;
98 static int symbol_replacements_size; /* calloced size */
100 /* ------------------------------------------------------------------------- */
101 /* The symbols table is "hash-coded" into a disjoint union of linked */
102 /* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
103 /* that it's the last in its list) or the next in the list. */
105 /* Each list contains, in alphabetical order, all the symbols which share */
106 /* the same "hash code" (a numerical function of the text of the symbol */
107 /* name, designed with the aim that roughly equal numbers of symbols are */
108 /* given each possible hash code). The hash codes are 0 to HASH_TAB_SIZE */
109 /* (which is a memory setting) minus 1: start_of_list[h] gives the first */
110 /* symbol with hash code h, or -1 if no symbol exists with hash code h. */
112 /* Note that the running time of the symbol search algorithm is about */
114 /* O ( n^2 / HASH_TAB_SIZE ) */
116 /* (where n is the number of symbols in the program) so that it is a good */
117 /* idea to choose HASH_TAB_SIZE as large as conveniently possible. */
118 /* ------------------------------------------------------------------------- */
120 static int *next_entry;
121 static int32 *start_of_list;
123 /* ------------------------------------------------------------------------- */
124 /* Initialisation. */
125 /* ------------------------------------------------------------------------- */
127 static void init_symbol_banks(void)
129 for (i=0; i<HASH_TAB_SIZE; i++) start_of_list[i] = -1;
132 /* ------------------------------------------------------------------------- */
133 /* The hash coding we use is quite standard; the variable hashcode is */
134 /* expected to overflow a good deal. (The aim is to produce a number */
135 /* so that similar names do not produce the same number.) Note that */
136 /* 30011 is prime. It doesn't matter if the unsigned int to int cast */
137 /* behaves differently on different ports. */
138 /* ------------------------------------------------------------------------- */
140 int case_conversion_grid[128];
142 static void make_case_conversion_grid(void)
144 /* Assumes that A to Z are contiguous in the host OS character set:
145 true for ASCII but not for EBCDIC, for instance. */
148 for (i=0; i<128; i++) case_conversion_grid[i] = i;
149 for (i=0; i<26; i++) case_conversion_grid['A'+i]='a'+i;
152 extern int hash_code_from_string(char *p)
154 for (; *p; p++) hashcode=hashcode*30011 + case_conversion_grid[(uchar)*p];
155 return (int) (hashcode % HASH_TAB_SIZE);
158 extern int strcmpcis(char *p, char *q)
160 /* Case insensitive strcmp */
163 for (i=0;p[i] != 0;i++)
164 { pc = p[i]; if (isupper(pc)) pc = tolower(pc);
165 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
169 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
173 /* ------------------------------------------------------------------------- */
174 /* Symbol finding, creating, and removing. */
175 /* ------------------------------------------------------------------------- */
177 extern int symbol_index(char *p, int hashcode)
179 /* Return the index in the symbs/svals/sflags/stypes/... arrays of symbol
180 "p", creating a new symbol with that name if it isn't already there.
182 New symbols are created with flag UNKNOWN_SFLAG, value 0x100
183 (a 2-byte quantity in Z-machine terms) and type CONSTANT_T.
185 The string "p" is undamaged. */
187 int32 new_entry, this, last; char *r;
189 if (hashcode == -1) hashcode = hash_code_from_string(p);
191 this = start_of_list[hashcode]; last = -1;
194 { if (this == -1) break;
196 r = (char *)symbs[this];
197 new_entry = strcmpcis(r, p);
200 if (track_unused_routines)
201 df_note_function_symbol(this);
204 if (new_entry > 0) break;
207 this = next_entry[this];
208 } while (this != -1);
210 if (no_symbols >= MAX_SYMBOLS)
211 memoryerror("MAX_SYMBOLS", MAX_SYMBOLS);
214 { next_entry[no_symbols]=start_of_list[hashcode];
215 start_of_list[hashcode]=no_symbols;
218 { next_entry[no_symbols]=this;
219 next_entry[last]=no_symbols;
222 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
224 = my_malloc(SYMBOLS_CHUNK_SIZE, "symbol names chunk");
225 symbols_ceiling = symbols_free_space + SYMBOLS_CHUNK_SIZE;
226 /* If we've passed MAX_SYMBOL_CHUNKS chunks, we print an error
227 message telling the user to increase SYMBOLS_CHUNK_SIZE.
228 That is the correct cure, even though the error comes out
229 worded inaccurately. */
230 if (no_symbol_name_space_chunks >= MAX_SYMBOL_CHUNKS)
231 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
232 symbol_name_space_chunks[no_symbol_name_space_chunks++]
233 = (char *) symbols_free_space;
234 if (symbols_free_space+strlen(p)+1 >= symbols_ceiling)
235 memoryerror("SYMBOLS_CHUNK_SIZE", SYMBOLS_CHUNK_SIZE);
238 strcpy((char *) symbols_free_space, p);
239 symbs[no_symbols] = (int32 *) symbols_free_space;
240 symbols_free_space += strlen((char *)symbols_free_space) + 1;
242 svals[no_symbols] = 0x100; /* ###-wrong? Would this fix the
243 unbound-symbol-causes-asm-error? */
244 sflags[no_symbols] = UNKNOWN_SFLAG;
245 stypes[no_symbols] = CONSTANT_T;
246 slines[no_symbols] = get_brief_location(&ErrorReport);
247 if (debugfile_switch)
248 { nullify_debug_file_position
249 (&symbol_debug_backpatch_positions[no_symbols]);
250 nullify_debug_file_position
251 (&replacement_debug_backpatch_positions[no_symbols]);
254 if (track_unused_routines)
255 df_note_function_symbol(no_symbols);
256 return(no_symbols++);
259 extern void end_symbol_scope(int k)
261 /* Remove the given symbol from the hash table, making it
262 invisible to symbol_index. This is used by the Undef directive.
263 If the symbol is not found, this silently does nothing.
267 j = hash_code_from_string((char *) symbs[k]);
268 if (start_of_list[j] == k)
269 { start_of_list[j] = next_entry[k];
272 j = start_of_list[j];
275 if (next_entry[j] == k)
276 { next_entry[j] = next_entry[k];
283 /* ------------------------------------------------------------------------- */
284 /* Printing diagnostics */
285 /* ------------------------------------------------------------------------- */
287 extern char *typename(int type)
290 /* These are the possible symbol types. Note that local variables
291 do not reside in the symbol table (for scope and efficiency
292 reasons) and actions have their own name-space (via routine
293 names with "Sub" appended). */
295 case ROUTINE_T: return("Routine");
296 case LABEL_T: return("Label");
297 case GLOBAL_VARIABLE_T: return("Global variable");
298 case ARRAY_T: return("Array");
299 case STATIC_ARRAY_T: return("Static array");
300 case CONSTANT_T: return("Defined constant");
301 case ATTRIBUTE_T: return("Attribute");
302 case PROPERTY_T: return("Property");
303 case INDIVIDUAL_PROPERTY_T: return("Individual property");
304 case OBJECT_T: return("Object");
305 case CLASS_T: return("Class");
306 case FAKE_ACTION_T: return("Fake action");
308 default: return("(Unknown type)");
312 static void describe_flags(int flags)
313 { if (flags & UNKNOWN_SFLAG) printf("(?) ");
314 if (flags & USED_SFLAG) printf("(used) ");
315 if (flags & REPLACE_SFLAG) printf("(Replaced) ");
316 if (flags & DEFCON_SFLAG) printf("(Defaulted) ");
317 if (flags & STUB_SFLAG) printf("(Stubbed) ");
318 if (flags & CHANGE_SFLAG) printf("(value will change) ");
319 if (flags & IMPORT_SFLAG) printf("(Imported) ");
320 if (flags & EXPORT_SFLAG) printf("(Exported) ");
321 if (flags & SYSTEM_SFLAG) printf("(System) ");
322 if (flags & INSF_SFLAG) printf("(created in sys file) ");
323 if (flags & UERROR_SFLAG) printf("('Unknown' error issued) ");
324 if (flags & ALIASED_SFLAG) printf("(aliased) ");
325 if (flags & ACTION_SFLAG) printf("(Action name) ");
326 if (flags & REDEFINABLE_SFLAG) printf("(Redefinable) ");
329 extern void describe_symbol(int k)
330 { printf("%4d %-16s %2d:%04d %04x %s ",
331 k, (char *) (symbs[k]),
332 (int)(slines[k].file_index),
333 (int)(slines[k].line_number),
334 svals[k], typename(stypes[k]));
335 describe_flags(sflags[k]);
338 extern void list_symbols(int level)
340 for (k=0; k<no_symbols; k++)
342 ((sflags[k] & (SYSTEM_SFLAG + UNKNOWN_SFLAG + INSF_SFLAG)) == 0))
343 { describe_symbol(k); printf("\n");
348 extern void issue_unused_warnings(void)
351 if (module_switch) return;
353 /* Update any ad-hoc variables that might help the library */
355 { global_initial_value[10]=statusline_flag;
357 /* Now back to mark anything necessary as used */
359 i = symbol_index("Main", -1);
360 if (!(sflags[i] & UNKNOWN_SFLAG)) sflags[i] |= USED_SFLAG;
362 for (i=0;i<no_symbols;i++)
364 & (SYSTEM_SFLAG + UNKNOWN_SFLAG + EXPORT_SFLAG
365 + INSF_SFLAG + USED_SFLAG + REPLACE_SFLAG)) == 0)
366 && (stypes[i] != OBJECT_T))
367 dbnu_warning(typename(stypes[i]), (char *) symbs[i], slines[i]);
371 /* ------------------------------------------------------------------------- */
372 /* These are arrays used only during story file (never module) creation, */
373 /* and not allocated until then. */
375 int32 *individual_name_strings; /* Packed addresses of Z-encoded
376 strings of the names of the
377 properties: this is an array
378 indexed by the property ID */
379 int32 *action_name_strings; /* Ditto for actions */
380 int32 *attribute_name_strings; /* Ditto for attributes */
381 int32 *array_name_strings; /* Ditto for arrays */
383 extern void write_the_identifier_names(void)
384 { int i, j, k, t, null_value; char idname_string[256];
385 static char unknown_attribute[20] = "<unknown attribute>";
387 for (i=0; i<no_individual_properties; i++)
388 individual_name_strings[i] = 0;
390 if (module_switch) return;
394 null_value = compile_string(unknown_attribute, FALSE, FALSE);
395 for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
397 for (i=0; i<no_symbols; i++)
399 if ((t == INDIVIDUAL_PROPERTY_T) || (t == PROPERTY_T))
400 { if (sflags[i] & ALIASED_SFLAG)
401 { if (individual_name_strings[svals[i]] == 0)
402 { sprintf(idname_string, "%s", (char *) symbs[i]);
404 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
405 { if ((stypes[j] == stypes[i])
406 && (svals[j] == svals[i]))
407 { sprintf(idname_string+strlen(idname_string),
408 "/%s", (char *) symbs[j]);
413 individual_name_strings[svals[i]]
414 = compile_string(idname_string, FALSE, FALSE);
418 { sprintf(idname_string, "%s", (char *) symbs[i]);
420 individual_name_strings[svals[i]]
421 = compile_string(idname_string, FALSE, FALSE);
424 if (t == ATTRIBUTE_T)
425 { if (sflags[i] & ALIASED_SFLAG)
426 { if (attribute_name_strings[svals[i]] == null_value)
427 { sprintf(idname_string, "%s", (char *) symbs[i]);
429 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
430 { if ((stypes[j] == stypes[i])
431 && (svals[j] == svals[i]))
432 { sprintf(idname_string+strlen(idname_string),
433 "/%s", (char *) symbs[j]);
438 attribute_name_strings[svals[i]]
439 = compile_string(idname_string, FALSE, FALSE);
443 { sprintf(idname_string, "%s", (char *) symbs[i]);
445 attribute_name_strings[svals[i]]
446 = compile_string(idname_string, FALSE, FALSE);
449 if (sflags[i] & ACTION_SFLAG)
450 { sprintf(idname_string, "%s", (char *) symbs[i]);
451 idname_string[strlen(idname_string)-3] = 0;
453 if (debugfile_switch)
454 { debug_file_printf("<action>");
456 ("<identifier>##%s</identifier>", idname_string);
457 debug_file_printf("<value>%d</value>", svals[i]);
458 debug_file_printf("</action>");
461 action_name_strings[svals[i]]
462 = compile_string(idname_string, FALSE, FALSE);
466 for (i=0; i<no_symbols; i++)
467 { if (stypes[i] == FAKE_ACTION_T)
468 { sprintf(idname_string, "%s", (char *) symbs[i]);
469 idname_string[strlen(idname_string)-3] = 0;
471 action_name_strings[svals[i]
472 - ((grammar_version_number==1)?256:4096) + no_actions]
473 = compile_string(idname_string, FALSE, FALSE);
477 for (j=0; j<no_arrays; j++)
478 { i = array_symbols[j];
479 sprintf(idname_string, "%s", (char *) symbs[i]);
481 array_name_strings[j]
482 = compile_string(idname_string, FALSE, FALSE);
484 if (define_INFIX_switch)
485 { for (i=0; i<no_symbols; i++)
486 { if (stypes[i] == GLOBAL_VARIABLE_T)
487 { sprintf(idname_string, "%s", (char *) symbs[i]);
488 array_name_strings[no_arrays + svals[i] -16]
489 = compile_string(idname_string, FALSE, FALSE);
493 for (i=0; i<no_named_routines; i++)
494 { sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
495 array_name_strings[no_arrays + no_globals + i]
496 = compile_string(idname_string, FALSE, FALSE);
499 for (i=0, no_named_constants=0; i<no_symbols; i++)
500 { if (((stypes[i] == OBJECT_T) || (stypes[i] == CLASS_T)
501 || (stypes[i] == CONSTANT_T))
502 && ((sflags[i] & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
503 { sprintf(idname_string, "%s", (char *) symbs[i]);
504 array_name_strings[no_arrays + no_globals + no_named_routines
505 + no_named_constants++]
506 = compile_string(idname_string, FALSE, FALSE);
513 /* ------------------------------------------------------------------------- */
514 /* Creating symbols */
515 /* ------------------------------------------------------------------------- */
517 static void assign_symbol_base(int index, int32 value, int type)
518 { svals[index] = value;
519 stypes[index] = type;
520 if (sflags[index] & UNKNOWN_SFLAG)
521 { sflags[index] &= (~UNKNOWN_SFLAG);
522 if (is_systemfile()) sflags[index] |= INSF_SFLAG;
523 slines[index] = get_brief_location(&ErrorReport);
527 extern void assign_symbol(int index, int32 value, int type)
530 assign_symbol_base(index, value, type);
534 assign_symbol_base(index, value, type);
538 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
541 assign_symbol_base(index, (int32)marker*0x10000 + (value % 0x10000),
545 smarks[index] = marker;
546 assign_symbol_base(index, value, type);
550 static void emit_debug_information_for_predefined_symbol
551 (char *name, int32 symbol, int32 value, int type)
552 { if (debugfile_switch)
555 debug_file_printf("<constant>");
556 debug_file_printf("<identifier>%s</identifier>", name);
557 write_debug_symbol_optional_backpatch(symbol);
558 debug_file_printf("</constant>");
560 case GLOBAL_VARIABLE_T:
561 debug_file_printf("<global-variable>");
562 debug_file_printf("<identifier>%s</identifier>", name);
563 debug_file_printf("<address>");
564 write_debug_global_backpatch(value);
565 debug_file_printf("</address>");
566 debug_file_printf("</global-variable>");
570 { compiler_error("Non-nothing object predefined");
572 debug_file_printf("<object>");
573 debug_file_printf("<identifier>%s</identifier>", name);
574 debug_file_printf("<value>0</value>");
575 debug_file_printf("</object>");
578 debug_file_printf("<attribute>");
579 debug_file_printf("<identifier>%s</identifier>", name);
580 debug_file_printf("<value>%d</value>", value);
581 debug_file_printf("</attribute>");
584 case INDIVIDUAL_PROPERTY_T:
585 debug_file_printf("<property>");
586 debug_file_printf("<identifier>%s</identifier>", name);
587 debug_file_printf("<value>%d</value>", value);
588 debug_file_printf("</property>");
592 ("Unable to emit debug information for predefined symbol");
598 static void create_symbol(char *p, int32 value, int type)
599 { int i = symbol_index(p, -1);
600 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
601 sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
602 emit_debug_information_for_predefined_symbol(p, i, value, type);
605 static void create_rsymbol(char *p, int value, int type)
606 { int i = symbol_index(p, -1);
607 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
608 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
609 emit_debug_information_for_predefined_symbol(p, i, value, type);
612 static void stockup_symbols(void)
615 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
617 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
619 create_symbol("nothing", 0, OBJECT_T);
620 create_symbol("name", 1, PROPERTY_T);
622 create_symbol("true", 1, CONSTANT_T);
623 create_symbol("false", 0, CONSTANT_T);
625 /* Glulx defaults to GV2; Z-code to GV1 */
627 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
629 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
630 grammar_version_symbol = symbol_index("Grammar__Version", -1);
633 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
635 if (runtime_error_checking_switch)
636 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
638 if (define_DEBUG_switch)
639 create_rsymbol("DEBUG", 0, CONSTANT_T);
641 if (define_USE_MODULES_switch)
642 create_rsymbol("USE_MODULES",0, CONSTANT_T);
644 if (define_INFIX_switch)
645 { create_rsymbol("INFIX", 0, CONSTANT_T);
646 create_symbol("infix__watching", 0, ATTRIBUTE_T);
649 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
650 create_symbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
652 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
653 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
656 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
657 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
658 if (DICT_CHAR_SIZE != 1)
659 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
660 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
661 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
662 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
663 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
664 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
665 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
666 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
667 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
668 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
669 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
673 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
674 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
675 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
676 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
677 create_symbol("self", 251, GLOBAL_VARIABLE_T);
678 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
679 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
681 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
682 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
683 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
685 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
686 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
687 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
688 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
689 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
690 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
691 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
692 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
695 /* In Glulx, these system globals are entered in order, not down
697 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
699 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
701 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
703 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
705 create_symbol("self", MAX_LOCAL_VARIABLES+4,
707 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
709 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
712 /* These are almost certainly meaningless, and can be removed. */
713 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
715 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
717 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
720 /* value of statusline_flag to be written later */
721 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
724 /* These are created in order, but not necessarily at a fixed
726 create_symbol("create", INDIV_PROP_START+0,
727 INDIVIDUAL_PROPERTY_T);
728 create_symbol("recreate", INDIV_PROP_START+1,
729 INDIVIDUAL_PROPERTY_T);
730 create_symbol("destroy", INDIV_PROP_START+2,
731 INDIVIDUAL_PROPERTY_T);
732 create_symbol("remaining", INDIV_PROP_START+3,
733 INDIVIDUAL_PROPERTY_T);
734 create_symbol("copy", INDIV_PROP_START+4,
735 INDIVIDUAL_PROPERTY_T);
736 create_symbol("call", INDIV_PROP_START+5,
737 INDIVIDUAL_PROPERTY_T);
738 create_symbol("print", INDIV_PROP_START+6,
739 INDIVIDUAL_PROPERTY_T);
740 create_symbol("print_to_array",INDIV_PROP_START+7,
741 INDIVIDUAL_PROPERTY_T);
743 /* Floating-point constants. Note that FLOAT_NINFINITY is not
744 -FLOAT_INFINITY, because float negation doesn't work that
745 way. Also note that FLOAT_NAN is just one of many possible
746 "not-a-number" values. */
747 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
748 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
749 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
753 /* ------------------------------------------------------------------------- */
754 /* The symbol replacement table. This is needed only for the */
755 /* "Replace X Y" directive. */
756 /* ------------------------------------------------------------------------- */
758 extern void add_symbol_replacement_mapping(int original, int renamed)
762 if (original == renamed) {
763 error_named("A routine cannot be 'Replace'd to itself:", (char *)symbs[original]);
767 if (symbol_replacements_count == symbol_replacements_size) {
768 int oldsize = symbol_replacements_size;
769 if (symbol_replacements_size == 0)
770 symbol_replacements_size = 4;
772 symbol_replacements_size *= 2;
773 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
774 symbol_replacements_size, "symbol replacement table");
777 /* If the original form is already in our table, report an error.
778 Same goes if the replaced form is already in the table as an
779 original. (Other collision cases have already been
782 for (ix=0; ix<symbol_replacements_count; ix++) {
783 if (original == symbol_replacements[ix].original_symbol) {
784 error_named("A routine cannot be 'Replace'd to more than one new name:", (char *)symbs[original]);
786 if (renamed == symbol_replacements[ix].original_symbol) {
787 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", (char *)symbs[original]);
791 symbol_replacements[symbol_replacements_count].original_symbol = original;
792 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
793 symbol_replacements_count++;
796 extern int find_symbol_replacement(int *value)
801 if (!symbol_replacements)
804 for (ix=0; ix<symbol_replacements_count; ix++) {
805 if (*value == symbol_replacements[ix].original_symbol) {
806 *value = symbol_replacements[ix].renamed_symbol;
814 /* ------------------------------------------------------------------------- */
815 /* The dead-function removal optimization. */
816 /* ------------------------------------------------------------------------- */
818 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
819 OMIT_UNUSED_ROUTINES is nonzero */
820 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
821 static int df_tables_closed; /* set at end of compiler pass */
823 typedef struct df_function_struct df_function_t;
824 typedef struct df_reference_struct df_reference_t;
826 struct df_function_struct {
827 char *name; /* borrowed reference, generally to the symbs[] table */
828 brief_location source_line; /* copied from routine_starts_line */
829 int sysfile; /* does this occur in a system file? */
830 uint32 address; /* function offset in zcode_area (not the final address) */
831 uint32 newaddress; /* function offset after stripping */
834 df_reference_t *refs; /* chain of references made *from* this function */
837 df_function_t *funcnext; /* in forward functions order */
838 df_function_t *todonext; /* in the todo chain */
839 df_function_t *next; /* in the hash table */
842 struct df_reference_struct {
843 uint32 address; /* function offset in zcode_area (not the final address) */
844 int symbol; /* index in symbols array */
846 df_reference_t *refsnext; /* in the function's refs chain */
847 df_reference_t *next; /* in the hash table */
850 /* Bitmask flags for how functions are used: */
851 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
852 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
853 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
854 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
856 #define DF_FUNCTION_HASH_BUCKETS (1023)
858 /* Table of all compiled functions. (Only created if track_unused_routines
859 is set.) This is a hash table. */
860 static df_function_t **df_functions;
861 /* List of all compiled functions, in address order. The first entry
862 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
863 static df_function_t *df_functions_head;
864 static df_function_t *df_functions_tail;
865 /* Used during output_file(), to track how far the code-area output has
867 static df_function_t *df_iterator;
869 /* Array of all compiled functions in address order. (Does not include
870 the global namespace entry.) This is generated only if needed. */
871 static df_function_t **df_functions_sorted;
872 static int df_functions_sorted_count;
874 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
875 #define DF_SYMBOL_HASH_BUCKETS (4095)
877 /* Map of what functions reference what other functions. (Only created if
878 track_unused_routines is set.) */
879 static df_reference_t **df_symbol_map;
881 /* Globals used while a function is being compiled. When a function
882 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
883 and df_current_function will refer to the global namespace record. */
884 static df_function_t *df_current_function;
885 static char *df_current_function_name;
886 static uint32 df_current_function_addr;
888 /* Size totals for compiled code. These are only meaningful if
889 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
890 these values will be set, but the "after" value will not affect the
892 uint32 df_total_size_before_stripping;
893 uint32 df_total_size_after_stripping;
895 /* When we begin compiling a function, call this to note that fact.
896 Any symbol referenced from now on will be associated with the function.
898 extern void df_note_function_start(char *name, uint32 address,
899 int embedded_flag, brief_location source_line)
904 if (df_tables_closed)
905 error("Internal error in stripping: Tried to start a new function after tables were closed.");
907 /* We retain the name only for debugging output. Note that embedded
908 functions all show up as "<embedded>" -- their "obj.prop" name
909 never gets stored in permanent memory. */
910 df_current_function_name = name;
911 df_current_function_addr = address;
913 func = my_malloc(sizeof(df_function_t), "df function entry");
914 memset(func, 0, sizeof(df_function_t));
916 func->address = address;
917 func->source_line = source_line;
918 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
919 /* An embedded function is stored in an object property, so we
920 consider it to be used a priori. */
922 func->usage |= DF_USAGE_EMBEDDED;
924 if (!df_functions_head) {
925 df_functions_head = func;
926 df_functions_tail = func;
929 df_functions_tail->funcnext = func;
930 df_functions_tail = func;
933 bucket = address % DF_FUNCTION_HASH_BUCKETS;
934 func->next = df_functions[bucket];
935 df_functions[bucket] = func;
937 df_current_function = func;
940 /* When we're done compiling a function, call this. Any symbol referenced
941 from now on will be associated with the global namespace.
943 extern void df_note_function_end(uint32 endaddress)
945 df_current_function->length = endaddress - df_current_function->address;
947 df_current_function_name = NULL;
948 df_current_function_addr = DF_NOT_IN_FUNCTION;
949 df_current_function = df_functions_head; /* the global namespace */
952 /* Find the function record for a given address. (Addresses are offsets
955 static df_function_t *df_function_for_address(uint32 address)
957 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
959 for (func = df_functions[bucket]; func; func = func->next) {
960 if (func->address == address)
966 /* Whenever a function is referenced, we call this to note who called it.
968 extern void df_note_function_symbol(int symbol)
973 /* If the compiler pass is over, looking up symbols does not create
974 a global reference. */
975 if (df_tables_closed)
977 /* In certain cases during parsing, looking up symbols does not
978 create a global reference. (For example, when reading the name
979 of a function being defined.) */
980 if (df_dont_note_global_symbols)
983 /* We are only interested in functions, or forward-declared symbols
984 that might turn out to be functions. */
985 symtype = stypes[symbol];
986 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
988 if (symtype == CONSTANT_T && !(sflags[symbol] & UNKNOWN_SFLAG))
991 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
992 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
993 if (ent->address == df_current_function_addr && ent->symbol == symbol)
997 /* Create a new reference entry in df_symbol_map. */
998 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
999 ent->address = df_current_function_addr;
1000 ent->symbol = symbol;
1001 ent->next = df_symbol_map[bucket];
1002 df_symbol_map[bucket] = ent;
1004 /* Add the reference to the function's entry as well. */
1005 /* The current function is the most recently added, so it will be
1006 at the top of its bucket. That makes this call fast. Unless
1007 we're in global scope, in which case it might be slower.
1008 (I suppose we could cache the df_function_t pointer of the
1009 current function, to speed things up.) */
1010 if (!df_current_function || df_current_function_addr != df_current_function->address)
1011 compiler_error("DF: df_current_function does not match current address.");
1012 ent->refsnext = df_current_function->refs;
1013 df_current_function->refs = ent;
1016 /* This does the hard work of figuring out what functions are truly dead.
1017 It's called near the end of run_pass() in inform.c.
1019 extern void locate_dead_functions(void)
1021 df_function_t *func, *tofunc;
1022 df_reference_t *ent;
1025 if (!track_unused_routines)
1026 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1028 df_tables_closed = TRUE;
1029 df_current_function = NULL;
1031 /* Note that Main__ was tagged as global implicitly during
1032 compile_initial_routine(). Main was tagged during
1033 issue_unused_warnings(). But for the sake of thoroughness,
1034 we'll mark them specially. */
1036 ix = symbol_index("Main__", -1);
1037 if (stypes[ix] == ROUTINE_T) {
1038 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1039 tofunc = df_function_for_address(addr);
1041 tofunc->usage |= DF_USAGE_MAIN;
1043 ix = symbol_index("Main", -1);
1044 if (stypes[ix] == ROUTINE_T) {
1045 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1046 tofunc = df_function_for_address(addr);
1048 tofunc->usage |= DF_USAGE_MAIN;
1051 /* Go through all the functions referenced at the global level;
1052 mark them as used. */
1054 func = df_functions_head;
1055 if (!func || func->address != DF_NOT_IN_FUNCTION)
1056 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1058 for (ent = func->refs; ent; ent=ent->refsnext) {
1060 int symbol = ent->symbol;
1061 if (stypes[symbol] != ROUTINE_T)
1063 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1064 tofunc = df_function_for_address(addr);
1066 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1069 /* A function may be marked here more than once. That's fine. */
1070 tofunc->usage |= DF_USAGE_GLOBAL;
1073 /* Perform a breadth-first search through functions, starting with
1074 the ones that are known to be used at the top level. */
1076 df_function_t *todo, *todotail;
1077 df_function_t *func;
1081 for (func = df_functions_head; func; func = func->funcnext) {
1082 if (func->address == DF_NOT_IN_FUNCTION)
1084 if (func->usage == 0)
1091 todotail->todonext = func;
1096 /* todo is a linked list of functions which are known to be
1097 used. If a function's usage field is nonzero, it must be
1098 either be on the todo list or have come off already (in
1099 which case processed will be set). */
1102 /* Pop the next function. */
1104 todo = todo->todonext;
1108 if (func->processed)
1109 error_named("Internal error in stripping: function has been processed twice:", func->name);
1111 /* Go through the function's symbol references. Any
1112 reference to a routine, push it into the todo list (if
1113 it isn't there already). */
1115 for (ent = func->refs; ent; ent=ent->refsnext) {
1117 int symbol = ent->symbol;
1118 if (stypes[symbol] != ROUTINE_T)
1120 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1121 tofunc = df_function_for_address(addr);
1123 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1129 /* Not yet known to be used. Add it to the todo list. */
1130 tofunc->usage |= DF_USAGE_FUNCTION;
1136 todotail->todonext = tofunc;
1141 func->processed = TRUE;
1145 /* Go through all functions; figure out how much space is consumed,
1146 with and without useless functions. */
1149 df_function_t *func;
1151 df_total_size_before_stripping = 0;
1152 df_total_size_after_stripping = 0;
1154 for (func = df_functions_head; func; func = func->funcnext) {
1155 if (func->address == DF_NOT_IN_FUNCTION)
1158 if (func->address != df_total_size_before_stripping)
1159 compiler_error("DF: Address gap in function list");
1161 df_total_size_before_stripping += func->length;
1163 func->newaddress = df_total_size_after_stripping;
1164 df_total_size_after_stripping += func->length;
1167 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1168 compiler_error("DF: New function address is not aligned");
1170 if (WARN_UNUSED_ROUTINES && !func->usage) {
1171 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1172 uncalled_routine_warning("Routine", func->name, func->source_line);
1177 /* df_measure_hash_table_usage(); */
1180 /* Given an original function address, return where it winds up after
1181 unused-function stripping. The function must not itself be unused.
1183 Both the input and output are offsets, and already scaled by
1186 This is used by the backpatching system.
1188 extern uint32 df_stripped_address_for_address(uint32 addr)
1190 df_function_t *func;
1192 if (!track_unused_routines)
1193 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1196 func = df_function_for_address(addr*scale_factor);
1198 func = df_function_for_address(addr);
1201 compiler_error("DF: Unable to find function while backpatching");
1205 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1208 return func->newaddress / scale_factor;
1210 return func->newaddress;
1213 /* Given an address in the function area, return where it winds up after
1214 unused-function stripping. The address can be a function or anywhere
1215 within the function. If the address turns out to be in a stripped
1216 function, returns 0 (and sets *stripped).
1218 The input and output are offsets, but *not* scaled.
1220 This is only used by the debug-file system.
1222 uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
1224 df_function_t *func;
1227 if (!track_unused_routines)
1228 compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
1230 if (!df_functions_sorted) {
1231 /* To do this efficiently, we need a binary-searchable table. Fine,
1232 we'll make one. Include both used and unused functions. */
1234 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1235 if (func->address == DF_NOT_IN_FUNCTION)
1239 df_functions_sorted_count = count;
1241 df_functions_sorted = my_calloc(sizeof(df_function_t *), df_functions_sorted_count, "df function sorted table");
1243 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1244 if (func->address == DF_NOT_IN_FUNCTION)
1246 df_functions_sorted[count] = func;
1251 /* Do a binary search. Maintain beg <= res < end, where res is the
1252 function containing the desired address. */
1254 int end = df_functions_sorted_count;
1256 /* Set stripped flag until we decide on a non-stripped function. */
1261 error("DF: offset_for_code_offset: Could not locate address.");
1265 func = df_functions_sorted[beg];
1266 if (func->usage == 0)
1269 return func->newaddress + (offset - func->address);
1271 int new = (beg + end) / 2;
1272 if (new <= beg || new >= end)
1273 compiler_error("DF: binary search went off the rails");
1275 func = df_functions_sorted[new];
1276 if (offset >= func->address) {
1277 if (offset < func->address+func->length) {
1278 /* We don't need to loop further; decide here. */
1279 if (func->usage == 0)
1282 return func->newaddress + (offset - func->address);
1292 /* The output_file() routines in files.c have to run down the list of
1293 functions, deciding who is in and who is out. But I don't want to
1294 export the df_function_t list structure. Instead, I provide this
1295 silly iterator pair. Set it up with df_prepare_function_iterate();
1296 then repeatedly call df_next_function_iterate().
1299 extern void df_prepare_function_iterate(void)
1301 df_iterator = df_functions_head;
1302 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1303 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1304 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1305 compiler_error("DF: First function entry is not second in the chain.");
1308 /* This returns the end of the next function, and whether the next function
1311 extern uint32 df_next_function_iterate(int *funcused)
1314 df_iterator = df_iterator->funcnext;
1317 return df_total_size_before_stripping+1;
1319 *funcused = (df_iterator->usage != 0);
1320 return df_iterator->address + df_iterator->length;
1323 /* ========================================================================= */
1324 /* Data structure management routines */
1325 /* ------------------------------------------------------------------------- */
1327 extern void init_symbols_vars(void)
1335 start_of_list = NULL;
1337 symbol_name_space_chunks = NULL;
1338 no_symbol_name_space_chunks = 0;
1339 symbols_free_space=NULL;
1340 symbols_ceiling=symbols_free_space;
1344 symbol_replacements = NULL;
1345 symbol_replacements_count = 0;
1346 symbol_replacements_size = 0;
1348 make_case_conversion_grid();
1350 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1351 df_tables_closed = FALSE;
1352 df_symbol_map = NULL;
1353 df_functions = NULL;
1354 df_functions_head = NULL;
1355 df_functions_tail = NULL;
1356 df_current_function = NULL;
1357 df_functions_sorted = NULL;
1358 df_functions_sorted_count = 0;
1361 extern void symbols_begin_pass(void)
1363 df_total_size_before_stripping = 0;
1364 df_total_size_after_stripping = 0;
1365 df_dont_note_global_symbols = FALSE;
1369 extern void symbols_allocate_arrays(void)
1371 symbs = my_calloc(sizeof(char *), MAX_SYMBOLS, "symbols");
1372 svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
1374 smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
1375 slines = my_calloc(sizeof(brief_location), MAX_SYMBOLS, "symbol lines");
1376 stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
1377 sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
1378 if (debugfile_switch)
1379 { symbol_debug_backpatch_positions =
1380 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1381 "symbol debug information backpatch positions");
1382 replacement_debug_backpatch_positions =
1383 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1384 "replacement debug information backpatch positions");
1386 next_entry = my_calloc(sizeof(int), MAX_SYMBOLS,
1387 "symbol linked-list forward links");
1388 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1389 "hash code list beginnings");
1391 symbol_name_space_chunks
1392 = my_calloc(sizeof(char *), MAX_SYMBOL_CHUNKS, "symbol names chunk addresses");
1394 if (track_unused_routines) {
1395 df_tables_closed = FALSE;
1397 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1398 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1400 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1401 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1402 df_functions_head = NULL;
1403 df_functions_tail = NULL;
1405 df_functions_sorted = NULL;
1406 df_functions_sorted_count = 0;
1408 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, blank_brief_location);
1409 df_note_function_end(DF_NOT_IN_FUNCTION);
1410 /* Now df_current_function is df_functions_head. */
1413 init_symbol_banks();
1416 /* Allocated as needed */
1417 symbol_replacements = NULL;
1419 /* Allocated during story file construction, not now */
1420 individual_name_strings = NULL;
1421 attribute_name_strings = NULL;
1422 action_name_strings = NULL;
1423 array_name_strings = NULL;
1426 extern void symbols_free_arrays(void)
1429 for (i=0; i<no_symbol_name_space_chunks; i++)
1430 my_free(&(symbol_name_space_chunks[i]),
1431 "symbol names chunk");
1433 my_free(&symbol_name_space_chunks, "symbol names chunk addresses");
1435 my_free(&symbs, "symbols");
1436 my_free(&svals, "symbol values");
1437 my_free(&smarks, "symbol markers");
1438 my_free(&slines, "symbol lines");
1439 my_free(&stypes, "symbol types");
1440 my_free(&sflags, "symbol flags");
1441 if (debugfile_switch)
1443 (&symbol_debug_backpatch_positions,
1444 "symbol debug information backpatch positions");
1446 (&replacement_debug_backpatch_positions,
1447 "replacement debug information backpatch positions");
1449 my_free(&next_entry, "symbol linked-list forward links");
1450 my_free(&start_of_list, "hash code list beginnings");
1452 if (symbol_replacements)
1453 my_free(&symbol_replacements, "symbol replacement table");
1455 if (df_symbol_map) {
1456 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1457 df_reference_t *ent = df_symbol_map[i];
1459 df_reference_t *next = ent->next;
1460 my_free(&ent, "df symbol map entry");
1464 my_free(&df_symbol_map, "df symbol-map hash table");
1466 if (df_functions_sorted) {
1467 my_free(&df_functions, "df function sorted table");
1470 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1471 df_function_t *func = df_functions[i];
1473 df_function_t *next = func->next;
1474 my_free(&func, "df function entry");
1478 my_free(&df_functions, "df function hash table");
1480 df_functions_head = NULL;
1481 df_functions_tail = NULL;
1483 if (individual_name_strings != NULL)
1484 my_free(&individual_name_strings, "property name strings");
1485 if (action_name_strings != NULL)
1486 my_free(&action_name_strings, "action name strings");
1487 if (attribute_name_strings != NULL)
1488 my_free(&attribute_name_strings, "attribute name strings");
1489 if (array_name_strings != NULL)
1490 my_free(&array_name_strings, "array name strings");
1493 /* ========================================================================= */