From 1f83704a70b9c4065a5eb9f65e94919415d238ae Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 30 Jun 2022 14:25:16 +0300 Subject: Add support for using bool with std::vector, std::set, and std::map --- cli-examples/features/driver.cxx | 2 +- cli-examples/features/options.cli | 6 +-- cli/cli/bootstrap/cli/options.cxx | 98 +++++++++++++++++++++++++-------------- cli/cli/runtime-source.cxx | 44 +++++++++++++++--- cli/cli/source.cxx | 9 ++-- cli/doc/cli-guide.xhtml | 6 +-- 6 files changed, 113 insertions(+), 52 deletions(-) diff --git a/cli-examples/features/driver.cxx b/cli-examples/features/driver.cxx index c14b5c7..a6299b9 100644 --- a/cli-examples/features/driver.cxx +++ b/cli-examples/features/driver.cxx @@ -45,7 +45,7 @@ main (int argc, char* argv[]) // --map | -m // - typedef map str_map; + typedef map str_map; const str_map& m = o.map (); str_map::const_iterator i (m.find ("a")); diff --git a/cli-examples/features/options.cli b/cli-examples/features/options.cli index ea055b3..4065830 100644 --- a/cli-examples/features/options.cli +++ b/cli-examples/features/options.cli @@ -31,9 +31,9 @@ namespace features std::set --set | -s; // We can also use maps. In this case the option value is expected to have - // two parts: the key and the value, separated by '='. For example: -m a=A - // -m =B -m c= -m d (same as -m d=). + // two parts: the key and the value, separated by '='. For example: -m a=1 + // -m =true -m c= -m d (same as -m d=). // - std::map --map | -m; + std::map --map | -m; }; } diff --git a/cli/cli/bootstrap/cli/options.cxx b/cli/cli/bootstrap/cli/options.cxx index 5ed58b4..2cb2f75 100644 --- a/cli/cli/bootstrap/cli/options.cxx +++ b/cli/cli/bootstrap/cli/options.cxx @@ -542,10 +542,31 @@ namespace cli struct parser { static void - parse (bool& x, scanner& s) + parse (bool& x, bool& xs, scanner& s) { - s.next (); - x = true; + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; } }; @@ -662,6 +683,14 @@ namespace cli parser::parse (x.*M, s); } + template + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + template void thunk (X& x, scanner& s) @@ -671,7 +700,6 @@ namespace cli } #include -#include // options // @@ -1815,9 +1843,9 @@ struct _cli_options_map_init &::cli::thunk< options, std::uint64_t, &options::build2_metadata_, &options::build2_metadata_specified_ >; _cli_options_map_["--help"] = - &::cli::thunk< options, bool, &options::help_ >; + &::cli::thunk< options, &options::help_ >; _cli_options_map_["--version"] = - &::cli::thunk< options, bool, &options::version_ >; + &::cli::thunk< options, &options::version_ >; _cli_options_map_["--include-path"] = &::cli::thunk< options, std::vector, &options::include_path_, &options::include_path_specified_ >; @@ -1834,25 +1862,25 @@ struct _cli_options_map_init &::cli::thunk< options, cxx_version, &options::std_, &options::std_specified_ >; _cli_options_map_["--generate-modifier"] = - &::cli::thunk< options, bool, &options::generate_modifier_ >; + &::cli::thunk< options, &options::generate_modifier_ >; _cli_options_map_["--generate-specifier"] = - &::cli::thunk< options, bool, &options::generate_specifier_ >; + &::cli::thunk< options, &options::generate_specifier_ >; _cli_options_map_["--generate-parse"] = - &::cli::thunk< options, bool, &options::generate_parse_ >; + &::cli::thunk< options, &options::generate_parse_ >; _cli_options_map_["--generate-merge"] = - &::cli::thunk< options, bool, &options::generate_merge_ >; + &::cli::thunk< options, &options::generate_merge_ >; _cli_options_map_["--generate-description"] = - &::cli::thunk< options, bool, &options::generate_description_ >; + &::cli::thunk< options, &options::generate_description_ >; _cli_options_map_["--generate-file-scanner"] = - &::cli::thunk< options, bool, &options::generate_file_scanner_ >; + &::cli::thunk< options, &options::generate_file_scanner_ >; _cli_options_map_["--generate-vector-scanner"] = - &::cli::thunk< options, bool, &options::generate_vector_scanner_ >; + &::cli::thunk< options, &options::generate_vector_scanner_ >; _cli_options_map_["--generate-group-scanner"] = - &::cli::thunk< options, bool, &options::generate_group_scanner_ >; + &::cli::thunk< options, &options::generate_group_scanner_ >; _cli_options_map_["--suppress-inline"] = - &::cli::thunk< options, bool, &options::suppress_inline_ >; + &::cli::thunk< options, &options::suppress_inline_ >; _cli_options_map_["--suppress-cli"] = - &::cli::thunk< options, bool, &options::suppress_cli_ >; + &::cli::thunk< options, &options::suppress_cli_ >; _cli_options_map_["--cli-namespace"] = &::cli::thunk< options, std::string, &options::cli_namespace_, &options::cli_namespace_specified_ >; @@ -1863,23 +1891,23 @@ struct _cli_options_map_init &::cli::thunk< options, std::string, &options::export_symbol_, &options::export_symbol_specified_ >; _cli_options_map_["--generate-cxx"] = - &::cli::thunk< options, bool, &options::generate_cxx_ >; + &::cli::thunk< options, &options::generate_cxx_ >; _cli_options_map_["--generate-man"] = - &::cli::thunk< options, bool, &options::generate_man_ >; + &::cli::thunk< options, &options::generate_man_ >; _cli_options_map_["--generate-html"] = - &::cli::thunk< options, bool, &options::generate_html_ >; + &::cli::thunk< options, &options::generate_html_ >; _cli_options_map_["--generate-txt"] = - &::cli::thunk< options, bool, &options::generate_txt_ >; + &::cli::thunk< options, &options::generate_txt_ >; _cli_options_map_["--stdout"] = - &::cli::thunk< options, bool, &options::stdout__ >; + &::cli::thunk< options, &options::stdout__ >; _cli_options_map_["--suppress-undocumented"] = - &::cli::thunk< options, bool, &options::suppress_undocumented_ >; + &::cli::thunk< options, &options::suppress_undocumented_ >; _cli_options_map_["--suppress-usage"] = - &::cli::thunk< options, bool, &options::suppress_usage_ >; + &::cli::thunk< options, &options::suppress_usage_ >; _cli_options_map_["--long-usage"] = - &::cli::thunk< options, bool, &options::long_usage_ >; + &::cli::thunk< options, &options::long_usage_ >; _cli_options_map_["--short-usage"] = - &::cli::thunk< options, bool, &options::short_usage_ >; + &::cli::thunk< options, &options::short_usage_ >; _cli_options_map_["--page-usage"] = &::cli::thunk< options, std::string, &options::page_usage_, &options::page_usage_specified_ >; @@ -1887,13 +1915,13 @@ struct _cli_options_map_init &::cli::thunk< options, std::size_t, &options::option_length_, &options::option_length_specified_ >; _cli_options_map_["--ascii-tree"] = - &::cli::thunk< options, bool, &options::ascii_tree_ >; + &::cli::thunk< options, &options::ascii_tree_ >; _cli_options_map_["--ansi-color"] = - &::cli::thunk< options, bool, &options::ansi_color_ >; + &::cli::thunk< options, &options::ansi_color_ >; _cli_options_map_["--exclude-base"] = - &::cli::thunk< options, bool, &options::exclude_base_ >; + &::cli::thunk< options, &options::exclude_base_ >; _cli_options_map_["--include-base-last"] = - &::cli::thunk< options, bool, &options::include_base_last_ >; + &::cli::thunk< options, &options::include_base_last_ >; _cli_options_map_["--class-doc"] = &::cli::thunk< options, std::map, &options::class_doc_, &options::class_doc_specified_ >; @@ -1910,12 +1938,12 @@ struct _cli_options_map_init &::cli::thunk< options, std::vector, &options::link_regex_, &options::link_regex_specified_ >; _cli_options_map_["--link-regex-trace"] = - &::cli::thunk< options, bool, &options::link_regex_trace_ >; + &::cli::thunk< options, &options::link_regex_trace_ >; _cli_options_map_["--html-heading-map"] = &::cli::thunk< options, std::map, &options::html_heading_map_, &options::html_heading_map_specified_ >; _cli_options_map_["--omit-link-check"] = - &::cli::thunk< options, bool, &options::omit_link_check_ >; + &::cli::thunk< options, &options::omit_link_check_ >; _cli_options_map_["--hxx-prologue"] = &::cli::thunk< options, std::vector, &options::hxx_prologue_, &options::hxx_prologue_specified_ >; @@ -2019,13 +2047,13 @@ struct _cli_options_map_init &::cli::thunk< options, std::string, &options::option_separator_, &options::option_separator_specified_ >; _cli_options_map_["--keep-separator"] = - &::cli::thunk< options, bool, &options::keep_separator_ >; + &::cli::thunk< options, &options::keep_separator_ >; _cli_options_map_["--no-combined-flags"] = - &::cli::thunk< options, bool, &options::no_combined_flags_ >; + &::cli::thunk< options, &options::no_combined_flags_ >; _cli_options_map_["--no-combined-values"] = - &::cli::thunk< options, bool, &options::no_combined_values_ >; + &::cli::thunk< options, &options::no_combined_values_ >; _cli_options_map_["--include-with-brackets"] = - &::cli::thunk< options, bool, &options::include_with_brackets_ >; + &::cli::thunk< options, &options::include_with_brackets_ >; _cli_options_map_["--include-prefix"] = &::cli::thunk< options, std::string, &options::include_prefix_, &options::include_prefix_specified_ >; diff --git a/cli/cli/runtime-source.cxx b/cli/cli/runtime-source.cxx index d5334a0..9620648 100644 --- a/cli/cli/runtime-source.cxx +++ b/cli/cli/runtime-source.cxx @@ -17,11 +17,11 @@ generate_runtime_source (context& ctx, bool complete) << "#include " << endl << "#include " << endl // pair << "#include " << endl - << "#include " << endl; + << "#include " << endl + << "#include " << endl; if (complete && ctx.options.generate_file_scanner ()) - os << "#include " << endl - << "#include " << endl; + os << "#include " << endl; os << endl; @@ -1011,11 +1011,33 @@ generate_runtime_source (context& ctx, bool complete) << "{"; os << "static void" << endl - << "parse (bool& x, scanner& s)" + << "parse (bool& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" << "{" - << "s.next ();" - << "x = true;" - << "}"; + << "const char* o (s.next ());" + << endl + << "if (s.more ())" + << "{" + << "const char* v (s.next ());" + << endl + << "if (std::strcmp (v, \"1\") == 0 ||" << endl + << "std::strcmp (v, \"true\") == 0 ||" << endl + << "std::strcmp (v, \"TRUE\") == 0 ||" << endl + << "std::strcmp (v, \"True\") == 0)" << endl + << "x = true;" + << "else if (std::strcmp (v, \"0\") == 0 ||" << endl + << "std::strcmp (v, \"false\") == 0 ||" << endl + << "std::strcmp (v, \"FALSE\") == 0 ||" << endl + << "std::strcmp (v, \"False\") == 0)" << endl + << "x = false;" + << "else" << endl + << "throw invalid_value (o, v);" + << "}" + << "else" << endl + << "throw missing_value (o);"; + if (sp) + os << endl + << "xs = true;"; + os << "}"; if (gen_merge) os << "static void" << endl @@ -1203,6 +1225,14 @@ generate_runtime_source (context& ctx, bool complete) << "parser::parse (x.*M, s);" << "}"; + os << "template " << endl + << "void" << endl + << "thunk (X& x, scanner& s)" + << "{" + << "s.next ();" + << "x.*M = true;" + << "}"; + if (ctx.gen_specifier) os << "template " << endl << "void" << endl diff --git a/cli/cli/source.cxx b/cli/cli/source.cxx index 1b9e832..3c04d1a 100644 --- a/cli/cli/source.cxx +++ b/cli/cli/source.cxx @@ -110,8 +110,12 @@ namespace for (names::name_iterator i (n.name_begin ()); i != n.name_end (); ++i) { os << "_cli_" << scope << "_map_[\"" << *i << "\"] =" << endl - << "&" << cli << "::thunk< " << scope << ", " << type << ", " << - "&" << scope << "::" << member; + << "&" << cli << "::thunk< " << scope; + + if (type != "bool") + os << ", " << type; + + os << ", " << "&" << scope << "::" << member; if (gen_specifier && type != "bool") os << "," << endl @@ -1272,7 +1276,6 @@ generate_source (context& ctx) ostream& os (ctx.os); os << "#include " << endl - << "#include " << endl << endl; traversal::cli_unit unit; diff --git a/cli/doc/cli-guide.xhtml b/cli/doc/cli-guide.xhtml index 675db03..94c006c 100644 --- a/cli/doc/cli-guide.xhtml +++ b/cli/doc/cli-guide.xhtml @@ -1084,12 +1084,12 @@ include <string>; class options { - std::map<std::string, std::string> --map | -m; + std::map<std::string, bool> --map | -m; }; -

The possible option values for this interface are: -m a=A, - -m =B (key is an empty string), -m c= (value +

The possible option values for this interface are: -m a=1, + -m =true (key is an empty string), -m c= (value is an empty string), or -m d (same as -m d=).

The last component in the option definition is optional documentation. -- cgit v1.1