~ubuntu-branches/ubuntu/hoary/inform/hoary

« back to all changes in this revision

Viewing changes to src/linker.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Baker
  • Date: 2004-03-29 23:52:44 UTC
  • Revision ID: james.westby@ubuntu.com-20040329235244-fox1z1yv7d6vojoo
Tags: upstream-6.30
ImportĀ upstreamĀ versionĀ 6.30

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ------------------------------------------------------------------------- */
 
2
/*   "linker" : For compiling and linking modules                            */
 
3
/*                                                                           */
 
4
/*   Part of Inform 6.30                                                     */
 
5
/*   copyright (c) Graham Nelson 1993 - 2004                                 */
 
6
/*                                                                           */
 
7
/* ------------------------------------------------------------------------- */
 
8
 
 
9
#include "header.h"
 
10
 
 
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;
 
17
 
 
18
/* ------------------------------------------------------------------------- */
 
19
/*   Marker values                                                           */
 
20
/* ------------------------------------------------------------------------- */
 
21
 
 
22
extern char *describe_mv(int mval)
 
23
{   switch(mval)
 
24
    {   case NULL_MV:       return("null");
 
25
 
 
26
        /*  Marker values used in ordinary story file backpatching  */
 
27
 
 
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");
 
40
 
 
41
        /*  Additional marker values used in module backpatching  */
 
42
 
 
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");
 
47
 
 
48
        /*  Record types in the import/export table (not really marker
 
49
            values at all)  */
 
50
 
 
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   ");
 
55
    }
 
56
    return("** No such MV **");
 
57
}
 
58
 
 
59
/* ------------------------------------------------------------------------- */
 
60
/*   Import/export records                                                   */
 
61
/* ------------------------------------------------------------------------- */
 
62
 
 
63
typedef struct importexport_s
 
64
{   int module_value;
 
65
    int32 symbol_number;
 
66
    char symbol_type;
 
67
    int backpatch;
 
68
    int32 symbol_value;
 
69
    char *symbol_name;
 
70
} ImportExport;
 
71
 
 
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));
 
76
}
 
77
 
 
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   */
 
85
/*   used.)                                                                  */
 
86
/* ------------------------------------------------------------------------- */
 
87
 
 
88
static int variables_map[256], actions_map[256];
 
89
 
 
90
int32 module_map[16];
 
91
 
 
92
ImportExport IE;
 
93
 
 
94
/* ------------------------------------------------------------------------- */
 
95
/*   These are offsets within the module:                                    */
 
96
/* ------------------------------------------------------------------------- */
 
97
 
 
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;
 
101
 
 
102
static int m_no_objects, m_no_globals, p_no_globals, lowest_imported_global_no;
 
103
 
 
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;
 
109
 
 
110
/* ------------------------------------------------------------------------- */
 
111
/*   Reading and writing bytes/words in the module (as loaded in), indexing  */
 
112
/*   via "marker addresses".                                                 */
 
113
/* ------------------------------------------------------------------------- */
 
114
 
 
115
static int32 read_marker_address(uchar *p, int size,
 
116
    int zmachine_area, int32 offset)
 
117
{
 
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.                                          */
 
121
 
 
122
    int32 addr = 0;
 
123
 
 
124
    switch(zmachine_area)
 
125
    {
 
126
        case DYNAMIC_ARRAY_ZA:
 
127
            addr = m_vars_offset; break;
 
128
        case ZCODE_ZA:
 
129
            addr = m_code_offset; break;
 
130
        case STATIC_STRINGS_ZA:
 
131
            addr = m_strs_offset; break;
 
132
        case DICTIONARY_ZA:
 
133
            addr = m_dict_offset; break;
 
134
        case OBJECT_TREE_ZA:
 
135
            addr = m_objs_offset; break;
 
136
        case PROP_ZA:
 
137
            addr = m_props_offset; break;
 
138
        case INDIVIDUAL_PROP_ZA:
 
139
            addr = m_individuals_offset; break;
 
140
    }
 
141
    if (size == 1) return p[addr+offset];
 
142
    return 256*p[addr+offset] + p[addr+offset+1];
 
143
}
 
144
 
 
145
static void write_marker_address(uchar *p, int size,
 
146
    int zmachine_area, int32 offset, int32 value)
 
