From 120722059c8612fb13d7bf585a5593582a49220d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 17 Mar 2017 11:09:36 +0200 Subject: Implement alternative command line buildspec and variable assignment syntax b test: foo/ bar/ b config.import.libhello = ../libhello/ --- build2/b.cxx | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'build2/b.cxx') 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 , // 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) -- cgit v1.1