<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MixClient.cpp
 * @author Arkadiy Paronyan arkadiy@ethdev.com
 * @date 2015
 * Ethereum IDE client.
 */

#include "MixClient.h"
#include <vector>
#include <utility>
#include <libdevcore/Exceptions.h>
#include <libethcore/ChainOperationParams.h>
#include <libethcore/BasicAuthority.h>
#include <libethereum/BlockChain.h>
#include <libethereum/Transaction.h>
#include <libethereum/Executive.h>
#include <libethereum/ExtVM.h>
#include <libethereum/BlockChain.h>
#include <libevm/VM.h>
#include "Exceptions.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

namespace dev
{
namespace mix
{

u256 const c_mixGenesisDifficulty = 131072; //TODO: make it lower for Mix somehow

namespace
{
}

MixBlockChain::MixBlockChain(std::string const& _path, AccountMap const& _pre):
	BlockChain(createParams(_pre), _path, WithExisting::Kill)
{
}

ChainParams MixBlockChain::createParams(AccountMap const& _pre)
{
	ChainParams ret;
	ret.accountStartNonce = 0;
	ret.author = Address();
	ret.blockReward = 5000 * ether;
	ret.difficulty = 0;
	ret.gasLimit = 3141592;
	ret.gasUsed = 0;
	ret.genesisState = _pre;
	ret.maximumExtraDataSize = 1024;
	ret.parentHash = h256();
	ret.sealEngineName = "NoProof";
	ret.sealFields = 0;
	ret.timestamp = 0;
	return ret;
}

MixClient::MixClient(std::string const& _dbPath):
	m_preSeal(Block::Null),
	m_postSeal(Block::Null),
	m_dbPath(_dbPath)
{
	resetState(AccountMap());
}

MixClient::~MixClient()
{
}

void MixClient::resetState(std::unordered_map<Address, Account> const& _accounts, Secret const& _miner)
{
	WriteGuard l(x_state);
	Guard fl(x_filtersWatches);

	m_filters.clear();
	for (auto& i: m_specialFilters)
		i.second.clear();
	m_watches.clear();

	m_stateDB = OverlayDB();
	SecureTrieDB<Address, MemoryDB> accountState(&m_stateDB);
	accountState.init();
	dev::eth::commit(_accounts, accountState);

	m_bc.reset();
	m_bc.reset(new MixBlockChain(m_dbPath, _accounts));
	Block b(*m_bc, m_stateDB, BaseState::PreExisting, KeyPair(_miner).address());
	b.sync(bc());
	m_preSeal = b;
	m_postSeal = b;

	DEV_WRITE_GUARDED(x_executions)
		m_executions.clear();
}

Transaction MixClient::replaceGas(Transaction const& _t, u256 const& _gas, Secret const& _secret)
{
	Transaction ret;
	if (_secret)
	{
		if (_t.isCreation())
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret);
		else
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret);
	}
	else
	{
		if (_t.isCreation())
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce());
		else
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce());
		ret.forceSender(_t.safeSender());
	}
	return ret;
}

// TODO: prototype changed - will need rejigging.
ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& _state, EnvInfo const& _envInfo, bool _call)
{
	State execState = _state;
	execState.addBalance(_t.sender(), _t.gas() * _t.gasPrice()); //give it enough balance for gas estimation
	eth::ExecutionResult er;
	Executive execution(execState, _envInfo, m_bc->sealEngine());
	execution.setResultRecipient(er);

	ExecutionResult d;
	d.address = _t.receiveAddress();
	d.sender = _t.sender();
	d.value = _t.value();
	d.inputParameters = _t.data();
	d.executonIndex = m_executions.size();
	if (!_call)
		d.transactionIndex = m_postSeal.pending().size();

	try
	{
		execution.initialize(_t);
		execution.execute();
	}
	catch (Exception const& _e)
	{
		d.excepted = toTransactionException(_e);
		d.transactionData.push_back(_t.data());
		return d;
	}

	std::vector<MachineState> machineStates;
	std::vector<unsigned> levels;
	std::vector<MachineCode> codes;
	std::map<bytes const*, unsigned> codeIndexes;
	std::vector<bytes> data;
	std::map<bytesConstRef const*, unsigned> dataIndexes;
	bytes const* lastCode = nullptr;
	bytesConstRef const* lastData = nullptr;
	unsigned codeIndex = 0;
	unsigned dataIndex = 0;
	auto onOp = [&](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, void* voidVM, void const* voidExt)
	{
		VM& vm = *static_cast<VM*>(voidVM);
		ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
		if (lastCode == nullptr || lastCode != &ext.code)
		{
			auto const& iter = codeIndexes.find(&ext.code);
			if (iter != codeIndexes.end())
				codeIndex = iter->second;
			else
			{
				codeIndex = codes.size();
				codes.push_back(MachineCode({ext.myAddress, ext.code}));
				codeIndexes[&ext.code] = codeIndex;
			}
			lastCode = &ext.code;
		}

		if (lastData == nullptr || lastData != &ext.data)
		{
			auto const& iter = dataIndexes.find(&ext.data);
			if (iter != dataIndexes.end())
				dataIndex = iter->second;
			else
			{
				dataIndex = data.size();
				data.push_back(ext.data.toBytes());
				dataIndexes[&ext.data] = dataIndex;
			}
			lastData = &ext.data;
		}

		if (levels.size() < ext.depth)
			levels.push_back(machineStates.size() - 1);
		else
			levels.resize(ext.depth);

		machineStates.push_back(MachineState{
									steps,
									vm.curPC(),
									inst,
									newMemSize,
									static_cast<u256>(gas),
									vm.stack(),
									vm.memory(),
									gasCost,
									ext.state().storage(ext.myAddress),
									std::move(levels),
									codeIndex,
									dataIndex
								});
	};

	execution.go(onOp);
	execution.finalize();

	d.excepted = er.excepted;
	d.result = er;
	d.machineStates = machineStates;
	d.executionCode = std::move(codes);
	d.transactionData = std::move(data);
	EVMSchedule schedule; // TODO: make relevant to supposed context.
	d.gasUsed = er.gasUsed + er.gasRefunded + schedule.callStipend;
	if (_t.isCreation())
		d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce())));
	return d;
}

void MixClient::executeTransaction(Transaction const& _t, Block& _block, bool _call, bool _gasAuto, Secret const& _secret)
{
	Transaction t = _gasAuto ? replaceGas(_t, m_postSeal.gasLimitRemaining()) : _t;

	// do debugging run first
	EnvInfo envInfo(bc().info(), bc().lastHashes());
	ExecutionResult d = debugTransaction(t, _block.state(), envInfo, _call);

	// execute on a state
	if (!_call && d.excepted == TransactionException::None)
	{
		u256 useGas = min(d.gasUsed, _block.gasLimitRemaining());
		t = _gasAuto ? replaceGas(_t, useGas, _secret) : _t;
		eth::ExecutionResult const& er = _block.execute(envInfo.lastHashes(), t);
		if (t.isCreation() && _block.state().code(d.contractAddress).empty())
			BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment"));
		EVMSchedule schedule;	// TODO: make relevant to supposed context.
		d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit + schedule.callStipend;
		LocalisedLogEntries logs;
		TransactionReceipt const& tr = _block.receipt(_block.pending().size() - 1);

		LogEntries le = tr.log();
		if (le.size())
			for (unsigned j = 0; j < le.size(); ++j)
				logs.insert(logs.begin(), LocalisedLogEntry(le[j]));
		d.logs =  logs;
	}
	WriteGuard l(x_executions);
	m_executions.emplace_back(std::move(d));
}

std::unordered_map<u256, u256> MixClient::contractStorage(Address _contract)
{
	return m_preSeal.state().storage(_contract);
}

void MixClient::mine()
{
	WriteGuard l(x_state);
	NoProof sealer;
	m_postSeal.commitToSeal(bc());
	Notified<bytes> sealed;
	sealer.onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
	sealer.generateSeal(m_postSeal.info());
	m_postSeal.sealBlock(sealed);
	bc().import(m_postSeal.blockData(), m_postSeal.state().db(), (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0);
	m_postSeal.sync(bc());
	m_preSeal = m_postSeal;
}

ExecutionResult MixClient::lastExecution() const
{
	ReadGuard l(x_executions);
	return m_executions.empty() ? ExecutionResult() : m_executions.back();
}

ExecutionResult MixClient::execution(unsigned _index) const
{
	ReadGuard l(x_executions);
	return m_executions.size() > _index ? m_executions.at(_index) : ExecutionResult();
}

Block MixClient::asOf(h256 const& _block) const
{
	ReadGuard l(x_state);
	Block ret(*m_bc, m_stateDB);
	ret.populateFromChain(bc(), _block);
	return ret;
}

pair<h256, Address> MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto)
{
	TransactionSkeleton ts = _ts;
	ts.from = toAddress(_secret);
	ts.nonce = postSeal().transactionsFrom(ts.from);
	if (ts.nonce == Invalid256)
		ts.nonce = max<u256>(postSeal().transactionsFrom(ts.from), m_tq.maxNonce(ts.from));
	if (ts.gasPrice == Invalid256)
		ts.gasPrice = gasBidPrice();
	if (ts.gas == Invalid256)
		ts.gas = min<u256>(gasLimitRemaining() / 5, balanceAt(ts.from) / ts.gasPrice);
	WriteGuard l(x_state);
	eth::Transaction t(ts, _secret);
	executeTransaction(t, m_postSeal, false, _gasAuto, _secret);
	return make_pair(t.sha3(), toAddress(ts.from, ts.nonce));
}

dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff)
{
	(void)_blockNumber;
	Block block = asOf(eth::PendingBlock);
	u256 n = block.transactionsFrom(_from);
	u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas;
	u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
	Transaction t(_value, gasPrice, gas, _dest, _data, n);
	t.forceSender(_from);
	if (_ff == FudgeFactor::Lenient)
		block.mutableState().addBalance(_from, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
	WriteGuard lw(x_state); //TODO: lock is required only for last execution state
	executeTransaction(t, block, true, _gasAuto);
	return lastExecution().result;
}

dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
	return call(_from, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff);
}

dev::eth::ExecutionResult MixClient::create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
	(void)_blockNumber;
	u256 n;
	Block temp(Block::Null);
	{
		ReadGuard lr(x_state);
		temp = asOf(eth::PendingBlock);
		n = temp.transactionsFrom(_from);
	}
	Transaction t(_value, _gasPrice, _gas, _data, n);
	t.forceSender(_from);
	if (_ff == FudgeFactor::Lenient)
		temp.mutableState().addBalance(_from, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
	WriteGuard lw(x_state); //TODO: lock is required only for last execution state
	executeTransaction(t, temp, true, false);
	return lastExecution().result;
}

eth::BlockHeader MixClient::blockInfo() const
{
	ReadGuard l(x_state);
	return BlockHeader(bc().block());
}

void MixClient::setAuthor(Address const& _us)
{
	WriteGuard l(x_state);
	m_postSeal.setAuthor(_us);
}

}
}
<commit_msg>Fixups for new API.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MixClient.cpp
 * @author Arkadiy Paronyan arkadiy@ethdev.com
 * @date 2015
 * Ethereum IDE client.
 */

#include "MixClient.h"
#include <vector>
#include <utility>
#include <libdevcore/Exceptions.h>
#include <libethcore/ChainOperationParams.h>
#include <libethcore/BasicAuthority.h>
#include <libethereum/BlockChain.h>
#include <libethereum/Transaction.h>
#include <libethereum/Executive.h>
#include <libethereum/ExtVM.h>
#include <libethereum/BlockChain.h>
#include <libevm/VM.h>
#include "Exceptions.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

namespace dev
{
namespace mix
{

u256 const c_mixGenesisDifficulty = 131072; //TODO: make it lower for Mix somehow

namespace
{
}

MixBlockChain::MixBlockChain(std::string const& _path, AccountMap const& _pre):
	BlockChain(createParams(_pre), _path, WithExisting::Kill)
{
}

ChainParams MixBlockChain::createParams(AccountMap const& _pre)
{
	ChainParams ret;
	ret.accountStartNonce = 0;
	ret.author = Address();
	ret.blockReward = 5000 * ether;
	ret.difficulty = 0;
	ret.gasLimit = 3141592;
	ret.gasUsed = 0;
	ret.genesisState = _pre;
	ret.maximumExtraDataSize = 1024;
	ret.parentHash = h256();
	ret.sealEngineName = "NoProof";
	ret.sealFields = 0;
	ret.timestamp = 0;
	return ret;
}

MixClient::MixClient(std::string const& _dbPath):
	m_preSeal(Block::Null),
	m_postSeal(Block::Null),
	m_dbPath(_dbPath)
{
	resetState(AccountMap());
}

MixClient::~MixClient()
{
}

void MixClient::resetState(std::unordered_map<Address, Account> const& _accounts, Secret const& _miner)
{
	WriteGuard l(x_state);
	Guard fl(x_filtersWatches);

	m_filters.clear();
	for (auto& i: m_specialFilters)
		i.second.clear();
	m_watches.clear();

	m_stateDB = OverlayDB();
	SecureTrieDB<Address, MemoryDB> accountState(&m_stateDB);
	accountState.init();
	dev::eth::commit(_accounts, accountState);

	m_bc.reset();
	m_bc.reset(new MixBlockChain(m_dbPath, _accounts));
	Block b(*m_bc, m_stateDB, BaseState::PreExisting, KeyPair(_miner).address());
	b.sync(bc());
	m_preSeal = b;
	m_postSeal = b;

	DEV_WRITE_GUARDED(x_executions)
		m_executions.clear();
}

Transaction MixClient::replaceGas(Transaction const& _t, u256 const& _gas, Secret const& _secret)
{
	Transaction ret;
	if (_secret)
	{
		if (_t.isCreation())
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret);
		else
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret);
	}
	else
	{
		if (_t.isCreation())
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce());
		else
			ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce());
		ret.forceSender(_t.safeSender());
	}
	return ret;
}

// TODO: prototype changed - will need rejigging.
ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& _state, EnvInfo const& _envInfo, bool _call)
{
	State execState = _state;
	execState.addBalance(_t.sender(), _t.gas() * _t.gasPrice()); //give it enough balance for gas estimation
	eth::ExecutionResult er;
	Executive execution(execState, _envInfo, m_bc->sealEngine());
	execution.setResultRecipient(er);

	ExecutionResult d;
	d.address = _t.receiveAddress();
	d.sender = _t.sender();
	d.value = _t.value();
	d.inputParameters = _t.data();
	d.executonIndex = m_executions.size();
	if (!_call)
		d.transactionIndex = m_postSeal.pending().size();

	try
	{
		execution.initialize(_t);
		execution.execute();
	}
	catch (Exception const& _e)
	{
		d.excepted = toTransactionException(_e);
		d.transactionData.push_back(_t.data());
		return d;
	}

	std::vector<MachineState> machineStates;
	std::vector<unsigned> levels;
	std::vector<MachineCode> codes;
	std::map<bytes const*, unsigned> codeIndexes;
	std::vector<bytes> data;
	std::map<bytesConstRef const*, unsigned> dataIndexes;
	bytes const* lastCode = nullptr;
	bytesConstRef const* lastData = nullptr;
	unsigned codeIndex = 0;
	unsigned dataIndex = 0;
	auto onOp = [&](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, void* voidVM, void const* voidExt)
	{
		VM& vm = *static_cast<VM*>(voidVM);
		ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
		if (lastCode == nullptr || lastCode != &ext.code)
		{
			auto const& iter = codeIndexes.find(&ext.code);
			if (iter != codeIndexes.end())
				codeIndex = iter->second;
			else
			{
				codeIndex = codes.size();
				codes.push_back(MachineCode({ext.myAddress, ext.code}));
				codeIndexes[&ext.code] = codeIndex;
			}
			lastCode = &ext.code;
		}

		if (lastData == nullptr || lastData != &ext.data)
		{
			auto const& iter = dataIndexes.find(&ext.data);
			if (iter != dataIndexes.end())
				dataIndex = iter->second;
			else
			{
				dataIndex = data.size();
				data.push_back(ext.data.toBytes());
				dataIndexes[&ext.data] = dataIndex;
			}
			lastData = &ext.data;
		}

		if (levels.size() < ext.depth)
			levels.push_back(machineStates.size() - 1);
		else
			levels.resize(ext.depth);

		machineStates.push_back(MachineState{
									steps,
									vm.curPC(),
									inst,
									newMemSize,
									static_cast<u256>(gas),
									vm.stack(),
									vm.memory(),
									gasCost,
									ext.state().storage(ext.myAddress),
									std::move(levels),
									codeIndex,
									dataIndex
								});
	};

	execution.go(onOp);
	execution.finalize();

	d.excepted = er.excepted;
	d.result = er;
	d.machineStates = machineStates;
	d.executionCode = std::move(codes);
	d.transactionData = std::move(data);
	EVMSchedule schedule; // TODO: make relevant to supposed context.
	d.gasUsed = er.gasUsed + er.gasRefunded + schedule.callStipend;
	if (_t.isCreation())
		d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce())));
	return d;
}

