windows-nt/Source/XPSP1/NT/sdktools/link16/newtp1.c

2498 lines
93 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* Copyright Microsoft Corporation, 1983-1989
*
* This Module contains Proprietary Information of Microsoft
* Corporation and should be treated as Confidential.
*/
/****************************************************************
* *
* NEWTP1.C *
* *
* Pass 1 object module processing routines. *
* *
****************************************************************/
#include <minlit.h> /* Basic types and constants */
#include <bndtrn.h> /* More types and constants */
#include <bndrel.h> /* Relocation record definitions */
#include <lnkio.h> /* Linker I/O definitions */
#include <newexe.h> /* DOS & 286 .EXE data structures */
#if EXE386
#include <exe386.h> /* 386 .EXE data structures */
#endif
#include <lnkmsg.h> /* Error messages */
#if OXOUT OR OIAPX286
#include <xenfmt.h> /* Xenix format definitions */
#endif
#include <extern.h> /* External declarations */
#include <undname.h>
#if OVERLAYS
WORD iovFile; /* Overlay number of input file */
#endif
LOCAL FTYPE fP2Start; /* Start of Pass 2 records */
LOCAL FTYPE fModEnd; /* MODEND seen */
LOCAL WORD cSegCode; /* Number of code seg's in module */
#if O68K
#define F68KCODE(ch) ((ch) >= 'A' && (ch) <= 'E')
#endif /* O68K */
/*
* LOCAL FUNCTION PROTOTYPES
*/
LOCAL void NEAR TypErr(MSGTYPE msg,unsigned char *sb);
LOCAL void NEAR DoCommon(APROPUNDEFPTR apropUndef,
long length,
unsigned short cbEl,
unsigned char *sb);
LOCAL void NEAR SegUnreliable(APROPSNPTR apropSn);
LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes);
LOCAL void NEAR SegRc1(void);
LOCAL void NEAR TypRc1(void);
LOCAL void NEAR ComDf1(void);
LOCAL void NEAR GrpRc1(void);
LOCAL void NEAR PubRc1(void);
LOCAL void NEAR ExtRc1(void);
LOCAL void NEAR imprc1(void);
LOCAL void NEAR exprc1(void);
LOCAL void NEAR ComRc1(void);
LOCAL void NEAR EndRc1(void);
extern void NEAR FixRc1(void);
LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes)
{
// Redefinition of default resolution.
// Warn the user.
SBTYPE oldDefault;
SBTYPE newDefault;
APROPUNDEFPTR undef;
AHTEPTR rhte;
undef = (APROPUNDEFPTR ) FetchSym(oldDefRes, FALSE);
while (undef->au_attr != ATTRNIL)
{
rhte = (AHTEPTR) undef->au_next;
/* Try next entry in list */
undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
/* Fetch it from VM */
}
strcpy(oldDefault, GetFarSb(rhte->cch));
undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextDefRes], FALSE);
while (undef->au_attr != ATTRNIL)
{
rhte = (AHTEPTR) undef->au_next;
/* Try next entry in list */
undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
/* Fetch it from VM */
}
strcpy(newDefault, GetFarSb(rhte->cch));
undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], FALSE);
while (undef->au_attr != ATTRNIL)
{
rhte = (AHTEPTR) undef->au_next;
/* Try next entry in list */
undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE);
/* Fetch it from VM */
}
OutWarn(ER_weakredef, 1 + GetFarSb(rhte->cch), &oldDefault[1], &newDefault[1]);
}
/*** IsDebSeg - check is segment is one of the special debug segments
*
* Purpose:
* Check if segment name and class name match reserved debugger
* segment names.
*
* Input:
* - rhteClass - pointer to class name
* - rhteSeg - pointer to segment name
*
* Output:
* If this is a debug segment function returns 1 for $$TYPES, and 2
* for $$SYMBOLS. For non-debug segments it returns FALSE.
*
* Exceptions:
* None.
*
* Notes:
* None.
*
*************************************************************************/
WORD NEAR IsDebSeg(RBTYPE rhteClass, RBTYPE rhteSeg)
{
if (rhteClass == rhteDebTyp)
return ((rhteSeg == rhteTypes || rhteSeg == rhte0Types) ? 1 : FALSE);
else if (rhteClass == rhteDebSym)
return ((rhteSeg == rhteSymbols || rhteSeg == rhte0Symbols) ? 2 : FALSE);
else
return(FALSE);
}
/****************************************************************
* *
* ModRc1: *
* *
* This function reads the name from a THEADR record and makes *
* an entry containing the name in the hash table. *
* See p. 26 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
void NEAR ModRc1(void)
{
APROPFILEPTR apropFile;
sbModule[0] = (BYTE) Gets(); /* Read in the length byte */
GetBytes(&sbModule[1],B2W(sbModule[0]));
/* Read in the name */
PropSymLookup(sbModule, ATTRNIL, TRUE);
/* Make entry in hash table */
apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,TRUE);
/* Allocate space in virt mem */
// The name of a module is given by the very first THEADR record
if(apropFile->af_rMod == 0)
apropFile->af_rMod = vrhte; /* Load pointer into hash table */
#if FDEBUG
if(fDebug) /* If runtime debugging on */
{
OutFileCur(stderr); /* Write current file and module */
NEWLINE(stderr);
}
#endif
}
long NEAR TypLen() /* Get type length */
{
WORD b; /* Byte value */
long l; /* Size */
if(cbRec < 2) InvalidObject(); /* Make sure record long enough */
b = Gets(); /* Get length byte */
if(b < 128) return(B2L(b)); /* One byte length field */
if(b == 129) /* If two byte length */
{
if(cbRec < 3) InvalidObject(); /* Make sure record long enough */
return((long) WGets()); /* Return the length */
}
if(b == 132) /* If three byte length */
{
if(cbRec < 4) InvalidObject(); /* Make sure record long enough */
l = (long) WGets(); /* Get the low word */
return(l + ((long) Gets() << WORDLN));
/* Return the length */
}
if(b == 136) /* If four byte length */
{
if(cbRec < 5) InvalidObject(); /* Make sure record long enough */
l = (long) WGets(); /* Get the low word */
return(l + ((long) WGets() << WORDLN));
/* Return the length */
}
InvalidObject(); /* Bad length specification */
}
/****************************************************************
* *
* TypRc1: *
* *
* This function processes TYPDEF records. These records are *
* difficult to understand. They are (poorly) described on *
* pp. 40-43 of "8086 Object Module Formats EPS," with some *
* additional information on pp. 89-90. *
* Microsoft used to used them for communal variables but they *
* have been superseded by COMDEF records. *
* *
****************************************************************/
LOCAL void NEAR TypRc1(void)
{
long l;
WORD b;
WORD typ; /* Near or FAR */
WORD ityp; /* Type index */
if(typMac >= TYPMAX)
Fatal(ER_typdef);
SkipBytes(Gets()); /* Skip the name field */
Gets(); /* Skip the EN byte */
l = -1L; /* Initialize */
mpityptyp[typMac] = 0; /* Assume no element type */
if(cbRec > 3) /* If at least four bytes left */
{
typ = Gets(); /* Get type leaf */
b = Gets(); /* Get next leaf */
if(typ == TYPENEAR) /* If near variable */
{
if(b != 0x7B && b != 0x79 && b != 0x77) InvalidObject();
/* Scalar, structure, or array */
fCommon = (FTYPE) TRUE; /* We have communal variables */
l = (TypLen() + 7) >> 3; /* Round length to nearest byte */
}
else if(typ == TYPEFAR) /* Else if FAR variable */
{
if(b != 0x77) InvalidObject();
/* Must have an array */
fCommon = (FTYPE) TRUE; /* We have communal variables */
l = TypLen(); /* Get number of elements */
ityp = GetIndex(1, (WORD) (typMac - 1));
/* Get type index */
if(mpityptyp[ityp] || mpitypelen[ityp] == -1L) InvalidObject();
/* Must index valid TYPDEF */
mpityptyp[typMac] = ityp; /* Save type index */
/* If element length too big, treat as TYPENEAR */
if(mpitypelen[ityp] > CBELMAX)
{
l *= mpitypelen[ityp];
mpitypelen[ityp] = 0;
}
}
}
mpitypelen[typMac++] = l; /* Store length */
SkipBytes((WORD) (cbRec - 1)); /* Skip all but the checksum */
}
LOCAL void NEAR TypErr(msg,sb) /* Type error message routine */
MSGTYPE msg; /* Message */
BYTE *sb; /* Symbol to which error refers */
{
sb[B2W(sb[0]) + 1] = '\0'; /* Null-terminate */
OutError(msg,1 + sb);
}
/*
* DoCommon
*
* Resolves old and new communal definitions of the same symbol.
* Does work for both ComDf1() and ExtRc1().
*/
LOCAL void NEAR DoCommon (apropUndef, length, cbEl, sb)
APROPUNDEFPTR apropUndef; /* Ptr to property cell */
long length; /* Length or number of elements */
WORD cbEl; /* # bytes per array element */
BYTE *sb; /* Name of symbol */
{
if(apropUndef->au_len == -1L) /* If not previously a communal */
{
apropUndef->au_cbEl = cbEl; /* Set the element size */
MARKVP(); /* Page has changed */
}
else if (cbEl == 0 && apropUndef->au_cbEl != 0)
{ /* Else if near reference to FAR */
apropUndef->au_len *= apropUndef->au_cbEl;
/* Calculate FAR variable length */
apropUndef->au_cbEl = 0; /* Force DS-type to near */
MARKVP(); /* Page has changed */
if (apropUndef->au_len > LXIVK) /* If huge variable */
{
TypErr(ER_nearhuge,sb); /* Issue error message */
return; /* Skip this symbol */
}
}
else if (cbEl != 0 && apropUndef->au_cbEl == 0)
{ /* Else if FAR reference to near */
length *= cbEl; /* Calculate FAR variable length */
cbEl = 0; /* Force DS-type to near */
if (length > LXIVK) /* If huge variable */
{
TypErr(ER_nearhuge,sb); /* Issue error message */
return; /* Skip this symbol */
}
}
else if (cbEl != apropUndef->au_cbEl)
{ /* If array element sizes don't match */
TypErr(ER_arrmis,sb);
return; /* Skip this symbol */
}
if (apropUndef->au_len < length)
{ /* If new length is larger */
apropUndef->au_len = length; /* Save it */
MARKVP();
}
}
/*
* ComDf1
*
* This function processes COMDEF records on pass 1.
*/
LOCAL void NEAR ComDf1 (void)
{
int tmp; /* workaround a cl bug */
SBTYPE sb; /* COMDEF symbol */
REGISTER APROPUNDEFPTR
apropUndef; /* Pointer to symbol entry */
long length; /* Communal variable length */
long cbEl; /* Size of array element */
WORD itype; /* Type index */
while(cbRec > 1) /* While there are symbols left */
{
if(extMac >= EXTMAX - 1) /* Check for table overflow */
Fatal(ER_extdef);
sb[0] = (BYTE) Gets(); /* Get symbol length */
if(rect == COMDEF)
GetBytes(&sb[1],B2W(sb[0]));/* Read in text of symbol */
else
GetLocName(sb); /* Transform local name */
#if CMDXENIX
if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen;
/* Truncate if necessary */
#endif
itype = GetIndex(0,0x7FFF); /* Get type index */
tmp = Gets();
switch(tmp) /* Get data seg type */
{
case TYPENEAR:
length = TypLen(); /* Get length */
cbEl = 0;
break;
case TYPEFAR:
length = TypLen(); /* Get number of elements */
/* Get element length. If too big, treat as near. Cmerge
* will never generate cbEl > 64K so this is not a problem.
*/
if((cbEl = TypLen()) > CBELMAX)
{
length *= cbEl;
cbEl = 0;
}
break;
default:
InvalidObject(); /* Unrecognized DS type */
}
#if FALSE
if(fDebug)
{
sb[sb[0]+1] = '\0';
fprintf(stdout, "%s has index = %u\r\n", sb+1, extMac);
}
#endif
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE);
/* Look for a matching PUBDEF */
if(apropUndef == PROPNIL) /* If there isn't one */
{
/* Insert as undefined symbol */
if (vrhte == RHTENIL)
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE);
else
apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
mpextprop[extMac++] = vrprop;
fCommon = (FTYPE) TRUE; /* There are communals */
if (vfCreated)
apropUndef->au_flags |= UNDECIDED;
else if (apropUndef->au_flags & UNDECIDED)
{
apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE);
apropUndef->au_flags |= STRONGEXT;
}
else if (apropUndef->au_flags & WEAKEXT)
apropUndef->au_flags |= UNDECIDED;
if (vfCreated || !(apropUndef->au_flags & COMMUNAL))
{ /* If not previously defined */
apropUndef->au_flags |= COMMUNAL;
/* Mark as communal */
apropUndef->au_len = -1L;
#if ILINK
apropUndef->u.au_module = imodFile;
/* Save module index. */
#endif
DoCommon(apropUndef, length, (WORD) cbEl, sb);
#if SYMDEB
if (fSymdeb && (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~'))
{
#if O68K
/* REVIEW: This should not be under the O68K flag. */
apropUndef->au_CVtype = itype;
#endif /* O68K */
DebPublic(mpextprop[extMac-1], rect);
}
#endif
}
else
DoCommon(apropUndef, length, (WORD) cbEl, sb);
}
else
{
mpextprop[extMac++] = vrprop;
if (mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn])
/* Communal matches code PUBDEF */
DupErr(sb); /* Duplicate definition */
}
}
}
/****************************************************************
* *
* LNmRc1: *
* *
* This function reads LNAME records and stores the names in *
* the hash table. The function does not return a meaningful *
* value. *
* See p. 31 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
void NEAR LNmRc1(WORD fLocal)
{
SBTYPE lname; /* Buffer for lnames */
RBTYPE FAR *lnameTab;
#if NOT ALIGN_REC
FILE *f;
#endif
WORD cb;
while(cbRec > 1) /* While not at end of record */
{
if (lnameMac >= lnameMax)
{
if (lnameMax >= (LXIVK >> 2))
Fatal(ER_nammax);
lnameTab = (RBTYPE FAR *) FREALLOC(mplnamerhte, 2*lnameMax*sizeof(RBTYPE));
if (lnameTab == NULL)
Fatal(ER_nammax);
mplnamerhte = lnameTab;
lnameMax <<= 1;
}
#if ALIGN_REC
if (!fLocal)
{
cb = 1 + *pbRec;
PropSymLookup(pbRec, ATTRNIL, TRUE);
cbRec -= cb;
pbRec += cb;
}
else
{
lname[0] = (BYTE)Gets(); /* Get name length */
GetLocName(lname); /* Read in text of name */
PropSymLookup(lname, ATTRNIL, TRUE);
}
#else
f = bsInput;
if (!fLocal && f->_cnt && (WORD)f->_cnt > (cb = 1 + *(BYTE *)f->_ptr))
{
PropSymLookup((BYTE *)f->_ptr, ATTRNIL, TRUE);
f->_cnt -= cb;
f->_ptr += cb;
cbRec -= cb;
}
else
{
lname[0] = (BYTE) Gets(); /* Get name length */
DEBUGVALUE(B2W(lname[0])); /* Length of name */
if (lname[0] > SBLEN - 1)
Fatal(ER_badobj);
if (fLocal)
GetLocName(lname);
else
GetBytes(&lname[1],B2W(lname[0]));
/* Read in text of name */
DEBUGSB(lname); /* The name itself */
PropSymLookup(lname, ATTRNIL, TRUE);
}
#endif
/* Insert symbol in hash table */
mplnamerhte[lnameMac++] = vrhte;/* Save address of hash table entry */
}
}
/*
* GetPropName - get the name of a property cell.
*
* Return pointer to the result, stored in a static buffer.
* Alternate between two buffers so we can be used in multi-part
* messages.
* Terminate result with null byte.
*/
typedef BYTE SBTYPE1[SBLEN+1];/* 1 extra for null byte */
BYTE * NEAR GetPropName(ahte)
AHTEPTR ahte;
{
static SBTYPE1 msgbuf[2];
static int toggle = 0;
char *p;
while(ahte->attr != ATTRNIL)
ahte = (AHTEPTR ) FetchSym(ahte->rhteNext,FALSE);
p = msgbuf[toggle ^= 1];
/* Copy string to buffer */
FMEMCPY((char FAR *) p, ahte->cch, B2W(ahte->cch[0]) + 1);
p[1 + B2W(p[0])] = '\0'; /* Null-terminate */
return(p);
}
/*
* SegUnreliable - warning message for 286 bug
*/
LOCAL void NEAR SegUnreliable (apropSn)
APROPSNPTR apropSn;
{
static FTYPE fReported = FALSE;
MARKVP(); /* Take care of current vp */
if (!fReported)
{
OutWarn(ER_segunsf,1 + GetPropName(apropSn));
fReported = (FTYPE) TRUE;
}
}
/*** CheckClass - check segment's class name
*
* Purpose:
* Check if we have the segment with the same name but with different
* class name.
*
* Input:
* apropSn - real pointer to segment symbol table descriptor
* rhteClass - hash vector entry for class name
*
* Output:
* Returns real pointer to segment symbol table descriptor.
*
* Exceptions:
* Found same segment with different class name - display error.
*
* Notes:
* None.
*
*************************************************************************/
APROPSNPTR CheckClass(APROPSNPTR apropSn, RBTYPE rhteClass)
{
#if ILINK
FTYPE fDifClass = FALSE;
#endif
while(apropSn->as_attr != ATTRNIL)
{ /* Look for class match or list end */
if(apropSn->as_attr == ATTRPSN &&
apropSn->as_rCla == rhteClass) break;
/* Break if pub. with matching class */
apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE);
/* Advance down the list */
#if ILINK
fDifClass = (FTYPE) TRUE; /* Same seg exists with dif. class */
#endif
}
#if ILINK
if(fIncremental && fDifClass)
OutError(ER_difcls, 1 + GetPropName(apropSn));
#endif
if(apropSn->as_attr == ATTRNIL)
{ /* If attribute not public */
vfCreated = (FTYPE) TRUE; /* New cell */
apropSn = (APROPSNPTR ) PropAdd(vrhte, ATTRPSN);
/* Segment is public */
}
return(apropSn);
}
#if OVERLAYS
void CheckOvl(APROPSNPTR apropSn, WORD iovFile)
{
SNTYPE gsn;
WORD fCanOverlayData;
WORD fOverlaySegment;
if (fOverlays)
{
// First check if mapping tables are allocated.
//
// SNTYPE mposngsn[OSNMAX];
// SNTYPE htgsnosn[OSNMAX];
if (mposngsn == NULL && htgsnosn == NULL)
{
mposngsn = (SNTYPE FAR *) GetMem(2*OSNMAX*sizeof(SNTYPE));
htgsnosn = (SNTYPE FAR *) &mposngsn[OSNMAX];
}
fCanOverlayData = IsDataFlg(apropSn->as_flags) &&
apropSn->as_ggr != ggrDGroup &&
apropSn->as_fExtra & FROM_DEF_FILE &&
apropSn->as_iov != (IOVTYPE) NOTIOVL;
fOverlaySegment = IsCodeFlg(apropSn->as_flags) || fCanOverlayData;
if (fOverlaySegment)
{
// We allow DATA segment overlaying ONLY if they ar NOT a members
// of DGROUP and HAVE preassigned overlay number form .DEF file.
// If segment is to be overlaid - check overlay number assigments
if ((apropSn->as_iov != (IOVTYPE) NOTIOVL) && (iovFile != apropSn->as_iov))
{
if (apropSn->as_fExtra & FROM_DEF_FILE)
{
// Use .DEF file overlay assigment
iovFile = apropSn->as_iov;
}
else
{
// Use current .OBJ file overlay assigment
OutWarn(ER_badsegovl, 1 + GetPropName(apropSn), apropSn->as_iov, iovFile);
}
}
}
if (iovFile != IOVROOT && fOverlaySegment)
{
if (osnMac < OSNMAX)
{
gsn = (SNTYPE)(apropSn->as_gsn & ((LG2OSN << 1) - 1));
// Get initial hash index
while (htgsnosn[gsn] != SNNIL)
{ // While buckets are full
if ((gsn += HTDELTA) >= OSNMAX)
gsn -= OSNMAX; // Calculate next hash index
}
htgsnosn[gsn] = osnMac; // Save overlay segment number
mposngsn[osnMac++] = apropSn->as_gsn;
// Map osn to gsn
apropSn->as_iov = iovFile; // Save overlay number
}
else
{
if (osnMac++ == OSNMAX)
OutWarn(ER_osnmax, OSNMAX);
apropSn->as_iov = IOVROOT;
}
}
else
apropSn->as_iov = IOVROOT; // Not an overlay
}
else
apropSn->as_iov = IOVROOT;
}
#endif
/****************************************************************
* *
* SegRc1: *
* *
* This function processes SEGDEF records. *
* See pp. 32-35 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
LOCAL void NEAR SegRc1(void)
{
WORD tysn; /* ACBP byte */
LNAMETYPE lname; /* Index into mplnamerhte */
APROPSNPTR apropSn; /* Pointer to seg. record */
SNTYPE gsn; /* Global SEGDEF number */
WORD align; /* This contributuion alignment */
WORD prevAlign; /* Logical segment aligment so FAR */
WORD comb; /* Segment combine-type */
DWORD seglen; /* Segment length */
DWORD contriblen; /* Contribution length */
DWORD cbMaxPrev; /* Segment length previously */
AHTEPTR ahte; /* Pointer to hash table entry */
SATYPE saAbs; /* Address for absolute seg */
BYTE flags; /* Segment attribute flags */
RBTYPE rhteClass; /* Class hash table address */
#if SYMDEB
APROPFILEPTR apropFile;
CVINFO FAR *pCvInfo; // Pointer to CodeView information
#endif
if(snMac >= SNMAX)
Fatal(ER_segdef);
tysn = Gets(); /* Read in the ACBP byte */
align = (WORD) ((tysn >> 5) & 7); /* Get the alignment field */
ASSERT(align != 6); /* Not supported by this linker */
if(align == ALGNABS) /* If absolute LSEG */
{
saAbs = (SATYPE) WGets(); /* Get the frame number */
Gets(); /* Punt the frame offset */
}
#if OMF386
if(rect & 1) /* If 386 extension */
seglen = LGets();
else
#endif
seglen = (DWORD) WGets(); /* Get segment length */
if(tysn & BIGBIT)
{
#if OMF386
if(rect & 1)
seglen = CBMAXSEG32 + 1; /* Force fatal error below */
else
#endif
seglen = LXIVK; /* Sixty-four K */
}
contriblen = seglen;
lname = (LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1));
/* Get segment name index */
ahte = (AHTEPTR ) FetchSym(mplnamerhte[lname],FALSE);
rhteClass = mplnamerhte[(LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1))];
/* Get class name rhte */
#if SYMDEB
if (IsDebSeg(rhteClass, mplnamerhte[lname]))
{ /* If MS debug segment */
mpsngsn[snMac++] = 0;
if (fSymdeb) /* If debugger support on */
{
apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE);
if (apropFile->af_cvInfo == NULL)
apropFile->af_cvInfo = (CVINFO FAR *) GetMem(sizeof(CVINFO));
pCvInfo = apropFile->af_cvInfo;
if (rhteClass == rhteDebTyp)
{
// "DEBTYP"
pCvInfo->cv_cbTyp = (DWORD) seglen;
#ifdef RGMI_IN_PLACE
pCvInfo->cv_typ = NULL; // defer allocation until pass 2 (!)
#else
pCvInfo->cv_typ = GetMem(seglen);
#endif
}
else if (rhteClass == rhteDebSym)
{
// "DEBSYM"
pCvInfo->cv_cbSym = (DWORD) seglen;
#ifdef RGMI_IN_PLACE
pCvInfo->cv_sym = NULL; // defer allocation until pass 2 (!)
#else
pCvInfo->cv_sym = GetMem(seglen);
#endif
}
}
SkipBytes((WORD) (cbRec - 1));
return;
}
#endif
GetIndex(0, (WORD) (lnameMac - 1)); /* Eat overlay name index */
DEBUGVALUE(seglen); /* Debug info */
DEBUGVALUE(lname); /* Debug info */
ahte = (AHTEPTR ) FetchSym(rhteClass,FALSE);
/* Fetch hash table entry from VM */
if(SbSuffix(GetFarSb(ahte->cch),"\004CODE",TRUE))
flags = FCODE;
else
flags = 0;
#if OMF386
/* Remember if 32-bit segment */
if(tysn & CODE386BIT)
{
flags |= FCODE386;
#if EXE386
/* Must set f386 here because newdeb needs to know in pass 1 */
f386 = (FTYPE) TRUE;
#endif
}
#endif
#if ILINK
else
if (fIncremental && !fLibraryFile && seglen && seglen != LXIVK)
{
/* Add padding to non-zero-length, non-library, non-64K segment
* contributions. (64K from huge model)
* UNDONE: More general overflow check, accounting for previous
* UNDONE: contributions.
*/
seglen += (flags & FCODE) ? cbPadCode : cbPadData;
}
#endif
switch(align) /* Switch on alignment type */
{
case ALGNABS: /* Absolute LSEG */
case ALGNBYT: /* Relocatable byte-aligned LSEG */
case ALGNWRD: /* Relocatable word-aligned LSEG */
case ALGNPAR: /* Relocatable para-aligned LSEG */
case ALGNPAG: /* Relocatable page-aligned LSEG */
#if OMF386
case ALGNDBL: /* double-word-aligned */
#endif
break;
default: /* ABSMAS, LTL LSEG, or error */
mpsngsn[snMac++] = 0;
return;
}
++snkey; /* Increment segment i.d. key */
if(comb = (WORD) ((tysn >> 2) & 7)) /* If "public" segment */
{
apropSn = (APROPSNPTR )
PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) TRUE);
/* Look up symbol table entry */
if(!vfCreated) /* If it was already there */
{
apropSn = CheckClass(apropSn, rhteClass);
#if OSEGEXE
if (apropSn->as_fExtra & FROM_DEF_FILE)
{ /* Override .DEF file segment attributes */
mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE);
apropSn->as_tysn = (TYSNTYPE) tysn;
/* Save ACBP field */
#if NOT EXE386
if (flags & FCODE386 || seglen > LXIVK)
apropSn->as_flags |= NS32BIT;
/* Set Big/Default bit */
#endif
apropSn->as_key = snkey;/* Save the key value */
}
#endif
}
}
else /* Else if private segment */
{
apropSn = (APROPSNPTR )
PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) FALSE);
/* Check if defined in .def file - caviar:4767 */
if(apropSn && apropSn->as_fExtra & FROM_DEF_FILE)
{
OutWarn(ER_farovl, GetPropName(apropSn)+1, "root");
}
vfCreated = (FTYPE) TRUE; /* This is a new segment */
apropSn = (APROPSNPTR ) PropAdd(mplnamerhte[lname],ATTRLSN);
}
if(vfCreated) /* If a new cell was created */
{
if(gsnMac >= gsnMax)
Fatal(ER_segmax);
/* Check for table overflow */
apropSn->as_gsn = gsnMac; /* Assign new global SEGDEF number */
mpgsnrprop[gsnMac++] = vrprop; /* Save address of property list */
apropSn->as_rCla = rhteClass; /* Save ptr to class hash tab ent */
/* Superclass hash table entry */
DEBUGVALUE(apropSn); /* Debug info */
DEBUGVALUE(apropSn->as_rCla); /* Debug info */
apropSn->as_tysn = (TYSNTYPE) tysn;
/* Save ACBP field */
mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE);
#if OSEGEXE
#if EXE386
apropSn->as_flags = flags & FCODE ? dfCode : dfData;
/* Assume default flags */
#else
apropSn->as_flags = (WORD) (flags & FCODE ? dfCode : dfData);
/* Assume default flags */
if (flags & FCODE386 || seglen > LXIVK)
apropSn->as_flags |= NS32BIT;
/* Set Big/Default bit */
#endif
#else
apropSn->as_flags = flags;
#endif
apropSn->as_key = snkey; /* Save the key value */
apropSn->as_ComDat = NULL; /* No COMDATs yet */
#if OVERLAYS
apropSn->as_iov = (IOVTYPE) NOTIOVL;
// No overlay assigment yet
#endif
}
#if OMF386 AND NOT EXE386
else
{
/* If segment defined as both 16- and 32-bit, fatal error */
WORD fNew, fOld;
fNew = (WORD) ((flags & FCODE386) ? 1 : 0);
fOld = (WORD) (
#if OSEGEXE
(apropSn->as_flags & NS32BIT) ?
#else
(apropSn->as_flags & FCODE386) ?
#endif
1 : 0);
if (fNew != fOld)
Fatal(ER_16seg32,1 + GetPropName(apropSn));
}
#endif
#if OVERLAYS
CheckOvl(apropSn, iovFile);
#endif
#if SYMDEB
if (seglen && (flags & FCODE))
cSegCode++; /* Count code seg's, so CV gets proper */
/* number of sstModule subsections */
#endif
gsn = apropSn->as_gsn; /* Save global SEGDEF no. */
if(comb == COMBSTK) /* If segment combines like stack */
{
gsnStack = gsn; /* Set stack global SEGDEF number */
align = ALGNBYT; /* Force to byte alignment */
if (cbStack)
seglen = 0L; /* Ignore stack segment size if /STACK given */
}
else if(comb == COMBCOM) /* If segment combines like common */
{
cbMaxPrev = apropSn->as_cbMx; /* Get previous segment size */
apropSn->as_cbMx = 0L; /* Set size to zero */
if(seglen < cbMaxPrev) seglen = cbMaxPrev;
/* Take the larger of the two sizes */
}
cbMaxPrev = apropSn->as_cbMx; /* Get previous size */
if(align == ALGNWRD) cbMaxPrev = (~0L<<1) & (cbMaxPrev + (1<<1) - 1);
/* Round size up to word boundary */
#if OMF386
else if(align == ALGNDBL) cbMaxPrev = (~0L<<2) & (cbMaxPrev + (1<<2) - 1);
#endif /* Round size up to double boundary */
else if(align == ALGNPAR) cbMaxPrev = (~0L<<4) & (cbMaxPrev + (1<<4) - 1);
/* Round size up to para. boundary */
else if(align == ALGNPAG) cbMaxPrev = (~0L<<8) & (cbMaxPrev + (1<<8) - 1);
/* Round size up to word boundary */
prevAlign = (WORD) ((apropSn->as_tysn >> 5) & 7);
// In Assign Addresses pass the aligment of the whole logical
// segment has to be equal to the biggest aligment of all
// contributions for given logical segment. Here we are checking
// if current contribution has bigger aligment then the
// contributions seen so FAR. The bigger aligment criteria is a
// bit tricky - the aligment constants are defined as follows:
//
// 1 - byte aligment
// 2 - word aligment
// 3 - paragraph aligment
// 4 - page aligment
// 5 - double word aligment
//
// The aligment ordering is as follows:
//
// byte < word < dword < para < page
// 1 2 5 3 4
//
// If align greater than prev. val.
if (prevAlign == ALGNDBL || align == ALGNDBL)
{
if (prevAlign == ALGNDBL && align >= ALGNPAR)
apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
/* Use new value */
else if (align == ALGNDBL && prevAlign <= ALGNWRD)
apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
/* Use new value */
}
else if (align > prevAlign)
apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5));
/* Use new value */
if (align != ALGNABS) /* If not an absolute LSEG */
{
seglen += cbMaxPrev;
#if EXE386 OR OMF386
if ((flags & FCODE386) != 0
#if O68K
&& iMacType == MAC_NONE
#endif
)
{
#if EXE386
if (seglen < cbMaxPrev) /* errmsg takes # megabytes */
Fatal(ER_seg386, 1 + GetPropName(apropSn), 1 << (LG2SEG32 - 20));
#else
if (seglen > CBMAXSEG32) /* errmsg takes # megabytes */
Fatal(ER_seg386,1 + GetPropName(apropSn),1 << (LG2SEG32 - 20));
#endif
}
else
#endif
if (seglen > LXIVK)
{
if (comb != COMBSTK)
OutError(ER_segsize,1 + GetPropName(apropSn));
/* Check for segment overflow */
else
{
if (!cbStack)
OutWarn(ER_stack64);
cbStack = LXIVK - 2;/* Assume 64k stack segment */
}
}
apropSn->as_cbMx = seglen; /* Save new segment size */
/*
* If this is a 16-bit code segment, check for unreliable
* lengths due to the 286 bug. For DOS exes, assume worst
* case, i.e. real mode limit.
*/
if((flags & FCODE) && !(EXE386 && (flags & FCODE386)))
#if OIAPX286
if(seglen == LXIVK)
#else
if(seglen > LXIVK - 36)
#endif
SegUnreliable(apropSn);
}
else apropSn->as_cbMx = (long) saAbs;
/* "Hack to save origin of abs seg" */
mpgsndra[gsn] = cbMaxPrev; /* Save previous size */
mpsngsn[snMac++] = gsn; /* Map SEGDEF no to global SEGDEF no */
MARKVP(); /* Virtual page has changed */
if (fFullMap && contriblen)
AddContributor(gsn, (unsigned long) -1L, contriblen);
}
/****************************************************************
* *
* GrpRc1: *
* *
* This function processes GRPDEF records on pass 1. *
* See pp. 36-39 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
LOCAL void NEAR GrpRc1(void)
{
LNAMETYPE lnameGroup; /* Group LNAME number */
SNTYPE sn; /* Group (local) segment number */
APROPSNPTR apropSn;
APROPGROUPPTR apropGroup;
GRTYPE ggr; /* Global GRPDEF number */
WORD gcdesc; /* GRPDEF component descriptor */
#if EXE386
BYTE *pGrName; /* Group name */
#endif
if(grMac >= GRMAX) Fatal(ER_grpdef);
lnameGroup = GetIndex(1, (WORD) (lnameMac - 1));
/* Read in group name index */
apropGroup = (APROPGROUPPTR )
PropRhteLookup(mplnamerhte[lnameGroup], ATTRGRP, (FTYPE) TRUE);
/* Look up cell in hash table */
if(vfCreated) /* If entry did not exist before */
{
if(ggrMac >= GGRMAX) Fatal(ER_grpmax);
apropGroup->ag_ggr = ggrMac++; /* Save global GRPDEF no. */
}
ggr = apropGroup->ag_ggr; /* Get global GRPDEF no. */
mpggrrhte[ggr] = mplnamerhte[lnameGroup];
/* Save pointer to name */
mpgrggr[grMac++] = ggr; /* Map local to global */
#if EXE386
/* Check for pseudo-group FLAT here */
pGrName = GetFarSb(((AHTEPTR)(FetchSym(mpggrrhte[ggr], FALSE)))->cch);
if (SbCompare(pGrName, sbFlat, TRUE))
ggrFlat = ggr;
#endif
while(cbRec > 1) /* While not at end of record */
{
gcdesc = Gets(); /* Read in the descriptor */
ASSERT(gcdesc == 0xFF); /* Linker doesn't handle others */
sn = GetIndex(1,snMac); /* Get local SEGDEF index */
apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
/* Fetch from virt mem */
if(apropSn->as_ggr == GRNIL)
{ /* Store global GRPDEF no. if none */
apropSn->as_ggr = ggr;
#if OSEGEXE
/*
* Check if a segment which is part of DGROUP was defined
* as class "CODE", also if it was given a sharing attribute
* that conflicts with the autodata type.
* Could only happen if seg defined in a def-file. Must be
* done here because only now do we know that it's in DGROUP.
*/
if(ggr == ggrDGroup && (apropSn->as_fExtra & FROM_DEF_FILE))
{
#if EXE386
if (IsEXECUTABLE(apropSn->as_flags))
{
SetREADABLE(apropSn->as_flags);
SetWRITABLE(apropSn->as_flags);
apropSn->as_rCla = rhteBegdata;
mpgsnfCod[apropSn->as_gsn] = FALSE;
OutWarn(ER_cod2dat,1 + GetPropName(apropSn));
apropSn = (APROPSNPTR )
FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
}
if (((vFlags & NESOLO) && !IsSHARED(apropSn->as_flags)) ||
((vFlags & NEINST) && IsSHARED(apropSn->as_flags)))
{
if (vFlags & NESOLO)
SetSHARED(apropSn->as_flags);
else
apropSn->as_flags &= ~OBJ_SHARED;
OutWarn(ER_adcvt,1 + GetPropName(apropSn));
}
#else
if((apropSn->as_flags & NSTYPE) != NSDATA)
{
apropSn->as_flags &= ~NSTYPE;
apropSn->as_flags |= NSDATA;
apropSn->as_rCla = rhteBegdata;
mpgsnfCod[apropSn->as_gsn] = FALSE;
OutWarn(ER_cod2dat,1 + GetPropName(apropSn));
apropSn = (APROPSNPTR )
FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE);
}
if(((vFlags & NESOLO) && !(apropSn->as_flags & NSSHARED)) ||
((vFlags & NEINST) && (apropSn->as_flags & NSSHARED)))
{
if(vFlags & NESOLO) apropSn->as_flags |= NSSHARED;
else apropSn->as_flags &= ~NSSHARED;
OutWarn(ER_adcvt,1 + GetPropName(apropSn));
}
#endif /* EXE386 */
}
#endif /* OSEGEXE */
}
else if (apropSn->as_ggr != ggr)/* If segment belongs to other group */
{
if(fLstFileOpen) fflush(bsLst);
/* Flush list file, if any */
OutWarn(ER_grpmul,1 + GetPropName(apropSn));
}
}
}
void NEAR DupErr(BYTE *sb)/* Duplicate definition error */
/* Symbol to which error refers */
{
BSTYPE bsTmp; /* Temporary file pointer */
MSGTYPE msg; /* Message to use */
#if OSMSDOS
extern char *pExtDic; /* Pointer to extended dictionary */
#endif
SBTYPE sbUndecor; /* a buffer for undecorated name */
/* If this module is in an extended dictionary, suggest /NOEXT in error
* message.
*/
msg = (MSGTYPE) (
#if OSMSDOS
pExtDic ? ER_symdup1 :
#endif
ER_symdup);
UndecorateSb((char FAR*) sb, (char FAR*) sbUndecor, sizeof(sbUndecor) );
OutError(msg,1 + sbUndecor);
if(fLstFileOpen && bsErr != bsLst)
{
bsTmp = bsErr;
bsErr = bsLst;
OutError(msg,1 + sbUndecor);
bsErr = bsTmp;
}
}
/****************************************************************
* *
* PubRc1: *
* *
* This function processes PUBDEF records on pass 1. *
* See pp. 44-46 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
LOCAL void NEAR PubRc1(void)
{
GRTYPE ggr; /* Group definition number */
SNTYPE sn; /* Local SEGDEF no. */
SNTYPE gsn; /* Global SEGDEF no. */
RATYPE dra;
SBTYPE sb; /* Public symbol */
RATYPE ra; /* Public symbol offset */
APROPNAMEPTR apropName; /* Table entry for symbol name */
WORD type; /* Local type no. */
int fSkipCv = FALSE;/* Don't register DATA PUBDEF if a COMDEF
for that symbol has already been seen */
DEBUGVALUE(grMac - 1); /* Debug info */
ggr = (GRTYPE) GetIndex(0, (WORD) (grMac - 1));/* Get group index */
DEBUGVALUE(ggr); /* Debug info */
if (!(sn = GetIndex(0, (WORD) (snMac - 1))))/* If frame number present */
{
gsn = 0; /* No global SEGDEF no. */
dra = 0;
SkipBytes(2); /* Skip the frame number */
}
else /* Else if local SEGDEF no. given */
{
if (ggr != GRNIL)
ggr = mpgrggr[ggr]; /* If group specified, get global no */
gsn = mpsngsn[sn]; /* Get global SEGDEF no. */
dra = mpgsndra[gsn];
}
DEBUGVALUE(cbRec); /* Debug info */
while (cbRec > 1) /* While there are symbols left */
{
sb[0] = (BYTE) Gets(); /* Get symbol length */
if (TYPEOF(rect) == PUBDEF)
GetBytes(&sb[1],B2W(sb[0]));/* Read in symbol text */
else
GetLocName(sb); /* Transform local name */
#if CMDXENIX
if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen;
/* Truncate if necessary */
#endif
#if OMF386
if (rect & 1)
ra = LGets();
else
#endif
ra = WGets(); /* Get symbol segment offset */
type = GetIndex(0,0x7FFF); /* Get type index */
if (!vfNewOMF)
type = 0;
/* Look for symbol among undefined */
apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRUND, FALSE);
if (apropName != PROPNIL) /* Symbol known to be undefined */
{
if (((APROPUNDEFPTR )apropName)->au_flags & COMMUNAL)
{
if (mpgsnfCod[gsn])
DupErr(sb); /* Communal matches code PUBDEF */
fSkipCv = TRUE;
}
vfCreated = (FTYPE) TRUE;
}
else
{
/* Look for symbol among ALIASes */
if (vrhte == RHTENIL)
apropName = PROPNIL;
else
apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
if (apropName != PROPNIL)
{
#if FDEBUG
if (fDebug)
{
sb[sb[0] + 1] = '\0';
OutWarn(ER_ignoalias, &sb[1]);
}
#endif
continue;
}
else if (vrhte == RHTENIL)
{
apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRPNM, TRUE);
}
else
{
apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRPNM, TRUE);
}
}
if (vfCreated) /* If new PUBNAM entry created or */
{ /* old UNDEF entry to modify */
// If printable symbol, increment counter and set flags
if (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~')
{
++pubMac;
apropName->an_flags = FPRINT;
}
else
{
#if ILINK
++locMac; /* Included in .SYM file */
#endif
}
apropName->an_attr = ATTRPNM;
/* Symbol is a public name */
apropName->an_ra = ra + dra;/* Give symbol its adjusted offset */
apropName->an_gsn = gsn; /* Save its global SEGDEF no. */
apropName->an_ggr = ggr; /* Save its global SEGDEF no. */
#if OVERLAYS
apropName->an_thunk = THUNKNIL;
#endif
#if ILINK
apropName->an_module = imodFile;
#endif
MARKVP(); /* Mark virtual page as changed */
#if SYMDEB
if (fSymdeb && (apropName->an_flags & FPRINT) && !fSkipPublics && !fSkipCv)
{
// Remember CV type index
apropName->an_CVtype = type;
DebPublic(vrprop, rect);
}
#endif
}
else if(apropName->an_gsn != gsn || apropName->an_ra != ra + dra)
{
DupErr(sb); /* Definitions do not match */
}
}
}
/****************************************************************
* *
* ExtRc1: *
* *
* This function processes EXTDEF records on pass 1. *
* See pp. 47-48 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
LOCAL void NEAR ExtRc1(void)
{
SBTYPE sb; /* EXTDEF symbol */
APROPUNDEFPTR apropUndef; /* Pointer to symbol entry */
APROPALIASPTR apropAlias; /* Pointer to symbol entry */
APROPNAMEPTR apropName; /* Pointer to symbol entry */
APROPCOMDATPTR apropComdat; /* pointer to symbol entry */
WORD itype; /* Type index */
RBTYPE rhte; /* Virt. addr. of hash table entry */
AHTEPTR ahte; // Symbol table hash entry
while (cbRec > 1) /* While there are symbols left */
{
if (extMac >= EXTMAX - 1) /* Check for table overflow */
Fatal(ER_extdef);
if (TYPEOF(rect) == CEXTDEF)
{
itype = GetIndex(0, (WORD) (lnameMac - 1));
rhte = mplnamerhte[itype];
ahte = (AHTEPTR) FetchSym(rhte, FALSE);
FMEMCPY((char FAR *) sb, ahte->cch, ahte->cch[0] + 1);
/* Look for a matching PUBDEF */
apropUndef = (APROPUNDEFPTR) PropRhteLookup(rhte, ATTRPNM, FALSE);
}
else
{
rhte = RHTENIL;
sb[0] = (BYTE) Gets(); /* Get symbol length */
if (TYPEOF(rect) == EXTDEF)
GetBytes(&sb[1], B2W(sb[0]));
/* Read in text of symbol */
else
GetLocName(sb); /* Get local name */
#if CMDXENIX
if (symlen && B2W(sb[0]) > symlen)
sb[0] = symlen; /* Truncate if necessary */
#endif
/* Look for a matching PUBDEF */
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE);
}
DEBUGSB(sb); /* Print symbol */
if (!vfNewOMF) /* If old-style OMF */
itype = GetIndex(0, (WORD) (typMac - 1));/* Get type index */
else
itype = GetIndex(0, 0x7FFF); /* Get type index (any value OK) */
#if FALSE
if (fDebug)
{
sb[sb[0]+1] = '\0';
fprintf(stdout, "\r\n%s has index = %u", sb+1, extMac);
}
#endif
apropName = PROPNIL;
if (apropUndef == PROPNIL) /* If there isn't one */
{
/* Look for a matching ALIAS */
if (vrhte == RHTENIL)
apropAlias = PROPNIL;
else
apropAlias = (APROPALIASPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
if (apropAlias != PROPNIL)
{
/* ALIAS matches this EXTDEF */
mpextprop[extMac++] = apropAlias->al_sym;
apropName = (APROPNAMEPTR) FetchSym(apropAlias->al_sym, TRUE);
if (apropName->an_attr == ATTRPNM)
{
// If substitute name is a PUBDEF then use it
if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) &&
mpgsnfCod[apropName->an_gsn])
/* Communal matches code PUBDEF */
DupErr(sb); /* Duplicate definition */
}
else
{
// The substitute name is an EXTDEF
// Mark substitute name so it causes the library search, because
// we don't know neither the alias nor the substitute
apropUndef = (APROPUNDEFPTR) apropName;
apropUndef->au_flags |= SEARCH_LIB;
apropName = PROPNIL;
#if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside)
StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0);
#endif
#ifdef DEBUG_SHOWALIAS
sb[sb[0]+1] = '\0';
fprintf(stderr, "extdef alias: %s\r\n", sb+1);
fflush(stderr);
#endif
}
}
else
{
/* Insert as undefined symbol */
if (vrhte == RHTENIL)
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE);
else
apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
mpextprop[extMac++] = vrprop;
if(vfCreated)
{
apropUndef->au_flags |= UNDECIDED;
apropUndef->au_len = -1L;
#if NEWLIST
apropUndef->u.au_rbNxt = rbLstUndef;
rbLstUndef = vrprop;
#endif
}
else if (apropUndef->au_flags & UNDECIDED)
{
apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE);
apropUndef->au_flags |= STRONGEXT;
#if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside)
StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0);
#endif
}
else if (apropUndef->au_flags & WEAKEXT)
apropUndef->au_flags |= UNDECIDED;
if (vfNewOMF) continue; /* Skip if module uses COMDEFs */
if(itype) /* If there is reference to TYPDEF */
DoCommon(apropUndef, mpitypelen[itype],
(WORD) (mpityptyp[itype] ? mpitypelen[mpityptyp[itype]] : 0),
sb);
if (apropUndef->au_len > 0L)
apropUndef->au_flags |= COMMUNAL;
/* Mark as true communal or not */
MARKVP(); /* Mark virt page as changed */
}
}
else
{
apropName = (APROPNAMEPTR ) apropUndef;
mpextprop[extMac++] = vrprop;
if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) &&
mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn])
/* Communal matches code PUBDEF */
DupErr(sb); /* Duplicate definition */
}
// If we are processing CEXTDEF/EXTDEF and there is public symbol
// matching the CEXTDEF/EXTDEF symbol, then mark COMDAT descriptor
// as referenced
if (apropName != PROPNIL)
{
apropComdat = (APROPCOMDATPTR) PropRhteLookup(vrhte, ATTRCOMDAT,
#if TCE
FALSE
#else
TRUE
#endif
);
if (apropComdat != PROPNIL)
{
apropComdat->ac_flags |= REFERENCED_BIT;
#if TCE_DEBUG
fprintf(stdout, "\r\nEXTDEF1 referencing '%s' ", 1+GetPropName(apropComdat));
#endif
}
}
}
}
#if OSEGEXE AND NOT QCLINK
/****************************************************************
* *
* imprc1: *
* *
* This function processes Microsoft OMF extension records of *
* type IMPDEF (i.e. IMPort DEFinition records). *
* *
****************************************************************/
LOCAL void NEAR imprc1(void)
{
SBTYPE sbInt; /* Internal name */
SBTYPE sbMod; /* Module name */
SBTYPE sbImp; /* Imported name */
FTYPE fOrd; /* Import-by-ordinal flag */
#if ODOS3EXE
fNewExe = (FTYPE) TRUE; /* Import forces new-format exe */
#endif
fOrd = (FTYPE) Gets(); /* Get ordinal flag */
sbInt[0] = (BYTE) Gets(); /* Get length of internal name */
GetBytes(&sbInt[1],B2W(sbInt[0])); /* Get the internal name */
sbMod[0] = (BYTE) Gets(); /* Get length of module name */
GetBytes(&sbMod[1],B2W(sbMod[0])); /* Get the module name */
if(!(fOrd & 0x1)) /* If import by name */
{
sbImp[0] = (BYTE) Gets(); /* Get length of imported name */
if(sbImp[0] != '\0') /* If names differ */
{
GetBytes(&sbImp[1],B2W(sbImp[0]));
/* Get the imported name */
#if EXE386
NewImport(sbImp,0,sbMod,sbInt, (fOrd & 0x2));
#else
NewImport(sbImp,0,sbMod,sbInt);
#endif
/* Enter new import */
}
else
#if EXE386
NewImport(sbInt,0,sbMod,sbInt, (fOrd & 0x2));
#else
NewImport(sbInt,0,sbMod,sbInt);
#endif
/* Enter new import */
}
else
#if EXE386
NewImport(NULL,WGets(),sbMod,sbInt, (fOrd & 0x2));
#else
NewImport(NULL,WGets(),sbMod,sbInt);
#endif
/* Else import by ordinal */
}
/****************************************************************
* *
* exprc1: *
* *
* This function processes Microsoft OMF extension records of *
* type EXPDEF (i.e. EXPort DEFinition records). *
* *
****************************************************************/
LOCAL void NEAR exprc1(void)
{
SBTYPE sbInt; /* Internal name */
SBTYPE sbExp; /* Exported name */
WORD OrdNum; /* Ordinal number */
WORD fRec; /* Record flags */
#if ODOS3EXE
fNewExe = (FTYPE) TRUE; /* Export forces new-format exe */
#endif
fRec = (BYTE) Gets(); /* Get record flags */
sbExp[0] = (BYTE) Gets(); /* Get length of exported name */
GetBytes(&sbExp[1],B2W(sbExp[0])); /* Get the exported name */
sbInt[0] = (BYTE) Gets(); /* Get length of internal name */
if (sbInt[0])
GetBytes(&sbInt[1],B2W(sbInt[0]));
/* Get the internal name */
if (fRec & 0x80)
{ /* If ordinal number specified */
OrdNum = WGets(); /* Read it and set highest bit */
OrdNum |= ((fRec & 0x40) << 1); /* if resident name */
}
else
OrdNum = 0; /* No ordinal number specified */
// Convert flags:
// OMF flags:
// 80h = set if ordinal number specified
// 40h = set if RESIDENTNAME
// 20h = set if NODATA
// 1Fh = # of parameter words
// EXE flags:
// 01h = set if entry is exported
// 02h = set if entry uses global (shared) data segment (!NODATA)
// F8h = # of parameter words
//
// Since the logic is reversed for the NODATA flag, we toggle bit 0x20
// in the OMF flags via the expression ((fRec & 0x20) ^ 0x20).
fRec = (BYTE) (((fRec & 0x1f) << 3) | (((fRec & 0x20) ^ 0x20) >> 4) | 1);
// Mark fRec, so NewExport doesn't try to free name buffers
fRec |= 0x8000;
if (sbInt[0])
NewExport(sbExp, sbInt, OrdNum, fRec);
else
NewExport(sbExp, NULL, OrdNum, fRec);
}
#endif /* OSEGEXE */
/****************************************************************
* *
* ComRc1: *
* *
* This function processes COMENT records on pass 1. *
* See pp. 86-87 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
#pragma check_stack(on)
LOCAL void NEAR ComRc1(void)
{
#if OXOUT OR OIAPX286
WORD mismatch; /* Model mismatch flag */
#endif
#if FALSE
static BYTE modtype = 0; /* Initial model type */
BYTE curmodtype; /* Current model type */
#endif
SBTYPE text; /* Comment text */
SBTYPE LibName;
APROPFILEPTR aprop;
WORD iextWeak;
WORD iextDefRes;
APROPUNDEFPTR undefName;
FTYPE fIgnoreCaseSave;
BYTE flags;
void FAR *pTmp;
#if ILINK
SNTYPE noPadSn;
APROPSNPTR apropSn; /* Pointer to seg. record */
#endif
#if O68K
BYTE chModel;
#endif /* O68K */
Gets(); /* Skip byte 1 of comment type field */
switch(Gets()) /* Switch on comment class */
{
#if OEXE
case 0: /* Translator record */
if(fNewExe)
break;
#if ODOS3EXE
text[0] = (BYTE) (cbRec - 1);/* Get length of comment */
GetBytes(&text[1],(WORD)(cbRec - 1));/* Read in text of comment */
/*
* If translator is pre-3.30 MS/IBM PASCAL or FORTRAN,
* force on /DS and /NOG.
*/
if(SbCompare(text,"\011MS PASCAL", TRUE) ||
SbCompare(text,"\012FORTRAN 77", TRUE))
vfDSAlloc = fNoGrpAssoc = (FTYPE) TRUE;
#endif
break;
#endif
case 0x81: /* Library specifier */
#if OSMSDOS OR OSPCDOS
case 0x9F: /* Library specifier (alt.) */
#endif
text[0] = (BYTE) (cbRec - 1);/* Get length of comment */
if (text[0] == 0)
break; /* Skip empty spec */
GetBytes(&text[1], (WORD) (cbRec - 1));/* Read in text of comment */
/* Add name to search list */
#if CMDMSDOS
strcpy(LibName, sbDotLib);
UpdateFileParts(LibName, text);
#endif
#if CMDXENIX
memcpy(LibName, text, B2W(text[0]) + 1);
/* Leave name unchanged */
#endif
if(!vfNoDefaultLibrarySearch)
{
#if OSMSDOS
fIgnoreCaseSave = fIgnoreCase;
fIgnoreCase = (FTYPE) TRUE;
/* If the name begins with a drive letter, skip it. This
* is to allow compatibility with old compilers which
* generated comments of the form "A:FOO.LIB".
*/
if(LibName[2] == ':' && B2W(LibName[0]) > 1)
{
LibName[2] = (BYTE) (LibName[0] - 2);
if (PropSymLookup(LibName+2,ATTRSKIPLIB,FALSE) == PROPNIL)
AddLibrary(LibName+2);
}
else
#endif
if (PropSymLookup(LibName,ATTRSKIPLIB,FALSE) == PROPNIL)
AddLibrary(LibName);
fIgnoreCase = fIgnoreCaseSave;
}
break;
#if OEXE
case 0x9E: /* Force segment order directive */
SetDosseg(); /* Set switch */
break;
#endif /* OEXE */
case 0x9D: /* Model specifier */
#if FALSE
/* Removed */
mismatch = 0; /* Assume all is well */
while(cbRec > 1) /* While bytes remain */
{
curmodtype = Gets(); /* Get byte value */
switch(curmodtype)
{
case 'c': /* Compact model */
case 's': /* Small model */
case 'm': /* Medium model */
case 'l': /* Large model */
case 'h': /* Huge model */
if (modtype)
mismatch = curmodtype != modtype;
else
modtype = curmodtype;
break;
}
}
if(mismatch) OutWarn(ER_memmodel);
/* Warn if mismatch found */
#endif
#if OXOUT OR OIAPX286
mismatch = 0; /* Assume all is well */
while(cbRec > 1) /* While bytes remain */
{
modtype = Gets(); /* Get byte value */
if (fMixed) continue; /* Mixed model means we don't care */
switch(modtype)
{
case 'c': /* Compact model */
if(!fLarge || fMedium) mismatch = 1;
break; /* Warn if near data or FAR code */
case 's': /* Small model */
if(fLarge || fMedium) mismatch = 1;
/* Warn if FAR data or FAR code */
break;
case 'm': /* Medium model */
if(fLarge || !fMedium) mismatch = 1;
/* Warn if FAR data or near code */
break;
case 'l': /* Large model */
case 'h': /* Huge model */
if(!fLarge || !fMedium) mismatch = 1;
/* Warn if near data or near code */
break;
}
}
if(mismatch) OutError(ER_modelmis);
/* Warn if mismatch found */
#endif /* OXOUT OR OIAPX286 */
#if O68K
while (!f68k && cbRec > 1) /* While bytes remain */
{
chModel = (BYTE) Gets();/* Get byte value */
f68k = (FTYPE) F68KCODE(chModel);
}
#endif /* O68K */
break;
#if OSEGEXE AND NOT QCLINK
case 0xA0: /* Microsoft OMF extension */
switch(Gets()) /* Switch on extension record type */
{
case 0x01: /* IMPort DEFinition */
imprc1(); /* Call the processing routine */
break;
case 0x02: /* EXPort DEFinition */
exprc1(); /* Call the processing routine */
break;
case 0x03:
break; /* In pass-1 skip INCDEF's for QC */
#if EXE386
case 0x04: // OMF extension - link386
// if (IsDLL(vFlags))
// vFlags |= E32PROTDLL;
// Protected memory library module
break;
#endif
case 0x05: // C++ directives
flags = (BYTE) Gets();// Get flags field
#if NOT EXE386
if (flags & 0x01)
fNewExe = (FTYPE) TRUE; // PCODE forces segmented exe format
#endif
#if SYMDEB
if (flags & 0x02)
fSkipPublics = (FTYPE) TRUE;
// In C++ they don't want PUBLIC subsection in CV info
#endif
if ((flags & 0x04) && !fIgnoreMpcRun) // ignore if /PCODE:NOMPC
fMPC = (FTYPE) TRUE; // PCODE app - spawn MPC
break;
case 0x06: // target is a big-endian machine
#if O68K
fTBigEndian = (FTYPE) TRUE;
#endif /* O68K */
break;
case 0x07: // Use SSTPRETYPES instead of SSTTYPES4 in OutSSt
aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE);
aprop->af_flags |= FPRETYPES;
break;
default: /* Unknown */
InvalidObject(); /* Invalid object module */
}
break;
#endif
case 0xA1: /* 1st OMF extension: COMDEFs */
vfNewOMF = (FTYPE) TRUE;
aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE);
aprop->af_flags |= FNEWOMF;
break;
case 0xA2: /* 2nd OMF extension */
switch(Gets())
{
case 0x01: /* Start linkpass2 records */
/*
* WARNING: It is assumed this comment will NOT be in a
* module whose MODEND record contains a program starting
* address. If there are overlays, we need to see the
* starting address on pass 1 to define the symbol $$MAIN.
*/
fP2Start = fModEnd = (FTYPE) TRUE;
break;
default:
break;
}
break;
#if FALSE
case 0xA3: // DON'T use - already used by LIB
break;
#endif
case 0xA4: /* OMF extension - EXESTR */
fExeStrSeen = (FTYPE) TRUE;
// WARNING: The code in this loop assumes:
//
// ExeStrLen, cBrec and ExeStrMax are 16-bit unsigned WORDS
// An int is 32-bits
// All arithmetic and comparisons are 32-bit
//
while (cbRec > 1)
{
// Limit total EXESTR to 64K - 2 bytes. We lose 1 because 0 means 0,
// and we lose another because the buffer extension loop tops out at
// 0xFFFE bytes.
if (ExeStrLen + cbRec - 1 > 0xFFFEu)
{
SkipBytes ( (WORD) (cbRec - 1) );
}
else
if (ExeStrLen + cbRec - 1 > ExeStrMax)
{
if (ExeStrBuf == NULL)
{
ExeStrBuf = GetMem(cbRec - 1);
ExeStrMax = cbRec - 1;
}
else
{
// This loop doubles the buffer size until it overflows 16 bits. After this,
// it adds one half of the difference between the current value and 0xFFFF
//
while (ExeStrMax < ExeStrLen + cbRec - 1) {
ASSERT (ExeStrMax != 0);
if ((ExeStrMax << 1) >= 0x10000)
ExeStrMax += (~ExeStrMax & 0xFFFF) >> 1;
else
ExeStrMax <<= 1;
}
pTmp = GetMem(ExeStrMax);
FMEMCPY(pTmp, ExeStrBuf, ExeStrLen);
FFREE(ExeStrBuf);
ExeStrBuf = pTmp;
}
}
// This must be done first because GetBytes() decrements
// cbRec as a side effect.
ExeStrLen += cbRec - 1;
GetBytes(&ExeStrBuf[ExeStrLen-cbRec+1], (WORD) (cbRec - 1));
}
break;
case 0xA6: /* OMF extension - INCERR */
Fatal(ER_incerr); /* Invalid object due to aborted incremental compile */
break;
#if ILINK
case 0xA7: /* OMF extension - NOPAD */
if (fIncremental && !fLibraryFile)
{
/* Remove padding from non-zero-length, non-library,
* non-64K segment contributions. (64K from huge model)
*/
while (cbRec > 1)
{
noPadSn = GetIndex(1, snMac - 1);
apropSn = (APROPSNPTR) FetchSym(mpgsnrprop[mpsngsn[noPadSn]], TRUE);
if (apropSn->as_cbMx > 0L && apropSn->as_cbMx != LXIVK)
{
apropSn->as_cbMx -= mpgsnfCod[mpsngsn[noPadSn]] ? cbPadCode : cbPadData;
apropSn->as_fExtra |= NOPAD;
}
}
}
break;
#endif
case 0xA8: /* OMF extension - WeaK EXTern */
while (cbRec > 1)
{
iextWeak = GetIndex(1, (WORD) (extMac - 1));
/* Get weak extern index */
iextDefRes = GetIndex(1, (WORD) (extMac - 1));
/* Get default extern index */
#if FALSE
DumpWeakExtern(mpextprop, iextWeak, iextDefRes);
#endif
if (mpextprop[iextWeak] != PROPNIL && iextWeak < extMac)
{
undefName = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], TRUE);
if (undefName->au_attr == ATTRUND)
{
// If this is EXTDEF
if (undefName->au_flags & UNDECIDED)
{
// This can be one of the following:
// - weakness specified for the first time
// if WEAKEXT is not set
// - redefinition of weakness if the WEAKEXT
// is set.
// In case of weakness redefinition check if
// it specified the same default resolution as
// the first one. Issue warning if different
// default resolutions and override old one
// with new. In both cases reset UNDECIDED bit.
undefName->au_flags &= ~UNDECIDED;
if (undefName->au_flags & WEAKEXT)
{
if (undefName->au_Default != mpextprop[iextDefRes])
redefinition(iextWeak, iextDefRes, undefName->au_Default);
undefName->au_Default = mpextprop[iextDefRes];
}
else
{
undefName->au_Default = mpextprop[iextDefRes];
undefName->au_flags |= WEAKEXT;
}
}
// Ignore weakness - must be strong extern form
// some other .OBJ
}
}
else
InvalidObject();
}
break;
default: /* Unrecognized */
break;
}
if (cbRec > 1)
SkipBytes((WORD) (cbRec - 1)); /* Punt rest of text */
}
/*** AliasRc1 - pass 1 ALIAS record processing
*
* Purpose:
* Read and decode ALIAS OMF record (Microsoft OMF extension).
* ALIAS record introduces pair of names - alias name and substitute
* name. Enter both names into linker symbol table.
*
* Input:
* No explicit value is passed. When this function is called the record
* type and lenght are already read, so we can start reading name pairs.
*
* Output:
* No explicit value is returned. Names are entered into symbol table.
*
* Exceptions:
* Warning - redefinition of ALIAS <name>; substitute name changed
* from <name1> to <name2>.
*
* Notes:
* None.
*
*************************************************************************/
LOCAL void NEAR AliasRc1(void)
{
SBTYPE alias;
SBTYPE substitute;
APROPALIASPTR aliasDsc;
RBTYPE vAliasDsc;
APROPNAMEPTR pubName;
APROPUNDEFPTR undefName;
RBTYPE vPtr;
WORD fReferenced;
while (cbRec > 1) /* While there are symbols left */
{
/* Read alias and its substitute */
alias[0] = (BYTE) Gets();
GetBytes(&alias[1], B2W(alias[0]));
substitute[0] = (BYTE) Gets();
GetBytes(&substitute[1], B2W(substitute[0]));
aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, FALSE);
vAliasDsc = vrprop;
if (aliasDsc == PROPNIL)
{
/* New ALIAS - check if we have PUBDEF for the alias name */
pubName = (APROPNAMEPTR ) PropSymLookup(alias, ATTRPNM, FALSE);
if (pubName == PROPNIL)
{
/* Enter ALIAS name in to symbol table */
aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, TRUE);
vAliasDsc = vrprop;
#if SYMDEB
if (fSymdeb)
DebPublic(vrprop, ALIAS);
#endif
// Check if we have an EXTDEF for alias name. If we have
// this means, that substitute name has to be used in
// the library search.
undefName = (APROPUNDEFPTR ) PropSymLookup(alias, ATTRUND, FALSE);
fReferenced = (WORD) (undefName != PROPNIL);
// Check if we know the substitute name as PUBDEF or EXTDEF
pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE);
if (pubName != PROPNIL)
vPtr = vrprop;
else
{
undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE);
if (undefName != NULL)
{
vPtr = vrprop;
undefName->au_flags |= (SUBSTITUTE | SEARCH_LIB);
undefName->au_Default = vAliasDsc;
#if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside)
StoreUndef((APROPNAMEPTR)undefName, RhteFromProp((APROPPTR)undefName),0,0);
#endif
}
else
{
/* Enter substitute name into symbol table */
/* as undefined symbol */
if (extMac >= EXTMAX - 1)
Fatal(ER_extdef);
undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, TRUE);
vPtr = vrprop;
mpextprop[extMac++] = vrprop;
if (fReferenced)
undefName->au_flags |= (STRONGEXT | SUBSTITUTE | SEARCH_LIB);
else
undefName->au_flags |= (UNDECIDED | SUBSTITUTE);
undefName->au_len = -1L;
undefName->au_Default = vAliasDsc;
#if NEWLIST
undefName->u.au_rbNxt = rbLstUndef;
rbLstUndef = vrprop;
#endif
}
}
/* Attach substitute symbol to the ALIAS */
aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
aliasDsc->al_sym = vPtr;
}
else
{
#if FDEBUG
if (fDebug)
{
alias[alias[0] + 1] = '\0';
OutWarn(ER_ignoalias, &alias[1]);
}
#endif
}
}
else
{
/* Check if we have redefinition */
vPtr = aliasDsc->al_sym;
pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE);
if (pubName != PROPNIL)
{
if (vPtr != vrprop)
{
aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
aliasDsc->al_sym = vrprop;
OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(pubName), &substitute[1]);
}
}
else
{
undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE);
if (undefName != PROPNIL)
{
if (vPtr != vrprop)
{
aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE);
aliasDsc->al_sym = vrprop;
OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(undefName), &substitute[1]);
}
}
}
}
}
}
#pragma check_stack(off)
#if OVERLAYS
/****************************************************************
* *
* EndRc1: *
* *
* This function is called to process the information *
* contained in a MODEND (type 8AH) record concerning the *
* program starting address. The function does not return a *
* meaningful value. *
* See pp. 80-81 in "8086 Object Module Formats EPS." *
* *
****************************************************************/
LOCAL void NEAR EndRc1(void)
{
WORD modtyp; /* MODEND record modtyp byte */
WORD fixdat; /* Fixdat byte */
SNTYPE gsn; /* Global SEGDEF number */
RATYPE ra; /* Symbol offset */
APROPSNPTR apropSn; /* Pointer to segment info */
WORD frameMethod;
if ((modtyp = Gets()) & FSTARTADDRESS)
{ /* If execution start address given */
ASSERT(modtyp & 1); /* Must be logical start address */
fixdat = Gets(); /* Get fixdat byte */
ASSERT(!(fixdat & 0x8F)); /* Frame, target must be explicit,
* target must be given by seg index
*/
frameMethod = (fixdat & 0x70) >> 4;
if (frameMethod != F4 && frameMethod != F5)
GetIndex(0,IMAX - 1); /* Punt frame index */
gsn = mpsngsn[GetIndex((WORD)1,(WORD)(snMac - 1))];
/* Get gsn from target segment index */
#if OMF386
if(rect & 1) ra = LGets() + mpgsndra[gsn];
else
#endif
ra = WGets() + mpgsndra[gsn]; /* Get offset */
apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE);
/* Get segment information */
MkPubSym("\006$$MAIN",apropSn->as_ggr,gsn,ra);
/* Make public symbol */
}
}
#endif /* OVERLAYS */
/****************************************************************
* *
* ProcP1: *
* *
* This function controls the processing of an object module *
* on pass 1. *
* *
****************************************************************/
#pragma check_stack(on)
void NEAR ProcP1(void)
{
long typlen[TYPMAX];
WORD typtyp[TYPMAX];
RBTYPE extprop[EXTMAX];
FTYPE fFirstRec; /* First record flag */
FTYPE fFirstMod; /* First module flag */
APROPFILEPTR apropFile; /* File name entry */
#if OXOUT OR OIAPX286
RUNTYPE xhdr;
LFATYPE lfa;
#endif
mpitypelen = typlen; /* Initialize pointer */
mpityptyp = typtyp; /* Initialize pointer */
mpextprop = (RBTYPE FAR *) extprop; /* Initialize pointer */
FMEMSET(mpextprop, 0, sizeof(extprop));
fFirstMod = (FTYPE) TRUE; /* First module */
for(;;) /* Loop to process file */
{
snMac = 1; /* Initialize counter */
grMac = 1; /* Initialize */
extMac = 1; /* Initialize counter */
lnameMac = 1; /* Initialize counter */
typMac = 1; /* Initialize counter */
vfNewOMF = FALSE; /* Assume old OMF */
DEBUGVALUE(gsnMac); /* Debug info */
DEBUGVALUE(ggrMac); /* Debug info */
#if OXOUT OR OIAPX286
lfa = ftell(bsInput); /* Save initial file position */
fread(&xhdr,1,CBRUN,bsInput); /* Read x.out header */
if(xhdr.x_magic == X_MAGIC) /* If magic number found */
{
#if OXOUT
if((xhdr.x_cpu & XC_CPU) != XC_8086) InvalidObject();
/* Bad if not 8086 */
#else
xhdr.x_cpu &= XC_CPU; /* Get CPU specification */
if(xhdr.x_cpu != XC_286 && xhdr.x_cpu != XC_8086) InvalidObject();
/* Bad if not 286 or 8086 */
#endif
if(xhdr.x_relsym != (XR_R86REL | XR_S86REL)) InvalidObject();
/* Check symbol table type */
if((xhdr.x_renv & XE_VERS) != xever) InvalidObject();
/* Check Xenix version */
}
else
fseek(bsInput,lfa,0); /* Else return to start */
#endif /* OXOUT OR OIAPX286 */
#if OVERLAYS
if(fOverlays) /* If there are overlays */
iovFile = ((APROPFILEPTR) vrpropFile)->af_iov;
/* Save overlay number for file */
else
iovFile = 0; /* File contains part of root */
#endif
fFirstRec = (FTYPE) TRUE; /* Looking at first record */
fModEnd = FALSE; /* Not at module's end */
fP2Start = FALSE; /* No p2start record yet */
#if SYMDEB
cSegCode = 0; /* No code segments yet */
#endif
while(!fModEnd) /* Loop to process object module */
{
rect = (WORD) getc(bsInput);/* Read record type */
if(fFirstRec) /* If first record */
{
if(rect != THEADR && rect != LHEADR)
{ /* If not header */
if(fFirstMod) break;/* Error if first module */
return; /* Else return */
}
fFirstRec = FALSE; /* Not first record any more */
}
else if (IsBadRec(rect)) break;
/* Break if invalid object */
cbRec = WSGets(); /* Read record length */
lfaLast += cbRec + 3; /* Update current file pos. */
#if ALIGN_REC
if (bsInput->_cnt >= cbRec)
{
pbRec = bsInput->_ptr;
bsInput->_ptr += cbRec;
bsInput->_cnt -= cbRec;
}
else
{
if (cbRec > sizeof(recbuf))
{
// error -- record too large [rm]
InvalidObject();
}
// read record into contiguous buffer
fread(recbuf,1,cbRec,bsInput);
pbRec = recbuf;
}
#endif
DEBUGVALUE(rect); /* Debug info */
DEBUGVALUE(cbRec); /* Debug info */
switch(TYPEOF(rect)) /* Switch on record type */
{
#if TCE
case FIXUPP:
if(fTCE)
FixRc1();
else
SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
break;
#endif
case TYPDEF:
TypRc1();
break;
case COMDEF:
case LCOMDEF:
ComDf1();
break;
case SEGDEF:
SegRc1();
break;
case THEADR:
ModRc1();
break;
case COMENT:
ComRc1();
break;
case LHEADR:
ModRc1();
break;
case GRPDEF:
GrpRc1();
break;
case EXTDEF:
case LEXTDEF:
case CEXTDEF:
ExtRc1();
break;
case LNAMES:
case LLNAMES:
LNmRc1((WORD) (TYPEOF(rect) == LLNAMES));
break;
case PUBDEF:
case LPUBDEF:
PubRc1();
break;
case MODEND:
#if OVERLAYS
if(fOverlays) EndRc1();
else
#endif
SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
fModEnd = (FTYPE) TRUE; /* Stop processing module */
break;
case COMDAT:
ComDatRc1();
break;
case ALIAS:
AliasRc1();
break;
default:
if (rect == EOF)
InvalidObject();
SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */
break;
}
if(cbRec != 1) break; /* If record length bad */
Gets(); /* Eat the checksum byte */
}
if(!fModEnd)
{
ChkInput(); /* First check for I/O problems */
InvalidObject(); /* Invalid module */
}
++modkey; /* For local symbols */
#if SYMDEB
if (fSymdeb)
{
apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE);
if (apropFile->af_cvInfo || apropFile->af_Src)
++ObjDebTotal; /* Count the .OBJ with CV info */
}
#endif
if(extMac > extMax) /* Possibly set new extMax */
extMax = extMac;
if(fLibraryFile || fP2Start) return;
fFirstMod = FALSE; /* Not first module */
}
}
#pragma check_stack(off)