1
/* ------------------------------------------------------------------------- */
2
/* "linker" : For compiling and linking modules */
4
/* Part of Inform 6.30 */
5
/* copyright (c) Graham Nelson 1993 - 2004 */
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++;
290
assign_symbol(index, IE.backpatch*0x10000 + IE.symbol_value,
292
if (IE.backpatch != 0) sflags[index] |= CHANGE_SFLAG;
293
sflags[index] |= EXPORT_SFLAG;
294
if (IE.module_value == EXPORTSF_MV)
295
sflags[index] |= INSF_SFLAG;
296
if (IE.module_value == EXPORTAC_MV)
297
sflags[index] |= ACTION_SFLAG;
300
if (IE.module_value == EXPORTAC_MV)
301
{ if (linker_trace_level >= 4)
302
printf("Map %d '%s' to %d\n",
303
IE.symbol_value, (char *) (symbs[index]), svals[index]);
304
actions_map[map_to] = svals[index];
308
static void accept_import(void)
311
index = symbol_index(IE.symbol_name, -1);
312
sflags[index] |= USED_SFLAG;
313
xref_table[IE.symbol_number] = index;
315
if (!(sflags[index] & UNKNOWN_SFLAG))
316
{ switch (IE.symbol_type)
318
case GLOBAL_VARIABLE_T:
319
if (stypes[index] != GLOBAL_VARIABLE_T)
321
"module (wrongly) declared this a variable:", IE.symbol_name);
322
variables_map[IE.symbol_value] = svals[index];
323
if (IE.symbol_value < lowest_imported_global_no)
324
lowest_imported_global_no = IE.symbol_value;
327
switch(stypes[index])
330
"this attribute is undeclared within module:", IE.symbol_name);; break;
333
"this property is undeclared within module:", IE.symbol_name); break;
334
case INDIVIDUAL_PROPERTY_T:
344
"this was referred to as a constant, but isn't:", IE.symbol_name);
351
{ switch (IE.symbol_type)
353
case GLOBAL_VARIABLE_T:
354
if (stypes[index] != GLOBAL_VARIABLE_T)
356
"Module tried to import a Global variable not defined here:",
358
variables_map[IE.symbol_value] = 16;
359
if (IE.symbol_value < lowest_imported_global_no)
360
lowest_imported_global_no = IE.symbol_value;
366
static int32 backpatch_backpatch(int32 v)
367
{ switch(backpatch_marker)
369
/* Backpatches made now which are final */
373
backpatch_marker = NULL_MV;
377
if ((v<0) || (v>=256) || (actions_map[v] == -1))
378
{ link_error("unmapped action number");
379
printf("*** Link: unmapped action number %d ***", v);
384
backpatch_marker = NULL_MV;
388
{ int f = v & 0x8000;
389
v = f + property_identifier_map[v-f];
390
backpatch_marker = NULL_MV;
395
backpatch_marker = NULL_MV;
396
if (v < lowest_imported_global_no)
397
{ v = v + p_no_globals; break;
399
if (variables_map[v] == -1)
400
{ printf("** Unmapped variable %d! **\n", v);
401
variables_map[v] = 16;
402
link_error("unmapped variable error"); break;
404
v = variables_map[v];
407
/* Backpatch values which are themselves being backpatched */
410
v += individuals_length;
415
if ((v<0) || (v>=no_symbols))
416
{ printf("** Symbol number %d cannot be crossreferenced **\n", v);
417
link_error("symbol crossreference error"); v=0;
423
v += static_strings_extent/scale_factor;
428
for (i=0;i<no_rr;i++)
429
if (v == routine_replace[i])
430
{ v = routine_replace_with[i];
431
backpatch_marker = SYMBOL_MV;
434
v += zmachine_pc/scale_factor;
443
if (v < (MAX_GLOBAL_VARIABLES*2))
444
{ v = 2*(variables_map[v/2 + 16] - 16);
447
{ v += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
452
v = accession_numbers_map[v];
456
v += properties_table_size;
459
case INHERIT_INDIV_MV:
460
v += individuals_length;
466
static void backpatch_module_image(uchar *p,
467
int marker_value, int zmachine_area, int32 offset)
468
{ int size = (marker_value>=0x80)?1:2; int32 v;
469
marker_value &= 0x7f;
471
backpatch_marker = marker_value;
473
if (zmachine_area == PROP_DEFAULTS_ZA) return;
475
if (linker_trace_level >= 3)
476
printf("Backpatch %s area %d offset %04x size %d: ",
477
describe_mv(marker_value), zmachine_area, offset, size);
479
v = read_marker_address(p, size, zmachine_area, offset);
480
if (linker_trace_level >= 3) printf("%04x ", v);
482
v = backpatch_backpatch(v);
484
write_marker_address(p, size, zmachine_area, offset, v);
485
if (linker_trace_level >= 3) printf("%04x\n", v);
488
/* ------------------------------------------------------------------------- */
489
/* The main routine: linking in a module with the given filename. */
490
/* ------------------------------------------------------------------------- */
492
char current_module_filename[128];
494
void link_module(char *given_filename)
499
int32 last, i, j, k, l, m, vn, len, size, link_offset, module_size, map,
500
max_property_identifier, symbols_base = no_symbols;
502
strcpy(current_module_filename, given_filename);
504
/* (1) Load in the module to link */
508
{ i = translate_link_filename(i, filename, given_filename);
509
fin=fopen(filename,"rb");
510
} while ((fin == NULL) && (i != 0));
513
{ error_named("Couldn't open module file", filename); return;
516
for (i=0;i<64;i++) p0[i]=fgetc(fin);
519
if ((vn<65) || (vn>75))
520
{ error_named("File isn't a module:", filename);
524
if (vn != 64 + version_number)
527
"module compiled as Version %d (so it can't link\
528
into this V%d game):", vn-64, version_number);
529
error_named(ebuff, filename);
533
module_size = (256*p0[26] + p0[27])*scale_factor;
534
p = my_malloc(module_size + 16, "link module storage");
535
/* The + 16 allows for rounding errors */
537
for (k=0;k<64;k++) p[k] = p0[k];
538
for (k=64;k<module_size;k++) p[k] = fgetc(fin);
541
if ((p0[52] != 0) || (p0[53] != 0))
542
{ /* Then the module contains a character set table */
543
if (alphabet_modified)
544
{ k = FALSE; m = 256*p0[52] + p0[53];
545
for (i=0;i<3;i++) for (j=0;j<26;j++)
546
{ l = alphabet[i][j]; if (l == '~') l = '\"';
547
if (l != p[m]) k = TRUE;
550
link_error("module and game both define non-standard character sets, \
557
{ if (alphabet_modified) k = TRUE;
561
link_error("module and game use different character sets");
564
if (i > MODULE_VERSION_NUMBER)
565
warning_named("module has a more advanced format than this release \
566
of the Inform 6 compiler knows about: it may not link in correctly", filename);
568
/* (2) Calculate offsets: see the header-writing code in "tables.c" */
570
map = (256*p[6] + p[7]);
571
for (i=0; i<16; i++) module_map[i] = 256*p[map + i*2] + p[map + i*2 + 1];
573
m_vars_offset = (256*p[12] + p[13]);
574
m_static_offset = (256*p[14] + p[15]);
575
m_dict_offset = (256*p[8] + p[9]);
576
m_code_offset = (256*p[4] + p[5]);
578
/* (3) Read the "module map" table */
580
if (linker_trace_level>=4)
581
{ printf("[Reading module map:\n");
582
for (i=0; i<16; i++) printf("%04x ", module_map[i]);
586
m_objs_offset = module_map[0];
587
m_props_offset = module_map[1];
588
m_strs_offset = scale_factor*module_map[2];
589
m_class_numbers = module_map[3];
590
m_individuals_offset = module_map[4];
591
m_individuals_length = module_map[5];
593
for (i=16;i<256;i++) variables_map[i] = -1;
594
for (i=0;i<16;i++) variables_map[i] = i;
595
for (i=LOWEST_SYSTEM_VAR_NUMBER;i<256;i++) variables_map[i] = i;
597
for (i=0;i<256;i++) actions_map[i] = -1;
599
xref_table = my_calloc(sizeof(int32), module_map[6],
600
"linker cross-references table");
601
for (i=0;i<module_map[6];i++) xref_table[i] = -1;
603
max_property_identifier = module_map[7];
604
property_identifier_map = my_calloc(sizeof(int32), max_property_identifier,
605
"property identifier map");
606
for (i=0; i<max_property_identifier; i++)
607
property_identifier_map[i] = i;
609
m_no_objects = module_map[8];
610
link_offset = module_map[9];
612
m_no_globals = 0; p_no_globals = no_globals;
613
lowest_imported_global_no=236;
617
if ((linker_trace_level>=1) || transcript_switch)
618
{ char link_banner[128];
620
"[Linking release %d.%c%c%c%c%c%c of module '%s' (size %dK)]",
621
p[2]*256 + p[3], p[18], p[19], p[20], p[21], p[22], p[23],
622
filename, module_size/1024);
623
if (linker_trace_level >= 1) printf("%s\n", link_banner);
624
if (transcript_switch)
625
write_to_transcript_file(link_banner);
628
/* (4) Merge in the dictionary */
630
if (linker_trace_level >= 2)
631
printf("Merging module's dictionary at %04x\n", m_dict_offset);
632
k=m_dict_offset; k+=p[k]+1;
634
size = p[k]*256 + p[k+1]; k+=2;
636
accession_numbers_map = my_calloc(sizeof(int), size,
637
"dictionary accession numbers map");
639
for (i=0;i<size;i++, k+=len)
641
word_to_ascii(p+k,word);
642
if (linker_trace_level >= 3)
643
printf("%03d %04x '%s' %02x %02x %02x\n",i,k,
644
word, p[k+len-3], p[k+len-2], p[k+len-1]);
646
accession_numbers_map[i]
647
= dictionary_add(word, p[k+len-3], p[k+len-2], p[k+len-1]);
650
/* (5) Run through import/export table */
652
m_read_pos = module_map[9];
653
if (linker_trace_level>=2)
654
printf("Import/export table is at byte offset %04x\n", m_read_pos);
657
{ record_type = get_next_record(p);
658
if (((record_type == EXPORT_MV) || (record_type == EXPORTSF_MV))
659
&& (IE.symbol_type == INDIVIDUAL_PROPERTY_T))
660
{ int32 si = symbol_index(IE.symbol_name, -1);
661
property_identifier_map[IE.symbol_value] = svals[si];
667
accept_export(); break;
669
accept_import(); break;
671
} while (record_type != 0);
673
if ((linker_trace_level >= 4) && (no_rr != 0))
674
{ printf("Replaced routine addresses:\n");
675
for (i=0; i<no_rr; i++)
676
{ printf("Replace code offset %04x with %04x\n",
677
routine_replace[i], routine_replace_with[i]);
681
if (linker_trace_level >= 4)
682
{ printf("Symbol cross-references table:\n");
683
for (i=0; i<module_map[6]; i++)
684
{ if (xref_table[i] != -1)
685
printf("module %4d -> story file '%s'\n", i,
686
(char *) symbs[xref_table[i]]);
690
if (linker_trace_level >= 4)
691
{ printf("Action numbers map:\n");
692
for (i=0; i<256; i++)
693
if (actions_map[i] != -1)
694
printf("%3d -> %3d\n", i, actions_map[i]);
697
if ((linker_trace_level >= 4) && (max_property_identifier > 72))
698
{ printf("Property identifier number map:\n");
699
for (i=72; i<max_property_identifier; i++)
700
{ printf("module %04x -> program %04x\n",
701
i, property_identifier_map[i]);
705
/* (6) Backpatch the backpatch markers attached to exported symbols */
707
for (i=symbols_base; i<no_symbols; i++)
708
{ if ((sflags[i] & CHANGE_SFLAG) && (sflags[i] & EXPORT_SFLAG))
709
{ backpatch_marker = svals[i]/0x10000;
710
j = svals[i] % 0x10000;
712
j = backpatch_backpatch(j);
714
svals[i] = backpatch_marker*0x10000 + j;
715
if (backpatch_marker == 0) sflags[i] &= (~(CHANGE_SFLAG));
719
/* (7) Run through the Z-code backpatch table */
721
for (i=module_map[11]; i<module_map[11]+module_map[12]; i += 3)
722
{ int marker_value = p[i];
723
int32 offset = 256*p[i+1] + p[i+2];
725
switch(marker_value & 0x7f)
730
backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
733
backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
734
write_byte_to_memory_block(&zcode_backpatch_table,
735
zcode_backpatch_size++, backpatch_marker);
736
write_byte_to_memory_block(&zcode_backpatch_table,
737
zcode_backpatch_size++, (offset + zmachine_pc)/256);
738
write_byte_to_memory_block(&zcode_backpatch_table,
739
zcode_backpatch_size++, (offset + zmachine_pc)%256);
744
/* (8) Run through the Z-machine backpatch table */
746
for (i=module_map[13]; i<module_map[13]+module_map[14]; i += 4)
747
{ int marker_value = p[i], zmachine_area = p[i+1];
748
int32 offset = 256*p[i+2] + p[i+3];
754
backpatch_module_image(p, marker_value, zmachine_area, offset);
757
backpatch_module_image(p, marker_value, zmachine_area, offset);
758
switch(zmachine_area)
759
{ case PROP_DEFAULTS_ZA:
762
offset += properties_table_size; break;
763
case INDIVIDUAL_PROP_ZA:
764
offset += individuals_length; break;
765
case DYNAMIC_ARRAY_ZA:
766
if (offset < (MAX_GLOBAL_VARIABLES*2))
767
{ offset = 2*(variables_map[offset/2 + 16] - 16);
770
{ offset += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
774
backpatch_zmachine(backpatch_marker, zmachine_area, offset);
779
/* (9) Adjust initial values of variables */
781
if (linker_trace_level >= 3)
782
printf("\nFinal variables map, Module -> Main:\n");
785
if (variables_map[i]!=-1)
786
{ if (linker_trace_level>=2)
787
printf("%d->%d ",i,variables_map[i]);
788
if (i<lowest_imported_global_no)
789
{ int32 j = read_marker_address(p, 2,
790
DYNAMIC_ARRAY_ZA, 2*(i-16));
791
set_variable_value(variables_map[i]-16, j);
792
if (linker_trace_level>=2)
793
printf("(set var %d to %d) ",
794
variables_map[i], j);
797
if (linker_trace_level>=2) printf("\n");
799
/* (10) Glue in the dynamic array data */
801
i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
802
if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
803
memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
805
if (linker_trace_level >= 2)
806
printf("Inserting dynamic array area, %04x to %04x, at %04x\n",
807
m_vars_offset + MAX_GLOBAL_VARIABLES*2, m_static_offset,
808
variables_offset + dynamic_array_area_size);
810
{ dynamic_array_area[dynamic_array_area_size+k]
811
= p[m_vars_offset+MAX_GLOBAL_VARIABLES*2+k];
813
dynamic_array_area_size+=i;
815
/* (11) Glue in the code area */
817
if (linker_trace_level >= 2)
818
printf("Inserting code area, %04x to %04x, at code offset %04x (+%04x)\n",
819
m_code_offset, m_strs_offset, code_offset, zmachine_pc);
821
for (k=m_code_offset;k<m_strs_offset;k++)
822
{ if (temporary_files_switch)
823
{ fputc(p[k],Temp2_fp);
827
write_byte_to_memory_block(&zcode_area, zmachine_pc++, p[k]);
830
/* (12) Glue in the static strings area */
832
if (linker_trace_level >= 2)
833
printf("Inserting strings area, %04x to %04x, \
834
at strings offset %04x (+%04x)\n",
835
m_strs_offset, link_offset, strings_offset,
836
static_strings_extent);
837
for (k=m_strs_offset;k<link_offset;k++)
838
{ if (temporary_files_switch)
839
{ fputc(p[k], Temp1_fp);
840
static_strings_extent++;
843
write_byte_to_memory_block(&static_strings_area,
844
static_strings_extent++, p[k]);
847
/* (13) Append the class object-numbers table: note that modules
848
provide extra information in this table */
852
{ j = p[i]*256 + p[i+1]; i+=2;
855
class_object_numbers[no_classes] = j + no_objects;
856
j = p[i]*256 + p[i+1]; i+=2;
857
class_begins_at[no_classes++] = j + properties_table_size;
861
/* (14) Glue on the object tree */
863
if ((linker_trace_level>=2) && (m_no_objects>0))
864
printf("Joining on object tree of size %d\n", m_no_objects);
866
for (i=0, k=no_objects, last=m_props_offset;i<m_no_objects;i++)
867
{ objectsz[no_objects].atts[0]=p[m_objs_offset+14*i];
868
objectsz[no_objects].atts[1]=p[m_objs_offset+14*i+1];
869
objectsz[no_objects].atts[2]=p[m_objs_offset+14*i+2];
870
objectsz[no_objects].atts[3]=p[m_objs_offset+14*i+3];
871
objectsz[no_objects].atts[4]=p[m_objs_offset+14*i+4];
872
objectsz[no_objects].atts[5]=p[m_objs_offset+14*i+5];
873
objectsz[no_objects].parent =
874
(p[m_objs_offset+14*i+6])*256+p[m_objs_offset+14*i+7];
875
objectsz[no_objects].next =
876
(p[m_objs_offset+14*i+8])*256+p[m_objs_offset+14*i+9];
877
objectsz[no_objects].child =
878
(p[m_objs_offset+14*i+10])*256+p[m_objs_offset+14*i+11];
879
if (linker_trace_level>=4)
880
printf("Module objects[%d] has %d,%d,%d\n",
881
i,objectsz[no_objects].parent,
882
objectsz[no_objects].next,objectsz[no_objects].child);
883
if (objectsz[no_objects].parent == 0x7fff)
884
{ objectsz[no_objects].parent = 1;
885
if (objectsz[1].child == 0)
886
{ objectsz[1].child = no_objects+1;
889
{ int j1, j2 = objectsz[1].child;
892
j2 = objectsz[j2].next;
894
objectsz[j1].next = no_objects+1;
896
objectsz[no_objects].next = 0;
899
if (objectsz[no_objects].parent>0) objectsz[no_objects].parent += k;
900
if (objectsz[no_objects].next>0) objectsz[no_objects].next += k;
901
if (objectsz[no_objects].child>0) objectsz[no_objects].child += k;
902
objectsz[no_objects].propsize =
903
(p[m_objs_offset+14*i+12])*256+p[m_objs_offset+14*i+13];
904
last += objectsz[no_objects].propsize;
905
if (linker_trace_level>=4)
906
printf("Objects[%d] has %d,%d,%d\n",
907
no_objects,objectsz[no_objects].parent,
908
objectsz[no_objects].next,objectsz[no_objects].child);
912
/* (15) Glue on the properties */
914
if (last>m_props_offset)
915
{ i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
916
if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
917
memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
919
if (linker_trace_level >= 2)
920
printf("Inserting object properties area, %04x to %04x, at +%04x\n",
921
m_props_offset, last, properties_table_size);
922
for (k=0;k<last-m_props_offset;k++)
923
properties_table[properties_table_size++] = p[m_props_offset+k];
926
/* (16) Bitwise OR Flags 2 (Z-machine requirements flags) */
928
j = p[16]*256 + p[17];
929
for (i=0, k=1;i<16;i++, k=k*2) flags2_requirements[i] |= ((j/k)%2);
931
/* (17) Append the individual property values table */
933
i = m_individuals_length;
934
if (individuals_length + i >= MAX_INDIV_PROP_TABLE_SIZE)
935
memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
936
MAX_INDIV_PROP_TABLE_SIZE);
938
if (linker_trace_level >= 2)
939
printf("Inserting individual prop tables area, %04x to %04x, at +%04x\n",
940
m_individuals_offset, m_individuals_offset + i,
943
{ individuals_table[individuals_length + k]
944
= p[m_individuals_offset + k];
946
individuals_length += i;
950
if (linker_trace_level >= 2)
951
printf("Link complete\n");
953
my_free(&p, "link module storage");
954
my_free(&xref_table, "linker cross-references table");
955
my_free(&property_identifier_map, "property identifier map");
956
my_free(&accession_numbers_map, "accession numbers map");
959
/* ========================================================================= */
960
/* Writing imports, exports and markers to the link data table during */
961
/* module compilation */
962
/* ------------------------------------------------------------------------- */
963
/* Writing to the link data table */
964
/* ------------------------------------------------------------------------- */
966
static void write_link_byte(int x)
967
{ *link_data_top=(unsigned char) x; link_data_top++; link_data_size++;
968
if (subtract_pointers(link_data_top,link_data_holding_area)
969
>= MAX_LINK_DATA_SIZE)
970
{ memoryerror("MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE);
974
extern void flush_link_data(void)
976
j = subtract_pointers(link_data_top, link_data_holding_area);
977
if (temporary_files_switch)
978
for (i=0;i<j;i++) fputc(link_data_holding_area[i], Temp3_fp);
981
write_byte_to_memory_block(&link_data_area, link_data_size-j+i,
982
link_data_holding_area[i]);
983
link_data_top=link_data_holding_area;
986
static void write_link_word(int32 x)
987
{ write_link_byte(x/256); write_link_byte(x%256);
990
static void write_link_string(char *s)
992
for (i=0; s[i]!=0; i++) write_link_byte(s[i]);
996
/* ------------------------------------------------------------------------- */
997
/* Exports and imports */
998
/* ------------------------------------------------------------------------- */
1000
static void export_symbols(void)
1001
{ int symbol_number;
1003
for (symbol_number = 0; symbol_number < no_symbols; symbol_number++)
1004
{ int export_flag = FALSE, import_flag = FALSE;
1006
if (stypes[symbol_number]==GLOBAL_VARIABLE_T)
1007
{ if (svals[symbol_number] < LOWEST_SYSTEM_VAR_NUMBER)
1008
{ if (sflags[symbol_number] & IMPORT_SFLAG)
1011
if (!(sflags[symbol_number] & SYSTEM_SFLAG))
1016
{ if (!(sflags[symbol_number] & SYSTEM_SFLAG))
1017
{ if (sflags[symbol_number] & UNKNOWN_SFLAG)
1018
{ if (sflags[symbol_number] & IMPORT_SFLAG)
1022
switch(stypes[symbol_number])
1029
default: export_flag = TRUE;
1035
{ if (linker_trace_level >= 1)
1036
{ IE.module_value = EXPORT_MV;
1037
IE.symbol_number = symbol_number;
1038
IE.symbol_type = stypes[symbol_number];
1039
IE.symbol_value = svals[symbol_number];
1040
IE.symbol_name = (char *) (symbs[symbol_number]);
1041
describe_importexport(&IE);
1044
if (sflags[symbol_number] & ACTION_SFLAG)
1045
write_link_byte(EXPORTAC_MV);
1047
if (sflags[symbol_number] & INSF_SFLAG)
1048
write_link_byte(EXPORTSF_MV);
1050
write_link_byte(EXPORT_MV);
1052
write_link_word(symbol_number);
1053
write_link_byte(stypes[symbol_number]);
1054
if (sflags[symbol_number] & CHANGE_SFLAG)
1055
write_link_byte(svals[symbol_number] / 0x10000);
1056
else write_link_byte(0);
1057
write_link_word(svals[symbol_number] % 0x10000);
1058
write_link_string((char *) (symbs[symbol_number]));
1063
{ if (linker_trace_level >= 1)
1064
{ IE.module_value = IMPORT_MV;
1065
IE.symbol_number = symbol_number;
1066
IE.symbol_type = stypes[symbol_number];
1067
IE.symbol_value = svals[symbol_number];
1068
IE.symbol_name = (char *) (symbs[symbol_number]);
1069
describe_importexport(&IE);
1072
write_link_byte(IMPORT_MV);
1073
write_link_word(symbol_number);
1074
write_link_byte(stypes[symbol_number]);
1075
write_link_word(svals[symbol_number]);
1076
write_link_string((char *) (symbs[symbol_number]));
1082
/* ------------------------------------------------------------------------- */
1083
/* Marking for later importation */
1084
/* ------------------------------------------------------------------------- */
1086
int mv_vref=LOWEST_SYSTEM_VAR_NUMBER-1;
1088
void import_symbol(int32 symbol_number)
1089
{ sflags[symbol_number] |= IMPORT_SFLAG;
1090
switch(stypes[symbol_number])
1091
{ case GLOBAL_VARIABLE_T:
1092
assign_symbol(symbol_number, mv_vref--, stypes[symbol_number]);
1097
/* ========================================================================= */
1098
/* Data structure management routines */
1099
/* ------------------------------------------------------------------------- */
1101
extern void init_linker_vars(void)
1102
{ link_data_size = 0;
1103
initialise_memory_block(&link_data_area);
1106
extern void linker_begin_pass(void)
1107
{ link_data_top = link_data_holding_area;
1110
extern void linker_endpass(void)
1116
extern void linker_allocate_arrays(void)
1117
{ if (!module_switch)
1118
link_data_holding_area
1119
= my_malloc(64, "link data holding area");
1121
link_data_holding_area
1122
= my_malloc(MAX_LINK_DATA_SIZE, "link data holding area");
1125
extern void linker_free_arrays(void)
1126
{ my_free(&link_data_holding_area, "link data holding area");
1127
deallocate_memory_block(&link_data_area);
1130
/* ========================================================================= */