|
@ -27,6 +27,7 @@ |
|
|
#include <fstream> |
|
|
#include <fstream> |
|
|
|
|
|
|
|
|
#include <boost/filesystem.hpp> |
|
|
#include <boost/filesystem.hpp> |
|
|
|
|
|
#include <boost/algorithm/string.hpp> |
|
|
|
|
|
|
|
|
#include "BuildInfo.h" |
|
|
#include "BuildInfo.h" |
|
|
#include <libdevcore/Common.h> |
|
|
#include <libdevcore/Common.h> |
|
@ -50,6 +51,7 @@ namespace dev |
|
|
namespace solidity |
|
|
namespace solidity |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LTODO: Maybe some argument class pairing names with
|
|
|
// LTODO: Maybe some argument class pairing names with
|
|
|
// extensions and other attributes would be a better choice here?
|
|
|
// extensions and other attributes would be a better choice here?
|
|
|
static string const g_argAbiStr = "json-abi"; |
|
|
static string const g_argAbiStr = "json-abi"; |
|
@ -64,6 +66,18 @@ static string const g_argNatspecDevStr = "natspec-dev"; |
|
|
static string const g_argNatspecUserStr = "natspec-user"; |
|
|
static string const g_argNatspecUserStr = "natspec-user"; |
|
|
static string const g_argAddStandard = "add-std"; |
|
|
static string const g_argAddStandard = "add-std"; |
|
|
|
|
|
|
|
|
|
|
|
/// Possible arguments to for --combined-json
|
|
|
|
|
|
static set<string> const g_combinedJsonArgs{ |
|
|
|
|
|
"binary", |
|
|
|
|
|
"opcodes", |
|
|
|
|
|
"json-abi", |
|
|
|
|
|
"sol-abi", |
|
|
|
|
|
"asm", |
|
|
|
|
|
"ast", |
|
|
|
|
|
"natspec-user", |
|
|
|
|
|
"natspec-dev" |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
static void version() |
|
|
static void version() |
|
|
{ |
|
|
{ |
|
|
cout << "solc, the solidity compiler commandline interface " << dev::Version << endl |
|
|
cout << "solc, the solidity compiler commandline interface " << dev::Version << endl |
|
@ -72,24 +86,24 @@ static void version() |
|
|
exit(0); |
|
|
exit(0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static inline bool argToStdout(po::variables_map const& _args, string const& _name) |
|
|
static inline bool humanTargetedStdout(po::variables_map const& _args, string const& _name) |
|
|
{ |
|
|
{ |
|
|
return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE; |
|
|
return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static bool needStdout(po::variables_map const& _args) |
|
|
static bool needsHumanTargetedStdout(po::variables_map const& _args) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
return |
|
|
return |
|
|
argToStdout(_args, g_argAbiStr) || |
|
|
humanTargetedStdout(_args, g_argAbiStr) || |
|
|
argToStdout(_args, g_argSolAbiStr) || |
|
|
humanTargetedStdout(_args, g_argSolAbiStr) || |
|
|
argToStdout(_args, g_argNatspecUserStr) || |
|
|
humanTargetedStdout(_args, g_argNatspecUserStr) || |
|
|
argToStdout(_args, g_argAstJson) || |
|
|
humanTargetedStdout(_args, g_argAstJson) || |
|
|
argToStdout(_args, g_argNatspecDevStr) || |
|
|
humanTargetedStdout(_args, g_argNatspecDevStr) || |
|
|
argToStdout(_args, g_argAsmStr) || |
|
|
humanTargetedStdout(_args, g_argAsmStr) || |
|
|
argToStdout(_args, g_argAsmJsonStr) || |
|
|
humanTargetedStdout(_args, g_argAsmJsonStr) || |
|
|
argToStdout(_args, g_argOpcodesStr) || |
|
|
humanTargetedStdout(_args, g_argOpcodesStr) || |
|
|
argToStdout(_args, g_argBinaryStr); |
|
|
humanTargetedStdout(_args, g_argBinaryStr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static inline bool outputToFile(OutputType type) |
|
|
static inline bool outputToFile(OutputType type) |
|
@ -220,6 +234,11 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) |
|
|
("optimize", po::value<bool>()->default_value(false), "Optimize bytecode for size") |
|
|
("optimize", po::value<bool>()->default_value(false), "Optimize bytecode for size") |
|
|
("add-std", po::value<bool>()->default_value(false), "Add standard contracts") |
|
|
("add-std", po::value<bool>()->default_value(false), "Add standard contracts") |
|
|
("input-file", po::value<vector<string>>(), "input file") |
|
|
("input-file", po::value<vector<string>>(), "input file") |
|
|
|
|
|
( |
|
|
|
|
|
"combined-json", |
|
|
|
|
|
po::value<string>()->value_name(boost::join(g_combinedJsonArgs, ",")), |
|
|
|
|
|
"Output a single json document containing the specified information, can be combined." |
|
|
|
|
|
) |
|
|
(g_argAstStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), |
|
|
(g_argAstStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), |
|
|
"Request to output the AST of the contract.") |
|
|
"Request to output the AST of the contract.") |
|
|
(g_argAstJson.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), |
|
|
(g_argAstJson.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), |
|
@ -255,6 +274,16 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) |
|
|
cout << _exception.what() << endl; |
|
|
cout << _exception.what() << endl; |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
if (m_args.count("combined-json")) |
|
|
|
|
|
{ |
|
|
|
|
|
vector<string> requests; |
|
|
|
|
|
for (string const& item: boost::split(requests, m_args["combined-json"].as<string>(), boost::is_any_of(","))) |
|
|
|
|
|
if (!g_combinedJsonArgs.count(item)) |
|
|
|
|
|
{ |
|
|
|
|
|
cout << "Invalid option to --combined-json: " << item << endl; |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
po::notify(m_args); |
|
|
po::notify(m_args); |
|
|
|
|
|
|
|
|
if (m_args.count("help")) |
|
|
if (m_args.count("help")) |
|
@ -350,6 +379,52 @@ bool CommandLineInterface::processInput() |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CommandLineInterface::handleCombinedJSON() |
|
|
|
|
|
{ |
|
|
|
|
|
Json::Value output(Json::objectValue); |
|
|
|
|
|
|
|
|
|
|
|
set<string> requests; |
|
|
|
|
|
boost::split(requests, m_args["combined-json"].as<string>(), boost::is_any_of(",")); |
|
|
|
|
|
vector<string> contracts = m_compiler->getContractNames(); |
|
|
|
|
|
|
|
|
|
|
|
if (!contracts.empty()) |
|
|
|
|
|
output["contracts"] = Json::Value(Json::objectValue); |
|
|
|
|
|
for (string const& contractName: contracts) |
|
|
|
|
|
{ |
|
|
|
|
|
Json::Value contractData(Json::objectValue); |
|
|
|
|
|
if (requests.count("sol-abi")) |
|
|
|
|
|
contractData["sol-abi"] = m_compiler->getSolidityInterface(contractName); |
|
|
|
|
|
if (requests.count("json-abi")) |
|
|
|
|
|
contractData["json-abi"] = m_compiler->getInterface(contractName); |
|
|
|
|
|
if (requests.count("binary")) |
|
|
|
|
|
contractData["binary"] = toHex(m_compiler->getBytecode(contractName)); |
|
|
|
|
|
if (requests.count("opcodes")) |
|
|
|
|
|
contractData["opcodes"] = eth::disassemble(m_compiler->getBytecode(contractName)); |
|
|
|
|
|
if (requests.count("asm")) |
|
|
|
|
|
{ |
|
|
|
|
|
ostringstream unused; |
|
|
|
|
|
contractData["asm"] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true); |
|
|
|
|
|
} |
|
|
|
|
|
if (requests.count("natspec-dev")) |
|
|
|
|
|
contractData["natspec-dev"] = m_compiler->getMetadata(contractName, DocumentationType::NatspecDev); |
|
|
|
|
|
if (requests.count("natspec-user")) |
|
|
|
|
|
contractData["natspec-user"] = m_compiler->getMetadata(contractName, DocumentationType::NatspecUser); |
|
|
|
|
|
output["contracts"][contractName] = contractData; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (requests.count("ast")) |
|
|
|
|
|
{ |
|
|
|
|
|
output["sources"] = Json::Value(Json::objectValue); |
|
|
|
|
|
for (auto const& sourceCode: m_sourceCodes) |
|
|
|
|
|
{ |
|
|
|
|
|
ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); |
|
|
|
|
|
output["sources"][sourceCode.first] = Json::Value(Json::objectValue); |
|
|
|
|
|
output["sources"][sourceCode.first]["AST"] = converter.json(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
cout << Json::FastWriter().write(output) << endl; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void CommandLineInterface::handleAst(string const& _argStr) |
|
|
void CommandLineInterface::handleAst(string const& _argStr) |
|
|
{ |
|
|
{ |
|
|
string title; |
|
|
string title; |
|
@ -408,6 +483,8 @@ void CommandLineInterface::handleAst(string const& _argStr) |
|
|
|
|
|
|
|
|
void CommandLineInterface::actOnInput() |
|
|
void CommandLineInterface::actOnInput() |
|
|
{ |
|
|
{ |
|
|
|
|
|
handleCombinedJSON(); |
|
|
|
|
|
|
|
|
// do we need AST output?
|
|
|
// do we need AST output?
|
|
|
handleAst(g_argAstStr); |
|
|
handleAst(g_argAstStr); |
|
|
handleAst(g_argAstJson); |
|
|
handleAst(g_argAstJson); |
|
@ -415,7 +492,7 @@ void CommandLineInterface::actOnInput() |
|
|
vector<string> contracts = m_compiler->getContractNames(); |
|
|
vector<string> contracts = m_compiler->getContractNames(); |
|
|
for (string const& contract: contracts) |
|
|
for (string const& contract: contracts) |
|
|
{ |
|
|
{ |
|
|
if (needStdout(m_args)) |
|
|
if (needsHumanTargetedStdout(m_args)) |
|
|
cout << endl << "======= " << contract << " =======" << endl; |
|
|
cout << endl << "======= " << contract << " =======" << endl; |
|
|
|
|
|
|
|
|
// do we need EVM assembly?
|
|
|
// do we need EVM assembly?
|
|
|