147
{
 
148
    /*  Similar, but to write to it.                                         */
 
149
 
 
150
    int32 addr = 0;
 
151
 
 
152
    switch(zmachine_area)
 
153
    {
 
154
        case DYNAMIC_ARRAY_ZA:
 
155
            addr = m_vars_offset; break;
 
156
        case ZCODE_ZA:
 
157
            addr = m_code_offset; break;
 
158
        case STATIC_STRINGS_ZA:
 
159
            addr = m_strs_offset; break;
 
160
        case DICTIONARY_ZA:
 
161
            addr = m_dict_offset; break;
 
162
        case OBJECT_TREE_ZA:
 
163
            addr = m_objs_offset; break;
 
164
        case PROP_ZA:
 
165
            addr = m_props_offset; break;
 
166
        case INDIVIDUAL_PROP_ZA:
 
167
            addr = m_individuals_offset; break;
 
168
    }
 
169
    if (size == 1) { p[addr+offset] = value%256; return; }
 
170
    p[addr+offset] = value/256;
 
171
    p[addr+offset+1] = value%256;
 
172
}
 
173
 
 
174
int m_read_pos;
 
175
 
 
176
static int get_next_record(uchar *p)
 
177
{   int i;
 
178
    int record_type = p[m_read_pos++];
 
179
    switch(record_type)
 
180
    {   case 0: break;
 
181
        case EXPORT_MV:
 
182
        case EXPORTSF_MV:
 
183
        case EXPORTAC_MV:
 
184
        case IMPORT_MV:
 
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);
 
193
            break;
 
194
        default:
 
195
            printf("Marker value of %d\n", record_type);
 
196
            compiler_error("Link: illegal import/export marker value");
 
197
            return -1;
 
198
    }
 
199
    return record_type;
 
200
}
 
201
 
 
202
static char link_errorm[128];
 
203
 
 
204
static void accept_export(void)
 
205
{   int32 index, map_to = IE.symbol_value % 0x10000;
 
206
    index = symbol_index(IE.symbol_name, -1);
 
207
 
 
208
    xref_table[IE.symbol_number] = index;
 
209
 
 
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))
 
214
                link_error_named(
 
215
"action name clash with", IE.symbol_name);
 
216
        }
 
217
        else
 
218
        if (stypes[index] == IE.symbol_type)
 
219
        {   switch(IE.symbol_type)
 
220
            {   case CONSTANT_T:
 
221
                    if ((!(svals[index] == IE.symbol_value))
 
222
                        || (IE.backpatch != 0))
 
223
                        link_error_named(
 
224
"program and module give differing values of", IE.symbol_name);
 
225
                    break;
 
226
                case INDIVIDUAL_PROPERTY_T:
 
227
                    property_identifier_map[IE.symbol_value] = svals[index];
 
228
                    break;
 
229
                case ROUTINE_T:
 
230
                    if ((IE.module_value == EXPORTSF_MV)
 
231
                        && (sflags[index] & REPLACE_SFLAG))
 
232
                    break;
 
233
                default:
 
234
                    sprintf(link_errorm,
 
235
                        "%s '%s' in both program and module",
 
236
                        typename(IE.symbol_type), IE.symbol_name);
 
237
                    link_error(link_errorm);
 
238
                    break;
 
239
            }
 
240
        }
 
241
        else
 
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);
 
247
        }
 
248
    }
 
249
    else
 
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]);
 
255
        }
 
256
        else
 
257
        switch(IE.symbol_type)
 
258
        {   case ROUTINE_T:
 
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;
 
263
                    return;
 
264
                }
 
265
                IE.symbol_value += (zmachine_pc/scale_factor);
 
266
                break;
 
267
            case OBJECT_T:
 
268
            case CLASS_T:
 
269
                IE.symbol_value += no_objects;
 
270
                break;
 
271
            case ARRAY_T:
 
272
                IE.symbol_value += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
 
273
                break;
 
274
            case GLOBAL_VARIABLE_T:
 
275
                if (no_globals==233)
 
276
                {   link_error(
 
277
"failed because too many extra global variables needed");
 
278
                    return;
 
279
                }
 
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++;
 
283
                break;
 
