From be14801929cf2a6caced87df034ae12a85f42aa6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 30 Nov 2016 17:32:43 +0200 Subject: Add support for typed/untyped concatenated expansion --- build2/functions-path.cxx | 115 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 15 deletions(-) (limited to 'build2/functions-path.cxx') 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 (move (l)) /= path_cast (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 (move (pr)); + else + return value (path_cast (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 (move (n)).normalize ().string (); - } - return ns; - }; + if (n.directory ()) + n.dir.normalize (); + else + n.value = convert (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 (move (ur))); + }; + + b[".concat"] = [](dir_path l, names ur) + { + return concat_dir_path_string (move (l), convert (move (ur))); + }; } } -- cgit v1.1