aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/script/parser.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/script/parser.hxx')
-rw-r--r--libbuild2/script/parser.hxx86
1 files changed, 69 insertions, 17 deletions
diff --git a/libbuild2/script/parser.hxx b/libbuild2/script/parser.hxx
index 9098b3c..795ce4e 100644
--- a/libbuild2/script/parser.hxx
+++ b/libbuild2/script/parser.hxx
@@ -42,6 +42,15 @@ namespace build2
using build2::parser::apply_value_attributes;
+ // Return true if a command line element needs to be re-lexed.
+ //
+ // Specifically, it needs to be re-lexed if it contains any of the
+ // special characters (|<>&), quotes ("') or effective escape sequences
+ // (\", \', \\).
+ //
+ static bool
+ need_cmdline_relex (const string&);
+
// Commonly used parsing functions. Issue diagnostics and throw failed
// in case of an error.
//
@@ -88,15 +97,34 @@ namespace build2
};
using here_docs = vector<here_doc>;
- pair<command_expr, here_docs>
- parse_command_expr (token&, token_type&, const redirect_aliases&);
+ struct parse_command_expr_result
+ {
+ command_expr expr; // Single pipe for the for-loop.
+ here_docs docs;
+ bool for_loop = false;
+
+ parse_command_expr_result () = default;
+
+ parse_command_expr_result (command_expr&& e,
+ here_docs&& h,
+ bool f)
+ : expr (move (e)), docs (move (h)), for_loop (f) {}
+ };
+
+ // Pass the first special command program name (token_type::word) if it
+ // is already pre-parsed.
+ //
+ parse_command_expr_result
+ parse_command_expr (token&, token_type&,
+ const redirect_aliases&,
+ optional<token>&& program = nullopt);
command_exit
parse_command_exit (token&, token_type&);
void
parse_here_documents (token&, token_type&,
- pair<command_expr, here_docs>&);
+ parse_command_expr_result&);
struct parsed_doc
{
@@ -112,7 +140,7 @@ namespace build2
parsed_doc (string, uint64_t line, uint64_t column);
parsed_doc (regex_lines&&, uint64_t line, uint64_t column);
- parsed_doc (parsed_doc&&); // Note: move constuctible-only type.
+ parsed_doc (parsed_doc&&) noexcept; // Note: move constuctible-only type.
~parsed_doc ();
};
@@ -126,19 +154,26 @@ namespace build2
// the first two tokens. Use the specified lexer mode to peek the second
// token.
//
+ // Always return the cmd_for_stream line type for the for-loop. Note
+ // that the for-loop form cannot be detected easily, based on the first
+ // two tokens. Also note that the detection can be specific for the
+ // script implementation (custom lexing mode, special variables, etc).
+ //
line_type
pre_parse_line_start (token&, token_type&, lexer_mode);
// Parse the env pseudo-builtin arguments up to the program name. Return
- // the program execution timeout, the list of the variables that should
- // be unset ("name") and/or set ("name=value") in the command
- // environment, and the token/type that starts the program name. Note
- // that the variable unsets come first, if present.
+ // the program execution timeout and its success flag, CWD, the list of
+ // the variables that should be unset ("name") and/or set ("name=value")
+ // in the command environment, and the token/type that starts the
+ // program name. Note that the variable unsets come first, if present.
//
struct parsed_env
{
optional<duration> timeout;
- environment_vars variables;
+ bool timeout_success = false;
+ optional<dir_path> cwd;
+ environment_vars variables;
};
parsed_env
@@ -149,19 +184,26 @@ namespace build2
protected:
// Return false if the execution of the script should be terminated with
// the success status (e.g., as a result of encountering the exit
- // builtin). For unsuccessful termination the failed exception is thrown.
+ // builtin). For unsuccessful termination the failed exception is
+ // thrown.
//
using exec_set_function = void (const variable&,
token&, token_type&,
const location&);
using exec_cmd_function = void (token&, token_type&,
- size_t li,
+ const iteration_index*, size_t li,
bool single,
+ const function<command_function>&,
const location&);
- using exec_if_function = bool (token&, token_type&,
- size_t li,
+ using exec_cond_function = bool (token&, token_type&,
+ const iteration_index*, size_t li,
+ const location&);
+
+ using exec_for_function = void (const variable&,
+ value&&,
+ const attributes& value_attrs,
const location&);
// If a parser implementation doesn't pre-enter variables into a pool
@@ -173,8 +215,9 @@ namespace build2
exec_lines (lines::const_iterator b, lines::const_iterator e,
const function<exec_set_function>&,
const function<exec_cmd_function>&,
- const function<exec_if_function>&,
- size_t& li,
+ const function<exec_cond_function>&,
+ const function<exec_for_function>&,
+ const iteration_index*, size_t& li,
variable_pool* = nullptr);
// Customization hooks.
@@ -187,7 +230,7 @@ namespace build2
// During the execution phase try to parse and translate the leading
// names into the process path and return nullopt if choose not to do
// so, leaving it to the parser to handle. Also return in the last
- // argument uninterpreted names, if any.
+ // two arguments uninterpreted names, if any.
//
// The default implementation always returns nullopt. The derived parser
// can provide an override that can, for example, handle process path
@@ -199,13 +242,22 @@ namespace build2
// something that requires re-lexing, for example `foo|bar`, which won't
// be easy to translate but which are handled by the parser.
//
+ // Note that the chunk could be of the special cmdline type in which
+ // case the names may need to be "preprocessed" (at least unquoted or
+ // potentially fully re-lexed) before being analyzed/consumed. Note also
+ // that in this case any names left unconsumed must remain of the
+ // cmdline type.
+ //
+ //
// During the pre-parsing phase the returned process path and names
// (that must still be parsed) are discarded. The main purpose of the
// call is to allow implementations to perform static script analysis,
// recognize and execute certain directives, or some such.
//
virtual optional<process_path>
- parse_program (token&, token_type&, bool first, bool env, names&);
+ parse_program (token&, token_type&,
+ bool first, bool env,
+ names&, parse_names_result&);
// Set lexer pointers for both the current and the base classes.
//