From 0267ede2d356abdef7b3e9af19d4725605a58947 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 20 Jan 2011 15:38:10 +0200 Subject: Add support for multiple file options and file search callbacks --- cli/runtime-header.cxx | 33 ++++++++++++++++++++++++++++++--- cli/runtime-inline.cxx | 43 +++++++++++++++++++++++++++++++++++++++++-- cli/runtime-source.cxx | 35 +++++++++++++++++++++++++++++------ 3 files changed, 100 insertions(+), 11 deletions(-) (limited to 'cli') diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx index 1e4941b..41c56c9 100644 --- a/cli/runtime-header.cxx +++ b/cli/runtime-header.cxx @@ -21,6 +21,7 @@ generate_runtime_header (context& ctx) os << "#include " << endl << "#include " << endl + << "#include " << endl << "#include " << endl << endl; @@ -266,13 +267,32 @@ generate_runtime_header (context& ctx) << "public:" << endl << "argv_file_scanner (int& argc," << endl << "char** argv," << endl - << "const std::string& file_option," << endl + << "const std::string& option," << endl << "bool erase = false);" << endl << "argv_file_scanner (int start," << endl << "int& argc," << endl << "char** argv," << endl - << "const std::string& file_option," << endl + << "const std::string& option," << endl + << "bool erase = false);" + << endl + << "struct option_info" + << "{" + << " const char* option;" + << " std::string (*search_func) (const char*, void* arg);" + << " void* arg;" + << "};" + << "argv_file_scanner (int& argc," << endl + << "char** argv," << endl + << "const option_info* options," << endl + << "std::size_t options_count," << endl + << "bool erase = false);" + << endl + << "argv_file_scanner (int start," << endl + << "int& argc," << endl + << "char** argv," << endl + << "const option_info* options," << endl + << "std::size_t options_count," << endl << "bool erase = false);" << endl << "virtual bool" << endl @@ -288,12 +308,19 @@ generate_runtime_header (context& ctx) << "skip ();" << endl << "private:" << endl + << "const option_info*" << endl + << "find (const char*) const;" + << endl << "void" << endl - << "load (const char* file);" + << "load (const std::string& file);" << endl << "typedef argv_scanner base;" << endl << "const std::string option_;" + << "option_info option_info_;" + << "const option_info* options_;" + << "std::size_t options_count_;" + << endl << "std::string hold_;" << "std::deque args_;"; diff --git a/cli/runtime-inline.cxx b/cli/runtime-inline.cxx index 633d7db..4d95a78 100644 --- a/cli/runtime-inline.cxx +++ b/cli/runtime-inline.cxx @@ -189,11 +189,15 @@ generate_runtime_inline (context& ctx) << "const std::string& option," << endl << "bool erase)" << endl << ": argv_scanner (argc, argv, erase)," << endl - << " option_ (option)"; + << " option_ (option)," << endl + << " options_ (&option_info_)," << endl + << " options_count_ (1)"; if (sep) os << "," << endl << " skip_ (false)"; os << "{" + << "option_info_.option = option_.c_str ();" + << "option_info_.search_func = 0;" << "}"; os << inl << "argv_file_scanner::" << endl @@ -203,7 +207,42 @@ generate_runtime_inline (context& ctx) << "const std::string& option," << endl << "bool erase)" << endl << ": argv_scanner (start, argc, argv, erase)," << endl - << " option_ (option)"; + << " option_ (option)," << endl + << " options_ (&option_info_)," << endl + << " options_count_ (1)"; + if (sep) + os << "," << endl + << " skip_ (false)"; + os << "{" + << "option_info_.option = option_.c_str ();" + << "option_info_.search_func = 0;" + << "}"; + + os << inl << "argv_file_scanner::" << endl + << "argv_file_scanner (int& argc," << endl + << "char** argv," << endl + << "const option_info* options," << endl + << "std::size_t options_count," << endl + << "bool erase)" << endl + << ": argv_scanner (argc, argv, erase)," << endl + << " options_ (options)," << endl + << " options_count_ (options_count)"; + if (sep) + os << "," << endl + << " skip_ (false)"; + os << "{" + << "}"; + + os << inl << "argv_file_scanner::" << endl + << "argv_file_scanner (int start," << endl + << "int& argc," << endl + << "char** argv," << endl + << "const option_info* options," << endl + << "std::size_t options_count," << endl + << "bool erase)" << endl + << ": argv_scanner (start, argc, argv, erase)," << endl + << " options_ (options)," << endl + << " options_count_ (options_count)"; if (sep) os << "," << endl << " skip_ (false)"; diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx index cae8c84..4c6b2a2 100644 --- a/cli/runtime-source.cxx +++ b/cli/runtime-source.cxx @@ -255,14 +255,18 @@ generate_runtime_source (context& ctx) << "// See if the next argument is the file option." << endl << "//" << endl << "const char* a (base::peek ());" + << "const option_info* oi;" << endl - << "if (" << (sep ? "!skip_ && " : "") << "a == option_)" + << "if (" << (sep ? "!skip_ && " : "") << "(oi = find (a)))" << "{" << "base::next ();" << endl << "if (!base::more ())" << endl - << "throw missing_value (option_);" + << "throw missing_value (oi->option);" << endl + << "if (oi->search_func != 0)" << endl + << "load (oi->search_func (base::next (), oi->arg));" + << "else" << endl << "load (base::next ());" << endl << "if (!args_.empty ())" << endl @@ -317,12 +321,22 @@ generate_runtime_source (context& ctx) << "args_.pop_front ();" << "}" + << "const argv_file_scanner::option_info* argv_file_scanner::" << endl + << "find (const char* a) const" + << "{" + << "for (std::size_t i (0); i < options_count_; ++i)" << endl + << "if (std::strcmp (a, options_[i].option) == 0)" << endl + << "return &options_[i];" + << endl + << "return 0;" + << "}" + << "void argv_file_scanner::" << endl - << "load (const char* file)" + << "load (const std::string& file)" << "{" << "using namespace std;" << endl - << "ifstream is (file);" + << "ifstream is (file.c_str ());" << endl << "if (!is.is_open ())" << endl << "throw file_io_failure (file);" @@ -400,8 +414,17 @@ generate_runtime_source (context& ctx) << endl << "s2 = string (s2, 1, n - 2);" << "}" - << "if (" << (sep ? "!skip_ && " : "") << "s1 == option_)" << endl - << "load (s2.c_str ());" + << "const option_info* oi;" + << "if (" << (sep ? "!skip_ && " : "") << "(oi = find (s1.c_str ())))" << endl + << "{" + << "if (s2.empty ())" << endl + << "throw missing_value (oi->option);" + << endl + << "if (oi->search_func != 0)" << endl + << "load (oi->search_func (s2.c_str (), oi->arg));" + << "else" << endl + << "load (s2);" + << "}" << "else" << "{" << "args_.push_back (s1);" -- cgit v1.1