aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/parse_execution.cpp
diff options
context:
space:
mode:
authorGravatar Kurtis Rader <krader@skepticism.us>2016-05-02 12:31:33 -0700
committerGravatar Kurtis Rader <krader@skepticism.us>2016-05-02 13:00:03 -0700
commitea945cc4377d91ceeeb0954ae8ad862f82f91918 (patch)
treef8801902fda879e447cd9df3e4ae2089b0e8e8fa /src/parse_execution.cpp
parent13d7432368dbb4272997b3b4cb7d50cc5e9f786b (diff)
restyle parse_execution module to match project style
Reduces lint errors from 184 to 84 (-54%). Line count from 2139 to 1943 (-9%). Another step in resolving issue #2902.
Diffstat (limited to 'src/parse_execution.cpp')
-rw-r--r--src/parse_execution.cpp1381
1 files changed, 619 insertions, 762 deletions
diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp
index 202194e7..a553f4cb 100644
--- a/src/parse_execution.cpp
+++ b/src/parse_execution.cpp
@@ -1,67 +1,67 @@
-/**\file parse_execution.cpp
-
- Provides the "linkage" between a parse_node_tree_t and actual execution structures (job_t, etc.)
-
- A note on error handling: fish has two kind of errors, fatal parse errors non-fatal runtime errors. A fatal error prevents execution of the entire file, while a non-fatal error skips that job.
-
- Non-fatal errors are printed as soon as they are encountered; otherwise you would have to wait for the execution to finish to see them.
-*/
+// Provides the "linkage" between a parse_node_tree_t and actual execution structures (job_t, etc.)
+//
+// A note on error handling: fish has two kind of errors, fatal parse errors non-fatal runtime
+// errors. A fatal error prevents execution of the entire file, while a non-fatal error skips that
+// job.
+//
+// Non-fatal errors are printed as soon as they are encountered; otherwise you would have to wait
+// for the execution to finish to see them.
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
-#include <string>
#include <memory>
+#include <string>
#include <vector>
-#include <stdbool.h>
-#include "parse_execution.h"
+#include "builtin.h"
+#include "common.h"
+#include "complete.h"
#include "env.h"
#include "event.h"
-#include "tokenizer.h"
-#include "util.h"
-#include "parse_util.h"
-#include "complete.h"
-#include "wildcard.h"
-#include "parser.h"
+#include "exec.h"
#include "expand.h"
-#include "reader.h"
-#include "wutil.h"
-#include "path.h"
#include "function.h"
-#include "builtin.h"
-#include "exec.h"
-#include "common.h"
#include "io.h"
#include "parse_constants.h"
+#include "parse_execution.h"
#include "parse_tree.h"
+#include "parse_util.h"
+#include "parser.h"
+#include "path.h"
#include "proc.h"
+#include "reader.h"
+#include "tokenizer.h"
+#include "util.h"
+#include "wildcard.h"
+#include "wutil.h"
-/* These are the specific statement types that support redirections */
-static bool specific_statement_type_is_redirectable_block(const parse_node_t &node)
-{
- return node.type == symbol_block_statement || node.type == symbol_if_statement || node.type == symbol_switch_statement;
-
+/// These are the specific statement types that support redirections.
+static bool specific_statement_type_is_redirectable_block(const parse_node_t &node) {
+ return node.type == symbol_block_statement || node.type == symbol_if_statement ||
+ node.type == symbol_switch_statement;
}
-/* Get the name of a redirectable block, for profiling purposes */
-static wcstring profiling_cmd_name_for_redirectable_block(const parse_node_t &node, const parse_node_tree_t &tree, const wcstring &src)
-{
+/// Get the name of a redirectable block, for profiling purposes.
+static wcstring profiling_cmd_name_for_redirectable_block(const parse_node_t &node,
+ const parse_node_tree_t &tree,
+ const wcstring &src) {
assert(specific_statement_type_is_redirectable_block(node));
assert(node.has_source());
- /* Get the source for the block, and cut it at the next statement terminator. */
+ // Get the source for the block, and cut it at the next statement terminator.
const size_t src_start = node.source_start;
size_t src_len = node.source_length;
- const parse_node_tree_t::parse_node_list_t statement_terminator_nodes = tree.find_nodes(node, parse_token_type_end, 1);
- if (! statement_terminator_nodes.empty())
- {
+ const parse_node_tree_t::parse_node_list_t statement_terminator_nodes =
+ tree.find_nodes(node, parse_token_type_end, 1);
+ if (!statement_terminator_nodes.empty()) {
const parse_node_t *term = statement_terminator_nodes.at(0);
assert(term->source_start >= src_start);
src_len = term->source_start - src_start;
@@ -72,25 +72,31 @@ static wcstring profiling_cmd_name_for_redirectable_block(const parse_node_t &no
return result;
}
-parse_execution_context_t::parse_execution_context_t(moved_ref<parse_node_tree_t> t, const wcstring &s, parser_t *p, int initial_eval_level) : tree(t), src(s), parser(p), eval_level(initial_eval_level), executing_node_idx(NODE_OFFSET_INVALID), cached_lineno_offset(0), cached_lineno_count(0)
-{
-}
+parse_execution_context_t::parse_execution_context_t(moved_ref<parse_node_tree_t> t,
+ const wcstring &s, parser_t *p,
+ int initial_eval_level)
+ : tree(t),
+ src(s),
+ parser(p),
+ eval_level(initial_eval_level),
+ executing_node_idx(NODE_OFFSET_INVALID),
+ cached_lineno_offset(0),
+ cached_lineno_count(0) {}
-/* Utilities */
+// Utilities
-wcstring parse_execution_context_t::get_source(const parse_node_t &node) const
-{
+wcstring parse_execution_context_t::get_source(const parse_node_t &node) const {
return node.get_source(this->src);
}
-const parse_node_t *parse_execution_context_t::get_child(const parse_node_t &parent, node_offset_t which, parse_token_type_t expected_type) const
-{
+const parse_node_t *parse_execution_context_t::get_child(const parse_node_t &parent,
+ node_offset_t which,
+ parse_token_type_t expected_type) const {
return this->tree.get_child(parent, which, expected_type);
}
-node_offset_t parse_execution_context_t::get_offset(const parse_node_t &node) const
-{
- /* Get the offset of a node via pointer arithmetic, very hackish */
+node_offset_t parse_execution_context_t::get_offset(const parse_node_t &node) const {
+ // Get the offset of a node via pointer arithmetic, very hackish.
const parse_node_t *addr = &node;
const parse_node_t *base = &this->tree.at(0);
assert(addr >= base);
@@ -101,433 +107,388 @@ node_offset_t parse_execution_context_t::get_offset(const parse_node_t &node) co
return offset;
}
-const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_job_list(const parse_node_t &job_list, wcstring *out_func_name) const
-{
+const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_job_list(
+ const parse_node_t &job_list, wcstring *out_func_name) const {
assert(job_list.type == symbol_job_list);
- /*
- This is a bit fragile. It is a test to see if we are
- inside of function call, but not inside a block in that
- function call. If, in the future, the rules for what
- block scopes are pushed on function invocation changes,
- then this check will break.
- */
+ // This is a bit fragile. It is a test to see if we are inside of function call, but not inside
+ // a block in that function call. If, in the future, the rules for what block scopes are pushed
+ // on function invocation changes, then this check will break.
const block_t *current = parser->block_at_index(0), *parent = parser->block_at_index(1);
- bool is_within_function_call = (current && parent && current->type() == TOP && parent->type() == FUNCTION_CALL);
- if (! is_within_function_call)
- {
+ bool is_within_function_call =
+ (current && parent && current->type() == TOP && parent->type() == FUNCTION_CALL);
+ if (!is_within_function_call) {
return NULL;
}
- /* Check to see which function call is forbidden */
- if (parser->forbidden_function.empty())
- {
+ // Check to see which function call is forbidden.
+ if (parser->forbidden_function.empty()) {
return NULL;
}
const wcstring &forbidden_function_name = parser->forbidden_function.back();
- /* Get the first job in the job list. */
+ // Get the first job in the job list.
const parse_node_t *first_job = tree.next_node_in_node_list(job_list, symbol_job, NULL);
- if (first_job == NULL)
- {
+ if (first_job == NULL) {
return NULL;
}
- /* Here's the statement node we find that's infinite recursive */
+ // Here's the statement node we find that's infinite recursive.
const parse_node_t *infinite_recursive_statement = NULL;
- /* Get the list of statements */
- const parse_node_tree_t::parse_node_list_t statements = tree.specific_statements_for_job(*first_job);
+ // Get the list of statements.
+ const parse_node_tree_t::parse_node_list_t statements =
+ tree.specific_statements_for_job(*first_job);
- /* Find all the decorated statements. We are interested in statements with no decoration (i.e. not command, not builtin) whose command expands to the forbidden function */
- for (size_t i=0; i < statements.size(); i++)
- {
- /* We only care about decorated statements, not while statements, etc. */
+ // Find all the decorated statements. We are interested in statements with no decoration (i.e.
+ // not command, not builtin) whose command expands to the forbidden function.
+ for (size_t i = 0; i < statements.size(); i++) {
+ // We only care about decorated statements, not while statements, etc.
const parse_node_t &statement = *statements.at(i);
- if (statement.type != symbol_decorated_statement)
- {
+ if (statement.type != symbol_decorated_statement) {
continue;
}
const parse_node_t &plain_statement = tree.find_child(statement, symbol_plain_statement);
- if (tree.decoration_for_plain_statement(plain_statement) != parse_statement_decoration_none)
- {
- /* This statement has a decoration like 'builtin' or 'command', and therefore is not infinite recursion. In particular this is what enables 'wrapper functions' */
+ if (tree.decoration_for_plain_statement(plain_statement) !=
+ parse_statement_decoration_none) {
+ // This statement has a decoration like 'builtin' or 'command', and therefore is not
+ // infinite recursion. In particular this is what enables 'wrapper functions'.
continue;
}
- /* Ok, this is an undecorated plain statement. Get and expand its command */
+ // Ok, this is an undecorated plain statement. Get and expand its command.
wcstring cmd;
tree.command_for_plain_statement(plain_statement, src, &cmd);
if (expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES, NULL) &&
- cmd == forbidden_function_name)
- {
- /* This is it */
+ cmd == forbidden_function_name) {
+ // This is it.
infinite_recursive_statement = &statement;
- if (out_func_name != NULL)
- {
+ if (out_func_name != NULL) {
*out_func_name = forbidden_function_name;
}
break;
}
}
- assert(infinite_recursive_statement == NULL || infinite_recursive_statement->type == symbol_decorated_statement);
+ assert(infinite_recursive_statement == NULL ||
+ infinite_recursive_statement->type == symbol_decorated_statement);
return infinite_recursive_statement;
}
-enum process_type_t parse_execution_context_t::process_type_for_command(const parse_node_t &plain_statement, const wcstring &cmd) const
-{
+enum process_type_t parse_execution_context_t::process_type_for_command(
+ const parse_node_t &plain_statement, const wcstring &cmd) const {
assert(plain_statement.type == symbol_plain_statement);
enum process_type_t process_type = EXTERNAL;
- /* Determine the process type, which depends on the statement decoration (command, builtin, etc) */
- enum parse_statement_decoration_t decoration = tree.decoration_for_plain_statement(plain_statement);
+ // Determine the process type, which depends on the statement decoration (command, builtin,
+ // etc).
+ enum parse_statement_decoration_t decoration =
+ tree.decoration_for_plain_statement(plain_statement);
- if (decoration == parse_statement_decoration_exec)
- {
- /* Always exec */
+ if (decoration == parse_statement_decoration_exec) {
+ // Always exec.
process_type = INTERNAL_EXEC;
- }
- else if (decoration == parse_statement_decoration_command)
- {
- /* Always a command */
+ } else if (decoration == parse_statement_decoration_command) {
+ // Always a command.
process_type = EXTERNAL;
- }
- else if (decoration == parse_statement_decoration_builtin)
- {
- /* What happens if this builtin is not valid? */
+ } else if (decoration == parse_statement_decoration_builtin) {
+ // What happens if this builtin is not valid?
process_type = INTERNAL_BUILTIN;
- }
- else if (function_exists(cmd))
- {
+ } else if (function_exists(cmd)) {
process_type = INTERNAL_FUNCTION;
- }
- else if (builtin_exists(cmd))
- {
+ } else if (builtin_exists(cmd)) {
process_type = INTERNAL_BUILTIN;
- }
- else
- {
+ } else {
process_type = EXTERNAL;
}
return process_type;
}
-bool parse_execution_context_t::should_cancel_execution(const block_t *block) const
-{
+bool parse_execution_context_t::should_cancel_execution(const block_t *block) const {
return cancellation_reason(block) != execution_cancellation_none;
}
-parse_execution_context_t::execution_cancellation_reason_t parse_execution_context_t::cancellation_reason(const block_t *block) const
-{
- if (shell_is_exiting())
- {
+parse_execution_context_t::execution_cancellation_reason_t
+parse_execution_context_t::cancellation_reason(const block_t *block) const {
+ if (shell_is_exiting()) {
return execution_cancellation_exit;
- }
- else if (parser && parser->cancellation_requested)
- {
+ } else if (parser && parser->cancellation_requested) {
return execution_cancellation_skip;
- }
- else if (block && block->loop_status != LOOP_NORMAL)
- {
- /* Nasty hack - break and continue set the 'skip' flag as well as the loop status flag. */
+ } else if (block && block->loop_status != LOOP_NORMAL) {
+ // Nasty hack - break and continue set the 'skip' flag as well as the loop status flag.
return execution_cancellation_loop_control;
- }
- else if (block && block->skip)
- {
+ } else if (block && block->skip) {
return execution_cancellation_skip;
- }
- else
- {
+ } else {
return execution_cancellation_none;
}
}
-/* Return whether the job contains a single statement, of block type, with no redirections */
-bool parse_execution_context_t::job_is_simple_block(const parse_node_t &job_node) const
-{
+/// Return whether the job contains a single statement, of block type, with no redirections.
+bool parse_execution_context_t::job_is_simple_block(const parse_node_t &job_node) const {
assert(job_node.type == symbol_job);
- /* Must have one statement */
+ // Must have one statement.
const parse_node_t &statement = *get_child(job_node, 0, symbol_statement);
const parse_node_t &specific_statement = *get_child(statement, 0);
- if (! specific_statement_type_is_redirectable_block(specific_statement))
- {
- /* Not an appropriate block type */
+ if (!specific_statement_type_is_redirectable_block(specific_statement)) {
+ // Not an appropriate block type.
return false;
}
-
- /* Must be no pipes */
+ // Must be no pipes.
const parse_node_t &continuation = *get_child(job_node, 1, symbol_job_continuation);
- if (continuation.child_count > 0)
- {
- /* Multiple statements in this job, so there's pipes involved */
+ if (continuation.child_count > 0) {
+ // Multiple statements in this job, so there's pipes involved.
return false;
}
- /* Check for arguments and redirections. All of the above types have an arguments / redirections list. It must be empty. */
- const parse_node_t &args_and_redirections = tree.find_child(specific_statement, symbol_arguments_or_redirections_list);
- if (args_and_redirections.child_count > 0)
- {
- /* Non-empty, we have an argument or redirection */
+ // Check for arguments and redirections. All of the above types have an arguments / redirections
+ // list. It must be empty.
+ const parse_node_t &args_and_redirections =
+ tree.find_child(specific_statement, symbol_arguments_or_redirections_list);
+ if (args_and_redirections.child_count > 0) {
+ // Non-empty, we have an argument or redirection.
return false;
}
- /* Ok, we are a simple block! */
+ // Ok, we are a simple block!
return true;
}
-parse_execution_result_t parse_execution_context_t::run_if_statement(const parse_node_t &statement)
-{
+parse_execution_result_t parse_execution_context_t::run_if_statement(
+ const parse_node_t &statement) {
assert(statement.type == symbol_if_statement);
- /* Push an if block */
+ // Push an if block.
if_block_t *ib = new if_block_t();
ib->node_offset = this->get_offset(statement);
parser->push_block(ib);
parse_execution_result_t result = parse_execution_success;
- /* We have a sequence of if clauses, with a final else, resulting in a single job list that we execute */
+ // We have a sequence of if clauses, with a final else, resulting in a single job list that we
+ // execute.
const parse_node_t *job_list_to_execute = NULL;
const parse_node_t *if_clause = get_child(statement, 0, symbol_if_clause);
const parse_node_t *else_clause = get_child(statement, 1, symbol_else_clause);
- for (;;)
- {
- if (should_cancel_execution(ib))
- {
+ for (;;) {
+ if (should_cancel_execution(ib)) {
result = parse_execution_cancelled;
break;
}
-
- /* An if condition has a job and a "tail" of andor jobs, e.g. "foo ; and bar; or baz" */
+
+ // An if condition has a job and a "tail" of andor jobs, e.g. "foo ; and bar; or baz".
assert(if_clause != NULL && else_clause != NULL);
const parse_node_t &condition_head = *get_child(*if_clause, 1, symbol_job);
- const parse_node_t &condition_boolean_tail = *get_child(*if_clause, 3, symbol_andor_job_list);
+ const parse_node_t &condition_boolean_tail =
+ *get_child(*if_clause, 3, symbol_andor_job_list);
- /* Check the condition and the tail. We treat parse_execution_errored here as failure, in accordance with historic behavior */
+ // Check the condition and the tail. We treat parse_execution_errored here as failure, in
+ // accordance with historic behavior.
parse_execution_result_t cond_ret = run_1_job(condition_head, ib);
- if (cond_ret == parse_execution_success)
- {
+ if (cond_ret == parse_execution_success) {
cond_ret = run_job_list(condition_boolean_tail, ib);
}
- const bool take_branch = (cond_ret == parse_execution_success) && proc_get_last_status() == EXIT_SUCCESS;
+ const bool take_branch =
+ (cond_ret == parse_execution_success) && proc_get_last_status() == EXIT_SUCCESS;
- if (take_branch)
- {
- /* condition succeeded */
+ if (take_branch) {
+ // Condition succeeded.
job_list_to_execute = get_child(*if_clause, 4, symbol_job_list);
break;
- }
- else if (else_clause->child_count == 0)
- {
- /* 'if' condition failed, no else clause, return 0, we're done. */
+ } else if (else_clause->child_count == 0) {
+ // 'if' condition failed, no else clause, return 0, we're done.
job_list_to_execute = NULL;
proc_set_last_status(STATUS_BUILTIN_OK);
break;
- }
- else
- {
- /* We have an 'else continuation' (either else-if or else) */
+ } else {
+ // We have an 'else continuation' (either else-if or else).
const parse_node_t &else_cont = *get_child(*else_clause, 1, symbol_else_continuation);
const parse_node_t *maybe_if_clause = get_child(else_cont, 0);
- if (maybe_if_clause && maybe_if_clause->type == symbol_if_clause)
- {
- /* it's an 'else if', go to the next one */
+ if (maybe_if_clause && maybe_if_clause->type == symbol_if_clause) {
+ // it's an 'else if', go to the next one.
if_clause = maybe_if_clause;
else_clause = get_child(else_cont, 1, symbol_else_clause);
- }
- else
- {
- /* it's the final 'else', we're done */
+ } else {
+ // It's the final 'else', we're done.
job_list_to_execute = get_child(else_cont, 1, symbol_job_list);
break;
}
}
}
- /* Execute any job list we got */
- if (job_list_to_execute != NULL)
- {
+ // Execute any job list we got.
+ if (job_list_to_execute != NULL) {
run_job_list(*job_list_to_execute, ib);
- }
- else
- { /* No job list means no sucessful conditions, so return 0 (#1443). */
+ } else {
+ // No job list means no sucessful conditions, so return 0 (issue #1443).
proc_set_last_status(STATUS_BUILTIN_OK);
}
- /* It's possible there's a last-minute cancellation (#1297). */
- if (should_cancel_execution(ib))
- {
+ // It's possible there's a last-minute cancellation (issue #1297).
+ if (should_cancel_execution(ib)) {
result = parse_execution_cancelled;
}
- /* Done */
+ // Done
parser->pop_block(ib);
- /* Otherwise, take the exit status of the job list. Reversal of #1061. */
+ // Otherwise, take the exit status of the job list. Reversal of issue #1061.
return result;
}
-parse_execution_result_t parse_execution_context_t::run_begin_statement(const parse_node_t &header, const parse_node_t &contents)
-{
+parse_execution_result_t parse_execution_context_t::run_begin_statement(
+ const parse_node_t &header, const parse_node_t &contents) {
assert(header.type == symbol_begin_header);
assert(contents.type == symbol_job_list);
- /* Basic begin/end block. Push a scope block. */
+ // Basic begin/end block. Push a scope block.
scope_block_t *sb = new scope_block_t(BEGIN);
parser->push_block(sb);
- /* Run the job list */
+ // Run the job list.
parse_execution_result_t ret = run_job_list(contents, sb);
- /* Pop the block */
+ // Pop the block.
parser->pop_block(sb);
return ret;
}
-/* Define a function */
-parse_execution_result_t parse_execution_context_t::run_function_statement(const parse_node_t &header, const parse_node_t &block_end_command)
-{
+// Define a function.
+parse_execution_result_t parse_execution_context_t::run_function_statement(
+ const parse_node_t &header, const parse_node_t &block_end_command) {
assert(header.type == symbol_function_header);
assert(block_end_command.type == symbol_end_command);
-
- /* Get arguments */
+
+ // Get arguments.
wcstring_list_t argument_list;
parse_execution_result_t result = this->determine_arguments(header, &argument_list, failglob);
- if (result == parse_execution_success)
- {
- /* The function definition extends from the end of the header to the function end. It's not just the range of the contents because that loses comments - see issue #1710 */
+ if (result == parse_execution_success) {
+ // The function definition extends from the end of the header to the function end. It's not
+ // just the range of the contents because that loses comments - see issue #1710.
assert(block_end_command.has_source());
size_t contents_start = header.source_start + header.source_length;
- size_t contents_end = block_end_command.source_start; // 1 past the last character in the function definition
+ size_t contents_end =
+ block_end_command.source_start; // 1 past the last character in the function definition
assert(contents_end >= contents_start);
-
- // Swallow whitespace at both ends
- while (contents_start < contents_end && iswspace(this->src.at(contents_start)))
- {
+
+ // Swallow whitespace at both ends.
+ while (contents_start < contents_end && iswspace(this->src.at(contents_start))) {
contents_start++;
}
- while (contents_start < contents_end && iswspace(this->src.at(contents_end - 1)))
- {
+ while (contents_start < contents_end && iswspace(this->src.at(contents_end - 1))) {
contents_end--;
}
-
+
assert(contents_end >= contents_start);
- const wcstring contents_str = wcstring(this->src, contents_start, contents_end - contents_start);
+ const wcstring contents_str =
+ wcstring(this->src, contents_start, contents_end - contents_start);
int definition_line_offset = this->line_offset_of_character_at_offset(contents_start);
wcstring error_str;
io_streams_t streams;
- int err = define_function(*parser, streams, argument_list, contents_str, definition_line_offset, &error_str);
+ int err = define_function(*parser, streams, argument_list, contents_str,
+ definition_line_offset, &error_str);
proc_set_last_status(err);
- if (! error_str.empty())
- {
+ if (!error_str.empty()) {
this->report_error(header, L"%ls", error_str.c_str());
result = parse_execution_errored;
}
}
return result;
-
}
-parse_execution_result_t parse_execution_context_t::run_block_statement(const parse_node_t &statement)
-{
+parse_execution_result_t parse_execution_context_t::run_block_statement(
+ const parse_node_t &statement) {
assert(statement.type == symbol_block_statement);
- const parse_node_t &block_header = *get_child(statement, 0, symbol_block_header); //block header
- const parse_node_t &header = *get_child(block_header, 0); //specific header type (e.g. for loop)
- const parse_node_t &contents = *get_child(statement, 1, symbol_job_list); //block contents
+ const parse_node_t &block_header =
+ *get_child(statement, 0, symbol_block_header); // block header
+ const parse_node_t &header =
+ *get_child(block_header, 0); // specific header type (e.g. for loop)
+ const parse_node_t &contents = *get_child(statement, 1, symbol_job_list); // block contents
parse_execution_result_t ret = parse_execution_success;
- switch (header.type)
- {
- case symbol_for_header:
+ switch (header.type) {
+ case symbol_for_header: {
ret = run_for_statement(header, contents);
break;
-
- case symbol_while_header:
+ }
+ case symbol_while_header: {
ret = run_while_statement(header, contents);
break;
-
- case symbol_function_header:
- {
- const parse_node_t &function_end = *get_child(statement, 2, symbol_end_command); //the 'end' associated with the block
+ }
+ case symbol_function_header: {
+ const parse_node_t &function_end = *get_child(
+ statement, 2, symbol_end_command); // the 'end' associated with the block
ret = run_function_statement(header, function_end);
break;
}
-
- case symbol_begin_header:
+ case symbol_begin_header: {
ret = run_begin_statement(header, contents);
break;
-
- default:
+ }
+ default: {
fprintf(stderr, "Unexpected block header: %ls\n", header.describe().c_str());
PARSER_DIE();
break;
+ }
}
return ret;
}
-parse_execution_result_t parse_execution_context_t::run_for_statement(const parse_node_t &header, const parse_node_t &block_contents)
-{
+parse_execution_result_t parse_execution_context_t::run_for_statement(
+ const parse_node_t &header, const parse_node_t &block_contents) {
assert(header.type == symbol_for_header);
assert(block_contents.type == symbol_job_list);
- /* Get the variable name: `for var_name in ...`. We expand the variable name. It better result in just one. */
+ // Get the variable name: `for var_name in ...`. We expand the variable name. It better result
+ // in just one.
const parse_node_t &var_name_node = *get_child(header, 1, parse_token_type_string);
wcstring for_var_name = get_source(var_name_node);
- if (! expand_one(for_var_name, 0, NULL))
- {
+ if (!expand_one(for_var_name, 0, NULL)) {
report_error(var_name_node, FAILED_EXPANSION_VARIABLE_NAME_ERR_MSG, for_var_name.c_str());
return parse_execution_errored;
}
- /* Get the contents to iterate over. */
+ // Get the contents to iterate over.
wcstring_list_t argument_sequence;
parse_execution_result_t ret = this->determine_arguments(header, &argument_sequence, nullglob);
- if (ret != parse_execution_success)
- {
+ if (ret != parse_execution_success) {
return ret;
}
for_block_t *fb = new for_block_t();
parser->push_block(fb);
- /* Now drive the for loop. */
+ // Now drive the for loop.
const size_t arg_count = argument_sequence.size();
- for (size_t i=0; i < arg_count; i++)
- {
- if (should_cancel_execution(fb))
- {
+ for (size_t i = 0; i < arg_count; i++) {
+ if (should_cancel_execution(fb)) {
ret = parse_execution_cancelled;
break;
}
const wcstring &val = argument_sequence.at(i);
- env_set(for_var_name, val.c_str(), ENV_LOCAL);
+ env_set(for_var_name, val.c_str(), ENV_LOCAL);
fb->loop_status = LOOP_NORMAL;
fb->skip = 0;
this->run_job_list(block_contents, fb);
- if (this->cancellation_reason(fb) == execution_cancellation_loop_control)
- {
- /* Handle break or continue */
- if (fb->loop_status == LOOP_CONTINUE)
- {
- /* Reset the loop state */
+ if (this->cancellation_reason(fb) == execution_cancellation_loop_control) {
+ // Handle break or continue.
+ if (fb->loop_status == LOOP_CONTINUE) {
+ // Reset the loop state.
fb->loop_status = LOOP_NORMAL;
fb->skip = false;
continue;
- }
- else if (fb->loop_status == LOOP_BREAK)
- {
+ } else if (fb->loop_status == LOOP_BREAK) {
break;
}
}
@@ -538,99 +499,88 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
return ret;
}
-
-parse_execution_result_t parse_execution_context_t::run_switch_statement(const parse_node_t &statement)
-{
+parse_execution_result_t parse_execution_context_t::run_switch_statement(
+ const parse_node_t &statement) {
assert(statement.type == symbol_switch_statement);
parse_execution_result_t result = parse_execution_success;
- /* Get the switch variable */
+ // Get the switch variable.
const parse_node_t &switch_value_node = *get_child(statement, 1, symbol_argument);
const wcstring switch_value = get_source(switch_value_node);
- /* Expand it. We need to offset any errors by the position of the string */
+ // Expand it. We need to offset any errors by the position of the string.
std::vector<completion_t> switch_values_expanded;
parse_error_list_t errors;
- int expand_ret = expand_string(switch_value, &switch_values_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
+ int expand_ret =
+ expand_string(switch_value, &switch_values_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
parse_error_offset_source_start(&errors, switch_value_node.source_start);
- switch (expand_ret)
- {
- case EXPAND_ERROR:
- {
+ switch (expand_ret) {
+ case EXPAND_ERROR: {
result = report_errors(errors);
break;
}
-
- case EXPAND_WILDCARD_NO_MATCH:
- {
+ case EXPAND_WILDCARD_NO_MATCH: {
result = report_unmatched_wildcard_error(switch_value_node);
break;
}
-
case EXPAND_WILDCARD_MATCH:
- case EXPAND_OK:
- {
+ case EXPAND_OK: {
break;
}
}
- if (result == parse_execution_success && switch_values_expanded.size() != 1)
- {
- result = report_error(switch_value_node,
- _(L"switch: Expected exactly one argument, got %lu\n"),
- switch_values_expanded.size());
+ if (result == parse_execution_success && switch_values_expanded.size() != 1) {
+ result =
+ report_error(switch_value_node, _(L"switch: Expected exactly one argument, got %lu\n"),
+ switch_values_expanded.size());
}
- if (result == parse_execution_success)
- {
+ if (result == parse_execution_success) {
const wcstring &switch_value_expanded = switch_values_expanded.at(0).completion;
switch_block_t *sb = new switch_block_t();
parser->push_block(sb);
-
- /* Expand case statements */
+ // Expand case statements.
const parse_node_t *case_item_list = get_child(statement, 3, symbol_case_item_list);
- /* Loop while we don't have a match but do have more of the list */
+ // Loop while we don't have a match but do have more of the list.
const parse_node_t *matching_case_item = NULL;
- while (matching_case_item == NULL && case_item_list != NULL)
- {
- if (should_cancel_execution(sb))
- {
+ while (matching_case_item == NULL && case_item_list != NULL) {
+ if (should_cancel_execution(sb)) {
result = parse_execution_cancelled;
break;
}
- /* Get the next item and the remainder of the list */
- const parse_node_t *case_item = tree.next_node_in_node_list(*case_item_list, symbol_case_item, &case_item_list);
- if (case_item == NULL)
- {
- /* No more items */
+ // Get the next item and the remainder of the list.
+ const parse_node_t *case_item =
+ tree.next_node_in_node_list(*case_item_list, symbol_case_item, &case_item_list);
+ if (case_item == NULL) {
+ // No more items.
break;
}
- /* Pull out the argument list */
+ // Pull out the argument list.
const parse_node_t &arg_list = *get_child(*case_item, 1, symbol_argument_list);
- /* Expand arguments. A case item list may have a wildcard that fails to expand to anything. We also report case errors, but don't stop execution; i.e. a case item that contains an unexpandable process will report and then fail to match. */
+ // Expand arguments. A case item list may have a wildcard that fails to expand to
+ // anything. We also report case errors, but don't stop execution; i.e. a case item that
+ // contains an unexpandable process will report and then fail to match.
wcstring_list_t case_args;
- parse_execution_result_t case_result = this->determine_arguments(arg_list, &case_args, failglob);
- if (case_result == parse_execution_success)
- {
- for (size_t i=0; i < case_args.size(); i++)
- {
+ parse_execution_result_t case_result =
+ this->determine_arguments(arg_list, &case_args, failglob);
+ if (case_result == parse_execution_success) {
+ for (size_t i = 0; i < case_args.size(); i++) {
const wcstring &arg = case_args.at(i);
- /* Unescape wildcards so they can be expanded again */
+ // Unescape wildcards so they can be expanded again.
wcstring unescaped_arg = parse_util_unescape_wildcards(arg);
bool match = wildcard_match(switch_value_expanded, unescaped_arg);
- /* If this matched, we're done */
- if (match)
- {
+ // If this matched, we're done.
+ if (match) {
matching_case_item = case_item;
break;
}
@@ -638,9 +588,8 @@ parse_execution_result_t parse_execution_context_t::run_switch_statement(const p
}
}
- if (result == parse_execution_success && matching_case_item != NULL)
- {
- /* Success, evaluate the job list */
+ if (result == parse_execution_success && matching_case_item != NULL) {
+ // Success, evaluate the job list.
const parse_node_t *job_list = get_child(*matching_case_item, 3, symbol_job_list);
result = this->run_job_list(*job_list, sb);
}
@@ -651,68 +600,59 @@ parse_execution_result_t parse_execution_context_t::run_switch_statement(const p
return result;
}
-parse_execution_result_t parse_execution_context_t::run_while_statement(const parse_node_t &header, const parse_node_t &block_contents)
-{
+parse_execution_result_t parse_execution_context_t::run_while_statement(
+ const parse_node_t &header, const parse_node_t &block_contents) {
assert(header.type == symbol_while_header);
assert(block_contents.type == symbol_job_list);
- /* Push a while block */
+ // Push a while block.
while_block_t *wb = new while_block_t();
wb->node_offset = this->get_offset(header);
parser->push_block(wb);
parse_execution_result_t ret = parse_execution_success;
- /* The conditions of the while loop */
+ // The conditions of the while loop.
const parse_node_t &condition_head = *get_child(header, 1, symbol_job);
const parse_node_t &condition_boolean_tail = *get_child(header, 3, symbol_andor_job_list);
- /* Run while the condition is true */
- for (;;)
- {
- /* Check the condition */
+ // Run while the condition is true.
+ for (;;) {
+ // Check the condition.
parse_execution_result_t cond_ret = this->run_1_job(condition_head, wb);
- if (cond_ret == parse_execution_success)
- {
+ if (cond_ret == parse_execution_success) {
cond_ret = run_job_list(condition_boolean_tail, wb);
}
-
- /* We only continue on successful execution and EXIT_SUCCESS */
- if (cond_ret != parse_execution_success || proc_get_last_status() != EXIT_SUCCESS)
- {
+
+ // We only continue on successful execution and EXIT_SUCCESS.
+ if (cond_ret != parse_execution_success || proc_get_last_status() != EXIT_SUCCESS) {
break;
}
- /* Check cancellation */
- if (this->should_cancel_execution(wb))
- {
+ // Check cancellation.
+ if (this->should_cancel_execution(wb)) {
ret = parse_execution_cancelled;
break;
}
-
- /* The block ought to go inside the loop (see #1212) */
+ // The block ought to go inside the loop (see issue #1212).
this->run_job_list(block_contents, wb);
- if (this->cancellation_reason(wb) == execution_cancellation_loop_control)
- {
- /* Handle break or continue */
- if (wb->loop_status == LOOP_CONTINUE)
- {
- /* Reset the loop state */
+ if (this->cancellation_reason(wb) == execution_cancellation_loop_control) {
+ // Handle break or continue.
+ if (wb->loop_status == LOOP_CONTINUE) {
+ // Reset the loop state.
wb->loop_status = LOOP_NORMAL;
wb->skip = false;
continue;
- }
- else if (wb->loop_status == LOOP_BREAK)
- {
+ } else if (wb->loop_status == LOOP_BREAK) {
break;
}
}
-
- /* no_exec means that fish was invoked with -n or --no-execute. If set, we allow the loop to not-execute once so its contents can be checked, and then break */
- if (no_exec)
- {
+
+ // no_exec means that fish was invoked with -n or --no-execute. If set, we allow the loop to
+ // not-execute once so its contents can be checked, and then break.
+ if (no_exec) {
break;
}
}
@@ -723,15 +663,16 @@ parse_execution_result_t parse_execution_context_t::run_while_statement(const pa
return ret;
}
-/* Reports an error. Always returns parse_execution_errored, so you can assign the result to an 'errored' variable */
-parse_execution_result_t parse_execution_context_t::report_error(const parse_node_t &node, const wchar_t *fmt, ...) const
-{
- /* Create an error */
+// Reports an error. Always returns parse_execution_errored, so you can assign the result to an
+// 'errored' variable.
+parse_execution_result_t parse_execution_context_t::report_error(const parse_node_t &node,
+ const wchar_t *fmt, ...) const {
+ // Create an error.
parse_error_list_t error_list = parse_error_list_t(1);
parse_error_t *error = &error_list.at(0);
error->source_start = node.source_start;
error->source_length = node.source_length;
- error->code = parse_error_syntax; //hackish
+ error->code = parse_error_syntax; // hackish
va_list va;
va_start(va, fmt);
@@ -742,109 +683,85 @@ parse_execution_result_t parse_execution_context_t::report_error(const parse_nod
return parse_execution_errored;
}
-parse_execution_result_t parse_execution_context_t::report_errors(const parse_error_list_t &error_list) const
-{
- if (! parser->cancellation_requested)
- {
- if (error_list.empty())
- {
+parse_execution_result_t parse_execution_context_t::report_errors(
+ const parse_error_list_t &error_list) const {
+ if (!parser->cancellation_requested) {
+ if (error_list.empty()) {
fprintf(stderr, "Bug: Error reported but no error text found.");
}
- /* Get a backtrace */
+ // Get a backtrace.
wcstring backtrace_and_desc;
parser->get_backtrace(src, error_list, &backtrace_and_desc);
- /* Print it */
+ // Print it.
fprintf(stderr, "%ls", backtrace_and_desc.c_str());
}
return parse_execution_errored;
}
-/* Reports an unmatched wildcard error and returns parse_execution_errored */
-parse_execution_result_t parse_execution_context_t::report_unmatched_wildcard_error(const parse_node_t &unmatched_wildcard)
-{
+/// Reports an unmatched wildcard error and returns parse_execution_errored.
+parse_execution_result_t parse_execution_context_t::report_unmatched_wildcard_error(
+ const parse_node_t &unmatched_wildcard) {
proc_set_last_status(STATUS_UNMATCHED_WILDCARD);
report_error(unmatched_wildcard, WILDCARD_ERR_MSG, get_source(unmatched_wildcard).c_str());
return parse_execution_errored;
}
-/* Handle the case of command not found */
-parse_execution_result_t parse_execution_context_t::handle_command_not_found(const wcstring &cmd_str, const parse_node_t &statement_node, int err_code)
-{
+/// Handle the case of command not found.
+parse_execution_result_t parse_execution_context_t::handle_command_not_found(
+ const wcstring &cmd_str, const parse_node_t &statement_node, int err_code) {
assert(statement_node.type == symbol_plain_statement);
- /* We couldn't find the specified command. This is a non-fatal error. We want to set the exit status to 127, which is the standard number used by other shells like bash and zsh. */
+ // We couldn't find the specified command. This is a non-fatal error. We want to set the exit
+ // status to 127, which is the standard number used by other shells like bash and zsh.
- const wchar_t * const cmd = cmd_str.c_str();
- const wchar_t * const equals_ptr = wcschr(cmd, L'=');
- if (equals_ptr != NULL)
- {
- /* Try to figure out if this is a pure variable assignment (foo=bar), or if this appears to be running a command (foo=bar ruby...) */
+ const wchar_t *const cmd = cmd_str.c_str();
+ const wchar_t *const equals_ptr = wcschr(cmd, L'=');
+ if (equals_ptr != NULL) {
+ // Try to figure out if this is a pure variable assignment (foo=bar), or if this appears to
+ // be running a command (foo=bar ruby...).
+ const wcstring name_str = wcstring(cmd, equals_ptr - cmd); // variable name, up to the =
+ const wcstring val_str = wcstring(equals_ptr + 1); // variable value, past the =
- const wcstring name_str = wcstring(cmd, equals_ptr - cmd); //variable name, up to the =
- const wcstring val_str = wcstring(equals_ptr + 1); //variable value, past the =
+ const parse_node_tree_t::parse_node_list_t args =
+ tree.find_nodes(statement_node, symbol_argument, 1);
-
- const parse_node_tree_t::parse_node_list_t args = tree.find_nodes(statement_node, symbol_argument, 1);
-
- if (! args.empty())
- {
+ if (!args.empty()) {
const wcstring argument = get_source(*args.at(0));
wcstring ellipsis_str = wcstring(1, ellipsis_char);
- if (ellipsis_str == L"$")
- ellipsis_str = L"...";
-
- /* Looks like a command */
- this->report_error(statement_node,
- ERROR_BAD_EQUALS_IN_COMMAND5,
- argument.c_str(),
- name_str.c_str(),
- val_str.c_str(),
- argument.c_str(),
+ if (ellipsis_str == L"$") ellipsis_str = L"...";
+
+ // Looks like a command.
+ this->report_error(statement_node, ERROR_BAD_EQUALS_IN_COMMAND5, argument.c_str(),
+ name_str.c_str(), val_str.c_str(), argument.c_str(),
ellipsis_str.c_str());
- }
- else
- {
- this->report_error(statement_node,
- ERROR_BAD_COMMAND_ASSIGN_ERR_MSG,
- name_str.c_str(),
+ } else {
+ this->report_error(statement_node, ERROR_BAD_COMMAND_ASSIGN_ERR_MSG, name_str.c_str(),
val_str.c_str());
}
- }
- else if ((cmd[0] == L'$' || cmd[0] == VARIABLE_EXPAND || cmd[0] == VARIABLE_EXPAND_SINGLE) && cmd[1] != L'\0')
- {
- this->report_error(statement_node,
- _(L"Variables may not be used as commands. In fish, please define a function or use 'eval %ls'."),
- cmd);
- }
- else if (wcschr(cmd, L'$'))
- {
- this->report_error(statement_node,
- _(L"Commands may not contain variables. In fish, please use 'eval %ls'."),
+ } else if ((cmd[0] == L'$' || cmd[0] == VARIABLE_EXPAND || cmd[0] == VARIABLE_EXPAND_SINGLE) &&
+ cmd[1] != L'\0') {
+ this->report_error(statement_node, _(L"Variables may not be used as commands. In fish, "
+ L"please define a function or use 'eval %ls'."),
cmd);
- }
- else if (err_code!=ENOENT)
- {
- this->report_error(statement_node,
- _(L"The file '%ls' is not executable by this user"),
- cmd?cmd:L"UNKNOWN");
- }
- else
- {
- /*
- Handle unrecognized commands with standard
- command not found handler that can make better
- error messages
- */
-
+ } else if (wcschr(cmd, L'$')) {
+ this->report_error(
+ statement_node,
+ _(L"Commands may not contain variables. In fish, please use 'eval %ls'."), cmd);
+ } else if (err_code != ENOENT) {
+ this->report_error(statement_node, _(L"The file '%ls' is not executable by this user"),
+ cmd ? cmd : L"UNKNOWN");
+ } else {
+ // Handle unrecognized commands with standard command not found handler that can make better
+ // error messages.
wcstring_list_t event_args;
{
- parse_execution_result_t arg_result = this->determine_arguments(statement_node, &event_args, failglob);
+ parse_execution_result_t arg_result =
+ this->determine_arguments(statement_node, &event_args, failglob);
- if (arg_result != parse_execution_success)
- {
+ if (arg_result != parse_execution_success) {
return arg_result;
}
@@ -853,114 +770,110 @@ parse_execution_result_t parse_execution_context_t::handle_command_not_found(con
event_fire_generic(L"fish_command_not_found", &event_args);
- /* Here we want to report an error (so it shows a backtrace), but with no text */
+ // Here we want to report an error (so it shows a backtrace), but with no text.
this->report_error(statement_node, L"");
}
- /* Set the last proc status appropriately */
- proc_set_last_status(err_code==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE);
+ // Set the last proc status appropriately.
+ proc_set_last_status(err_code == ENOENT ? STATUS_UNKNOWN_COMMAND : STATUS_NOT_EXECUTABLE);
return parse_execution_errored;
}
-/* Creates a 'normal' (non-block) process */
-parse_execution_result_t parse_execution_context_t::populate_plain_process(job_t *job, process_t *proc, const parse_node_t &statement)
-{
+/// Creates a 'normal' (non-block) process.
+parse_execution_result_t parse_execution_context_t::populate_plain_process(
+ job_t *job, process_t *proc, const parse_node_t &statement) {
assert(job != NULL);
assert(proc != NULL);
assert(statement.type == symbol_plain_statement);
- /* We may decide that a command should be an implicit cd */
+ // We may decide that a command should be an implicit cd.
bool use_implicit_cd = false;
- /* Get the command. We expect to always get it here. */
+ // Get the command. We expect to always get it here.
wcstring cmd;
bool got_cmd = tree.command_for_plain_statement(statement, src, &cmd);
assert(got_cmd);
- /* Expand it as a command. Return an error on failure. */
+ // Expand it as a command. Return an error on failure.
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES, NULL);
- if (! expanded)
- {
+ if (!expanded) {
report_error(statement, ILLEGAL_CMD_ERR_MSG, cmd.c_str());
return parse_execution_errored;
}
- /* Determine the process type */
+ // Determine the process type.
enum process_type_t process_type = process_type_for_command(statement, cmd);
- /* Check for stack overflow */
- if (process_type == INTERNAL_FUNCTION && parser->forbidden_function.size() > FISH_MAX_STACK_DEPTH)
- {
+ // Check for stack overflow.
+ if (process_type == INTERNAL_FUNCTION &&
+ parser->forbidden_function.size() > FISH_MAX_STACK_DEPTH) {
this->report_error(statement, CALL_STACK_LIMIT_EXCEEDED_ERR_MSG);
return parse_execution_errored;
}
wcstring path_to_external_command;
- if (process_type == EXTERNAL || process_type == INTERNAL_EXEC)
- {
- /* Determine the actual command. This may be an implicit cd. */
+ if (process_type == EXTERNAL || process_type == INTERNAL_EXEC) {
+ // Determine the actual command. This may be an implicit cd.
bool has_command = path_get_path(cmd, &path_to_external_command);
- /* If there was no command, then we care about the value of errno after checking for it, to distinguish between e.g. no file vs permissions problem */
+ // If there was no command, then we care about the value of errno after checking for it, to
+ // distinguish between e.g. no file vs permissions problem.
const int no_cmd_err_code = errno;
- /* If the specified command does not exist, and is undecorated, try using an implicit cd. */
- if (! has_command && tree.decoration_for_plain_statement(statement) == parse_statement_decoration_none)
- {
- /* Implicit cd requires an empty argument and redirection list */
- const parse_node_t *args = get_child(statement, 1, symbol_arguments_or_redirections_list);
- if (args->child_count == 0)
- {
- /* Ok, no arguments or redirections; check to see if the first argument is a directory */
+ // If the specified command does not exist, and is undecorated, try using an implicit cd.
+ if (!has_command &&
+ tree.decoration_for_plain_statement(statement) == parse_statement_decoration_none) {
+ // Implicit cd requires an empty argument and redirection list.
+ const parse_node_t *args =
+ get_child(statement, 1, symbol_arguments_or_redirections_list);
+ if (args->child_count == 0) {
+ // Ok, no arguments or redirections; check to see if the first argument is a
+ // directory.
wcstring implicit_cd_path;
use_implicit_cd = path_can_be_implicit_cd(cmd, &implicit_cd_path);
}
}
- if (! has_command && ! use_implicit_cd)
- {
- /* No command */
+ if (!has_command && !use_implicit_cd) {
+ // No command.
return this->handle_command_not_found(cmd, statement, no_cmd_err_code);
}
}
- /* The argument list and set of IO redirections that we will construct for the process */
+ // The argument list and set of IO redirections that we will construct for the process.
io_chain_t process_io_chain;
wcstring_list_t argument_list;
- if (use_implicit_cd)
- {
+ if (use_implicit_cd) {
/* Implicit cd is simple */
argument_list.push_back(L"cd");
argument_list.push_back(cmd);
path_to_external_command.clear();
- /* If we have defined a wrapper around cd, use it, otherwise use the cd builtin */
+ // If we have defined a wrapper around cd, use it, otherwise use the cd builtin.
process_type = function_exists(L"cd") ? INTERNAL_FUNCTION : INTERNAL_BUILTIN;
- }
- else
- {
+ } else {
const globspec_t glob_behavior = contains(cmd, L"set", L"count") ? nullglob : failglob;
- /* Form the list of arguments. The command is the first argument. TODO: count hack, where we treat 'count --help' as different from 'count $foo' that expands to 'count --help'. fish 1.x never successfully did this, but it tried to! */
- parse_execution_result_t arg_result = this->determine_arguments(statement, &argument_list, glob_behavior);
- if (arg_result != parse_execution_success)
- {
+ // Form the list of arguments. The command is the first argument. TODO: count hack, where we
+ // treat 'count --help' as different from 'count $foo' that expands to 'count --help'. fish
+ // 1.x never successfully did this, but it tried to!
+ parse_execution_result_t arg_result =
+ this->determine_arguments(statement, &argument_list, glob_behavior);
+ if (arg_result != parse_execution_success) {
return arg_result;
}
argument_list.insert(argument_list.begin(), cmd);
- /* The set of IO redirections that we construct for the process */
- if (! this->determine_io_chain(statement, &process_io_chain))
- {
+ // The set of IO redirections that we construct for the process.
+ if (!this->determine_io_chain(statement, &process_io_chain)) {
return parse_execution_errored;
}
- /* Determine the process type */
+ // Determine the process type.
process_type = process_type_for_command(statement, cmd);
}
-
- /* Populate the process */
+ // Populate the process.
proc->type = process_type;
proc->set_argv(argument_list);
proc->set_io_chain(process_io_chain);
@@ -968,58 +881,53 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(job_t
return parse_execution_success;
}
-/* Determine the list of arguments, expanding stuff. Reports any errors caused by expansion. If we have a wildcard that could not be expanded, report the error and continue. */
-parse_execution_result_t parse_execution_context_t::determine_arguments(const parse_node_t &parent, wcstring_list_t *out_arguments, globspec_t glob_behavior)
-{
- /* Get all argument nodes underneath the statement. We guess we'll have that many arguments (but may have more or fewer, if there are wildcards involved) */
- const parse_node_tree_t::parse_node_list_t argument_nodes = tree.find_nodes(parent, symbol_argument);
+// Determine the list of arguments, expanding stuff. Reports any errors caused by expansion. If we
+// have a wildcard that could not be expanded, report the error and continue.
+parse_execution_result_t parse_execution_context_t::determine_arguments(
+ const parse_node_t &parent, wcstring_list_t *out_arguments, globspec_t glob_behavior) {
+ // Get all argument nodes underneath the statement. We guess we'll have that many arguments (but
+ // may have more or fewer, if there are wildcards involved).
+ const parse_node_tree_t::parse_node_list_t argument_nodes =
+ tree.find_nodes(parent, symbol_argument);
out_arguments->reserve(out_arguments->size() + argument_nodes.size());
std::vector<completion_t> arg_expanded;
- for (size_t i=0; i < argument_nodes.size(); i++)
- {
+ for (size_t i = 0; i < argument_nodes.size(); i++) {
const parse_node_t &arg_node = *argument_nodes.at(i);
- /* Expect all arguments to have source */
+ // Expect all arguments to have source.
assert(arg_node.has_source());
const wcstring arg_str = arg_node.get_source(src);
- /* Expand this string */
+ // Expand this string.
parse_error_list_t errors;
arg_expanded.clear();
int expand_ret = expand_string(arg_str, &arg_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
parse_error_offset_source_start(&errors, arg_node.source_start);
- switch (expand_ret)
- {
- case EXPAND_ERROR:
- {
+ switch (expand_ret) {
+ case EXPAND_ERROR: {
this->report_errors(errors);
return parse_execution_errored;
}
-
- case EXPAND_WILDCARD_NO_MATCH:
- {
- if (glob_behavior == failglob)
- {
- // report the unmatched wildcard error and stop processing
+ case EXPAND_WILDCARD_NO_MATCH: {
+ if (glob_behavior == failglob) {
+ // Report the unmatched wildcard error and stop processing.
report_unmatched_wildcard_error(arg_node);
return parse_execution_errored;
}
break;
}
-
case EXPAND_WILDCARD_MATCH:
- case EXPAND_OK:
- {
+ case EXPAND_OK: {
break;
}
}
- /* Now copy over any expanded arguments. Do it using swap() to avoid extra allocations; this is called very frequently. */
+ // Now copy over any expanded arguments. Do it using swap() to avoid extra allocations; this
+ // is called very frequently.
size_t old_arg_count = out_arguments->size();
size_t new_arg_count = arg_expanded.size();
out_arguments->resize(old_arg_count + new_arg_count);
- for (size_t i=0; i < new_arg_count; i++)
- {
+ for (size_t i = 0; i < new_arg_count; i++) {
wcstring &new_arg = arg_expanded.at(i).completion;
out_arguments->at(old_arg_count + i).swap(new_arg);
}
@@ -1028,143 +936,130 @@ parse_execution_result_t parse_execution_context_t::determine_arguments(const pa
return parse_execution_success;
}
-bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement_node, io_chain_t *out_chain)
-{
+bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement_node,
+ io_chain_t *out_chain) {
io_chain_t result;
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);
+ // 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 */
- const parse_node_tree_t::parse_node_list_t redirect_nodes = tree.find_nodes(args_and_redirections_list, symbol_redirection);
- for (size_t i=0; i < redirect_nodes.size(); i++)
- {
+ // Get all redirection nodes underneath the statement.
+ const parse_node_tree_t::parse_node_list_t redirect_nodes =
+ tree.find_nodes(args_and_redirections_list, symbol_redirection);
+ 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 */
- wcstring target; /* file path or target fd */
- enum token_type redirect_type = tree.type_for_redirection(redirect_node, src, &source_fd, &target);
+ int source_fd = -1; // source fd
+ wcstring target; // file path or target fd
+ enum token_type redirect_type =
+ tree.type_for_redirection(redirect_node, 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);
- if (! target_expanded || target.empty())
- {
- /* Should improve this error message */
- errored = report_error(redirect_node,
- _(L"Invalid redirection target: %ls"),
- target.c_str());
+ if (!target_expanded || target.empty()) {
+ // TODO: Improve this error message.
+ errored =
+ report_error(redirect_node, _(L"Invalid redirection target: %ls"), target.c_str());
}
-
- /* Generate the actual IO redirection */
+ // Generate the actual IO redirection.
shared_ptr<io_data_t> new_io;
assert(redirect_type != TOK_NONE);
- switch (redirect_type)
- {
- case TOK_REDIRECT_FD:
- {
- if (target == L"-")
- {
+ switch (redirect_type) {
+ case TOK_REDIRECT_FD: {
+ if (target == L"-") {
new_io.reset(new io_close_t(source_fd));
- }
- else
- {
+ } else {
wchar_t *end = NULL;
errno = 0;
int old_fd = fish_wcstoi(target.c_str(), &end, 10);
- if (old_fd < 0 || errno || *end)
- {
- errored = report_error(redirect_node,
- _(L"Requested redirection to '%ls', which is not a valid file descriptor"),
- target.c_str());
- }
- else
- {
+ if (old_fd < 0 || errno || *end) {
+ errored =
+ report_error(redirect_node, _(L"Requested redirection to '%ls', which "
+ L"is not a valid file descriptor"),
+ target.c_str());
+ } else {
new_io.reset(new io_fd_t(source_fd, old_fd, true));
}
}
break;
}
-
case TOK_REDIRECT_OUT:
case TOK_REDIRECT_APPEND:
case TOK_REDIRECT_IN:
- case TOK_REDIRECT_NOCLOB:
- {
+ case TOK_REDIRECT_NOCLOB: {
int oflags = oflags_for_redirection_type(redirect_type);
io_file_t *new_io_file = new io_file_t(source_fd, target, oflags);
new_io.reset(new_io_file);
break;
}
-
- default:
- {
- // Should be unreachable
- fprintf(stderr, "Unexpected redirection type %ld. aborting.\n", (long)redirect_type);
+ default: {
+ // Should be unreachable.
+ fprintf(stderr, "Unexpected redirection type %ld. aborting.\n",
+ (long)redirect_type);
PARSER_DIE();
break;
}
}
- /* Append the new_io if we got one */
- if (new_io.get() != NULL)
- {
+ // Append the new_io if we got one.
+ if (new_io.get() != NULL) {
result.push_back(new_io);
}
}
- if (out_chain && ! errored)
- {
+ if (out_chain && !errored) {
out_chain->swap(result);
}
- return ! errored;
+ return !errored;
}
-parse_execution_result_t parse_execution_context_t::populate_boolean_process(job_t *job, process_t *proc, const parse_node_t &bool_statement)
-{
- // Handle a boolean statement
+parse_execution_result_t parse_execution_context_t::populate_boolean_process(
+ job_t *job, process_t *proc, const parse_node_t &bool_statement) {
+ // Handle a boolean statement.
bool skip_job = false;
assert(bool_statement.type == symbol_boolean_statement);
- switch (parse_node_tree_t::statement_boolean_type(bool_statement))
- {
- case parse_bool_and:
+ switch (parse_node_tree_t::statement_boolean_type(bool_statement)) {
+ case parse_bool_and: {
// AND. Skip if the last job failed.
skip_job = (proc_get_last_status() != 0);
break;
-
- case parse_bool_or:
+ }
+ case parse_bool_or: {
// OR. Skip if the last job succeeded.
skip_job = (proc_get_last_status() == 0);
break;
-
- case parse_bool_not:
+ }
+ case parse_bool_not: {
// NOT. Negate it.
job_set_flag(job, JOB_NEGATE, !job_get_flag(job, JOB_NEGATE));
break;
+ }
}
- if (skip_job)
- {
+ if (skip_job) {
return parse_execution_skipped;
- }
- else
- {
+ } else {
const parse_node_t &subject = *tree.get_child(bool_statement, 1, symbol_statement);
return this->populate_job_process(job, proc, subject);
}
}
-parse_execution_result_t parse_execution_context_t::populate_block_process(job_t *job, process_t *proc, const parse_node_t &statement_node)
-{
- /* We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when it's time to execute them */
- assert(statement_node.type == symbol_block_statement || statement_node.type == symbol_if_statement || statement_node.type == symbol_switch_statement);
+parse_execution_result_t parse_execution_context_t::populate_block_process(
+ job_t *job, process_t *proc, const parse_node_t &statement_node) {
+ // We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when
+ // it's time to execute them.
+ assert(statement_node.type == symbol_block_statement ||
+ statement_node.type == symbol_if_statement ||
+ statement_node.type == symbol_switch_statement);
- /* The set of IO redirections that we construct for the process */
+ // The set of IO redirections that we construct for the process.
io_chain_t process_io_chain;
- bool errored = ! this->determine_io_chain(statement_node, &process_io_chain);
- if (errored)
- return parse_execution_errored;
+ bool errored = !this->determine_io_chain(statement_node, &process_io_chain);
+ if (errored) return parse_execution_errored;
proc->type = INTERNAL_BLOCK_NODE;
proc->internal_block_node = this->get_offset(statement_node);
@@ -1172,116 +1067,105 @@ parse_execution_result_t parse_execution_context_t::populate_block_process(job_t
return parse_execution_success;
}
-
-/* Returns a process_t allocated with new. It's the caller's responsibility to delete it (!) */
-parse_execution_result_t parse_execution_context_t::populate_job_process(job_t *job, process_t *proc, const parse_node_t &statement_node)
-{
+// Returns a process_t allocated with new. It's the caller's responsibility to delete it (!).
+parse_execution_result_t parse_execution_context_t::populate_job_process(
+ job_t *job, process_t *proc, const parse_node_t &statement_node) {
assert(statement_node.type == symbol_statement);
assert(statement_node.child_count == 1);
- // Get the "specific statement" which is boolean / block / if / switch / decorated
+ // Get the "specific statement" which is boolean / block / if / switch / decorated.
const parse_node_t &specific_statement = *get_child(statement_node, 0);
parse_execution_result_t result = parse_execution_success;
- switch (specific_statement.type)
- {
- case symbol_boolean_statement:
- {
+ switch (specific_statement.type) {
+ case symbol_boolean_statement: {
result = this->populate_boolean_process(job, proc, specific_statement);
break;
}
-
case symbol_block_statement:
case symbol_if_statement:
- case symbol_switch_statement:
- {
+ case symbol_switch_statement: {
result = this->populate_block_process(job, proc, specific_statement);
break;
}
-
- case symbol_decorated_statement:
- {
- /* Get the plain statement. It will pull out the decoration itself */
- const parse_node_t &plain_statement = tree.find_child(specific_statement, symbol_plain_statement);
+ case symbol_decorated_statement: {
+ // Get the plain statement. It will pull out the decoration itself.
+ const parse_node_t &plain_statement =
+ tree.find_child(specific_statement, symbol_plain_statement);
result = this->populate_plain_process(job, proc, plain_statement);
break;
}
-
- default:
- fprintf(stderr, "'%ls' not handled by new parser yet\n", specific_statement.describe().c_str());
+ default: {
+ fprintf(stderr, "'%ls' not handled by new parser yet\n",
+ specific_statement.describe().c_str());
PARSER_DIE();
break;
+ }
}
return result;
}
-
-parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(job_t *j, const parse_node_t &job_node, const block_t *associated_block)
-{
+parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(
+ job_t *j, const parse_node_t &job_node, const block_t *associated_block) {
assert(job_node.type == symbol_job);
- /* Tell the job what its command is */
+ // Tell the job what its command is.
j->set_command(get_source(job_node));
- /* We are going to construct process_t structures for every statement in the job. Get the first statement. */
+ // We are going to construct process_t structures for every statement in the job. Get the first
+ // statement.
const parse_node_t *statement_node = get_child(job_node, 0, symbol_statement);
assert(statement_node != NULL);
parse_execution_result_t result = parse_execution_success;
- /* Create processes. Each one may fail. */
+ // Create processes. Each one may fail.
std::vector<process_t *> processes;
processes.push_back(new process_t());
result = this->populate_job_process(j, processes.back(), *statement_node);
- /* Construct process_ts for job continuations (pipelines), by walking the list until we hit the terminal (empty) job continuation */
+ // Construct process_ts for job continuations (pipelines), by walking the list until we hit the
+ // terminal (empty) job continuation.
const parse_node_t *job_cont = get_child(job_node, 1, symbol_job_continuation);
assert(job_cont != NULL);
- while (result == parse_execution_success && job_cont->child_count > 0)
- {
+ while (result == parse_execution_success && job_cont->child_count > 0) {
assert(job_cont->type == symbol_job_continuation);
- /* Handle the pipe, whose fd may not be the obvious stdout */
+ // Handle the pipe, whose fd may not be the obvious stdout.
const parse_node_t &pipe_node = *get_child(*job_cont, 0, parse_token_type_pipe);
int pipe_write_fd = fd_redirected_by_pipe(get_source(pipe_node));
- if (pipe_write_fd == -1)
- {
+ if (pipe_write_fd == -1) {
result = report_error(pipe_node, ILLEGAL_FD_ERR_MSG, get_source(pipe_node).c_str());
break;
}
processes.back()->pipe_write_fd = pipe_write_fd;
- /* Get the statement node and make a process from it */
+ // Get the statement node and make a process from it.
const parse_node_t *statement_node = get_child(*job_cont, 1, symbol_statement);
assert(statement_node != NULL);
- /* Store the new process (and maybe with an error) */
+ // Store the new process (and maybe with an error).
processes.push_back(new process_t());
result = this->populate_job_process(j, processes.back(), *statement_node);
- /* Get the next continuation */
+ // Get the next continuation.
job_cont = get_child(*job_cont, 2, symbol_job_continuation);
assert(job_cont != NULL);
}
- /* Return what happened */
- if (result == parse_execution_success)
- {
- /* Link up the processes */
- assert(! processes.empty());
+ // Return what happened.
+ if (result == parse_execution_success) {
+ // Link up the processes.
+ assert(!processes.empty());
j->first_process = processes.at(0);
- for (size_t i=1 ; i < processes.size(); i++)
- {
- processes.at(i-1)->next = processes.at(i);
+ for (size_t i = 1; i < processes.size(); i++) {
+ processes.at(i - 1)->next = processes.at(i);
}
- }
- else
- {
- /* Clean up processes */
- for (size_t i=0; i < processes.size(); i++)
- {
+ } else {
+ // Clean up processes.
+ for (size_t i = 0; i < processes.size(); i++) {
const process_t *proc = processes.at(i);
processes.at(i) = NULL;
delete proc;
@@ -1290,75 +1174,75 @@ parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(j
return result;
}
-parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t &job_node, const block_t *associated_block)
-{
- if (should_cancel_execution(associated_block))
- {
+parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t &job_node,
+ const block_t *associated_block) {
+ if (should_cancel_execution(associated_block)) {
return parse_execution_cancelled;
}
- // Get terminal modes
+ // Get terminal modes.
struct termios tmodes = {};
- if (get_is_interactive())
- {
- if (tcgetattr(STDIN_FILENO, &tmodes))
- {
- // need real error handling here
+ if (get_is_interactive()) {
+ if (tcgetattr(STDIN_FILENO, &tmodes)) {
+ // Need real error handling here.
wperror(L"tcgetattr");
return parse_execution_errored;
}
}
- /* Increment the eval_level for the duration of this command */
+ // Increment the eval_level for the duration of this command.
scoped_push<int> saved_eval_level(&eval_level, eval_level + 1);
- /* Save the node index */
+ // Save the node index.
scoped_push<node_offset_t> saved_node_offset(&executing_node_idx, this->get_offset(job_node));
- /* Profiling support */
+ // Profiling support.
long long start_time = 0, parse_time = 0, exec_time = 0;
profile_item_t *profile_item = this->parser->create_profile_item();
- if (profile_item != NULL)
- {
+ if (profile_item != NULL) {
start_time = get_time();
}
- /* When we encounter a block construct (e.g. while loop) in the general case, we create a "block process" that has a pointer to its source. This allows us to handle block-level redirections. However, if there are no redirections, then we can just jump into the block directly, which is significantly faster. */
- if (job_is_simple_block(job_node))
- {
+ // When we encounter a block construct (e.g. while loop) in the general case, we create a "block
+ // process" that has a pointer to its source. This allows us to handle block-level redirections.
+ // However, if there are no redirections, then we can just jump into the block directly, which
+ // is significantly faster.
+ if (job_is_simple_block(job_node)) {
parse_execution_result_t result = parse_execution_success;
-
+
const parse_node_t &statement = *get_child(job_node, 0, symbol_statement);
const parse_node_t &specific_statement = *get_child(statement, 0);
assert(specific_statement_type_is_redirectable_block(specific_statement));
- switch (specific_statement.type)
- {
- case symbol_block_statement:
+ switch (specific_statement.type) {
+ case symbol_block_statement: {
result = this->run_block_statement(specific_statement);
break;
-
- case symbol_if_statement:
+ }
+ case symbol_if_statement: {
result = this->run_if_statement(specific_statement);
break;
-
- case symbol_switch_statement:
+ }
+ case symbol_switch_statement: {
result = this->run_switch_statement(specific_statement);
break;
-
- default:
- /* Other types should be impossible due to the specific_statement_type_is_redirectable_block check */
+ }
+ default: {
+ // Other types should be impossible due to the
+ // specific_statement_type_is_redirectable_block check.
PARSER_DIE();
break;
+ }
}
- if (profile_item != NULL)
- {
- /* Block-types profile a little weird. They have no 'parse' time, and their command is just the block type */
+ if (profile_item != NULL) {
+ // Block-types profile a little weird. They have no 'parse' time, and their command is
+ // just the block type.
exec_time = get_time();
- profile_item->level=eval_level;
+ profile_item->level = eval_level;
profile_item->parse = 0;
- profile_item->exec=(int)(exec_time-start_time);
- profile_item->cmd = profiling_cmd_name_for_redirectable_block(specific_statement, this->tree, this->src);
+ profile_item->exec = (int)(exec_time - start_time);
+ profile_item->cmd = profiling_cmd_name_for_redirectable_block(specific_statement,
+ this->tree, this->src);
profile_item->skipped = false;
}
@@ -1368,27 +1252,27 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t
job_t *j = new job_t(acquire_job_id(), block_io);
j->tmodes = tmodes;
job_set_flag(j, JOB_CONTROL,
- (job_control_mode==JOB_CONTROL_ALL) ||
- ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive())));
+ (job_control_mode == JOB_CONTROL_ALL) ||
+ ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive())));
- job_set_flag(j, JOB_FOREGROUND, ! tree.job_should_be_backgrounded(job_node));
+ job_set_flag(j, JOB_FOREGROUND, !tree.job_should_be_backgrounded(job_node));
- job_set_flag(j, JOB_TERMINAL,
- job_get_flag(j, JOB_CONTROL) && !is_subshell && !is_event);
+ job_set_flag(j, JOB_TERMINAL, job_get_flag(j, JOB_CONTROL) && !is_subshell && !is_event);
job_set_flag(j, JOB_SKIP_NOTIFICATION,
is_subshell || is_block || is_event || !get_is_interactive());
- /* Tell the current block what its job is. This has to happen before we populate it (#1394) */
+ // Tell the current block what its job is. This has to happen before we populate it (#1394).
parser->current_block()->job = j;
- /* Populate the job. This may fail for reasons like command_not_found. If this fails, an error will have been printed */
- parse_execution_result_t pop_result = this->populate_job_from_job_node(j, job_node, associated_block);
+ // Populate the job. This may fail for reasons like command_not_found. If this fails, an error
+ // will have been printed.
+ parse_execution_result_t pop_result =
+ this->populate_job_from_job_node(j, job_node, associated_block);
- /* Clean up the job on failure or cancellation */
+ // Clean up the job on failure or cancellation.
bool populated_job = (pop_result == parse_execution_success);
- if (! populated_job || this->should_cancel_execution(associated_block))
- {
+ if (!populated_job || this->should_cancel_execution(associated_block)) {
assert(parser->current_block()->job == j);
parser->current_block()->job = NULL;
delete j;
@@ -1396,191 +1280,169 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t
populated_job = false;
}
-
- /* Store time it took to 'parse' the command */
- if (profile_item != NULL)
- {
+ // Store time it took to 'parse' the command.
+ if (profile_item != NULL) {
parse_time = get_time();
}
- if (populated_job)
- {
- /* Success. Give the job to the parser - it will clean it up. */
+ if (populated_job) {
+ // Success. Give the job to the parser - it will clean it up.
parser->job_add(j);
- /* Check to see if this contained any external commands */
+ // Check to see if this contained any external commands.
bool job_contained_external_command = false;
- for (const process_t *proc = j->first_process; proc != NULL; proc = proc->next)
- {
- if (proc->type == EXTERNAL)
- {
+ for (const process_t *proc = j->first_process; proc != NULL; proc = proc->next) {
+ if (proc->type == EXTERNAL) {
job_contained_external_command = true;
break;
}
}
- /* Actually execute the job */
+ // Actually execute the job.
exec_job(*this->parser, j);
- /* Only external commands require a new fishd barrier */
- if (job_contained_external_command)
- {
+ // Only external commands require a new fishd barrier.
+ if (job_contained_external_command) {
set_proc_had_barrier(false);
}
}
- if (profile_item != NULL)
- {
+ if (profile_item != NULL) {
exec_time = get_time();
- profile_item->level=eval_level;
- profile_item->parse = (int)(parse_time-start_time);
- profile_item->exec=(int)(exec_time-parse_time);
+ profile_item->level = eval_level;
+ profile_item->parse = (int)(parse_time - start_time);
+ profile_item->exec = (int)(exec_time - parse_time);
profile_item->cmd = j ? j->command() : wcstring();
- profile_item->skipped = ! populated_job;
+ profile_item->skipped = !populated_job;
}
-
- /* Clean up jobs. */
- job_reap(0);
-
- /* All done */
+ job_reap(0); // clean up jobs
return parse_execution_success;
}
-parse_execution_result_t parse_execution_context_t::run_job_list(const parse_node_t &job_list_node, const block_t *associated_block)
-{
+parse_execution_result_t parse_execution_context_t::run_job_list(const parse_node_t &job_list_node,
+ const block_t *associated_block) {
assert(job_list_node.type == symbol_job_list || job_list_node.type == symbol_andor_job_list);
parse_execution_result_t result = parse_execution_success;
const parse_node_t *job_list = &job_list_node;
- while (job_list != NULL && ! should_cancel_execution(associated_block))
- {
+ while (job_list != NULL && !should_cancel_execution(associated_block)) {
assert(job_list->type == symbol_job_list || job_list_node.type == symbol_andor_job_list);
- // Try pulling out a job
+ // Try pulling out a job.
const parse_node_t *job = tree.next_node_in_node_list(*job_list, symbol_job, &job_list);
- if (job != NULL)
- {
+ if (job != NULL) {
result = this->run_1_job(*job, associated_block);
}
}
- /* Returns the last job executed */
+ // Returns the last job executed.
return result;
}
-parse_execution_result_t parse_execution_context_t::eval_node_at_offset(node_offset_t offset, const block_t *associated_block, const io_chain_t &io)
-{
- /* Don't ever expect to have an empty tree if this is called */
- assert(! tree.empty());
+parse_execution_result_t parse_execution_context_t::eval_node_at_offset(
+ node_offset_t offset, const block_t *associated_block, const io_chain_t &io) {
+ // Don't ever expect to have an empty tree if this is called.
+ assert(!tree.empty());
assert(offset < tree.size());
- /* Apply this block IO for the duration of this function */
+ // Apply this block IO for the duration of this function.
scoped_push<io_chain_t> block_io_push(&block_io, io);
const parse_node_t &node = tree.at(offset);
- /* Currently, we only expect to execute the top level job list, or a block node. Assert that. */
+ // Currently, we only expect to execute the top level job list, or a block node. Assert that.
assert(node.type == symbol_job_list || specific_statement_type_is_redirectable_block(node));
enum parse_execution_result_t status = parse_execution_success;
- switch (node.type)
- {
- case symbol_job_list:
- {
- /* We should only get a job list if it's the very first node. This is because this is the entry point for both top-level execution (the first node) and INTERNAL_BLOCK_NODE execution (which does block statements, but never job lists) */
+ switch (node.type) {
+ case symbol_job_list: {
+ // We should only get a job list if it's the very first node. This is because this is
+ // the entry point for both top-level execution (the first node) and INTERNAL_BLOCK_NODE
+ // execution (which does block statements, but never job lists).
assert(offset == 0);
wcstring func_name;
- const parse_node_t *infinite_recursive_node = this->infinite_recursive_statement_in_job_list(node, &func_name);
- if (infinite_recursive_node != NULL)
- {
- /* We have an infinite recursion */
- this->report_error(*infinite_recursive_node, INFINITE_FUNC_RECURSION_ERR_MSG, func_name.c_str());
+ const parse_node_t *infinite_recursive_node =
+ this->infinite_recursive_statement_in_job_list(node, &func_name);
+ if (infinite_recursive_node != NULL) {
+ // We have an infinite recursion.
+ this->report_error(*infinite_recursive_node, INFINITE_FUNC_RECURSION_ERR_MSG,
+ func_name.c_str());
status = parse_execution_errored;
- }
- else
- {
- /* No infinite recursion */
+ } else {
+ // No infinite recursion.
status = this->run_job_list(node, associated_block);
}
break;
}
-
- case symbol_block_statement:
+ case symbol_block_statement: {
status = this->run_block_statement(node);
break;
-
- case symbol_if_statement:
+ }
+ case symbol_if_statement: {
status = this->run_if_statement(node);
break;
-
- case symbol_switch_statement:
+ }
+ case symbol_switch_statement: {
status = this->run_switch_statement(node);
break;
-
- default:
- /* In principle, we could support other node types. However we never expect to be passed them - see above. */
- fprintf(stderr, "Unexpected node %ls found in %s\n", node.describe().c_str(), __FUNCTION__);
+ }
+ default: {
+ // In principle, we could support other node types. However we never expect to be passed
+ // them - see above.
+ fprintf(stderr, "Unexpected node %ls found in %s\n", node.describe().c_str(),
+ __FUNCTION__);
PARSER_DIE();
break;
+ }
}
return status;
}
-int parse_execution_context_t::line_offset_of_node_at_offset(node_offset_t requested_index)
-{
- /* If we're not executing anything, return -1 */
- if (requested_index == NODE_OFFSET_INVALID)
- {
+int parse_execution_context_t::line_offset_of_node_at_offset(node_offset_t requested_index) {
+ // If we're not executing anything, return -1.
+ if (requested_index == NODE_OFFSET_INVALID) {
return -1;
}
- /* If for some reason we're executing a node without source, return -1 */
+ // If for some reason we're executing a node without source, return -1.
const parse_node_t &node = tree.at(requested_index);
- if (! node.has_source())
- {
+ if (!node.has_source()) {
return -1;
}
-
+
size_t char_offset = tree.at(requested_index).source_start;
return this->line_offset_of_character_at_offset(char_offset);
}
-int parse_execution_context_t::line_offset_of_character_at_offset(size_t offset)
-{
- /* Count the number of newlines, leveraging our cache */
+int parse_execution_context_t::line_offset_of_character_at_offset(size_t offset) {
+ // Count the number of newlines, leveraging our cache.
assert(offset <= src.size());
- /* Easy hack to handle 0 */
- if (offset == 0)
- {
+ // Easy hack to handle 0.
+ if (offset == 0) {
return 0;
}
- /* We want to return (one plus) the number of newlines at offsets less than the given offset. cached_lineno_count is the number of newlines at indexes less than cached_lineno_offset. */
+ // We want to return (one plus) the number of newlines at offsets less than the given offset.
+ // cached_lineno_count is the number of newlines at indexes less than cached_lineno_offset.
const wchar_t *str = src.c_str();
- if (offset > cached_lineno_offset)
- {
+ if (offset > cached_lineno_offset) {
size_t i;
- for (i = cached_lineno_offset; str[i] != L'\0' && i < offset; i++)
- {
- /* Add one for every newline we find in the range [cached_lineno_offset, offset) */
- if (str[i] == L'\n')
- {
+ for (i = cached_lineno_offset; str[i] != L'\0' && i < offset; i++) {
+ // Add one for every newline we find in the range [cached_lineno_offset, offset).
+ if (str[i] == L'\n') {
cached_lineno_count++;
}
}
- cached_lineno_offset = i; //note: i, not offset, in case offset is beyond the length of the string
- }
- else if (offset < cached_lineno_offset)
- {
- /* Subtract one for every newline we find in the range [offset, cached_lineno_offset) */
- for (size_t i = offset; i < cached_lineno_offset; i++)
- {
- if (str[i] == L'\n')
- {
+ cached_lineno_offset =
+ i; // note: i, not offset, in case offset is beyond the length of the string
+ } else if (offset < cached_lineno_offset) {
+ // Subtract one for every newline we find in the range [offset, cached_lineno_offset).
+ for (size_t i = offset; i < cached_lineno_offset; i++) {
+ if (str[i] == L'\n') {
cached_lineno_count--;
}
}
@@ -1589,26 +1451,21 @@ int parse_execution_context_t::line_offset_of_character_at_offset(size_t offset)
return cached_lineno_count;
}
-int parse_execution_context_t::get_current_line_number()
-{
+int parse_execution_context_t::get_current_line_number() {
int line_number = -1;
int line_offset = this->line_offset_of_node_at_offset(this->executing_node_idx);
- if (line_offset >= 0)
- {
- /* The offset is 0 based; the number is 1 based */
+ if (line_offset >= 0) {
+ // The offset is 0 based; the number is 1 based.
line_number = line_offset + 1;
}
return line_number;
}
-int parse_execution_context_t::get_current_source_offset() const
-{
+int parse_execution_context_t::get_current_source_offset() const {
int result = -1;
- if (executing_node_idx != NODE_OFFSET_INVALID)
- {
+ if (executing_node_idx != NODE_OFFSET_INVALID) {
const parse_node_t &node = tree.at(executing_node_idx);
- if (node.has_source())
- {
+ if (node.has_source()) {
result = static_cast<int>(node.source_start);
}
}