aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/script/script.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/script/script.cxx')
-rw-r--r--libbuild2/script/script.cxx170
1 files changed, 151 insertions, 19 deletions
diff --git a/libbuild2/script/script.cxx b/libbuild2/script/script.cxx
index f540687..b53fc23 100644
--- a/libbuild2/script/script.cxx
+++ b/libbuild2/script/script.cxx
@@ -20,14 +20,17 @@ namespace build2
switch (lt)
{
- case line_type::var: s = "variable"; break;
- case line_type::cmd: s = "command"; break;
- case line_type::cmd_if: s = "'if'"; break;
- case line_type::cmd_ifn: s = "'if!'"; break;
- case line_type::cmd_elif: s = "'elif'"; break;
- case line_type::cmd_elifn: s = "'elif!'"; break;
- case line_type::cmd_else: s = "'else'"; break;
- case line_type::cmd_end: s = "'end'"; break;
+ case line_type::var: s = "variable"; break;
+ case line_type::cmd: s = "command"; break;
+ case line_type::cmd_if: s = "'if'"; break;
+ case line_type::cmd_ifn: s = "'if!'"; break;
+ case line_type::cmd_elif: s = "'elif'"; break;
+ case line_type::cmd_elifn: s = "'elif!'"; break;
+ case line_type::cmd_else: s = "'else'"; break;
+ case line_type::cmd_while: s = "'while'"; break;
+ case line_type::cmd_for_args: s = "'for'"; break;
+ case line_type::cmd_for_stream: s = "'for'"; break;
+ case line_type::cmd_end: s = "'end'"; break;
}
return o << s;
@@ -186,14 +189,14 @@ namespace build2
void
dump (ostream& os, const string& ind, const lines& ls)
{
- // Additionally indent the if-branch lines.
+ // Additionally indent the flow control construct block lines.
//
- string if_ind;
+ string fc_ind;
for (const line& l: ls)
{
- // Before printing indentation, decrease it if the else or end line is
- // reached.
+ // Before printing indentation, decrease it if the else, end, etc line
+ // is reached.
//
switch (l.type)
{
@@ -202,9 +205,9 @@ namespace build2
case line_type::cmd_else:
case line_type::cmd_end:
{
- size_t n (if_ind.size ());
+ size_t n (fc_ind.size ());
assert (n >= 2);
- if_ind.resize (n - 2);
+ fc_ind.resize (n - 2);
break;
}
default: break;
@@ -212,9 +215,10 @@ namespace build2
// Print indentations.
//
- os << ind << if_ind;
+ os << ind << fc_ind;
- // After printing indentation, increase it for if/else branch.
+ // After printing indentation, increase it for the flow control
+ // construct block lines.
//
switch (l.type)
{
@@ -222,7 +226,10 @@ namespace build2
case line_type::cmd_ifn:
case line_type::cmd_elif:
case line_type::cmd_elifn:
- case line_type::cmd_else: if_ind += " "; break;
+ case line_type::cmd_else:
+ case line_type::cmd_while:
+ case line_type::cmd_for_args:
+ case line_type::cmd_for_stream: fc_ind += " "; break;
default: break;
}
@@ -411,16 +418,29 @@ namespace build2
{
// Print the env builtin if any of its options/arguments are present.
//
- if (!c.variables.empty () || c.timeout)
+ if (c.timeout || c.cwd || !c.variables.empty ())
{
o << "env";
// Timeout.
//
if (c.timeout)
+ {
o << " -t "
<< chrono::duration_cast<chrono::seconds> (*c.timeout).count ();
+ if (c.timeout_success)
+ o << " -s";
+ }
+
+ // CWD.
+ //
+ if (c.cwd)
+ {
+ o << " -c ";
+ print_path (*c.cwd);
+ }
+
// Variable unsets/sets.
//
auto b (c.variables.begin ()), i (b), e (c.variables.end ());
@@ -609,6 +629,34 @@ namespace build2
}
}
+ // environment_vars
+ //
+ environment_vars::iterator environment_vars::
+ find (const string& var)
+ {
+ size_t n (var.find ('='));
+ if (n == string::npos)
+ n = var.size ();
+
+ return find_if (begin (), end (),
+ [&var, n] (const string& v)
+ {
+ return v.compare (0, n, var, 0, n) == 0 &&
+ (v[n] == '=' || v[n] == '\0');
+ });
+ }
+
+ void environment_vars::
+ add (string var)
+ {
+ iterator i (find (var));
+
+ if (i != end ())
+ *i = move (var);
+ else
+ push_back (move (var));
+ }
+
// redirect
//
redirect::
@@ -725,7 +773,9 @@ namespace build2
{
using script::cleanup;
- assert (!implicit || c.type == cleanup_type::always);
+ // Implicit never-cleanup doesn't make sense.
+ //
+ assert (!implicit || c.type != cleanup_type::never);
const path& p (c.path);
@@ -751,5 +801,87 @@ namespace build2
{
special_cleanups.emplace_back (move (p));
}
+
+ const environment_vars& environment::
+ exported_variables (environment_vars&)
+ {
+ return exported_vars;
+ }
+
+ const environment_vars& environment::
+ merge_exported_variables (const environment_vars& vars,
+ environment_vars& storage)
+ {
+ const environment_vars& own (exported_variables (storage));
+
+ // If both, the own and the specified variable (un)sets are present,
+ // then merge them. Otherwise, return the own (un)sets, if present, or
+ // the specified (un)sets otherwise.
+ //
+ if (!own.empty () && !vars.empty ())
+ {
+ // Copy the own (un)sets into the storage, if they are not there yet.
+ //
+ if (&storage != &own)
+ storage = own;
+
+ for (const string& v: vars)
+ storage.add (v);
+
+ return storage;
+ }
+ else if (!own.empty ())
+ return own;
+ else
+ return vars;
+ }
+
+ // Helpers.
+ //
+ void
+ verify_environment_var_name (const string& name,
+ const char* prefix,
+ const location& l,
+ const char* opt)
+ {
+ if (name.empty ())
+ {
+ diag_record dr (fail (l));
+ dr << prefix << "empty ";
+
+ if (opt == nullptr)
+ dr << "variable name";
+ else
+ dr << "value for option " << opt;
+ }
+
+ if (name.find ('=') != string::npos)
+ {
+ diag_record dr (fail (l));
+ dr << prefix << "invalid ";
+
+ if (opt == nullptr)
+ dr << "variable name '" << name << "'";
+ else
+ dr << "value '" << name << "' for option " << opt;
+
+ dr << ": contains '='";
+ }
+ }
+
+ void
+ verify_environment_var_assignment (const string& var,
+ const char* prefix,
+ const location& l)
+ {
+ size_t p (var.find ('='));
+
+ if (p == 0)
+ fail (l) << prefix << "empty variable name";
+
+ if (p == string::npos)
+ fail (l) << prefix << "expected variable assignment instead of '"
+ << var << "'";
+ }
}
}