inform.c: Update the copyright year that gets printed out in light of the change...
[inform.git] / linker.c
1 /* ------------------------------------------------------------------------- */
2 /*   "linker" : For compiling and linking modules                            */
3 /*                                                                           */
4 /* Copyright (c) Graham Nelson 1993 - 2016                                   */
5 /*                                                                           */
6 /* This file is part of Inform.                                              */
7 /*                                                                           */
8 /* Inform is free software: you can redistribute it and/or modify            */
9 /* it under the terms of the GNU General Public License as published by      */
10 /* the Free Software Foundation, either version 3 of the License, or         */
11 /* (at your option) any later version.                                       */
12 /*                                                                           */
13 /* Inform is distributed in the hope that it will be useful,                 */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
16 /* GNU General Public License for more details.                              */
17 /*                                                                           */
18 /* You should have received a copy of the GNU General Public License         */
19 /* along with Inform. If not, see https://gnu.org/licenses/                  */
20 /*                                                                           */
21 /* ------------------------------------------------------------------------- */
22
23 #include "header.h"
24
25 memory_block link_data_area;
26 uchar *link_data_holding_area, *link_data_top;
27                                           /*  Start, current top, size of    */
28 int32 link_data_size;                     /*  link data table being written  */
29                                           /*  (holding import/export names)  */
30 extern int32 *action_symbol;
31
32 /* ------------------------------------------------------------------------- */
33 /*   Marker values                                                           */
34 /* ------------------------------------------------------------------------- */
35
36 extern char *describe_mv(int mval)
37 {   switch(mval)
38     {   case NULL_MV:       return("null");
39
40         /*  Marker values used in ordinary story file backpatching  */
41
42         case DWORD_MV:      return("dictionary word");
43         case STRING_MV:     return("string literal");
44         case INCON_MV:      return("system constant");
45         case IROUTINE_MV:   return("routine");
46         case VROUTINE_MV:   return("veneer routine");
47         case ARRAY_MV:      return("internal array");
48         case NO_OBJS_MV:    return("the number of objects");
49         case INHERIT_MV:    return("inherited common p value");
50         case INDIVPT_MV:    return("indiv prop table address");
51         case INHERIT_INDIV_MV: return("inherited indiv p value");
52         case MAIN_MV:       return("ref to Main");
53         case SYMBOL_MV:     return("ref to symbol value");
54
55         /*  Additional marker values used in module backpatching  */
56
57         case VARIABLE_MV:   return("global variable");
58         case IDENT_MV:      return("prop identifier number");
59         case ACTION_MV:     return("action");
60         case OBJECT_MV:     return("internal object");
61
62         /*  Record types in the import/export table (not really marker
63             values at all)  */
64
65         case EXPORT_MV:     return("Export   ");
66         case EXPORTSF_MV:   return("Export sf");
67         case EXPORTAC_MV:   return("Export ##");
68         case IMPORT_MV:     return("Import   ");
69     }
70     return("** No such MV **");
71 }
72
73 /* ------------------------------------------------------------------------- */
74 /*   Import/export records                                                   */
75 /* ------------------------------------------------------------------------- */
76
77 typedef struct importexport_s
78 {   int module_value;
79     int32 symbol_number;
80     char symbol_type;
81     int backpatch;
82     int32 symbol_value;
83     char *symbol_name;
84 } ImportExport;
85
86 static void describe_importexport(ImportExport *I)
87 {   printf("%8s %20s %04d %04x %s\n",
88         describe_mv(I->module_value), I->symbol_name,
89             I->symbol_number, I->symbol_value, typename(I->symbol_type));
90 }
91
92 /* ========================================================================= */
93 /*   Linking in external modules: this code is run when the external         */
94 /*   program hits a Link directive.                                          */
95 /* ------------------------------------------------------------------------- */
96 /*   This map is between global variable numbers in the module and in the    */
97 /*   external program: variables_map[n] will be the external global variable */
98 /*   no for module global variable no n.  (The entries [0] to [15] are not   */
99 /*   used.)                                                                  */
100 /* ------------------------------------------------------------------------- */
101
102 static int variables_map[256], actions_map[256];
103
104 int32 module_map[16];
105
106 ImportExport IE;
107
108 /* ------------------------------------------------------------------------- */
109 /*   These are offsets within the module:                                    */
110 /* ------------------------------------------------------------------------- */
111
112 static int32 m_code_offset, m_strs_offset, m_static_offset, m_dict_offset,
113              m_vars_offset, m_objs_offset, m_props_offset, m_class_numbers,
114              m_individuals_offset,         m_individuals_length;
115
116 static int m_no_objects, m_no_globals, p_no_globals, lowest_imported_global_no;
117
118 int32 *xref_table; int xref_top;
119 int32 *property_identifier_map;
120 int *accession_numbers_map;
121 int32 routine_replace[64],
122       routine_replace_with[64]; int no_rr;
123
124 /* ------------------------------------------------------------------------- */
125 /*   Reading and writing bytes/words in the module (as loaded in), indexing  */
126 /*   via "marker addresses".                                                 */
127 /* ------------------------------------------------------------------------- */
128
129 static int32 read_marker_address(uchar *p, int size,
130     int zmachine_area, int32 offset)
131 {
132     /*  A routine to read the value referred to by the marker address
133         (zmachine_area, offset): size is 1 for byte, 2 for word, and the
134         module itself resides at p.                                          */
135
136     int32 addr = 0;
137
138     switch(zmachine_area)
139     {
140         case DYNAMIC_ARRAY_ZA:
141             addr = m_vars_offset; break;
142         case ZCODE_ZA:
143             addr = m_code_offset; break;
144         case STATIC_STRINGS_ZA:
145             addr = m_strs_offset; break;
146         case DICTIONARY_ZA:
147             addr = m_dict_offset; break;
148         case OBJECT_TREE_ZA:
149             addr = m_objs_offset; break;
150         case PROP_ZA:
151             addr = m_props_offset; break;
152         case INDIVIDUAL_PROP_ZA:
153             addr = m_individuals_offset; break;
154     }
155     if (size == 1) return p[addr+offset];
156     return 256*p[addr+offset] + p[addr+offset+1];
157 }
158
159 static void write_marker_address(uchar *p, int size,
160     int zmachine_area, int32 offset, int32 value)
161 {
162     /*  Similar, but to write to it.                                         */
163
164     int32 addr = 0;
165
166     switch(zmachine_area)
167     {
168         case DYNAMIC_ARRAY_ZA:
169             addr = m_vars_offset; break;
170         case ZCODE_ZA:
171             addr = m_code_offset; break;
172         case STATIC_STRINGS_ZA:
173             addr = m_strs_offset; break;
174         case DICTIONARY_ZA:
175             addr = m_dict_offset; break;
176         case OBJECT_TREE_ZA:
177             addr = m_objs_offset; break;
178         case PROP_ZA:
179             addr = m_props_offset; break;
180         case INDIVIDUAL_PROP_ZA:
181             addr = m_individuals_offset; break;
182     }
183     if (size == 1) { p[addr+offset] = value%256; return; }
184     p[addr+offset] = value/256;
185     p[addr+offset+1] = value%256;
186 }
187
188 int m_read_pos;
189
190 static int get_next_record(uchar *p)
191 {   int i;
192     int record_type = p[m_read_pos++];
193     switch(record_type)
194     {   case 0: break;
195         case EXPORT_MV:
196         case EXPORTSF_MV:
197         case EXPORTAC_MV:
198         case IMPORT_MV:
199             IE.module_value = record_type;
200             i=p[m_read_pos++]; IE.symbol_number = 256*i + p[m_read_pos++];
201             IE.symbol_type = p[m_read_pos++];
202             if (record_type != IMPORT_MV) IE.backpatch = p[m_read_pos++];
203             i=p[m_read_pos++]; IE.symbol_value = 256*i + p[m_read_pos++];
204             IE.symbol_name = (char *) (p+m_read_pos);
205             m_read_pos += strlen((char *) (p+m_read_pos))+1;
206             if (linker_trace_level >= 2) describe_importexport(&IE);
207             break;
208         default:
209             printf("Marker value of %d\n", record_type);
210             compiler_error("Link: illegal import/export marker value");
211             return -1;
212     }
213     return record_type;
214 }
215
216 static char link_errorm[128];
217
218 static void accept_export(void)
219 {   int32 index, map_to = IE.symbol_value % 0x10000;
220     index = symbol_index(IE.symbol_name, -1);
221
222     xref_table[IE.symbol_number] = index;
223
224     if (!(sflags[index] & UNKNOWN_SFLAG))
225     {   if (IE.module_value == EXPORTAC_MV)
226         {   if ((!(sflags[index] & ACTION_SFLAG))
227                 && (stypes[index] != FAKE_ACTION_T))
228                 link_error_named(
229 "action name clash with", IE.symbol_name);
230         }
231         else
232         if (stypes[index] == IE.symbol_type)
233         {   switch(IE.symbol_type)
234             {   case CONSTANT_T:
235                     if ((!(svals[index] == IE.symbol_value))
236                         || (IE.backpatch != 0))
237                         link_error_named(
238 "program and module give differing values of", IE.symbol_name);
239                     break;
240                 case INDIVIDUAL_PROPERTY_T:
241                     property_identifier_map[IE.symbol_value] = svals[index];
242                     break;
243                 case ROUTINE_T:
244                     if ((IE.module_value == EXPORTSF_MV)
245                         && (sflags[index] & REPLACE_SFLAG))
246                     break;
247                 default:
248                     sprintf(link_errorm,
249                         "%s '%s' in both program and module",
250                         typename(IE.symbol_type), IE.symbol_name);
251                     link_error(link_errorm);
252                     break;
253             }
254         }
255         else
256         {   sprintf(link_errorm,
257                     "'%s' has type %s in program but type %s in module",
258                     IE.symbol_name, typename(stypes[index]),
259                     typename(IE.symbol_type));
260             link_error(link_errorm);
261         }
262     }
263     else
264     {   if (IE.module_value == EXPORTAC_MV)
265         {   IE.symbol_value = no_actions;
266             action_symbol[no_actions++] = index;
267             if (linker_trace_level >= 4)
268                 printf("Creating action ##%s\n", (char *) symbs[index]);
269         }
270         else
271         switch(IE.symbol_type)
272         {   case ROUTINE_T:
273                 if ((IE.module_value == EXPORTSF_MV)
274                     && (sflags[index] & REPLACE_SFLAG))
275                 {   routine_replace[no_rr] = IE.symbol_value;
276                     routine_replace_with[no_rr++] = index;
277                     return;
278                 }
279                 IE.symbol_value += (zmachine_pc/scale_factor);
280                 break;
281             case OBJECT_T:
282             case CLASS_T:
283                 IE.symbol_value += no_objects;
284                 break;
285             case ARRAY_T:
286                 IE.symbol_value += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
287                 break;
288             case GLOBAL_VARIABLE_T:
289                 if (no_globals==233)
290                 {   link_error(
291 "failed because too many extra global variables needed");
292                     return;
293                 }
294                 variables_map[16 + m_no_globals++] = 16 + no_globals;
295                 set_variable_value(no_globals, IE.symbol_value);
296                 IE.symbol_value = 16 + no_globals++;
297                 break;
298             case INDIVIDUAL_PROPERTY_T:
299                 property_identifier_map[IE.symbol_value]
300                     = no_individual_properties;
301                 IE.symbol_value = no_individual_properties++;
302
303                 if (debugfile_switch)
304                 {   debug_file_printf("<property>");
305                     debug_file_printf
306                         ("<identifier>%s</identifier>", IE.symbol_name);
307                     debug_file_printf
308                         ("<value>%d</value>", IE.symbol_value);
309                     debug_file_printf("</property>");
310                 }
311
312                 break;
313         }
314         assign_symbol(index, IE.backpatch*0x10000 + IE.symbol_value,
315             IE.symbol_type);
316         if (IE.backpatch != 0) sflags[index] |= CHANGE_SFLAG;
317         sflags[index] |= EXPORT_SFLAG;
318         if (IE.module_value == EXPORTSF_MV)
319             sflags[index] |= INSF_SFLAG;
320         if (IE.module_value == EXPORTAC_MV)
321             sflags[index] |= ACTION_SFLAG;
322     }
323
324     if (IE.module_value == EXPORTAC_MV)
325     {   if (linker_trace_level >= 4)
326             printf("Map %d '%s' to %d\n",
327                 IE.symbol_value, (char *) (symbs[index]), svals[index]);
328         actions_map[map_to] = svals[index];
329     }
330 }
331
332 static void accept_import(void)
333 {   int32 index;
334
335     index = symbol_index(IE.symbol_name, -1);
336     sflags[index] |= USED_SFLAG;
337     xref_table[IE.symbol_number] = index;
338
339     if (!(sflags[index] & UNKNOWN_SFLAG))
340     {   switch (IE.symbol_type)
341         {
342             case GLOBAL_VARIABLE_T:
343                 if (stypes[index] != GLOBAL_VARIABLE_T)
344                     link_error_named(
345 "module (wrongly) declared this a variable:", IE.symbol_name);
346                 variables_map[IE.symbol_value] = svals[index];
347                 if (IE.symbol_value < lowest_imported_global_no)
348                     lowest_imported_global_no = IE.symbol_value;
349                 break;
350             default:
351                 switch(stypes[index])
352                 {   case ATTRIBUTE_T:
353                         link_error_named(
354 "this attribute is undeclared within module:", IE.symbol_name);; break;
355                     case PROPERTY_T:
356                         link_error_named(
357 "this property is undeclared within module:", IE.symbol_name); break;
358                     case INDIVIDUAL_PROPERTY_T:
359                     case ARRAY_T:
360                     case ROUTINE_T:
361                     case CONSTANT_T:
362                     case OBJECT_T:
363                     case CLASS_T:
364                     case FAKE_ACTION_T:
365                         break;
366                     default:
367                         link_error_named(
368 "this was referred to as a constant, but isn't:", IE.symbol_name);
369                         break;
370                 }
371                 break;
372         }
373     }
374     else
375     {   switch (IE.symbol_type)
376         {
377             case GLOBAL_VARIABLE_T:
378                 if (stypes[index] != GLOBAL_VARIABLE_T)
379                     link_error_named(
380                 "Module tried to import a Global variable not defined here:",
381                         IE.symbol_name);
382                 variables_map[IE.symbol_value] = 16;
383                 if (IE.symbol_value < lowest_imported_global_no)
384                     lowest_imported_global_no = IE.symbol_value;
385                 break;
386         }
387     }
388 }
389
390 static int32 backpatch_backpatch(int32 v)
391 {   switch(backpatch_marker)
392     {
393         /*  Backpatches made now which are final  */
394
395         case OBJECT_MV:
396             v += no_objects;
397             backpatch_marker = NULL_MV;
398             break;
399
400         case ACTION_MV:
401             if ((v<0) || (v>=256) || (actions_map[v] == -1))
402             {   link_error("unmapped action number");
403                 printf("*** Link: unmapped action number %d ***", v);
404                 v = 0;
405                 break;
406             }
407             v = actions_map[v];
408             backpatch_marker = NULL_MV;
409             break;
410
411         case IDENT_MV:
412             {   int f = v & 0x8000;
413                 v = f + property_identifier_map[v-f];
414                 backpatch_marker = NULL_MV;
415                 break;
416             }
417
418         case VARIABLE_MV:
419             backpatch_marker = NULL_MV;
420             if (v < lowest_imported_global_no)
421             {   v = v + p_no_globals; break;
422             }
423             if (variables_map[v] == -1)
424             {   printf("** Unmapped variable %d! **\n", v);
425                 variables_map[v] = 16;
426                 link_error("unmapped variable error"); break;
427             }
428             v = variables_map[v];
429             break;
430
431         /*  Backpatch values which are themselves being backpatched  */
432
433         case INDIVPT_MV:
434             v += individuals_length;
435             break;
436
437         case SYMBOL_MV:
438             v = xref_table[v];
439             if ((v<0) || (v>=no_symbols))
440             {   printf("** Symbol number %d cannot be crossreferenced **\n", v);
441                 link_error("symbol crossreference error"); v=0;
442                 break;
443             }
444             break;
445
446         case STRING_MV:
447             v += static_strings_extent/scale_factor;
448             break;
449
450         case IROUTINE_MV:
451             {   int i;
452                 for (i=0;i<no_rr;i++)
453                     if (v == routine_replace[i])
454                     {   v = routine_replace_with[i];
455                         backpatch_marker = SYMBOL_MV;
456                         goto IR_Done;
457                     }
458                 v += zmachine_pc/scale_factor;
459             }
460             IR_Done: break;
461
462         case VROUTINE_MV:
463             veneer_routine(v);
464             break;
465
466         case ARRAY_MV:
467             if (v < (MAX_GLOBAL_VARIABLES*2))
468             {   v = 2*(variables_map[v/2 + 16] - 16);
469             }
470             else
471             {   v += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
472             }
473             break;
474
475         case DWORD_MV:
476             v = accession_numbers_map[v];
477             break;
478
479         case INHERIT_MV:
480             v += properties_table_size;
481             break;
482
483         case INHERIT_INDIV_MV:
484             v += individuals_length;
485             break;
486     }
487     return v;
488 }
489
490 static void backpatch_module_image(uchar *p,
491     int marker_value, int zmachine_area, int32 offset)
492 {   int size = (marker_value>=0x80)?1:2; int32 v;
493     marker_value &= 0x7f;
494
495     backpatch_marker = marker_value;
496
497     if (zmachine_area == PROP_DEFAULTS_ZA) return;
498
499     if (linker_trace_level >= 3)
500         printf("Backpatch %s area %d offset %04x size %d: ",
501             describe_mv(marker_value), zmachine_area, offset, size);
502
503     v = read_marker_address(p, size, zmachine_area, offset);
504     if (linker_trace_level >= 3) printf("%04x ", v);
505
506     v = backpatch_backpatch(v);
507
508     write_marker_address(p, size, zmachine_area, offset, v);
509     if (linker_trace_level >= 3) printf("%04x\n", v);
510 }
511
512 /* ------------------------------------------------------------------------- */
513 /*   The main routine: linking in a module with the given filename.          */
514 /* ------------------------------------------------------------------------- */
515
516 char current_module_filename[128];
517
518 void link_module(char *given_filename)
519 {   FILE *fin;
520     int record_type;
521     char filename[128];
522     uchar *p, p0[64];
523     int32 last, i, j, k, l, m, vn, len, size, link_offset, module_size, map,
524           max_property_identifier, symbols_base = no_symbols;
525
526     strcpy(current_module_filename, given_filename);
527
528     /* (1) Load in the module to link */
529
530     i = 0;
531     do
532     {   i = translate_link_filename(i, filename, given_filename);
533         fin=fopen(filename,"rb");
534     } while ((fin == NULL) && (i != 0));
535
536     if (fin==NULL)
537     {   error_named("Couldn't open module file", filename); return;
538     }
539
540     for (i=0;i<64;i++) p0[i]=fgetc(fin);
541
542     vn = p0[0];
543     if ((vn<65) || (vn>75))
544     {   error_named("File isn't a module:", filename);
545         fclose(fin); return;
546     }
547
548     if (vn != 64 + version_number)
549     {   char ebuff[100];
550         sprintf(ebuff,
551            "module compiled as Version %d (so it can't link\
552  into this V%d game):", vn-64, version_number);
553         error_named(ebuff, filename);
554         fclose(fin); return;
555     }
556
557     module_size     = (256*p0[26] + p0[27])*scale_factor;
558     p = my_malloc(module_size + 16, "link module storage");
559         /*  The + 16 allows for rounding errors  */
560
561     for (k=0;k<64;k++) p[k] = p0[k];
562     for (k=64;k<module_size;k++) p[k] = fgetc(fin);
563     fclose(fin);
564
565     if ((p0[52] != 0) || (p0[53] != 0))
566     {   /*  Then the module contains a character set table  */
567         if (alphabet_modified)
568         {   k = FALSE; m = 256*p0[52] + p0[53];
569             for (i=0;i<3;i++) for (j=0;j<26;j++)
570             {   l = alphabet[i][j]; if (l == '~') l = '\"';
571                 if (l != p[m]) k = TRUE;
572             }
573             if (k)
574         link_error("module and game both define non-standard character sets, \
575 but they disagree");
576             k = FALSE;
577         }
578         else k = TRUE;
579     }
580     else
581     {   if (alphabet_modified) k = TRUE;
582         else k = FALSE;
583     }
584     if (k)
585         link_error("module and game use different character sets");
586
587     i = p[1];
588     if (i > MODULE_VERSION_NUMBER)
589         warning_named("module has a more advanced format than this release \
590 of the Inform 6 compiler knows about: it may not link in correctly", filename);
591
592     /* (2) Calculate offsets: see the header-writing code in "tables.c"  */
593
594     map             = (256*p[6] + p[7]);
595     for (i=0; i<16; i++) module_map[i] = 256*p[map + i*2] + p[map + i*2 + 1];
596
597     m_vars_offset   = (256*p[12] + p[13]);
598     m_static_offset = (256*p[14] + p[15]);
599     m_dict_offset   = (256*p[8] + p[9]);
600     m_code_offset   = (256*p[4] + p[5]);
601
602     /* (3) Read the "module map" table   */
603
604     if (linker_trace_level>=4)
605     {   printf("[Reading module map:\n");
606         for (i=0; i<16; i++) printf("%04x ", module_map[i]);
607         printf("]\n");
608     }
609
610     m_objs_offset        = module_map[0];
611     m_props_offset       = module_map[1];
612     m_strs_offset        = scale_factor*module_map[2];
613     m_class_numbers      = module_map[3];
614     m_individuals_offset = module_map[4];
615     m_individuals_length = module_map[5];
616
617     for (i=16;i<256;i++) variables_map[i] = -1;
618     for (i=0;i<16;i++)  variables_map[i] = i;
619     for (i=LOWEST_SYSTEM_VAR_NUMBER;i<256;i++) variables_map[i] = i;
620
621     for (i=0;i<256;i++) actions_map[i] = -1;
622
623     xref_table = my_calloc(sizeof(int32), module_map[6],
624         "linker cross-references table");
625     for (i=0;i<module_map[6];i++) xref_table[i] = -1;
626
627     max_property_identifier = module_map[7];
628     property_identifier_map = my_calloc(sizeof(int32), max_property_identifier,
629         "property identifier map");
630     for (i=0; i<max_property_identifier; i++)
631         property_identifier_map[i] = i;
632
633     m_no_objects         = module_map[8];
634     link_offset          = module_map[9];
635
636     m_no_globals = 0; p_no_globals = no_globals;
637     lowest_imported_global_no=236;
638
639     no_rr = 0;
640
641     if ((linker_trace_level>=1) || transcript_switch)
642     {   char link_banner[128];
643         sprintf(link_banner,
644             "[Linking release %d.%c%c%c%c%c%c of module '%s' (size %dK)]",
645             p[2]*256 + p[3], p[18], p[19], p[20], p[21], p[22], p[23],
646             filename, module_size/1024);
647         if (linker_trace_level >= 1) printf("%s\n", link_banner);
648         if (transcript_switch)
649             write_to_transcript_file(link_banner);
650     }
651
652     /* (4) Merge in the dictionary */
653
654     if (linker_trace_level >= 2)
655         printf("Merging module's dictionary at %04x\n", m_dict_offset);
656     k=m_dict_offset; k+=p[k]+1;
657     len=p[k++];
658     size = p[k]*256 + p[k+1]; k+=2;
659
660     accession_numbers_map = my_calloc(sizeof(int), size,
661         "dictionary accession numbers map");
662
663     for (i=0;i<size;i++, k+=len)
664     {   char word[10];
665         word_to_ascii(p+k,word);
666         if (linker_trace_level >= 3)
667             printf("%03d %04x  '%s' %02x %02x %02x\n",i,k,
668             word, p[k+len-3], p[k+len-2], p[k+len-1]);
669
670         accession_numbers_map[i]
671             = dictionary_add(word, p[k+len-3], p[k+len-2], p[k+len-1]);
672     }
673
674     /* (5) Run through import/export table  */
675
676     m_read_pos = module_map[9];
677     if (linker_trace_level>=2)
678         printf("Import/export table is at byte offset %04x\n", m_read_pos);
679
680     do
681     {   record_type = get_next_record(p);
682         if (((record_type == EXPORT_MV) || (record_type == EXPORTSF_MV))
683             && (IE.symbol_type == INDIVIDUAL_PROPERTY_T))
684         {   int32 si = symbol_index(IE.symbol_name, -1);
685             property_identifier_map[IE.symbol_value] = svals[si];
686         }
687         switch(record_type)
688         {   case EXPORT_MV:
689             case EXPORTSF_MV:
690             case EXPORTAC_MV:
691                 accept_export(); break;
692             case IMPORT_MV:
693                 accept_import(); break;
694         }
695     } while (record_type != 0);
696
697     if ((linker_trace_level >= 4) && (no_rr != 0))
698     {   printf("Replaced routine addresses:\n");
699         for (i=0; i<no_rr; i++)
700         {   printf("Replace code offset %04x with %04x\n",
701                 routine_replace[i], routine_replace_with[i]);
702         }
703     }
704
705     if (linker_trace_level >= 4)
706     {   printf("Symbol cross-references table:\n");
707         for (i=0; i<module_map[6]; i++)
708         {   if (xref_table[i] != -1)
709                 printf("module %4d -> story file '%s'\n", i,
710                     (char *) symbs[xref_table[i]]);
711         }
712     }
713
714     if (linker_trace_level >= 4)
715     {   printf("Action numbers map:\n");
716         for (i=0; i<256; i++)
717             if (actions_map[i] != -1)
718                 printf("%3d -> %3d\n", i, actions_map[i]);
719     }
720
721     if ((linker_trace_level >= 4) && (max_property_identifier > 72))
722     {   printf("Property identifier number map:\n");
723         for (i=72; i<max_property_identifier; i++)
724         {   printf("module %04x -> program %04x\n",
725                 i, property_identifier_map[i]);
726         }
727     }
728
729     /* (6) Backpatch the backpatch markers attached to exported symbols  */
730
731     for (i=symbols_base; i<no_symbols; i++)
732     {   if ((sflags[i] & CHANGE_SFLAG) && (sflags[i] & EXPORT_SFLAG))
733         {   backpatch_marker = svals[i]/0x10000;
734             j = svals[i] % 0x10000;
735
736             j = backpatch_backpatch(j);
737
738             svals[i] = backpatch_marker*0x10000 + j;
739             if (backpatch_marker == 0) sflags[i] &= (~(CHANGE_SFLAG));
740         }
741     }
742
743     /* (7) Run through the Z-code backpatch table  */
744
745     for (i=module_map[11]; i<module_map[11]+module_map[12]; i += 3)
746     {   int marker_value = p[i];
747         int32 offset = 256*p[i+1] + p[i+2];
748
749         switch(marker_value & 0x7f)
750         {   case OBJECT_MV:
751             case ACTION_MV:
752             case IDENT_MV:
753             case VARIABLE_MV:
754                 backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
755                 break;
756             default:
757                 backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
758                 write_byte_to_memory_block(&zcode_backpatch_table,
759                     zcode_backpatch_size++, backpatch_marker);
760                 write_byte_to_memory_block(&zcode_backpatch_table,
761                     zcode_backpatch_size++, (offset + zmachine_pc)/256);
762                 write_byte_to_memory_block(&zcode_backpatch_table,
763                     zcode_backpatch_size++, (offset + zmachine_pc)%256);
764                 break;
765         }
766     }
767
768     /* (8) Run through the Z-machine backpatch table  */
769
770     for (i=module_map[13]; i<module_map[13]+module_map[14]; i += 4)
771     {   int marker_value = p[i], zmachine_area = p[i+1];
772         int32 offset = 256*p[i+2] + p[i+3];
773
774         switch(marker_value)
775         {   case OBJECT_MV:
776             case ACTION_MV:
777             case IDENT_MV:
778                 backpatch_module_image(p, marker_value, zmachine_area, offset);
779                 break;
780             default:
781                 backpatch_module_image(p, marker_value, zmachine_area, offset);
782                 switch(zmachine_area)
783                 {   case PROP_DEFAULTS_ZA:
784                         break;
785                     case PROP_ZA:
786                         offset += properties_table_size; break;
787                     case INDIVIDUAL_PROP_ZA:
788                         offset += individuals_length; break;
789                     case DYNAMIC_ARRAY_ZA:
790                         if (offset < (MAX_GLOBAL_VARIABLES*2))
791                         {   offset = 2*(variables_map[offset/2 + 16] - 16);
792                         }
793                         else
794                         {   offset += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
795                         }
796                         break;
797                 }
798                 backpatch_zmachine(backpatch_marker, zmachine_area, offset);
799                 break;
800         }
801     }
802
803     /* (9) Adjust initial values of variables */
804
805     if (linker_trace_level >= 3)
806         printf("\nFinal variables map, Module -> Main:\n");
807
808     for (i=16;i<255;i++)
809         if (variables_map[i]!=-1)
810         {   if (linker_trace_level>=2)
811                 printf("%d->%d  ",i,variables_map[i]);
812             if (i<lowest_imported_global_no)
813             {   int32 j = read_marker_address(p, 2,
814                     DYNAMIC_ARRAY_ZA, 2*(i-16));
815                 set_variable_value(variables_map[i]-16, j);
816                 if (linker_trace_level>=2)
817                     printf("(set var %d to %d) ",
818                         variables_map[i], j);
819             }
820         }
821     if (linker_trace_level>=2) printf("\n");
822
823     /* (10) Glue in the dynamic array data */
824
825     i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
826     if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
827         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
828
829     if (linker_trace_level >= 2)
830         printf("Inserting dynamic array area, %04x to %04x, at %04x\n",
831             m_vars_offset + MAX_GLOBAL_VARIABLES*2, m_static_offset,
832             variables_offset + dynamic_array_area_size);
833     for (k=0;k<i;k++)
834     {   dynamic_array_area[dynamic_array_area_size+k]
835             = p[m_vars_offset+MAX_GLOBAL_VARIABLES*2+k];
836     }
837     dynamic_array_area_size+=i;
838
839     /* (11) Glue in the code area */
840
841     if (linker_trace_level >= 2)
842       printf("Inserting code area, %04x to %04x, at code offset %04x (+%04x)\n",
843         m_code_offset, m_strs_offset, code_offset, zmachine_pc);
844
845     for (k=m_code_offset;k<m_strs_offset;k++)
846     {   if (temporary_files_switch)
847         {   fputc(p[k],Temp2_fp);
848             zmachine_pc++;
849         }
850         else
851             write_byte_to_memory_block(&zcode_area, zmachine_pc++, p[k]);
852     }
853
854     /* (12) Glue in the static strings area */
855
856     if (linker_trace_level >= 2)
857         printf("Inserting strings area, %04x to %04x, \
858 at strings offset %04x (+%04x)\n",
859         m_strs_offset, link_offset, strings_offset,
860         static_strings_extent);
861     for (k=m_strs_offset;k<link_offset;k++)
862     {   if (temporary_files_switch)
863         {   fputc(p[k], Temp1_fp);
864             static_strings_extent++;
865         }
866         else
867             write_byte_to_memory_block(&static_strings_area,
868                     static_strings_extent++, p[k]);
869     }
870
871     /* (13) Append the class object-numbers table: note that modules
872             provide extra information in this table */
873
874     i = m_class_numbers;
875     do
876     {   j = p[i]*256 + p[i+1]; i+=2;
877         if (j == 0) break;
878
879         class_object_numbers[no_classes] = j + no_objects;
880         j = p[i]*256 + p[i+1]; i+=2;
881         class_begins_at[no_classes++] = j + properties_table_size;
882
883     } while (TRUE);
884
885     /* (14) Glue on the object tree */
886
887     if ((linker_trace_level>=2) && (m_no_objects>0))
888         printf("Joining on object tree of size %d\n", m_no_objects);
889
890     for (i=0, k=no_objects, last=m_props_offset;i<m_no_objects;i++)
891     {   objectsz[no_objects].atts[0]=p[m_objs_offset+14*i];
892         objectsz[no_objects].atts[1]=p[m_objs_offset+14*i+1];
893         objectsz[no_objects].atts[2]=p[m_objs_offset+14*i+2];
894         objectsz[no_objects].atts[3]=p[m_objs_offset+14*i+3];
895         objectsz[no_objects].atts[4]=p[m_objs_offset+14*i+4];
896         objectsz[no_objects].atts[5]=p[m_objs_offset+14*i+5];
897         objectsz[no_objects].parent =
898             (p[m_objs_offset+14*i+6])*256+p[m_objs_offset+14*i+7];
899         objectsz[no_objects].next =
900             (p[m_objs_offset+14*i+8])*256+p[m_objs_offset+14*i+9];
901         objectsz[no_objects].child =
902             (p[m_objs_offset+14*i+10])*256+p[m_objs_offset+14*i+11];
903         if (linker_trace_level>=4)
904             printf("Module objects[%d] has %d,%d,%d\n",
905                 i,objectsz[no_objects].parent,
906                 objectsz[no_objects].next,objectsz[no_objects].child);
907         if (objectsz[no_objects].parent == 0x7fff)
908         {   objectsz[no_objects].parent = 1;
909             if (objectsz[1].child == 0)
910             {   objectsz[1].child = no_objects+1;
911             }
912             else
913             {   int j1 = 0, j2 = objectsz[1].child;
914                 while (j2 != 0)
915                 {   j1 = j2;
916                     j2 = objectsz[j2].next;
917                 }
918                 objectsz[j1].next = no_objects+1;
919             }
920             objectsz[no_objects].next = 0;
921         }
922         else
923         if (objectsz[no_objects].parent>0) objectsz[no_objects].parent += k;
924         if (objectsz[no_objects].next>0)   objectsz[no_objects].next   += k;
925         if (objectsz[no_objects].child>0)  objectsz[no_objects].child  += k;
926         objectsz[no_objects].propsize =
927             (p[m_objs_offset+14*i+12])*256+p[m_objs_offset+14*i+13];
928         last += objectsz[no_objects].propsize;
929         if (linker_trace_level>=4)
930             printf("Objects[%d] has %d,%d,%d\n",
931                 no_objects,objectsz[no_objects].parent,
932                 objectsz[no_objects].next,objectsz[no_objects].child);
933         no_objects++;
934     }
935
936     /* (15) Glue on the properties */
937
938     if (last>m_props_offset)
939     {   i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
940         if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
941             memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
942
943         if (linker_trace_level >= 2)
944             printf("Inserting object properties area, %04x to %04x, at +%04x\n",
945                 m_props_offset, last, properties_table_size);
946         for (k=0;k<last-m_props_offset;k++)
947             properties_table[properties_table_size++] = p[m_props_offset+k];
948     }
949
950     /* (16) Bitwise OR Flags 2 (Z-machine requirements flags) */
951
952     j = p[16]*256 + p[17];
953     for (i=0, k=1;i<16;i++, k=k*2) flags2_requirements[i] |= ((j/k)%2);
954
955     /* (17) Append the individual property values table */
956
957     i = m_individuals_length;
958     if (individuals_length + i >= MAX_INDIV_PROP_TABLE_SIZE)
959         memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
960             MAX_INDIV_PROP_TABLE_SIZE);
961
962     if (linker_trace_level >= 2)
963       printf("Inserting individual prop tables area, %04x to %04x, at +%04x\n",
964             m_individuals_offset, m_individuals_offset + i,
965             individuals_length);
966     for (k=0;k<i;k++)
967     {   individuals_table[individuals_length + k]
968             = p[m_individuals_offset + k];
969     }
970     individuals_length += i;
971
972     /* (18) All done */
973
974     if (linker_trace_level >= 2)
975          printf("Link complete\n");
976
977   my_free(&p, "link module storage");
978   my_free(&xref_table, "linker cross-references table");
979   my_free(&property_identifier_map, "property identifier map");
980   my_free(&accession_numbers_map, "accession numbers map");
981 }
982
983 /* ========================================================================= */
984 /*   Writing imports, exports and markers to the link data table during      */
985 /*   module compilation                                                      */
986 /* ------------------------------------------------------------------------- */
987 /*   Writing to the link data table                                          */
988 /* ------------------------------------------------------------------------- */
989
990 static void write_link_byte(int x)
991 {   *link_data_top=(unsigned char) x; link_data_top++; link_data_size++;
992     if (subtract_pointers(link_data_top,link_data_holding_area)
993         >= MAX_LINK_DATA_SIZE)
994     {   memoryerror("MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE);
995     }
996 }
997
998 extern void flush_link_data(void)
999 {   int32 i, j;
1000     j = subtract_pointers(link_data_top, link_data_holding_area);
1001     if (temporary_files_switch)
1002         for (i=0;i<j;i++) fputc(link_data_holding_area[i], Temp3_fp);
1003     else
1004         for (i=0;i<j;i++)
1005             write_byte_to_memory_block(&link_data_area, link_data_size-j+i,
1006             link_data_holding_area[i]);
1007     link_data_top=link_data_holding_area;
1008 }
1009
1010 static void write_link_word(int32 x)
1011 {   write_link_byte(x/256); write_link_byte(x%256);
1012 }
1013
1014 static void write_link_string(char *s)
1015 {   int i;
1016     for (i=0; s[i]!=0; i++) write_link_byte(s[i]);
1017     write_link_byte(0);
1018 }
1019
1020 /* ------------------------------------------------------------------------- */
1021 /*   Exports and imports                                                     */
1022 /* ------------------------------------------------------------------------- */
1023
1024 static void export_symbols(void)
1025 {   int symbol_number;
1026
1027     for (symbol_number = 0; symbol_number < no_symbols; symbol_number++)
1028     {   int export_flag = FALSE, import_flag = FALSE;
1029
1030         if (stypes[symbol_number]==GLOBAL_VARIABLE_T)
1031         {   if (svals[symbol_number] < LOWEST_SYSTEM_VAR_NUMBER)
1032             {   if (sflags[symbol_number] & IMPORT_SFLAG)
1033                     import_flag = TRUE;
1034                 else
1035                     if (!(sflags[symbol_number] & SYSTEM_SFLAG))
1036                         export_flag = TRUE;
1037             }
1038         }
1039         else
1040         {   if (!(sflags[symbol_number] & SYSTEM_SFLAG))
1041             {   if (sflags[symbol_number] & UNKNOWN_SFLAG)
1042                 {   if (sflags[symbol_number] & IMPORT_SFLAG)
1043                         import_flag = TRUE;
1044                 }
1045                 else
1046                 switch(stypes[symbol_number])
1047                 {   case LABEL_T:
1048                     case ATTRIBUTE_T:
1049                     case PROPERTY_T:
1050                          /*  Ephemera  */
1051                          break;
1052
1053                     default: export_flag = TRUE;
1054                 }
1055             }
1056         }
1057
1058         if (export_flag)
1059         {   if (linker_trace_level >= 1)
1060             {   IE.module_value = EXPORT_MV;
1061                 IE.symbol_number = symbol_number;
1062                 IE.symbol_type = stypes[symbol_number];
1063                 IE.symbol_value = svals[symbol_number];
1064                 IE.symbol_name = (char *) (symbs[symbol_number]);
1065                 describe_importexport(&IE);
1066             }
1067
1068             if (sflags[symbol_number] & ACTION_SFLAG)
1069                 write_link_byte(EXPORTAC_MV);
1070             else
1071             if (sflags[symbol_number] & INSF_SFLAG)
1072                 write_link_byte(EXPORTSF_MV);
1073             else
1074                 write_link_byte(EXPORT_MV);
1075
1076             write_link_word(symbol_number);
1077             write_link_byte(stypes[symbol_number]);
1078             if (sflags[symbol_number] & CHANGE_SFLAG)
1079                  write_link_byte(svals[symbol_number] / 0x10000);
1080             else write_link_byte(0);
1081             write_link_word(svals[symbol_number] % 0x10000);
1082             write_link_string((char *) (symbs[symbol_number]));
1083             flush_link_data();
1084         }
1085
1086         if (import_flag)
1087         {   if (linker_trace_level >= 1)
1088             {   IE.module_value = IMPORT_MV;
1089                 IE.symbol_number = symbol_number;
1090                 IE.symbol_type = stypes[symbol_number];
1091                 IE.symbol_value = svals[symbol_number];
1092                 IE.symbol_name = (char *) (symbs[symbol_number]);
1093                 describe_importexport(&IE);
1094             }
1095
1096             write_link_byte(IMPORT_MV);
1097             write_link_word(symbol_number);
1098             write_link_byte(stypes[symbol_number]);
1099             write_link_word(svals[symbol_number]);
1100             write_link_string((char *) (symbs[symbol_number]));
1101             flush_link_data();
1102         }
1103     }
1104 }
1105
1106 /* ------------------------------------------------------------------------- */
1107 /*   Marking for later importation                                           */
1108 /* ------------------------------------------------------------------------- */
1109
1110 int mv_vref=LOWEST_SYSTEM_VAR_NUMBER-1;
1111
1112 void import_symbol(int32 symbol_number)
1113 {   sflags[symbol_number] |= IMPORT_SFLAG;
1114     switch(stypes[symbol_number])
1115     {   case GLOBAL_VARIABLE_T:
1116             assign_symbol(symbol_number, mv_vref--, stypes[symbol_number]);
1117             break;
1118     }
1119 }
1120
1121 /* ========================================================================= */
1122 /*   Data structure management routines                                      */
1123 /* ------------------------------------------------------------------------- */
1124
1125 extern void init_linker_vars(void)
1126 {   link_data_size = 0;
1127     initialise_memory_block(&link_data_area);
1128 }
1129
1130 extern void linker_begin_pass(void)
1131 {   link_data_top = link_data_holding_area;
1132 }
1133
1134 extern void linker_endpass(void)
1135 {   export_symbols();
1136     write_link_byte(0);
1137     flush_link_data();
1138 }
1139
1140 extern void linker_allocate_arrays(void)
1141 {   if (!module_switch)
1142         link_data_holding_area
1143             = my_malloc(64, "link data holding area");
1144     else
1145         link_data_holding_area
1146             = my_malloc(MAX_LINK_DATA_SIZE, "link data holding area");
1147 }
1148
1149 extern void linker_free_arrays(void)
1150 {   my_free(&link_data_holding_area, "link data holding area");
1151     deallocate_memory_block(&link_data_area);
1152 }
1153
1154 /* ========================================================================= */