aboutsummaryrefslogtreecommitdiff
path: root/build2/name.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build2/name.cxx')
-rw-r--r--build2/name.cxx73
1 files changed, 65 insertions, 8 deletions
diff --git a/build2/name.cxx b/build2/name.cxx
index f3e4c0f..de1ee51 100644
--- a/build2/name.cxx
+++ b/build2/name.cxx
@@ -4,15 +4,69 @@
#include <build2/types> // Note: not <build2/names>
+#include <string.h> // strchr()
+
+#include <sstream>
+
#include <build2/diagnostics>
namespace build2
{
ostream&
- operator<< (ostream& os, const name& n)
+ to_stream (ostream& os, const name& n, bool quote, char pair)
{
+ auto write_string = [quote, pair, &os](const string& v)
+ {
+ char sc[] = {
+ '{', '}', '[', ']', '$', '(', ')', // Token endings.
+ ' ', '\t', '\n', '#', // Spaces.
+ '\\', '"', // Escaping and quoting.
+ '%', // Project name separator.
+ pair, // Pair separator, if any.
+ '\0'};
+
+ if (quote && v.find ('\'') != string::npos)
+ {
+ // Quote the string with the double quotes rather than with the single
+ // one. Escape some of the special characters.
+ //
+ os << '"';
+
+ for (auto c: v)
+ {
+ if (strchr ("\\$(\"", c) != nullptr) // Special inside double quotes.
+ os << '\\';
+
+ os << c;
+ }
+
+ os << '"';
+ }
+ else if (quote && v.find_first_of (sc) != string::npos)
+ os << "'" << v << "'";
+ else
+ os << v;
+ };
+
+ auto write_dir = [quote, &os, &write_string](const dir_path& d)
+ {
+ if (quote)
+ {
+ std::ostringstream s;
+ stream_verb (s, stream_verb (os));
+ s << d;
+
+ write_string (s.str ());
+ }
+ else
+ os << d;
+ };
+
if (n.proj != nullptr)
- os << *n.proj << '%';
+ {
+ write_string (*n.proj);
+ os << '%';
+ }
// If the value is empty, then we want to print the directory
// inside {}, e.g., dir{bar/}, not bar/dir{}. We also want to
@@ -23,15 +77,18 @@ namespace build2
bool t (!n.type.empty () || (!d && !v));
if (v)
- os << n.dir;
+ write_dir (n.dir);
if (t)
- os << n.type << '{';
+ {
+ write_string (n.type);
+ os << '{';
+ }
if (v)
- os << n.value;
+ write_string (n.value);
else
- os << n.dir;
+ write_dir (n.dir);
if (t)
os << '}';
@@ -40,13 +97,13 @@ namespace build2
}
ostream&
- operator<< (ostream& os, const names_view& ns)
+ to_stream (ostream& os, const names_view& ns, bool quote, char pair)
{
for (auto i (ns.begin ()), e (ns.end ()); i != e; )
{
const name& n (*i);
++i;
- os << n;
+ to_stream (os, n, quote, pair);
if (n.pair)
os << n.pair;