diff -r 000000000000 -r 7f656887cf89 commands/kerninfo/kerninfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/kerninfo/kerninfo.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,226 @@ +// kerninfo.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Accenture - Initial contribution +// + +#include +#include +#include +#include +#include +#ifdef FSHELL_SPCRE_SUPPORT +#include +#endif + +using namespace IoUtils; +class CRegEx; + +class CCmdKerninfo : public CMemoryAccessCommandBase + { +public: + static CCommandBase* NewLC(); + ~CCmdKerninfo(); +private: + CCmdKerninfo(); + TInt InfoL(TInt aIndex, TBool aUseId, TBool aVerbose); + void PrintInfoForL(TInt aIndex, TBool aUseId=EFalse); + static TBool SupportsIds(TKernelObjectType aType); + static void ChompBlankLines(TDes& aDes); + +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual void DoRunL(); + virtual void ArgumentsL(RCommandArgumentList& aArguments); + virtual void OptionsL(RCommandOptionList& aOptions); +private: + TKernelObjectType iType; + TInt iObjectIndex; + TBool iVerbose; + TBool iVerboseMatch; + HBufC* iMatch; + HBufC* iRegexMatch; + + CKernelObjectList* iModel; + RBuf iTitle, iInfo; + LtkUtils::RLtkBuf8 iNarrowBuf; + CRegEx* iRegex; + }; + + +CCommandBase* CCmdKerninfo::NewLC() + { + CCmdKerninfo* self = new(ELeave) CCmdKerninfo(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdKerninfo::~CCmdKerninfo() + { + delete iModel; + iTitle.Close(); + iInfo.Close(); + iNarrowBuf.Close(); + delete iMatch; + delete iRegexMatch; +#ifdef FSHELL_SPCRE_SUPPORT + delete iRegex; +#endif + } + +CCmdKerninfo::CCmdKerninfo() + { + } + +const TDesC& CCmdKerninfo::Name() const + { + _LIT(KName, "kerninfo"); + return KName; + } + +void CCmdKerninfo::ArgumentsL(RCommandArgumentList& aArguments) + { + aArguments.AppendEnumL((TInt&)iType, _L("object-type")); + aArguments.AppendIntL(iObjectIndex, _L("object-index")); + } + +void CCmdKerninfo::OptionsL(RCommandOptionList& aOptions) + { + aOptions.AppendStringL(iMatch, _L("match")); +#ifdef FSHELL_SPCRE_SUPPORT + aOptions.AppendStringL(iRegexMatch, _L("regex-match")); +#endif + aOptions.AppendBoolL(iVerbose, _L("verbose")); + aOptions.AppendBoolL(iVerboseMatch, _L("verbosematch")); + } + +EXE_BOILER_PLATE(CCmdKerninfo) + +void CCmdKerninfo::DoRunL() + { + LoadMemoryAccessL(); + + iModel = CKernelObjectList::NewL(&iMemAccess); + + iModel->SetCurrentType(iType); + TRAPL(iModel->RefreshDataL(), _L("Couldn't get model data")); + + iTitle.CreateL(256); + iInfo.CreateL(256); + +#ifdef FSHELL_SPCRE_SUPPORT + if (iRegexMatch) + { + if (iMatch) LeaveIfErr(KErrArgument, _L("Can't specify both --match and --regex-match, use one or the other")); + iRegex = CRegEx::NewL(*iRegexMatch, TRegExOptions(EPcreExtended|EPcreNewlineAny)); + } +#endif + if (iVerboseMatch) iVerbose = ETrue; // verbosematch implies verbose + + const TInt n = iModel->Count(); + TBool listAll = !iArguments.IsPresent(&iObjectIndex); + if (listAll) + { + for (TInt i = 0; i < n; i++) + { + PrintInfoForL(i); + } + } + else + { + TBool usingId = SupportsIds(iType); + if (!usingId && (iObjectIndex < 0 || iObjectIndex >= n)) + { + LeaveIfErr(KErrArgument, _L("Bad argument %d. Number of objects in this category: %d"), iObjectIndex, n); + } + PrintInfoForL(iObjectIndex, usingId); + } + } + +TInt CCmdKerninfo::InfoL(TInt aIndex, TBool aUseId, TBool aVerbose) + { + TInt err = KErrNone; + TInt itemid = 0; + if (aUseId) + { + TRAP(err, iModel->GetInfoByIdL(aIndex, aVerbose, iTitle, iInfo)); + } + else + { + TRAP(err, itemid = iModel->GetInfoByIndexL(aIndex, aVerbose, iTitle, iInfo)); + } + LeaveIfErr(err, _L("Couldn't get info for item %d"), aIndex); + return itemid; + } + +void CCmdKerninfo::PrintInfoForL(TInt aIndex, TBool aUseId /* =EFalse */) + { + TInt itemid = 0; + + if (iMatch || iRegexMatch) + { + // Filter out anything not matching iMatch/iRegexMatch + // Unless --verbosematch is specified, match on the non-verbose (but display the verbose if specified). This is because calculating the verbose can be really slow so don't do it until we know we match. + itemid = InfoL(aIndex, aUseId, (TBool)iVerboseMatch); + const TDesC& toMatchAgainst = iVerboseMatch ? iInfo : iTitle; + + TBool match = EFalse; + if (iMatch) + { + match = (toMatchAgainst.MatchF(*iMatch) != KErrNotFound); + } +#ifdef FSHELL_SPCRE_SUPPORT + else if (iRegexMatch) + { + iNarrowBuf.Zero(); + iNarrowBuf.AppendL(toMatchAgainst); + match = iRegex->PartialMatchL(iNarrowBuf); + } +#endif + if (!match) return; + } + + if ((!iMatch && !iRegexMatch) || (iVerbose && !iVerboseMatch)) + { + // Need to get info for first time (if !iMatch) or re-get the verbose info (in the case of we just did a match on the non-verbose info) + itemid = InfoL(aIndex, aUseId, iVerbose); + } + + TInt idxToDisplay = (SupportsIds(iType) && !aUseId) ? itemid : aIndex; + if (iVerbose) + { + // In verbose mode the title is always just "Process info" (etc) so no point displaying it + Printf(_L("%d:\n"), idxToDisplay); + ChompBlankLines(iInfo); // When doing a verbose listing (specially multiple ones) it's easier to remove the blank lines that the model adds for readability in the QResources dialog + Write(iInfo); + Write(_L("\n\n")); + } + else + { + Printf(_L("%d: %S\t%S\n"), idxToDisplay, &iTitle, &iInfo); + } + } + +TBool CCmdKerninfo::SupportsIds(TKernelObjectType aType) + { + // These types can (and should) be looked up directly by id and not by index into the list. + return (aType == EListThread || aType == EListProcess || aType == EListHal); + } + +void CCmdKerninfo::ChompBlankLines(TDes& aDes) + { + _LIT(KLfLf, "\n\n"); + TInt found; + while ((found = aDes.Find(KLfLf)) != KErrNotFound) + { + aDes.Delete(found, 1); // Nuke one of the newlines + } + } +