aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/functions-path.cxx148
-rw-r--r--tests/function/path/testscript65
2 files changed, 213 insertions, 0 deletions
diff --git a/build2/functions-path.cxx b/build2/functions-path.cxx
index 45ec8ed..77c1464 100644
--- a/build2/functions-path.cxx
+++ b/build2/functions-path.cxx
@@ -63,6 +63,38 @@ namespace build2
: value (path_cast<path> (move (l)) /= pr);
}
+ // Return untyped value or NULL value if extension is not present.
+ //
+ static inline value
+ extension (path p)
+ {
+ const char* e (p.extension_cstring ());
+
+ if (e == nullptr)
+ return value ();
+
+ names r;
+ r.emplace_back (e);
+ return value (move (r));
+ }
+
+ template <typename P>
+ static inline P
+ leaf (const P& p, const optional<dir_path>& d)
+ {
+ if (!d)
+ return p.leaf ();
+
+ try
+ {
+ return p.leaf (*d);
+ }
+ catch (const invalid_path&)
+ {
+ fail << "'" << *d << "' is not a prefix of '" << p << "'" << endf;
+ }
+ }
+
void
path_functions ()
{
@@ -193,6 +225,122 @@ namespace build2
return ns;
};
+ // directory
+ //
+ f["directory"] = &path::directory;
+
+ f["directory"] = [](paths v)
+ {
+ dir_paths r;
+ for (const path& p: v)
+ r.push_back (p.directory ());
+ return r;
+ };
+
+ f["directory"] = [](dir_paths v)
+ {
+ for (dir_path& p: v)
+ p = p.directory ();
+ return v;
+ };
+
+ f[".directory"] = [](names ns)
+ {
+ // For each path decide based on the presence of a trailing slash
+ // whether it is a directory. Return as list of directory names.
+ //
+ for (name& n: ns)
+ {
+ if (n.directory ())
+ n.dir = n.dir.directory ();
+ else
+ n = convert<path> (move (n)).directory ();
+ }
+ return ns;
+ };
+
+ // base
+ //
+ f["base"] = &path::base;
+
+ f["base"] = [](paths v)
+ {
+ for (path& p: v)
+ p = p.base ();
+ return v;
+ };
+
+ f["base"] = [](dir_paths v)
+ {
+ for (dir_path& p: v)
+ p = p.base ();
+ return v;
+ };
+
+ f[".base"] = [](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)
+ {
+ if (n.directory ())
+ n.dir = n.dir.base ();
+ else
+ n.value = convert<path> (move (n)).base ().string ();
+ }
+ return ns;
+ };
+
+ // leaf
+ //
+ f["leaf"] = &path::leaf;
+
+ f["leaf"] = [](path p, dir_path d)
+ {
+ return leaf (p, move (d));
+ };
+
+ f["leaf"] = [](paths v, optional<dir_path> d)
+ {
+ for (path& p: v)
+ p = leaf (p, d);
+ return v;
+ };
+
+ f["leaf"] = [](dir_paths v, optional<dir_path> d)
+ {
+ for (dir_path& p: v)
+ p = leaf (p, d);
+ return v;
+ };
+
+ f[".leaf"] = [](names ns, optional<dir_path> d)
+ {
+ // 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 = leaf (n.dir, d);
+ else
+ n.value = leaf (convert<path> (move (n)), d).string ();
+ }
+ return ns;
+ };
+
+ // extension
+ //
+ f["extension"] = &extension;
+
+ f[".extension"] = [](names ns)
+ {
+ return extension (convert<path> (move (ns)));
+ };
+
// Path-specific overloads from builtins.
//
function_family b ("builtin", &path_thunk);
diff --git a/tests/function/path/testscript b/tests/function/path/testscript
index bfbc895..7d53807 100644
--- a/tests/function/path/testscript
+++ b/tests/function/path/testscript
@@ -36,6 +36,71 @@ s = ($cxx.target.class != 'windows' ? '/' : '\')
}
}
+: directory
+:
+{
+ $* <'print $directory([path] a/b)' >"a/" : path
+ $* <'print $directory([dir_path] a/b)' >"a/" : dir-path
+ $* <'print $directory([paths] a/b c/d/)' >"a/ c/" : paths
+ $* <'print $directory([dir_paths] a/b c/d/)' >"a/ c/" : dir-paths
+ $* <'print $path.directory(a/b c/d/)' >"a/ c/" : dir-names
+}
+
+: base
+:
+{
+ $* <'print $base([path] a.c)' >"a" : path
+ $* <'print $base([dir_path] a.tmp)' >"a$s" : dir-path
+ $* <'print $base([paths] a.c b.tmp/)' >"a b/" : paths
+ $* <'print $base([dir_paths] a.tmp b.tmp/)' >"a$s b/" : dir-paths
+ $* <'print $path.base(a.c b.tmp/)' >"a b/" : dir-names
+}
+
+: leaf
+:
+{
+ $* <'print $leaf([path] a/b)' >"b" : path
+ $* <'print $leaf([dir_path] a/b)' >"b$s" : dir-path
+ $* <'print $leaf([path] a/b/c, [dir_path] a)' >"b/c" : sub-path
+ $* <'print $leaf([dir_path] a/b/c, [dir_path] a)' >"b/c$s" : sub-dir-path
+ $* <'print $leaf([paths] a/b/c a/b/e, [dir_path] a/b)' >"c e" : sub-paths
+ $* <'print $leaf([dir_paths] a/b/c, [dir_path] a/b)' >"c$s" : sub-dir-paths
+ $* <'print $path.leaf(a/b c/d/)' >"b d/" : dir-names
+ $* <'print $path.leaf(a/b/c a/b/d/, [dir_path] a)' >"b/c b/d/" : sub-dir-names
+
+ : not-prefix
+ :
+ $* <'print $leaf([path] a/b/c, [dir_path] a/d)' 2>>"EOE" != 0
+ error: 'a/d$s' is not a prefix of 'a/b/c'
+ EOE
+}
+
+: extension
+:
+{
+ $* <'print $extension([path] a.c)' >"c" : path
+ $* <'print $extension([dir_path] a.tmp/)' >"tmp" : dir_path
+ $* <'print $path.extension(a.c)' >"c" : untyped
+ $* <'print $path.extension(a)' >"[null]" : null
+}
+
+: combined
+:
+{
+ mkdir -p a/b;
+ touch a/b/c.t.cpp;
+ $* <<EOI >>/EOO
+ t = $src_base/a/b/c.t.cpp
+ d = $path.leaf($path.directory($t), $src_base)
+ n = $path.base($path.base($path.leaf($t)))
+ print $d/exe{$n}
+ print $d/{+$n*.cpp}
+ EOI
+ a/b/exe{c}
+ a/b/c.t.cpp
+ EOO
+}
+
: invalid-path
:
p = ($cxx.target.class != 'windows' ? /../foo : 'c:/../foo');