commands/kerninfo/kerninfo.cpp
changeset 0 7f656887cf89
--- /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 <fshell/ioutils.h>
+#include <fshell/memoryaccesscmd.h>
+#include <fshell/qr3dll.h>
+#include <fshell/ltkutils.h>
+#include <fshell/descriptorutils.h>
+#ifdef FSHELL_SPCRE_SUPPORT
+#include <fshell/pcre/cregex.h>
+#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
+		}
+	}
+