mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-28 04:03:39 +08:00
Convert populate_block_process to tnode_t
This commit is contained in:
parent
2bf96493fc
commit
fa0f552fe9
|
@ -839,7 +839,7 @@ void highlighter_t::color_redirection(tnode_t<g::redirection> redirection_node)
|
||||||
if (redir_prim) {
|
if (redir_prim) {
|
||||||
wcstring target;
|
wcstring target;
|
||||||
const enum token_type redirect_type =
|
const enum token_type redirect_type =
|
||||||
this->parse_tree.type_for_redirection(redirection_node, this->buff, NULL, &target);
|
redirection_type(redirection_node, this->buff, nullptr, &target);
|
||||||
|
|
||||||
// We may get a TOK_NONE redirection type, e.g. if the redirection is invalid.
|
// We may get a TOK_NONE redirection type, e.g. if the redirection is invalid.
|
||||||
auto hl = redirect_type == TOK_NONE ? highlight_spec_error : highlight_spec_redirection;
|
auto hl = redirect_type == TOK_NONE ? highlight_spec_error : highlight_spec_redirection;
|
||||||
|
|
|
@ -843,7 +843,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(
|
||||||
argument_list.insert(argument_list.begin(), cmd);
|
argument_list.insert(argument_list.begin(), cmd);
|
||||||
|
|
||||||
// The set of IO redirections that we construct for the process.
|
// The set of IO redirections that we construct for the process.
|
||||||
if (!this->determine_io_chain(statement, &process_io_chain)) {
|
if (!this->determine_io_chain(statement.child<1>(), &process_io_chain)) {
|
||||||
return parse_execution_errored;
|
return parse_execution_errored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,26 +912,18 @@ parse_execution_result_t parse_execution_context_t::expand_arguments_from_nodes(
|
||||||
return parse_execution_success;
|
return parse_execution_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement_node,
|
bool parse_execution_context_t::determine_io_chain(tnode_t<g::arguments_or_redirections_list> node,
|
||||||
io_chain_t *out_chain) {
|
io_chain_t *out_chain) {
|
||||||
io_chain_t result;
|
io_chain_t result;
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
|
|
||||||
// We are called with a statement of varying types. We require that the statement have an
|
|
||||||
// arguments_or_redirections_list child.
|
|
||||||
const parse_node_t &args_and_redirections_list =
|
|
||||||
tree().find_child(statement_node, symbol_arguments_or_redirections_list);
|
|
||||||
|
|
||||||
// Get all redirection nodes underneath the statement.
|
// Get all redirection nodes underneath the statement.
|
||||||
const parse_node_tree_t::parse_node_list_t redirect_nodes =
|
auto redirect_nodes = node.descendants<g::redirection>();
|
||||||
tree().find_nodes(args_and_redirections_list, symbol_redirection);
|
for (tnode_t<g::redirection> redirect_node : redirect_nodes) {
|
||||||
for (size_t i = 0; i < redirect_nodes.size(); i++) {
|
|
||||||
const parse_node_t &redirect_node = *redirect_nodes.at(i);
|
|
||||||
|
|
||||||
int source_fd = -1; // source fd
|
int source_fd = -1; // source fd
|
||||||
wcstring target; // file path or target fd
|
wcstring target; // file path or target fd
|
||||||
enum token_type redirect_type =
|
enum token_type redirect_type =
|
||||||
tree().type_for_redirection(redirect_node, pstree->src, &source_fd, &target);
|
redirection_type(redirect_node, pstree->src, &source_fd, &target);
|
||||||
|
|
||||||
// PCA: I can't justify this EXPAND_SKIP_VARIABLES flag. It was like this when I got here.
|
// PCA: I can't justify this EXPAND_SKIP_VARIABLES flag. It was like this when I got here.
|
||||||
bool target_expanded = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0, NULL);
|
bool target_expanded = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0, NULL);
|
||||||
|
@ -1019,22 +1011,26 @@ parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
||||||
bool_statement.require_get_child<g::statement, 1>());
|
bool_statement.require_get_child<g::statement, 1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_execution_result_t parse_execution_context_t::populate_block_process(
|
template <typename Type>
|
||||||
job_t *job, process_t *proc, const parse_node_t &statement_node) {
|
parse_execution_result_t parse_execution_context_t::populate_block_process(job_t *job,
|
||||||
|
process_t *proc,
|
||||||
|
tnode_t<Type> node) {
|
||||||
// We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when
|
// We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when
|
||||||
// it's time to execute them.
|
// it's time to execute them.
|
||||||
UNUSED(job);
|
UNUSED(job);
|
||||||
assert(statement_node.type == symbol_block_statement ||
|
static_assert(Type::token == symbol_block_statement || Type::token == symbol_if_statement ||
|
||||||
statement_node.type == symbol_if_statement ||
|
Type::token == symbol_switch_statement,
|
||||||
statement_node.type == symbol_switch_statement);
|
"Invalid block process");
|
||||||
|
|
||||||
// The set of IO redirections that we construct for the process.
|
// The set of IO redirections that we construct for the process.
|
||||||
|
// TODO: fix this ugly find_child.
|
||||||
|
auto arguments = node.template find_child<g::arguments_or_redirections_list>();
|
||||||
io_chain_t process_io_chain;
|
io_chain_t process_io_chain;
|
||||||
bool errored = !this->determine_io_chain(statement_node, &process_io_chain);
|
bool errored = !this->determine_io_chain(arguments, &process_io_chain);
|
||||||
if (errored) return parse_execution_errored;
|
if (errored) return parse_execution_errored;
|
||||||
|
|
||||||
proc->type = INTERNAL_BLOCK_NODE;
|
proc->type = INTERNAL_BLOCK_NODE;
|
||||||
proc->internal_block_node = this->get_offset(statement_node);
|
proc->internal_block_node = this->get_offset(node);
|
||||||
proc->set_io_chain(process_io_chain);
|
proc->set_io_chain(process_io_chain);
|
||||||
return parse_execution_success;
|
return parse_execution_success;
|
||||||
}
|
}
|
||||||
|
@ -1052,11 +1048,17 @@ parse_execution_result_t parse_execution_context_t::populate_job_process(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case symbol_block_statement:
|
case symbol_block_statement:
|
||||||
case symbol_if_statement:
|
result = this->populate_block_process(
|
||||||
case symbol_switch_statement: {
|
job, proc, tnode_t<g::block_statement>(&tree(), &specific_statement));
|
||||||
result = this->populate_block_process(job, proc, specific_statement);
|
break;
|
||||||
|
case symbol_if_statement:
|
||||||
|
result = this->populate_block_process(
|
||||||
|
job, proc, tnode_t<g::if_statement>(&tree(), &specific_statement));
|
||||||
|
break;
|
||||||
|
case symbol_switch_statement:
|
||||||
|
result = this->populate_block_process(
|
||||||
|
job, proc, tnode_t<g::switch_statement>(&tree(), &specific_statement));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case symbol_decorated_statement: {
|
case symbol_decorated_statement: {
|
||||||
// Get the plain statement. It will pull out the decoration itself.
|
// Get the plain statement. It will pull out the decoration itself.
|
||||||
tnode_t<g::decorated_statement> dec_stat{&tree(), &specific_statement};
|
tnode_t<g::decorated_statement> dec_stat{&tree(), &specific_statement};
|
||||||
|
|
|
@ -90,8 +90,10 @@ class parse_execution_context_t {
|
||||||
job_t *job, process_t *proc, tnode_t<grammar::boolean_statement> bool_statement);
|
job_t *job, process_t *proc, tnode_t<grammar::boolean_statement> bool_statement);
|
||||||
parse_execution_result_t populate_plain_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_plain_process(job_t *job, process_t *proc,
|
||||||
tnode_t<grammar::plain_statement> statement);
|
tnode_t<grammar::plain_statement> statement);
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
||||||
const parse_node_t &statement_node);
|
tnode_t<Type> statement_node);
|
||||||
|
|
||||||
// These encapsulate the actual logic of various (block) statements.
|
// These encapsulate the actual logic of various (block) statements.
|
||||||
parse_execution_result_t run_block_statement(tnode_t<grammar::block_statement> statement);
|
parse_execution_result_t run_block_statement(tnode_t<grammar::block_statement> statement);
|
||||||
|
@ -113,7 +115,8 @@ class parse_execution_context_t {
|
||||||
globspec_t glob_behavior);
|
globspec_t glob_behavior);
|
||||||
|
|
||||||
// Determines the IO chain. Returns true on success, false on error.
|
// Determines the IO chain. Returns true on success, false on error.
|
||||||
bool determine_io_chain(const parse_node_t &statement, io_chain_t *out_chain);
|
bool determine_io_chain(tnode_t<grammar::arguments_or_redirections_list> node,
|
||||||
|
io_chain_t *out_chain);
|
||||||
|
|
||||||
parse_execution_result_t run_1_job(const parse_node_t &job_node,
|
parse_execution_result_t run_1_job(const parse_node_t &job_node,
|
||||||
const block_t *associated_block);
|
const block_t *associated_block);
|
||||||
|
|
|
@ -1331,6 +1331,23 @@ enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_st
|
||||||
return static_cast<parse_bool_statement_type_t>(stmt.tag());
|
return static_cast<parse_bool_statement_type_t>(stmt.tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum token_type redirection_type(tnode_t<grammar::redirection> redirection, const wcstring &src,
|
||||||
|
int *out_fd, wcstring *out_target) {
|
||||||
|
assert(redirection && "redirection is missing");
|
||||||
|
enum token_type result = TOK_NONE;
|
||||||
|
tnode_t<grammar::tok_redirection> prim = redirection.child<0>(); // like 2>
|
||||||
|
assert(prim && "expected to have primitive");
|
||||||
|
|
||||||
|
if (prim.has_source()) {
|
||||||
|
result = redirection_type_for_string(prim.get_source(src), out_fd);
|
||||||
|
}
|
||||||
|
if (out_target != NULL) {
|
||||||
|
tnode_t<grammar::tok_string> target = redirection.child<1>(); // like &1 or file path
|
||||||
|
*out_target = target ? target.get_source(src) : wcstring();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
||||||
bool include_first) const {
|
bool include_first) const {
|
||||||
// Moderately nasty hack! Walk up our ancestor chain and see if we are in a job_continuation.
|
// Moderately nasty hack! Walk up our ancestor chain and see if we are in a job_continuation.
|
||||||
|
@ -1360,25 +1377,6 @@ bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum token_type parse_node_tree_t::type_for_redirection(const parse_node_t &redirection_node,
|
|
||||||
const wcstring &src, int *out_fd,
|
|
||||||
wcstring *out_target) const {
|
|
||||||
assert(redirection_node.type == symbol_redirection);
|
|
||||||
enum token_type result = TOK_NONE;
|
|
||||||
const parse_node_t *redirection_primitive =
|
|
||||||
this->get_child(redirection_node, 0, parse_token_type_redirection); // like 2>
|
|
||||||
const parse_node_t *redirection_target =
|
|
||||||
this->get_child(redirection_node, 1, parse_token_type_string); // like &1 or file path
|
|
||||||
|
|
||||||
if (redirection_primitive != NULL && redirection_primitive->has_source()) {
|
|
||||||
result = redirection_type_for_string(redirection_primitive->get_source(src), out_fd);
|
|
||||||
}
|
|
||||||
if (out_target != NULL) {
|
|
||||||
*out_target = redirection_target ? redirection_target->get_source(src) : L"";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parse_node_t *parse_node_tree_t::header_node_for_block_statement(
|
const parse_node_t *parse_node_tree_t::header_node_for_block_statement(
|
||||||
const parse_node_t &node) const {
|
const parse_node_t &node) const {
|
||||||
const parse_node_t *result = NULL;
|
const parse_node_t *result = NULL;
|
||||||
|
|
|
@ -200,10 +200,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
|
||||||
/// only the second or additional commands are.
|
/// only the second or additional commands are.
|
||||||
bool statement_is_in_pipeline(const parse_node_t &node, bool include_first) const;
|
bool statement_is_in_pipeline(const parse_node_t &node, bool include_first) const;
|
||||||
|
|
||||||
/// Given a redirection, get the redirection type (or TOK_NONE) and target (file path, or fd).
|
|
||||||
enum token_type type_for_redirection(const parse_node_t &node, const wcstring &src, int *out_fd,
|
|
||||||
wcstring *out_target) const;
|
|
||||||
|
|
||||||
/// If the given node is a block statement, returns the header node (for_header, while_header,
|
/// If the given node is a block statement, returns the header node (for_header, while_header,
|
||||||
/// begin_header, or function_header). Otherwise returns NULL.
|
/// begin_header, or function_header). Otherwise returns NULL.
|
||||||
const parse_node_t *header_node_for_block_statement(const parse_node_t &node) const;
|
const parse_node_t *header_node_for_block_statement(const parse_node_t &node) const;
|
||||||
|
@ -428,6 +424,10 @@ parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> st
|
||||||
/// Return the type for a boolean statement.
|
/// Return the type for a boolean statement.
|
||||||
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt);
|
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt);
|
||||||
|
|
||||||
|
/// Given a redirection, get the redirection type (or TOK_NONE) and target (file path, or fd).
|
||||||
|
enum token_type redirection_type(tnode_t<grammar::redirection> redirection, const wcstring &src,
|
||||||
|
int *out_fd, wcstring *out_target);
|
||||||
|
|
||||||
/// Return the arguments under an arguments_list or arguments_or_redirection_list
|
/// Return the arguments under an arguments_list or arguments_or_redirection_list
|
||||||
using arguments_node_list_t = std::vector<tnode_t<grammar::argument>>;
|
using arguments_node_list_t = std::vector<tnode_t<grammar::argument>>;
|
||||||
arguments_node_list_t get_argument_nodes(tnode_t<grammar::argument_list>);
|
arguments_node_list_t get_argument_nodes(tnode_t<grammar::argument_list>);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user