diff options
Diffstat (limited to 'cli/cli')
33 files changed, 1671 insertions, 479 deletions
diff --git a/cli/cli/.gitignore b/cli/cli/.gitignore index 903d015..614e56f 100644 --- a/cli/cli/.gitignore +++ b/cli/cli/.gitignore @@ -1,5 +1,7 @@ -cli -version.hxx +/cli +/pregenerated/cli/cli +/version.hxx +/options.?xx # Unit test executables and Testscript output directories (can be symlinks). # diff --git a/cli/cli/buildfile b/cli/cli/buildfile index 2385a7d..92c3e6e 100644 --- a/cli/cli/buildfile +++ b/cli/cli/buildfile @@ -15,63 +15,146 @@ exe{cli}: cli.checksum = $version } -libue{cli}: {hxx ixx txx cxx}{** -cli -version -options -**.test...} \ - {hxx}{version} {hxx ixx cxx}{options} \ - $libs +hdr = {hxx ixx txx}{* -cli -version -options -*.test...} +src = cxx{* -cli -version -options -*.test...} + +all_s = semantics/{hxx ixx txx cxx}{*} +all_t = traversal/{hxx ixx txx cxx}{*} + +libue{cli}: $hdr $src $all_s $all_t {hxx}{version} $libs hxx{version}: in{version} $src_root/manifest -# Unit tests. +# Build options (apply to both bootstrap and final version). # -exe{*.test}: +cxx.poptions =+ "-I$out_root" "-I$src_root" + +# CLI uses its own generated code to handle the command line. To solve the +# chicken and egg problem that this poses we keep pregenerated source code in +# pregenerated/. +# +# In the consumption build ($config.cli.develop == false), we just use this +# pregenerated source code to build the final version of the compiler. In the +# development build ($config.cli.develop == true) we use this pregenerated +# source code to build a bootstrap version of the compiler which we then use +# to regenerate the source code and build that final version from that. + +## Consumption build ($develop == false). +# + +# Use pregenerated versions to build the final version of cli. +# +libue{cli}: pregenerated/{hxx ixx cxx}{**}: include = (!$develop) + +if! $develop + cxx.poptions =+ "-I($src_base/pregenerated)" # Note: must come first. + +# Distribute pregenerated versions only in the consumption build. +# +pregenerated/{hxx ixx cxx}{*}: dist = (!$develop) + +# +## + +## Development build ($develop == true). +# +libue{cli}: {hxx ixx cxx}{options}: include = $develop + +# Bootstrap. +# +# The plan is as follows: +# +# 1. Build the bootstrap version of cli using a copy of options.?xx saved in +# pregenerated/cli/. +# +# 2. Use that to regenerate options.?xx. If the result differs from the saved +# version, copy it over and fail the build, asking for a restart. +# +# 3. Otherwise, proceed to build the final version of cli using regenerated +# options.?xx. +# +pregenerated/ { - test = true - install = false + # This should only apply to the bootstrap build. + # + cxx.poptions =+ "-I$src_base" # Note: must come first. + + cli/ + { + # Note: semantics/ and traversal/ do not include options.hxx so we can + # share their object files. + # + exe{cli}: obj{cli $name($src) options} ../../{$all_s $all_t} $libs + + for s: cli $name($src) + obj{$s}: ../../cxx{$s} $libs + + obj{options}: {hxx ixx cxx}{options} + + obj{cli}: cxx.poptions += -DCLI_BOOTSTRAP + } } -for t: cxx{**.test...} +# In the development build distribute regenerated {hxx ixx cxx}{options}, +# remapping their locations to the paths of the pregenerated versions (which +# are only distributed in the consumption build; see above). This way we make +# sure that the distributed files are always up-to-date. +# +<{hxx ixx cxx}{options}>: cli{options} pregenerated/cli/exe{cli} { - d = $directory($t) - n = $name($t)... + dist = ($develop ? pregenerated/cli/ : false) - ./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n} - $d/exe{$n}: libue{cli}: bin.whole = false + # Symlink the generated code in src for convenience of development. + # + backlink = true } +% +if $develop +{{ + options = --include-with-brackets --include-prefix cli \ + --guard-prefix CLI --generate-file-scanner \ + --generate-specifier --generate-modifier \ + --suppress-undocumented --reserved-name stdout + + diag cli ($<[0]) -> $> + ($<[1]) $options -o $out_base $path($<[0]) + + # If the result differs from the bootstrap version, copy it over and + # request the build restart. + # + if diff $src_base/pregenerated/cli/options.hxx $path($>[0]) >- && \ + diff $src_base/pregenerated/cli/options.ixx $path($>[1]) >- && \ + diff $src_base/pregenerated/cli/options.cxx $path($>[2]) >- + exit + end + + cp $path($>[0]) $src_base/pregenerated/cli/options.hxx + cp $path($>[1]) $src_base/pregenerated/cli/options.ixx + cp $path($>[2]) $src_base/pregenerated/cli/options.cxx + + exit "bootstrap options.?xx have changed, restart the build" +}} -# Build options. # +## + # Pass the copyright notice extracted from the LICENSE file. # -copyright = $process.run_regex(cat $src_root/LICENSE, \ - 'Copyright \(c\) (.+)\.', \ - '\1') - obj{cli}: cxx.poptions += -DCLI_COPYRIGHT=\"$copyright\" -# Generated options parsing code. -# -# @@ This will eventually be replaced with an ah hoc recipe. +# Unit tests. # -if ($config.cli != [null] && $config.cli != false) +exe{*.test}: { - cli.cxx{options}: cli{options} - - cli.options += --include-with-brackets --include-prefix cli \ ---guard-prefix CLI --generate-file-scanner --generate-specifier \ ---generate-modifier --suppress-undocumented --reserved-name stdout + test = true + install = false +} - cli.cxx{*}: - { - # Include the generated cli files into the distribution and don't remove - # them when cleaning in src (so that clean results in a state identical to - # distributed). - # - dist = true - clean = ($src_root != $out_root) +for t: cxx{**.test...} +{ + d = $directory($t) + n = $name($t)... - # We keep the generated code in the repository so copy it back to src - # in case of a forwarded configuration. - # - backlink = overwrite - } + ./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n} + $d/exe{$n}: libue{cli}: bin.whole = false } diff --git a/cli/cli/cli.cxx b/cli/cli/cli.cxx index 754c5ff..d56f9e2 100644 --- a/cli/cli/cli.cxx +++ b/cli/cli/cli.cxx @@ -6,9 +6,10 @@ #include <string> #include <memory> // unique_ptr #include <fstream> +#include <utility> // move() #include <iostream> -#include <cutl/compiler/code-stream.hxx> +#include <libcutl/compiler/code-stream.hxx> #include <cli/semantics/doc.hxx> @@ -16,7 +17,13 @@ #include <cli/parser.hxx> #include <cli/generator.hxx> -#include <cli/version.hxx> +#ifndef CLI_BOOTSTRAP +# include <cli/version.hxx> +#else +# define CLI_VERSION_ID 0 +# define CLI_VERSION_FULL 0 +# define CLI_COPYRIGHT "" +#endif using namespace std; using namespace cutl; @@ -115,8 +122,9 @@ main (int argc, char* argv[]) // Parse and generate. // - parser p (include_paths); - unique_ptr<semantics::cli_unit> unit (p.parse (ifs, path)); + parser p (include_paths, ops.generate_dep ()); + parser::parse_result r (p.parse (ifs, path)); + unique_ptr<semantics::cli_unit>& unit (r.unit); // Merge documentation variables from the command line. // @@ -137,7 +145,7 @@ main (int argc, char* argv[]) } generator g; - g.generate (ops, *unit, path); + g.generate (ops, move (*unit), move (r.dependencies), path); } catch (cli::exception const& ex) { diff --git a/cli/cli/context.cxx b/cli/cli/context.cxx index 54bb988..2c6a733 100644 --- a/cli/cli/context.cxx +++ b/cli/cli/context.cxx @@ -7,6 +7,7 @@ #include <cstring> // strncmp() #include <fstream> #include <sstream> +#include <utility> // move() #include <iostream> #include <cli/context.hxx> @@ -114,6 +115,8 @@ context (ostream& os_, opt_prefix (options.option_prefix ()), opt_sep (options.option_separator ()), cli (data_->cli_), + exp (data_->exp_), + exp_inl (data_->exp_inl_), reserved_name_map (options.reserved_name ()), keyword_set (data_->keyword_set_), link_regex (data_->link_regex_), @@ -141,6 +144,16 @@ context (ostream& os_, if (!cli.empty () && cli[0] != ':') data_->cli_ = "::" + data_->cli_; + data_->exp_ = options.export_symbol (); + + if (!exp.empty ()) + { + data_->exp_ += ' '; + + if (options.suppress_inline ()) + data_->exp_inl_ = data_->exp_; + } + for (size_t i (0); i < sizeof (keywords) / sizeof (char*); ++i) data_->keyword_set_.insert (keywords[i]); @@ -179,6 +192,8 @@ context (context& c) opt_prefix (c.opt_prefix), opt_sep (c.opt_sep), cli (c.cli), + exp (c.exp), + exp_inl (c.exp_inl), reserved_name_map (c.reserved_name_map), keyword_set (c.keyword_set), link_regex (c.link_regex), @@ -296,6 +311,59 @@ process_link_target (const string& tg) return found ? r : tg; } +void context:: +preprocess_ascii_tree (string& s) +{ + // tree --charset=UTF-8 uses the following box-drawing characters (see + // color.c): + // + // CHAR UTF-8 ASCII + //---------------------------- + // + // | E29482 | + // + // -- E29480 - + // + // |- E2949C | + // + // |_ E29494 ` + // + // <nbspace> C2A0 <space> + // + // Note that here we rely on the fact that neither E2 nor C2 can appear as + // continuation bytes. + // + for (size_t i (0); i != s.size (); ++i) + { + i = s.find_first_of ("\xE2\xC2", i); + + if (i == string::npos) + break; + + if (s[i] == '\xE2') + { + if (s[i + 1] == '\x94') + { + const char* r; + switch (s[i + 2]) + { + case '\x80': r = "-"; break; + case '\x82': + case '\x9c': r = "|"; break; + case '\x94': r = "`"; break; + default: continue; + } + + s.replace (i, 3, r); + } + } + else + { + if (s[i + 1] == '\xA0') + s.replace (i, 2, " "); + } + } +} string context:: translate_arg (string const& s, std::set<string>& set) @@ -1270,15 +1338,32 @@ format (semantics::scope& scope, string const& s, bool para) stack<block> blocks; blocks.push (block (block::text, para, "")); // Top-level. - // Number of li in ol. Since we don't support nested lists, we don't - // need to push it into the stack. + // Number of li in ol. Since we don't support nested lists (except in HTML + // where this is unused), we don't need to push it into the stack. // size_t ol_count (0); // Mapping of \h to HTML tag. By default it is <h1> until we encounter - // \h0 or \h1 at which point we change it to <h2>. + // \h0 or \h1 at which point we change it to <h2>. It can also be mapped + // with --html-heading-map. // - char html_h ('1'); + char html_h ('\0'); + + typedef map<char, string> html_hmap; + if (ot == ot_html) + { + const html_hmap& hm (options.html_heading_map ()); + html_hmap::const_iterator mi (hm.find ('h')); + + if (mi != hm.end ()) + { + // Note: this mapping back is necessary for TOC to function correctly + // with multiple string fragments. + // + if (mi->second == "h1") html_h = '1'; + else if (mi->second == "h2") html_h = '2'; + } + } bool last (false); for (size_t b (0), e; !last; b = e + 1) @@ -1532,7 +1617,10 @@ format (semantics::scope& scope, string const& s, bool para) case block::dl: good = (k == block::li); break; case block::li: good = (k == block::note || k == block::text || - k == block::pre ); break; + k == block::pre || + (ot == ot_html && (k == block::ul || + k == block::ol || + k == block::dl))); break; case block::note: good = (k == block::text || k == block::pre || (ot == ot_html && (k == block::ul || @@ -1644,7 +1732,7 @@ format (semantics::scope& scope, string const& s, bool para) { case block::h: blocks.push (block (k, false, id, header)); break; case block::ul: - case block::ol: ol_count = 0; // Fall through. + case block::ol: if (ot != ot_html) ol_count = 0; // Fall through. case block::dl: blocks.push (block (k, true, id)); break; case block::li: { @@ -1652,9 +1740,12 @@ format (semantics::scope& scope, string const& s, bool para) { case block::ol: { - ostringstream os; - os << ++ol_count; - header = os.str (); + if (ot != ot_html) + { + ostringstream os; + os << ++ol_count; + header = os.str (); + } break; } case block::dl: @@ -1919,7 +2010,7 @@ format (semantics::scope& scope, string const& s, bool para) case '1': break; // Always unwind. case 'h': { - pop = html_h == '1' || e.type == 'h' || e.type == '2'; + pop = html_h != '2' || e.type == 'h' || e.type == '2'; break; } case '2': pop = e.type == '2'; break; @@ -2016,9 +2107,10 @@ format (semantics::scope& scope, string const& s, bool para) // Same as in non-TOC mode below. // - // @@ This only works for a single string fragment. + // This only works automatically for a single string fragment. + // For multiple string fragments use --html-heading-map. // - if (t == '0' || t == '1') + if (html_h == '\0' && (t == '0' || t == '1')) html_h = '2'; break; @@ -2136,9 +2228,8 @@ format (semantics::scope& scope, string const& s, bool para) string h; string c; - typedef map<char, string> map; - const map& hm (options.html_heading_map ()); - map::const_iterator mi (hm.find (t)); + const html_hmap& hm (options.html_heading_map ()); + html_hmap::const_iterator mi (hm.find (t)); if (mi == hm.end ()) { @@ -2147,7 +2238,7 @@ format (semantics::scope& scope, string const& s, bool para) case '0': h = "h1"; c = "preface"; break; case 'H': h = "h1"; c = "part"; break; case '1': h = "h1"; break; - case 'h': h = html_h == '1' ? "h1" : "h2"; break; + case 'h': h = html_h != '2' ? "h1" : "h2"; break; case '2': h = "h3"; break; } } @@ -2173,9 +2264,10 @@ format (semantics::scope& scope, string const& s, bool para) v += "</" + h + '>'; - // @@ This only works for a single string fragment. + // This only works automatically for a single string fragment. + // For multiple string fragments use --html-heading-map. // - if (t == '0' || t == '1') + if (html_h == '\0' && (t == '0' || t == '1')) html_h = '2'; break; diff --git a/cli/cli/context.hxx b/cli/cli/context.hxx index 633b8ad..c5802ed 100644 --- a/cli/cli/context.hxx +++ b/cli/cli/context.hxx @@ -12,9 +12,9 @@ #include <ostream> #include <cstddef> // std::size_t -#include <cutl/re.hxx> -#include <cutl/shared-ptr.hxx> -#include <cutl/fs/path.hxx> +#include <libcutl/re.hxx> +#include <libcutl/shared-ptr.hxx> +#include <libcutl/fs/path.hxx> #include <cli/options.hxx> #include <cli/semantics.hxx> @@ -92,6 +92,8 @@ public: string const& opt_prefix; string const& opt_sep; string const& cli; + string const& exp; + string const& exp_inl; // Export symbol if inline is suppressed. typedef std::map<string, string> reserved_name_map_type; reserved_name_map_type const& reserved_name_map; @@ -135,6 +137,8 @@ private: { string inl_; string cli_; + string exp_; + string exp_inl_; keyword_set_type keyword_set_; regex_mapping link_regex_; id_set_type id_set_; @@ -153,10 +157,13 @@ public: string process_link_target (const string&); - // Translate and format the documentation string. Translate converts - // the <arg>-style constructs to \i{arg}. Format converts the string - // to the output format. + // Preprocess, translate, and format the documentation string. Translate + // converts the <arg>-style constructs to \i{arg}. Format converts the + // string to the output format. // + static void + preprocess_ascii_tree (string&); + static string translate_arg (string const&, std::set<string>&); diff --git a/cli/cli/generator.cxx b/cli/cli/generator.cxx index df1b99e..623ac67 100644 --- a/cli/cli/generator.cxx +++ b/cli/cli/generator.cxx @@ -2,15 +2,16 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cctype> // std::toupper, std::is{alpha,upper,lower} +#include <cctype> // toupper, is{alpha,upper,lower} #include <string> #include <fstream> +#include <utility> // move() #include <iostream> -#include <cutl/fs/auto-remove.hxx> +#include <libcutl/fs/auto-remove.hxx> -#include <cutl/compiler/code-stream.hxx> -#include <cutl/compiler/cxx-indenter.hxx> +#include <libcutl/compiler/code-stream.hxx> +#include <libcutl/compiler/cxx-indenter.hxx> #include <cli/header.hxx> #include <cli/inline.hxx> @@ -98,7 +99,10 @@ namespace } void - append (context& ctx, vector<string> const& text, string const& file) + append (context& ctx, + vector<string> const& text, + string const& file, + vector<path>* pdeps) { for (vector<string>::const_iterator i (text.begin ()); i != text.end (); ++i) @@ -111,7 +115,8 @@ namespace ifstream ifs; open (ifs, file); - path d (path (file).directory ()); + path p (file); + path d (p.directory ()); // getline() will set the failbit if it failed to extract anything, // not even the delimiter and eofbit if it reached eof before seeing @@ -119,6 +124,9 @@ namespace // for (string s; getline (ifs, s); ) append (ctx, s, &d); + + if (pdeps != nullptr) + pdeps->push_back (move (p.normalize ())); } } } @@ -129,7 +137,10 @@ generator () } void generator:: -generate (options& ops, semantics::cli_unit& unit, path const& p) +generate (options& ops, + semantics::cli_unit&& unit, + vector<path>&& deps, + path const& p) { if (ops.generate_group_scanner ()) ops.generate_vector_scanner (true); @@ -168,8 +179,48 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) } } + bool gen_dep (ops.generate_dep ()); + vector<path>* pdeps (gen_dep ? &deps : nullptr); + vector<path> depts; // Dependents. + fs::auto_removes auto_rm; + // gen_dep + // + // Make sure that we remove the potentially outdated dependency file if we + // fail to generate any source/documentation file. + // + // Note that we will write the dependency file content later, when all the + // dependents and dependencies are determined. + // + ofstream dep; + + if (gen_dep) + { + path dep_path; + + if (ops.dep_file ().empty ()) + { + dep_path = path (pfx + base + sfx + ops.dep_suffix ()); + + if (!ops.output_dir ().empty ()) + dep_path = path (ops.output_dir ()) / dep_path; + } + else + dep_path = path (ops.dep_file ()); + + dep.open (dep_path.string ().c_str (), ios_base::out); + + if (!dep.is_open ()) + { + cerr << "error: unable to open '" << dep_path << "' in write mode" + << endl; + throw failed (); + } + + auto_rm.add (dep_path); + } + // C++ output. // if (gen_cxx) @@ -235,6 +286,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) auto_rm.add (hxx_path); + if (gen_dep) + depts.push_back (move (hxx_path.normalize ())); + // // ofstream ixx; @@ -251,6 +305,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) } auto_rm.add (ixx_path); + + if (gen_dep) + depts.push_back (move (ixx_path.normalize ())); } // @@ -266,6 +323,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) auto_rm.add (cxx_path); + if (gen_dep) + depts.push_back (move (cxx_path.normalize ())); + // Print headers. // hxx << cxx_header; @@ -304,7 +364,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // hxx << "// Begin prologue." << endl << "//" << endl; - append (ctx, ops.hxx_prologue (), ops.hxx_prologue_file ()); + append (ctx, ops.hxx_prologue (), ops.hxx_prologue_file (), pdeps); hxx << "//" << endl << "// End prologue." << endl << endl; @@ -331,7 +391,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // hxx << "// Begin epilogue." << endl << "//" << endl; - append (ctx, ops.hxx_epilogue (), ops.hxx_epilogue_file ()); + append (ctx, ops.hxx_epilogue (), ops.hxx_epilogue_file (), pdeps); hxx << "//" << endl << "// End epilogue." << endl << endl; @@ -349,7 +409,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // ixx << "// Begin prologue." << endl << "//" << endl; - append (ctx, ops.ixx_prologue (), ops.ixx_prologue_file ()); + append (ctx, ops.ixx_prologue (), ops.ixx_prologue_file (), pdeps); ixx << "//" << endl << "// End prologue." << endl << endl; @@ -369,7 +429,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // ixx << "// Begin epilogue." << endl << "//" << endl; - append (ctx, ops.ixx_epilogue (), ops.ixx_epilogue_file ()); + append (ctx, ops.ixx_epilogue (), ops.ixx_epilogue_file (), pdeps); ixx << "//" << endl << "// End epilogue." << endl; } @@ -383,7 +443,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // cxx << "// Begin prologue." << endl << "//" << endl; - append (ctx, ops.cxx_prologue (), ops.cxx_prologue_file ()); + append (ctx, ops.cxx_prologue (), ops.cxx_prologue_file (), pdeps); cxx << "//" << endl << "// End prologue." << endl << endl; @@ -413,7 +473,7 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) // cxx << "// Begin epilogue." << endl << "//" << endl; - append (ctx, ops.cxx_epilogue (), ops.cxx_epilogue_file ()); + append (ctx, ops.cxx_epilogue (), ops.cxx_epilogue_file (), pdeps); cxx << "//" << endl << "// End epilogue." << endl << endl; @@ -443,6 +503,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) } auto_rm.add (man_path); + + if (gen_dep) + depts.push_back (move (man_path.normalize ())); } // The explicit cast helps VC++ 8.0 overcome its issues. @@ -452,9 +515,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) for (bool first (true); first || ctx.toc; first = false) { - append (ctx, ops.man_prologue (), ops.man_prologue_file ()); + append (ctx, ops.man_prologue (), ops.man_prologue_file (), pdeps); generate_man (ctx); - append (ctx, ops.man_epilogue (), ops.man_epilogue_file ()); + append (ctx, ops.man_epilogue (), ops.man_epilogue_file (), pdeps); if (ctx.toc) { @@ -492,6 +555,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) } auto_rm.add (html_path); + + if (gen_dep) + depts.push_back (move (html_path.normalize ())); } // The explicit cast helps VC++ 8.0 overcome its issues. @@ -501,9 +567,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) for (bool first (true); first || ctx.toc; first = false) { - append (ctx, ops.html_prologue (), ops.html_prologue_file ()); + append (ctx, ops.html_prologue (), ops.html_prologue_file (), pdeps); generate_html (ctx); - append (ctx, ops.html_epilogue (), ops.html_epilogue_file ()); + append (ctx, ops.html_epilogue (), ops.html_epilogue_file (), pdeps); if (ctx.toc) { @@ -538,6 +604,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) } auto_rm.add (txt_path); + + if (gen_dep) + depts.push_back (move (txt_path.normalize ())); } // The explicit cast helps VC++ 8.0 overcome its issues. @@ -547,9 +616,9 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) for (bool first (true); first || ctx.toc; first = false) { - append (ctx, ops.txt_prologue (), ops.txt_prologue_file ()); + append (ctx, ops.txt_prologue (), ops.txt_prologue_file (), pdeps); generate_txt (ctx); - append (ctx, ops.txt_epilogue (), ops.txt_epilogue_file ()); + append (ctx, ops.txt_epilogue (), ops.txt_epilogue_file (), pdeps); if (ctx.toc) { @@ -561,6 +630,49 @@ generate (options& ops, semantics::cli_unit& unit, path const& p) ctx.verify_id_ref (); } + // gen_dep + // + if (gen_dep) + { + // Write the specified path to the dependencies file stream, escaping + // colons and backslashes. + // + auto write = [&dep] (path const& p) + { + for (char c: p.string ()) + { + if (c == ':' || c == '\\') + dep << '\\'; + + dep << c; + } + }; + + // Note that we don't add the dependency file as a dependent, but in the + // future may invent some option which triggers that. + // + bool first (true); + for (const auto& p: depts) + { + if (!first) + dep << " \\" << endl; + else + first = false; + + write (p); + } + + dep << ':'; + + for (const auto& p: deps) + { + dep << " \\" << endl + << " "; write (p); + } + + dep << endl; + } + auto_rm.cancel (); } catch (const generation_failed&) diff --git a/cli/cli/generator.hxx b/cli/cli/generator.hxx index f567528..3deb3f3 100644 --- a/cli/cli/generator.hxx +++ b/cli/cli/generator.hxx @@ -5,6 +5,8 @@ #ifndef CLI_GENERATOR_HXX #define CLI_GENERATOR_HXX +#include <vector> + #include <cli/options.hxx> #include <cli/semantics/unit.hxx> @@ -16,7 +18,10 @@ public: class failed {}; void - generate (options&, semantics::cli_unit&, semantics::path const&); + generate (options&, + semantics::cli_unit&&, + std::vector<semantics::path>&& dependencies, + semantics::path const&); private: generator (generator const&); diff --git a/cli/cli/header.cxx b/cli/cli/header.cxx index a2a3ccd..87ff259 100644 --- a/cli/cli/header.cxx +++ b/cli/cli/header.cxx @@ -115,7 +115,7 @@ namespace string name (escape (c.name ())); string um (cli + "::unknown_mode"); - os << "class " << name; + os << "class " << exp << name; { base b (*this); @@ -367,13 +367,13 @@ generate_header (context& ctx) string up (ctx.cli + "::usage_para"); string const& ost (ctx.options.ostream_type ()); - os << up << endl + os << ctx.exp << up << endl << n << "usage (" << ost << "&," << endl << up << " = " << up << "::none);" << endl; if (ctx.gen_usage == ut_both) - os << up << endl + os << ctx.exp << up << endl << n << "long_usage (" << ost << "&," << endl << up << " = " << up << "::none);" << endl; diff --git a/cli/cli/html.cxx b/cli/cli/html.cxx index b374b91..48eb5e3 100644 --- a/cli/cli/html.cxx +++ b/cli/cli/html.cxx @@ -127,13 +127,16 @@ namespace // n > 2 - arg string, short string, long string // size_t n (ds.size ()); - const string& d ( + string d ( n == 1 ? (cd_ == cd_short ? first_sentence (ds[0]) : ds[0]) : (n == 2 ? (cd_ == cd_short ? first_sentence (ds[1]) : ds[1]) : ds[cd_ == cd_short ? 1 : 2])); + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + std::set<string> arg_set; if (n > 1) translate_arg (ds[0], arg_set); @@ -211,6 +214,8 @@ namespace if (type != "bool" || doc.size () >= 3) { + // Note: we naturally assume this doesn't need --ascii-tree treatment. + // string s ( translate_arg ( doc.size () > 0 ? doc[0] : string ("<arg>"), arg_set)); @@ -236,6 +241,9 @@ namespace d = (cd_ == cd_short ? first_sentence (doc[1]) : doc[1]); } + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + // Format the documentation string. // d = format (o.scope (), escape_html (translate (d, arg_set)), false); diff --git a/cli/cli/lexer.test.cxx b/cli/cli/lexer.test.cxx index 0eb4dcb..a5cc2f3 100644 --- a/cli/cli/lexer.test.cxx +++ b/cli/cli/lexer.test.cxx @@ -8,6 +8,9 @@ #include <cli/token.hxx> #include <cli/lexer.hxx> +#undef NDEBUG +#include <cassert> + using namespace std; const char* keywords[] = diff --git a/cli/cli/man.cxx b/cli/cli/man.cxx index df703e8..d446b2a 100644 --- a/cli/cli/man.cxx +++ b/cli/cli/man.cxx @@ -91,13 +91,16 @@ namespace // n > 2 - arg string, short string, long string // size_t n (ds.size ()); - const string& d ( + string d ( n == 1 ? (cd_ == cd_short ? first_sentence (ds[0]) : ds[0]) : (n == 2 ? (cd_ == cd_short ? first_sentence (ds[1]) : ds[1]) : ds[cd_ == cd_short ? 1 : 2])); + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + std::set<string> arg_set; if (n > 1) translate_arg (ds[0], arg_set); @@ -149,6 +152,8 @@ namespace if (type != "bool" || doc.size () >= 3) { + // Note: we naturally assume this doesn't need --ascii-tree treatment. + // string s ( translate_arg ( doc.size () > 0 ? doc[0] : string ("<arg>"), arg_set)); @@ -174,6 +179,9 @@ namespace d = (cd_ == cd_short ? first_sentence (doc[1]) : doc[1]); } + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + // Format the documentation string. // d = format (o.scope (), translate (d, arg_set), false); diff --git a/cli/cli/options.cli b/cli/cli/options.cli index ff462d3..211e01f 100644 --- a/cli/cli/options.cli +++ b/cli/cli/options.cli @@ -108,11 +108,15 @@ class options { -f }+ { -b }+ arg +{ f=1 } +{ b=2 } # 'arg' with '-f' 'b' 'f=1' 'b=2' \ - Note that the group applies to a single argument only. For example: + The group applies to a single argument only unless multiple arguments + are themselves grouped with '\cb{{}' and '\cb{\}}'. For example: \ - { --foo }+ arg1 arg2 +{ --bar } # 'arg1' with '--foo' and - # 'arg2' with '--bar' + { --foo }+ arg1 arg2 +{ --bar } # 'arg1' with '--foo' + # 'arg2' with '--bar' + + { --foo }+ { arg1 arg2 } +{ --bar } # 'arg1' with '--foo' '--bar' + # 'arg2' with '--foo' '--bar' \ The group separators ('\cb{{}', '\cb{\}+'}, etc) must be separate command @@ -167,6 +171,13 @@ class options should be used to print usage and exception information." }; + std::string --export-symbol + { + "<symbol>", + "Insert <symbol> in places where DLL export/import control statements + (\cb{__declspec(dllexport/dllimport)}) are necessary." + }; + bool --generate-cxx { "Generate C++ code. If neither \cb{--generate-man}, \cb{--generate-html}, @@ -188,6 +199,18 @@ class options "Generate documentation in the plain text format, similar to usage." }; + bool --generate-dep + { + "Generate \cb{make} dependency information. This option triggers the + creation of the \cb{.d} file containing the dependencies of the generated + files on the main \cb{.cli} file as well as all the \cb{.cli} files that + it includes or sources, transitively. Paths specified with the + \cb{--*-prologue-file} and \cb{--*-epilogue-file} options are also + added as dependencies. Note, however, that paths specified with the + \cb{--options-file} option are not added (since they may or may not + contain options that affect the output)." + }; + bool --stdout { "Write output to STDOUT instead of a file. This option is not valid @@ -253,6 +276,13 @@ class options files, and would like their usage to have the same indentation level." }; + bool --ascii-tree + { + "Convert UTF-8 \cb{tree(1)} output to ASCII. Specifically, box-drawing + characters used in the \cb{--charset=UTF-8} output are replaced with + ASCII characters used in the \cb{--charset=ASCII} output." + }; + bool --ansi-color { "Use ANSI color escape sequences when printing usage. By \"color\" we @@ -568,6 +598,20 @@ class options the generated text file." }; + std::string --dep-suffix = ".d" + { + "<suffix>", + "Use <suffix> instead of the default \cb{.d} to construct the name of the + generated dependency file. See also \cb{--dep-file}." + }; + + std::string --dep-file + { + "<path>", + "Use <path> as the generated dependency file path instead of deriving it + from the input file name." + }; + std::string --option-prefix = "-" { "<prefix>", diff --git a/cli/cli/parser.cxx b/cli/cli/parser.cxx index 4685edc..e2efca5 100644 --- a/cli/cli/parser.cxx +++ b/cli/cli/parser.cxx @@ -17,6 +17,7 @@ #include <fstream> #include <sstream> +#include <utility> // move() #include <iostream> #include <cli/token.hxx> @@ -66,7 +67,7 @@ const char* punctuation[] = { // Output the token type and value in a format suitable for diagnostics. // -std::ostream& +static std::ostream& operator<< (std::ostream& os, token const& t) { switch (t.type ()) @@ -184,16 +185,19 @@ recover (token& t) } } -unique_ptr<cli_unit> parser:: +parser::parse_result parser:: parse (std::istream& is, path const& p) { unique_ptr<cli_unit> unit (new cli_unit (p, 1, 1)); { path ap (p); - ap.absolute (); + ap.complete (); ap.normalize (); - include_map_[ap] = unit.get (); + include_map_[move (ap)] = unit.get (); + + if (collect_dependencies_) + dependencies_.push_back (path (p).normalize ()); } root_ = cur_ = unit.get (); @@ -211,7 +215,7 @@ parse (std::istream& is, path const& p) if (!valid_ || !l.valid ()) throw invalid_input (); - return unit; + return parse_result {move (unit), move (dependencies_)}; } void parser:: @@ -350,6 +354,16 @@ source_decl () if (valid_) { + if (collect_dependencies_) + { + path ap (p); + ap.complete (); + ap.normalize (); + + if (include_map_.emplace (move (ap), nullptr).second) + dependencies_.push_back (p); + } + auto_restore<path const> new_path (path_, &p); ifstream ifs (p.string ().c_str ()); @@ -468,15 +482,18 @@ include_decl () // Detect and ignore multiple inclusions. // path ap (p); - ap.absolute (); + ap.complete (); ap.normalize (); include_map::iterator it (include_map_.find (ap)); - if (it == include_map_.end ()) + if (it == include_map_.end () || it->second == nullptr) { + if (collect_dependencies_ && it == include_map_.end ()) + dependencies_.push_back (p); + cli_unit& n (root_->new_node<cli_unit> (p, 1, 1)); root_->new_edge<cli_includes> (*cur_, n, ik, f); - include_map_[ap] = &n; + include_map_[move (ap)] = &n; auto_restore<cli_unit> new_cur (cur_, &n); auto_restore<path const> new_path (path_, &p); diff --git a/cli/cli/parser.hxx b/cli/cli/parser.hxx index 326768e..960e74b 100644 --- a/cli/cli/parser.hxx +++ b/cli/cli/parser.hxx @@ -23,11 +23,23 @@ class parser public: typedef std::vector<semantics::path> paths; - parser (paths const& include_paths): include_paths_ (include_paths) {} + parser (paths const& include_paths, bool collect_dependencies) + : include_paths_ (include_paths), + collect_dependencies_ (collect_dependencies) {} struct invalid_input {}; - std::unique_ptr<semantics::cli_unit> + struct parse_result + { + std::unique_ptr<semantics::cli_unit> unit; + + // Normalized paths of the main CLI file and files it includes and sources + // recursively, with the duplicates suppressed. + // + paths dependencies; + }; + + parse_result parse (std::istream& is, semantics::path const& path); private: @@ -72,6 +84,7 @@ private: private: paths const include_paths_; + bool collect_dependencies_; bool valid_; semantics::path const* path_; @@ -84,8 +97,12 @@ private: std::size_t doc_count_; // Scope doc counter, see scope_doc() for details. + // If the entry's value is NULL, then the key refers to a sourced file. + // typedef std::map<semantics::path, semantics::cli_unit*> include_map; include_map include_map_; + + paths dependencies_; }; #endif // CLI_PARSER_HXX diff --git a/cli/cli/parser.test.cxx b/cli/cli/parser.test.cxx index 6ef0d11..44109b3 100644 --- a/cli/cli/parser.test.cxx +++ b/cli/cli/parser.test.cxx @@ -9,6 +9,9 @@ #include <cli/semantics.hxx> #include <cli/traversal.hxx> +#undef NDEBUG +#include <cassert> + using namespace std; int @@ -29,7 +32,7 @@ main (int argc, char* argv[]) ifs.open (path.string ().c_str ()); parser::paths include_paths; - parser p (include_paths); + parser p (include_paths, true /* collect_dependencies */); p.parse (ifs, path); } catch (semantics::invalid_path const& e) diff --git a/cli/cli/options.cxx b/cli/cli/pregenerated/cli/options.cxx index d64e801..9f0be5f 100644 --- a/cli/cli/options.cxx +++ b/cli/cli/pregenerated/cli/options.cxx @@ -15,6 +15,7 @@ #include <set> #include <string> #include <vector> +#include <utility> #include <ostream> #include <sstream> #include <cstring> @@ -196,6 +197,7 @@ namespace cli else ++i_; + ++start_position_; return r; } else @@ -206,11 +208,20 @@ namespace cli skip () { if (i_ < argc_) + { ++i_; + ++start_position_; + } else throw eos_reached (); } + std::size_t argv_scanner:: + position () + { + return start_position_; + } + // argv_file_scanner // int argv_file_scanner::zero_argc_ = 0; @@ -321,6 +332,7 @@ namespace cli { hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value); args_.pop_front (); + ++start_position_; return hold_[i_].c_str (); } } @@ -334,7 +346,10 @@ namespace cli if (args_.empty ()) return base::skip (); else + { args_.pop_front (); + ++start_position_; + } } const argv_file_scanner::option_info* argv_file_scanner:: @@ -347,6 +362,12 @@ namespace cli return 0; } + std::size_t argv_file_scanner:: + position () + { + return start_position_; + } + void argv_file_scanner:: load (const std::string& file) { @@ -459,12 +480,28 @@ namespace cli if (oi->search_func != 0) { - std::string f (oi->search_func (s2.c_str (), oi->arg)); + string f (oi->search_func (s2.c_str (), oi->arg)); if (!f.empty ()) load (f); } else + { + // If the path of the file being parsed is not simple and the + // path of the file that needs to be loaded is relative, then + // complete the latter using the former as a base. + // +#ifndef _WIN32 + string::size_type p (file.find_last_of ('/')); + bool c (p != string::npos && s2[0] != '/'); +#else + string::size_type p (file.find_last_of ("/\\")); + bool c (p != string::npos && s2[1] != ':'); +#endif + if (c) + s2.insert (0, file, 0, p + 1); + load (s2); + } continue; } @@ -505,10 +542,31 @@ namespace cli struct parser<bool> { 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; } }; @@ -530,6 +588,17 @@ namespace cli }; template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + }; + + template <typename X> struct parser<std::vector<X> > { static void @@ -543,11 +612,11 @@ namespace cli } }; - template <typename X> - struct parser<std::set<X> > + template <typename X, typename C> + struct parser<std::set<X, C> > { static void - parse (std::set<X>& c, bool& xs, scanner& s) + parse (std::set<X, C>& c, bool& xs, scanner& s) { X x; bool dummy; @@ -557,16 +626,17 @@ namespace cli } }; - template <typename K, typename V> - struct parser<std::map<K, V> > + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > { static void - parse (std::map<K, V>& m, bool& xs, scanner& s) + parse (std::map<K, V, C>& m, bool& xs, scanner& s) { const char* o (s.next ()); if (s.more ()) { + std::size_t pos (s.position ()); std::string ov (s.next ()); std::string::size_type p = ov.find ('='); @@ -586,14 +656,14 @@ namespace cli if (!kstr.empty ()) { av[1] = const_cast<char*> (kstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser<K>::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast<char*> (vstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser<V>::parse (v, dummy, s); } @@ -606,6 +676,56 @@ namespace cli } }; + template <typename K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + }; + template <typename X, typename T, T X::*M> void thunk (X& x, scanner& s) @@ -613,6 +733,14 @@ namespace cli parser<T>::parse (x.*M, s); } + template <typename X, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + template <typename X, typename T, T X::*M, bool X::*S> void thunk (X& x, scanner& s) @@ -622,7 +750,6 @@ namespace cli } #include <map> -#include <cstring> // options // @@ -653,10 +780,13 @@ options () cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -666,6 +796,7 @@ options () page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -745,6 +876,10 @@ options () html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -794,10 +929,13 @@ options (int& argc, cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -807,6 +945,7 @@ options (int& argc, page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -886,6 +1025,10 @@ options (int& argc, html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -938,10 +1081,13 @@ options (int start, cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -951,6 +1097,7 @@ options (int start, page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -1030,6 +1177,10 @@ options (int start, html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -1082,10 +1233,13 @@ options (int& argc, cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -1095,6 +1249,7 @@ options (int& argc, page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -1174,6 +1329,10 @@ options (int& argc, html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -1228,10 +1387,13 @@ options (int start, cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -1241,6 +1403,7 @@ options (int start, page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -1320,6 +1483,10 @@ options (int start, html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -1370,10 +1537,13 @@ options (::cli::scanner& s, cli_namespace_specified_ (false), ostream_type_ ("::std::ostream"), ostream_type_specified_ (false), + export_symbol_ (), + export_symbol_specified_ (false), generate_cxx_ (), generate_man_ (), generate_html_ (), generate_txt_ (), + generate_dep_ (), stdout__ (), suppress_undocumented_ (), suppress_usage_ (), @@ -1383,6 +1553,7 @@ options (::cli::scanner& s, page_usage_specified_ (false), option_length_ (0), option_length_specified_ (false), + ascii_tree_ (), ansi_color_ (), exclude_base_ (), include_base_last_ (), @@ -1462,6 +1633,10 @@ options (::cli::scanner& s, html_suffix_specified_ (false), txt_suffix_ (".txt"), txt_suffix_specified_ (false), + dep_suffix_ (".d"), + dep_suffix_specified_ (false), + dep_file_ (), + dep_file_specified_ (false), option_prefix_ ("-"), option_prefix_specified_ (false), option_separator_ ("--"), @@ -1535,6 +1710,10 @@ print_usage (::std::ostream& os, ::cli::usage_para p) << " std::ostream that should be used to print usage" << ::std::endl << " and exception information." << ::std::endl; + os << "--export-symbol <symbol> Insert <symbol> in places where DLL export/import" << ::std::endl + << " control statements" << ::std::endl + << " (__declspec(dllexport/dllimport)) are necessary." << ::std::endl; + os << "--generate-cxx Generate C++ code." << ::std::endl; os << "--generate-man Generate documentation in the man page format." << ::std::endl; @@ -1544,6 +1723,8 @@ print_usage (::std::ostream& os, ::cli::usage_para p) os << "--generate-txt Generate documentation in the plain text format," << ::std::endl << " similar to usage." << ::std::endl; + os << "--generate-dep Generate make dependency information." << ::std::endl; + os << "--stdout Write output to STDOUT instead of a file." << ::std::endl; os << "--suppress-undocumented Suppress the generation of documentation entries" << ::std::endl @@ -1564,6 +1745,8 @@ print_usage (::std::ostream& os, ::cli::usage_para p) os << "--option-length <len> Indent option descriptions <len> characters when" << ::std::endl << " printing usage." << ::std::endl; + os << "--ascii-tree Convert UTF-8 tree(1) output to ASCII." << ::std::endl; + os << "--ansi-color Use ANSI color escape sequences when printing" << ::std::endl << " usage." << ::std::endl; @@ -1692,6 +1875,13 @@ print_usage (::std::ostream& os, ::cli::usage_para p) os << "--txt-suffix <suffix> Use <suffix> instead of the default .txt to" << ::std::endl << " construct the name of the generated text file." << ::std::endl; + os << "--dep-suffix <suffix> Use <suffix> instead of the default .d to" << ::std::endl + << " construct the name of the generated dependency" << ::std::endl + << " file." << ::std::endl; + + os << "--dep-file <path> Use <path> as the generated dependency file path" << ::std::endl + << " instead of deriving it from the input file name." << ::std::endl; + os << "--option-prefix <prefix> Use <prefix> instead of the default '-' as an" << ::std::endl << " option prefix." << ::std::endl; @@ -1742,9 +1932,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<std::string>, &options::include_path_, &options::include_path_specified_ >; @@ -1761,61 +1951,68 @@ 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_ >; _cli_options_map_["--ostream-type"] = &::cli::thunk< options, std::string, &options::ostream_type_, &options::ostream_type_specified_ >; + _cli_options_map_["--export-symbol"] = + &::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_["--generate-dep"] = + &::cli::thunk< options, &options::generate_dep_ >; _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_ >; _cli_options_map_["--option-length"] = &::cli::thunk< options, std::size_t, &options::option_length_, &options::option_length_specified_ >; + _cli_options_map_["--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<std::string, std::string>, &options::class_doc_, &options::class_doc_specified_ >; @@ -1832,12 +2029,12 @@ struct _cli_options_map_init &::cli::thunk< options, std::vector<std::string>, &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<char, std::string>, &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<std::string>, &options::hxx_prologue_, &options::hxx_prologue_specified_ >; @@ -1934,6 +2131,12 @@ struct _cli_options_map_init _cli_options_map_["--txt-suffix"] = &::cli::thunk< options, std::string, &options::txt_suffix_, &options::txt_suffix_specified_ >; + _cli_options_map_["--dep-suffix"] = + &::cli::thunk< options, std::string, &options::dep_suffix_, + &options::dep_suffix_specified_ >; + _cli_options_map_["--dep-file"] = + &::cli::thunk< options, std::string, &options::dep_file_, + &options::dep_file_specified_ >; _cli_options_map_["--option-prefix"] = &::cli::thunk< options, std::string, &options::option_prefix_, &options::option_prefix_specified_ >; @@ -1941,13 +2144,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/options.hxx b/cli/cli/pregenerated/cli/options.hxx index b54d81f..f44258f 100644 --- a/cli/cli/options.hxx +++ b/cli/cli/pregenerated/cli/options.hxx @@ -236,6 +236,14 @@ namespace cli // for the two previous arguments up until a call to a third // peek() or next(). // + // The position() function returns a monotonically-increasing + // number which, if stored, can later be used to determine the + // relative position of the argument returned by the following + // call to next(). Note that if multiple scanners are used to + // extract arguments from multiple sources, then the end + // position of the previous scanner should be used as the + // start position of the next. + // class scanner { public: @@ -253,13 +261,24 @@ namespace cli virtual void skip () = 0; + + virtual std::size_t + position () = 0; }; class argv_scanner: public scanner { public: - argv_scanner (int& argc, char** argv, bool erase = false); - argv_scanner (int start, int& argc, char** argv, bool erase = false); + argv_scanner (int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + argv_scanner (int start, + int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); int end () const; @@ -276,7 +295,11 @@ namespace cli virtual void skip (); - private: + virtual std::size_t + position (); + + protected: + std::size_t start_position_; int i_; int& argc_; char** argv_; @@ -289,16 +312,19 @@ namespace cli argv_file_scanner (int& argc, char** argv, const std::string& option, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const std::string& option, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (const std::string& file, - const std::string& option); + const std::string& option, + std::size_t start_position = 0); struct option_info { @@ -315,18 +341,21 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const option_info* options, std::size_t options_count, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (const std::string& file, const option_info* options = 0, - std::size_t options_count = 0); + std::size_t options_count = 0, + std::size_t start_position = 0); virtual bool more (); @@ -340,6 +369,9 @@ namespace cli virtual void skip (); + virtual std::size_t + position (); + // Return the file path if the peeked at argument came from a file and // the empty string otherwise. The reference is guaranteed to be valid // till the end of the scanner lifetime. @@ -641,6 +673,21 @@ class options void ostream_type_specified (bool); + const std::string& + export_symbol () const; + + std::string& + export_symbol (); + + void + export_symbol (const std::string&); + + bool + export_symbol_specified () const; + + void + export_symbol_specified (bool); + const bool& generate_cxx () const; @@ -678,6 +725,15 @@ class options generate_txt (const bool&); const bool& + generate_dep () const; + + bool& + generate_dep (); + + void + generate_dep (const bool&); + + const bool& stdout_ () const; bool& @@ -753,6 +809,15 @@ class options option_length_specified (bool); const bool& + ascii_tree () const; + + bool& + ascii_tree (); + + void + ascii_tree (const bool&); + + const bool& ansi_color () const; bool& @@ -1353,6 +1418,36 @@ class options txt_suffix_specified (bool); const std::string& + dep_suffix () const; + + std::string& + dep_suffix (); + + void + dep_suffix (const std::string&); + + bool + dep_suffix_specified () const; + + void + dep_suffix_specified (bool); + + const std::string& + dep_file () const; + + std::string& + dep_file (); + + void + dep_file (const std::string&); + + bool + dep_file_specified () const; + + void + dep_file_specified (bool); + + const std::string& option_prefix () const; std::string& @@ -1521,10 +1616,13 @@ class options bool cli_namespace_specified_; std::string ostream_type_; bool ostream_type_specified_; + std::string export_symbol_; + bool export_symbol_specified_; bool generate_cxx_; bool generate_man_; bool generate_html_; bool generate_txt_; + bool generate_dep_; bool stdout__; bool suppress_undocumented_; bool suppress_usage_; @@ -1534,6 +1632,7 @@ class options bool page_usage_specified_; std::size_t option_length_; bool option_length_specified_; + bool ascii_tree_; bool ansi_color_; bool exclude_base_; bool include_base_last_; @@ -1613,6 +1712,10 @@ class options bool html_suffix_specified_; std::string txt_suffix_; bool txt_suffix_specified_; + std::string dep_suffix_; + bool dep_suffix_specified_; + std::string dep_file_; + bool dep_file_specified_; std::string option_prefix_; bool option_prefix_specified_; std::string option_separator_; diff --git a/cli/cli/options.ixx b/cli/cli/pregenerated/cli/options.ixx index 5916883..54fa54a 100644 --- a/cli/cli/options.ixx +++ b/cli/cli/pregenerated/cli/options.ixx @@ -141,14 +141,29 @@ namespace cli // argv_scanner // inline argv_scanner:: - argv_scanner (int& argc, char** argv, bool erase) - : i_ (1), argc_ (argc), argv_ (argv), erase_ (erase) + argv_scanner (int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + 1), + i_ (1), + argc_ (argc), + argv_ (argv), + erase_ (erase) { } inline argv_scanner:: - argv_scanner (int start, int& argc, char** argv, bool erase) - : i_ (start), argc_ (argc), argv_ (argv), erase_ (erase) + argv_scanner (int start, + int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + static_cast<std::size_t> (start)), + i_ (start), + argc_ (argc), + argv_ (argv), + erase_ (erase) { } @@ -164,8 +179,9 @@ namespace cli argv_file_scanner (int& argc, char** argv, const std::string& option, - bool erase) - : argv_scanner (argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -181,8 +197,9 @@ namespace cli int& argc, char** argv, const std::string& option, - bool erase) - : argv_scanner (start, argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -195,8 +212,9 @@ namespace cli inline argv_file_scanner:: argv_file_scanner (const std::string& file, - const std::string& option) - : argv_scanner (0, zero_argc_, 0), + const std::string& option, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -214,8 +232,9 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase) - : argv_scanner (argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), options_ (options), options_count_ (options_count), i_ (1), @@ -229,8 +248,9 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase) - : argv_scanner (start, argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), options_ (options), options_count_ (options_count), i_ (1), @@ -241,8 +261,9 @@ namespace cli 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), + std::size_t options_count, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), options_ (options), options_count_ (options_count), i_ (1), @@ -268,7 +289,7 @@ build2_metadata () } inline void options:: -build2_metadata(const std::uint64_t& x) +build2_metadata (const std::uint64_t& x) { this->build2_metadata_ = x; } @@ -280,7 +301,7 @@ build2_metadata_specified () const } inline void options:: -build2_metadata_specified(bool x) +build2_metadata_specified (bool x) { this->build2_metadata_specified_ = x; } @@ -298,7 +319,7 @@ help () } inline void options:: -help(const bool& x) +help (const bool& x) { this->help_ = x; } @@ -316,7 +337,7 @@ version () } inline void options:: -version(const bool& x) +version (const bool& x) { this->version_ = x; } @@ -334,7 +355,7 @@ include_path () } inline void options:: -include_path(const std::vector<std::string>& x) +include_path (const std::vector<std::string>& x) { this->include_path_ = x; } @@ -346,7 +367,7 @@ include_path_specified () const } inline void options:: -include_path_specified(bool x) +include_path_specified (bool x) { this->include_path_specified_ = x; } @@ -364,7 +385,7 @@ output_dir () } inline void options:: -output_dir(const std::string& x) +output_dir (const std::string& x) { this->output_dir_ = x; } @@ -376,7 +397,7 @@ output_dir_specified () const } inline void options:: -output_dir_specified(bool x) +output_dir_specified (bool x) { this->output_dir_specified_ = x; } @@ -394,7 +415,7 @@ std () } inline void options:: -std(const cxx_version& x) +std (const cxx_version& x) { this->std_ = x; } @@ -406,7 +427,7 @@ std_specified () const } inline void options:: -std_specified(bool x) +std_specified (bool x) { this->std_specified_ = x; } @@ -424,7 +445,7 @@ generate_modifier () } inline void options:: -generate_modifier(const bool& x) +generate_modifier (const bool& x) { this->generate_modifier_ = x; } @@ -442,7 +463,7 @@ generate_specifier () } inline void options:: -generate_specifier(const bool& x) +generate_specifier (const bool& x) { this->generate_specifier_ = x; } @@ -460,7 +481,7 @@ generate_parse () } inline void options:: -generate_parse(const bool& x) +generate_parse (const bool& x) { this->generate_parse_ = x; } @@ -478,7 +499,7 @@ generate_merge () } inline void options:: -generate_merge(const bool& x) +generate_merge (const bool& x) { this->generate_merge_ = x; } @@ -496,7 +517,7 @@ generate_description () } inline void options:: -generate_description(const bool& x) +generate_description (const bool& x) { this->generate_description_ = x; } @@ -514,7 +535,7 @@ generate_file_scanner () } inline void options:: -generate_file_scanner(const bool& x) +generate_file_scanner (const bool& x) { this->generate_file_scanner_ = x; } @@ -532,7 +553,7 @@ generate_vector_scanner () } inline void options:: -generate_vector_scanner(const bool& x) +generate_vector_scanner (const bool& x) { this->generate_vector_scanner_ = x; } @@ -550,7 +571,7 @@ generate_group_scanner () } inline void options:: -generate_group_scanner(const bool& x) +generate_group_scanner (const bool& x) { this->generate_group_scanner_ = x; } @@ -568,7 +589,7 @@ suppress_inline () } inline void options:: -suppress_inline(const bool& x) +suppress_inline (const bool& x) { this->suppress_inline_ = x; } @@ -586,7 +607,7 @@ suppress_cli () } inline void options:: -suppress_cli(const bool& x) +suppress_cli (const bool& x) { this->suppress_cli_ = x; } @@ -604,7 +625,7 @@ cli_namespace () } inline void options:: -cli_namespace(const std::string& x) +cli_namespace (const std::string& x) { this->cli_namespace_ = x; } @@ -616,7 +637,7 @@ cli_namespace_specified () const } inline void options:: -cli_namespace_specified(bool x) +cli_namespace_specified (bool x) { this->cli_namespace_specified_ = x; } @@ -634,7 +655,7 @@ ostream_type () } inline void options:: -ostream_type(const std::string& x) +ostream_type (const std::string& x) { this->ostream_type_ = x; } @@ -646,11 +667,41 @@ ostream_type_specified () const } inline void options:: -ostream_type_specified(bool x) +ostream_type_specified (bool x) { this->ostream_type_specified_ = x; } +inline const std::string& options:: +export_symbol () const +{ + return this->export_symbol_; +} + +inline std::string& options:: +export_symbol () +{ + return this->export_symbol_; +} + +inline void options:: +export_symbol (const std::string& x) +{ + this->export_symbol_ = x; +} + +inline bool options:: +export_symbol_specified () const +{ + return this->export_symbol_specified_; +} + +inline void options:: +export_symbol_specified (bool x) +{ + this->export_symbol_specified_ = x; +} + inline const bool& options:: generate_cxx () const { @@ -664,7 +715,7 @@ generate_cxx () } inline void options:: -generate_cxx(const bool& x) +generate_cxx (const bool& x) { this->generate_cxx_ = x; } @@ -682,7 +733,7 @@ generate_man () } inline void options:: -generate_man(const bool& x) +generate_man (const bool& x) { this->generate_man_ = x; } @@ -700,7 +751,7 @@ generate_html () } inline void options:: -generate_html(const bool& x) +generate_html (const bool& x) { this->generate_html_ = x; } @@ -718,12 +769,30 @@ generate_txt () } inline void options:: -generate_txt(const bool& x) +generate_txt (const bool& x) { this->generate_txt_ = x; } inline const bool& options:: +generate_dep () const +{ + return this->generate_dep_; +} + +inline bool& options:: +generate_dep () +{ + return this->generate_dep_; +} + +inline void options:: +generate_dep (const bool& x) +{ + this->generate_dep_ = x; +} + +inline const bool& options:: stdout_ () const { return this->stdout__; @@ -736,7 +805,7 @@ stdout_ () } inline void options:: -stdout_(const bool& x) +stdout_ (const bool& x) { this->stdout__ = x; } @@ -754,7 +823,7 @@ suppress_undocumented () } inline void options:: -suppress_undocumented(const bool& x) +suppress_undocumented (const bool& x) { this->suppress_undocumented_ = x; } @@ -772,7 +841,7 @@ suppress_usage () } inline void options:: -suppress_usage(const bool& x) +suppress_usage (const bool& x) { this->suppress_usage_ = x; } @@ -790,7 +859,7 @@ long_usage () } inline void options:: -long_usage(const bool& x) +long_usage (const bool& x) { this->long_usage_ = x; } @@ -808,7 +877,7 @@ short_usage () } inline void options:: -short_usage(const bool& x) +short_usage (const bool& x) { this->short_usage_ = x; } @@ -826,7 +895,7 @@ page_usage () } inline void options:: -page_usage(const std::string& x) +page_usage (const std::string& x) { this->page_usage_ = x; } @@ -838,7 +907,7 @@ page_usage_specified () const } inline void options:: -page_usage_specified(bool x) +page_usage_specified (bool x) { this->page_usage_specified_ = x; } @@ -856,7 +925,7 @@ option_length () } inline void options:: -option_length(const std::size_t& x) +option_length (const std::size_t& x) { this->option_length_ = x; } @@ -868,12 +937,30 @@ option_length_specified () const } inline void options:: -option_length_specified(bool x) +option_length_specified (bool x) { this->option_length_specified_ = x; } inline const bool& options:: +ascii_tree () const +{ + return this->ascii_tree_; +} + +inline bool& options:: +ascii_tree () +{ + return this->ascii_tree_; +} + +inline void options:: +ascii_tree (const bool& x) +{ + this->ascii_tree_ = x; +} + +inline const bool& options:: ansi_color () const { return this->ansi_color_; @@ -886,7 +973,7 @@ ansi_color () } inline void options:: -ansi_color(const bool& x) +ansi_color (const bool& x) { this->ansi_color_ = x; } @@ -904,7 +991,7 @@ exclude_base () } inline void options:: -exclude_base(const bool& x) +exclude_base (const bool& x) { this->exclude_base_ = x; } @@ -922,7 +1009,7 @@ include_base_last () } inline void options:: -include_base_last(const bool& x) +include_base_last (const bool& x) { this->include_base_last_ = x; } @@ -940,7 +1027,7 @@ class_doc () } inline void options:: -class_doc(const std::map<std::string, std::string>& x) +class_doc (const std::map<std::string, std::string>& x) { this->class_doc_ = x; } @@ -952,7 +1039,7 @@ class_doc_specified () const } inline void options:: -class_doc_specified(bool x) +class_doc_specified (bool x) { this->class_doc_specified_ = x; } @@ -970,7 +1057,7 @@ class_ () } inline void options:: -class_(const std::vector<std::string>& x) +class_ (const std::vector<std::string>& x) { this->class__ = x; } @@ -982,7 +1069,7 @@ class__specified () const } inline void options:: -class__specified(bool x) +class__specified (bool x) { this->class__specified_ = x; } @@ -1000,7 +1087,7 @@ docvar () } inline void options:: -docvar(const std::map<std::string, std::string>& x) +docvar (const std::map<std::string, std::string>& x) { this->docvar_ = x; } @@ -1012,7 +1099,7 @@ docvar_specified () const } inline void options:: -docvar_specified(bool x) +docvar_specified (bool x) { this->docvar_specified_ = x; } @@ -1030,7 +1117,7 @@ link_regex () } inline void options:: -link_regex(const std::vector<std::string>& x) +link_regex (const std::vector<std::string>& x) { this->link_regex_ = x; } @@ -1042,7 +1129,7 @@ link_regex_specified () const } inline void options:: -link_regex_specified(bool x) +link_regex_specified (bool x) { this->link_regex_specified_ = x; } @@ -1060,7 +1147,7 @@ link_regex_trace () } inline void options:: -link_regex_trace(const bool& x) +link_regex_trace (const bool& x) { this->link_regex_trace_ = x; } @@ -1078,7 +1165,7 @@ html_heading_map () } inline void options:: -html_heading_map(const std::map<char, std::string>& x) +html_heading_map (const std::map<char, std::string>& x) { this->html_heading_map_ = x; } @@ -1090,7 +1177,7 @@ html_heading_map_specified () const } inline void options:: -html_heading_map_specified(bool x) +html_heading_map_specified (bool x) { this->html_heading_map_specified_ = x; } @@ -1108,7 +1195,7 @@ omit_link_check () } inline void options:: -omit_link_check(const bool& x) +omit_link_check (const bool& x) { this->omit_link_check_ = x; } @@ -1126,7 +1213,7 @@ hxx_prologue () } inline void options:: -hxx_prologue(const std::vector<std::string>& x) +hxx_prologue (const std::vector<std::string>& x) { this->hxx_prologue_ = x; } @@ -1138,7 +1225,7 @@ hxx_prologue_specified () const } inline void options:: -hxx_prologue_specified(bool x) +hxx_prologue_specified (bool x) { this->hxx_prologue_specified_ = x; } @@ -1156,7 +1243,7 @@ ixx_prologue () } inline void options:: -ixx_prologue(const std::vector<std::string>& x) +ixx_prologue (const std::vector<std::string>& x) { this->ixx_prologue_ = x; } @@ -1168,7 +1255,7 @@ ixx_prologue_specified () const } inline void options:: -ixx_prologue_specified(bool x) +ixx_prologue_specified (bool x) { this->ixx_prologue_specified_ = x; } @@ -1186,7 +1273,7 @@ cxx_prologue () } inline void options:: -cxx_prologue(const std::vector<std::string>& x) +cxx_prologue (const std::vector<std::string>& x) { this->cxx_prologue_ = x; } @@ -1198,7 +1285,7 @@ cxx_prologue_specified () const } inline void options:: -cxx_prologue_specified(bool x) +cxx_prologue_specified (bool x) { this->cxx_prologue_specified_ = x; } @@ -1216,7 +1303,7 @@ man_prologue () } inline void options:: -man_prologue(const std::vector<std::string>& x) +man_prologue (const std::vector<std::string>& x) { this->man_prologue_ = x; } @@ -1228,7 +1315,7 @@ man_prologue_specified () const } inline void options:: -man_prologue_specified(bool x) +man_prologue_specified (bool x) { this->man_prologue_specified_ = x; } @@ -1246,7 +1333,7 @@ html_prologue () } inline void options:: -html_prologue(const std::vector<std::string>& x) +html_prologue (const std::vector<std::string>& x) { this->html_prologue_ = x; } @@ -1258,7 +1345,7 @@ html_prologue_specified () const } inline void options:: -html_prologue_specified(bool x) +html_prologue_specified (bool x) { this->html_prologue_specified_ = x; } @@ -1276,7 +1363,7 @@ txt_prologue () } inline void options:: -txt_prologue(const std::vector<std::string>& x) +txt_prologue (const std::vector<std::string>& x) { this->txt_prologue_ = x; } @@ -1288,7 +1375,7 @@ txt_prologue_specified () const } inline void options:: -txt_prologue_specified(bool x) +txt_prologue_specified (bool x) { this->txt_prologue_specified_ = x; } @@ -1306,7 +1393,7 @@ hxx_epilogue () } inline void options:: -hxx_epilogue(const std::vector<std::string>& x) +hxx_epilogue (const std::vector<std::string>& x) { this->hxx_epilogue_ = x; } @@ -1318,7 +1405,7 @@ hxx_epilogue_specified () const } inline void options:: -hxx_epilogue_specified(bool x) +hxx_epilogue_specified (bool x) { this->hxx_epilogue_specified_ = x; } @@ -1336,7 +1423,7 @@ ixx_epilogue () } inline void options:: -ixx_epilogue(const std::vector<std::string>& x) +ixx_epilogue (const std::vector<std::string>& x) { this->ixx_epilogue_ = x; } @@ -1348,7 +1435,7 @@ ixx_epilogue_specified () const } inline void options:: -ixx_epilogue_specified(bool x) +ixx_epilogue_specified (bool x) { this->ixx_epilogue_specified_ = x; } @@ -1366,7 +1453,7 @@ cxx_epilogue () } inline void options:: -cxx_epilogue(const std::vector<std::string>& x) +cxx_epilogue (const std::vector<std::string>& x) { this->cxx_epilogue_ = x; } @@ -1378,7 +1465,7 @@ cxx_epilogue_specified () const } inline void options:: -cxx_epilogue_specified(bool x) +cxx_epilogue_specified (bool x) { this->cxx_epilogue_specified_ = x; } @@ -1396,7 +1483,7 @@ man_epilogue () } inline void options:: -man_epilogue(const std::vector<std::string>& x) +man_epilogue (const std::vector<std::string>& x) { this->man_epilogue_ = x; } @@ -1408,7 +1495,7 @@ man_epilogue_specified () const } inline void options:: -man_epilogue_specified(bool x) +man_epilogue_specified (bool x) { this->man_epilogue_specified_ = x; } @@ -1426,7 +1513,7 @@ html_epilogue () } inline void options:: -html_epilogue(const std::vector<std::string>& x) +html_epilogue (const std::vector<std::string>& x) { this->html_epilogue_ = x; } @@ -1438,7 +1525,7 @@ html_epilogue_specified () const } inline void options:: -html_epilogue_specified(bool x) +html_epilogue_specified (bool x) { this->html_epilogue_specified_ = x; } @@ -1456,7 +1543,7 @@ txt_epilogue () } inline void options:: -txt_epilogue(const std::vector<std::string>& x) +txt_epilogue (const std::vector<std::string>& x) { this->txt_epilogue_ = x; } @@ -1468,7 +1555,7 @@ txt_epilogue_specified () const } inline void options:: -txt_epilogue_specified(bool x) +txt_epilogue_specified (bool x) { this->txt_epilogue_specified_ = x; } @@ -1486,7 +1573,7 @@ hxx_prologue_file () } inline void options:: -hxx_prologue_file(const std::string& x) +hxx_prologue_file (const std::string& x) { this->hxx_prologue_file_ = x; } @@ -1498,7 +1585,7 @@ hxx_prologue_file_specified () const } inline void options:: -hxx_prologue_file_specified(bool x) +hxx_prologue_file_specified (bool x) { this->hxx_prologue_file_specified_ = x; } @@ -1516,7 +1603,7 @@ ixx_prologue_file () } inline void options:: -ixx_prologue_file(const std::string& x) +ixx_prologue_file (const std::string& x) { this->ixx_prologue_file_ = x; } @@ -1528,7 +1615,7 @@ ixx_prologue_file_specified () const } inline void options:: -ixx_prologue_file_specified(bool x) +ixx_prologue_file_specified (bool x) { this->ixx_prologue_file_specified_ = x; } @@ -1546,7 +1633,7 @@ cxx_prologue_file () } inline void options:: -cxx_prologue_file(const std::string& x) +cxx_prologue_file (const std::string& x) { this->cxx_prologue_file_ = x; } @@ -1558,7 +1645,7 @@ cxx_prologue_file_specified () const } inline void options:: -cxx_prologue_file_specified(bool x) +cxx_prologue_file_specified (bool x) { this->cxx_prologue_file_specified_ = x; } @@ -1576,7 +1663,7 @@ man_prologue_file () } inline void options:: -man_prologue_file(const std::string& x) +man_prologue_file (const std::string& x) { this->man_prologue_file_ = x; } @@ -1588,7 +1675,7 @@ man_prologue_file_specified () const } inline void options:: -man_prologue_file_specified(bool x) +man_prologue_file_specified (bool x) { this->man_prologue_file_specified_ = x; } @@ -1606,7 +1693,7 @@ html_prologue_file () } inline void options:: -html_prologue_file(const std::string& x) +html_prologue_file (const std::string& x) { this->html_prologue_file_ = x; } @@ -1618,7 +1705,7 @@ html_prologue_file_specified () const } inline void options:: -html_prologue_file_specified(bool x) +html_prologue_file_specified (bool x) { this->html_prologue_file_specified_ = x; } @@ -1636,7 +1723,7 @@ txt_prologue_file () } inline void options:: -txt_prologue_file(const std::string& x) +txt_prologue_file (const std::string& x) { this->txt_prologue_file_ = x; } @@ -1648,7 +1735,7 @@ txt_prologue_file_specified () const } inline void options:: -txt_prologue_file_specified(bool x) +txt_prologue_file_specified (bool x) { this->txt_prologue_file_specified_ = x; } @@ -1666,7 +1753,7 @@ hxx_epilogue_file () } inline void options:: -hxx_epilogue_file(const std::string& x) +hxx_epilogue_file (const std::string& x) { this->hxx_epilogue_file_ = x; } @@ -1678,7 +1765,7 @@ hxx_epilogue_file_specified () const } inline void options:: -hxx_epilogue_file_specified(bool x) +hxx_epilogue_file_specified (bool x) { this->hxx_epilogue_file_specified_ = x; } @@ -1696,7 +1783,7 @@ ixx_epilogue_file () } inline void options:: -ixx_epilogue_file(const std::string& x) +ixx_epilogue_file (const std::string& x) { this->ixx_epilogue_file_ = x; } @@ -1708,7 +1795,7 @@ ixx_epilogue_file_specified () const } inline void options:: -ixx_epilogue_file_specified(bool x) +ixx_epilogue_file_specified (bool x) { this->ixx_epilogue_file_specified_ = x; } @@ -1726,7 +1813,7 @@ cxx_epilogue_file () } inline void options:: -cxx_epilogue_file(const std::string& x) +cxx_epilogue_file (const std::string& x) { this->cxx_epilogue_file_ = x; } @@ -1738,7 +1825,7 @@ cxx_epilogue_file_specified () const } inline void options:: -cxx_epilogue_file_specified(bool x) +cxx_epilogue_file_specified (bool x) { this->cxx_epilogue_file_specified_ = x; } @@ -1756,7 +1843,7 @@ man_epilogue_file () } inline void options:: -man_epilogue_file(const std::string& x) +man_epilogue_file (const std::string& x) { this->man_epilogue_file_ = x; } @@ -1768,7 +1855,7 @@ man_epilogue_file_specified () const } inline void options:: -man_epilogue_file_specified(bool x) +man_epilogue_file_specified (bool x) { this->man_epilogue_file_specified_ = x; } @@ -1786,7 +1873,7 @@ html_epilogue_file () } inline void options:: -html_epilogue_file(const std::string& x) +html_epilogue_file (const std::string& x) { this->html_epilogue_file_ = x; } @@ -1798,7 +1885,7 @@ html_epilogue_file_specified () const } inline void options:: -html_epilogue_file_specified(bool x) +html_epilogue_file_specified (bool x) { this->html_epilogue_file_specified_ = x; } @@ -1816,7 +1903,7 @@ txt_epilogue_file () } inline void options:: -txt_epilogue_file(const std::string& x) +txt_epilogue_file (const std::string& x) { this->txt_epilogue_file_ = x; } @@ -1828,7 +1915,7 @@ txt_epilogue_file_specified () const } inline void options:: -txt_epilogue_file_specified(bool x) +txt_epilogue_file_specified (bool x) { this->txt_epilogue_file_specified_ = x; } @@ -1846,7 +1933,7 @@ output_prefix () } inline void options:: -output_prefix(const std::string& x) +output_prefix (const std::string& x) { this->output_prefix_ = x; } @@ -1858,7 +1945,7 @@ output_prefix_specified () const } inline void options:: -output_prefix_specified(bool x) +output_prefix_specified (bool x) { this->output_prefix_specified_ = x; } @@ -1876,7 +1963,7 @@ output_suffix () } inline void options:: -output_suffix(const std::string& x) +output_suffix (const std::string& x) { this->output_suffix_ = x; } @@ -1888,7 +1975,7 @@ output_suffix_specified () const } inline void options:: -output_suffix_specified(bool x) +output_suffix_specified (bool x) { this->output_suffix_specified_ = x; } @@ -1906,7 +1993,7 @@ hxx_suffix () } inline void options:: -hxx_suffix(const std::string& x) +hxx_suffix (const std::string& x) { this->hxx_suffix_ = x; } @@ -1918,7 +2005,7 @@ hxx_suffix_specified () const } inline void options:: -hxx_suffix_specified(bool x) +hxx_suffix_specified (bool x) { this->hxx_suffix_specified_ = x; } @@ -1936,7 +2023,7 @@ ixx_suffix () } inline void options:: -ixx_suffix(const std::string& x) +ixx_suffix (const std::string& x) { this->ixx_suffix_ = x; } @@ -1948,7 +2035,7 @@ ixx_suffix_specified () const } inline void options:: -ixx_suffix_specified(bool x) +ixx_suffix_specified (bool x) { this->ixx_suffix_specified_ = x; } @@ -1966,7 +2053,7 @@ cxx_suffix () } inline void options:: -cxx_suffix(const std::string& x) +cxx_suffix (const std::string& x) { this->cxx_suffix_ = x; } @@ -1978,7 +2065,7 @@ cxx_suffix_specified () const } inline void options:: -cxx_suffix_specified(bool x) +cxx_suffix_specified (bool x) { this->cxx_suffix_specified_ = x; } @@ -1996,7 +2083,7 @@ man_suffix () } inline void options:: -man_suffix(const std::string& x) +man_suffix (const std::string& x) { this->man_suffix_ = x; } @@ -2008,7 +2095,7 @@ man_suffix_specified () const } inline void options:: -man_suffix_specified(bool x) +man_suffix_specified (bool x) { this->man_suffix_specified_ = x; } @@ -2026,7 +2113,7 @@ html_suffix () } inline void options:: -html_suffix(const std::string& x) +html_suffix (const std::string& x) { this->html_suffix_ = x; } @@ -2038,7 +2125,7 @@ html_suffix_specified () const } inline void options:: -html_suffix_specified(bool x) +html_suffix_specified (bool x) { this->html_suffix_specified_ = x; } @@ -2056,7 +2143,7 @@ txt_suffix () } inline void options:: -txt_suffix(const std::string& x) +txt_suffix (const std::string& x) { this->txt_suffix_ = x; } @@ -2068,12 +2155,72 @@ txt_suffix_specified () const } inline void options:: -txt_suffix_specified(bool x) +txt_suffix_specified (bool x) { this->txt_suffix_specified_ = x; } inline const std::string& options:: +dep_suffix () const +{ + return this->dep_suffix_; +} + +inline std::string& options:: +dep_suffix () +{ + return this->dep_suffix_; +} + +inline void options:: +dep_suffix (const std::string& x) +{ + this->dep_suffix_ = x; +} + +inline bool options:: +dep_suffix_specified () const +{ + return this->dep_suffix_specified_; +} + +inline void options:: +dep_suffix_specified (bool x) +{ + this->dep_suffix_specified_ = x; +} + +inline const std::string& options:: +dep_file () const +{ + return this->dep_file_; +} + +inline std::string& options:: +dep_file () +{ + return this->dep_file_; +} + +inline void options:: +dep_file (const std::string& x) +{ + this->dep_file_ = x; +} + +inline bool options:: +dep_file_specified () const +{ + return this->dep_file_specified_; +} + +inline void options:: +dep_file_specified (bool x) +{ + this->dep_file_specified_ = x; +} + +inline const std::string& options:: option_prefix () const { return this->option_prefix_; @@ -2086,7 +2233,7 @@ option_prefix () } inline void options:: -option_prefix(const std::string& x) +option_prefix (const std::string& x) { this->option_prefix_ = x; } @@ -2098,7 +2245,7 @@ option_prefix_specified () const } inline void options:: -option_prefix_specified(bool x) +option_prefix_specified (bool x) { this->option_prefix_specified_ = x; } @@ -2116,7 +2263,7 @@ option_separator () } inline void options:: -option_separator(const std::string& x) +option_separator (const std::string& x) { this->option_separator_ = x; } @@ -2128,7 +2275,7 @@ option_separator_specified () const } inline void options:: -option_separator_specified(bool x) +option_separator_specified (bool x) { this->option_separator_specified_ = x; } @@ -2146,7 +2293,7 @@ keep_separator () } inline void options:: -keep_separator(const bool& x) +keep_separator (const bool& x) { this->keep_separator_ = x; } @@ -2164,7 +2311,7 @@ no_combined_flags () } inline void options:: -no_combined_flags(const bool& x) +no_combined_flags (const bool& x) { this->no_combined_flags_ = x; } @@ -2182,7 +2329,7 @@ no_combined_values () } inline void options:: -no_combined_values(const bool& x) +no_combined_values (const bool& x) { this->no_combined_values_ = x; } @@ -2200,7 +2347,7 @@ include_with_brackets () } inline void options:: -include_with_brackets(const bool& x) +include_with_brackets (const bool& x) { this->include_with_brackets_ = x; } @@ -2218,7 +2365,7 @@ include_prefix () } inline void options:: -include_prefix(const std::string& x) +include_prefix (const std::string& x) { this->include_prefix_ = x; } @@ -2230,7 +2377,7 @@ include_prefix_specified () const } inline void options:: -include_prefix_specified(bool x) +include_prefix_specified (bool x) { this->include_prefix_specified_ = x; } @@ -2248,7 +2395,7 @@ guard_prefix () } inline void options:: -guard_prefix(const std::string& x) +guard_prefix (const std::string& x) { this->guard_prefix_ = x; } @@ -2260,7 +2407,7 @@ guard_prefix_specified () const } inline void options:: -guard_prefix_specified(bool x) +guard_prefix_specified (bool x) { this->guard_prefix_specified_ = x; } @@ -2278,7 +2425,7 @@ reserved_name () } inline void options:: -reserved_name(const std::map<std::string, std::string>& x) +reserved_name (const std::map<std::string, std::string>& x) { this->reserved_name_ = x; } @@ -2290,7 +2437,7 @@ reserved_name_specified () const } inline void options:: -reserved_name_specified(bool x) +reserved_name_specified (bool x) { this->reserved_name_specified_ = x; } @@ -2308,7 +2455,7 @@ options_file () } inline void options:: -options_file(const std::string& x) +options_file (const std::string& x) { this->options_file_ = x; } @@ -2320,7 +2467,7 @@ options_file_specified () const } inline void options:: -options_file_specified(bool x) +options_file_specified (bool x) { this->options_file_specified_ = x; } diff --git a/cli/cli/runtime-header.cxx b/cli/cli/runtime-header.cxx index adf70dd..1003e91 100644 --- a/cli/cli/runtime-header.cxx +++ b/cli/cli/runtime-header.cxx @@ -43,10 +43,13 @@ generate_runtime_header (context& ctx) ctx.ns_open (ctx.cli); + string const& exp (ctx.exp); + string const& exp_inl (ctx.exp_inl); + // usage_para // if (!ctx.options.suppress_usage ()) - os << "class usage_para" + os << "class " << exp_inl << "usage_para" << "{" << "public:" << endl << "enum value" @@ -64,7 +67,7 @@ generate_runtime_header (context& ctx) // unknown_mode // - os << "class unknown_mode" + os << "class " << exp_inl << "unknown_mode" << "{" << "public:" << endl << "enum value" @@ -85,26 +88,30 @@ generate_runtime_header (context& ctx) string const& os_type (ctx.options.ostream_type ()); + const char* nothrow (ctx.options.std () < cxx_version::cxx11 + ? "throw ()" + : "noexcept"); + os << "// Exceptions." << endl << "//" << endl << endl; - os << "class exception: public std::exception" + os << "class " << exp << "exception: public std::exception" << "{" << "public:" << endl << "virtual void" << endl << "print (" << os_type << "&) const = 0;" << "};"; - os << os_type << "&" << endl + os << exp_inl << os_type << "&" << endl << "operator<< (" << os_type << "&, const exception&);" << endl; - os << "class unknown_option: public exception" + os << "class " << exp << "unknown_option: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~unknown_option () throw ();" + << "~unknown_option () " << nothrow << ';' << endl << "unknown_option (const std::string& option);" << endl @@ -115,17 +122,17 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string option_;" << "};"; - os << "class unknown_argument: public exception" + os << "class " << exp << "unknown_argument: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~unknown_argument () throw ();" + << "~unknown_argument () " << nothrow << ';' << endl << "unknown_argument (const std::string& argument);" << endl @@ -136,17 +143,17 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string argument_;" << "};"; - os << "class missing_value: public exception" + os << "class " << exp << "missing_value: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~missing_value () throw ();" + << "~missing_value () " << nothrow << ';' << endl << "missing_value (const std::string& option);" << endl @@ -157,17 +164,17 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string option_;" << "};"; - os << "class invalid_value: public exception" + os << "class " << exp << "invalid_value: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~invalid_value () throw ();" + << "~invalid_value () " << nothrow << ';' << endl << "invalid_value (const std::string& option," << endl << "const std::string& value," << endl @@ -186,7 +193,7 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string option_;" @@ -194,23 +201,23 @@ generate_runtime_header (context& ctx) << "std::string message_;" << "};"; - os << "class eos_reached: public exception" + os << "class " << exp << "eos_reached: public exception" << "{" << "public:" << endl << "virtual void" << endl << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << "};"; if (ctx.options.generate_file_scanner ()) { - os << "class file_io_failure: public exception" + os << "class " << exp << "file_io_failure: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~file_io_failure () throw ();" + << "~file_io_failure () " << nothrow << ';' << endl << "file_io_failure (const std::string& file);" << endl @@ -221,17 +228,17 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string file_;" << "};"; - os << "class unmatched_quote: public exception" + os << "class " << exp << "unmatched_quote: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~unmatched_quote () throw ();" + << "~unmatched_quote () " << nothrow << ';' << endl << "unmatched_quote (const std::string& argument);" << endl @@ -242,7 +249,7 @@ generate_runtime_header (context& ctx) << "print (" << os_type << "&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string argument_;" @@ -251,11 +258,11 @@ generate_runtime_header (context& ctx) if (ctx.options.generate_group_scanner ()) { - os << "class unexpected_group: public exception" + os << "class " << exp << "unexpected_group: public exception" << "{" << "public:" << endl << "virtual" << endl - << "~unexpected_group () throw ();" + << "~unexpected_group () " << nothrow << ';' << endl << "unexpected_group (const std::string& argument," << endl << "const std::string& group);" @@ -270,18 +277,18 @@ generate_runtime_header (context& ctx) << "print (std::ostream&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string argument_;" << "std::string group_;" << "};"; - os << "class group_separator: public exception" << endl + os << "class " << exp << "group_separator: public exception" << endl << "{" << "public:" << endl << "virtual" << endl - << "~group_separator () throw ();" + << "~group_separator () " << nothrow << ';' << endl << "// Note: either (but not both) can be empty." << endl << "//" << endl @@ -298,7 +305,7 @@ generate_runtime_header (context& ctx) << "print (std::ostream&) const;" << endl << "virtual const char*" << endl - << "what () const throw ();" + << "what () const " << nothrow << ';' << endl << "private:" << endl << "std::string encountered_;" @@ -308,13 +315,21 @@ generate_runtime_header (context& ctx) // scanner // - os << "// Command line argument scanner interface." << endl - << "//" << endl - << "// The values returned by next() are guaranteed to be valid" << endl - << "// for the two previous arguments up until a call to a third" << endl - << "// peek() or next()." << endl - << "//" << endl - << "class scanner" + os << "// Command line argument scanner interface." << endl + << "//" << endl + << "// The values returned by next() are guaranteed to be valid" << endl + << "// for the two previous arguments up until a call to a third" << endl + << "// peek() or next()." << endl + << "//" << endl + << "// The position() function returns a monotonically-increasing" << endl + << "// number which, if stored, can later be used to determine the"<< endl + << "// relative position of the argument returned by the following"<< endl + << "// call to next(). Note that if multiple scanners are used to" << endl + << "// extract arguments from multiple sources, then the end" << endl + << "// position of the previous scanner should be used as the" << endl + << "// start position of the next." << endl + << "//" << endl + << "class " << exp << "scanner" << "{" << "public:" << endl << "virtual" << endl @@ -331,15 +346,26 @@ generate_runtime_header (context& ctx) << endl << "virtual void" << endl << "skip () = 0;" + << endl + << "virtual std::size_t" << endl + << "position () = 0;" << "};"; // argv_scanner // - os << "class argv_scanner: public scanner" + os << "class " << exp << "argv_scanner: public scanner" << "{" << "public:" << endl - << "argv_scanner (int& argc, char** argv, bool erase = false);" - << "argv_scanner (int start, int& argc, char** argv, bool erase = false);" + << "argv_scanner (int& argc," << endl + << "char** argv," << endl + << "bool erase = false," << endl + << "std::size_t start_position = 0);" + << endl + << "argv_scanner (int start," << endl + << "int& argc," << endl + << "char** argv," << endl + << "bool erase = false," << endl + << "std::size_t start_position = 0);" << endl << "int" << endl << "end () const;" @@ -356,7 +382,11 @@ generate_runtime_header (context& ctx) << "virtual void" << endl << "skip ();" << endl - << "private:" << endl + << "virtual std::size_t" << endl + << "position ();" + << endl + << "protected:" << endl + << "std::size_t start_position_;" << "int i_;" << "int& argc_;" << "char** argv_;" @@ -367,17 +397,18 @@ generate_runtime_header (context& ctx) // if (ctx.options.generate_vector_scanner ()) { - os << "class vector_scanner: public scanner" + os << "class " << exp << "vector_scanner: public scanner" << "{" << "public:" << endl - << "vector_scanner (const std::vector<std::string>&, " << - "std::size_t start = 0);" + << "vector_scanner (const std::vector<std::string>&," << endl + << "std::size_t start = 0," << endl + << "std::size_t start_position = 0);" << endl << "std::size_t" << endl << "end () const;" << endl << "void" << endl - << "reset (std::size_t start = 0);" + << "reset (std::size_t start = 0, std::size_t start_position = 0);" << endl << "virtual bool" << endl << "more ();" @@ -391,7 +422,11 @@ generate_runtime_header (context& ctx) << "virtual void" << endl << "skip ();" << endl + << "virtual std::size_t" << endl + << "position ();" + << endl << "private:" << endl + << "std::size_t start_position_;" << "const std::vector<std::string>& v_;" << "std::size_t i_;" << "};"; @@ -401,22 +436,25 @@ generate_runtime_header (context& ctx) // if (ctx.options.generate_file_scanner ()) { - os << "class argv_file_scanner: public argv_scanner" + os << "class " << exp << "argv_file_scanner: public argv_scanner" << "{" << "public:" << endl << "argv_file_scanner (int& argc," << endl << "char** argv," << endl << "const std::string& option," << endl - << "bool erase = false);" + << "bool erase = false," << endl + << "std::size_t start_position = 0);" << endl << "argv_file_scanner (int start," << endl << "int& argc," << endl << "char** argv," << endl << "const std::string& option," << endl - << "bool erase = false);" + << "bool erase = false," << endl + << "std::size_t start_position = 0);" << endl << "argv_file_scanner (const std::string& file," << endl - << "const std::string& option);" + << "const std::string& option," << endl + << "std::size_t start_position = 0);" << endl << "struct option_info" << "{" @@ -432,18 +470,21 @@ generate_runtime_header (context& ctx) << "char** argv," << endl << "const option_info* options," << endl << "std::size_t options_count," << endl - << "bool erase = false);" + << "bool erase = false," << endl + << "std::size_t start_position = 0);" << 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);" + << "bool erase = false," << endl + << "std::size_t start_position = 0);" << endl << "argv_file_scanner (const std::string& file," << endl << "const option_info* options = 0," << endl - << "std::size_t options_count = 0);" + << "std::size_t options_count = 0," << endl + << "std::size_t start_position = 0);" << endl << "virtual bool" << endl << "more ();" @@ -457,6 +498,9 @@ generate_runtime_header (context& ctx) << "virtual void" << endl << "skip ();" << endl + << "virtual std::size_t" << endl + << "position ();" + << endl << "// Return the file path if the peeked at argument came from a file and" << endl << "// the empty string otherwise. The reference is guaranteed to be valid" << endl << "// till the end of the scanner lifetime." << endl @@ -512,7 +556,7 @@ generate_runtime_header (context& ctx) // if (ctx.options.generate_group_scanner ()) { - os << "class group_scanner: public scanner" + os << "class " << exp << "group_scanner: public scanner" << "{" << "public:" << endl << "group_scanner (scanner&);" @@ -529,12 +573,18 @@ generate_runtime_header (context& ctx) << "virtual void" << endl << "skip ();" << endl + << "virtual std::size_t" << endl + << "position ();" + << endl << "// The group is only available after the call to next()" << endl << "// (and skip() -- in case one needs to make sure the group" << endl << "// was empty, or some such) and is only valid (and must be" << endl << "// handled) until the next call to any of the scanner" << endl << "// functions (including more())." << endl << "//" << endl + << "// Note also that argument positions within each group start"<< endl + << "// from 0." << endl + << "//" << endl << "scanner&" << endl << "group ();" << endl @@ -562,21 +612,20 @@ generate_runtime_header (context& ctx) << "static separator" << endl << "sense (const char*);" << endl - << "// If the state is scanned or skipped, then scan the" << endl - << "// leading groups and save the next (unescaped) argument in" << endl - << "// arg_. If the state is peeked, then scan the trailing" << endl - << "// groups. In both cases set the new state." << endl + + << "// Scan the leading groups, the next argument/argument pack,"<< endl + << "// and the trailing groups." << endl << "//" << endl << "void" << endl - << "scan_group (state);" + << "scan_group ();" << endl << "scanner& scan_;" << "state state_;" << endl << "// Circular buffer of two arguments." << endl << "//" << endl - << "std::string arg_[2];" - << "std::size_t i_;" + << "std::vector<std::string> arg_[2];" + << "std::size_t i_, j_, pos_;" << endl << "std::vector<std::string> group_;" << "vector_scanner group_scan_;" @@ -590,7 +639,7 @@ generate_runtime_header (context& ctx) os << "typedef std::vector<std::string> option_names;" << endl; - os << "class option" + os << "class " << exp_inl << "option" << "{" << "public:" << endl << endl @@ -620,7 +669,7 @@ generate_runtime_header (context& ctx) << "std::string default_value_;" << "};"; - os << "class options: public std::vector<option>" + os << "class " << exp << "options: public std::vector<option>" << "{" << "public:" << endl << "typedef std::vector<option> container_type;" diff --git a/cli/cli/runtime-inline.cxx b/cli/cli/runtime-inline.cxx index 8f0e84c..ce18e92 100644 --- a/cli/cli/runtime-inline.cxx +++ b/cli/cli/runtime-inline.cxx @@ -232,14 +232,29 @@ generate_runtime_inline (context& ctx) << "//" << endl; os << inl << "argv_scanner::" << endl - << "argv_scanner (int& argc, char** argv, bool erase)" << endl - << ": i_ (1), argc_ (argc), argv_ (argv), erase_ (erase)" + << "argv_scanner (int& argc," << endl + << "char** argv," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": start_position_ (sp + 1)," << endl + << " i_ (1)," << endl + << " argc_ (argc)," << endl + << " argv_ (argv)," << endl + << " erase_ (erase)" << "{" << "}"; os << inl << "argv_scanner::" << endl - << "argv_scanner (int start, int& argc, char** argv, bool erase)" << endl - << ": i_ (start), argc_ (argc), argv_ (argv), erase_ (erase)" + << "argv_scanner (int start," << endl + << "int& argc," << endl + << "char** argv," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": start_position_ (sp + static_cast<std::size_t> (start))," << endl + << " i_ (start)," << endl + << " argc_ (argc)," << endl + << " argv_ (argv)," << endl + << " erase_ (erase)" << "{" << "}"; @@ -257,9 +272,10 @@ generate_runtime_inline (context& ctx) << "//" << endl; os << inl << "vector_scanner::" << endl - << "vector_scanner (const std::vector<std::string>& v, " << - "std::size_t i)" << endl - << ": v_ (v), i_ (i)" + << "vector_scanner (const std::vector<std::string>& v," << endl + << "std::size_t i," << endl + << "std::size_t sp)" << endl + << ": start_position_ (sp), v_ (v), i_ (i)" << "{" << "}"; @@ -270,9 +286,10 @@ generate_runtime_inline (context& ctx) << "}"; os << inl << "void vector_scanner::" << endl - << "reset (std::size_t i)" + << "reset (std::size_t i, std::size_t sp)" << "{" << "i_ = i;" + << "start_position_ = sp;" << "}"; } @@ -289,8 +306,9 @@ generate_runtime_inline (context& ctx) << "argv_file_scanner (int& argc," << endl << "char** argv," << endl << "const std::string& option," << endl - << "bool erase)" << endl - << ": argv_scanner (argc, argv, erase)," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (argc, argv, erase, sp)," << endl << " option_ (option)," << endl << " options_ (&option_info_)," << endl << " options_count_ (1)," << endl @@ -308,8 +326,9 @@ generate_runtime_inline (context& ctx) << "int& argc," << endl << "char** argv," << endl << "const std::string& option," << endl - << "bool erase)" << endl - << ": argv_scanner (start, argc, argv, erase)," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (start, argc, argv, erase, sp)," << endl << " option_ (option)," << endl << " options_ (&option_info_)," << endl << " options_count_ (1)," << endl @@ -324,8 +343,9 @@ 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 + << "const std::string& option," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (0, zero_argc_, 0, sp)," << endl << " option_ (option)," << endl << " options_ (&option_info_)," << endl << " options_count_ (1)," << endl @@ -345,8 +365,9 @@ generate_runtime_inline (context& ctx) << "char** argv," << endl << "const option_info* options," << endl << "std::size_t options_count," << endl - << "bool erase)" << endl - << ": argv_scanner (argc, argv, erase)," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (argc, argv, erase, sp)," << endl << " options_ (options)," << endl << " options_count_ (options_count)," << endl << " i_ (1)"; @@ -362,8 +383,9 @@ generate_runtime_inline (context& ctx) << "char** argv," << endl << "const option_info* options," << endl << "std::size_t options_count," << endl - << "bool erase)" << endl - << ": argv_scanner (start, argc, argv, erase)," << endl + << "bool erase," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (start, argc, argv, erase, sp)," << endl << " options_ (options)," << endl << " options_count_ (options_count)," << endl << " i_ (1)"; @@ -376,8 +398,9 @@ generate_runtime_inline (context& ctx) 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 + << "std::size_t options_count," << endl + << "std::size_t sp)" << endl + << ": argv_scanner (0, zero_argc_, 0, sp)," << endl << " options_ (options)," << endl << " options_count_ (options_count)," << endl << " i_ (1)"; @@ -398,7 +421,7 @@ generate_runtime_inline (context& ctx) << inl << "group_scanner::" << endl << "group_scanner (scanner& s)" << endl - << ": scan_ (s), state_ (skipped), i_ (1), group_scan_ (group_)" + << ": scan_ (s), state_ (skipped), i_ (1), j_ (0), group_scan_ (group_)" << "{" << "}" diff --git a/cli/cli/runtime-source.cxx b/cli/cli/runtime-source.cxx index 3864163..11cd746 100644 --- a/cli/cli/runtime-source.cxx +++ b/cli/cli/runtime-source.cxx @@ -15,12 +15,13 @@ generate_runtime_source (context& ctx, bool complete) << "#include <set>" << endl << "#include <string>" << endl << "#include <vector>" << endl + << "#include <utility>" << endl // pair << "#include <ostream>" << endl - << "#include <sstream>" << endl; + << "#include <sstream>" << endl + << "#include <cstring>" << endl; if (complete && ctx.options.generate_file_scanner ()) - os << "#include <cstring>" << endl - << "#include <fstream>" << endl; + os << "#include <fstream>" << endl; os << endl; @@ -30,12 +31,16 @@ generate_runtime_source (context& ctx, bool complete) { string const& os_type (ctx.options.ostream_type ()); + const char* nothrow (ctx.options.std () < cxx_version::cxx11 + ? "throw ()" + : "noexcept"); + // unknown_option // os << "// unknown_option" << endl << "//" << endl << "unknown_option::" << endl - << "~unknown_option () throw ()" + << "~unknown_option () " << nothrow << "{" << "}" @@ -46,7 +51,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* unknown_option::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"unknown option\";" << "}"; @@ -56,7 +61,7 @@ generate_runtime_source (context& ctx, bool complete) os << "// unknown_argument" << endl << "//" << endl << "unknown_argument::" << endl - << "~unknown_argument () throw ()" + << "~unknown_argument () " << nothrow << "{" << "}" @@ -67,7 +72,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* unknown_argument::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"unknown argument\";" << "}"; @@ -77,7 +82,7 @@ generate_runtime_source (context& ctx, bool complete) os << "// missing_value" << endl << "//" << endl << "missing_value::" << endl - << "~missing_value () throw ()" + << "~missing_value () " << nothrow << "{" << "}" @@ -88,7 +93,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* missing_value::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"missing option value\";" << "}"; @@ -98,7 +103,7 @@ generate_runtime_source (context& ctx, bool complete) os << "// invalid_value" << endl << "//" << endl << "invalid_value::" << endl - << "~invalid_value () throw ()" + << "~invalid_value () " << nothrow << "{" << "}" @@ -114,7 +119,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* invalid_value::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"invalid option value\";" << "}"; @@ -130,7 +135,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* eos_reached::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"end of argument stream reached\";" << "}"; @@ -142,7 +147,7 @@ generate_runtime_source (context& ctx, bool complete) os << "// file_io_failure" << endl << "//" << endl << "file_io_failure::" << endl - << "~file_io_failure () throw ()" + << "~file_io_failure () " << nothrow << "{" << "}" @@ -154,7 +159,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* file_io_failure::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"unable to open file or read failure\";" << "}"; @@ -164,7 +169,7 @@ generate_runtime_source (context& ctx, bool complete) os << "// unmatched_quote" << endl << "//" << endl << "unmatched_quote::" << endl - << "~unmatched_quote () throw ()" + << "~unmatched_quote () " << nothrow << "{" << "}" @@ -176,7 +181,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* unmatched_quote::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"unmatched quote\";" << "}"; @@ -190,7 +195,7 @@ generate_runtime_source (context& ctx, bool complete) << "//" << endl << "unexpected_group::" << endl - << "~unexpected_group () throw ()" + << "~unexpected_group () " << nothrow << "{" << "}" @@ -202,7 +207,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* unexpected_group::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "return \"unexpected grouped argument\";" << "}"; @@ -213,7 +218,7 @@ generate_runtime_source (context& ctx, bool complete) << "//" << endl << "group_separator::" << endl - << "~group_separator () throw ()" + << "~group_separator () " << nothrow << "{" << "}" @@ -237,7 +242,7 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "const char* group_separator::" << endl - << "what () const throw ()" + << "what () const " << nothrow << "{" << "bool ex (!expected_.empty ());" << "bool en (!encountered_.empty ());" @@ -259,6 +264,10 @@ generate_runtime_source (context& ctx, bool complete) // argv_scanner // + // Note that due to the erase logic we cannot just add i_ to + // start_position and so have to increment it instead. See also + // argv_file_scanner that continues with this logic. + // os << "// argv_scanner" << endl << "//" << endl @@ -295,6 +304,7 @@ generate_runtime_source (context& ctx, bool complete) << "else" << endl << "++i_;" << endl + << "++start_position_;" << "return r;" << "}" << "else" << endl @@ -304,10 +314,19 @@ generate_runtime_source (context& ctx, bool complete) << "void argv_scanner::" << endl << "skip ()" << "{" - << "if (i_ < argc_)" << endl + << "if (i_ < argc_)" + << "{" << "++i_;" + << "++start_position_;" + << "}" << "else" << endl << "throw eos_reached ();" + << "}" + + << "std::size_t argv_scanner::" << endl + << "position ()" + << "{" + << "return start_position_;" << "}"; // vector_scanner @@ -348,11 +367,19 @@ generate_runtime_source (context& ctx, bool complete) << "++i_;" << "else" << endl << "throw eos_reached ();" + << "}" + + << "std::size_t vector_scanner::" << endl + << "position ()" + << "{" + << "return start_position_ + i_;" << "}"; } // argv_file_scanner // + // Note that we continue incrementing start_position like argv_scanner. + // if (ctx.options.generate_file_scanner ()) { bool sep (!ctx.opt_sep.empty ()); @@ -486,6 +513,7 @@ generate_runtime_source (context& ctx, bool complete) << "{" << "hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value);" << "args_.pop_front ();" + << "++start_position_;" << "return hold_[i_].c_str ();" << "}" << "}" @@ -498,8 +526,11 @@ generate_runtime_source (context& ctx, bool complete) << endl << "if (args_.empty ())" << endl << "return base::skip ();" - << "else" << endl + << "else" + << "{" << "args_.pop_front ();" + << "++start_position_;" + << "}" << "}" << "const argv_file_scanner::option_info* argv_file_scanner::" << endl @@ -512,6 +543,12 @@ generate_runtime_source (context& ctx, bool complete) << "return 0;" << "}" + << "std::size_t argv_file_scanner::" << endl + << "position ()" + << "{" + << "return start_position_;" + << "}" + << "void argv_file_scanner::" << endl << "load (const std::string& file)" << "{" @@ -699,43 +736,50 @@ generate_runtime_source (context& ctx, bool complete) << "if (state_ == scanned)" << "{" << "if (group_scan_.end () != group_.size ())" << endl - << "throw unexpected_group (arg_[i_], group_scan_.next ());" + << "throw unexpected_group (arg_[i_][j_], group_scan_.next ());" << "}" - << "return scan_.more ();" + << "return j_ != 0 || scan_.more ();" << "}" << "const char* group_scanner::" << endl << "peek ()" << "{" - << "if (state_ != peeked)" << endl - << "scan_group (peeked);" - << "scan_.peek ();" + << "if (state_ != peeked)" + << "{" + << "scan_group ();" + << "state_ = peeked;" + << "}" << "// Return unescaped." << endl - << "return arg_[i_].c_str ();" + << "return arg_[i_][j_ - 1].c_str ();" << "}" << "const char* group_scanner::" << endl << "next ()" << "{" << "if (state_ != peeked)" << endl - << "scan_group (peeked);" - << "scan_.next ();" - << "scan_group (scanned);" + << "scan_group ();" + << "state_ = scanned;" << "// Return unescaped." << endl - << "return arg_[i_].c_str ();" + << "return arg_[i_][--j_].c_str ();" << "}" << "void group_scanner::" << endl << "skip ()" << "{" << "if (state_ != peeked)" << endl - << "scan_group (peeked);" - << "scan_.skip ();" - << "scan_group (skipped);" + << "scan_group ();" + << "state_ = skipped;" + << "--j_;" + << "}" + + << "std::size_t group_scanner::" << endl + << "position ()" + << "{" + << "return j_ == 0 ? scan_.position () : pos_ + (arg_[i_].size () - j_);" << "}" << "void group_scanner::" << endl - << "scan_group (state st)" + << "scan_group ()" << "{" << "// If the previous argument has been scanned, then make" << endl << "// sure the group has been scanned (handled) as well." << endl @@ -743,53 +787,66 @@ generate_runtime_source (context& ctx, bool complete) << "if (state_ == scanned)" << "{" << "if (group_scan_.end () != group_.size ())" << endl - << "throw unexpected_group (arg_[i_], group_scan_.next ());" + << "throw unexpected_group (arg_[i_][j_], group_scan_.next ());" << "}" - << "if (state_ != peeked)" + << "// If we still have arguments in the pack, rewind the group." << endl + << "//" << endl + << "if (j_ != 0)" << "{" - << "arg_[i_ == 0 ? ++i_ : --i_].clear ();" - << "group_.clear ();" << "group_scan_.reset ();" + << "return;" << "}" - << "// We recognize all group sequences both before and " << endl - << "// after the argument and diagnose any misuse. We may" << endl - << "// also have multiple groups:" << endl - << "//" << endl - << "// { -x }+ { -y }+ arg" << endl - << "//" << endl + // Position must remain the same from before the first call to peek() + // (comes directly from the scanner) and until next(). + // + // Note that while it may seem like a good idea to pass + // scan_.position() to reset() below, the trailing group positions + // will overlap with the argument's. So it seems best to start + // positions of each argument in a group from 0. + // + // Note also that we try hard not to throw away allocated memory in + // arg_[][0]. + // + << "i_ += (i_ == 0 ? 1 : -1);" + << "group_.clear ();" + << "group_scan_.reset ();" + << "pos_ = scan_.position ();" << endl - << "// Using group_ won't cover empty groups." << endl + + << "// Note: using group_ won't cover empty groups and using" << endl + << "// j_ won't cover single-argument packs." << endl << "//" << endl - << "bool g (false);" + << "bool group (false), pack (false);" << endl - << "while (scan_.more ())" + << "do" << "{" - << "const char* a (scan_.peek ());" + << "const char* a (scan_.next ());" << "size_t i (*a == '\\\\' ? 1 : 0);" << "separator s (sense (a + i));" << endl << "if (s == none || i != 0)" << "{" - << "if (state_ != peeked)" << endl - << "arg_[i_] = a + (s != none ? i : 0);" + << "if (arg_[i_].size () != 1)" << endl + << "arg_[i_].resize (1);" + << endl + << "arg_[i_][0] = a + (s != none ? i : 0);" + << "j_ = 1;" << "break;" << "}" - << "// Start of a leading group for the next argument." << endl + << "// Start of a leading group for the next argument or" << endl + << "// argument pack. We will only know which once we see" << endl + << "// the closing separator." << endl << "//" << endl - << "if (s == open && state_ == peeked)" << endl - << "break;" - << endl - << "if (s != (state_ == peeked ? open_plus : open))" << endl + << "if (s != open)" << endl << "throw group_separator (a, \"\");" << endl - << "g = true;" + << "size_t n (group_.size ());" << endl << "// Scan the group until the closing separator." << endl << "//" << endl - << "scan_.next ();" << "s = none;" << "while (s == none && scan_.more ())" << "{" @@ -804,20 +861,88 @@ generate_runtime_source (context& ctx, bool complete) << "}" << "}" - << "if (s != (state_ == peeked ? close : close_plus))" + << "if (s == close)" << "{" - << "throw group_separator ((s != none ? a : \"\")," << endl - << "(state_ == peeked ? \"}\" : \"}+\"));" + << "size_t m (group_.size ());" + << endl + << "j_ = m - n;" + << "if (j_ == 0)" << endl + << "throw group_separator (\"{\", \"\");" + << endl + << "if (arg_[i_].size () != j_)" << endl + << "arg_[i_].resize (j_);" + << endl + << "// Move from group_ to arg_. Add in reverse for ease " << endl + << "// of iteration." << endl + << "//" << endl + << "for (size_t j (0); j != j_; ++j)" << endl + << "arg_[i_][j] = group_[m - j - 1];" + << "group_.resize (n);" + << endl + << "pack = true;" + << "break;" << "}" + << "else if (s == close_plus)" << endl + << "group = true;" + << "else" << endl + << "throw group_separator ((s != none ? a : \"\"), \"}+\");" << "}" + << "while (scan_.more ());" + << endl << "// Handle the case where we have seen the leading group" << endl << "// but there are no more arguments." << endl << "//" << endl - << "if (g && state_ != peeked && !scan_.more ())" << endl + << "if (group && j_ == 0)" << endl << "throw group_separator (\"{\", \"\");" << endl - << "state_ = st;" + << "// Handle trailing groups, if any." << endl + << "//" << endl + + << "while (scan_.more ())" + << "{" + << "const char* a (scan_.peek ());" + << "size_t i (*a == '\\\\' ? 1 : 0);" + << "separator s (sense (a + i));" + << endl + + << "// Next argument, argument pack, or leading group." << endl + << "//" << endl + << "if (s == none || s == open || i != 0)" << endl + << "break;" + << endl + << "if (s != open_plus)" << endl + << "throw group_separator (a, \"\");" + << endl + << "group = true;" + << endl + << "// Scan the group until the closing separator." << endl + << "//" << endl + << "scan_.next ();" + << "s = none;" + << "while (s == none && scan_.more ())" + << "{" + << "a = scan_.next ();" + << "i = (*a == '\\\\' ? 1 : 0);" + << "s = sense (a + i);" + << endl + << "if (s == none || i != 0)" + << "{" + << "group_.push_back (a + (s != none ? i : 0));" + << "s = none;" + << "}" + << "}" + + << "if (s != close)" << endl + << "throw group_separator ((s != none ? a : \"\"), \"}\");" + << "}" + + << "// Handle the case where we have seen the argument pack" << endl + << "// without leading or trailing group." << endl + << "//" << endl + << "if (pack && !group)" << endl + << "throw group_separator (\"{\", \"\");" + << "}"; } @@ -890,11 +1015,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 @@ -934,6 +1081,28 @@ generate_runtime_source (context& ctx, bool complete) os << "};"; + // parser<std::pair<X, std::size_t>> + // + os << "template <typename X>" << endl + << "struct parser<std::pair<X, std::size_t> >" + << "{"; + + os << "static void" << endl + << "parse (std::pair<X, std::size_t>& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "x.second = s.position ();" + << "parser<X>::parse (x.first, " << (sp ? "xs, " : "") << "s);" + << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a)" + << "{" + << "b = a;" + << "}"; + + os << "};"; + // parser<std::vector<X>> // os << "template <typename X>" << endl @@ -1001,6 +1170,7 @@ generate_runtime_source (context& ctx, bool complete) << endl << "if (s.more ())" << "{" + << "std::size_t pos (s.position ());" << "std::string ov (s.next ());" << "std::string::size_type p = ov.find ('=');" << endl @@ -1020,13 +1190,13 @@ generate_runtime_source (context& ctx, bool complete) os << "if (!kstr.empty ())" << "{" << "av[1] = const_cast<char*> (kstr.c_str ());" - << "argv_scanner s (0, ac, av);" + << "argv_scanner s (0, ac, av, false, pos);" << "parser<K>::parse (k, " << (sp ? "dummy, " : "") << "s);" << "}" << "if (!vstr.empty ())" << "{" << "av[1] = const_cast<char*> (vstr.c_str ());" - << "argv_scanner s (0, ac, av);" + << "argv_scanner s (0, ac, av, false, pos);" << "parser<V>::parse (v, " << (sp ? "dummy, " : "") << "s);" << "}" << "m[k] = v;" @@ -1050,6 +1220,70 @@ generate_runtime_source (context& ctx, bool complete) os << "};"; + // parser<std::multimap<K,V,C>> + // + os << "template <typename K, typename V, typename C>" << endl + << "struct parser<std::multimap<K, V, C> >" + << "{"; + + os << "static void" << endl + << "parse (std::multimap<K, V, C>& m, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "const char* o (s.next ());" + << endl + << "if (s.more ())" + << "{" + << "std::size_t pos (s.position ());" + << "std::string ov (s.next ());" + << "std::string::size_type p = ov.find ('=');" + << endl + << "K k = K ();" + << "V v = V ();" + << "std::string kstr (ov, 0, p);" + << "std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));" + << endl + << "int ac (2);" + << "char* av[] =" + << "{" + << "const_cast<char*> (o)," << endl + << "0" + << "};"; + if (sp) + os << "bool dummy;"; + os << "if (!kstr.empty ())" + << "{" + << "av[1] = const_cast<char*> (kstr.c_str ());" + << "argv_scanner s (0, ac, av, false, pos);" + << "parser<K>::parse (k, " << (sp ? "dummy, " : "") << "s);" + << "}" + << "if (!vstr.empty ())" + << "{" + << "av[1] = const_cast<char*> (vstr.c_str ());" + << "argv_scanner s (0, ac, av, false, pos);" + << "parser<V>::parse (v, " << (sp ? "dummy, " : "") << "s);" + << "}" + << "m.insert (typename std::multimap<K, V, C>::value_type (k, v));" + << "}" + << "else" << endl + << "throw missing_value (o);"; + if (sp) + os << endl + << "xs = true;"; + os << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a)" + << "{" + << "for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); " << endl + << "i != a.end (); " << endl + << "++i)" << endl + << "b.insert (typename std::multimap<K, V, C>::value_type (i->first," << endl + << "i->second));" << endl + << "}"; + + os << "};"; + // Parser thunk. // os << "template <typename X, typename T, T X::*M>" << endl @@ -1059,6 +1293,14 @@ generate_runtime_source (context& ctx, bool complete) << "parser<T>::parse (x.*M, s);" << "}"; + os << "template <typename X, bool X::*M>" << endl + << "void" << endl + << "thunk (X& x, scanner& s)" + << "{" + << "s.next ();" + << "x.*M = true;" + << "}"; + if (ctx.gen_specifier) os << "template <typename X, typename T, T X::*M, bool X::*S>" << endl << "void" << endl diff --git a/cli/cli/semantics/class.cxx b/cli/cli/semantics/class.cxx index 494d5d0..cd90f8e 100644 --- a/cli/cli/semantics/class.cxx +++ b/cli/cli/semantics/class.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/class.hxx> diff --git a/cli/cli/semantics/doc.cxx b/cli/cli/semantics/doc.cxx index c31260c..a12893d 100644 --- a/cli/cli/semantics/doc.cxx +++ b/cli/cli/semantics/doc.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/doc.hxx> diff --git a/cli/cli/semantics/elements.cxx b/cli/cli/semantics/elements.cxx index ed8eb7d..3c43f91 100644 --- a/cli/cli/semantics/elements.cxx +++ b/cli/cli/semantics/elements.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/elements.hxx> diff --git a/cli/cli/semantics/elements.hxx b/cli/cli/semantics/elements.hxx index 6235a06..e43f707 100644 --- a/cli/cli/semantics/elements.hxx +++ b/cli/cli/semantics/elements.hxx @@ -14,12 +14,12 @@ #include <utility> // std::pair #include <cassert> -#include <cutl/fs/path.hxx> +#include <libcutl/fs/path.hxx> -#include <cutl/container/graph.hxx> -#include <cutl/container/pointer-iterator.hxx> +#include <libcutl/container/graph.hxx> +#include <libcutl/container/pointer-iterator.hxx> -#include <cutl/compiler/context.hxx> +#include <libcutl/compiler/context.hxx> namespace semantics { diff --git a/cli/cli/semantics/expression.cxx b/cli/cli/semantics/expression.cxx index 18d3312..5d1260d 100644 --- a/cli/cli/semantics/expression.cxx +++ b/cli/cli/semantics/expression.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/expression.hxx> diff --git a/cli/cli/semantics/namespace.cxx b/cli/cli/semantics/namespace.cxx index 3c2643c..b9ed422 100644 --- a/cli/cli/semantics/namespace.cxx +++ b/cli/cli/semantics/namespace.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/namespace.hxx> diff --git a/cli/cli/semantics/option.cxx b/cli/cli/semantics/option.cxx index 8746a5e..215a169 100644 --- a/cli/cli/semantics/option.cxx +++ b/cli/cli/semantics/option.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/option.hxx> diff --git a/cli/cli/semantics/unit.cxx b/cli/cli/semantics/unit.cxx index 9c532ea..690011f 100644 --- a/cli/cli/semantics/unit.cxx +++ b/cli/cli/semantics/unit.cxx @@ -2,7 +2,7 @@ // author : Boris Kolpackov <boris@codesynthesis.com> // license : MIT; see accompanying LICENSE file -#include <cutl/compiler/type-info.hxx> +#include <libcutl/compiler/type-info.hxx> #include <cli/semantics/unit.hxx> diff --git a/cli/cli/source.cxx b/cli/cli/source.cxx index b6df839..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 @@ -278,6 +282,9 @@ namespace : (n == 1 ? ds[0] : ds[1]); // Else, use common (no first sentence). } + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + std::set<string> arg_set; if (n > 1 && options.ansi_color ()) translate_arg (ds[0], arg_set); @@ -345,6 +352,8 @@ namespace { l++; // ' ' seperator + // Note: we naturally assume this doesn't need --ascii-tree treatment. + // string s (doc.size () > 0 ? doc[0] : string ("<arg>")); if (options.ansi_color ()) @@ -439,6 +448,8 @@ namespace os << ' '; l++; + // Note: we naturally assume this doesn't need --ascii-tree treatment. + // string s (doc.size () > 0 ? doc[0] : string ("<arg>")); if (color) @@ -475,6 +486,9 @@ namespace } } + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + // Format the documentation string. // if (color) @@ -1262,7 +1276,6 @@ generate_source (context& ctx) ostream& os (ctx.os); os << "#include <map>" << endl - << "#include <cstring>" << endl << endl; traversal::cli_unit unit; diff --git a/cli/cli/traversal/elements.hxx b/cli/cli/traversal/elements.hxx index a2ada23..f56de49 100644 --- a/cli/cli/traversal/elements.hxx +++ b/cli/cli/traversal/elements.hxx @@ -5,7 +5,7 @@ #ifndef CLI_TRAVERSAL_ELEMENTS_HXX #define CLI_TRAVERSAL_ELEMENTS_HXX -#include <cutl/compiler/traversal.hxx> +#include <libcutl/compiler/traversal.hxx> #include <cli/semantics/elements.hxx> diff --git a/cli/cli/txt.cxx b/cli/cli/txt.cxx index 16de45a..1e9094d 100644 --- a/cli/cli/txt.cxx +++ b/cli/cli/txt.cxx @@ -164,13 +164,16 @@ namespace // n > 2 - arg string, short string, long string // size_t n (ds.size ()); - const string& d ( + string d ( n == 1 ? (cd_ == cd_short ? first_sentence (ds[0]) : ds[0]) : (n == 2 ? (cd_ == cd_short ? first_sentence (ds[1]) : ds[1]) : ds[cd_ == cd_short ? 1 : 2])); + if (options.ascii_tree ()) + preprocess_ascii_tree (d); + std::set<string> arg_set; if (n > 1 && options.ansi_color ()) translate_arg (ds[0], arg_set); diff --git a/cli/cli/version.hxx.in b/cli/cli/version.hxx.in index ceb5389..11db861 100644 --- a/cli/cli/version.hxx.in +++ b/cli/cli/version.hxx.in @@ -38,7 +38,7 @@ #define CLI_VERSION_FULL "$cli.version$" -#include <cutl/version.hxx> +#include <libcutl/version.hxx> $libcutl.check(LIBCUTL_VERSION, LIBCUTL_SNAPSHOT)$ |