@ -27,6 +27,7 @@
# include <fstream>
# include <boost/filesystem.hpp>
# include <boost/algorithm/string.hpp>
# include "BuildInfo.h"
# include <libdevcore/Common.h>
@ -64,6 +65,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 < string > 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 +85,24 @@ static void version()
exit ( 0 ) ;
}
static inline bool argTo Stdout( po : : variables_map const & _args , string const & _name )
static inline bool humanTargeted Stdout( po : : variables_map const & _args , string const & _name )
{
return _args . count ( _name ) & & _args [ _name ] . as < OutputType > ( ) ! = OutputType : : FILE ;
}
static bool needStdout ( po : : variables_map const & _args )
static bool needsHumanTargeted Stdout ( po : : variables_map const & _args )
{
return
argTo Stdout( _args , g_argAbiStr ) | |
argTo Stdout( _args , g_argSolAbiStr ) | |
argTo Stdout( _args , g_argNatspecUserStr ) | |
argTo Stdout( _args , g_argAstJson ) | |
argTo Stdout( _args , g_argNatspecDevStr ) | |
argTo Stdout( _args , g_argAsmStr ) | |
argTo Stdout( _args , g_argAsmJsonStr ) | |
argTo Stdout( _args , g_argOpcodesStr ) | |
argTo Stdout( _args , g_argBinaryStr ) ;
humanTargeted Stdout( _args , g_argAbiStr ) | |
humanTargeted Stdout( _args , g_argSolAbiStr ) | |
humanTargeted Stdout( _args , g_argNatspecUserStr ) | |
humanTargeted Stdout( _args , g_argAstJson ) | |
humanTargeted Stdout( _args , g_argNatspecDevStr ) | |
humanTargeted Stdout( _args , g_argAsmStr ) | |
humanTargeted Stdout( _args , g_argAsmJsonStr ) | |
humanTargeted Stdout( _args , g_argOpcodesStr ) | |
humanTargeted Stdout( _args , g_argBinaryStr ) ;
}
static inline bool outputToFile ( OutputType type )
@ -220,6 +233,11 @@ bool CommandLineInterface::parseArguments(int argc, char** argv)
( " optimize " , po : : value < bool > ( ) - > default_value ( false ) , " Optimize bytecode for size " )
( " add-std " , po : : value < bool > ( ) - > default_value ( false ) , " Add standard contracts " )
( " input-file " , po : : value < vector < string > > ( ) , " input file " )
(
" combined-json " ,
po : : value < string > ( ) - > value_name ( boost : : join ( g_combinedJsonArgs , " , " ) ) ,
" Output a single json document containing the specified information, can be combined. "
)
( g_argAstStr . c_str ( ) , po : : value < OutputType > ( ) - > value_name ( " stdout|file|both " ) ,
" Request to output the AST of the contract. " )
( g_argAstJson . c_str ( ) , po : : value < OutputType > ( ) - > value_name ( " stdout|file|both " ) ,
@ -252,9 +270,19 @@ 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 " ) )
{
vector < string > requests ;
for ( string const & item : boost : : split ( requests , m_args [ " combined-json " ] . as < string > ( ) , boost : : is_any_of ( " , " ) ) )
if ( ! g_combinedJsonArgs . count ( item ) )
{
cerr < < " Invalid option to --combined-json: " < < item < < endl ;
return false ;
}
}
po : : notify ( m_args ) ;
if ( m_args . count ( " help " ) )
@ -289,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 ;
}
@ -350,6 +378,52 @@ bool CommandLineInterface::processInput()
return true ;
}
void CommandLineInterface : : handleCombinedJSON ( )
{
Json : : Value output ( Json : : objectValue ) ;
set < string > requests ;
boost : : split ( requests , m_args [ " combined-json " ] . as < string > ( ) , boost : : is_any_of ( " , " ) ) ;
vector < string > contracts = m_compiler - > getContractNames ( ) ;
if ( ! contracts . empty ( ) )
output [ " contracts " ] = Json : : Value ( Json : : objectValue ) ;
for ( string const & contractName : contracts )
{
Json : : Value contractData ( Json : : objectValue ) ;
if ( requests . count ( " sol-abi " ) )
contractData [ " sol-abi " ] = m_compiler - > getSolidityInterface ( contractName ) ;
if ( requests . count ( " json-abi " ) )
contractData [ " json-abi " ] = m_compiler - > getInterface ( contractName ) ;
if ( requests . count ( " binary " ) )
contractData [ " binary " ] = toHex ( m_compiler - > getBytecode ( contractName ) ) ;
if ( requests . count ( " opcodes " ) )
contractData [ " opcodes " ] = eth : : disassemble ( m_compiler - > getBytecode ( contractName ) ) ;
if ( requests . count ( " asm " ) )
{
ostringstream unused ;
contractData [ " asm " ] = m_compiler - > streamAssembly ( unused , contractName , m_sourceCodes , true ) ;
}
if ( requests . count ( " natspec-dev " ) )
contractData [ " natspec-dev " ] = m_compiler - > getMetadata ( contractName , DocumentationType : : NatspecDev ) ;
if ( requests . count ( " natspec-user " ) )
contractData [ " natspec-user " ] = m_compiler - > getMetadata ( contractName , DocumentationType : : NatspecUser ) ;
output [ " contracts " ] [ contractName ] = contractData ;
}
if ( requests . count ( " ast " ) )
{
output [ " sources " ] = Json : : Value ( Json : : objectValue ) ;
for ( auto const & sourceCode : m_sourceCodes )
{
ASTJsonConverter converter ( m_compiler - > getAST ( sourceCode . first ) ) ;
output [ " sources " ] [ sourceCode . first ] = Json : : Value ( Json : : objectValue ) ;
output [ " sources " ] [ sourceCode . first ] [ " AST " ] = converter . json ( ) ;
}
}
cout < < Json : : FastWriter ( ) . write ( output ) < < endl ;
}
void CommandLineInterface : : handleAst ( string const & _argStr )
{
string title ;
@ -408,6 +482,8 @@ void CommandLineInterface::handleAst(string const& _argStr)
void CommandLineInterface : : actOnInput ( )
{
handleCombinedJSON ( ) ;
// do we need AST output?
handleAst ( g_argAstStr ) ;
handleAst ( g_argAstJson ) ;
@ -415,7 +491,7 @@ void CommandLineInterface::actOnInput()
vector < string > contracts = m_compiler - > getContractNames ( ) ;
for ( string const & contract : contracts )
{
if ( needStdout ( m_args ) )
if ( needsHumanTargeted Stdout ( m_args ) )
cout < < endl < < " ======= " < < contract < < " ======= " < < endl ;
// do we need EVM assembly?