void MixClient::executeTransaction(Transaction const& _t, Block& _block, bool _call, bool _gasAuto, Secret const& _secret)
{
	Transaction t = _gasAuto ? replaceGas(_t, m_postSeal.gasLimitRemaining()) : _t;

	// do debugging run first
	EnvInfo envInfo(bc().info(), bc().lastHashes());
	ExecutionResult d = debugTransaction(t, _block.state(), envInfo, _call);

	// execute on a state
	if (!_call && d.excepted == TransactionException::None)
	{
		u256 useGas = min(d.gasUsed, _block.gasLimitRemaining());
		t = _gasAuto ? replaceGas(_t, useGas, _secret) : _t;
		eth::ExecutionResult const& er = _block.execute(envInfo.lastHashes(), t);
		if (t.isCreation() && _block.state().code(d.contractAddress).empty())
			BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment"));
		EVMSchedule schedule;	// TODO: make relevant to supposed context.
		d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit + schedule.callStipend;
		LocalisedLogEntries logs;
		TransactionReceipt const& tr = _block.receipt(_block.pending().size() - 1);

		LogEntries le = tr.log();
		if (le.size())
			for (unsigned j = 0; j < le.size(); ++j)
				logs.insert(logs.begin(), LocalisedLogEntry(le[j]));
		d.logs =  logs;
	}
	WriteGuard l(x_executions);
	m_executions.emplace_back(std::move(d));
}

std::unordered_map<u256, u256> MixClient::contractStorage(Address _contract)
{
	return m_preSeal.state().storage(_contract);
}

void MixClient::mine()
{
	WriteGuard l(x_state);
	NoProof sealer;
	m_postSeal.commitToSeal(bc());
	Notified<bytes> sealed;
	sealer.onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
	sealer.generateSeal(m_postSeal.info());
	m_postSeal.sealBlock(sealed);
	bc().import(m_postSeal.blockData(), m_postSeal.state().db(), (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0);
	m_postSeal.sync(bc());
	m_preSeal = m_postSeal;
}

ExecutionResult MixClient::lastExecution() const
{
	ReadGuard l(x_executions);
	return m_executions.empty() ? ExecutionResult() : m_executions.back();
}

ExecutionResult MixClient::execution(unsigned _index) const
{
	ReadGuard l(x_executions);
	return m_executions.size() > _index ? m_executions.at(_index) : ExecutionResult();
}

Block MixClient::asOf(h256 const& _block) const
{
	ReadGuard l(x_state);
	Block ret(*m_bc, m_stateDB);
	ret.populateFromChain(bc(), _block);
	return ret;
}

pair<h256, Address> MixClient::submitTransaction(eth::TransactionSkeleton const& _ts, Secret const& _secret, bool _gasAuto)
{
	TransactionSkeleton ts = _ts;
	ts.from = toAddress(_secret);
	ts.nonce = postSeal().transactionsFrom(ts.from);
	if (ts.nonce == Invalid256)
		ts.nonce = max<u256>(postSeal().transactionsFrom(ts.from), m_tq.maxNonce(ts.from));
	if (ts.gasPrice == Invalid256)
		ts.gasPrice = gasBidPrice();
	if (ts.gas == Invalid256)
		ts.gas = min<u256>(gasLimitRemaining() / 5, balanceAt(ts.from) / ts.gasPrice);
	WriteGuard l(x_state);
	eth::Transaction t(ts, _secret);
	executeTransaction(t, m_postSeal, false, _gasAuto, _secret);
	return make_pair(t.sha3(), toAddress(ts.from, ts.nonce));
}

dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff)
{
	(void)_blockNumber;
	Block block = asOf(eth::PendingBlock);
	u256 n = block.transactionsFrom(_from);
	u256 gas = _gas == Invalid256 ? gasLimitRemaining() : _gas;
	u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;
	Transaction t(_value, gasPrice, gas, _dest, _data, n);
	t.forceSender(_from);
	if (_ff == FudgeFactor::Lenient)
		block.mutableState().addBalance(_from, (u256)(t.gasRequired(EVMSchedule()) * t.gasPrice() + t.value()));
	WriteGuard lw(x_state); //TODO: lock is required only for last execution state
	executeTransaction(t, block, true, _gasAuto);
	return lastExecution().result;
}

dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
	return call(_from, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff);
}

dev::eth::ExecutionResult MixClient::create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{
	(void)_blockNumber;
	u256 n;
	Block temp(Block::Null);
	{
		ReadGuard lr(x_state);
		temp = asOf(eth::PendingBlock);
		n = temp.transactionsFrom(_from);
	}
	Transaction t(_value, _gasPrice, _gas, _data, n);
	t.forceSender(_from);
	if (_ff == FudgeFactor::Lenient)
		temp.mutableState().addBalance(_from, (u256)(t.gasRequired(EVMSchedule()) * t.gasPrice() + t.value()));
	WriteGuard lw(x_state); //TODO: lock is required only for last execution state
	executeTransaction(t, temp, true, false);
	return lastExecution().result;
}

eth::BlockHeader MixClient::blockInfo() const
{
	ReadGuard l(x_state);
	return BlockHeader(bc().block());
}

void MixClient::setAuthor(Address const& _us)
{
	WriteGuard l(x_state);
	m_postSeal.setAuthor(_us);
}

}
}
<|endoftext|>


<commit_before>/**
 * @file ModeledPR.hpp
 * Class to compute modeled pseudoranges of a mobile receiver
 */

#ifndef GPSTK_MODELEDPR_HPP
#define GPSTK_MODELEDPR_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk 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 Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Dagoberto Salazar - gAGE. 2006
//
//============================================================================

#include "ModeledReferencePR.hpp"
#include "Matrix.hpp"
#include "Bancroft.hpp"
#include "PRSolution.hpp"
#include "DataStructures.hpp"

namespace gpstk
{
      /** @addtogroup GPSsolutions */
      //@{

      /** This class compute modeled pseudoranges from satellites to a mobile receiver.
       *
       * The main difference between this class and ModeledReferencePR is that for a
       * mobile receiver we should "prepare" the computation giving an estimate of
       * the mobile station position. This position may be the last known
       * position or it may be estimated using a method such as Bancroft.
       *
       * Prepare() method is used for this.
       *
       * @sa ModeledPseudorangeBase.hpp and ModeledReferencePR.hpp for base classes.
       *
       */
   class ModeledPR : public ModeledReferencePR
   {
    public:

        /// Implicit constructor
        ModeledPR() : modelPrepared(false) {};

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param Tr            Time of observation
         * @param Satellite     Vector of satellites in view
         * @param Pseudorange   Pseudoranges measured from mobile to satellites
         * @param Eph           Satellites Ephemeris
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const DayTime& Tr, std::vector<SatID>& Satellite, std::vector<double>& Pseudorange, const EphemerisStore& Eph);

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param Tr            Time of observation
         * @param Satellite     Vector of satellites in view
         * @param Pseudorange   Pseudoranges measured from mobile to satellites
         * @param Eph           Satellites Ephemeris
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const DayTime& Tr, const Vector<SatID>& Satellite, const Vector<double>& Pseudorange, const EphemerisStore& Eph)
        {
            int i;
            std::vector<SatID> vSat;
            std::vector<double> vPR;

            // Convert from gpstk::Vector to std::vector
            for (i = 0; i < (int)Satellite.size(); i++)
                vSat.push_back(Satellite[i]);

            for (i = 0; i < (int)Pseudorange.size(); i++)
                vPR.push_back(Pseudorange[i]);

            return Prepare(Tr, vSat, vPR, Eph);

        };

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param gData         GNSS data structure to be used
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(gnssSatTypeValue& gData)
        {
            int i;
            std::vector<SatID> vSat;
            std::vector<double> vPR;
            Vector<SatID> Satellite( gData.getVectorOfSatID() );
            Vector<double> Pseudorange( gData.getVectorOfTypeID( (*this).getDefaultObservable() ) );

            // Convert from gpstk::Vector to std::vector
            for (i = 0; i < (int)Satellite.size(); i++)
                vSat.push_back(Satellite[i]);

            for (i = 0; i < (int)Pseudorange.size(); i++)
                vPR.push_back(Pseudorange[i]);

            return Prepare(gData.header.epoch, vSat, vPR, (*( (*this).getDefaultEphemeris())) );

        };

        /** Method to set the initial (a priori) position of receiver before
         * Compute() method.
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const double& aRx, const double& bRx, const double& cRx,
            Position::CoordinateSystem s=Position::Cartesian,
            GeoidModel *geoid=NULL) throw(GeometryException);

        /** Method to set the initial (a priori) position of receiver before
         * Compute() method.
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const Position& RxCoordinates) throw(GeometryException);

        /// Destructor.
        virtual ~ModeledPR() throw() {};

    protected:

        bool modelPrepared;

   }; // class ModeledPR

   //@}

} // namespace

#endif
<commit_msg>Added new constructors to ModeledPR.<commit_after>/**
 * @file ModeledPR.hpp
 * Class to compute modeled pseudoranges of a mobile receiver
 */

