aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-12-14 08:03:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-12-14 08:03:32 +0200
commit218a739b33325c5dd6baa5cf6291dad849ad2441 (patch)
tree754661d712d80d87c1c113cb7bfd6ec542e5858b
parent6d892e32a83908406a6f2fc6d47dd4a8b131fc60 (diff)
Handle NULL values in $string() and $concat() functions
This is relied upon by the parser to provide conversion/concatenation semantics consistent with untyped values. Note that we handle NULL values only for types that have empty representation.
-rw-r--r--libbuild2/functions-bool.cxx3
-rw-r--r--libbuild2/functions-integer.cxx3
-rw-r--r--libbuild2/functions-name.cxx13
-rw-r--r--libbuild2/functions-path.cxx13
-rw-r--r--libbuild2/functions-project-name.cxx13
-rw-r--r--libbuild2/functions-string.cxx34
-rw-r--r--libbuild2/functions-target-triplet.cxx19
-rw-r--r--libbuild2/parser.cxx3
-rw-r--r--tests/value/concat.testscript42
9 files changed, 124 insertions, 19 deletions
diff --git a/libbuild2/functions-bool.cxx b/libbuild2/functions-bool.cxx
index 1ae89d2..1d9c72f 100644
--- a/libbuild2/functions-bool.cxx
+++ b/libbuild2/functions-bool.cxx
@@ -15,6 +15,9 @@ namespace build2
// $string(<bool>)
//
+ // Note that we don't handle NULL values for this type since it has no
+ // empty representation.
+ //
f["string"] += [](bool b) {return b ? "true" : "false";};
}
}
diff --git a/libbuild2/functions-integer.cxx b/libbuild2/functions-integer.cxx
index ddfc250..a634ae9 100644
--- a/libbuild2/functions-integer.cxx
+++ b/libbuild2/functions-integer.cxx
@@ -69,6 +69,9 @@ namespace build2
// $string(<int64>)
// $string(<uint64>[, <base>[, <width>]])
//
+ // Note that we don't handle NULL values for these type since they have no
+ // empty representation.
+ //
f["string"] += [](int64_t i) {return to_string (i);};
f["string"] += [](uint64_t i, optional<value> base, optional<value> width)
diff --git a/libbuild2/functions-name.cxx b/libbuild2/functions-name.cxx
index 9011cc0..84608d4 100644
--- a/libbuild2/functions-name.cxx
+++ b/libbuild2/functions-name.cxx
@@ -142,7 +142,13 @@ namespace build2
//
function_family fn (m, "name");
- fn["string"] += [](name n) {return to_string (n);};
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
+ //
+ fn["string"] += [](name* n)
+ {
+ return n != nullptr ? to_string (move (*n)) : string ();
+ };
fn["name"] += [](const scope* s, name n)
{
@@ -438,6 +444,11 @@ namespace build2
//
function_family fb (m, "builtin");
+ // Note that while we should normally handle NULL values (relied upon by
+ // the parser to provide concatenation semantics consistent with untyped
+ // values), the result will unlikely be what the user expected. So for now
+ // we keep it a bit tighter.
+ //
fb[".concat"] += [](dir_path d, name n)
{
d /= n.dir;
diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx
index 0c9b57f..b5511ad 100644
--- a/libbuild2/functions-path.cxx
+++ b/libbuild2/functions-path.cxx
@@ -161,7 +161,13 @@ namespace build2
// string
//
- f["string"] += [](path p) {return move (p).string ();};
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
+ //
+ f["string"] += [](path* p)
+ {
+ return p != nullptr ? move (*p).string () : string ();
+ };
f["string"] += [](paths v)
{
@@ -694,6 +700,11 @@ namespace build2
//
function_family b (m, "builtin", &path_thunk);
+ // Note that while we should normally handle NULL values (relied upon by
+ // the parser to provide concatenation semantics consistent with untyped
+ // values), the result will unlikely be what the user expected, especially
+ // if the NULL value is on the LHS. So for now we keep it a bit tighter.
+ //
b[".concat"] += &concat_path_string;
b[".concat"] += &concat_dir_path_string;
diff --git a/libbuild2/functions-project-name.cxx b/libbuild2/functions-project-name.cxx
index 145e62c..4a8394d 100644
--- a/libbuild2/functions-project-name.cxx
+++ b/libbuild2/functions-project-name.cxx
@@ -13,7 +13,13 @@ namespace build2
{
function_family f (m, "project_name");
- f["string"] += [](project_name p) {return move (p).string ();};
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
+ //
+ f["string"] += [](project_name* p)
+ {
+ return p != nullptr ? move (*p).string () : string ();
+ };
f["base"] += [](project_name p, optional<string> ext)
{
@@ -32,6 +38,11 @@ namespace build2
//
function_family b (m, "builtin");
+ // Note that while we should normally handle NULL values (relied upon by
+ // the parser to provide concatenation semantics consistent with untyped
+ // values), the result will unlikely be what the user expected. So for now
+ // we keep it a bit tighter.
+ //
b[".concat"] += [](project_name n, string s)
{
string r (move (n).string ());
diff --git a/libbuild2/functions-string.cxx b/libbuild2/functions-string.cxx
index f5d7cb1..06fe89d 100644
--- a/libbuild2/functions-string.cxx
+++ b/libbuild2/functions-string.cxx
@@ -39,12 +39,13 @@ namespace build2
{
function_family f (m, "string");
- f["string"] += [](string s) {return s;};
-
- // @@ Shouldn't it concatenate elements into the single string?
- // @@ Doesn't seem to be used so far. Can consider removing.
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
//
- // f["string"] += [](strings v) {return v;};
+ f["string"] += [](string* s)
+ {
+ return s != nullptr ? move (*s) : string ();
+ };
// Compare ASCII strings ignoring case and returning the boolean value.
//
@@ -195,19 +196,26 @@ namespace build2
//
function_family b (m, "builtin");
- b[".concat"] += [](string l, string r) {l += r; return l;};
+ // Note that we must handle NULL values (relied upon by the parser to
+ // provide concatenation semantics consistent with untyped values).
+ //
+ b[".concat"] += [](string* l, string* r)
+ {
+ return l != nullptr
+ ? r != nullptr ? move (*l += *r) : move (*l)
+ : r != nullptr ? move (*r) : string ();
+ };
- b[".concat"] += [](string l, names ur)
+ b[".concat"] += [](string* l, names* ur)
{
- l += convert<string> (move (ur));
- return l;
+ string r (ur != nullptr ? convert<string> (move (*ur)) : string ());
+ return l != nullptr ? move (*l += r) : move (r);
};
- b[".concat"] += [](names ul, string r)
+ b[".concat"] += [](names* ul, string* r)
{
- string l (convert<string> (move (ul)));
- l += r;
- return l;
+ string l (ul != nullptr ? convert<string> (move (*ul)) : string ());
+ return r != nullptr ? move (l += *r) : move (l);
};
}
}
diff --git a/libbuild2/functions-target-triplet.cxx b/libbuild2/functions-target-triplet.cxx
index 4b0ec02..b89cadf 100644
--- a/libbuild2/functions-target-triplet.cxx
+++ b/libbuild2/functions-target-triplet.cxx
@@ -13,13 +13,28 @@ namespace build2
{
function_family f (m, "target_triplet");
- f["string"] += [](target_triplet t) {return t.string ();};
- f["representation"] += [](target_triplet t) {return t.representation ();};
+ // Note that we must handle NULL values (relied upon by the parser
+ // to provide conversion semantics consistent with untyped values).
+ //
+ f["string"] += [](target_triplet* t)
+ {
+ return t != nullptr ? t->string () : string ();
+ };
+
+ f["representation"] += [](target_triplet t)
+ {
+ return t.representation ();
+ };
// Target triplet-specific overloads from builtins.
//
function_family b (m, "builtin");
+ // Note that while we should normally handle NULL values (relied upon by
+ // the parser to provide concatenation semantics consistent with untyped
+ // values), the result will unlikely be what the user expected. So for now
+ // we keep it a bit tighter.
+ //
b[".concat"] += [](target_triplet l, string sr) {return l.string () + sr;};
b[".concat"] += [](string sl, target_triplet r) {return sl + r.string ();};
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index dd2944d..812f201 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -7719,7 +7719,8 @@ namespace build2
// then it should not be overloaded for a type). In a quoted
// context we use $string() which returns a "canonical
// representation" (e.g., a directory path without a trailing
- // slash).
+ // slash). Note: looks like we use typed $concat() now in the
+ // unquoted context.
//
if (result->type != nullptr && quoted)
{
diff --git a/tests/value/concat.testscript b/tests/value/concat.testscript
index 97391c4..69ec9fc 100644
--- a/tests/value/concat.testscript
+++ b/tests/value/concat.testscript
@@ -3,6 +3,48 @@
.include ../common.testscript
+: null
+:
+{
+ : untyped
+ :
+ $* <<EOI >>/EOO
+ x = [null]
+
+ print y "$x x"
+ print "x $x" y
+
+ print $x"x"
+ print "x"$x
+ print $x$x
+ EOI
+ y x
+ x y
+ x
+ x
+ {}
+ EOO
+
+ : string
+ :
+ $* <<EOI >>/EOO
+ x = [string,null]
+
+ print y "$x x"
+ print "x $x" y
+
+ print $x"x"
+ print "x"$x
+ print $x$x
+ EOI
+ y x
+ x y
+ x
+ x
+ {}
+ EOO
+}
+
: dir_path
:
{