Skip to content

Commit 46514ff

Browse files
authored
Merge pull request #11520 from ethereum/local-streams-in-command-line-parser
Local output streams in CommandLineParser
2 parents b281c01 + baced5d commit 46514ff

File tree

6 files changed

+108
-65
lines changed

6 files changed

+108
-65
lines changed

solc/CommandLineInterface.cpp

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
#include <unistd.h>
7171
#endif
7272

73-
#include <iostream>
7473
#include <fstream>
7574

7675
#if !defined(STDERR_FILENO)
@@ -86,27 +85,21 @@ using namespace solidity::langutil;
8685
namespace solidity::frontend
8786
{
8887

89-
namespace
88+
ostream& CommandLineInterface::sout(bool _markAsUsed)
9089
{
91-
92-
static bool g_hasOutput = false;
93-
94-
std::ostream& sout(bool _used = true)
95-
{
96-
if (_used)
97-
g_hasOutput = true;
98-
return cout;
90+
if (_markAsUsed)
91+
m_hasOutput = true;
92+
return m_sout;
9993
}
10094

101-
std::ostream& serr(bool _used = true)
95+
ostream& CommandLineInterface::serr(bool _markAsUsed)
10296
{
103-
if (_used)
104-
g_hasOutput = true;
105-
return cerr;
106-
}
107-
97+
if (_markAsUsed)
98+
m_hasOutput = true;
99+
return m_serr;
108100
}
109101

102+
#define cin
110103
#define cout
111104
#define cerr
112105

@@ -423,7 +416,7 @@ bool CommandLineInterface::readInputFilesAndConfigureFileReader()
423416
}
424417

425418
if (m_options.input.addStdin)
426-
m_fileReader.setSource(g_stdinFileName, readUntilEnd(cin));
419+
m_fileReader.setSource(g_stdinFileName, readUntilEnd(m_sin));
427420

