diff options
-rw-r--r-- | bbot/build-config | 4 | ||||
-rw-r--r-- | bbot/build-config.cxx | 18 | ||||
-rw-r--r-- | bbot/buildfile | 1 | ||||
-rw-r--r-- | bbot/manifest | 17 | ||||
-rw-r--r-- | bbot/manifest.cxx | 38 | ||||
-rw-r--r-- | bbot/variable | 46 | ||||
-rw-r--r-- | bbot/variable.cxx | 94 | ||||
-rw-r--r-- | tests/buildtab/testscript | 22 | ||||
-rw-r--r-- | tests/manifest/task.test | 21 | ||||
-rw-r--r-- | tests/variable/buildfile | 9 | ||||
-rw-r--r-- | tests/variable/driver.cxx | 61 | ||||
-rw-r--r-- | tests/variable/testscript | 55 |
12 files changed, 93 insertions, 293 deletions
diff --git a/bbot/build-config b/bbot/build-config index 0a3ecb3..0f92eb8 100644 --- a/bbot/build-config +++ b/bbot/build-config @@ -16,8 +16,6 @@ #include <bbot/export> -#include <bbot/variable> - namespace bbot { // Build configuration matching specific machine names. Used by bbot @@ -30,7 +28,7 @@ namespace bbot butl::optional<butl::target_triplet> target; - variables vars; + std::vector<std::string> vars; }; using build_configs = std::vector<build_config>; diff --git a/bbot/build-config.cxx b/bbot/build-config.cxx index 226ead3..0ee00e9 100644 --- a/bbot/build-config.cxx +++ b/bbot/build-config.cxx @@ -13,6 +13,8 @@ #include <butl/fdstream> #include <butl/tab-parser> +#include <bbot/manifest> // task_manifest::check_config() + using namespace std; using namespace butl; @@ -34,17 +36,17 @@ namespace bbot // then we refer to the end-of-line column (presumably reporting a missed // field). // - auto bad_line = [&name, &tl, &i, n] (const string& d, size_t offset = 0) + auto bad_line = [&name, &tl, &i, n] (const string& d) { // Offset beyond the end-of-line is meaningless. // - assert (i < n || (i == n && offset == 0)); + assert (i <= n); throw tab_parsing (name, tl.line, i == n ? tl.end_column - : tl[i].column + offset, + : tl[i].column, d); }; @@ -93,12 +95,14 @@ namespace bbot try { for (; i < n; ++i) - config.vars.emplace_back (variable (move (tl[i].value))); + { + task_manifest::check_config (tl[i].value); + config.vars.emplace_back (move (tl[i].value)); + } } - catch (const invalid_variable& e) + catch (const invalid_argument& e) { - bad_line (e.what (), e.pos); // Note that tl[i].value is moved from, - // but happily we don't use it + bad_line (e.what ()); } // Save the configuration. diff --git a/bbot/buildfile b/bbot/buildfile index 1bb608f..27bde1a 100644 --- a/bbot/buildfile +++ b/bbot/buildfile @@ -8,7 +8,6 @@ lib{bbot}: \ {hxx cxx}{ build-config } \ {hxx }{ export } \ {hxx cxx}{ manifest } \ -{hxx cxx}{ variable } \ {hxx }{ version } \ $int_libs diff --git a/bbot/manifest b/bbot/manifest index 3022535..087fd25 100644 --- a/bbot/manifest +++ b/bbot/manifest @@ -17,8 +17,6 @@ #include <bbot/export> -#include <bbot/variable> - namespace bbot { using strings = std::vector<std::string>; @@ -105,8 +103,12 @@ namespace bbot // Build system configuration variables (in addition to build environment // configuration variables). + // Note: could be quoted. // - variables config; + strings config; + + strings + unquoted_config (); task_manifest (std::string nm, bpkg::version vr, @@ -114,7 +116,7 @@ namespace bbot strings tr, std::string mn, butl::optional<butl::target_triplet> tg, - variables cf) + strings cf) : name (std::move (nm)), version (std::move (vr)), repository (std::move (rl)), @@ -132,6 +134,13 @@ namespace bbot void serialize (butl::manifest_serializer&) const; + + // Check that a string has the name=value format. The name must not + // contain spaces. Throw invalid_argument if the string doesn't conform to + // these rules. + // + static void + check_config (const std::string&); }; class LIBBBOT_EXPORT task_response_manifest diff --git a/bbot/manifest.cxx b/bbot/manifest.cxx index 0f7a053..1d164db 100644 --- a/bbot/manifest.cxx +++ b/bbot/manifest.cxx @@ -16,6 +16,7 @@ #include <butl/utility> // digit() #include <butl/tab-parser> +#include <butl/string-parser> #include <butl/manifest-parser> #include <butl/manifest-serializer> @@ -442,14 +443,16 @@ namespace bbot { try { - config.emplace_back (variable (move (tf.value))); + check_config (tf.value); } - catch (const invalid_variable& e) + catch (const invalid_argument& e) { bad_value (string ("invalid task configuration: ") + e.what (), - tf.column - 1 + e.pos, + tf.column - 1, tl.line - 1); } + + config.emplace_back (move (tf.value)); } } } @@ -520,6 +523,35 @@ namespace bbot s.next ("", ""); // End of manifest. } + strings task_manifest:: + unquoted_config () + { + return string_parser::unquote (config); + } + + void task_manifest:: + check_config (const string& s) + { + auto i (s.begin ()); + auto e (s.end ()); + + // Iterate until the variable name end and check that it contains no + // whitespaces. + // + for (; i != e; ++i) + { + char c (*i); + + if (c == ' ' || c == '\t') // Whitespace in name. + throw invalid_argument ("expected variable assignment"); + else if (c == '=') + break; + } + + if (i == e) + throw invalid_argument ("no variable value"); + } + // task_response_manifest // task_response_manifest:: diff --git a/bbot/variable b/bbot/variable deleted file mode 100644 index 11e84ec..0000000 --- a/bbot/variable +++ /dev/null @@ -1,46 +0,0 @@ -// file : bbot/variable -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BBOT_VARIABLE -#define BBOT_VARIABLE - -#include <string> -#include <vector> -#include <cstdint> // uint64_t -#include <stdexcept> // invalid_argument - -#include <bbot/export> - -namespace bbot -{ - class LIBBBOT_EXPORT invalid_variable: public std::invalid_argument - { - public: - invalid_variable (std::uint64_t p, const std::string& d) - : invalid_argument (d), pos (p) {} - - std::uint64_t pos; // Zero-based. - }; - - // String in the name=value format. Can contain single or double quoted - // substrings. No escaping is supported. The name must not contain spaces. - // Throw variable_error if the string doesn't conform to these rules. - // - struct LIBBBOT_EXPORT variable: std::string - { - variable (std::string); - - // Remove a single level of quotes. Don't validate the format or the - // correctness of the quotation. Note that the variable can potentially be - // modified through the std::string interface in a way that breaks - // format/quoting. - // - std::string - unquoted () const; - }; - - using variables = std::vector<variable>; -} - -#endif // BBOT_VARIABLE diff --git a/bbot/variable.cxx b/bbot/variable.cxx deleted file mode 100644 index a25b007..0000000 --- a/bbot/variable.cxx +++ /dev/null @@ -1,94 +0,0 @@ -// file : bbot/variable.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <bbot/variable> - -#include <utility> // move() - -using namespace std; - -namespace bbot -{ - variable:: - variable (string v): string (move (v)) - { - // Scan the string untill the end to check that the quoting is terminated. - // We will also make sure that the name doesn't contain spaces and the - // value is provided. - // - char quoting ('\0'); // Current quoting mode, can be used as bool. - bool name (true); // True while we are parsing the variable name. - - auto b (cbegin ()); - auto i (b); - - auto bad_variable = [&b, &i] (const string& d) - { - throw invalid_variable (i - b, d); - }; - - for (auto e (cend ()); i != e; ++i) - { - char c (*i); - - if (!quoting) - { - if (c == '"' || c == '\'') // Begin of quoted string, - { - quoting = c; - continue; - } - } - else if (c == quoting) // End of quoted string, - { - quoting = '\0'; - continue; - } - - if (name) - { - if (c == ' ' || c == '\t') - bad_variable ("expected variable assignment"); - else if (c == '=') - name = false; - } - } - - if (quoting) - bad_variable ("unterminated quoted string"); - - if (name) - bad_variable ("no variable value"); - } - - string variable:: - unquoted () const - { - string r; - char quoting ('\0'); // Current quoting mode, can be used as bool. - - for (auto i (cbegin ()), e (cend ()); i != e; ++i) - { - char c (*i); - - if (!quoting) - { - if (c == '"' || c == '\'') // Begin of quoted string. - { - quoting = c; - continue; - } - } - else if (c == quoting) // End of quoted string. - { - quoting = '\0'; - continue; - } - - r += c; - } - - return r; - } -} diff --git a/tests/buildtab/testscript b/tests/buildtab/testscript index 5bf6b24..6bf76bc 100644 --- a/tests/buildtab/testscript +++ b/tests/buildtab/testscript @@ -48,11 +48,23 @@ : invalid-var : - $* <<EOI 2>>EOE == 1 - windows*-vc_14* windows-vc_14-32 config.cc.coptions="/Z7 - EOI - cin:1:57: error: unterminated quoted string - EOE + { + : unquoted + : + $* <<EOI 2>>EOE == 1 + windows*-vc_14* windows-vc_14-32 config.cc.coptions="/Z7 + EOI + cin:1:57: error: unterminated quoted string + EOE + + : no-value + : + $* <<EOI 2>>EOE == 1 + windows*-vc_14* windows-vc_14-32 i686-microsoft-win32-msvc14.0 config.cc.coptions + EOI + cin:1:64: error: no variable value + EOE + } : dup-config-name : diff --git a/tests/manifest/task.test b/tests/manifest/task.test index cbb4598..f2afd9c 100644 --- a/tests/manifest/task.test +++ b/tests/manifest/task.test @@ -198,10 +198,21 @@ test.options += -t : bad-var : - $* <<EOI 2>'stdin:2:12: error: invalid task configuration: no variable value' == 1 - : 1 - config: abc xyz=1 - EOI + { + : no-value + : + $* <<EOI 2>'stdin:2:9: error: invalid task configuration: no variable value' == 1 + : 1 + config: abc xyz=1 + EOI + + : no-assignment + : + $* <<EOI 2>'stdin:2:9: error: invalid task configuration: expected variable assignment' == 1 + : 1 + config: 'abc xyz'=1 + EOI + } : multiline : @@ -217,7 +228,7 @@ test.options += -t : bad-var : - $* <<EOI 2>'stdin:3:4: error: invalid task configuration: no variable value' == 1 + $* <<EOI 2>'stdin:3:1: error: invalid task configuration: no variable value' == 1 : 1 config: \ abc xyz=1 diff --git a/tests/variable/buildfile b/tests/variable/buildfile deleted file mode 100644 index e9c0cf2..0000000 --- a/tests/variable/buildfile +++ /dev/null @@ -1,9 +0,0 @@ -# file : tests/variable/buildfile -# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -# license : MIT; see accompanying LICENSE file - -import libs = libbutl%lib{butl} - -exe{driver}: cxx{driver} ../../bbot/lib{bbot} $libs test{testscript} - -include ../../bbot/ diff --git a/tests/variable/driver.cxx b/tests/variable/driver.cxx deleted file mode 100644 index 88167ad..0000000 --- a/tests/variable/driver.cxx +++ /dev/null @@ -1,61 +0,0 @@ -// file : tests/variable/driver.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <ios> // ios_base::failbit, ios_base::badbit -#include <string> -#include <cassert> -#include <cstddef> // size_t -#include <iostream> - -#include <butl/utility> // operator<<(ostream,exception) - -#include <bbot/variable> - -using namespace std; -using namespace butl; -using namespace bbot; - -// Usage: argv[0] [-u] -// -// Read variables from STDIN (one per line) and serialize them to STDOUT (also -// one per line). -// -// -u output variables being unquoted beforehand -// -int -main (int argc, char* argv[]) -{ - assert (argc <= 2); - bool unquote (false); - - if (argc == 2) - { - assert (argv[1] == string ("-u")); - unquote = true; - } - - cin.exceptions (ios_base::badbit); - cout.exceptions (ios_base::failbit | ios_base::badbit); - - string s; - for (size_t l (1); getline (cin, s); ++l) - { - try - { - variable v (move (s)); - - cout << (unquote - ? v.unquoted () - : static_cast<const string&> (v)) - << '\n'; - } - catch (const invalid_variable& e) - { - cerr << l << ':' << 1 + e.pos << ": error: " << e << endl; - return 1; - } - } - - return 0; -} diff --git a/tests/variable/testscript b/tests/variable/testscript deleted file mode 100644 index 3269a37..0000000 --- a/tests/variable/testscript +++ /dev/null @@ -1,55 +0,0 @@ -# file : tests/variable/testscript -# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -# license : MIT; see accompanying LICENSE file - -test.options += -u - -: valid -: -{ - $* <<EOI >>EOO - config.cc.coptions="-O3 -stdlib='libc++'" - ab'c="x y"' - var=xy - var= - EOI - config.cc.coptions=-O3 -stdlib='libc++' - abc="x y" - var=xy - var= - EOO -} - -: invalid -: -{ - : expected-assignment - : - $* <'v"a r=abc"' 2>'1:4: error: expected variable assignment' == 1 - - : unterminated-quoted-string - : - $* <'var="a b' 2>'1:9: error: unterminated quoted string' == 1 - - : no-value - : - $* <'var' 2>'1:4: error: no variable value' == 1 -} - -: unquoting -: -{ - : single - : - $* <"var='a \" b'" >'var=a " b' - - : double - : - $* <'var="a '"'"' b"' >"var=a ' b" - - : mixed - : - $* <<EOI >'var=a bc e' - var='a b'"c e" - EOI -} |