From f50d0d58c8eb659e803282e19cf15398e3a8e373 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 3 Jun 2020 14:38:39 +0300 Subject: Fix $process.run() to properly handle proces_path_ex --- libbuild2/build/script/parser.cxx | 12 +++--------- libbuild2/functions-process.cxx | 34 +++++++++++++++++++++++++++------- libbuild2/variable.cxx | 15 ++++++++++++++- libbuild2/variable.hxx | 14 ++++++++++---- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 2a0555e..c4c4b03 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -475,18 +475,12 @@ namespace build2 { // Find the end of the value. // - auto b (ns.begin ()), i (b), e (ns.end ()); - for (i += i->pair ? 2 : 1; i != e && i->pair; i += 2) - { - if (!i->simple () || - (i->value != "name" && i->value != "checksum")) - break; - } + auto b (ns.begin ()); + auto i (value_traits::find_end (ns)); if (b->pair || i != b + 1) // First is a pair or pairs after. { - pp_ns.insert (pp_ns.end (), - make_move_iterator (b), make_move_iterator (i)); + pp_ns = names (make_move_iterator (b), make_move_iterator (i)); ns.erase (b, i); diff --git a/libbuild2/functions-process.cxx b/libbuild2/functions-process.cxx index e6c0582..de06f27 100644 --- a/libbuild2/functions-process.cxx +++ b/libbuild2/functions-process.cxx @@ -210,19 +210,39 @@ namespace build2 if (args.empty () || args[0].empty ()) fail << "executable name expected in process." << fn << "()"; - process_path pp; + optional pp; + try { size_t erase; - // This can be a process_path (pair) or just a path. + // This can be a process_path (pair), process_path_ex (process_path + // followed by the name@ and checksum@ pairs), or just a path. + // + // First, check if the arguments begin with a process_path[_ex] and, if + // that's the case, only use the leading name/pair to create the process + // path, discarding the meta-information. // - if (args[0].pair) + if (args[0].file ()) { - pp = convert (move (args[0]), move (args[1])); - erase = 2; + // Find the end of the process_path[_ex] value. + // + auto b (args.begin ()); + auto i (value_traits::find_end (args)); + + if (b->pair || i != b + 1) // First is a pair or pairs after. + { + pp = convert ( + names (make_move_iterator (b), + make_move_iterator (b + (b->pair ? 2 : 1)))); + + erase = i - b; + } } - else + + // Fallback to a path, if this is not a process path. + // + if (!pp) { // Strip the builtin-escaping '^' character, if present. // @@ -254,7 +274,7 @@ namespace build2 fail << "invalid process." << fn << "() executable path: " << e; } - return pair (move (pp), + return pair (move (*pp), program_args (move (args), fn)); } diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx index e0502ef..9009fdc 100644 --- a/libbuild2/variable.cxx +++ b/libbuild2/variable.cxx @@ -1083,7 +1083,7 @@ namespace build2 const string& k ((i++)->value); - // NOTE: see also build::script::parser::parse_program(). + // NOTE: see also find_end() below. // if (k == "name") { @@ -1107,6 +1107,19 @@ namespace build2 return pp; } + names::iterator value_traits:: + find_end (names& ns) + { + auto b (ns.begin ()), i (b), e (ns.end ()); + for (i += i->pair ? 2 : 1; i != e && i->pair; i += 2) + { + if (!i->simple () || (i->value != "name" && i->value != "checksum")) + break; + } + + return i; + } + static void process_path_ex_assign (value& v, names&& ns, const variable* var) { diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx index 9febe5e..c1cfa84 100644 --- a/libbuild2/variable.hxx +++ b/libbuild2/variable.hxx @@ -881,8 +881,8 @@ namespace build2 static_assert (sizeof (process_path) <= value::size_, "insufficient space"); - // Represented as a @-pair of names. As a result it cannot be stored in a - // container. + // Represented as a potential @-pair of name(s). As a result it cannot be + // stored in a container. // static process_path convert (name&&, name*); static void assign (value&, process_path&&); @@ -902,8 +902,9 @@ namespace build2 static_assert (sizeof (process_path_ex) <= value::size_, "insufficient space"); - // Represented as a @-pair of names corresponding to process_path followed - // by the name@ and checksum@ pairs. So it's a container-like. + // Represented as a potential @-pair of name(s) corresponding to + // process_path followed by the name@ and checksum@ pairs. So it's a + // container-like. // static process_path_ex convert (names&&); static void assign (value&, process_path_ex&&); @@ -912,6 +913,11 @@ namespace build2 static const bool empty_value = true; static const char* const type_name; static const build2::value_type value_type; + + // Find the end of the process_path_ex value representation assuming + // the first name or name pair is the process_path representation. + // + static names::iterator find_end (names&); }; // target_triplet -- cgit v1.1