284
            case INDIVIDUAL_PROPERTY_T:
 
285
                property_identifier_map[IE.symbol_value]
 
286
                    = no_individual_properties;
 
287
                IE.symbol_value = no_individual_properties++;
 
288
                break;
 
289
        }
 
290
        assign_symbol(index, IE.backpatch*0x10000 + IE.symbol_value,
 
291
            IE.symbol_type);
 
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;
 
298
    }
 
299
 
 
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];
 
305
    }
 
306
}
 
307
 
 
308
static void accept_import(void)
 
309
{   int32 index;
 
310
 
 
311
    index = symbol_index(IE.symbol_name, -1);
 
312
    sflags[index] |= USED_SFLAG;
 
313
    xref_table[IE.symbol_number] = index;
 
314
 
 
315
    if (!(sflags[index] & UNKNOWN_SFLAG))
 
316
    {   switch (IE.symbol_type)
 
317
        {
 
318
            case GLOBAL_VARIABLE_T:
 
319
                if (stypes[index] != GLOBAL_VARIABLE_T)
 
320
                    link_error_named(
 
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;
 
325
                break;
 
326
            default:
 
327
                switch(stypes[index])
 
328
                {   case ATTRIBUTE_T:
 
329
                        link_error_named(
 
330
"this attribute is undeclared within module:", IE.symbol_name);; break;
 
331
                    case PROPERTY_T:
 
332
                        link_error_named(
 
333
"this property is undeclared within module:", IE.symbol_name); break;
 
334
                    case INDIVIDUAL_PROPERTY_T:
 
335
                    case ARRAY_T:
 
336
                    case ROUTINE_T:
 
337
                    case CONSTANT_T:
 
338
                    case OBJECT_T:
 
339
                    case CLASS_T:
 
340
                    case FAKE_ACTION_T:
 
341
                        break;
 
342
                    default:
 
343
                        link_error_named(
 
344
"this was referred to as a constant, but isn't:", IE.symbol_name);
 
345
                        break;
 
346
                }
 
347
                break;
 
348
        }
 
349
    }
 
350
    else
 
351
    {   switch (IE.symbol_type)
 
352
        {
 
353
            case GLOBAL_VARIABLE_T:
 
354
                if (stypes[index] != GLOBAL_VARIABLE_T)
 
355
                    link_error_named(
 
356
                "Module tried to import a Global variable not defined here:",
 
357
                        IE.symbol_name);
 
358
                variables_map[IE.symbol_value] = 16;
 
359
                if (IE.symbol_value < lowest_imported_global_no)
 
360
                    lowest_imported_global_no = IE.symbol_value;
 
361
                break;
 
362
        }
 
363
    }
 
364
}
 
365
 
 
366
static int32 backpatch_backpatch(int32 v)
 
367
{   switch(backpatch_marker)
 
368
    {
 
369
        /*  Backpatches made now which are final  */
 
370
 
 
371
        case OBJECT_MV:
 
372
            v += no_objects;
 
373
            backpatch_marker = NULL_MV;
 
374
            break;
 
375
 
 
376
        case ACTION_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);
 
380
                v = 0;
 
381
                break;
 
382
            }
 
383
            v = actions_map[v];
 
384
            backpatch_marker = NULL_MV;
 
385
            break;
 
386
 
 
387
        case IDENT_MV:
 
388
            {   int f = v & 0x8000;
 
389
                v = f + property_identifier_map[v-f];
 
390
                backpatch_marker = NULL_MV;
 
391
                break;
 
392
            }
 
393
 
 
394
        case VARIABLE_MV:
 
395
            backpatch_marker = NULL_MV;
 
396
            if (v < lowest_imported_global_no)
 
397
            {   v = v + p_no_globals; break;
 
398
            }
 
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;
 
403
            }
 
404
            v = variables_map[v];
 
405
            break;
 
406
 
 
407
        /*  Backpatch values which are themselves being backpatched  */
 
408
 
 
409
        case INDIVPT_MV:
 
410
            v += individuals_length;
 
411
            break;
 
412
 
 
413
        case SYMBOL_MV:
 
414
            v = xref_table[v];
 
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;
 
418
                break;
 
419
            }
 
420
            break;
 
421
 
 
422
        case STRING_MV:
 
