diff options
Diffstat (limited to 'libbuild2/script/script.hxx')
-rw-r--r-- | libbuild2/script/script.hxx | 168 |
1 files changed, 158 insertions, 10 deletions
diff --git a/libbuild2/script/script.hxx b/libbuild2/script/script.hxx index 4a62c77..f5bd69a 100644 --- a/libbuild2/script/script.hxx +++ b/libbuild2/script/script.hxx @@ -27,6 +27,9 @@ namespace build2 cmd_elif, cmd_elifn, cmd_else, + cmd_while, + cmd_for_args, // `for x: ...` + cmd_for_stream, // `... | for x` and `for x <...` cmd_end }; @@ -40,7 +43,7 @@ namespace build2 union { - const variable* var; // Pre-entered for line_type::var. + const variable* var; // Pre-entered for line_type::{var,cmd_for_*}. }; }; @@ -262,7 +265,7 @@ namespace build2 cleanup_type type; build2::path path; }; - using cleanups = vector<cleanup>; + using cleanups = small_vector<cleanup, 1>; // command_exit // @@ -295,11 +298,30 @@ namespace build2 // command // - // Align with butl::process_env, assuming it is not very common to (un)set - // more than two variables. + // Assume it is not very common to (un)set more than a few environment + // variables in the script. // - using environment_vars = small_vector<string, 2>; + struct environment_vars: small_vector<string, 4> + { + // Find a variable (un)set. + // + // Note that only the variable name is considered for both arguments. In + // other words, passing a variable set as a first argument can result + // with a variable unset being found and vice versa. + // + environment_vars::iterator + find (const string&); + + // Add or overwrite an existing variable (un)set. + // + void + add (string); + }; + // @@ For better diagnostics we may want to store an individual location + // of each command in the pipeline (maybe we can share the file part + // somehow since a pipline cannot span multiple files). + // struct command { // We use NULL initial as an indication that the path stored in recall @@ -308,8 +330,14 @@ namespace build2 // process_path program; - strings arguments; - environment_vars variables; + strings arguments; + + // These come from the env builtin. + // + optional<dir_path> cwd; + environment_vars variables; + optional<duration> timeout; + bool timeout_success = false; optional<redirect> in; optional<redirect> out; @@ -337,6 +365,10 @@ namespace build2 // command_pipe // + // Note that we cannot use small_vector here, since moving from objects of + // the command_pipe type would invalidate the command redirects of the + // reference type in this case. + // using command_pipe = vector<command>; void @@ -355,7 +387,7 @@ namespace build2 command_pipe pipe; }; - using command_expr = vector<expr_term>; + using command_expr = small_vector<expr_term, 1>; void to_stream (ostream&, const command_expr&, command_to_stream); @@ -363,6 +395,46 @@ namespace build2 ostream& operator<< (ostream&, const command_expr&); + // Stack-allocated linked list of iteration indexes of the nested loops. + // + struct iteration_index + { + size_t index; // 1-based. + + const iteration_index* prev; // NULL for the top-most loop. + }; + + struct timeout + { + duration value; + bool success; + + timeout (duration d, bool s): value (d), success (s) {} + }; + + struct deadline + { + timestamp value; + bool success; + + deadline (timestamp t, bool s): value (t), success (s) {} + }; + + // If timestamps/durations are equal, the failure is less than the + // success. + // + bool + operator< (const deadline&, const deadline&); + + bool + operator< (const timeout&, const timeout&); + + optional<deadline> + to_deadline (const optional<timestamp>&, bool success); + + optional<timeout> + to_timeout (const optional<duration>&, bool success); + // Script execution environment. // class environment @@ -447,7 +519,8 @@ namespace build2 // Register a cleanup. If the cleanup is explicit, then override the // cleanup type if this path is already registered. Ignore implicit - // registration of a path outside root directory (see below). + // registration of a path outside sandbox directory, if specified (see + // above). // void clean (cleanup, bool implicit); @@ -460,15 +533,55 @@ namespace build2 void clean_special (path); + // Command execution environment variables. + // + public: + // Environment variable (un)sets from the export builtin call. + // + // Each variable in the list can only be present once. + // + environment_vars exported_vars; + + // Return the environment variable (un)sets which can potentially rely + // on factors besides the export builtin call sequence (scoping, + // etc). The default implementation returns exported_vars. + // + virtual const environment_vars& + exported_variables (environment_vars& storage); + + // Merge the own environment variable (un)sets with the specified ones, + // overriding the former with the latter. + // + const environment_vars& + merge_exported_variables (const environment_vars&, + environment_vars& storage); + public: // Set variable value with optional (non-empty) attributes. // virtual void - set_variable (string&& name, + set_variable (string name, names&&, const string& attrs, const location&) = 0; + // Set the script execution timeout from the timeout builtin call. + // + // The builtin argument semantics is script implementation-dependent. If + // success is true then a process missing this deadline should not be + // considered as failed unless it didn't terminate gracefully and had to + // be killed. + // + virtual void + set_timeout (const string& arg, bool success, const location&) = 0; + + // Return the script execution deadline which can potentially rely on + // factors besides the latest timeout builtin call (variables, scoping, + // etc). + // + virtual optional<deadline> + effective_deadline () = 0; + // Create the temporary directory and set the temp_dir reference target // to its path. Must only be called if temp_dir is empty. // @@ -479,6 +592,41 @@ namespace build2 virtual ~environment () = default; }; + + // Custom command function that can be executed at the end of the + // pipeline. Should throw io_error on the underlying OS error. + // + // Note: the pipeline can be NULL (think of `for x <<<='foo'`). + // + struct pipe_command; + + using command_function = void (environment&, + const strings& args, + auto_fd in, + pipe_command* pipeline, + const optional<deadline>&, + const location&); + + // Helpers. + // + // Issue diagnostics with the specified prefix and fail if the string + // (potentially an option value) is not a valid variable name or + // assignment (empty, etc). + // + void + verify_environment_var_name (const string&, + const char* prefix, + const location&, + const char* opt = nullptr); + + void + verify_environment_var_assignment (const string&, + const char* prefix, + const location&); + + // "Unhide" operator<< from the build2 namespace. + // + using build2::operator<<; } } |