From 7ece4e4ed1b81f2c0410a7195efcde77842dcd31 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 10 Oct 2014 16:37:54 +0200 Subject: [PATCH 001/105] AST printer and command line tool, some fixes. --- CMakeLists.txt | 31 ++++++++++++++++++++ main.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..9224c109d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_policy(SET CMP0015 NEW) + +aux_source_directory(. SRC_LIST) + +include_directories(..) + +set(EXECUTABLE solc) + +add_executable(${EXECUTABLE} ${SRC_LIST}) + +target_link_libraries(${EXECUTABLE} solidity) +target_link_libraries(${EXECUTABLE} devcore) + +if ("${TARGET_PLATFORM}" STREQUAL "w64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + target_link_libraries(${EXECUTABLE} gcc) + target_link_libraries(${EXECUTABLE} gdi32) + target_link_libraries(${EXECUTABLE} ws2_32) + target_link_libraries(${EXECUTABLE} mswsock) + target_link_libraries(${EXECUTABLE} shlwapi) + target_link_libraries(${EXECUTABLE} iphlpapi) + target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) +elseif (UNIX) +else () + find_package(Threads REQUIRED) + target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) +endif () + +install( TARGETS ${EXECUTABLE} DESTINATION bin ) + diff --git a/main.cpp b/main.cpp new file mode 100644 index 000000000..6fca11a67 --- /dev/null +++ b/main.cpp @@ -0,0 +1,78 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace dev { +namespace solidity { + +ptr parseAST(std::string const& _source) +{ + ptr scanner = std::make_shared(CharStream(_source)); + Parser parser; + return parser.parse(scanner); +} + +} } // end namespaces + +void help() +{ + std::cout + << "Usage solc [OPTIONS] " << std::endl + << "Options:" << std::endl + << " -h,--help Show this help message and exit." << std::endl + << " -V,--version Show the version and exit." << std::endl; + exit(0); +} + +void version() +{ + std::cout + << "solc, the solidity complier commandline interface " << dev::Version << std::endl + << " by Christian , (c) 2014." << std::endl + << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << std::endl; + exit(0); +} + +int main(int argc, char** argv) +{ + std::string infile; + + for (int i = 1; i < argc; ++i) + { + std::string arg = argv[i]; + if (arg == "-h" || arg == "--help") + help(); + else if (arg == "-V" || arg == "--version") + version(); + else + infile = argv[i]; + } + + std::string src; + if (infile.empty()) + { + std::string s; + while (!std::cin.eof()) + { + getline(std::cin, s); + src.append(s); + } + } else { + src = dev::asString(dev::contents(infile)); + } + + std::cout << "Parsing..." << std::endl; + // @todo catch exception + dev::solidity::ptr ast = dev::solidity::parseAST(src); + std::cout << "Syntax tree for the contract:" << std::endl; + dev::solidity::ASTPrinter printer(ast, src); + printer.print(std::cout); + return 0; +} From 3e72f3d455951c447a92501d05380efe394f42f5 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2014 15:07:21 +0200 Subject: [PATCH 002/105] Name resolution. --- main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 6fca11a67..a92f466ec 100644 --- a/main.cpp +++ b/main.cpp @@ -8,11 +8,12 @@ #include #include #include +#include namespace dev { namespace solidity { -ptr parseAST(std::string const& _source) +ptr parseAST(std::string const& _source) { ptr scanner = std::make_shared(CharStream(_source)); Parser parser; @@ -70,9 +71,12 @@ int main(int argc, char** argv) std::cout << "Parsing..." << std::endl; // @todo catch exception - dev::solidity::ptr ast = dev::solidity::parseAST(src); + dev::solidity::ptr ast = dev::solidity::parseAST(src); std::cout << "Syntax tree for the contract:" << std::endl; dev::solidity::ASTPrinter printer(ast, src); printer.print(std::cout); + std::cout << "Resolving identifiers..." << std::endl; + dev::solidity::NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*ast.get()); return 0; } From 8c0b7054f3849fcf2b611c4aa21af6a53dd4b57e Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 16 Oct 2014 14:08:54 +0200 Subject: [PATCH 003/105] Corrected coding style. --- main.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index a92f466ec..a2b791462 100644 --- a/main.cpp +++ b/main.cpp @@ -10,8 +10,10 @@ #include #include -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ ptr parseAST(std::string const& _source) { @@ -20,15 +22,16 @@ ptr parseAST(std::string const& _source) return parser.parse(scanner); } -} } // end namespaces +} +} // end namespaces void help() { std::cout - << "Usage solc [OPTIONS] " << std::endl - << "Options:" << std::endl - << " -h,--help Show this help message and exit." << std::endl - << " -V,--version Show the version and exit." << std::endl; + << "Usage solc [OPTIONS] " << std::endl + << "Options:" << std::endl + << " -h,--help Show this help message and exit." << std::endl + << " -V,--version Show the version and exit." << std::endl; exit(0); } @@ -44,7 +47,6 @@ void version() int main(int argc, char** argv) { std::string infile; - for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; @@ -55,7 +57,6 @@ int main(int argc, char** argv) else infile = argv[i]; } - std::string src; if (infile.empty()) { @@ -65,10 +66,11 @@ int main(int argc, char** argv) getline(std::cin, s); src.append(s); } - } else { + } + else + { src = dev::asString(dev::contents(infile)); } - std::cout << "Parsing..." << std::endl; // @todo catch exception dev::solidity::ptr ast = dev::solidity::parseAST(src); From 309ac55e3665ba60fd72bb2e6084215b84af4b10 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 20 Oct 2014 14:00:37 +0200 Subject: [PATCH 004/105] Pointer type cleanup: Use ASTPointer only for AST nodes and shared_ptr for type pointer. --- main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index a2b791462..e155b0fe6 100644 --- a/main.cpp +++ b/main.cpp @@ -15,9 +15,9 @@ namespace dev namespace solidity { -ptr parseAST(std::string const& _source) +ASTPointer parseAST(std::string const& _source) { - ptr scanner = std::make_shared(CharStream(_source)); + ASTPointer scanner = std::make_shared(CharStream(_source)); Parser parser; return parser.parse(scanner); } @@ -73,7 +73,7 @@ int main(int argc, char** argv) } std::cout << "Parsing..." << std::endl; // @todo catch exception - dev::solidity::ptr ast = dev::solidity::parseAST(src); + dev::solidity::ASTPointer ast = dev::solidity::parseAST(src); std::cout << "Syntax tree for the contract:" << std::endl; dev::solidity::ASTPrinter printer(ast, src); printer.print(std::cout); From 892f15cd9fa9f1d6cda62f8aee932cf4d34c9f86 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 16 Oct 2014 17:56:10 +0200 Subject: [PATCH 005/105] Improved exceptions and reporting exceptions for command-line compiler. --- main.cpp | 95 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/main.cpp b/main.cpp index e155b0fe6..91cabfb33 100644 --- a/main.cpp +++ b/main.cpp @@ -9,21 +9,10 @@ #include #include #include +#include -namespace dev -{ -namespace solidity -{ - -ASTPointer parseAST(std::string const& _source) -{ - ASTPointer scanner = std::make_shared(CharStream(_source)); - Parser parser; - return parser.parse(scanner); -} - -} -} // end namespaces +using namespace dev; +using namespace solidity; void help() { @@ -44,6 +33,33 @@ void version() exit(0); } +void printSourcePart(std::ostream& _stream, Location const& _location, Scanner const& _scanner) +{ + int startLine; + int startColumn; + std::tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start); + _stream << " starting at line " << (startLine + 1) << ", column " << (startColumn + 1) << "\n"; + int endLine; + int endColumn; + std::tie(endLine, endColumn) = _scanner.translatePositionToLineColumn(_location.end); + if (startLine == endLine) + { + _stream << _scanner.getLineAtPosition(_location.start) << "\n" + << std::string(startColumn, ' ') << "^"; + if (endColumn > startColumn + 2) + _stream << std::string(endColumn - startColumn - 2, '-'); + if (endColumn > startColumn + 1) + _stream << "^"; + _stream << "\n"; + } + else + { + _stream << _scanner.getLineAtPosition(_location.start) << "\n" + << std::string(startColumn, ' ') << "^\n" + << "Spanning multiple lines.\n"; + } +} + int main(int argc, char** argv) { std::string infile; @@ -57,28 +73,57 @@ int main(int argc, char** argv) else infile = argv[i]; } - std::string src; + std::string sourceCode; if (infile.empty()) { std::string s; while (!std::cin.eof()) { getline(std::cin, s); - src.append(s); + sourceCode.append(s); } } else + sourceCode = asString(dev::contents(infile)); + + ASTPointer ast; + std::shared_ptr scanner = std::make_shared(CharStream(sourceCode)); + Parser parser; + try { - src = dev::asString(dev::contents(infile)); + ast = parser.parse(scanner); } - std::cout << "Parsing..." << std::endl; - // @todo catch exception - dev::solidity::ASTPointer ast = dev::solidity::parseAST(src); - std::cout << "Syntax tree for the contract:" << std::endl; - dev::solidity::ASTPrinter printer(ast, src); - printer.print(std::cout); - std::cout << "Resolving identifiers..." << std::endl; + catch (ParserError const& exc) + { + int line; + int column; + std::tie(line, column) = scanner->translatePositionToLineColumn(exc.getPosition()); + std::cerr << exc.what() << " at line " << (line + 1) << ", column " << (column + 1) << std::endl; + std::cerr << scanner->getLineAtPosition(exc.getPosition()) << std::endl; + std::cerr << std::string(column, ' ') << "^" << std::endl; + return -1; + } + dev::solidity::NameAndTypeResolver resolver; - resolver.resolveNamesAndTypes(*ast.get()); + try + { + resolver.resolveNamesAndTypes(*ast.get()); + } + catch (DeclarationError const& exc) + { + std::cerr << exc.what() << std::endl; + printSourcePart(std::cerr, exc.getLocation(), *scanner); + return -1; + } + catch (TypeError const& exc) + { + std::cerr << exc.what() << std::endl; + printSourcePart(std::cerr, exc.getLocation(), *scanner); + return -1; + } + + std::cout << "Syntax tree for the contract:" << std::endl; + dev::solidity::ASTPrinter printer(ast, sourceCode); + printer.print(std::cout); return 0; } From fa256b7f95e9c823d1dbac7edb3d15b01c12c981 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 23 Oct 2014 19:22:30 +0200 Subject: [PATCH 006/105] Use boost errinfo. --- main.cpp | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/main.cpp b/main.cpp index 91cabfb33..ba0b6ccf7 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace dev; using namespace solidity; @@ -33,33 +34,6 @@ void version() exit(0); } -void printSourcePart(std::ostream& _stream, Location const& _location, Scanner const& _scanner) -{ - int startLine; - int startColumn; - std::tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start); - _stream << " starting at line " << (startLine + 1) << ", column " << (startColumn + 1) << "\n"; - int endLine; - int endColumn; - std::tie(endLine, endColumn) = _scanner.translatePositionToLineColumn(_location.end); - if (startLine == endLine) - { - _stream << _scanner.getLineAtPosition(_location.start) << "\n" - << std::string(startColumn, ' ') << "^"; - if (endColumn > startColumn + 2) - _stream << std::string(endColumn - startColumn - 2, '-'); - if (endColumn > startColumn + 1) - _stream << "^"; - _stream << "\n"; - } - else - { - _stream << _scanner.getLineAtPosition(_location.start) << "\n" - << std::string(startColumn, ' ') << "^\n" - << "Spanning multiple lines.\n"; - } -} - int main(int argc, char** argv) { std::string infile; @@ -93,14 +67,9 @@ int main(int argc, char** argv) { ast = parser.parse(scanner); } - catch (ParserError const& exc) + catch (ParserError const& exception) { - int line; - int column; - std::tie(line, column) = scanner->translatePositionToLineColumn(exc.getPosition()); - std::cerr << exc.what() << " at line " << (line + 1) << ", column " << (column + 1) << std::endl; - std::cerr << scanner->getLineAtPosition(exc.getPosition()) << std::endl; - std::cerr << std::string(column, ' ') << "^" << std::endl; + SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Parser error", *scanner); return -1; } @@ -109,16 +78,14 @@ int main(int argc, char** argv) { resolver.resolveNamesAndTypes(*ast.get()); } - catch (DeclarationError const& exc) + catch (DeclarationError const& exception) { - std::cerr << exc.what() << std::endl; - printSourcePart(std::cerr, exc.getLocation(), *scanner); + SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Declaration error", *scanner); return -1; } - catch (TypeError const& exc) + catch (TypeError const& exception) { - std::cerr << exc.what() << std::endl; - printSourcePart(std::cerr, exc.getLocation(), *scanner); + SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Type error", *scanner); return -1; } From 221975bce81940628660aa264001eaf9cc48dd95 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 20 Oct 2014 12:41:56 +0200 Subject: [PATCH 007/105] Expression compiler. --- main.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/main.cpp b/main.cpp index ba0b6ccf7..221ab962e 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include using namespace dev; @@ -34,6 +35,35 @@ void version() exit(0); } + +/// Helper class that extracts the first expression in an AST. +class FirstExpressionExtractor: private ASTVisitor +{ +public: + FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); } + Expression* getExpression() const { return m_expression; } +private: + virtual bool visit(Expression& _expression) override { return checkExpression(_expression); } + virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); } + virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); } + virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); } + virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); } + virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); } + virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); } + virtual bool visit(PrimaryExpression& _expression) override { return checkExpression(_expression); } + virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); } + virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); } + virtual bool visit(Literal& _expression) override { return checkExpression(_expression); } + bool checkExpression(Expression& _expression) + { + if (m_expression == nullptr) + m_expression = &_expression; + return false; + } +private: + Expression* m_expression; +}; + int main(int argc, char** argv) { std::string infile; @@ -92,5 +122,16 @@ int main(int argc, char** argv) std::cout << "Syntax tree for the contract:" << std::endl; dev::solidity::ASTPrinter printer(ast, sourceCode); printer.print(std::cout); + + FirstExpressionExtractor extractor(*ast); + + CompilerContext context; + ExpressionCompiler compiler(context); + compiler.compile(*extractor.getExpression()); + bytes instructions = compiler.getAssembledBytecode(); + // debug + std::cout << "Bytecode for the first expression: " << std::endl; + std::cout << eth::disassemble(instructions) << std::endl; + return 0; } From c9f62cefda53f0638a87847d25e6160bcdd9bb36 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 25 Oct 2014 17:13:40 +0200 Subject: [PATCH 008/105] Remove stupid assertion. Add licence header to solc. --- main.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/main.cpp b/main.cpp index ba0b6ccf7..1acdefd8c 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,24 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * Solidity abstract syntax tree. + */ #include #include From fd347fbf4ef7ed3214d38074dfce8a87a5022833 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 25 Oct 2014 17:56:44 +0200 Subject: [PATCH 009/105] CMakeLists library dependency cleanup for libdevcore, libevmface, libsolidity and solc. Fixes #417. --- CMakeLists.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9224c109d..386d4a1a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,23 +9,6 @@ set(EXECUTABLE solc) add_executable(${EXECUTABLE} ${SRC_LIST}) target_link_libraries(${EXECUTABLE} solidity) -target_link_libraries(${EXECUTABLE} devcore) - -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") - target_link_libraries(${EXECUTABLE} gcc) - target_link_libraries(${EXECUTABLE} gdi32) - target_link_libraries(${EXECUTABLE} ws2_32) - target_link_libraries(${EXECUTABLE} mswsock) - target_link_libraries(${EXECUTABLE} shlwapi) - target_link_libraries(${EXECUTABLE} iphlpapi) - target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -elseif (UNIX) -else () - find_package(Threads REQUIRED) - target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) -endif () install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 2e5e7e676240e49d8e2a3ddc0ef53afd50a7f47c Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 25 Oct 2014 18:30:43 +0200 Subject: [PATCH 010/105] Corrected file description. --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 1acdefd8c..0843cfa02 100644 --- a/main.cpp +++ b/main.cpp @@ -17,7 +17,7 @@ /** * @author Christian * @date 2014 - * Solidity abstract syntax tree. + * Solidity commandline compiler. */ #include From 3306835c9d880f6a056b5ed22e8d7fd0e751719f Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 28 Oct 2014 16:51:26 +0100 Subject: [PATCH 011/105] Asterisk-syntax for doxygen class documentation. --- main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 221ab962e..33e8db794 100644 --- a/main.cpp +++ b/main.cpp @@ -36,7 +36,9 @@ void version() } -/// Helper class that extracts the first expression in an AST. +/** + * Helper class that extracts the first expression in an AST. + */ class FirstExpressionExtractor: private ASTVisitor { public: From 03a6cf0e81407df00742fe42929bdbdca89473c7 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 25 Oct 2014 16:52:22 +0200 Subject: [PATCH 012/105] Compiler for assignments. --- main.cpp | 60 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/main.cpp b/main.cpp index f5c4c8a0f..24f07d952 100644 --- a/main.cpp +++ b/main.cpp @@ -34,25 +34,24 @@ #include #include +using namespace std; using namespace dev; using namespace solidity; void help() { - std::cout - << "Usage solc [OPTIONS] " << std::endl - << "Options:" << std::endl - << " -h,--help Show this help message and exit." << std::endl - << " -V,--version Show the version and exit." << std::endl; + cout << "Usage solc [OPTIONS] " << endl + << "Options:" << endl + << " -h,--help Show this help message and exit." << endl + << " -V,--version Show the version and exit." << endl; exit(0); } void version() { - std::cout - << "solc, the solidity complier commandline interface " << dev::Version << std::endl - << " by Christian , (c) 2014." << std::endl - << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << std::endl; + cout << "solc, the solidity complier commandline interface " << dev::Version << endl + << " by Christian , (c) 2014." << endl + << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; exit(0); } @@ -87,10 +86,10 @@ private: int main(int argc, char** argv) { - std::string infile; + string infile; for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; + string arg = argv[i]; if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") @@ -98,13 +97,13 @@ int main(int argc, char** argv) else infile = argv[i]; } - std::string sourceCode; + string sourceCode; if (infile.empty()) { - std::string s; - while (!std::cin.eof()) + string s; + while (!cin.eof()) { - getline(std::cin, s); + getline(cin, s); sourceCode.append(s); } } @@ -112,7 +111,7 @@ int main(int argc, char** argv) sourceCode = asString(dev::contents(infile)); ASTPointer ast; - std::shared_ptr scanner = std::make_shared(CharStream(sourceCode)); + shared_ptr scanner = make_shared(CharStream(sourceCode)); Parser parser; try { @@ -120,39 +119,48 @@ int main(int argc, char** argv) } catch (ParserError const& exception) { - SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Parser error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner); return -1; } - dev::solidity::NameAndTypeResolver resolver; + NameAndTypeResolver resolver; try { resolver.resolveNamesAndTypes(*ast.get()); } catch (DeclarationError const& exception) { - SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Declaration error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner); return -1; } catch (TypeError const& exception) { - SourceReferenceFormatter::printExceptionInformation(std::cerr, exception, "Type error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner); return -1; } - std::cout << "Syntax tree for the contract:" << std::endl; + cout << "Syntax tree for the contract:" << endl; dev::solidity::ASTPrinter printer(ast, sourceCode); - printer.print(std::cout); + printer.print(cout); FirstExpressionExtractor extractor(*ast); CompilerContext context; ExpressionCompiler compiler(context); - compiler.compile(*extractor.getExpression()); + try + { + compiler.compile(*extractor.getExpression()); + } + catch (CompilerError const& exception) + { + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner); + return -1; + } + bytes instructions = compiler.getAssembledBytecode(); - // debug - std::cout << "Bytecode for the first expression: " << std::endl; - std::cout << eth::disassemble(instructions) << std::endl; + + cout << "Bytecode for the first expression: " << endl; + cout << eth::disassemble(instructions) << endl; return 0; } From 877aa91c57bb9cda410a7b521ed3b7630b5ae2dc Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 30 Oct 2014 01:20:32 +0100 Subject: [PATCH 013/105] Contract compiler and also add ExpressionStatement to AST. ExpressionStatement functions as glue between Statements and Expressions. This way it is possible to detect when the border between statements and expressions is crossed while walking the AST. Note that ExpressionStatement is not the only border, almost every statement can contains expressions. --- main.cpp | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/main.cpp b/main.cpp index 24f07d952..945b53db5 100644 --- a/main.cpp +++ b/main.cpp @@ -55,35 +55,6 @@ void version() exit(0); } - -/// Helper class that extracts the first expression in an AST. -class FirstExpressionExtractor: private ASTVisitor -{ -public: - FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); } - Expression* getExpression() const { return m_expression; } -private: - virtual bool visit(Expression& _expression) override { return checkExpression(_expression); } - virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); } - virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); } - virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); } - virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); } - virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); } - virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); } - virtual bool visit(PrimaryExpression& _expression) override { return checkExpression(_expression); } - virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); } - virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); } - virtual bool visit(Literal& _expression) override { return checkExpression(_expression); } - bool checkExpression(Expression& _expression) - { - if (m_expression == nullptr) - m_expression = &_expression; - return false; - } -private: - Expression* m_expression; -}; - int main(int argc, char** argv) { string infile; @@ -143,13 +114,10 @@ int main(int argc, char** argv) dev::solidity::ASTPrinter printer(ast, sourceCode); printer.print(cout); - FirstExpressionExtractor extractor(*ast); - - CompilerContext context; - ExpressionCompiler compiler(context); + bytes instructions; try { - compiler.compile(*extractor.getExpression()); + instructions = Compiler::compile(*ast); } catch (CompilerError const& exception) { @@ -157,10 +125,9 @@ int main(int argc, char** argv) return -1; } - bytes instructions = compiler.getAssembledBytecode(); - - cout << "Bytecode for the first expression: " << endl; + cout << "EVM assembly: " << endl; cout << eth::disassemble(instructions) << endl; + cout << "Binary: " << toHex(instructions) << endl; return 0; } From 9eb7fd274c9af259ea1718af8ab0180841f535f3 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 30 Oct 2014 18:15:25 +0100 Subject: [PATCH 014/105] Function selector and variable (un)packing. --- main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 945b53db5..1cf466c72 100644 --- a/main.cpp +++ b/main.cpp @@ -115,9 +115,11 @@ int main(int argc, char** argv) printer.print(cout); bytes instructions; + Compiler compiler; try { - instructions = Compiler::compile(*ast); + compiler.compileContract(*ast); + instructions = compiler.getAssembledBytecode(); } catch (CompilerError const& exception) { @@ -125,7 +127,9 @@ int main(int argc, char** argv) return -1; } - cout << "EVM assembly: " << endl; + cout << "EVM assembly:" << endl; + compiler.streamAssembly(cout); + cout << "Opcodes:" << endl; cout << eth::disassemble(instructions) << endl; cout << "Binary: " << toHex(instructions) << endl; From 8c384232eb6c729021a5bd89bd2eccea7c2af34c Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 14:20:56 +0100 Subject: [PATCH 015/105] Converted all asserts to exceptions. --- main.cpp | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/main.cpp b/main.cpp index 1cf466c72..04fee2905 100644 --- a/main.cpp +++ b/main.cpp @@ -84,21 +84,27 @@ int main(int argc, char** argv) ASTPointer ast; shared_ptr scanner = make_shared(CharStream(sourceCode)); Parser parser; + bytes instructions; + Compiler compiler; try { ast = parser.parse(scanner); + + NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*ast.get()); + + cout << "Syntax tree for the contract:" << endl; + dev::solidity::ASTPrinter printer(ast, sourceCode); + printer.print(cout); + + compiler.compileContract(*ast); + instructions = compiler.getAssembledBytecode(); } catch (ParserError const& exception) { SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner); return -1; } - - NameAndTypeResolver resolver; - try - { - resolver.resolveNamesAndTypes(*ast.get()); - } catch (DeclarationError const& exception) { SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner); @@ -109,23 +115,26 @@ int main(int argc, char** argv) SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner); return -1; } - - cout << "Syntax tree for the contract:" << endl; - dev::solidity::ASTPrinter printer(ast, sourceCode); - printer.print(cout); - - bytes instructions; - Compiler compiler; - try - { - compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(); - } catch (CompilerError const& exception) { SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner); return -1; } + catch (InternalCompilerError const& exception) + { + cerr << "Internal compiler error: " << boost::diagnostic_information(exception) << endl; + return -1; + } + catch (Exception const& exception) + { + cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl; + return -1; + } + catch (...) + { + cerr << "Unknown exception during compilation." << endl; + return -1; + } cout << "EVM assembly:" << endl; compiler.streamAssembly(cout); From 7594813e1e4a29bc8197a4500e53c91c4c4e6424 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 6 Nov 2014 16:30:50 +0100 Subject: [PATCH 016/105] Option to activate the optimizer for solidity. --- main.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index 04fee2905..04fdc0ee1 100644 --- a/main.cpp +++ b/main.cpp @@ -42,7 +42,8 @@ void help() { cout << "Usage solc [OPTIONS] " << endl << "Options:" << endl - << " -h,--help Show this help message and exit." << endl + << " -o,--optimize Optimize the bytecode for size." << endl + << " -h,--help Show this help message and exit." << endl << " -V,--version Show the version and exit." << endl; exit(0); } @@ -58,10 +59,13 @@ void version() int main(int argc, char** argv) { string infile; + bool optimize = false; for (int i = 1; i < argc; ++i) { string arg = argv[i]; - if (arg == "-h" || arg == "--help") + if (arg == "-o" || arg == "--optimize") + optimize = true; + else if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") version(); @@ -98,7 +102,7 @@ int main(int argc, char** argv) printer.print(cout); compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(); + instructions = compiler.getAssembledBytecode(optimize); } catch (ParserError const& exception) { From a44bd8c987aa4921db4ace42d4dd5357eb9e2ac2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 10 Nov 2014 22:51:10 +0100 Subject: [PATCH 017/105] merge --- main.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index 04fee2905..04fdc0ee1 100644 --- a/main.cpp +++ b/main.cpp @@ -42,7 +42,8 @@ void help() { cout << "Usage solc [OPTIONS] " << endl << "Options:" << endl - << " -h,--help Show this help message and exit." << endl + << " -o,--optimize Optimize the bytecode for size." << endl + << " -h,--help Show this help message and exit." << endl << " -V,--version Show the version and exit." << endl; exit(0); } @@ -58,10 +59,13 @@ void version() int main(int argc, char** argv) { string infile; + bool optimize = false; for (int i = 1; i < argc; ++i) { string arg = argv[i]; - if (arg == "-h" || arg == "--help") + if (arg == "-o" || arg == "--optimize") + optimize = true; + else if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") version(); @@ -98,7 +102,7 @@ int main(int argc, char** argv) printer.print(cout); compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(); + instructions = compiler.getAssembledBytecode(optimize); } catch (ParserError const& exception) { From ad4b027781a4f7b8adfd708b3b37c2b4bec99a83 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 11 Nov 2014 17:41:48 +0100 Subject: [PATCH 018/105] Provide interface for calls in JSON and some other formatting changes. --- main.cpp | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/main.cpp b/main.cpp index 04fdc0ee1..a7216e594 100644 --- a/main.cpp +++ b/main.cpp @@ -26,12 +26,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include using namespace std; @@ -85,48 +86,34 @@ int main(int argc, char** argv) else sourceCode = asString(dev::contents(infile)); - ASTPointer ast; - shared_ptr scanner = make_shared(CharStream(sourceCode)); - Parser parser; - bytes instructions; - Compiler compiler; + CompilerStack compiler; try { - ast = parser.parse(scanner); - - NameAndTypeResolver resolver; - resolver.resolveNamesAndTypes(*ast.get()); - - cout << "Syntax tree for the contract:" << endl; - dev::solidity::ASTPrinter printer(ast, sourceCode); - printer.print(cout); - - compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(optimize); + compiler.compile(sourceCode, optimize); } catch (ParserError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner()); return -1; } catch (DeclarationError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner()); return -1; } catch (TypeError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner()); return -1; } catch (CompilerError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner()); return -1; } catch (InternalCompilerError const& exception) { - cerr << "Internal compiler error: " << boost::diagnostic_information(exception) << endl; + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner()); return -1; } catch (Exception const& exception) @@ -140,11 +127,15 @@ int main(int argc, char** argv) return -1; } + cout << "Syntax tree for the contract:" << endl; + ASTPrinter printer(compiler.getAST(), sourceCode); + printer.print(cout); cout << "EVM assembly:" << endl; compiler.streamAssembly(cout); cout << "Opcodes:" << endl; - cout << eth::disassemble(instructions) << endl; - cout << "Binary: " << toHex(instructions) << endl; + cout << eth::disassemble(compiler.getBytecode()) << endl; + cout << "Binary: " << toHex(compiler.getBytecode()) << endl; + cout << "Interface specification: " << compiler.getInterface() << endl; return 0; } From 0cc271fae9101ac27dad3491020a3b599d533254 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 2 Dec 2014 11:03:34 +0100 Subject: [PATCH 019/105] Handle absence of Natspec doc and add option to solc --- main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main.cpp b/main.cpp index a7216e594..6ca130a79 100644 --- a/main.cpp +++ b/main.cpp @@ -136,6 +136,7 @@ int main(int argc, char** argv) cout << eth::disassemble(compiler.getBytecode()) << endl; cout << "Binary: " << toHex(compiler.getBytecode()) << endl; cout << "Interface specification: " << compiler.getInterface() << endl; + cout << "Natspec documentation: " << compiler.getDocumentation() << endl; return 0; } From e6902e070e5952d7d732a537edc81331609bc55b Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 3 Dec 2014 07:46:55 +0100 Subject: [PATCH 020/105] Import directive. --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index a7216e594..76d8ef6b7 100644 --- a/main.cpp +++ b/main.cpp @@ -127,7 +127,7 @@ int main(int argc, char** argv) return -1; } - cout << "Syntax tree for the contract:" << endl; + cout << "Syntax tree for the source unit:" << endl; ASTPrinter printer(compiler.getAST(), sourceCode); printer.print(cout); cout << "EVM assembly:" << endl; From d0758ccf1e07b162a894b5901c863a6bfa4a4636 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 3 Dec 2014 13:50:04 +0100 Subject: [PATCH 021/105] Separate user and dev natspec documentation - plus other small changes according to the spec --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 6ca130a79..29239a717 100644 --- a/main.cpp +++ b/main.cpp @@ -136,7 +136,7 @@ int main(int argc, char** argv) cout << eth::disassemble(compiler.getBytecode()) << endl; cout << "Binary: " << toHex(compiler.getBytecode()) << endl; cout << "Interface specification: " << compiler.getInterface() << endl; - cout << "Natspec documentation: " << compiler.getDocumentation() << endl; + cout << "Natspec user documentation: " << compiler.getUserDocumentation() << endl; return 0; } From 9ce5a4ebcfdea8751062aeae7dfa4de604c2c356 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 3 Dec 2014 16:40:37 +0100 Subject: [PATCH 022/105] Moving all Interface and Documentation functionality to own class - Creating the Interface Handler class which will take care of the parsing of Natspec comments and of interfacing with and outputing to JSON files. - Will also handle the ABI interface creation --- main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 29239a717..daeb2707c 100644 --- a/main.cpp +++ b/main.cpp @@ -135,8 +135,9 @@ int main(int argc, char** argv) cout << "Opcodes:" << endl; cout << eth::disassemble(compiler.getBytecode()) << endl; cout << "Binary: " << toHex(compiler.getBytecode()) << endl; - cout << "Interface specification: " << compiler.getInterface() << endl; - cout << "Natspec user documentation: " << compiler.getUserDocumentation() << endl; + cout << "Interface specification: " << compiler.getJsonDocumentation(ABI_INTERFACE) << endl; + cout << "Natspec user documentation: " << compiler.getJsonDocumentation(NATSPEC_USER) << endl; + cout << "Natspec developer documentation: " << compiler.getJsonDocumentation(NATSPEC_DEV) << endl; return 0; } From aae508748e0537c1afc0d9507c427cd5ca30189a Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 3 Dec 2014 18:52:28 +0100 Subject: [PATCH 023/105] Improved external interface for multi-source and multi-contract compilation. --- main.cpp | 55 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/main.cpp b/main.cpp index 76d8ef6b7..3284be74a 100644 --- a/main.cpp +++ b/main.cpp @@ -59,7 +59,7 @@ void version() int main(int argc, char** argv) { - string infile; + vector infiles; bool optimize = false; for (int i = 1; i < argc; ++i) { @@ -71,49 +71,52 @@ int main(int argc, char** argv) else if (arg == "-V" || arg == "--version") version(); else - infile = argv[i]; + infiles.push_back(argv[i]); } - string sourceCode; - if (infile.empty()) + map sourceCodes; + if (infiles.empty()) { string s; while (!cin.eof()) { getline(cin, s); - sourceCode.append(s); + sourceCodes[""].append(s); } } else - sourceCode = asString(dev::contents(infile)); + for (string const& infile: infiles) + sourceCodes[infile] = asString(dev::contents(infile)); CompilerStack compiler; try { - compiler.compile(sourceCode, optimize); + for (auto const& sourceCode: sourceCodes) + compiler.addSource(sourceCode.first, sourceCode.second); + compiler.compile(optimize); } catch (ParserError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner()); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler); return -1; } catch (DeclarationError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner()); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler); return -1; } catch (TypeError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner()); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler); return -1; } catch (CompilerError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner()); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler); return -1; } catch (InternalCompilerError const& exception) { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner()); + SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler); return -1; } catch (Exception const& exception) @@ -127,15 +130,25 @@ int main(int argc, char** argv) return -1; } - cout << "Syntax tree for the source unit:" << endl; - ASTPrinter printer(compiler.getAST(), sourceCode); - printer.print(cout); - cout << "EVM assembly:" << endl; - compiler.streamAssembly(cout); - cout << "Opcodes:" << endl; - cout << eth::disassemble(compiler.getBytecode()) << endl; - cout << "Binary: " << toHex(compiler.getBytecode()) << endl; - cout << "Interface specification: " << compiler.getInterface() << endl; + cout << "Syntax trees:" << endl << endl; + for (auto const& sourceCode: sourceCodes) + { + cout << endl << "======= " << sourceCode.first << " =======" << endl; + ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); + printer.print(cout); + } + vector contracts = compiler.getContractNames(); + cout << endl << "Contracts:" << endl; + for (string const& contract: contracts) + { + cout << endl << "======= " << contract << " =======" << endl + << "EVM assembly:" << endl; + compiler.streamAssembly(cout, contract); + cout << "Opcodes:" << endl + << eth::disassemble(compiler.getBytecode(contract)) << endl + << "Binary: " << toHex(compiler.getBytecode(contract)) << endl + << "Interface specification: " << compiler.getInterface(contract) << endl; + } return 0; } From d8a65552d81454e0d3fa761d90cfe35263aafacf Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 4 Dec 2014 09:55:54 +0100 Subject: [PATCH 024/105] removed automocs --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 386d4a1a8..ab402ed8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_policy(SET CMP0015 NEW) +set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) From 122b42579ec9fa2d086247e07b03fbc68463c569 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 5 Dec 2014 15:50:39 +0100 Subject: [PATCH 025/105] Replacing old cstyle enums with c++11 enums in natspec --- main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index daeb2707c..21ffc98cc 100644 --- a/main.cpp +++ b/main.cpp @@ -135,9 +135,9 @@ int main(int argc, char** argv) cout << "Opcodes:" << endl; cout << eth::disassemble(compiler.getBytecode()) << endl; cout << "Binary: " << toHex(compiler.getBytecode()) << endl; - cout << "Interface specification: " << compiler.getJsonDocumentation(ABI_INTERFACE) << endl; - cout << "Natspec user documentation: " << compiler.getJsonDocumentation(NATSPEC_USER) << endl; - cout << "Natspec developer documentation: " << compiler.getJsonDocumentation(NATSPEC_DEV) << endl; + cout << "Interface specification: " << compiler.getJsonDocumentation(DocumentationType::ABI_INTERFACE) << endl; + cout << "Natspec user documentation: " << compiler.getJsonDocumentation(DocumentationType::NATSPEC_USER) << endl; + cout << "Natspec developer documentation: " << compiler.getJsonDocumentation(DocumentationType::NATSPEC_DEV) << endl; return 0; } From 9b3417903b155441b313494265627d568592af5d Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 11:29:38 +0100 Subject: [PATCH 026/105] solidity compiling under msvc && boosts cmake file fixed --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab402ed8e..203a616b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,13 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE solc) -add_executable(${EXECUTABLE} ${SRC_LIST}) +file(GLOB HEADERS "*.h") +add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} solidity) From 9dd74d13d38fd86147d4aec621756988667d3800 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 19:07:51 +0100 Subject: [PATCH 027/105] solc working --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 203a616b4..303318502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From ed28d3013b1d3d2d77de2b40122c67f246fd6c1b Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 7 Dec 2014 19:55:40 +0100 Subject: [PATCH 028/105] serpent compiling under msvc --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 303318502..203a616b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,6 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From d4d0b07c35123590230b30096fca249643b93221 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 12:42:29 +0100 Subject: [PATCH 029/105] using boost::program_options for argument parsing --- CMakeLists.txt | 1 + main.cpp | 59 +++++++++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 386d4a1a8..689700a64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(EXECUTABLE solc) add_executable(${EXECUTABLE} ${SRC_LIST}) +target_link_libraries(${EXECUTABLE} boost_program_options) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) diff --git a/main.cpp b/main.cpp index 61f73b45d..1f8348746 100644 --- a/main.cpp +++ b/main.cpp @@ -23,6 +23,9 @@ #include #include +#include + +#include "BuildInfo.h" #include #include #include @@ -38,43 +41,45 @@ using namespace std; using namespace dev; using namespace solidity; - -void help() -{ - cout << "Usage solc [OPTIONS] " << endl - << "Options:" << endl - << " -o,--optimize Optimize the bytecode for size." << endl - << " -h,--help Show this help message and exit." << endl - << " -V,--version Show the version and exit." << endl; - exit(0); -} +namespace po = boost::program_options; void version() { cout << "solc, the solidity complier commandline interface " << dev::Version << endl - << " by Christian , (c) 2014." << endl + << " by Christian and Lefteris , (c) 2014." << endl << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; exit(0); } int main(int argc, char** argv) { - vector infiles; - bool optimize = false; - for (int i = 1; i < argc; ++i) - { - string arg = argv[i]; - if (arg == "-o" || arg == "--optimize") - optimize = true; - else if (arg == "-h" || arg == "--help") - help(); - else if (arg == "-V" || arg == "--version") - version(); - else - infiles.push_back(argv[i]); + // 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()->default_value(false), "Optimize bytecode for size") + ("input-file", po::value>(), "input file"); + + // All positional options should be interpreted as input files + po::positional_options_description p; + p.add("input-file", -1); + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); + po::notify(vm); + + if (vm.count("help")) { + cout << desc; + return 0; + } + + if (vm.count("version")) { + version(); + return 0; } map sourceCodes; - if (infiles.empty()) + if (!vm.count("input-file")) { string s; while (!cin.eof()) @@ -84,7 +89,7 @@ int main(int argc, char** argv) } } else - for (string const& infile: infiles) + for (string const& infile: vm["input-file"].as>()) sourceCodes[infile] = asString(dev::contents(infile)); CompilerStack compiler; @@ -92,7 +97,7 @@ int main(int argc, char** argv) { for (auto const& sourceCode: sourceCodes) compiler.addSource(sourceCode.first, sourceCode.second); - compiler.compile(optimize); + compiler.compile( vm["optimize"].as()); } catch (ParserError const& exception) { From 7193ac2edc3ea63aa5712a10ce0b8738eb6ebf6a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 13:30:55 +0100 Subject: [PATCH 030/105] Unknown solc arguments are now ignored --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 1f8348746..6b16c1249 100644 --- a/main.cpp +++ b/main.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) p.add("input-file", -1); po::variables_map vm; - po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), vm); po::notify(vm); if (vm.count("help")) { From 3cb4562e5d6c58623a4868ea8d46cea65f9f4ca6 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 14:46:00 +0100 Subject: [PATCH 031/105] Solc cmdline option for ast outputting either to stdout or a file --- CMakeLists.txt | 1 + main.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 689700a64..84f87eb53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(EXECUTABLE solc) add_executable(${EXECUTABLE} ${SRC_LIST}) +target_link_libraries(${EXECUTABLE} boost_filesystem) target_link_libraries(${EXECUTABLE} boost_program_options) target_link_libraries(${EXECUTABLE} solidity) diff --git a/main.cpp b/main.cpp index 6b16c1249..c79ba52a6 100644 --- a/main.cpp +++ b/main.cpp @@ -22,8 +22,10 @@ #include #include +#include #include +#include #include "BuildInfo.h" #include @@ -51,6 +53,28 @@ void version() exit(0); } +enum class AstOutput +{ + STDOUT, + FILE, + BOTH +}; + +std::istream& operator>>(std::istream& _in, AstOutput& io_output) +{ + std::string token; + _in >> token; + if (token == "stdout") + io_output = AstOutput::STDOUT; + else if (token == "file") + io_output = AstOutput::FILE; + else if (token == "both") + io_output = AstOutput::BOTH; + else + throw boost::program_options::invalid_option_value(token); + return _in; +} + int main(int argc, char** argv) { // Declare the supported options. @@ -59,14 +83,27 @@ int main(int argc, char** argv) ("help", "Show help message and exit") ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") - ("input-file", po::value>(), "input file"); + ("input-file", po::value>(), "input file") + ("ast", po::value(), + "Request to output the AST of the contract. Legal values:\n" + "\tstdout: Print it to standar output\n" + "\tfile: Print it to a file with same name\n"); // 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::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), vm); + try + { + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), vm); + } + catch (po::error const& exception) + { + cout << exception.what() << endl; + return -1; + } po::notify(vm); if (vm.count("help")) { @@ -135,13 +172,36 @@ int main(int argc, char** argv) return -1; } - cout << "Syntax trees:" << endl << endl; - for (auto const& sourceCode: sourceCodes) + + // do we need AST output? + if (vm.count("ast")) { - cout << endl << "======= " << sourceCode.first << " =======" << endl; - ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); - printer.print(cout); + auto choice = vm["ast"].as(); + if (choice != AstOutput::FILE) + { + cout << "Syntax trees:" << endl << endl; + for (auto const& sourceCode: sourceCodes) + { + cout << endl << "======= " << sourceCode.first << " =======" << endl; + ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); + printer.print(cout); + } + } + + if (choice != AstOutput::STDOUT) + { + for (auto const& sourceCode: sourceCodes) + { + boost::filesystem::path p(sourceCode.first); + ofstream outFile(p.stem().string() + ".ast"); + ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); + printer.print(outFile); + outFile.close(); + } + } } + + vector contracts = compiler.getContractNames(); cout << endl << "Contracts:" << endl; for (string const& contract: contracts) From 501d6f4a2ccfa45782454a8229af3d6a2e727ad7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 15:05:23 +0100 Subject: [PATCH 032/105] Solc evm assembly to either file or stdout option --- main.cpp | 56 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/main.cpp b/main.cpp index c79ba52a6..96e834ff1 100644 --- a/main.cpp +++ b/main.cpp @@ -53,23 +53,28 @@ void version() exit(0); } -enum class AstOutput +enum class OutputType { STDOUT, FILE, BOTH }; -std::istream& operator>>(std::istream& _in, AstOutput& io_output) +#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" + +std::istream& operator>>(std::istream& _in, OutputType& io_output) { std::string token; _in >> token; if (token == "stdout") - io_output = AstOutput::STDOUT; + io_output = OutputType::STDOUT; else if (token == "file") - io_output = AstOutput::FILE; + io_output = OutputType::FILE; else if (token == "both") - io_output = AstOutput::BOTH; + io_output = OutputType::BOTH; else throw boost::program_options::invalid_option_value(token); return _in; @@ -84,10 +89,10 @@ int main(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - ("ast", po::value(), - "Request to output the AST of the contract. Legal values:\n" - "\tstdout: Print it to standar output\n" - "\tfile: Print it to a file with same name\n"); + ("ast", po::value(), + "Request to output the AST of the contract. " outputTypeStr) + ("asm", po::value(), + "Request to output the EVM assembly of the contract. " outputTypeStr); // All positional options should be interpreted as input files po::positional_options_description p; @@ -176,8 +181,8 @@ int main(int argc, char** argv) // do we need AST output? if (vm.count("ast")) { - auto choice = vm["ast"].as(); - if (choice != AstOutput::FILE) + auto choice = vm["ast"].as(); + if (choice != OutputType::FILE) { cout << "Syntax trees:" << endl << endl; for (auto const& sourceCode: sourceCodes) @@ -188,7 +193,7 @@ int main(int argc, char** argv) } } - if (choice != AstOutput::STDOUT) + if (choice != OutputType::STDOUT) { for (auto const& sourceCode: sourceCodes) { @@ -201,14 +206,33 @@ int main(int argc, char** argv) } } - vector contracts = compiler.getContractNames(); + // do we need EVM assembly? + if (vm.count("asm")) + { + auto choice = vm["asm"].as(); + for (string const& contract: contracts) + { + if (choice != OutputType::FILE) + { + cout << endl << "======= " << contract << " =======" << endl + << "EVM assembly:" << endl; + compiler.streamAssembly(cout, contract); + } + + if (choice != OutputType::STDOUT) + { + ofstream outFile(contract + ".evm"); + compiler.streamAssembly(outFile, contract); + outFile.close(); + } + } + } + + cout << endl << "Contracts:" << endl; for (string const& contract: contracts) { - cout << endl << "======= " << contract << " =======" << endl - << "EVM assembly:" << endl; - compiler.streamAssembly(cout, contract); cout << "Opcodes:" << endl << eth::disassemble(compiler.getBytecode(contract)) << endl << "Binary: " << toHex(compiler.getBytecode(contract)) << endl From 5ccf5b5c9e884e4d5dc342a91b4f977c2986b39f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 15:21:20 +0100 Subject: [PATCH 033/105] Solc option to output binary and opcode --- main.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/main.cpp b/main.cpp index 96e834ff1..38295dcc3 100644 --- a/main.cpp +++ b/main.cpp @@ -92,7 +92,11 @@ int main(int argc, char** argv) ("ast", po::value(), "Request to output the AST of the contract. " outputTypeStr) ("asm", po::value(), - "Request to output the EVM assembly of the contract. " outputTypeStr); + "Request to output the EVM assembly of the contract. " outputTypeStr) + ("opcodes", po::value(), + "Request to output the Opcodes of the contract. " outputTypeStr) + ("binary", po::value(), + "Request to output the contract in binary (hexadecimal). " outputTypeStr); // All positional options should be interpreted as input files po::positional_options_description p; @@ -207,16 +211,17 @@ int main(int argc, char** argv) } vector contracts = compiler.getContractNames(); - // do we need EVM assembly? - if (vm.count("asm")) + for (string const& contract: contracts) { - auto choice = vm["asm"].as(); - for (string const& contract: contracts) + cout << endl << "======= " << contract << " =======" << endl; + + // do we need EVM assembly? + if (vm.count("asm")) { + auto choice = vm["asm"].as(); if (choice != OutputType::FILE) { - cout << endl << "======= " << contract << " =======" << endl - << "EVM assembly:" << endl; + cout << "EVM assembly:" << endl; compiler.streamAssembly(cout, contract); } @@ -227,16 +232,49 @@ int main(int argc, char** argv) outFile.close(); } } - } + // do we need opcodes? + if (vm.count("opcodes")) + { + auto choice = vm["opcodes"].as(); + if (choice != OutputType::FILE) + { + cout << "Opcodes:" << endl; + cout << eth::disassemble(compiler.getBytecode(contract)) << endl; + } + + if (choice != OutputType::STDOUT) + { + ofstream outFile(contract + ".opcodes"); + outFile << eth::disassemble(compiler.getBytecode(contract)); + outFile.close(); + } + } + + // do we need binary? + if (vm.count("binary")) + { + auto choice = vm["binary"].as(); + if (choice != OutputType::FILE) + { + cout << "Binary:" << endl; + cout << toHex(compiler.getBytecode(contract)) << endl; + } + + if (choice != OutputType::STDOUT) + { // TODO: Think, if we really want that? Could simply output to normal binary + ofstream outFile(contract + ".bin"); + outFile << toHex(compiler.getBytecode(contract)); + outFile.close(); + } + } + + } // end of contracts iteration cout << endl << "Contracts:" << endl; for (string const& contract: contracts) { - cout << "Opcodes:" << endl - << eth::disassemble(compiler.getBytecode(contract)) << endl - << "Binary: " << toHex(compiler.getBytecode(contract)) << endl - << "Interface specification: " << compiler.getJsonDocumentation(contract, DocumentationType::ABI_INTERFACE) << endl + cout << "Interface specification: " << compiler.getJsonDocumentation(contract, DocumentationType::ABI_INTERFACE) << endl << "Natspec user documentation: " << compiler.getJsonDocumentation(contract, DocumentationType::NATSPEC_USER) << endl << "Natspec developer documentation: " << compiler.getJsonDocumentation(contract, DocumentationType::NATSPEC_DEV) << endl; } From 88cbcdf98a1816b171fba2f56821a5a35474e0a2 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 8 Dec 2014 16:42:56 +0100 Subject: [PATCH 034/105] Solc gets arguments for interface and documentation related output --- main.cpp | 155 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 109 insertions(+), 46 deletions(-) diff --git a/main.cpp b/main.cpp index 38295dcc3..8650d429c 100644 --- a/main.cpp +++ b/main.cpp @@ -80,6 +80,96 @@ std::istream& operator>>(std::istream& _in, OutputType& io_output) return _in; } +static void handleBytecode(po::variables_map const& vm, + char const* _argName, + string const& _title, + string const& _contract, + CompilerStack&_compiler, + string const& _suffix) +{ + if (vm.count(_argName)) + { + auto choice = vm[_argName].as(); + if (choice != OutputType::FILE) + { + cout << _title << endl; + if (_suffix == "opcodes") + cout << _compiler.getBytecode(_contract) << endl; + else + cout << toHex(_compiler.getBytecode(_contract)) << endl; + } + + if (choice != OutputType::STDOUT) + { + ofstream outFile(_contract + _suffix); + if (_suffix == "opcodes") + outFile << _compiler.getBytecode(_contract); + else + outFile << toHex(_compiler.getBytecode(_contract)); + outFile.close(); + } + } +} + +static void handleJson(po::variables_map const& _vm, + DocumentationType _type, + string const& _contract, + CompilerStack&_compiler) +{ + 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 (_vm.count(argName.c_str())) + { + auto choice = _vm[argName.c_str()].as(); + if (choice != OutputType::FILE) + { + cout << title << endl; + cout << _compiler.getJsonDocumentation(_contract, _type); + } + + if (choice != OutputType::STDOUT) + { + ofstream outFile(_contract + suffix); + outFile << _compiler.getJsonDocumentation(_contract, _type); + outFile.close(); + } + } +} + +static inline bool argToStdout(po::variables_map const& _vm, const char* _name) +{ + return _vm.count(_name) && _vm[_name].as() != OutputType::FILE; +} + +static bool needStdout(po::variables_map const& _vm) +{ + return argToStdout(_vm, "abi") || argToStdout(_vm, "natspec-user") || argToStdout(_vm, "natspec-dev") || + argToStdout(_vm, "asm") || argToStdout(_vm, "opcodes") || argToStdout(_vm, "binary"); +} + int main(int argc, char** argv) { // Declare the supported options. @@ -96,7 +186,13 @@ int main(int argc, char** argv) ("opcodes", po::value(), "Request to output the Opcodes of the contract. " outputTypeStr) ("binary", po::value(), - "Request to output the contract in binary (hexadecimal). " outputTypeStr); + "Request to output the contract in binary (hexadecimal). " outputTypeStr) + ("abi", po::value(), + "Request to output the contract's ABI interface. " outputTypeStr) + ("natspec-user", po::value(), + "Request to output the contract's Natspec user documentation. " outputTypeStr) + ("natspec-dev", po::value(), + "Request to output the contract's Natspec developer documentation. " outputTypeStr); // All positional options should be interpreted as input files po::positional_options_description p; @@ -124,6 +220,8 @@ int main(int argc, char** argv) version(); return 0; } + + // create a map of input files to source code strings map sourceCodes; if (!vm.count("input-file")) { @@ -138,6 +236,7 @@ int main(int argc, char** argv) for (string const& infile: vm["input-file"].as>()) sourceCodes[infile] = asString(dev::contents(infile)); + // parse the files CompilerStack compiler; try { @@ -182,6 +281,8 @@ int main(int argc, char** argv) } + /* -- act depending on the provided arguments -- */ + // do we need AST output? if (vm.count("ast")) { @@ -213,7 +314,8 @@ int main(int argc, char** argv) vector contracts = compiler.getContractNames(); for (string const& contract: contracts) { - cout << endl << "======= " << contract << " =======" << endl; + if (needStdout(vm)) + cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? if (vm.count("asm")) @@ -233,51 +335,12 @@ int main(int argc, char** argv) } } - // do we need opcodes? - if (vm.count("opcodes")) - { - auto choice = vm["opcodes"].as(); - if (choice != OutputType::FILE) - { - cout << "Opcodes:" << endl; - cout << eth::disassemble(compiler.getBytecode(contract)) << endl; - } - - if (choice != OutputType::STDOUT) - { - ofstream outFile(contract + ".opcodes"); - outFile << eth::disassemble(compiler.getBytecode(contract)); - outFile.close(); - } - } - - // do we need binary? - if (vm.count("binary")) - { - auto choice = vm["binary"].as(); - if (choice != OutputType::FILE) - { - cout << "Binary:" << endl; - cout << toHex(compiler.getBytecode(contract)) << endl; - } - - if (choice != OutputType::STDOUT) - { // TODO: Think, if we really want that? Could simply output to normal binary - ofstream outFile(contract + ".bin"); - outFile << toHex(compiler.getBytecode(contract)); - outFile.close(); - } - } - + 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); } // end of contracts iteration - cout << endl << "Contracts:" << endl; - for (string const& contract: contracts) - { - cout << "Interface specification: " << compiler.getJsonDocumentation(contract, DocumentationType::ABI_INTERFACE) << endl - << "Natspec user documentation: " << compiler.getJsonDocumentation(contract, DocumentationType::NATSPEC_USER) << endl - << "Natspec developer documentation: " << compiler.getJsonDocumentation(contract, DocumentationType::NATSPEC_DEV) << endl; - } - return 0; } From 63e9b3940c76f36ec01000f58100b15fa708352a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 9 Dec 2014 12:05:32 +0100 Subject: [PATCH 035/105] Style improvements and succinctness in solc main.cpp --- main.cpp | 132 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 59 deletions(-) diff --git a/main.cpp b/main.cpp index 8650d429c..9500eb97f 100644 --- a/main.cpp +++ b/main.cpp @@ -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; +} -std::istream& operator>>(std::istream& _in, OutputType& io_output) +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; @@ -81,16 +87,16 @@ 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, + CompilerStack& _compiler, string const& _suffix) { if (vm.count(_argName)) { auto choice = vm[_argName].as(); - 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(); - if (choice != OutputType::FILE) + auto choice = _args[argName].as(); + 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,71 +165,78 @@ 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::FILE; + return _args.count(_name) && _args[_name].as() != 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() - ("help", "Show help message and exit") - ("version", "Show version and exit") - ("optimize", po::value()->default_value(false), "Optimize bytecode for size") - ("input-file", po::value>(), "input file") - ("ast", po::value(), - "Request to output the AST of the contract. " outputTypeStr) - ("asm", po::value(), - "Request to output the EVM assembly of the contract. " outputTypeStr) - ("opcodes", po::value(), - "Request to output the Opcodes of the contract. " outputTypeStr) - ("binary", po::value(), - "Request to output the contract in binary (hexadecimal). " outputTypeStr) - ("abi", po::value(), - "Request to output the contract's ABI interface. " outputTypeStr) - ("natspec-user", po::value(), - "Request to output the contract's Natspec user documentation. " outputTypeStr) - ("natspec-dev", po::value(), - "Request to output the contract's Natspec developer documentation. " outputTypeStr); + ("help", "Show help message and exit") + ("version", "Show version and exit") + ("optimize", po::value()->default_value(false), "Optimize bytecode for size") + ("input-file", po::value>(), "input file") + ("ast", po::value(), + "Request to output the AST of the contract. " OUTPUT_TYPE_STR) + ("asm", po::value(), + "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) + ("opcodes", po::value(), + "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) + ("binary", po::value(), + "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) + ("abi", po::value(), + "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + ("natspec-user", po::value(), + "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) + ("natspec-dev", po::value(), + "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 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>()) + for (string const& infile: args["input-file"].as>()) 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()); + // TODO: Perhaps we should not compile unless requested + compiler.compile(args["optimize"].as()); } 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(); - if (choice != OutputType::FILE) + auto choice = args["ast"].as(); + 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 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(); - if (choice != OutputType::FILE) + auto choice = args["asm"].as(); + 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; From 5ab37de94a0a5398e452a6839501a3262c847e61 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 9 Dec 2014 13:43:08 +0100 Subject: [PATCH 036/105] Moving most of the solc functionality to own class and splitting implementation in modular functions --- SolContext.cpp | 368 +++++++++++++++++++++++++++++++++++++++++++++++++ SolContext.h | 72 ++++++++++ main.cpp | 336 +------------------------------------------- 3 files changed, 447 insertions(+), 329 deletions(-) create mode 100644 SolContext.cpp create mode 100644 SolContext.h diff --git a/SolContext.cpp b/SolContext.cpp new file mode 100644 index 000000000..620ad112f --- /dev/null +++ b/SolContext.cpp @@ -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 . +*/ +/** + * @author Lefteris + * @date 2014 + * Solidity compiler context class. + */ +#include "SolContext.h" + +#include +#include +#include + +#include + +#include "BuildInfo.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 and Lefteris , (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::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 SolContext::handleBytecode(string const& _argName, + string const& _title, + string const& _contract, + string const& _suffix) +{ + if (m_args.count(_argName)) + { + auto choice = m_args[_argName].as(); + if (outputToStdout(choice)) + { + cout << _title << endl; + if (_suffix == "opcodes") + ; + // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes + // cout << m_compiler.getBytecode(_contract) << endl; + else + cout << toHex(m_compiler.getBytecode(_contract)) << endl; + } + + if (outputToFile(choice)) + { + ofstream outFile(_contract + _suffix); + if (_suffix == "opcodes") + ; + // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes + // outFile << m_compiler.getBytecode(_contract); + else + outFile << toHex(m_compiler.getBytecode(_contract)); + outFile.close(); + } + } +} + +void SolContext::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(); + 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 SolContext::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()->default_value(false), "Optimize bytecode for size") + ("input-file", po::value>(), "input file") + ("ast", po::value(), + "Request to output the AST of the contract. " OUTPUT_TYPE_STR) + ("asm", po::value(), + "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) + ("opcodes", po::value(), + "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) + ("binary", po::value(), + "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) + ("abi", po::value(), + "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + ("natspec-user", po::value(), + "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) + ("natspec-dev", po::value(), + "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 SolContext::processInput() +{ + if (!m_args.count("input-file")) + { + string s; + while (!cin.eof()) + { + getline(cin, s); + m_sourceCodes[""].append(s); + } + } + else + for (string const& infile: m_args["input-file"].as>()) + 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()); + } + 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 SolContext::actOnInput() +{ + // do we need AST output? + if (m_args.count("ast")) + { + auto choice = m_args["ast"].as(); + 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 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(); + 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("opcodes", "Opcodes:", contract, ".opcodes"); + handleBytecode("binary", "Binary:", contract, ".binary"); + handleJson(DocumentationType::ABI_INTERFACE, contract); + handleJson(DocumentationType::NATSPEC_DEV, contract); + handleJson(DocumentationType::NATSPEC_USER, contract); + } // end of contracts iteration +} + +} +} diff --git a/SolContext.h b/SolContext.h new file mode 100644 index 000000000..922d471ab --- /dev/null +++ b/SolContext.h @@ -0,0 +1,72 @@ +/* + 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 . +*/ +/** + * @author Lefteris + * @date 2014 + * Solidity compiler context class. + */ +#pragma once + +#include + +#include + +namespace dev +{ +namespace solidity +{ + +//forward declaration +enum class DocumentationType: uint8_t; + +enum class OutputType: uint8_t +{ + STDOUT, + FILE, + BOTH +}; + +class SolContext +{ +public: + SolContext() {} + + /// 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 handleBytecode(std::string const& _argName, + std::string const& _title, + std::string const& _contract, + std::string const& _suffix); + 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 m_sourceCodes; + /// Solidity compiler stack + dev::solidity::CompilerStack m_compiler; +}; + +} +} diff --git a/main.cpp b/main.cpp index 9500eb97f..f692725d2 100644 --- a/main.cpp +++ b/main.cpp @@ -20,341 +20,19 @@ * Solidity commandline compiler. */ -#include -#include -#include -#include -#include - -#include "BuildInfo.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace dev; -using namespace solidity; -namespace po = boost::program_options; - -void version() -{ - cout << "solc, the solidity complier commandline interface " << dev::Version << endl - << " by Christian and Lefteris , (c) 2014." << endl - << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; - exit(0); -} - -enum class OutputType -{ - STDOUT, - FILE, - BOTH -}; - -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; -} +#include "SolContext.h" -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; -} - -static void handleBytecode(po::variables_map const& vm, - string const& _argName, - string const& _title, - string const& _contract, - CompilerStack& _compiler, - string const& _suffix) -{ - if (vm.count(_argName)) - { - auto choice = vm[_argName].as(); - if (outputToStdout(choice)) - { - cout << _title << endl; - if (_suffix == "opcodes") - cout << _compiler.getBytecode(_contract) << endl; - else - cout << toHex(_compiler.getBytecode(_contract)) << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + _suffix); - if (_suffix == "opcodes") - outFile << _compiler.getBytecode(_contract); - else - outFile << toHex(_compiler.getBytecode(_contract)); - outFile.close(); - } - } -} - -static void handleJson(po::variables_map const& _args, - DocumentationType _type, - string const& _contract, - CompilerStack&_compiler) -{ - 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 (_args.count(argName)) - { - auto choice = _args[argName].as(); - if (outputToStdout(choice)) - { - cout << title << endl; - cout << _compiler.getJsonDocumentation(_contract, _type); - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + suffix); - outFile << _compiler.getJsonDocumentation(_contract, _type); - outFile.close(); - } - } -} - -static inline bool argToStdout(po::variables_map const& _args, const char* _name) -{ - return _args.count(_name) && _args[_name].as() != 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"); -} 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() - ("help", "Show help message and exit") - ("version", "Show version and exit") - ("optimize", po::value()->default_value(false), "Optimize bytecode for size") - ("input-file", po::value>(), "input file") - ("ast", po::value(), - "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - ("asm", po::value(), - "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - ("opcodes", po::value(), - "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - ("binary", po::value(), - "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - ("abi", po::value(), - "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - ("natspec-user", po::value(), - "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - ("natspec-dev", po::value(), - "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 args; - try - { - 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(args); - - if (args.count("help")) - { - cout << desc; - return 0; - } - - if (args.count("version")) - { - version(); - return 0; - } - - // create a map of input files to source code strings - map sourceCodes; - if (!args.count("input-file")) - { - string s; - while (!cin.eof()) - { - getline(cin, s); - sourceCodes[""].append(s); - } - } - else - for (string const& infile: args["input-file"].as>()) - sourceCodes[infile] = asString(dev::contents(infile)); - - // parse the files - CompilerStack compiler; - try - { - for (auto const& sourceCode: sourceCodes) - compiler.addSource(sourceCode.first, sourceCode.second); - // TODO: Perhaps we should not compile unless requested - compiler.compile(args["optimize"].as()); - } - catch (ParserError const& exception) - { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler); - return -1; - } - catch (DeclarationError const& exception) - { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler); - return -1; - } - catch (TypeError const& exception) - { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler); - return -1; - } - catch (CompilerError const& exception) - { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler); - return -1; - } - catch (InternalCompilerError const& exception) - { - SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler); - return -1; - } - catch (Exception const& exception) - { - cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl; - return -1; - } - catch (...) - { - cerr << "Unknown exception during compilation." << endl; - return -1; - } - - - /* -- act depending on the provided arguments -- */ - - // do we need AST output? - if (args.count("ast")) - { - auto choice = args["ast"].as(); - if (outputToStdout(choice)) - { - cout << "Syntax trees:" << endl << endl; - for (auto const& sourceCode: sourceCodes) - { - cout << endl << "======= " << sourceCode.first << " =======" << endl; - ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); - printer.print(cout); - } - } - - if (outputToFile(choice)) - { - for (auto const& sourceCode: sourceCodes) - { - boost::filesystem::path p(sourceCode.first); - ofstream outFile(p.stem().string() + ".ast"); - ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second); - printer.print(outFile); - outFile.close(); - } - } - } - - vector contracts = compiler.getContractNames(); - for (string const& contract: contracts) - { - if (needStdout(args)) - cout << endl << "======= " << contract << " =======" << endl; - - // do we need EVM assembly? - if (args.count("asm")) - { - auto choice = args["asm"].as(); - if (outputToStdout(choice)) - { - cout << "EVM assembly:" << endl; - compiler.streamAssembly(cout, contract); - } - - if (outputToFile(choice)) - { - ofstream outFile(contract + ".evm"); - compiler.streamAssembly(outFile, contract); - outFile.close(); - } - } - - 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 + dev::solidity::SolContext ctx; + if (!ctx.parseArguments(argc, argv)) + return 1; + if (!ctx.processInput()) + return 1; + ctx.actOnInput(); return 0; } From df82e26d5ad3eff2514c4461ff94ada8fa1ebd55 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 9 Dec 2014 17:39:34 +0100 Subject: [PATCH 037/105] Styling issues and new class name for the CLI --- SolContext.cpp => CommandLineInterface.cpp | 152 ++++++++++----------- SolContext.h => CommandLineInterface.h | 40 +++--- main.cpp | 17 +-- 3 files changed, 98 insertions(+), 111 deletions(-) rename SolContext.cpp => CommandLineInterface.cpp (69%) rename SolContext.h => CommandLineInterface.h (53%) diff --git a/SolContext.cpp b/CommandLineInterface.cpp similarity index 69% rename from SolContext.cpp rename to CommandLineInterface.cpp index 620ad112f..332dc771d 100644 --- a/SolContext.cpp +++ b/CommandLineInterface.cpp @@ -17,9 +17,9 @@ /** * @author Lefteris * @date 2014 - * Solidity compiler context class. + * Solidity command line interface. */ -#include "SolContext.h" +#include "CommandLineInterface.h" #include #include @@ -69,15 +69,14 @@ static bool needStdout(po::variables_map const& _args) static inline bool outputToFile(OutputType type) { - return type == OutputType::FILE || type == OutputType::BOTH; + return type == OutputType::FILE || type == OutputType::BOTH; } static inline bool outputToStdout(OutputType type) { - return type == OutputType::STDOUT || type == OutputType::BOTH; + return type == OutputType::STDOUT || type == OutputType::BOTH; } - static std::istream& operator>>(std::istream& _in, OutputType& io_output) { std::string token; @@ -93,10 +92,10 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) return _in; } -void SolContext::handleBytecode(string const& _argName, - string const& _title, - string const& _contract, - string const& _suffix) +void CommandLineInterface::handleBytecode(string const& _argName, + string const& _title, + string const& _contract, + string const& _suffix) { if (m_args.count(_argName)) { @@ -105,8 +104,8 @@ void SolContext::handleBytecode(string const& _argName, { cout << _title << endl; if (_suffix == "opcodes") - ; - // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes + ; + // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes // cout << m_compiler.getBytecode(_contract) << endl; else cout << toHex(m_compiler.getBytecode(_contract)) << endl; @@ -116,8 +115,8 @@ void SolContext::handleBytecode(string const& _argName, { ofstream outFile(_contract + _suffix); if (_suffix == "opcodes") - ; - // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes + ; + // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes // outFile << m_compiler.getBytecode(_contract); else outFile << toHex(m_compiler.getBytecode(_contract)); @@ -126,8 +125,8 @@ void SolContext::handleBytecode(string const& _argName, } } -void SolContext::handleJson(DocumentationType _type, - string const& _contract) +void CommandLineInterface::handleJson(DocumentationType _type, + string const& _contract) { std::string argName; std::string suffix; @@ -172,76 +171,67 @@ void SolContext::handleJson(DocumentationType _type, } } - - - - - - - - - -bool SolContext::parseArguments(int argc, char** argv) +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()->default_value(false), "Optimize bytecode for size") - ("input-file", po::value>(), "input file") - ("ast", po::value(), - "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - ("asm", po::value(), - "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - ("opcodes", po::value(), - "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - ("binary", po::value(), - "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - ("abi", po::value(), - "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - ("natspec-user", po::value(), - "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - ("natspec-dev", po::value(), - "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); +#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()->default_value(false), "Optimize bytecode for size") + ("input-file", po::value>(), "input file") + ("ast", po::value(), + "Request to output the AST of the contract. " OUTPUT_TYPE_STR) + ("asm", po::value(), + "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) + ("opcodes", po::value(), + "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) + ("binary", po::value(), + "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) + ("abi", po::value(), + "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + ("natspec-user", po::value(), + "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) + ("natspec-dev", po::value(), + "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); + // 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); + // 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("help")) + { + cout << desc; + return false; + } - if (m_args.count("version")) - { - version(); - return false; - } + if (m_args.count("version")) + { + version(); + return false; + } - return true; + return true; } -bool SolContext::processInput() +bool CommandLineInterface::processInput() { if (!m_args.count("input-file")) { @@ -260,7 +250,7 @@ bool SolContext::processInput() { for (auto const& sourceCode: m_sourceCodes) m_compiler.addSource(sourceCode.first, sourceCode.second); - // TODO: Perhaps we should not compile unless requested + // TODO: Perhaps we should not compile unless requested m_compiler.compile(m_args["optimize"].as()); } catch (ParserError const& exception) @@ -299,10 +289,10 @@ bool SolContext::processInput() return false; } - return true; + return true; } -void SolContext::actOnInput() +void CommandLineInterface::actOnInput() { // do we need AST output? if (m_args.count("ast")) @@ -342,13 +332,13 @@ void SolContext::actOnInput() if (m_args.count("asm")) { auto choice = m_args["asm"].as(); - if (outputToStdout(choice)) + if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; m_compiler.streamAssembly(cout, contract); } - if (outputToFile(choice)) + if (outputToFile(choice)) { ofstream outFile(contract + ".evm"); m_compiler.streamAssembly(outFile, contract); diff --git a/SolContext.h b/CommandLineInterface.h similarity index 53% rename from SolContext.h rename to CommandLineInterface.h index 922d471ab..8eb1fff3e 100644 --- a/SolContext.h +++ b/CommandLineInterface.h @@ -17,7 +17,7 @@ /** * @author Lefteris * @date 2014 - * Solidity compiler context class. + * Solidity command line interface. */ #pragma once @@ -40,32 +40,32 @@ enum class OutputType: uint8_t BOTH }; -class SolContext +class CommandLineInterface { public: - SolContext() {} + 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(); + /// 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 handleBytecode(std::string const& _argName, - std::string const& _title, - std::string const& _contract, - std::string const& _suffix); - void handleJson(DocumentationType _type, - std::string const& _contract); + void handleBytecode(std::string const& _argName, + std::string const& _title, + std::string const& _contract, + std::string const& _suffix); + void handleJson(DocumentationType _type, + std::string const& _contract); - /// Compiler arguments variable map - boost::program_options::variables_map m_args; + /// Compiler arguments variable map + boost::program_options::variables_map m_args; /// map of input files to source code strings - std::map m_sourceCodes; - /// Solidity compiler stack - dev::solidity::CompilerStack m_compiler; + std::map m_sourceCodes; + /// Solidity compiler stack + dev::solidity::CompilerStack m_compiler; }; } diff --git a/main.cpp b/main.cpp index f692725d2..c5f72980d 100644 --- a/main.cpp +++ b/main.cpp @@ -20,19 +20,16 @@ * Solidity commandline compiler. */ - -#include "SolContext.h" - - +#include "CommandLineInterface.h" int main(int argc, char** argv) { - dev::solidity::SolContext ctx; - if (!ctx.parseArguments(argc, argv)) - return 1; - if (!ctx.processInput()) - return 1; - ctx.actOnInput(); + dev::solidity::CommandLineInterface cli; + if (!cli.parseArguments(argc, argv)) + return 1; + if (!cli.processInput()) + return 1; + cli.actOnInput(); return 0; } From e851d2173daea4f464d5f72910bb2934c0596a65 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 9 Dec 2014 18:17:54 +0100 Subject: [PATCH 038/105] Explicitly calling dev::operator<<() on two occassions due to mixup with boost --- CommandLineInterface.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 332dc771d..aef5512e3 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -104,9 +104,11 @@ void CommandLineInterface::handleBytecode(string const& _argName, { cout << _title << endl; if (_suffix == "opcodes") - ; - // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes - // cout << m_compiler.getBytecode(_contract) << endl; + { + // TODO: Figure out why the wrong operator << (from boost) is used here + dev::operator<<(cout, m_compiler.getBytecode(_contract)); + cout << endl; + } else cout << toHex(m_compiler.getBytecode(_contract)) << endl; } @@ -115,9 +117,9 @@ void CommandLineInterface::handleBytecode(string const& _argName, { ofstream outFile(_contract + _suffix); if (_suffix == "opcodes") - ; - // TODO: Figure out why after moving to own class ostream operator does not work for vector of bytes - // outFile << m_compiler.getBytecode(_contract); + // TODO: Figure out why the wrong operator << (from boost) is used here + dev::operator<<(outFile, m_compiler.getBytecode(_contract)); + else outFile << toHex(m_compiler.getBytecode(_contract)); outFile.close(); From d377ad3fb13dda6e8a629adfe7484359bda0706d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 9 Dec 2014 20:29:29 +0100 Subject: [PATCH 039/105] Cleaner interface for Solc CLI bytecode handling --- CommandLineInterface.cpp | 72 ++++++++++++++++++++++------------------ CommandLineInterface.h | 7 ++-- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index aef5512e3..d3dd39459 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -92,39 +92,48 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) return _in; } -void CommandLineInterface::handleBytecode(string const& _argName, - string const& _title, - string const& _contract, - string const& _suffix) +void CommandLineInterface::handleBinary(string const& _contract) { - if (m_args.count(_argName)) + auto choice = m_args["binary"].as(); + if (outputToStdout(choice)) { - auto choice = m_args[_argName].as(); - if (outputToStdout(choice)) - { - cout << _title << endl; - if (_suffix == "opcodes") - { - // TODO: Figure out why the wrong operator << (from boost) is used here - dev::operator<<(cout, m_compiler.getBytecode(_contract)); - cout << endl; - } - else - cout << toHex(m_compiler.getBytecode(_contract)) << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + _suffix); - if (_suffix == "opcodes") - // TODO: Figure out why the wrong operator << (from boost) is used here - dev::operator<<(outFile, m_compiler.getBytecode(_contract)); - - else - outFile << toHex(m_compiler.getBytecode(_contract)); - outFile.close(); - } + 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(); + 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, @@ -348,8 +357,7 @@ void CommandLineInterface::actOnInput() } } - handleBytecode("opcodes", "Opcodes:", contract, ".opcodes"); - handleBytecode("binary", "Binary:", contract, ".binary"); + handleBytecode(contract); handleJson(DocumentationType::ABI_INTERFACE, contract); handleJson(DocumentationType::NATSPEC_DEV, contract); handleJson(DocumentationType::NATSPEC_USER, contract); diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 8eb1fff3e..7e3ad2502 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -53,10 +53,9 @@ public: void actOnInput(); private: - void handleBytecode(std::string const& _argName, - std::string const& _title, - std::string const& _contract, - std::string const& _suffix); + 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); From a68d58cb9e9eee838c63e3cf8317a70be6852707 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 10 Dec 2014 16:56:30 +0100 Subject: [PATCH 040/105] recent changes from solc working on macos --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7cc5a1a6..cf1e42572 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} boost_filesystem) -target_link_libraries(${EXECUTABLE} boost_program_options) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 207da9ef0f8c67bc39393652d995b55cbfd0eb97 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 11 Dec 2014 00:22:35 +0100 Subject: [PATCH 041/105] Fixing segfault for solc if stdin is given as input file - Solc should now check its input files and skip them if they don't exist or if they are not a valid file --- CommandLineInterface.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index d3dd39459..6ace332f7 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -255,7 +255,22 @@ bool CommandLineInterface::processInput() } else for (string const& infile: m_args["input-file"].as>()) + { + auto path = boost::filesystem::path(infile); + if (!boost::filesystem::exists(path)) + { + cout << "Skipping non existant input file \"" << infile << "\"" << endl; + continue; + } + + if (!boost::filesystem::is_regular_file(path)) + { + cout << "\"" << infile << "\" is not a valid file. Skipping" << endl; + continue; + } + m_sourceCodes[infile] = asString(dev::contents(infile)); + } try { From a909383fc48061fa6db8370bf66e5e5eedad8a6f Mon Sep 17 00:00:00 2001 From: ethdev Date: Mon, 15 Dec 2014 18:19:58 +0100 Subject: [PATCH 042/105] start of implementing windows debug --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf1e42572..bc8632373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY_RELEASE}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 34816de10520dc338d28ba1cdd842bde2070e031 Mon Sep 17 00:00:00 2001 From: ethdev Date: Mon, 15 Dec 2014 19:01:20 +0100 Subject: [PATCH 043/105] boost library -> libraries --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc8632373..8c0ece27e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARY}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARY}) +target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From 40b4740b43040790ed2f9e7b610630070e040808 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:08:25 +0100 Subject: [PATCH 044/105] Fix for unhandled solc exception with opcodes argument - This should fix #631 --- CommandLineInterface.cpp | 51 ++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 6ace332f7..f13423edb 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -43,6 +43,16 @@ using namespace std; namespace po = boost::program_options; +// LTODO: Maybe some argument class pairing names with +// extensions and other attributes would be a better choice here? +#define ARG_ABI_STR "abi" +#define ARG_ASM_STR "asm" +#define ARG_AST_STR "ast" +#define ARG_BINARY_STR "binary" +#define ARG_OPCODES_STR "opcodes" +#define ARG_NATSPECDEV_STR "natspec-dev" +#define ARG_NATSPECUSER_STR "natspec-user" + namespace dev { namespace solidity @@ -63,8 +73,9 @@ static inline bool argToStdout(po::variables_map const& _args, const char* _name 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, ARG_ABI_STR) || argToStdout(_args, ARG_NATSPECUSER_STR) || + argToStdout(_args, ARG_NATSPECDEV_STR) || argToStdout(_args, ARG_ASM_STR) || + argToStdout(_args, ARG_OPCODES_STR) || argToStdout(_args, ARG_BINARY_STR); } 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(); + auto choice = m_args[ARG_BINARY_STR].as(); if (outputToStdout(choice)) { cout << "Binary: " << endl; @@ -112,7 +123,7 @@ 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(); + auto choice = m_args[ARG_OPCODES_STR].as(); if (outputToStdout(choice)) { cout << "Opcodes: " << endl; @@ -130,9 +141,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract) { - if (m_args.count("opcodes")) + if (m_args.count(ARG_OPCODES_STR)) handleOpcode(_contract); - if (m_args.count("binary")) + if (m_args.count(ARG_BINARY_STR)) handleBinary(_contract); } @@ -145,17 +156,17 @@ void CommandLineInterface::handleJson(DocumentationType _type, switch(_type) { case DocumentationType::ABI_INTERFACE: - argName = "abi"; + argName = ARG_ABI_STR; suffix = ".abi"; title = "Contract ABI"; break; case DocumentationType::NATSPEC_USER: - argName = "natspec-user"; + argName = "ARG_NATSPECUSER_STR"; suffix = ".docuser"; title = "User Documentation"; break; case DocumentationType::NATSPEC_DEV: - argName = "natspec-dev"; + argName = ARG_NATSPECDEV_STR; suffix = ".docdev"; title = "Developer Documentation"; break; @@ -195,19 +206,19 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - ("ast", po::value(), + (ARG_AST_STR, po::value(), "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - ("asm", po::value(), + (ARG_ASM_STR, po::value(), "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - ("opcodes", po::value(), + (ARG_OPCODES_STR, po::value(), "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - ("binary", po::value(), + (ARG_BINARY_STR, po::value(), "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - ("abi", po::value(), + (ARG_ABI_STR, po::value(), "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - ("natspec-user", po::value(), + (ARG_NATSPECUSER_STR, po::value(), "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - ("natspec-dev", po::value(), + (ARG_NATSPECDEV_STR, po::value(), "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); #undef OUTPUT_TYPE_STR @@ -321,9 +332,9 @@ bool CommandLineInterface::processInput() void CommandLineInterface::actOnInput() { // do we need AST output? - if (m_args.count("ast")) + if (m_args.count(ARG_AST_STR)) { - auto choice = m_args["ast"].as(); + auto choice = m_args[ARG_AST_STR].as(); 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(ARG_ASM_STR)) { - auto choice = m_args["asm"].as(); + auto choice = m_args[ARG_ASM_STR].as(); if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; From d9f0160a41988c546eeb69f2eac6b7bca2c3d0d7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:31:22 +0100 Subject: [PATCH 045/105] Properly outputing opcodes in solc, using normal stream operator --- CommandLineInterface.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index f13423edb..8aa182b5c 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -122,19 +122,18 @@ 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[ARG_OPCODES_STR].as(); 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(); } } From dfff5810578a582c286e05f7634bea1fe0587799 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 16 Dec 2014 23:55:38 +0100 Subject: [PATCH 046/105] Using strings instead of #defined literals in solc --- CommandLineInterface.cpp | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 8aa182b5c..fd660a0ca 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -43,21 +43,21 @@ using namespace std; namespace po = boost::program_options; -// LTODO: Maybe some argument class pairing names with -// extensions and other attributes would be a better choice here? -#define ARG_ABI_STR "abi" -#define ARG_ASM_STR "asm" -#define ARG_AST_STR "ast" -#define ARG_BINARY_STR "binary" -#define ARG_OPCODES_STR "opcodes" -#define ARG_NATSPECDEV_STR "natspec-dev" -#define ARG_NATSPECUSER_STR "natspec-user" - 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 @@ -66,16 +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::FILE; } static bool needStdout(po::variables_map const& _args) { - return argToStdout(_args, ARG_ABI_STR) || argToStdout(_args, ARG_NATSPECUSER_STR) || - argToStdout(_args, ARG_NATSPECDEV_STR) || argToStdout(_args, ARG_ASM_STR) || - argToStdout(_args, ARG_OPCODES_STR) || argToStdout(_args, ARG_BINARY_STR); + 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) @@ -105,7 +105,7 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) void CommandLineInterface::handleBinary(string const& _contract) { - auto choice = m_args[ARG_BINARY_STR].as(); + auto choice = m_args[g_argBinaryStr].as(); if (outputToStdout(choice)) { cout << "Binary: " << endl; @@ -122,7 +122,7 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { - auto choice = m_args[ARG_OPCODES_STR].as(); + auto choice = m_args[g_argOpcodesStr].as(); if (outputToStdout(choice)) { cout << "Opcodes: " << endl; @@ -140,9 +140,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract) { - if (m_args.count(ARG_OPCODES_STR)) + if (m_args.count(g_argOpcodesStr)) handleOpcode(_contract); - if (m_args.count(ARG_BINARY_STR)) + if (m_args.count(g_argBinaryStr)) handleBinary(_contract); } @@ -155,17 +155,17 @@ void CommandLineInterface::handleJson(DocumentationType _type, switch(_type) { case DocumentationType::ABI_INTERFACE: - argName = ARG_ABI_STR; + argName = g_argAbiStr; suffix = ".abi"; title = "Contract ABI"; break; case DocumentationType::NATSPEC_USER: - argName = "ARG_NATSPECUSER_STR"; + argName = "g_argNatspecUserStr"; suffix = ".docuser"; title = "User Documentation"; break; case DocumentationType::NATSPEC_DEV: - argName = ARG_NATSPECDEV_STR; + argName = g_argNatspecDevStr; suffix = ".docdev"; title = "Developer Documentation"; break; @@ -205,20 +205,20 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - (ARG_AST_STR, po::value(), + (g_argAstStr.c_str(), po::value(), "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - (ARG_ASM_STR, po::value(), - "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - (ARG_OPCODES_STR, po::value(), - "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - (ARG_BINARY_STR, po::value(), - "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - (ARG_ABI_STR, po::value(), - "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) - (ARG_NATSPECUSER_STR, po::value(), - "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - (ARG_NATSPECDEV_STR, po::value(), - "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); + (g_argAsmStr.c_str(), po::value(), + "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) + (g_argOpcodesStr.c_str(), po::value(), + "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) + (g_argBinaryStr.c_str(), po::value(), + "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) + (g_argAbiStr.c_str(), po::value(), + "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + (g_argNatspecUserStr.c_str(), po::value(), + "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) + (g_argNatspecDevStr.c_str(), po::value(), + "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 @@ -331,9 +331,9 @@ bool CommandLineInterface::processInput() void CommandLineInterface::actOnInput() { // do we need AST output? - if (m_args.count(ARG_AST_STR)) + if (m_args.count(g_argAstStr)) { - auto choice = m_args[ARG_AST_STR].as(); + auto choice = m_args[g_argAstStr].as(); if (outputToStdout(choice)) { cout << "Syntax trees:" << endl << endl; @@ -365,9 +365,9 @@ void CommandLineInterface::actOnInput() cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? - if (m_args.count(ARG_ASM_STR)) + if (m_args.count(g_argAsmStr)) { - auto choice = m_args[ARG_ASM_STR].as(); + auto choice = m_args[g_argAsmStr].as(); if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; From a6fd19c8f30f3bb46cd66d5ed810017dab95e51c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 17 Dec 2014 00:17:38 +0100 Subject: [PATCH 047/105] better alignment of global string constants --- CommandLineInterface.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index fd660a0ca..81dd25ec7 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -50,13 +50,13 @@ 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 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() { From 80b8db4f17c838369b4ef45e8ccec856a7f13cc7 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 17 Dec 2014 16:23:18 +0100 Subject: [PATCH 048/105] Assertions that throw InternalCompilerErrors. --- CommandLineInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 81dd25ec7..399f52436 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -311,7 +311,8 @@ bool CommandLineInterface::processInput() } 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) From d7873d9cd0745fcc3642c217f37d95303613a35a Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 17 Dec 2014 17:08:57 +0100 Subject: [PATCH 049/105] Format catch arguments as function parameters. --- CommandLineInterface.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 399f52436..2a79521ef 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -230,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); @@ -289,35 +289,35 @@ bool CommandLineInterface::processInput() // TODO: Perhaps we should not compile unless requested m_compiler.compile(m_args["optimize"].as()); } - 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) { cerr << "Internal compiler error during compilation:" << endl - << boost::diagnostic_information(exception); + << 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 (...) From 6de29142ef6b8839207b01f636c8a05285ab2151 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 9 Jan 2015 08:05:52 +0100 Subject: [PATCH 050/105] Rename "JSON Documentation" -> Metadata. solc integration for Solidity-format ABI. --- CommandLineInterface.cpp | 37 ++++++++++++++++++++++++------------- CommandLineInterface.h | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 2a79521ef..46a293a7b 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -16,6 +16,7 @@ */ /** * @author Lefteris + * @author Gav Wood * @date 2014 * Solidity command line interface. */ @@ -51,6 +52,7 @@ 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_argSolAbiStr = "sol-abi"; static string const g_argAsmStr = "asm"; static string const g_argAstStr = "ast"; static string const g_argBinaryStr = "binary"; @@ -60,7 +62,7 @@ static string const g_argNatspecUserStr = "natspec-user"; static void version() { - cout << "solc, the solidity complier commandline interface " << dev::Version << endl + cout << "solc, the solidity compiler commandline interface " << dev::Version << endl << " by Christian and Lefteris , (c) 2014." << endl << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; exit(0); @@ -73,9 +75,11 @@ static inline bool argToStdout(po::variables_map const& _args, string const& _na static bool needStdout(po::variables_map const& _args) { - 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); + return + argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argSolAbiStr) || + 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) @@ -146,8 +150,7 @@ void CommandLineInterface::handleBytecode(string const& _contract) handleBinary(_contract); } -void CommandLineInterface::handleJson(DocumentationType _type, - string const& _contract) +void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) { std::string argName; std::string suffix; @@ -159,8 +162,13 @@ void CommandLineInterface::handleJson(DocumentationType _type, suffix = ".abi"; title = "Contract ABI"; break; + case DocumentationType::ABI_SOLIDITY_INTERFACE: + argName = g_argSolAbiStr; + suffix = ".sol"; + title = "Contract Solidity ABI"; + break; case DocumentationType::NATSPEC_USER: - argName = "g_argNatspecUserStr"; + argName = g_argNatspecUserStr; suffix = ".docuser"; title = "User Documentation"; break; @@ -180,13 +188,13 @@ void CommandLineInterface::handleJson(DocumentationType _type, if (outputToStdout(choice)) { cout << title << endl; - cout << m_compiler.getJsonDocumentation(_contract, _type); + cout << m_compiler.getMetadata(_contract, _type); } if (outputToFile(choice)) { ofstream outFile(_contract + suffix); - outFile << m_compiler.getJsonDocumentation(_contract, _type); + outFile << m_compiler.getMetadata(_contract, _type); outFile.close(); } } @@ -214,7 +222,9 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) (g_argBinaryStr.c_str(), po::value(), "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) (g_argAbiStr.c_str(), po::value(), - "Request to output the contract's ABI interface. " OUTPUT_TYPE_STR) + "Request to output the contract's JSON ABI interface. " OUTPUT_TYPE_STR) + (g_argSolAbiStr.c_str(), po::value(), + "Request to output the contract's Solidity ABI interface. " OUTPUT_TYPE_STR) (g_argNatspecUserStr.c_str(), po::value(), "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) (g_argNatspecDevStr.c_str(), po::value(), @@ -384,9 +394,10 @@ void CommandLineInterface::actOnInput() } handleBytecode(contract); - handleJson(DocumentationType::ABI_INTERFACE, contract); - handleJson(DocumentationType::NATSPEC_DEV, contract); - handleJson(DocumentationType::NATSPEC_USER, contract); + handleMeta(DocumentationType::ABI_INTERFACE, contract); + handleMeta(DocumentationType::ABI_SOLIDITY_INTERFACE, contract); + handleMeta(DocumentationType::NATSPEC_DEV, contract); + handleMeta(DocumentationType::NATSPEC_USER, contract); } // end of contracts iteration } diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 7e3ad2502..9dfee7199 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -56,7 +56,7 @@ private: void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); void handleBytecode(std::string const& _contract); - void handleJson(DocumentationType _type, + void handleMeta(DocumentationType _type, std::string const& _contract); /// Compiler arguments variable map From 8233c071f21040dd47ade1c46f8abe252b51f5a7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 9 Jan 2015 08:09:30 +0100 Subject: [PATCH 051/105] CLI tweaks. --- CommandLineInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 46a293a7b..c03b60d41 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -160,7 +160,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co case DocumentationType::ABI_INTERFACE: argName = g_argAbiStr; suffix = ".abi"; - title = "Contract ABI"; + title = "Contract JSON ABI"; break; case DocumentationType::ABI_SOLIDITY_INTERFACE: argName = g_argSolAbiStr; @@ -188,7 +188,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co if (outputToStdout(choice)) { cout << title << endl; - cout << m_compiler.getMetadata(_contract, _type); + cout << m_compiler.getMetadata(_contract, _type) << endl; } if (outputToFile(choice)) From 245fba5055776885501ad46827ad680651248823 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 9 Jan 2015 08:16:35 +0100 Subject: [PATCH 052/105] abi -> json-abi --- CommandLineInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index c03b60d41..8c5192abe 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -51,7 +51,7 @@ 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_argAbiStr = "json-abi"; static string const g_argSolAbiStr = "sol-abi"; static string const g_argAsmStr = "asm"; static string const g_argAstStr = "ast"; From d0f02c28c69b1ce7696670a09835cc7cc173bd03 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 5 Jan 2015 15:46:40 +0100 Subject: [PATCH 053/105] Preparing the ground for AST outputing to JSON --- CommandLineInterface.cpp | 64 +++++++++++++++++++++++++++++++++------- CommandLineInterface.h | 1 + 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 8c5192abe..7be27297a 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ static string const g_argAbiStr = "json-abi"; static string const g_argSolAbiStr = "sol-abi"; static string const g_argAsmStr = "asm"; static string const g_argAstStr = "ast"; +static string const g_argAstJson = "ast-json"; static string const g_argBinaryStr = "binary"; static string const g_argOpcodesStr = "opcodes"; static string const g_argNatspecDevStr = "natspec-dev"; @@ -75,9 +77,10 @@ static inline bool argToStdout(po::variables_map const& _args, string const& _na static bool needStdout(po::variables_map const& _args) { + return argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argSolAbiStr) || - argToStdout(_args, g_argNatspecUserStr) || + argToStdout(_args, g_argNatspecUserStr) || argToStdout(_args, g_argAstJson) || argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) || argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr); } @@ -215,6 +218,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("input-file", po::value>(), "input file") (g_argAstStr.c_str(), po::value(), "Request to output the AST of the contract. " OUTPUT_TYPE_STR) + (g_argAstJson.c_str(), po::value(), + "Request to output the AST of the contract in JSON format. " OUTPUT_TYPE_STR) (g_argAsmStr.c_str(), po::value(), "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) (g_argOpcodesStr.c_str(), po::value(), @@ -339,20 +344,44 @@ bool CommandLineInterface::processInput() return true; } -void CommandLineInterface::actOnInput() +void CommandLineInterface::handleAst(std::string const& _argStr) { - // do we need AST output? - if (m_args.count(g_argAstStr)) + std::string title; + std::string suffix; + + if (_argStr == g_argAstStr) { - auto choice = m_args[g_argAstStr].as(); + title = "Syntax trees:"; + suffix = ".ast"; + } + else if (_argStr == g_argAstJson) + { + title = "JSON AST:"; + suffix = ".json"; + } + else + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal argStr for AST")); + + // do we need AST output? + if (m_args.count(_argStr)) + { + auto choice = m_args[_argStr].as(); if (outputToStdout(choice)) { - cout << "Syntax trees:" << endl << endl; + cout << title << 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 (_argStr == g_argAstStr) + { + ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); + printer.print(cout); + } + else + { + ASTJsonConverter converter(m_compiler.getAST(sourceCode.first)); + converter.print(cout); + } } } @@ -362,12 +391,27 @@ void CommandLineInterface::actOnInput() { boost::filesystem::path p(sourceCode.first); ofstream outFile(p.stem().string() + ".ast"); - ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); - printer.print(outFile); + if (_argStr == g_argAstStr) + { + ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); + printer.print(outFile); + } + else + { + ASTJsonConverter converter(m_compiler.getAST(sourceCode.first)); + converter.print(outFile); + } outFile.close(); } } } +} + +void CommandLineInterface::actOnInput() +{ + // do we need AST output? + handleAst(g_argAstStr); + handleAst(g_argAstJson); vector contracts = m_compiler.getContractNames(); for (string const& contract: contracts) diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 9dfee7199..2862773ba 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -53,6 +53,7 @@ public: void actOnInput(); private: + void handleAst(std::string const& _argStr); void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); void handleBytecode(std::string const& _contract); From 78d6e82f37efcc877a0e01d5f63a3e4d33ab0467 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 16 Jan 2015 11:44:55 +0100 Subject: [PATCH 054/105] Style fixes and refactoring in ASTJsonConverter --- CommandLineInterface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 7be27297a..3888f2314 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -344,10 +344,10 @@ bool CommandLineInterface::processInput() return true; } -void CommandLineInterface::handleAst(std::string const& _argStr) +void CommandLineInterface::handleAst(string const& _argStr) { - std::string title; - std::string suffix; + string title; + string suffix; if (_argStr == g_argAstStr) { From 3e8876d57e2004e41a3c56edf5d3fb1e4db48b19 Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Tue, 27 Jan 2015 00:26:13 +0800 Subject: [PATCH 055/105] simplify solc's option output The original one is too verbose. --- CommandLineInterface.cpp | 41 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 3888f2314..87edb24b0 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -205,10 +205,6 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co 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() @@ -216,25 +212,24 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("input-file", po::value>(), "input file") - (g_argAstStr.c_str(), po::value(), - "Request to output the AST of the contract. " OUTPUT_TYPE_STR) - (g_argAstJson.c_str(), po::value(), - "Request to output the AST of the contract in JSON format. " OUTPUT_TYPE_STR) - (g_argAsmStr.c_str(), po::value(), - "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR) - (g_argOpcodesStr.c_str(), po::value(), - "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR) - (g_argBinaryStr.c_str(), po::value(), - "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR) - (g_argAbiStr.c_str(), po::value(), - "Request to output the contract's JSON ABI interface. " OUTPUT_TYPE_STR) - (g_argSolAbiStr.c_str(), po::value(), - "Request to output the contract's Solidity ABI interface. " OUTPUT_TYPE_STR) - (g_argNatspecUserStr.c_str(), po::value(), - "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR) - (g_argNatspecDevStr.c_str(), po::value(), - "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR); -#undef OUTPUT_TYPE_STR + (g_argAstStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the AST of the contract.") + (g_argAstJson.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the AST of the contract in JSON format.") + (g_argAsmStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the EVM assembly of the contract.") + (g_argOpcodesStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the Opcodes of the contract.") + (g_argBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract in binary (hexadecimal).") + (g_argAbiStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract's JSON ABI interface.") + (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract's Solidity ABI interface.") + (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract's Natspec user documentation.") + (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract's Natspec developer documentation."); // All positional options should be interpreted as input files po::positional_options_description p; From a07b3f1da8238686e15456e809522a4097b3fa01 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 28 Jan 2015 10:01:46 +0100 Subject: [PATCH 056/105] Dockerfile to build the solidity compiler using emscripten. --- docker_emscripten/Dockerfile | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 docker_emscripten/Dockerfile diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile new file mode 100644 index 000000000..c866d427a --- /dev/null +++ b/docker_emscripten/Dockerfile @@ -0,0 +1,57 @@ +FROM ubuntu:14.04 + +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update +RUN apt-get upgrade -y + +# Ethereum dependencies +RUN apt-get install -qy build-essential git cmake libcurl4-openssl-dev wget +RUN apt-get install -qy automake libtool yasm scons + +RUN useradd -ms /bin/bash user +USER user +WORKDIR /home/user + +# Emscripten SDK +RUN wget -c https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz +RUN tar xzf emsdk-portable.tar.gz +WORKDIR /home/user/emsdk_portable +RUN ./emsdk update && ./emsdk install latest && ./emsdk activate latest +ENV PATH $PATH:/home/user/emsdk_portable:/home/user/emsdk_portable/clang/fastcomp/build_master_64/bin:/home/user/emsdk_portable/emscripten/master + +USER root +RUN apt-get install -qy nodejs +USER user +RUN sed -i "s/NODE_JS = 'node'/NODE_JS = 'nodejs'/g" ~/.emscripten + +# CryptoPP +WORKDIR /home/user +RUN git clone https://github.com/mmoss/cryptopp.git +WORKDIR /home/user/cryptopp +RUN emcmake cmake -DCRYPTOPP_LIBRARY_TYPE=STATIC -DCRYPTOPP_RUNTIME_TYPE=STATIC && emmake make -j 4 +RUN ln -s . src/cryptopp + +# Boost +WORKDIR /home/user +RUN wget 'http://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.57.0%2F&ts=1421887207&use_mirror=cznic' -O boost_1_57_0.tar.bz2 +RUN tar xjf boost_1_57_0.tar.bz2 +WORKDIR /home/user/boost_1_57_0 +RUN ./bootstrap.sh --with-libraries=thread,system,regex +RUN sed -i 's/using gcc ;/using gcc : : \/home\/user\/emsdk_portable\/emscripten\/master\/em++ ;/g' ./project-config.jam +RUN sed -i 's/$(archiver\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emar/g' ./tools/build/src/tools/gcc.jam +RUN sed -i 's/$(ranlib\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emranlib/g' ./tools/build/src/tools/gcc.jam +RUN ./b2 link=static variant=release threading=single runtime-link=static thread system regex + + +# Build soljs +WORKDIR /home/user +ADD https://api.github.com/repos/ethereum/cpp-ethereum/git/refs/heads/develop unused.txt +RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum +WORKDIR /home/user/cpp-ethereum +ADD https://api.github.com/repos/chriseth/cpp-ethereum/git/refs/heads/solidity-js unused2.txt +RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum +RUN git merge solidityjs/solidity-js +RUN emcmake cmake -DETH_STATIC=1 -DONLY_SOLIDITY=1 -DHEADLESS=1 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc +RUN emmake make -j 6 soljs + +ENTRYPOINT cat soljs/soljs.js From f4b52ebac1be0235b3ea54ad47fc8ed9d93c457f Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 29 Jan 2015 01:29:43 +0100 Subject: [PATCH 057/105] Exclude standard contracts by default. --- CommandLineInterface.cpp | 41 +++++++++++++++++++++------------------- CommandLineInterface.h | 6 +++--- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 87edb24b0..aa651eb41 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -61,6 +61,7 @@ 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 string const g_argAddStandard = "add-std"; static void version() { @@ -116,13 +117,13 @@ void CommandLineInterface::handleBinary(string const& _contract) if (outputToStdout(choice)) { cout << "Binary: " << endl; - cout << toHex(m_compiler.getBytecode(_contract)) << endl; + cout << toHex(m_compiler->getBytecode(_contract)) << endl; } if (outputToFile(choice)) { ofstream outFile(_contract + ".binary"); - outFile << toHex(m_compiler.getBytecode(_contract)); + outFile << toHex(m_compiler->getBytecode(_contract)); outFile.close(); } } @@ -133,14 +134,14 @@ void CommandLineInterface::handleOpcode(string const& _contract) if (outputToStdout(choice)) { cout << "Opcodes: " << endl; - cout << eth::disassemble(m_compiler.getBytecode(_contract)); + cout << eth::disassemble(m_compiler->getBytecode(_contract)); cout << endl; } if (outputToFile(choice)) { ofstream outFile(_contract + ".opcode"); - outFile << eth::disassemble(m_compiler.getBytecode(_contract)); + outFile << eth::disassemble(m_compiler->getBytecode(_contract)); outFile.close(); } } @@ -191,13 +192,13 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co if (outputToStdout(choice)) { cout << title << endl; - cout << m_compiler.getMetadata(_contract, _type) << endl; + cout << m_compiler->getMetadata(_contract, _type) << endl; } if (outputToFile(choice)) { ofstream outFile(_contract + suffix); - outFile << m_compiler.getMetadata(_contract, _type); + outFile << m_compiler->getMetadata(_contract, _type); outFile.close(); } } @@ -211,6 +212,7 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("help", "Show help message and exit") ("version", "Show version and exit") ("optimize", po::value()->default_value(false), "Optimize bytecode for size") + ("add-std", po::value()->default_value(false), "Add standard contracts") ("input-file", po::value>(), "input file") (g_argAstStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the AST of the contract.") @@ -292,31 +294,32 @@ bool CommandLineInterface::processInput() m_sourceCodes[infile] = asString(dev::contents(infile)); } + m_compiler.reset(new CompilerStack(m_args["add-std"].as())); try { for (auto const& sourceCode: m_sourceCodes) - m_compiler.addSource(sourceCode.first, sourceCode.second); + m_compiler->addSource(sourceCode.first, sourceCode.second); // TODO: Perhaps we should not compile unless requested - m_compiler.compile(m_args["optimize"].as()); + m_compiler->compile(m_args["optimize"].as()); } 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) { - SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Declaration error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Declaration error", *m_compiler); return false; } 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) { - SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Compiler error", m_compiler); + SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Compiler error", *m_compiler); return false; } catch (InternalCompilerError const& _exception) @@ -369,12 +372,12 @@ void CommandLineInterface::handleAst(string const& _argStr) cout << endl << "======= " << sourceCode.first << " =======" << endl; if (_argStr == g_argAstStr) { - ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); + ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); printer.print(cout); } else { - ASTJsonConverter converter(m_compiler.getAST(sourceCode.first)); + ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); converter.print(cout); } } @@ -388,12 +391,12 @@ void CommandLineInterface::handleAst(string const& _argStr) ofstream outFile(p.stem().string() + ".ast"); if (_argStr == g_argAstStr) { - ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second); + ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); printer.print(outFile); } else { - ASTJsonConverter converter(m_compiler.getAST(sourceCode.first)); + ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); converter.print(outFile); } outFile.close(); @@ -408,7 +411,7 @@ void CommandLineInterface::actOnInput() handleAst(g_argAstStr); handleAst(g_argAstJson); - vector contracts = m_compiler.getContractNames(); + vector contracts = m_compiler->getContractNames(); for (string const& contract: contracts) { if (needStdout(m_args)) @@ -421,13 +424,13 @@ void CommandLineInterface::actOnInput() if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; - m_compiler.streamAssembly(cout, contract); + m_compiler->streamAssembly(cout, contract); } if (outputToFile(choice)) { ofstream outFile(contract + ".evm"); - m_compiler.streamAssembly(outFile, contract); + m_compiler->streamAssembly(outFile, contract); outFile.close(); } } diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 2862773ba..79029f9d1 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -21,9 +21,9 @@ */ #pragma once -#include - #include +#include +#include namespace dev { @@ -65,7 +65,7 @@ private: /// map of input files to source code strings std::map m_sourceCodes; /// Solidity compiler stack - dev::solidity::CompilerStack m_compiler; + std::unique_ptr m_compiler; }; } From c797df730714846773938f1ec51190edf7defc2f Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 30 Jan 2015 20:49:45 +0100 Subject: [PATCH 058/105] Workaround for a problem with `git merge`. --- docker_emscripten/Dockerfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index c866d427a..b593cbf74 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -42,16 +42,20 @@ RUN sed -i 's/$(archiver\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\ RUN sed -i 's/$(ranlib\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emranlib/g' ./tools/build/src/tools/gcc.jam RUN ./b2 link=static variant=release threading=single runtime-link=static thread system regex - # Build soljs WORKDIR /home/user ADD https://api.github.com/repos/ethereum/cpp-ethereum/git/refs/heads/develop unused.txt RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum WORKDIR /home/user/cpp-ethereum +RUN git config --global user.email "me@example.com" +RUN git config --global user.name "Jane Doe" ADD https://api.github.com/repos/chriseth/cpp-ethereum/git/refs/heads/solidity-js unused2.txt RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum -RUN git merge solidityjs/solidity-js +# TODO this should be a proper merge but somehow causes problems +# NOTE that we only get the latest commit of that branch +RUN git cherry-pick solidityjs/solidity-js RUN emcmake cmake -DETH_STATIC=1 -DONLY_SOLIDITY=1 -DHEADLESS=1 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc RUN emmake make -j 6 soljs ENTRYPOINT cat soljs/soljs.js + From 75f6e2a4ea66af1dbbb646085cabf1b1e73ec5d1 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 8 Feb 2015 21:56:15 +0100 Subject: [PATCH 059/105] cmake mess --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c0ece27e..96129c499 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From a2644c0967c6d498ba827f0e1523c0ebc77c0095 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 9 Feb 2015 14:12:36 +0100 Subject: [PATCH 060/105] Styling in Natspec Enums --- CommandLineInterface.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index aa651eb41..db12231a7 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -161,22 +161,22 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co std::string title; switch(_type) { - case DocumentationType::ABI_INTERFACE: + case DocumentationType::ABIInterface: argName = g_argAbiStr; suffix = ".abi"; title = "Contract JSON ABI"; break; - case DocumentationType::ABI_SOLIDITY_INTERFACE: + case DocumentationType::ABISolidityInterface: argName = g_argSolAbiStr; suffix = ".sol"; title = "Contract Solidity ABI"; break; - case DocumentationType::NATSPEC_USER: + case DocumentationType::NatspecUser: argName = g_argNatspecUserStr; suffix = ".docuser"; title = "User Documentation"; break; - case DocumentationType::NATSPEC_DEV: + case DocumentationType::NatspecDev: argName = g_argNatspecDevStr; suffix = ".docdev"; title = "Developer Documentation"; @@ -436,10 +436,10 @@ void CommandLineInterface::actOnInput() } handleBytecode(contract); - handleMeta(DocumentationType::ABI_INTERFACE, contract); - handleMeta(DocumentationType::ABI_SOLIDITY_INTERFACE, contract); - handleMeta(DocumentationType::NATSPEC_DEV, contract); - handleMeta(DocumentationType::NATSPEC_USER, contract); + handleMeta(DocumentationType::ABIInterface, contract); + handleMeta(DocumentationType::ABISolidityInterface, contract); + handleMeta(DocumentationType::NatspecDev, contract); + handleMeta(DocumentationType::NatspecUser, contract); } // end of contracts iteration } From a70d7f04c9cc92d354ad7b7216540e232bc92e99 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 11 Feb 2015 11:41:56 +0100 Subject: [PATCH 061/105] fixed transitive dependencies for msvc --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96129c499..8c0ece27e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,6 @@ add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) From af0357898b6ebbe80b47323a89d969e939ca4ab3 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 11 Feb 2015 16:47:56 +0100 Subject: [PATCH 062/105] fixed cmake include_directories --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c0ece27e..2a7bd7b6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) include_directories(${Boost_INCLUDE_DIRS}) +include_directories(${JSONCPP_INCLUDE_DIRS}) include_directories(..) set(EXECUTABLE solc) From 089c2ef39e33be2c314618d6a5a8a62664a4ecc9 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 13 Feb 2015 09:03:03 +0100 Subject: [PATCH 063/105] fixed issue with including wrong json/json.h file --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a7bd7b6d..747effad0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,9 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(${Boost_INCLUDE_DIRS}) -include_directories(${JSONCPP_INCLUDE_DIRS}) include_directories(..) +include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE solc) From d4e2e60ceb98962c93067ef4a93409ca5857eb5b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 16 Feb 2015 13:48:25 +0100 Subject: [PATCH 064/105] fixed #1022 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 747effad0..d3a39dbc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE solc) From c4cc2bcea72c197a86b9099ccf7c0c9b0e372ef8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 20 Feb 2015 21:59:21 +0100 Subject: [PATCH 065/105] Add EVMJIT. --- CMakeLists.txt | 20 -- CommandLineInterface.cpp | 447 ----------------------------------- CommandLineInterface.h | 72 ------ docker_emscripten/Dockerfile | 61 ----- main.cpp | 35 --- 5 files changed, 635 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 CommandLineInterface.cpp delete mode 100644 CommandLineInterface.h delete mode 100644 docker_emscripten/Dockerfile delete mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index d3a39dbc8..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -cmake_policy(SET CMP0015 NEW) -set(CMAKE_AUTOMOC OFF) - -aux_source_directory(. SRC_LIST) - -include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) - -set(EXECUTABLE solc) - -file(GLOB HEADERS "*.h") -add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) - -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) -target_link_libraries(${EXECUTABLE} solidity) - -install( TARGETS ${EXECUTABLE} DESTINATION bin ) - diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp deleted file mode 100644 index db12231a7..000000000 --- a/CommandLineInterface.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @author Gav Wood - * @date 2014 - * Solidity command line interface. - */ -#include "CommandLineInterface.h" - -#include -#include -#include - -#include - -#include "BuildInfo.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -namespace po = boost::program_options; - -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 = "json-abi"; -static string const g_argSolAbiStr = "sol-abi"; -static string const g_argAsmStr = "asm"; -static string const g_argAstStr = "ast"; -static string const g_argAstJson = "ast-json"; -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 string const g_argAddStandard = "add-std"; - -static void version() -{ - cout << "solc, the solidity compiler commandline interface " << dev::Version << endl - << " by Christian and Lefteris , (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, string const& _name) -{ - return _args.count(_name) && _args[_name].as() != OutputType::FILE; -} - -static bool needStdout(po::variables_map const& _args) -{ - - return - argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argSolAbiStr) || - argToStdout(_args, g_argNatspecUserStr) || argToStdout(_args, g_argAstJson) || - argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) || - argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr); -} - -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[g_argBinaryStr].as(); - 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) -{ - auto choice = m_args[g_argOpcodesStr].as(); - if (outputToStdout(choice)) - { - cout << "Opcodes: " << endl; - cout << eth::disassemble(m_compiler->getBytecode(_contract)); - cout << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + ".opcode"); - outFile << eth::disassemble(m_compiler->getBytecode(_contract)); - outFile.close(); - } -} - -void CommandLineInterface::handleBytecode(string const& _contract) -{ - if (m_args.count(g_argOpcodesStr)) - handleOpcode(_contract); - if (m_args.count(g_argBinaryStr)) - handleBinary(_contract); -} - -void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) -{ - std::string argName; - std::string suffix; - std::string title; - switch(_type) - { - case DocumentationType::ABIInterface: - argName = g_argAbiStr; - suffix = ".abi"; - title = "Contract JSON ABI"; - break; - case DocumentationType::ABISolidityInterface: - argName = g_argSolAbiStr; - suffix = ".sol"; - title = "Contract Solidity ABI"; - break; - case DocumentationType::NatspecUser: - argName = g_argNatspecUserStr; - suffix = ".docuser"; - title = "User Documentation"; - break; - case DocumentationType::NatspecDev: - argName = g_argNatspecDevStr; - 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(); - if (outputToStdout(choice)) - { - cout << title << endl; - cout << m_compiler->getMetadata(_contract, _type) << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + suffix); - outFile << m_compiler->getMetadata(_contract, _type); - outFile.close(); - } - } -} - -bool CommandLineInterface::parseArguments(int argc, char** argv) -{ - // 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()->default_value(false), "Optimize bytecode for size") - ("add-std", po::value()->default_value(false), "Add standard contracts") - ("input-file", po::value>(), "input file") - (g_argAstStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the AST of the contract.") - (g_argAstJson.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the AST of the contract in JSON format.") - (g_argAsmStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the EVM assembly of the contract.") - (g_argOpcodesStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the Opcodes of the contract.") - (g_argBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract in binary (hexadecimal).") - (g_argAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's JSON ABI interface.") - (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Solidity ABI interface.") - (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec user documentation.") - (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec developer documentation."); - - // 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[""].append(s); - } - } - else - for (string const& infile: m_args["input-file"].as>()) - { - auto path = boost::filesystem::path(infile); - if (!boost::filesystem::exists(path)) - { - cout << "Skipping non existant input file \"" << infile << "\"" << endl; - continue; - } - - if (!boost::filesystem::is_regular_file(path)) - { - cout << "\"" << infile << "\" is not a valid file. Skipping" << endl; - continue; - } - - m_sourceCodes[infile] = asString(dev::contents(infile)); - } - - m_compiler.reset(new CompilerStack(m_args["add-std"].as())); - 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()); - } - 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) - { - cerr << "Internal compiler error during compilation:" << endl - << boost::diagnostic_information(_exception); - 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::handleAst(string const& _argStr) -{ - string title; - string suffix; - - if (_argStr == g_argAstStr) - { - title = "Syntax trees:"; - suffix = ".ast"; - } - else if (_argStr == g_argAstJson) - { - title = "JSON AST:"; - suffix = ".json"; - } - else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal argStr for AST")); - - // do we need AST output? - if (m_args.count(_argStr)) - { - auto choice = m_args[_argStr].as(); - if (outputToStdout(choice)) - { - cout << title << endl << endl; - for (auto const& sourceCode: m_sourceCodes) - { - cout << endl << "======= " << sourceCode.first << " =======" << endl; - if (_argStr == g_argAstStr) - { - ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); - printer.print(cout); - } - else - { - ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); - converter.print(cout); - } - } - } - - if (outputToFile(choice)) - { - for (auto const& sourceCode: m_sourceCodes) - { - boost::filesystem::path p(sourceCode.first); - ofstream outFile(p.stem().string() + ".ast"); - if (_argStr == g_argAstStr) - { - ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); - printer.print(outFile); - } - else - { - ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); - converter.print(outFile); - } - outFile.close(); - } - } - } -} - -void CommandLineInterface::actOnInput() -{ - // do we need AST output? - handleAst(g_argAstStr); - handleAst(g_argAstJson); - - vector 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(g_argAsmStr)) - { - auto choice = m_args[g_argAsmStr].as(); - 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); - handleMeta(DocumentationType::ABIInterface, contract); - handleMeta(DocumentationType::ABISolidityInterface, contract); - handleMeta(DocumentationType::NatspecDev, contract); - handleMeta(DocumentationType::NatspecUser, contract); - } // end of contracts iteration -} - -} -} diff --git a/CommandLineInterface.h b/CommandLineInterface.h deleted file mode 100644 index 79029f9d1..000000000 --- a/CommandLineInterface.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @date 2014 - * Solidity command line interface. - */ -#pragma once - -#include -#include -#include - -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 handleAst(std::string const& _argStr); - void handleBinary(std::string const& _contract); - void handleOpcode(std::string const& _contract); - void handleBytecode(std::string const& _contract); - void handleMeta(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 m_sourceCodes; - /// Solidity compiler stack - std::unique_ptr m_compiler; -}; - -} -} diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile deleted file mode 100644 index b593cbf74..000000000 --- a/docker_emscripten/Dockerfile +++ /dev/null @@ -1,61 +0,0 @@ -FROM ubuntu:14.04 - -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update -RUN apt-get upgrade -y - -# Ethereum dependencies -RUN apt-get install -qy build-essential git cmake libcurl4-openssl-dev wget -RUN apt-get install -qy automake libtool yasm scons - -RUN useradd -ms /bin/bash user -USER user -WORKDIR /home/user - -# Emscripten SDK -RUN wget -c https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz -RUN tar xzf emsdk-portable.tar.gz -WORKDIR /home/user/emsdk_portable -RUN ./emsdk update && ./emsdk install latest && ./emsdk activate latest -ENV PATH $PATH:/home/user/emsdk_portable:/home/user/emsdk_portable/clang/fastcomp/build_master_64/bin:/home/user/emsdk_portable/emscripten/master - -USER root -RUN apt-get install -qy nodejs -USER user -RUN sed -i "s/NODE_JS = 'node'/NODE_JS = 'nodejs'/g" ~/.emscripten - -# CryptoPP -WORKDIR /home/user -RUN git clone https://github.com/mmoss/cryptopp.git -WORKDIR /home/user/cryptopp -RUN emcmake cmake -DCRYPTOPP_LIBRARY_TYPE=STATIC -DCRYPTOPP_RUNTIME_TYPE=STATIC && emmake make -j 4 -RUN ln -s . src/cryptopp - -# Boost -WORKDIR /home/user -RUN wget 'http://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.57.0%2F&ts=1421887207&use_mirror=cznic' -O boost_1_57_0.tar.bz2 -RUN tar xjf boost_1_57_0.tar.bz2 -WORKDIR /home/user/boost_1_57_0 -RUN ./bootstrap.sh --with-libraries=thread,system,regex -RUN sed -i 's/using gcc ;/using gcc : : \/home\/user\/emsdk_portable\/emscripten\/master\/em++ ;/g' ./project-config.jam -RUN sed -i 's/$(archiver\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emar/g' ./tools/build/src/tools/gcc.jam -RUN sed -i 's/$(ranlib\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emranlib/g' ./tools/build/src/tools/gcc.jam -RUN ./b2 link=static variant=release threading=single runtime-link=static thread system regex - -# Build soljs -WORKDIR /home/user -ADD https://api.github.com/repos/ethereum/cpp-ethereum/git/refs/heads/develop unused.txt -RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum -WORKDIR /home/user/cpp-ethereum -RUN git config --global user.email "me@example.com" -RUN git config --global user.name "Jane Doe" -ADD https://api.github.com/repos/chriseth/cpp-ethereum/git/refs/heads/solidity-js unused2.txt -RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum -# TODO this should be a proper merge but somehow causes problems -# NOTE that we only get the latest commit of that branch -RUN git cherry-pick solidityjs/solidity-js -RUN emcmake cmake -DETH_STATIC=1 -DONLY_SOLIDITY=1 -DHEADLESS=1 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc -RUN emmake make -j 6 soljs - -ENTRYPOINT cat soljs/soljs.js - diff --git a/main.cpp b/main.cpp deleted file mode 100644 index c5f72980d..000000000 --- a/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2014 - * Solidity commandline compiler. - */ - -#include "CommandLineInterface.h" - -int main(int argc, char** argv) -{ - dev::solidity::CommandLineInterface cli; - if (!cli.parseArguments(argc, argv)) - return 1; - if (!cli.processInput()) - return 1; - cli.actOnInput(); - - return 0; -} From 665edd3f8648e227dfe196a60162a7ff8e16f45c Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 4 Mar 2015 18:01:23 +0100 Subject: [PATCH 066/105] added source code printing for each output line. some changes after pr review --- CommandLineInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index db12231a7..08acb5ebd 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -424,13 +424,13 @@ void CommandLineInterface::actOnInput() if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; - m_compiler->streamAssembly(cout, contract); + m_compiler->streamAssembly(cout, contract, m_sourceCodes); } if (outputToFile(choice)) { ofstream outFile(contract + ".evm"); - m_compiler->streamAssembly(outFile, contract); + m_compiler->streamAssembly(outFile, contract, m_sourceCodes); outFile.close(); } } From 3fa4c64aef5dcd370b2c86613bb64ea5736e97c3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 9 Mar 2015 22:11:16 +0100 Subject: [PATCH 067/105] Fixed dockerfile. --- docker_emscripten/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index b593cbf74..06467a2c5 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -10,6 +10,7 @@ RUN apt-get install -qy automake libtool yasm scons RUN useradd -ms /bin/bash user USER user +ENV HOME /home/user WORKDIR /home/user # Emscripten SDK From c6653d5ffc41b7ee2758452d24c683ae18926585 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 9 Mar 2015 13:15:59 +0100 Subject: [PATCH 068/105] fixed new line for user input from terminal. --- CommandLineInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 08acb5ebd..01d8f8485 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -272,7 +272,7 @@ bool CommandLineInterface::processInput() while (!cin.eof()) { getline(cin, s); - m_sourceCodes[""].append(s); + m_sourceCodes[""].append(s + '\n'); } } else From c7ac1f55b25d3e6becfab02801ae5ea8cf125f82 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 10 Mar 2015 15:11:13 +0100 Subject: [PATCH 069/105] Fixed some checker warnings. --- CommandLineInterface.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 08acb5ebd..867e832d7 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -345,18 +345,11 @@ bool CommandLineInterface::processInput() void CommandLineInterface::handleAst(string const& _argStr) { string title; - string suffix; if (_argStr == g_argAstStr) - { title = "Syntax trees:"; - suffix = ".ast"; - } else if (_argStr == g_argAstJson) - { title = "JSON AST:"; - suffix = ".json"; - } else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal argStr for AST")); From 3dcc0f089331e060c4f5ead49740bfd8f1f80aab Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 17 Apr 2015 17:41:41 +0200 Subject: [PATCH 070/105] added asm-json flag to cl compiler Conflicts: libsolidity/CompilerStack.cpp --- CommandLineInterface.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 6ed90cdea..d21839f14 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -55,6 +55,7 @@ namespace solidity static string const g_argAbiStr = "json-abi"; static string const g_argSolAbiStr = "sol-abi"; static string const g_argAsmStr = "asm"; +static string const g_argAsmJsonStr = "asm-json"; static string const g_argAstStr = "ast"; static string const g_argAstJson = "ast-json"; static string const g_argBinaryStr = "binary"; @@ -80,10 +81,15 @@ static bool needStdout(po::variables_map const& _args) { return - argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argSolAbiStr) || - argToStdout(_args, g_argNatspecUserStr) || argToStdout(_args, g_argAstJson) || - argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) || - argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr); + argToStdout(_args, g_argAbiStr) || + argToStdout(_args, g_argSolAbiStr) || + argToStdout(_args, g_argNatspecUserStr) || + argToStdout(_args, g_argAstJson) || + argToStdout(_args, g_argNatspecDevStr) || + argToStdout(_args, g_argAsmStr) || + argToStdout(_args, g_argAsmJsonStr) || + argToStdout(_args, g_argOpcodesStr) || + argToStdout(_args, g_argBinaryStr); } static inline bool outputToFile(OutputType type) @@ -215,23 +221,25 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("add-std", po::value()->default_value(false), "Add standard contracts") ("input-file", po::value>(), "input file") (g_argAstStr.c_str(), po::value()->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()->value_name("stdout|file|both"), - "Request to output the AST of the contract in JSON format.") + "Request to output the AST of the contract in JSON format.") (g_argAsmStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the EVM assembly of the contract.") + "Request to output the EVM assembly of the contract.") + (g_argAsmJsonStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the EVM assembly of the contract in JSON format.") (g_argOpcodesStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the Opcodes of the contract.") + "Request to output the Opcodes of the contract.") (g_argBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract in binary (hexadecimal).") + "Request to output the contract in binary (hexadecimal).") (g_argAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's JSON ABI interface.") + "Request to output the contract's JSON ABI interface.") (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Solidity ABI interface.") + "Request to output the contract's Solidity ABI interface.") (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec user documentation.") + "Request to output the contract's Natspec user documentation.") (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec developer documentation."); + "Request to output the contract's Natspec developer documentation."); // All positional options should be interpreted as input files po::positional_options_description p; @@ -417,13 +425,13 @@ void CommandLineInterface::actOnInput() if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; - m_compiler->streamAssembly(cout, contract, m_sourceCodes); + m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); } if (outputToFile(choice)) { ofstream outFile(contract + ".evm"); - m_compiler->streamAssembly(outFile, contract, m_sourceCodes); + m_compiler->streamAssembly(outFile, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); outFile.close(); } } From 104c5bca078ba31a128e298efb48f1349efaae08 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 17 Apr 2015 16:13:34 +0200 Subject: [PATCH 071/105] initial output for asm-json flag. Conflicts: libevmcore/Assembly.cpp --- CommandLineInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index d21839f14..cb924d9b5 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -419,9 +419,9 @@ void CommandLineInterface::actOnInput() cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? - if (m_args.count(g_argAsmStr)) + if (m_args.count(g_argAsmStr) || m_args.count(g_argAsmJsonStr)) { - auto choice = m_args[g_argAsmStr].as(); + auto choice = m_args.count(g_argAsmStr) ? m_args[g_argAsmStr].as() : m_args[g_argAsmJsonStr].as(); if (outputToStdout(choice)) { cout << "EVM assembly:" << endl; From 8e04b27252abf101a2899b5729fe012c159dab80 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 15 Apr 2015 13:28:49 +0200 Subject: [PATCH 072/105] fixed extension of file json format changed value for PUSH to hex --- CommandLineInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index cb924d9b5..182015709 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -430,7 +430,7 @@ void CommandLineInterface::actOnInput() if (outputToFile(choice)) { - ofstream outFile(contract + ".evm"); + ofstream outFile(contract + (m_args.count(g_argAsmJsonStr) ? "_evm.json" : ".evm")); m_compiler->streamAssembly(outFile, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); outFile.close(); } From 41c2990ed7b93862219715b4c77317e1443bb5ce Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 17 Apr 2015 17:59:05 +0200 Subject: [PATCH 073/105] Add jsoncpp dependency for solidity-js. --- docker_emscripten/Dockerfile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index 06467a2c5..1ad1875d7 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -43,7 +43,14 @@ RUN sed -i 's/$(archiver\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\ RUN sed -i 's/$(ranlib\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emranlib/g' ./tools/build/src/tools/gcc.jam RUN ./b2 link=static variant=release threading=single runtime-link=static thread system regex -# Build soljs +# Json-CPP +WORKDIR /home/user +RUN git clone https://github.com/open-source-parsers/jsoncpp.git +WORKDIR /home/user/jsoncpp +RUN emcmake cmake -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -G "Unix Makefiles" . +RUN emmake make + +## Build soljs WORKDIR /home/user ADD https://api.github.com/repos/ethereum/cpp-ethereum/git/refs/heads/develop unused.txt RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum @@ -55,8 +62,10 @@ RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum # TODO this should be a proper merge but somehow causes problems # NOTE that we only get the latest commit of that branch RUN git cherry-pick solidityjs/solidity-js -RUN emcmake cmake -DETH_STATIC=1 -DONLY_SOLIDITY=1 -DHEADLESS=1 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc +RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc RUN emmake make -j 6 soljs -ENTRYPOINT cat soljs/soljs.js +WORKDIR /home/user/cpp-ethereum/soljs +# somehow it does not work to pipe out both files +#ENTRYPOINT tar -c soljs.js soljs.js.mem | base64 From 21a4c342d8102b30cde1e10f2750b8f5cb1317c3 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 28 Jan 2015 08:50:53 +0100 Subject: [PATCH 074/105] JSON compiler. --- CMakeLists.txt | 7 +++ jsonCompiler.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 jsonCompiler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d3a39dbc8..177823963 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_policy(SET CMP0015 NEW) set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +list(REMOVE_ITEM SRC_LIST "./jsonCompiler.cpp") include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) @@ -18,3 +19,9 @@ target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) +if (ETH_STATIC) + add_library(soljson STATIC jsonCompiler.cpp ${HEADERS}) +else() + add_library(soljson SHARED jsonCompiler.cpp ${HEADERS}) +endif() +target_link_libraries(soljson solidity) diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp new file mode 100644 index 000000000..7475483c3 --- /dev/null +++ b/jsonCompiler.cpp @@ -0,0 +1,124 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * JSON interface for the solidity compiler to be used from Javascript. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace solidity; + +string formatError(Exception const& _exception, string const& _name, CompilerStack const& _compiler) +{ + ostringstream errorOutput; + SourceReferenceFormatter::printExceptionInformation(errorOutput, _exception, _name, _compiler); + + Json::Value output(Json::objectValue); + output["error"] = errorOutput.str(); + return Json::FastWriter().write(output); +} + +string compile(string _input, bool optimize) +{ + StringMap sources; + sources[""] = _input; + + Json::Value output(Json::objectValue); + CompilerStack compiler; + try + { + compiler.compile(_input, optimize); + } + catch (ParserError const& exception) + { + return formatError(exception, "Parser error", compiler); + } + catch (DeclarationError const& exception) + { + return formatError(exception, "Declaration error", compiler); + } + catch (TypeError const& exception) + { + return formatError(exception, "Type error", compiler); + } + catch (CompilerError const& exception) + { + return formatError(exception, "Compiler error", compiler); + } + catch (InternalCompilerError const& exception) + { + return formatError(exception, "Internal compiler error", compiler); + } + catch (Exception const& exception) + { + output["error"] = "Exception during compilation: " + boost::diagnostic_information(exception); + return Json::FastWriter().write(output); + } + catch (...) + { + output["error"] = "Unknown exception during compilation."; + return Json::FastWriter().write(output); + } + + output["contracts"] = Json::Value(Json::objectValue); + for (string const& contractName: compiler.getContractNames()) + { + Json::Value contractData(Json::objectValue); + contractData["solidity_interface"] = compiler.getSolidityInterface(contractName); + contractData["interface"] = compiler.getInterface(contractName); + contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); + contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); + ostringstream unused; + contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources); + output["contracts"][contractName] = contractData; + } + + output["sources"] = Json::Value(Json::objectValue); + output["sources"][""] = Json::Value(Json::objectValue); + output["sources"][""]["AST"] = ASTJsonConverter(compiler.getAST("")).json(); + + return Json::FastWriter().write(output); +} + +static string outputBuffer; + +extern "C" +{ +extern char const* compileJSON(char const* _input, bool optimize) +{ + outputBuffer = compile(_input, optimize); + return outputBuffer.c_str(); +} +} From be3f9e26814c2ea57ad42f5893802e7213d64dce Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Apr 2015 11:33:02 +0200 Subject: [PATCH 075/105] Style fixes. --- jsonCompiler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index 7475483c3..3079df69f 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -50,7 +50,7 @@ string formatError(Exception const& _exception, string const& _name, CompilerSta return Json::FastWriter().write(output); } -string compile(string _input, bool optimize) +string compile(string _input, bool _optimize) { StringMap sources; sources[""] = _input; @@ -59,7 +59,7 @@ string compile(string _input, bool optimize) CompilerStack compiler; try { - compiler.compile(_input, optimize); + compiler.compile(_input, _optimize); } catch (ParserError const& exception) { @@ -116,9 +116,9 @@ static string outputBuffer; extern "C" { -extern char const* compileJSON(char const* _input, bool optimize) +extern char const* compileJSON(char const* _input, bool _optimize) { - outputBuffer = compile(_input, optimize); + outputBuffer = compile(_input, _optimize); return outputBuffer.c_str(); } } From 5fff87cf2b747f5ca5446aeab387ebca52080ea6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Apr 2015 12:59:09 +0200 Subject: [PATCH 076/105] Modifications to docker file to build the json compiler. --- docker_emscripten/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index 1ad1875d7..23a0caba9 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -63,9 +63,9 @@ RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum # NOTE that we only get the latest commit of that branch RUN git cherry-pick solidityjs/solidity-js RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc -RUN emmake make -j 6 soljs +RUN emmake make -j 6 soljson -WORKDIR /home/user/cpp-ethereum/soljs +WORKDIR /home/user/cpp-ethereum/solc # somehow it does not work to pipe out both files -#ENTRYPOINT tar -c soljs.js soljs.js.mem | base64 +#ENTRYPOINT tar -c soljson.js soljson.js.mem | base64 From 61c7f29b46f0fc417d6cd90d15ef998e7482e6ab Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Apr 2015 16:27:45 +0200 Subject: [PATCH 077/105] Actually output assembly in JSON format. --- jsonCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index 3079df69f..6f3834af4 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -101,7 +101,7 @@ string compile(string _input, bool _optimize) contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); ostringstream unused; - contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources); + contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources, true); output["contracts"][contractName] = contractData; } From ec01bfa074a42bae927b4d7d554f33d04213140d Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 23 Apr 2015 14:40:42 +0200 Subject: [PATCH 078/105] json output for the commandline compiler. --- CommandLineInterface.cpp | 101 ++++++++++++++++++++++++++++++++++----- CommandLineInterface.h | 1 + 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 182015709..2d8720371 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "BuildInfo.h" #include @@ -50,6 +51,7 @@ 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 = "json-abi"; @@ -64,6 +66,18 @@ static string const g_argNatspecDevStr = "natspec-dev"; static string const g_argNatspecUserStr = "natspec-user"; static string const g_argAddStandard = "add-std"; +/// Possible arguments to for --combined-json +static set const g_combinedJsonArgs{ + "binary", + "opcodes", + "json-abi", + "sol-abi", + "asm", + "ast", + "natspec-user", + "natspec-dev" +}; + static void version() { cout << "solc, the solidity compiler commandline interface " << dev::Version << endl @@ -72,24 +86,24 @@ static void version() 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::FILE; } -static bool needStdout(po::variables_map const& _args) +static bool needsHumanTargetedStdout(po::variables_map const& _args) { return - argToStdout(_args, g_argAbiStr) || - argToStdout(_args, g_argSolAbiStr) || - argToStdout(_args, g_argNatspecUserStr) || - argToStdout(_args, g_argAstJson) || - argToStdout(_args, g_argNatspecDevStr) || - argToStdout(_args, g_argAsmStr) || - argToStdout(_args, g_argAsmJsonStr) || - argToStdout(_args, g_argOpcodesStr) || - argToStdout(_args, g_argBinaryStr); + humanTargetedStdout(_args, g_argAbiStr) || + humanTargetedStdout(_args, g_argSolAbiStr) || + humanTargetedStdout(_args, g_argNatspecUserStr) || + humanTargetedStdout(_args, g_argAstJson) || + humanTargetedStdout(_args, g_argNatspecDevStr) || + humanTargetedStdout(_args, g_argAsmStr) || + humanTargetedStdout(_args, g_argAsmJsonStr) || + humanTargetedStdout(_args, g_argOpcodesStr) || + humanTargetedStdout(_args, g_argBinaryStr); } static inline bool outputToFile(OutputType type) @@ -220,6 +234,11 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) ("optimize", po::value()->default_value(false), "Optimize bytecode for size") ("add-std", po::value()->default_value(false), "Add standard contracts") ("input-file", po::value>(), "input file") + ( + "combined-json", + po::value()->value_name(boost::join(g_combinedJsonArgs, ",")), + "Output a single json document containing the specified information, can be combined." + ) (g_argAstStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the AST of the contract.") (g_argAstJson.c_str(), po::value()->value_name("stdout|file|both"), @@ -255,6 +274,16 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) cout << _exception.what() << endl; return false; } + if (m_args.count("combined-json")) + { + vector requests; + for (string const& item: boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(","))) + if (!g_combinedJsonArgs.count(item)) + { + cout << "Invalid option to --combined-json: " << item << endl; + return false; + } + } po::notify(m_args); if (m_args.count("help")) @@ -350,6 +379,52 @@ bool CommandLineInterface::processInput() return true; } +void CommandLineInterface::handleCombinedJSON() +{ + Json::Value output(Json::objectValue); + + set requests; + boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(",")); + vector 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) { string title; @@ -408,6 +483,8 @@ void CommandLineInterface::handleAst(string const& _argStr) void CommandLineInterface::actOnInput() { + handleCombinedJSON(); + // do we need AST output? handleAst(g_argAstStr); handleAst(g_argAstJson); @@ -415,7 +492,7 @@ void CommandLineInterface::actOnInput() vector contracts = m_compiler->getContractNames(); for (string const& contract: contracts) { - if (needStdout(m_args)) + if (needsHumanTargetedStdout(m_args)) cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 79029f9d1..459f17d3e 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -53,6 +53,7 @@ public: void actOnInput(); private: + void handleCombinedJSON(); void handleAst(std::string const& _argStr); void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); From 245620bdc2da688c5738045ef6e1d739f99cb075 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 23 Apr 2015 15:47:54 +0200 Subject: [PATCH 079/105] Removed extra blank line. --- CommandLineInterface.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 2d8720371..5e4c901f3 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -51,7 +51,6 @@ 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 = "json-abi"; From d8f7051685c7a335bac68af628d33b4147b030be Mon Sep 17 00:00:00 2001 From: Ryan Casey Date: Thu, 23 Apr 2015 09:42:01 -0700 Subject: [PATCH 080/105] Direct more mundane failures to cerr as well. --- CommandLineInterface.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 5e4c901f3..0cc1ab259 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -270,7 +270,7 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) } catch (po::error const& _exception) { - cout << _exception.what() << endl; + cerr << _exception.what() << endl; return false; } if (m_args.count("combined-json")) @@ -279,7 +279,7 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) for (string const& item: boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(","))) if (!g_combinedJsonArgs.count(item)) { - cout << "Invalid option to --combined-json: " << item << endl; + cerr << "Invalid option to --combined-json: " << item << endl; return false; } } @@ -317,13 +317,13 @@ bool CommandLineInterface::processInput() auto path = boost::filesystem::path(infile); if (!boost::filesystem::exists(path)) { - cout << "Skipping non existant input file \"" << infile << "\"" << endl; + cerr << "Skipping non existant input file \"" << infile << "\"" << endl; continue; } if (!boost::filesystem::is_regular_file(path)) { - cout << "\"" << infile << "\" is not a valid file. Skipping" << endl; + cerr << "\"" << infile << "\" is not a valid file. Skipping" << endl; continue; } From 87e8c8151436ec45236309710d47b97ae8248d49 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 24 Apr 2015 11:48:23 +0200 Subject: [PATCH 081/105] Do not handle combined JSON if option not given. --- CommandLineInterface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 5e4c901f3..eadc6c56f 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -380,6 +380,9 @@ bool CommandLineInterface::processInput() void CommandLineInterface::handleCombinedJSON() { + if (!m_args.count("combined-json")) + return; + Json::Value output(Json::objectValue); set requests; From 075b4f87b953deace046be4e9ff4e621fb588654 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Apr 2015 11:30:33 +0200 Subject: [PATCH 082/105] Use BUILD_SHARED_LIB --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 177823963..c8e74ed71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,9 +19,5 @@ target_link_libraries(${EXECUTABLE} solidity) install( TARGETS ${EXECUTABLE} DESTINATION bin ) -if (ETH_STATIC) - add_library(soljson STATIC jsonCompiler.cpp ${HEADERS}) -else() - add_library(soljson SHARED jsonCompiler.cpp ${HEADERS}) -endif() +add_library(soljson jsonCompiler.cpp ${HEADERS}) target_link_libraries(soljson solidity) From e78be5f4be99c0ecef4d8984dba329dc01da03b6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 4 May 2015 16:21:44 +0200 Subject: [PATCH 083/105] Feature for commandline compiler to output the function signature hashes. --- CommandLineInterface.cpp | 23 +++++++++++++++++++++++ CommandLineInterface.h | 1 + 2 files changed, 24 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index d5ff7b297..0b5e046d0 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -55,6 +55,7 @@ namespace solidity // extensions and other attributes would be a better choice here? static string const g_argAbiStr = "json-abi"; static string const g_argSolAbiStr = "sol-abi"; +static string const g_argSignatureHashes = "hashes"; static string const g_argAsmStr = "asm"; static string const g_argAsmJsonStr = "asm-json"; static string const g_argAstStr = "ast"; @@ -96,6 +97,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) return humanTargetedStdout(_args, g_argAbiStr) || humanTargetedStdout(_args, g_argSolAbiStr) || + humanTargetedStdout(_args, g_argSignatureHashes) || humanTargetedStdout(_args, g_argNatspecUserStr) || humanTargetedStdout(_args, g_argAstJson) || humanTargetedStdout(_args, g_argNatspecDevStr) || @@ -173,6 +175,24 @@ void CommandLineInterface::handleBytecode(string const& _contract) handleBinary(_contract); } +void CommandLineInterface::handleSignatureHashes(string const& _contract) +{ + string out; + for (auto const& it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions()) + out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n"; + + auto choice = m_args[g_argSignatureHashes].as(); + if (outputToStdout(choice)) + cout << "Function signatures: " << endl << out; + + if (outputToFile(choice)) + { + ofstream outFile(_contract + ".signatures"); + outFile << out; + outFile.close(); + } +} + void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) { std::string argName; @@ -254,6 +274,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) "Request to output the contract's JSON ABI interface.") (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract's Solidity ABI interface.") + (g_argSignatureHashes.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the contract's functions' signature hashes.") (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract's Natspec user documentation.") (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), @@ -516,6 +538,7 @@ void CommandLineInterface::actOnInput() } handleBytecode(contract); + handleSignatureHashes(contract); handleMeta(DocumentationType::ABIInterface, contract); handleMeta(DocumentationType::ABISolidityInterface, contract); handleMeta(DocumentationType::NatspecDev, contract); diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 459f17d3e..7d3a067cd 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -58,6 +58,7 @@ private: void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); void handleBytecode(std::string const& _contract); + void handleSignatureHashes(std::string const& _contract); void handleMeta(DocumentationType _type, std::string const& _contract); From a9d5cba6b2c6a5ce8ec6e898e4e7291958544661 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 4 May 2015 16:50:30 +0200 Subject: [PATCH 084/105] Removed layouting space. --- CommandLineInterface.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 0b5e046d0..0d5f47242 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -51,20 +51,18 @@ 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 = "json-abi"; -static string const g_argSolAbiStr = "sol-abi"; +static string const g_argAbiStr = "json-abi"; +static string const g_argSolAbiStr = "sol-abi"; static string const g_argSignatureHashes = "hashes"; -static string const g_argAsmStr = "asm"; -static string const g_argAsmJsonStr = "asm-json"; -static string const g_argAstStr = "ast"; -static string const g_argAstJson = "ast-json"; -static string const g_argBinaryStr = "binary"; -static string const g_argOpcodesStr = "opcodes"; -static string const g_argNatspecDevStr = "natspec-dev"; +static string const g_argAsmStr = "asm"; +static string const g_argAsmJsonStr = "asm-json"; +static string const g_argAstStr = "ast"; +static string const g_argAstJson = "ast-json"; +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 string const g_argAddStandard = "add-std"; +static string const g_argAddStandard = "add-std"; /// Possible arguments to for --combined-json static set const g_combinedJsonArgs{ From b5491873bc5d430ee66874857d00ada5260bef07 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 5 May 2015 17:08:30 +0200 Subject: [PATCH 085/105] Fix for exception if function hashes not requested. --- CommandLineInterface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 0d5f47242..e6f03a2ef 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -175,6 +175,9 @@ void CommandLineInterface::handleBytecode(string const& _contract) void CommandLineInterface::handleSignatureHashes(string const& _contract) { + if (!m_args.count(g_argSignatureHashes)) + return; + string out; for (auto const& it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions()) out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n"; From 16e468460fab786ddcdff7944e993bd852166f25 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 6 May 2015 10:43:59 +0200 Subject: [PATCH 086/105] Structural gas estimator. --- CommandLineInterface.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index e6f03a2ef..944c8f68a 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace std; namespace po = boost::program_options; @@ -464,6 +465,17 @@ void CommandLineInterface::handleAst(string const& _argStr) // do we need AST output? if (m_args.count(_argStr)) { + StructuralGasEstimator gasEstimator; + vector asts; + for (auto const& sourceCode: m_sourceCodes) + asts.push_back(&m_compiler->getAST(sourceCode.first)); + map gasCosts; + if (m_compiler->getRuntimeAssemblyItems()) + gasCosts = gasEstimator.breakToStatementLevel( + gasEstimator.performEstimation(*m_compiler->getRuntimeAssemblyItems(), asts), + asts + ); + auto choice = m_args[_argStr].as(); if (outputToStdout(choice)) { @@ -473,7 +485,11 @@ void CommandLineInterface::handleAst(string const& _argStr) cout << endl << "======= " << sourceCode.first << " =======" << endl; if (_argStr == g_argAstStr) { - ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); + ASTPrinter printer( + m_compiler->getAST(sourceCode.first), + sourceCode.second, + gasCosts + ); printer.print(cout); } else From ed0193d9e4dd5d23ec5c14ed008757f4723f73ed Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 May 2015 11:59:59 +0200 Subject: [PATCH 087/105] package solc, eth, ethminer, rlp && abi in cpack nsis installer --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8e74ed71..14e95a4e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) -install( TARGETS ${EXECUTABLE} DESTINATION bin ) +eth_install_executable(${EXECUTABLE}) add_library(soljson jsonCompiler.cpp ${HEADERS}) target_link_libraries(soljson solidity) From 01ec30338851142a397fbb53b2959b0822d2cc76 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 7 May 2015 02:23:28 +0200 Subject: [PATCH 088/105] Fix macos builds following changes from #1809. --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14e95a4e7..e60d3c8cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,11 @@ target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) -eth_install_executable(${EXECUTABLE}) +if (APPLE) + install(TARGETS ${EXECUTABLE} DESTINATION bin) +else() + eth_install_executable(${EXECUTABLE}) +endif() add_library(soljson jsonCompiler.cpp ${HEADERS}) target_link_libraries(soljson solidity) From c82a3e06a01174831b7c919824c71110b5d8e267 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 17:00:08 +0200 Subject: [PATCH 089/105] Function hashes for JSON compiler. --- jsonCompiler.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index 6f3834af4..d47903fca 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -50,6 +50,14 @@ string formatError(Exception const& _exception, string const& _name, CompilerSta return Json::FastWriter().write(output); } +Json::Value functionHashes(ContractDefinition const& _contract) +{ + Json::Value functionHashes(Json::objectValue); + for (auto const& it: _contract.getInterfaceFunctions()) + functionHashes[it.second->externalSignature()] = toHex(it.first.ref()); + return functionHashes; +} + string compile(string _input, bool _optimize) { StringMap sources; @@ -100,6 +108,7 @@ string compile(string _input, bool _optimize) contractData["interface"] = compiler.getInterface(contractName); contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); + contractData["functionHashes"] = functionHashes(compiler.getContractDefinition(contractName)); ostringstream unused; contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources, true); output["contracts"][contractName] = contractData; From 61fae129f2f1ae7ed73603edf06b48f5e8c8582f Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 22 May 2015 10:48:54 +0200 Subject: [PATCH 090/105] Functional gas estimator. --- CommandLineInterface.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 944c8f68a..b81fcad1c 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include using namespace std; namespace po = boost::program_options; @@ -465,14 +465,13 @@ void CommandLineInterface::handleAst(string const& _argStr) // do we need AST output? if (m_args.count(_argStr)) { - StructuralGasEstimator gasEstimator; vector asts; for (auto const& sourceCode: m_sourceCodes) asts.push_back(&m_compiler->getAST(sourceCode.first)); map gasCosts; if (m_compiler->getRuntimeAssemblyItems()) - gasCosts = gasEstimator.breakToStatementLevel( - gasEstimator.performEstimation(*m_compiler->getRuntimeAssemblyItems(), asts), + gasCosts = GasEstimator::breakToStatementLevel( + GasEstimator::structuralEstimation(*m_compiler->getRuntimeAssemblyItems(), asts), asts ); From fdbce582ab6f6028f4bf3081f1ce24ddc2473ea2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 22 May 2015 14:19:58 +0200 Subject: [PATCH 091/105] Commandline interface for gas estimation. --- CommandLineInterface.cpp | 32 ++++++++++++++++++++++++++++++++ CommandLineInterface.h | 1 + 2 files changed, 33 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index b81fcad1c..c86938f81 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,7 @@ namespace solidity static string const g_argAbiStr = "json-abi"; static string const g_argSolAbiStr = "sol-abi"; static string const g_argSignatureHashes = "hashes"; +static string const g_argGas = "gas"; static string const g_argAsmStr = "asm"; static string const g_argAsmJsonStr = "asm-json"; static string const g_argAstStr = "ast"; @@ -94,6 +96,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) { return + _args.count(g_argGas) || humanTargetedStdout(_args, g_argAbiStr) || humanTargetedStdout(_args, g_argSolAbiStr) || humanTargetedStdout(_args, g_argSignatureHashes) || @@ -245,6 +248,30 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co } } +void CommandLineInterface::handleGasEstimation(string const& _contract) +{ + using Gas = GasEstimator::GasConsumption; + if (!m_compiler->getAssemblyItems(_contract) && !m_compiler->getRuntimeAssemblyItems(_contract)) + return; + cout << "Gas estimation:" << endl; + if (eth::AssemblyItems const* items = m_compiler->getAssemblyItems(_contract)) + { + Gas gas = GasEstimator::functionalEstimation(*items); + u256 bytecodeSize(m_compiler->getRuntimeBytecode(_contract).size()); + cout << "[construction]:\t"; + cout << gas << " + " << (bytecodeSize * eth::c_createDataGas) << " = "; + gas += bytecodeSize * eth::c_createDataGas; + cout << gas << endl; + } + if (eth::AssemblyItems const* items = m_compiler->getRuntimeAssemblyItems(_contract)) + for (auto it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions()) + { + string sig = it.second->externalSignature(); + GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, sig); + cout << sig << ":\t" << gas << endl; + } +} + bool CommandLineInterface::parseArguments(int argc, char** argv) { // Declare the supported options. @@ -278,6 +305,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) "Request to output the contract's Solidity ABI interface.") (g_argSignatureHashes.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract's functions' signature hashes.") + (g_argGas.c_str(), + "Request to output an estimate for each function's maximal gas usage.") (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract's Natspec user documentation.") (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), @@ -553,6 +582,9 @@ void CommandLineInterface::actOnInput() } } + if (m_args.count(g_argGas)) + handleGasEstimation(contract); + handleBytecode(contract); handleSignatureHashes(contract); handleMeta(DocumentationType::ABIInterface, contract); diff --git a/CommandLineInterface.h b/CommandLineInterface.h index 7d3a067cd..46b9b1e22 100644 --- a/CommandLineInterface.h +++ b/CommandLineInterface.h @@ -61,6 +61,7 @@ private: void handleSignatureHashes(std::string const& _contract); void handleMeta(DocumentationType _type, std::string const& _contract); + void handleGasEstimation(std::string const& _contract); /// Compiler arguments variable map boost::program_options::variables_map m_args; From b6fa534868fdf631dd432574008f2a3faadd41ca Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 26 May 2015 11:27:59 +0200 Subject: [PATCH 092/105] Gas estimation for internal functions. --- CommandLineInterface.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index c86938f81..8129f60c5 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -258,18 +258,38 @@ void CommandLineInterface::handleGasEstimation(string const& _contract) { Gas gas = GasEstimator::functionalEstimation(*items); u256 bytecodeSize(m_compiler->getRuntimeBytecode(_contract).size()); - cout << "[construction]:\t"; - cout << gas << " + " << (bytecodeSize * eth::c_createDataGas) << " = "; + cout << "construction:" << endl; + cout << " " << gas << " + " << (bytecodeSize * eth::c_createDataGas) << " = "; gas += bytecodeSize * eth::c_createDataGas; cout << gas << endl; } if (eth::AssemblyItems const* items = m_compiler->getRuntimeAssemblyItems(_contract)) - for (auto it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions()) + { + ContractDefinition const& contract = m_compiler->getContractDefinition(_contract); + cout << "external:" << endl; + for (auto it: contract.getInterfaceFunctions()) { string sig = it.second->externalSignature(); GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, sig); - cout << sig << ":\t" << gas << endl; + cout << " " << sig << ":\t" << gas << endl; } + cout << "internal:" << endl; + for (auto const& it: contract.getDefinedFunctions()) + { + if (it->isPartOfExternalInterface() || it->isConstructor()) + continue; + size_t entry = m_compiler->getFunctionEntryPoint(_contract, *it); + GasEstimator::GasConsumption gas = GasEstimator::GasConsumption::infinite(); + if (entry > 0) + gas = GasEstimator::functionalEstimation(*items, entry, *it); + FunctionType type(*it); + cout << " " << it->getName() << "("; + auto end = type.getParameterTypes().end(); + for (auto it = type.getParameterTypes().begin(); it != end; ++it) + cout << (*it)->toString() << (it + 1 == end ? "" : ","); + cout << "):\t" << gas << endl; + } + } } bool CommandLineInterface::parseArguments(int argc, char** argv) From 90c1203e566726b94c89820191cd0a6e89c91ec6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 1 Jun 2015 13:25:02 +0200 Subject: [PATCH 093/105] Gas estimates for JSON compiler. --- jsonCompiler.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index d47903fca..7bde3e47c 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,61 @@ Json::Value functionHashes(ContractDefinition const& _contract) return functionHashes; } +Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) +{ + if (_gas.isInfinite || _gas.value > std::numeric_limits::max()) + return Json::Value(Json::nullValue); + else + return Json::Value(Json::LargestUInt(_gas.value)); +} + +Json::Value estimateGas(CompilerStack const& _compiler, string const& _contract) +{ + Json::Value gasEstimates(Json::objectValue); + using Gas = GasEstimator::GasConsumption; + if (!_compiler.getAssemblyItems(_contract) && !_compiler.getRuntimeAssemblyItems(_contract)) + return gasEstimates; + if (eth::AssemblyItems const* items = _compiler.getAssemblyItems(_contract)) + { + Gas gas = GasEstimator::functionalEstimation(*items); + u256 bytecodeSize(_compiler.getRuntimeBytecode(_contract).size()); + Json::Value creationGas(Json::arrayValue); + creationGas[0] = gasToJson(gas); + creationGas[1] = gasToJson(bytecodeSize * eth::c_createDataGas); + gasEstimates["creation"] = creationGas; + } + if (eth::AssemblyItems const* items = _compiler.getRuntimeAssemblyItems(_contract)) + { + ContractDefinition const& contract = _compiler.getContractDefinition(_contract); + Json::Value externalFunctions(Json::objectValue); + for (auto it: contract.getInterfaceFunctions()) + { + string sig = it.second->externalSignature(); + externalFunctions[sig] = gasToJson(GasEstimator::functionalEstimation(*items, sig)); + } + gasEstimates["external"] = externalFunctions; + Json::Value internalFunctions(Json::objectValue); + for (auto const& it: contract.getDefinedFunctions()) + { + if (it->isPartOfExternalInterface() || it->isConstructor()) + continue; + size_t entry = _compiler.getFunctionEntryPoint(_contract, *it); + GasEstimator::GasConsumption gas = GasEstimator::GasConsumption::infinite(); + if (entry > 0) + gas = GasEstimator::functionalEstimation(*items, entry, *it); + FunctionType type(*it); + string sig = it->getName() + "("; + auto end = type.getParameterTypes().end(); + for (auto it = type.getParameterTypes().begin(); it != end; ++it) + sig += (*it)->toString() + (it + 1 == end ? "" : ","); + sig += ")"; + internalFunctions[sig] = gasToJson(gas); + } + gasEstimates["internal"] = internalFunctions; + } + return gasEstimates; +} + string compile(string _input, bool _optimize) { StringMap sources; @@ -109,6 +165,7 @@ string compile(string _input, bool _optimize) contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); contractData["functionHashes"] = functionHashes(compiler.getContractDefinition(contractName)); + contractData["gasEstimates"] = estimateGas(compiler, contractName); ostringstream unused; contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources, true); output["contracts"][contractName] = contractData; From a53859e3094a8740ebaf06eaf189a5755f273fb9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 1 Jun 2015 12:32:59 +0200 Subject: [PATCH 094/105] Compute constants --- CommandLineInterface.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 8129f60c5..860b4c3b8 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -299,7 +299,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) desc.add_options() ("help", "Show help message and exit") ("version", "Show version and exit") - ("optimize", po::value()->default_value(false), "Optimize bytecode for size") + ("optimize", po::value()->default_value(false), "Optimize bytecode") + ("optimize-runs", po::value()->default_value(200), "Estimated number of contract runs for optimizer.") ("add-std", po::value()->default_value(false), "Add standard contracts") ("input-file", po::value>(), "input file") ( @@ -409,7 +410,11 @@ bool CommandLineInterface::processInput() 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 optimize = m_args["optimize"].as(); + unsigned runs = m_args["optimize-runs"].as(); + if (m_args.count("optimize-runs")) + optimize = true; + m_compiler->compile(optimize, runs); } catch (ParserError const& _exception) { From a418656615c82a03844adabc9d2e2c6da9c0716c Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 6 Jun 2015 15:32:15 +0200 Subject: [PATCH 095/105] Fix: Optimiser was enabled by default. --- CommandLineInterface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 860b4c3b8..e65c602ab 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -412,8 +412,6 @@ bool CommandLineInterface::processInput() // TODO: Perhaps we should not compile unless requested bool optimize = m_args["optimize"].as(); unsigned runs = m_args["optimize-runs"].as(); - if (m_args.count("optimize-runs")) - optimize = true; m_compiler->compile(optimize, runs); } catch (ParserError const& _exception) From f9bbe3279e7ecbbc6c25bc484500977a56af8e52 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 16 Jun 2015 14:58:03 +0200 Subject: [PATCH 096/105] Some changes in libdevcore. --- CommandLineInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index e65c602ab..ec2a90033 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -401,7 +401,7 @@ bool CommandLineInterface::processInput() continue; } - m_sourceCodes[infile] = asString(dev::contents(infile)); + m_sourceCodes[infile] = dev::contentsString(infile); } m_compiler.reset(new CompilerStack(m_args["add-std"].as())); From ffb7d94035bf650c79cac1f94e2711795ee3f85b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 18 Jun 2015 17:38:26 +0200 Subject: [PATCH 097/105] Added fallback function to gas estimation and fixed mix gas estimation. Fixes #2156 --- CommandLineInterface.cpp | 5 +++++ jsonCompiler.cpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index ec2a90033..c95f34f62 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -273,6 +273,11 @@ void CommandLineInterface::handleGasEstimation(string const& _contract) GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, sig); cout << " " << sig << ":\t" << gas << endl; } + if (contract.getFallbackFunction()) + { + GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, "INVALID"); + cout << " fallback:\t" << gas << endl; + } cout << "internal:" << endl; for (auto const& it: contract.getDefinedFunctions()) { diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index 7bde3e47c..340713b1d 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -91,6 +91,8 @@ Json::Value estimateGas(CompilerStack const& _compiler, string const& _contract) string sig = it.second->externalSignature(); externalFunctions[sig] = gasToJson(GasEstimator::functionalEstimation(*items, sig)); } + if (contract.getFallbackFunction()) + externalFunctions[""] = gasToJson(GasEstimator::functionalEstimation(*items, "INVALID")); gasEstimates["external"] = externalFunctions; Json::Value internalFunctions(Json::objectValue); for (auto const& it: contract.getDefinedFunctions()) From 66e0e6028fd172dda64aa6ca9bc3226b4b529b68 Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sat, 4 Jul 2015 23:51:20 +0800 Subject: [PATCH 098/105] add missing dependencies for BuildInfo.h in libwebthree and solc --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e60d3c8cf..df72f52dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set(EXECUTABLE solc) file(GLOB HEADERS "*.h") add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +add_dependencies(${EXECUTABLE} BuildInfo.h) + target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) target_link_libraries(${EXECUTABLE} solidity) From b458d543b55dbf0438bd45df843f637c8b71485a Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 8 Jul 2015 19:32:43 +0200 Subject: [PATCH 099/105] Versioning for Solidity. --- CommandLineInterface.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index c95f34f62..00bf2ab33 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -81,9 +82,12 @@ static set const g_combinedJsonArgs{ static void version() { - cout << "solc, the solidity compiler commandline interface " << dev::Version << endl - << " by Christian and Lefteris , (c) 2014." << endl - << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; + cout << + "solc, the solidity compiler commandline interface" << + endl << + "Version: " << + dev::solidity::VersionString << + endl; exit(0); } From eb139fd4d114cd7100a7d74637b507713fbffbbb Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 15 Jun 2015 15:21:23 +0200 Subject: [PATCH 100/105] contract documentation is now parsing during compilation and not by request. --- CommandLineInterface.cpp | 5 +++++ jsonCompiler.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 00bf2ab33..1b1dbd3eb 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -449,6 +449,11 @@ bool CommandLineInterface::processInput() << boost::diagnostic_information(_exception); return false; } + catch (DocstringParsingError const& _exception) + { + cerr << "Documentation parsing error: " << *boost::get_error_info(_exception) << endl; + return false; + } catch (Exception const& _exception) { cerr << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp index 340713b1d..bde13762a 100644 --- a/jsonCompiler.cpp +++ b/jsonCompiler.cpp @@ -147,6 +147,10 @@ string compile(string _input, bool _optimize) { return formatError(exception, "Internal compiler error", compiler); } + catch (DocstringParsingError const& exception) + { + return formatError(exception, "Documentation parsing error", compiler); + } catch (Exception const& exception) { output["error"] = "Exception during compilation: " + boost::diagnostic_information(exception); From c11d2a2c62a49140fd6dde49ee48ed157f7ca985 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Jul 2015 19:20:00 +0200 Subject: [PATCH 101/105] Fully automate the dockerfile again. --- docker_emscripten/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index 23a0caba9..380615478 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -66,6 +66,5 @@ RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/hom RUN emmake make -j 6 soljson WORKDIR /home/user/cpp-ethereum/solc -# somehow it does not work to pipe out both files -#ENTRYPOINT tar -c soljson.js soljson.js.mem | base64 +ENTRYPOINT cat soljson.js From 598e66f395182e758a6e30516a9192f3a13a1362 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 31 Jul 2015 19:23:31 +0200 Subject: [PATCH 102/105] Create and output clone contracts. --- CommandLineInterface.cpp | 44 ++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp index 1b1dbd3eb..e579d8839 100644 --- a/CommandLineInterface.cpp +++ b/CommandLineInterface.cpp @@ -63,6 +63,7 @@ static string const g_argAsmJsonStr = "asm-json"; static string const g_argAstStr = "ast"; static string const g_argAstJson = "ast-json"; static string const g_argBinaryStr = "binary"; +static string const g_argCloneBinaryStr = "clone-binary"; static string const g_argOpcodesStr = "opcodes"; static string const g_argNatspecDevStr = "natspec-dev"; static string const g_argNatspecUserStr = "natspec-user"; @@ -71,6 +72,7 @@ static string const g_argAddStandard = "add-std"; /// Possible arguments to for --combined-json static set const g_combinedJsonArgs{ "binary", + "clone-binary", "opcodes", "json-abi", "sol-abi", @@ -110,7 +112,8 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) humanTargetedStdout(_args, g_argAsmStr) || humanTargetedStdout(_args, g_argAsmJsonStr) || humanTargetedStdout(_args, g_argOpcodesStr) || - humanTargetedStdout(_args, g_argBinaryStr); + humanTargetedStdout(_args, g_argBinaryStr) || + humanTargetedStdout(_args, g_argCloneBinaryStr); } static inline bool outputToFile(OutputType type) @@ -140,18 +143,33 @@ static std::istream& operator>>(std::istream& _in, OutputType& io_output) void CommandLineInterface::handleBinary(string const& _contract) { - auto choice = m_args[g_argBinaryStr].as(); - if (outputToStdout(choice)) + if (m_args.count(g_argBinaryStr)) { - cout << "Binary: " << endl; - cout << toHex(m_compiler->getBytecode(_contract)) << endl; + if (outputToStdout(m_args[g_argBinaryStr].as())) + { + cout << "Binary: " << endl; + cout << toHex(m_compiler->getBytecode(_contract)) << endl; + } + if (outputToFile(m_args[g_argBinaryStr].as())) + { + ofstream outFile(_contract + ".binary"); + outFile << toHex(m_compiler->getBytecode(_contract)); + outFile.close(); + } } - - if (outputToFile(choice)) + if (m_args.count(g_argCloneBinaryStr)) { - ofstream outFile(_contract + ".binary"); - outFile << toHex(m_compiler->getBytecode(_contract)); - outFile.close(); + if (outputToStdout(m_args[g_argCloneBinaryStr].as())) + { + cout << "Clone Binary: " << endl; + cout << toHex(m_compiler->getCloneBytecode(_contract)) << endl; + } + if (outputToFile(m_args[g_argCloneBinaryStr].as())) + { + ofstream outFile(_contract + ".clone_binary"); + outFile << toHex(m_compiler->getCloneBytecode(_contract)); + outFile.close(); + } } } @@ -177,7 +195,7 @@ void CommandLineInterface::handleBytecode(string const& _contract) { if (m_args.count(g_argOpcodesStr)) handleOpcode(_contract); - if (m_args.count(g_argBinaryStr)) + if (m_args.count(g_argBinaryStr) || m_args.count(g_argCloneBinaryStr)) handleBinary(_contract); } @@ -329,6 +347,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv) "Request to output the Opcodes of the contract.") (g_argBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract in binary (hexadecimal).") + (g_argCloneBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), + "Request to output the clone contract in binary (hexadecimal).") (g_argAbiStr.c_str(), po::value()->value_name("stdout|file|both"), "Request to output the contract's JSON ABI interface.") (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), @@ -490,6 +510,8 @@ void CommandLineInterface::handleCombinedJSON() contractData["json-abi"] = m_compiler->getInterface(contractName); if (requests.count("binary")) contractData["binary"] = toHex(m_compiler->getBytecode(contractName)); + if (requests.count("clone-binary")) + contractData["clone-binary"] = toHex(m_compiler->getCloneBytecode(contractName)); if (requests.count("opcodes")) contractData["opcodes"] = eth::disassemble(m_compiler->getBytecode(contractName)); if (requests.count("asm")) From c9664bbfd756b797bb03d1383ea9344e4189cba4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 4 Aug 2015 20:03:04 +0200 Subject: [PATCH 103/105] Updated dockerfile to changed build process. --- docker_emscripten/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index 380615478..d6cfa9961 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -62,7 +62,7 @@ RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum # TODO this should be a proper merge but somehow causes problems # NOTE that we only get the latest commit of that branch RUN git cherry-pick solidityjs/solidity-js -RUN emcmake cmake -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc +RUN emcmake cmake -DMINER=Off -DETHKEY=Off -DSERPENT=Off -DTESTS=Off -DETHASHCL=Off -DJSCONSOLE=Off -DEVMJIT=Off -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc RUN emmake make -j 6 soljson WORKDIR /home/user/cpp-ethereum/solc From 2b9e8adeed8889b4acf85aa8151163952306516d Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 5 Aug 2015 17:14:41 +0200 Subject: [PATCH 104/105] Use 0/1 for cmake switches. --- docker_emscripten/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile index d6cfa9961..881f602d9 100644 --- a/docker_emscripten/Dockerfile +++ b/docker_emscripten/Dockerfile @@ -62,7 +62,7 @@ RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum # TODO this should be a proper merge but somehow causes problems # NOTE that we only get the latest commit of that branch RUN git cherry-pick solidityjs/solidity-js -RUN emcmake cmake -DMINER=Off -DETHKEY=Off -DSERPENT=Off -DTESTS=Off -DETHASHCL=Off -DJSCONSOLE=Off -DEVMJIT=Off -DETH_STATIC=1 -DSOLIDITY=ON -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc +RUN emcmake cmake -DMINER=0 -DETHKEY=0 -DSERPENT=0 -DTESTS=0 -DETHASHCL=0 -DJSCONSOLE=0 -DEVMJIT=0 -DETH_STATIC=1 -DSOLIDITY=1 -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc RUN emmake make -j 6 soljson WORKDIR /home/user/cpp-ethereum/solc From b106ecfa1ccbde8664f75ff6b94cee2ae0431a9e Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 19 Aug 2015 12:50:04 +0200 Subject: [PATCH 105/105] Moved files. --- CMakeLists.txt | 29 -- CommandLineInterface.cpp | 657 ----------------------------------- CommandLineInterface.h | 75 ---- docker_emscripten/Dockerfile | 70 ---- jsonCompiler.cpp | 196 ----------- main.cpp | 35 -- 6 files changed, 1062 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 CommandLineInterface.cpp delete mode 100644 CommandLineInterface.h delete mode 100644 docker_emscripten/Dockerfile delete mode 100644 jsonCompiler.cpp delete mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index df72f52dd..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_policy(SET CMP0015 NEW) -set(CMAKE_AUTOMOC OFF) - -aux_source_directory(. SRC_LIST) -list(REMOVE_ITEM SRC_LIST "./jsonCompiler.cpp") - -include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) -include_directories(BEFORE ..) -include_directories(${Boost_INCLUDE_DIRS}) - -set(EXECUTABLE solc) - -file(GLOB HEADERS "*.h") -add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) - -add_dependencies(${EXECUTABLE} BuildInfo.h) - -target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) -target_link_libraries(${EXECUTABLE} ${Boost_PROGRAM_OPTIONS_LIBRARIES}) -target_link_libraries(${EXECUTABLE} solidity) - -if (APPLE) - install(TARGETS ${EXECUTABLE} DESTINATION bin) -else() - eth_install_executable(${EXECUTABLE}) -endif() - -add_library(soljson jsonCompiler.cpp ${HEADERS}) -target_link_libraries(soljson solidity) diff --git a/CommandLineInterface.cpp b/CommandLineInterface.cpp deleted file mode 100644 index e579d8839..000000000 --- a/CommandLineInterface.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @author Gav Wood - * @date 2014 - * Solidity command line interface. - */ -#include "CommandLineInterface.h" - -#include -#include -#include - -#include -#include - -#include "BuildInfo.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -namespace po = boost::program_options; - -namespace dev -{ -namespace solidity -{ - -static string const g_argAbiStr = "json-abi"; -static string const g_argSolAbiStr = "sol-abi"; -static string const g_argSignatureHashes = "hashes"; -static string const g_argGas = "gas"; -static string const g_argAsmStr = "asm"; -static string const g_argAsmJsonStr = "asm-json"; -static string const g_argAstStr = "ast"; -static string const g_argAstJson = "ast-json"; -static string const g_argBinaryStr = "binary"; -static string const g_argCloneBinaryStr = "clone-binary"; -static string const g_argOpcodesStr = "opcodes"; -static string const g_argNatspecDevStr = "natspec-dev"; -static string const g_argNatspecUserStr = "natspec-user"; -static string const g_argAddStandard = "add-std"; - -/// Possible arguments to for --combined-json -static set const g_combinedJsonArgs{ - "binary", - "clone-binary", - "opcodes", - "json-abi", - "sol-abi", - "asm", - "ast", - "natspec-user", - "natspec-dev" -}; - -static void version() -{ - cout << - "solc, the solidity compiler commandline interface" << - endl << - "Version: " << - dev::solidity::VersionString << - endl; - exit(0); -} - -static inline bool humanTargetedStdout(po::variables_map const& _args, string const& _name) -{ - return _args.count(_name) && _args[_name].as() != OutputType::FILE; -} - -static bool needsHumanTargetedStdout(po::variables_map const& _args) -{ - - return - _args.count(g_argGas) || - humanTargetedStdout(_args, g_argAbiStr) || - humanTargetedStdout(_args, g_argSolAbiStr) || - humanTargetedStdout(_args, g_argSignatureHashes) || - humanTargetedStdout(_args, g_argNatspecUserStr) || - humanTargetedStdout(_args, g_argAstJson) || - humanTargetedStdout(_args, g_argNatspecDevStr) || - humanTargetedStdout(_args, g_argAsmStr) || - humanTargetedStdout(_args, g_argAsmJsonStr) || - humanTargetedStdout(_args, g_argOpcodesStr) || - humanTargetedStdout(_args, g_argBinaryStr) || - humanTargetedStdout(_args, g_argCloneBinaryStr); -} - -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) -{ - if (m_args.count(g_argBinaryStr)) - { - if (outputToStdout(m_args[g_argBinaryStr].as())) - { - cout << "Binary: " << endl; - cout << toHex(m_compiler->getBytecode(_contract)) << endl; - } - if (outputToFile(m_args[g_argBinaryStr].as())) - { - ofstream outFile(_contract + ".binary"); - outFile << toHex(m_compiler->getBytecode(_contract)); - outFile.close(); - } - } - if (m_args.count(g_argCloneBinaryStr)) - { - if (outputToStdout(m_args[g_argCloneBinaryStr].as())) - { - cout << "Clone Binary: " << endl; - cout << toHex(m_compiler->getCloneBytecode(_contract)) << endl; - } - if (outputToFile(m_args[g_argCloneBinaryStr].as())) - { - ofstream outFile(_contract + ".clone_binary"); - outFile << toHex(m_compiler->getCloneBytecode(_contract)); - outFile.close(); - } - } -} - -void CommandLineInterface::handleOpcode(string const& _contract) -{ - auto choice = m_args[g_argOpcodesStr].as(); - if (outputToStdout(choice)) - { - cout << "Opcodes: " << endl; - cout << eth::disassemble(m_compiler->getBytecode(_contract)); - cout << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + ".opcode"); - outFile << eth::disassemble(m_compiler->getBytecode(_contract)); - outFile.close(); - } -} - -void CommandLineInterface::handleBytecode(string const& _contract) -{ - if (m_args.count(g_argOpcodesStr)) - handleOpcode(_contract); - if (m_args.count(g_argBinaryStr) || m_args.count(g_argCloneBinaryStr)) - handleBinary(_contract); -} - -void CommandLineInterface::handleSignatureHashes(string const& _contract) -{ - if (!m_args.count(g_argSignatureHashes)) - return; - - string out; - for (auto const& it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions()) - out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n"; - - auto choice = m_args[g_argSignatureHashes].as(); - if (outputToStdout(choice)) - cout << "Function signatures: " << endl << out; - - if (outputToFile(choice)) - { - ofstream outFile(_contract + ".signatures"); - outFile << out; - outFile.close(); - } -} - -void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) -{ - std::string argName; - std::string suffix; - std::string title; - switch(_type) - { - case DocumentationType::ABIInterface: - argName = g_argAbiStr; - suffix = ".abi"; - title = "Contract JSON ABI"; - break; - case DocumentationType::ABISolidityInterface: - argName = g_argSolAbiStr; - suffix = ".sol"; - title = "Contract Solidity ABI"; - break; - case DocumentationType::NatspecUser: - argName = g_argNatspecUserStr; - suffix = ".docuser"; - title = "User Documentation"; - break; - case DocumentationType::NatspecDev: - argName = g_argNatspecDevStr; - 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(); - if (outputToStdout(choice)) - { - cout << title << endl; - cout << m_compiler->getMetadata(_contract, _type) << endl; - } - - if (outputToFile(choice)) - { - ofstream outFile(_contract + suffix); - outFile << m_compiler->getMetadata(_contract, _type); - outFile.close(); - } - } -} - -void CommandLineInterface::handleGasEstimation(string const& _contract) -{ - using Gas = GasEstimator::GasConsumption; - if (!m_compiler->getAssemblyItems(_contract) && !m_compiler->getRuntimeAssemblyItems(_contract)) - return; - cout << "Gas estimation:" << endl; - if (eth::AssemblyItems const* items = m_compiler->getAssemblyItems(_contract)) - { - Gas gas = GasEstimator::functionalEstimation(*items); - u256 bytecodeSize(m_compiler->getRuntimeBytecode(_contract).size()); - cout << "construction:" << endl; - cout << " " << gas << " + " << (bytecodeSize * eth::c_createDataGas) << " = "; - gas += bytecodeSize * eth::c_createDataGas; - cout << gas << endl; - } - if (eth::AssemblyItems const* items = m_compiler->getRuntimeAssemblyItems(_contract)) - { - ContractDefinition const& contract = m_compiler->getContractDefinition(_contract); - cout << "external:" << endl; - for (auto it: contract.getInterfaceFunctions()) - { - string sig = it.second->externalSignature(); - GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, sig); - cout << " " << sig << ":\t" << gas << endl; - } - if (contract.getFallbackFunction()) - { - GasEstimator::GasConsumption gas = GasEstimator::functionalEstimation(*items, "INVALID"); - cout << " fallback:\t" << gas << endl; - } - cout << "internal:" << endl; - for (auto const& it: contract.getDefinedFunctions()) - { - if (it->isPartOfExternalInterface() || it->isConstructor()) - continue; - size_t entry = m_compiler->getFunctionEntryPoint(_contract, *it); - GasEstimator::GasConsumption gas = GasEstimator::GasConsumption::infinite(); - if (entry > 0) - gas = GasEstimator::functionalEstimation(*items, entry, *it); - FunctionType type(*it); - cout << " " << it->getName() << "("; - auto end = type.getParameterTypes().end(); - for (auto it = type.getParameterTypes().begin(); it != end; ++it) - cout << (*it)->toString() << (it + 1 == end ? "" : ","); - cout << "):\t" << gas << endl; - } - } -} - -bool CommandLineInterface::parseArguments(int argc, char** argv) -{ - // 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()->default_value(false), "Optimize bytecode") - ("optimize-runs", po::value()->default_value(200), "Estimated number of contract runs for optimizer.") - ("add-std", po::value()->default_value(false), "Add standard contracts") - ("input-file", po::value>(), "input file") - ( - "combined-json", - po::value()->value_name(boost::join(g_combinedJsonArgs, ",")), - "Output a single json document containing the specified information, can be combined." - ) - (g_argAstStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the AST of the contract.") - (g_argAstJson.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the AST of the contract in JSON format.") - (g_argAsmStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the EVM assembly of the contract.") - (g_argAsmJsonStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the EVM assembly of the contract in JSON format.") - (g_argOpcodesStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the Opcodes of the contract.") - (g_argBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract in binary (hexadecimal).") - (g_argCloneBinaryStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the clone contract in binary (hexadecimal).") - (g_argAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's JSON ABI interface.") - (g_argSolAbiStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Solidity ABI interface.") - (g_argSignatureHashes.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's functions' signature hashes.") - (g_argGas.c_str(), - "Request to output an estimate for each function's maximal gas usage.") - (g_argNatspecUserStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec user documentation.") - (g_argNatspecDevStr.c_str(), po::value()->value_name("stdout|file|both"), - "Request to output the contract's Natspec developer documentation."); - - // 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) - { - cerr << _exception.what() << endl; - return false; - } - if (m_args.count("combined-json")) - { - vector requests; - for (string const& item: boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(","))) - if (!g_combinedJsonArgs.count(item)) - { - cerr << "Invalid option to --combined-json: " << item << 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[""].append(s + '\n'); - } - } - else - for (string const& infile: m_args["input-file"].as>()) - { - auto path = boost::filesystem::path(infile); - if (!boost::filesystem::exists(path)) - { - cerr << "Skipping non existant input file \"" << infile << "\"" << endl; - continue; - } - - if (!boost::filesystem::is_regular_file(path)) - { - cerr << "\"" << infile << "\" is not a valid file. Skipping" << endl; - continue; - } - - m_sourceCodes[infile] = dev::contentsString(infile); - } - - m_compiler.reset(new CompilerStack(m_args["add-std"].as())); - try - { - for (auto const& sourceCode: m_sourceCodes) - m_compiler->addSource(sourceCode.first, sourceCode.second); - // TODO: Perhaps we should not compile unless requested - bool optimize = m_args["optimize"].as(); - unsigned runs = m_args["optimize-runs"].as(); - m_compiler->compile(optimize, runs); - } - 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) - { - cerr << "Internal compiler error during compilation:" << endl - << boost::diagnostic_information(_exception); - return false; - } - catch (DocstringParsingError const& _exception) - { - cerr << "Documentation parsing error: " << *boost::get_error_info(_exception) << endl; - 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::handleCombinedJSON() -{ - if (!m_args.count("combined-json")) - return; - - Json::Value output(Json::objectValue); - - set requests; - boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(",")); - vector 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("clone-binary")) - contractData["clone-binary"] = toHex(m_compiler->getCloneBytecode(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) -{ - string title; - - if (_argStr == g_argAstStr) - title = "Syntax trees:"; - else if (_argStr == g_argAstJson) - title = "JSON AST:"; - else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal argStr for AST")); - - // do we need AST output? - if (m_args.count(_argStr)) - { - vector asts; - for (auto const& sourceCode: m_sourceCodes) - asts.push_back(&m_compiler->getAST(sourceCode.first)); - map gasCosts; - if (m_compiler->getRuntimeAssemblyItems()) - gasCosts = GasEstimator::breakToStatementLevel( - GasEstimator::structuralEstimation(*m_compiler->getRuntimeAssemblyItems(), asts), - asts - ); - - auto choice = m_args[_argStr].as(); - if (outputToStdout(choice)) - { - cout << title << endl << endl; - for (auto const& sourceCode: m_sourceCodes) - { - cout << endl << "======= " << sourceCode.first << " =======" << endl; - if (_argStr == g_argAstStr) - { - ASTPrinter printer( - m_compiler->getAST(sourceCode.first), - sourceCode.second, - gasCosts - ); - printer.print(cout); - } - else - { - ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); - converter.print(cout); - } - } - } - - if (outputToFile(choice)) - { - for (auto const& sourceCode: m_sourceCodes) - { - boost::filesystem::path p(sourceCode.first); - ofstream outFile(p.stem().string() + ".ast"); - if (_argStr == g_argAstStr) - { - ASTPrinter printer(m_compiler->getAST(sourceCode.first), sourceCode.second); - printer.print(outFile); - } - else - { - ASTJsonConverter converter(m_compiler->getAST(sourceCode.first)); - converter.print(outFile); - } - outFile.close(); - } - } - } -} - -void CommandLineInterface::actOnInput() -{ - handleCombinedJSON(); - - // do we need AST output? - handleAst(g_argAstStr); - handleAst(g_argAstJson); - - vector contracts = m_compiler->getContractNames(); - for (string const& contract: contracts) - { - if (needsHumanTargetedStdout(m_args)) - cout << endl << "======= " << contract << " =======" << endl; - - // do we need EVM assembly? - if (m_args.count(g_argAsmStr) || m_args.count(g_argAsmJsonStr)) - { - auto choice = m_args.count(g_argAsmStr) ? m_args[g_argAsmStr].as() : m_args[g_argAsmJsonStr].as(); - if (outputToStdout(choice)) - { - cout << "EVM assembly:" << endl; - m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); - } - - if (outputToFile(choice)) - { - ofstream outFile(contract + (m_args.count(g_argAsmJsonStr) ? "_evm.json" : ".evm")); - m_compiler->streamAssembly(outFile, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); - outFile.close(); - } - } - - if (m_args.count(g_argGas)) - handleGasEstimation(contract); - - handleBytecode(contract); - handleSignatureHashes(contract); - handleMeta(DocumentationType::ABIInterface, contract); - handleMeta(DocumentationType::ABISolidityInterface, contract); - handleMeta(DocumentationType::NatspecDev, contract); - handleMeta(DocumentationType::NatspecUser, contract); - } // end of contracts iteration -} - -} -} diff --git a/CommandLineInterface.h b/CommandLineInterface.h deleted file mode 100644 index 46b9b1e22..000000000 --- a/CommandLineInterface.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris - * @date 2014 - * Solidity command line interface. - */ -#pragma once - -#include -#include -#include - -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 handleCombinedJSON(); - void handleAst(std::string const& _argStr); - void handleBinary(std::string const& _contract); - void handleOpcode(std::string const& _contract); - void handleBytecode(std::string const& _contract); - void handleSignatureHashes(std::string const& _contract); - void handleMeta(DocumentationType _type, - std::string const& _contract); - void handleGasEstimation(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 m_sourceCodes; - /// Solidity compiler stack - std::unique_ptr m_compiler; -}; - -} -} diff --git a/docker_emscripten/Dockerfile b/docker_emscripten/Dockerfile deleted file mode 100644 index 881f602d9..000000000 --- a/docker_emscripten/Dockerfile +++ /dev/null @@ -1,70 +0,0 @@ -FROM ubuntu:14.04 - -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update -RUN apt-get upgrade -y - -# Ethereum dependencies -RUN apt-get install -qy build-essential git cmake libcurl4-openssl-dev wget -RUN apt-get install -qy automake libtool yasm scons - -RUN useradd -ms /bin/bash user -USER user -ENV HOME /home/user -WORKDIR /home/user - -# Emscripten SDK -RUN wget -c https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz -RUN tar xzf emsdk-portable.tar.gz -WORKDIR /home/user/emsdk_portable -RUN ./emsdk update && ./emsdk install latest && ./emsdk activate latest -ENV PATH $PATH:/home/user/emsdk_portable:/home/user/emsdk_portable/clang/fastcomp/build_master_64/bin:/home/user/emsdk_portable/emscripten/master - -USER root -RUN apt-get install -qy nodejs -USER user -RUN sed -i "s/NODE_JS = 'node'/NODE_JS = 'nodejs'/g" ~/.emscripten - -# CryptoPP -WORKDIR /home/user -RUN git clone https://github.com/mmoss/cryptopp.git -WORKDIR /home/user/cryptopp -RUN emcmake cmake -DCRYPTOPP_LIBRARY_TYPE=STATIC -DCRYPTOPP_RUNTIME_TYPE=STATIC && emmake make -j 4 -RUN ln -s . src/cryptopp - -# Boost -WORKDIR /home/user -RUN wget 'http://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.57.0%2F&ts=1421887207&use_mirror=cznic' -O boost_1_57_0.tar.bz2 -RUN tar xjf boost_1_57_0.tar.bz2 -WORKDIR /home/user/boost_1_57_0 -RUN ./bootstrap.sh --with-libraries=thread,system,regex -RUN sed -i 's/using gcc ;/using gcc : : \/home\/user\/emsdk_portable\/emscripten\/master\/em++ ;/g' ./project-config.jam -RUN sed -i 's/$(archiver\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emar/g' ./tools/build/src/tools/gcc.jam -RUN sed -i 's/$(ranlib\[1\])/\/home\/user\/emsdk_portable\/emscripten\/master\/emranlib/g' ./tools/build/src/tools/gcc.jam -RUN ./b2 link=static variant=release threading=single runtime-link=static thread system regex - -# Json-CPP -WORKDIR /home/user -RUN git clone https://github.com/open-source-parsers/jsoncpp.git -WORKDIR /home/user/jsoncpp -RUN emcmake cmake -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -G "Unix Makefiles" . -RUN emmake make - -## Build soljs -WORKDIR /home/user -ADD https://api.github.com/repos/ethereum/cpp-ethereum/git/refs/heads/develop unused.txt -RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum -WORKDIR /home/user/cpp-ethereum -RUN git config --global user.email "me@example.com" -RUN git config --global user.name "Jane Doe" -ADD https://api.github.com/repos/chriseth/cpp-ethereum/git/refs/heads/solidity-js unused2.txt -RUN git remote add -f solidityjs https://github.com/chriseth/cpp-ethereum -# TODO this should be a proper merge but somehow causes problems -# NOTE that we only get the latest commit of that branch -RUN git cherry-pick solidityjs/solidity-js -RUN emcmake cmake -DMINER=0 -DETHKEY=0 -DSERPENT=0 -DTESTS=0 -DETHASHCL=0 -DJSCONSOLE=0 -DEVMJIT=0 -DETH_STATIC=1 -DSOLIDITY=1 -DGUI=0 -DCMAKE_CXX_COMPILER=/home/user/emsdk_portable/emscripten/master/em++ -DCMAKE_C_COMPILER=/home/user/emsdk_portable/emscripten/master/emcc -RUN emmake make -j 6 soljson - -WORKDIR /home/user/cpp-ethereum/solc -ENTRYPOINT cat soljson.js - diff --git a/jsonCompiler.cpp b/jsonCompiler.cpp deleted file mode 100644 index bde13762a..000000000 --- a/jsonCompiler.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2014 - * JSON interface for the solidity compiler to be used from Javascript. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace dev; -using namespace solidity; - -string formatError(Exception const& _exception, string const& _name, CompilerStack const& _compiler) -{ - ostringstream errorOutput; - SourceReferenceFormatter::printExceptionInformation(errorOutput, _exception, _name, _compiler); - - Json::Value output(Json::objectValue); - output["error"] = errorOutput.str(); - return Json::FastWriter().write(output); -} - -Json::Value functionHashes(ContractDefinition const& _contract) -{ - Json::Value functionHashes(Json::objectValue); - for (auto const& it: _contract.getInterfaceFunctions()) - functionHashes[it.second->externalSignature()] = toHex(it.first.ref()); - return functionHashes; -} - -Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) -{ - if (_gas.isInfinite || _gas.value > std::numeric_limits::max()) - return Json::Value(Json::nullValue); - else - return Json::Value(Json::LargestUInt(_gas.value)); -} - -Json::Value estimateGas(CompilerStack const& _compiler, string const& _contract) -{ - Json::Value gasEstimates(Json::objectValue); - using Gas = GasEstimator::GasConsumption; - if (!_compiler.getAssemblyItems(_contract) && !_compiler.getRuntimeAssemblyItems(_contract)) - return gasEstimates; - if (eth::AssemblyItems const* items = _compiler.getAssemblyItems(_contract)) - { - Gas gas = GasEstimator::functionalEstimation(*items); - u256 bytecodeSize(_compiler.getRuntimeBytecode(_contract).size()); - Json::Value creationGas(Json::arrayValue); - creationGas[0] = gasToJson(gas); - creationGas[1] = gasToJson(bytecodeSize * eth::c_createDataGas); - gasEstimates["creation"] = creationGas; - } - if (eth::AssemblyItems const* items = _compiler.getRuntimeAssemblyItems(_contract)) - { - ContractDefinition const& contract = _compiler.getContractDefinition(_contract); - Json::Value externalFunctions(Json::objectValue); - for (auto it: contract.getInterfaceFunctions()) - { - string sig = it.second->externalSignature(); - externalFunctions[sig] = gasToJson(GasEstimator::functionalEstimation(*items, sig)); - } - if (contract.getFallbackFunction()) - externalFunctions[""] = gasToJson(GasEstimator::functionalEstimation(*items, "INVALID")); - gasEstimates["external"] = externalFunctions; - Json::Value internalFunctions(Json::objectValue); - for (auto const& it: contract.getDefinedFunctions()) - { - if (it->isPartOfExternalInterface() || it->isConstructor()) - continue; - size_t entry = _compiler.getFunctionEntryPoint(_contract, *it); - GasEstimator::GasConsumption gas = GasEstimator::GasConsumption::infinite(); - if (entry > 0) - gas = GasEstimator::functionalEstimation(*items, entry, *it); - FunctionType type(*it); - string sig = it->getName() + "("; - auto end = type.getParameterTypes().end(); - for (auto it = type.getParameterTypes().begin(); it != end; ++it) - sig += (*it)->toString() + (it + 1 == end ? "" : ","); - sig += ")"; - internalFunctions[sig] = gasToJson(gas); - } - gasEstimates["internal"] = internalFunctions; - } - return gasEstimates; -} - -string compile(string _input, bool _optimize) -{ - StringMap sources; - sources[""] = _input; - - Json::Value output(Json::objectValue); - CompilerStack compiler; - try - { - compiler.compile(_input, _optimize); - } - catch (ParserError const& exception) - { - return formatError(exception, "Parser error", compiler); - } - catch (DeclarationError const& exception) - { - return formatError(exception, "Declaration error", compiler); - } - catch (TypeError const& exception) - { - return formatError(exception, "Type error", compiler); - } - catch (CompilerError const& exception) - { - return formatError(exception, "Compiler error", compiler); - } - catch (InternalCompilerError const& exception) - { - return formatError(exception, "Internal compiler error", compiler); - } - catch (DocstringParsingError const& exception) - { - return formatError(exception, "Documentation parsing error", compiler); - } - catch (Exception const& exception) - { - output["error"] = "Exception during compilation: " + boost::diagnostic_information(exception); - return Json::FastWriter().write(output); - } - catch (...) - { - output["error"] = "Unknown exception during compilation."; - return Json::FastWriter().write(output); - } - - output["contracts"] = Json::Value(Json::objectValue); - for (string const& contractName: compiler.getContractNames()) - { - Json::Value contractData(Json::objectValue); - contractData["solidity_interface"] = compiler.getSolidityInterface(contractName); - contractData["interface"] = compiler.getInterface(contractName); - contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); - contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); - contractData["functionHashes"] = functionHashes(compiler.getContractDefinition(contractName)); - contractData["gasEstimates"] = estimateGas(compiler, contractName); - ostringstream unused; - contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources, true); - output["contracts"][contractName] = contractData; - } - - output["sources"] = Json::Value(Json::objectValue); - output["sources"][""] = Json::Value(Json::objectValue); - output["sources"][""]["AST"] = ASTJsonConverter(compiler.getAST("")).json(); - - return Json::FastWriter().write(output); -} - -static string outputBuffer; - -extern "C" -{ -extern char const* compileJSON(char const* _input, bool _optimize) -{ - outputBuffer = compile(_input, _optimize); - return outputBuffer.c_str(); -} -} diff --git a/main.cpp b/main.cpp deleted file mode 100644 index c5f72980d..000000000 --- a/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2014 - * Solidity commandline compiler. - */ - -#include "CommandLineInterface.h" - -int main(int argc, char** argv) -{ - dev::solidity::CommandLineInterface cli; - if (!cli.parseArguments(argc, argv)) - return 1; - if (!cli.processInput()) - return 1; - cli.actOnInput(); - - return 0; -}