423
            v += static_strings_extent/scale_factor;
 
424
            break;
 
425
 
 
426
        case IROUTINE_MV:
 
427
            {   int i;
 
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;
 
432
                        goto IR_Done;
 
433
                    }
 
434
                v += zmachine_pc/scale_factor;
 
435
            }
 
436
            IR_Done: break;
 
437
 
 
438
        case VROUTINE_MV:
 
439
            veneer_routine(v);
 
440
            break;
 
441
 
 
442
        case ARRAY_MV:
 
443
            if (v < (MAX_GLOBAL_VARIABLES*2))
 
444
            {   v = 2*(variables_map[v/2 + 16] - 16);
 
445
            }
 
446
            else
 
447
            {   v += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
 
448
            }
 
449
            break;
 
450
 
 
451
        case DWORD_MV:
 
452
            v = accession_numbers_map[v];
 
453
            break;
 
454
 
 
455
        case INHERIT_MV:
 
456
            v += properties_table_size;
 
457
            break;
 
458
 
 
459
        case INHERIT_INDIV_MV:
 
460
            v += individuals_length;
 
461
            break;
 
462
    }
 
463
    return v;
 
464
}
 
465
 
 
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;
 
470
 
 
471
    backpatch_marker = marker_value;
 
472
 
 
473
    if (zmachine_area == PROP_DEFAULTS_ZA) return;
 
474
 
 
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);
 
478
 
 
479
    v = read_marker_address(p, size, zmachine_area, offset);
 
480
    if (linker_trace_level >= 3) printf("%04x ", v);
 
481
 
 
482
    v = backpatch_backpatch(v);
 
483
 
 
484
    write_marker_address(p, size, zmachine_area, offset, v);
 
485
    if (linker_trace_level >= 3) printf("%04x\n", v);
 
486
}
 
487
 
 
488
/* ------------------------------------------------------------------------- */
 
489
/*   The main routine: linking in a module with the given filename.          */
 
490
/* ------------------------------------------------------------------------- */
 
491
 
 
492
char current_module_filename[128];
 
493
 
 
494
void link_module(char *given_filename)
 
495
{   FILE *fin;
 
496
    int record_type;
 
497
    char filename[128];
 
498
    uchar *p, p0[64];
 
499
    int32 last, i, j, k, l, m, vn, len, size, link_offset, module_size, map,
 
500
          max_property_identifier, symbols_base = no_symbols;
 
501
 
 
502
    strcpy(current_module_filename, given_filename);
 
503
 
 
504
    /* (1) Load in the module to link */
 
505
 
 
506
    i = 0;
 
507
    do
 
508
    {   i = translate_link_filename(i, filename, given_filename);
 
509
        fin=fopen(filename,"rb");
 
510
    } while ((fin == NULL) && (i != 0));
 
511
 
 
512
    if (fin==NULL)
 
513
    {   error_named("Couldn't open module file", filename); return;
 
514
    }
 
515
 
 
516
    for (i=0;i<64;i++) p0[i]=fgetc(fin);
 
517
 
 
518
    vn = p0[0];
 
519
    if ((vn<65) || (vn>75))
 
520
    {   error_named("File isn't a module:", filename);
 
521
        fclose(fin); return;
 
522
    }
 
523
 
 
524
    if (vn != 64 + version_number)
 
525
    {   char ebuff[100];
 
526
        sprintf(ebuff,
 
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);
 
530
        fclose(fin); return;
 
531
    }
 
532
 
 
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  */
 
536
 
 
537
    for (k=0;k<64;k++) p[k] = p0[k];
 
538
    for (k=64;k<module_size;k++) p[k] = fgetc(fin);
 
539
    fclose(fin);
 
540
 
 
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;
 
548
            }
 
549
            if (k)
 
550
        link_error("module and game both define non-standard character sets, \
 
551
but they disagree");
 
552
            k = FALSE;
 
553
        }
 
554
        else k = TRUE;
 
555
    }
 
556
    else
 
557
    {   if (alphabet_modified) k = TRUE;
 
558
        else k = FALSE;
 
559
    }
 
560
    if (k)
 
561
        link_error("module and game use different character sets");
 
562
 
 
563
    i = p[1];
 
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);
 
