aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/script/run.hxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2022-10-03 21:23:22 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2022-10-13 13:08:02 +0300
commitf59d82eb8fda3ddcf790556c6c3615e40ae8b15b (patch)
tree74cd2d3415259c6cb3e116a01eef215f6b39861f /libbuild2/script/run.hxx
parentf0959bca1b44e62c1745027fed42a5973f44cdb4 (diff)
Add support for 'for' loop second (... | for x) and third (for x <...) forms in script
Diffstat (limited to 'libbuild2/script/run.hxx')
-rw-r--r--libbuild2/script/run.hxx66
1 files changed, 62 insertions, 4 deletions
diff --git a/libbuild2/script/run.hxx b/libbuild2/script/run.hxx
index 01b010c..5d46d21 100644
--- a/libbuild2/script/run.hxx
+++ b/libbuild2/script/run.hxx
@@ -38,22 +38,24 @@ namespace build2
// Location is the start position of this command line in the script. It
// can be used in diagnostics.
//
- // Optionally, save the command output into the referenced variable. In
- // this case assume that the expression contains a single pipline.
+ // Optionally, execute the specified function at the end of the pipe,
+ // either after the last command or instead of it.
//
void
run (environment&,
const command_expr&,
const iteration_index*, size_t index,
const location&,
- string* output = nullptr);
+ const function<command_function>& = nullptr,
+ bool last_cmd = true);
bool
run_cond (environment&,
const command_expr&,
const iteration_index*, size_t index,
const location&,
- string* output = nullptr);
+ const function<command_function>& = nullptr,
+ bool last_cmd = true);
// Perform the registered special file cleanups in the direct order and
// then the regular cleanups in the reverse order.
@@ -80,6 +82,62 @@ namespace build2
//
string
diag_path (const dir_name_view&);
+
+ // Read out the stream content into a string, optionally splitting the
+ // input data at whitespaces or newlines in which case return one
+ // sub-string at a time (see the set builtin options for the splitting
+ // semantics). Throw io_error on the underlying OS error.
+ //
+ // If the execution deadline is specified, then turn the stream into the
+ // non-blocking mode. If the specified deadline is reached while reading
+ // the stream, then bail out for the successful deadline and fail
+ // otherwise. Note that in the former case the result will be incomplete,
+ // but we leave it to the caller to handle that.
+ //
+ // Note that on Windows we can only turn pipe file descriptors into the
+ // non-blocking mode. Thus, we have no choice but to read from descriptors
+ // of other types synchronously there. That implies that we can
+ // potentially block indefinitely reading a file and missing the deadline
+ // on Windows. Note though, that the user can normally rewrite the
+ // command, for example, `set foo <<<file` with `cat file | set foo` to
+ // avoid this problem.
+ //
+ class stream_reader
+ {
+ public:
+ stream_reader (auto_fd&&,
+ bool pipe,
+ bool whitespace, bool newline, bool exact,
+ const optional<deadline>&,
+ const command& deadline_cmd,
+ const location&);
+
+ // Return nullopt if eos is reached.
+ //
+ optional<string>
+ next ();
+
+ private:
+ ifdstream is_;
+ bool whitespace_;
+ bool newline_;
+ bool exact_;
+ optional<deadline> deadline_;
+ const command& deadline_cmd_;
+ const location& location_;
+
+ bool empty_ = true; // Set to false after the first character is read.
+ };
+
+ // Read the stream content using the stream reader in the no-split exact
+ // mode.
+ //
+ string
+ stream_read (auto_fd&&,
+ bool pipe,
+ const optional<deadline>&,
+ const command& deadline_cmd,
+ const location&);
}
}