Source

gb_emulator / gb_debugger_msvs / expression_context.cpp

/*  Copyright Š 2011 Chris Spencer <spencercw@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "stdafx.h"

#include "expression_context.h"

#include <string>

#include "expression.h"

using std::wstring;

// IDebugExpressionContext2 methods

HRESULT CExpressionContext::GetName(BSTR * /*pbstrName*/)
{
	return E_NOTIMPL;
}

HRESULT CExpressionContext::ParseText(
	const OLECHAR *pszCode,
	PARSEFLAGS dwFlags,
	UINT nRadix,
	IDebugExpression2 **ppExpr,
	BSTR *pbstrError,
	UINT *pichError)
{
	// Check the arguments
	if (!pszCode || !ppExpr || !pbstrError || !pichError)
	{
		return E_POINTER;
	}
	*ppExpr = NULL;
	*pbstrError = NULL;
	*pichError = 0;

	if (nRadix != 10)
	{
		return E_INVALIDARG;
	}
	if (dwFlags != PARSE_EXPRESSION)
	{
		return E_NOTIMPL;
	}

	// Check the string is not empty
	wstring str(pszCode);
	if (str.empty())
	{
		*pbstrError = SysAllocString(L"Expression is empty.");
		return E_INVALIDARG;
	}

	// Determine if the value is an integer
	CExpression::Type type = CExpression::INTEGER;
	bool isHex = false;
	if (str.substr(0, 2) == L"0x")
	{
		isHex = true;
		str = str.substr(2);
	}

	const wchar_t *validChars;
	if (isHex)
	{
		validChars = L"0123456789abcdefABCDEF";
	}
	else
	{
		validChars = L"0123456789";
	}
	size_t index = str.find_first_not_of(validChars);
	if (index != wstring::npos)
	{
		// Invalid integer charaters; check if it could be a variable
		bool isAddressOf = false;
		if (str[0] == '&')
		{
			isAddressOf = true;
			str = str.substr(1);
		}

		static const wstring validStartChars =
			L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
		validChars = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";

		if ((index = validStartChars.find(str[0])) == wstring::npos ||
			(index = str.find_first_not_of(validChars, 1)) != wstring::npos)
		{
			*pbstrError = SysAllocString(L"Expression contains invalid characters.");
			*pichError = static_cast<UINT>(index);
			return E_INVALIDARG;
		}

		type = isAddressOf ? CExpression::VARIABLE_ADDRESS : CExpression::VARIABLE;
	}

	// Create the expression object
	CComObject<CExpression> *expression;
	CComObject<CExpression>::CreateInstance(&expression);
	expression->AddRef();
	expression->Init(frame_, type, str, isHex);

	*ppExpr = expression;
	return S_OK;
}

// CExpressionContext methods

void CExpressionContext::Init(shared_ptr<GbStackFrame> frame)
{
	frame_ = frame;
}