|
|
@ -48,6 +48,16 @@ namespace dev |
|
|
|
namespace solidity |
|
|
|
{ |
|
|
|
|
|
|
|
// LTODO: Maybe some argument class pairing names with
|
|
|
|
// extensions and other attributes would be a better choice here?
|
|
|
|
static string const g_argAbiStr = "abi"; |
|
|
|
static string const g_argAsmStr = "asm"; |
|
|
|
static string const g_argAstStr = "ast"; |
|
|
|
static string const g_argBinaryStr = "binary"; |
|
|
|
static string const g_argOpcodesStr = "opcodes"; |
|
|
|
static string const g_argNatspecDevStr = "natspec-dev"; |
|
|
|
static string const g_argNatspecUserStr = "natspec-user"; |
|
|
|
|
|
|
|
static void version() |
|
|
|
{ |
|
|
|
cout << "solc, the solidity complier commandline interface " << dev::Version << endl |
|
|
@ -56,15 +66,16 @@ static void version() |
|
|
|
exit(0); |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool argToStdout(po::variables_map const& _args, const char* _name) |
|
|
|
static inline bool argToStdout(po::variables_map const& _args, string const& _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"); |
|
|
|
return argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argNatspecUserStr) || |
|
|
|
argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) || |
|
|
|
argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr); |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool outputToFile(OutputType type) |
|
|
@ -94,7 +105,7 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) |
|
|
|
|
|
|
|
void CommandLineInterface::handleBinary(string const& _contract) |
|
|
|
{ |
|
|
|
auto choice = m_args["binary"].as<OutputType>(); |
|
|
|
auto choice = m_args[g_argBinaryStr].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "Binary: " << endl; |
|
|
@ -111,28 +122,27 @@ void CommandLineInterface::handleBinary(string const& _contract) |
|
|
|
|
|
|
|
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>(); |
|
|
|
auto choice = m_args[g_argOpcodesStr].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "Opcodes: " << endl; |
|
|
|
dev::operator<<(cout, m_compiler.getBytecode(_contract)); |
|
|
|
cout << eth::disassemble(m_compiler.getBytecode(_contract)); |
|
|
|
cout << endl; |
|
|
|
} |
|
|
|
|
|
|
|
if (outputToFile(choice)) |
|
|
|
{ |
|
|
|
ofstream outFile(_contract + ".opcode"); |
|
|
|
dev::operator<<(outFile, m_compiler.getBytecode(_contract)); |
|
|
|
outFile << eth::disassemble(m_compiler.getBytecode(_contract)); |
|
|
|
outFile.close(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void CommandLineInterface::handleBytecode(string const& _contract) |
|
|
|
{ |
|
|
|
if (m_args.count("opcodes")) |
|
|
|
if (m_args.count(g_argOpcodesStr)) |
|
|
|
handleOpcode(_contract); |
|
|
|
if (m_args.count("binary")) |
|
|
|
if (m_args.count(g_argBinaryStr)) |
|
|
|
handleBinary(_contract); |
|
|
|
} |
|
|
|
|
|
|
@ -145,17 +155,17 @@ void CommandLineInterface::handleJson(DocumentationType _type, |
|
|
|
switch(_type) |
|
|
|
{ |
|
|
|
case DocumentationType::ABI_INTERFACE: |
|
|
|
argName = "abi"; |
|
|
|
argName = g_argAbiStr; |
|
|
|
suffix = ".abi"; |
|
|
|
title = "Contract ABI"; |
|
|
|
break; |
|
|
|
case DocumentationType::NATSPEC_USER: |
|
|
|
argName = "natspec-user"; |
|
|
|
argName = "g_argNatspecUserStr"; |
|
|
|
suffix = ".docuser"; |
|
|
|
title = "User Documentation"; |
|
|
|
break; |
|
|
|
case DocumentationType::NATSPEC_DEV: |
|
|
|
argName = "natspec-dev"; |
|
|
|
argName = g_argNatspecDevStr; |
|
|
|
suffix = ".docdev"; |
|
|
|
title = "Developer Documentation"; |
|
|
|
break; |
|
|
@ -195,20 +205,20 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) |
|
|
|
("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>(), |
|
|
|
(g_argAstStr.c_str(), 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); |
|
|
|
(g_argAsmStr.c_str(), po::value<OutputType>(), |
|
|
|
"Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) |
|
|
|
(g_argOpcodesStr.c_str(), po::value<OutputType>(), |
|
|
|
"Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) |
|
|
|
(g_argBinaryStr.c_str(), po::value<OutputType>(), |
|
|
|
"Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) |
|
|
|
(g_argAbiStr.c_str(), po::value<OutputType>(), |
|
|
|
"Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) |
|
|
|
(g_argNatspecUserStr.c_str(), po::value<OutputType>(), |
|
|
|
"Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) |
|
|
|
(g_argNatspecDevStr.c_str(), 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
|
|
|
@ -220,9 +230,9 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) |
|
|
|
{ |
|
|
|
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), m_args); |
|
|
|
} |
|
|
|
catch (po::error const& exception) |
|
|
|
catch (po::error const& _exception) |
|
|
|
{ |
|
|
|
cout << exception.what() << endl; |
|
|
|
cout << _exception.what() << endl; |
|
|
|
return false; |
|
|
|
} |
|
|
|
po::notify(m_args); |
|
|
@ -279,34 +289,35 @@ bool CommandLineInterface::processInput() |
|
|
|
// TODO: Perhaps we should not compile unless requested
|
|
|
|
m_compiler.compile(m_args["optimize"].as<bool>()); |
|
|
|
} |
|
|
|
catch (ParserError const& exception) |
|
|
|
catch (ParserError const& _exception) |
|
|
|
{ |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", m_compiler); |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Parser error", m_compiler); |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (DeclarationError const& exception) |
|
|
|
catch (DeclarationError const& _exception) |
|
|
|
{ |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", m_compiler); |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Declaration error", m_compiler); |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (TypeError const& exception) |
|
|
|
catch (TypeError const& _exception) |
|
|
|
{ |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", m_compiler); |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Type error", m_compiler); |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (CompilerError const& exception) |
|
|
|
catch (CompilerError const& _exception) |
|
|
|
{ |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", m_compiler); |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Compiler error", m_compiler); |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (InternalCompilerError const& exception) |
|
|
|
catch (InternalCompilerError const& _exception) |
|
|
|
{ |
|
|
|
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", m_compiler); |
|
|
|
cerr << "Internal compiler error during compilation:" << endl |
|
|
|
<< boost::diagnostic_information(_exception); |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (Exception const& exception) |
|
|
|
catch (Exception const& _exception) |
|
|
|
{ |
|
|
|
cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl; |
|
|
|
cerr << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; |
|
|
|
return false; |
|
|
|
} |
|
|
|
catch (...) |
|
|
@ -321,9 +332,9 @@ bool CommandLineInterface::processInput() |
|
|
|
void CommandLineInterface::actOnInput() |
|
|
|
{ |
|
|
|
// do we need AST output?
|
|
|
|
if (m_args.count("ast")) |
|
|
|
if (m_args.count(g_argAstStr)) |
|
|
|
{ |
|
|
|
auto choice = m_args["ast"].as<OutputType>(); |
|
|
|
auto choice = m_args[g_argAstStr].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "Syntax trees:" << endl << endl; |
|
|
@ -355,9 +366,9 @@ void CommandLineInterface::actOnInput() |
|
|
|
cout << endl << "======= " << contract << " =======" << endl; |
|
|
|
|
|
|
|
// do we need EVM assembly?
|
|
|
|
if (m_args.count("asm")) |
|
|
|
if (m_args.count(g_argAsmStr)) |
|
|
|
{ |
|
|
|
auto choice = m_args["asm"].as<OutputType>(); |
|
|
|
auto choice = m_args[g_argAsmStr].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "EVM assembly:" << endl; |
|
|
|