aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/functions-name.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/functions-name.cxx')
-rw-r--r--libbuild2/functions-name.cxx160
1 files changed, 52 insertions, 108 deletions
diff --git a/libbuild2/functions-name.cxx b/libbuild2/functions-name.cxx
index a853db1..7dddc3a 100644
--- a/libbuild2/functions-name.cxx
+++ b/libbuild2/functions-name.cxx
@@ -151,23 +151,30 @@ namespace build2
// on prerequisite names. They also won't always return the same result as
// if we were interrogating an actual target (e.g., the directory may be
// relative). Plus we now have functions that can only be called on
- // targets (see below).
+ // targets (see functions-target.cxx).
//
- function_family fn (m, "name");
+ function_family f (m, "name");
+ // Note: let's leave this undocumented for now since it's not often needed
+ // and is a can of worms.
+ //
// Note that we must handle NULL values (relied upon by the parser
// to provide conversion semantics consistent with untyped values).
//
- fn["string"] += [](name* n)
+ f["string"] += [](name* n)
{
return n != nullptr ? to_string (move (*n)) : string ();
};
- fn["name"] += [](const scope* s, name n)
+ // $name(<names>)
+ //
+ // Return the name of a target (or a list of names for a list of targets).
+ //
+ f["name"] += [](const scope* s, name n)
{
return to_target_name (s, move (n)).first.value;
};
- fn["name"] += [](const scope* s, names ns)
+ f["name"] += [](const scope* s, names ns)
{
small_vector<string, 1> r;
@@ -185,14 +192,18 @@ namespace build2
make_move_iterator (r.end ())));
};
- // Note: returns NULL if extension is unspecified (default) and empty if
- // specified as no extension.
+ // $extension(<name>)
+ //
+ // Return the extension of a target.
+ //
+ // Note that this function returns `null` if the extension is unspecified
+ // (default) and empty string if it's specified as no extension.
//
- fn["extension"] += [](const scope* s, name n)
+ f["extension"] += [](const scope* s, name n)
{
return to_target_name (s, move (n)).second;
};
- fn["extension"] += [](const scope* s, names ns)
+ f["extension"] += [](const scope* s, names ns)
{
// Note: can't do multiple due to NULL semantics.
//
@@ -207,11 +218,16 @@ namespace build2
return to_target_name (s, move (n), o).second;
};
- fn["directory"] += [](const scope* s, name n)
+ // $directory(<names>)
+ //
+ // Return the directory of a target (or a list of directories for a list
+ // of targets).
+ //
+ f["directory"] += [](const scope* s, name n)
{
return to_target_name (s, move (n)).first.dir;
};
- fn["directory"] += [](const scope* s, names ns)
+ f["directory"] += [](const scope* s, names ns)
{
small_vector<dir_path, 1> r;
@@ -229,11 +245,16 @@ namespace build2
make_move_iterator (r.end ())));
};
- fn["target_type"] += [](const scope* s, name n)
+ // $target_type(<names>)
+ //
+ // Return the target type name of a target (or a list of target type names
+ // for a list of targets).
+ //
+ f["target_type"] += [](const scope* s, name n)
{
return to_target_name (s, move (n)).first.type;
};
- fn["target_type"] += [](const scope* s, names ns)
+ f["target_type"] += [](const scope* s, names ns)
{
small_vector<string, 1> r;
@@ -251,13 +272,15 @@ namespace build2
make_move_iterator (r.end ())));
};
- // Note: returns NULL if no project specified.
+ // $project(<name>)
+ //
+ // Return the project of a target or `null` if not project-qualified.
//
- fn["project"] += [](const scope* s, name n)
+ f["project"] += [](const scope* s, name n)
{
return to_target_name (s, move (n)).first.proj;
};
- fn["project"] += [](const scope* s, names ns)
+ f["project"] += [](const scope* s, names ns)
{
// Note: can't do multiple due to NULL semantics.
//
@@ -278,11 +301,11 @@ namespace build2
// this is a dynamic type check that takes into account target type
// inheritance.
//
- fn["is_a"] += [](const scope* s, name n, names t)
+ f["is_a"] += [](const scope* s, name n, names t)
{
return is_a (s, move (n), name (), move (t));
};
- fn["is_a"] += [](const scope* s, names ns, names t)
+ f["is_a"] += [](const scope* s, names ns, names t)
{
auto i (ns.begin ());
@@ -298,15 +321,15 @@ namespace build2
// $filter(<names>, <target-types>)
// $filter_out(<names>, <target-types>)
//
- // Return names with target types which are-a (filter) or not are-a
- // (filter_out) one of <target-types>. See $is_a() for background.
+ // Return names with target types which are-a (`filter`) or not are-a
+ // (`filter_out`) one of <target-types>. See `$is_a()` for background.
//
- fn["filter"] += [](const scope* s, names ns, names ts)
+ f["filter"] += [](const scope* s, names ns, names ts)
{
return filter (s, move (ns), move (ts), false /* out */);
};
- fn["filter_out"] += [](const scope* s, names ns, names ts)
+ f["filter_out"] += [](const scope* s, names ns, names ts)
{
return filter (s, move (ns), move (ts), true /* out */);
};
@@ -315,7 +338,7 @@ namespace build2
//
// Return the number of elements in the sequence.
//
- fn["size"] += [] (names ns)
+ f["size"] += [] (names ns)
{
size_t n (0);
@@ -329,15 +352,15 @@ namespace build2
return n;
};
- // $sort(<names> [, <flags>])
+ // $sort(<names>[, <flags>])
//
// Sort names in ascending order.
//
// The following flags are supported:
//
- // dedup - in addition to sorting also remove duplicates
+ // dedup - in addition to sorting also remove duplicates
//
- fn["sort"] += [] (names ns, optional<names> fs)
+ f["sort"] += [] (names ns, optional<names> fs)
{
//@@ TODO: shouldn't we do this in a pair-aware manner?
@@ -353,7 +376,7 @@ namespace build2
//
// Return true if the name sequence contains the specified name.
//
- fn["find"] += [](names vs, names v)
+ f["find"] += [](names vs, names v)
{
//@@ TODO: shouldn't we do this in a pair-aware manner?
@@ -364,9 +387,9 @@ namespace build2
// $find_index(<names>, <name>)
//
// Return the index of the first element in the name sequence that is
- // equal to the specified name or $size(<names>) if none is found.
+ // equal to the specified name or `$size(names)` if none is found.
//
- fn["find_index"] += [](names vs, names v)
+ f["find_index"] += [](names vs, names v)
{
//@@ TODO: shouldn't we do this in a pair-aware manner?
@@ -374,85 +397,6 @@ namespace build2
return i != vs.end () ? i - vs.begin () : vs.size ();
};
- // Functions that can be called only on real targets.
- //
- function_family ft (m, "target");
-
- // Note that while this function is not technically pure, we don't mark it
- // as such since it can only be called (normally form a recipe) after the
- // target has been matched, meaning that this target is a prerequisite and
- // therefore this impurity has been accounted for.
- //
- ft["path"] += [](const scope* s, names ns)
- {
- if (s == nullptr)
- fail << "target.path() called out of scope";
-
- // Most of the time we will have a single target so optimize for that.
- //
- small_vector<path, 1> r;
-
- for (auto i (ns.begin ()); i != ns.end (); ++i)
- {
- name& n (*i), o;
- const target& t (to_target (*s, move (n), move (n.pair ? *++i : o)));
-
- if (const auto* pt = t.is_a<path_target> ())
- {
- const path& p (pt->path ());
-
- if (&p != &empty_path)
- r.push_back (p);
- else
- fail << "target " << t << " path is not assigned";
- }
- else
- fail << "target " << t << " is not path-based";
- }
-
- // We want the result to be path if we were given a single target and
- // paths if multiple (or zero). The problem is, we cannot distinguish it
- // based on the argument type (e.g., name vs names) since passing an
- // out-qualified single target requires two names.
- //
- if (r.size () == 1)
- return value (move (r[0]));
-
- return value (paths (make_move_iterator (r.begin ()),
- make_move_iterator (r.end ())));
- };
-
- // This one can only be called on a single target since we don't support
- // containers of process_path's (though we probably could).
- //
- // Note that while this function is not technically pure, we don't mark it
- // as such for the same reasons as $path() above.
- //
- ft["process_path"] += [](const scope* s, names ns)
- {
- if (s == nullptr)
- fail << "target.process_path() called out of scope";
-
- if (ns.empty () || ns.size () != (ns[0].pair ? 2 : 1))
- fail << "target.process_path() expects single target";
-
- name o;
- const target& t (
- to_target (*s, move (ns[0]), move (ns[0].pair ? ns[1] : o)));
-
- if (const auto* et = t.is_a<exe> ())
- {
- process_path r (et->process_path ());
-
- if (r.empty ())
- fail << "target " << t << " path is not assigned";
-
- return r;
- }
- else
- fail << "target " << t << " is not process_path-based" << endf;
- };
-
// Name-specific overloads from builtins.
//
function_family fb (m, "builtin");