31 #include <boost/tokenizer.hpp>
38 main(
int argc,
char** argv)
40 std::vector<std::string> args(argv + 1, argv + argc);
50 if (args[0] ==
"-V" || args[0] ==
"--version") {
57 std::string noun, verb;
62 auto processLine = [&parser] (
const std::vector<std::string>& line) -> Command {
65 return {noun, verb, ca, execute};
67 catch (
const std::invalid_argument& e) {
68 int ret =
help(std::cout, parser, line);
70 std::cerr << e.what() << std::endl;
75 std::list<Command> commands;
77 if (args[0] ==
"-f" || args[0] ==
"--batch") {
78 if (args.size() != 2) {
79 std::cerr <<
"ERROR: Invalid command line arguments: " << args[0] <<
" should follow with batch-file."
80 <<
" Use -h for more detail." << std::endl;
84 auto processIstream = [&commands, &processLine] (std::istream& is,
const std::string& inputFile) {
86 size_t lineCounter = 0;
87 while (std::getline(is, line)) {
90 auto hasEscapeSlash = [] (
const std::string& str) {
91 auto count = std::count(str.rbegin(), str.rend(),
'\\');
92 return (count % 2) == 1;
94 while (!line.empty() && hasEscapeSlash(line)) {
95 std::string extraLine;
96 const auto& hasMore = std::getline(is, extraLine);
98 line = line.substr(0, line.size() - 1) + extraLine;
103 boost::tokenizer<boost::escaped_list_separator<char>> tokenizer(
105 boost::escaped_list_separator<char>(
"\\",
" \t",
"\"'"));
107 auto firstNonEmptyToken = tokenizer.begin();
108 while (firstNonEmptyToken != tokenizer.end() && firstNonEmptyToken->empty()) {
109 ++firstNonEmptyToken;
114 if (firstNonEmptyToken == tokenizer.end() || (*firstNonEmptyToken)[0] ==
'#') {
118 std::vector<std::string> lineArgs;
119 std::copy_if(firstNonEmptyToken, tokenizer.end(), std::back_inserter(lineArgs),
120 [] (
const auto& t) { return !t.empty(); });
122 auto cmd = processLine(lineArgs);
123 if (cmd.noun.empty()) {
124 std::cerr <<
" >> Syntax error on line " << lineCounter <<
" of the batch in "
125 << inputFile << std::endl;
128 commands.push_back(std::move(cmd));
133 if (args[1] ==
"-") {
134 auto retval = processIstream(std::cin,
"standard input");
140 std::ifstream iff(args[1]);
142 std::cerr <<
"ERROR: Could not open `" << args[1] <<
"` batch file "
143 <<
"(" << strerror(errno) <<
")" << std::endl;
146 auto retval = processIstream(iff, args[1]);
153 commands.push_back(processLine(args));
158 ndn::KeyChain keyChain;
159 ndn::nfd::Controller controller(face, keyChain);
160 size_t commandCounter = 0;
161 for (
auto& command : commands) {
164 std::cout, std::cerr, face, keyChain, controller};
165 command.execute(ctx);
167 if (ctx.exitCode != 0) {
168 if (commands.size() > 1) {
169 std::cerr <<
" >> Failed to execute command on line " << commandCounter
170 <<
" of the batch file " << args[1] << std::endl;
171 std::cerr <<
" Note that nfdc has executed all commands on previous lines and "
172 <<
"stopped processing at this line" << std::endl;
180 catch (
const std::exception& e) {
181 std::cerr << e.what() << std::endl;
Context for command execution.
int main(int argc, char **argv)
const char NFD_VERSION_BUILD_STRING[]
NFD version string, including git commit information if NFD is build from a specific git commit.