1 /* ------------------------------------------------------------------------- */
2 /* "linker" : For compiling and linking modules */
4 /* Part of Inform 6.33 */
5 /* copyright (c) Graham Nelson 1993 - 2014 */
7 /* ------------------------------------------------------------------------- */
11 memory_block link_data_area
;
12 uchar
*link_data_holding_area
, *link_data_top
;
13 /* Start, current top, size of */
14 int32 link_data_size
; /* link data table being written */
15 /* (holding import/export names) */
16 extern int32
*action_symbol
;
18 /* ------------------------------------------------------------------------- */
20 /* ------------------------------------------------------------------------- */
22 extern char *describe_mv(int mval
)
24 { case NULL_MV
: return("null");
26 /* Marker values used in ordinary story file backpatching */
28 case DWORD_MV
: return("dictionary word");
29 case STRING_MV
: return("string literal");
30 case INCON_MV
: return("system constant");
31 case IROUTINE_MV
: return("routine");
32 case VROUTINE_MV
: return("veneer routine");
33 case ARRAY_MV
: return("internal array");
34 case NO_OBJS_MV
: return("the number of objects");
35 case INHERIT_MV
: return("inherited common p value");
36 case INDIVPT_MV
: return("indiv prop table address");
37 case INHERIT_INDIV_MV
: return("inherited indiv p value");
38 case MAIN_MV
: return("ref to Main");
39 case SYMBOL_MV
: return("ref to symbol value");
41 /* Additional marker values used in module backpatching */
43 case VARIABLE_MV
: return("global variable");
44 case IDENT_MV
: return("prop identifier number");
45 case ACTION_MV
: return("action");
46 case OBJECT_MV
: return("internal object");
48 /* Record types in the import/export table (not really marker
51 case EXPORT_MV
: return("Export ");
52 case EXPORTSF_MV
: return("Export sf");
53 case EXPORTAC_MV
: return("Export ##");
54 case IMPORT_MV
: return("Import ");
56 return("** No such MV **");
59 /* ------------------------------------------------------------------------- */
60 /* Import/export records */
61 /* ------------------------------------------------------------------------- */
63 typedef struct importexport_s
72 static void describe_importexport(ImportExport
*I
)
73 { printf("%8s %20s %04d %04x %s\n",
74 describe_mv(I
->module_value
), I
->symbol_name
,
75 I
->symbol_number
, I
->symbol_value
, typename(I
->symbol_type
));
78 /* ========================================================================= */
79 /* Linking in external modules: this code is run when the external */
80 /* program hits a Link directive. */
81 /* ------------------------------------------------------------------------- */
82 /* This map is between global variable numbers in the module and in the */
83 /* external program: variables_map[n] will be the external global variable */
84 /* no for module global variable no n. (The entries [0] to [15] are not */
86 /* ------------------------------------------------------------------------- */
88 static int variables_map
[256], actions_map
[256];
94 /* ------------------------------------------------------------------------- */
95 /* These are offsets within the module: */
96 /* ------------------------------------------------------------------------- */
98 static int32 m_code_offset
, m_strs_offset
, m_static_offset
, m_dict_offset
,
99 m_vars_offset
, m_objs_offset
, m_props_offset
, m_class_numbers
,
100 m_individuals_offset
, m_individuals_length
;
102 static int m_no_objects
, m_no_globals
, p_no_globals
, lowest_imported_global_no
;
104 int32
*xref_table
; int xref_top
;
105 int32
*property_identifier_map
;
106 int *accession_numbers_map
;
107 int32 routine_replace
[64],
108 routine_replace_with
[64]; int no_rr
;
110 /* ------------------------------------------------------------------------- */
111 /* Reading and writing bytes/words in the module (as loaded in), indexing */
112 /* via "marker addresses". */
113 /* ------------------------------------------------------------------------- */
115 static int32
read_marker_address(uchar
*p
, int size
,
116 int zmachine_area
, int32 offset
)
118 /* A routine to read the value referred to by the marker address
119 (zmachine_area, offset): size is 1 for byte, 2 for word, and the
120 module itself resides at p. */
124 switch(zmachine_area
)
126 case DYNAMIC_ARRAY_ZA
:
127 addr
= m_vars_offset
; break;
129 addr
= m_code_offset
; break;
130 case STATIC_STRINGS_ZA
:
131 addr
= m_strs_offset
; break;
133 addr
= m_dict_offset
; break;
135 addr
= m_objs_offset
; break;
137 addr
= m_props_offset
; break;
138 case INDIVIDUAL_PROP_ZA
:
139 addr
= m_individuals_offset
; break;
141 if (size
== 1) return p
[addr
+offset
];
142 return 256*p
[addr
+offset
] + p
[addr
+offset
+1];
145 static void write_marker_address(uchar
*p
, int size
,
146 int zmachine_area
, int32 offset
, int32 value
)
148 /* Similar, but to write to it. */
152 switch(zmachine_area
)
154 case DYNAMIC_ARRAY_ZA
:
155 addr
= m_vars_offset
; break;
157 addr
= m_code_offset
; break;
158 case STATIC_STRINGS_ZA
:
159 addr
= m_strs_offset
; break;
161 addr
= m_dict_offset
; break;
163 addr
= m_objs_offset
; break;
165 addr
= m_props_offset
; break;
166 case INDIVIDUAL_PROP_ZA
:
167 addr
= m_individuals_offset
; break;
169 if (size
== 1) { p
[addr
+offset
] = value
%256; return; }
170 p
[addr
+offset
] = value
/256;
171 p
[addr
+offset
+1] = value
%256;
176 static int get_next_record(uchar
*p
)
178 int record_type
= p
[m_read_pos
++];
185 IE
.module_value
= record_type
;
186 i
=p
[m_read_pos
++]; IE
.symbol_number
= 256*i
+ p
[m_read_pos
++];
187 IE
.symbol_type
= p
[m_read_pos
++];
188 if (record_type
!= IMPORT_MV
) IE
.backpatch
= p
[m_read_pos
++];
189 i
=p
[m_read_pos
++]; IE
.symbol_value
= 256*i
+ p
[m_read_pos
++];
190 IE
.symbol_name
= (char *) (p
+m_read_pos
);
191 m_read_pos
+= strlen((char *) (p
+m_read_pos
))+1;
192 if (linker_trace_level
>= 2) describe_importexport(&IE
);
195 printf("Marker value of %d\n", record_type
);
196 compiler_error("Link: illegal import/export marker value");
202 static char link_errorm
[128];
204 static void accept_export(void)
205 { int32 index
, map_to
= IE
.symbol_value
% 0x10000;
206 index
= symbol_index(IE
.symbol_name
, -1);
208 xref_table
[IE
.symbol_number
] = index
;
210 if (!(sflags
[index
] & UNKNOWN_SFLAG
))
211 { if (IE
.module_value
== EXPORTAC_MV
)
212 { if ((!(sflags
[index
] & ACTION_SFLAG
))
213 && (stypes
[index
] != FAKE_ACTION_T
))
215 "action name clash with", IE
.symbol_name
);
218 if (stypes
[index
] == IE
.symbol_type
)
219 { switch(IE
.symbol_type
)
221 if ((!(svals
[index
] == IE
.symbol_value
))
222 || (IE
.backpatch
!= 0))
224 "program and module give differing values of", IE
.symbol_name
);
226 case INDIVIDUAL_PROPERTY_T
:
227 property_identifier_map
[IE
.symbol_value
] = svals
[index
];
230 if ((IE
.module_value
== EXPORTSF_MV
)
231 && (sflags
[index
] & REPLACE_SFLAG
))
235 "%s '%s' in both program and module",
236 typename(IE
.symbol_type
), IE
.symbol_name
);
237 link_error(link_errorm
);
242 { sprintf(link_errorm
,
243 "'%s' has type %s in program but type %s in module",
244 IE
.symbol_name
, typename(stypes
[index
]),
245 typename(IE
.symbol_type
));
246 link_error(link_errorm
);
250 { if (IE
.module_value
== EXPORTAC_MV
)
251 { IE
.symbol_value
= no_actions
;
252 action_symbol
[no_actions
++] = index
;
253 if (linker_trace_level
>= 4)
254 printf("Creating action ##%s\n", (char *) symbs
[index
]);
257 switch(IE
.symbol_type
)
259 if ((IE
.module_value
== EXPORTSF_MV
)
260 && (sflags
[index
] & REPLACE_SFLAG
))
261 { routine_replace
[no_rr
] = IE
.symbol_value
;
262 routine_replace_with
[no_rr
++] = index
;
265 IE
.symbol_value
+= (zmachine_pc
/scale_factor
);
269 IE
.symbol_value
+= no_objects
;
272 IE
.symbol_value
+= dynamic_array_area_size
- (MAX_GLOBAL_VARIABLES
*2);
274 case GLOBAL_VARIABLE_T
:
277 "failed because too many extra global variables needed");
280 variables_map
[16 + m_no_globals
++] = 16 + no_globals
;
281 set_variable_value(no_globals
, IE
.symbol_value
);
282 IE
.symbol_value
= 16 + no_globals
++;
284 case INDIVIDUAL_PROPERTY_T
:
285 property_identifier_map
[IE
.symbol_value
]
286 = no_individual_properties
;
287 IE
.symbol_value
= no_individual_properties
++;
289 if (debugfile_switch
)
290 { debug_file_printf("<property>");
292 ("<identifier>%s</identifier>", IE
.symbol_name
);
294 ("<value>%d</value>", IE
.symbol_value
);
295 debug_file_printf("</property>");
300 assign_symbol(index
, IE
.backpatch
*0x10000 + IE
.symbol_value
,
302 if (IE
.backpatch
!= 0) sflags
[index
] |= CHANGE_SFLAG
;
303 sflags
[index
] |= EXPORT_SFLAG
;
304 if (IE
.module_value
== EXPORTSF_MV
)
305 sflags
[index
] |= INSF_SFLAG
;
306 if (IE
.module_value
== EXPORTAC_MV
)
307 sflags
[index
] |= ACTION_SFLAG
;
310 if (IE
.module_value
== EXPORTAC_MV
)
311 { if (linker_trace_level
>= 4)
312 printf("Map %d '%s' to %d\n",
313 IE
.symbol_value
, (char *) (symbs
[index
]), svals
[index
]);
314 actions_map
[map_to
] = svals
[index
];
318 static void accept_import(void)
321 index
= symbol_index(IE
.symbol_name
, -1);
322 sflags
[index
] |= USED_SFLAG
;
323 xref_table
[IE
.symbol_number
] = index
;
325 if (!(sflags
[index
] & UNKNOWN_SFLAG
))
326 { switch (IE
.symbol_type
)
328 case GLOBAL_VARIABLE_T
:
329 if (stypes
[index
] != GLOBAL_VARIABLE_T
)
331 "module (wrongly) declared this a variable:", IE
.symbol_name
);
332 variables_map
[IE
.symbol_value
] = svals
[index
];
333 if (IE
.symbol_value
< lowest_imported_global_no
)
334 lowest_imported_global_no
= IE
.symbol_value
;
337 switch(stypes
[index
])
340 "this attribute is undeclared within module:", IE
.symbol_name
);; break;
343 "this property is undeclared within module:", IE
.symbol_name
); break;
344 case INDIVIDUAL_PROPERTY_T
:
354 "this was referred to as a constant, but isn't:", IE
.symbol_name
);
361 { switch (IE
.symbol_type
)
363 case GLOBAL_VARIABLE_T
:
364 if (stypes
[index
] != GLOBAL_VARIABLE_T
)
366 "Module tried to import a Global variable not defined here:",
368 variables_map
[IE
.symbol_value
] = 16;
369 if (IE
.symbol_value
< lowest_imported_global_no
)
370 lowest_imported_global_no
= IE
.symbol_value
;
376 static int32
backpatch_backpatch(int32 v
)
377 { switch(backpatch_marker
)
379 /* Backpatches made now which are final */
383 backpatch_marker
= NULL_MV
;
387 if ((v
<0) || (v
>=256) || (actions_map
[v
] == -1))
388 { link_error("unmapped action number");
389 printf("*** Link: unmapped action number %d ***", v
);
394 backpatch_marker
= NULL_MV
;
398 { int f
= v
& 0x8000;
399 v
= f
+ property_identifier_map
[v
-f
];
400 backpatch_marker
= NULL_MV
;
405 backpatch_marker
= NULL_MV
;
406 if (v
< lowest_imported_global_no
)
407 { v
= v
+ p_no_globals
; break;
409 if (variables_map
[v
] == -1)
410 { printf("** Unmapped variable %d! **\n", v
);
411 variables_map
[v
] = 16;
412 link_error("unmapped variable error"); break;
414 v
= variables_map
[v
];
417 /* Backpatch values which are themselves being backpatched */
420 v
+= individuals_length
;
425 if ((v
<0) || (v
>=no_symbols
))
426 { printf("** Symbol number %d cannot be crossreferenced **\n", v
);
427 link_error("symbol crossreference error"); v
=0;
433 v
+= static_strings_extent
/scale_factor
;
438 for (i
=0;i
<no_rr
;i
++)
439 if (v
== routine_replace
[i
])
440 { v
= routine_replace_with
[i
];
441 backpatch_marker
= SYMBOL_MV
;
444 v
+= zmachine_pc
/scale_factor
;
453 if (v
< (MAX_GLOBAL_VARIABLES
*2))
454 { v
= 2*(variables_map
[v
/2 + 16] - 16);
457 { v
+= dynamic_array_area_size
- (MAX_GLOBAL_VARIABLES
*2);
462 v
= accession_numbers_map
[v
];
466 v
+= properties_table_size
;
469 case INHERIT_INDIV_MV
:
470 v
+= individuals_length
;
476 static void backpatch_module_image(uchar
*p
,
477 int marker_value
, int zmachine_area
, int32 offset
)
478 { int size
= (marker_value
>=0x80)?1:2; int32 v
;
479 marker_value
&= 0x7f;
481 backpatch_marker
= marker_value
;
483 if (zmachine_area
== PROP_DEFAULTS_ZA
) return;
485 if (linker_trace_level
>= 3)
486 printf("Backpatch %s area %d offset %04x size %d: ",
487 describe_mv(marker_value
), zmachine_area
, offset
, size
);
489 v
= read_marker_address(p
, size
, zmachine_area
, offset
);
490 if (linker_trace_level
>= 3) printf("%04x ", v
);
492 v
= backpatch_backpatch(v
);
494 write_marker_address(p
, size
, zmachine_area
, offset
, v
);
495 if (linker_trace_level
>= 3) printf("%04x\n", v
);
498 /* ------------------------------------------------------------------------- */
499 /* The main routine: linking in a module with the given filename. */
500 /* ------------------------------------------------------------------------- */
502 char current_module_filename
[128];
504 void link_module(char *given_filename
)
509 int32 last
, i
, j
, k
, l
, m
, vn
, len
, size
, link_offset
, module_size
, map
,
510 max_property_identifier
, symbols_base
= no_symbols
;
512 strcpy(current_module_filename
, given_filename
);
514 /* (1) Load in the module to link */
518 { i
= translate_link_filename(i
, filename
, given_filename
);
519 fin
=fopen(filename
,"rb");
520 } while ((fin
== NULL
) && (i
!= 0));
523 { error_named("Couldn't open module file", filename
); return;
526 for (i
=0;i
<64;i
++) p0
[i
]=fgetc(fin
);
529 if ((vn
<65) || (vn
>75))
530 { error_named("File isn't a module:", filename
);
534 if (vn
!= 64 + version_number
)
537 "module compiled as Version %d (so it can't link\
538 into this V%d game):", vn
-64, version_number
);
539 error_named(ebuff
, filename
);
543 module_size
= (256*p0
[26] + p0
[27])*scale_factor
;
544 p
= my_malloc(module_size
+ 16, "link module storage");
545 /* The + 16 allows for rounding errors */
547 for (k
=0;k
<64;k
++) p
[k
] = p0
[k
];
548 for (k
=64;k
<module_size
;k
++) p
[k
] = fgetc(fin
);
551 if ((p0
[52] != 0) || (p0
[53] != 0))
552 { /* Then the module contains a character set table */
553 if (alphabet_modified
)
554 { k
= FALSE
; m
= 256*p0
[52] + p0
[53];
555 for (i
=0;i
<3;i
++) for (j
=0;j
<26;j
++)
556 { l
= alphabet
[i
][j
]; if (l
== '~') l
= '\"';
557 if (l
!= p
[m
]) k
= TRUE
;
560 link_error("module and game both define non-standard character sets, \
567 { if (alphabet_modified
) k
= TRUE
;
571 link_error("module and game use different character sets");
574 if (i
> MODULE_VERSION_NUMBER
)
575 warning_named("module has a more advanced format than this release \
576 of the Inform 6 compiler knows about: it may not link in correctly", filename
);
578 /* (2) Calculate offsets: see the header-writing code in "tables.c" */
580 map
= (256*p
[6] + p
[7]);
581 for (i
=0; i
<16; i
++) module_map
[i
] = 256*p
[map
+ i
*2] + p
[map
+ i
*2 + 1];
583 m_vars_offset
= (256*p
[12] + p
[13]);
584 m_static_offset
= (256*p
[14] + p
[15]);
585 m_dict_offset
= (256*p
[8] + p
[9]);
586 m_code_offset
= (256*p
[4] + p
[5]);
588 /* (3) Read the "module map" table */
590 if (linker_trace_level
>=4)
591 { printf("[Reading module map:\n");
592 for (i
=0; i
<16; i
++) printf("%04x ", module_map
[i
]);
596 m_objs_offset
= module_map
[0];
597 m_props_offset
= module_map
[1];
598 m_strs_offset
= scale_factor
*module_map
[2];
599 m_class_numbers
= module_map
[3];
600 m_individuals_offset
= module_map
[4];
601 m_individuals_length
= module_map
[5];
603 for (i
=16;i
<256;i
++) variables_map
[i
] = -1;
604 for (i
=0;i
<16;i
++) variables_map
[i
] = i
;
605 for (i
=LOWEST_SYSTEM_VAR_NUMBER
;i
<256;i
++) variables_map
[i
] = i
;
607 for (i
=0;i
<256;i
++) actions_map
[i
] = -1;
609 xref_table
= my_calloc(sizeof(int32
), module_map
[6],
610 "linker cross-references table");
611 for (i
=0;i
<module_map
[6];i
++) xref_table
[i
] = -1;
613 max_property_identifier
= module_map
[7];
614 property_identifier_map
= my_calloc(sizeof(int32
), max_property_identifier
,
615 "property identifier map");
616 for (i
=0; i
<max_property_identifier
; i
++)
617 property_identifier_map
[i
] = i
;
619 m_no_objects
= module_map
[8];
620 link_offset
= module_map
[9];
622 m_no_globals
= 0; p_no_globals
= no_globals
;
623 lowest_imported_global_no
=236;
627 if ((linker_trace_level
>=1) || transcript_switch
)
628 { char link_banner
[128];
630 "[Linking release %d.%c%c%c%c%c%c of module '%s' (size %dK)]",
631 p
[2]*256 + p
[3], p
[18], p
[19], p
[20], p
[21], p
[22], p
[23],
632 filename
, module_size
/1024);
633 if (linker_trace_level
>= 1) printf("%s\n", link_banner
);
634 if (transcript_switch
)
635 write_to_transcript_file(link_banner
);
638 /* (4) Merge in the dictionary */
640 if (linker_trace_level
>= 2)
641 printf("Merging module's dictionary at %04x\n", m_dict_offset
);
642 k
=m_dict_offset
; k
+=p
[k
]+1;
644 size
= p
[k
]*256 + p
[k
+1]; k
+=2;
646 accession_numbers_map
= my_calloc(sizeof(int), size
,
647 "dictionary accession numbers map");
649 for (i
=0;i
<size
;i
++, k
+=len
)
651 word_to_ascii(p
+k
,word
);
652 if (linker_trace_level
>= 3)
653 printf("%03d %04x '%s' %02x %02x %02x\n",i
,k
,
654 word
, p
[k
+len
-3], p
[k
+len
-2], p
[k
+len
-1]);
656 accession_numbers_map
[i
]
657 = dictionary_add(word
, p
[k
+len
-3], p
[k
+len
-2], p
[k
+len
-1]);
660 /* (5) Run through import/export table */
662 m_read_pos
= module_map
[9];
663 if (linker_trace_level
>=2)
664 printf("Import/export table is at byte offset %04x\n", m_read_pos
);
667 { record_type
= get_next_record(p
);
668 if (((record_type
== EXPORT_MV
) || (record_type
== EXPORTSF_MV
))
669 && (IE
.symbol_type
== INDIVIDUAL_PROPERTY_T
))
670 { int32 si
= symbol_index(IE
.symbol_name
, -1);
671 property_identifier_map
[IE
.symbol_value
] = svals
[si
];
677 accept_export(); break;
679 accept_import(); break;
681 } while (record_type
!= 0);
683 if ((linker_trace_level
>= 4) && (no_rr
!= 0))
684 { printf("Replaced routine addresses:\n");
685 for (i
=0; i
<no_rr
; i
++)
686 { printf("Replace code offset %04x with %04x\n",
687 routine_replace
[i
], routine_replace_with
[i
]);
691 if (linker_trace_level
>= 4)
692 { printf("Symbol cross-references table:\n");
693 for (i
=0; i
<module_map
[6]; i
++)
694 { if (xref_table
[i
] != -1)
695 printf("module %4d -> story file '%s'\n", i
,
696 (char *) symbs
[xref_table
[i
]]);
700 if (linker_trace_level
>= 4)
701 { printf("Action numbers map:\n");
702 for (i
=0; i
<256; i
++)
703 if (actions_map
[i
] != -1)
704 printf("%3d -> %3d\n", i
, actions_map
[i
]);
707 if ((linker_trace_level
>= 4) && (max_property_identifier
> 72))
708 { printf("Property identifier number map:\n");
709 for (i
=72; i
<max_property_identifier
; i
++)
710 { printf("module %04x -> program %04x\n",
711 i
, property_identifier_map
[i
]);
715 /* (6) Backpatch the backpatch markers attached to exported symbols */
717 for (i
=symbols_base
; i
<no_symbols
; i
++)
718 { if ((sflags
[i
] & CHANGE_SFLAG
) && (sflags
[i
] & EXPORT_SFLAG
))
719 { backpatch_marker
= svals
[i
]/0x10000;
720 j
= svals
[i
] % 0x10000;
722 j
= backpatch_backpatch(j
);
724 svals
[i
] = backpatch_marker
*0x10000 + j
;
725 if (backpatch_marker
== 0) sflags
[i
] &= (~(CHANGE_SFLAG
));
729 /* (7) Run through the Z-code backpatch table */
731 for (i
=module_map
[11]; i
<module_map
[11]+module_map
[12]; i
+= 3)
732 { int marker_value
= p
[i
];
733 int32 offset
= 256*p
[i
+1] + p
[i
+2];
735 switch(marker_value
& 0x7f)
740 backpatch_module_image(p
, marker_value
, ZCODE_ZA
, offset
);
743 backpatch_module_image(p
, marker_value
, ZCODE_ZA
, offset
);
744 write_byte_to_memory_block(&zcode_backpatch_table
,
745 zcode_backpatch_size
++, backpatch_marker
);
746 write_byte_to_memory_block(&zcode_backpatch_table
,
747 zcode_backpatch_size
++, (offset
+ zmachine_pc
)/256);
748 write_byte_to_memory_block(&zcode_backpatch_table
,
749 zcode_backpatch_size
++, (offset
+ zmachine_pc
)%256);
754 /* (8) Run through the Z-machine backpatch table */
756 for (i
=module_map
[13]; i
<module_map
[13]+module_map
[14]; i
+= 4)
757 { int marker_value
= p
[i
], zmachine_area
= p
[i
+1];
758 int32 offset
= 256*p
[i
+2] + p
[i
+3];
764 backpatch_module_image(p
, marker_value
, zmachine_area
, offset
);
767 backpatch_module_image(p
, marker_value
, zmachine_area
, offset
);
768 switch(zmachine_area
)
769 { case PROP_DEFAULTS_ZA
:
772 offset
+= properties_table_size
; break;
773 case INDIVIDUAL_PROP_ZA
:
774 offset
+= individuals_length
; break;
775 case DYNAMIC_ARRAY_ZA
:
776 if (offset
< (MAX_GLOBAL_VARIABLES
*2))
777 { offset
= 2*(variables_map
[offset
/2 + 16] - 16);
780 { offset
+= dynamic_array_area_size
- (MAX_GLOBAL_VARIABLES
*2);
784 backpatch_zmachine(backpatch_marker
, zmachine_area
, offset
);
789 /* (9) Adjust initial values of variables */
791 if (linker_trace_level
>= 3)
792 printf("\nFinal variables map, Module -> Main:\n");
795 if (variables_map
[i
]!=-1)
796 { if (linker_trace_level
>=2)
797 printf("%d->%d ",i
,variables_map
[i
]);
798 if (i
<lowest_imported_global_no
)
799 { int32 j
= read_marker_address(p
, 2,
800 DYNAMIC_ARRAY_ZA
, 2*(i
-16));
801 set_variable_value(variables_map
[i
]-16, j
);
802 if (linker_trace_level
>=2)
803 printf("(set var %d to %d) ",
804 variables_map
[i
], j
);
807 if (linker_trace_level
>=2) printf("\n");
809 /* (10) Glue in the dynamic array data */
811 i
= m_static_offset
- m_vars_offset
- MAX_GLOBAL_VARIABLES
*2;
812 if (dynamic_array_area_size
+ i
>= MAX_STATIC_DATA
)
813 memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA
);
815 if (linker_trace_level
>= 2)
816 printf("Inserting dynamic array area, %04x to %04x, at %04x\n",
817 m_vars_offset
+ MAX_GLOBAL_VARIABLES
*2, m_static_offset
,
818 variables_offset
+ dynamic_array_area_size
);
820 { dynamic_array_area
[dynamic_array_area_size
+k
]
821 = p
[m_vars_offset
+MAX_GLOBAL_VARIABLES
*2+k
];
823 dynamic_array_area_size
+=i
;
825 /* (11) Glue in the code area */
827 if (linker_trace_level
>= 2)
828 printf("Inserting code area, %04x to %04x, at code offset %04x (+%04x)\n",
829 m_code_offset
, m_strs_offset
, code_offset
, zmachine_pc
);
831 for (k
=m_code_offset
;k
<m_strs_offset
;k
++)
832 { if (temporary_files_switch
)
833 { fputc(p
[k
],Temp2_fp
);
837 write_byte_to_memory_block(&zcode_area
, zmachine_pc
++, p
[k
]);
840 /* (12) Glue in the static strings area */
842 if (linker_trace_level
>= 2)
843 printf("Inserting strings area, %04x to %04x, \
844 at strings offset %04x (+%04x)\n",
845 m_strs_offset
, link_offset
, strings_offset
,
846 static_strings_extent
);
847 for (k
=m_strs_offset
;k
<link_offset
;k
++)
848 { if (temporary_files_switch
)
849 { fputc(p
[k
], Temp1_fp
);
850 static_strings_extent
++;
853 write_byte_to_memory_block(&static_strings_area
,
854 static_strings_extent
++, p
[k
]);
857 /* (13) Append the class object-numbers table: note that modules
858 provide extra information in this table */
862 { j
= p
[i
]*256 + p
[i
+1]; i
+=2;
865 class_object_numbers
[no_classes
] = j
+ no_objects
;
866 j
= p
[i
]*256 + p
[i
+1]; i
+=2;
867 class_begins_at
[no_classes
++] = j
+ properties_table_size
;
871 /* (14) Glue on the object tree */
873 if ((linker_trace_level
>=2) && (m_no_objects
>0))
874 printf("Joining on object tree of size %d\n", m_no_objects
);
876 for (i
=0, k
=no_objects
, last
=m_props_offset
;i
<m_no_objects
;i
++)
877 { objectsz
[no_objects
].atts
[0]=p
[m_objs_offset
+14*i
];
878 objectsz
[no_objects
].atts
[1]=p
[m_objs_offset
+14*i
+1];
879 objectsz
[no_objects
].atts
[2]=p
[m_objs_offset
+14*i
+2];
880 objectsz
[no_objects
].atts
[3]=p
[m_objs_offset
+14*i
+3];
881 objectsz
[no_objects
].atts
[4]=p
[m_objs_offset
+14*i
+4];
882 objectsz
[no_objects
].atts
[5]=p
[m_objs_offset
+14*i
+5];
883 objectsz
[no_objects
].parent
=
884 (p
[m_objs_offset
+14*i
+6])*256+p
[m_objs_offset
+14*i
+7];
885 objectsz
[no_objects
].next
=
886 (p
[m_objs_offset
+14*i
+8])*256+p
[m_objs_offset
+14*i
+9];
887 objectsz
[no_objects
].child
=
888 (p
[m_objs_offset
+14*i
+10])*256+p
[m_objs_offset
+14*i
+11];
889 if (linker_trace_level
>=4)
890 printf("Module objects[%d] has %d,%d,%d\n",
891 i
,objectsz
[no_objects
].parent
,
892 objectsz
[no_objects
].next
,objectsz
[no_objects
].child
);
893 if (objectsz
[no_objects
].parent
== 0x7fff)
894 { objectsz
[no_objects
].parent
= 1;
895 if (objectsz
[1].child
== 0)
896 { objectsz
[1].child
= no_objects
+1;
899 { int j1
, j2
= objectsz
[1].child
;
902 j2
= objectsz
[j2
].next
;
904 objectsz
[j1
].next
= no_objects
+1;
906 objectsz
[no_objects
].next
= 0;
909 if (objectsz
[no_objects
].parent
>0) objectsz
[no_objects
].parent
+= k
;
910 if (objectsz
[no_objects
].next
>0) objectsz
[no_objects
].next
+= k
;
911 if (objectsz
[no_objects
].child
>0) objectsz
[no_objects
].child
+= k
;
912 objectsz
[no_objects
].propsize
=
913 (p
[m_objs_offset
+14*i
+12])*256+p
[m_objs_offset
+14*i
+13];
914 last
+= objectsz
[no_objects
].propsize
;
915 if (linker_trace_level
>=4)
916 printf("Objects[%d] has %d,%d,%d\n",
917 no_objects
,objectsz
[no_objects
].parent
,
918 objectsz
[no_objects
].next
,objectsz
[no_objects
].child
);
922 /* (15) Glue on the properties */
924 if (last
>m_props_offset
)
925 { i
= m_static_offset
- m_vars_offset
- MAX_GLOBAL_VARIABLES
*2;
926 if (dynamic_array_area_size
+ i
>= MAX_STATIC_DATA
)
927 memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA
);
929 if (linker_trace_level
>= 2)
930 printf("Inserting object properties area, %04x to %04x, at +%04x\n",
931 m_props_offset
, last
, properties_table_size
);
932 for (k
=0;k
<last
-m_props_offset
;k
++)
933 properties_table
[properties_table_size
++] = p
[m_props_offset
+k
];
936 /* (16) Bitwise OR Flags 2 (Z-machine requirements flags) */
938 j
= p
[16]*256 + p
[17];
939 for (i
=0, k
=1;i
<16;i
++, k
=k
*2) flags2_requirements
[i
] |= ((j
/k
)%2);
941 /* (17) Append the individual property values table */
943 i
= m_individuals_length
;
944 if (individuals_length
+ i
>= MAX_INDIV_PROP_TABLE_SIZE
)
945 memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
946 MAX_INDIV_PROP_TABLE_SIZE
);
948 if (linker_trace_level
>= 2)
949 printf("Inserting individual prop tables area, %04x to %04x, at +%04x\n",
950 m_individuals_offset
, m_individuals_offset
+ i
,
953 { individuals_table
[individuals_length
+ k
]
954 = p
[m_individuals_offset
+ k
];
956 individuals_length
+= i
;
960 if (linker_trace_level
>= 2)
961 printf("Link complete\n");
963 my_free(&p
, "link module storage");
964 my_free(&xref_table
, "linker cross-references table");
965 my_free(&property_identifier_map
, "property identifier map");
966 my_free(&accession_numbers_map
, "accession numbers map");
969 /* ========================================================================= */
970 /* Writing imports, exports and markers to the link data table during */
971 /* module compilation */
972 /* ------------------------------------------------------------------------- */
973 /* Writing to the link data table */
974 /* ------------------------------------------------------------------------- */
976 static void write_link_byte(int x
)
977 { *link_data_top
=(unsigned char) x
; link_data_top
++; link_data_size
++;
978 if (subtract_pointers(link_data_top
,link_data_holding_area
)
979 >= MAX_LINK_DATA_SIZE
)
980 { memoryerror("MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE
);
984 extern void flush_link_data(void)
986 j
= subtract_pointers(link_data_top
, link_data_holding_area
);
987 if (temporary_files_switch
)
988 for (i
=0;i
<j
;i
++) fputc(link_data_holding_area
[i
], Temp3_fp
);
991 write_byte_to_memory_block(&link_data_area
, link_data_size
-j
+i
,
992 link_data_holding_area
[i
]);
993 link_data_top
=link_data_holding_area
;
996 static void write_link_word(int32 x
)
997 { write_link_byte(x
/256); write_link_byte(x
%256);
1000 static void write_link_string(char *s
)
1002 for (i
=0; s
[i
]!=0; i
++) write_link_byte(s
[i
]);
1006 /* ------------------------------------------------------------------------- */
1007 /* Exports and imports */
1008 /* ------------------------------------------------------------------------- */
1010 static void export_symbols(void)
1011 { int symbol_number
;
1013 for (symbol_number
= 0; symbol_number
< no_symbols
; symbol_number
++)
1014 { int export_flag
= FALSE
, import_flag
= FALSE
;
1016 if (stypes
[symbol_number
]==GLOBAL_VARIABLE_T
)
1017 { if (svals
[symbol_number
] < LOWEST_SYSTEM_VAR_NUMBER
)
1018 { if (sflags
[symbol_number
] & IMPORT_SFLAG
)
1021 if (!(sflags
[symbol_number
] & SYSTEM_SFLAG
))
1026 { if (!(sflags
[symbol_number
] & SYSTEM_SFLAG
))
1027 { if (sflags
[symbol_number
] & UNKNOWN_SFLAG
)
1028 { if (sflags
[symbol_number
] & IMPORT_SFLAG
)
1032 switch(stypes
[symbol_number
])
1039 default: export_flag
= TRUE
;
1045 { if (linker_trace_level
>= 1)
1046 { IE
.module_value
= EXPORT_MV
;
1047 IE
.symbol_number
= symbol_number
;
1048 IE
.symbol_type
= stypes
[symbol_number
];
1049 IE
.symbol_value
= svals
[symbol_number
];
1050 IE
.symbol_name
= (char *) (symbs
[symbol_number
]);
1051 describe_importexport(&IE
);
1054 if (sflags
[symbol_number
] & ACTION_SFLAG
)
1055 write_link_byte(EXPORTAC_MV
);
1057 if (sflags
[symbol_number
] & INSF_SFLAG
)
1058 write_link_byte(EXPORTSF_MV
);
1060 write_link_byte(EXPORT_MV
);
1062 write_link_word(symbol_number
);
1063 write_link_byte(stypes
[symbol_number
]);
1064 if (sflags
[symbol_number
] & CHANGE_SFLAG
)
1065 write_link_byte(svals
[symbol_number
] / 0x10000);
1066 else write_link_byte(0);
1067 write_link_word(svals
[symbol_number
] % 0x10000);
1068 write_link_string((char *) (symbs
[symbol_number
]));
1073 { if (linker_trace_level
>= 1)
1074 { IE
.module_value
= IMPORT_MV
;
1075 IE
.symbol_number
= symbol_number
;
1076 IE
.symbol_type
= stypes
[symbol_number
];
1077 IE
.symbol_value
= svals
[symbol_number
];
1078 IE
.symbol_name
= (char *) (symbs
[symbol_number
]);
1079 describe_importexport(&IE
);
1082 write_link_byte(IMPORT_MV
);
1083 write_link_word(symbol_number
);
1084 write_link_byte(stypes
[symbol_number
]);
1085 write_link_word(svals
[symbol_number
]);
1086 write_link_string((char *) (symbs
[symbol_number
]));
1092 /* ------------------------------------------------------------------------- */
1093 /* Marking for later importation */
1094 /* ------------------------------------------------------------------------- */
1096 int mv_vref
=LOWEST_SYSTEM_VAR_NUMBER
-1;
1098 void import_symbol(int32 symbol_number
)
1099 { sflags
[symbol_number
] |= IMPORT_SFLAG
;
1100 switch(stypes
[symbol_number
])
1101 { case GLOBAL_VARIABLE_T
:
1102 assign_symbol(symbol_number
, mv_vref
--, stypes
[symbol_number
]);
1107 /* ========================================================================= */
1108 /* Data structure management routines */
1109 /* ------------------------------------------------------------------------- */
1111 extern void init_linker_vars(void)
1112 { link_data_size
= 0;
1113 initialise_memory_block(&link_data_area
);
1116 extern void linker_begin_pass(void)
1117 { link_data_top
= link_data_holding_area
;
1120 extern void linker_endpass(void)
1126 extern void linker_allocate_arrays(void)
1127 { if (!module_switch
)
1128 link_data_holding_area
1129 = my_malloc(64, "link data holding area");
1131 link_data_holding_area
1132 = my_malloc(MAX_LINK_DATA_SIZE
, "link data holding area");
1135 extern void linker_free_arrays(void)
1136 { my_free(&link_data_holding_area
, "link data holding area");
1137 deallocate_memory_block(&link_data_area
);
1140 /* ========================================================================= */