1 /* ------------------------------------------------------------------------- */
2 /* "symbols" : The symbols table; creating stock of reserved words */
4 /* Part of Inform 6.40 */
5 /* copyright (c) Graham Nelson 1993 - 2022 */
7 /* Inform is free software: you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation, either version 3 of the License, or */
10 /* (at your option) any later version. */
12 /* Inform is distributed in the hope that it will be useful, */
13 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
15 /* GNU General Public License for more details. */
17 /* You should have received a copy of the GNU General Public License */
18 /* along with Inform. If not, see https://gnu.org/licenses/ */
20 /* ------------------------------------------------------------------------- */
24 /* ------------------------------------------------------------------------- */
25 /* This section of Inform is a service detached from the rest. */
26 /* Only two variables are accessible from the outside: */
27 /* ------------------------------------------------------------------------- */
29 int no_symbols; /* Total number of symbols defined */
30 int no_named_constants; /* Copied into story file */
32 /* ------------------------------------------------------------------------- */
33 /* Plus an array of symbolinfo. Each symbol has its own index n (an */
34 /* int32) in the array. The struct there contains: */
36 /* value is its value. In Z-code, this holds both the 16-bit value */
37 /* and the 16-bit backpatch marker, so it is an int32. */
38 /* marker is the backpatch marker in Glulx. */
39 /* flags holds flags (see "header.h" for a list of ?_SFLAGS) */
40 /* type is the "type", distinguishing between the data type of */
41 /* different kinds of constants/variables. */
42 /* (A ?_T constant; see the "typename()" below.) */
43 /* name is the name of the symbol, in the same case form as */
45 /* line is the source line on which the symbol value was first */
47 /* next_entry is the forward link in the symbol hash table. (See */
48 /* start_of_list, below.) */
50 /* When generating a debug file (-k switch), we also allocate an array */
51 /* of symboldebuginfo, which contains: */
54 /* is a file position in the debug information file where */
55 /* the symbol's value should be written after backpatching, */
56 /* or else the null position if the value was known and */
57 /* written beforehand */
58 /* replacement_backpatch_pos */
59 /* is a file position in the debug information file where */
60 /* the symbol's name can be erased if it is replaced, or */
61 /* else null if the name will never need to be replaced */
63 /* Comparison is case insensitive. */
64 /* Note that local variable names are not entered into the symbols table, */
65 /* as their numbers and scope are too limited for this to be efficient. */
66 /* ------------------------------------------------------------------------- */
68 symbolinfo *symbols; /* Allocated up to no_symbols */
69 static memory_list symbols_memlist;
70 symboldebuginfo *symbol_debug_info; /* Allocated up to no_symbols */
71 static memory_list symbol_debug_info_memlist;
73 /* ------------------------------------------------------------------------- */
74 /* Memory to hold the text of symbol names: note that this memory is */
75 /* allocated as needed in chunks of size SYMBOLS_CHUNK_SIZE. */
76 /* ------------------------------------------------------------------------- */
78 #define SYMBOLS_CHUNK_SIZE (4096)
80 static char *symbols_free_space, /* Next byte free to hold new names */
81 *symbols_ceiling; /* Pointer to the end of the current
82 allocation of memory for names */
84 static char** symbol_name_space_chunks; /* For chunks of memory used to hold
85 the name strings of symbols */
86 static int no_symbol_name_space_chunks;
87 static memory_list symbol_name_space_chunks_memlist;
89 /* Symbol replacements (used by the "Replace X Y" directive). */
91 typedef struct value_pair_struct {
95 static value_pair_t *symbol_replacements;
96 static int symbol_replacements_count;
97 static int symbol_replacements_size; /* calloced size */
99 /* Symbol definitions requested at compile time. (There may not be any.)
100 These are set up at command-line parse time, not in init_symbols_vars().
101 Similarly, they are not cleaned up by symbols_free_arrays(). */
103 typedef struct keyvalue_pair_struct {
107 static keyvalue_pair_t *symbol_definitions = NULL;
108 static int symbol_definitions_count = 0;
109 static int symbol_definitions_size = 0; /* calloced size */
111 /* ------------------------------------------------------------------------- */
112 /* The symbols table is "hash-coded" into a disjoint union of linked */
113 /* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
114 /* that it's the last in its list) or the next in the list. */
116 /* Each list contains, in alphabetical order, all the symbols which share */
117 /* the same "hash code" (a numerical function of the text of the symbol */
118 /* name, designed with the aim that roughly equal numbers of symbols are */
119 /* given each possible hash code). The hash codes are 0 to HASH_TAB_SIZE */
120 /* (which is a memory setting) minus 1: start_of_list[h] gives the first */
121 /* symbol with hash code h, or -1 if no symbol exists with hash code h. */
123 /* Note that the running time of the symbol search algorithm is about */
125 /* O ( n^2 / HASH_TAB_SIZE ) */
127 /* (where n is the number of symbols in the program) so that it is a good */
128 /* idea to choose HASH_TAB_SIZE as large as conveniently possible. */
129 /* ------------------------------------------------------------------------- */
131 static int32 *start_of_list; /* Allocated array of size HASH_TAB_SIZE */
132 /* The next_entry field is part of the symbolinfo struct. */
134 /* ------------------------------------------------------------------------- */
135 /* Initialisation. */
136 /* ------------------------------------------------------------------------- */
138 static void init_symbol_banks(void)
140 for (i=0; i<HASH_TAB_SIZE; i++) start_of_list[i] = -1;
143 /* ------------------------------------------------------------------------- */
144 /* The hash coding we use is quite standard; the variable hashcode is */
145 /* expected to overflow a good deal. (The aim is to produce a number */
146 /* so that similar names do not produce the same number.) Note that */
147 /* 30011 is prime. It doesn't matter if the unsigned int to int cast */
148 /* behaves differently on different ports. */
149 /* ------------------------------------------------------------------------- */
151 int case_conversion_grid[128];
153 static void make_case_conversion_grid(void)
155 /* Assumes that A to Z are contiguous in the host OS character set:
156 true for ASCII but not for EBCDIC, for instance. */
159 for (i=0; i<128; i++) case_conversion_grid[i] = i;
160 for (i=0; i<26; i++) case_conversion_grid['A'+i]='a'+i;
163 extern int hash_code_from_string(char *p)
165 for (; *p; p++) hashcode=hashcode*30011 + case_conversion_grid[(uchar)*p];
166 return (int) (hashcode % HASH_TAB_SIZE);
169 extern int strcmpcis(char *p, char *q)
171 /* Case insensitive strcmp */
174 for (i=0;p[i] != 0;i++)
175 { pc = p[i]; if (isupper(pc)) pc = tolower(pc);
176 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
180 qc = q[i]; if (isupper(qc)) qc = tolower(qc);
184 /* ------------------------------------------------------------------------- */
186 extern void add_config_symbol_definition(char *symbol, int32 value)
189 if (symbol_definitions_count == symbol_definitions_size) {
190 int oldsize = symbol_definitions_size;
191 if (symbol_definitions_size == 0)
192 symbol_definitions_size = 4;
194 symbol_definitions_size *= 2;
195 my_recalloc(&symbol_definitions, sizeof(keyvalue_pair_t), oldsize,
196 symbol_definitions_size, "symbol definition table");
199 str = my_malloc(strlen(symbol)+1, "symbol name");
202 symbol_definitions[symbol_definitions_count].symbol = str;
203 symbol_definitions[symbol_definitions_count].value = value;
204 symbol_definitions_count++;
207 /* ------------------------------------------------------------------------- */
208 /* Symbol finding, creating, and removing. */
209 /* ------------------------------------------------------------------------- */
211 extern int get_symbol_index(char *p)
213 /* Return the index in the symbols array of symbol "p", or -1
214 if it isn't there. Does not create a new symbol or mark the
217 int32 new_entry, this;
219 int hashcode = hash_code_from_string(p);
221 this = start_of_list[hashcode];
224 { if (this == -1) break;
226 r = symbols[this].name;
227 new_entry = strcmpcis(r, p);
232 if (new_entry > 0) break;
234 this = symbols[this].next_entry;
235 } while (this != -1);
240 extern int symbol_index(char *p, int hashcode)
242 /* Return the index in the symbols array of symbol "p", creating a
243 new symbol with that name if it isn't already there.
245 New symbols are created with flag UNKNOWN_SFLAG, value 0x100
246 (a 2-byte quantity in Z-machine terms) and type CONSTANT_T.
248 The string "p" is undamaged. */
250 int32 new_entry, this, last;
254 if (hashcode == -1) hashcode = hash_code_from_string(p);
256 this = start_of_list[hashcode]; last = -1;
259 { if (this == -1) break;
261 r = symbols[this].name;
262 new_entry = strcmpcis(r, p);
265 if (track_unused_routines)
266 df_note_function_symbol(this);
269 if (new_entry > 0) break;
272 this = symbols[this].next_entry;
273 } while (this != -1);
275 if (symdef_trace_setting)
276 printf("Encountered symbol %d '%s'\n", no_symbols, p);
278 ensure_memory_list_available(&symbols_memlist, no_symbols+1);
279 if (debugfile_switch)
280 ensure_memory_list_available(&symbol_debug_info_memlist, no_symbols+1);
283 { symbols[no_symbols].next_entry=start_of_list[hashcode];
284 start_of_list[hashcode]=no_symbols;
287 { symbols[no_symbols].next_entry=this;
288 symbols[last].next_entry=no_symbols;
292 if (symbols_free_space+len+1 >= symbols_ceiling)
294 = my_malloc(SYMBOLS_CHUNK_SIZE, "symbol names chunk");
295 symbols_ceiling = symbols_free_space + SYMBOLS_CHUNK_SIZE;
296 ensure_memory_list_available(&symbol_name_space_chunks_memlist, no_symbol_name_space_chunks+1);
297 symbol_name_space_chunks[no_symbol_name_space_chunks++]
298 = symbols_free_space;
299 if (symbols_free_space+len+1 >= symbols_ceiling)
301 /* This should be impossible, since SYMBOLS_CHUNK_SIZE > MAX_IDENTIFIER_LENGTH. */
302 fatalerror("Symbol exceeds the maximum possible length");
306 strcpy(symbols_free_space, p);
307 symbols[no_symbols].name = symbols_free_space;
308 symbols_free_space += (len+1);
310 symbols[no_symbols].value = 0x100; /* ###-wrong? Would this fix the
311 unbound-symbol-causes-asm-error? */
312 symbols[no_symbols].flags = UNKNOWN_SFLAG;
313 symbols[no_symbols].marker = 0;
314 symbols[no_symbols].type = CONSTANT_T;
315 symbols[no_symbols].line = get_brief_location(&ErrorReport);
316 if (debugfile_switch)
317 { nullify_debug_file_position
318 (&symbol_debug_info[no_symbols].backpatch_pos);
319 nullify_debug_file_position
320 (&symbol_debug_info[no_symbols].replacement_backpatch_pos);
323 if (track_unused_routines)
324 df_note_function_symbol(no_symbols);
325 return(no_symbols++);
328 extern void end_symbol_scope(int k)
330 /* Remove the given symbol from the hash table, making it
331 invisible to symbol_index. This is used by the Undef directive.
332 If the symbol is not found, this silently does nothing.
336 j = hash_code_from_string(symbols[k].name);
337 if (start_of_list[j] == k)
338 { start_of_list[j] = symbols[k].next_entry;
341 j = start_of_list[j];
344 if (symbols[j].next_entry == k)
345 { symbols[j].next_entry = symbols[k].next_entry;
348 j = symbols[j].next_entry;
352 /* ------------------------------------------------------------------------- */
353 /* Printing diagnostics */
354 /* ------------------------------------------------------------------------- */
356 extern char *typename(int type)
359 /* These are the possible symbol types. Note that local variables
360 do not reside in the symbol table (for scope and efficiency
361 reasons) and actions have their own name-space (via routine
362 names with "Sub" appended). */
364 case ROUTINE_T: return("Routine");
365 case LABEL_T: return("Label");
366 case GLOBAL_VARIABLE_T: return("Global variable");
367 case ARRAY_T: return("Array");
368 case STATIC_ARRAY_T: return("Static array");
369 case CONSTANT_T: return("Defined constant");
370 case ATTRIBUTE_T: return("Attribute");
371 case PROPERTY_T: return("Property");
372 case INDIVIDUAL_PROPERTY_T: return("Individual property");
373 case OBJECT_T: return("Object");
374 case CLASS_T: return("Class");
375 case FAKE_ACTION_T: return("Fake action");
377 /* These are not symbol types, but they get printed in errors. */
378 case STRING_REQ_T: return("String");
379 case DICT_WORD_REQ_T: return("Dictionary word");
381 default: return("(Unknown type)");
385 static void describe_flags(int flags)
386 { if (flags & UNKNOWN_SFLAG) printf("(?) ");
387 if (flags & REPLACE_SFLAG) printf("(Replaced) ");
388 if (flags & USED_SFLAG) printf("(used) ");
389 if (flags & DEFCON_SFLAG) printf("(Defaulted) ");
390 if (flags & STUB_SFLAG) printf("(Stubbed) ");
391 if (flags & IMPORT_SFLAG) printf("(Imported) ");
392 if (flags & EXPORT_SFLAG) printf("(Exported) ");
393 if (flags & ALIASED_SFLAG) printf("(aliased) ");
394 if (flags & CHANGE_SFLAG) printf("(value will change) ");
395 if (flags & SYSTEM_SFLAG) printf("(System) ");
396 if (flags & INSF_SFLAG) printf("(created in sys file) ");
397 if (flags & UERROR_SFLAG) printf("('Unknown' error issued) ");
398 if (flags & ACTION_SFLAG) printf("(Action name) ");
399 if (flags & REDEFINABLE_SFLAG) printf("(Redefinable) ");
400 if (flags & STAR_SFLAG) printf("(*) ");
403 extern void describe_symbol(int k)
404 { printf("%4d %-16s %2d:%04d %04x %s ",
405 k, (symbols[k].name),
406 (int)(symbols[k].line.file_index),
407 (int)(symbols[k].line.line_number),
408 symbols[k].value, typename(symbols[k].type));
409 describe_flags(symbols[k].flags);
412 extern void list_symbols(int level)
414 for (k=0; k<no_symbols; k++)
416 ((symbols[k].flags & (SYSTEM_SFLAG + UNKNOWN_SFLAG + INSF_SFLAG)) == 0))
417 { describe_symbol(k); printf("\n");
422 /* Check that the operand is of the given symbol type (XXX_T). If wanttype2 is nonzero, that's a second allowable type.
423 Generate a warning if no match. */
424 extern void check_warn_symbol_type(const assembly_operand *AO, int wanttype, int wanttype2, char *context)
429 if (AO->symindex < 0)
431 /* This argument is not a symbol; it's a local variable, a literal, or a computed expression. */
432 /* We can recognize and type-check some literals. */
433 if (AO->marker == DWORD_MV) {
434 if (wanttype != DICT_WORD_REQ_T && wanttype2 != DICT_WORD_REQ_T)
435 symtype_warning(context, NULL, typename(DICT_WORD_REQ_T), typename(wanttype));
437 if (AO->marker == STRING_MV) {
438 if (wanttype != STRING_REQ_T && wanttype2 != STRING_REQ_T)
439 symtype_warning(context, NULL, typename(STRING_REQ_T), typename(wanttype));
444 sym = &symbols[AO->symindex];
447 if (symtype == GLOBAL_VARIABLE_T)
449 /* A global variable could have any value. No way to generate a warning. */
452 if (symtype == CONSTANT_T)
454 /* A constant could also have any value. This case also includes forward-declared constants (UNKNOWN_SFLAG). */
455 /* We try inferring its type by looking at the backpatch marker. Sadly, this only works for objects. (And not in Z-code, where object values are not backpatched.) */
456 if (sym->marker == OBJECT_MV) {
457 /* Continue with inferred type. */
466 if (!( (symtype == wanttype)
467 || (wanttype2 != 0 && symtype == wanttype2)))
469 symtype_warning(context, sym->name, typename(symtype), typename(wanttype));
473 /* Similar, but we allow any type that has a metaclass: Object, Class, String, or Routine.
474 Generate a warning if no match. */
475 extern void check_warn_symbol_has_metaclass(const assembly_operand *AO, char *context)
480 if (AO->symindex < 0)
482 /* This argument is not a symbol; it's a local variable, a literal, or a computed expression. */
483 /* We can recognize and type-check some literals. */
484 if (AO->marker == DWORD_MV) {
485 symtype_warning(context, NULL, typename(DICT_WORD_REQ_T), "Object/Class/Routine/String");
487 if (AO->marker == STRING_MV) {
488 /* Strings are good here. */
493 sym = &symbols[AO->symindex];
496 if (symtype == GLOBAL_VARIABLE_T)
498 /* A global variable could have any value. No way to generate a warning. */
501 if (symtype == CONSTANT_T)
503 /* A constant could also have any value. This case also includes forward-declared constants (UNKNOWN_SFLAG). */
504 /* We try inferring its type by looking at the backpatch marker. Sadly, this only works for objects. (And not in Z-code, where object values are not backpatched.) */
505 if (sym->marker == OBJECT_MV) {
506 /* Continue with inferred type. */
515 if (!(symtype == ROUTINE_T || symtype == CLASS_T || symtype == OBJECT_T))
517 symtype_warning(context, sym->name, typename(symtype), "Object/Class/Routine/String");
521 extern void issue_unused_warnings(void)
524 if (module_switch) return;
526 /* Update any ad-hoc variables that might help the library */
528 { global_initial_value[10]=statusline_flag;
530 /* Now back to mark anything necessary as used */
532 i = symbol_index("Main", -1);
533 if (!(symbols[i].flags & UNKNOWN_SFLAG)) symbols[i].flags |= USED_SFLAG;
535 for (i=0;i<no_symbols;i++)
536 { if (((symbols[i].flags
537 & (SYSTEM_SFLAG + UNKNOWN_SFLAG + EXPORT_SFLAG
538 + INSF_SFLAG + USED_SFLAG + REPLACE_SFLAG)) == 0)
539 && (symbols[i].type != OBJECT_T))
540 dbnu_warning(typename(symbols[i].type), symbols[i].name, symbols[i].line);
544 extern void issue_debug_symbol_warnings(void)
546 int value = get_symbol_index("DEBUG");
547 if (value >= 0 && (symbols[value].flags & USED_SFLAG) && !(symbols[value].flags & UNKNOWN_SFLAG)) {
548 value = get_symbol_index("debug_flag");
549 if (value >= 0 && (symbols[value].flags & USED_SFLAG) && (symbols[value].flags & UNKNOWN_SFLAG)) {
550 warning("DEBUG mode is on, but this story or library does not appear to support it");
555 /* ------------------------------------------------------------------------- */
556 /* These are arrays used only during story file (never module) creation, */
557 /* and not allocated until then. */
559 int32 *individual_name_strings; /* Packed addresses of Z-encoded
560 strings of the names of the
561 properties: this is an array
562 indexed by the property ID */
563 int32 *action_name_strings; /* Ditto for actions */
564 int32 *attribute_name_strings; /* Ditto for attributes */
565 int32 *array_name_strings; /* Ditto for arrays */
567 extern void write_the_identifier_names(void)
568 { int i, j, k, t, null_value; char idname_string[256];
569 static char unknown_attribute[20] = "<unknown attribute>";
571 for (i=0; i<no_individual_properties; i++)
572 individual_name_strings[i] = 0;
574 if (module_switch) return;
578 null_value = compile_string(unknown_attribute, STRCTX_SYMBOL);
579 for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
581 for (i=0; i<no_symbols; i++)
583 if ((t == INDIVIDUAL_PROPERTY_T) || (t == PROPERTY_T))
584 { if (symbols[i].flags & ALIASED_SFLAG)
585 { if (individual_name_strings[symbols[i].value] == 0)
586 { sprintf(idname_string, "%s", symbols[i].name);
588 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
589 { if ((symbols[j].type == symbols[i].type)
590 && (symbols[j].value == symbols[i].value))
591 { sprintf(idname_string+strlen(idname_string),
592 "/%s", symbols[j].name);
597 individual_name_strings[symbols[i].value]
598 = compile_string(idname_string, STRCTX_SYMBOL);
602 { sprintf(idname_string, "%s", symbols[i].name);
604 individual_name_strings[symbols[i].value]
605 = compile_string(idname_string, STRCTX_SYMBOL);
608 if (t == ATTRIBUTE_T)
609 { if (symbols[i].flags & ALIASED_SFLAG)
610 { if (attribute_name_strings[symbols[i].value] == null_value)
611 { sprintf(idname_string, "%s", symbols[i].name);
613 for (j=i+1, k=0; (j<no_symbols && k<3); j++)
614 { if ((symbols[j].type == symbols[i].type)
615 && (symbols[j].value == symbols[i].value))
616 { sprintf(idname_string+strlen(idname_string),
617 "/%s", symbols[j].name);
622 attribute_name_strings[symbols[i].value]
623 = compile_string(idname_string, STRCTX_SYMBOL);
627 { sprintf(idname_string, "%s", symbols[i].name);
629 attribute_name_strings[symbols[i].value]
630 = compile_string(idname_string, STRCTX_SYMBOL);
633 if (symbols[i].flags & ACTION_SFLAG)
634 { sprintf(idname_string, "%s", symbols[i].name);
635 idname_string[strlen(idname_string)-3] = 0;
637 if (debugfile_switch)
638 { debug_file_printf("<action>");
640 ("<identifier>##%s</identifier>", idname_string);
641 debug_file_printf("<value>%d</value>", symbols[i].value);
642 debug_file_printf("</action>");
645 action_name_strings[symbols[i].value]
646 = compile_string(idname_string, STRCTX_SYMBOL);
650 for (i=0; i<no_symbols; i++)
651 { if (symbols[i].type == FAKE_ACTION_T)
652 { sprintf(idname_string, "%s", symbols[i].name);
653 idname_string[strlen(idname_string)-3] = 0;
655 action_name_strings[symbols[i].value
656 - ((grammar_version_number==1)?256:4096) + no_actions]
657 = compile_string(idname_string, STRCTX_SYMBOL);
661 for (j=0; j<no_arrays; j++)
662 { i = arrays[j].symbol;
663 sprintf(idname_string, "%s", symbols[i].name);
665 array_name_strings[j]
666 = compile_string(idname_string, STRCTX_SYMBOL);
668 if (define_INFIX_switch)
669 { for (i=0; i<no_symbols; i++)
670 { if (symbols[i].type == GLOBAL_VARIABLE_T)
671 { sprintf(idname_string, "%s", symbols[i].name);
672 array_name_strings[no_arrays + symbols[i].value -16]
673 = compile_string(idname_string, STRCTX_SYMBOL);
677 for (i=0; i<no_named_routines; i++)
678 { sprintf(idname_string, "%s", symbols[named_routine_symbols[i]].name);
679 array_name_strings[no_arrays + no_globals + i]
680 = compile_string(idname_string, STRCTX_SYMBOL);
683 for (i=0, no_named_constants=0; i<no_symbols; i++)
684 { if (((symbols[i].type == OBJECT_T) || (symbols[i].type == CLASS_T)
685 || (symbols[i].type == CONSTANT_T))
686 && ((symbols[i].flags & (UNKNOWN_SFLAG+ACTION_SFLAG))==0))
687 { sprintf(idname_string, "%s", symbols[i].name);
688 array_name_strings[no_arrays + no_globals + no_named_routines
689 + no_named_constants++]
690 = compile_string(idname_string, STRCTX_SYMBOL);
697 /* ------------------------------------------------------------------------- */
698 /* Creating symbols */
699 /* ------------------------------------------------------------------------- */
701 static void assign_symbol_base(int index, int32 value, int type)
702 { symbols[index].value = value;
703 symbols[index].type = type;
704 if (symbols[index].flags & UNKNOWN_SFLAG)
705 { symbols[index].flags &= (~UNKNOWN_SFLAG);
706 if (is_systemfile()) symbols[index].flags |= INSF_SFLAG;
707 symbols[index].line = get_brief_location(&ErrorReport);
711 extern void assign_symbol(int index, int32 value, int type)
713 assign_symbol_base(index, value, type);
714 symbols[index].marker = 0;
715 if (symdef_trace_setting)
716 printf("Defined symbol %d '%s' as %d (%s)\n", index, symbols[index].name, value, typename(type));
719 extern void assign_marked_symbol(int index, int marker, int32 value, int type)
721 assign_symbol_base(index, value, type);
722 symbols[index].marker = marker;
723 if (symdef_trace_setting)
724 printf("Defined symbol %d '%s' as %s %d (%s)\n", index, symbols[index].name, describe_mv(marker), value, typename(type));
727 static void emit_debug_information_for_predefined_symbol
728 (char *name, int32 symbol, int32 value, int type)
729 { if (debugfile_switch)
732 debug_file_printf("<constant>");
733 debug_file_printf("<identifier>%s</identifier>", name);
734 write_debug_symbol_optional_backpatch(symbol);
735 debug_file_printf("</constant>");
737 case GLOBAL_VARIABLE_T:
738 debug_file_printf("<global-variable>");
739 debug_file_printf("<identifier>%s</identifier>", name);
740 debug_file_printf("<address>");
741 write_debug_global_backpatch(value);
742 debug_file_printf("</address>");
743 debug_file_printf("</global-variable>");
747 { compiler_error("Non-nothing object predefined");
749 debug_file_printf("<object>");
750 debug_file_printf("<identifier>%s</identifier>", name);
751 debug_file_printf("<value>0</value>");
752 debug_file_printf("</object>");
755 debug_file_printf("<attribute>");
756 debug_file_printf("<identifier>%s</identifier>", name);
757 debug_file_printf("<value>%d</value>", value);
758 debug_file_printf("</attribute>");
761 case INDIVIDUAL_PROPERTY_T:
762 debug_file_printf("<property>");
763 debug_file_printf("<identifier>%s</identifier>", name);
764 debug_file_printf("<value>%d</value>", value);
765 debug_file_printf("</property>");
769 ("Unable to emit debug information for predefined symbol");
775 static void create_symbol(char *p, int32 value, int type)
776 { int i = symbol_index(p, -1);
777 if (!(symbols[i].flags & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))) {
778 /* Symbol already defined! */
779 if (symbols[i].value == value && symbols[i].type == type) {
780 /* Special case: the symbol was already defined with this same
781 value. We let it pass. */
785 ebf_symbol_error("new symbol", p, typename(symbols[i].type), symbols[i].line);
789 symbols[i].value = value; symbols[i].type = type; symbols[i].line = blank_brief_location;
790 /* If the symbol already existed with REDEFINABLE_SFLAG, we keep that. */
791 symbols[i].flags = USED_SFLAG + SYSTEM_SFLAG + (symbols[i].flags & REDEFINABLE_SFLAG);
792 emit_debug_information_for_predefined_symbol(p, i, value, type);
795 static void create_rsymbol(char *p, int value, int type)
796 { int i = symbol_index(p, -1);
797 /* This is only called for a few symbols with known names.
798 They will not collide. */
799 symbols[i].value = value; symbols[i].type = type; symbols[i].line = blank_brief_location;
800 symbols[i].flags = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
801 emit_debug_information_for_predefined_symbol(p, i, value, type);
804 static void stockup_symbols(void)
807 create_symbol("TARGET_ZCODE", 0, CONSTANT_T);
809 create_symbol("TARGET_GLULX", 0, CONSTANT_T);
811 create_symbol("nothing", 0, OBJECT_T);
812 create_symbol("name", 1, PROPERTY_T);
814 create_symbol("true", 1, CONSTANT_T);
815 create_symbol("false", 0, CONSTANT_T);
817 /* Glulx defaults to GV2; Z-code to GV1 */
819 create_rsymbol("Grammar__Version", 1, CONSTANT_T);
821 create_rsymbol("Grammar__Version", 2, CONSTANT_T);
822 grammar_version_symbol = symbol_index("Grammar__Version", -1);
825 create_rsymbol("MODULE_MODE",0, CONSTANT_T);
827 if (runtime_error_checking_switch)
828 create_rsymbol("STRICT_MODE",0, CONSTANT_T);
830 if (define_DEBUG_switch)
831 create_rsymbol("DEBUG", 0, CONSTANT_T);
833 if (define_USE_MODULES_switch)
834 create_rsymbol("USE_MODULES",0, CONSTANT_T);
836 if (define_INFIX_switch)
837 { create_rsymbol("INFIX", 0, CONSTANT_T);
838 create_symbol("infix__watching", 0, ATTRIBUTE_T);
841 create_symbol("WORDSIZE", WORDSIZE, CONSTANT_T);
842 /* DICT_ENTRY_BYTES must be REDEFINABLE_SFLAG because the Version directive can change it. */
843 create_rsymbol("DICT_ENTRY_BYTES", DICT_ENTRY_BYTE_LENGTH, CONSTANT_T);
845 create_symbol("DICT_WORD_SIZE", ((version_number==3)?4:6), CONSTANT_T);
846 create_symbol("NUM_ATTR_BYTES", ((version_number==3)?4:6), CONSTANT_T);
849 create_symbol("DICT_WORD_SIZE", DICT_WORD_SIZE, CONSTANT_T);
850 create_symbol("DICT_CHAR_SIZE", DICT_CHAR_SIZE, CONSTANT_T);
851 if (DICT_CHAR_SIZE != 1)
852 create_symbol("DICT_IS_UNICODE", 1, CONSTANT_T);
853 create_symbol("NUM_ATTR_BYTES", NUM_ATTR_BYTES, CONSTANT_T);
854 create_symbol("GOBJFIELD_CHAIN", GOBJFIELD_CHAIN(), CONSTANT_T);
855 create_symbol("GOBJFIELD_NAME", GOBJFIELD_NAME(), CONSTANT_T);
856 create_symbol("GOBJFIELD_PROPTAB", GOBJFIELD_PROPTAB(), CONSTANT_T);
857 create_symbol("GOBJFIELD_PARENT", GOBJFIELD_PARENT(), CONSTANT_T);
858 create_symbol("GOBJFIELD_SIBLING", GOBJFIELD_SIBLING(), CONSTANT_T);
859 create_symbol("GOBJFIELD_CHILD", GOBJFIELD_CHILD(), CONSTANT_T);
860 create_symbol("GOBJ_EXT_START", 1+NUM_ATTR_BYTES+6*WORDSIZE, CONSTANT_T);
861 create_symbol("GOBJ_TOTAL_LENGTH", 1+NUM_ATTR_BYTES+6*WORDSIZE+GLULX_OBJECT_EXT_BYTES, CONSTANT_T);
862 create_symbol("INDIV_PROP_START", INDIV_PROP_START, CONSTANT_T);
866 create_symbol("temp_global", 255, GLOBAL_VARIABLE_T);
867 create_symbol("temp__global2", 254, GLOBAL_VARIABLE_T);
868 create_symbol("temp__global3", 253, GLOBAL_VARIABLE_T);
869 create_symbol("temp__global4", 252, GLOBAL_VARIABLE_T);
870 create_symbol("self", 251, GLOBAL_VARIABLE_T);
871 create_symbol("sender", 250, GLOBAL_VARIABLE_T);
872 create_symbol("sw__var", 249, GLOBAL_VARIABLE_T);
874 create_symbol("sys__glob0", 16, GLOBAL_VARIABLE_T);
875 create_symbol("sys__glob1", 17, GLOBAL_VARIABLE_T);
876 create_symbol("sys__glob2", 18, GLOBAL_VARIABLE_T);
878 create_symbol("create", 64, INDIVIDUAL_PROPERTY_T);
879 create_symbol("recreate", 65, INDIVIDUAL_PROPERTY_T);
880 create_symbol("destroy", 66, INDIVIDUAL_PROPERTY_T);
881 create_symbol("remaining", 67, INDIVIDUAL_PROPERTY_T);
882 create_symbol("copy", 68, INDIVIDUAL_PROPERTY_T);
883 create_symbol("call", 69, INDIVIDUAL_PROPERTY_T);
884 create_symbol("print", 70, INDIVIDUAL_PROPERTY_T);
885 create_symbol("print_to_array",71, INDIVIDUAL_PROPERTY_T);
888 /* In Glulx, these system globals are entered in order, not down
890 create_symbol("temp_global", MAX_LOCAL_VARIABLES+0,
892 create_symbol("temp__global2", MAX_LOCAL_VARIABLES+1,
894 create_symbol("temp__global3", MAX_LOCAL_VARIABLES+2,
896 create_symbol("temp__global4", MAX_LOCAL_VARIABLES+3,
898 create_symbol("self", MAX_LOCAL_VARIABLES+4,
900 create_symbol("sender", MAX_LOCAL_VARIABLES+5,
902 create_symbol("sw__var", MAX_LOCAL_VARIABLES+6,
905 /* These are almost certainly meaningless, and can be removed. */
906 create_symbol("sys__glob0", MAX_LOCAL_VARIABLES+7,
908 create_symbol("sys__glob1", MAX_LOCAL_VARIABLES+8,
910 create_symbol("sys__glob2", MAX_LOCAL_VARIABLES+9,
913 /* value of statusline_flag to be written later */
914 create_symbol("sys_statusline_flag", MAX_LOCAL_VARIABLES+10,
917 /* These are created in order, but not necessarily at a fixed
919 create_symbol("create", INDIV_PROP_START+0,
920 INDIVIDUAL_PROPERTY_T);
921 create_symbol("recreate", INDIV_PROP_START+1,
922 INDIVIDUAL_PROPERTY_T);
923 create_symbol("destroy", INDIV_PROP_START+2,
924 INDIVIDUAL_PROPERTY_T);
925 create_symbol("remaining", INDIV_PROP_START+3,
926 INDIVIDUAL_PROPERTY_T);
927 create_symbol("copy", INDIV_PROP_START+4,
928 INDIVIDUAL_PROPERTY_T);
929 create_symbol("call", INDIV_PROP_START+5,
930 INDIVIDUAL_PROPERTY_T);
931 create_symbol("print", INDIV_PROP_START+6,
932 INDIVIDUAL_PROPERTY_T);
933 create_symbol("print_to_array",INDIV_PROP_START+7,
934 INDIVIDUAL_PROPERTY_T);
936 /* Floating-point constants. Note that FLOAT_NINFINITY is not
937 -FLOAT_INFINITY, because float negation doesn't work that
938 way. Also note that FLOAT_NAN is just one of many possible
939 "not-a-number" values. */
940 create_symbol("FLOAT_INFINITY", 0x7F800000, CONSTANT_T);
941 create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
942 create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
945 if (symbol_definitions && symbol_definitions_count) {
947 for (ix=0; ix<symbol_definitions_count; ix++) {
948 char *str = symbol_definitions[ix].symbol;
949 int32 val = symbol_definitions[ix].value;
950 create_symbol(str, val, CONSTANT_T);
955 /* ------------------------------------------------------------------------- */
956 /* The symbol replacement table. This is needed only for the */
957 /* "Replace X Y" directive. */
958 /* ------------------------------------------------------------------------- */
960 extern void add_symbol_replacement_mapping(int original, int renamed)
964 if (original == renamed) {
965 error_named("A routine cannot be 'Replace'd to itself:", symbols[original].name);
969 if (symbol_replacements_count == symbol_replacements_size) {
970 int oldsize = symbol_replacements_size;
971 if (symbol_replacements_size == 0)
972 symbol_replacements_size = 4;
974 symbol_replacements_size *= 2;
975 my_recalloc(&symbol_replacements, sizeof(value_pair_t), oldsize,
976 symbol_replacements_size, "symbol replacement table");
979 /* If the original form is already in our table, report an error.
980 Same goes if the replaced form is already in the table as an
981 original. (Other collision cases have already been
984 for (ix=0; ix<symbol_replacements_count; ix++) {
985 if (original == symbol_replacements[ix].original_symbol) {
986 error_named("A routine cannot be 'Replace'd to more than one new name:", symbols[original].name);
988 if (renamed == symbol_replacements[ix].original_symbol) {
989 error_named("A routine cannot be 'Replace'd to a 'Replace'd name:", symbols[original].name);
993 symbol_replacements[symbol_replacements_count].original_symbol = original;
994 symbol_replacements[symbol_replacements_count].renamed_symbol = renamed;
995 symbol_replacements_count++;
998 extern int find_symbol_replacement(int *value)
1000 int changed = FALSE;
1003 if (!symbol_replacements)
1006 for (ix=0; ix<symbol_replacements_count; ix++) {
1007 if (*value == symbol_replacements[ix].original_symbol) {
1008 *value = symbol_replacements[ix].renamed_symbol;
1016 /* ------------------------------------------------------------------------- */
1017 /* The dead-function removal optimization. */
1018 /* ------------------------------------------------------------------------- */
1020 int track_unused_routines; /* set if either WARN_UNUSED_ROUTINES or
1021 OMIT_UNUSED_ROUTINES is nonzero */
1022 int df_dont_note_global_symbols; /* temporarily set at times in parsing */
1023 static int df_tables_closed; /* set at end of compiler pass */
1025 typedef struct df_function_struct df_function_t;
1026 typedef struct df_reference_struct df_reference_t;
1028 struct df_function_struct {
1029 char *name; /* borrowed reference, generally to the symbs[] table */
1030 brief_location source_line; /* copied from routine_starts_line */
1031 int sysfile; /* does this occur in a system file? */
1032 uint32 address; /* function offset in zcode_area (not the final address) */
1033 uint32 newaddress; /* function offset after stripping */
1036 df_reference_t *refs; /* chain of references made *from* this function */
1039 df_function_t *funcnext; /* in forward functions order */
1040 df_function_t *todonext; /* in the todo chain */
1041 df_function_t *next; /* in the hash table */
1044 struct df_reference_struct {
1045 uint32 address; /* function offset in zcode_area (not the final address) */
1046 int symbol; /* index in symbols array */
1048 df_reference_t *refsnext; /* in the function's refs chain */
1049 df_reference_t *next; /* in the hash table */
1052 /* Bitmask flags for how functions are used: */
1053 #define DF_USAGE_GLOBAL (1<<0) /* In a global variable, array, etc */
1054 #define DF_USAGE_EMBEDDED (1<<1) /* An anonymous function in a property */
1055 #define DF_USAGE_MAIN (1<<2) /* Main() or Main__() */
1056 #define DF_USAGE_FUNCTION (1<<3) /* Used from another used function */
1058 #define DF_FUNCTION_HASH_BUCKETS (1023)
1060 /* Table of all compiled functions. (Only created if track_unused_routines
1061 is set.) This is a hash table. */
1062 static df_function_t **df_functions;
1063 /* List of all compiled functions, in address order. The first entry
1064 has address DF_NOT_IN_FUNCTION, and stands in for the global namespace. */
1065 static df_function_t *df_functions_head;
1066 static df_function_t *df_functions_tail;
1067 /* Used during output_file(), to track how far the code-area output has
1069 static df_function_t *df_iterator;
1071 /* Array of all compiled functions in address order. (Does not include
1072 the global namespace entry.) This is generated only if needed. */
1073 static df_function_t **df_functions_sorted;
1074 static int df_functions_sorted_count;
1076 #define DF_NOT_IN_FUNCTION ((uint32)0xFFFFFFFF)
1077 #define DF_SYMBOL_HASH_BUCKETS (4095)
1079 /* Map of what functions reference what other functions. (Only created if
1080 track_unused_routines is set.) */
1081 static df_reference_t **df_symbol_map;
1083 /* Globals used while a function is being compiled. When a function
1084 *isn't* being compiled, df_current_function_addr will be DF_NOT_IN_FUNCTION
1085 and df_current_function will refer to the global namespace record. */
1086 static df_function_t *df_current_function;
1087 static char *df_current_function_name;
1088 static uint32 df_current_function_addr;
1090 /* Size totals for compiled code. These are only meaningful if
1091 track_unused_routines is true. (If we're only doing WARN_UNUSED_ROUTINES,
1092 these values will be set, but the "after" value will not affect the
1093 final game file.) */
1094 uint32 df_total_size_before_stripping;
1095 uint32 df_total_size_after_stripping;
1097 /* When we begin compiling a function, call this to note that fact.
1098 Any symbol referenced from now on will be associated with the function.
1100 extern void df_note_function_start(char *name, uint32 address,
1101 int embedded_flag, brief_location source_line)
1103 df_function_t *func;
1106 if (df_tables_closed)
1107 error("Internal error in stripping: Tried to start a new function after tables were closed.");
1109 /* We retain the name only for debugging output. Note that embedded
1110 functions all show up as "<embedded>" -- their "obj.prop" name
1111 never gets stored in permanent memory. */
1112 df_current_function_name = name;
1113 df_current_function_addr = address;
1115 func = my_malloc(sizeof(df_function_t), "df function entry");
1116 memset(func, 0, sizeof(df_function_t));
1118 func->address = address;
1119 func->source_line = source_line;
1120 func->sysfile = (address == DF_NOT_IN_FUNCTION || is_systemfile());
1121 /* An embedded function is stored in an object property, so we
1122 consider it to be used a priori. */
1124 func->usage |= DF_USAGE_EMBEDDED;
1126 if (!df_functions_head) {
1127 df_functions_head = func;
1128 df_functions_tail = func;
1131 df_functions_tail->funcnext = func;
1132 df_functions_tail = func;
1135 bucket = address % DF_FUNCTION_HASH_BUCKETS;
1136 func->next = df_functions[bucket];
1137 df_functions[bucket] = func;
1139 df_current_function = func;
1142 /* When we're done compiling a function, call this. Any symbol referenced
1143 from now on will be associated with the global namespace.
1145 extern void df_note_function_end(uint32 endaddress)
1147 df_current_function->length = endaddress - df_current_function->address;
1149 df_current_function_name = NULL;
1150 df_current_function_addr = DF_NOT_IN_FUNCTION;
1151 df_current_function = df_functions_head; /* the global namespace */
1154 /* Find the function record for a given address. (Addresses are offsets
1157 static df_function_t *df_function_for_address(uint32 address)
1159 int bucket = address % DF_FUNCTION_HASH_BUCKETS;
1160 df_function_t *func;
1161 for (func = df_functions[bucket]; func; func = func->next) {
1162 if (func->address == address)
1168 /* Whenever a function is referenced, we call this to note who called it.
1170 extern void df_note_function_symbol(int symbol)
1172 int bucket, symtype;
1173 df_reference_t *ent;
1175 /* If the compiler pass is over, looking up symbols does not create
1176 a global reference. */
1177 if (df_tables_closed)
1179 /* In certain cases during parsing, looking up symbols does not
1180 create a global reference. (For example, when reading the name
1181 of a function being defined.) */
1182 if (df_dont_note_global_symbols)
1184 /* If we're compiling an unreachable statement, no reference. */
1185 if (execution_never_reaches_here)
1188 /* We are only interested in functions, or forward-declared symbols
1189 that might turn out to be functions. */
1190 symtype = symbols[symbol].type;
1191 if (symtype != ROUTINE_T && symtype != CONSTANT_T)
1193 if (symtype == CONSTANT_T && !(symbols[symbol].flags & UNKNOWN_SFLAG))
1196 bucket = (df_current_function_addr ^ (uint32)symbol) % DF_SYMBOL_HASH_BUCKETS;
1197 for (ent = df_symbol_map[bucket]; ent; ent = ent->next) {
1198 if (ent->address == df_current_function_addr && ent->symbol == symbol)
1202 /* Create a new reference entry in df_symbol_map. */
1203 ent = my_malloc(sizeof(df_reference_t), "df symbol map entry");
1204 ent->address = df_current_function_addr;
1205 ent->symbol = symbol;
1206 ent->next = df_symbol_map[bucket];
1207 df_symbol_map[bucket] = ent;
1209 /* Add the reference to the function's entry as well. */
1210 /* The current function is the most recently added, so it will be
1211 at the top of its bucket. That makes this call fast. Unless
1212 we're in global scope, in which case it might be slower.
1213 (I suppose we could cache the df_function_t pointer of the
1214 current function, to speed things up.) */
1215 if (!df_current_function || df_current_function_addr != df_current_function->address)
1216 compiler_error("DF: df_current_function does not match current address.");
1217 ent->refsnext = df_current_function->refs;
1218 df_current_function->refs = ent;
1221 /* This does the hard work of figuring out what functions are truly dead.
1222 It's called near the end of run_pass() in inform.c.
1224 extern void locate_dead_functions(void)
1226 df_function_t *func, *tofunc;
1227 df_reference_t *ent;
1230 if (!track_unused_routines)
1231 compiler_error("DF: locate_dead_functions called, but function references have not been mapped");
1233 df_tables_closed = TRUE;
1234 df_current_function = NULL;
1236 /* Note that Main__ was tagged as global implicitly during
1237 compile_initial_routine(). Main was tagged during
1238 issue_unused_warnings(). But for the sake of thoroughness,
1239 we'll mark them specially. */
1241 ix = symbol_index("Main__", -1);
1242 if (symbols[ix].type == ROUTINE_T) {
1243 uint32 addr = symbols[ix].value * (glulx_mode ? 1 : scale_factor);
1244 tofunc = df_function_for_address(addr);
1246 tofunc->usage |= DF_USAGE_MAIN;
1248 ix = symbol_index("Main", -1);
1249 if (symbols[ix].type == ROUTINE_T) {
1250 uint32 addr = symbols[ix].value * (glulx_mode ? 1 : scale_factor);
1251 tofunc = df_function_for_address(addr);
1253 tofunc->usage |= DF_USAGE_MAIN;
1256 /* Go through all the functions referenced at the global level;
1257 mark them as used. */
1259 func = df_functions_head;
1260 if (!func || func->address != DF_NOT_IN_FUNCTION) {
1261 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1265 for (ent = func->refs; ent; ent=ent->refsnext) {
1267 int symbol = ent->symbol;
1268 if (symbols[symbol].type != ROUTINE_T)
1270 addr = symbols[symbol].value * (glulx_mode ? 1 : scale_factor);
1271 tofunc = df_function_for_address(addr);
1273 error_named("Internal error in stripping: global ROUTINE_T symbol is not found in df_function map:", symbols[symbol].name);
1276 /* A function may be marked here more than once. That's fine. */
1277 tofunc->usage |= DF_USAGE_GLOBAL;
1280 /* Perform a breadth-first search through functions, starting with
1281 the ones that are known to be used at the top level. */
1283 df_function_t *todo, *todotail;
1284 df_function_t *func;
1288 for (func = df_functions_head; func; func = func->funcnext) {
1289 if (func->address == DF_NOT_IN_FUNCTION)
1291 if (func->usage == 0)
1298 todotail->todonext = func;
1303 /* todo is a linked list of functions which are known to be
1304 used. If a function's usage field is nonzero, it must be
1305 either be on the todo list or have come off already (in
1306 which case processed will be set). */
1309 /* Pop the next function. */
1311 todo = todo->todonext;
1315 if (func->processed)
1316 error_named("Internal error in stripping: function has been processed twice:", func->name);
1318 /* Go through the function's symbol references. Any
1319 reference to a routine, push it into the todo list (if
1320 it isn't there already). */
1322 for (ent = func->refs; ent; ent=ent->refsnext) {
1324 int symbol = ent->symbol;
1325 if (symbols[symbol].type != ROUTINE_T)
1327 addr = symbols[symbol].value * (glulx_mode ? 1 : scale_factor);
1328 tofunc = df_function_for_address(addr);
1330 error_named("Internal error in stripping: function ROUTINE_T symbol is not found in df_function map:", symbols[symbol].name);
1336 /* Not yet known to be used. Add it to the todo list. */
1337 tofunc->usage |= DF_USAGE_FUNCTION;
1343 todotail->todonext = tofunc;
1348 func->processed = TRUE;
1352 /* Go through all functions; figure out how much space is consumed,
1353 with and without useless functions. */
1356 df_function_t *func;
1358 df_total_size_before_stripping = 0;
1359 df_total_size_after_stripping = 0;
1361 for (func = df_functions_head; func; func = func->funcnext) {
1362 if (func->address == DF_NOT_IN_FUNCTION)
1365 if (func->address != df_total_size_before_stripping)
1366 compiler_error("DF: Address gap in function list");
1368 df_total_size_before_stripping += func->length;
1370 func->newaddress = df_total_size_after_stripping;
1371 df_total_size_after_stripping += func->length;
1374 if (!glulx_mode && (df_total_size_after_stripping % scale_factor != 0))
1375 compiler_error("DF: New function address is not aligned");
1377 if (WARN_UNUSED_ROUTINES && !func->usage) {
1378 if (!func->sysfile || WARN_UNUSED_ROUTINES >= 2)
1379 uncalled_routine_warning("Routine", func->name, func->source_line);
1384 /* df_measure_hash_table_usage(); */
1387 /* Given an original function address, return where it winds up after
1388 unused-function stripping. The function must not itself be unused.
1390 Both the input and output are offsets, and already scaled by
1393 This is used by the backpatching system.
1395 extern uint32 df_stripped_address_for_address(uint32 addr)
1397 df_function_t *func;
1399 if (!track_unused_routines)
1400 compiler_error("DF: df_stripped_address_for_address called, but function references have not been mapped");
1403 func = df_function_for_address(addr*scale_factor);
1405 func = df_function_for_address(addr);
1408 compiler_error("DF: Unable to find function while backpatching");
1412 compiler_error("DF: Tried to backpatch a function address which should be stripped");
1415 return func->newaddress / scale_factor;
1417 return func->newaddress;
1420 /* Given an address in the function area, return where it winds up after
1421 unused-function stripping. The address can be a function or anywhere
1422 within the function. If the address turns out to be in a stripped
1423 function, returns 0 (and sets *stripped).
1425 The input and output are offsets, but *not* scaled.
1427 This is only used by the debug-file system.
1429 uint32 df_stripped_offset_for_code_offset(uint32 offset, int *stripped)
1431 df_function_t *func;
1436 if (!track_unused_routines)
1437 compiler_error("DF: df_stripped_offset_for_code_offset called, but function references have not been mapped");
1439 if (!df_functions_sorted) {
1440 /* To do this efficiently, we need a binary-searchable table. Fine,
1441 we'll make one. Include both used and unused functions. */
1443 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1444 if (func->address == DF_NOT_IN_FUNCTION)
1448 df_functions_sorted_count = count;
1450 df_functions_sorted = my_calloc(sizeof(df_function_t *), df_functions_sorted_count, "df function sorted table");
1452 for (func = df_functions_head, count = 0; func; func = func->funcnext) {
1453 if (func->address == DF_NOT_IN_FUNCTION)
1455 df_functions_sorted[count] = func;
1460 /* Do a binary search. Maintain beg <= res < end, where res is the
1461 function containing the desired address. */
1463 end = df_functions_sorted_count;
1465 /* Set stripped flag until we decide on a non-stripped function. */
1471 error("DF: offset_for_code_offset: Could not locate address.");
1475 func = df_functions_sorted[beg];
1476 if (func->usage == 0)
1479 return func->newaddress + (offset - func->address);
1481 new = (beg + end) / 2;
1482 if (new <= beg || new >= end)
1483 compiler_error("DF: binary search went off the rails");
1485 func = df_functions_sorted[new];
1486 if (offset >= func->address) {
1487 if (offset < func->address+func->length) {
1488 /* We don't need to loop further; decide here. */
1489 if (func->usage == 0)
1492 return func->newaddress + (offset - func->address);
1502 /* The output_file() routines in files.c have to run down the list of
1503 functions, deciding who is in and who is out. But I don't want to
1504 export the df_function_t list structure. Instead, I provide this
1505 silly iterator pair. Set it up with df_prepare_function_iterate();
1506 then repeatedly call df_next_function_iterate().
1509 extern void df_prepare_function_iterate(void)
1511 df_iterator = df_functions_head;
1512 if (!df_iterator || df_iterator->address != DF_NOT_IN_FUNCTION)
1513 compiler_error("DF: Global namespace entry is not at the head of the chain.");
1514 if (!df_iterator->funcnext || df_iterator->funcnext->address != 0)
1515 compiler_error("DF: First function entry is not second in the chain.");
1518 /* This returns the end of the next function, and whether the next function
1521 extern uint32 df_next_function_iterate(int *funcused)
1524 df_iterator = df_iterator->funcnext;
1527 return df_total_size_before_stripping+1;
1529 *funcused = (df_iterator->usage != 0);
1530 return df_iterator->address + df_iterator->length;
1533 /* ========================================================================= */
1534 /* Data structure management routines */
1535 /* ------------------------------------------------------------------------- */
1537 extern void init_symbols_vars(void)
1540 start_of_list = NULL;
1541 symbol_debug_info = NULL;
1543 symbol_name_space_chunks = NULL;
1544 no_symbol_name_space_chunks = 0;
1545 symbols_free_space=NULL;
1546 symbols_ceiling=NULL;
1550 symbol_replacements = NULL;
1551 symbol_replacements_count = 0;
1552 symbol_replacements_size = 0;
1554 make_case_conversion_grid();
1556 track_unused_routines = (WARN_UNUSED_ROUTINES || OMIT_UNUSED_ROUTINES);
1557 df_tables_closed = FALSE;
1558 df_symbol_map = NULL;
1559 df_functions = NULL;
1560 df_functions_head = NULL;
1561 df_functions_tail = NULL;
1562 df_current_function = NULL;
1563 df_functions_sorted = NULL;
1564 df_functions_sorted_count = 0;
1567 extern void symbols_begin_pass(void)
1569 df_total_size_before_stripping = 0;
1570 df_total_size_after_stripping = 0;
1571 df_dont_note_global_symbols = FALSE;
1575 extern void symbols_allocate_arrays(void)
1577 initialise_memory_list(&symbols_memlist,
1578 sizeof(symbolinfo), 6400, (void**)&symbols,
1580 if (debugfile_switch)
1582 initialise_memory_list(&symbol_debug_info_memlist,
1583 sizeof(symboldebuginfo), 6400, (void**)&symbol_debug_info,
1584 "symbol debug backpatch info");
1586 start_of_list = my_calloc(sizeof(int32), HASH_TAB_SIZE,
1587 "hash code list beginnings");
1589 initialise_memory_list(&symbol_name_space_chunks_memlist,
1590 sizeof(char *), 32, (void**)&symbol_name_space_chunks,
1591 "symbol names chunk addresses");
1593 if (track_unused_routines) {
1594 df_tables_closed = FALSE;
1596 df_symbol_map = my_calloc(sizeof(df_reference_t *), DF_SYMBOL_HASH_BUCKETS, "df symbol-map hash table");
1597 memset(df_symbol_map, 0, sizeof(df_reference_t *) * DF_SYMBOL_HASH_BUCKETS);
1599 df_functions = my_calloc(sizeof(df_function_t *), DF_FUNCTION_HASH_BUCKETS, "df function hash table");
1600 memset(df_functions, 0, sizeof(df_function_t *) * DF_FUNCTION_HASH_BUCKETS);
1601 df_functions_head = NULL;
1602 df_functions_tail = NULL;
1604 df_functions_sorted = NULL;
1605 df_functions_sorted_count = 0;
1607 df_note_function_start("<global namespace>", DF_NOT_IN_FUNCTION, FALSE, blank_brief_location);
1608 df_note_function_end(DF_NOT_IN_FUNCTION);
1609 /* Now df_current_function is df_functions_head. */
1612 init_symbol_banks();
1615 /* Allocated as needed */
1616 symbol_replacements = NULL;
1618 /* Allocated during story file construction, not now */
1619 individual_name_strings = NULL;
1620 attribute_name_strings = NULL;
1621 action_name_strings = NULL;
1622 array_name_strings = NULL;
1625 extern void symbols_free_arrays(void)
1628 for (i=0; i<no_symbol_name_space_chunks; i++)
1629 my_free(&(symbol_name_space_chunks[i]),
1630 "symbol names chunk");
1632 deallocate_memory_list(&symbol_name_space_chunks_memlist);
1634 deallocate_memory_list(&symbols_memlist);
1635 if (debugfile_switch)
1637 deallocate_memory_list(&symbol_debug_info_memlist);
1639 my_free(&start_of_list, "hash code list beginnings");
1641 if (symbol_replacements)
1642 my_free(&symbol_replacements, "symbol replacement table");
1644 if (df_symbol_map) {
1645 for (i=0; i<DF_SYMBOL_HASH_BUCKETS; i++) {
1646 df_reference_t *ent = df_symbol_map[i];
1648 df_reference_t *next = ent->next;
1649 my_free(&ent, "df symbol map entry");
1653 my_free(&df_symbol_map, "df symbol-map hash table");
1655 if (df_functions_sorted) {
1656 my_free(&df_functions, "df function sorted table");
1659 for (i=0; i<DF_FUNCTION_HASH_BUCKETS; i++) {
1660 df_function_t *func = df_functions[i];
1662 df_function_t *next = func->next;
1663 my_free(&func, "df function entry");
1667 my_free(&df_functions, "df function hash table");
1669 df_functions_head = NULL;
1670 df_functions_tail = NULL;
1672 if (individual_name_strings != NULL)
1673 my_free(&individual_name_strings, "property name strings");
1674 if (action_name_strings != NULL)
1675 my_free(&action_name_strings, "action name strings");
1676 if (attribute_name_strings != NULL)
1677 my_free(&attribute_name_strings, "attribute name strings");
1678 if (array_name_strings != NULL)
1679 my_free(&array_name_strings, "array name strings");
1682 /* ========================================================================= */