summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--cli-examples/features/driver.cxx25
-rw-r--r--cli-examples/features/options.cli7
-rw-r--r--cli-examples/manifest6
-rw-r--r--cli-tests/manifest6
-rw-r--r--cli/NEWS17
-rw-r--r--cli/cli/buildfile2
-rw-r--r--cli/cli/context.cxx60
-rw-r--r--cli/cli/pregenerated/cli/options.cxx50
-rw-r--r--cli/cli/runtime-header.cxx38
-rw-r--r--cli/cli/runtime-source.cxx102
-rw-r--r--cli/doc/buildfile10
-rw-r--r--cli/doc/pregenerated/cli.14
-rw-r--r--cli/doc/pregenerated/cli.xhtml6
-rw-r--r--cli/manifest6
15 files changed, 254 insertions, 87 deletions
diff --git a/LICENSE b/LICENSE
index 279d01b..313757d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2009-2022 Code Synthesis Tools CC.
+Copyright (c) 2009-2023 Code Synthesis Tools CC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/cli-examples/features/driver.cxx b/cli-examples/features/driver.cxx
index a6299b9..fc364a0 100644
--- a/cli-examples/features/driver.cxx
+++ b/cli-examples/features/driver.cxx
@@ -2,6 +2,7 @@
// author : Boris Kolpackov <boris@codesynthesis.com>
// license : MIT; see accompanying LICENSE file
+#include <utility> // pair
#include <iostream>
#include <iterator>
#include <algorithm>
@@ -45,13 +46,27 @@ main (int argc, char* argv[])
// --map | -m
//
- typedef map<std::string, bool> str_map;
- const str_map& m = o.map ();
- str_map::const_iterator i (m.find ("a"));
+ {
+ typedef map<string, bool> str_map;
+ const str_map& m = o.map ();
+ str_map::const_iterator i (m.find ("a"));
- if (i != m.end ())
- cerr << "value for the 'a' key: " << i->second << endl;
+ if (i != m.end ())
+ cerr << "value for the 'a' map key: " << i->second << endl;
+ }
+ // --multimap
+ //
+ {
+ typedef multimap<string, int> str_multimap;
+ const str_multimap& m = o.multimap ();
+
+ pair<str_multimap::const_iterator, str_multimap::const_iterator> r (
+ m.equal_range ("a"));
+
+ for (str_multimap::const_iterator i (r.first); i != r.second; ++i)
+ cerr << "value for the 'a' multimap key: " << i->second << endl;
+ }
}
catch (const cli::exception& e)
{
diff --git a/cli-examples/features/options.cli b/cli-examples/features/options.cli
index 4065830..d1e4b0c 100644
--- a/cli-examples/features/options.cli
+++ b/cli-examples/features/options.cli
@@ -30,10 +30,11 @@ namespace features
std::vector<int> --vector | -v;
std::set<int> --set | -s;
- // We can also use maps. In this case the option value is expected to have
- // two parts: the key and the value, separated by '='. For example: -m a=1
- // -m =true -m c= -m d (same as -m d=).
+ // We can also use maps and multimaps. In this case the option value is
+ // expected to have two parts: the key and the value, separated by '='.
+ // For example: -m a=1 -m =true -m c= -m d (same as -m d=).
//
std::map<std::string, bool> --map | -m;
+ std::multimap<std::string, int> --multimap;
};
}
diff --git a/cli-examples/manifest b/cli-examples/manifest
index 2db796c..a7f30dd 100644
--- a/cli-examples/manifest
+++ b/cli-examples/manifest
@@ -1,6 +1,6 @@
: 1
name: cli-examples
-version: 1.2.0-b.9.z
+version: 1.2.0
project: cli
summary: Examples of using the CLI language and compiler for C++
license: MIT
@@ -10,5 +10,5 @@ doc-url: https://www.codesynthesis.com/projects/cli/doc/guide/
src-url: https://git.codesynthesis.com/cgit/cli/cli/tree/cli-examples/
email: cli-users@codesynthesis.com ; Mailing list
requires: c++14
-depends: * build2 >= 0.15.0-
-depends: * bpkg >= 0.15.0-
+depends: * build2 >= 0.16.0
+depends: * bpkg >= 0.16.0
diff --git a/cli-tests/manifest b/cli-tests/manifest
index 26c8815..4c3626b 100644
--- a/cli-tests/manifest
+++ b/cli-tests/manifest
@@ -1,6 +1,6 @@
: 1
name: cli-tests
-version: 1.2.0-b.9.z
+version: 1.2.0
project: cli
summary: Tests for the CLI compiler for C++
license: MIT
@@ -10,5 +10,5 @@ doc-url: https://www.codesynthesis.com/projects/cli/doc/guide/
src-url: https://git.codesynthesis.com/cgit/cli/cli/tree/cli-tests/
email: cli-users@codesynthesis.com ; Mailing list
requires: c++14
-depends: * build2 >= 0.15.0-
-depends: * bpkg >= 0.15.0-
+depends: * build2 >= 0.16.0
+depends: * bpkg >= 0.16.0
diff --git a/cli/NEWS b/cli/NEWS
index a1fe25e..07da75f 100644
--- a/cli/NEWS
+++ b/cli/NEWS
@@ -4,8 +4,8 @@ Version 1.2.0
function which can be used to merge several already parsed options class
instances, for example, to implement option appending/overriding.
- * New option, --generate-specifier, triggers the generation of functions
- for determining whether the option was specified on the command line.
+ * New option, --generate-specifier, triggers the generation of functions for
+ determining whether the option was specified on the command line.
* New option, --suppress-undocumented, suppresses the generation of
documentation entries for undocumented options.
@@ -13,12 +13,17 @@ Version 1.2.0
* New option, --cli-namespace, allows changing of the namespace for the
generated CLI support types.
- * The argv_file_scanner now supports double and single-quoting option
- values in option files. This is useful to preserve leading and trailing
+ * The argv_file_scanner now supports double and single-quoting option values
+ in option files. This is useful to preserve leading and trailing
whitespaces as well as to specify empty values.
- * The argv_file_scanner now supports multiple file options as well as
- file search callbacks.
+ * The argv_file_scanner now supports multiple file options as well as file
+ search callbacks.
+
+ * New option, --generate-dep, triggers the generation of the make dependency
+ information. Other related new options: --dep-suffix, --dep-file.
+
+ * Support for std::multimap as an option type in addition to std::map.
Version 1.1.0
diff --git a/cli/cli/buildfile b/cli/cli/buildfile
index 5f51b67..92c3e6e 100644
--- a/cli/cli/buildfile
+++ b/cli/cli/buildfile
@@ -116,7 +116,7 @@ if $develop
--generate-specifier --generate-modifier \
--suppress-undocumented --reserved-name stdout
- diag cli ($<[0])
+ diag cli ($<[0]) -> $>
($<[1]) $options -o $out_base $path($<[0])
# If the result differs from the bootstrap version, copy it over and
diff --git a/cli/cli/context.cxx b/cli/cli/context.cxx
index 46896f2..2c6a733 100644
--- a/cli/cli/context.cxx
+++ b/cli/cli/context.cxx
@@ -1338,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)
@@ -1600,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 ||
@@ -1712,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:
{
@@ -1720,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:
@@ -1987,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;
@@ -2084,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;
@@ -2204,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 ())
{
@@ -2215,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;
}
}
@@ -2241,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/pregenerated/cli/options.cxx b/cli/cli/pregenerated/cli/options.cxx
index 99aa50d..9f0be5f 100644
--- a/cli/cli/pregenerated/cli/options.cxx
+++ b/cli/cli/pregenerated/cli/options.cxx
@@ -676,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)
diff --git a/cli/cli/runtime-header.cxx b/cli/cli/runtime-header.cxx
index c6e06dc..1003e91 100644
--- a/cli/cli/runtime-header.cxx
+++ b/cli/cli/runtime-header.cxx
@@ -88,6 +88,10 @@ 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;
@@ -107,7 +111,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~unknown_option () throw ();"
+ << "~unknown_option () " << nothrow << ';'
<< endl
<< "unknown_option (const std::string& option);"
<< endl
@@ -118,7 +122,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_;"
@@ -128,7 +132,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~unknown_argument () throw ();"
+ << "~unknown_argument () " << nothrow << ';'
<< endl
<< "unknown_argument (const std::string& argument);"
<< endl
@@ -139,7 +143,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_;"
@@ -149,7 +153,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~missing_value () throw ();"
+ << "~missing_value () " << nothrow << ';'
<< endl
<< "missing_value (const std::string& option);"
<< endl
@@ -160,7 +164,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_;"
@@ -170,7 +174,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~invalid_value () throw ();"
+ << "~invalid_value () " << nothrow << ';'
<< endl
<< "invalid_value (const std::string& option," << endl
<< "const std::string& value," << endl
@@ -189,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_;"
@@ -204,7 +208,7 @@ generate_runtime_header (context& ctx)
<< "print (" << os_type << "&) const;"
<< endl
<< "virtual const char*" << endl
- << "what () const throw ();"
+ << "what () const " << nothrow << ';'
<< "};";
if (ctx.options.generate_file_scanner ())
@@ -213,7 +217,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~file_io_failure () throw ();"
+ << "~file_io_failure () " << nothrow << ';'
<< endl
<< "file_io_failure (const std::string& file);"
<< endl
@@ -224,7 +228,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 file_;"
@@ -234,7 +238,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~unmatched_quote () throw ();"
+ << "~unmatched_quote () " << nothrow << ';'
<< endl
<< "unmatched_quote (const std::string& argument);"
<< endl
@@ -245,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_;"
@@ -258,7 +262,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~unexpected_group () throw ();"
+ << "~unexpected_group () " << nothrow << ';'
<< endl
<< "unexpected_group (const std::string& argument," << endl
<< "const std::string& group);"
@@ -273,7 +277,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 argument_;"
@@ -284,7 +288,7 @@ generate_runtime_header (context& ctx)
<< "{"
<< "public:" << endl
<< "virtual" << endl
- << "~group_separator () throw ();"
+ << "~group_separator () " << nothrow << ';'
<< endl
<< "// Note: either (but not both) can be empty." << endl
<< "//" << endl
@@ -301,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_;"
diff --git a/cli/cli/runtime-source.cxx b/cli/cli/runtime-source.cxx
index 9620648..11cd746 100644
--- a/cli/cli/runtime-source.cxx
+++ b/cli/cli/runtime-source.cxx
@@ -31,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
<< "{"
<< "}"
@@ -47,7 +51,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "}"
<< "const char* unknown_option::" << endl
- << "what () const throw ()"
+ << "what () const " << nothrow
<< "{"
<< "return \"unknown option\";"
<< "}";
@@ -57,7 +61,7 @@ generate_runtime_source (context& ctx, bool complete)
os << "// unknown_argument" << endl
<< "//" << endl
<< "unknown_argument::" << endl
- << "~unknown_argument () throw ()"
+ << "~unknown_argument () " << nothrow
<< "{"
<< "}"
@@ -68,7 +72,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "}"
<< "const char* unknown_argument::" << endl
- << "what () const throw ()"
+ << "what () const " << nothrow
<< "{"
<< "return \"unknown argument\";"
<< "}";
@@ -78,7 +82,7 @@ generate_runtime_source (context& ctx, bool complete)
os << "// missing_value" << endl
<< "//" << endl
<< "missing_value::" << endl
- << "~missing_value () throw ()"
+ << "~missing_value () " << nothrow
<< "{"
<< "}"
@@ -89,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\";"
<< "}";
@@ -99,7 +103,7 @@ generate_runtime_source (context& ctx, bool complete)
os << "// invalid_value" << endl
<< "//" << endl
<< "invalid_value::" << endl
- << "~invalid_value () throw ()"
+ << "~invalid_value () " << nothrow
<< "{"
<< "}"
@@ -115,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\";"
<< "}";
@@ -131,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\";"
<< "}";
@@ -143,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
<< "{"
<< "}"
@@ -155,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\";"
<< "}";
@@ -165,7 +169,7 @@ generate_runtime_source (context& ctx, bool complete)
os << "// unmatched_quote" << endl
<< "//" << endl
<< "unmatched_quote::" << endl
- << "~unmatched_quote () throw ()"
+ << "~unmatched_quote () " << nothrow
<< "{"
<< "}"
@@ -177,7 +181,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "}"
<< "const char* unmatched_quote::" << endl
- << "what () const throw ()"
+ << "what () const " << nothrow
<< "{"
<< "return \"unmatched quote\";"
<< "}";
@@ -191,7 +195,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "//" << endl
<< "unexpected_group::" << endl
- << "~unexpected_group () throw ()"
+ << "~unexpected_group () " << nothrow
<< "{"
<< "}"
@@ -203,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\";"
<< "}";
@@ -214,7 +218,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "//" << endl
<< "group_separator::" << endl
- << "~group_separator () throw ()"
+ << "~group_separator () " << nothrow
<< "{"
<< "}"
@@ -238,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 ());"
@@ -1216,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
diff --git a/cli/doc/buildfile b/cli/doc/buildfile
index 07aa917..753b620 100644
--- a/cli/doc/buildfile
+++ b/cli/doc/buildfile
@@ -42,7 +42,7 @@ pregenerated/{man1 xhtml}{*}: dist = (!$develop)
if $develop
{
- doc_version = [string] "$version.major\.$version.minor\.$version.patch"
+ doc_version = [string] "$version.major.$version.minor.$version.patch"
if $version.pre_release
doc_version += "-$version.pre_release_string"
@@ -73,7 +73,7 @@ man1{cli}: ../cli/cli{options} file{cli-prologue.1 cli-epilogue.1}
%
if $develop
{{
- diag cli --man ($<[1])
+ diag 'cli --man' ($<[1]) -> $>
# Use the copyright year to approximate the last authoring date.
#
@@ -96,7 +96,7 @@ xhtml{cli}: ../cli/cli{options} file{cli-prologue.xhtml cli-epilogue.xhtml}
%
if $develop
{{
- diag cli --html ($<[1])
+ diag 'cli --html' ($<[1]) -> $>
($<[0]) --generate-html $man_options \
--html-prologue-file $path($<[2]) \
@@ -177,7 +177,7 @@ if $html2pdf
{{
options =
- diag html2ps ($<[0])
+ diag html2ps ($<[0]) -> $>
$html2ps $options -f $path($<[1]) -o $path($>) $path($<[0])
cp --no-cleanup $path($>) $src_base/pregenerated/cli-guide.ps
@@ -189,7 +189,7 @@ if $html2pdf
{{
options = -dOptimize=true -dEmbedAllFonts=true
- diag ps2pdf ($<[0])
+ diag ps2pdf ($<[0]) -> $>
$ps2pdf $options $path($<[0]) $path($>)
cp --no-cleanup $path($>) $src_base/pregenerated/cli-guide.pdf
diff --git a/cli/doc/pregenerated/cli.1 b/cli/doc/pregenerated/cli.1
index 91e18f5..d452ca4 100644
--- a/cli/doc/pregenerated/cli.1
+++ b/cli/doc/pregenerated/cli.1
@@ -1,7 +1,7 @@
.\" Process this file with
.\" groff -man -Tascii cli.1
.\"
-.TH CLI 1 "January 2022" "CLI 1.2.0-b.9"
+.TH CLI 1 "January 2023" "CLI 1.2.0"
.SH NAME
cli \- command line interface compiler for C++
.\"
@@ -431,7 +431,7 @@ Send bug reports to the cli-users@codesynthesis.com mailing list.
.\" COPYRIGHT
.\"
.SH COPYRIGHT
-Copyright (c) 2009-2022 Code Synthesis Tools CC.
+Copyright (c) 2009-2023 Code Synthesis Tools CC.
Permission is granted to copy, distribute and/or modify this document under
the terms of the MIT License. Copy of this license can be obtained from
diff --git a/cli/doc/pregenerated/cli.xhtml b/cli/doc/pregenerated/cli.xhtml
index 84d013a..2a4f751 100644
--- a/cli/doc/pregenerated/cli.xhtml
+++ b/cli/doc/pregenerated/cli.xhtml
@@ -2,9 +2,9 @@
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
- <title>CLI 1.2.0-b.9 Compiler Command Line Manual</title>
+ <title>CLI 1.2.0 Compiler Command Line Manual</title>
- <meta name="copyright" content="&#169; 2009-2022 Code Synthesis Tools CC"/>
+ <meta name="copyright" content="&#169; 2009-2023 Code Synthesis Tools CC"/>
<meta name="keywords" content="cli,command,line,interface,compiler,c++"/>
<meta name="description" content="CLI Compiler Command Line Manual"/>
@@ -592,7 +592,7 @@ arg+{ --foo } # 'arg+{' ...</pre>
</div>
<div id="footer">
- Copyright &#169; 2009-2022 Code Synthesis Tools CC.
+ Copyright &#169; 2009-2023 Code Synthesis Tools CC.
<div id="terms">
Permission is granted to copy, distribute and/or modify this
diff --git a/cli/manifest b/cli/manifest
index 40ee1bb..a90072b 100644
--- a/cli/manifest
+++ b/cli/manifest
@@ -1,6 +1,6 @@
: 1
name: cli
-version: 1.2.0-b.9.z
+version: 1.2.0
summary: Command line interface (CLI) compiler for C++
license: MIT
topics: C++, command line interface, source code generation, \
@@ -14,8 +14,8 @@ email: cli-users@codesynthesis.com ; Mailing list
build-warning-email: builds@codesynthesis.com
requires: c++14
requires: host
-depends: * build2 >= 0.15.0-
-depends: * bpkg >= 0.15.0-
+depends: * build2 >= 0.16.0
+depends: * bpkg >= 0.16.0
depends: libcutl ^1.11.0-
tests: * cli-tests == $
examples: * cli-examples == $