|
|
@ -60,12 +60,18 @@ enum class OutputType |
|
|
|
BOTH |
|
|
|
}; |
|
|
|
|
|
|
|
#define outputTypeStr "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" |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::istream& operator>>(std::istream& _in, OutputType& io_output) |
|
|
|
static std::istream& operator>>(std::istream& _in, OutputType& io_output) |
|
|
|
{ |
|
|
|
std::string token; |
|
|
|
_in >> token; |
|
|
@ -81,7 +87,7 @@ std::istream& operator>>(std::istream& _in, OutputType& io_output) |
|
|
|
} |
|
|
|
|
|
|
|
static void handleBytecode(po::variables_map const& vm, |
|
|
|
char const* _argName, |
|
|
|
string const& _argName, |
|
|
|
string const& _title, |
|
|
|
string const& _contract, |
|
|
|
CompilerStack& _compiler, |
|
|
@ -90,7 +96,7 @@ static void handleBytecode(po::variables_map const& vm, |
|
|
|
if (vm.count(_argName)) |
|
|
|
{ |
|
|
|
auto choice = vm[_argName].as<OutputType>(); |
|
|
|
if (choice != OutputType::FILE) |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << _title << endl; |
|
|
|
if (_suffix == "opcodes") |
|
|
@ -99,7 +105,7 @@ static void handleBytecode(po::variables_map const& vm, |
|
|
|
cout << toHex(_compiler.getBytecode(_contract)) << endl; |
|
|
|
} |
|
|
|
|
|
|
|
if (choice != OutputType::STDOUT) |
|
|
|
if (outputToFile(choice)) |
|
|
|
{ |
|
|
|
ofstream outFile(_contract + _suffix); |
|
|
|
if (_suffix == "opcodes") |
|
|
@ -111,7 +117,7 @@ static void handleBytecode(po::variables_map const& vm, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void handleJson(po::variables_map const& _vm, |
|
|
|
static void handleJson(po::variables_map const& _args, |
|
|
|
DocumentationType _type, |
|
|
|
string const& _contract, |
|
|
|
CompilerStack&_compiler) |
|
|
@ -141,16 +147,16 @@ static void handleJson(po::variables_map const& _vm, |
|
|
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation _type")); |
|
|
|
} |
|
|
|
|
|
|
|
if (_vm.count(argName.c_str())) |
|
|
|
if (_args.count(argName)) |
|
|
|
{ |
|
|
|
auto choice = _vm[argName.c_str()].as<OutputType>(); |
|
|
|
if (choice != OutputType::FILE) |
|
|
|
auto choice = _args[argName].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << title << endl; |
|
|
|
cout << _compiler.getJsonDocumentation(_contract, _type); |
|
|
|
} |
|
|
|
|
|
|
|
if (choice != OutputType::STDOUT) |
|
|
|
if (outputToFile(choice)) |
|
|
|
{ |
|
|
|
ofstream outFile(_contract + suffix); |
|
|
|
outFile << _compiler.getJsonDocumentation(_contract, _type); |
|
|
@ -159,19 +165,23 @@ static void handleJson(po::variables_map const& _vm, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool argToStdout(po::variables_map const& _vm, const char* _name) |
|
|
|
static inline bool argToStdout(po::variables_map const& _args, const char* _name) |
|
|
|
{ |
|
|
|
return _vm.count(_name) && _vm[_name].as<OutputType>() != OutputType::FILE; |
|
|
|
return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE; |
|
|
|
} |
|
|
|
|
|
|
|
static bool needStdout(po::variables_map const& _vm) |
|
|
|
static bool needStdout(po::variables_map const& _args) |
|
|
|
{ |
|
|
|
return argToStdout(_vm, "abi") || argToStdout(_vm, "natspec-user") || argToStdout(_vm, "natspec-dev") || |
|
|
|
argToStdout(_vm, "asm") || argToStdout(_vm, "opcodes") || argToStdout(_vm, "binary"); |
|
|
|
return argToStdout(_args, "abi") || argToStdout(_args, "natspec-user") || argToStdout(_args, "natspec-dev") || |
|
|
|
argToStdout(_args, "asm") || argToStdout(_args, "opcodes") || argToStdout(_args, "binary"); |
|
|
|
} |
|
|
|
|
|
|
|
int main(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() |
|
|
@ -180,50 +190,53 @@ int main(int argc, char** argv) |
|
|
|
("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. " outputTypeStr) |
|
|
|
"Request to output the AST of the contract. " OUTPUT_TYPE_STR) |
|
|
|
("asm", po::value<OutputType>(), |
|
|
|
"Request to output the EVM assembly of the contract. " outputTypeStr) |
|
|
|
"Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) |
|
|
|
("opcodes", po::value<OutputType>(), |
|
|
|
"Request to output the Opcodes of the contract. " outputTypeStr) |
|
|
|
"Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) |
|
|
|
("binary", po::value<OutputType>(), |
|
|
|
"Request to output the contract in binary (hexadecimal). " outputTypeStr) |
|
|
|
"Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) |
|
|
|
("abi", po::value<OutputType>(), |
|
|
|
"Request to output the contract's ABI interface. " outputTypeStr) |
|
|
|
"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. " outputTypeStr) |
|
|
|
"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. " outputTypeStr); |
|
|
|
"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
|
|
|
|
po::variables_map vm; |
|
|
|
po::variables_map args; |
|
|
|
try |
|
|
|
{ |
|
|
|
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), vm); |
|
|
|
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), args); |
|
|
|
} |
|
|
|
catch (po::error const& exception) |
|
|
|
{ |
|
|
|
cout << exception.what() << endl; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
po::notify(vm); |
|
|
|
po::notify(args); |
|
|
|
|
|
|
|
if (vm.count("help")) { |
|
|
|
if (args.count("help")) |
|
|
|
{ |
|
|
|
cout << desc; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (vm.count("version")) { |
|
|
|
if (args.count("version")) |
|
|
|
{ |
|
|
|
version(); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
// create a map of input files to source code strings
|
|
|
|
map<string, string> sourceCodes; |
|
|
|
if (!vm.count("input-file")) |
|
|
|
if (!args.count("input-file")) |
|
|
|
{ |
|
|
|
string s; |
|
|
|
while (!cin.eof()) |
|
|
@ -233,7 +246,7 @@ int main(int argc, char** argv) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
for (string const& infile: vm["input-file"].as<vector<string>>()) |
|
|
|
for (string const& infile: args["input-file"].as<vector<string>>()) |
|
|
|
sourceCodes[infile] = asString(dev::contents(infile)); |
|
|
|
|
|
|
|
// parse the files
|
|
|
@ -242,7 +255,8 @@ int main(int argc, char** argv) |
|
|
|
{ |
|
|
|
for (auto const& sourceCode: sourceCodes) |
|
|
|
compiler.addSource(sourceCode.first, sourceCode.second); |
|
|
|
compiler.compile( vm["optimize"].as<bool>()); |
|
|
|
// TODO: Perhaps we should not compile unless requested
|
|
|
|
compiler.compile(args["optimize"].as<bool>()); |
|
|
|
} |
|
|
|
catch (ParserError const& exception) |
|
|
|
{ |
|
|
@ -284,10 +298,10 @@ int main(int argc, char** argv) |
|
|
|
/* -- act depending on the provided arguments -- */ |
|
|
|
|
|
|
|
// do we need AST output?
|
|
|
|
if (vm.count("ast")) |
|
|
|
if (args.count("ast")) |
|
|
|
{ |
|
|
|
auto choice = vm["ast"].as<OutputType>(); |
|
|
|
if (choice != OutputType::FILE) |
|
|
|
auto choice = args["ast"].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "Syntax trees:" << endl << endl; |
|
|
|
for (auto const& sourceCode: sourceCodes) |
|
|
@ -298,7 +312,7 @@ int main(int argc, char** argv) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (choice != OutputType::STDOUT) |
|
|
|
if (outputToFile(choice)) |
|
|
|
{ |
|
|
|
for (auto const& sourceCode: sourceCodes) |
|
|
|
{ |
|
|
@ -314,20 +328,20 @@ int main(int argc, char** argv) |
|
|
|
vector<string> contracts = compiler.getContractNames(); |
|
|
|
for (string const& contract: contracts) |
|
|
|
{ |
|
|
|
if (needStdout(vm)) |
|
|
|
if (needStdout(args)) |
|
|
|
cout << endl << "======= " << contract << " =======" << endl; |
|
|
|
|
|
|
|
// do we need EVM assembly?
|
|
|
|
if (vm.count("asm")) |
|
|
|
if (args.count("asm")) |
|
|
|
{ |
|
|
|
auto choice = vm["asm"].as<OutputType>(); |
|
|
|
if (choice != OutputType::FILE) |
|
|
|
auto choice = args["asm"].as<OutputType>(); |
|
|
|
if (outputToStdout(choice)) |
|
|
|
{ |
|
|
|
cout << "EVM assembly:" << endl; |
|
|
|
compiler.streamAssembly(cout, contract); |
|
|
|
} |
|
|
|
|
|
|
|
if (choice != OutputType::STDOUT) |
|
|
|
if (outputToFile(choice)) |
|
|
|
{ |
|
|
|
ofstream outFile(contract + ".evm"); |
|
|
|
compiler.streamAssembly(outFile, contract); |
|
|
@ -335,11 +349,11 @@ int main(int argc, char** argv) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
handleBytecode(vm, "opcodes", "Opcodes:", contract, compiler, ".opcodes"); |
|
|
|
handleBytecode(vm, "binary", "Binary:", contract, compiler, ".binary"); |
|
|
|
handleJson(vm, DocumentationType::ABI_INTERFACE, contract, compiler); |
|
|
|
handleJson(vm, DocumentationType::NATSPEC_DEV, contract, compiler); |
|
|
|
handleJson(vm, DocumentationType::NATSPEC_USER, contract, compiler); |
|
|
|
handleBytecode(args, "opcodes", "Opcodes:", contract, compiler, ".opcodes"); |
|
|
|
handleBytecode(args, "binary", "Binary:", contract, compiler, ".binary"); |
|
|
|
handleJson(args, DocumentationType::ABI_INTERFACE, contract, compiler); |
|
|
|
handleJson(args, DocumentationType::NATSPEC_DEV, contract, compiler); |
|
|
|
handleJson(args, DocumentationType::NATSPEC_USER, contract, compiler); |
|
|
|
} // end of contracts iteration
|
|
|
|
|
|
|
|
return 0; |
|
|
|