From 813e4744038ec3a1ca8095111074c1cb2a824d83 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 19 Nov 2015 14:53:52 +0200 Subject: Implement entire page usage generation --- cli/context.cxx | 85 ++++++++-- cli/context.hxx | 37 +++-- cli/generator.cxx | 65 +------- cli/header.cxx | 31 ++++ cli/makefile | 4 +- cli/options.cli | 24 +++ cli/options.cxx | 417 ++++++++++++++++++++++++++++++++++++++++++------- cli/options.hxx | 160 +++++++++++++++++++ cli/options.ixx | 240 ++++++++++++++++++++++++++++ cli/runtime-header.cxx | 17 +- cli/runtime-inline.cxx | 4 +- cli/runtime-source.cxx | 4 +- cli/source.cxx | 412 ++++++++++++++++++++++++++++++++++-------------- 13 files changed, 1233 insertions(+), 267 deletions(-) (limited to 'cli') diff --git a/cli/context.cxx b/cli/context.cxx index a014824..d13f1e5 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -1403,6 +1403,69 @@ format (output_type ot, string const& s, bool para) } string context:: +substitute (const string& s, semantics::cli_unit& u) +{ + string r; + + // Scan the string looking for variables ($var$). + // + size_t b (0), e (b); + for (size_t n (s.size ()); e != n; ++e) + { + if (s[e] == '$' && e + 1 != n) + { + if (s[e + 1] == '$') // Escape. + { + r.append (s, b, ++e - b); // Keep one, skip the other. + b = e + 1; + continue; + } + + // Scan for as long as it is a C identifier. + // + size_t p (e + 1); // Position of the second '$'. + for (; p != n; ++p) + { + char c (s[p]); + + if (!(c == '_' || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + (p != e + 1 && '0' <= c && c <= '9'))) + break; + } + + // Note: check that the second '$' is not escaped. + // + if (p != n && s[p] == '$' && (p + 1 == n || s[p + 1] != '$')) + { + r.append (s, b, e - b); + + // Lookup and substiute the variable. + // + ++e; + string v (s, e, p - e); + + if (semantics::doc* d = u.lookup ("", "var: " + v)) + r += d->front (); + else + { + cerr << "error: undefined variable '" << v << "' in '" << s << "'" + << endl; + throw generation_failed (); + } + + e = p; + b = e + 1; + } + } + } + + r.append (s, b, e - b); // Last chunk. + return r; +} + +string context:: fq_name (semantics::nameable& n, bool cxx_name) { using namespace semantics; @@ -1423,23 +1486,23 @@ fq_name (semantics::nameable& n, bool cxx_name) return r; } -void context:: -cli_open () +string context:: +ns_open (const string& qn, bool last) { string::size_type b (0), e; do { - e = cli.find ("::", b); - string n (cli, b, e == string::npos ? e : e - b); + e = qn.find ("::", b); + string n (qn, b, e == string::npos ? e : e - b); - if (!n.empty ()) + if (!n.empty () && (last || e != string::npos)) os << "namespace " << n << "{"; b = e; if (b == string::npos) - break; + return n; b += 2; @@ -1447,22 +1510,22 @@ cli_open () } void context:: -cli_close () +ns_close (const string& qn, bool last) { string::size_type b (0), e; do { - e = cli.find ("::", b); - string n (cli, b, e == string::npos ? e : e - b); + e = qn.find ("::", b); + string n (qn, b, e == string::npos ? e : e - b); - if (!n.empty ()) + if (!n.empty () && (last || e != string::npos)) os << "}"; b = e; if (b == string::npos) - break; + return; b += 2; diff --git a/cli/context.hxx b/cli/context.hxx index 0170c7c..460287c 100644 --- a/cli/context.hxx +++ b/cli/context.hxx @@ -22,21 +22,22 @@ using std::endl; class generation_failed {}; +enum usage +{ + ut_none, + ut_short, + ut_long, + ut_both +}; + class context { public: typedef std::size_t size_t; typedef std::string string; - typedef ::options options_type; -public: - enum usage_type - { - ut_none, - ut_short, - ut_long, - ut_both - }; + typedef ::options options_type; + typedef ::usage usage_type; private: struct data; @@ -101,6 +102,14 @@ public: void format_line (output_type, string&, const char*, size_t); + // Substitute doc variable expansions ($var$). + // + static string + substitute (const string&, semantics::cli_unit&); + + string + substitute (const string& s) {return substitute (s, unit);} + public: static string const& ename (semantics::nameable& n) @@ -132,14 +141,16 @@ public: string fq_name (semantics::nameable& n, bool cxx_name = true); - // Open/close cli namespace. + // Open/close namespace. If last is false, then the last name + // component is not treated as a namespace. The open function + // also returns the last name component. // public: - void - cli_open (); + string + ns_open (const string& name, bool last = true); void - cli_close (); + ns_close (const string& name, bool last = true); public: context (std::ostream&, semantics::cli_unit&, options_type const&); diff --git a/cli/generator.cxx b/cli/generator.cxx index b45d0ec..37092ab 100644 --- a/cli/generator.cxx +++ b/cli/generator.cxx @@ -79,67 +79,6 @@ namespace } void - append (ostream& os, const string& s, semantics::cli_unit& u) - { - // Scan the string looking for variable substitutions ($var$). - // - size_t b (0), e (b); - for (size_t n (s.size ()); e != n; ++e) - { - if (s[e] == '$' && e + 1 != n) - { - if (s[e + 1] == '$') // Escape. - { - os.write (s.c_str () + b, ++e - b); // Write one, skip the other. - b = e + 1; - continue; - } - - // Scan for as long as it is a C identifier. - // - size_t p (e + 1); // Position of the second '$'. - for (; p != n; ++p) - { - char c (s[p]); - - if (!(c == '_' || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - (p != e + 1 && '0' <= c && c <= '9'))) - break; - } - - // Note: check that the second '$' is not escaped. - // - if (p != n && s[p] == '$' && (p + 1 == n || s[p + 1] != '$')) - { - os.write (s.c_str () + b, e - b); - - // Lookup and substiute the variable. - // - ++e; - string v (s, e, p - e); - - if (semantics::doc* d = u.lookup ("", "var: " + v)) - os << d->front (); - else - { - cerr << "error: undefined variable '" << v << "' in '" << s << "'" - << endl; - throw generation_failed (); - } - - e = p; - b = e + 1; - } - } - } - - os.write (s.c_str () + b, e - b); // Last chunk. - os << endl; - } - - void append (ostream& os, vector const& text, string const& file, @@ -147,7 +86,7 @@ namespace { for (vector::const_iterator i (text.begin ()); i != text.end (); ++i) - append (os, *i, u); + os << context::substitute (*i, u) << endl; if (!file.empty ()) { @@ -159,7 +98,7 @@ namespace // the delimiter. // for (string s; getline (ifs, s); ) - append (os, s, u); + os << context::substitute (s, u) << endl; } } } diff --git a/cli/header.cxx b/cli/header.cxx index 6ff1f6b..76e2626 100644 --- a/cli/header.cxx +++ b/cli/header.cxx @@ -5,6 +5,8 @@ #include "header.hxx" +using namespace std; + namespace { // @@ -308,6 +310,8 @@ namespace void generate_header (context& ctx) { + ostream& os (ctx.os); + traversal::cli_unit unit; includes includes (ctx); traversal::names unit_names; @@ -324,4 +328,31 @@ generate_header (context& ctx) ns_names >> cl; unit.dispatch (ctx.unit); + + // Entire page usage. + // + if (ctx.usage != ut_none && ctx.options.page_usage_specified ()) + { + os << "// Print page usage information." << endl + << "//" << endl; + + const string& qn (ctx.options.page_usage ()); + string n (ctx.escape (ctx.substitute (ctx.ns_open (qn, false)))); + + string const& ost (ctx.options.ostream_type ()); + + if (ctx.usage != ut_both) + os << "void" << endl + << n << "usage (" << ost << "&);" + << endl; + else + os << "void" << endl + << n << "short_usage (" << ost << "&);" + << endl + << "void" << endl + << n << "long_usage (" << ost << "&);" + << endl; + + ctx.ns_close (qn, false); + } } diff --git a/cli/makefile b/cli/makefile index 78e09b1..71ddd9c 100644 --- a/cli/makefile +++ b/cli/makefile @@ -65,8 +65,8 @@ genf := $(cli_tun:.cli=.hxx) $(cli_tun:.cli=.ixx) $(cli_tun:.cli=.cxx) gen := $(addprefix $(out_base)/,$(genf)) $(gen): cli := $(out_root)/cli/cli -$(gen): cli_options += --generate-file-scanner --guard-prefix CLI \ ---reserved-name stdout +$(gen): cli_options += --generate-file-scanner --generate-specifier \ +--guard-prefix CLI --reserved-name stdout $(call include-dep,$(cxx_od),$(cxx_obj),$(gen)) diff --git a/cli/options.cli b/cli/options.cli index 4972ba9..437f848 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -131,6 +131,30 @@ class options even if the short version is provided." }; + std::string --page-usage + { + "", + "Generate the combined usage printing code for the entire page. + Specifically, this will include all the namespace-level documentation as + well as usage for all the options classes printed in the order they are + defined in the main translation unit (documentation/classes from included + units are ignored except for base classes). + + The argument is used as a prefix to form the name of the usage + printing function. It can include the namespace qualification as well + as documentation variable expansion, for example: + + \ + --page-usage print_ # print_usage() in global namespace + --page-usage app::print_ # print_usage() in app namespace + --page-usage print_$name$_ # print_foo_usage() if name is foo + \ + + If both \cb{--long-usage} and \cb{--short-usage} options are specified, + then two functions are generated with the \cb{*short_usage()} and + \cb{*long_usage()} suffixes." + }; + std::size_t --option-length = 0 { "", diff --git a/cli/options.cxx b/cli/options.cxx index d6b0e84..0ac1b4c 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -416,7 +416,7 @@ namespace cli struct parser { static void - parse (X& x, scanner& s) + parse (X& x, bool& xs, scanner& s) { std::string o (s.next ()); @@ -429,6 +429,8 @@ namespace cli } else throw missing_value (o); + + xs = true; } }; @@ -447,7 +449,7 @@ namespace cli struct parser { static void - parse (std::string& x, scanner& s) + parse (std::string& x, bool& xs, scanner& s) { const char* o (s.next ()); @@ -455,6 +457,8 @@ namespace cli x = s.next (); else throw missing_value (o); + + xs = true; } }; @@ -462,11 +466,13 @@ namespace cli struct parser > { static void - parse (std::vector& c, scanner& s) + parse (std::vector& c, bool& xs, scanner& s) { X x; - parser::parse (x, s); + bool dummy; + parser::parse (x, dummy, s); c.push_back (x); + xs = true; } }; @@ -474,11 +480,13 @@ namespace cli struct parser > { static void - parse (std::set& c, scanner& s) + parse (std::set& c, bool& xs, scanner& s) { X x; - parser::parse (x, s); + bool dummy; + parser::parse (x, dummy, s); c.insert (x); + xs = true; } }; @@ -486,7 +494,7 @@ namespace cli struct parser > { static void - parse (std::map& m, scanner& s) + parse (std::map& m, bool& xs, scanner& s) { const char* o (s.next ()); @@ -506,24 +514,27 @@ namespace cli const_cast (o), 0 }; + bool dummy; if (!kstr.empty ()) { av[1] = const_cast (kstr.c_str ()); argv_scanner s (0, ac, av); - parser::parse (k, s); + parser::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast (vstr.c_str ()); argv_scanner s (0, ac, av); - parser::parse (v, s); + parser::parse (v, dummy, s); } m[k] = v; } else throw missing_value (o); + + xs = true; } }; @@ -533,6 +544,13 @@ namespace cli { parser::parse (x.*M, s); } + + template + void + thunk (X& x, scanner& s) + { + parser::parse (x.*M, x.*S, s); + } } #include @@ -546,7 +564,9 @@ options () : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -554,7 +574,9 @@ options () generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -563,43 +585,79 @@ options () suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { } @@ -612,7 +670,9 @@ options (int& argc, : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -620,7 +680,9 @@ options (int& argc, generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -629,43 +691,79 @@ options (int& argc, suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { ::cli::argv_scanner s (argc, argv, erase); _parse (s, opt, arg); @@ -681,7 +779,9 @@ options (int start, : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -689,7 +789,9 @@ options (int start, generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -698,43 +800,79 @@ options (int start, suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { ::cli::argv_scanner s (start, argc, argv, erase); _parse (s, opt, arg); @@ -750,7 +888,9 @@ options (int& argc, : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -758,7 +898,9 @@ options (int& argc, generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -767,43 +909,79 @@ options (int& argc, suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { ::cli::argv_scanner s (argc, argv, erase); _parse (s, opt, arg); @@ -821,7 +999,9 @@ options (int start, : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -829,7 +1009,9 @@ options (int start, generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -838,43 +1020,79 @@ options (int start, suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { ::cli::argv_scanner s (start, argc, argv, erase); _parse (s, opt, arg); @@ -888,7 +1106,9 @@ options (::cli::scanner& s, : help_ (), version_ (), include_path_ (), + include_path_specified_ (false), output_dir_ (), + output_dir_specified_ (false), generate_modifier_ (), generate_specifier_ (), generate_parse_ (), @@ -896,7 +1116,9 @@ options (::cli::scanner& s, generate_file_scanner_ (), suppress_inline_ (), cli_namespace_ ("::cli"), + cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), + ostream_type_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), @@ -905,43 +1127,79 @@ options (::cli::scanner& s, suppress_usage_ (), long_usage_ (), short_usage_ (), + page_usage_ (), + page_usage_specified_ (false), option_length_ (0), + option_length_specified_ (false), ansi_color_ (), exclude_base_ (), class__ (), + class__specified_ (false), docvar_ (), + docvar_specified_ (false), hxx_prologue_ (), + hxx_prologue_specified_ (false), ixx_prologue_ (), + ixx_prologue_specified_ (false), cxx_prologue_ (), + cxx_prologue_specified_ (false), man_prologue_ (), + man_prologue_specified_ (false), html_prologue_ (), + html_prologue_specified_ (false), hxx_epilogue_ (), + hxx_epilogue_specified_ (false), ixx_epilogue_ (), + ixx_epilogue_specified_ (false), cxx_epilogue_ (), + cxx_epilogue_specified_ (false), man_epilogue_ (), + man_epilogue_specified_ (false), html_epilogue_ (), + html_epilogue_specified_ (false), hxx_prologue_file_ (), + hxx_prologue_file_specified_ (false), ixx_prologue_file_ (), + ixx_prologue_file_specified_ (false), cxx_prologue_file_ (), + cxx_prologue_file_specified_ (false), man_prologue_file_ (), + man_prologue_file_specified_ (false), html_prologue_file_ (), + html_prologue_file_specified_ (false), hxx_epilogue_file_ (), + hxx_epilogue_file_specified_ (false), ixx_epilogue_file_ (), + ixx_epilogue_file_specified_ (false), cxx_epilogue_file_ (), + cxx_epilogue_file_specified_ (false), man_epilogue_file_ (), + man_epilogue_file_specified_ (false), html_epilogue_file_ (), + html_epilogue_file_specified_ (false), hxx_suffix_ (".hxx"), + hxx_suffix_specified_ (false), ixx_suffix_ (".ixx"), + ixx_suffix_specified_ (false), cxx_suffix_ (".cxx"), + cxx_suffix_specified_ (false), man_suffix_ (".1"), + man_suffix_specified_ (false), html_suffix_ (".html"), + html_suffix_specified_ (false), option_prefix_ ("-"), + option_prefix_specified_ (false), option_separator_ ("--"), + option_separator_specified_ (false), include_with_brackets_ (), include_prefix_ (), + include_prefix_specified_ (false), guard_prefix_ (), + guard_prefix_specified_ (false), reserved_name_ (), - options_file_ () + reserved_name_specified_ (false), + options_file_ (), + options_file_specified_ (false) { _parse (s, opt, arg); } @@ -1002,6 +1260,9 @@ print_usage (::std::ostream& os) os << "--short-usage If specified together with '--long-usage'," << ::std::endl << " generate both short and long usage versions." << ::std::endl; + os << "--page-usage Generate the combined usage printing code for the" << ::std::endl + << " entire page." << ::std::endl; + os << "--option-length Indent option descriptions characters when" << ::std::endl << " printing usage." << ::std::endl; @@ -1131,13 +1392,17 @@ struct _cli_options_map_init _cli_options_map_["--version"] = &::cli::thunk< options, bool, &options::version_ >; _cli_options_map_["--include-path"] = - &::cli::thunk< options, std::vector, &options::include_path_ >; + &::cli::thunk< options, std::vector, &options::include_path_, + &options::include_path_specified_ >; _cli_options_map_["-I"] = - &::cli::thunk< options, std::vector, &options::include_path_ >; + &::cli::thunk< options, std::vector, &options::include_path_, + &options::include_path_specified_ >; _cli_options_map_["--output-dir"] = - &::cli::thunk< options, std::string, &options::output_dir_ >; + &::cli::thunk< options, std::string, &options::output_dir_, + &options::output_dir_specified_ >; _cli_options_map_["-o"] = - &::cli::thunk< options, std::string, &options::output_dir_ >; + &::cli::thunk< options, std::string, &options::output_dir_, + &options::output_dir_specified_ >; _cli_options_map_["--generate-modifier"] = &::cli::thunk< options, bool, &options::generate_modifier_ >; _cli_options_map_["--generate-specifier"] = @@ -1151,9 +1416,11 @@ struct _cli_options_map_init _cli_options_map_["--suppress-inline"] = &::cli::thunk< options, bool, &options::suppress_inline_ >; _cli_options_map_["--cli-namespace"] = - &::cli::thunk< options, std::string, &options::cli_namespace_ >; + &::cli::thunk< options, std::string, &options::cli_namespace_, + &options::cli_namespace_specified_ >; _cli_options_map_["--ostream-type"] = - &::cli::thunk< options, std::string, &options::ostream_type_ >; + &::cli::thunk< options, std::string, &options::ostream_type_, + &options::ostream_type_specified_ >; _cli_options_map_["--generate-cxx"] = &::cli::thunk< options, bool, &options::generate_cxx_ >; _cli_options_map_["--generate-man"] = @@ -1170,82 +1437,120 @@ struct _cli_options_map_init &::cli::thunk< options, bool, &options::long_usage_ >; _cli_options_map_["--short-usage"] = &::cli::thunk< options, bool, &options::short_usage_ >; + _cli_options_map_["--page-usage"] = + &::cli::thunk< options, std::string, &options::page_usage_, + &options::page_usage_specified_ >; _cli_options_map_["--option-length"] = - &::cli::thunk< options, std::size_t, &options::option_length_ >; + &::cli::thunk< options, std::size_t, &options::option_length_, + &options::option_length_specified_ >; _cli_options_map_["--ansi-color"] = &::cli::thunk< options, bool, &options::ansi_color_ >; _cli_options_map_["--exclude-base"] = &::cli::thunk< options, bool, &options::exclude_base_ >; _cli_options_map_["--class"] = - &::cli::thunk< options, std::vector, &options::class__ >; + &::cli::thunk< options, std::vector, &options::class__, + &options::class__specified_ >; _cli_options_map_["--docvar"] = - &::cli::thunk< options, std::map, &options::docvar_ >; + &::cli::thunk< options, std::map, &options::docvar_, + &options::docvar_specified_ >; _cli_options_map_["-v"] = - &::cli::thunk< options, std::map, &options::docvar_ >; + &::cli::thunk< options, std::map, &options::docvar_, + &options::docvar_specified_ >; _cli_options_map_["--hxx-prologue"] = - &::cli::thunk< options, std::vector, &options::hxx_prologue_ >; + &::cli::thunk< options, std::vector, &options::hxx_prologue_, + &options::hxx_prologue_specified_ >; _cli_options_map_["--ixx-prologue"] = - &::cli::thunk< options, std::vector, &options::ixx_prologue_ >; + &::cli::thunk< options, std::vector, &options::ixx_prologue_, + &options::ixx_prologue_specified_ >; _cli_options_map_["--cxx-prologue"] = - &::cli::thunk< options, std::vector, &options::cxx_prologue_ >; + &::cli::thunk< options, std::vector, &options::cxx_prologue_, + &options::cxx_prologue_specified_ >; _cli_options_map_["--man-prologue"] = - &::cli::thunk< options, std::vector, &options::man_prologue_ >; + &::cli::thunk< options, std::vector, &options::man_prologue_, + &options::man_prologue_specified_ >; _cli_options_map_["--html-prologue"] = - &::cli::thunk< options, std::vector, &options::html_prologue_ >; + &::cli::thunk< options, std::vector, &options::html_prologue_, + &options::html_prologue_specified_ >; _cli_options_map_["--hxx-epilogue"] = - &::cli::thunk< options, std::vector, &options::hxx_epilogue_ >; + &::cli::thunk< options, std::vector, &options::hxx_epilogue_, + &options::hxx_epilogue_specified_ >; _cli_options_map_["--ixx-epilogue"] = - &::cli::thunk< options, std::vector, &options::ixx_epilogue_ >; + &::cli::thunk< options, std::vector, &options::ixx_epilogue_, + &options::ixx_epilogue_specified_ >; _cli_options_map_["--cxx-epilogue"] = - &::cli::thunk< options, std::vector, &options::cxx_epilogue_ >; + &::cli::thunk< options, std::vector, &options::cxx_epilogue_, + &options::cxx_epilogue_specified_ >; _cli_options_map_["--man-epilogue"] = - &::cli::thunk< options, std::vector, &options::man_epilogue_ >; + &::cli::thunk< options, std::vector, &options::man_epilogue_, + &options::man_epilogue_specified_ >; _cli_options_map_["--html-epilogue"] = - &::cli::thunk< options, std::vector, &options::html_epilogue_ >; + &::cli::thunk< options, std::vector, &options::html_epilogue_, + &options::html_epilogue_specified_ >; _cli_options_map_["--hxx-prologue-file"] = - &::cli::thunk< options, std::string, &options::hxx_prologue_file_ >; + &::cli::thunk< options, std::string, &options::hxx_prologue_file_, + &options::hxx_prologue_file_specified_ >; _cli_options_map_["--ixx-prologue-file"] = - &::cli::thunk< options, std::string, &options::ixx_prologue_file_ >; + &::cli::thunk< options, std::string, &options::ixx_prologue_file_, + &options::ixx_prologue_file_specified_ >; _cli_options_map_["--cxx-prologue-file"] = - &::cli::thunk< options, std::string, &options::cxx_prologue_file_ >; + &::cli::thunk< options, std::string, &options::cxx_prologue_file_, + &options::cxx_prologue_file_specified_ >; _cli_options_map_["--man-prologue-file"] = - &::cli::thunk< options, std::string, &options::man_prologue_file_ >; + &::cli::thunk< options, std::string, &options::man_prologue_file_, + &options::man_prologue_file_specified_ >; _cli_options_map_["--html-prologue-file"] = - &::cli::thunk< options, std::string, &options::html_prologue_file_ >; + &::cli::thunk< options, std::string, &options::html_prologue_file_, + &options::html_prologue_file_specified_ >; _cli_options_map_["--hxx-epilogue-file"] = - &::cli::thunk< options, std::string, &options::hxx_epilogue_file_ >; + &::cli::thunk< options, std::string, &options::hxx_epilogue_file_, + &options::hxx_epilogue_file_specified_ >; _cli_options_map_["--ixx-epilogue-file"] = - &::cli::thunk< options, std::string, &options::ixx_epilogue_file_ >; + &::cli::thunk< options, std::string, &options::ixx_epilogue_file_, + &options::ixx_epilogue_file_specified_ >; _cli_options_map_["--cxx-epilogue-file"] = - &::cli::thunk< options, std::string, &options::cxx_epilogue_file_ >; + &::cli::thunk< options, std::string, &options::cxx_epilogue_file_, + &options::cxx_epilogue_file_specified_ >; _cli_options_map_["--man-epilogue-file"] = - &::cli::thunk< options, std::string, &options::man_epilogue_file_ >; + &::cli::thunk< options, std::string, &options::man_epilogue_file_, + &options::man_epilogue_file_specified_ >; _cli_options_map_["--html-epilogue-file"] = - &::cli::thunk< options, std::string, &options::html_epilogue_file_ >; + &::cli::thunk< options, std::string, &options::html_epilogue_file_, + &options::html_epilogue_file_specified_ >; _cli_options_map_["--hxx-suffix"] = - &::cli::thunk< options, std::string, &options::hxx_suffix_ >; + &::cli::thunk< options, std::string, &options::hxx_suffix_, + &options::hxx_suffix_specified_ >; _cli_options_map_["--ixx-suffix"] = - &::cli::thunk< options, std::string, &options::ixx_suffix_ >; + &::cli::thunk< options, std::string, &options::ixx_suffix_, + &options::ixx_suffix_specified_ >; _cli_options_map_["--cxx-suffix"] = - &::cli::thunk< options, std::string, &options::cxx_suffix_ >; + &::cli::thunk< options, std::string, &options::cxx_suffix_, + &options::cxx_suffix_specified_ >; _cli_options_map_["--man-suffix"] = - &::cli::thunk< options, std::string, &options::man_suffix_ >; + &::cli::thunk< options, std::string, &options::man_suffix_, + &options::man_suffix_specified_ >; _cli_options_map_["--html-suffix"] = - &::cli::thunk< options, std::string, &options::html_suffix_ >; + &::cli::thunk< options, std::string, &options::html_suffix_, + &options::html_suffix_specified_ >; _cli_options_map_["--option-prefix"] = - &::cli::thunk< options, std::string, &options::option_prefix_ >; + &::cli::thunk< options, std::string, &options::option_prefix_, + &options::option_prefix_specified_ >; _cli_options_map_["--option-separator"] = - &::cli::thunk< options, std::string, &options::option_separator_ >; + &::cli::thunk< options, std::string, &options::option_separator_, + &options::option_separator_specified_ >; _cli_options_map_["--include-with-brackets"] = &::cli::thunk< options, bool, &options::include_with_brackets_ >; _cli_options_map_["--include-prefix"] = - &::cli::thunk< options, std::string, &options::include_prefix_ >; + &::cli::thunk< options, std::string, &options::include_prefix_, + &options::include_prefix_specified_ >; _cli_options_map_["--guard-prefix"] = - &::cli::thunk< options, std::string, &options::guard_prefix_ >; + &::cli::thunk< options, std::string, &options::guard_prefix_, + &options::guard_prefix_specified_ >; _cli_options_map_["--reserved-name"] = - &::cli::thunk< options, std::map, &options::reserved_name_ >; + &::cli::thunk< options, std::map, &options::reserved_name_, + &options::reserved_name_specified_ >; _cli_options_map_["--options-file"] = - &::cli::thunk< options, std::string, &options::options_file_ >; + &::cli::thunk< options, std::string, &options::options_file_, + &options::options_file_specified_ >; } }; diff --git a/cli/options.hxx b/cli/options.hxx index 933a41a..020ff40 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -371,9 +371,15 @@ class options const std::vector& include_path () const; + bool + include_path_specified () const; + const std::string& output_dir () const; + bool + output_dir_specified () const; + const bool& generate_modifier () const; @@ -395,9 +401,15 @@ class options const std::string& cli_namespace () const; + bool + cli_namespace_specified () const; + const std::string& ostream_type () const; + bool + ostream_type_specified () const; + const bool& generate_cxx () const; @@ -422,9 +434,18 @@ class options const bool& short_usage () const; + const std::string& + page_usage () const; + + bool + page_usage_specified () const; + const std::size_t& option_length () const; + bool + option_length_specified () const; + const bool& ansi_color () const; @@ -434,105 +455,204 @@ class options const std::vector& class_ () const; + bool + class__specified () const; + const std::map& docvar () const; + bool + docvar_specified () const; + const std::vector& hxx_prologue () const; + bool + hxx_prologue_specified () const; + const std::vector& ixx_prologue () const; + bool + ixx_prologue_specified () const; + const std::vector& cxx_prologue () const; + bool + cxx_prologue_specified () const; + const std::vector& man_prologue () const; + bool + man_prologue_specified () const; + const std::vector& html_prologue () const; + bool + html_prologue_specified () const; + const std::vector& hxx_epilogue () const; + bool + hxx_epilogue_specified () const; + const std::vector& ixx_epilogue () const; + bool + ixx_epilogue_specified () const; + const std::vector& cxx_epilogue () const; + bool + cxx_epilogue_specified () const; + const std::vector& man_epilogue () const; + bool + man_epilogue_specified () const; + const std::vector& html_epilogue () const; + bool + html_epilogue_specified () const; + const std::string& hxx_prologue_file () const; + bool + hxx_prologue_file_specified () const; + const std::string& ixx_prologue_file () const; + bool + ixx_prologue_file_specified () const; + const std::string& cxx_prologue_file () const; + bool + cxx_prologue_file_specified () const; + const std::string& man_prologue_file () const; + bool + man_prologue_file_specified () const; + const std::string& html_prologue_file () const; + bool + html_prologue_file_specified () const; + const std::string& hxx_epilogue_file () const; + bool + hxx_epilogue_file_specified () const; + const std::string& ixx_epilogue_file () const; + bool + ixx_epilogue_file_specified () const; + const std::string& cxx_epilogue_file () const; + bool + cxx_epilogue_file_specified () const; + const std::string& man_epilogue_file () const; + bool + man_epilogue_file_specified () const; + const std::string& html_epilogue_file () const; + bool + html_epilogue_file_specified () const; + const std::string& hxx_suffix () const; + bool + hxx_suffix_specified () const; + const std::string& ixx_suffix () const; + bool + ixx_suffix_specified () const; + const std::string& cxx_suffix () const; + bool + cxx_suffix_specified () const; + const std::string& man_suffix () const; + bool + man_suffix_specified () const; + const std::string& html_suffix () const; + bool + html_suffix_specified () const; + const std::string& option_prefix () const; + bool + option_prefix_specified () const; + const std::string& option_separator () const; + bool + option_separator_specified () const; + const bool& include_with_brackets () const; const std::string& include_prefix () const; + bool + include_prefix_specified () const; + const std::string& guard_prefix () const; + bool + guard_prefix_specified () const; + const std::map& reserved_name () const; + bool + reserved_name_specified () const; + const std::string& options_file () const; + bool + options_file_specified () const; + // Print usage information. // static void @@ -554,7 +674,9 @@ class options bool help_; bool version_; std::vector include_path_; + bool include_path_specified_; std::string output_dir_; + bool output_dir_specified_; bool generate_modifier_; bool generate_specifier_; bool generate_parse_; @@ -562,7 +684,9 @@ class options bool generate_file_scanner_; bool suppress_inline_; std::string cli_namespace_; + bool cli_namespace_specified_; std::string ostream_type_; + bool ostream_type_specified_; bool generate_cxx_; bool generate_man_; bool generate_html_; @@ -571,43 +695,79 @@ class options bool suppress_usage_; bool long_usage_; bool short_usage_; + std::string page_usage_; + bool page_usage_specified_; std::size_t option_length_; + bool option_length_specified_; bool ansi_color_; bool exclude_base_; std::vector class__; + bool class__specified_; std::map docvar_; + bool docvar_specified_; std::vector hxx_prologue_; + bool hxx_prologue_specified_; std::vector ixx_prologue_; + bool ixx_prologue_specified_; std::vector cxx_prologue_; + bool cxx_prologue_specified_; std::vector man_prologue_; + bool man_prologue_specified_; std::vector html_prologue_; + bool html_prologue_specified_; std::vector hxx_epilogue_; + bool hxx_epilogue_specified_; std::vector ixx_epilogue_; + bool ixx_epilogue_specified_; std::vector cxx_epilogue_; + bool cxx_epilogue_specified_; std::vector man_epilogue_; + bool man_epilogue_specified_; std::vector html_epilogue_; + bool html_epilogue_specified_; std::string hxx_prologue_file_; + bool hxx_prologue_file_specified_; std::string ixx_prologue_file_; + bool ixx_prologue_file_specified_; std::string cxx_prologue_file_; + bool cxx_prologue_file_specified_; std::string man_prologue_file_; + bool man_prologue_file_specified_; std::string html_prologue_file_; + bool html_prologue_file_specified_; std::string hxx_epilogue_file_; + bool hxx_epilogue_file_specified_; std::string ixx_epilogue_file_; + bool ixx_epilogue_file_specified_; std::string cxx_epilogue_file_; + bool cxx_epilogue_file_specified_; std::string man_epilogue_file_; + bool man_epilogue_file_specified_; std::string html_epilogue_file_; + bool html_epilogue_file_specified_; std::string hxx_suffix_; + bool hxx_suffix_specified_; std::string ixx_suffix_; + bool ixx_suffix_specified_; std::string cxx_suffix_; + bool cxx_suffix_specified_; std::string man_suffix_; + bool man_suffix_specified_; std::string html_suffix_; + bool html_suffix_specified_; std::string option_prefix_; + bool option_prefix_specified_; std::string option_separator_; + bool option_separator_specified_; bool include_with_brackets_; std::string include_prefix_; + bool include_prefix_specified_; std::string guard_prefix_; + bool guard_prefix_specified_; std::map reserved_name_; + bool reserved_name_specified_; std::string options_file_; + bool options_file_specified_; }; #include "options.ixx" diff --git a/cli/options.ixx b/cli/options.ixx index c4a3220..447fe18 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -221,12 +221,24 @@ include_path () const return this->include_path_; } +inline bool options:: +include_path_specified () const +{ + return this->include_path_specified_; +} + inline const std::string& options:: output_dir () const { return this->output_dir_; } +inline bool options:: +output_dir_specified () const +{ + return this->output_dir_specified_; +} + inline const bool& options:: generate_modifier () const { @@ -269,12 +281,24 @@ cli_namespace () const return this->cli_namespace_; } +inline bool options:: +cli_namespace_specified () const +{ + return this->cli_namespace_specified_; +} + inline const std::string& options:: ostream_type () const { return this->ostream_type_; } +inline bool options:: +ostream_type_specified () const +{ + return this->ostream_type_specified_; +} + inline const bool& options:: generate_cxx () const { @@ -323,12 +347,30 @@ short_usage () const return this->short_usage_; } +inline const std::string& options:: +page_usage () const +{ + return this->page_usage_; +} + +inline bool options:: +page_usage_specified () const +{ + return this->page_usage_specified_; +} + inline const std::size_t& options:: option_length () const { return this->option_length_; } +inline bool options:: +option_length_specified () const +{ + return this->option_length_specified_; +} + inline const bool& options:: ansi_color () const { @@ -347,174 +389,348 @@ class_ () const return this->class__; } +inline bool options:: +class__specified () const +{ + return this->class__specified_; +} + inline const std::map& options:: docvar () const { return this->docvar_; } +inline bool options:: +docvar_specified () const +{ + return this->docvar_specified_; +} + inline const std::vector& options:: hxx_prologue () const { return this->hxx_prologue_; } +inline bool options:: +hxx_prologue_specified () const +{ + return this->hxx_prologue_specified_; +} + inline const std::vector& options:: ixx_prologue () const { return this->ixx_prologue_; } +inline bool options:: +ixx_prologue_specified () const +{ + return this->ixx_prologue_specified_; +} + inline const std::vector& options:: cxx_prologue () const { return this->cxx_prologue_; } +inline bool options:: +cxx_prologue_specified () const +{ + return this->cxx_prologue_specified_; +} + inline const std::vector& options:: man_prologue () const { return this->man_prologue_; } +inline bool options:: +man_prologue_specified () const +{ + return this->man_prologue_specified_; +} + inline const std::vector& options:: html_prologue () const { return this->html_prologue_; } +inline bool options:: +html_prologue_specified () const +{ + return this->html_prologue_specified_; +} + inline const std::vector& options:: hxx_epilogue () const { return this->hxx_epilogue_; } +inline bool options:: +hxx_epilogue_specified () const +{ + return this->hxx_epilogue_specified_; +} + inline const std::vector& options:: ixx_epilogue () const { return this->ixx_epilogue_; } +inline bool options:: +ixx_epilogue_specified () const +{ + return this->ixx_epilogue_specified_; +} + inline const std::vector& options:: cxx_epilogue () const { return this->cxx_epilogue_; } +inline bool options:: +cxx_epilogue_specified () const +{ + return this->cxx_epilogue_specified_; +} + inline const std::vector& options:: man_epilogue () const { return this->man_epilogue_; } +inline bool options:: +man_epilogue_specified () const +{ + return this->man_epilogue_specified_; +} + inline const std::vector& options:: html_epilogue () const { return this->html_epilogue_; } +inline bool options:: +html_epilogue_specified () const +{ + return this->html_epilogue_specified_; +} + inline const std::string& options:: hxx_prologue_file () const { return this->hxx_prologue_file_; } +inline bool options:: +hxx_prologue_file_specified () const +{ + return this->hxx_prologue_file_specified_; +} + inline const std::string& options:: ixx_prologue_file () const { return this->ixx_prologue_file_; } +inline bool options:: +ixx_prologue_file_specified () const +{ + return this->ixx_prologue_file_specified_; +} + inline const std::string& options:: cxx_prologue_file () const { return this->cxx_prologue_file_; } +inline bool options:: +cxx_prologue_file_specified () const +{ + return this->cxx_prologue_file_specified_; +} + inline const std::string& options:: man_prologue_file () const { return this->man_prologue_file_; } +inline bool options:: +man_prologue_file_specified () const +{ + return this->man_prologue_file_specified_; +} + inline const std::string& options:: html_prologue_file () const { return this->html_prologue_file_; } +inline bool options:: +html_prologue_file_specified () const +{ + return this->html_prologue_file_specified_; +} + inline const std::string& options:: hxx_epilogue_file () const { return this->hxx_epilogue_file_; } +inline bool options:: +hxx_epilogue_file_specified () const +{ + return this->hxx_epilogue_file_specified_; +} + inline const std::string& options:: ixx_epilogue_file () const { return this->ixx_epilogue_file_; } +inline bool options:: +ixx_epilogue_file_specified () const +{ + return this->ixx_epilogue_file_specified_; +} + inline const std::string& options:: cxx_epilogue_file () const { return this->cxx_epilogue_file_; } +inline bool options:: +cxx_epilogue_file_specified () const +{ + return this->cxx_epilogue_file_specified_; +} + inline const std::string& options:: man_epilogue_file () const { return this->man_epilogue_file_; } +inline bool options:: +man_epilogue_file_specified () const +{ + return this->man_epilogue_file_specified_; +} + inline const std::string& options:: html_epilogue_file () const { return this->html_epilogue_file_; } +inline bool options:: +html_epilogue_file_specified () const +{ + return this->html_epilogue_file_specified_; +} + inline const std::string& options:: hxx_suffix () const { return this->hxx_suffix_; } +inline bool options:: +hxx_suffix_specified () const +{ + return this->hxx_suffix_specified_; +} + inline const std::string& options:: ixx_suffix () const { return this->ixx_suffix_; } +inline bool options:: +ixx_suffix_specified () const +{ + return this->ixx_suffix_specified_; +} + inline const std::string& options:: cxx_suffix () const { return this->cxx_suffix_; } +inline bool options:: +cxx_suffix_specified () const +{ + return this->cxx_suffix_specified_; +} + inline const std::string& options:: man_suffix () const { return this->man_suffix_; } +inline bool options:: +man_suffix_specified () const +{ + return this->man_suffix_specified_; +} + inline const std::string& options:: html_suffix () const { return this->html_suffix_; } +inline bool options:: +html_suffix_specified () const +{ + return this->html_suffix_specified_; +} + inline const std::string& options:: option_prefix () const { return this->option_prefix_; } +inline bool options:: +option_prefix_specified () const +{ + return this->option_prefix_specified_; +} + inline const std::string& options:: option_separator () const { return this->option_separator_; } +inline bool options:: +option_separator_specified () const +{ + return this->option_separator_specified_; +} + inline const bool& options:: include_with_brackets () const { @@ -527,24 +743,48 @@ include_prefix () const return this->include_prefix_; } +inline bool options:: +include_prefix_specified () const +{ + return this->include_prefix_specified_; +} + inline const std::string& options:: guard_prefix () const { return this->guard_prefix_; } +inline bool options:: +guard_prefix_specified () const +{ + return this->guard_prefix_specified_; +} + inline const std::map& options:: reserved_name () const { return this->reserved_name_; } +inline bool options:: +reserved_name_specified () const +{ + return this->reserved_name_specified_; +} + inline const std::string& options:: options_file () const { return this->options_file_; } +inline bool options:: +options_file_specified () const +{ + return this->options_file_specified_; +} + // Begin epilogue. // // diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx index 21d3723..42f7063 100644 --- a/cli/runtime-header.cxx +++ b/cli/runtime-header.cxx @@ -25,7 +25,20 @@ generate_runtime_header (context& ctx) << "#include " << endl << endl; - ctx.cli_open (); + // VC++ and xlC don't like the (void)x expression if x is a reference + // to an incomplete type. On the other hand, GCC warns that (void*)&x + // doesn't have any effect. + // + os << "#ifndef CLI_POTENTIALLY_UNUSED" << endl + << "# if defined(_MSC_VER) || defined(__xlC__)" << endl + << "# define CLI_POTENTIALLY_UNUSED(x) (void*)&x" << endl + << "# else" << endl + << "# define CLI_POTENTIALLY_UNUSED(x) (void)x" << endl + << "# endif" << endl + << "#endif" << endl + << endl; + + ctx.ns_open (ctx.cli); // unknown_mode // @@ -396,5 +409,5 @@ generate_runtime_header (context& ctx) << "struct parser;" << endl; - ctx.cli_close (); + ctx.ns_close (ctx.cli); } diff --git a/cli/runtime-inline.cxx b/cli/runtime-inline.cxx index cb0e0e4..15efa8d 100644 --- a/cli/runtime-inline.cxx +++ b/cli/runtime-inline.cxx @@ -14,7 +14,7 @@ generate_runtime_inline (context& ctx) string const& inl (ctx.inl); string const& os_type (ctx.options.ostream_type ()); - ctx.cli_open (); + ctx.ns_open (ctx.cli); // unknown_mode // @@ -305,5 +305,5 @@ generate_runtime_inline (context& ctx) << "}"; } - ctx.cli_close (); + ctx.ns_close (ctx.cli); } diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx index be29a57..cb0cde0 100644 --- a/cli/runtime-source.cxx +++ b/cli/runtime-source.cxx @@ -25,7 +25,7 @@ generate_runtime_source (context& ctx, bool complete) os << endl; - ctx.cli_open (); + ctx.ns_open (ctx.cli); if (complete) { @@ -652,5 +652,5 @@ generate_runtime_source (context& ctx, bool complete) << "parser::parse (x.*M, x.*S, s);" << "}"; - ctx.cli_close (); + ctx.ns_close (ctx.cli); } diff --git a/cli/source.cxx b/cli/source.cxx index d58f46b..0258c84 100644 --- a/cli/source.cxx +++ b/cli/source.cxx @@ -201,12 +201,104 @@ namespace return r; } - struct option_length: traversal::option, context + static string + escape_str (string const& s) { - option_length (context& c, size_t& l, type*& o) - : context (c), length_ (l), option_ (o) + string r; + + for (size_t i (0), n (s.size ()); i < n; ++i) + { + switch (s[i]) + { + case '\\': + { + r += "\\\\"; + break; + } + case '"': + { + r += "\\\""; + break; + } + case '\033': + { + r += "\\033"; + break; + } + default: + { + r += s[i]; + break; + } + } + } + + return r; + } + + // This function assumes that the string opening part has already been + // written. The 'first' argument is the number of characters already + // written in the first line (e.g., an option name). + // + static void + wrap_lines (ostream& os, + const string& d, + size_t indent = 0, + size_t first = 0) + { + assert (!d.empty ()); + + string ind (indent, ' '); + os << string (indent - first, ' '); + + size_t b (0), e (0), i (0); + for (size_t n (d.size ()); i < n; ++i) + { + if (d[i] == ' ' || d[i] == '\n') + e = i; + + if (d[i] == '\n' || text_size (d, b, i - b) == 79 - indent) + { + if (b != 0) // Not a first line. + os << endl + << " << \"" << ind; + + string s (d, b, (e != b ? e : i) - b); + os << escape_str (s) << "\" << ::std::endl"; + + // Handle consecutive newlines (e.g., pre, paragraph separator). + // + if (d[i] == '\n') + { + for (; i + 1 < n && d[i + 1] == '\n'; e = ++i) + os << endl + << " << ::std::endl"; + } + + b = e = (e != b ? e : i) + 1; + } + } + + // Flush the last line. + // + if (b != i) { + if (b != 0) + os << endl + << " << \"" << ind; + + string s (d, b, i - b); + os << escape_str (s) << "\" << ::std::endl"; } + } + + struct option_length: traversal::option, context + { + option_length (context& c, size_t& l) + : context (c), length_ (l), option_ (0) {} + + option_length (context& c, size_t& l, type*& o) + : context (c), length_ (l), option_ (&o) {} virtual void traverse (type& o) @@ -218,8 +310,6 @@ namespace if (options.suppress_undocumented () && doc.empty ()) return; - bool color (options.ansi_color ()); - size_t l (0); names& n (o.named ()); @@ -239,7 +329,7 @@ namespace string s (doc.size () > 0 ? doc[0] : string ("")); - if (color) + if (options.ansi_color ()) { std::set arg_set; s = translate_arg (s, arg_set); @@ -251,13 +341,14 @@ namespace if (l > length_) { length_ = l; - option_ = &o; + if (option_ != 0) + *option_ = &o; } } private: size_t& length_; - type*& option_; + type** option_; }; // @@ -355,60 +446,7 @@ namespace d = format (ot_plain, d, false); if (!d.empty ()) - { - pad (length_ - l); - - size_t b (0), e (0), i (0); - - for (size_t n (d.size ()); i < n; ++i) - { - if (d[i] == ' ' || d[i] == '\n') - e = i; - - // Assume we have 78 characters instead of 79 per line to make sure - // we get the same output on Windows (which has two characters for - // a newline). - // - if (d[i] == '\n' || text_size (d, b, i - b) == 78 - length_) - { - if (b != 0) // Not a first line. - { - os << endl - << " << \""; - pad (); - } - - string s (d, b, (e != b ? e : i) - b); - os << escape_str (s) << "\" << ::std::endl"; - - // Handle consecutive newlines (e.g., pre, paragraph separator). - // - if (d[i] == '\n') - { - for (; i + 1 < n && d[i + 1] == '\n'; e = ++i) - os << endl - << " << ::std::endl"; - } - - b = e = (e != b ? e : i) + 1; - } - } - - // Flush the last line. - // - if (b != i) - { - if (b != 0) - { - os << endl - << " << \""; - pad (); - } - - string s (d, b, i - b); - os << escape_str (s) << "\" << ::std::endl"; - } - } + wrap_lines (os, d, length_ + 1, l); // +1 for extra space after arg. else os << "\" << std::endl"; @@ -417,21 +455,6 @@ namespace } private: - void - pad (size_t n) - { - for (; n > 0; --n) - os << ' '; - - os << ' '; // Space between arg and description. - } - - void - pad () - { - pad (length_); - } - string first_sentence (string const& s) { @@ -449,42 +472,6 @@ namespace return p == string::npos ? s : string (s, 0, p + 1); } - string - escape_str (string const& s) - { - string r; - r.reserve (s.size ()); - - for (size_t i (0), n (s.size ()); i < n; ++i) - { - switch (s[i]) - { - case '\\': - { - r += "\\\\"; - break; - } - case '"': - { - r += "\\\""; - break; - } - case '\033': - { - r += "\\033"; - break; - } - default: - { - r += s[i]; - break; - } - } - } - - return r; - } - private: size_t length_; usage_type usage_; @@ -1000,14 +987,127 @@ namespace option_desc option_desc_; traversal::names names_option_desc_; }; + + // Page usage. + // + enum paragraph {para_none, para_text, para_option}; + + struct doc: traversal::doc, context + { + doc (context& c, usage_type u, paragraph& p) + : context (c), usage_ (u), para_ (p) {} + + virtual void + traverse (type& ds) + { + if (ds.name ().compare (0, 3, "doc") != 0) // Ignore doc variables. + return; + + // Figure out which documentation string we should use. + // + // n = 1 - common doc string + // n = 2 - arg string, common doc string + // n > 2 - arg string, short string, long string + // + size_t n (ds.size ()); + string d; + + if (usage == ut_both && usage_ == ut_long) + { + d = n > 2 // Have both short and long? + ? ds[2] // Then use long. + : (n == 1 ? ds[0] : ds[1]); // Else, use common. + } + else // Short or long. + { + d = n > 2 // Have both short and long? + ? ds[1] // Then use short, + : (n == 1 ? ds[0] : ds[1]); // Else, use common (no first sentence). + } + + std::set arg_set; + if (n > 1 && options.ansi_color ()) + translate_arg (ds[0], arg_set); + + d = format (ot_plain, translate (d, arg_set), true); + + if (d.empty ()) + return; + + if (para_ == para_none) // First. + os << "os << \""; + else + os << "os << ::std::endl" << endl + << " << \""; + + wrap_lines (os, d); + os << ";" + << endl; + + para_ = para_text; + } + + private: + usage_type usage_; + paragraph& para_; + }; + + struct class_usage: traversal::class_, context + { + class_usage (context& c, usage_type u, paragraph& p) + : context (c), usage_ (u), para_ (p) {} + + virtual void + traverse (type& c) + { + // Figure out if this class has any documentation by calculating + // the option length. If it is 0, then we don't have any. + // + size_t len (0); + { + option_length olt (*this, len); + traversal::class_ ct; + traversal::inherits i; + traversal::names n; + + if (!options.exclude_base ()) // Go into bases unless --exclude-base. + ct >> i >> ct; + + ct >> n >> olt; + ct.traverse (c); + } + + if (len == 0) + return; + + if (para_ == para_text) + os << "os << ::std::endl;"; + + const char* t ( + usage != ut_both + ? "" + : usage_ == ut_short ? "short_" : "long_"); + + os << fq_name (c) << "::print_" << t << "usage (os);" + << endl; + + para_ = para_option; + } + + private: + usage_type usage_; + paragraph& para_; + }; } void generate_source (context& ctx) { - ctx.os << "#include " << endl - << "#include " << endl - << endl; + ostream& os (ctx.os); + + os << "#include " << endl + << "#include " << endl + << endl; traversal::cli_unit unit; traversal::names unit_names; @@ -1023,4 +1123,84 @@ generate_source (context& ctx) ns_names >> cl; unit.dispatch (ctx.unit); + + // Entire page usage. + // + if (ctx.usage != ut_none && ctx.options.page_usage_specified ()) + { + const string& qn (ctx.options.page_usage ()); + string n (ctx.escape (ctx.substitute (ctx.ns_open (qn, false)))); + + usage u (ctx.usage); + string const& ost (ctx.options.ostream_type ()); + + { + os << "void" << endl + << n << (u == ut_both ? "short_" : "") << "usage (" << ost << "& os)" + << "{" + << "CLI_POTENTIALLY_UNUSED (os);" + << endl; + + paragraph para (para_none); + + traversal::cli_unit unit; + traversal::names unit_names; + traversal::namespace_ ns; + doc dc (ctx, u == ut_both ? ut_short : u, para); + class_usage cl (ctx, u == ut_both ? ut_short : u, para); + + unit >> unit_names; + unit_names >> dc; + unit_names >> ns; + unit_names >> cl; + + traversal::names ns_names; + + ns >> ns_names; + ns_names >> dc; + ns_names >> ns; + ns_names >> cl; + + unit.dispatch (ctx.unit); + + os << "}"; + } + + // Long version. + // + if (u == ut_both) + { + os << "void" << endl + << n << "long_usage (" << ost << "& os)" + << "{" + << "CLI_POTENTIALLY_UNUSED (os);" + << endl; + + paragraph para (para_none); + + traversal::cli_unit unit; + traversal::names unit_names; + traversal::namespace_ ns; + doc dc (ctx, ut_long, para); + class_usage cl (ctx, ut_long, para); + + unit >> unit_names; + unit_names >> dc; + unit_names >> ns; + unit_names >> cl; + + traversal::names ns_names; + + ns >> ns_names; + ns_names >> dc; + ns_names >> ns; + ns_names >> cl; + + unit.dispatch (ctx.unit); + + os << "}"; + } + + ctx.ns_close (qn, false); + } } -- cgit v1.1