From a59f35a378e381747efdb616baf2e321007e54b0 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 22 Dec 2019 15:37:14 -0800 Subject: [PATCH] Make block_type_t an enum class --- src/builtin.cpp | 8 +- src/builtin_block.cpp | 3 +- src/builtin_eval.cpp | 2 +- src/builtin_return.cpp | 2 +- src/event.cpp | 2 +- src/exec.cpp | 7 +- src/fish.cpp | 4 +- src/fish_tests.cpp | 14 ++-- src/input.cpp | 2 +- src/parse_execution.cpp | 8 +- src/parser.cpp | 160 ++++++++++++++++++++-------------------- src/parser.h | 35 ++++----- src/reader.cpp | 6 +- 13 files changed, 129 insertions(+), 124 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index b727fba4c..7af538e95 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -165,7 +165,7 @@ void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t * // If it's an error, redirect the output of __fish_print_help to stderr ios.push_back(std::make_shared(STDOUT_FILENO, STDERR_FILENO)); } - parser.eval(cmd, ios, TOP); + parser.eval(cmd, ios, block_type_t::top); // ignore the exit status of __fish_print_help } @@ -265,11 +265,11 @@ static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar // Paranoia: ensure we have a real loop. bool has_loop = false; for (const auto &b : parser.blocks()) { - if (b.type() == WHILE || b.type() == FOR) { + if (b.type() == block_type_t::while_block || b.type() == block_type_t::for_block) { has_loop = true; break; } - if (b.is_function()) break; + if (b.is_function_call()) break; } if (!has_loop) { wcstring error_message = format_string(_(L"%ls: Not inside of loop\n"), argv[0]); @@ -298,7 +298,7 @@ static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t * // Ensure we don't allow creating a breakpoint at an interactive prompt. There may be a simpler // or clearer way to do this but this works. const block_t *block1 = parser.block_at_index(1); - if (!block1 || block1->type() == BREAKPOINT) { + if (!block1 || block1->type() == block_type_t::breakpoint) { streams.err.append_format(_(L"%ls: Command not valid at an interactive prompt\n"), cmd); return STATUS_ILLEGAL_CMD; } diff --git a/src/builtin_block.cpp b/src/builtin_block.cpp index 73509e8cb..f1f566553 100644 --- a/src/builtin_block.cpp +++ b/src/builtin_block.cpp @@ -117,8 +117,7 @@ int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) { break; } case UNSET: { - while (block != nullptr && block->type() != FUNCTION_CALL && - block->type() != FUNCTION_CALL_NO_SHADOW) { + while (block && !block->is_function_call()) { // Set it in function scope block = parser.block_at_index(++block_idx); } diff --git a/src/builtin_eval.cpp b/src/builtin_eval.cpp index 1cbb0d262..f53b5be1b 100644 --- a/src/builtin_eval.cpp +++ b/src/builtin_eval.cpp @@ -27,7 +27,7 @@ int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const auto cached_exec_count = parser.libdata().exec_count; int status = STATUS_CMD_OK; if (argc > 1) { - if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::TOP) != + if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::top) != eval_result_t::ok) { status = STATUS_CMD_ERROR; } else if (cached_exec_count == parser.libdata().exec_count) { diff --git a/src/builtin_return.cpp b/src/builtin_return.cpp index 7ef2e5f7f..767f503cb 100644 --- a/src/builtin_return.cpp +++ b/src/builtin_return.cpp @@ -93,7 +93,7 @@ int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) { // Find the function block. bool has_function_block = false; for (const auto &b : parser.blocks()) { - if (b.is_function()) { + if (b.is_function_call()) { has_function_block = true; break; } diff --git a/src/event.cpp b/src/event.cpp index b78da1f15..011c3e007 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -286,7 +286,7 @@ static void event_fire_internal(parser_t &parser, const event_t &event) { auto prev_statuses = parser.get_last_statuses(); block_t *b = parser.push_block(block_t::event_block(event)); - parser.eval(buffer, io_chain_t(), TOP); + parser.eval(buffer, io_chain_t(), block_type_t::top); parser.pop_block(b); parser.set_last_statuses(std::move(prev_statuses)); } diff --git a/src/exec.cpp b/src/exec.cpp index 3b1505ee9..664afcc5c 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -733,7 +733,7 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job tnode_t node = p->internal_block_node; assert(source && node && "Process is missing node info"); return [=](parser_t &parser) { - eval_result_t res = parser.eval_node(source, node, TOP, lineage); + eval_result_t res = parser.eval_node(source, node, block_type_t::top, lineage); switch (res) { case eval_result_t::ok: case eval_result_t::error: @@ -758,7 +758,8 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job const auto &ld = parser.libdata(); auto saved_exec_count = ld.exec_count; const block_t *fb = function_prepare_environment(parser, *argv, *props); - auto res = parser.eval_node(props->parsed_source, props->body_node, TOP, lineage); + auto res = parser.eval_node(props->parsed_source, props->body_node, block_type_t::top, + lineage); function_restore_environment(parser, fb); switch (res) { @@ -1175,7 +1176,7 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstrin // be null. std::shared_ptr buffer; if (auto bufferfill = io_bufferfill_t::create(fd_set_t{}, ld.read_limit)) { - if (parser.eval(cmd, io_chain_t{bufferfill}, SUBST) == eval_result_t::ok) { + if (parser.eval(cmd, io_chain_t{bufferfill}, block_type_t::subst) == eval_result_t::ok) { subcommand_statuses = parser.get_last_statuses(); } buffer = io_bufferfill_t::finish(std::move(bufferfill)); diff --git a/src/fish.cpp b/src/fish.cpp index 33bc0e198..80ca51949 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -228,7 +228,7 @@ static void source_config_in_directory(const wcstring &dir) { const wcstring cmd = L"builtin source " + escaped_pathname; parser_t &parser = parser_t::principal_parser(); set_is_within_fish_initialization(true); - parser.eval(cmd, io_chain_t(), TOP); + parser.eval(cmd, io_chain_t(), block_type_t::top); set_is_within_fish_initialization(false); } @@ -254,7 +254,7 @@ int run_command_list(std::vector *cmds, const io_chain_t &io) { for (const auto &cmd : *cmds) { const wcstring cmd_wcs = str2wcstring(cmd); - eval_result_t eval_res = parser.eval(cmd_wcs, io, TOP); + eval_result_t eval_res = parser.eval(cmd_wcs, io, block_type_t::top); res = (eval_res == eval_result_t::ok ? 0 : 1); } diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 55cf42eae..3720f7315 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1003,16 +1003,17 @@ static void test_parser() { // Ensure that we don't crash on infinite self recursion and mutual recursion. These must use // the principal parser because we cannot yet execute jobs on other parsers. say(L"Testing recursion detection"); - parser->eval(L"function recursive ; recursive ; end ; recursive; ", io_chain_t(), TOP); + parser->eval(L"function recursive ; recursive ; end ; recursive; ", io_chain_t(), + block_type_t::top); #if 0 // This is disabled since it produces a long backtrace. We should find a way to either visually // compress the backtrace, or disable error spewing. parser->.eval(L"function recursive1 ; recursive2 ; end ; " - L"function recursive2 ; recursive1 ; end ; recursive1; ", io_chain_t(), TOP); + L"function recursive2 ; recursive1 ; end ; recursive1; ", io_chain_t(), block_type_t::top); #endif say(L"Testing empty function name"); - parser->eval(L"function '' ; echo fail; exit 42 ; end ; ''", io_chain_t(), TOP); + parser->eval(L"function '' ; echo fail; exit 42 ; end ; ''", io_chain_t(), block_type_t::top); say(L"Testing eval_args"); completion_list_t comps = parser_t::expand_argument_list( @@ -1032,7 +1033,8 @@ static void test_1_cancellation(const wchar_t *src) { usleep(delay * 1E6); pthread_kill(thread, SIGINT); }); - eval_result_t ret = parser_t::principal_parser().eval(src, io_chain_t{filler}, TOP); + eval_result_t ret = + parser_t::principal_parser().eval(src, io_chain_t{filler}, block_type_t::top); auto buffer = io_bufferfill_t::finish(std::move(filler)); if (buffer->buffer().size() != 0) { err(L"Expected 0 bytes in out_buff, but instead found %lu bytes, for command %ls\n", @@ -1074,7 +1076,7 @@ static void test_cancellation() { bool iis = is_interactive_session(); set_interactive_session(true); const wchar_t *child_self_destructor = L"while true ; sh -c 'sleep .25; kill -s INT $$' ; end"; - parser_t::principal_parser().eval(child_self_destructor, io_chain_t(), TOP); + parser_t::principal_parser().eval(child_self_destructor, io_chain_t(), block_type_t::top); set_interactive_session(iis); // Restore signal handling. @@ -5198,7 +5200,7 @@ static void test_illegal_command_exit_code() { parser_t &parser = parser_t::principal_parser(); for (const auto &test : tests) { - parser.eval(test.txt, empty_ios, TOP); + parser.eval(test.txt, empty_ios, block_type_t::top); int exit_status = parser.get_last_status(); if (exit_status != test.result) { diff --git a/src/input.cpp b/src/input.cpp index 404cbce71..a194fab2a 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -389,7 +389,7 @@ void inputter_t::mapping_execute(const input_mapping_t &m, bool allow_commands) // see that until all other commands have also been run. auto last_statuses = parser_->get_last_statuses(); for (const wcstring &cmd : m.commands) { - parser_->eval(cmd, io_chain_t(), TOP); + parser_->eval(cmd, io_chain_t(), block_type_t::top); } parser_->set_last_statuses(std::move(last_statuses)); event_queue_.push_front(char_event_type_t::check_exit); diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index 7403e6d9e..c292e7208 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -105,7 +105,7 @@ tnode_t parse_execution_context_t::infinite_recursive_statem // 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); + (current && parent && current->type() == block_type_t::top && parent->is_function_call()); if (!is_within_function_call) { return {}; } @@ -322,7 +322,7 @@ eval_result_t parse_execution_context_t::run_if_statement(tnode_t contents) { // Basic begin/end block. Push a scope block, run jobs, pop it trace_if_enabled(*parser, L"begin"); - block_t *sb = parser->push_block(block_t::scope_block(BEGIN)); + block_t *sb = parser->push_block(block_t::scope_block(block_type_t::begin)); eval_result_t ret = run_job_list(contents, sb); parser->pop_block(sb); trace_if_enabled(*parser, L"end begin"); @@ -380,7 +380,7 @@ bool parse_execution_context_t::is_function_context() const { const block_t *current = parser->block_at_index(0); const block_t *parent = parser->block_at_index(1); bool is_within_function_call = - (current && parent && current->type() == TOP && parent->type() == FUNCTION_CALL); + (current && parent && current->type() == block_type_t::top && parent->is_function_call()); return is_within_function_call; } @@ -1461,7 +1461,7 @@ eval_result_t parse_execution_context_t::eval_node(tnode_t job_list } // Check for stack overflow. The TOP check ensures we only do this for function calls. - if (associated_block->type() == TOP && parser->function_stack_is_overflowing()) { + if (associated_block->type() == block_type_t::top && parser->function_stack_is_overflowing()) { return this->report_error(job_list, CALL_STACK_LIMIT_EXCEEDED_ERR_MSG); } return this->run_job_list(job_list, associated_block); diff --git a/src/parser.cpp b/src/parser.cpp index d4c700db6..3c95491e2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -75,33 +75,6 @@ class io_chain_t; /// Unknown block description. #define UNKNOWN_BLOCK N_(L"unknown/invalid block") -/// Data structure to describe a block type, like while blocks, command substitution blocks, etc. -struct block_lookup_entry { - // The block type id. The legal values are defined in parser.h. - block_type_t type; - // The name of the builtin that creates this type of block, if any. - const wchar_t *name; - // A description of this block type. - const wchar_t *desc; -}; - -/// List of all legal block types. -static const struct block_lookup_entry block_lookup[] = { - {WHILE, L"while", WHILE_BLOCK}, - {FOR, L"for", FOR_BLOCK}, - {IF, L"if", IF_BLOCK}, - {FUNCTION_CALL, nullptr, FUNCTION_CALL_BLOCK}, - {FUNCTION_CALL_NO_SHADOW, nullptr, FUNCTION_CALL_NO_SHADOW_BLOCK}, - {SWITCH, L"switch", SWITCH_BLOCK}, - {TOP, nullptr, TOP_BLOCK}, - {SUBST, nullptr, SUBST_BLOCK}, - {BEGIN, L"begin", BEGIN_BLOCK}, - {SOURCE, L"source", SOURCE_BLOCK}, - {EVENT, nullptr, EVENT_BLOCK}, - {BREAKPOINT, L"breakpoint", BREAKPOINT_BLOCK}, - {VARIABLE_ASSIGNMENT, L"variable assignment", VARIABLE_ASSIGNMENT_BLOCK}, - {static_cast(0), nullptr, nullptr}}; - // Given a file path, return something nicer. Currently we just "unexpand" tildes. wcstring parser_t::user_presentable_path(const wcstring &path) const { return replace_home_directory_with_tilde(path, vars()); @@ -148,17 +121,18 @@ block_t *parser_t::push_block(block_t &&block) { new_current.src_filename = intern(filename); } - // Types TOP and SUBST are not considered blocks for the purposes of `status is-block`. - if (type != TOP && type != SUBST) { + // Types top and subst are not considered blocks for the purposes of `status is-block`. + if (type != block_type_t::top && type != block_type_t::subst) { libdata().is_block = true; } - if (type == BREAKPOINT) { + if (type == block_type_t::breakpoint) { libdata().is_breakpoint = true; } - if (new_current.type() != TOP) { - vars().push(type == FUNCTION_CALL); + if (new_current.type() != block_type_t::top) { + bool shadow = (type == block_type_t::function_call); + vars().push(shadow); new_current.wants_pop_env = true; } @@ -181,7 +155,7 @@ void parser_t::pop_block(const block_t *expected) { // Figure out if `status is-block` should consider us to be in a block now. bool new_is_block = false; for (const auto &b : block_list) { - if (b.type() != TOP && b.type() != SUBST) { + if (b.type() != block_type_t::top && b.type() != block_type_t::subst) { new_is_block = true; break; } @@ -191,7 +165,7 @@ void parser_t::pop_block(const block_t *expected) { // Are we still in a breakpoint? bool new_is_breakpoint = false; for (const auto &b : block_list) { - if (b.type() == BREAKPOINT) { + if (b.type() == block_type_t::breakpoint) { new_is_breakpoint = true; break; } @@ -199,11 +173,35 @@ void parser_t::pop_block(const block_t *expected) { libdata().is_breakpoint = new_is_breakpoint; } -const wchar_t *parser_t::get_block_desc(int block) const { - for (size_t i = 0; block_lookup[i].desc; i++) { - if (block_lookup[i].type == block) { - return _(block_lookup[i].desc); - } +const wchar_t *parser_t::get_block_desc(block_type_t block) { + switch (block) { + case block_type_t::while_block: + return WHILE_BLOCK; + case block_type_t::for_block: + return FOR_BLOCK; + case block_type_t::if_block: + return IF_BLOCK; + case block_type_t::function_call: + return FUNCTION_CALL_BLOCK; + + case block_type_t::function_call_no_shadow: + return FUNCTION_CALL_NO_SHADOW_BLOCK; + case block_type_t::switch_block: + return SWITCH_BLOCK; + case block_type_t::subst: + return SUBST_BLOCK; + case block_type_t::top: + return TOP_BLOCK; + case block_type_t::begin: + return BEGIN_BLOCK; + case block_type_t::source: + return SOURCE_BLOCK; + case block_type_t::event: + return EVENT_BLOCK; + case block_type_t::breakpoint: + return BREAKPOINT_BLOCK; + case block_type_t::variable_assignment: + return VARIABLE_ASSIGNMENT_BLOCK; } return _(UNKNOWN_BLOCK); } @@ -339,7 +337,7 @@ std::shared_ptr parser_t::shared() { return shared_from_this(); } wcstring parser_t::stack_trace() const { wcstring trace; for (const auto &b : blocks()) { - if (b.type() == EVENT) { + if (b.type() == block_type_t::event) { // This is an event handler. assert(b.event && "Should have an event"); wcstring description = event_get_desc(*b.event); @@ -353,18 +351,19 @@ wcstring parser_t::stack_trace() const { break; } - if (b.type() == FUNCTION_CALL || b.type() == FUNCTION_CALL_NO_SHADOW || - b.type() == SOURCE || b.type() == SUBST) { + if (b.type() == block_type_t::function_call || + b.type() == block_type_t::function_call_no_shadow || b.type() == block_type_t::source || + b.type() == block_type_t::subst) { // These types of blocks should be printed. switch (b.type()) { - case SOURCE: { + case block_type_t::source: { const wchar_t *source_dest = b.sourced_file; append_format(trace, _(L"from sourcing file %ls\n"), user_presentable_path(source_dest).c_str()); break; } - case FUNCTION_CALL: - case FUNCTION_CALL_NO_SHADOW: { + case block_type_t::function_call: + case block_type_t::function_call_no_shadow: { append_format(trace, _(L"in function '%ls'"), b.function_name.c_str()); // Print arguments on the same line. wcstring args_str; @@ -385,7 +384,7 @@ wcstring parser_t::stack_trace() const { trace.push_back('\n'); break; } - case SUBST: { + case block_type_t::subst: { append_format(trace, _(L"in command substitution\n")); break; } @@ -422,9 +421,9 @@ const wchar_t *parser_t::is_function(size_t idx) const { for (size_t block_idx = idx; block_idx < block_list.size(); block_idx++) { const block_t &b = block_list[block_idx]; - if (b.is_function()) { + if (b.is_function_call()) { return b.function_name.c_str(); - } else if (b.type() == SOURCE) { + } else if (b.type() == block_type_t::source) { // If a function sources a file, obviously that function's offset doesn't // contribute. break; @@ -442,9 +441,9 @@ const wchar_t *parser_t::get_function_name(int level) { // Walk until we find a breakpoint, then take the next function. bool found_breakpoint = false; for (const auto &b : block_list) { - if (b.type() == BREAKPOINT) { + if (b.type() == block_type_t::breakpoint) { found_breakpoint = true; - } else if (found_breakpoint && b.is_function()) { + } else if (found_breakpoint && b.is_function_call()) { return b.function_name.c_str(); } } @@ -457,7 +456,7 @@ const wchar_t *parser_t::get_function_name(int level) { // Level 1 is the topmost function call. Level 2 is its caller. Etc. int funcs_seen = 0; for (const auto &b : block_list) { - if (b.is_function()) { + if (b.is_function_call()) { funcs_seen++; if (funcs_seen == level) { return b.function_name.c_str(); @@ -479,9 +478,9 @@ const wchar_t *parser_t::current_filename() const { ASSERT_IS_MAIN_THREAD(); for (const auto &b : block_list) { - if (b.is_function()) { + if (b.is_function_call()) { return function_get_definition_file(b.function_name); - } else if (b.type() == SOURCE) { + } else if (b.type() == block_type_t::source) { return b.sourced_file; } } @@ -499,7 +498,7 @@ bool parser_t::function_stack_is_overflowing() const { // Count the functions. int depth = 0; for (const auto &b : block_list) { - depth += b.is_function(); + depth += b.is_function_call(); } return depth > FISH_MAX_STACK_DEPTH; } @@ -620,7 +619,7 @@ eval_result_t parser_t::eval(const wcstring &cmd, const io_chain_t &io, eval_result_t parser_t::eval(parsed_source_ref_t ps, const io_chain_t &io, enum block_type_t block_type) { - assert(block_type == TOP || block_type == SUBST); + assert(block_type == block_type_t::top || block_type == block_type_t::subst); if (!ps->tree.empty()) { job_lineage_t lineage; lineage.block_io = io; @@ -648,7 +647,8 @@ eval_result_t parser_t::eval_node(parsed_source_ref_t ps, tnode_t node, block } // Only certain blocks are allowed. - assert((block_type == TOP || block_type == SUBST) && "Invalid block type"); + assert((block_type == block_type_t::top || block_type == block_type_t::subst) && + "Invalid block type"); job_reap(*this, false); // not sure why we reap jobs here @@ -728,55 +728,55 @@ block_t::~block_t() = default; wcstring block_t::description() const { wcstring result; switch (this->type()) { - case WHILE: { + case block_type_t::while_block: { result.append(L"while"); break; } - case FOR: { + case block_type_t::for_block: { result.append(L"for"); break; } - case IF: { + case block_type_t::if_block: { result.append(L"if"); break; } - case FUNCTION_CALL: { + case block_type_t::function_call: { result.append(L"function_call"); break; } - case FUNCTION_CALL_NO_SHADOW: { + case block_type_t::function_call_no_shadow: { result.append(L"function_call_no_shadow"); break; } - case SWITCH: { + case block_type_t::switch_block: { result.append(L"switch"); break; } - case SUBST: { + case block_type_t::subst: { result.append(L"substitution"); break; } - case TOP: { + case block_type_t::top: { result.append(L"top"); break; } - case BEGIN: { + case block_type_t::begin: { result.append(L"begin"); break; } - case SOURCE: { + case block_type_t::source: { result.append(L"source"); break; } - case EVENT: { + case block_type_t::event: { result.append(L"event"); break; } - case BREAKPOINT: { + case block_type_t::breakpoint: { result.append(L"breakpoint"); break; } - case VARIABLE_ASSIGNMENT: { + case block_type_t::variable_assignment: { result.append(L"variable_assignment"); break; } @@ -793,33 +793,35 @@ wcstring block_t::description() const { // Various block constructors. -block_t block_t::if_block() { return block_t(IF); } +block_t block_t::if_block() { return block_t(block_type_t::if_block); } block_t block_t::event_block(event_t evt) { - block_t b{EVENT}; + block_t b{block_type_t::event}; b.event = std::move(evt); return b; } block_t block_t::function_block(wcstring name, wcstring_list_t args, bool shadows) { - block_t b{shadows ? FUNCTION_CALL : FUNCTION_CALL_NO_SHADOW}; + block_t b{shadows ? block_type_t::function_call : block_type_t::function_call_no_shadow}; b.function_name = std::move(name); b.function_args = std::move(args); return b; } block_t block_t::source_block(const wchar_t *src) { - block_t b{SOURCE}; + block_t b{block_type_t::source}; b.sourced_file = src; return b; } -block_t block_t::for_block() { return block_t{FOR}; } -block_t block_t::while_block() { return block_t{WHILE}; } -block_t block_t::switch_block() { return block_t{SWITCH}; } +block_t block_t::for_block() { return block_t{block_type_t::for_block}; } +block_t block_t::while_block() { return block_t{block_type_t::while_block}; } +block_t block_t::switch_block() { return block_t{block_type_t::switch_block}; } block_t block_t::scope_block(block_type_t type) { - assert((type == BEGIN || type == TOP || type == SUBST) && "Invalid scope type"); + assert( + (type == block_type_t::begin || type == block_type_t::top || type == block_type_t::subst) && + "Invalid scope type"); return block_t(type); } -block_t block_t::breakpoint_block() { return block_t(BREAKPOINT); } -block_t block_t::variable_assignment_block() { return block_t(VARIABLE_ASSIGNMENT); } +block_t block_t::breakpoint_block() { return block_t(block_type_t::breakpoint); } +block_t block_t::variable_assignment_block() { return block_t(block_type_t::variable_assignment); } diff --git a/src/parser.h b/src/parser.h index 41fdb8999..697f520d6 100644 --- a/src/parser.h +++ b/src/parser.h @@ -31,20 +31,20 @@ inline bool event_block_list_blocks_type(const event_blockage_list_t &ebls) { } /// Types of blocks. -enum block_type_t { - WHILE, /// While loop block - FOR, /// For loop block - IF, /// If block - FUNCTION_CALL, /// Function invocation block - FUNCTION_CALL_NO_SHADOW, /// Function invocation block with no variable shadowing - SWITCH, /// Switch block - SUBST, /// Command substitution scope - TOP, /// Outermost block - BEGIN, /// Unconditional block - SOURCE, /// Block created by the . (source) builtin - EVENT, /// Block created on event notifier invocation - BREAKPOINT, /// Breakpoint block - VARIABLE_ASSIGNMENT, /// Variable assignment before a command +enum class block_type_t { + while_block, /// While loop block + for_block, /// For loop block + if_block, /// If block + function_call, /// Function invocation block + function_call_no_shadow, /// Function invocation block with no variable shadowing + switch_block, /// Switch block + subst, /// Command substitution scope + top, /// Outermost block + begin, /// Unconditional block + source, /// Block created by the . (source) builtin + event, /// Block created on event notifier invocation + breakpoint, /// Breakpoint block + variable_assignment, /// Variable assignment before a command }; /// Possible states for a loop. @@ -91,8 +91,9 @@ class block_t { wcstring description() const; /// \return if we are a function call (with or without shadowing). - bool is_function() const { - return type() == FUNCTION_CALL || type() == FUNCTION_CALL_NO_SHADOW; + bool is_function_call() const { + return type() == block_type_t::function_call || + type() == block_type_t::function_call_no_shadow; } /// Entry points for creating blocks. @@ -329,7 +330,7 @@ class parser_t : public std::enable_shared_from_this { void pop_block(const block_t *expected); /// Return a description of the given blocktype. - const wchar_t *get_block_desc(int block) const; + static const wchar_t *get_block_desc(block_type_t block); /// Return the function name for the specified stack frame. Default is one (current frame). const wchar_t *get_function_name(int level = 1); diff --git a/src/reader.cpp b/src/reader.cpp index 517c94d13..6a857aa9b 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -1952,7 +1952,7 @@ void reader_run_command(parser_t &parser, const wcstring &cmd) { gettimeofday(&time_before, nullptr); - parser.eval(cmd, io_chain_t(), TOP); + parser.eval(cmd, io_chain_t(), block_type_t::top); job_reap(parser, true); gettimeofday(&time_after, nullptr); @@ -2205,7 +2205,7 @@ void reader_bg_job_warning(const parser_t &parser) { static void handle_end_loop(const parser_t &parser) { if (!reader_exit_forced()) { for (const auto &b : parser.blocks()) { - if (b.type() == BREAKPOINT) { + if (b.type() == block_type_t::breakpoint) { // We're executing within a breakpoint so we do not want to terminate the shell and // kill background jobs. return; @@ -3551,7 +3551,7 @@ static int read_ni(parser_t &parser, int fd, const io_chain_t &io) { parsed_source_ref_t pstree; if (!parse_util_detect_errors(str, &errors, false /* do not accept incomplete */, &pstree)) { - parser.eval(pstree, io, TOP); + parser.eval(pstree, io, block_type_t::top); } else { wcstring sb; parser.get_backtrace(str, errors, sb);