aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-10 10:01:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-10 10:01:45 +0200
commit1ea33ab70f88fcfebf388a9a438e3c1e56fbdf0f (patch)
tree359f61dc51fee77abd1f376b45418501de549104 /libbuild2/parser.cxx
parentd5faeeab1d2115c02a330ac9c95d63ba225faabc (diff)
Handle special variable names when spelled as $(<char>) rather than $<char>
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r--libbuild2/parser.cxx43
1 files changed, 41 insertions, 2 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index db00633..36e75a3 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -5815,7 +5815,44 @@ namespace build2
// token is a paren or a word, we turn it on and switch to the eval
// mode if what we get next is a paren.
//
+ // Also sniff out the special variables string from mode data for
+ // the ad hoc $() handling below.
+ //
mode (lexer_mode::variable);
+
+ auto special = [s = reinterpret_cast<const char*> (mode_data ())]
+ (const token& t) -> char
+ {
+ char r ('\0');
+
+ if (s != nullptr)
+ {
+ switch (t.type)
+ {
+ case type::less: r = '<'; break;
+ case type::greater: r = '>'; break;
+ case type::colon: r = ':'; break;
+ case type::dollar: r = '$'; break;
+ case type::question: r = '?'; break;
+ case type::comma: r = ','; break;
+ case type::log_not: r = '!'; break;
+ case type::lparen: r = '('; break;
+ case type::rparen: r = ')'; break;
+ case type::lcbrace: r = '{'; break;
+ case type::rcbrace: r = '}'; break;
+ case type::lsbrace: r = '['; break;
+ case type::rsbrace: r = ']'; break;
+ case type::pair_separator: r = t.value[0]; break;
+ default: break;
+ }
+
+ if (r != '\0' && strchr (s, r) == nullptr)
+ r = '\0';
+ }
+
+ return r;
+ };
+
next (t, tt);
loc = get_location (t);
@@ -5838,9 +5875,11 @@ namespace build2
// the variable name even during pre-parse. It should also be
// faster.
//
- if (tt == type::word && peek () == type::rparen)
+ char c;
+ if ((tt == type::word || (c = special (t))) &&
+ peek () == type::rparen)
{
- name = move (t.value);
+ name = (tt == type::word ? move (t.value) : string (1, c));
next (t, tt); // Get `)`.
}
else