From 8c1e0035404050376350d5e9b9242f5d39a6b53e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 27 Jul 2019 17:28:27 +0200 Subject: Add support for direct file loading with argv_file_scanner --- cli/options.cxx | 3 +- cli/options.hxx | 9 +++++ cli/options.ixx | 29 ++++++++++++++ cli/runtime-header.cxx | 11 +++++- cli/runtime-inline.cxx | 33 ++++++++++++++++ cli/runtime-source.cxx | 3 ++ tests/file/driver.cxx | 19 +++++++-- tests/file/testscript | 103 +++++++++++++++++++++++++++++++++---------------- 8 files changed, 170 insertions(+), 40 deletions(-) diff --git a/cli/options.cxx b/cli/options.cxx index 2e69cc9..7edc7f2 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -213,6 +213,8 @@ namespace cli // argv_file_scanner // + int argv_file_scanner::zero_argc_ = 0; + bool argv_file_scanner:: more () { @@ -459,7 +461,6 @@ namespace cli using namespace std; const char* o (s.next ()); - if (s.more ()) { string v (s.next ()); diff --git a/cli/options.hxx b/cli/options.hxx index 9f5124f..a865148 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -296,6 +296,9 @@ namespace cli const std::string& option, bool erase = false); + argv_file_scanner (const std::string& file, + const std::string& option); + struct option_info { // If search_func is not NULL, it is called, with the arg @@ -320,6 +323,10 @@ namespace cli std::size_t options_count, bool erase = false); + argv_file_scanner (const std::string& file, + const option_info* options = 0, + std::size_t options_count = 0); + virtual bool more (); @@ -354,6 +361,8 @@ namespace cli std::size_t i_; bool skip_; + + static int zero_argc_; }; template diff --git a/cli/options.ixx b/cli/options.ixx index ba5fff2..2b63fa8 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -194,6 +194,22 @@ namespace cli } inline argv_file_scanner:: + argv_file_scanner (const std::string& file, + const std::string& option) + : argv_scanner (0, zero_argc_, 0), + option_ (option), + options_ (&option_info_), + options_count_ (1), + i_ (1), + skip_ (false) + { + option_info_.option = option_.c_str (); + option_info_.search_func = 0; + + load (file); + } + + inline argv_file_scanner:: argv_file_scanner (int& argc, char** argv, const option_info* options, @@ -221,6 +237,19 @@ namespace cli skip_ (false) { } + + inline argv_file_scanner:: + argv_file_scanner (const std::string& file, + const option_info* options, + std::size_t options_count) + : argv_scanner (0, zero_argc_, 0), + options_ (options), + options_count_ (options_count), + i_ (1), + skip_ (false) + { + load (file); + } } // options diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx index 9d200bc..2b01071 100644 --- a/cli/runtime-header.cxx +++ b/cli/runtime-header.cxx @@ -415,6 +415,9 @@ generate_runtime_header (context& ctx) << "const std::string& option," << endl << "bool erase = false);" << endl + << "argv_file_scanner (const std::string& file," << endl + << "const std::string& option);" + << endl << "struct option_info" << "{" << "// If search_func is not NULL, it is called, with the arg" << endl @@ -438,6 +441,10 @@ generate_runtime_header (context& ctx) << "std::size_t options_count," << endl << "bool erase = false);" << endl + << "argv_file_scanner (const std::string& file," << endl + << "const option_info* options = 0," << endl + << "std::size_t options_count = 0);" + << endl << "virtual bool" << endl << "more ();" << endl @@ -475,7 +482,9 @@ generate_runtime_header (context& ctx) os << endl << "bool skip_;"; - os << "};"; + os << endl + << "static int zero_argc_;" + << "};"; } // group_scanner diff --git a/cli/runtime-inline.cxx b/cli/runtime-inline.cxx index 18c5889..3a62db8 100644 --- a/cli/runtime-inline.cxx +++ b/cli/runtime-inline.cxx @@ -324,6 +324,24 @@ generate_runtime_inline (context& ctx) << "}"; os << inl << "argv_file_scanner::" << endl + << "argv_file_scanner (const std::string& file," << endl + << "const std::string& option)" << endl + << ": argv_scanner (0, zero_argc_, 0)," << endl + << " option_ (option)," << endl + << " options_ (&option_info_)," << endl + << " options_count_ (1)," << endl + << " i_ (1)"; + if (sep) + os << "," << endl + << " skip_ (false)"; + os << "{" + << "option_info_.option = option_.c_str ();" + << "option_info_.search_func = 0;" + << endl + << "load (file);" + << "}"; + + os << inl << "argv_file_scanner::" << endl << "argv_file_scanner (int& argc," << endl << "char** argv," << endl << "const option_info* options," << endl @@ -355,6 +373,21 @@ generate_runtime_inline (context& ctx) << " skip_ (false)"; os << "{" << "}"; + + os << inl << "argv_file_scanner::" << endl + << "argv_file_scanner (const std::string& file," << endl + << "const option_info* options," << endl + << "std::size_t options_count)" << endl + << ": argv_scanner (0, zero_argc_, 0)," << endl + << " options_ (options)," << endl + << " options_count_ (options_count)," << endl + << " i_ (1)"; + if (sep) + os << "," << endl + << " skip_ (false)"; + os << "{" + << "load (file);" + << "}"; } // group_scanner diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx index 54a085f..dab695c 100644 --- a/cli/runtime-source.cxx +++ b/cli/runtime-source.cxx @@ -365,6 +365,9 @@ generate_runtime_source (context& ctx, bool complete) os << "// argv_file_scanner" << endl << "//" << endl + << "int argv_file_scanner::zero_argc_ = 0;" + << endl + << "bool argv_file_scanner::" << endl << "more ()" << "{" diff --git a/tests/file/driver.cxx b/tests/file/driver.cxx index e2dc9d5..82f944c 100644 --- a/tests/file/driver.cxx +++ b/tests/file/driver.cxx @@ -5,7 +5,8 @@ // Test argv_file_scanner. // - +#include +#include #include #include "test.hxx" @@ -17,10 +18,20 @@ main (int argc, char* argv[]) { try { - cli::argv_file_scanner s (argc, argv, "--file"); + string a (argc > 1 ? argv[1] : ""); + + // Special modes. + // + // ---- + // --- + // + unique_ptr s ( + a == "----" ? new cli::argv_file_scanner (argv[2], "--file") : + a == "---" ? new cli::argv_file_scanner (argv[2]) : + new cli::argv_file_scanner (argc, argv, "--file")); - while (s.more ()) - cout << s.next () << endl; + while (s->more ()) + cout << s->next () << endl; } catch (const cli::exception& e) { diff --git a/tests/file/testscript b/tests/file/testscript index 3f9d43b..ab0eb12 100644 --- a/tests/file/testscript +++ b/tests/file/testscript @@ -8,12 +8,12 @@ # eol = "" -+cat <=empty.cli ++cat <=empty.ops # Empty options file. # EOI -+cat <=base.cli ++cat <=base.ops -a 21 -b 21 EOI @@ -23,7 +23,7 @@ EOI : 000 : -cat <=test.cli; +cat <=test.ops; -a 11 -b 11 -a 12 @@ -31,7 +31,7 @@ cat <=test.cli; -b 12 a EOI -$* -a 1 --file ../empty.cli -b 1 --file ../base.cli --file test.cli b >>EOO +$* -a 1 --file ../empty.ops -b 1 --file ../base.ops --file test.ops b >>EOO -a 1 -b @@ -54,32 +54,32 @@ EOO : 001 : -cat <=test.cli; +cat <=test.ops; # Empty options file. # EOI -$* -a 1 -- --file test.cli b >>EOO +$* -a 1 -- --file test.ops b >>EOO -a 1 -- --file -test.cli +test.ops b EOO : 002 : -cat <=test.cli; +cat <=test.ops; -a 11 -b 11 -- ---file ../base.cli +--file ../base.ops -a 12 -b 12 a EOI -$* -a 1 --file test.cli --file ../empty.cli b >>EOO +$* -a 1 --file test.ops --file ../empty.ops b >>EOO -a 1 -a @@ -88,20 +88,20 @@ $* -a 1 --file test.cli --file ../empty.cli b >>EOO 11 -- --file -../base.cli +../base.ops -a 12 -b 12 a --file -../empty.cli +../empty.ops b EOO : 003 : -$* -a 1 --file ../base.cli --file test.cli b >>EOO 2>>EOE +$* -a 1 --file ../base.ops --file test.ops b >>EOO 2>>EOE -a 1 -a @@ -109,12 +109,12 @@ $* -a 1 --file ../base.cli --file test.cli b >>EOO 2>>EOE -b 21 EOO -unable to open file 'test.cli' or read failure +unable to open file 'test.ops' or read failure EOE : 004 : -cat <=test.cli; +cat <=test.ops; -a a"b"c -a "abc" -a "a"b" @@ -133,7 +133,7 @@ cat <=test.cli; -a ''' -a '"' EOI -$* --file test.cli >>"EOO" +$* --file test.ops >>"EOO" -a a"b"c -a @@ -170,83 +170,118 @@ EOO : 005 : -cat <=test.cli; +cat <=test.ops; -a " EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument '"' EOE : 006 : -cat <=test.cli; +cat <=test.ops; -a "abc EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument '"abc' EOE : 007 : -cat <=test.cli; +cat <=test.ops; -a abc" EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument 'abc"' EOE : 008 : -cat <=test.cli; +cat <=test.ops; -a ' EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument ''' EOE : 009 : -cat <=test.cli; +cat <=test.ops; -a 'abc EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument ''abc' EOE : 010 : -cat <=test.cli; +cat <=test.ops; -a abc' EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument 'abc'' EOE : 011 : -cat <=test.cli; +cat <=test.ops; -a "abc' EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument '"abc'' EOE : 012 : -cat <=test.cli; +cat <=test.ops; -a 'abc" EOI -$* --file test.cli 2>>EOE +$* --file test.ops 2>>EOE unmatched quote in argument ''abc"' EOE : quoted-argument : -cat <=test.cli; +cat <=test.ops; "'foo bar'" '"foo bar"' EOI -$* --file test.cli >>EOO +$* --file test.ops >>EOO 'foo bar' "foo bar" EOO + +: direct-file-load +: +cat <=test.ops; +-f +-a 123 +EOI +$* --- test.ops >>EOO +-f +-a +123 +EOO + +: direct-file-empty +: +cat <=test.ops; +EOI +$* --- test.ops + +: direct-file-load-nested +: +cat <=test.ops; +-f +--file ../base.ops +-a 123 +EOI +$* ---- test.ops >>EOO +-f +-a +21 +-b +21 +-a +123 +EOO -- cgit v1.1