/* ------------------------------------------------------------------------- */
/* "linker" : For compiling and linking modules */
/* */
/* Part of Inform 6.33 */
/* copyright (c) Graham Nelson 1993 - 2016 */
/* */
/* ------------------------------------------------------------------------- */
#include "header.h"
memory_block link_data_area;
uchar *link_data_holding_area, *link_data_top;
/* Start, current top, size of */
int32 link_data_size; /* link data table being written */
/* (holding import/export names) */
extern int32 *action_symbol;
/* ------------------------------------------------------------------------- */
/* Marker values */
/* ------------------------------------------------------------------------- */
extern char *describe_mv(int mval)
{ switch(mval)
{ case NULL_MV: return("null");
/* Marker values used in ordinary story file backpatching */
case DWORD_MV: return("dictionary word");
case STRING_MV: return("string literal");
case INCON_MV: return("system constant");
case IROUTINE_MV: return("routine");
case VROUTINE_MV: return("veneer routine");
case ARRAY_MV: return("internal array");
case NO_OBJS_MV: return("the number of objects");
case INHERIT_MV: return("inherited common p value");
case INDIVPT_MV: return("indiv prop table address");
case INHERIT_INDIV_MV: return("inherited indiv p value");
case MAIN_MV: return("ref to Main");
case SYMBOL_MV: return("ref to symbol value");
/* Additional marker values used in module backpatching */
case VARIABLE_MV: return("global variable");
case IDENT_MV: return("prop identifier number");
case ACTION_MV: return("action");
case OBJECT_MV: return("internal object");
/* Record types in the import/export table (not really marker
values at all) */
case EXPORT_MV: return("Export ");
case EXPORTSF_MV: return("Export sf");
case EXPORTAC_MV: return("Export ##");
case IMPORT_MV: return("Import ");
}
return("** No such MV **");
}
/* ------------------------------------------------------------------------- */
/* Import/export records */
/* ------------------------------------------------------------------------- */
typedef struct importexport_s
{ int module_value;
int32 symbol_number;
char symbol_type;
int backpatch;
int32 symbol_value;
char *symbol_name;
} ImportExport;
static void describe_importexport(ImportExport *I)
{ printf("%8s %20s %04d %04x %s\n",
describe_mv(I->module_value), I->symbol_name,
I->symbol_number, I->symbol_value, typename(I->symbol_type));
}
/* ========================================================================= */
/* Linking in external modules: this code is run when the external */
/* program hits a Link directive. */
/* ------------------------------------------------------------------------- */
/* This map is between global variable numbers in the module and in the */
/* external program: variables_map[n] will be the external global variable */
/* no for module global variable no n. (The entries [0] to [15] are not */
/* used.) */
/* ------------------------------------------------------------------------- */
static int variables_map[256], actions_map[256];
int32 module_map[16];
ImportExport IE;
/* ------------------------------------------------------------------------- */
/* These are offsets within the module: */
/* ------------------------------------------------------------------------- */
static int32 m_code_offset, m_strs_offset, m_static_offset, m_dict_offset,
m_vars_offset, m_objs_offset, m_props_offset, m_class_numbers,
m_individuals_offset, m_individuals_length;
static int m_no_objects, m_no_globals, p_no_globals, lowest_imported_global_no;
int32 *xref_table; int xref_top;
int32 *property_identifier_map;
int *accession_numbers_map;
int32 routine_replace[64],
routine_replace_with[64]; int no_rr;
/* ------------------------------------------------------------------------- */
/* Reading and writing bytes/words in the module (as loaded in), indexing */
/* via "marker addresses". */
/* ------------------------------------------------------------------------- */
static int32 read_marker_address(uchar *p, int size,
int zmachine_area, int32 offset)
{
/* A routine to read the value referred to by the marker address
(zmachine_area, offset): size is 1 for byte, 2 for word, and the
module itself resides at p. */
int32 addr = 0;
switch(zmachine_area)
{
case DYNAMIC_ARRAY_ZA:
addr = m_vars_offset; break;
case ZCODE_ZA:
addr = m_code_offset; break;
case STATIC_STRINGS_ZA:
addr = m_strs_offset; break;
case DICTIONARY_ZA:
addr = m_dict_offset; break;
case OBJECT_TREE_ZA:
addr = m_objs_offset; break;
case PROP_ZA:
addr = m_props_offset; break;
case INDIVIDUAL_PROP_ZA:
addr = m_individuals_offset; break;
}
if (size == 1) return p[addr+offset];
return 256*p[addr+offset] + p[addr+offset+1];
}
static void write_marker_address(uchar *p, int size,
int zmachine_area, int32 offset, int32 value)
{
/* Similar, but to write to it. */
int32 addr = 0;
switch(zmachine_area)
{
case DYNAMIC_ARRAY_ZA:
addr = m_vars_offset; break;
case ZCODE_ZA:
addr = m_code_offset; break;
case STATIC_STRINGS_ZA:
addr = m_strs_offset; break;
case DICTIONARY_ZA:
addr = m_dict_offset; break;
case OBJECT_TREE_ZA:
addr = m_objs_offset; break;
case PROP_ZA:
addr = m_props_offset; break;
case INDIVIDUAL_PROP_ZA:
addr = m_individuals_offset; break;
}
if (size == 1) { p[addr+offset] = value%256; return; }
p[addr+offset] = value/256;
p[addr+offset+1] = value%256;
}
int m_read_pos;
static int get_next_record(uchar *p)
{ int i;
int record_type = p[m_read_pos++];
switch(record_type)
{ case 0: break;
case EXPORT_MV:
case EXPORTSF_MV:
case EXPORTAC_MV:
case IMPORT_MV:
IE.module_value = record_type;
i=p[m_read_pos++]; IE.symbol_number = 256*i + p[m_read_pos++];
IE.symbol_type = p[m_read_pos++];
if (record_type != IMPORT_MV) IE.backpatch = p[m_read_pos++];
i=p[m_read_pos++]; IE.symbol_value = 256*i + p[m_read_pos++];
IE.symbol_name = (char *) (p+m_read_pos);
m_read_pos += strlen((char *) (p+m_read_pos))+1;
if (linker_trace_level >= 2) describe_importexport(&IE);
break;
default:
printf("Marker value of %d\n", record_type);
compiler_error("Link: illegal import/export marker value");
return -1;
}
return record_type;
}
static char link_errorm[128];
static void accept_export(void)
{ int32 index, map_to = IE.symbol_value % 0x10000;
index = symbol_index(IE.symbol_name, -1);
xref_table[IE.symbol_number] = index;
if (!(sflags[index] & UNKNOWN_SFLAG))
{ if (IE.module_value == EXPORTAC_MV)
{ if ((!(sflags[index] & ACTION_SFLAG))
&& (stypes[index] != FAKE_ACTION_T))
link_error_named(
"action name clash with", IE.symbol_name);
}
else
if (stypes[index] == IE.symbol_type)
{ switch(IE.symbol_type)
{ case CONSTANT_T:
if ((!(svals[index] == IE.symbol_value))
|| (IE.backpatch != 0))
link_error_named(
"program and module give differing values of", IE.symbol_name);
break;
case INDIVIDUAL_PROPERTY_T:
property_identifier_map[IE.symbol_value] = svals[index];
break;
case ROUTINE_T:
if ((IE.module_value == EXPORTSF_MV)
&& (sflags[index] & REPLACE_SFLAG))
break;
default:
sprintf(link_errorm,
"%s '%s' in both program and module",
typename(IE.symbol_type), IE.symbol_name);
link_error(link_errorm);
break;
}
}
else
{ sprintf(link_errorm,
"'%s' has type %s in program but type %s in module",
IE.symbol_name, typename(stypes[index]),
typename(IE.symbol_type));
link_error(link_errorm);
}
}
else
{ if (IE.module_value == EXPORTAC_MV)
{ IE.symbol_value = no_actions;
action_symbol[no_actions++] = index;
if (linker_trace_level >= 4)
printf("Creating action ##%s\n", (char *) symbs[index]);
}
else
switch(IE.symbol_type)
{ case ROUTINE_T:
if ((IE.module_value == EXPORTSF_MV)
&& (sflags[index] & REPLACE_SFLAG))
{ routine_replace[no_rr] = IE.symbol_value;
routine_replace_with[no_rr++] = index;
return;
}
IE.symbol_value += (zmachine_pc/scale_factor);
break;
case OBJECT_T:
case CLASS_T:
IE.symbol_value += no_objects;
break;
case ARRAY_T:
IE.symbol_value += dynamic_array_area_size - (MAX_GLOBAL_VARIABLES*2);
break;
case GLOBAL_VARIABLE_T:
if (no_globals==233)
{ link_error(
"failed because too many extra global variables needed");
return;
}
variables_map[16 + m_no_globals++] = 16 + no_globals;
set_variable_value(no_globals, IE.symbol_value);
IE.symbol_value = 16 + no_globals++;
break;
case INDIVIDUAL_PROPERTY_T:
property_identifier_map[IE.symbol_value]
= no_individual_properties;
IE.symbol_value = no_individual_properties++;
if (debugfile_switch)
{ debug_file_printf("");
debug_file_printf
("%s", IE.symbol_name);
debug_file_printf
("%d", IE.symbol_value);
debug_file_printf("");
}
break;
}
assign_symbol(index, IE.backpatch*0x10000 + IE.symbol_value,
IE.symbol_type);
if (IE.backpatch != 0) sflags[index] |= CHANGE_SFLAG;
sflags[index] |= EXPORT_SFLAG;
if (IE.module_value == EXPORTSF_MV)
sflags[index] |= INSF_SFLAG;
if (IE.module_value == EXPORTAC_MV)
sflags[index] |= ACTION_SFLAG;
}
if (IE.module_value == EXPORTAC_MV)
{ if (linker_trace_level >= 4)
printf("Map %d '%s' to %d\n",
IE.symbol_value, (char *) (symbs[index]), svals[index]);
actions_map[map_to] = svals[index];
}
}
static void accept_import(void)
{ int32 index;
index = symbol_index(IE.symbol_name, -1);
sflags[index] |= USED_SFLAG;
xref_table[IE.symbol_number] = index;
if (!(sflags[index] & UNKNOWN_SFLAG))
{ switch (IE.symbol_type)
{
case GLOBAL_VARIABLE_T:
if (stypes[index] != GLOBAL_VARIABLE_T)
link_error_named(
"module (wrongly) declared this a variable:", IE.symbol_name);
variables_map[IE.symbol_value] = svals[index];
if (IE.symbol_value < lowest_imported_global_no)
lowest_imported_global_no = IE.symbol_value;
break;
default:
switch(stypes[index])
{ case ATTRIBUTE_T:
link_error_named(
"this attribute is undeclared within module:", IE.symbol_name);; break;
case PROPERTY_T:
link_error_named(
"this property is undeclared within module:", IE.symbol_name); break;
case INDIVIDUAL_PROPERTY_T:
case ARRAY_T:
case ROUTINE_T:
case CONSTANT_T:
case OBJECT_T:
case CLASS_T:
case FAKE_ACTION_T:
break;
default:
link_error_named(
"this was referred to as a constant, but isn't:", IE.symbol_name);
break;
}
break;
}
}
else
{ switch (IE.symbol_type)
{
case GLOBAL_VARIABLE_T:
if (stypes[index] != GLOBAL_VARIABLE_T)
link_error_named(
"Module tried to import a Global variable not defined here:",
IE.symbol_name);
variables_map[IE.symbol_value] = 16;
if (IE.symbol_value < lowest_imported_global_no)
lowest_imported_global_no = IE.symbol_value;
break;
}
}
}
static int32 backpatch_backpatch(int32 v)
{ switch(backpatch_marker)
{
/* Backpatches made now which are final */
case OBJECT_MV:
v += no_objects;
backpatch_marker = NULL_MV;
break;
case ACTION_MV:
if ((v<0) || (v>=256) || (actions_map[v] == -1))
{ link_error("unmapped action number");
printf("*** Link: unmapped action number %d ***", v);
v = 0;
break;
}
v = actions_map[v];
backpatch_marker = NULL_MV;
break;
case IDENT_MV:
{ int f = v & 0x8000;
v = f + property_identifier_map[v-f];
backpatch_marker = NULL_MV;
break;
}
case VARIABLE_MV:
backpatch_marker = NULL_MV;
if (v < lowest_imported_global_no)
{ v = v + p_no_globals; break;
}
if (variables_map[v] == -1)
{ printf("** Unmapped variable %d! **\n", v);
variables_map[v] = 16;
link_error("unmapped variable error"); break;
}
v = variables_map[v];
break;
/* Backpatch values which are themselves being backpatched */
case INDIVPT_MV:
v += individuals_length;
break;
case SYMBOL_MV:
v = xref_table[v];
if ((v<0) || (v>=no_symbols))
{ printf("** Symbol number %d cannot be crossreferenced **\n", v);
link_error("symbol crossreference error"); v=0;
break;
}
break;
case STRING_MV:
v += static_strings_extent/scale_factor;
break;
case IROUTINE_MV:
{ int i;
for (i=0;i=0x80)?1:2; int32 v;
marker_value &= 0x7f;
backpatch_marker = marker_value;
if (zmachine_area == PROP_DEFAULTS_ZA) return;
if (linker_trace_level >= 3)
printf("Backpatch %s area %d offset %04x size %d: ",
describe_mv(marker_value), zmachine_area, offset, size);
v = read_marker_address(p, size, zmachine_area, offset);
if (linker_trace_level >= 3) printf("%04x ", v);
v = backpatch_backpatch(v);
write_marker_address(p, size, zmachine_area, offset, v);
if (linker_trace_level >= 3) printf("%04x\n", v);
}
/* ------------------------------------------------------------------------- */
/* The main routine: linking in a module with the given filename. */
/* ------------------------------------------------------------------------- */
char current_module_filename[128];
void link_module(char *given_filename)
{ FILE *fin;
int record_type;
char filename[128];
uchar *p, p0[64];
int32 last, i, j, k, l, m, vn, len, size, link_offset, module_size, map,
max_property_identifier, symbols_base = no_symbols;
strcpy(current_module_filename, given_filename);
/* (1) Load in the module to link */
i = 0;
do
{ i = translate_link_filename(i, filename, given_filename);
fin=fopen(filename,"rb");
} while ((fin == NULL) && (i != 0));
if (fin==NULL)
{ error_named("Couldn't open module file", filename); return;
}
for (i=0;i<64;i++) p0[i]=fgetc(fin);
vn = p0[0];
if ((vn<65) || (vn>75))
{ error_named("File isn't a module:", filename);
fclose(fin); return;
}
if (vn != 64 + version_number)
{ char ebuff[100];
sprintf(ebuff,
"module compiled as Version %d (so it can't link\
into this V%d game):", vn-64, version_number);
error_named(ebuff, filename);
fclose(fin); return;
}
module_size = (256*p0[26] + p0[27])*scale_factor;
p = my_malloc(module_size + 16, "link module storage");
/* The + 16 allows for rounding errors */
for (k=0;k<64;k++) p[k] = p0[k];
for (k=64;k MODULE_VERSION_NUMBER)
warning_named("module has a more advanced format than this release \
of the Inform 6 compiler knows about: it may not link in correctly", filename);
/* (2) Calculate offsets: see the header-writing code in "tables.c" */
map = (256*p[6] + p[7]);
for (i=0; i<16; i++) module_map[i] = 256*p[map + i*2] + p[map + i*2 + 1];
m_vars_offset = (256*p[12] + p[13]);
m_static_offset = (256*p[14] + p[15]);
m_dict_offset = (256*p[8] + p[9]);
m_code_offset = (256*p[4] + p[5]);
/* (3) Read the "module map" table */
if (linker_trace_level>=4)
{ printf("[Reading module map:\n");
for (i=0; i<16; i++) printf("%04x ", module_map[i]);
printf("]\n");
}
m_objs_offset = module_map[0];
m_props_offset = module_map[1];
m_strs_offset = scale_factor*module_map[2];
m_class_numbers = module_map[3];
m_individuals_offset = module_map[4];
m_individuals_length = module_map[5];
for (i=16;i<256;i++) variables_map[i] = -1;
for (i=0;i<16;i++) variables_map[i] = i;
for (i=LOWEST_SYSTEM_VAR_NUMBER;i<256;i++) variables_map[i] = i;
for (i=0;i<256;i++) actions_map[i] = -1;
xref_table = my_calloc(sizeof(int32), module_map[6],
"linker cross-references table");
for (i=0;i=1) || transcript_switch)
{ char link_banner[128];
sprintf(link_banner,
"[Linking release %d.%c%c%c%c%c%c of module '%s' (size %dK)]",
p[2]*256 + p[3], p[18], p[19], p[20], p[21], p[22], p[23],
filename, module_size/1024);
if (linker_trace_level >= 1) printf("%s\n", link_banner);
if (transcript_switch)
write_to_transcript_file(link_banner);
}
/* (4) Merge in the dictionary */
if (linker_trace_level >= 2)
printf("Merging module's dictionary at %04x\n", m_dict_offset);
k=m_dict_offset; k+=p[k]+1;
len=p[k++];
size = p[k]*256 + p[k+1]; k+=2;
accession_numbers_map = my_calloc(sizeof(int), size,
"dictionary accession numbers map");
for (i=0;i= 3)
printf("%03d %04x '%s' %02x %02x %02x\n",i,k,
word, p[k+len-3], p[k+len-2], p[k+len-1]);
accession_numbers_map[i]
= dictionary_add(word, p[k+len-3], p[k+len-2], p[k+len-1]);
}
/* (5) Run through import/export table */
m_read_pos = module_map[9];
if (linker_trace_level>=2)
printf("Import/export table is at byte offset %04x\n", m_read_pos);
do
{ record_type = get_next_record(p);
if (((record_type == EXPORT_MV) || (record_type == EXPORTSF_MV))
&& (IE.symbol_type == INDIVIDUAL_PROPERTY_T))
{ int32 si = symbol_index(IE.symbol_name, -1);
property_identifier_map[IE.symbol_value] = svals[si];
}
switch(record_type)
{ case EXPORT_MV:
case EXPORTSF_MV:
case EXPORTAC_MV:
accept_export(); break;
case IMPORT_MV:
accept_import(); break;
}
} while (record_type != 0);
if ((linker_trace_level >= 4) && (no_rr != 0))
{ printf("Replaced routine addresses:\n");
for (i=0; i= 4)
{ printf("Symbol cross-references table:\n");
for (i=0; i story file '%s'\n", i,
(char *) symbs[xref_table[i]]);
}
}
if (linker_trace_level >= 4)
{ printf("Action numbers map:\n");
for (i=0; i<256; i++)
if (actions_map[i] != -1)
printf("%3d -> %3d\n", i, actions_map[i]);
}
if ((linker_trace_level >= 4) && (max_property_identifier > 72))
{ printf("Property identifier number map:\n");
for (i=72; i program %04x\n",
i, property_identifier_map[i]);
}
}
/* (6) Backpatch the backpatch markers attached to exported symbols */
for (i=symbols_base; i= 3)
printf("\nFinal variables map, Module -> Main:\n");
for (i=16;i<255;i++)
if (variables_map[i]!=-1)
{ if (linker_trace_level>=2)
printf("%d->%d ",i,variables_map[i]);
if (i=2)
printf("(set var %d to %d) ",
variables_map[i], j);
}
}
if (linker_trace_level>=2) printf("\n");
/* (10) Glue in the dynamic array data */
i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
if (linker_trace_level >= 2)
printf("Inserting dynamic array area, %04x to %04x, at %04x\n",
m_vars_offset + MAX_GLOBAL_VARIABLES*2, m_static_offset,
variables_offset + dynamic_array_area_size);
for (k=0;k= 2)
printf("Inserting code area, %04x to %04x, at code offset %04x (+%04x)\n",
m_code_offset, m_strs_offset, code_offset, zmachine_pc);
for (k=m_code_offset;k= 2)
printf("Inserting strings area, %04x to %04x, \
at strings offset %04x (+%04x)\n",
m_strs_offset, link_offset, strings_offset,
static_strings_extent);
for (k=m_strs_offset;k=2) && (m_no_objects>0))
printf("Joining on object tree of size %d\n", m_no_objects);
for (i=0, k=no_objects, last=m_props_offset;i=4)
printf("Module objects[%d] has %d,%d,%d\n",
i,objectsz[no_objects].parent,
objectsz[no_objects].next,objectsz[no_objects].child);
if (objectsz[no_objects].parent == 0x7fff)
{ objectsz[no_objects].parent = 1;
if (objectsz[1].child == 0)
{ objectsz[1].child = no_objects+1;
}
else
{ int j1 = 0, j2 = objectsz[1].child;
while (j2 != 0)
{ j1 = j2;
j2 = objectsz[j2].next;
}
objectsz[j1].next = no_objects+1;
}
objectsz[no_objects].next = 0;
}
else
if (objectsz[no_objects].parent>0) objectsz[no_objects].parent += k;
if (objectsz[no_objects].next>0) objectsz[no_objects].next += k;
if (objectsz[no_objects].child>0) objectsz[no_objects].child += k;
objectsz[no_objects].propsize =
(p[m_objs_offset+14*i+12])*256+p[m_objs_offset+14*i+13];
last += objectsz[no_objects].propsize;
if (linker_trace_level>=4)
printf("Objects[%d] has %d,%d,%d\n",
no_objects,objectsz[no_objects].parent,
objectsz[no_objects].next,objectsz[no_objects].child);
no_objects++;
}
/* (15) Glue on the properties */
if (last>m_props_offset)
{ i = m_static_offset - m_vars_offset - MAX_GLOBAL_VARIABLES*2;
if (dynamic_array_area_size + i >= MAX_STATIC_DATA)
memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
if (linker_trace_level >= 2)
printf("Inserting object properties area, %04x to %04x, at +%04x\n",
m_props_offset, last, properties_table_size);
for (k=0;k= MAX_INDIV_PROP_TABLE_SIZE)
memoryerror("MAX_INDIV_PROP_TABLE_SIZE",
MAX_INDIV_PROP_TABLE_SIZE);
if (linker_trace_level >= 2)
printf("Inserting individual prop tables area, %04x to %04x, at +%04x\n",
m_individuals_offset, m_individuals_offset + i,
individuals_length);
for (k=0;k= 2)
printf("Link complete\n");
my_free(&p, "link module storage");
my_free(&xref_table, "linker cross-references table");
my_free(&property_identifier_map, "property identifier map");
my_free(&accession_numbers_map, "accession numbers map");
}
/* ========================================================================= */
/* Writing imports, exports and markers to the link data table during */
/* module compilation */
/* ------------------------------------------------------------------------- */
/* Writing to the link data table */
/* ------------------------------------------------------------------------- */
static void write_link_byte(int x)
{ *link_data_top=(unsigned char) x; link_data_top++; link_data_size++;
if (subtract_pointers(link_data_top,link_data_holding_area)
>= MAX_LINK_DATA_SIZE)
{ memoryerror("MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE);
}
}
extern void flush_link_data(void)
{ int32 i, j;
j = subtract_pointers(link_data_top, link_data_holding_area);
if (temporary_files_switch)
for (i=0;i= 1)
{ IE.module_value = EXPORT_MV;
IE.symbol_number = symbol_number;
IE.symbol_type = stypes[symbol_number];
IE.symbol_value = svals[symbol_number];
IE.symbol_name = (char *) (symbs[symbol_number]);
describe_importexport(&IE);
}
if (sflags[symbol_number] & ACTION_SFLAG)
write_link_byte(EXPORTAC_MV);
else
if (sflags[symbol_number] & INSF_SFLAG)
write_link_byte(EXPORTSF_MV);
else
write_link_byte(EXPORT_MV);
write_link_word(symbol_number);
write_link_byte(stypes[symbol_number]);
if (sflags[symbol_number] & CHANGE_SFLAG)
write_link_byte(svals[symbol_number] / 0x10000);
else write_link_byte(0);
write_link_word(svals[symbol_number] % 0x10000);
write_link_string((char *) (symbs[symbol_number]));
flush_link_data();
}
if (import_flag)
{ if (linker_trace_level >= 1)
{ IE.module_value = IMPORT_MV;
IE.symbol_number = symbol_number;
IE.symbol_type = stypes[symbol_number];
IE.symbol_value = svals[symbol_number];
IE.symbol_name = (char *) (symbs[symbol_number]);
describe_importexport(&IE);
}
write_link_byte(IMPORT_MV);
write_link_word(symbol_number);
write_link_byte(stypes[symbol_number]);
write_link_word(svals[symbol_number]);
write_link_string((char *) (symbs[symbol_number]));
flush_link_data();
}
}
}
/* ------------------------------------------------------------------------- */
/* Marking for later importation */
/* ------------------------------------------------------------------------- */
int mv_vref=LOWEST_SYSTEM_VAR_NUMBER-1;
void import_symbol(int32 symbol_number)
{ sflags[symbol_number] |= IMPORT_SFLAG;
switch(stypes[symbol_number])
{ case GLOBAL_VARIABLE_T:
assign_symbol(symbol_number, mv_vref--, stypes[symbol_number]);
break;
}
}
/* ========================================================================= */
/* Data structure management routines */
/* ------------------------------------------------------------------------- */
extern void init_linker_vars(void)
{ link_data_size = 0;
initialise_memory_block(&link_data_area);
}
extern void linker_begin_pass(void)
{ link_data_top = link_data_holding_area;
}
extern void linker_endpass(void)
{ export_symbols();
write_link_byte(0);
flush_link_data();
}
extern void linker_allocate_arrays(void)
{ if (!module_switch)
link_data_holding_area
= my_malloc(64, "link data holding area");
else
link_data_holding_area
= my_malloc(MAX_LINK_DATA_SIZE, "link data holding area");
}
extern void linker_free_arrays(void)
{ my_free(&link_data_holding_area, "link data holding area");
deallocate_memory_block(&link_data_area);
}
/* ========================================================================= */