home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
pgmutl
/
val_link.arc
/
TMODULE.C
< prev
next >
Wrap
Text File
|
1989-02-18
|
82KB
|
2,167 lines
/* TMODULE.C */
/*
Object modules are parsed via recursive descent as defined below:
obj_t_module:: obj_THEADR obj_seg_grp {obj_component} obj_modtail
obj_seg_grp:: {obj_LNAMES | obj_SEGDEF | obj_EXTDEF}
{obj_TYPDEF | obj_EXTDEF | obj_GRPDEF}
obj_component:: obj_data | obj_debug_record
obj_data:: obj_content_def | obj_thread_def | obj_COMDEF |
obj_TYPDEF | obj_PUBDEF | obj_EXTDEF |
obj_FORREF | obj_MODPUB | obj_MODEXT
obj_debug_record:: obj_LINNUM
obj_content_def:: obj_data_record {obj_FIXUPP}
obj_thread_def:: obj_FIXUPP (containing only thread fields)
obj_data_record:: obj_LIDATA | obj_LEDATA
obj_modtail:: obj_MODEND
*/
/*+-------------------------------------------------------------------------+
| |
| obj_COMDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_COMDEF()
BeginDeclarations
bit_32 element_count;
bit_32 element_size;
bit_8 element_type;
bit_8 expected_type;
bit_16 len;
public_entry_ptr pub;
#define Pub (*pub)
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot COMDEF_record
Then
return(False);
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If n_externals NotLessThan max_externals.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many externals. Max of %u exceeded.\n"
"\t Retry with larger \"/maxexternals:n\" "
"switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_externals.val);
EndIf;
len = obj_name_length();
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
pub = lookup_public(len, obj_ptr.b8, 0);
obj_ptr.b8 += len;
obj_name_length(); /* Eat the type index. */
externals[++n_externals] = pub;
element_type = *obj_ptr.b8++;
Using element_type
BeginCase
When 0x61:
expected_type = far_communal;
element_count = obj_leaf_descriptor();
element_size = obj_leaf_descriptor();
break;
When 0x62:
expected_type = near_communal;
element_size = obj_leaf_descriptor();
element_count = 1L;
break;
Otherwise:
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Communal type of \"%02X\" is illegal.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
element_type);
EndCase;
If Pub.type_entry Is unused
Then
Insert pub AtEnd InList external_list EndInsert;
Pub.type_entry = expected_type;
Pub.Communal.element_size = element_size;
Pub.Communal.element_count = element_count;
Using element_type
BeginCase
When 0x61:
Pub.Communal.next_communal = far_communals;
far_communals = pub;
break;
When 0x62:
Pub.Communal.next_communal = near_communals;
near_communals = pub;
break;
EndCase;
Else
If Pub.type_entry Is expected_type
Then
If (element_size * element_count) Exceeds
(Pub.Communal.element_size * Pub.Communal.element_count)
Then /* We need the largest common */
Pub.Communal.element_size = element_size;
Pub.Communal.element_count = element_count;
EndIf;
Else
If (Pub.type_entry Is near_communal) OrIf
(Pub.type_entry Is far_communal)
Then
linker_error(4, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Communal \"%Fs\" is declared both near "
"and far.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
Pub.symbol);
EndIf;
EndIf;
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| obj_COMENT |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_COMENT()
BeginDeclarations
bit_8 comment_class;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot COMENT_record
Then
return(False);
EndIf;
obj_ptr.b8++;
comment_class = *obj_ptr.b8++;
Using comment_class
BeginCase
When 158:
DOSSEG.val = True;
break;
When 161:
codeview_information_present = True;
break;
Otherwise:
break;
EndCase;
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_component |
| |
+-------------------------------------------------------------------------+*/
/* obj_component:: obj_data | obj_debug_record */
bit_16 obj_component()
BeginDeclarations
EndDeclarations
BeginCode
If obj_data() OrIf obj_debug_record()
Then
return(True);
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_content_def |
| |
+-------------------------------------------------------------------------+*/
/* obj_content_def:: obj_data_record {obj_FIXUPP} */
bit_16 obj_content_def()
BeginDeclarations
EndDeclarations
BeginCode
If Not obj_data_record()
Then
return(False);
EndIf;
While obj_FIXUPP()
BeginWhile
EndWhile;
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_data |
| |
+-------------------------------------------------------------------------+*/
/* obj_data:: obj_content_def |
obj_thread_def |
obj_TYPDEF |
obj_PUBDEF |
obj_EXTDEF */
bit_16 obj_data()
BeginDeclarations
EndDeclarations
BeginCode
If obj_content_def() OrIf
obj_thread_def() OrIf
obj_TYPDEF() OrIf
obj_PUBDEF() OrIf
obj_EXTDEF() OrIf
obj_FORREF() OrIf
obj_COMDEF() OrIf
obj_MODEXT() OrIf
obj_MODPUB()
Then
return(True);
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_data_record |
| |
+-------------------------------------------------------------------------+*/
/* obj_data_record:: obj_LIDATA | obj_LEDATA */
bit_16 obj_data_record()
BeginDeclarations
EndDeclarations
BeginCode
If obj_LIDATA() OrIf obj_LEDATA()
Then
return(True);
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_debug_record |
| |
+-------------------------------------------------------------------------+*/
/* obj_debug_record:: obj_LINNUM */
bit_16 obj_debug_record()
BeginDeclarations
EndDeclarations
BeginCode
If obj_LINNUM()
Then
return(True);
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_EXTDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_EXTDEF()
BeginDeclarations
bit_16 len;
public_entry_ptr pub;
#define Pub (*pub)
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot EXTDEF_record
Then
return(False);
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If n_externals NotLessThan max_externals.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many externals. Max of %u exceeded.\n"
"\t Retry with larger \"/maxexternals:n\" "
"switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_externals.val);
EndIf;
len = obj_name_length();
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
pub = lookup_public(len, obj_ptr.b8, 0);
obj_ptr.b8 += len;
obj_name_length(); /* Eat the type index. */
externals[++n_externals] = pub;
If Pub.type_entry Is unused
Then
Insert pub AtEnd InList external_list EndInsert;
Pub.type_entry = external;
Else
If (Pub.type_entry Is public_in_library) AndIf
(Not Pub.Library.requested)
Then
library_request_count++;
(*Pub.Library.lib_file).request_count++;
Pub.Library.requested = True;
EndIf;
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| obj_FIXUPP |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_FIXUPP()
BeginDeclarations
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot FIXUPP_record
Then
return(False);
EndIf;
FIXUPP_contains_only_threads = True;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If (*obj_ptr.TRD_DAT).type_fixupp_record IsZero
Then
obj_FIXUPP_thread();
Else
FIXUPP_contains_only_threads = False;
obj_FIXUPP_fixup();
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_FIXUPP_fixup |
| |
+-------------------------------------------------------------------------+*/
void obj_FIXUPP_fixup()
BeginDeclarations
FIX_DAT_type FIX_DAT;
bit_16 frame_method;
LOCAT_type LOCAT;
bit_16 target_method;
bit_8 temp;
bit_16 thread_number;
EndDeclarations
BeginCode
/*+-------------------------------------------------------------------------+
| |
| The LOCAT field in a FIXUPP record has its low and high bytes swapped |
| because the high order bit must be 0 for threads and 1 for fixups. |
| Since that bit could not be placed in the offset, the bytes were |
| swapped instead. |
| |
+-------------------------------------------------------------------------+*/
temp = obj_ptr.b8[0];
obj_ptr.b8[0] = obj_ptr.b8[1];
obj_ptr.b8[1] = temp;
/*+-------------------------------------------------------------------------+
| |
| Pick up the two required fields (LOCAT and FIX_DAT) |
| |
+-------------------------------------------------------------------------+*/
LOCAT = *obj_ptr.LOCAT++;
FIX_DAT = *obj_ptr.FIX_DAT++;
/*+-------------------------------------------------------------------------+
| |
| A fixup consists of a location, mode, frame and target. |
| Process the location part. |
| |
+-------------------------------------------------------------------------+*/
fixup_index = LOCAT.data_record_offset;
fixup.location_type = LOCAT.loc;
/*+-------------------------------------------------------------------------+
| |
| Process the mode part. |
| |
+-------------------------------------------------------------------------+*/
fixup.mode = LOCAT.m;
/*+-------------------------------------------------------------------------+
| |
| Process the frame part. |
| |
+-------------------------------------------------------------------------+*/
If FIX_DAT.f IsZero
Then /* Frame is specified explicitly */
frame_method = FIX_DAT.frame;
fixup.frame_method = frame_method;
Using frame_method
BeginCase
When 0:
fixup.frame_referent = (void far *) snames[obj_index_segment()];
break;
When 1:
fixup.frame_referent = (void far *) gnames[obj_index_group()];
break;
When 2:
fixup.frame_referent = (void far *) externals[obj_index_external()];
break;
When 3:
fixup.frame_referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
Otherwise:
fixup.frame_referent = Null;
break;
EndCase;
Else /* Frame is specified by a thread */
thread_number = FIX_DAT.frame;
If Not frame_thread[thread_number].thread_defined
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Reference to frame thread %u which has "
"been defined.n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
thread_number);
EndIf;
fixup.frame_referent = frame_thread[thread_number].referent;
fixup.frame_method = frame_thread[thread_number].method;
EndIf;
/*+-------------------------------------------------------------------------+
| |
| Process the target part. |
| |
+-------------------------------------------------------------------------+*/
If FIX_DAT.t IsZero
Then /* Target is specified explicitly */
target_method = FIX_DAT.targt;
fixup.target_method = target_method;
Using target_method
BeginCase
When 0: /* Target is the segment referenced by the index */
fixup.target_referent = (void far *) snames[obj_index_segment()];
break;
When 1: /* Target is the lowest seg in the group referenced
by the index */
fixup.target_referent = (void far *) gnames[obj_index_group()];
break;
When 2:
fixup.target_referent = (void far *) externals[obj_index_external()];
break;
When 3:
fixup.target_referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
break;
EndCase;
Else /* Target is specified by a thread */
thread_number = FIX_DAT.targt;
If Not target_thread[thread_number].thread_defined
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Reference to target thread %u which has "
"been defined.n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
thread_number);
EndIf;
fixup.target_referent = target_thread[thread_number].referent;
fixup.target_method = target_thread[thread_number].method;
EndIf;
If FIX_DAT.p IsZero
Then /* There is a target displacement */
fixup.target_offset = *obj_ptr.b16++;
Else /* The target displacement is zero */
fixup.target_offset = 0;
EndIf;
fixup.external_error_detected = False;
If (fixup.mode IsZero) AndIf
((fixup.location_type Is base_location) OrIf
(fixup.location_type Is pointer_location) OrIf
(fixup.location_type Is hibyte_location))
Then /* Undefined fixup action */
linker_error(4, "Possible translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Base, pointer or hibyte self-relative fixups\n"
"\t are undefined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If last_LxDATA_record_type Is LEDATA_record
Then
If ((fixup.location_type Is base_location) OrIf
(fixup.location_type Is pointer_location)) AndIf
(exefile IsTrue)
Then /* Base and pointer locations will require a relocation item
in the EXE header */
n_relocation_items++;
EndIf;
write_temp_file(Current_record_header.rec_typ,
last_LxDATA_lseg,
last_LxDATA_offset + fixup_index,
BytePtr(Addr(fixup)),
sizeof(fixup));
Else
If fixup.mode IsZero
Then
linker_error(4, "Translator warning:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Self-relative fixup not permitted for "
"LIDATA.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
Else
obj_fixup_LIDATA();
EndIf;
EndIf;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_fixup_LIDATA |
| |
+-------------------------------------------------------------------------+*/
void obj_fixup_LIDATA()
BeginDeclarations
obj_ptr_type old_obj_ptr;
EndDeclarations
BeginCode
LIDATA_index = 0;
LIDATA_offset = last_LxDATA_offset;
old_obj_ptr = obj_ptr;
obj_ptr.b8 = Last_LIDATA_record_header.variant_part;
end_of_last_LIDATA_record.b8 =
(byte *)
Addr(Last_LIDATA_record_header.variant_part
[Last_LIDATA_record_header.rec_len-1]);
obj_index_segment();
obj_ptr.b16++;
While obj_ptr.b8 IsNot end_of_last_LIDATA_record.b8
BeginWhile
obj_fixup_LIDATA_IDB();
EndWhile;
obj_ptr = old_obj_ptr;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_fixup_LIDATA_IDB |
| |
+-------------------------------------------------------------------------+*/
void obj_fixup_LIDATA_IDB()
BeginDeclarations
bit_16 block_count;
bit_8 *content;
bit_16 i;
bit_16 j;
bit_16 len;
bit_16 old_index;
bit_16 repeat_count;
EndDeclarations
BeginCode
repeat_count = *obj_ptr.b16++; LIDATA_index += sizeof(bit_16);
block_count = *obj_ptr.b16++; LIDATA_index += sizeof(bit_16);
content = obj_ptr.b8;
old_index = LIDATA_index;
If block_count IsNotZero
Then /* Handle recursive case: Content is iterated data block */
For i=0; i<repeat_count; i++
BeginFor
obj_ptr.b8 = content;
LIDATA_index = old_index;
For j=0; j<block_count; j++
BeginFor
obj_fixup_LIDATA_IDB();
EndFor;
EndFor;
Else /* Handle non-recursive case: Content is data. */
For i=0; i<repeat_count; i++
BeginFor
obj_ptr.b8 = content;
LIDATA_index = old_index;
len = Bit_16(*obj_ptr.b8++); LIDATA_index += sizeof(bit_8);
If (fixup_index NotLessThan LIDATA_index) AndIf
(fixup_index LessThan (LIDATA_index + len))
Then
write_temp_file(Current_record_header.rec_typ,
last_LxDATA_lseg,
LIDATA_offset + fixup_index - LIDATA_index,
BytePtr(Addr(fixup)),
sizeof(fixup));
If ((fixup.location_type Is base_location) OrIf
(fixup.location_type Is pointer_location)) AndIf
(exefile IsTrue)
Then /* Base and pointer locations will require a relocation item
in the EXE header */
n_relocation_items++;
EndIf;
EndIf;
LIDATA_offset += len;
EndFor;
obj_ptr.b8 += len;
LIDATA_index += len;
EndIf;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_FIXUPP_thread |
| |
+-------------------------------------------------------------------------+*/
void obj_FIXUPP_thread()
BeginDeclarations
bit_16 method;
bit_16 thread;
TRD_DAT_type TRD_DAT;
EndDeclarations
BeginCode
TRD_DAT = *obj_ptr.TRD_DAT++;
thread = TRD_DAT.thred;
method = TRD_DAT.method;
If TRD_DAT.d IsZero
Then /* This is a target thread */
target_thread[thread].method = Bit_8(method);
target_thread[thread].thread_defined = True;
Using method
BeginCase
When 0:
target_thread[thread].referent =
(void far *) snames[obj_index_segment()];
break;
When 1:
target_thread[thread].referent =
(void far *) gnames[obj_index_group()];
break;
When 2:
target_thread[thread].referent =
(void far *) externals[obj_index_external()];
break;
When 3:
target_thread[thread].referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
Otherwise:
target_thread[thread].referent = Null;
break;
EndCase;
Else /* This is a frame thread */
frame_thread[thread].method = Bit_8(method);
frame_thread[thread].thread_defined = True;
Using method
BeginCase
When 0:
frame_thread[thread].referent =
(void far *) snames[obj_index_segment()];
break;
When 1:
frame_thread[thread].referent =
(void far *) gnames[obj_index_group()];
break;
When 2:
frame_thread[thread].referent =
(void far *) externals[obj_index_external()];
break;
When 3:
frame_thread[thread].referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
Otherwise:
frame_thread[thread].referent = Null;
break;
EndCase;
EndIf;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_FORREF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_FORREF()
BeginDeclarations
bit_16 len;
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot FORREF_record
Then
return(False);
EndIf;
segment_index = obj_index_segment();
len = Current_record_header.rec_len - 2;
If segment_index Exceeds 127
Then
len--;
EndIf;
write_temp_file(Current_record_header.rec_typ,
snames[segment_index],
0,
BytePtr(obj_ptr.b8),
len);
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_generate_segment |
| |
+-------------------------------------------------------------------------+*/
lseg_ptr obj_generate_segment(lname_entry_ptr segment_lname,
lname_entry_ptr class_lname,
combine_type combine,
bit_8 align,
lname_entry_ptr tmodule,
file_info_ptr file,
bit_32 address,
bit_32 length)
BeginDeclarations
lseg_ptr lseg;
#define Lseg (*lseg)
segment_entry_ptr seg;
#define Seg (*seg)
EndDeclarations
BeginCode
If combine Is stack_combine
Then
length += AlignmentGap(length, 1L); /* Stacks should be an integral
number of words. */
EndIf;
seg = lookup_segment(segment_lname, class_lname, combine);
If (combine IsNot common_combine) OrIf (Seg.lsegs.first IsNull)
Then
Seg.address = address;
Seg.length += length;
lseg = (lseg_ptr)
allocate_memory(Addr(static_pool),
Bit_32(sizeof(lseg_type)));
Lseg.segment = seg;
Lseg.tmodule = tmodule;
Lseg.file = file;
Lseg.address = address;
Lseg.length = length;
Lseg.align = align;
If (combine IsNot common_combine) AndIf
(combine IsNot blank_common_combine)
Then /* Don't allocate common data yet. (We will wait until we
know how long the common block will be.) */
Lseg.data = allocate_memory(Addr(static_pool), length);
EndIf;
Lseg.highest_uninitialized_byte = 0L;
Insert lseg AtEnd InList Seg.lsegs EndInsert;
Else /* Not the first occurrence of this common */
lseg = Seg.lsegs.first;
If length Exceeds Seg.length
Then /* Expand common block to be big enough to hold this entry. */
Seg.length =
Lseg.length = length;
EndIf;
If align Exceeds Lseg.align
Then /* Align to largest boundary. */
Lseg.align = align;
EndIf;
EndIf;
If Seg.combine Is stack_combine
Then
If Not stack_segment_found
Then
largest_stack_seg = seg;
largest_stack_seg_length = Seg.length;
stack_segment_found = True;
Else
If Seg.length Exceeds largest_stack_seg_length
Then
largest_stack_seg = seg;
largest_stack_seg_length = Seg.length;
EndIf;
EndIf;
EndIf;
return(lseg);
EndCode
#undef Lseg
#undef Seg
/*+-------------------------------------------------------------------------+
| |
| obj_GRPDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_GRPDEF()
BeginDeclarations
group_entry_ptr group;
#define Group (*group)
bit_16 group_index;
lseg_ptr lseg;
#define Lseg (*lseg)
segment_entry_ptr seg;
#define Seg (*seg)
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot GRPDEF_record
Then
return(False);
EndIf;
group_index = obj_index_LNAME();
group = lookup_group(lnames[group_index]);
If n_groups NotLessThan max_groups.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many GRPDEFs. Max of %u exceeded.\n"
"\t Retry with larger \"/maxgroups:n\" switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_groups.val);
EndIf;
gnames[++n_groups] = group;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If *obj_ptr.b8++ IsNot 0xFF
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: GRPDEF record has a group component "
"descriptor which\n"
"\t does not start with 0xFF.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
segment_index = obj_index_segment();
lseg = snames[segment_index];
seg = Lseg.segment;
If Seg.owning_group IsNull
Then
Seg.owning_group = group;
Else
If Seg.owning_group IsNot group
Then
linker_error(4, "Attempt to place segment \"%Fs\" into group \"%Fs\"\n"
"\twhen it is already in group \"%Fs\".\n"
"\tRequest to place in group \"%Fs\" ignored.\n",
(*Seg.segment_name).symbol, (*Group.group_name).symbol,
(*(*Seg.owning_group).group_name).symbol,
(*Group.group_name).symbol);
EndIf;
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Seg
#undef Group
#undef Lseg
/*+-------------------------------------------------------------------------+
| |
| obj_index_external |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_index_external()
BeginDeclarations
bit_16 index;
EndDeclarations
BeginCode
If *obj_ptr.b8 LessThan 128
Then
index = Bit_16(*obj_ptr.b8++);
Else
index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
Bit_16(*obj_ptr.b8++);
EndIf;
If index Exceeds n_externals
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Invalid external index (%u) with only %u "
"externals defined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
index, n_externals);
EndIf;
return(index);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_index_group |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_index_group()
BeginDeclarations
bit_16 index;
EndDeclarations
BeginCode
If *obj_ptr.b8 LessThan 128
Then
index = Bit_16(*obj_ptr.b8++);
Else
index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
Bit_16(*obj_ptr.b8++);
EndIf;
If index Exceeds n_groups
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Invalid group index (%u) with only %u "
"groups defined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
index, n_groups);
EndIf;
return(index);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_index_LNAME |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_index_LNAME()
BeginDeclarations
bit_16 index;
EndDeclarations
BeginCode
If *obj_ptr.b8 LessThan 128
Then
index = Bit_16(*obj_ptr.b8++);
Else
index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
Bit_16(*obj_ptr.b8++);
EndIf;
If index Exceeds n_lnames
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Invalid LNAME index (%u) with only %u "
"LNAMEs defined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
index, n_lnames);
EndIf;
return(index);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_index_segment |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_index_segment()
BeginDeclarations
bit_16 index;
EndDeclarations
BeginCode
If *obj_ptr.b8 LessThan 128
Then
index = Bit_16(*obj_ptr.b8++);
Else
index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
Bit_16(*obj_ptr.b8++);
EndIf;
If index Exceeds n_segments
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Invalid segment index (%u) with only %u "
"segments defined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
index, n_segments);
EndIf;
return(index);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_iterated_data_block |
| |
+-------------------------------------------------------------------------+*/
void obj_iterated_data_block()
BeginDeclarations
bit_16 block_count;
bit_8 *content;
bit_16 i;
bit_16 j;
bit_16 len;
bit_16 repeat_count;
EndDeclarations
BeginCode
repeat_count = *obj_ptr.b16++;
block_count = *obj_ptr.b16++;
If block_count IsNotZero
Then /* Handle recursive case: Content is iterated data block */
content = obj_ptr.b8;
For i=0; i<repeat_count; i++
BeginFor
obj_ptr.b8 = content;
For j=0; j<block_count; j++
BeginFor
obj_iterated_data_block();
EndFor;
EndFor;
Else /* Handle non-recursive case: Content is data. */
len = Bit_16(*obj_ptr.b8++);
For i=0; i<repeat_count; i++
BeginFor
far_move(Addr(last_LxDATA_Lseg.data[LIDATA_offset]),
obj_ptr.b8, len);
LIDATA_offset += len;
EndFor;
obj_ptr.b8 += len;
EndIf;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_iterated_data_block_length |
| |
+-------------------------------------------------------------------------+*/
bit_32 obj_iterated_data_block_length()
BeginDeclarations
bit_16 block_count;
bit_16 i;
bit_16 len;
bit_32 length;
bit_16 repeat_count;
EndDeclarations
BeginCode
repeat_count = *obj_ptr.b16++;
block_count = *obj_ptr.b16++;
If repeat_count IsZero
Then /* This is a translator error. */
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Repeat count in LIDATA iterated data block "
"is zero.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
length = 0L;
If block_count IsNotZero
Then /* Handle recursive case: Content is iterated data block */
For i=0; i<block_count; i++
BeginFor
length += Bit_32(repeat_count) * obj_iterated_data_block_length();
EndFor;
Else /* Handle non-recursive case: Content is data. */
len = Bit_16(*obj_ptr.b8++);
obj_ptr.b8 += len;
length = Bit_32(repeat_count) * Bit_32(len);
EndIf;
return(length);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_leaf_descriptor |
| |
+-------------------------------------------------------------------------+*/
bit_32 obj_leaf_descriptor()
BeginDeclarations
bit_8 element_size;
EndDeclarations
BeginCode
element_size = *obj_ptr.b8++;
If element_size LessThan 129
Then
return(Bit_32(element_size));
Else
If element_size Is 129
Then
return(Bit_32(*obj_ptr.b16++));
Else
If element_size Is 132
Then
obj_ptr.b8--;
return((*obj_ptr.b32++) And 0x00FFFFFFL);
Else
If element_size Is 136
Then
return(*obj_ptr.b32++);
Else
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Communal element size of %u is illegal.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
element_size);
EndIf;
EndIf;
EndIf;
EndIf;
return(0L);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_LEDATA |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_LEDATA()
BeginDeclarations
bit_32 next_byte;
bit_16 len;
lseg_ptr lseg;
#define Lseg (*lseg)
bit_16 offset;
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot LEDATA_record
Then
return(False);
EndIf;
last_LxDATA_record_type = Current_record_header.rec_typ;
segment_index = obj_index_segment();
last_LxDATA_lseg =
lseg = snames[segment_index];
len = Current_record_header.rec_len - 4;
If segment_index Exceeds 127
Then
len--;
EndIf;
last_LxDATA_offset =
offset = *obj_ptr.b16++;
next_byte = Bit_32(offset) + Bit_32(len);
If next_byte Exceeds Lseg.length
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Attempt to initialize past end of LSEG.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If next_byte Exceeds Lseg.highest_uninitialized_byte
Then
Lseg.highest_uninitialized_byte = next_byte;
EndIf;
If (*last_LxDATA_Lseg.segment).combine IsNot common_combine
Then
far_move(Addr(Lseg.data[offset]), obj_ptr.b8, len);
Else /* We must save the initialization data out to the tmp file until
later when we know the length. */
write_temp_file(Current_record_header.rec_typ,
last_LxDATA_lseg,
last_LxDATA_offset,
BytePtr(obj_ptr.b8),
len);
EndIf;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_LIDATA |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_LIDATA()
BeginDeclarations
bit_16 len;
bit_32 LIDATA_length;
bit_32 next_byte;
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot LIDATA_record
Then
return(False);
EndIf;
far_move(BytePtr(last_LIDATA_record),
BytePtr(object_file_element),
Current_record_header.rec_len + sizeof(obj_record_header_type) - 1);
last_LxDATA_record_type = Current_record_header.rec_typ;
segment_index = obj_index_segment();
last_LxDATA_lseg = snames[segment_index];
LIDATA_offset =
last_LxDATA_offset = *obj_ptr.b16++;
LIDATA_length = obj_LIDATA_length();
next_byte = last_LxDATA_offset + LIDATA_length;
If next_byte Exceeds last_LxDATA_Lseg.length
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Attempt to initialize past end of LSEG.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If next_byte Exceeds last_LxDATA_Lseg.highest_uninitialized_byte
Then
last_LxDATA_Lseg.highest_uninitialized_byte = next_byte;
EndIf;
If (*last_LxDATA_Lseg.segment).combine IsNot common_combine
Then
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
obj_iterated_data_block();
EndWhile;
Else /* We must save the initialization data out to the tmp file until
later when we know the length. */
len = Current_record_header.rec_len - 4;
If segment_index Exceeds 127
Then
len--;
EndIf;
write_temp_file(Current_record_header.rec_typ,
last_LxDATA_lseg,
last_LxDATA_offset,
BytePtr(obj_ptr.b8),
len);
EndIf;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_LIDATA_length |
| |
+-------------------------------------------------------------------------+*/
bit_32 obj_LIDATA_length()
BeginDeclarations
bit_32 length;
bit_8 *start;
EndDeclarations
BeginCode
start = obj_ptr.b8;
length = 0L;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
length += obj_iterated_data_block_length();
EndWhile;
obj_ptr.b8 = start;
return(length);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_LINNUM |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_LINNUM()
BeginDeclarations
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot LINNUM_record
Then
return(False);
EndIf;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_LNAMES |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_LNAMES()
BeginDeclarations
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot LNAMES_record
Then
return(False);
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If n_lnames NotLessThan max_lnames.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many LNAMES. Max of %u exceeded.\n"
"\t Retry with larger \"/maxlnames:n\" switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_lnames.val);
EndIf;
lnames[++n_lnames] = obj_name();
EndWhile;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_MODEND |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_MODEND()
BeginDeclarations
FIX_DAT_type END_DAT;
bit_16 frame_method;
MOD_TYP_type MOD_TYP;
bit_16 target_method;
bit_16 thread_number;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot MODEND_record
Then
return(False);
EndIf;
MOD_TYP = *obj_ptr.MOD_TYP++;
If MOD_TYP.zeros IsNotZero
Then
linker_error(4, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Bits 1 thru 5 of MOD TYP must be zero.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If (MOD_TYP.mattr IsNot 1) AndIf (MOD_TYP.mattr IsNot 3)
Then /* We have no starting address */
return(True);
EndIf;
If MOD_TYP.l IsNot 1
Then
linker_error(4, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Bit 0 of MOD TYP must be one.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If start_address_found IsTrue
Then
linker_error(4, "Multiple start address encountered. The start address\n"
"in module \"%Fs\" of file \"%Fs\" has been ignored.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename);
EndIf;
start_address_found = True;
/*+-------------------------------------------------------------------------+
| |
| Pick up the required field END_DAT. |
| |
+-------------------------------------------------------------------------+*/
END_DAT = *obj_ptr.FIX_DAT++;
/*+-------------------------------------------------------------------------+
| |
| Process the frame part. |
| |
+-------------------------------------------------------------------------+*/
If END_DAT.f IsZero
Then /* Frame is specified explicitly */
frame_method = END_DAT.frame;
start_address.frame_method = frame_method;
Using frame_method
BeginCase
When 0:
start_address.frame_referent =
(void far *) snames[obj_index_segment()];
break;
When 1:
start_address.frame_referent =
(void far *) gnames[obj_index_group()];
break;
When 2:
start_address.frame_referent =
(void far *) externals[obj_index_external()];
break;
When 3:
start_address.frame_referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
Otherwise:
start_address.frame_referent = Null;
break;
EndCase;
Else /* Frame is specified by a thread */
thread_number = END_DAT.frame;
If Not frame_thread[thread_number].thread_defined
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Reference to frame thread %u which has "
"been defined.n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
thread_number);
EndIf;
start_address.frame_referent = frame_thread[thread_number].referent;
start_address.frame_method = frame_thread[thread_number].method;
EndIf;
/*+-------------------------------------------------------------------------+
| |
| Process the target part. |
| |
+-------------------------------------------------------------------------+*/
If END_DAT.t IsZero
Then /* Target is specified explicitly */
target_method = END_DAT.targt;
start_address.target_method = target_method;
Using target_method
BeginCase
When 0:
start_address.target_referent =
(void far *) snames[obj_index_segment()];
break;
When 1:
start_address.target_referent =
(void far *) gnames[obj_index_group()];
break;
When 2:
start_address.target_referent =
(void far *) externals[obj_index_external()];
break;
When 3:
start_address.target_referent =
(void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
break;
EndCase;
Else /* Target is specified by a thread */
thread_number = END_DAT.targt;
If Not target_thread[thread_number].thread_defined
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Reference to target thread %u which has "
"been defined.n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
thread_number);
EndIf;
start_address.target_referent = target_thread[thread_number].referent;
start_address.target_method = target_thread[thread_number].method;
EndIf;
If END_DAT.p IsZero
Then /* There is a target displacement */
start_address.target_offset = *obj_ptr.b16++;
Else /* The target displacement is zero */
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Only primary fixups allowed in MODEND.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
start_address.target_offset = 0;
EndIf;
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_MODEXT |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_MODEXT()
BeginDeclarations
bit_16 len;
public_entry_ptr pub;
#define Pub (*pub)
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot MODEXT_record
Then
return(False);
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If n_externals NotLessThan max_externals.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many externals. Max of %u exceeded.\n"
"\t Retry with larger \"/maxexternals:n\" "
"switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_externals.val);
EndIf;
len = obj_name_length();
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
pub = lookup_public(len, obj_ptr.b8, tmodule_number);
obj_ptr.b8 += len;
obj_name_length(); /* Eat the type index. */
externals[++n_externals] = pub;
If Pub.type_entry Is unused
Then
Insert pub AtEnd InList external_list EndInsert;
Pub.type_entry = external;
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| obj_MODPUB |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_MODPUB()
BeginDeclarations
bit_16 group_index;
bit_16 frame;
bit_16 len;
public_entry_ptr pub;
#define Pub (*pub)
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot MODPUB_record
Then
return(False);
EndIf;
group_index = obj_index_group();
segment_index = obj_index_segment();
If (segment_index IsZero) AndIf (group_index IsZero)
Then
frame = *obj_ptr.b16++;
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
len = obj_name_length();
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
pub = lookup_public(len, obj_ptr.b8, tmodule_number);
obj_ptr.b8 += len;
If Pub.type_entry Is internal
Then
linker_error(4, "Duplicate definition of public \"%Fs\".\n"
"\tDefinition in module \"%Fs\" of file \"%Fs\" "
"ignored.\n",
Pub.symbol,
(*tmodule_name).symbol,(*infile.file_info).filename);
obj_ptr.b16++; /* Eat offset. */
obj_name_length(); /* Eat type index. */
Else
If Pub.type_entry Is unused
Then
Insert pub AtEnd InList external_list EndInsert;
EndIf;
Pub.type_entry = internal;
Pub.Internal.group = gnames[group_index];
Pub.Internal.lseg = snames[segment_index];
Pub.Internal.frame = frame;
Pub.Internal.offset = *obj_ptr.b16++;
obj_name_length(); /* Eat type index. */
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| obj_modtail |
| |
+-------------------------------------------------------------------------+*/
/* obj_modtail:: obj_MODEND */
bit_16 obj_modtail()
BeginDeclarations
EndDeclarations
BeginCode
If obj_MODEND()
Then
return(True);
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_name |
| |
+-------------------------------------------------------------------------+*/
lname_entry_ptr obj_name()
BeginDeclarations
lname_entry_ptr name;
bit_16 len;
EndDeclarations
BeginCode
len = obj_name_length();
If len IsZero
Then
name = none_lname;
Else
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
name = lookup_lname(len, obj_ptr.b8);
obj_ptr.b8 += len;
EndIf;
return(name);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_name_length |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_name_length()
BeginDeclarations
EndDeclarations
BeginCode
If *obj_ptr.b8 LessThan 128
Then
return(Bit_16(*obj_ptr.b8++));
Else
return((Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
(Bit_16(*obj_ptr.b8++)));
EndIf;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_next_record |
| |
+-------------------------------------------------------------------------+*/
void obj_next_record()
BeginDeclarations
EndDeclarations
BeginCode
Repeat
BeginRepeat
file_read(object_file_element, sizeof(obj_record_header_type) - 1);
While (Current_record_header.rec_typ Is LINNUM_record) OrIf
((Current_record_header.rec_typ Is COMENT_record) AndIf
(Current_record_header.rec_len Exceeds MAX_OBJECT_FILE_READ_SIZE))
BeginWhile
file_position(Bit_32(infile.byte_position) +
infile.start_of_buffer_position +
Bit_32(Current_record_header.rec_len));
file_read(object_file_element, sizeof(obj_record_header_type) - 1);
EndWhile;
current_record_offset = Bit_32(infile.byte_position) +
infile.start_of_buffer_position -
Bit_32(sizeof(obj_record_header_type)-1);
If Current_record_header.rec_len Exceeds MAX_OBJECT_FILE_READ_SIZE
Then
linker_error(12, "Probable invalid OBJ format "
"or possible translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Record too long.\n"
"\t Max record length supported by this "
"linker is %u bytes.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
MAX_OBJECT_FILE_READ_SIZE);
EndIf;
file_read(Current_record_header.variant_part,
Current_record_header.rec_len);
If (objchecksum.val IsTrue) AndIf
(Bit_8(checksum(Current_record_header.rec_len +
sizeof(obj_record_header_type)-1,
(byte *) current_record_header)) IsNotZero)
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Checksum error.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
obj_ptr.b8 = Current_record_header.variant_part;
end_of_record.b8 =
(byte *)
Addr(Current_record_header.variant_part[Current_record_header.rec_len-1]);
RepeatIf obj_COMENT()
EndRepeat;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_PUBDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_PUBDEF()
BeginDeclarations
bit_16 group_index;
bit_16 frame;
bit_16 len;
public_entry_ptr pub;
#define Pub (*pub)
bit_16 segment_index;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot PUBDEF_record
Then
return(False);
EndIf;
group_index = obj_index_group();
segment_index = obj_index_segment();
If (segment_index IsZero) AndIf (group_index IsZero)
Then
frame = *obj_ptr.b16++;
EndIf;
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
len = obj_name_length();
If case_ignore.val
Then
far_to_lower(BytePtr(obj_ptr.b8), len);
EndIf;
pub = lookup_public(len, obj_ptr.b8, 0);
obj_ptr.b8 += len;
If Pub.type_entry Is internal
Then
linker_error(4, "Duplicate definition of public \"%Fs\".\n"
"\tDefinition in module \"%Fs\" of file \"%Fs\" "
"ignored.\n",
Pub.symbol,
(*tmodule_name).symbol,(*infile.file_info).filename);
obj_ptr.b16++; /* Eat offset. */
obj_name_length(); /* Eat type index. */
Else
If Pub.type_entry Is unused
Then
Insert pub AtEnd InList external_list EndInsert;
EndIf;
If (Pub.type_entry Is public_in_library) AndIf
(Pub.Library.requested)
Then
library_request_count--;
(*Pub.Library.lib_file).request_count--;
EndIf;
Pub.type_entry = internal;
Pub.Internal.group = gnames[group_index];
Pub.Internal.lseg = snames[segment_index];
Pub.Internal.frame = frame;
Pub.Internal.offset = *obj_ptr.b16++;
obj_name_length(); /* Eat type index. */
EndIf;
EndWhile;
obj_next_record();
return(True);
EndCode
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| obj_SEGDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_SEGDEF()
BeginDeclarations
acbp_type acbp;
bit_32 address;
bit_8 align;
lname_entry_ptr class_lname;
bit_8 combine;
bit_32 length;
lseg_ptr lseg;
#define Lseg (*lseg)
bit_16 segment_index;
lname_entry_ptr segment_lname;
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot SEGDEF_record
Then
return(False);
EndIf;
acbp = *obj_ptr.acbp++;
align = Bit_8(acbp.a);
If align Is absolute_segment
Then
address = (Bit_32(*obj_ptr.b16++) ShiftedLeft 4L); /* Frame */
address += Bit_32(*obj_ptr.b8++); /* Offset */
Else
address = 0L;
EndIf;
If align Exceeds dword_aligned
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Align type of %u is undefined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
align);
EndIf;
combine = Bit_8(acbp.c);
If (combine Is 4) OrIf (combine Is 7)
Then /* Treat combine types 4 and 7 the same as 2. */
combine = public_combine;
EndIf;
If (combine Is 1) OrIf (combine Is 3)
Then /* This is a translator error. */
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Combine type of %u is undefined.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
combine);
EndIf;
length = Bit_32(*obj_ptr.b16++);
If acbp.b IsNotZero
Then
If length IsNotZero
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: SEGDEF has acbp.b of 1 and length not "
"zero.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
length = 65536L;
EndIf;
segment_index = obj_index_LNAME();
segment_lname = lnames[segment_index];
class_lname = lnames[obj_index_LNAME()];
lseg = obj_generate_segment(segment_lname,
class_lname,
combine,
align,
tmodule_name,
infile.file_info,
address,
length);
If n_segments NotLessThan max_segments.val
Then
linker_error(12, "Internal limit exceeded:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Too many SEGDEFs. Max of %u exceeded.\n"
"\t Retry with larger \"/maxsegments:n\" "
"switch.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset,
max_segments.val);
EndIf;
snames[++n_segments] = lseg;
obj_next_record();
return(True);
EndCode
#undef Lseg
/*+-------------------------------------------------------------------------+
| |
| obj_seg_grp |
| |
+-------------------------------------------------------------------------+*/
/* obj_seg_grp:: {obj_LNAMES | obj_SEGDEF | obj_EXTDEF}
{obj_TYPDEF | obj_EXTDEF | obj_GRPDEF} */
bit_16 obj_seg_grp()
BeginDeclarations
EndDeclarations
BeginCode
While obj_LNAMES() OrIf obj_SEGDEF() OrIf obj_EXTDEF()
BeginWhile
EndWhile;
While obj_TYPDEF() OrIf obj_EXTDEF() OrIf obj_GRPDEF()
BeginWhile
EndWhile;
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_THEADR |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_THEADR()
BeginDeclarations
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot THEADR_record
Then
return(False);
EndIf;
tmodule_name = obj_name();
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_thread_def |
| |
+-------------------------------------------------------------------------+*/
/* obj_thread_def:: obj_FIXUPP (containing only thread fields) */
bit_16 obj_thread_def()
BeginDeclarations
EndDeclarations
BeginCode
If obj_FIXUPP()
Then
If FIXUPP_contains_only_threads
Then
return(True);
Else
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: \"THREAD DEF\" FIXUPP encountered which "
"did not contain\n"
"\t only thread defs.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
EndIf;
return(False);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_tmodule |
| |
+-------------------------------------------------------------------------+*/
/* obj_t_module:: obj_THEADR obj_seg_grp {obj_component} obj_modtail */
bit_16 obj_tmodule()
BeginDeclarations
EndDeclarations
BeginCode
far_set(BytePtr(externals), 0,
sizeof(public_entry_ptr)*(max_externals.val+1));
far_set(BytePtr(gnames), 0,
sizeof(group_entry_ptr)*(max_groups.val+1));
far_set(BytePtr(lnames), 0,
sizeof(lname_entry_ptr)*(max_lnames.val+1));
far_set(BytePtr(snames), 0,
sizeof(lseg_ptr)*(max_segments.val+1));
far_set(BytePtr(target_thread), 0, sizeof(thread_type)*4);
far_set(BytePtr(frame_thread), 0, sizeof(thread_type)*4);
n_externals =
n_groups =
n_lnames =
n_segments = 0;
tmodule_number++;
tmodule_name = lookup_lname(31, (byte *) "(THEADR record not encountered)");
obj_next_record();
If Not obj_THEADR()
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: T-MODULE record missing.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
If Not obj_seg_grp()
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: Segment/Group definition record(s) missing.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
While obj_component()
BeginWhile
EndWhile;
If Not obj_modtail()
Then
linker_error(12, "Translator error:\n"
"\tModule: \"%Fs\"\n"
"\t File: \"%Fs\"\n"
"\tOffset: %lu\n"
"\t Error: MODEND record missing.\n",
(*tmodule_name).symbol,
(*infile.file_info).filename,
current_record_offset);
EndIf;
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| obj_TYPDEF |
| |
+-------------------------------------------------------------------------+*/
bit_16 obj_TYPDEF()
BeginDeclarations
EndDeclarations
BeginCode
If Current_record_header.rec_typ IsNot TYPDEF_record
Then
return(False);
EndIf;
obj_next_record();
return(True);
EndCode
/*+-------------------------------------------------------------------------+
| |
| write_temp_file |
| |
+-------------------------------------------------------------------------+*/
void write_temp_file(bit_8 rec_typ,
lseg_ptr lseg,
bit_16 offset,
byte_ptr data,
bit_16 len)
BeginDeclarations
EndDeclarations
BeginCode
temp_file_header.rec_typ = rec_typ;
temp_file_header.rec_len = len;
temp_file_header.lseg = lseg;
temp_file_header.offset = offset;
file_write(BytePtr(Addr(temp_file_header)),
Bit_32(sizeof(temp_file_header)));
If len Exceeds 0
Then
file_write(data, Bit_32(len));
EndIf;
return;
EndCode