#ifndef GPSTK_MODELEDPR_HPP
#define GPSTK_MODELEDPR_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk 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 Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Dagoberto Salazar - gAGE. 2006
//
//============================================================================

#include "ModeledReferencePR.hpp"
#include "Matrix.hpp"
#include "Bancroft.hpp"
#include "PRSolution.hpp"
#include "DataStructures.hpp"

namespace gpstk
{
      /** @addtogroup GPSsolutions */
      //@{

      /** This class compute modeled pseudoranges from satellites to a mobile receiver.
       *
       * The main difference between this class and ModeledReferencePR is that for a
       * mobile receiver we should "prepare" the computation giving an estimate of
       * the mobile station position. This position may be the last known
       * position or it may be estimated using a method such as Bancroft.
       *
       * Prepare() method is used for this.
       *
       * @sa ModeledPseudorangeBase.hpp and ModeledReferencePR.hpp for base classes.
       *
       */
   class ModeledPR : public ModeledReferencePR
   {
    public:

        /// Implicit constructor
        ModeledPR() : modelPrepared(false) {};

        /** Explicit constructor, taking as input initial receiver coordinates, default
         * ionospheric and tropospheric models, and default observable.
         *
         * @param RxCoordinates Initial receiver coordinates.
         * @param dIonoModel    Ionospheric model to be used by default.
         * @param dTropoModel   Tropospheric model to be used by default.
         * @param dObservable   Observable type to be used by default.
         * @param dEphemeris    EphemerisStore object to be used by default.
         * @param usetgd        Whether TGD will be used by default or not.
         *
         * @sa DataStructures.hpp.
         */
        ModeledPR(const Position& RxCoordinates, IonoModelStore& dIonoModel, TropModel& dTropoModel, EphemerisStore& dEphemeris, const TypeID& dObservable, bool usetgd = true) throw(Exception) {
            InitializeValues();
            setInitialRxPosition(RxCoordinates);
            setDefaultIonoModel(dIonoModel);
            setDefaultTropoModel(dTropoModel);
            setDefaultObservable(dObservable);
            setDefaultEphemeris(dEphemeris);
            useTGD = usetgd;
        };

        /** Explicit constructor, taking as input default ionospheric and tropospheric models, and default observable.
         *
         * @param dIonoModel    Ionospheric model to be used by default.
         * @param dTropoModel   Tropospheric model to be used by default.
         * @param dObservable   Observable type to be used by default.
         * @param dEphemeris    EphemerisStore object to be used by default.
         * @param usetgd        Whether TGD will be used by default or not.
         *
         * @sa DataStructures.hpp.
         */
        ModeledPR(IonoModelStore& dIonoModel, TropModel& dTropoModel, EphemerisStore& dEphemeris, const TypeID& dObservable, bool usetgd = true) throw(Exception) {
            InitializeValues();
            setDefaultIonoModel(dIonoModel);
            setDefaultTropoModel(dTropoModel);
            setDefaultObservable(dObservable);
            setDefaultEphemeris(dEphemeris);
            useTGD = usetgd;
        };

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param Tr            Time of observation
         * @param Satellite     Vector of satellites in view
         * @param Pseudorange   Pseudoranges measured from mobile to satellites
         * @param Eph           Satellites Ephemeris
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const DayTime& Tr, std::vector<SatID>& Satellite, std::vector<double>& Pseudorange, const EphemerisStore& Eph);

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param Tr            Time of observation
         * @param Satellite     Vector of satellites in view
         * @param Pseudorange   Pseudoranges measured from mobile to satellites
         * @param Eph           Satellites Ephemeris
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const DayTime& Tr, const Vector<SatID>& Satellite, const Vector<double>& Pseudorange, const EphemerisStore& Eph)
        {
            int i;
            std::vector<SatID> vSat;
            std::vector<double> vPR;

            // Convert from gpstk::Vector to std::vector
            for (i = 0; i < (int)Satellite.size(); i++)
                vSat.push_back(Satellite[i]);

            for (i = 0; i < (int)Pseudorange.size(); i++)
                vPR.push_back(Pseudorange[i]);

            return Prepare(Tr, vSat, vPR, Eph);

        };

        /** Method to set an a priori position of receiver using Bancroft method.
         *
         * @param gData         GNSS data structure to be used
         *
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(gnssSatTypeValue& gData)
        {
            int i;
            std::vector<SatID> vSat;
            std::vector<double> vPR;
            Vector<SatID> Satellite( gData.getVectorOfSatID() );
            Vector<double> Pseudorange( gData.getVectorOfTypeID( (*this).getDefaultObservable() ) );

            // Convert from gpstk::Vector to std::vector
            for (i = 0; i < (int)Satellite.size(); i++)
                vSat.push_back(Satellite[i]);

            for (i = 0; i < (int)Pseudorange.size(); i++)
                vPR.push_back(Pseudorange[i]);

            return Prepare(gData.header.epoch, vSat, vPR, (*( (*this).getDefaultEphemeris())) );

        };

        /** Method to set the initial (a priori) position of receiver before
         * Compute() method.
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const double& aRx, const double& bRx, const double& cRx,
            Position::CoordinateSystem s=Position::Cartesian,
            GeoidModel *geoid=NULL) throw(GeometryException);

        /** Method to set the initial (a priori) position of receiver before
         * Compute() method.
         * @return
         *  0 if OK
         *  -1 if problems arose
         */
        int Prepare(const Position& RxCoordinates) throw(GeometryException);

        /// Destructor.
        virtual ~ModeledPR() throw() {};

    protected:

        bool modelPrepared;

   }; // class ModeledPR

   //@}

} // namespace

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h>
#endif

#include <chainparams.h>
#include <chainparamsbase.h>
#include <logging.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallettool.h>

#include <functional>
#include <stdio.h>

const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;

