aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-12-16 12:00:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-12-16 12:00:53 +0200
commit44e1022f8141bd57756c2be4277c728ca7443eb3 (patch)
tree4b3d7e4be8c79d00acc52aec7f1cf64d184f9f73
parent497353a7eeec26d35741afd45b7cd759105f0246 (diff)
Redo string/stream representation of dir{} name/target
Now instead of: dir{foo/bar/} We get: foo/dir{bar/} Which feels more consistent with how we print other names/targets. That is, "directory bar/ in directory foo/" similar how foo/exe{bar} is "executable bar in directory foo/".
-rw-r--r--build2/name.cxx72
-rw-r--r--build2/name.hxx1
-rw-r--r--build2/target.cxx25
-rw-r--r--tests/variable/prerequisite-specific/testscript16
-rw-r--r--unit-tests/name/buildfile6
-rw-r--r--unit-tests/name/driver.cxx96
6 files changed, 170 insertions, 46 deletions
diff --git a/build2/name.cxx b/build2/name.cxx
index d1f3bd7..f71c7c1 100644
--- a/build2/name.cxx
+++ b/build2/name.cxx
@@ -6,8 +6,6 @@
#include <string.h> // strchr()
-#include <sstream>
-
#include <build2/diagnostics.hxx>
namespace build2
@@ -31,15 +29,18 @@ namespace build2
r += '%';
}
- // If the value is empty, then we want to put the directory inside {},
- // e.g., dir{bar/}, not bar/dir{}.
+ // If the value is empty, then we want to put the last component of the
+ // directory inside {}, e.g., dir{bar/}, not bar/dir{}.
//
- bool d (!n.dir.empty ());
bool v (!n.value.empty ());
bool t (!n.type.empty ());
- if (v && d)
- r += n.dir.representation ();
+ const dir_path& pd (v ? n.dir :
+ t ? n.dir.directory () :
+ dir_path ());
+
+ if (!pd.empty ())
+ r += pd.representation ();
if (t)
{
@@ -50,7 +51,7 @@ namespace build2
if (v)
r += n.value;
else
- r += n.dir.representation ();
+ r += (pd.empty () ? n.dir : n.dir.leaf ()).representation ();
if (t)
r += '}';
@@ -95,18 +96,17 @@ namespace build2
os << v;
};
- auto write_dir = [quote, &os, &write_string](const dir_path& d)
+ uint16_t dv (stream_verb (os)); // Directory verbosity.
+
+ auto write_dir = [dv, quote, &os, &write_string] (const dir_path& d)
{
+ const string& s (dv < 2
+ ? diag_relative (d)
+ : d.representation ());
if (quote)
- {
- std::ostringstream s;
- stream_verb (s, stream_verb (os));
- s << d;
-
- write_string (s.str ());
- }
+ write_string (s);
else
- os << d;
+ os << s;
};
// Note: similar to to_string() below.
@@ -123,29 +123,45 @@ namespace build2
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 print {} for an empty
- // name (unless quoted).
+ // If the value is empty, then we want to print the last component of the
+ // directory inside {}, e.g., dir{bar/}, not bar/dir{}. We also want to
+ // print {} for an empty name (unless quoted, which is handled above).
//
bool d (!n.dir.empty ());
bool v (!n.value.empty ());
- bool t (!n.type.empty () || (!d && !v));
+ bool t (!n.type.empty ());
- if (v)
- write_dir (n.dir);
+ // Note: relative() may return empty.
+ //
+ const dir_path& rd (dv < 2 ? relative (n.dir) : n.dir); // Relative.
+ const dir_path& pd (v ? rd :
+ t ? rd.directory () :
+ dir_path ());
- if (t)
+ if (!pd.empty ())
+ write_dir (pd);
+
+ if (t || (!d && !v))
{
- write_string (n.type);
+ if (t)
+ write_string (n.type);
+
os << '{';
}
if (v)
write_string (n.value);
- else
- write_dir (n.dir);
+ else if (d)
+ {
+ if (rd.empty ())
+ write_string (dir_path (".").representation ());
+ else if (!pd.empty ())
+ write_string (rd.leaf ().representation ());
+ else
+ write_dir (rd);
+ }
- if (t)
+ if (t || (!d && !v))
os << '}';
return os;
diff --git a/build2/name.hxx b/build2/name.hxx
index 20a8aa0..aac0ad1 100644
--- a/build2/name.hxx
+++ b/build2/name.hxx
@@ -43,6 +43,7 @@ namespace build2
name (string v): value (move (v)) {}
name (dir_path d): dir (move (d)) {}
name (string t, string v): type (move (t)), value (move (v)) {}
+ name (dir_path d, string v): dir (move (d)), value (move (v)) {}
name (dir_path d, string t, string v)
: dir (move (d)), type (move (t)), value (move (v)) {}
diff --git a/build2/target.cxx b/build2/target.cxx
index aca977e..99c002b 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -418,19 +418,24 @@ namespace build2
ostream&
to_stream (ostream& os, const target_key& k, uint16_t ev)
{
- // If the name is empty, then we want to print the directory
- // inside {}, e.g., dir{bar/}, not bar/dir{}.
+ uint16_t dv (stream_verb (os)); // Directory verbosity.
+
+ // If the name is empty, then we want to print the last component of the
+ // directory inside {}, e.g., dir{bar/}, not bar/dir{}.
//
bool n (!k.name->empty ());
- if (n)
+ // Note: relative() returns empty for './'.
+ //
+ const dir_path& rd (dv < 2 ? relative (*k.dir) : *k.dir); // Relative.
+ const dir_path& pd (n ? rd : rd.directory ()); // Parent.
+
+ if (!pd.empty ())
{
- // Avoid printing './' in './{...}'
- //
- if (stream_verb (os) < 2)
- os << diag_relative (*k.dir, false);
+ if (dv < 2)
+ os << diag_relative (pd);
else
- os << *k.dir;
+ os << pd.representation ();
}
const target_type& tt (*k.type);
@@ -459,7 +464,7 @@ namespace build2
assert (!k.ext);
}
else
- os << *k.dir;
+ os << (rd.empty () ? dir_path (".") : rd.leaf ()).representation ();
os << '}';
@@ -467,7 +472,7 @@ namespace build2
//
if (!k.out->empty ())
{
- if (stream_verb (os) < 2)
+ if (dv < 2)
{
// Don't print '@./'.
//
diff --git a/tests/variable/prerequisite-specific/testscript b/tests/variable/prerequisite-specific/testscript
index c4993f2..ba21557 100644
--- a/tests/variable/prerequisite-specific/testscript
+++ b/tests/variable/prerequisite-specific/testscript
@@ -18,19 +18,19 @@ dir{x}: dir{c}: bar = [bool] true
dump dir{x}
EOI
<stdin>:5:1: dump:
-% dir\{.+/x/\}:%
+% .+/dir\{x/\}:%
{
fox = FOX
}
-% dir\{.+/x/\}: .+:dir\{a/\}:%
+% .+/dir\{x/\}: .+:dir\{a/\}:%
{
foo = FOO
}
-% dir\{.+/x/\}: .+:dir\{b/\}:%
+% .+/dir\{x/\}: .+:dir\{b/\}:%
{
fox = FOX FOX
}
-% dir\{.+/x/\}: .+:dir\{c/\}:%
+% .+/dir\{x/\}: .+:dir\{c/\}:%
{
bar = [bool] true
}
@@ -43,20 +43,20 @@ dir{x} dir{y}: dir{a} dir{b}: foo = FOO
dump dir{x} dir{y}
EOI
<stdin>:2:1: dump:
-% dir\{.+/x/\}: .+:dir\{a/\}:%
+% .+/dir\{x/\}: .+:dir\{a/\}:%
{
foo = FOO
}
-% dir\{.+/x/\}: .+:dir\{b/\}:%
+% .+/dir\{x/\}: .+:dir\{b/\}:%
{
foo = FOO
}
-% dir\{.+/y/\}: .+:dir\{a/\}:%
+% .+/dir\{y/\}: .+:dir\{a/\}:%
{
foo = FOO
}
-% dir\{.+/y/\}: .+:dir\{b/\}:%
+% .+/dir\{y/\}: .+:dir\{b/\}:%
{
foo = FOO
}
diff --git a/unit-tests/name/buildfile b/unit-tests/name/buildfile
new file mode 100644
index 0000000..84f22c4
--- /dev/null
+++ b/unit-tests/name/buildfile
@@ -0,0 +1,6 @@
+# file : unit-tests/name/buildfile
+# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+# license : MIT; see accompanying LICENSE file
+
+include ../../build2/
+exe{driver}: {hxx cxx}{*} ../../build2/libu{b}
diff --git a/unit-tests/name/driver.cxx b/unit-tests/name/driver.cxx
new file mode 100644
index 0000000..d454685
--- /dev/null
+++ b/unit-tests/name/driver.cxx
@@ -0,0 +1,96 @@
+// file : unit-tests/name/driver.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <sstream>
+
+#include <cassert>
+#include <iostream>
+
+#include <build2/types.hxx> // Includes name.
+#include <build2/utility.hxx>
+
+#include <build2/diagnostics.hxx>
+
+using namespace std;
+
+namespace build2
+{
+ int
+ main (int, char*[])
+ {
+ using dir = dir_path;
+
+ // Test string representation.
+ //
+ {
+ auto ts = [] (const name& n) {return to_string (n);};
+
+ assert (ts (name ()) == "");
+
+ assert (ts (name ("foo")) == "foo");
+
+ assert (ts (name (dir ("bar/"))) == "bar/");
+ assert (ts (name (dir ("bar/baz/"))) == "bar/baz/");
+
+ assert (ts (name (dir ("bar/"), "dir", "")) == "dir{bar/}");
+ assert (ts (name (dir ("bar/baz/"), "dir", "")) == "bar/dir{baz/}");
+
+ assert (ts (name (dir ("bar/"), "foo")) == "bar/foo");
+
+ assert (ts (name (dir ("bar/"), "dir", "foo")) == "bar/dir{foo}");
+ assert (ts (name (dir ("bar/baz/"), "dir", "foo")) == "bar/baz/dir{foo}");
+ }
+
+ // Test stream representation.
+ //
+ {
+ auto ts = [] (const name& n, bool quote = true)
+ {
+ ostringstream os;
+ stream_verb (os, 1);
+ to_stream (os, n, quote);
+ return os.str ();
+ };
+
+ assert (ts (name ()) == "''");
+ assert (ts (name (), false) == "{}");
+
+ assert (ts (name ("foo")) == "foo");
+
+ assert (ts (name (dir ("bar/"))) == "bar/");
+ assert (ts (name (dir ("bar/baz/"))) == "bar/baz/");
+
+ assert (ts (name (dir ("bar/"), "dir", "")) == "dir{bar/}");
+ assert (ts (name (dir ("bar/baz/"), "dir", "")) == "bar/dir{baz/}");
+
+ assert (ts (name (dir ("bar/"), "foo")) == "bar/foo");
+
+ assert (ts (name (dir ("bar/"), "dir", "foo")) == "bar/dir{foo}");
+ assert (ts (name (dir ("bar/baz/"), "dir", "foo")) == "bar/baz/dir{foo}");
+
+ // Quoting.
+ //
+ assert (ts (name (dir ("bar baz/"), "dir", "foo fox")) == "'bar baz/'dir{'foo fox'}");
+
+ // Relative logic.
+ //
+#ifndef _WIN32
+ dir rb ("/bar/");
+ relative_base = &rb;
+
+ assert (ts (name (dir ("/bar/"), "dir", "")) == "dir{./}");
+ assert (ts (name (dir ("/bar/"), "", "foo")) == "foo");
+ assert (ts (name (dir ("/bar/baz/"), "dir", "")) == "dir{baz/}");
+#endif
+ }
+
+ return 0;
+ }
+}
+
+int
+main (int argc, char* argv[])
+{
+ return build2::main (argc, argv);
+}