aboutsummaryrefslogtreecommitdiff
path: root/build2/functions-path.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-11-30 17:32:43 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-30 17:32:43 +0200
commitbe14801929cf2a6caced87df034ae12a85f42aa6 (patch)
tree74670e0a746961424e50c09449d526e143c1abfc /build2/functions-path.cxx
parent4b31ef06275ad423e48a75d15fb0ee21c3127e3c (diff)
Add support for typed/untyped concatenated expansion
Diffstat (limited to 'build2/functions-path.cxx')
-rw-r--r--build2/functions-path.cxx115
1 files changed, 100 insertions, 15 deletions
diff --git a/build2/functions-path.cxx b/build2/functions-path.cxx
index c97518c..e21609c 100644
--- a/build2/functions-path.cxx
+++ b/build2/functions-path.cxx
@@ -20,33 +20,118 @@ namespace build2
fail << "invalid path: '" << e.path << "'" << endf;
}
+ static value
+ concat_path_string (path l, string sr)
+ {
+ if (path::traits::is_separator (sr[0])) // '\0' if empty.
+ {
+ sr.erase (0, 1);
+ path pr (move (sr));
+ pr.canonicalize (); // Convert to canonical directory separators.
+
+ // If RHS is syntactically a directory (ends with a trailing slash),
+ // then return it as dir_path, not path.
+ //
+ if (pr.to_directory () || pr.empty ())
+ return value (
+ path_cast<dir_path> (move (l)) /= path_cast<dir_path> (move (pr)));
+ else
+ l /= pr;
+ }
+ else
+ l += sr;
+
+ return value (move (l));
+ }
+
+ static value
+ concat_dir_path_string (dir_path l, string sr)
+ {
+ if (path::traits::is_separator (sr[0])) // '\0' if empty.
+ {
+ sr.erase (0, 1);
+ path pr (move (sr));
+ pr.canonicalize (); // Convert to canonical directory separators.
+
+ // If RHS is syntactically a directory (ends with a trailing slash),
+ // then return it as dir_path, not path.
+ //
+ if (pr.to_directory () || pr.empty ())
+ l /= path_cast<dir_path> (move (pr));
+ else
+ return value (path_cast<path> (move (l)) /= pr);
+ }
+ else
+ l += sr;
+
+ return value (move (l));
+ }
+
void
path_functions ()
{
function_family f ("path", &path_thunk);
+ // string
+ //
+ f["string"] = [](path p) {return move (p).string ();};
+ f["string"] = [](dir_path p) {return move (p).string ();};
+
+ f["string"] = [](paths v)
+ {
+ strings r;
+ for (auto& p: v)
+ r.push_back (move (p).string ());
+ return r;
+ };
+
+ f["string"] = [](dir_paths v)
+ {
+ strings r;
+ for (auto& p: v)
+ r.push_back (move (p).string ());
+ return r;
+ };
+
// normalize
//
f["normalize"] = [](path p) {p.normalize (); return p;};
- f["normalize"] = [](paths v) {for (auto& p: v) p.normalize (); return v;};
-
f["normalize"] = [](dir_path p) {p.normalize (); return p;};
+
+ f["normalize"] = [](paths v) {for (auto& p: v) p.normalize (); return v;};
f["normalize"] = [](dir_paths v) {for (auto& p: v) p.normalize (); return v;};
f[".normalize"] = [](names ns)
+ {
+ // For each path decide based on the presence of a trailing slash
+ // whether it is a directory. Return as untyped list of (potentially
+ // mixed) paths.
+ //
+ for (name& n: ns)
{
- // For each path decide based on the presence of a trailing slash
- // whether it is a directory. Return as untyped list of (potentially
- // mixed) paths.
- //
- for (name& n: ns)
- {
- if (n.directory ())
- n.dir.normalize ();
- else
- n.value = convert<path> (move (n)).normalize ().string ();
- }
- return ns;
- };
+ if (n.directory ())
+ n.dir.normalize ();
+ else
+ n.value = convert<path> (move (n)).normalize ().string ();
+ }
+ return ns;
+ };
+
+ // Path-specific overloads from builtins.
+ //
+ function_family b ("builtin", &path_thunk);
+
+ b[".concat"] = &concat_path_string;
+ b[".concat"] = &concat_dir_path_string;
+
+ b[".concat"] = [](path l, names ur)
+ {
+ return concat_path_string (move (l), convert<string> (move (ur)));
+ };
+
+ b[".concat"] = [](dir_path l, names ur)
+ {
+ return concat_dir_path_string (move (l), convert<string> (move (ur)));
+ };
}
}