static void SetupWalletToolArgs()
{
    SetupHelpOptions(gArgs);
    SetupChainParamsBaseOptions();

    gArgs.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    gArgs.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
    gArgs.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
    gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);

    gArgs.AddArg("info", "Get wallet info", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
    gArgs.AddArg("create", "Create new wallet file", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
}

static bool WalletAppInit(int argc, char* argv[])
{
    SetupWalletToolArgs();
    std::string error_message;
    if (!gArgs.ParseParameters(argc, argv, error_message)) {
        tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message.c_str());
        return false;
    }
    if (argc < 2 || HelpRequested(gArgs)) {
        std::string usage = strprintf("%s syscoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
                                      "wallet-tool is an offline tool for creating and interacting with Syscoin Core wallet files.\n" +
                                      "By default wallet-tool will act on wallets in the default mainnet wallet directory in the datadir.\n" +
                                      "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" +
                                      "Usage:\n" +
                                     "  syscoin-wallet [options] <command>\n\n" +
                                     gArgs.GetHelpMessage();

        tfm::format(std::cout, "%s", usage.c_str());
        return false;
    }

    // check for printtoconsole, allow -debug
    LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", gArgs.GetBoolArg("-debug", false));

    if (!CheckDataDirOption()) {
        tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
        return false;
    }
    // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
    SelectParams(gArgs.GetChainName());

    return true;
}

int main(int argc, char* argv[])
{
#ifdef WIN32
    util::WinCmdLineArgs winArgs;
    std::tie(argc, argv) = winArgs.get();
#endif
    SetupEnvironment();
    RandomInit();
    try {
        if (!WalletAppInit(argc, argv)) return EXIT_FAILURE;
    } catch (const std::exception& e) {
        PrintExceptionContinue(&e, "WalletAppInit()");
        return EXIT_FAILURE;
    } catch (...) {
        PrintExceptionContinue(nullptr, "WalletAppInit()");
        return EXIT_FAILURE;
    }

    std::string method {};
    for(int i = 1; i < argc; ++i) {
        if (!IsSwitchChar(argv[i][0])) {
            if (!method.empty()) {
                tfm::format(std::cerr, "Error: two methods provided (%s and %s). Only one method should be provided.\n", method.c_str(), argv[i]);
                return EXIT_FAILURE;
            }
            method = argv[i];
        }
    }

    if (method.empty()) {
        tfm::format(std::cerr, "No method provided. Run `syscoin-wallet -help` for valid methods.\n");
        return EXIT_FAILURE;
    }

    // A name must be provided when creating a file
    if (method == "create" && !gArgs.IsArgSet("-wallet")) {
        tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
        return EXIT_FAILURE;
    }

    std::string name = gArgs.GetArg("-wallet", "");

    ECCVerifyHandle globalVerifyHandle;
    ECC_Start();
    if (!WalletTool::ExecuteWalletToolFunc(method, name))
        return EXIT_FAILURE;
    ECC_Stop();
    return EXIT_SUCCESS;
}
<commit_msg>bitcoin-wallet: Add a missing closing parenthesis in the help<commit_after>// Copyright (c) 2016-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/syscoin-config.h>
#endif

#include <chainparams.h>
#include <chainparamsbase.h>
#include <logging.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallettool.h>

#include <functional>
#include <stdio.h>

const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;

static void SetupWalletToolArgs()
{
    SetupHelpOptions(gArgs);
    SetupChainParamsBaseOptions();

    gArgs.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    gArgs.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
    gArgs.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
    gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);

    gArgs.AddArg("info", "Get wallet info", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
    gArgs.AddArg("create", "Create new wallet file", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
}

static bool WalletAppInit(int argc, char* argv[])
{
    SetupWalletToolArgs();
    std::string error_message;
    if (!gArgs.ParseParameters(argc, argv, error_message)) {
        tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message.c_str());
        return false;
    }
    if (argc < 2 || HelpRequested(gArgs)) {
        std::string usage = strprintf("%s syscoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
                                      "wallet-tool is an offline tool for creating and interacting with Syscoin Core wallet files.\n" +
                                      "By default wallet-tool will act on wallets in the default mainnet wallet directory in the datadir.\n" +
                                      "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" +
                                      "Usage:\n" +
                                     "  syscoin-wallet [options] <command>\n\n" +
                                     gArgs.GetHelpMessage();

        tfm::format(std::cout, "%s", usage.c_str());
        return false;
    }

    // check for printtoconsole, allow -debug
    LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", gArgs.GetBoolArg("-debug", false));

    if (!CheckDataDirOption()) {
        tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
        return false;
    }
    // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
    SelectParams(gArgs.GetChainName());

    return true;
}

int main(int argc, char* argv[])
{
#ifdef WIN32
    util::WinCmdLineArgs winArgs;
    std::tie(argc, argv) = winArgs.get();
#endif
    SetupEnvironment();
    RandomInit();
    try {
        if (!WalletAppInit(argc, argv)) return EXIT_FAILURE;
    } catch (const std::exception& e) {
        PrintExceptionContinue(&e, "WalletAppInit()");
        return EXIT_FAILURE;
    } catch (...) {
        PrintExceptionContinue(nullptr, "WalletAppInit()");
        return EXIT_FAILURE;
    }

    std::string method {};
    for(int i = 1; i < argc; ++i) {
        if (!IsSwitchChar(argv[i][0])) {
            if (!method.empty()) {
                tfm::format(std::cerr, "Error: two methods provided (%s and %s). Only one method should be provided.\n", method.c_str(), argv[i]);
                return EXIT_FAILURE;
            }
            method = argv[i];
        }
    }

    if (method.empty()) {
        tfm::format(std::cerr, "No method provided. Run `syscoin-wallet -help` for valid methods.\n");
        return EXIT_FAILURE;
    }

    // A name must be provided when creating a file
    if (method == "create" && !gArgs.IsArgSet("-wallet")) {
        tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
        return EXIT_FAILURE;
    }

    std::string name = gArgs.GetArg("-wallet", "");

    ECCVerifyHandle globalVerifyHandle;
    ECC_Start();
    if (!WalletTool::ExecuteWalletToolFunc(method, name))
        return EXIT_FAILURE;
    ECC_Stop();
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <map>

#include "IRVisitor.h"
#include "IRMatch.h"
#include "IREquality.h"
#include "IROperator.h"

namespace Halide {
namespace Internal {

using std::vector;
using std::map;
using std::string;

void expr_match_test() {
    vector<Expr> matches;
    Expr w = Variable::make(Int(32), "*");
    Expr fw = Variable::make(Float(32), "*");
    Expr x = Variable::make(Int(32), "x");
    Expr y = Variable::make(Int(32), "y");
    Expr fx = Variable::make(Float(32), "fx");
    Expr fy = Variable::make(Float(32), "fy");

    Expr vec_wild = Variable::make(Int(32, 4), "*");

    internal_assert(expr_match(w, 3, matches) &&
                    equal(matches[0], 3));

    internal_assert(expr_match(w + 3, (y*2) + 3, matches) &&
                    equal(matches[0], y*2));

    internal_assert(expr_match(fw * 17 + cast<float>(w + cast<int>(fw)),
                               (81.0f * fy) * 17 + cast<float>(x/2 + cast<int>(x + 4.5f)), matches) &&
                    equal(matches[0], 81.0f * fy) &&
                    equal(matches[1], x/2) &&
                    equal(matches[2], x + 4.5f)) << matches[0] << ", " << matches[1] << ", " << matches[2] << "\n";

    internal_assert(!expr_match(fw + 17, fx + 18, matches) &&
                    matches.empty());
    internal_assert(!expr_match((w*2) + 17, fx + 17, matches) &&
                    matches.empty());
    internal_assert(!expr_match(w * 3, 3 * x, matches) &&
                    matches.empty());

    internal_assert(expr_match(vec_wild * 3, Ramp::make(x, y, 4) * 3, matches));

    std::cout << "expr_match test passed" << std::endl;
}

class IRMatch : public IRVisitor {
public:
    bool result;
    vector<Expr> *matches;
    map<string, Expr> *var_matches;
    Expr expr;

    IRMatch(Expr e, vector<Expr> &m) : result(true), matches(&m), var_matches(NULL), expr(e) {
    }
    IRMatch(Expr e, map<string, Expr> &m) : result(true), matches(NULL), var_matches(&m), expr(e) {
    }

    using IRVisitor::visit;

    bool types_match(Type pattern_type, Type expr_type) {
        bool bits_matches  = (pattern_type.bits  == -1) || (pattern_type.bits  == expr_type.bits);
        bool width_matches = (pattern_type.width == -1) || (pattern_type.width == expr_type.width);
        bool code_matches  = (pattern_type.code  == expr_type.code);
        return bits_matches && width_matches && code_matches;
    }

    void visit(const IntImm *op) {
        const IntImm *e = expr.as<IntImm>();
        if (!e ||
            e->value != op->value ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const UIntImm *op) {
        const UIntImm *e = expr.as<UIntImm>();
        if (!e ||
            e->value != op->value ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const FloatImm *op) {
        const FloatImm *e = expr.as<FloatImm>();
        // Note we use uint64_t equality instead of double equality to
        // catch NaNs. We're checking for the same bits.
        if (!e ||
            reinterpret_bits<uint64_t>(e->value) !=
            reinterpret_bits<uint64_t>(op->value) ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const Cast *op) {
        const Cast *e = expr.as<Cast>();
        if (result && e && types_match(op->type, e->type)) {
            expr = e->value;
            op->value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Variable *op) {
        if (!result) {
            return;
        }

        if (!types_match(op->type, expr.type())) {
            result = false;
        } else if (matches) {
            if (op->name == "*") {
                matches->push_back(expr);
            } else {
                const Variable *e = expr.as<Variable>();
                result = e && (e->name == op->name);
            }
        } else if (var_matches) {
            Expr &match = (*var_matches)[op->name];
            if (match.defined()) {
                result = equal(match, expr);
            } else {
                match = expr;
            }
        }
    }

    template<typename T>
    void visit_binary_operator(const T *op) {
        const T *e = expr.as<T>();
        if (result && e) {
            expr = e->a;
            op->a.accept(this);
            expr = e->b;
            op->b.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Add *op) {visit_binary_operator(op);}
    void visit(const Sub *op) {visit_binary_operator(op);}
    void visit(const Mul *op) {visit_binary_operator(op);}
    void visit(const Div *op) {visit_binary_operator(op);}
    void visit(const Mod *op) {visit_binary_operator(op);}
    void visit(const Min *op) {visit_binary_operator(op);}
    void visit(const Max *op) {visit_binary_operator(op);}
    void visit(const EQ *op) {visit_binary_operator(op);}
    void visit(const NE *op) {visit_binary_operator(op);}
    void visit(const LT *op) {visit_binary_operator(op);}
    void visit(const LE *op) {visit_binary_operator(op);}
    void visit(const GT *op) {visit_binary_operator(op);}
    void visit(const GE *op) {visit_binary_operator(op);}
    void visit(const And *op) {visit_binary_operator(op);}
    void visit(const Or *op) {visit_binary_operator(op);}

    void visit(const Not *op) {
        const Not *e = expr.as<Not>();
        if (result && e) {
            expr = e->a;
            op->a.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Select *op) {
        const Select *e = expr.as<Select>();
        if (result && e) {
            expr = e->condition;
            op->condition.accept(this);
            expr = e->true_value;
            op->true_value.accept(this);
            expr = e->false_value;
            op->false_value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Load *op) {
        const Load *e = expr.as<Load>();
        if (result && e && types_match(op->type, e->type) && e->name == op->name) {
            expr = e->index;
            op->index.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Ramp *op) {
        const Ramp *e = expr.as<Ramp>();
        if (result && e && e->width == op->width) {
            expr = e->base;
            op->base.accept(this);
            expr = e->stride;
            op->stride.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Broadcast *op) {
        const Broadcast *e = expr.as<Broadcast>();
        if (result && e && types_match(op->type, e->type)) {
            expr = e->value;
            op->value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Call *op) {
        const Call *e = expr.as<Call>();
        if (result && e &&
            types_match(op->type, e->type) &&
            e->name == op->name &&
            e->value_index == op->value_index &&
            e->call_type == op->call_type &&
            e->args.size() == op->args.size()) {
            for (size_t i = 0; result && (i < e->args.size()); i++) {
                expr = e->args[i];
                op->args[i].accept(this);
            }
        } else {
            result = false;
        }
    }

    void visit(const Let *op) {
        const Let *e = expr.as<Let>();
        if (result && e && e->name == op->name) {
            expr = e->value;
            op->value.accept(this);
            expr = e->body;
            op->body.accept(this);
        } else {
            result = false;
        }
    }
};

bool expr_match(Expr pattern, Expr expr, vector<Expr> &matches) {
    matches.clear();
    if (!pattern.defined() && !expr.defined()) return true;
    if (!pattern.defined() || !expr.defined()) return false;

    IRMatch eq(expr, matches);
    pattern.accept(&eq);
    if (eq.result) {
        return true;
    } else {
        matches.clear();
        return false;
    }
}

bool expr_match(Expr pattern, Expr expr, map<string, Expr> &matches) {
    // Explicitly don't clear matches. This allows usages to pre-match
    // some variables.

    if (!pattern.defined() && !expr.defined()) return true;
    if (!pattern.defined() || !expr.defined()) return false;

    IRMatch eq(expr, matches);
    pattern.accept(&eq);
    if (eq.result) {
        return true;
    } else {
        matches.clear();
        return false;
    }
}

}}
<commit_msg>Fix technical out-of-bounds read in IRMatch test<commit_after>#include <iostream>
#include <map>

#include "IRVisitor.h"
#include "IRMatch.h"
#include "IREquality.h"
#include "IROperator.h"

namespace Halide {
namespace Internal {

using std::vector;
using std::map;
using std::string;

void expr_match_test() {
    vector<Expr> matches;
    Expr w = Variable::make(Int(32), "*");
    Expr fw = Variable::make(Float(32), "*");
    Expr x = Variable::make(Int(32), "x");
    Expr y = Variable::make(Int(32), "y");
    Expr fx = Variable::make(Float(32), "fx");
    Expr fy = Variable::make(Float(32), "fy");

    Expr vec_wild = Variable::make(Int(32, 4), "*");

    internal_assert(expr_match(w, 3, matches) &&
                    equal(matches[0], 3));

    internal_assert(expr_match(w + 3, (y*2) + 3, matches) &&
                    equal(matches[0], y*2));

    internal_assert(expr_match(fw * 17 + cast<float>(w + cast<int>(fw)),
                               (81.0f * fy) * 17 + cast<float>(x/2 + cast<int>(x + 4.5f)), matches) &&
                    matches.size() == 3 &&
                    equal(matches[0], 81.0f * fy) &&
                    equal(matches[1], x/2) &&
                    equal(matches[2], x + 4.5f));

    internal_assert(!expr_match(fw + 17, fx + 18, matches) &&
                    matches.empty());
    internal_assert(!expr_match((w*2) + 17, fx + 17, matches) &&
                    matches.empty());
    internal_assert(!expr_match(w * 3, 3 * x, matches) &&
                    matches.empty());

    internal_assert(expr_match(vec_wild * 3, Ramp::make(x, y, 4) * 3, matches));

    std::cout << "expr_match test passed" << std::endl;
}

class IRMatch : public IRVisitor {
public:
    bool result;
    vector<Expr> *matches;
    map<string, Expr> *var_matches;
    Expr expr;

    IRMatch(Expr e, vector<Expr> &m) : result(true), matches(&m), var_matches(NULL), expr(e) {
    }
    IRMatch(Expr e, map<string, Expr> &m) : result(true), matches(NULL), var_matches(&m), expr(e) {
    }

    using IRVisitor::visit;

    bool types_match(Type pattern_type, Type expr_type) {
        bool bits_matches  = (pattern_type.bits  == -1) || (pattern_type.bits  == expr_type.bits);
        bool width_matches = (pattern_type.width == -1) || (pattern_type.width == expr_type.width);
        bool code_matches  = (pattern_type.code  == expr_type.code);
        return bits_matches && width_matches && code_matches;
    }

    void visit(const IntImm *op) {
        const IntImm *e = expr.as<IntImm>();
        if (!e ||
            e->value != op->value ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const UIntImm *op) {
        const UIntImm *e = expr.as<UIntImm>();
        if (!e ||
            e->value != op->value ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const FloatImm *op) {
        const FloatImm *e = expr.as<FloatImm>();
        // Note we use uint64_t equality instead of double equality to
        // catch NaNs. We're checking for the same bits.
        if (!e ||
            reinterpret_bits<uint64_t>(e->value) !=
            reinterpret_bits<uint64_t>(op->value) ||
            !types_match(op->type, e->type)) {
            result = false;
        }
    }

    void visit(const Cast *op) {
        const Cast *e = expr.as<Cast>();
        if (result && e && types_match(op->type, e->type)) {
            expr = e->value;
            op->value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Variable *op) {
        if (!result) {
            return;
        }

        if (!types_match(op->type, expr.type())) {
            result = false;
        } else if (matches) {
            if (op->name == "*") {
                matches->push_back(expr);
            } else {
                const Variable *e = expr.as<Variable>();
                result = e && (e->name == op->name);
            }
        } else if (var_matches) {
            Expr &match = (*var_matches)[op->name];
            if (match.defined()) {
                result = equal(match, expr);
            } else {
                match = expr;
            }
        }
    }

    template<typename T>
    void visit_binary_operator(const T *op) {
        const T *e = expr.as<T>();
        if (result && e) {
            expr = e->a;
            op->a.accept(this);
            expr = e->b;
            op->b.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Add *op) {visit_binary_operator(op);}
    void visit(const Sub *op) {visit_binary_operator(op);}
    void visit(const Mul *op) {visit_binary_operator(op);}
    void visit(const Div *op) {visit_binary_operator(op);}
    void visit(const Mod *op) {visit_binary_operator(op);}
    void visit(const Min *op) {visit_binary_operator(op);}
    void visit(const Max *op) {visit_binary_operator(op);}
    void visit(const EQ *op) {visit_binary_operator(op);}
    void visit(const NE *op) {visit_binary_operator(op);}
    void visit(const LT *op) {visit_binary_operator(op);}
    void visit(const LE *op) {visit_binary_operator(op);}
    void visit(const GT *op) {visit_binary_operator(op);}
    void visit(const GE *op) {visit_binary_operator(op);}
    void visit(const And *op) {visit_binary_operator(op);}
    void visit(const Or *op) {visit_binary_operator(op);}

    void visit(const Not *op) {
        const Not *e = expr.as<Not>();
        if (result && e) {
            expr = e->a;
            op->a.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Select *op) {
        const Select *e = expr.as<Select>();
        if (result && e) {
            expr = e->condition;
            op->condition.accept(this);
            expr = e->true_value;
            op->true_value.accept(this);
            expr = e->false_value;
            op->false_value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Load *op) {
        const Load *e = expr.as<Load>();
        if (result && e && types_match(op->type, e->type) && e->name == op->name) {
            expr = e->index;
            op->index.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Ramp *op) {
        const Ramp *e = expr.as<Ramp>();
        if (result && e && e->width == op->width) {
            expr = e->base;
            op->base.accept(this);
            expr = e->stride;
            op->stride.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Broadcast *op) {
        const Broadcast *e = expr.as<Broadcast>();
        if (result && e && types_match(op->type, e->type)) {
            expr = e->value;
            op->value.accept(this);
        } else {
            result = false;
        }
    }

    void visit(const Call *op) {
        const Call *e = expr.as<Call>();
        if (result && e &&
            types_match(op->type, e->type) &&
            e->name == op->name &&
            e->value_index == op->value_index &&
            e->call_type == op->call_type &&
            e->args.size() == op->args.size()) {
            for (size_t i = 0; result && (i < e->args.size()); i++) {
                expr = e->args[i];
                op->args[i].accept(this);
            }
        } else {
            result = false;
        }
    }

    void visit(const Let *op) {
        const Let *e = expr.as<Let>();
        if (result && e && e->name == op->name) {
            expr = e->value;
            op->value.accept(this);
            expr = e->body;
            op->body.accept(this);
        } else {
            result = false;
        }
    }
};

bool expr_match(Expr pattern, Expr expr, vector<Expr> &matches) {
    matches.clear();
    if (!pattern.defined() && !expr.defined()) return true;
    if (!pattern.defined() || !expr.defined()) return false;

    IRMatch eq(expr, matches);
    pattern.accept(&eq);
    if (eq.result) {
        return true;
    } else {
        matches.clear();
        return false;
    }
}

bool expr_match(Expr pattern, Expr expr, map<string, Expr> &matches) {
    // Explicitly don't clear matches. This allows usages to pre-match
    // some variables.

    if (!pattern.defined() && !expr.defined()) return true;
    if (!pattern.defined() || !expr.defined()) return false;

    IRMatch eq(expr, matches);
    pattern.accept(&eq);
    if (eq.result) {
        return true;
    } else {
        matches.clear();
        return false;
    }
}

}}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexBaan.cxx
 ** Lexer for Baan.
 ** Based heavily on LexCPP.cxx
 **/
// Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const int  ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	if (initStyle == SCE_BAAN_STRINGEOL)	// Does not leak onto next line
		initStyle = SCE_BAAN_DEFAULT;

	int visibleChars = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_BAAN_OPERATOR) {
			sc.SetState(SCE_BAAN_DEFAULT);
		} else if (sc.state == SCE_BAAN_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD2);
				}
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			} else {
				if (sc.atLineEnd && (sc.chNext != '^')) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			}
		} else if (sc.state == SCE_BAAN_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_COMMENTDOC) {
			if (sc.MatchIgnoreCase("enddllusage")) {
				for (unsigned int i = 0; i < 10; i++){
					sc.Forward();
				}
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_STRING) {
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			} else if ((sc.atLineEnd) && (sc.chNext != '^')) {
				sc.ChangeState(SCE_BAAN_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		}

		if (sc.state == SCE_BAAN_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_BAAN_NUMBER);
			} else if (sc.MatchIgnoreCase("dllusage")){
					sc.SetState(SCE_BAAN_COMMENTDOC);
					do {
						sc.Forward();
					} while ((!sc.atLineEnd) && sc.More());
			} else if (IsAWordStart(sc.ch)) {
					sc.SetState(SCE_BAAN_IDENTIFIER);
			} else if (sc.Match('|')){
					sc.SetState(SCE_BAAN_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_BAAN_STRING);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_BAAN_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while (IsASpace(sc.ch) && sc.More());
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_BAAN_OPERATOR);
			}
		}
		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment &&
			(style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_BAAN_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

const LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc);
<commit_msg>Made LexerModule objects not be const again as that was impairing static linking.<commit_after>// Scintilla source code edit control
/** @file LexBaan.cxx
 ** Lexer for Baan.
 ** Based heavily on LexCPP.cxx
 **/
// Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const int  ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	if (initStyle == SCE_BAAN_STRINGEOL)	// Does not leak onto next line
		initStyle = SCE_BAAN_DEFAULT;

	int visibleChars = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_BAAN_OPERATOR) {
			sc.SetState(SCE_BAAN_DEFAULT);
		} else if (sc.state == SCE_BAAN_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD2);
				}
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			} else {
				if (sc.atLineEnd && (sc.chNext != '^')) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			}
		} else if (sc.state == SCE_BAAN_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_COMMENTDOC) {
			if (sc.MatchIgnoreCase("enddllusage")) {
				for (unsigned int i = 0; i < 10; i++){
					sc.Forward();
				}
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_STRING) {
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			} else if ((sc.atLineEnd) && (sc.chNext != '^')) {
				sc.ChangeState(SCE_BAAN_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		}

		if (sc.state == SCE_BAAN_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_BAAN_NUMBER);
			} else if (sc.MatchIgnoreCase("dllusage")){
					sc.SetState(SCE_BAAN_COMMENTDOC);
					do {
						sc.Forward();
					} while ((!sc.atLineEnd) && sc.More());
			} else if (IsAWordStart(sc.ch)) {
					sc.SetState(SCE_BAAN_IDENTIFIER);
			} else if (sc.Match('|')){
					sc.SetState(SCE_BAAN_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_BAAN_STRING);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_BAAN_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while (IsASpace(sc.ch) && sc.More());
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_BAAN_OPERATOR);
			}
		}
		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment &&
			(style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_BAAN_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc);
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexLisp.cxx
 ** Lexer for Lisp.
 ** Written by Alexey Yutkin.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StyleContext.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define SCE_LISP_CHARACTER 29
#define SCE_LISP_MACRO 30
#define SCE_LISP_MACRO_DISPATCH 31

static inline bool isLispoperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' )
		return true;
	return false;
}

static inline bool isLispwordstart(char ch) {
	return isascii(ch) && ch != ';'  && !isspacechar(ch) && !isLispoperator(ch) &&
		ch != '\n' && ch != '\r' &&  ch != '\"';
}

static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
	PLATFORM_ASSERT(end >= start);
	char s[100];
	unsigned int i;
	bool digit_flag = true;
	for (i = 0; (i < end - start + 1) && (i < 99); i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
		if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
	}
	char chAttr = SCE_LISP_IDENTIFIER;

	if(digit_flag) chAttr = SCE_LISP_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LISP_KEYWORD;
		} else if (keywords_kw.InList(s)) {
			chAttr = SCE_LISP_KEYWORD_KW;
		} else if ((s[0] == '*' && s[i-1] == '*') ||
			   (s[0] == '+' && s[i-1] == '+')) {
			chAttr = SCE_LISP_SPECIAL;
		}
	}
	styler.ColourTo(end, chAttr);
	return;
}

static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords_kw = *keywordlists[1];

	styler.StartAt(startPos);

	int state = initStyle, radix = -1;
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i += 1;
			continue;
		}

		if (state == SCE_LISP_DEFAULT) {
			if (ch == '#') {
				styler.ColourTo(i - 1, state);
				radix = -1;
				state = SCE_LISP_MACRO_DISPATCH;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_IDENTIFIER;
			}
			else if (ch == ';') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_COMMENT;
			}
			else if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
			else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_STRING;
			}
		} else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
			if (!isLispwordstart(ch)) {
				if (state == SCE_LISP_IDENTIFIER) {
					classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
				} else {
					styler.ColourTo(i - 1, state);
				}
				state = SCE_LISP_DEFAULT;
			} /*else*/
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else if (state == SCE_LISP_MACRO_DISPATCH) {
			if (!isdigit(ch)) {
				if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
					state = SCE_LISP_DEFAULT;
				} else {
					switch (ch) {
						case '|': state = SCE_LISP_MULTI_COMMENT; break;
						case 'o':
						case 'O': radix = 8; state = SCE_LISP_MACRO; break;
						case 'x':
						case 'X': radix = 16; state = SCE_LISP_MACRO; break;
						case 'b':
						case 'B': radix = 2; state = SCE_LISP_MACRO; break;
						case '\\': state = SCE_LISP_CHARACTER; break;
						case ':':
						case '-':
						case '+': state = SCE_LISP_MACRO; break;
						case '\'': if (isLispwordstart(chNext)) {
								   state = SCE_LISP_SPECIAL;
							   } else {
								   styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								   styler.ColourTo(i, SCE_LISP_OPERATOR);
								   state = SCE_LISP_DEFAULT;
							   }
							   break;
						default: if (isLispoperator(ch)) {
								 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								 styler.ColourTo(i, SCE_LISP_OPERATOR);
							 }
							 state = SCE_LISP_DEFAULT;
							 break;
					}
				}
			}
		} else if (state == SCE_LISP_MACRO) {
			if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_CHARACTER) {
			if (isLispoperator(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_DEFAULT;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_SPECIAL) {
			if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_DEFAULT;
			}
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else {
			if (state == SCE_LISP_COMMENT) {
				if (atEOL) {
					styler.ColourTo(i - 1, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_MULTI_COMMENT) {
				if (ch == '|' && chNext == '#') {
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			}
		}

	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LISP_OPERATOR) {
			if (ch == '(') {
				levelCurrent++;
			} else if (ch == ')') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const lispWordListDesc[] = {
	"Functions and special operators",
	"Keywords",
	0
};

LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);
<commit_msg>Feature request #2794901 LexLisp: Colourise keyword arguments as symbols from Eric Kidd.<commit_after>// Scintilla source code edit control
/** @file LexLisp.cxx
 ** Lexer for Lisp.
 ** Written by Alexey Yutkin.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StyleContext.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define SCE_LISP_CHARACTER 29
#define SCE_LISP_MACRO 30
#define SCE_LISP_MACRO_DISPATCH 31

static inline bool isLispoperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' )
		return true;
	return false;
}

static inline bool isLispwordstart(char ch) {
	return isascii(ch) && ch != ';'  && !isspacechar(ch) && !isLispoperator(ch) &&
		ch != '\n' && ch != '\r' &&  ch != '\"';
}

static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
	PLATFORM_ASSERT(end >= start);
	char s[100];
	unsigned int i;
	bool digit_flag = true;
	for (i = 0; (i < end - start + 1) && (i < 99); i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
		if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
	}
	char chAttr = SCE_LISP_IDENTIFIER;

	if(digit_flag) chAttr = SCE_LISP_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LISP_KEYWORD;
		} else if (keywords_kw.InList(s)) {
			chAttr = SCE_LISP_KEYWORD_KW;
		} else if ((s[0] == '*' && s[i-1] == '*') ||
			   (s[0] == '+' && s[i-1] == '+')) {
			chAttr = SCE_LISP_SPECIAL;
		}
	}
	styler.ColourTo(end, chAttr);
	return;
}

static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords_kw = *keywordlists[1];

	styler.StartAt(startPos);

	int state = initStyle, radix = -1;
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i += 1;
			continue;
		}

		if (state == SCE_LISP_DEFAULT) {
			if (ch == '#') {
				styler.ColourTo(i - 1, state);
				radix = -1;
				state = SCE_LISP_MACRO_DISPATCH;
			} else if (ch == ':' && isLispwordstart(chNext)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_SYMBOL;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_IDENTIFIER;
			}
			else if (ch == ';') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_COMMENT;
			}
			else if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
			else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_STRING;
			}
		} else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
			if (!isLispwordstart(ch)) {
				if (state == SCE_LISP_IDENTIFIER) {
					classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
				} else {
					styler.ColourTo(i - 1, state);
				}
				state = SCE_LISP_DEFAULT;
			} /*else*/
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else if (state == SCE_LISP_MACRO_DISPATCH) {
			if (!isdigit(ch)) {
				if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
					state = SCE_LISP_DEFAULT;
				} else {
					switch (ch) {
						case '|': state = SCE_LISP_MULTI_COMMENT; break;
						case 'o':
						case 'O': radix = 8; state = SCE_LISP_MACRO; break;
						case 'x':
						case 'X': radix = 16; state = SCE_LISP_MACRO; break;
						case 'b':
						case 'B': radix = 2; state = SCE_LISP_MACRO; break;
						case '\\': state = SCE_LISP_CHARACTER; break;
						case ':':
						case '-':
						case '+': state = SCE_LISP_MACRO; break;
						case '\'': if (isLispwordstart(chNext)) {
								   state = SCE_LISP_SPECIAL;
							   } else {
								   styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								   styler.ColourTo(i, SCE_LISP_OPERATOR);
								   state = SCE_LISP_DEFAULT;
							   }
							   break;
						default: if (isLispoperator(ch)) {
								 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								 styler.ColourTo(i, SCE_LISP_OPERATOR);
							 }
							 state = SCE_LISP_DEFAULT;
							 break;
					}
				}
			}
		} else if (state == SCE_LISP_MACRO) {
			if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_CHARACTER) {
			if (isLispoperator(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_DEFAULT;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_SPECIAL) {
			if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_DEFAULT;
			}
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else {
			if (state == SCE_LISP_COMMENT) {
				if (atEOL) {
					styler.ColourTo(i - 1, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_MULTI_COMMENT) {
				if (ch == '|' && chNext == '#') {
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			}
		}

	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LISP_OPERATOR) {
			if (ch == '(') {
				levelCurrent++;
			} else if (ch == ')') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const lispWordListDesc[] = {
	"Functions and special operators",
	"Keywords",
	0
};

LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);
<|endoftext|>


<commit_before>#include "Common.h"
#include "Logging.h"

#include <stdarg.h>

VINYL_NS_BEGIN;

namespace Log
{
	FormatVarInt::FormatVarInt(int i)
	{
		m_value = i;
	}

	FormatVarInt::~FormatVarInt()
	{
		if (m_cache != nullptr) {
			delete m_cache;
		}
	}

	const char* FormatVarInt::GetString()
	{
		if (m_cache != nullptr) {
			delete m_cache;
		}
		m_cache = (char*)malloc(14);
		snprintf(m_cache, 14, "%d", m_value);
		return m_cache;
	}

	FormatVarString::FormatVarString(const char* str)
	{
		m_value = str;
	}

	const char* FormatVarString::GetString()
	{
		return m_value;
	}

	s::String Format(const char* format, va_list vl)
	{
		s::StackArray<FormatVar> vars;
		vars.sa_bOnlyPop = true;

		int numHighest = 0;

		int bufferLen = 128;
		s::String ret;

		int len = strlen(format);
		for (int i = 0; i < len; i++) {
			char c = format[i];
			if (c == '%') {
				char cn = format[++i];
				char str[5];
				int strc = 0;
				while (cn >= '0' && cn <= '9' && strc < 4 && i < len) {
					str[strc] = cn;
					strc++;
					cn = format[++i];
				}
				i--;
				str[strc] = '\0';
				int num = atoi(str);
				if (num == 0) {
					continue;
				}
				if (num > numHighest) {
					for (int j = numHighest; j < num; j++) {
						FormatVar &newvar = va_arg(vl, FormatVar);
						vars.Push(&newvar);
					}
					numHighest = num;
				}
				FormatVar &var = vars[num - 1];
				ret += var.GetString();
				continue;
			}

			ret += c;
		}

		return ret;
	}

	LogLevel Level = LogLevel_Info;

	static s::Mutex _mutex;

	void Trace(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 8);
		printf("[TRACE] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[02m[TRACE]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Debug(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		printf("[DEBUG] %s\n", (const char*)str);

		_mutex.Unlock();
	}

	void Info(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 15);
		printf("[INFO] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[38m[INFO]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Warning(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 13);
		printf("[WARNING] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[35m[WARNING]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Error(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 14);
		printf("[ERROR] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[33m[ERROR]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Fatal(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 12);
		printf("[FATAL] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[31m[FATAL]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}
}

VINYL_NS_END;
<commit_msg>Real white<commit_after>#include "Common.h"
#include "Logging.h"

#include <stdarg.h>

VINYL_NS_BEGIN;

namespace Log
{
	FormatVarInt::FormatVarInt(int i)
	{
		m_value = i;
	}

	FormatVarInt::~FormatVarInt()
	{
		if (m_cache != nullptr) {
			delete m_cache;
		}
	}

	const char* FormatVarInt::GetString()
	{
		if (m_cache != nullptr) {
			delete m_cache;
		}
		m_cache = (char*)malloc(14);
		snprintf(m_cache, 14, "%d", m_value);
		return m_cache;
	}

	FormatVarString::FormatVarString(const char* str)
	{
		m_value = str;
	}

	const char* FormatVarString::GetString()
	{
		return m_value;
	}

	s::String Format(const char* format, va_list vl)
	{
		s::StackArray<FormatVar> vars;
		vars.sa_bOnlyPop = true;

		int numHighest = 0;

		int bufferLen = 128;
		s::String ret;

		int len = strlen(format);
		for (int i = 0; i < len; i++) {
			char c = format[i];
			if (c == '%') {
				char cn = format[++i];
				char str[5];
				int strc = 0;
				while (cn >= '0' && cn <= '9' && strc < 4 && i < len) {
					str[strc] = cn;
					strc++;
					cn = format[++i];
				}
				i--;
				str[strc] = '\0';
				int num = atoi(str);
				if (num == 0) {
					continue;
				}
				if (num > numHighest) {
					for (int j = numHighest; j < num; j++) {
						FormatVar &newvar = va_arg(vl, FormatVar);
						vars.Push(&newvar);
					}
					numHighest = num;
				}
				FormatVar &var = vars[num - 1];
				ret += var.GetString();
				continue;
			}

			ret += c;
		}

		return ret;
	}

	LogLevel Level = LogLevel_Info;

	static s::Mutex _mutex;

	void Trace(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 8);
		printf("[TRACE] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[02m[TRACE]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Debug(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		printf("[DEBUG] %s\n", (const char*)str);

		_mutex.Unlock();
	}

	void Info(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 15);
		printf("[INFO] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[37m[INFO]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Warning(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 13);
		printf("[WARNING] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[35m[WARNING]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Error(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 14);
		printf("[ERROR] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[33m[ERROR]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Fatal(const char* format, ...)
	{
		_mutex.Lock();

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, 12);
		printf("[FATAL] ");
		SetConsoleTextAttribute(hConsole, 7);
		printf("%s\n", (const char*)str);
#else
		printf("\x1B[31m[FATAL]\x1B[0m %s\n", (const char*)str);
#endif

		_mutex.Unlock();
	}
}

VINYL_NS_END;
<|endoftext|>