567
 
 
568
    /* (2) Calculate offsets: see the header-writing code in "tables.c"  */
 
569
 
 
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];
 
572
 
 
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]);
 
577
 
 
578
    /* (3) Read the "module map" table   */
 
579
 
 
580
    if (linker_trace_level>=4)
 
581
    {   printf("[Reading module map:\n");
 
582
        for (i=0; i<16; i++) printf("%04x ", module_map[i]);
 
583
        printf("]\n");
 
584
    }
 
585
 
 
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];
 
592
 
 
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;
 
596
 
 
597
    for (i=0;i<256;i++) actions_map[i] = -1;
 
598
 
 
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;
 
602
 
 
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;
 
608
 
 
609
    m_no_objects         = module_map[8];
 
610
    link_offset          = module_map[9];
 
611
 
 
612
    m_no_globals = 0; p_no_globals = no_globals;
 
613
    lowest_imported_global_no=236;
 
614
 
 
615
    no_rr = 0;
 
616
 
 
617
    if ((linker_trace_level>=1) || transcript_switch)
 
618
    {   char link_banner[128];
 
619
        sprintf(link_banner,
 
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);
 
626
    }
 
627
 
 
628
    /* (4) Merge in the dictionary */
 
629
 
 
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;
 
633
    len=p[k++];
 
634
    size = p[k]*256 + p[k+1]; k+=2;
 
635
 
 
636
    accession_numbers_map = my_calloc(sizeof(int), size,
 
637
        "dictionary accession numbers map");
 
638
 
 
639
    for (i=0;i<size;i++, k+=len)
 
640
    {   char word[10];
 
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]);
 
645
 
 
646
        accession_numbers_map[i]
 
647
            = dictionary_add(word, p[k+len-3], p[k+len-2], p[k+len-1]);
 
648
    }
 
649
 
 
650
    /* (5) Run through import/export table  */
 
651
 
 
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);
 
655
 
 
656
    do
 
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];
 
662
        }
 
663
        switch(record_type)
 
664
        {   case EXPORT_MV:
 
665
            case EXPORTSF_MV:
 
666
            case EXPORTAC_MV:
 
667
                accept_export(); break;
 
668
            case IMPORT_MV:
 
669
                accept_import(); break;
 
670
        }
 
671
    } while (record_type != 0);
 
672
 
 
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]);
 
678
        }
 
679
    }
 
680
 
 
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]]);
 
687
        }
 
688
    }
 
689
 
 
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]);
 
695
    }
 
696
 
 
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]);
 
702
        }
 
703
    }
 
704
 
 
705
    /* (6) Backpatch the backpatch markers attached to exported symbols  */
 
706
 
 
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;
 
711
 
 
712
            j = backpatch_backpatch(j);
 
713
 
 
714
            svals[i] = backpatch_marker*0x10000 + j;
 
715
            if (backpatch_marker == 0) sflags[i] &= (~(CHANGE_SFLAG));
 
716
        }
 
717
    }
 
718
 
 
719
    /* (7) Run through the Z-code backpatch table  */
 
720
 
 
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];
 
724
 
 
725
        switch(marker_value & 0x7f)
 
726
        {   case OBJECT_MV:
 
727
            case ACTION_MV:
 
728
            case IDENT_MV:
 
729
            case VARIABLE_MV:
 
730
                backpatch_module_image(p, marker_value, ZCODE_ZA, offset);
 
731
                break;
 
732
            default:
 
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);
 
740
                break;
 
741
        }
 
742
    }
 
743
 
 
744
    /* (8) Run through the Z-machine backpatch table  */
 
745
 
 
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];
 
749
 
 
750
        switch(marker_value)
 
751
        {   case OBJECT_MV:
 
752
            case ACTION_MV:
 
753
            case IDENT_MV:
 
754
                backpatch_module_image(p, marker_value, zmachine_area, offset);
 
755
                break;
 
756
            default:
 
757
                backpatch_module_image(p, marker_value, zmachine_area, offset);
 
758
                switch(zmachine_area)
 
759
                {   case PROP_DEFAULTS_ZA:
 
760
                        break;
 
761
                    case PROP_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);
 
768
                        }
 
769
                        else
 
770
                        {   offset += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
 
771
                        }
 
