/* Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ /*************************************************************************** Author: ShonK Project: Kauai Reviewed: Copyright (c) Microsoft Corporation Error registration and reporting. Uses a stack of error code. Not based on lists (which seem like an obvious choice), since we don't want to do any allocation when registering an error. ***************************************************************************/ #include "util.h" ASSERTNAME ERS _ers; ERS *vpers = &_ers; RTCLASS(ERS) /*************************************************************************** Initialize the error code stack. ***************************************************************************/ ERS::ERS(void) { _cerd = 0; } /*************************************************************************** Push an error code onto the stack. If overflow occurs, blt the top kcerdMax - 1 entries down by one (and lose the bottom entry). ***************************************************************************/ #ifdef DEBUG void ERS::Push(long erc, PSZS pszsFile, long lwLine) #else //!DEBUG void ERS::Push(long erc) #endif //!DEBUG { AssertThis(0); #ifdef DEBUG STN stn; SZS szs; stn.FFormatSz(PszLit("Error %d"), erc); stn.GetSzs(szs); WarnProc(pszsFile, lwLine, szs); #endif //DEBUG _mutx.Enter(); if (_cerd > 0 && erc == _rgerd[_cerd - 1].erc) goto LDone; if (_cerd == kcerdMax) { Warn("Warning: error code stack has filled"); BltPb(_rgerd + 1, _rgerd, LwMul(size(_rgerd[0]), kcerdMax - 1)); _cerd--; } #ifdef DEBUG _rgerd[_cerd].pszsFile = pszsFile; _rgerd[_cerd].lwLine = lwLine; #endif //DEBUG _rgerd[_cerd++].erc = erc; LDone: _mutx.Leave(); AssertThis(0); } /*************************************************************************** Pop the top error from the stack. Return fFalse if underflow. ***************************************************************************/ bool ERS::FPop(long *perc) { AssertThis(0); AssertNilOrVarMem(perc); _mutx.Enter(); if (_cerd == 0) { TrashVar(perc); _mutx.Leave(); return fFalse; } --_cerd; if (pvNil != perc) *perc = _rgerd[_cerd].erc; _mutx.Leave(); AssertThis(0); return fTrue; } /*************************************************************************** Clear the error stack. ***************************************************************************/ void ERS::Clear(void) { AssertThis(0); _mutx.Enter(); _cerd = 0; _mutx.Leave(); } /*************************************************************************** Return the size of the error stack. ***************************************************************************/ long ERS::Cerc(void) { AssertThis(0); return _cerd; } /*************************************************************************** See if the given error code is on the stack. ***************************************************************************/ bool ERS::FIn(long erc) { AssertThis(0); long ierd; _mutx.Enter(); for (ierd = 0; ierd < _cerd; ierd++) { if (_rgerd[ierd].erc == erc) { _mutx.Leave(); return fTrue; } } _mutx.Leave(); return fFalse; } /*************************************************************************** Return the i'th entry. ***************************************************************************/ long ERS::ErcGet(long ierc) { AssertThis(0); long erc; _mutx.Enter(); if (!::FIn(ierc, 0, _cerd)) erc = ercNil; else erc = _rgerd[ierc].erc; _mutx.Leave(); return erc; } /*************************************************************************** Flush all instances of the given error code from the error stack. ***************************************************************************/ void ERS::Flush(long erc) { AssertThis(0); long ierdSrc, ierdDst; _mutx.Enter(); for (ierdSrc = ierdDst = 0; ierdSrc < _cerd; ierdSrc++) { if (_rgerd[ierdSrc].erc != erc) { if (ierdDst < ierdSrc) _rgerd[ierdDst] = _rgerd[ierdSrc]; ierdDst++; } } _cerd = ierdDst; _mutx.Leave(); } #ifdef DEBUG /*************************************************************************** Assert the error stack is valid. ***************************************************************************/ void ERS::AssertValid(ulong grf) { ERS_PAR::AssertValid(0); AssertIn(_cerd, 0, kcerdMax + 1); } #endif //DEBUG