mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
717 lines
20 KiB
717 lines
20 KiB
/* %W% %E% */
|
|
/*
|
|
* Copyright Microsoft Corporation, 1983-1987
|
|
*
|
|
* This Module contains Proprietary Information of Microsoft
|
|
* Corporation and should be treated as Confidential.
|
|
*/
|
|
/****************************************************************
|
|
* *
|
|
* LINKER INITIALIZATION *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include <minlit.h> /* Types and constants */
|
|
#include <bndtrn.h> /* More of the same */
|
|
#include <bndrel.h> /* More of the same */
|
|
#include <lnkio.h> /* Linker I/O definitions */
|
|
#include <newexe.h> /* DOS & 286 .EXE format definitions */
|
|
#if EXE386
|
|
#include <exe386.h> /* 386 .EXE format definitions */
|
|
#endif
|
|
#include <signal.h> /* Signal definitions */
|
|
#if QCLINK
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <lnkmsg.h> /* Error messages */
|
|
#if OSMSDOS AND NOT (WIN_NT OR DOSEXTENDER OR DOSX32) AND NOT WIN_3
|
|
#define INCL_BASE
|
|
#define INCL_DOSMISC
|
|
#include <os2.h> /* OS/2 system calls */
|
|
#if defined(M_I86LM)
|
|
#undef NEAR
|
|
#define NEAR
|
|
#endif
|
|
#endif
|
|
#include <extern.h> /* External declarations */
|
|
#include <impexp.h>
|
|
#include <direct.h>
|
|
#if defined(DOSX32) OR defined(WIN_NT)
|
|
extern char FAR * _stdcall GetCommandLineA(void);
|
|
#endif
|
|
|
|
|
|
/*
|
|
* FUNCTION PROTOTYPES
|
|
*/
|
|
|
|
|
|
LOCAL void NEAR InitLeadByte(void);
|
|
LOCAL void NEAR SetupEnv(void);
|
|
LOCAL int NEAR IsPrefix(BYTE *pszPrefix, BYTE *pszString);
|
|
#if TCE
|
|
extern SYMBOLUSELIST aEntryPoints; // List of program entry points
|
|
#endif
|
|
|
|
#if ECS
|
|
|
|
/*
|
|
* InitLeadByte
|
|
*
|
|
* Initialize lead byte table structures.
|
|
* Returns no meaningful value.
|
|
*/
|
|
|
|
LOCAL void NEAR InitLeadByte ()
|
|
{
|
|
struct lbrange
|
|
{
|
|
unsigned char low; /* minimum */
|
|
unsigned char high; /* maximum */
|
|
};
|
|
static struct lbrange lbtab[5] = { { 0, 0 } };
|
|
struct lbrange *ptab;
|
|
WORD i; /* index */
|
|
COUNTRYCODE cc; /* country code */
|
|
|
|
cc.country = cc.codepage = 0;
|
|
if (DosGetDBCSEv(sizeof(lbtab), &cc, (char FAR *)lbtab))
|
|
return;
|
|
|
|
// For each range, set corresponding entries in fLeadByte
|
|
|
|
for (ptab = lbtab; ptab->low || ptab->high; ptab++)
|
|
if (ptab->low >= 0x80)
|
|
for (i = ptab->low; i <= ptab->high; i++)
|
|
fLeadByte[i-0x80] = (FTYPE) TRUE;
|
|
// Mark inclusive range true
|
|
}
|
|
#endif /* ECS */
|
|
|
|
#if NOT (WIN_NT OR DOSX32)
|
|
/*** _setenvp - stub for C run-time
|
|
*
|
|
* Purpose:
|
|
* Call stub instead of real function, we don't want C run-time to
|
|
* setup enviroment.
|
|
*
|
|
* Input:
|
|
* None;
|
|
*
|
|
* Output:
|
|
* None;
|
|
*
|
|
* Exceptions:
|
|
* None.
|
|
*
|
|
* Notes:
|
|
* None.
|
|
*
|
|
*************************************************************************/
|
|
|
|
void cdecl _setenvp(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*** IsPrefix - self-explanatory
|
|
*
|
|
* Purpose:
|
|
* Check if one string is a prefix of another.
|
|
*
|
|
* Input:
|
|
* pszPrefix - pointer to prefix string
|
|
* pszString - the string
|
|
*
|
|
* Output:
|
|
* The function returns TRUE if the first string is a prefix of the
|
|
* second; otherwise it returns FALSE.
|
|
*
|
|
* Exceptions:
|
|
* None.
|
|
*
|
|
* Notes:
|
|
* None.
|
|
*
|
|
*************************************************************************/
|
|
|
|
|
|
LOCAL int NEAR IsPrefix(BYTE *pszPrefix, BYTE *pszString)
|
|
{
|
|
while(*pszPrefix) // While not at end of prefix
|
|
{
|
|
if (*pszPrefix != *pszString) return(FALSE);
|
|
// Return zero if mismatch
|
|
++pszPrefix; // Increment pointer
|
|
++pszString; // Increment pointer
|
|
}
|
|
return(TRUE); // We have a prefix
|
|
}
|
|
#endif
|
|
|
|
|
|
/*** SetupEnv - set up pointer to linker evironment variables
|
|
*
|
|
* Purpose:
|
|
* Every byte in the DGROUP is to valuable to waste it to hold
|
|
* information available elswere in the memory linker is not using
|
|
* C run-time GETENV function, which accesses copy of the entire
|
|
* environemt in the DGROUP placed there by the startup code.
|
|
* Insted this function scans enviroment and set up pointers to
|
|
* appropriate strings. Because initially enviroment is in the FAR
|
|
* memory no space in DGROUP is used.
|
|
*
|
|
* Input:
|
|
* No explicit parameters are passed.
|
|
*
|
|
* Output:
|
|
* Four global pointer set to appropriate enviroment strings
|
|
*
|
|
* lpszLink - the LINK
|
|
* lpszPath - the PATH
|
|
* lpszTMP - the TMP
|
|
* lpszLIB - the LIB
|
|
* lpszQH - the QH for QuickHelp
|
|
*
|
|
* Exceptions:
|
|
* None.
|
|
*
|
|
* Notes:
|
|
* None.
|
|
*
|
|
*************************************************************************/
|
|
|
|
LOCAL void NEAR SetupEnv(void)
|
|
{
|
|
#if WIN_NT OR DOSX32
|
|
#if C8_IDE
|
|
char * pIDE = getenv("_MSC_IDE_FLAGS");
|
|
|
|
if(pIDE)
|
|
{
|
|
if(strstr(pIDE, "FEEDBACK"))
|
|
{
|
|
fC8IDE = TRUE;
|
|
#if DEBUG_IDE
|
|
fprintf(stdout, "\r\nIDE ACTIVE - FEEDBACK is ON");
|
|
#endif
|
|
}
|
|
if(strstr(pIDE, "BATCH"))
|
|
{
|
|
// NOTE: The link response file will still be echoed in this case!
|
|
// NOTE: this is different than if you specify /BATCH on the
|
|
// NOTE: command line -- also, the banner is still displayed
|
|
// NOTE: this is intentional as the IDE wants to BATCH to cause
|
|
// NOTE: the linker not to prompt, but it does want the banner
|
|
// NOTE: and response file echoed unless /NOLOGO is also specified
|
|
// NOTE: see CAVIAR 2378 [rm]
|
|
|
|
fNoprompt = (FTYPE) TRUE;
|
|
fPauseRun = FALSE; /* Disable /PAUSE */
|
|
#if DEBUG_IDE
|
|
fprintf(stdout, "\r\nIDE ACTIVE - BATCH is ON");
|
|
#endif
|
|
}
|
|
if(strstr(pIDE, "NOLOGO"))
|
|
{
|
|
fNoBanner = (FTYPE) TRUE;
|
|
#if DEBUG_IDE
|
|
fprintf(stdout, "\r\nIDE ACTIVE - LOGO is OFF");
|
|
#endif
|
|
}
|
|
|
|
|
|
}
|
|
#if DEBUG_IDE
|
|
else
|
|
fprintf(stdout, "\r\nIDE NOT ACTIVE");
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
#endif // C8_IDE
|
|
|
|
lpszPath = getenv("PATH");
|
|
lpszLink = getenv("LINK");
|
|
lpszTMP = getenv("TMP");
|
|
lpszLIB = getenv("LIB");
|
|
lpszQH = getenv("QH");
|
|
lpszHELPFILES = getenv("HELPFILES");
|
|
lpszCmdLine = GetCommandLineA();
|
|
while (*lpszCmdLine != ' ')
|
|
lpszCmdLine++;
|
|
#else
|
|
WORD selEnv;
|
|
WORD cmdOffset;
|
|
register WORD offMac;
|
|
char FAR *lpszEnv;
|
|
char FAR *lpch;
|
|
SBTYPE buf;
|
|
register WORD ich;
|
|
WORD fEOS;
|
|
|
|
|
|
|
|
#if QCLINK OR CPU8086 OR DOSEXTENDER
|
|
// Get the segment address of the environment block
|
|
// and set the command line offset to infinity. We
|
|
// stop scanning environment block at NULL string.
|
|
|
|
lpszEnv = (char FAR *)
|
|
(((long) _psp << 16)
|
|
+ 0x2c);
|
|
selEnv = *((WORD FAR *) lpszEnv);
|
|
lpszCmdLine = (char FAR *)(((long) _psp << 16) + 0x80);
|
|
lpszCmdLine[lpszCmdLine[0] + 1] = '\0';
|
|
lpszCmdLine++;
|
|
cmdOffset = 0xffff;
|
|
#else
|
|
if (DosGetEnv((unsigned FAR *) &selEnv, (unsigned FAR *) &cmdOffset))
|
|
return;
|
|
#endif
|
|
|
|
lpszEnv = (char FAR *)((long) selEnv << 16);
|
|
#if NOT (QCLINK OR CPU8086 OR DOSEXTENDER)
|
|
lpszCmdLine = lpszEnv + cmdOffset;
|
|
|
|
// Skip LINK
|
|
|
|
lpszCmdLine += _fstrlen(lpszCmdLine) + 1;
|
|
#endif
|
|
|
|
// Skip leading spaces in command line
|
|
|
|
while (*lpszCmdLine == ' ')
|
|
lpszCmdLine++;
|
|
|
|
lpch = lpszEnv;
|
|
for (offMac = 0; offMac < cmdOffset && *lpszEnv; )
|
|
{
|
|
// Copy the enviroment variable string into near buffer
|
|
|
|
ich = 0;
|
|
while (*lpch && ich < sizeof(buf) - 1)
|
|
buf[ich++] = *lpch++;
|
|
|
|
if (*lpch == '\0')
|
|
{
|
|
|
|
// Skip over terminating zero
|
|
|
|
lpch++;
|
|
fEOS = TRUE;
|
|
}
|
|
else
|
|
fEOS = FALSE;
|
|
|
|
buf[ich] = '\0';
|
|
|
|
// Check what it is and setup appropriate pointer
|
|
|
|
if (lpszPath == NULL && IsPrefix((BYTE *) "PATH=", buf))
|
|
lpszPath = lpszEnv + 5;
|
|
else if (lpszLink == NULL && IsPrefix((BYTE *) "LINK=", buf))
|
|
lpszLink = lpszEnv + 5;
|
|
else if (lpszTMP == NULL && IsPrefix((BYTE *) "TMP=", buf))
|
|
lpszTMP = lpszEnv + 4;
|
|
else if (lpszLIB == NULL && IsPrefix((BYTE *) "LIB=", buf))
|
|
lpszLIB = lpszEnv + 4;
|
|
else if (lpszQH == NULL && IsPrefix((BYTE *) "QH=", buf))
|
|
lpszQH = lpszEnv + 3;
|
|
else if (lpszHELPFILES == NULL && IsPrefix((BYTE *) "HELPFILES=", buf))
|
|
lpszHELPFILES = lpszEnv + 10;
|
|
|
|
// If everything setup don't bother to look father
|
|
|
|
if (lpszPath && lpszLink && lpszTMP && lpszLIB && lpszQH && lpszHELPFILES)
|
|
break;
|
|
|
|
// Update enviroment pointer and offset in enviroment segment
|
|
|
|
offMac += ich;
|
|
if (!fEOS)
|
|
{
|
|
// Oops ! - enviroment variable longer then buffer
|
|
// skip to its end
|
|
|
|
while (*lpch && offMac < cmdOffset)
|
|
{
|
|
lpch++;
|
|
offMac++;
|
|
}
|
|
|
|
// Skip over terminating zero
|
|
|
|
lpch++;
|
|
offMac++;
|
|
}
|
|
lpszEnv = lpch;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if FALSE
|
|
|
|
/*** Dos3SetMaxFH - set max file handle count for DOS
|
|
*
|
|
* Purpose:
|
|
* Sets the maximum number of files that may be opened
|
|
* simultaneously using handles by the linker.
|
|
*
|
|
* Input:
|
|
* cFH - number of desired handles
|
|
*
|
|
* Output:
|
|
* No explicit value is returned.
|
|
*
|
|
* Exceptions:
|
|
* None.
|
|
*
|
|
* Notes:
|
|
* This function uses the int 21h function 67h which available on
|
|
* DOS 3.3 and higher. The function fails if the requested number of
|
|
* handles is greater then 20 and there is not sufficient free memory
|
|
* in the system to allocate a new block to hold the enlarged table.
|
|
*
|
|
* If the number of handles requested is larger the available
|
|
* entries in the system's global table for file handles (controlled
|
|
* by the FILES entry in CONFIG.SYS), no error is returned.
|
|
* However, a subsequent attempt to open a file or create a new
|
|
* file will fail if all entries in the system's global file table
|
|
* are in use, even if the requesting process has not used up all
|
|
* of its own handles
|
|
*
|
|
* We don't check for error, because we can't do much about it.
|
|
* Linker will try to run with what is available.
|
|
*
|
|
*************************************************************************/
|
|
|
|
LOCAL void NEAR Dos3SetMaxFH(WORD cFH)
|
|
{
|
|
if ((_osmajor >= 3) && (_osminor >= 30))
|
|
{
|
|
_asm
|
|
{
|
|
mov ax, 0x6700
|
|
mov bx, cFH
|
|
int 0x21
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************
|
|
* *
|
|
* InitializeWorld: *
|
|
* *
|
|
* This function takes no arguments and returns no meaningful *
|
|
* value. It sets up virtual memory, the symbol table *
|
|
* Handlers, and it initializes segment structures. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
void InitializeWorld(void)
|
|
{
|
|
#if OSMSDOS
|
|
BYTE buf[512]; /* Temporary buffer */
|
|
char FAR *lpch; /* Temporary pointer */
|
|
int i; /* Temporary index */
|
|
#endif
|
|
|
|
#if NOT (FIXEDSTACK OR CPU386)
|
|
InitStack(); /* Initialize stack */
|
|
#endif
|
|
#if OSMSDOS
|
|
DskCur = (BYTE) (_getdrive() - 1); /* Get current (default) disk drive */
|
|
#if FALSE
|
|
if(!isatty(fileno(stderr))) /* No prompts if output not console */
|
|
fNoprompt = TRUE;
|
|
#endif
|
|
#if CRLF
|
|
/* Default mode of stdout, stdin, stderr is text, change to binary. */
|
|
_setmode(fileno(stdout),O_BINARY);
|
|
if(stderr != stdout)
|
|
_setmode(fileno(stderr),O_BINARY);
|
|
_setmode(fileno(stdin),O_BINARY);
|
|
#endif
|
|
#endif
|
|
InitSym(); /* Initialize symbol table handler */
|
|
DeclareStdIds();
|
|
|
|
// Install CTRL-C handler
|
|
|
|
#if OSMSDOS AND NOT WIN_NT
|
|
signal(SIGINT, (void (__cdecl *)(int)) UserKill);
|
|
#endif /* OSMSDOS */
|
|
|
|
#if OSXENIX
|
|
if(signal(SIGINT,UserKill) == SIG_IGN) signal(SIGINT,SIG_IGN);
|
|
/* Trap user interrupts */
|
|
if(signal(SIGHUP,UserKill) == SIG_IGN) signal(SIGHUP,SIG_IGN);
|
|
/* Trap hangup signal */
|
|
if(signal(SIGTERM,UserKill) == SIG_IGN) signal(SIGTERM,SIG_IGN);
|
|
/* Trap software termination */
|
|
#endif
|
|
|
|
#if SYMDEB
|
|
InitDbRhte();
|
|
#endif
|
|
|
|
#if ECS
|
|
InitLeadByte(); /* Initialize lead byte table */
|
|
#endif
|
|
|
|
#if OSMSDOS
|
|
// Initialize LINK environment.
|
|
// Do it yourself to save the memory.
|
|
|
|
SetupEnv();
|
|
|
|
/* Process switches from LINK environment variable */
|
|
|
|
if (lpszLink != NULL)
|
|
{
|
|
lpch = lpszLink;
|
|
|
|
/* Skip leading whitespace. */
|
|
|
|
while(*lpch == ' ' || *lpch == '\t')
|
|
lpch++;
|
|
if(*lpch++ == CHSWITCH)
|
|
{
|
|
// If string begins with switchr
|
|
// Copy string to buf, removing whitespace
|
|
|
|
for (i = 1; *lpch && i < sizeof(buf); lpch++)
|
|
if (*lpch != ' ' && *lpch != '\t')
|
|
buf[i++] = *lpch;
|
|
buf[0] = (BYTE) (i - 1); /* Set the length of buf */
|
|
if(buf[0]) /* If any switches, process them */
|
|
BreakLine(buf,ProcFlag,CHSWITCH);
|
|
}
|
|
}
|
|
#endif
|
|
#if CPU286
|
|
if (_osmode == OS2_MODE)
|
|
{
|
|
DosSetMaxFH(128); /* This is the same as _NFILE in crt0dat.asm */
|
|
DosError(EXCEPTION_DISABLE);
|
|
}
|
|
#if FALSE
|
|
else
|
|
Dos3SetMaxFH(40);
|
|
#endif
|
|
#endif
|
|
#if FALSE AND CPU8086
|
|
Dos3SetMaxFH(40);
|
|
#endif
|
|
|
|
// Initialize import/export tables
|
|
|
|
InitByteArray(&ResidentName);
|
|
InitByteArray(&NonResidentName);
|
|
InitByteArray(&ImportedName);
|
|
ImportedName.byteMac++; // Ensure non-zero offsets to imported names
|
|
InitWordArray(&ModuleRefTable);
|
|
InitByteArray(&EntryTable);
|
|
#if TCE
|
|
aEntryPoints.cMaxEntries = 64;
|
|
aEntryPoints.pEntries = (RBTYPE*)GetMem(aEntryPoints.cMaxEntries * sizeof(RBTYPE*));
|
|
#endif
|
|
}
|
|
|
|
#if (OSXENIX OR OSMSDOS OR OSPCDOS) AND NOT WIN_NT
|
|
/****************************************************************
|
|
* *
|
|
* UserKill: *
|
|
* *
|
|
* Clean up if linker killed by user. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
void cdecl UserKill()
|
|
{
|
|
signal(SIGINT, SIG_IGN); /* Disallow ctrl-c during handler */
|
|
CtrlC();
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* InitTabs:
|
|
*
|
|
* Initialize tables required in Pass 1.
|
|
*/
|
|
|
|
|
|
void InitTabs(void)
|
|
{
|
|
#if NOT FAR_SEG_TABLES
|
|
char *tabs; /* Pointer to table space */
|
|
unsigned cbtabs;
|
|
#endif
|
|
|
|
|
|
/* Initialize the following tables:
|
|
*
|
|
* NAME TYPE
|
|
* ---- ----
|
|
* mpsegraFirst RATYPE
|
|
* mpgsnfCod FTYPE
|
|
* mpgsndra RATYPE
|
|
* mpgsnrprop RBTYPE
|
|
* mplnamerhte RBTYPE
|
|
*/
|
|
|
|
#if FAR_SEG_TABLES
|
|
mplnamerhte = (RBTYPE FAR *) GetMem(lnameMax * sizeof(RBTYPE));
|
|
mpsegraFirst = (RATYPE FAR *) GetMem(gsnMax * sizeof(RATYPE));
|
|
mpgsnfCod = (FTYPE FAR *) mpsegraFirst; /* Use same space twice */
|
|
mpgsndra = (RATYPE FAR *) GetMem(gsnMax * sizeof(RATYPE));
|
|
mpgsnrprop = (RBTYPE FAR *) GetMem(gsnMax * sizeof(RBTYPE));
|
|
#else
|
|
mplnamerhte = (RBTYPE *) malloc(lnameMax * sizeof(RBTYPE));
|
|
if (mplnamerhte == NULL)
|
|
Fatal(ER_seglim);
|
|
|
|
memset(mplnamerhte, 0, lnameMax * sizeof(RATYPE));
|
|
|
|
cbtabs = gsnMax * (sizeof(RATYPE) + sizeof(RATYPE) + sizeof(RBTYPE));
|
|
if((tabs = malloc(cbtabs)) == NULL)
|
|
Fatal(ER_seglim);
|
|
memset(tabs,0,cbtabs); /* Clear everything */
|
|
mpsegraFirst = (RATYPE *) tabs; /* Initialize base */
|
|
mpgsnfCod = (FTYPE *) mpsegraFirst; /* Use same space twice */
|
|
mpgsndra = (RATYPE *) &mpsegraFirst[gsnMax];
|
|
mpgsnrprop = (RBTYPE *) &mpgsndra[gsnMax];
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* InitP2Tabs:
|
|
*
|
|
* Initialize tables not needed until Pass 2.
|
|
*/
|
|
|
|
void InitP2Tabs (void)
|
|
{
|
|
char FAR *tabs; /* Pointer to table space */
|
|
unsigned cbtabs; /* Size of table space */
|
|
unsigned TabSize;
|
|
|
|
|
|
TabSize = gsnMac + iovMac + 1;
|
|
|
|
/* Tables required regardless of exe format generated:
|
|
* mpsegsa SATYPE
|
|
* mpgsnseg SEGTYPE
|
|
*/
|
|
|
|
#if FAR_SEG_TABLES
|
|
cbtabs = 0;
|
|
mpsegsa = (SATYPE FAR *) GetMem(TabSize * sizeof(SATYPE));
|
|
mpgsnseg = (SEGTYPE FAR *) GetMem(TabSize * sizeof(SEGTYPE));
|
|
mpseggsn = (SNTYPE FAR *) GetMem(TabSize * sizeof(SNTYPE));
|
|
#else
|
|
cbtabs = TabSize * (sizeof(RATYPE) + sizeof(SATYPE));
|
|
#endif
|
|
|
|
/* Tables required according to exe format generated:
|
|
*
|
|
* DOS 3:
|
|
* mpsegcb[TabSize] long
|
|
* mpsegFlags[TabSize] FTYPE
|
|
* mpsegalign[TabSize] ALIGNTYPE
|
|
* mpsegiov[TabSize] IOVTYPE
|
|
* mpiovRlc[iovMac] RUNRLC
|
|
* Seg. exe:
|
|
* mpsacb[SAMAX] long
|
|
* mpsadraDP[SAMAX] long; for O68K
|
|
* mpsacbinit[SAMAX] long
|
|
* mpsaRlc[SAMAX] HASHRLC FAR *
|
|
* mpsaflags[SAMAX] WORD; DWORD for EXE386
|
|
* htsaraep[HEPLEN] EPTYPE FAR *
|
|
* X.out:
|
|
* mpsegcb[TabSize] long
|
|
* mpsegFlags[TabSize] FTYPE
|
|
* mpstsa[TabSize] SATYPE
|
|
*/
|
|
#if EXE386
|
|
if(fNewExe)
|
|
cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(DWORD)+
|
|
sizeof(DWORD))) + (HEPLEN * sizeof(WORD));
|
|
else
|
|
#else
|
|
if(fNewExe)
|
|
#if O68K
|
|
cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(long)+sizeof(WORD)+
|
|
sizeof(WORD))) + (HEPLEN * sizeof(WORD));
|
|
#else
|
|
cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(RLCHASH FAR *) +
|
|
sizeof(WORD))) + (HEPLEN * sizeof(EPTYPE FAR *));
|
|
#endif
|
|
else
|
|
#endif
|
|
#if OEXE
|
|
cbtabs += TabSize * (sizeof(long) + sizeof(FTYPE) + sizeof(ALIGNTYPE));
|
|
#else
|
|
cbtabs += TabSize * (sizeof(long) + sizeof(FTYPE) + sizeof(SATYPE));
|
|
#endif
|
|
|
|
|
|
cbtabs += sizeof(WORD);
|
|
tabs = GetMem(cbtabs);
|
|
#if NOT FAR_SEG_TABLES
|
|
mpgsnseg = (SEGTYPE *)tabs;
|
|
mpsegsa = (SATYPE *)&mpgsnseg[TabSize];
|
|
tabs = (char *)&mpsegsa[TabSize];
|
|
#endif
|
|
#if OSEGEXE
|
|
if(fNewExe)
|
|
{
|
|
mpsacb = (DWORD FAR *) tabs;
|
|
#if O68K
|
|
mpsadraDP = (long *)&mpsacb[SAMAX];
|
|
mpsacbinit = (long *)&mpsadraDP[SAMAX];
|
|
#else
|
|
mpsacbinit = (DWORD FAR *)&mpsacb[SAMAX];
|
|
#endif
|
|
#if EXE386
|
|
mpsacrlc = (DWORD *)&mpsacbinit[SAMAX];
|
|
mpsaflags = (DWORD *)&mpsacrlc[SAMAX];
|
|
#else
|
|
mpsaRlc = (RLCHASH FAR * FAR *) &mpsacbinit[SAMAX];
|
|
mpsaflags = (WORD FAR *) &mpsaRlc[SAMAX];
|
|
#endif
|
|
htsaraep = (EPTYPE FAR * FAR *)&mpsaflags[SAMAX];
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#if ODOS3EXE OR OIAPX286
|
|
mpsegcb = (long FAR *) tabs;
|
|
mpsegFlags = (FTYPE FAR *)&mpsegcb[TabSize];
|
|
#if OEXE
|
|
mpsegalign = (ALIGNTYPE FAR *)&mpsegFlags[TabSize];
|
|
#if OVERLAYS
|
|
cbtabs = iovMac * sizeof(RUNRLC) + TabSize * sizeof(IOVTYPE) +
|
|
(sizeof(DWORD) - 1); // leave room to align mpiovRlc
|
|
mpsegiov = (IOVTYPE FAR*) GetMem(cbtabs);
|
|
|
|
// align mpiovRlc on a DWORD, the alignment needed by struct _RUNRLC
|
|
|
|
mpiovRlc = (RUNRLC FAR*) ( ( (__int64)&mpsegiov[TabSize] +
|
|
(sizeof(DWORD) - 1)
|
|
) & ~(sizeof(DWORD) - 1)
|
|
);
|
|
#endif
|
|
#endif
|
|
#if OIAPX286
|
|
mpstsa = (SATYPE *)&mpsegFlags[TabSize];
|
|
#endif
|
|
#endif /* ODOS3EXE OR OIAPX286 */
|
|
}
|
|
/* Attempt to allocate space for mpextprop. */
|
|
cbtabs = extMax * sizeof(RBTYPE);
|
|
mpextprop = (RBTYPE FAR *) GetMem(cbtabs);
|
|
|
|
}
|