/***************************************************************************** * * * 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; }