windows-nt/Source/XPSP1/NT/sdktools/link16/newmap3.c
2020-09-26 16:20:57 +08:00

651 lines
27 KiB
C

/*static char *SCCSID = "%W% %E%";*/
/*
* Copyright Microsoft Corporation 1986,1987
*
* This Module contains Proprietary Information of Microsoft
* Corporation and should be treated as Confidential.
*/
/*
* NEWMAP3.C
*
* Routines to set up load image map for DOS3 exes.
*/
#include <minlit.h> /* Types and constants */
#include <bndtrn.h> /* Types and constants */
#include <bndrel.h> /* Types and constants */
#include <lnkmsg.h> /* Error messages */
#include <extern.h> /* External declarations */
#include <string.h>
LOCAL SEGTYPE seg; /* Current seg number */
/*
* FUNCTION PROTOTYPES
*/
LOCAL void NEAR SetSizes(unsigned short segPrev);
LOCAL void NEAR PackCodeSegs(unsigned short segTop);
#if OVERLAYS
/*
* SetupOverlays:
*
* Set up the overlay area.
* Called by AssignAddresses.
*/
void NEAR SetupOverlays ()
{
APROPSNPTR apropSn;
WORD cbOvlData; /* Amount of overlay data */
if(osnMac > OSNMAX) osnMac = OSNMAX;
apropSn = GenSeg("\014OVERLAY_DATA","\004DATA",ggrDGroup, (FTYPE) TRUE);
/* Create (maybe) data segment */
apropSn->as_flags = dfData; /* Type data */
gsnOvlData = apropSn->as_gsn; /* Save SEGDEF number */
cbOvlData = (((WORD) apropSn->as_cbMx) + 0xF) & 0xFFF0;
/* Round size up to paragraph bound */
/* We will have one word table indexed by overlay segment number, one
* char table indexed by overlay seg. no., one long table indexed by
* overlay number, 15 bytes for the file name, a word for the number of
* overlays, a word for the number of overlay segs., and a byte for the
* interrupt number.
*/
apropSn->as_cbMx = 20 + ((long) osnMac << 1) +
(long) (fDynamic ? osnMac << 1 : osnMac) +
((long) iovMac << 2) + (long) cbOvlData;
// For dynamic overlays add one table of longs indexed by overlay
// number and one byte for overlay interrup number.
if (fDynamic)
apropSn->as_cbMx += ((long) iovMac << 2) + 1;
MARKVP(); /* Page has been modified */
MkPubSym("\006$$CGSN",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Count of segments */
cbOvlData += 2; /* Increment size */
MkPubSym("\006$$COVL",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Count of overlays */
cbOvlData += 2; /* Increment size */
MkPubSym("\013$$MPGSNBASE",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Gsn to base table */
cbOvlData += osnMac << 1; /* Accumulate size of data so far */
MkPubSym("\012$$MPGSNOVL",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Gsn to overlay table */
if (fDynamic)
cbOvlData += osnMac << 1; /* Accumulate size of data so far */
else
cbOvlData += osnMac;
MkPubSym("\012$$MPOVLLFA",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Overlay to file address table */
cbOvlData += iovMac << 2; /* Accumulate size of data so far */
if (fDynamic)
{
MkPubSym("\013$$MPOVLSIZE",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Overlay to size table */
cbOvlData += iovMac << 2; /* Accumulate size of data so far */
MkPubSym("\007$$INTNO",ggrDGroup,gsnOvlData, (RATYPE)cbOvlData);
/* Overlay interrupt number */
cbOvlData++;
MkPubSym("\010$$OVLEND", ggrDGroup, gsnOvlData, (RATYPE) cbOvlData);
/* Last byte in overlay area */
apropSn = GenSeg("\016OVERLAY_THUNKS","\004CODE",GRNIL, TRUE);
/* Create thunk segment */
apropSn->as_flags = dfCode; /* Code segment */
apropSn->as_cbMx = ovlThunkMax * OVLTHUNKSIZE;
apropSn->as_tysn = apropSn->as_tysn & ~MASKTYSNCOMBINE;
apropSn->as_tysn = apropSn->as_tysn | TYSNCOMMON;
gsnOverlay = apropSn->as_gsn; /* Save thunks SEGDEF number */
MARKVP(); /* Page has changed */
MkPubSym("\015$$OVLTHUNKBEG", GRNIL, gsnOverlay,0);
MkPubSym("\015$$OVLTHUNKEND", GRNIL, gsnOverlay,ovlThunkMax*OVLTHUNKSIZE);
}
else
{
MkPubSym("\010$$EXENAM",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Executable file name */
cbOvlData += 15; /* 15-byte name field */
MkPubSym("\007$$INTNO",ggrDGroup,gsnOvlData,(RATYPE)cbOvlData);
/* Overlay interrupt number */
apropSn = GenSeg("\014OVERLAY_AREA","\004CODE",GRNIL,FALSE);
/* Create overlay area */
apropSn->as_flags = dfCode; /* Code segment */
gsnOverlay = apropSn->as_gsn; /* Save overlay SEGDEF number */
MARKVP(); /* Page has changed */
MkPubSym("\011$$OVLBASE",GRNIL,gsnOverlay,(RATYPE)0);
/* First byte in overlay area */
apropSn = GenSeg("\013OVERLAY_END","\004CODE",GRNIL,FALSE);
/* Create overlay end */
apropSn->as_flags = dfCode; /* Code segment */
MkPubSym("\010$$OVLEND",GRNIL,apropSn->as_gsn,(RATYPE)0);
/* Last byte in overlay area */
MARKVP(); /* Page has changed */
}
}
#endif /* OVERLAYS */
/****************************************************************
* *
* SetSizes: *
* *
* This function sets the starting address for the segth *
* segment assuming the segment indexed by segPrev immediately *
* precedes the segth segment. If there is a starting address *
* for the segth segment already, then SetSizes will not *
* change that address unless the new address it calculates *
* is higher. *
* *
****************************************************************/
LOCAL void NEAR SetSizes (segPrev)
SEGTYPE segPrev;
{
long addr; /* 20-bit address */
/* Get address of end of previous segment */
addr = ((long) mpsegsa[segPrev] << 4) +
mpsegcb[segPrev] + mpsegraFirst[segPrev];
/* Form 20-bit address of segment */
switch(B2W(mpsegalign[seg])) /* Align the address properly */
{
case ALGNWRD: /* Word-aligned */
addr = (addr + 1) & ~1L; /* Round up to word offset */
break;
#if OMF386
case ALGNDBL: /* Double word-aligned */
addr = (addr + 3) & ~3L; /* Round up to dword offset */
break;
#endif
case ALGNPAR: /* Paragraph-aligned */
addr = (addr + 0xF) & ~0xFL;
/* Round up to paragraph offset */
break;
case ALGNPAG: /* Page-aligned */
addr = (addr + 0xFF) & ~0xFFL;
/* Round up to page offset */
default: /* Byte-aligned */
break;
}
/* Assign beginning of this segment */
if(addr > ((long) mpsegsa[seg] << 4) + (long) mpsegraFirst[seg])
{
mpsegsa[seg] = (WORD)(addr >> 4);
mpsegraFirst[seg] = (WORD) addr & 0xF;
}
}
/*
* PackCodeSegs : Pack adjacent code segments
*
* Pack as many adjacent code segments (which are in the same
* overlay) together as possible. Start with the current
* segment, seg, and stop when the packing limit is exceeded,
* a data segment is reached, or the given highest segment is
* reached. For DOS3, packing means assigning the same base
* address and adjusting the offset of the first byte.
*
* Parameters:
* segTop Number of highest segment which can be packed.
* Returns:
* Nothing.
* Side effects:
* seg is set to the last segment included in the packing group
*/
LOCAL void NEAR PackCodeSegs (segTop)
SEGTYPE segTop;
{
DWORD sacb; /* Length of packing group */
SEGTYPE segi; /* Our private current segment no. */
RATYPE raSave; /* Original mpsegraFirst[segi] */
#if OVERLAYS
IOVTYPE iov; /* Overlay of 1st seg in group */
iov = mpsegiov[seg]; /* Determine current overlay */
#endif
sacb = mpsegcb[seg] + mpsegraFirst[seg]; /* Initialize group size */
for(segi = seg + 1; segi <= segTop; ++segi)
{ /* Loop until highest code seg */
#if OVERLAYS
if(mpsegiov[segi] != iov) /* If not a member of this ovl, skip */
continue;
#endif
if(!(mpsegFlags[segi] & FCODE)) /* Stop if we hit a data segment */
break;
/* Adjust alignment */
switch(mpsegalign[segi]) /* Switch on alignment type */
{
case ALGNWRD: /* Word-aligned */
sacb = (sacb + 1) & ~1L;
/* Round up size to word boundary */
break;
#if OMF386
case ALGNDBL: /* Double word-aligned */
sacb = (sacb + 3) & ~3L; /* Round up to dword offset */
break;
#endif
case ALGNPAR: /* Paragraph-aligned */
sacb = (sacb + 0xF) & ~0xFL;
/* Round up size to para boundary */
break;
case ALGNPAG: /* Page-aligned */
sacb = (sacb + 0xFF) & ~0xFFL;
/* Round up size to page boundary */
break;
}
raSave = mpsegraFirst[segi]; /* Save original value */
mpsegraFirst[segi] = sacb; /* Set new offset */
sacb += mpsegcb[segi]; /* Increment size of group */
if(sacb > packLim) /* If packing limit exceeded, stop */
{
mpsegraFirst[segi] = raSave; /* Restore original value */
break;
}
mpsegsa[segi] = mpsegsa[seg]; /* Assign base address */
}
}
/*
* AssignDos3Addr:
*
* Assign addresses for a DOS3-format program.
* Called by AssignAddresses.
*/
void NEAR AssignDos3Addr(void)
{
APROPSNPTR apropSn; /* Pointer to a SEGDEF */
SNTYPE gsn; /* Current global SEGDEF no. */
ALIGNTYPE align; /* Alignment type */
GRTYPE ggr; /* Current global GRPDEF no. */
SEGTYPE segTop=0; /* Highest segment in DGROUP */
SNTYPE gsnTop=0; /* Highest segment in DGROUP */
SNTYPE gsnBottomDGroup;/* For DS-allocate */
SEGTYPE segBottomDGroup;/* For DS-allocate */
SATYPE saMaxDGroup; /* For DS-allocate */
SEGTYPE segOverlay;
SEGTYPE segPrev;
#if OVERLAYS
SEGTYPE FAR *mpiovsegPrev;
IOVTYPE iov;
ALIGNTYPE alignOverlay;
long cbOverlay;
WORD segOvlSa;
RATYPE segOvlRaFirst;
#endif
SEGTYPE segStack; /* Logical segment no. of stack */
#if OVERLAYS
mpiovsegPrev = (SEGTYPE FAR *) GetMem(iovMac*sizeof(SEGTYPE));
#endif
segTop = 0;
/* We haven't yet assigned absolute segments (it is assumed
* they are empty and are used only for addressing purposes),
* but now we must assign them somewhere.
*/
csegsAbs = 0; /* Assume there are no absolute segs */
for(gsn = 1; gsn < gsnMac; ++gsn) /* Loop to initialize absolute segs */
{
if(mpgsnseg[gsn] == SEGNIL) /* If we have an absolute segment */
{
++csegsAbs; /* Increment counter */
mpgsnseg[gsn] = ++segLast; /* Assign a segment order number */
}
}
if(vfDSAlloc) /* If doing DS allocation */
{
if(gsnMac >= gsnMax)
Fatal(ER_segmax);
/* We implicitly use another segment */
gsnBottomDGroup = gsnMac; /* Fix the bottom of DGROUP */
++csegsAbs; /* Inc absolute seg counter */
segBottomDGroup = ++segLast; /* Bottom segment in DGROUP */
mpgsnseg[gsnBottomDGroup] = segLast;
/* Store entry in table */
}
#if OVERLAYS
alignOverlay = ALGNPAR; /* Overlays are para-aligned */
#endif
segLast -= csegsAbs; /* Get no. of last non-abs seg */
/* Find lowest segment in groups, etc. */
for(gsn = 1; gsn < gsnMac; ++gsn) /* Loop to find lowest segs */
{
seg = mpgsnseg[gsn]; /* Get segment number */
apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],TRUE);
/* Get symbol table entry */
mpgsndra[gsn] = 0;
#if OVERLAYS
mpsegiov[seg] = apropSn->as_iov;
/* Save overlay number */
#endif
mpsegcb[seg] = apropSn->as_cbMx;
/* Save segment size */
if(apropSn->as_tysn == TYSNABS) /* Assign absolute segs their loc. */
mpsegsa[seg] = (SATYPE) apropSn->as_cbMx;
ggr = apropSn->as_ggr; /* Get GRPDEF number */
if(ggr != GRNIL) /* If segment is group member */
{
if(mpggrgsn[ggr] == SNNIL || mpgsnseg[mpggrgsn[ggr]] > seg)
mpggrgsn[ggr] = gsn;
if(ggr == ggrDGroup && seg > segTop)
{
segTop = seg;
gsnTop = gsn;
}
}
align = (ALIGNTYPE) ((apropSn->as_tysn) >> 5);
if((apropSn->as_tysn & MASKTYSNCOMBINE) == TYSNSTACK) align = ALGNPAR;
if(align > mpsegalign[seg]) mpsegalign[seg] = align;
#if OVERLAYS
if(mpsegiov[seg] != IOVROOT &&
mpiovsegPrev[mpsegiov[seg]] == SEGNIL && align > alignOverlay)
{
mpiovsegPrev[mpsegiov[seg]] = SEGNIL + 1;
alignOverlay = align;
}
#endif
/* Define special symbols "_edata" and "_end" */
if (fSegOrder)
Define_edata_end(apropSn);
}
if (fSegOrder)
Check_edata_end(gsnTop, segTop);
/* Now we assign actual addresses. The procedure is as follows:
* For each code segment
* (1) Assign all addresses of the root up to OVERLAY_AREA or THUNK_AREA.
* (2) Assign all addresses of the overlays.
* (3) If dynamic overlays then set the size of OVERLAY_AREA to zero
* else set the start of the segment after OVERLAY_AREA to be
* the greatest of all the overlays including the root
* OVERLAY_AREA.
* (4) Assign the rest of the root segments.
* Repeat steps one through four for all remaining segments.
*
* Set limit of part (1): up to OVERLAY_AREA(if there are overlays)
* or the end of the segment list. Do not assign OVERLAY_AREA until
* after all the overlays have been taken care of.
*
* For dynamic overlays the DGROUP part of the root overlay
* immediatelly follows the OVERLAY_THUNKS, since the OVERLAY_AREA
* is dynamically allocated by the overlay manager at run-time.
*/
#if OVERLAYS
if(fOverlays) /* If there are overlays */
{
segOverlay = mpgsnseg[gsnOverlay];
/* Set limit at 1st overlay */
mpsegalign[segOverlay] = alignOverlay;
}
else
#endif
segOverlay = segLast; /* Look at all segments */
/* Set the sizes of all of the root up until the OVERLAY_AREA. */
segPrev = 0; /* No previous segment */
for(seg = 1; seg <= segOverlay; ++seg)
{ /* Loop thru segs up to overlay area */
#if OVERLAYS
if(mpsegiov[seg] == IOVROOT)
{ /* If root member */
#endif
SetSizes(segPrev); /* Set start address */
/* If packing code segs and this is one, pack until segOverlay */
if (!fDynamic && packLim != 0L && (mpsegFlags[seg] & FCODE))
PackCodeSegs(segOverlay);
segPrev = seg; /* Save segment number */
#if OVERLAYS
}
#endif
}
#if OVERLAYS
/* If there are no overlays, then we have assigned all
* segments. Otherwise, the previous segment of the
* beginning of the overlays is the OVERLAY_AREA in the
* root. If the dynamic overlays were requested, then
* the OVERLAY_THUNKS becomes the previous segment for
* all overlay segments.
*/
if (fOverlays) /* If there are overlays */
{
for (iov = IOVROOT + 1; iov < (IOVTYPE) iovMac; ++iov)
mpiovsegPrev[iov] = segOverlay;
/* Assign addresses to the overlays. We do not assign the
* rest of the root because we may have to expand the size of
* OVERLAY_AREA to accommodate a large overlay.
*/
if (fDynamic)
{
// All dymanic overlay are zero based
segOvlSa = mpsegsa[segOverlay];
mpsegsa[segOverlay] = 0;
segOvlRaFirst = mpsegraFirst[segOverlay];
mpsegraFirst[segOverlay] = 0;
}
cbOverlay = mpsegcb[segOverlay];/* Save size of overlay segment */
mpsegcb[segOverlay] = 0; /* Zero the size field for SetSizes */
for (seg = 1; seg <= segLast; ++seg)
{
if(mpsegiov[seg] != IOVROOT)
{
SetSizes(mpiovsegPrev[mpsegiov[seg]]);
/* If packing code segs and this is one, pack until segLast */
if(packLim != 0L && (mpsegFlags[seg] & FCODE))
PackCodeSegs(segLast);
mpiovsegPrev[mpsegiov[seg]] = seg;
}
}
if (fDynamic)
{
mpsegsa[segOverlay] = segOvlSa;
mpsegraFirst[segOverlay] = segOvlRaFirst;
}
mpsegcb[segOverlay] = cbOverlay;/* Reset the size field */
/* Determine first segment in root after OVERLAY_AREA or OVERLAY_THUNKS */
seg = segOverlay + 1;
while (seg <= segLast && mpsegiov[seg] != IOVROOT)
++seg;
/*
* If there is a segment in the root after the overlays,
* then go through all of the overlays as previous segments
* and set its size with the previous one being the last seg
* of each overlay. We won't initialize the Vm for that
* segment because we won't know the maximum placement until
* afterward.
*/
if (seg <= segLast)
{
for (iov = IOVROOT + 1; iov < (IOVTYPE) iovMac; ++iov)
SetSizes(mpiovsegPrev[iov]);
/* Assign the rest of the root */
segPrev = segOverlay;
while (seg <= segLast)
{
if (mpsegiov[seg] == IOVROOT)
{
SetSizes(segPrev);
/* If packing code segs and this is one, pack until segLast */
if(packLim != 0L && (mpsegFlags[seg] & FCODE))
PackCodeSegs(segLast);
segPrev = seg;
}
++seg;
}
}
}
#endif /* OVERLAYS */
if(vfDSAlloc) /* If doing DS allocation */
{
saMaxDGroup = (SATYPE) (mpsegsa[segTop] +
((mpsegcb[segTop] + mpsegraFirst[segTop] + 0xF) >> 4));
mpggrgsn[ggrDGroup] = gsnBottomDGroup;
mpsegsa[segBottomDGroup] = (SATYPE)((saMaxDGroup - 0x1000) & ~(~0 << WORDLN));
#if OVERLAYS
mpsegiov[segBottomDGroup] = mpsegiov[segTop];
/* Top and bottom in same overlay */
#endif
mpgsndra[gsnBottomDGroup] = 0;
}
/* If /DOSSEG enabled, stack segment defined, and DGROUP defined,
* check for combined stack + DGROUP <= 64K.
*/
if(fSegOrder && gsnStack != SNNIL && mpggrgsn[ggrDGroup] != SNNIL)
{
segStack = mpgsnseg[gsnStack];
if ((((long) mpsegsa[segStack] << 4) + mpsegcb[segStack])
- ((long) mpsegsa[mpgsnseg[mpggrgsn[ggrDGroup]]] << 4)
> LXIVK)
Fatal(ER_stktoobig);
}
segResLast = segLast;
for(gsn = 1; gsn < gsnMac; ++gsn)
mpgsndra[gsn] += mpsegraFirst[mpgsnseg[gsn]];
#if OVERLAYS
/* Set all absolute segs to the root overlay */
seg = segLast + 1;
while(seg < (SEGTYPE) (segLast + csegsAbs)) mpsegiov[seg++] = IOVROOT;
/* "Remember those absolute symbols, too !" */
mpsegiov[0] = IOVROOT;
FFREE(mpiovsegPrev);
#endif
}
#if OVERLAYS
#pragma check_stack(on)
/****************************************************************
* *
* FixOvlData: *
* *
* Initialize overlay data tables. *
* *
****************************************************************/
void NEAR FixOvlData()
{
APROPNAMEPTR apropName; /* Public symbol name */
AHTEPTR ahte; /* Pointer to hash table entry */
BYTE wrd[2]; /* Word as byte array */
long ra; /* Offset */
SNTYPE osn; /* Overlay segment index */
SEGTYPE seg; /* Segment number */
SATYPE sa; /* Segment base */
BYTE *pb; /* Byte pointer */
SBTYPE sb; /* String buffer */
SNTYPE gsn;
apropName = (APROPNAMEPTR ) PropSymLookup("\006$$CGSN",ATTRPNM,FALSE);
/* Look up public symbol */
mpsegFlags[mpgsnseg[apropName->an_gsn]] |= FNOTEMPTY;
/* Segment is not empty */
wrd[0] = (BYTE) (osnMac & 0xff); /* Get lo byte */
wrd[1] = (BYTE) ((osnMac >> BYTELN) & 0xff); /* Get hi byte */
MoveToVm(2,wrd,mpgsnseg[apropName->an_gsn],apropName->an_ra);
/* Store value */
wrd[0] = (BYTE) (iovMac & 0xff); /* Get lo byte */
wrd[1] = (BYTE) ((iovMac >> BYTELN) & 0xff); /* Get hi byte */
apropName = (APROPNAMEPTR ) PropSymLookup("\006$$COVL",ATTRPNM,FALSE);
/* Look up public symbol */
MoveToVm(2,wrd,mpgsnseg[apropName->an_gsn],apropName->an_ra);
/* Store value */
apropName = (APROPNAMEPTR )PropSymLookup("\013$$MPGSNBASE",ATTRPNM,FALSE);
/* Look up public symbol */
ra = apropName->an_ra; /* Get table offset */
seg = mpgsnseg[apropName->an_gsn]; /* Get segment number */
vrectData = LEDATA;
RecordSegmentReference(seg,ra,seg); /* Record load-time fixup */
ra += 2; /* Increment offset */
/* Entries 1 thru osnMac - 1 contain bases of segments at runtime */
for(osn = 1; osn < osnMac; ++osn) /* Loop thru segment definitions */
{
sa = mpsegsa[mpgsnseg[mposngsn[osn]]];
/* Get segment base */
if (fDynamic)
sa <<= 4; /* Convert para address to offset from overlay base */
wrd[0] = (BYTE) (sa & 0xff); /* Lo byte */
wrd[1] = (BYTE) ((sa >> BYTELN) & 0xff); /* Hi byte */
MoveToVm(2,wrd,seg,ra); /* Move to VM */
if (!fDynamic)
RecordSegmentReference(seg,ra,seg);
/* Record load-time fixup */
ra += 2; /* Increment offset */
}
apropName = (APROPNAMEPTR ) PropSymLookup("\012$$MPGSNOVL",ATTRPNM,FALSE);
/* Look up public symbol */
ra = apropName->an_ra; /* Get table offset */
seg = mpgsnseg[apropName->an_gsn]; /* Get segment number */
if (fDynamic)
{
ra += 2; /* First entry null */
for(osn = 1; osn < osnMac; ++osn)
{ /* Loop thru segment definitions */
wrd[0] = (BYTE) mpsegiov[mpgsnseg[mposngsn[osn]]];
wrd[1] = (BYTE) ((mpsegiov[mpgsnseg[mposngsn[osn]]] >> BYTELN) & 0xff);
/* Get overlay number */
MoveToVm(2,wrd,seg,ra); /* Move to VM */
ra += 2;
}
}
else
{
++ra; /* First entry null */
for(osn = 1; osn < osnMac; ++osn)/* Loop thru segment definitions */
{
wrd[0] = (BYTE) mpsegiov[mpgsnseg[mposngsn[osn]]];
/* Get overlay number */
MoveToVm(1,wrd,seg,ra++); /* Move to VM */
}
apropName = (APROPNAMEPTR ) PropSymLookup("\010$$EXENAM",ATTRPNM,FALSE);
/* Look up public symbol */
ra = apropName->an_ra; /* Get table offset */
seg = mpgsnseg[apropName->an_gsn];
/* Get segment number */
ahte = (AHTEPTR ) FetchSym(rhteRunfile,FALSE);
memcpy(sb,GetFarSb(ahte->cch),1+B2W(ahte->cch[0]));
/* Copy the filename */
pb = StripDrivePath(sb); /* Strip drive and path */
sb[sb[0] + 1] = '\0';
if (strrchr(&sb[1], '.') == NULL)
UpdateFileParts(pb, sbDotExe);
MoveToVm(B2W(pb[0]),pb+1,seg,ra);
/* Move name to VM */
}
apropName = (APROPNAMEPTR ) PropSymLookup("\007$$INTNO",ATTRPNM,FALSE);
/* Look up public symbol */
MoveToVm(1,&vintno,mpgsnseg[apropName->an_gsn],apropName->an_ra);
/* Move overlay number to VM */
/* If /PACKCODE enabled, redefine $$OVLBASE so it has an offset of 0,
* which the overlay manager expects. Find 1st non-root segment
* and use that.
*/
if(packLim)
{
apropName = (APROPNAMEPTR) PropSymLookup("\011$$OVLBASE",ATTRPNM, TRUE);
for(gsn = 1; gsn < gsnMac && !mpsegiov[mpgsnseg[gsn]]; ++gsn);
apropName->an_gsn = gsn;
apropName->an_ra = 0;
}
}
#pragma check_stack(off)
#endif /* OVERLAYS */