Browse Source
Conflicts: libethereum/Executive.cpp libethereum/Executive.h libethereum/State.cpp libevm/VM.cpp libevm/VM.h libevm/VMFace.h test/createRandomTest.cpp test/vm.cpp windows/LibEthereum.vcxproj.filterscl-refactor
Paweł Bylica
10 years ago
91 changed files with 5254 additions and 1613 deletions
@ -1,28 +0,0 @@ |
|||
#include <libevm/VM.h> |
|||
|
|||
#if ETH_EVMJIT |
|||
#include<evmjit/libevmjit-cpp/JitVM.h> |
|||
#endif |
|||
|
|||
#include "VMFactory.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
std::unique_ptr<VMFace> VMFactory::create(VMFactory::Kind _kind, u256 _gas) |
|||
{ |
|||
#if ETH_EVMJIT |
|||
auto vm = _kind == Kind::JIT ? static_cast<VMFace*>(new JitVM) |
|||
: static_cast<VMFace*>(new VM); |
|||
#else |
|||
VMFace* vm = new VM; |
|||
#endif |
|||
|
|||
vm->reset(_gas); |
|||
return std::unique_ptr<VMFace>(vm); |
|||
} |
|||
|
|||
} |
|||
} |
@ -1,28 +0,0 @@ |
|||
#pragma once |
|||
|
|||
#include <libevm/VMFace.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
/**
|
|||
*/ |
|||
|
|||
class VMFactory |
|||
{ |
|||
public: |
|||
enum Kind: bool { |
|||
Interpreter, |
|||
#if ETH_EVMJIT |
|||
JIT |
|||
#endif |
|||
}; |
|||
|
|||
static std::unique_ptr<VMFace> create(Kind, u256 _gas = 0); |
|||
}; |
|||
|
|||
|
|||
} |
|||
} |
@ -0,0 +1,45 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
|
|||
#include "VMFactory.h" |
|||
#include "VM.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
namespace |
|||
{ |
|||
VMKind g_kind = VMKind::Interpreter; |
|||
} |
|||
|
|||
void VMFactory::setKind(VMKind _kind) |
|||
{ |
|||
g_kind = _kind; |
|||
} |
|||
|
|||
std::unique_ptr<VMFace> VMFactory::create(u256 _gas) |
|||
{ |
|||
asserts(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); |
|||
return std::unique_ptr<VMFace>(new VM(_gas)); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,187 @@ |
|||
/*
|
|||
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 Network.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @author Eric Lombrozo <elombrozo@gmail.com> (Windows version of getInterfaceAddresses()) |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include <sys/types.h> |
|||
#ifndef _WIN32 |
|||
#include <ifaddrs.h> |
|||
#endif |
|||
|
|||
#include <boost/algorithm/string.hpp> |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/CommonIO.h> |
|||
#include <libethcore/Exceptions.h> |
|||
#include "Common.h" |
|||
#include "UPnP.h" |
|||
#include "Network.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::p2p; |
|||
|
|||
std::vector<bi::address> Network::getInterfaceAddresses() |
|||
{ |
|||
std::vector<bi::address> addresses; |
|||
|
|||
#ifdef _WIN32 |
|||
WSAData wsaData; |
|||
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) |
|||
BOOST_THROW_EXCEPTION(NoNetworking()); |
|||
|
|||
char ac[80]; |
|||
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) |
|||
{ |
|||
clog(NetWarn) << "Error " << WSAGetLastError() << " when getting local host name."; |
|||
WSACleanup(); |
|||
BOOST_THROW_EXCEPTION(NoNetworking()); |
|||
} |
|||
|
|||
struct hostent* phe = gethostbyname(ac); |
|||
if (phe == 0) |
|||
{ |
|||
clog(NetWarn) << "Bad host lookup."; |
|||
WSACleanup(); |
|||
BOOST_THROW_EXCEPTION(NoNetworking()); |
|||
} |
|||
|
|||
for (int i = 0; phe->h_addr_list[i] != 0; ++i) |
|||
{ |
|||
struct in_addr addr; |
|||
memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); |
|||
char *addrStr = inet_ntoa(addr); |
|||
bi::address address(bi::address::from_string(addrStr)); |
|||
if (!isLocalHostAddress(address)) |
|||
addresses.push_back(address.to_v4()); |
|||
} |
|||
|
|||
WSACleanup(); |
|||
#else |
|||
ifaddrs* ifaddr; |
|||
if (getifaddrs(&ifaddr) == -1) |
|||
BOOST_THROW_EXCEPTION(NoNetworking()); |
|||
|
|||
for (auto ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) |
|||
{ |
|||
if (!ifa->ifa_addr || string(ifa->ifa_name) == "lo0") |
|||
continue; |
|||
|
|||
if (ifa->ifa_addr->sa_family == AF_INET) |
|||
{ |
|||
in_addr addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; |
|||
boost::asio::ip::address_v4 address(boost::asio::detail::socket_ops::network_to_host_long(addr.s_addr)); |
|||
if (!isLocalHostAddress(address)) |
|||
addresses.push_back(address); |
|||
} |
|||
else if (ifa->ifa_addr->sa_family == AF_INET6) |
|||
{ |
|||
sockaddr_in6* sockaddr = ((struct sockaddr_in6 *)ifa->ifa_addr); |
|||
in6_addr addr = sockaddr->sin6_addr; |
|||
boost::asio::ip::address_v6::bytes_type bytes; |
|||
memcpy(&bytes[0], addr.s6_addr, 16); |
|||
boost::asio::ip::address_v6 address(bytes, sockaddr->sin6_scope_id); |
|||
if (!isLocalHostAddress(address)) |
|||
addresses.push_back(address); |
|||
} |
|||
} |
|||
|
|||
if (ifaddr!=NULL) |
|||
freeifaddrs(ifaddr); |
|||
|
|||
#endif |
|||
|
|||
return std::move(addresses); |
|||
} |
|||
|
|||
int Network::listen4(bi::tcp::acceptor& _acceptor, unsigned short _listenPort) |
|||
{ |
|||
int retport = -1; |
|||
for (unsigned i = 0; i < 2; ++i) |
|||
{ |
|||
// try to connect w/listenPort, else attempt net-allocated port
|
|||
bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : _listenPort); |
|||
try |
|||
{ |
|||
_acceptor.open(endpoint.protocol()); |
|||
_acceptor.set_option(ba::socket_base::reuse_address(true)); |
|||
_acceptor.bind(endpoint); |
|||
_acceptor.listen(); |
|||
retport = _acceptor.local_endpoint().port(); |
|||
break; |
|||
} |
|||
catch (...) |
|||
{ |
|||
if (i) |
|||
{ |
|||
// both attempts failed
|
|||
cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information(); |
|||
} |
|||
|
|||
// first attempt failed
|
|||
_acceptor.close(); |
|||
continue; |
|||
} |
|||
} |
|||
return retport; |
|||
} |
|||
|
|||
bi::tcp::endpoint Network::traverseNAT(std::vector<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr) |
|||
{ |
|||
asserts(_listenPort != 0); |
|||
|
|||
UPnP* upnp = nullptr; |
|||
try |
|||
{ |
|||
upnp = new UPnP; |
|||
} |
|||
// let m_upnp continue as null - we handle it properly.
|
|||
catch (NoUPnPDevice) {} |
|||
|
|||
bi::tcp::endpoint upnpep; |
|||
if (upnp && upnp->isValid()) |
|||
{ |
|||
bi::address paddr; |
|||
int extPort = 0; |
|||
for (auto const& addr: _ifAddresses) |
|||
if (addr.is_v4() && isPrivateAddress(addr) && (extPort = upnp->addRedirect(addr.to_string().c_str(), _listenPort))) |
|||
{ |
|||
paddr = addr; |
|||
break; |
|||
} |
|||
|
|||
auto eip = upnp->externalIP(); |
|||
bi::address eipaddr(bi::address::from_string(eip)); |
|||
if (extPort && eip != string("0.0.0.0") && !isPrivateAddress(eipaddr)) |
|||
{ |
|||
clog(NetNote) << "Punched through NAT and mapped local port" << _listenPort << "onto external port" << extPort << "."; |
|||
clog(NetNote) << "External addr:" << eip; |
|||
o_upnpifaddr = paddr; |
|||
upnpep = bi::tcp::endpoint(eipaddr, (unsigned short)extPort); |
|||
} |
|||
else |
|||
clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place)."; |
|||
|
|||
if (upnp) |
|||
delete upnp; |
|||
} |
|||
|
|||
return upnpep; |
|||
} |
@ -0,0 +1,63 @@ |
|||
/*
|
|||
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 Network.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
namespace ba = boost::asio; |
|||
namespace bi = ba::ip; |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
namespace p2p |
|||
{ |
|||
|
|||
struct NetworkPreferences |
|||
{ |
|||
NetworkPreferences(unsigned short p = 30303, std::string i = std::string(), bool u = true, bool l = false): listenPort(p), publicIP(i), upnp(u), localNetworking(l) {} |
|||
|
|||
unsigned short listenPort = 30303; |
|||
std::string publicIP; |
|||
bool upnp = true; |
|||
bool localNetworking = false; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Network Class |
|||
* Static network operations and interface(s). |
|||
*/ |
|||
class Network |
|||
{ |
|||
public: |
|||
/// @returns public and private interface addresses
|
|||
static std::vector<bi::address> getInterfaceAddresses(); |
|||
|
|||
/// Try to bind and listen on _listenPort, else attempt net-allocated port.
|
|||
static int listen4(bi::tcp::acceptor& _acceptor, unsigned short _listenPort); |
|||
|
|||
/// Return public endpoint of upnp interface. If successful o_upnpifaddr will be a private interface address and endpoint will contain public address and port.
|
|||
static bi::tcp::endpoint traverseNAT(std::vector<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr); |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,493 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Implementation of the accept functions of AST nodes, included by AST.cpp to not clutter that |
|||
* file with these mechanical implementations. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libsolidity/AST.h> |
|||
#include <libsolidity/ASTVisitor.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
void SourceUnit::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_nodes, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void SourceUnit::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_nodes, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ImportDirective::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ImportDirective::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ContractDefinition::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
listAccept(m_definedStructs, _visitor); |
|||
listAccept(m_stateVariables, _visitor); |
|||
listAccept(m_definedFunctions, _visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ContractDefinition::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
listAccept(m_definedStructs, _visitor); |
|||
listAccept(m_stateVariables, _visitor); |
|||
listAccept(m_definedFunctions, _visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void StructDefinition::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_members, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void StructDefinition::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_members, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void StructDefinition::checkValidityOfMembers() const |
|||
{ |
|||
checkMemberTypes(); |
|||
checkRecursion(); |
|||
} |
|||
|
|||
void ParameterList::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_parameters, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ParameterList::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_parameters, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void FunctionDefinition::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_parameters->accept(_visitor); |
|||
if (m_returnParameters) |
|||
m_returnParameters->accept(_visitor); |
|||
m_body->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void FunctionDefinition::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_parameters->accept(_visitor); |
|||
if (m_returnParameters) |
|||
m_returnParameters->accept(_visitor); |
|||
m_body->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void VariableDeclaration::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_typeName) |
|||
m_typeName->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void VariableDeclaration::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_typeName) |
|||
m_typeName->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void TypeName::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void TypeName::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ElementaryTypeName::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ElementaryTypeName::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void UserDefinedTypeName::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void UserDefinedTypeName::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Mapping::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_keyType->accept(_visitor); |
|||
m_valueType->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Mapping::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_keyType->accept(_visitor); |
|||
m_valueType->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Block::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_statements, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Block::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
listAccept(m_statements, _visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void IfStatement::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_condition->accept(_visitor); |
|||
m_trueBody->accept(_visitor); |
|||
if (m_falseBody) |
|||
m_falseBody->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void IfStatement::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_condition->accept(_visitor); |
|||
m_trueBody->accept(_visitor); |
|||
if (m_falseBody) |
|||
m_falseBody->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void WhileStatement::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_condition->accept(_visitor); |
|||
m_body->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void WhileStatement::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_condition->accept(_visitor); |
|||
m_body->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Continue::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Continue::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Break::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Break::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Return::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_expression) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Return::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_expression) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ExpressionStatement::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_expression) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ExpressionStatement::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
if (m_expression) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void VariableDefinition::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_variable->accept(_visitor); |
|||
if (m_value) |
|||
m_value->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void VariableDefinition::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_variable->accept(_visitor); |
|||
if (m_value) |
|||
m_value->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Assignment::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_leftHandSide->accept(_visitor); |
|||
m_rightHandSide->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Assignment::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_leftHandSide->accept(_visitor); |
|||
m_rightHandSide->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void UnaryOperation::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
m_subExpression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void UnaryOperation::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
m_subExpression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void BinaryOperation::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_left->accept(_visitor); |
|||
m_right->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void BinaryOperation::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_left->accept(_visitor); |
|||
m_right->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void FunctionCall::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_expression->accept(_visitor); |
|||
listAccept(m_arguments, _visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void FunctionCall::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_expression->accept(_visitor); |
|||
listAccept(m_arguments, _visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void MemberAccess::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void MemberAccess::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
m_expression->accept(_visitor); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void IndexAccess::accept(ASTVisitor& _visitor) |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_base->accept(_visitor); |
|||
m_index->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void IndexAccess::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
if (_visitor.visit(*this)) |
|||
{ |
|||
m_base->accept(_visitor); |
|||
m_index->accept(_visitor); |
|||
} |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Identifier::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Identifier::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ElementaryTypeNameExpression::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void ElementaryTypeNameExpression::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Literal::accept(ASTVisitor& _visitor) |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
void Literal::accept(ASTConstVisitor& _visitor) const |
|||
{ |
|||
_visitor.visit(*this); |
|||
_visitor.endVisit(*this); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,71 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Routines used by both the compiler and the expression compiler. |
|||
*/ |
|||
|
|||
#include <libsolidity/CompilerUtils.h> |
|||
#include <libsolidity/AST.h> |
|||
#include <libevmcore/Instruction.h> |
|||
|
|||
using namespace std; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable) |
|||
{ |
|||
unsigned const stackPosition = m_context.baseToCurrentStackOffset(m_context.getBaseStackOffsetOfVariable(_variable)); |
|||
unsigned const size = _variable.getType()->getSizeOnStack(); |
|||
// move variable starting from its top end in the stack
|
|||
if (stackPosition - size + 1 > 16) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_variable.getLocation()) |
|||
<< errinfo_comment("Stack too deep.")); |
|||
for (unsigned i = 0; i < size; ++i) |
|||
m_context << eth::swapInstruction(stackPosition - size + 1) << eth::Instruction::POP; |
|||
} |
|||
|
|||
void CompilerUtils::copyToStackTop(unsigned _stackDepth, Type const& _type) |
|||
{ |
|||
if (_stackDepth > 16) |
|||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Stack too deep.")); |
|||
unsigned const size = _type.getSizeOnStack(); |
|||
for (unsigned i = 0; i < size; ++i) |
|||
m_context << eth::dupInstruction(_stackDepth); |
|||
} |
|||
|
|||
void CompilerUtils::popStackElement(Type const& _type) |
|||
{ |
|||
unsigned const size = _type.getSizeOnStack(); |
|||
for (unsigned i = 0; i < size; ++i) |
|||
m_context << eth::Instruction::POP; |
|||
} |
|||
|
|||
unsigned CompilerUtils::getSizeOnStack(vector<shared_ptr<Type const>> const& _variableTypes) |
|||
{ |
|||
unsigned size = 0; |
|||
for (shared_ptr<Type const> const& type: _variableTypes) |
|||
size += type->getSizeOnStack(); |
|||
return size; |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,63 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Christian <c@ethdev.com> |
|||
* @date 2014 |
|||
* Routines used by both the compiler and the expression compiler. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libsolidity/CompilerContext.h> |
|||
#include <libsolidity/ASTForward.h> |
|||
|
|||
namespace dev { |
|||
namespace solidity { |
|||
|
|||
class Type; // forward
|
|||
|
|||
class CompilerUtils |
|||
{ |
|||
public: |
|||
CompilerUtils(CompilerContext& _context): m_context(_context) {} |
|||
|
|||
/// Moves the value that is at the top of the stack to a stack variable.
|
|||
void moveToStackVariable(VariableDeclaration const& _variable); |
|||
/// Copies a variable of type @a _type from a stack depth of @a _stackDepth to the top of the stack.
|
|||
void copyToStackTop(unsigned _stackDepth, Type const& _type); |
|||
/// Removes the current value from the top of the stack.
|
|||
void popStackElement(Type const& _type); |
|||
|
|||
template <class T> |
|||
static unsigned getSizeOnStack(std::vector<T> const& _variables); |
|||
static unsigned getSizeOnStack(std::vector<std::shared_ptr<Type const>> const& _variableTypes); |
|||
|
|||
private: |
|||
CompilerContext& m_context; |
|||
}; |
|||
|
|||
template <class T> |
|||
unsigned CompilerUtils::getSizeOnStack(std::vector<T> const& _variables) |
|||
{ |
|||
unsigned size = 0; |
|||
for (T const& variable: _variables) |
|||
size += variable->getType()->getSizeOnStack(); |
|||
return size; |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,368 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Lefteris <lefteris@ethdev.com> |
|||
* @date 2014 |
|||
* Solidity command line interface. |
|||
*/ |
|||
#include "CommandLineInterface.h" |
|||
|
|||
#include <string> |
|||
#include <iostream> |
|||
#include <fstream> |
|||
|
|||
#include <boost/filesystem.hpp> |
|||
|
|||
#include "BuildInfo.h" |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/CommonData.h> |
|||
#include <libdevcore/CommonIO.h> |
|||
#include <libevmcore/Instruction.h> |
|||
#include <libsolidity/Scanner.h> |
|||
#include <libsolidity/Parser.h> |
|||
#include <libsolidity/ASTPrinter.h> |
|||
#include <libsolidity/NameAndTypeResolver.h> |
|||
#include <libsolidity/Exceptions.h> |
|||
#include <libsolidity/CompilerStack.h> |
|||
#include <libsolidity/SourceReferenceFormatter.h> |
|||
|
|||
using namespace std; |
|||
namespace po = boost::program_options; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
static void version() |
|||
{ |
|||
cout << "solc, the solidity complier commandline interface " << dev::Version << endl |
|||
<< " by Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com>, (c) 2014." << endl |
|||
<< "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; |
|||
exit(0); |
|||
} |
|||
|
|||
static inline bool argToStdout(po::variables_map const& _args, const char* _name) |
|||
{ |
|||
return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE; |
|||
} |
|||
|
|||
static bool needStdout(po::variables_map const& _args) |
|||
{ |
|||
return argToStdout(_args, "abi") || argToStdout(_args, "natspec-user") || argToStdout(_args, "natspec-dev") || |
|||
argToStdout(_args, "asm") || argToStdout(_args, "opcodes") || argToStdout(_args, "binary"); |
|||
} |
|||
|
|||
static inline bool outputToFile(OutputType type) |
|||
{ |
|||
return type == OutputType::FILE || type == OutputType::BOTH; |
|||
} |
|||
|
|||
static inline bool outputToStdout(OutputType type) |
|||
{ |
|||
return type == OutputType::STDOUT || type == OutputType::BOTH; |
|||
} |
|||
|
|||
static std::istream& operator>>(std::istream& _in, OutputType& io_output) |
|||
{ |
|||
std::string token; |
|||
_in >> token; |
|||
if (token == "stdout") |
|||
io_output = OutputType::STDOUT; |
|||
else if (token == "file") |
|||
io_output = OutputType::FILE; |
|||
else if (token == "both") |
|||
io_output = OutputType::BOTH; |
|||
else |
|||
throw boost::program_options::invalid_option_value(token); |
|||
return _in; |
|||
} |
|||
|
|||
void CommandLineInterface::handleBinary(string const& _contract) |
|||
{ |
|||
auto choice = m_args["binary"].as<OutputType>(); |
|||
if (outputToStdout(choice)) |
|||
{ |
|||
cout << "Binary: " << endl; |
|||
cout << toHex(m_compiler.getBytecode(_contract)) << endl; |
|||
} |
|||
|
|||
if (outputToFile(choice)) |
|||
{ |
|||
ofstream outFile(_contract + ".binary"); |
|||
outFile << toHex(m_compiler.getBytecode(_contract)); |
|||
outFile.close(); |
|||
} |
|||
} |
|||
|
|||
void CommandLineInterface::handleOpcode(string const& _contract) |
|||
{ |
|||
// TODO: Figure out why the wrong operator << (from boost) is used here
|
|||
auto choice = m_args["opcode"].as<OutputType>(); |
|||
if (outputToStdout(choice)) |
|||
{ |
|||
cout << "Opcodes: " << endl; |
|||
dev::operator<<(cout, m_compiler.getBytecode(_contract)); |
|||
cout << endl; |
|||
} |
|||
|
|||
if (outputToFile(choice)) |
|||
{ |
|||
ofstream outFile(_contract + ".opcode"); |
|||
dev::operator<<(outFile, m_compiler.getBytecode(_contract)); |
|||
outFile.close(); |
|||
} |
|||
} |
|||
|
|||
void CommandLineInterface::handleBytecode(string const& _contract) |
|||
{ |
|||
if (m_args.count("opcodes")) |
|||
handleOpcode(_contract); |
|||
if (m_args.count("binary")) |
|||
handleBinary(_contract); |
|||
} |
|||
|
|||
void CommandLineInterface::handleJson(DocumentationType _type, |
|||
string const& _contract) |
|||
{ |
|||
std::string argName; |
|||
std::string suffix; |
|||
std::string title; |
|||
switch(_type) |
|||
{ |
|||
case DocumentationType::ABI_INTERFACE: |
|||
argName = "abi"; |
|||
suffix = ".abi"; |
|||
title = "Contract ABI"; |
|||
break; |
|||
case DocumentationType::NATSPEC_USER: |
|||
argName = "natspec-user"; |
|||
suffix = ".docuser"; |
|||
title = "User Documentation"; |
|||
break; |
|||
case DocumentationType::NATSPEC_DEV: |
|||
argName = "natspec-dev"; |
|||
suffix = ".docdev"; |
|||
title = "Developer Documentation"; |
|||
break; |
|||
default: |
|||
// should never happen
|
|||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation _type")); |
|||
} |
|||
|
|||
if (m_args.count(argName)) |
|||
{ |
|||
auto choice = m_args[argName].as<OutputType>(); |
|||
if (outputToStdout(choice)) |
|||
{ |
|||
cout << title << endl; |
|||
cout << m_compiler.getJsonDocumentation(_contract, _type); |
|||
} |
|||
|
|||
if (outputToFile(choice)) |
|||
{ |
|||
ofstream outFile(_contract + suffix); |
|||
outFile << m_compiler.getJsonDocumentation(_contract, _type); |
|||
outFile.close(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool CommandLineInterface::parseArguments(int argc, char** argv) |
|||
{ |
|||
#define OUTPUT_TYPE_STR "Legal values:\n" \ |
|||
"\tstdout: Print it to standard output\n" \ |
|||
"\tfile: Print it to a file with same name\n" \ |
|||
"\tboth: Print both to a file and the stdout\n" |
|||
// Declare the supported options.
|
|||
po::options_description desc("Allowed options"); |
|||
desc.add_options() |
|||
("help", "Show help message and exit") |
|||
("version", "Show version and exit") |
|||
("optimize", po::value<bool>()->default_value(false), "Optimize bytecode for size") |
|||
("input-file", po::value<vector<string>>(), "input file") |
|||
("ast", po::value<OutputType>(), |
|||
"Request to output the AST of the contract. " OUTPUT_TYPE_STR) |
|||
("asm", po::value<OutputType>(), |
|||
"Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) |
|||
("opcodes", po::value<OutputType>(), |
|||
"Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) |
|||
("binary", po::value<OutputType>(), |
|||
"Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) |
|||
("abi", po::value<OutputType>(), |
|||
"Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) |
|||
("natspec-user", po::value<OutputType>(), |
|||
"Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) |
|||
("natspec-dev", po::value<OutputType>(), |
|||
"Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); |
|||
#undef OUTPUT_TYPE_STR |
|||
|
|||
// All positional options should be interpreted as input files
|
|||
po::positional_options_description p; |
|||
p.add("input-file", -1); |
|||
|
|||
// parse the compiler arguments
|
|||
try |
|||
{ |
|||
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), m_args); |
|||
} |
|||
catch (po::error const& exception) |
|||
{ |
|||
cout << exception.what() << endl; |
|||
return false; |
|||
} |
|||
po::notify(m_args); |
|||
|
|||
if (m_args.count("help")) |
|||
{ |
|||
cout << desc; |
|||
return false; |
|||
} |
|||
|
|||
if (m_args.count("version")) |
|||
{ |
|||
version(); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool CommandLineInterface::processInput() |
|||
{ |
|||
if (!m_args.count("input-file")) |
|||
{ |
|||
string s; |
|||
while (!cin.eof()) |
|||
{ |
|||
getline(cin, s); |
|||
m_sourceCodes["<stdin>"].append(s); |
|||
} |
|||
} |
|||
else |
|||
for (string const& infile: m_args["input-file"].as<vector<string>>()) |
|||
m_sourceCodes[infile] = asString(dev::contents(infile)); |
|||
|
|||
try |
|||
{ |
|||
for (auto const& sourceCode: m_sourceCodes) |
|||
m_compiler.addSource(sourceCode.first, sourceCode.second); |
|||
// TODO: Perhaps we should not compile unless requested
|
|||
m_compiler.compile(m_args["optimize"].as<bool>()); |
|||
} |
|||
catch (ParserError const& exception) |
|||
{ |
|||
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", m_compiler); |
|||
return false; |
|||
} |
|||
catch (DeclarationError const& exception) |
|||
{ |
|||
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", m_compiler); |
|||
return false; |
|||
} |
|||
catch (TypeError const& exception) |
|||
{ |
|||
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", m_compiler); |
|||
return false; |
|||
} |
|||
catch (CompilerError const& exception) |
|||
{ |
|||
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", m_compiler); |
|||
return false; |
|||
} |
|||
catch (InternalCompilerError const& exception) |
|||
{ |
|||
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", m_compiler); |
|||
return false; |
|||
} |
|||
catch (Exception const& exception) |
|||
{ |
|||
cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl; |
|||
return false; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Unknown exception during compilation." << endl; |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
void CommandLineInterface::actOnInput() |
|||
{ |
|||
// do we need AST output?
|
|||
if (m_args.count("ast")) |
|||
{ |
|||
auto choice = m_args["ast"].as<OutputType>(); |
|||
if (outputToStdout(choice)) |
|||
{ |
|||
cout << "Syntax trees:" << endl << endl; |
|||
for (auto const& sourceCode: m_sourceCodes) |
|||
{ |
|||
cout << endl << "======= " << sourceCode.first << " =======" << endl; |
|||
ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); |
|||
printer.print(cout); |
|||
} |
|||
} |
|||
|
|||
if (outputToFile(choice)) |
|||
{ |
|||
for (auto const& sourceCode: m_sourceCodes) |
|||
{ |
|||
boost::filesystem::path p(sourceCode.first); |
|||
ofstream outFile(p.stem().string() + ".ast"); |
|||
ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); |
|||
printer.print(outFile); |
|||
outFile.close(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
vector<string> contracts = m_compiler.getContractNames(); |
|||
for (string const& contract: contracts) |
|||
{ |
|||
if (needStdout(m_args)) |
|||
cout << endl << "======= " << contract << " =======" << endl; |
|||
|
|||
// do we need EVM assembly?
|
|||
if (m_args.count("asm")) |
|||
{ |
|||
auto choice = m_args["asm"].as<OutputType>(); |
|||
if (outputToStdout(choice)) |
|||
{ |
|||
cout << "EVM assembly:" << endl; |
|||
m_compiler.streamAssembly(cout, contract); |
|||
} |
|||
|
|||
if (outputToFile(choice)) |
|||
{ |
|||
ofstream outFile(contract + ".evm"); |
|||
m_compiler.streamAssembly(outFile, contract); |
|||
outFile.close(); |
|||
} |
|||
} |
|||
|
|||
handleBytecode(contract); |
|||
handleJson(DocumentationType::ABI_INTERFACE, contract); |
|||
handleJson(DocumentationType::NATSPEC_DEV, contract); |
|||
handleJson(DocumentationType::NATSPEC_USER, contract); |
|||
} // end of contracts iteration
|
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,71 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
/**
|
|||
* @author Lefteris <lefteris@ethdev.com> |
|||
* @date 2014 |
|||
* Solidity command line interface. |
|||
*/ |
|||
#pragma once |
|||
|
|||
#include <boost/program_options.hpp> |
|||
|
|||
#include <libsolidity/CompilerStack.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
//forward declaration
|
|||
enum class DocumentationType: uint8_t; |
|||
|
|||
enum class OutputType: uint8_t |
|||
{ |
|||
STDOUT, |
|||
FILE, |
|||
BOTH |
|||
}; |
|||
|
|||
class CommandLineInterface |
|||
{ |
|||
public: |
|||
CommandLineInterface() {} |
|||
|
|||
/// Parse command line arguments and return false if we should not continue
|
|||
bool parseArguments(int argc, char** argv); |
|||
/// Parse the files and create source code objects
|
|||
bool processInput(); |
|||
/// Perform actions on the input depending on provided compiler arguments
|
|||
void actOnInput(); |
|||
|
|||
private: |
|||
void handleBinary(std::string const& _contract); |
|||
void handleOpcode(std::string const& _contract); |
|||
void handleBytecode(std::string const& _contract); |
|||
void handleJson(DocumentationType _type, |
|||
std::string const& _contract); |
|||
|
|||
/// Compiler arguments variable map
|
|||
boost::program_options::variables_map m_args; |
|||
/// map of input files to source code strings
|
|||
std::map<std::string, std::string> m_sourceCodes; |
|||
/// Solidity compiler stack
|
|||
dev::solidity::CompilerStack m_compiler; |
|||
}; |
|||
|
|||
} |
|||
} |
File diff suppressed because it is too large
Loading…
Reference in new issue