1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
4 /* Copyright (c) Graham Nelson 1993 - 2020 */
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 */
68 brief_location *slines;
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] = get_brief_location(&ErrorReport);
248 if (debugfile_switch)
249 { nullify_debug_file_position
250 (&symbol_debug_backpatch_positions[no_symbols]);
251 nullify_debug_file_position
252 (&replacement_debug_backpatch_positions[no_symbols]);
255 if (track_unused_routines)
256 df_note_function_symbol(no_symbols);
257 return(no_symbols++);
260 extern void end_symbol_scope(int k)
262 /* Remove the given symbol from the hash table, making it
263 invisible to symbol_index. This is used by the Undef directive.
264 If the symbol is not found, this silently does nothing.
268 j = hash_code_from_string((char *) symbs[k]);
269 if (start_of_list[j] == k)
270 { start_of_list[j] = next_entry[k];
273 j = start_of_list[j];
276 if (next_entry[j] == k)
277 { next_entry[j] = next_entry[k];
284 /* ------------------------------------------------------------------------- */
285 /* Printing diagnostics */
286 /* ------------------------------------------------------------------------- */
288 extern char *typename(int type)
291 /* These are the possible symbol types. Note that local variables
292 do not reside in the symbol table (for scope and efficiency
293 reasons) and actions have their own name-space (via routine
294 names with "Sub" appended). */
296 case ROUTINE_T: return("Routine");
297 case LABEL_T: return("Label");
298 case GLOBAL_VARIABLE_T: return("Global variable");
299 case ARRAY_T: return("Array");
300 case STATIC_ARRAY_T: return("Static 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_index),
334 (int)(slines[k].line_number),
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] = get_brief_location(&ErrorReport);
528 extern void assign_symbol(int index, int32 value, int type)
531 assign_symbol_base(index, value, type);
535 assign_symbol_base(index, value, type);
539 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
542 assign_symbol_base(index, (int32)marker*0x10000 + (value % 0x10000),
546 smarks[index] = marker;
547 assign_symbol_base(index, value, type);
551 static void emit_debug_information_for_predefined_symbol
552 (char *name, int32 symbol, int32 value, int type)
553 { if (debugfile_switch)
556 debug_file_printf("<constant>");
557 debug_file_printf("<identifier>%s</identifier>", name);
558 write_debug_symbol_optional_backpatch(symbol);
559 debug_file_printf("</constant>");
561 case GLOBAL_VARIABLE_T:
562 debug_file_printf("<global-variable>");
563 debug_file_printf("<identifier>%s</identifier>", name);
564 debug_file_printf("<address>");
565 write_debug_global_backpatch(value);
566 debug_file_printf("</address>");
567 debug_file_printf("</global-variable>");
571 { compiler_error("Non-nothing object predefined");
573 debug_file_printf("<object>");
574 debug_file_printf("<identifier>%s</identifier>", name);
575 debug_file_printf("<value>0</value>");
576 debug_file_printf("</object>");
579 debug_file_printf("<attribute>");
580 debug_file_printf("<identifier>%s</identifier>", name);
581 debug_file_printf("<value>%d</value>", value);
582 debug_file_printf("</attribute>");
585 case INDIVIDUAL_PROPERTY_T:
586 debug_file_printf("<property>");
587 debug_file_printf("<identifier>%s</identifier>", name);
588 debug_file_printf("<value>%d</value>", value);
589 debug_file_printf("</property>");
593 ("Unable to emit debug information for predefined symbol");
599 static void create_symbol(char *p, int32 value, int type)
600 { int i = symbol_index(p, -1);
601 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
602 sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
603 emit_debug_information_for_predefined_symbol(p, i, value, type);
606 static void create_rsymbol(char *p, int value, int type)
607 { int i = symbol_index(p, -1);
608 svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
609 sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
610 emit_debug_information_for_predefined_symbol(p, i, value, type);
613 static void stockup_symbols(void)
616 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
618 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
620 create_symbol("nothing", 0, OBJECT_T);
621 create_symbol("name", 1, PROPERTY_T);
623 create_symbol("true", 1, CONSTANT_T);
624 create_symbol("false", 0, CONSTANT_T);
626 /* Glulx defaults to GV2; Z-code to GV1 */
628 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
630 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
631 grammar_version_symbol = symbol_index("Grammar__Version", -1);
634 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
636 if (runtime_error_checking_switch)
637 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
639 if (define_DEBUG_switch)
640 create_rsymbol("DEBUG", 0, CONSTANT_T);
642 if (define_USE_MODULES_switch)
643 create_rsymbol("USE_MODULES",0, CONSTANT_T);
645 if (define_INFIX_switch)
646 { create_rsymbol("INFIX", 0, CONSTANT_T);
647 create_symbol("infix__watching", 0, ATTRIBUTE_T);
650 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
651 create_symbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
653 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
654 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
657 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
658 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
659 if (DICT_CHAR_SIZE != 1)
660 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
661 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
662 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
663 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
664 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
665 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
666 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
667 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
668 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
669 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
670 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
674 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
675 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
676 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
677 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
678 create_symbol("self", 251, GLOBAL_VARIABLE_T);
679 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
680 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
682 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
683 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
684 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
686 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
687 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
688 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
689 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
690 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
691 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
692 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
693 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
696 /* In Glulx, these system globals are entered in order, not down
698 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
700 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
702 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
704 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
706 create_symbol("self", MAX_LOCAL_VARIABLES+4,
708 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
710 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
713 /* These are almost certainly meaningless, and can be removed. */
714 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
716 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
718 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
721 /* value of statusline_flag to be written later */
722 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
725 /* These are created in order, but not necessarily at a fixed
727 create_symbol("create", INDIV_PROP_START+0,
728 INDIVIDUAL_PROPERTY_T);
729 create_symbol("recreate", INDIV_PROP_START+1,
730 INDIVIDUAL_PROPERTY_T);
731 create_symbol("destroy", INDIV_PROP_START+2,
732 INDIVIDUAL_PROPERTY_T);
733 create_symbol("remaining", INDIV_PROP_START+3,
734 INDIVIDUAL_PROPERTY_T);
735 create_symbol("copy", INDIV_PROP_START+4,
736 INDIVIDUAL_PROPERTY_T);
737 create_symbol("call", INDIV_PROP_START+5,
738 INDIVIDUAL_PROPERTY_T);
739 create_symbol("print", INDIV_PROP_START+6,
740 INDIVIDUAL_PROPERTY_T);
741 create_symbol("print_to_array",INDIV_PROP_START+7,
742 INDIVIDUAL_PROPERTY_T);
744 /* Floating-point constants. Note that FLOAT_NINFINITY is not
745 -FLOAT_INFINITY, because float negation doesn't work that
746 way. Also note that FLOAT_NAN is just one of many possible
747 "not-a-number" values. */
748 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
749 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
750 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
754 /* ------------------------------------------------------------------------- */
755 /* The symbol replacement table. This is needed only for the */
756 /* "Replace X Y" directive. */
757 /* ------------------------------------------------------------------------- */
759 extern void add_symbol_replacement_mapping(int original, int renamed)
763 if (original == renamed) {
764 error_named("A routine cannot be 'Replace'd to itself:", (char *)symbs[original]);
768 if (symbol_replacements_count == symbol_replacements_size) {
769 int oldsize = symbol_replacements_size;
770 if (symbol_replacements_size == 0)
771 symbol_replacements_size = 4;
773 symbol_replacements_size *= 2;
774 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
775 symbol_replacements_size, "symbol replacement table");
778 /* If the original form is already in our table, report an error.
779 Same goes if the replaced form is already in the table as an
780 original. (Other collision cases have already been
783 for (ix=0; ix<symbol_replacements_count; ix++) {
784 if (original == symbol_replacements[ix].original_symbol) {
785 error_named("A routine cannot be 'Replace'd to more than one new name:", (char *)symbs[original]);
787 if (renamed == symbol_replacements[ix].original_symbol) {
788 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", (char *)symbs[original]);
792 symbol_replacements[symbol_replacements_count].original_symbol = original;
793 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
794 symbol_replacements_count++;
797 extern int find_symbol_replacement(int *value)
802 if (!symbol_replacements)
805 for (ix=0; ix<symbol_replacements_count; ix++) {
806 if (*value == symbol_replacements[ix].original_symbol) {
807 *value = symbol_replacements[ix].renamed_symbol;
815 /* ------------------------------------------------------------------------- */
816 /* The dead-function removal optimization. */
817 /* ------------------------------------------------------------------------- */
819 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
820 OMIT_UNUSED_ROUTINES is nonzero */
821 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
822 static int df_tables_closed; /* set at end of compiler pass */
824 typedef struct df_function_struct df_function_t;
825 typedef struct df_reference_struct df_reference_t;
827 struct df_function_struct {
828 char *name; /* borrowed reference, generally to the symbs[] table */
829 brief_location source_line; /* copied from routine_starts_line */
830 int sysfile; /* does this occur in a system file? */
831 uint32 address; /* function offset in zcode_area (not the final address) */
832 uint32 newaddress; /* function offset after stripping */
835 df_reference_t *refs; /* chain of references made *from* this function */
838 df_function_t *funcnext; /* in forward functions order */
839 df_function_t *todonext; /* in the todo chain */
840 df_function_t *next; /* in the hash table */
843 struct df_reference_struct {
844 uint32 address; /* function offset in zcode_area (not the final address) */
845 int symbol; /* index in symbols array */
847 df_reference_t *refsnext; /* in the function's refs chain */
848 df_reference_t *next; /* in the hash table */
851 /* Bitmask flags for how functions are used: */
852 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
853 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
854 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
855 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
857 #define DF_FUNCTION_HASH_BUCKETS (1023)
859 /* Table of all compiled functions. (Only created if track_unused_routines
860 is set.) This is a hash table. */
861 static df_function_t **df_functions;
862 /* List of all compiled functions, in address order. The first entry
863 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
864 static df_function_t *df_functions_head;
865 static df_function_t *df_functions_tail;
866 /* Used during output_file(), to track how far the code-area output has
868 static df_function_t *df_iterator;
870 /* Array of all compiled functions in address order. (Does not include
871 the global namespace entry.) This is generated only if needed. */
872 static df_function_t **df_functions_sorted;
873 static int df_functions_sorted_count;
875 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
876 #define DF_SYMBOL_HASH_BUCKETS (4095)
878 /* Map of what functions reference what other functions. (Only created if
879 track_unused_routines is set.) */
880 static df_reference_t **df_symbol_map;
882 /* Globals used while a function is being compiled. When a function
883 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
884 and df_current_function will refer to the global namespace record. */
885 static df_function_t *df_current_function;
886 static char *df_current_function_name;
887 static uint32 df_current_function_addr;
889 /* Size totals for compiled code. These are only meaningful if
890 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
891 these values will be set, but the "after" value will not affect the
893 uint32 df_total_size_before_stripping;
894 uint32 df_total_size_after_stripping;
896 /* When we begin compiling a function, call this to note that fact.
897 Any symbol referenced from now on will be associated with the function.
899 extern void df_note_function_start(char *name, uint32 address,
900 int embedded_flag, brief_location source_line)
905 if (df_tables_closed)
906 error("Internal error in stripping: Tried to start a new function after tables were closed.");
908 /* We retain the name only for debugging output. Note that embedded
909 functions all show up as "<embedded>" -- their "obj.prop" name
910 never gets stored in permanent memory. */
911 df_current_function_name = name;
912 df_current_function_addr = address;
914 func = my_malloc(sizeof(df_function_t), "df function entry");
915 memset(func, 0, sizeof(df_function_t));
917 func->address = address;
918 func->source_line = source_line;
919 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
920 /* An embedded function is stored in an object property, so we
921 consider it to be used a priori. */
923 func->usage |= DF_USAGE_EMBEDDED;
925 if (!df_functions_head) {
926 df_functions_head = func;
927 df_functions_tail = func;
930 df_functions_tail->funcnext = func;
931 df_functions_tail = func;
934 bucket = address % DF_FUNCTION_HASH_BUCKETS;
935 func->next = df_functions[bucket];
936 df_functions[bucket] = func;
938 df_current_function = func;
941 /* When we're done compiling a function, call this. Any symbol referenced
942 from now on will be associated with the global namespace.
944 extern void df_note_function_end(uint32 endaddress)
946 df_current_function->length = endaddress - df_current_function->address;
948 df_current_function_name = NULL;
949 df_current_function_addr = DF_NOT_IN_FUNCTION;
950 df_current_function = df_functions_head; /* the global namespace */
953 /* Find the function record for a given address. (Addresses are offsets
956 static df_function_t *df_function_for_address(uint32 address)
958 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
960 for (func = df_functions[bucket]; func; func = func->next) {
961 if (func->address == address)
967 /* Whenever a function is referenced, we call this to note who called it.
969 extern void df_note_function_symbol(int symbol)
974 /* If the compiler pass is over, looking up symbols does not create
975 a global reference. */
976 if (df_tables_closed)
978 /* In certain cases during parsing, looking up symbols does not
979 create a global reference. (For example, when reading the name
980 of a function being defined.) */
981 if (df_dont_note_global_symbols)
984 /* We are only interested in functions, or forward-declared symbols
985 that might turn out to be functions. */
986 symtype = stypes[symbol];
987 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
989 if (symtype == CONSTANT_T && !(sflags[symbol] & UNKNOWN_SFLAG))
992 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
993 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
994 if (ent->address == df_current_function_addr && ent->symbol == symbol)
998 /* Create a new reference entry in df_symbol_map. */
999 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
1000 ent->address = df_current_function_addr;
1001 ent->symbol = symbol;
1002 ent->next = df_symbol_map[bucket];
1003 df_symbol_map[bucket] = ent;
1005 /* Add the reference to the function's entry as well. */
1006 /* The current function is the most recently added, so it will be
1007 at the top of its bucket. That makes this call fast. Unless
1008 we're in global scope, in which case it might be slower.
1009 (I suppose we could cache the df_function_t pointer of the
1010 current function, to speed things up.) */
1011 if (!df_current_function || df_current_function_addr != df_current_function->address)
1012 compiler_error("DF: df_current_function does not match current address.");
1013 ent->refsnext = df_current_function->refs;
1014 df_current_function->refs = ent;
1017 /* This does the hard work of figuring out what functions are truly dead.
1018 It's called near the end of run_pass() in inform.c.
1020 extern void locate_dead_functions(void)
1022 df_function_t *func, *tofunc;
1023 df_reference_t *ent;
1026 if (!track_unused_routines)
1027 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1029 df_tables_closed = TRUE;
1030 df_current_function = NULL;
1032 /* Note that Main__ was tagged as global implicitly during
1033 compile_initial_routine(). Main was tagged during
1034 issue_unused_warnings(). But for the sake of thoroughness,
1035 we'll mark them specially. */
1037 ix = symbol_index("Main__", -1);
1038 if (stypes[ix] == ROUTINE_T) {
1039 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1040 tofunc = df_function_for_address(addr);
1042 tofunc->usage |= DF_USAGE_MAIN;
1044 ix = symbol_index("Main", -1);
1045 if (stypes[ix] == ROUTINE_T) {
1046 uint32 addr = svals[ix] * (glulx_mode ? 1 : scale_factor);
1047 tofunc = df_function_for_address(addr);
1049 tofunc->usage |= DF_USAGE_MAIN;
1052 /* Go through all the functions referenced at the global level;
1053 mark them as used. */
1055 func = df_functions_head;
1056 if (!func || func->address != DF_NOT_IN_FUNCTION)
1057 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1059 for (ent = func->refs; ent; ent=ent->refsnext) {
1061 int symbol = ent->symbol;
1062 if (stypes[symbol] != ROUTINE_T)
1064 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1065 tofunc = df_function_for_address(addr);
1067 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1070 /* A function may be marked here more than once. That's fine. */
1071 tofunc->usage |= DF_USAGE_GLOBAL;
1074 /* Perform a breadth-first search through functions, starting with
1075 the ones that are known to be used at the top level. */
1077 df_function_t *todo, *todotail;
1078 df_function_t *func;
1082 for (func = df_functions_head; func; func = func->funcnext) {
1083 if (func->address == DF_NOT_IN_FUNCTION)
1085 if (func->usage == 0)
1092 todotail->todonext = func;
1097 /* todo is a linked list of functions which are known to be
1098 used. If a function's usage field is nonzero, it must be
1099 either be on the todo list or have come off already (in
1100 which case processed will be set). */
1103 /* Pop the next function. */
1105 todo = todo->todonext;
1109 if (func->processed)
1110 error_named("Internal error in stripping: function has been processed twice:", func->name);
1112 /* Go through the function's symbol references. Any
1113 reference to a routine, push it into the todo list (if
1114 it isn't there already). */
1116 for (ent = func->refs; ent; ent=ent->refsnext) {
1118 int symbol = ent->symbol;
1119 if (stypes[symbol] != ROUTINE_T)
1121 addr = svals[symbol] * (glulx_mode ? 1 : scale_factor);
1122 tofunc = df_function_for_address(addr);
1124 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", (char *)symbs[symbol]);
1130 /* Not yet known to be used. Add it to the todo list. */
1131 tofunc->usage |= DF_USAGE_FUNCTION;
1137 todotail->todonext = tofunc;
1142 func->processed = TRUE;
1146 /* Go through all functions; figure out how much space is consumed,
1147 with and without useless functions. */
1150 df_function_t *func;
1152 df_total_size_before_stripping = 0;
1153 df_total_size_after_stripping = 0;
1155 for (func = df_functions_head; func; func = func->funcnext) {
1156 if (func->address == DF_NOT_IN_FUNCTION)
1159 if (func->address != df_total_size_before_stripping)
1160 compiler_error("DF: Address gap in function list");
1162 df_total_size_before_stripping += func->length;
1164 func->newaddress = df_total_size_after_stripping;
1165 df_total_size_after_stripping += func->length;
1168 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1169 compiler_error("DF: New function address is not aligned");
1171 if (WARN_UNUSED_ROUTINES && !func->usage) {
1172 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1173 uncalled_routine_warning("Routine", func->name, func->source_line);
1178 /* df_measure_hash_table_usage(); */
1181 /* Given an original function address, return where it winds up after
1182 unused-function stripping. The function must not itself be unused.
1184 Both the input and output are offsets, and already scaled by
1187 This is used by the backpatching system.
1189 extern uint32 df_stripped_address_for_address(uint32 addr)
1191 df_function_t *func;
1193 if (!track_unused_routines)
1194 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1197 func = df_function_for_address(addr*scale_factor);
1199 func = df_function_for_address(addr);
1202 compiler_error("DF: Unable to find function while backpatching");
1206 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1209 return func->newaddress / scale_factor;
1211 return func->newaddress;
1214 /* Given an address in the function area, return where it winds up after
1215 unused-function stripping. The address can be a function or anywhere
1216 within the function. If the address turns out to be in a stripped
1217 function, returns 0 (and sets *stripped).
1219 The input and output are offsets, but *not* scaled.
1221 This is only used by the debug-file system.
1223 uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
1225 df_function_t *func;
1228 if (!track_unused_routines)
1229 compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
1231 if (!df_functions_sorted) {
1232 /* To do this efficiently, we need a binary-searchable table. Fine,
1233 we'll make one. Include both used and unused functions. */
1235 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1236 if (func->address == DF_NOT_IN_FUNCTION)
1240 df_functions_sorted_count = count;
1242 df_functions_sorted = my_calloc(sizeof(df_function_t *), df_functions_sorted_count, "df function sorted table");
1244 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1245 if (func->address == DF_NOT_IN_FUNCTION)
1247 df_functions_sorted[count] = func;
1252 /* Do a binary search. Maintain beg <= res < end, where res is the
1253 function containing the desired address. */
1255 int end = df_functions_sorted_count;
1257 /* Set stripped flag until we decide on a non-stripped function. */
1262 error("DF: offset_for_code_offset: Could not locate address.");
1266 func = df_functions_sorted[beg];
1267 if (func->usage == 0)
1270 return func->newaddress + (offset - func->address);
1272 int new = (beg + end) / 2;
1273 if (new <= beg || new >= end)
1274 compiler_error("DF: binary search went off the rails");
1276 func = df_functions_sorted[new];
1277 if (offset >= func->address) {
1278 if (offset < func->address+func->length) {
1279 /* We don't need to loop further; decide here. */
1280 if (func->usage == 0)
1283 return func->newaddress + (offset - func->address);
1293 /* The output_file() routines in files.c have to run down the list of
1294 functions, deciding who is in and who is out. But I don't want to
1295 export the df_function_t list structure. Instead, I provide this
1296 silly iterator pair. Set it up with df_prepare_function_iterate();
1297 then repeatedly call df_next_function_iterate().
1300 extern void df_prepare_function_iterate(void)
1302 df_iterator = df_functions_head;
1303 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1304 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1305 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1306 compiler_error("DF: First function entry is not second in the chain.");
1309 /* This returns the end of the next function, and whether the next function
1312 extern uint32 df_next_function_iterate(int *funcused)
1315 df_iterator = df_iterator->funcnext;
1318 return df_total_size_before_stripping+1;
1320 *funcused = (df_iterator->usage != 0);
1321 return df_iterator->address + df_iterator->length;
1324 /* ========================================================================= */
1325 /* Data structure management routines */
1326 /* ------------------------------------------------------------------------- */
1328 extern void init_symbols_vars(void)
1336 start_of_list = NULL;
1338 symbol_name_space_chunks = NULL;
1339 no_symbol_name_space_chunks = 0;
1340 symbols_free_space=NULL;
1341 symbols_ceiling=symbols_free_space;
1345 symbol_replacements = NULL;
1346 symbol_replacements_count = 0;
1347 symbol_replacements_size = 0;
1349 make_case_conversion_grid();
1351 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1352 df_tables_closed = FALSE;
1353 df_symbol_map = NULL;
1354 df_functions = NULL;
1355 df_functions_head = NULL;
1356 df_functions_tail = NULL;
1357 df_current_function = NULL;
1358 df_functions_sorted = NULL;
1359 df_functions_sorted_count = 0;
1362 extern void symbols_begin_pass(void)
1364 df_total_size_before_stripping = 0;
1365 df_total_size_after_stripping = 0;
1366 df_dont_note_global_symbols = FALSE;
1370 extern void symbols_allocate_arrays(void)
1372 symbs = my_calloc(sizeof(char *), MAX_SYMBOLS, "symbols");
1373 svals = my_calloc(sizeof(int32), MAX_SYMBOLS, "symbol values");
1375 smarks = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol markers");
1376 slines = my_calloc(sizeof(brief_location), MAX_SYMBOLS, "symbol lines");
1377 stypes = my_calloc(sizeof(char), MAX_SYMBOLS, "symbol types");
1378 sflags = my_calloc(sizeof(int), MAX_SYMBOLS, "symbol flags");
1379 if (debugfile_switch)
1380 { symbol_debug_backpatch_positions =
1381 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1382 "symbol debug information backpatch positions");
1383 replacement_debug_backpatch_positions =
1384 my_calloc(sizeof(maybe_file_position), MAX_SYMBOLS,
1385 "replacement debug information backpatch positions");
1387 next_entry = my_calloc(sizeof(int), MAX_SYMBOLS,
1388 "symbol linked-list forward links");
1389 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1390 "hash code list beginnings");
1392 symbol_name_space_chunks
1393 = my_calloc(sizeof(char *), MAX_SYMBOL_CHUNKS, "symbol names chunk addresses");
1395 if (track_unused_routines) {
1396 df_tables_closed = FALSE;
1398 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1399 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1401 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1402 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1403 df_functions_head = NULL;
1404 df_functions_tail = NULL;
1406 df_functions_sorted = NULL;
1407 df_functions_sorted_count = 0;
1409 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, blank_brief_location);
1410 df_note_function_end(DF_NOT_IN_FUNCTION);
1411 /* Now df_current_function is df_functions_head. */
1414 init_symbol_banks();
1417 /* Allocated as needed */
1418 symbol_replacements = NULL;
1420 /* Allocated during story file construction, not now */
1421 individual_name_strings = NULL;
1422 attribute_name_strings = NULL;
1423 action_name_strings = NULL;
1424 array_name_strings = NULL;
1427 extern void symbols_free_arrays(void)
1430 for (i=0; i<no_symbol_name_space_chunks; i++)
1431 my_free(&(symbol_name_space_chunks[i]),
1432 "symbol names chunk");
1434 my_free(&symbol_name_space_chunks, "symbol names chunk addresses");
1436 my_free(&symbs, "symbols");
1437 my_free(&svals, "symbol values");
1438 my_free(&smarks, "symbol markers");
1439 my_free(&slines, "symbol lines");
1440 my_free(&stypes, "symbol types");
1441 my_free(&sflags, "symbol flags");
1442 if (debugfile_switch)
1444 (&symbol_debug_backpatch_positions,
1445 "symbol debug information backpatch positions");
1447 (&replacement_debug_backpatch_positions,
1448 "replacement debug information backpatch positions");
1450 my_free(&next_entry, "symbol linked-list forward links");
1451 my_free(&start_of_list, "hash code list beginnings");
1453 if (symbol_replacements)
1454 my_free(&symbol_replacements, "symbol replacement table");
1456 if (df_symbol_map) {
1457 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1458 df_reference_t *ent = df_symbol_map[i];
1460 df_reference_t *next = ent->next;
1461 my_free(&ent, "df symbol map entry");
1465 my_free(&df_symbol_map, "df symbol-map hash table");
1467 if (df_functions_sorted) {
1468 my_free(&df_functions, "df function sorted table");
1471 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1472 df_function_t *func = df_functions[i];
1474 df_function_t *next = func->next;
1475 my_free(&func, "df function entry");
1479 my_free(&df_functions, "df function hash table");
1481 df_functions_head = NULL;
1482 df_functions_tail = NULL;
1484 if (individual_name_strings != NULL)
1485 my_free(&individual_name_strings, "property name strings");
1486 if (action_name_strings != NULL)
1487 my_free(&action_name_strings, "action name strings");
1488 if (attribute_name_strings != NULL)
1489 my_free(&attribute_name_strings, "attribute name strings");
1490 if (array_name_strings != NULL)
1491 my_free(&array_name_strings, "array name strings");
1494 /* ========================================================================= */