428421
if (m_fileReader.sourceCodes().size() == 0)
429422
{
@@ -497,11 +490,11 @@ void CommandLineInterface::createJson(string const& _fileName, string const& _js
497490

498491
bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv)
499492
{
500-
CommandLineParser parser;
493+
CommandLineParser parser(sout(/* _markAsUsed */ false), serr(/* _markAsUsed */ false));
501494
bool success = parser.parse(_argc, _argv, isatty(fileno(stdin)));
502495
if (!success)
503496
return false;
504-
g_hasOutput = g_hasOutput || CommandLineParser::hasOutput();
497+
m_hasOutput = m_hasOutput || parser.hasOutput();
505498
m_options = parser.options();
506499

507500
return true;
@@ -521,7 +514,7 @@ bool CommandLineInterface::processInput()
521514
{
522515
string input;
523516
if (m_options.input.standardJsonFile.empty())
524-
input = readUntilEnd(cin);
517+
input = readUntilEnd(m_sin);
525518
else
526519
{
527520
try
@@ -626,7 +619,7 @@ bool CommandLineInterface::compile()
626619

627620
for (auto const& error: m_compiler->errors())
628621
{
629-
g_hasOutput = true;
622+
m_hasOutput = true;
630623
formatter.printErrorInformation(*error);
631624
}
632625

@@ -635,7 +628,7 @@ bool CommandLineInterface::compile()
635628
}
636629
catch (CompilerError const& _exception)
637630
{
638-
g_hasOutput = true;
631+
m_hasOutput = true;
639632
formatter.printExceptionInformation(_exception, "Compiler error");
640633
return false;
641634
}
@@ -669,7 +662,7 @@ bool CommandLineInterface::compile()
669662
serr() << "Documentation parsing error: " << *boost::get_error_info<errinfo_comment>(_error) << endl;
670663
else
671664
{
672-
g_hasOutput = true;
665+
m_hasOutput = true;
673666
formatter.printExceptionInformation(_error, _error.typeName());
674667
}
675668

@@ -985,7 +978,7 @@ bool CommandLineInterface::assemble(
985978

986979
for (auto const& error: stack.errors())
987980
{
988-
g_hasOutput = true;
981+
m_hasOutput = true;
989982
formatter.printErrorInformation(*error);
990983
}
991984
if (!Error::containsOnlyWarnings(stack.errors()))
@@ -1134,7 +1127,7 @@ void CommandLineInterface::outputCompilationResults()
11341127
handleNatspec(false, contract);
11351128
} // end of contracts iteration
11361129

1137-
if (!g_hasOutput)
1130+
if (!m_hasOutput)
11381131
{
11391132
if (!m_options.output.dir.empty())
11401133
sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_options.output.dir << "." << endl;

solc/CommandLineInterface.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <libsolidity/interface/FileReader.h>
3030
#include <libyul/AssemblyStack.h>
3131

32+
#include <iostream>
3233
#include <memory>
3334
#include <string>
3435

@@ -38,7 +39,15 @@ namespace solidity::frontend
3839
class CommandLineInterface
3940
{
4041
public:
41-
explicit CommandLineInterface(CommandLineOptions const& _options = CommandLineOptions{}):
42+
explicit CommandLineInterface(
43+
std::istream& _sin,
44+
std::ostream& _sout,
45+
std::ostream& _serr,
46+
CommandLineOptions const& _options = CommandLineOptions{}
47+
):
48+
m_sin(_sin),
49+
m_sout(_sout),
50+
m_serr(_serr),
4251
m_options(_options)
4352
{}
4453

@@ -106,6 +115,18 @@ class CommandLineInterface
106115
/// @arg _json json string to be written
107116
void createJson(std::string const& _fileName, std::string const& _json);
108117

118+
/// Returns the stream that should receive normal output. Sets m_hasOutput to true if the
119+
/// stream has ever been used unless @arg _markAsUsed is set to false.
120+
std::ostream& sout(bool _markAsUsed = true);
121+
122+
/// Returns the stream that should receive error output. Sets m_hasOutput to true if the
123+
/// stream has ever been used unless @arg _markAsUsed is set to false.
124+
std::ostream& serr(bool _markAsUsed = true);
125+
126+
std::istream& m_sin;
127+
std::ostream& m_sout;
128+
std::ostream& m_serr;
129+
bool m_hasOutput = false;
109130
bool m_error = false; ///< If true, some error occurred.
110131
FileReader m_fileReader;
111132
std::unique_ptr<frontend::CompilerStack> m_compiler;

solc/CommandLineParser.cpp

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,16 @@ namespace po = boost::program_options;
3434
namespace solidity::frontend
3535
{
3636

37-
static bool g_hasOutput = false;
38-
39-
namespace
40-
{
41-
42-
std::ostream& sout()
37+
ostream& CommandLineParser::sout()
4338
{
44-
g_hasOutput = true;
45-
return cout;
39+
m_hasOutput = true;
40+
return m_sout;
4641
}
4742

48-
std::ostream& serr(bool _used = true)
43+
ostream& CommandLineParser::serr()
4944
{
50-
if (_used)
51-
g_hasOutput = true;
52-
return cerr;
53-
}
54-
45+
m_hasOutput = true;
46+
return m_serr;
5547
}
5648

5749
#define cout
@@ -185,8 +177,7 @@ static set<string> const g_metadataHashArgs
185177
g_strNone
186178
};
187179

188-
[[noreturn]]
189-
static void printVersionAndExit()
180+
void CommandLineParser::printVersionAndExit()
190181
{
191182
sout() <<
192183
"solc, the solidity compiler commandline interface" <<
@@ -197,19 +188,16 @@ static void printVersionAndExit()
197188
exit(EXIT_SUCCESS);
198189
}
199190

200-
[[noreturn]]
201-
static void printLicenseAndExit()
191+
void CommandLineParser::printLicenseAndExit()
202192
{
203193
sout() << otherLicenses << endl;
204194
// This is a static variable generated by cmake from LICENSE.txt
205195
sout() << licenseText << endl;
206196
exit(EXIT_SUCCESS);
207197
}
208198

209-
namespace
210-
{
211199

212-
bool checkMutuallyExclusive(boost::program_options::variables_map const& args, std::string const& _optionA, std::string const& _optionB)
200+
bool CommandLineParser::checkMutuallyExclusive(boost::program_options::variables_map const& args, string const& _optionA, string const& _optionB)
213201
{
214202
if (args.count(_optionA) && args.count(_optionB))
215203
{
@@ -220,8 +208,6 @@ bool checkMutuallyExclusive(boost::program_options::variables_map const& args, s
220208
return true;
221209
}
222210

223-
}
224-
225211
bool CompilerOutputs::operator==(CompilerOutputs const& _other) const noexcept
226212
{
227213
static_assert(
@@ -441,7 +427,7 @@ bool CommandLineParser::parseLibraryOption(string const& _input)
441427

442428
bool CommandLineParser::parse(int _argc, char const* const* _argv, bool interactiveTerminal)
443429
{
444-
g_hasOutput = false;
430+
m_hasOutput = false;
445431

446432
// Declare the supported options.
447433
po::options_description desc((R"(solc, the Solidity commandline compiler.
@@ -1136,11 +1122,6 @@ General Information)").c_str(),
11361122
return true;
11371123
}
11381124

1139-
bool CommandLineParser::hasOutput()
1140-
{
1141-
return g_hasOutput;
1142-
}
1143-
11441125
bool CommandLineParser::parseCombinedJsonOption()
11451126
{
11461127
if (!m_args.count(g_strCombinedJson))
@@ -1192,4 +1173,5 @@ string CommandLineParser::joinOptionNames(vector<string> const& _optionNames, st
11921173
_separator
11931174
);
11941175
}
1176+
11951177
} // namespace solidity::frontend

solc/CommandLineParser.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <map>
3434
#include <memory>
3535
#include <optional>
36+
#include <ostream>
3637
#include <set>
3738
#include <string>
3839
#include <vector>
@@ -177,6 +178,11 @@ struct CommandLineOptions
177178
class CommandLineParser
178179
{
179180
public:
181+
explicit CommandLineParser(std::ostream& _sout, std::ostream& _serr):
182+
m_sout(_sout),
183+
m_serr(_serr)
184+
{}
185+
180186
/// Parses the command-line arguments and fills out the internal CommandLineOptions structure.
181187
/// Performs validation and prints error messages. If requested, prints usage banner, version
182188
/// or license.
@@ -191,9 +197,8 @@ class CommandLineParser
191197

192198
CommandLineOptions const& options() const { return m_options; }
193199

194-
/// Returns true if any parser instance has written anything to cout or cerr since the last
195-
/// call to parse().
196-
static bool hasOutput();
200+
/// Returns true if the parser has written anything to any of its output streams.
201+
bool hasOutput() const { return m_hasOutput; }
197202

198203
private:
199204
/// Parses the value supplied to --combined-json.
@@ -210,9 +215,28 @@ class CommandLineParser
210215
/// @return false if there are any validation errors, true otherwise.
211216
bool parseLibraryOption(std::string const& _input);
212217

218+
bool checkMutuallyExclusive(
219+
boost::program_options::variables_map const& args,
220+
std::string const& _optionA,
221+
std::string const& _optionB
222+
);
223+
[[noreturn]] void printVersionAndExit();
224+
[[noreturn]] void printLicenseAndExit();
213225
size_t countEnabledOptions(std::vector<std::string> const& _optionNames) const;
214226
static std::string joinOptionNames(std::vector<std::string> const& _optionNames, std::string _separator = ", ");
215227

228+
/// Returns the stream that should receive normal output. Sets m_hasOutput to true if the
229+
/// stream has ever been used.
230+
std::ostream& sout();
231+
232+
/// Returns the stream that should receive error output. Sets m_hasOutput to true if the
233+
/// stream has ever been used.
234+
std::ostream& serr();
235+
236+
std::ostream& m_sout;
237+
std::ostream& m_serr;
238+
bool m_hasOutput = false;
239+
216240
CommandLineOptions m_options;
217241

218242
/// Map of command-line arguments produced by boost::program_options.

solc/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static void setDefaultOrCLocale()
5454
int main(int argc, char** argv)
5555
{
5656
setDefaultOrCLocale();
57-
solidity::frontend::CommandLineInterface cli;
57+
solidity::frontend::CommandLineInterface cli(cin, cout, cerr);
5858
if (!cli.parseArguments(argc, argv))
5959
return 1;
6060
if (!cli.processInput())

0 commit comments

Comments
 (0)