From 8dd2d4f15d879484a1364d661e6526a9ec42c053 Mon Sep 17 00:00:00 2001 From: Soumya Date: Sat, 18 Jul 2020 10:25:43 -0700 Subject: [PATCH] Change builtins to return maybe_t instead of int --- src/builtin.cpp | 23 +++++++++++++---------- src/builtin.h | 2 +- src/builtin_argparse.cpp | 2 +- src/builtin_argparse.h | 4 +++- src/builtin_bg.cpp | 2 +- src/builtin_bg.h | 4 +++- src/builtin_bind.cpp | 2 +- src/builtin_bind.h | 4 ++-- src/builtin_block.cpp | 2 +- src/builtin_block.h | 4 +++- src/builtin_builtin.cpp | 2 +- src/builtin_builtin.h | 4 +++- src/builtin_cd.cpp | 2 +- src/builtin_cd.h | 4 +++- src/builtin_command.cpp | 2 +- src/builtin_command.h | 4 +++- src/builtin_commandline.cpp | 2 +- src/builtin_commandline.h | 2 +- src/builtin_complete.cpp | 2 +- src/builtin_complete.h | 2 +- src/builtin_contains.cpp | 2 +- src/builtin_contains.h | 4 +++- src/builtin_disown.cpp | 2 +- src/builtin_disown.h | 4 +++- src/builtin_echo.cpp | 2 +- src/builtin_echo.h | 4 +++- src/builtin_emit.cpp | 2 +- src/builtin_emit.h | 4 +++- src/builtin_eval.cpp | 2 +- src/builtin_eval.h | 4 +++- src/builtin_exit.cpp | 2 +- src/builtin_exit.h | 4 +++- src/builtin_fg.cpp | 2 +- src/builtin_fg.h | 4 +++- src/builtin_function.cpp | 2 +- src/builtin_function.h | 2 +- src/builtin_functions.cpp | 2 +- src/builtin_functions.h | 4 +++- src/builtin_history.cpp | 2 +- src/builtin_history.h | 4 +++- src/builtin_jobs.cpp | 2 +- src/builtin_jobs.h | 2 +- src/builtin_math.cpp | 2 +- src/builtin_math.h | 4 +++- src/builtin_printf.cpp | 2 +- src/builtin_printf.h | 2 +- src/builtin_pwd.cpp | 2 +- src/builtin_pwd.h | 4 +++- src/builtin_random.cpp | 2 +- src/builtin_random.h | 4 +++- src/builtin_read.cpp | 2 +- src/builtin_read.h | 4 +++- src/builtin_realpath.cpp | 2 +- src/builtin_realpath.h | 4 +++- src/builtin_return.cpp | 2 +- src/builtin_return.h | 4 +++- src/builtin_set.cpp | 2 +- src/builtin_set.h | 2 +- src/builtin_set_color.cpp | 2 +- src/builtin_set_color.h | 2 +- src/builtin_source.cpp | 2 +- src/builtin_source.h | 4 +++- src/builtin_status.cpp | 2 +- src/builtin_status.h | 4 +++- src/builtin_string.cpp | 2 +- src/builtin_string.h | 2 +- src/builtin_test.cpp | 2 +- src/builtin_test.h | 4 +++- src/builtin_ulimit.cpp | 2 +- src/builtin_ulimit.h | 2 +- src/builtin_wait.cpp | 2 +- src/builtin_wait.h | 4 +++- src/exec.cpp | 6 +++++- src/fish_tests.cpp | 20 ++++++++++++-------- src/maybe.h | 1 + src/parse_execution.cpp | 12 ++++++++---- src/proc.cpp | 24 ++++++++++++++++++++---- src/proc.h | 18 ++++++++++++++++-- 78 files changed, 197 insertions(+), 101 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index af5388ab4..14641071d 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -4,7 +4,7 @@ // // 1). Create a function in builtin.c with the following signature: // -// static int builtin_NAME(parser_t &parser, io_streams_t &streams, wchar_t **argv) +// static maybe_t builtin_NAME(parser_t &parser, io_streams_t &streams, wchar_t **argv) // // where NAME is the name of the builtin, and args is a zero-terminated list of arguments. // @@ -201,7 +201,7 @@ void builtin_print_error_trailer(parser_t &parser, output_stream_t &b, const wch /// A generic bultin that only supports showing a help message. This is only a placeholder that /// prints the help message. Useful for commands that live in the parser. -static int builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +static maybe_t builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; @@ -228,7 +228,7 @@ static int builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **ar // Since this is just for counting, it can be massive. #define COUNT_CHUNK_SIZE (512 * 256) /// Implementation of the builtin count command, used to count the number of arguments sent to it. -static int builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +static maybe_t builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); int argc = 0; @@ -256,7 +256,7 @@ static int builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv /// This function handles both the 'continue' and the 'break' builtins that are used for loop /// control. -static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +static maybe_t builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int is_break = (std::wcscmp(argv[0], L"break") == 0); int argc = builtin_count_args(argv); @@ -287,7 +287,7 @@ static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar } /// Implementation of the builtin breakpoint command, used to launch the interactive debugger. -static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +static maybe_t builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; if (argv[1] != nullptr) { streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, cmd, 0, builtin_count_args(argv) - 1); @@ -313,21 +313,21 @@ static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t * return parser.get_last_status(); } -int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); UNUSED(streams); UNUSED(argv); return STATUS_CMD_OK; } -int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); UNUSED(streams); UNUSED(argv); return STATUS_CMD_ERROR; } -int builtin_gettext(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_gettext(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); UNUSED(streams); for (int i = 1; i < builtin_count_args(argv); i++) { @@ -459,8 +459,11 @@ proc_status_t builtin_run(parser_t &parser, wchar_t **argv, io_streams_t &stream } if (const builtin_data_t *data = builtin_lookup(argv[0])) { - int ret = data->func(parser, streams, argv); - return proc_status_t::from_exit_code(ret); + maybe_t ret = data->func(parser, streams, argv); + if (!ret) { + return proc_status_t::empty(); + } + return proc_status_t::from_exit_code(ret.value()); } FLOGF(error, UNKNOWN_BUILTIN_ERR_MSG, argv[0]); diff --git a/src/builtin.h b/src/builtin.h index 1629c4a79..88e01769a 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -20,7 +20,7 @@ struct builtin_data_t { // Name of the builtin. const wchar_t *name; // Function pointer to the builtin implementation. - int (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv); + maybe_t (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv); // Description of what the builtin does. const wchar_t *desc; diff --git a/src/builtin_argparse.cpp b/src/builtin_argparse.cpp index bde552ef1..76f73dc3c 100644 --- a/src/builtin_argparse.cpp +++ b/src/builtin_argparse.cpp @@ -684,7 +684,7 @@ static void set_argparse_result_vars(env_stack_t &vars, const argparse_cmd_opts_ /// an external command also means its output has to be in a form that can be eval'd. Because our /// version is a builtin it can directly set variables local to the current scope (e.g., a /// function). It doesn't need to write anything to stdout that then needs to be eval'd. -int builtin_argparse(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_argparse(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); argparse_cmd_opts_t opts; diff --git a/src/builtin_argparse.h b/src/builtin_argparse.h index b515e0bce..24e4b6079 100644 --- a/src/builtin_argparse.h +++ b/src/builtin_argparse.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_ARGPARSE_H #define FISH_BUILTIN_ARGPARSE_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_argparse(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_argparse(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_bg.cpp b/src/builtin_bg.cpp index 64b0ec5c8..798d72511 100644 --- a/src/builtin_bg.cpp +++ b/src/builtin_bg.cpp @@ -37,7 +37,7 @@ static int send_to_bg(parser_t &parser, io_streams_t &streams, job_t *j) { } /// Builtin for putting a job in the background. -int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_bg.h b/src/builtin_bg.h index 3fcb3d0c0..bb628a433 100644 --- a/src/builtin_bg.h +++ b/src/builtin_bg.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_BG_H #define FISH_BUILTIN_BG_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_bind.cpp b/src/builtin_bind.cpp index 3c7c088e1..f497f8a68 100644 --- a/src/builtin_bind.cpp +++ b/src/builtin_bind.cpp @@ -413,7 +413,7 @@ int parse_cmd_opts(bind_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss meth } /// The bind builtin, used for setting character sequences. -int builtin_bind_t::builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_bind_t::builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); bind_cmd_opts_t opts; diff --git a/src/builtin_bind.h b/src/builtin_bind.h index 769fea782..a6050f93e 100644 --- a/src/builtin_bind.h +++ b/src/builtin_bind.h @@ -11,7 +11,7 @@ struct bind_cmd_opts_t; class builtin_bind_t { public: - int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv); + maybe_t builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv); builtin_bind_t() : input_mappings_(input_mappings()) {} @@ -38,7 +38,7 @@ class builtin_bind_t { io_streams_t &streams); }; -inline int builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +inline maybe_t builtin_bind(parser_t &parser, io_streams_t &streams, wchar_t **argv) { builtin_bind_t bind; return bind.builtin_bind(parser, streams, argv); } diff --git a/src/builtin_block.cpp b/src/builtin_block.cpp index fcf2dd3a2..e2e9b78d8 100644 --- a/src/builtin_block.cpp +++ b/src/builtin_block.cpp @@ -70,7 +70,7 @@ static int parse_cmd_opts(block_cmd_opts_t &opts, int *optind, //!OCLINT(high n } /// The block builtin, used for temporarily blocking events. -int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); block_cmd_opts_t opts; diff --git a/src/builtin_block.h b/src/builtin_block.h index 5399c4fa6..96cf844cf 100644 --- a/src/builtin_block.h +++ b/src/builtin_block.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_BLOCK_H #define FISH_BUILTIN_BLOCK_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_block(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_builtin.cpp b/src/builtin_builtin.cpp index 7e94ee2a1..30d291274 100644 --- a/src/builtin_builtin.cpp +++ b/src/builtin_builtin.cpp @@ -65,7 +65,7 @@ static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, wchar /// The builtin builtin, used for giving builtins precedence over functions. Mostly handled by the /// parser. All this code does is some additional operational modes, such as printing a list of all /// builtins, printing help, etc. -int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); builtin_cmd_opts_t opts; diff --git a/src/builtin_builtin.h b/src/builtin_builtin.h index ac8493447..75e5ccc4c 100644 --- a/src/builtin_builtin.h +++ b/src/builtin_builtin.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_BUILTIN_H #define FISH_BUILTIN_BUILTIN_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_cd.cpp b/src/builtin_cd.cpp index 93d1bd204..a09c05edb 100644 --- a/src/builtin_cd.cpp +++ b/src/builtin_cd.cpp @@ -20,7 +20,7 @@ /// The cd builtin. Changes the current directory to the one specified or to $HOME if none is /// specified. The directory can be relative to any directory in the CDPATH variable. -int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_cd.h b/src/builtin_cd.h index 85aa8cb28..a28a85f4c 100644 --- a/src/builtin_cd.h +++ b/src/builtin_cd.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_CD_H #define FISH_BUILTIN_CD_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_command.cpp b/src/builtin_command.cpp index 6de2347ac..462e33a84 100644 --- a/src/builtin_command.cpp +++ b/src/builtin_command.cpp @@ -73,7 +73,7 @@ static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, wchar /// Implementation of the builtin 'command'. Actual command running is handled by the parser, this /// just processes the flags. -int builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); command_cmd_opts_t opts; diff --git a/src/builtin_command.h b/src/builtin_command.h index 75f5fc1e6..8557bc13d 100644 --- a/src/builtin_command.h +++ b/src/builtin_command.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_COMMAND_H #define FISH_BUILTIN_COMMAND_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_command(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_commandline.cpp b/src/builtin_commandline.cpp index 1ee6fbc93..a4bcf9768 100644 --- a/src/builtin_commandline.cpp +++ b/src/builtin_commandline.cpp @@ -121,7 +121,7 @@ static void write_part(const wchar_t *begin, const wchar_t *end, int cut_at_curs } /// The commandline builtin. It is used for specifying a new value for the commandline. -int builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv) { // Pointer to what the commandline builtin considers to be the current contents of the command // line buffer. const wchar_t *current_buffer = nullptr; diff --git a/src/builtin_commandline.h b/src/builtin_commandline.h index 5237d240f..277056ae5 100644 --- a/src/builtin_commandline.h +++ b/src/builtin_commandline.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_commandline(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_complete.cpp b/src/builtin_complete.cpp index 2d6f9552c..9d70ca550 100644 --- a/src/builtin_complete.cpp +++ b/src/builtin_complete.cpp @@ -110,7 +110,7 @@ static void builtin_complete_remove(const wcstring_list_t &cmds, const wcstring_ /// The complete builtin. Used for specifying programmable tab-completions. Calls the functions in // complete.cpp for any heavy lifting. -int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) { ASSERT_IS_MAIN_THREAD(); wchar_t *cmd = argv[0]; diff --git a/src/builtin_complete.h b/src/builtin_complete.h index f69d98356..c2f3ab31b 100644 --- a/src/builtin_complete.h +++ b/src/builtin_complete.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_contains.cpp b/src/builtin_contains.cpp index 91ddb3c14..389ad0916 100644 --- a/src/builtin_contains.cpp +++ b/src/builtin_contains.cpp @@ -58,7 +58,7 @@ static int parse_cmd_opts(contains_cmd_opts_t &opts, int *optind, int argc, wcha /// Implementation of the builtin contains command, used to check if a specified string is part of /// a list. -int builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); contains_cmd_opts_t opts; diff --git a/src/builtin_contains.h b/src/builtin_contains.h index f331846f1..fca65875c 100644 --- a/src/builtin_contains.h +++ b/src/builtin_contains.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_CONTAINS_H #define FISH_BUILTIN_CONTAINS_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_contains(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_disown.cpp b/src/builtin_disown.cpp index 510044803..cfccefa7a 100644 --- a/src/builtin_disown.cpp +++ b/src/builtin_disown.cpp @@ -42,7 +42,7 @@ static int disown_job(const wchar_t *cmd, parser_t &parser, io_streams_t &stream } /// Builtin for removing jobs from the job list. -int builtin_disown(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_disown(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_disown.h b/src/builtin_disown.h index 4469880e1..d6c836928 100644 --- a/src/builtin_disown.h +++ b/src/builtin_disown.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_DISOWN_H #define FISH_BUILTIN_DISOWN_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_disown(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_disown(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_echo.cpp b/src/builtin_echo.cpp index bac2adf85..9d2c78e71 100644 --- a/src/builtin_echo.cpp +++ b/src/builtin_echo.cpp @@ -180,7 +180,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons /// /// Bash only respects -n if it's the first argument. We'll do the same. We also support a new, /// fish specific, option -s to mean "no spaces". -int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; UNUSED(cmd); int argc = builtin_count_args(argv); diff --git a/src/builtin_echo.h b/src/builtin_echo.h index ecf133700..612e869a7 100644 --- a/src/builtin_echo.h +++ b/src/builtin_echo.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_ECHO_H #define FISH_BUILTIN_ECHO_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_emit.cpp b/src/builtin_emit.cpp index b837b30ab..161d652a0 100644 --- a/src/builtin_emit.cpp +++ b/src/builtin_emit.cpp @@ -11,7 +11,7 @@ #include "wutil.h" // IWYU pragma: keep /// Implementation of the builtin emit command, used to create events. -int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_emit.h b/src/builtin_emit.h index 0bf500002..6ca671d88 100644 --- a/src/builtin_emit.h +++ b/src/builtin_emit.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_EMIT_H #define FISH_BUILTIN_EMIT_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_emit(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_eval.cpp b/src/builtin_eval.cpp index e8da6c7c8..d095cf61b 100644 --- a/src/builtin_eval.cpp +++ b/src/builtin_eval.cpp @@ -15,7 +15,7 @@ #include "wutil.h" // IWYU pragma: keep /// Implementation of eval builtin. -int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int argc = builtin_count_args(argv); if (argc <= 1) { return STATUS_CMD_OK; diff --git a/src/builtin_eval.h b/src/builtin_eval.h index 6cceaacc3..ae67c7da9 100644 --- a/src/builtin_eval.h +++ b/src/builtin_eval.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_EVAL_H #define FISH_BUILTIN_EVAL_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_exit.cpp b/src/builtin_exit.cpp index 8073dee53..51e2dffc4 100644 --- a/src/builtin_exit.cpp +++ b/src/builtin_exit.cpp @@ -58,7 +58,7 @@ static int parse_cmd_opts(exit_cmd_opts_t &opts, int *optind, //!OCLINT(high nc } /// The exit builtin. Calls reader_exit to exit and returns the value specified. -int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); exit_cmd_opts_t opts; diff --git a/src/builtin_exit.h b/src/builtin_exit.h index 1a279ab5f..f446daddf 100644 --- a/src/builtin_exit.h +++ b/src/builtin_exit.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_EXIT_H #define FISH_BUILTIN_EXIT_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_fg.cpp b/src/builtin_fg.cpp index 7bc05f467..1211c27c1 100644 --- a/src/builtin_fg.cpp +++ b/src/builtin_fg.cpp @@ -21,7 +21,7 @@ #include "wutil.h" // IWYU pragma: keep /// Builtin for putting a job in the foreground. -int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_fg.h b/src/builtin_fg.h index 251ce157b..8503f7286 100644 --- a/src/builtin_fg.h +++ b/src/builtin_fg.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_FG_H #define FISH_BUILTIN_FG_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_function.cpp b/src/builtin_function.cpp index 5300b3e07..ef7c329ae 100644 --- a/src/builtin_function.cpp +++ b/src/builtin_function.cpp @@ -199,7 +199,7 @@ static int validate_function_name(int argc, const wchar_t *const *argv, wcstring /// Define a function. Calls into `function.cpp` to perform the heavy lifting of defining a /// function. -int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, +maybe_t builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, const parsed_source_ref_t &source, const ast::block_statement_t &func_node) { assert(source && "Missing source in builtin_function"); // The wgetopt function expects 'function' as the first argument. Make a new wcstring_list with diff --git a/src/builtin_function.h b/src/builtin_function.h index 4da1a378c..e9aae2183 100644 --- a/src/builtin_function.h +++ b/src/builtin_function.h @@ -12,6 +12,6 @@ namespace ast { struct block_statement_t; } -int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, +maybe_t builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, const parsed_source_ref_t &source, const ast::block_statement_t &func_node); #endif diff --git a/src/builtin_functions.cpp b/src/builtin_functions.cpp index 7cf37d9c1..7e08a5415 100644 --- a/src/builtin_functions.cpp +++ b/src/builtin_functions.cpp @@ -282,7 +282,7 @@ static int report_function_metadata(const wchar_t *funcname, bool verbose, io_st } /// The functions builtin, used for listing and erasing functions. -int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); functions_cmd_opts_t opts; diff --git a/src/builtin_functions.h b/src/builtin_functions.h index c7d4b3d6f..1746eaac3 100644 --- a/src/builtin_functions.h +++ b/src/builtin_functions.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_FUNCTIONS_H #define FISH_BUILTIN_FUNCTIONS_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_functions(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_history.cpp b/src/builtin_history.cpp index 0009f58d2..61716a77f 100644 --- a/src/builtin_history.cpp +++ b/src/builtin_history.cpp @@ -200,7 +200,7 @@ static int parse_cmd_opts(history_cmd_opts_t &opts, int *optind, //!OCLINT(high } /// Manipulate history of interactive commands executed by the user. -int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); history_cmd_opts_t opts; diff --git a/src/builtin_history.h b/src/builtin_history.h index 7c27ed932..3aef6aacd 100644 --- a/src/builtin_history.h +++ b/src/builtin_history.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_HISTORY_H #define FISH_BUILTIN_HISTORY_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_jobs.cpp b/src/builtin_jobs.cpp index 9ac98c1bd..8248c3c5f 100644 --- a/src/builtin_jobs.cpp +++ b/src/builtin_jobs.cpp @@ -121,7 +121,7 @@ static void builtin_jobs_print(const job_t *j, int mode, int header, io_streams_ } /// The jobs builtin. Used for printing running jobs. Defined in builtin_jobs.c. -int builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); bool found = false; diff --git a/src/builtin_jobs.h b/src/builtin_jobs.h index adb3cfba0..a92375573 100644 --- a/src/builtin_jobs.h +++ b/src/builtin_jobs.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_math.cpp b/src/builtin_math.cpp index ac0caee6b..84111fb39 100644 --- a/src/builtin_math.cpp +++ b/src/builtin_math.cpp @@ -232,7 +232,7 @@ static int evaluate_expression(const wchar_t *cmd, const parser_t &parser, io_st } /// The math builtin evaluates math expressions. -int builtin_math(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_math(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); math_cmd_opts_t opts; diff --git a/src/builtin_math.h b/src/builtin_math.h index 76d5a5da8..80ef56702 100644 --- a/src/builtin_math.h +++ b/src/builtin_math.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_MATH_H #define FISH_BUILTIN_MATH_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_math(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_math(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_printf.cpp b/src/builtin_printf.cpp index 834fbc178..61cef9fcd 100644 --- a/src/builtin_printf.cpp +++ b/src/builtin_printf.cpp @@ -737,7 +737,7 @@ int builtin_printf_state_t::print_formatted(const wchar_t *format, int argc, wch } /// The printf builtin. -int builtin_printf(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_printf(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_printf.h b/src/builtin_printf.h index 4248d9785..08be3e076 100644 --- a/src/builtin_printf.h +++ b/src/builtin_printf.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_printf(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_printf(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_pwd.cpp b/src/builtin_pwd.cpp index e3619881f..907a04fdf 100644 --- a/src/builtin_pwd.cpp +++ b/src/builtin_pwd.cpp @@ -19,7 +19,7 @@ static const struct woption long_options[] = {{L"help", no_argument, nullptr, 'h {L"logical", no_argument, nullptr, 'L'}, {L"physical", no_argument, nullptr, 'P'}, {nullptr, 0, nullptr, 0}}; -int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); diff --git a/src/builtin_pwd.h b/src/builtin_pwd.h index 431a52ff5..5e7b392fa 100644 --- a/src/builtin_pwd.h +++ b/src/builtin_pwd.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_PWD_H #define FISH_BUILTIN_PWD_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_random.cpp b/src/builtin_random.cpp index 46771c766..88e4c431a 100644 --- a/src/builtin_random.cpp +++ b/src/builtin_random.cpp @@ -27,7 +27,7 @@ static std::minstd_rand get_seeded_engine() { } /// The random builtin generates random numbers. -int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; diff --git a/src/builtin_random.h b/src/builtin_random.h index 878c73f25..80fd5b3f7 100644 --- a/src/builtin_random.h +++ b/src/builtin_random.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_RANDOM_H #define FISH_BUILTIN_RANDOM_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_read.cpp b/src/builtin_read.cpp index b8df208b1..ed6853375 100644 --- a/src/builtin_read.cpp +++ b/src/builtin_read.cpp @@ -431,7 +431,7 @@ static int validate_read_args(const wchar_t *cmd, read_cmd_opts_t &opts, int arg } /// The read builtin. Reads from stdin and stores the values in environment variables. -int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); wcstring buff; diff --git a/src/builtin_read.h b/src/builtin_read.h index c65fe5bfa..f1fdccdee 100644 --- a/src/builtin_read.h +++ b/src/builtin_read.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_READ_H #define FISH_BUILTIN_READ_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_realpath.cpp b/src/builtin_realpath.cpp index 09858ee9d..1264545c8 100644 --- a/src/builtin_realpath.cpp +++ b/src/builtin_realpath.cpp @@ -17,7 +17,7 @@ /// An implementation of the external realpath command. Doesn't support any options. /// In general scripts shouldn't invoke this directly. They should just use `realpath` which /// will fallback to this builtin if an external command cannot be found. -int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; help_only_cmd_opts_t opts; int argc = builtin_count_args(argv); diff --git a/src/builtin_realpath.h b/src/builtin_realpath.h index 1fa7d16ad..2022e9d29 100644 --- a/src/builtin_realpath.h +++ b/src/builtin_realpath.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_REALPATH_H #define FISH_BUILTIN_REALPATH_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_return.cpp b/src/builtin_return.cpp index 8c0fb302b..2c384b23b 100644 --- a/src/builtin_return.cpp +++ b/src/builtin_return.cpp @@ -57,7 +57,7 @@ static int parse_cmd_opts(return_cmd_opts_t &opts, int *optind, //!OCLINT(high } /// Function for handling the return builtin. -int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); return_cmd_opts_t opts; diff --git a/src/builtin_return.h b/src/builtin_return.h index 81a3e4736..401ed6ec0 100644 --- a/src/builtin_return.h +++ b/src/builtin_return.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_RETURN_H #define FISH_BUILTIN_RETURN_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_return(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_set.cpp b/src/builtin_set.cpp index 5b30cc43a..06d04852e 100644 --- a/src/builtin_set.cpp +++ b/src/builtin_set.cpp @@ -804,7 +804,7 @@ static int builtin_set_set(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, w } /// The set builtin creates, updates, and erases (removes, deletes) variables. -int builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const int incoming_exit_status = parser.get_last_status(); wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); diff --git a/src/builtin_set.h b/src/builtin_set.h index ffd517da3..04c4877cd 100644 --- a/src/builtin_set.h +++ b/src/builtin_set.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_set(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_set_color.cpp b/src/builtin_set_color.cpp index 7320dfdcc..5d6ee22d1 100644 --- a/src/builtin_set_color.cpp +++ b/src/builtin_set_color.cpp @@ -67,7 +67,7 @@ static char dim_esc[] = "\x1B[2m"; #endif /// set_color builtin. -int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) { // By the time this is called we should have initialized the curses subsystem. assert(curses_initialized); diff --git a/src/builtin_set_color.h b/src/builtin_set_color.h index 87ae3e37f..06be7db91 100644 --- a/src/builtin_set_color.h +++ b/src/builtin_set_color.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_source.cpp b/src/builtin_source.cpp index 633487e90..be3ada8e7 100644 --- a/src/builtin_source.cpp +++ b/src/builtin_source.cpp @@ -22,7 +22,7 @@ /// The source builtin, sometimes called `.`. Evaluates the contents of a file in the current /// context. -int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv) { ASSERT_IS_MAIN_THREAD(); const wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); diff --git a/src/builtin_source.h b/src/builtin_source.h index 4aaf1259e..e292727da 100644 --- a/src/builtin_source.h +++ b/src/builtin_source.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_SOURCE_H #define FISH_BUILTIN_SOURCE_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_status.cpp b/src/builtin_status.cpp index 8b2cee5e3..58fbe9230 100644 --- a/src/builtin_status.cpp +++ b/src/builtin_status.cpp @@ -274,7 +274,7 @@ static int parse_cmd_opts(status_cmd_opts_t &opts, int *optind, //!OCLINT(high } /// The status builtin. Gives various status information on fish. -int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); status_cmd_opts_t opts; diff --git a/src/builtin_status.h b/src/builtin_status.h index bf5eea440..01855e120 100644 --- a/src/builtin_status.h +++ b/src/builtin_status.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_STATUS_H #define FISH_BUILTIN_STATUS_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index e4b3c9a44..429676f79 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -1451,7 +1451,7 @@ string_subcommands[] = { {nullptr, nullptr}}; /// The string builtin, for manipulating strings. -int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); if (argc <= 1) { diff --git a/src/builtin_string.h b/src/builtin_string.h index ce139a6f0..47c5e1227 100644 --- a/src/builtin_string.h +++ b/src/builtin_string.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_test.cpp b/src/builtin_test.cpp index b6851ebf5..717e9817f 100644 --- a/src/builtin_test.cpp +++ b/src/builtin_test.cpp @@ -845,7 +845,7 @@ static bool unary_primary_evaluate(test_expressions::token_t token, const wcstri /// supports a more limited range of functionality. /// /// Return status is the final shell status, i.e. 0 for true, 1 for false and 2 for error. -int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); using namespace test_expressions; diff --git a/src/builtin_test.h b/src/builtin_test.h index b350cc639..8b8935e86 100644 --- a/src/builtin_test.h +++ b/src/builtin_test.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_TEST_H #define FISH_BUILTIN_TEST_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_ulimit.cpp b/src/builtin_ulimit.cpp index df9621538..72b114cfe 100644 --- a/src/builtin_ulimit.cpp +++ b/src/builtin_ulimit.cpp @@ -149,7 +149,7 @@ static int set_limit(int resource, int hard, int soft, rlim_t value, io_streams_ } /// The ulimit builtin, used for setting resource limits. -int builtin_ulimit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_ulimit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; int argc = builtin_count_args(argv); bool report_all = false; diff --git a/src/builtin_ulimit.h b/src/builtin_ulimit.h index 19c9348e5..1d64c39e4 100644 --- a/src/builtin_ulimit.h +++ b/src/builtin_ulimit.h @@ -7,5 +7,5 @@ class parser_t; -int builtin_ulimit(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_ulimit(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/builtin_wait.cpp b/src/builtin_wait.cpp index 06dc575d8..0d60c42a4 100644 --- a/src/builtin_wait.cpp +++ b/src/builtin_wait.cpp @@ -172,7 +172,7 @@ static bool find_job_by_name(const wchar_t *proc, std::vector &ids, /// The following function is invoked on the main thread, because the job operation is not thread /// safe. It waits for child jobs, not for child processes individually. -int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) { +maybe_t builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) { ASSERT_IS_MAIN_THREAD(); int retval = STATUS_CMD_OK; const wchar_t *cmd = argv[0]; diff --git a/src/builtin_wait.h b/src/builtin_wait.h index d0444c34b..a9945325b 100644 --- a/src/builtin_wait.h +++ b/src/builtin_wait.h @@ -2,8 +2,10 @@ #ifndef FISH_BUILTIN_WAIT_H #define FISH_BUILTIN_WAIT_H +#include "maybe.h" + class parser_t; struct io_streams_t; -int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv); #endif diff --git a/src/exec.cpp b/src/exec.cpp index be05303d0..0202fa64c 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -289,7 +289,11 @@ static void run_internal_process_or_short_circuit(parser_t &parser, const std::s if (p->is_last_in_job) { FLOGF(exec_job_status, L"Set status of job %d (%ls) to %d using short circuit", j->job_id(), j->preview().c_str(), p->status); - parser.set_last_statuses(j->get_statuses()); + auto statuses = j->get_statuses(); + if (statuses) { + parser.set_last_statuses(statuses.value()); + parser.libdata().status_count++; + } } } else { run_internal_process(p, std::move(outdata), std::move(errdata), ios); diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 8ea642865..0f1b58293 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -2519,7 +2519,7 @@ static void test_is_potential_path() { } /// Test the 'test' builtin. -int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv); static bool run_one_test_test(int expected, wcstring_list_t &lst, bool bracket) { parser_t &parser = parser_t::principal_parser(); size_t i, count = lst.size(); @@ -2535,13 +2535,16 @@ static bool run_one_test_test(int expected, wcstring_list_t &lst, bool bracket) argv[i + 1] = NULL; null_output_stream_t null{}; io_streams_t streams(null, null); - int result = builtin_test(parser, streams, argv); + maybe_t result = builtin_test(parser, streams, argv); - if (expected != result) err(L"expected builtin_test() to return %d, got %d", expected, result); + if (result != expected) { + std::wstring got = result ? std::to_wstring(result.value()) : L"nothing"; + err(L"expected builtin_test() to return %d, got %s", expected, got.c_str()); + } delete[] argv; - return expected == result; + return result == expected; } static bool run_test_test(int expected, const wcstring &str) { @@ -5098,7 +5101,7 @@ static void test_pcre2_escape() { } } -int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv); +maybe_t builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv); static void run_one_string_test(const wchar_t *const *argv, int expected_rc, const wchar_t *expected_out) { parser_t &parser = parser_t::principal_parser(); @@ -5106,15 +5109,16 @@ static void run_one_string_test(const wchar_t *const *argv, int expected_rc, null_output_stream_t errs{}; io_streams_t streams(outs, errs); streams.stdin_is_directly_redirected = false; // read from argv instead of stdin - int rc = builtin_string(parser, streams, const_cast(argv)); + maybe_t rc = builtin_string(parser, streams, const_cast(argv)); wcstring args; for (int i = 0; argv[i] != NULL; i++) { args += escape_string(argv[i], ESCAPE_ALL) + L' '; } args.resize(args.size() - 1); if (rc != expected_rc) { - err(L"Test failed on line %lu: [%ls]: expected return code %d but got %d", __LINE__, - args.c_str(), expected_rc, rc); + std::wstring got = rc ? std::to_wstring(rc.value()) : L"nothing"; + err(L"Test failed on line %lu: [%ls]: expected return code %d but got %s", __LINE__, + args.c_str(), expected_rc, got.c_str()); } else if (outs.contents() != expected_out) { err(L"Test failed on line %lu: [%ls]: expected [%ls] but got [%ls]", __LINE__, args.c_str(), escape_string(expected_out, ESCAPE_ALL).c_str(), diff --git a/src/maybe.h b/src/maybe.h index 4f0a78800..42fe8ac3e 100644 --- a/src/maybe.h +++ b/src/maybe.h @@ -3,6 +3,7 @@ #include #include +#include namespace maybe_detail { // Template magic to make maybe_t copyable iff T is copyable. diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index eee1fc14e..ca62ed52d 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -392,13 +392,17 @@ end_execution_reason_t parse_execution_context_t::run_function_statement( buffered_output_stream_t outs(0); buffered_output_stream_t errs(0); io_streams_t streams(outs, errs); - int err = builtin_function(*parser, streams, arguments, pstree, statement); - parser->libdata().status_count++; - parser->set_last_statuses(statuses_t::just(err)); + int err_code = 0; + maybe_t err = builtin_function(*parser, streams, arguments, pstree, statement); + if (err) { + err_code = err.value(); + parser->libdata().status_count++; + parser->set_last_statuses(statuses_t::just(err_code)); + } wcstring errtext = errs.contents(); if (!errtext.empty()) { - return this->report_error(err, header, L"%ls", errtext.c_str()); + return this->report_error(err_code, header, L"%ls", errtext.c_str()); } return result; } diff --git a/src/proc.cpp b/src/proc.cpp index 150f0dddd..06e46b511 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -167,17 +167,30 @@ bool job_t::signal(int signal) { return true; } -statuses_t job_t::get_statuses() const { +maybe_t job_t::get_statuses() const { statuses_t st{}; + bool has_status = false; + int laststatus = 0; st.pipestatus.reserve(processes.size()); for (const auto &p : processes) { auto status = p->status; + if (status.is_empty()) { + // Corner case for if a variable assignment is part of a pipeline. + // e.g. `false | set foo bar | true` will push 1 in the second spot, + // for a complete pipestatus of `1 1 0`. + st.pipestatus.push_back(laststatus); + continue; + } if (status.signal_exited()) { st.kill_signal = status.signal_code(); } + laststatus = status.status_value(); + has_status = true; st.pipestatus.push_back(status.status_value()); } - int laststatus = st.pipestatus.back(); + if (!has_status) { + return none(); + } st.status = flags().negate ? !laststatus : laststatus; return st; } @@ -997,8 +1010,11 @@ void job_t::continue_job(parser_t &parser, bool in_foreground) { // finished. const auto &p = processes.back(); if (p->status.normal_exited() || p->status.signal_exited()) { - parser.set_last_statuses(get_statuses()); - parser.libdata().status_count++; + auto statuses = get_statuses(); + if (statuses) { + parser.set_last_statuses(statuses.value()); + parser.libdata().status_count++; + } } } } diff --git a/src/proc.h b/src/proc.h index 2700d4610..deb36a7c7 100644 --- a/src/proc.h +++ b/src/proc.h @@ -54,7 +54,12 @@ using job_group_ref_t = std::shared_ptr; class proc_status_t { int status_{}; - explicit proc_status_t(int status) : status_(status) {} + /// If set, there is no actual status to report, e.g. background or variable assignment. + bool empty_{}; + + explicit proc_status_t(int status) : status_(status), empty_(false) {} + + proc_status_t(int status, bool empty) : status_(status), empty_(empty) {} /// Encode a return value \p ret and signal \p sig into a status value like waitpid() does. static constexpr int w_exitcode(int ret, int sig) { @@ -84,6 +89,12 @@ class proc_status_t { return proc_status_t(w_exitcode(0 /* ret */, sig)); } + /// Construct an empty status_t (e.g. `set foo bar`). + static proc_status_t empty() { + bool empty = true; + return proc_status_t(0, empty); + } + /// \return if we are stopped (as in SIGSTOP). bool stopped() const { return WIFSTOPPED(status_); } @@ -111,6 +122,9 @@ class proc_status_t { /// \return if this status represents success. bool is_success() const { return normal_exited() && exit_code() == EXIT_SUCCESS; } + /// \return if this status is empty. + bool is_empty() const { return empty_; } + /// \return the value appropriate to populate $status. int status_value() const { if (signal_exited()) { @@ -465,7 +479,7 @@ class job_t { bool signal(int signal); /// \returns the statuses for this job. - statuses_t get_statuses() const; + maybe_t get_statuses() const; }; /// Whether this shell is attached to the keyboard at all.