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