mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 21:44:16 +00:00
Migrate the global exec_count into the parser
This commit is contained in:
parent
fe68287cb0
commit
b0a695e9fa
4 changed files with 18 additions and 21 deletions
|
@ -24,13 +24,13 @@ int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||||
new_cmd += argv[i];
|
new_cmd += argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cached_exec_count = exec_get_exec_count();
|
const auto cached_exec_count = parser.libdata().exec_count;
|
||||||
int status = STATUS_CMD_OK;
|
int status = STATUS_CMD_OK;
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::TOP) != 0) {
|
if (parser.eval(std::move(new_cmd), *streams.io_chain, block_type_t::TOP) != 0) {
|
||||||
// This indicates a parse error; nothing actually got executed.
|
// This indicates a parse error; nothing actually got executed.
|
||||||
status = STATUS_CMD_ERROR;
|
status = STATUS_CMD_ERROR;
|
||||||
} else if (cached_exec_count == exec_get_exec_count()) {
|
} else if (cached_exec_count == parser.libdata().exec_count) {
|
||||||
// Issue #5692, in particular, to catch `eval ""`, `eval "begin; end;"`, etc.
|
// Issue #5692, in particular, to catch `eval ""`, `eval "begin; end;"`, etc.
|
||||||
// where we have an argument but nothing is executed.
|
// where we have an argument but nothing is executed.
|
||||||
status = STATUS_CMD_OK;
|
status = STATUS_CMD_OK;
|
||||||
|
|
15
src/exec.cpp
15
src/exec.cpp
|
@ -864,14 +864,6 @@ static bool exec_block_or_func_process(parser_t &parser, std::shared_ptr<job_t>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The number of overall "command" executions, for whatever definition of "command". Its delta
|
|
||||||
// is used to determine the number of recursive `exec_process_in_job()` invocations.
|
|
||||||
static size_t exec_count = 0;
|
|
||||||
|
|
||||||
size_t exec_get_exec_count() {
|
|
||||||
return exec_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes a process \p in job \j, using the pipes \p pipes (which may have invalid fds if this is
|
/// Executes a process \p in job \j, using the pipes \p pipes (which may have invalid fds if this is
|
||||||
/// the first or last process).
|
/// the first or last process).
|
||||||
/// \p deferred_pipes represents the pipes from our deferred process; if set ensure they get closed
|
/// \p deferred_pipes represents the pipes from our deferred process; if set ensure they get closed
|
||||||
|
@ -936,7 +928,7 @@ static bool exec_process_in_job(parser_t &parser, process_t *p, std::shared_ptr<
|
||||||
|
|
||||||
if (p->type != process_type_t::block_node) {
|
if (p->type != process_type_t::block_node) {
|
||||||
// An simple `begin ... end` should not be considered an execution of a command.
|
// An simple `begin ... end` should not be considered an execution of a command.
|
||||||
exec_count++;
|
parser.libdata().exec_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the process.
|
// Execute the process.
|
||||||
|
@ -947,7 +939,7 @@ static bool exec_process_in_job(parser_t &parser, process_t *p, std::shared_ptr<
|
||||||
// Allow buffering unless this is a deferred run. If deferred, then processes after us
|
// Allow buffering unless this is a deferred run. If deferred, then processes after us
|
||||||
// were already launched, so they are ready to receive (or reject) our output.
|
// were already launched, so they are ready to receive (or reject) our output.
|
||||||
bool allow_buffering = !is_deferred_run;
|
bool allow_buffering = !is_deferred_run;
|
||||||
auto cached_exec_count = exec_count;
|
auto cached_exec_count = parser.libdata().exec_count;
|
||||||
if (!exec_block_or_func_process(parser, j, p, all_ios, process_net_io_chain,
|
if (!exec_block_or_func_process(parser, j, p, all_ios, process_net_io_chain,
|
||||||
allow_buffering)) {
|
allow_buffering)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -956,7 +948,8 @@ static bool exec_process_in_job(parser_t &parser, process_t *p, std::shared_ptr<
|
||||||
// Functions are basically treated as named blocks, and this is the only place we can
|
// Functions are basically treated as named blocks, and this is the only place we can
|
||||||
// distinguish between them. A block by default does not touch $status, on the other
|
// distinguish between them. A block by default does not touch $status, on the other
|
||||||
// hand, calling an empty function should clear $status.
|
// hand, calling an empty function should clear $status.
|
||||||
if (exec_count == cached_exec_count && p->type == process_type_t::function) {
|
if (parser.libdata().exec_count == cached_exec_count &&
|
||||||
|
p->type == process_type_t::function) {
|
||||||
p->status = proc_status_t::from_exit_code(0);
|
p->status = proc_status_t::from_exit_code(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,6 @@ int exec_subshell(const wcstring &cmd, parser_t &parser, bool preserve_exit_stat
|
||||||
/// Loops over close until the syscall was run without being interrupted.
|
/// Loops over close until the syscall was run without being interrupted.
|
||||||
void exec_close(int fd);
|
void exec_close(int fd);
|
||||||
|
|
||||||
/// Returns the number of executions. May roll over.
|
|
||||||
size_t exec_get_exec_count();
|
|
||||||
|
|
||||||
/// Gets the interpreter for a given command.
|
/// Gets the interpreter for a given command.
|
||||||
char *get_interpreter(const char *command, char *interpreter, size_t buff_size);
|
char *get_interpreter(const char *command, char *interpreter, size_t buff_size);
|
||||||
|
|
||||||
|
|
17
src/parser.h
17
src/parser.h
|
@ -147,6 +147,12 @@ struct profile_item_t {
|
||||||
class parse_execution_context_t;
|
class parse_execution_context_t;
|
||||||
class completion_t;
|
class completion_t;
|
||||||
|
|
||||||
|
/// Miscelleneous data used to avoid recursion and others.
|
||||||
|
struct library_data_t {
|
||||||
|
/// A counter incremented every time a command executes.
|
||||||
|
uint64_t exec_count{0};
|
||||||
|
};
|
||||||
|
|
||||||
class parser_t : public std::enable_shared_from_this<parser_t> {
|
class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
friend class parse_execution_context_t;
|
friend class parse_execution_context_t;
|
||||||
|
|
||||||
|
@ -165,11 +171,8 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
int eval_level = -1;
|
int eval_level = -1;
|
||||||
/// Set of variables for the parser.
|
/// Set of variables for the parser.
|
||||||
env_stack_t &variables;
|
env_stack_t &variables;
|
||||||
#if 0
|
/// Miscellaneous library data.
|
||||||
// TODO: Lint says this isn't used (which is true). Should this be removed?
|
library_data_t library_data{};
|
||||||
/// Gets a description of the block stack, for debugging.
|
|
||||||
wcstring block_stack_description() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// List of profile items
|
/// List of profile items
|
||||||
/// These are pointers because we return pointers to them to callers,
|
/// These are pointers because we return pointers to them to callers,
|
||||||
|
@ -269,6 +272,10 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
env_stack_t &vars() { return variables; }
|
env_stack_t &vars() { return variables; }
|
||||||
const env_stack_t &vars() const { return variables; }
|
const env_stack_t &vars() const { return variables; }
|
||||||
|
|
||||||
|
/// Get the library data.
|
||||||
|
library_data_t &libdata() { return library_data; }
|
||||||
|
const library_data_t &libdata() const { return library_data; }
|
||||||
|
|
||||||
/// Pushes a new block created with the given arguments
|
/// Pushes a new block created with the given arguments
|
||||||
/// Returns a pointer to the block. The pointer is valid
|
/// Returns a pointer to the block. The pointer is valid
|
||||||
/// until the call to pop_block()
|
/// until the call to pop_block()
|
||||||
|
|
Loading…
Reference in a new issue