mirror of https://github.com/lianthony/NT4.0
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.
416 lines
10 KiB
416 lines
10 KiB
/*****************************************************************************
|
|
* *
|
|
* DELAY.CPP *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1990-1994 *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* *
|
|
* This module handles delayed address processing. It is required because *
|
|
* physical addresses are not known until after a 16K block can be *
|
|
* processed with Zeck compression. Instead of writing addresses out *
|
|
* when they are encountered, the idfcp is recorded with a DelayExecution() *
|
|
* call. Then, after a block gets Zeck compressed and the addresses are *
|
|
* known, we go through this information and write out all the correct *
|
|
* addresses. *
|
|
*****************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Defines *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
// Maximum value of an object offset
|
|
|
|
const int MAX_OBJRG = (1 << CBITS_OBJOFF);
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Typedefs *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
// Delay Execution: Browse info
|
|
|
|
typedef struct {
|
|
PSTR szMajor, szMinor;
|
|
IDFCP idfcp;
|
|
} DEBROWSE, * QDEBROWSE;
|
|
|
|
// Delay Execution: Title info
|
|
|
|
typedef struct {
|
|
PSTR szTitle;
|
|
IDFCP idfcp;
|
|
} DETITLE, * LPDETITLE;
|
|
|
|
// Delay Execution: Context string info
|
|
|
|
typedef struct {
|
|
HASH hash;
|
|
IDFCP idfcp;
|
|
WORD wObjrg;
|
|
} DECONTEXT, * QDECONTEXT;
|
|
|
|
// Delay Execution: Keyword info
|
|
|
|
typedef struct {
|
|
CTable* ptbl;
|
|
KT chKey;
|
|
IDFCP idfcp;
|
|
WORD wObjrg;
|
|
} DEKEYWORD, * LPDEKEYWORD;
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Static Variables *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
static CDrg* pdrgBrowse;
|
|
static CDrg* pdrgTitle;
|
|
static CDrg* pdrgContext;
|
|
static CDrg* pdrgKeyword;
|
|
static CDrg* pdrgWObjrg; // DRG of wObjrg in each FCP
|
|
|
|
static WORD wObjrgTotal;
|
|
static IDFCP _idfcpFirst; // id of first FCP in above DRG
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Prototypes *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
void STDCALL FInitDelayExecution(void)
|
|
{
|
|
_idfcpFirst = FIRST_IDFCP; // REVIEW;
|
|
wObjrgTotal = 0;
|
|
|
|
pdrgTitle = new CDrg(sizeof(DETITLE), 100, 100);
|
|
pdrgContext = new CDrg(sizeof(DECONTEXT), 100, 100);
|
|
pdrgKeyword = new CDrg(sizeof(DEKEYWORD), 100, 100);
|
|
pdrgWObjrg = new CDrg(sizeof(WORD), 100, 100);
|
|
}
|
|
|
|
void STDCALL EndDelayExecution(void)
|
|
{
|
|
if (pdrgBrowse) {
|
|
delete pdrgBrowse;
|
|
pdrgBrowse = NULL;
|
|
}
|
|
|
|
// Use pdrgTitle to determine if any were created
|
|
|
|
if (pdrgTitle) {
|
|
delete pdrgWObjrg;
|
|
delete pdrgKeyword;
|
|
delete pdrgContext;
|
|
delete pdrgTitle;
|
|
|
|
pdrgTitle = NULL;
|
|
pdrgContext = NULL;
|
|
pdrgKeyword = NULL;
|
|
pdrgWObjrg = NULL;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: RcRegisterWObjrg
|
|
-
|
|
* Purpose:
|
|
* Used to register the number of object regions in every
|
|
* FCP, in order to calculate cumulative object offsets when
|
|
* determining physical addresses.
|
|
*
|
|
* Arguments:
|
|
* idfcp: id of FCP
|
|
* wObjrg: Number of object regions in FCP
|
|
*
|
|
* Returns:
|
|
* Return code:
|
|
* RC_Success: success
|
|
* RC_Failure: Current FCP overflows object region count. All
|
|
* FCPs up to but not including this one must be
|
|
* flushed.
|
|
* RC_TooBig: Current FCP overflows object region count all
|
|
* by itself. Paragraph contains too many objects
|
|
* and cannot be compiled.
|
|
* RC_OutOfMemory: Out of memory.
|
|
*
|
|
* Globals:
|
|
* Uses the global wObjrgTotal to accumulate current total of
|
|
* object offsets.
|
|
*
|
|
* +++
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
RC_TYPE STDCALL RcRegisterWObjrg(IDFCP idfcp, UINT wObjrg)
|
|
{
|
|
Unreferenced(idfcp); // in non-debug build
|
|
|
|
// This assert happens in dolphin\crt.hpj -- but what does it mean?
|
|
// ASSERT(_idfcpFirst + pdrgWObjrg->Count() == idfcp);
|
|
|
|
/*
|
|
* REVIEW: This assert is valid because this condition is checked in
|
|
* RcOutputCommand, and outputting an end of text command is the last
|
|
* thing that ever happens to any FCP. However, the constants they check
|
|
* against are declared differently, although they currently evaluate to
|
|
* the same thing.
|
|
*/
|
|
|
|
ASSERT(wObjrg <= MAX_OBJRG);
|
|
|
|
pdrgWObjrg->Add(&wObjrg);
|
|
|
|
wObjrgTotal += wObjrg;
|
|
|
|
if (wObjrgTotal > MAX_OBJRG)
|
|
return RC_Failure;
|
|
return RC_Success;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name: FKeepFlushing
|
|
-
|
|
* Purpose:
|
|
* This function is called to flush the zeck buffer until the
|
|
* total object region count is low enough to proceed.
|
|
*
|
|
* Arguments:
|
|
* none
|
|
*
|
|
* Returns:
|
|
* TRUE if the current object region total is still too large.
|
|
*
|
|
* Globals Used:
|
|
* wObjrgTotal
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL STDCALL FKeepFlushing(void)
|
|
{
|
|
return (wObjrgTotal > MAX_OBJRG);
|
|
}
|
|
|
|
void STDCALL FDelayExecutionBrowse(PSTR szMajor, PSTR szMinor,
|
|
IDFCP idfcp)
|
|
{
|
|
DEBROWSE debrowse;
|
|
|
|
if (!pdrgBrowse)
|
|
pdrgBrowse = new CDrg(sizeof(DEBROWSE), 100, 100);
|
|
|
|
if (strlen(szMajor) >= 50) {
|
|
VReportError(HCERR_MAJOR_BROWSE_TOO_BIG, &errHpj, szMajor);
|
|
szMajor[50] = '\0';
|
|
}
|
|
if (strlen(szMinor) >= 50) {
|
|
VReportError(HCERR_MINOR_BROWSE_TOO_BIG, &errHpj, szMinor);
|
|
szMinor[50] = '\0';
|
|
}
|
|
debrowse.szMajor = lcStrDup(szMajor);
|
|
debrowse.szMinor = lcStrDup(szMinor);
|
|
debrowse.idfcp = idfcp;
|
|
|
|
pdrgBrowse->Add(&debrowse);
|
|
}
|
|
|
|
void STDCALL FDelayExecutionTitle(PCSTR szTitle, IDFCP idfcp)
|
|
{
|
|
DETITLE detitle;
|
|
|
|
detitle.szTitle = lcStrDup(szTitle);
|
|
detitle.idfcp = idfcp;
|
|
|
|
pdrgTitle->Add(&detitle);
|
|
}
|
|
|
|
void STDCALL FDelayExecutionContext(HASH hash, IDFCP idfcp, UINT wObjrg)
|
|
{
|
|
DECONTEXT decontext;
|
|
|
|
decontext.hash = hash;
|
|
decontext.idfcp = idfcp;
|
|
decontext.wObjrg = wObjrg;
|
|
|
|
pdrgContext->Add(&decontext);
|
|
}
|
|
|
|
void STDCALL FDelayExecutionKeyword(CTable* ptbl, KT chKey, IDFCP idfcp,
|
|
UINT wObjrg)
|
|
{
|
|
DEKEYWORD dekeyword;
|
|
|
|
dekeyword.ptbl = ptbl;
|
|
dekeyword.chKey = chKey;
|
|
dekeyword.idfcp = idfcp;
|
|
dekeyword.wObjrg = wObjrg;
|
|
|
|
pdrgKeyword->Add(&dekeyword);
|
|
}
|
|
|
|
RC_TYPE STDCALL RcExecuteDelayedExecution(DWORD ulBlknum, IDFCP idfcpFirst,
|
|
IDFCP idfcpLast, BROWSE_CALLBACK pfnBrowseCallback)
|
|
{
|
|
WORD * rgwOffset;
|
|
WORD iwOffset;
|
|
PA pa;
|
|
RC_TYPE rc;
|
|
LPDETITLE lpDeTitle;
|
|
|
|
ASSERT(_idfcpFirst == idfcpFirst);
|
|
|
|
// REVIEW ! ! REVIEW ! !
|
|
|
|
if (idfcpFirst > idfcpLast)
|
|
return RC_Success;
|
|
|
|
// First, set up addresses:
|
|
|
|
pa.blknum = ulBlknum;
|
|
|
|
ASSERT((idfcpLast - idfcpFirst + 1) * sizeof(WORD) < 63L * 1024L);
|
|
|
|
CMem gmem((idfcpLast - idfcpFirst + 1) * sizeof(WORD));
|
|
rgwOffset = (WORD *) gmem.pb;
|
|
|
|
ASSERT((IDFCP) pdrgWObjrg->Count() > idfcpLast - idfcpFirst);
|
|
|
|
rgwOffset[0] = 0;
|
|
|
|
for (iwOffset = 1; (IDFCP) iwOffset <= idfcpLast - idfcpFirst;
|
|
++iwOffset) {
|
|
rgwOffset[iwOffset] = rgwOffset[iwOffset - 1] +
|
|
*(WORD*) pdrgWObjrg->GetBasePtr();
|
|
|
|
// This call removes the iwOffset-1 element from pdrgWObjrg
|
|
|
|
pdrgWObjrg->RemoveFirst();
|
|
}
|
|
|
|
/*
|
|
* Subtract from wObjrgTotal all the registered object region counts we
|
|
* have removed.
|
|
*/
|
|
|
|
wObjrgTotal -= rgwOffset[idfcpLast - idfcpFirst];
|
|
|
|
// Now we remove the wObjrg of the last FCP in this block from pdrgWObjrg
|
|
|
|
wObjrgTotal -= *(WORD*) pdrgWObjrg->GetBasePtr();
|
|
pdrgWObjrg->RemoveFirst();
|
|
_idfcpFirst = idfcpLast + 1;
|
|
|
|
if (pdrgBrowse) {
|
|
|
|
ASSERT(ptblBrowse);
|
|
|
|
if (!fBrowseButtonSet)
|
|
VReportError(HCERR_NO_BROWSE_BUTTONS, &errHpj);
|
|
|
|
// REVIEW: This is not very efficient
|
|
|
|
QDEBROWSE lpDeBrowse;
|
|
|
|
while (pdrgBrowse->Count() > 0 &&
|
|
(lpDeBrowse = (QDEBROWSE) pdrgBrowse->GetBasePtr())->idfcp <=
|
|
idfcpLast) {
|
|
int iBitdex;
|
|
|
|
FCL fcl = (*pfnBrowseCallback) (lpDeBrowse->idfcp, &iBitdex);
|
|
pa.objoff = rgwOffset[lpDeBrowse->idfcp - idfcpFirst];
|
|
|
|
// Print prev/next codes into file:
|
|
// szMajor : szMinor : fcl fixup pos : Zeck compression bit dex : PA
|
|
|
|
char szBuf[200];
|
|
|
|
ASSERT(strlen(lpDeBrowse->szMajor) + strlen(lpDeBrowse->szMinor) < 170);
|
|
|
|
wsprintf(szBuf, "%s:%s:%8lX:%8lX:%8lX\n",
|
|
lpDeBrowse->szMajor,
|
|
lpDeBrowse->szMinor, fcl, iBitdex, *(int *) (&pa));
|
|
if (!ptblBrowse->AddString(szBuf))
|
|
OOM(); // does not return
|
|
lcFree(lpDeBrowse->szMajor);
|
|
lcFree(lpDeBrowse->szMinor);
|
|
pdrgBrowse->RemoveFirst();
|
|
}
|
|
}
|
|
|
|
while (pdrgTitle->Count() > 0 &&
|
|
(lpDeTitle = (LPDETITLE) pdrgTitle->GetBasePtr())->idfcp <= idfcpLast) {
|
|
pa.objoff = rgwOffset[lpDeTitle->idfcp - idfcpFirst];
|
|
#ifdef _DEBUG
|
|
{
|
|
// Verify that things are sorted correctly. If they aren't,
|
|
// RcFillHbt() will create a broken btree.
|
|
|
|
static ADDR addrLast = addrNil;
|
|
ASSERT(addrLast == addrNil || addrLast < *(ADDR *) &pa);
|
|
addrLast = *(ADDR *) &pa;
|
|
}
|
|
#endif // DEBUG
|
|
if ((rc = RcFillHbt(fmsg.qbthrTTL, (KEY) &pa, lpDeTitle->szTitle))
|
|
!= RC_Success)
|
|
return rc;
|
|
ASSERT(lpDeTitle->szTitle);
|
|
lcFree(lpDeTitle->szTitle);
|
|
pdrgTitle->RemoveFirst();
|
|
}
|
|
|
|
QDECONTEXT qdectx;
|
|
while (pdrgContext->Count() > 0 &&
|
|
(qdectx = (QDECONTEXT) pdrgContext->GetBasePtr())->idfcp <=
|
|
idfcpLast) {
|
|
pa.objoff = rgwOffset[qdectx->idfcp - idfcpFirst] + qdectx->wObjrg;
|
|
if ((rc = RcInsertHbt(fmsg.qbthrCtx, (KEY) &qdectx->hash,
|
|
(LPVOID) &pa)) != RC_Success && rc != RC_Exists)
|
|
return rc;
|
|
pdrgContext->RemoveFirst();
|
|
}
|
|
|
|
LPDEKEYWORD pDeKeyword;
|
|
|
|
while (pdrgKeyword->Count() > 0 &&
|
|
(pDeKeyword = (LPDEKEYWORD) pdrgKeyword->GetBasePtr())->idfcp <=
|
|
idfcpLast) {
|
|
|
|
KWD kwd;
|
|
|
|
pa.objoff = rgwOffset[pDeKeyword->idfcp - idfcpFirst] +
|
|
pDeKeyword->wObjrg;
|
|
kwd.addr = *(ADDR *)&pa;
|
|
|
|
for (int iszKey = 1; iszKey <= pDeKeyword->ptbl->CountStrings();
|
|
++iszKey) {
|
|
kwd.szKey = pDeKeyword->ptbl->GetPointer(iszKey);
|
|
RcWritePkwd(&kwd, pDeKeyword->chKey);
|
|
}
|
|
|
|
delete pDeKeyword->ptbl;
|
|
pdrgKeyword->RemoveFirst();
|
|
}
|
|
|
|
return RC_Success;
|
|
}
|