772
                        break;
 
773
                }
 
774
                backpatch_zmachine(backpatch_marker, zmachine_area, offset);
 
775
                break;
 
776
        }
 
777
    }
 
778
 
 
779
    /* (9) Adjust initial values of variables */
 
780
 
 
781
    if (linker_trace_level >= 3)
 
782
        printf("\nFinal variables map, Module -> Main:\n");
 
783
 
 
784
    for (i=16;i<255;i++)
 
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);
 
795
            }
 
796
        }
 
797
    if (linker_trace_level>=2) printf("\n");
 
798
 
 
799
    /* (10) Glue in the dynamic array data */
 
800
 
 
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);
 
804
 
 
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);
 
809
    for (k=0;k<i;k++)
 
810
    {   dynamic_array_area[dynamic_array_area_size+k]
 
811
            = p[m_vars_offset+MAX_GLOBAL_VARIABLES*2+k];
 
812
    }
 
813
    dynamic_array_area_size+=i;
 
814
 
 
815
    /* (11) Glue in the code area */
 
816
 
 
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);
 
820
 
 
821
    for (k=m_code_offset;k<m_strs_offset;k++)
 
822
    {   if (temporary_files_switch)
 
823
        {   fputc(p[k],Temp2_fp);
 
824
            zmachine_pc++;
 
825
        }
 
826
        else
 
827
            write_byte_to_memory_block(&zcode_area, zmachine_pc++, p[k]);
 
828
    }
 
829
 
 
830
    /* (12) Glue in the static strings area */
 
831
 
 
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++;
 
841
        }
 
842
        else
 
843
            write_byte_to_memory_block(&static_strings_area,
 
844
                    static_strings_extent++, p[k]);
 
845
    }
 
846
 
 
847
    /* (13) Append the class object-numbers table: note that modules
 
848
            provide extra information in this table */
 
849
 
 
850
    i = m_class_numbers;
 
851
    do
 
852
    {   j = p[i]*256 + p[i+1]; i+=2;
 
853
        if (j == 0) break;
 
854
 
 
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;
 
858
 
 
859
    } while (TRUE);
 
860
 
 
861
    /* (14) Glue on the object tree */
 
862
 
 
863
    if ((linker_trace_level>=2) && (m_no_objects>0))
 
864
        printf("Joining on object tree of size %d\n", m_no_objects);
 
865
 
 
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;
 
887
            }
 
888
            else
 
889
            {   int j1, j2 = objectsz[1].child;
 
890
                while (j2 != 0)
 
891
                {   j1 = j2;
 
892
                    j2 = objectsz[j2].next;
 
893
                }
 
894
                objectsz[j1].next = no_objects+1;
 
895
            }
 
896
            objectsz[no_objects].next = 0;
 
897
        }
 
898
        else
 
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);
 
909
        no_objects++;
 
910
    }
 
911
 
 
912
    /* (15) Glue on the properties */
 
913
 
 
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);
 
918
 
 
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];
 
924
    }
 
925
 
 
926
    /* (16) Bitwise OR Flags 2 (Z-machine requirements flags) */
 
927
 
 
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);
 
930
 
 
931
    /* (17) Append the individual property values table */
 
932
 
 
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);
 
937
 
 
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,
 
941
            individuals_length);
 
942
    for (k=0;k<i;k++)
 
943
    {   individuals_table[individuals_length + k]
 
944
            = p[m_individuals_offset + k];
 
945
    }
 
946
    individuals_length += i;
 
947
 
 
948
    /* (18) All done */
 
949
 
 
950
    if (linker_trace_level >= 2)
 
951
         printf("Link complete\n");
 
952
 
 
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");
 
957
}
 
958
 
 
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
/* ------------------------------------------------------------------------- */
 
965
 
 
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);
 
971
    }
 
972
}
 
973
 
 
974
extern void flush_link_data(void)
 
975
{   int32 i, j;
 
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);
 
979
    else
 
980
        for (i=0;i<j;i++)
 
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;
 
984
}
 
985
 
 
986
static void write_link_word(int32 x)
 
987
{   write_link_byte(x/256); write_link_byte(x%256);
 
988
}
 
989
 
 
990
static void write_link_string(char *s)
 
