aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-13 15:50:17 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-13 15:50:17 +0200
commitace1743f7f78bb13f99553d6e97ad1beecf1ba99 (patch)
tree595bc9dad989e44f4be9a67e351219f3248dc5f0
parent534f9d8db025d58c9ce23f3b81a37e8c34386a27 (diff)
Add separate type to represent directory paths
-rw-r--r--build/algorithm2
-rw-r--r--build/algorithm.cxx6
-rw-r--r--build/b.cxx60
-rw-r--r--build/config/module.cxx4
-rw-r--r--build/config/operation.cxx33
-rw-r--r--build/context35
-rw-r--r--build/context.cxx65
-rw-r--r--build/context.txx40
-rw-r--r--build/cxx/module.cxx4
-rw-r--r--build/cxx/rule.cxx8
-rw-r--r--build/diagnostics14
-rw-r--r--build/diagnostics.cxx18
-rw-r--r--build/dump.cxx20
-rw-r--r--build/file8
-rw-r--r--build/file.cxx32
-rw-r--r--build/name8
-rw-r--r--build/name.cxx48
-rw-r--r--build/operation8
-rw-r--r--build/operation.cxx6
-rw-r--r--build/parser8
-rw-r--r--build/parser.cxx52
-rw-r--r--build/path170
-rw-r--r--build/path-io16
-rw-r--r--build/path-map14
-rw-r--r--build/path.cxx51
-rw-r--r--build/path.ixx74
-rw-r--r--build/path.txx123
-rw-r--r--build/prerequisite6
-rw-r--r--build/prerequisite.cxx58
-rw-r--r--build/scope33
-rw-r--r--build/scope.cxx6
-rw-r--r--build/search2
-rw-r--r--build/search.cxx8
-rw-r--r--build/spec4
-rw-r--r--build/spec.cxx15
-rw-r--r--build/target14
-rw-r--r--build/target.cxx38
-rw-r--r--build/types1
-rw-r--r--build/utility1
-rw-r--r--build/utility.cxx1
-rw-r--r--build/variable15
-rw-r--r--build/variable.cxx8
-rw-r--r--build/variable.ixx2
43 files changed, 606 insertions, 533 deletions
diff --git a/build/algorithm b/build/algorithm
index c056d57..7d2c226 100644
--- a/build/algorithm
+++ b/build/algorithm
@@ -35,7 +35,7 @@ namespace build
// in the same or a subdirectory of dir.
//
void
- search_and_match (action, target&, const path& dir);
+ search_and_match (action, target&, const dir_path& dir);
// Inject dependency on the parent directory fsdir{}, unless it is
// the project's out_root (or is outside of any project; think, for
diff --git a/build/algorithm.cxx b/build/algorithm.cxx
index 3fc2e92..7675b0c 100644
--- a/build/algorithm.cxx
+++ b/build/algorithm.cxx
@@ -155,7 +155,7 @@ namespace build
}
void
- search_and_match (action a, target& t, const path& d)
+ search_and_match (action a, target& t, const dir_path& d)
{
for (prerequisite& p: t.prerequisites)
{
@@ -177,12 +177,12 @@ namespace build
if (scope* rs = s.root_scope ()) // Could be outside any project.
{
- const path& out_root (rs->path ());
+ const dir_path& out_root (rs->path ());
// If t is a directory (name is empty), say foo/bar/, then
// t is bar and its parent directory is foo/.
//
- const path& d (t.name.empty () ? t.dir.directory () : t.dir);
+ const dir_path& d (t.name.empty () ? t.dir.directory () : t.dir);
if (d.sub (out_root) && d != out_root)
{
diff --git a/build/b.cxx b/build/b.cxx
index 8d2ca47..e53844c 100644
--- a/build/b.cxx
+++ b/build/b.cxx
@@ -47,33 +47,33 @@ namespace build
// based on the presence of known special files. Return empty
// path if not found.
//
- path
- find_src_root (const path& b)
+ dir_path
+ find_src_root (const dir_path& b)
{
- for (path d (b); !d.root () && d != home; d = d.directory ())
+ for (dir_path d (b); !d.root () && d != home; d = d.directory ())
{
if (is_src_root (d))
return d;
}
- return path ();
+ return dir_path ();
}
// The same but for out. Note that we also check whether a
// directory happens to be src_root, in case this is an in-
// tree build.
//
- path
- find_out_root (const path& b, bool& src)
+ dir_path
+ find_out_root (const dir_path& b, bool& src)
{
- for (path d (b); !d.root () && d != home; d = d.directory ())
+ for (dir_path d (b); !d.root () && d != home; d = d.directory ())
{
if ((src = is_src_root (d)) || is_out_root (d))
return d;
}
src = false;
- return path ();
+ return dir_path ();
}
}
@@ -179,10 +179,10 @@ main (int argc, char* argv[])
// Figure out work and home directories.
//
- work = path::current ();
+ work = dir_path::current ();
if (const char* h = getenv ("HOME"))
- home = path (h);
+ home = dir_path (h);
else
{
struct passwd* pw (getpwuid (getuid ()));
@@ -193,13 +193,13 @@ main (int argc, char* argv[])
fail << "unable to determine home directory: " << msg;
}
- home = path (pw->pw_dir);
+ home = dir_path (pw->pw_dir);
}
if (verb >= 4)
{
- trace << "work dir: " << work.string ();
- trace << "home dir: " << home.string ();
+ trace << "work dir: " << work;
+ trace << "home dir: " << home;
}
// Initialize the dependency state.
@@ -293,7 +293,7 @@ main (int argc, char* argv[])
const location l ("<buildspec>", 1, 0); //@@ TODO
if (os.empty ()) // Default target: dir{}.
- os.push_back (targetspec (name ("dir", path (), string ())));
+ os.push_back (targetspec (name ("dir", dir_path (), string ())));
operation_id oid (0); // Not yet translated.
const operation_info* oif (nullptr);
@@ -332,7 +332,7 @@ main (int argc, char* argv[])
// value has a directory prefix. This has a good balance of
// control and the expected result in most cases.
//
- path out_base (tn.dir);
+ dir_path out_base (tn.dir);
if (out_base.empty ())
{
const string& v (tn.value);
@@ -342,7 +342,7 @@ main (int argc, char* argv[])
// This code must be consistent with target_type_map::find().
//
if (v.empty () || v == "." || v == ".." || tn.type == "dir")
- out_base = path (v);
+ out_base = dir_path (v);
else
{
// See if there is a directory part in value. We cannot
@@ -352,7 +352,7 @@ main (int argc, char* argv[])
path::size_type i (path::traits::rfind_separator (v));
if (i != string::npos)
- out_base = path (v, i != 0 ? i : 1); // Special case: "/".
+ out_base = dir_path (v, i != 0 ? i : 1); // Special case: "/".
}
}
@@ -368,10 +368,10 @@ main (int argc, char* argv[])
// diagnostics for such cases.
//
bool guessing (false);
- path src_root;
- path out_root;
+ dir_path src_root;
+ dir_path out_root;
- path& src_base (ts.src_base); // Update it in buildspec.
+ dir_path& src_base (ts.src_base); // Update it in buildspec.
if (!src_base.empty ())
{
@@ -427,9 +427,9 @@ main (int argc, char* argv[])
catch (const invalid_path&)
{
fail << "out_base directory suffix does not match src_base"
- << info << "src_base is " << src_base.string ()
- << info << "src_root is " << src_root.string ()
- << info << "out_base is " << out_base.string ()
+ << info << "src_base is " << src_base
+ << info << "src_root is " << src_root
+ << info << "out_base is " << out_base
<< info << "consider explicitly specifying src_base "
<< "for " << tn;
}
@@ -470,7 +470,7 @@ main (int argc, char* argv[])
// If we also have src_root specified by the user, make
// sure they match.
//
- const path& p (v.as<const path&> ());
+ const dir_path& p (v.as<const dir_path&> ());
if (src_root.empty ())
src_root = p;
@@ -503,7 +503,7 @@ main (int argc, char* argv[])
v = src_root;
}
- rs.src_path_ = &v.as<const path&> ();
+ rs.src_path_ = &v.as<const dir_path&> ();
}
// At this stage we should have both roots and out_base figured
@@ -719,10 +719,10 @@ main (int argc, char* argv[])
if (verb >= 4)
{
trace << "target " << tn << ':';
- trace << " out_base: " << out_base.string ();
- trace << " src_base: " << src_base.string ();
- trace << " out_root: " << out_root.string ();
- trace << " src_root: " << src_root.string ();
+ trace << " out_base: " << out_base;
+ trace << " src_base: " << src_base;
+ trace << " out_root: " << out_root;
+ trace << " src_root: " << src_root;
}
path bf (src_base / path ("buildfile"));
@@ -753,7 +753,7 @@ main (int argc, char* argv[])
// If the directory is relative, assume it is relative to work
// (must be consistent with how we derived out_base above).
//
- path& d (tn.dir);
+ dir_path& d (tn.dir);
if (d.relative ())
d = work / d;
diff --git a/build/config/module.cxx b/build/config/module.cxx
index 59fbb1f..9ed0cec 100644
--- a/build/config/module.cxx
+++ b/build/config/module.cxx
@@ -36,8 +36,8 @@ namespace build
if (&root != &base)
fail (l) << "config module must be initialized in project root scope";
- const path& out_root (root.path ());
- level4 ([&]{trace << "for " << out_root << '/';});
+ const dir_path& out_root (root.path ());
+ level4 ([&]{trace << "for " << out_root;});
// Register meta-operations.
//
diff --git a/build/config/operation.cxx b/build/config/operation.cxx
index 85d0d07..14f2a0a 100644
--- a/build/config/operation.cxx
+++ b/build/config/operation.cxx
@@ -18,8 +18,8 @@ namespace build
{
namespace config
{
- static const path build_dir ("build");
- static const path bootstrap_dir ("build/bootstrap");
+ static const dir_path build_dir ("build");
+ static const dir_path bootstrap_dir ("build/bootstrap");
static const path config_file ("build/config.build");
static const path src_root_file ("build/bootstrap/src-root.build");
@@ -36,7 +36,7 @@ namespace build
}
static void
- save_src_root (const path& out_root, const path& src_root)
+ save_src_root (const dir_path& out_root, const dir_path& src_root)
{
path f (out_root / src_root_file);
@@ -57,7 +57,7 @@ namespace build
//
ofs << "# Created automatically by the config module." << endl
<< "#" << endl
- << "src_root = " << src_root.string () << '/' << endl;
+ << "src_root = " << src_root << endl;
}
catch (const ios_base::failure&)
{
@@ -68,7 +68,7 @@ namespace build
static void
save_config (scope& root)
{
- const path& out_root (root.path ());
+ const dir_path& out_root (root.path ());
path f (out_root / config_file);
if (verb >= 1)
@@ -90,7 +90,7 @@ namespace build
if (auto v = root.ro_variables ()["amalgamation"])
{
- const path& d (v.as<const path&> ());
+ const dir_path& d (v.as<const dir_path&> ());
ofs << "# Base configuration inherited from " << d << "/ ." << endl
<< "#" << endl;
@@ -144,8 +144,8 @@ namespace build
{
tracer trace ("configure_project");
- const path& out_root (root.path ());
- const path& src_root (root.src_path ());
+ const dir_path& out_root (root.path ());
+ const dir_path& src_root (root.src_path ());
// Make sure the directories exist.
//
@@ -182,7 +182,7 @@ namespace build
{
for (const name& n: v.as<const list_value&> ())
{
- path out_nroot (out_root / n.dir);
+ dir_path out_nroot (out_root / n.dir);
scope& nroot (scopes.find (out_nroot));
// @@ Strictly speaking we need to check whether the config
@@ -239,8 +239,8 @@ namespace build
static void
disfigure_load (const path& bf,
scope&,
- const path&,
- const path&,
+ const dir_path&,
+ const dir_path&,
const location&)
{
tracer trace ("disfigure_load");
@@ -266,8 +266,8 @@ namespace build
bool m (false); // Keep track of whether we actually did anything.
- const path& out_root (root.path ());
- const path& src_root (root.src_path ());
+ const dir_path& out_root (root.path ());
+ const dir_path& src_root (root.src_path ());
// Disfigure subprojects. Since we don't load buildfiles during
// disfigure, we do it for all known subprojects.
@@ -278,15 +278,16 @@ namespace build
{
// Create and bootstrap subproject's root scope.
//
- path out_nroot (out_root / n.dir);
- path src_nroot (src_root / n.dir);
+ dir_path out_nroot (out_root / n.dir);
+ dir_path src_nroot (src_root / n.dir);
scope& nroot (create_root (out_nroot, src_nroot));
bootstrap_out (nroot);
// Check if the bootstrap process changed src_root.
//
- const path& p (nroot.variables["src_root"].as<const path&> ());
+ const dir_path& p (
+ nroot.variables["src_root"].as<const dir_path&> ());
if (src_nroot != p)
fail << "bootstrapped src_root " << p << " does not match "
diff --git a/build/context b/build/context
index 39e00e7..0e28472 100644
--- a/build/context
+++ b/build/context
@@ -18,8 +18,8 @@ namespace build
class scope;
class file;
- extern path work;
- extern path home;
+ extern dir_path work;
+ extern dir_path home;
// Current action (meta/operation).
//
@@ -54,7 +54,7 @@ namespace build
// important. See the fsdir{} rule for details.
//
fs_status<mkdir_status>
- mkdir (const path&);
+ mkdir (const dir_path&);
// Remove the file and print the standard diagnostics. The second
// argument is only used in diagnostics, to print the target name.
@@ -72,39 +72,42 @@ namespace build
//
template <typename T>
fs_status<rmdir_status>
- rmdir (const path&, const T& target);
+ rmdir (const dir_path&, const T& target);
inline fs_status<rmdir_status>
- rmdir (const path& d) {return rmdir (d, d);}
+ rmdir (const dir_path& d) {return rmdir (d, d);}
// Return the src/out directory corresponding to the given out/src. The
// passed directory should be a sub-directory of out/src_root.
//
- path
- src_out (const path& out, scope&);
+ dir_path
+ src_out (const dir_path& out, scope&);
- path
- src_out (const path& out, const path& out_root, const path& src_root);
+ dir_path
+ src_out (const dir_path& out,
+ const dir_path& out_root, const dir_path& src_root);
- path
- out_src (const path& src, scope&);
+ dir_path
+ out_src (const dir_path& src, scope&);
- path
- out_src (const path& src, const path& out_root, const path& src_root);
+ dir_path
+ out_src (const dir_path& src,
+ const dir_path& out_root, const dir_path& src_root);
// If possible and beneficial, translate an absolute, normalized path
// into relative to the relative_base directory, which is normally
// work.
//
- path
- relative (const path&);
+ template <typename K>
+ basic_path<char, K>
+ relative (const basic_path<char, K>&);
// By default this points to work. Setting this to something else
// should only be done in tightly controlled, non-parallel
// situations (see dump). If base is empty, then relative()
// returns the original path.
//
- extern const path* relative_base;
+ extern const dir_path* relative_base;
}
#include <build/context.txx>
diff --git a/build/context.cxx b/build/context.cxx
index 7303e7d..d87ce11 100644
--- a/build/context.cxx
+++ b/build/context.cxx
@@ -15,8 +15,8 @@ using namespace std;
namespace build
{
- path work;
- path home;
+ dir_path work;
+ dir_path home;
const meta_operation_info* current_mif;
const operation_info* current_oif;
@@ -35,9 +35,9 @@ namespace build
// See the comment in <build/path-map> for details.
//
#ifdef _WIN32
- global_scope = &scopes[path ()];
+ global_scope = &scopes[dir_path ()];
#else
- global_scope = &scopes[path ("/")];
+ global_scope = &scopes[dir_path ("/")];
#endif
global_scope->variables["work"] = work;
@@ -45,7 +45,7 @@ namespace build
}
fs_status<mkdir_status>
- mkdir (const path& d)
+ mkdir (const dir_path& d)
{
// We don't want to print the command if the directory already
// exists. This makes the below code a bit ugly.
@@ -78,68 +78,35 @@ namespace build
return ms;
}
- path
- src_out (const path& out, scope& s)
+ dir_path
+ src_out (const dir_path& out, scope& s)
{
scope& rs (*s.root_scope ());
return src_out (out, rs.path (), rs.src_path ());
}
- path
- out_src (const path& src, scope& s)
+ dir_path
+ out_src (const dir_path& src, scope& s)
{
scope& rs (*s.root_scope ());
return out_src (src, rs.path (), rs.src_path ());
}
- path
- src_out (const path& o, const path& out_root, const path& src_root)
+ dir_path
+ src_out (const dir_path& o,
+ const dir_path& out_root, const dir_path& src_root)
{
assert (o.sub (out_root));
return src_root / o.leaf (out_root);
}
- path
- out_src (const path& s, const path& out_root, const path& src_root)
+ dir_path
+ out_src (const dir_path& s,
+ const dir_path& out_root, const dir_path& src_root)
{
assert (s.sub (src_root));
return out_root / s.leaf (src_root);
}
- const path* relative_base = &work;
-
- path
- relative (const path& p)
- {
- const path& b (*relative_base);
-
- if (b.empty ())
- return p;
-
- if (p.sub (b))
- return p.leaf (b);
-
- // If base is a sub-path of {src,out}_root and this path is also a
- // sub-path of it, then use '..' to form a relative path.
- //
- // Don't think this is a good heuristic. For example, why shouldn't
- // we display paths from imported projects as relative if they are
- // more readable than absolute?
- //
- /*
- if ((work.sub (src_root) && p.sub (src_root)) ||
- (work.sub (out_root) && p.sub (out_root)))
- return p.relative (work);
- */
-
- if (p.root_directory () == b.root_directory ())
- {
- path r (p.relative (b));
-
- if (r.string ().size () < p.string ().size ())
- return r;
- }
-
- return p;
- }
+ const dir_path* relative_base = &work;
}
diff --git a/build/context.txx b/build/context.txx
index 53081b1..218c65e 100644
--- a/build/context.txx
+++ b/build/context.txx
@@ -46,7 +46,7 @@ namespace build
template <typename T>
fs_status<rmdir_status>
- rmdir (const path& d, const T& t)
+ rmdir (const dir_path& d, const T& t)
{
bool w (d == work); // Don't try to remove working directory.
rmdir_status rs;
@@ -97,4 +97,42 @@ namespace build
return rs;
}
+
+ template <typename K>
+ basic_path<char, K>
+ relative (const basic_path<char, K>& p)
+ {
+ typedef basic_path<char, K> path;
+
+ const dir_path& b (*relative_base);
+
+ if (b.empty ())
+ return p;
+
+ if (p.sub (b))
+ return p.leaf (b);
+
+ // If base is a sub-path of {src,out}_root and this path is also a
+ // sub-path of it, then use '..' to form a relative path.
+ //
+ // Don't think this is a good heuristic. For example, why shouldn't
+ // we display paths from imported projects as relative if they are
+ // more readable than absolute?
+ //
+ /*
+ if ((work.sub (src_root) && p.sub (src_root)) ||
+ (work.sub (out_root) && p.sub (out_root)))
+ return p.relative (work);
+ */
+
+ if (p.root_directory () == b.root_directory ())
+ {
+ path r (p.relative (b));
+
+ if (r.string ().size () < p.string ().size ())
+ return r;
+ }
+
+ return p;
+ }
}
diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx
index e29d311..3c9a4b6 100644
--- a/build/cxx/module.cxx
+++ b/build/cxx/module.cxx
@@ -33,8 +33,8 @@ namespace build
//@@ TODO: need to register target types, rules here instead of main().
- const path& out_root (root.path ());
- level4 ([&]{trace << "for " << out_root << '/';});
+ const dir_path& out_root (root.path ());
+ level4 ([&]{trace << "for " << out_root;});
// Configure.
//
diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx
index b4cfb1c..d8a7190 100644
--- a/build/cxx/rule.cxx
+++ b/build/cxx/rule.cxx
@@ -270,7 +270,7 @@ namespace build
// extension rather than NULL (which would signify that the
// extension needs to be added).
//
- path d (f.directory ());
+ dir_path d (f.directory ());
string n (f.leaf ().base ().string ());
const char* es (f.extension ());
const string* e (&extension_pool.find (es != nullptr ? es : ""));
@@ -471,8 +471,8 @@ namespace build
// We may need the project roots for rule chaining (see below).
// We will resolve them lazily only if needed.
//
- const path* out_root (nullptr);
- const path* src_root (nullptr);
+ const dir_path* out_root (nullptr);
+ const dir_path* src_root (nullptr);
// Process prerequisites: do rule chaining for C and C++ source
// files as well as search and match.
@@ -516,7 +516,7 @@ namespace build
// c(xx){} directory is most likely under src_root, it is also
// possible it is under out_root (e.g., generated source).
//
- path d;
+ dir_path d;
if (cp.dir.relative () || cp.dir.sub (*out_root))
d = cp.dir;
else
diff --git a/build/diagnostics b/build/diagnostics
index 3ec80a3..09adaca 100644
--- a/build/diagnostics
+++ b/build/diagnostics
@@ -14,7 +14,8 @@
#include <exception>
#include <type_traits>
-#include <build/path> // <build/path-io> included at the end.
+#include <build/path>
+#include <build/path-io>
namespace build
{
@@ -24,12 +25,17 @@ namespace build
class failed: public std::exception {};
// In addition to calling relative(), this function also uses shorter
- // notations such as '~/'. If the path is the same as base, it returns
- // '.'.
+ // notations such as '~/'.
//
std::string
diag_relative (const path&);
+ // As above but also adds trailing '/'. If the path is the same as
+ // base, returns "./" if current is true and empty string otherwise.
+ //
+ std::string
+ diag_relative (const dir_path&, bool current = true);
+
// Action phrases, e.g., "configure update exe{foo}", "updating exe{foo}",
// and "updating exe{foo} already configured".
//
@@ -357,6 +363,4 @@ namespace build
extern const fail_mark<failed> fail;
}
-#include <build/path-io>
-
#endif // BUILD_DIAGNOSTICS
diff --git a/build/diagnostics.cxx b/build/diagnostics.cxx
index 2fad0d3..bc157ed 100644
--- a/build/diagnostics.cxx
+++ b/build/diagnostics.cxx
@@ -57,6 +57,24 @@ namespace build
return p.string ();
}
+ string
+ diag_relative (const dir_path& d, bool cur)
+ {
+ string r (diag_relative (static_cast<const path&> (d)));
+
+ // Translate "." to empty.
+ //
+ if (!cur && d.absolute () && r == ".")
+ r.clear ();
+
+ // Add trailing '/'.
+ //
+ if (!r.empty () && !dir_path::traits::is_separator (r.back ()))
+ r += '/';
+
+ return r;
+ }
+
// diag_do(), etc.
//
string
diff --git a/build/dump.cxx b/build/dump.cxx
index 05ec679..b41e489 100644
--- a/build/dump.cxx
+++ b/build/dump.cxx
@@ -25,7 +25,12 @@ namespace build
for (const prerequisite& p: t.prerequisites)
{
- os << ' ' << p;
+ os << ' ';
+
+ if (p.target != nullptr)
+ os << *p.target;
+ else
+ os << p;
}
}
@@ -36,15 +41,14 @@ namespace build
string& ind,
set<const target*>& rts)
{
- string d (relative (p.path ()).string ());
-
- if (d.back () != path::traits::directory_separator)
- d += '/';
-
- os << ind << d << ":" << endl
+ // We don't want the extra notations (e.g., ~/) provided by
+ // diag_relative() since we want the path to be relative to
+ // the outer scope.
+ //
+ os << ind << relative (p.path ()) << ":" << endl
<< ind << '{';
- const path* orb (relative_base);
+ const dir_path* orb (relative_base);
relative_base = &p.path ();
ind += " ";
diff --git a/build/file b/build/file
index 32cac48..937be1b 100644
--- a/build/file
+++ b/build/file
@@ -14,10 +14,10 @@ namespace build
struct location;
bool
- is_src_root (const path&);
+ is_src_root (const dir_path&);
bool
- is_out_root (const path&);
+ is_out_root (const dir_path&);
void
source (const path& buildfile, scope& root, scope& base);
@@ -37,7 +37,7 @@ namespace build
// passed src_root value is not empty.
//
scope&
- create_root (const path& out_root, const path& src_root);
+ create_root (const dir_path& out_root, const dir_path& src_root);
// Bootstrap the project's root scope, the out part.
//
@@ -61,7 +61,7 @@ namespace build
// none were created. Loading is done by load_root_pre() below.
//
scope&
- create_bootstrap_inner (scope& root, const path& out_base);
+ create_bootstrap_inner (scope& root, const dir_path& out_base);
// Load project's root[-pre].build unless already loaded. Also
// make sure all outer root scopes are loaded prior to loading
diff --git a/build/file.cxx b/build/file.cxx
index 70a5ed8..faffce5 100644
--- a/build/file.cxx
+++ b/build/file.cxx
@@ -16,14 +16,14 @@ using namespace std;
namespace build
{
bool
- is_src_root (const path& d)
+ is_src_root (const dir_path& d)
{
return file_exists (d / path ("build/bootstrap.build")) ||
file_exists (d / path ("build/root.build"));
}
bool
- is_out_root (const path& d)
+ is_out_root (const dir_path& d)
{
return file_exists (d / path ("build/bootstrap/src-root.build"));
}
@@ -67,7 +67,7 @@ namespace build
}
scope&
- create_root (const path& out_root, const path& src_root)
+ create_root (const dir_path& out_root, const dir_path& src_root)
{
scope& rs (scopes.insert (out_root, true).first);
@@ -96,7 +96,7 @@ namespace build
v = out_root;
else
{
- const path& p (v.as<const path&> ());
+ const dir_path& p (v.as<const dir_path&> ());
if (p != out_root)
fail << "new out_root " << out_root << " does not match "
@@ -112,7 +112,7 @@ namespace build
v = src_root;
else
{
- const path& p (v.as<const path&> ());
+ const dir_path& p (v.as<const dir_path&> ());
if (p != src_root)
fail << "new src_root " << src_root << " does not match "
@@ -166,9 +166,9 @@ namespace build
if (!v)
return;
- const path& d (v.as<const path&> ());
- path out_root (root.path () / d);
- path src_root (root.src_path () / d);
+ const dir_path& d (v.as<const dir_path&> ());
+ dir_path out_root (root.path () / d);
+ dir_path src_root (root.src_path () / d);
out_root.normalize ();
src_root.normalize ();
@@ -178,7 +178,7 @@ namespace build
// Check if the bootstrap process changed src_root.
//
- const path& p (rs.variables["src_root"].as<const path&> ());
+ const dir_path& p (rs.variables["src_root"].as<const dir_path&> ());
if (src_root != p)
fail << "bootstrapped src_root " << p << " does not match "
@@ -191,7 +191,7 @@ namespace build
}
scope&
- create_bootstrap_inner (scope& root, const path& out_base)
+ create_bootstrap_inner (scope& root, const dir_path& out_base)
{
if (auto v = root.ro_variables ()["subprojects"])
{
@@ -203,19 +203,19 @@ namespace build
fail << "expected directory in subprojects variable "
<< "instead of " << n;
- path out_root (root.path () / n.dir);
+ dir_path out_root (root.path () / n.dir);
if (!out_base.sub (out_root))
continue;
- path src_root (root.src_path () / n.dir);
+ dir_path src_root (root.src_path () / n.dir);
scope& rs (create_root (out_root, src_root));
bootstrap_out (rs);
// Check if the bootstrap process changed src_root.
//
- const path& p (rs.variables["src_root"].as<const path&> ());
+ const dir_path& p (rs.variables["src_root"].as<const dir_path&> ());
if (src_root != p)
fail << "bootstrapped src_root " << p << " does not match "
@@ -270,13 +270,13 @@ namespace build
info << "consider explicitly configuring its out_root via the "
<< var.name << " command line variable";
- const path& out_root (val.as<const path&> ());
+ const dir_path& out_root (val.as<const dir_path&> ());
// Bootstrap the imported root scope. This is pretty similar to
// what we do in main() except that here we don't try to guess
// src_root.
//
- path src_root (is_src_root (out_root) ? out_root : path ());
+ dir_path src_root (is_src_root (out_root) ? out_root : dir_path ());
scope& root (create_root (out_root, src_root));
bootstrap_out (root);
@@ -285,7 +285,7 @@ namespace build
//
if (auto v = root.ro_variables ()["src_root"])
{
- const path& p (v.as<const path&> ());
+ const dir_path& p (v.as<const dir_path&> ());
if (!src_root.empty () && p != src_root)
fail << "bootstrapped src_root " << p << " does not match "
diff --git a/build/name b/build/name
index cf7427b..b0fd6cb 100644
--- a/build/name
+++ b/build/name
@@ -28,9 +28,9 @@ namespace build
name (std::string v): value (std::move (v)) {}
explicit
- name (path d): dir (std::move (d)) {}
+ name (dir_path d): dir (std::move (d)) {}
- name (std::string t, path d, std::string v)
+ name (std::string t, dir_path d, std::string v)
: type (std::move (t)), dir (std::move (d)), value (std::move (v)) {}
bool
@@ -44,9 +44,9 @@ namespace build
{return type.empty () && !dir.empty () && value.empty ();}
std::string type;
- path dir;
+ dir_path dir;
std::string value;
- bool pair {false};
+ bool pair {false}; // Store pair symbol for printing?
};
inline bool
diff --git a/build/name.cxx b/build/name.cxx
index ebc7372..4d30684 100644
--- a/build/name.cxx
+++ b/build/name.cxx
@@ -15,42 +15,28 @@ namespace build
ostream&
operator<< (ostream& os, const name& n)
{
- bool ht (!n.type.empty ());
- bool hv (!n.value.empty ());
- bool hd (false);
-
- if (ht)
+ // 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.
+ //
+ bool d (!n.dir.empty ());
+ bool v (!n.value.empty ());
+ bool t (!n.type.empty () || (!d && !v));
+
+ if (v)
+ os << n.dir;
+
+ if (t)
os << n.type << '{';
- if (!n.dir.empty ())
- {
- string s (diag_relative (n.dir));
-
- // If both type and value are empty, there will be nothing printed.
- //
- if (s != "." || (!ht && !hv))
- {
- os << s;
-
- // Add the directory separator unless it is already there
- // or we have type but no value. The idea is to print foo/
- // or dir{foo}.
- //
- if (s.back () != path::traits::directory_separator && (hv || !ht))
- os << path::traits::directory_separator;
+ if (v)
+ os << n.value;
+ else
+ os << n.dir;
- hd = true;
- }
- }
-
- os << n.value;
-
- if (ht)
+ if (t)
os << '}';
- if (!ht && !hv && !hd)
- os << "{}"; // Nothing got printed.
-
return os;
}
diff --git a/build/operation b/build/operation
index 3d9c4a4..fc5651f 100644
--- a/build/operation
+++ b/build/operation
@@ -137,8 +137,8 @@ namespace build
//
void (*load) (const path& buildfile,
scope& root,
- const path& out_base,
- const path& src_base,
+ const dir_path& out_base,
+ const dir_path& src_base,
const location&);
void (*match) (action,
@@ -167,8 +167,8 @@ namespace build
void
load (const path& buildfile,
scope& root,
- const path& out_base,
- const path& src_base,
+ const dir_path& out_base,
+ const dir_path& src_base,
const location&);
// Resolve and match the target. This is the default implementation
diff --git a/build/operation.cxx b/build/operation.cxx
index a8fdfb1..bceede5 100644
--- a/build/operation.cxx
+++ b/build/operation.cxx
@@ -35,8 +35,8 @@ namespace build
void
load (const path& bf,
scope& root,
- const path& out_base,
- const path& src_base,
+ const dir_path& out_base,
+ const dir_path& src_base,
const location&)
{
// Load project's root[-pre].build.
@@ -51,7 +51,7 @@ namespace build
base.variables["out_base"] = out_base;
auto v (base.variables["src_base"] = src_base);
- base.src_path_ = &v.as<const path&> ();
+ base.src_path_ = &v.as<const dir_path&> ();
// Load the buildfile unless it has already been loaded.
//
diff --git a/build/parser b/build/parser
index 53ce2d0..6168645 100644
--- a/build/parser
+++ b/build/parser
@@ -76,7 +76,7 @@ namespace build
void
names (token&, token_type&,
names_type&, std::size_t pair,
- const path* dir, const std::string* type);
+ const dir_path* dir, const std::string* type);
// Buildspec.
//
@@ -116,12 +116,12 @@ namespace build
const fail_mark<failed> fail;
private:
- const std::string* path_; // Path processed by diagnostic_string().
+ const std::string* path_; // Path processed by diag_relative().
lexer* lexer_;
scope* scope_; // Current base scope (out_base).
scope* root_; // Current root scope (out_root).
- const path* out_root_;
- const path* src_root_;
+ const dir_path* out_root_;
+ const dir_path* src_root_;
target* default_target_;
token peek_ {token_type::eos, false, 0, 0};
diff --git a/build/parser.cxx b/build/parser.cxx
index d3abd46..7c326a6 100644
--- a/build/parser.cxx
+++ b/build/parser.cxx
@@ -140,7 +140,7 @@ namespace build
location nloc (get_location (t, &path_));
names_type ns (tt != type::colon
? names (t, tt)
- : names_type ({name ("dir", path (), string ())}));
+ : names_type ({name ("dir", dir_path (), string ())}));
if (tt == type::colon)
{
@@ -194,7 +194,7 @@ namespace build
//
scope& prev (*scope_);
- path p (move (ns[0].dir)); // Steal.
+ dir_path p (move (ns[0].dir)); // Steal.
if (p.relative ())
p = prev.path () / p;
@@ -441,7 +441,7 @@ namespace build
if (src_root_ == nullptr)
{
auto v (root_->ro_variables ()["src_root"]);
- src_root_ = v ? &v.as<const path&> () : nullptr;
+ src_root_ = v ? &v.as<const dir_path&> () : nullptr;
}
}
@@ -512,8 +512,8 @@ namespace build
// Determine new bases.
//
- path out_base;
- path src_base;
+ dir_path out_base;
+ dir_path src_base;
if (in_out)
{
@@ -557,7 +557,7 @@ namespace build
scope_->variables["out_base"] = move (out_base);
auto v (scope_->variables["src_base"] = move (src_base));
- scope_->src_path_ = &v.as<const path&> ();
+ scope_->src_path_ = &v.as<const dir_path&> ();
target* odt (default_target_);
default_target_ = nullptr;
@@ -768,7 +768,7 @@ namespace build
type& tt,
names_type& ns,
size_t pair,
- const path* dp,
+ const dir_path* dp,
const string* tp)
{
// If pair is not 0, then it is an index + 1 of the first half of
@@ -838,8 +838,8 @@ namespace build
if (p != n && tp != nullptr)
fail (t) << "nested type name " << name;
- path d1;
- const path* dp1 (dp);
+ dir_path d1;
+ const dir_path* dp1 (dp);
string t1;
const string* tp1 (tp);
@@ -849,9 +849,9 @@ namespace build
else if (p == n) // directory
{
if (dp == nullptr)
- d1 = path (name);
+ d1 = dir_path (name);
else
- d1 = *dp / path (name);
+ d1 = *dp / dir_path (name);
dp1 = &d1;
}
@@ -860,9 +860,9 @@ namespace build
t1.assign (name, p + 1, n - p);
if (dp == nullptr)
- d1 = path (name, 0, p + 1);
+ d1 = dir_path (name, 0, p + 1);
else
- d1 = *dp / path (name, 0, p + 1);
+ d1 = *dp / dir_path (name, 0, p + 1);
dp1 = &d1;
tp1 = &t1;
@@ -906,9 +906,9 @@ namespace build
// Search for global_scope for details.
//
#ifdef _WIN32
- path dir (name != "/" ? path (name) : path ());
+ dir_path dir (name != "/" ? dir_path (name) : dir_path ());
#else
- path dir (name);
+ dir_path dir (name);
#endif
if (dp != nullptr)
dir = *dp / dir;
@@ -919,7 +919,7 @@ namespace build
}
else
ns.emplace_back ((tp != nullptr ? *tp : string ()),
- (dp != nullptr ? *dp : path ()),
+ (dp != nullptr ? *dp : dir_path ()),
move (name));
count = 1;
@@ -1015,10 +1015,10 @@ namespace build
//
for (const name& n: lv)
{
- const path* dp1 (dp);
+ const dir_path* dp1 (dp);
const string* tp1 (tp);
- path d1;
+ dir_path d1;
if (!n.dir.empty ())
{
if (dp != nullptr)
@@ -1059,7 +1059,7 @@ namespace build
}
ns.emplace_back ((tp1 != nullptr ? *tp1 : string ()),
- (dp1 != nullptr ? *dp1 : path ()),
+ (dp1 != nullptr ? *dp1 : dir_path ()),
n.value);
}
@@ -1105,7 +1105,7 @@ namespace build
// Empty LHS, (e.g., {=y}), create an empty name.
//
ns.emplace_back ((tp != nullptr ? *tp : string ()),
- (dp != nullptr ? *dp : path ()),
+ (dp != nullptr ? *dp : dir_path ()),
"");
count = 1;
}
@@ -1129,7 +1129,7 @@ namespace build
ns.push_back (ns[pair - 1]);
ns.emplace_back ((tp != nullptr ? *tp : string ()),
- (dp != nullptr ? *dp : path ()),
+ (dp != nullptr ? *dp : dir_path ()),
"");
break;
}
@@ -1142,7 +1142,7 @@ namespace build
if (!ns.empty () && ns.back ().pair)
{
ns.emplace_back ((tp != nullptr ? *tp : string ()),
- (dp != nullptr ? *dp : path ()),
+ (dp != nullptr ? *dp : dir_path ()),
"");
}
}
@@ -1240,7 +1240,7 @@ namespace build
{
// Do we have the src_base?
//
- path src_base;
+ dir_path src_base;
if (i->pair)
{
if (!i->type.empty ())
@@ -1249,7 +1249,7 @@ namespace build
src_base = move (i->dir);
if (!i->value.empty ())
- src_base /= path (move (i->value));
+ src_base /= dir_path (move (i->value));
++i;
assert (i != e);
@@ -1344,10 +1344,10 @@ namespace build
// to their return values are not guaranteed to be stable (and,
// in fact, path()'s is not).
//
- out_root_ = &root_->ro_variables ()["out_root"].as<const path&> ();
+ out_root_ = &root_->ro_variables ()["out_root"].as<const dir_path&> ();
auto v (root_->ro_variables ()["src_root"]);
- src_root_ = v ? &v.as<const path&> () : nullptr;
+ src_root_ = v ? &v.as<const dir_path&> () : nullptr;
}
return r;
diff --git a/build/path b/build/path
index 1a62287..d153ed7 100644
--- a/build/path
+++ b/build/path
@@ -14,9 +14,6 @@
namespace build
{
template <typename C>
- class basic_path;
-
- template <typename C>
struct path_traits
{
typedef std::basic_string<C> string_type;
@@ -125,6 +122,15 @@ namespace build
return ln < rn ? -1 : (ln > rn ? 1 : 0);
}
+ // Get/set current working directory. Throw std::system_error
+ // to report the underlying OS errors.
+ //
+ static string_type
+ current ();
+
+ static void
+ current (string_type const&);
+
private:
#ifdef _WIN32
static C
@@ -135,10 +141,35 @@ namespace build
template <typename C>
class invalid_basic_path;
- typedef basic_path<char> path;
+ template <typename C, typename K>
+ class basic_path;
+
+ template <typename C>
+ class path_data;
+
+ template <typename C>
+ struct dir_path_kind;
+
+ template <typename C>
+ struct any_path_kind
+ {
+ typedef path_data<C> base_type;
+ typedef basic_path<C, dir_path_kind<C>> dir_type;
+ };
+
+ template <typename C>
+ struct dir_path_kind
+ {
+ typedef basic_path<C, any_path_kind<C>> base_type;
+ typedef basic_path<C, dir_path_kind<C>> dir_type;
+ };
+
+ typedef basic_path<char, any_path_kind<char>> path;
+ typedef basic_path<char, dir_path_kind<char>> dir_path;
typedef invalid_basic_path<char> invalid_path;
- typedef basic_path<wchar_t> wpath;
+ typedef basic_path<wchar_t, any_path_kind<wchar_t>> wpath;
+ typedef basic_path<wchar_t, dir_path_kind<wchar_t>> dir_wpath;
typedef invalid_basic_path<wchar_t> invalid_wpath;
//
@@ -171,66 +202,68 @@ namespace build
};
template <typename C>
- class basic_path
+ class path_data
+ {
+ public:
+ typedef std::basic_string<C> string_type;
+
+ path_data () = default;
+
+ explicit
+ path_data (string_type s): path_ (std::move (s)) {}
+
+ protected:
+ string_type path_;
+ };
+
+ template <typename C, typename K>
+ class basic_path: public K::base_type
{
public:
typedef std::basic_string<C> string_type;
typedef typename string_type::size_type size_type;
+ typedef typename K::base_type base_type;
+ typedef typename K::dir_type dir_type;
+
typedef path_traits<C> traits;
// Construct special empty path.
//
- basic_path ()
- {
- }
+ basic_path () = default;
explicit
- basic_path (C const* s)
- : path_ (s)
- {
- init ();
- }
+ basic_path (C const* s): base_type (s) {init ();}
basic_path (C const* s, size_type n)
- : path_ (s, n)
- {
- init ();
- }
+ : base_type (string_type (s, n)) {init ();}
explicit
- basic_path (string_type s)
- : path_ (std::move (s))
- {
- init ();
- }
+ basic_path (string_type s): base_type (std::move (s)) {init ();}
basic_path (const string_type& s, size_type n)
- : path_ (s, 0, n)
- {
- init ();
- }
+ : base_type (string_type (s, 0, n)) {init ();}
basic_path (const string_type& s, size_type p, size_type n)
- : path_ (s, p, n)
- {
- init ();
- }
+ : base_type (string_type (s, p, n)) {init ();}
void
swap (basic_path& p)
{
- path_.swap (p.path_);
+ this->path_.swap (p.path_);
}
void
clear ()
{
- path_.clear ();
+ this->path_.clear ();
}
- static basic_path
- current ();
+ // Get/set current working directory. Throw std::system_error
+ // to report the underlying OS errors.
+ //
+ static dir_type
+ current () {return dir_type (traits::current ());}
static void
current (basic_path const&);
@@ -239,7 +272,7 @@ namespace build
bool
empty () const
{
- return path_.empty ();
+ return this->path_.empty ();
}
bool
@@ -286,20 +319,20 @@ namespace build
// Return the directory part of the path or empty path if
// there is no directory.
//
- basic_path
+ dir_type
directory () const;
// Return the directory part of the path without the specified
// leaf part. Throws invalid_path if the leaf is not a suffix of
// *this. Expects both paths to be normalized.
//
- basic_path
+ dir_type
directory (basic_path const&) const;
// Return the root directory of the path or empty path if
// the directory is not absolute.
//
- basic_path
+ dir_type
root_directory () const;
// Return the path without the extension, if any.
@@ -335,40 +368,32 @@ namespace build
complete ();
public:
- basic_path
- operator/ (basic_path const& x) const
- {
- basic_path r (*this);
- r /= x;
- return r;
- }
-
basic_path&
operator/= (basic_path const&);
basic_path
operator+ (string_type const& s) const
{
- return basic_path (path_ + s);
+ return basic_path (this->path_ + s);
}
basic_path
operator+ (C c) const
{
- return basic_path (path_ + c);
+ return basic_path (this->path_ + c);
}
basic_path&
operator+= (string_type const& s)
{
- path_ += s;
+ this->path_ += s;
return *this;
}
basic_path&
operator+= (C c)
{
- path_ += c;
+ this->path_ += c;
return *this;
}
@@ -378,7 +403,7 @@ namespace build
bool
operator== (basic_path const& x) const
{
- return traits::compare (path_, x.path_) == 0;
+ return traits::compare (this->path_, x.path_) == 0;
}
bool
@@ -390,14 +415,14 @@ namespace build
bool
operator< (basic_path const& x) const
{
- return traits::compare (path_, x.path_) < 0;
+ return traits::compare (this->path_, x.path_) < 0;
}
public:
const string_type&
string () const
{
- return path_;
+ return this->path_;
}
// If possible, return a POSIX representation of the path. For example,
@@ -412,15 +437,36 @@ namespace build
private:
void
init ();
-
- private:
- string_type path_;
};
- /*
+ template <typename C, typename K>
+ inline basic_path<C, K>
+ operator/ (basic_path<C, K> const& x, basic_path<C, K> const& y)
+ {
+ basic_path<C, K> r (x);
+ r /= y;
+ return r;
+ }
+
+ // Additional operators for certain path kind combinations.
+ //
template <typename C>
+ inline basic_path<C, any_path_kind<C>>
+ operator/ (basic_path<C, dir_path_kind<C>> const& x,
+ basic_path<C, any_path_kind<C>> const& y)
+ {
+ basic_path<C, any_path_kind<C>> r (x);
+ r /= y;
+ return r;
+ }
+
+ // IO
+ //
+
+ /*
+ template <typename C, typename K>
inline std::basic_ostream<C>&
- operator<< (std::basic_ostream<C>& os, basic_path<C> const& p)
+ operator<< (std::basic_ostream<C>& os, basic_path<C, K> const& p)
{
return os << p.string ();
}
@@ -429,11 +475,11 @@ namespace build
namespace std
{
- template <typename C>
- struct hash<build::basic_path<C>>: hash<basic_string<C>>
+ template <typename C, typename K>
+ struct hash<build::basic_path<C, K>>: hash<basic_string<C>>
{
size_t
- operator() (const build::basic_path<C>& p) const noexcept
+ operator() (const build::basic_path<C, K>& p) const noexcept
{
return hash<basic_string<C>>::operator() (p.string ());
}
diff --git a/build/path-io b/build/path-io
index a9deea9..accdb94 100644
--- a/build/path-io
+++ b/build/path-io
@@ -8,14 +8,26 @@
#include <ostream>
#include <build/path>
-#include <build/diagnostics>
namespace build
{
inline std::ostream&
operator<< (std::ostream& os, const path& p)
{
- return os << (&os == diag_stream ? diag_relative (p) : p.string ());
+ return os << p.string ();
+ }
+
+ inline std::ostream&
+ operator<< (std::ostream& os, const dir_path& d)
+ {
+ const std::string& s (d.string ());
+
+ // Print the directory with trailing '/'.
+ //
+ if (!s.empty ())
+ os << s << (dir_path::traits::is_separator (s.back ()) ? "" : "/");
+
+ return os;
}
}
diff --git a/build/path-map b/build/path-map
index ee2dd79..2b32b0d 100644
--- a/build/path-map
+++ b/build/path-map
@@ -24,10 +24,10 @@ namespace build
// want a particular representation, pre-populate the map with
// it.
//
- template <typename C>
- struct compare_prefix<basic_path<C>>: compare_prefix<std::basic_string<C>>
+ template <typename C, typename K>
+ struct compare_prefix<basic_path<C, K>>: compare_prefix<std::basic_string<C>>
{
- typedef basic_path<C> K;
+ typedef basic_path<C, K> key_type;
typedef C delimiter_type;
typedef std::basic_string<C> string_type;
@@ -37,7 +37,7 @@ namespace build
compare_prefix (delimiter_type d): base (d) {}
bool
- operator() (const K& x, const K& y) const
+ operator() (const key_type& x, const key_type& y) const
{
const auto& xs (x.string ());
const auto& ys (y.string ());
@@ -56,7 +56,7 @@ namespace build
}
bool
- prefix (const K& p, const K& k) const
+ prefix (const key_type& p, const key_type& k) const
{
const auto& ps (p.string ());
const auto& ks (k.string ());
@@ -72,6 +72,10 @@ namespace build
template <typename T>
using path_map = prefix_map<path, T, path::traits::directory_separator>;
+
+ template <typename T>
+ using dir_path_map =
+ prefix_map<dir_path, T, dir_path::traits::directory_separator>;
}
#endif // BUILD_PATH_MAP
diff --git a/build/path.cxx b/build/path.cxx
index efd0532..899dc8f 100644
--- a/build/path.cxx
+++ b/build/path.cxx
@@ -8,11 +8,16 @@
# include <stdlib.h> // _MAX_PATH
# include <direct.h> // _[w]getcwd, _[w]chdir
#else
+# include <errno.h> // EINVAL
# include <stdlib.h> // mbstowcs, wcstombs
# include <limits.h> // PATH_MAX
# include <unistd.h> // getcwd, chdir
#endif
+#include <system_error>
+
+using namespace std;
+
namespace build
{
char const* invalid_path_base::
@@ -26,7 +31,7 @@ namespace build
//
template <>
- basic_path<char> basic_path<char>::
+ path_traits<char>::string_type path_traits<char>::
current ()
{
// @@ throw system_error (and in the other current() versions).
@@ -34,31 +39,26 @@ namespace build
#ifdef _WIN32
char cwd[_MAX_PATH];
if(_getcwd(cwd, _MAX_PATH) == 0)
- throw invalid_basic_path<char> (".");
+ throw system_error (errno, system_category ());
#else
char cwd[PATH_MAX];
if (getcwd (cwd, PATH_MAX) == 0)
- throw invalid_basic_path<char> (".");
+ throw system_error (errno, system_category ());
#endif
- return basic_path<char> (cwd);
+ return string_type (cwd);
}
template <>
- void basic_path<char>::
- current (basic_path const& p)
+ void path_traits<char>::
+ current (string_type const& s)
{
- string_type const& s (p.string ());
-
- if (p.empty ())
- throw invalid_basic_path<char> (s);
-
#ifdef _WIN32
if(_chdir(s.c_str ()) != 0)
- throw invalid_basic_path<char> (s);
+ throw system_error (errno, system_category ());
#else
if (chdir (s.c_str ()) != 0)
- throw invalid_basic_path<char> (s);
+ throw system_error (errno, system_category ());
#endif
}
@@ -67,48 +67,43 @@ namespace build
//
template <>
- basic_path<wchar_t> basic_path<wchar_t>::
+ path_traits<wchar_t>::string_type path_traits<wchar_t>::
current ()
{
#ifdef _WIN32
wchar_t wcwd[_MAX_PATH];
if(_wgetcwd(wcwd, _MAX_PATH) == 0)
- throw invalid_basic_path<wchar_t> (L".");
+ throw system_error (errno, system_category ());
#else
char cwd[PATH_MAX];
if (getcwd (cwd, PATH_MAX) == 0)
- throw invalid_basic_path<wchar_t> (L".");
+ throw system_error (errno, system_category ());
wchar_t wcwd[PATH_MAX];
if (mbstowcs (wcwd, cwd, PATH_MAX) == size_type (-1))
- throw invalid_basic_path<wchar_t> (L".");
+ throw system_error (EINVAL, system_category ());
#endif
- return basic_path<wchar_t> (wcwd);
+ return string_type (wcwd);
}
template <>
- void basic_path<wchar_t>::
- current (basic_path const& p)
+ void path_traits<wchar_t>::
+ current (string_type const& s)
{
- string_type const& s (p.string ());
-
- if (p.empty ())
- throw invalid_basic_path<wchar_t> (s);
-
#ifdef _WIN32
if(_wchdir(s.c_str ()) != 0)
- throw invalid_basic_path<wchar_t> (s);
+ throw system_error (errno, system_category ());
#else
char ns[PATH_MAX + 1];
if (wcstombs (ns, s.c_str (), PATH_MAX) == size_type (-1))
- throw invalid_basic_path<wchar_t> (s);
+ throw system_error (EINVAL, system_category ());
ns[PATH_MAX] = '\0';
if (chdir (ns) != 0)
- throw invalid_basic_path<wchar_t> (s);
+ throw system_error (errno, system_category ());
#endif
}
}
diff --git a/build/path.ixx b/build/path.ixx
index 95608e9..ff1ec32 100644
--- a/build/path.ixx
+++ b/build/path.ixx
@@ -25,30 +25,30 @@ namespace build
}
#endif
- template <typename C>
- inline bool basic_path<C>::
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
absolute () const
{
#ifdef _WIN32
- return path_.size () > 1 && path_[1] == ':';
+ return this->path_.size () > 1 && this->path_[1] == ':';
#else
- return !path_.empty () && traits::is_separator (path_[0]);
+ return !this->path_.empty () && traits::is_separator (this->path_[0]);
#endif
}
- template <typename C>
- inline bool basic_path<C>::
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
root () const
{
#ifdef _WIN32
- return path_.size () == 2 && path_[1] == ':';
+ return this->path_.size () == 2 && this->path_[1] == ':';
#else
- return path_.size () == 1 && traits::is_separator (path_[0]);
+ return this->path_.size () == 1 && traits::is_separator (this->path_[0]);
#endif
}
- template <typename C>
- inline bool basic_path<C>::
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
sub (const basic_path& p) const
{
size_type n (p.path_.size ());
@@ -56,18 +56,18 @@ namespace build
if (n == 0)
return true;
- size_type m (path_.size ());
+ size_type m (this->path_.size ());
// The second condition guards against the /foo-bar vs /foo case.
//
- return m >= n && path_.compare (0, n, p.path_) == 0 &&
+ return m >= n && this->path_.compare (0, n, p.path_) == 0 &&
(traits::is_separator (p.path_.back ()) || // p ends with a separator
m == n || // *this == p
- traits::is_separator (path_[n])); // next char is a separator
+ traits::is_separator (this->path_[n])); // next char is a separator
}
- template <typename C>
- inline bool basic_path<C>::
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
sup (const basic_path& p) const
{
size_type n (p.path_.size ());
@@ -75,17 +75,17 @@ namespace build
if (n == 0)
return true;
- size_type m (path_.size ());
+ size_type m (this->path_.size ());
// The second condition guards against the /foo-bar vs bar case.
//
- return m >= n && path_.compare (m - n, n, p.path_) == 0 &&
- (m == n || // *this == p
- traits::is_separator (path_[m - n - 1])); // prev char is a separator
+ return m >= n && this->path_.compare (m - n, n, p.path_) == 0 &&
+ (m == n || // *this == p
+ traits::is_separator (this->path_[m - n - 1])); // prev char separator
}
- template <typename C>
- inline basic_path<C>& basic_path<C>::
+ template <typename C, typename K>
+ inline basic_path<C, K>& basic_path<C, K>::
complete ()
{
if (relative ())
@@ -94,38 +94,40 @@ namespace build
return *this;
}
- template <typename C>
- inline basic_path<C> basic_path<C>::
+ template <typename C, typename K>
+ inline typename basic_path<C, K>::dir_type basic_path<C, K>::
root_directory () const
{
return absolute ()
#ifdef _WIN32
- ? path (path_, 2)
+ ? dir_type (this->path_, 2)
#else
- ? path ("/")
+ ? dir_type ("/")
#endif
- : path ();
+ : dir_type ();
}
- template <typename C>
- inline basic_path<C> basic_path<C>::
+ template <typename C, typename K>
+ inline basic_path<C, K> basic_path<C, K>::
base () const
{
- size_type p (traits::find_extension (path_));
- return p != string_type::npos ? basic_path (path_.c_str (), p) : *this;
+ size_type p (traits::find_extension (this->path_));
+ return p != string_type::npos
+ ? basic_path (this->path_.c_str (), p)
+ : *this;
}
- template <typename C>
- inline const C* basic_path<C>::
+ template <typename C, typename K>
+ inline const C* basic_path<C, K>::
extension () const
{
- size_type p (traits::find_extension (path_));
- return p != string_type::npos ? path_.c_str () + p + 1 : nullptr;
+ size_type p (traits::find_extension (this->path_));
+ return p != string_type::npos ? this->path_.c_str () + p + 1 : nullptr;
}
#ifndef _WIN32
- template <typename C>
- inline typename basic_path<C>::string_type basic_path<C>::
+ template <typename C, typename K>
+ inline typename basic_path<C, K>::string_type basic_path<C, K>::
posix_string () const
{
return string ();
diff --git a/build/path.txx b/build/path.txx
index a8bf859..67a271d 100644
--- a/build/path.txx
+++ b/build/path.txx
@@ -6,43 +6,43 @@
namespace build
{
- template <typename C>
- basic_path<C> basic_path<C>::
+ template <typename C, typename K>
+ basic_path<C, K> basic_path<C, K>::
leaf () const
{
- size_type p (traits::rfind_separator (path_));
+ size_type p (traits::rfind_separator (this->path_));
return p != string_type::npos
- ? basic_path (path_.c_str () + p + 1, path_.size () - p - 1)
+ ? basic_path (this->path_.c_str () + p + 1, this->path_.size () - p - 1)
: *this;
}
- template <typename C>
- basic_path<C> basic_path<C>::
+ template <typename C, typename K>
+ typename basic_path<C, K>::dir_type basic_path<C, K>::
directory () const
{
if (root ())
- return basic_path ();
+ return dir_type ();
- size_type p (traits::rfind_separator (path_));
+ size_type p (traits::rfind_separator (this->path_));
// Include the trailing slash so that we get correct behavior
// if directory is root.
//
return p != string_type::npos
- ? basic_path (path_.c_str (), p + 1)
- : basic_path ();
+ ? dir_type (this->path_.c_str (), p + 1)
+ : dir_type ();
}
#ifdef _WIN32
- template <typename C>
- typename basic_path<C>::string_type basic_path<C>::
+ template <typename C, typename K>
+ typename basic_path<C, K>::string_type basic_path<C, K>::
posix_string () const
{
if (absolute ())
- throw invalid_basic_path<C> (path_);
+ throw invalid_basic_path<C> (this->path_);
- string_type r (path_);
+ string_type r (this->path_);
// Translate Windows-style separators to the POSIX ones.
//
@@ -54,30 +54,29 @@ namespace build
}
#endif
- template <typename C>
- basic_path<C>& basic_path<C>::
- operator/= (basic_path<C> const& r)
+ template <typename C, typename K>
+ basic_path<C, K>& basic_path<C, K>::
+ operator/= (basic_path<C, K> const& r)
{
- if (r.absolute () && !path_.empty ()) // Allow ('' / '/foo').
+ if (r.absolute () && !this->path_.empty ()) // Allow ('' / '/foo').
throw invalid_basic_path<C> (r.path_);
- if (path_.empty () || r.path_.empty ())
+ if (this->path_.empty () || r.path_.empty ())
{
- path_ += r.path_;
+ this->path_ += r.path_;
return *this;
}
- if (!traits::is_separator (path_[path_.size () - 1]))
- path_ += traits::directory_separator;
-
- path_ += r.path_;
+ if (!traits::is_separator (this->path_[this->path_.size () - 1]))
+ this->path_ += traits::directory_separator;
+ this->path_ += r.path_;
return *this;
}
- template <typename C>
- basic_path<C> basic_path<C>::
- leaf (basic_path<C> const& d) const
+ template <typename C, typename K>
+ basic_path<C, K> basic_path<C, K>::
+ leaf (basic_path<C, K> const& d) const
{
size_type n (d.path_.size ());
@@ -85,9 +84,9 @@ namespace build
return *this;
if (!sub (d))
- throw invalid_basic_path<C> (path_);
+ throw invalid_basic_path<C> (this->path_);
- size_type m (path_.size ());
+ size_type m (this->path_.size ());
if (n != m
#ifndef _WIN32
@@ -96,32 +95,32 @@ namespace build
)
n++; // Skip the directory separator (unless it is POSIX root).
- return basic_path (path_.c_str () + n, m - n);
+ return basic_path (this->path_.c_str () + n, m - n);
}
- template <typename C>
- basic_path<C> basic_path<C>::
- directory (basic_path<C> const& l) const
+ template <typename C, typename K>
+ typename basic_path<C, K>::dir_type basic_path<C, K>::
+ directory (basic_path<C, K> const& l) const
{
size_type n (l.path_.size ());
if (n == 0)
- return *this;
+ return dir_type (this->path_);
if (!sup (l))
- throw invalid_basic_path<C> (path_);
+ throw invalid_basic_path<C> (this->path_);
- size_type m (path_.size ());
+ size_type m (this->path_.size ());
if (n != m)
n++; // Skip the directory separator.
- return basic_path (path_.c_str (), m - n);
+ return dir_type (this->path_.c_str (), m - n);
}
- template <typename C>
- basic_path<C> basic_path<C>::
- relative (basic_path<C> d) const
+ template <typename C, typename K>
+ basic_path<C, K> basic_path<C, K>::
+ relative (basic_path<C, K> d) const
{
basic_path r;
@@ -130,19 +129,19 @@ namespace build
if (sub (d))
break;
- r /= path ("..");
+ r /= basic_path ("..");
// Roots of the paths do not match.
//
if (d.root ())
- throw invalid_basic_path<C> (path_);
+ throw invalid_basic_path<C> (this->path_);
}
return r / leaf (d);
}
- template <typename C>
- basic_path<C>& basic_path<C>::
+ template <typename C, typename K>
+ basic_path<C, K>& basic_path<C, K>::
normalize ()
{
if (empty ())
@@ -153,11 +152,11 @@ namespace build
typedef std::vector<string_type> paths;
paths ps;
- for (size_type b (0), e (traits::find_separator (path_)),
- n (path_.size ());;
- e = traits::find_separator (path_, b))
+ for (size_type b (0), e (traits::find_separator (this->path_)),
+ n (this->path_.size ());;
+ e = traits::find_separator (this->path_, b))
{
- string_type s (path_, b, e == string_type::npos ? e : e - b);
+ string_type s (this->path_, b, e == string_type::npos ? e : e - b);
ps.push_back (s);
if (e == string_type::npos)
@@ -165,7 +164,7 @@ namespace build
++e;
- while (e < n && traits::is_separator (path_[e]))
+ while (e < n && traits::is_separator (this->path_[e]))
++e;
if (e == n)
@@ -200,7 +199,7 @@ namespace build
// Cannot go past the root directory.
//
if (abs && r.size () == 1)
- throw invalid_basic_path<C> (path_);
+ throw invalid_basic_path<C> (this->path_);
r.pop_back ();
continue;
@@ -227,19 +226,31 @@ namespace build
if (p.empty () && !r.empty ())
p += traits::directory_separator; // Root directory.
- path_.swap (p);
+ this->path_.swap (p);
return *this;
}
- template <typename C>
- void basic_path<C>::
+ template <typename C, typename K>
+ void basic_path<C, K>::
+ current (basic_path const& p)
+ {
+ const string_type& s (p.string ());
+
+ if (s.empty ())
+ throw invalid_basic_path<char> (s);
+
+ traits::current (s);
+ }
+
+ template <typename C, typename K>
+ void basic_path<C, K>::
init ()
{
// Strip trailing slashes except for the case where the single
// slash represents the root directory.
//
- size_type n (path_.size ());
- for (; n > 1 && traits::is_separator (path_[n - 1]); --n) ;
- path_.resize (n);
+ size_type n (this->path_.size ());
+ for (; n > 1 && traits::is_separator (this->path_[n - 1]); --n) ;
+ this->path_.resize (n);
}
}
diff --git a/build/prerequisite b/build/prerequisite
index d57f811..77e04c2 100644
--- a/build/prerequisite
+++ b/build/prerequisite
@@ -29,7 +29,7 @@ namespace build
typedef build::scope scope_type;
prerequisite (const target_type_type& t,
- path d,
+ dir_path d,
std::string n,
const std::string* e,
scope_type& s)
@@ -38,7 +38,7 @@ namespace build
public:
const target_type_type& type;
- const path dir; // Normalized absolute or relative (to scope).
+ const dir_path dir; // Normalized absolute or relative (to scope).
const std::string name;
const std::string* ext; // NULL if unspecified.
scope_type& scope;
@@ -55,7 +55,7 @@ namespace build
{
std::pair<prerequisite&, bool>
insert (const target_type&,
- path dir,
+ dir_path dir,
std::string name,
const std::string* ext,
scope&,
diff --git a/build/prerequisite.cxx b/build/prerequisite.cxx
index aa6c53c..5d3235c 100644
--- a/build/prerequisite.cxx
+++ b/build/prerequisite.cxx
@@ -18,52 +18,38 @@ namespace build
ostream&
operator<< (ostream& os, const prerequisite& p)
{
- if (p.target != nullptr)
- os << *p.target;
- else
+ // Print scope unless the prerequisite's directory is absolute.
+ //
+ if (!p.dir.absolute ())
{
- os << p.type.name << '{';
-
- // Print scope unless the directory is absolute.
- //
- if (!p.dir.absolute ())
- {
- string s (diag_relative (p.scope.path ()));
+ string s (diag_relative (p.scope.path (), false));
- if (s != ".")
- {
- os << s;
-
- if (s.back () != path::traits::directory_separator)
- os << path::traits::directory_separator;
-
- os << ": ";
- }
- }
+ if (!s.empty ())
+ os << s << ':';
+ }
- // Print directory.
- //
- if (!p.dir.empty ())
- {
- string s (diag_relative (p.dir));
+ // If the name is empty, then we want to print the directory
+ // inside {}, e.g., dir{bar/}, not bar/dir{}.
+ //
+ bool n (!p.name.empty ());
+ string d (diag_relative (p.dir, false));
- if (s != ".")
- {
- os << s;
+ if (n)
+ os << d;
- if (!p.name.empty () &&
- s.back () != path::traits::directory_separator)
- os << path::traits::directory_separator;
- }
- }
+ os << p.type.name << '{';
+ if (n)
+ {
os << p.name;
if (p.ext != nullptr && !p.ext->empty ())
os << '.' << *p.ext;
-
- os << '}';
}
+ else
+ os << d;
+
+ os << '}';
return os;
}
@@ -89,7 +75,7 @@ namespace build
//
auto prerequisite_set::
insert (const target_type& tt,
- path dir,
+ dir_path dir,
std::string name,
const std::string* ext,
scope& s,
diff --git a/build/scope b/build/scope
index 2eb8ac7..f9492e6 100644
--- a/build/scope
+++ b/build/scope
@@ -20,12 +20,10 @@ namespace build
class scope
{
public:
- typedef build::path path_type;
-
- const path_type&
+ const dir_path&
path () const {return i_->first;} // Absolute and normalized.
- const path_type&
+ const dir_path&
src_path () const {return *src_path_;} // Corresponding src path.
scope*
@@ -53,7 +51,7 @@ namespace build
value_proxy
operator[] (const variable&);
- const path_type* src_path_ {nullptr}; // Cached src_{root,base} var value.
+ const dir_path* src_path_ {nullptr}; // Cached src_{root,base} var value.
public:
variable_map variables;
@@ -69,6 +67,8 @@ namespace build
meta_operation_table meta_operations;
operation_table operations;
+ typedef build::path path_type;
+
// Set of buildfiles already loaded for this scope. The included
// buildfiles are checked against the project's root scope while
// imported -- against the global scope (global_scope).
@@ -90,7 +90,7 @@ namespace build
friend class scope_map;
friend class temp_scope;
- typedef path_map<scope>::const_iterator iterator;
+ typedef dir_path_map<scope>::const_iterator iterator;
scope (): variables (*this) {}
@@ -113,25 +113,36 @@ namespace build
temp_scope (scope& p) {i_ = p.i_; parent_ = &p; root_ = p.root_;}
};
- class scope_map: public path_map<scope>
+ class scope_map: public dir_path_map<scope>
{
public:
// Note that we assume the first insertion into the map is that
// of the global scope.
//
std::pair<scope&, bool>
- insert (const path&, bool root);
+ insert (const dir_path&, bool root);
scope&
- operator[] (const path& p) {return insert (p, false).first;}
+ operator[] (const dir_path& p) {return insert (p, false).first;}
// Find the most qualified scope that encompasses this path.
//
scope&
- find (const path&);
+ find (const dir_path&);
+
+ scope&
+ find (const path& p)
+ {
+ // Natural thing to do here would be to call find (p.directory ()).
+ // However, there could be a situation where the passed path is a
+ // directory (i.e., the calling code does not know what it is dealing
+ // with), so let's use the whole path.
+ //
+ return find (dir_path (p.string ()));
+ }
private:
- typedef path_map<scope> base;
+ typedef dir_path_map<scope> base;
};
extern scope_map scopes;
diff --git a/build/scope.cxx b/build/scope.cxx
index 68eba3d..aced21b 100644
--- a/build/scope.cxx
+++ b/build/scope.cxx
@@ -36,7 +36,7 @@ namespace build
scope* global_scope;
pair<scope&, bool> scope_map::
- insert (const path& k, bool root)
+ insert (const dir_path& k, bool root)
{
auto er (emplace (k, scope ()));
scope& s (er.first->second);
@@ -104,7 +104,7 @@ namespace build
// Find the most qualified scope that encompasses this path.
//
scope& scope_map::
- find (const path& k)
+ find (const dir_path& k)
{
// Normally we would have a scope for the full path so try
// that before making any copies.
@@ -114,7 +114,7 @@ namespace build
if (i != end ())
return i->second;
- for (path d (k.directory ());; d = d.directory ())
+ for (dir_path d (k.directory ());; d = d.directory ())
{
auto i (base::find (d));
diff --git a/build/search b/build/search
index e7d2acd..dfbe32e 100644
--- a/build/search
+++ b/build/search
@@ -20,7 +20,7 @@ namespace build
// Search for an existing file in the specified list of search paths.
//
target*
- search_existing_file (prerequisite&, const paths&);
+ search_existing_file (prerequisite&, const dir_paths&);
// Create a new target in this prerequisite's directory scope.
//
diff --git a/build/search.cxx b/build/search.cxx
index bd81822..6434bf7 100644
--- a/build/search.cxx
+++ b/build/search.cxx
@@ -27,7 +27,7 @@ namespace build
// Look for an existing target in this prerequisite's directory scope.
//
- path d;
+ dir_path d;
if (p.dir.absolute ())
d = p.dir; // Already normalized.
else
@@ -56,7 +56,7 @@ namespace build
}
target*
- search_existing_file (prerequisite& p, const paths& sp)
+ search_existing_file (prerequisite& p, const dir_paths& sp)
{
tracer trace ("search_existing_file");
@@ -64,7 +64,7 @@ namespace build
// Go over paths and extension looking for a file.
//
- for (const path& d: sp)
+ for (const dir_path& d: sp)
{
path f (d / p.dir / path (p.name));
f.normalize ();
@@ -116,7 +116,7 @@ namespace build
// We default to the target in this prerequisite's directory scope.
//
- path d;
+ dir_path d;
if (p.dir.absolute ())
d = p.dir; // Already normalized.
else
diff --git a/build/spec b/build/spec
index ace0400..4a6036a 100644
--- a/build/spec
+++ b/build/spec
@@ -21,10 +21,10 @@ namespace build
explicit
targetspec (name_type n): name (std::move (n)) {}
- targetspec (path sb, name_type n)
+ targetspec (dir_path sb, name_type n)
: src_base (std::move (sb)), name (std::move (n)) {}
- path src_base;
+ dir_path src_base;
name_type name;
};
diff --git a/build/spec.cxx b/build/spec.cxx
index a1f6283..f796ad9 100644
--- a/build/spec.cxx
+++ b/build/spec.cxx
@@ -17,19 +17,10 @@ namespace build
{
if (!s.src_base.empty ())
{
- string d (diag_relative (s.src_base));
+ string d (diag_relative (s.src_base, false));
- if (d != ".")
- {
- os << d;
-
- // Add the directory separator unless it is already there.
- //
- if (d.back () != path::traits::directory_separator)
- os << path::traits::directory_separator;
-
- os << '=';
- }
+ if (!d.empty ())
+ os << d << '@';
}
os << s.name;
diff --git a/build/target b/build/target
index 48accc8..dd62ec8 100644
--- a/build/target
+++ b/build/target
@@ -76,7 +76,7 @@ namespace build
std::type_index id;
const char* name;
const target_type* base;
- target* (*const factory) (path, std::string, const std::string*);
+ target* (*const factory) (dir_path, std::string, const std::string*);
target* (*const search) (prerequisite&);
};
@@ -92,10 +92,10 @@ namespace build
virtual
~target () = default;
- target (path d, std::string n, const std::string* e)
+ target (dir_path d, std::string n, const std::string* e)
: dir (std::move (d)), name (std::move (n)), ext (e) {}
- const path dir; // Absolute and normalized.
+ const dir_path dir; // Absolute and normalized.
const std::string name;
const std::string* ext; // Extension, NULL means unspecified.
@@ -183,7 +183,7 @@ namespace build
struct target_key
{
mutable const target_type* type;
- mutable const path* dir;
+ mutable const dir_path* dir;
mutable const std::string* name;
mutable const std::string* const* ext;
@@ -221,7 +221,7 @@ namespace build
iterator
find (const target_type& type,
- const path& dir,
+ const dir_path& dir,
const std::string& name,
const std::string* ext,
tracer& trace) const
@@ -235,7 +235,7 @@ namespace build
std::pair<target&, bool>
insert (const target_type&,
- path dir,
+ dir_path dir,
std::string name,
const std::string* ext,
tracer&);
@@ -278,7 +278,7 @@ namespace build
template <typename T>
target*
- target_factory (path d, std::string n, const std::string* e)
+ target_factory (dir_path d, std::string n, const std::string* e)
{
return new T (std::move (d), std::move (n), e);
}
diff --git a/build/target.cxx b/build/target.cxx
index 4f49206..db02979 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -105,7 +105,7 @@ namespace build
pair<target&, bool> target_set::
insert (const target_type& tt,
- path dir,
+ dir_path dir,
std::string name,
const std::string* ext,
tracer& trace)
@@ -127,26 +127,26 @@ namespace build
ostream&
operator<< (ostream& os, const target_key& k)
{
+ // If the name is empty, then we want to print the directory
+ // inside {}, e.g., dir{bar/}, not bar/dir{}.
+ //
+ bool n (!k.name->empty ());
+ string d (diag_relative (*k.dir, false));
+
+ if (n)
+ os << d;
+
os << k.type->name << '{';
- if (!k.dir->empty ())
+ if (n)
{
- string s (diag_relative (*k.dir));
-
- if (s != ".")
- {
- os << s;
+ os << *k.name;
- if (!k.name->empty () &&
- s.back () != path::traits::directory_separator)
- os << path::traits::directory_separator;
- }
+ if (*k.ext != nullptr && !(*k.ext)->empty ())
+ os << '.' << **k.ext;
}
-
- os << *k.name;
-
- if (*k.ext != nullptr && !(*k.ext)->empty ())
- os << '.' << **k.ext;
+ else
+ os << d;
os << '}';
@@ -197,7 +197,7 @@ namespace build
//
if (!v.empty ())
{
- n.dir /= path (v); // Move name value to dir.
+ n.dir /= dir_path (v); // Move name value to dir.
v.clear ();
}
}
@@ -212,7 +212,7 @@ namespace build
if (i != string::npos)
{
- n.dir /= path (v, i != 0 ? i : 1); // Special case: "/".
+ n.dir /= dir_path (v, i != 0 ? i : 1); // Special case: "/".
v = string (v, i + 1, string::npos);
}
@@ -255,7 +255,7 @@ namespace build
//
if (p.dir.relative ())
{
- paths sp;
+ dir_paths sp;
sp.push_back (src_out (p.scope.path (), p.scope)); // src_base
return search_existing_file (p, sp);
diff --git a/build/types b/build/types
index c191eec..6850056 100644
--- a/build/types
+++ b/build/types
@@ -15,6 +15,7 @@ namespace build
//
typedef std::vector<path> paths;
+ typedef std::vector<dir_path> dir_paths;
}
#endif // BUILD_TYPES
diff --git a/build/utility b/build/utility
index 3196c81..6584c0a 100644
--- a/build/utility
+++ b/build/utility
@@ -20,6 +20,7 @@ namespace build
//
extern const std::string empty_string;
extern const path empty_path;
+ extern const dir_path empty_dir_path;
// Comparators.
//
diff --git a/build/utility.cxx b/build/utility.cxx
index c66fba2..d84db52 100644
--- a/build/utility.cxx
+++ b/build/utility.cxx
@@ -10,6 +10,7 @@ namespace build
{
const string empty_string;
const path empty_path;
+ const dir_path empty_dir_path;
bool exception_unwinding_dtor = false;
diff --git a/build/variable b/build/variable
index 1365d54..f994b58 100644
--- a/build/variable
+++ b/build/variable
@@ -69,10 +69,7 @@ namespace build
public:
list_value (names d): names (std::move (d)) {}
list_value (std::string d) {emplace_back (std::move (d));}
-
- // Note: stored in name as a directory.
- //
- list_value (path d) {emplace_back (std::move (d));}
+ list_value (dir_path d) {emplace_back (std::move (d));}
virtual value_ptr
clone () const {return value_ptr (new list_value (*this));}
@@ -122,10 +119,8 @@ namespace build
const value_proxy&
operator= (std::string) const;
- // Note: stored in name as a directory.
- //
const value_proxy&
- operator= (path) const;
+ operator= (dir_path) const;
// Implementation details.
//
@@ -155,11 +150,9 @@ namespace build
const std::string& value_proxy::
as<const std::string&> () const;
- // Note: get the name's dir.
- //
template <>
- const path& value_proxy::
- as<const path&> () const;
+ const dir_path& value_proxy::
+ as<const dir_path&> () const;
}
namespace std
diff --git a/build/variable.cxx b/build/variable.cxx
index 7067d9b..8f99ad9 100644
--- a/build/variable.cxx
+++ b/build/variable.cxx
@@ -39,17 +39,15 @@ namespace build
return n.value;
}
- // Note: get the name's directory.
- //
template <>
- const path& value_proxy::
- as<const path&> () const
+ const dir_path& value_proxy::
+ as<const dir_path&> () const
{
const list_value& lv (as<list_value&> ());
assert (lv.size () < 2);
if (lv.empty ())
- return empty_path;
+ return empty_dir_path;
const name& n (lv.front ());
diff --git a/build/variable.ixx b/build/variable.ixx
index ca5a24a..2d52d9f 100644
--- a/build/variable.ixx
+++ b/build/variable.ixx
@@ -37,7 +37,7 @@ namespace build
}
inline const value_proxy& value_proxy::
- operator= (path v) const
+ operator= (dir_path v) const
{
p->reset (new list_value (std::move (v)));
return *this;