aboutsummaryrefslogtreecommitdiff
path: root/build2/b.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-03-17 11:09:36 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-03-17 11:09:36 +0200
commit120722059c8612fb13d7bf585a5593582a49220d (patch)
tree163286ebf4ac50515df8542a34652ef185910184 /build2/b.cxx
parent83f8b6a45fc041586819537ca86be2eb534f79b0 (diff)
Implement alternative command line buildspec and variable assignment syntax
b test: foo/ bar/ b config.import.libhello = ../libhello/
Diffstat (limited to 'build2/b.cxx')
-rw-r--r--build2/b.cxx62
1 files changed, 60 insertions, 2 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index d2ad368..1f0464f 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -117,6 +117,9 @@ main (int argc, char* argv[])
{
cl::argv_scanner scan (argc, argv);
+ size_t argn (0); // Argument count.
+ bool shortcut (false); // True if the shortcut syntax is used.
+
for (bool opt (true), var (true); scan.more (); )
{
if (opt)
@@ -159,12 +162,43 @@ main (int argc, char* argv[])
continue;
}
- if (strchr (s, '=') != nullptr) // Covers =, +=, and =+.
+ if (const char* p = strchr (s, '=')) // Covers =, +=, and =+.
{
+ // Diagnose the empty variable name situation. Note that we don't
+ // allow "partially broken down" assignments (as in foo =bar)
+ // since foo= bar would be ambigous.
+ //
+ if (p == s || (p == s + 1 && *s == '+'))
+ fail << "missing variable name in '" << s << "'";
+
cmd_vars.push_back (s);
continue;
}
+ // Handle the "broken down" variable assignments (i.e., foo = bar
+ // instead of foo=bar).
+ //
+ if (scan.more ())
+ {
+ const char* a (scan.peek ());
+
+ if (strcmp (a, "=" ) == 0 ||
+ strcmp (a, "+=") == 0 ||
+ strcmp (a, "=+") == 0)
+ {
+ string v (s);
+ v += a;
+
+ scan.next ();
+
+ if (scan.more ())
+ v += scan.next ();
+
+ cmd_vars.push_back (move (v));
+ continue;
+ }
+ }
+
// Fall through.
}
@@ -174,10 +208,34 @@ main (int argc, char* argv[])
// diagnostics (i.e., we could have used <buildspec-1>, <buildspec-2>
// to give the idea about which argument is invalid).
//
- if (!args.empty ())
+ // Or we could separate arguments with newlines so that a line number
+ // signifies the argument number.
+ //
+ if (argn != 0)
args += ' ';
args += s;
+
+ // See if we are using the shortcut syntax.
+ //
+ if (argn == 0 && args.back () == ':')
+ {
+ args.back () = '(';
+ shortcut = true;
+ }
+
+ argn++;
+ }
+
+ // Add the closing parenthesis unless there wasn't anything in between
+ // in which case pop the opening one.
+ //
+ if (shortcut)
+ {
+ if (argn == 1)
+ args.pop_back ();
+ else
+ args += ')';
}
}
catch (const cl::exception& e)