991
{   int i;
 
992
    for (i=0; s[i]!=0; i++) write_link_byte(s[i]);
 
993
    write_link_byte(0);
 
994
}
 
995
 
 
996
/* ------------------------------------------------------------------------- */
 
997
/*   Exports and imports                                                     */
 
998
/* ------------------------------------------------------------------------- */
 
999
 
 
1000
static void export_symbols(void)
 
1001
{   int symbol_number;
 
1002
 
 
1003
    for (symbol_number = 0; symbol_number < no_symbols; symbol_number++)
 
1004
    {   int export_flag = FALSE, import_flag = FALSE;
 
1005
 
 
1006
        if (stypes[symbol_number]==GLOBAL_VARIABLE_T)
 
1007
        {   if (svals[symbol_number] < LOWEST_SYSTEM_VAR_NUMBER)
 
1008
            {   if (sflags[symbol_number] & IMPORT_SFLAG)
 
1009
                    import_flag = TRUE;
 
1010
                else
 
1011
                    if (!(sflags[symbol_number] & SYSTEM_SFLAG))
 
1012
                        export_flag = TRUE;
 
1013
            }
 
1014
        }
 
1015
        else
 
1016
        {   if (!(sflags[symbol_number] & SYSTEM_SFLAG))
 
1017
            {   if (sflags[symbol_number] & UNKNOWN_SFLAG)
 
1018
                {   if (sflags[symbol_number] & IMPORT_SFLAG)
 
1019
                        import_flag = TRUE;
 
1020
                }
 
1021
                else
 
1022
                switch(stypes[symbol_number])
 
1023
                {   case LABEL_T:
 
1024
                    case ATTRIBUTE_T:
 
1025
                    case PROPERTY_T:
 
1026
                         /*  Ephemera  */
 
1027
                         break;
 
1028
 
 
1029
                    default: export_flag = TRUE;
 
1030
                }
 
1031
            }
 
1032
        }
 
1033
 
 
1034
        if (export_flag)
 
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);
 
1042
            }
 
1043
 
 
1044
            if (sflags[symbol_number] & ACTION_SFLAG)
 
1045
                write_link_byte(EXPORTAC_MV);
 
1046
            else
 
1047
            if (sflags[symbol_number] & INSF_SFLAG)
 
1048
                write_link_byte(EXPORTSF_MV);
 
1049
            else
 
1050
                write_link_byte(EXPORT_MV);
 
1051
 
 
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]));
 
1059
            flush_link_data();
 
1060
        }
 
1061
 
 
1062
        if (import_flag)
 
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);
 
1070
            }
 
1071
 
 
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]));
 
1077
            flush_link_data();
 
1078
        }
 
1079
    }
 
1080
}
 
1081
 
 
1082
/* ------------------------------------------------------------------------- */
 
1083
/*   Marking for later importation                                           */
 
1084
/* ------------------------------------------------------------------------- */
 
1085
 
 
1086
int mv_vref=LOWEST_SYSTEM_VAR_NUMBER-1;
 
1087
 
 
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]);
 
1093
            break;
 
1094
    }
 
1095
}
 
1096
 
 
1097
/* ========================================================================= */
 
1098
/*   Data structure management routines                                      */
 
1099
/* ------------------------------------------------------------------------- */
 
1100
 
 
1101
extern void init_linker_vars(void)
 
1102
{   link_data_size = 0;
 
1103
    initialise_memory_block(&link_data_area);
 
1104
}
 
1105
 
 
1106
extern void linker_begin_pass(void)
 
1107
{   link_data_top = link_data_holding_area;
 
1108
}
 
1109
 
 
1110
extern void linker_endpass(void)
 
1111
{   export_symbols();
 
1112
    write_link_byte(0);
 
1113
    flush_link_data();
 
1114
}
 
1115
 
 
1116
extern void linker_allocate_arrays(void)
 
1117
{   if (!module_switch)
 
1118
        link_data_holding_area
 
1119
            = my_malloc(64, "link data holding area");
 
1120
    else
 
1121
        link_data_holding_area
 
1122
            = my_malloc(MAX_LINK_DATA_SIZE, "link data holding area");
 
1123
}
 
1124
 
 
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);
 
1128
}
 
1129
 
 
1130
/* ========================================================================= */